mirror of https://git.ffmpeg.org/ffmpeg.git
Search relative path according to alias record when opening mov reference files.
Based on patch by Maksym Veremeyenko, verem at m1stereo dot tv Originally committed as revision 20539 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
b154ed5abe
commit
adeb907137
|
@ -56,6 +56,10 @@ typedef struct {
|
|||
typedef struct {
|
||||
uint32_t type;
|
||||
char *path;
|
||||
char *dir;
|
||||
char volume[28];
|
||||
char filename[64];
|
||||
int16_t nlvl_to, nlvl_from;
|
||||
} MOVDref;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -274,18 +274,33 @@ static int mov_read_dref(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
|
|||
if (dref->type == MKTAG('a','l','i','s') && size > 150) {
|
||||
/* macintosh alias record */
|
||||
uint16_t volume_len, len;
|
||||
char volume[28];
|
||||
int16_t type;
|
||||
|
||||
url_fskip(pb, 10);
|
||||
|
||||
volume_len = get_byte(pb);
|
||||
volume_len = FFMIN(volume_len, 27);
|
||||
get_buffer(pb, volume, 27);
|
||||
volume[volume_len] = 0;
|
||||
av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", volume, volume_len);
|
||||
get_buffer(pb, dref->volume, 27);
|
||||
dref->volume[volume_len] = 0;
|
||||
av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);
|
||||
|
||||
url_fskip(pb, 112);
|
||||
url_fskip(pb, 12);
|
||||
|
||||
len = get_byte(pb);
|
||||
len = FFMIN(len, 63);
|
||||
get_buffer(pb, dref->filename, 63);
|
||||
dref->filename[len] = 0;
|
||||
av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);
|
||||
|
||||
url_fskip(pb, 16);
|
||||
|
||||
/* read next level up_from_alias/down_to_target */
|
||||
dref->nlvl_from = get_be16(pb);
|
||||
dref->nlvl_to = get_be16(pb);
|
||||
av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",
|
||||
dref->nlvl_from, dref->nlvl_to);
|
||||
|
||||
url_fskip(pb, 16);
|
||||
|
||||
for (type = 0; type != -1 && url_ftell(pb) < next; ) {
|
||||
type = get_be16(pb);
|
||||
|
@ -299,7 +314,7 @@ static int mov_read_dref(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
|
|||
if (!dref->path)
|
||||
return AVERROR(ENOMEM);
|
||||
get_buffer(pb, dref->path, len);
|
||||
if (len > volume_len && !strncmp(dref->path, volume, volume_len)) {
|
||||
if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {
|
||||
len -= volume_len;
|
||||
memmove(dref->path, dref->path+volume_len, len);
|
||||
dref->path[len] = 0;
|
||||
|
@ -308,6 +323,17 @@ static int mov_read_dref(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
|
|||
if (dref->path[j] == ':')
|
||||
dref->path[j] = '/';
|
||||
av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);
|
||||
} else if (type == 0) { // directory name
|
||||
av_free(dref->dir);
|
||||
dref->dir = av_malloc(len+1);
|
||||
if (!dref->dir)
|
||||
return AVERROR(ENOMEM);
|
||||
get_buffer(pb, dref->dir, len);
|
||||
dref->dir[len] = 0;
|
||||
for (j = 0; j < len; j++)
|
||||
if (dref->dir[j] == ':')
|
||||
dref->dir[j] = '/';
|
||||
av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);
|
||||
} else
|
||||
url_fskip(pb, len);
|
||||
}
|
||||
|
@ -1526,6 +1552,52 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
|
|||
}
|
||||
}
|
||||
|
||||
static int mov_open_dref(ByteIOContext **pb, char *src, MOVDref *ref)
|
||||
{
|
||||
/* try absolute path */
|
||||
if (!url_fopen(pb, ref->path, URL_RDONLY))
|
||||
return 0;
|
||||
|
||||
/* try relative path */
|
||||
if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
|
||||
char filename[1024];
|
||||
char *src_path;
|
||||
int i, l;
|
||||
|
||||
/* find a source dir */
|
||||
src_path = strrchr(src, '/');
|
||||
if (src_path)
|
||||
src_path++;
|
||||
else
|
||||
src_path = src;
|
||||
|
||||
/* find a next level down to target */
|
||||
for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)
|
||||
if (ref->path[l] == '/') {
|
||||
if (i == ref->nlvl_to - 1)
|
||||
break;
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
/* compose filename if next level down to target was found */
|
||||
if (i == ref->nlvl_to - 1) {
|
||||
memcpy(filename, src, src_path - src);
|
||||
filename[src_path - src] = 0;
|
||||
|
||||
for (i = 1; i < ref->nlvl_from; i++)
|
||||
av_strlcat(filename, "../", 1024);
|
||||
|
||||
av_strlcat(filename, ref->path + l + 1, 1024);
|
||||
|
||||
if (!url_fopen(pb, filename, URL_RDONLY))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return AVERROR(ENOENT);
|
||||
};
|
||||
|
||||
static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
|
||||
{
|
||||
AVStream *st;
|
||||
|
@ -1571,9 +1643,13 @@ static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
|
|||
mov_build_index(c, st);
|
||||
|
||||
if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
|
||||
if (url_fopen(&sc->pb, sc->drefs[sc->dref_id-1].path, URL_RDONLY) < 0)
|
||||
av_log(c->fc, AV_LOG_ERROR, "stream %d, error opening file %s: %s\n",
|
||||
st->index, sc->drefs[sc->dref_id-1].path, strerror(errno));
|
||||
MOVDref *dref = &sc->drefs[sc->dref_id - 1];
|
||||
if (mov_open_dref(&sc->pb, c->fc->filename, dref) < 0)
|
||||
av_log(c->fc, AV_LOG_ERROR,
|
||||
"stream %d, error opening alias: path='%s', dir='%s', "
|
||||
"filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
|
||||
st->index, dref->path, dref->dir, dref->filename,
|
||||
dref->volume, dref->nlvl_from, dref->nlvl_to);
|
||||
} else
|
||||
sc->pb = c->fc->pb;
|
||||
|
||||
|
@ -2244,8 +2320,10 @@ static int mov_read_close(AVFormatContext *s)
|
|||
MOVStreamContext *sc = st->priv_data;
|
||||
|
||||
av_freep(&sc->ctts_data);
|
||||
for (j = 0; j < sc->drefs_count; j++)
|
||||
for (j = 0; j < sc->drefs_count; j++) {
|
||||
av_freep(&sc->drefs[j].path);
|
||||
av_freep(&sc->drefs[j].dir);
|
||||
}
|
||||
av_freep(&sc->drefs);
|
||||
if (sc->pb && sc->pb != s->pb)
|
||||
url_fclose(sc->pb);
|
||||
|
|
Loading…
Reference in New Issue