Mercurial > libavformat.hg
comparison mov.c @ 5369:347123a18feb libavformat
Search relative path according to alias record when opening mov reference files.
Based on patch by Maksym Veremeyenko, verem at m1stereo dot tv
author | bcoudurier |
---|---|
date | Sun, 15 Nov 2009 03:26:47 +0000 |
parents | 4a925b59dc1b |
children | a0846aa55f5e |
comparison
equal
deleted
inserted
replaced
5368:d93af9bfc0b8 | 5369:347123a18feb |
---|---|
272 dprintf(c->fc, "type %.4s size %d\n", (char*)&dref->type, size); | 272 dprintf(c->fc, "type %.4s size %d\n", (char*)&dref->type, size); |
273 | 273 |
274 if (dref->type == MKTAG('a','l','i','s') && size > 150) { | 274 if (dref->type == MKTAG('a','l','i','s') && size > 150) { |
275 /* macintosh alias record */ | 275 /* macintosh alias record */ |
276 uint16_t volume_len, len; | 276 uint16_t volume_len, len; |
277 char volume[28]; | |
278 int16_t type; | 277 int16_t type; |
279 | 278 |
280 url_fskip(pb, 10); | 279 url_fskip(pb, 10); |
281 | 280 |
282 volume_len = get_byte(pb); | 281 volume_len = get_byte(pb); |
283 volume_len = FFMIN(volume_len, 27); | 282 volume_len = FFMIN(volume_len, 27); |
284 get_buffer(pb, volume, 27); | 283 get_buffer(pb, dref->volume, 27); |
285 volume[volume_len] = 0; | 284 dref->volume[volume_len] = 0; |
286 av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", volume, volume_len); | 285 av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len); |
287 | 286 |
288 url_fskip(pb, 112); | 287 url_fskip(pb, 12); |
288 | |
289 len = get_byte(pb); | |
290 len = FFMIN(len, 63); | |
291 get_buffer(pb, dref->filename, 63); | |
292 dref->filename[len] = 0; | |
293 av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len); | |
294 | |
295 url_fskip(pb, 16); | |
296 | |
297 /* read next level up_from_alias/down_to_target */ | |
298 dref->nlvl_from = get_be16(pb); | |
299 dref->nlvl_to = get_be16(pb); | |
300 av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n", | |
301 dref->nlvl_from, dref->nlvl_to); | |
302 | |
303 url_fskip(pb, 16); | |
289 | 304 |
290 for (type = 0; type != -1 && url_ftell(pb) < next; ) { | 305 for (type = 0; type != -1 && url_ftell(pb) < next; ) { |
291 type = get_be16(pb); | 306 type = get_be16(pb); |
292 len = get_be16(pb); | 307 len = get_be16(pb); |
293 av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len); | 308 av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len); |
297 av_free(dref->path); | 312 av_free(dref->path); |
298 dref->path = av_mallocz(len+1); | 313 dref->path = av_mallocz(len+1); |
299 if (!dref->path) | 314 if (!dref->path) |
300 return AVERROR(ENOMEM); | 315 return AVERROR(ENOMEM); |
301 get_buffer(pb, dref->path, len); | 316 get_buffer(pb, dref->path, len); |
302 if (len > volume_len && !strncmp(dref->path, volume, volume_len)) { | 317 if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) { |
303 len -= volume_len; | 318 len -= volume_len; |
304 memmove(dref->path, dref->path+volume_len, len); | 319 memmove(dref->path, dref->path+volume_len, len); |
305 dref->path[len] = 0; | 320 dref->path[len] = 0; |
306 } | 321 } |
307 for (j = 0; j < len; j++) | 322 for (j = 0; j < len; j++) |
308 if (dref->path[j] == ':') | 323 if (dref->path[j] == ':') |
309 dref->path[j] = '/'; | 324 dref->path[j] = '/'; |
310 av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path); | 325 av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path); |
326 } else if (type == 0) { // directory name | |
327 av_free(dref->dir); | |
328 dref->dir = av_malloc(len+1); | |
329 if (!dref->dir) | |
330 return AVERROR(ENOMEM); | |
331 get_buffer(pb, dref->dir, len); | |
332 dref->dir[len] = 0; | |
333 for (j = 0; j < len; j++) | |
334 if (dref->dir[j] == ':') | |
335 dref->dir[j] = '/'; | |
336 av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir); | |
311 } else | 337 } else |
312 url_fskip(pb, len); | 338 url_fskip(pb, len); |
313 } | 339 } |
314 } | 340 } |
315 url_fseek(pb, next, SEEK_SET); | 341 url_fseek(pb, next, SEEK_SET); |
1524 } | 1550 } |
1525 } | 1551 } |
1526 } | 1552 } |
1527 } | 1553 } |
1528 | 1554 |
1555 static int mov_open_dref(ByteIOContext **pb, char *src, MOVDref *ref) | |
1556 { | |
1557 /* try absolute path */ | |
1558 if (!url_fopen(pb, ref->path, URL_RDONLY)) | |
1559 return 0; | |
1560 | |
1561 /* try relative path */ | |
1562 if (ref->nlvl_to > 0 && ref->nlvl_from > 0) { | |
1563 char filename[1024]; | |
1564 char *src_path; | |
1565 int i, l; | |
1566 | |
1567 /* find a source dir */ | |
1568 src_path = strrchr(src, '/'); | |
1569 if (src_path) | |
1570 src_path++; | |
1571 else | |
1572 src_path = src; | |
1573 | |
1574 /* find a next level down to target */ | |
1575 for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--) | |
1576 if (ref->path[l] == '/') { | |
1577 if (i == ref->nlvl_to - 1) | |
1578 break; | |
1579 else | |
1580 i++; | |
1581 } | |
1582 | |
1583 /* compose filename if next level down to target was found */ | |
1584 if (i == ref->nlvl_to - 1) { | |
1585 memcpy(filename, src, src_path - src); | |
1586 filename[src_path - src] = 0; | |
1587 | |
1588 for (i = 1; i < ref->nlvl_from; i++) | |
1589 av_strlcat(filename, "../", 1024); | |
1590 | |
1591 av_strlcat(filename, ref->path + l + 1, 1024); | |
1592 | |
1593 if (!url_fopen(pb, filename, URL_RDONLY)) | |
1594 return 0; | |
1595 } | |
1596 } | |
1597 | |
1598 return AVERROR(ENOENT); | |
1599 }; | |
1600 | |
1529 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOVAtom atom) | 1601 static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOVAtom atom) |
1530 { | 1602 { |
1531 AVStream *st; | 1603 AVStream *st; |
1532 MOVStreamContext *sc; | 1604 MOVStreamContext *sc; |
1533 int ret; | 1605 int ret; |
1569 } | 1641 } |
1570 | 1642 |
1571 mov_build_index(c, st); | 1643 mov_build_index(c, st); |
1572 | 1644 |
1573 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) { | 1645 if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) { |
1574 if (url_fopen(&sc->pb, sc->drefs[sc->dref_id-1].path, URL_RDONLY) < 0) | 1646 MOVDref *dref = &sc->drefs[sc->dref_id - 1]; |
1575 av_log(c->fc, AV_LOG_ERROR, "stream %d, error opening file %s: %s\n", | 1647 if (mov_open_dref(&sc->pb, c->fc->filename, dref) < 0) |
1576 st->index, sc->drefs[sc->dref_id-1].path, strerror(errno)); | 1648 av_log(c->fc, AV_LOG_ERROR, |
1649 "stream %d, error opening alias: path='%s', dir='%s', " | |
1650 "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n", | |
1651 st->index, dref->path, dref->dir, dref->filename, | |
1652 dref->volume, dref->nlvl_from, dref->nlvl_to); | |
1577 } else | 1653 } else |
1578 sc->pb = c->fc->pb; | 1654 sc->pb = c->fc->pb; |
1579 | 1655 |
1580 switch (st->codec->codec_id) { | 1656 switch (st->codec->codec_id) { |
1581 #if CONFIG_H261_DECODER | 1657 #if CONFIG_H261_DECODER |
2242 for (i = 0; i < s->nb_streams; i++) { | 2318 for (i = 0; i < s->nb_streams; i++) { |
2243 AVStream *st = s->streams[i]; | 2319 AVStream *st = s->streams[i]; |
2244 MOVStreamContext *sc = st->priv_data; | 2320 MOVStreamContext *sc = st->priv_data; |
2245 | 2321 |
2246 av_freep(&sc->ctts_data); | 2322 av_freep(&sc->ctts_data); |
2247 for (j = 0; j < sc->drefs_count; j++) | 2323 for (j = 0; j < sc->drefs_count; j++) { |
2248 av_freep(&sc->drefs[j].path); | 2324 av_freep(&sc->drefs[j].path); |
2325 av_freep(&sc->drefs[j].dir); | |
2326 } | |
2249 av_freep(&sc->drefs); | 2327 av_freep(&sc->drefs); |
2250 if (sc->pb && sc->pb != s->pb) | 2328 if (sc->pb && sc->pb != s->pb) |
2251 url_fclose(sc->pb); | 2329 url_fclose(sc->pb); |
2252 | 2330 |
2253 av_freep(&st->codec->palctrl); | 2331 av_freep(&st->codec->palctrl); |