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);