diff options
Diffstat (limited to 'libavformat/mov.c')
-rw-r--r-- | libavformat/mov.c | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/libavformat/mov.c b/libavformat/mov.c index acde35d..651c685 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3,20 +3,20 @@ * Copyright (c) 2001 Fabrice Bellard * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -81,15 +81,15 @@ typedef struct MOVParseTableEntry { static const MOVParseTableEntry mov_default_parse_table[]; -static int mov_metadata_trkn(MOVContext *c, AVIOContext *pb, unsigned len) +static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb, unsigned len, const char *type) { char buf[16]; avio_rb16(pb); // unknown snprintf(buf, sizeof(buf), "%d", avio_rb16(pb)); - av_dict_set(&c->fc->metadata, "track", buf, 0); + av_dict_set(&c->fc->metadata, type, buf, 0); - avio_rb16(pb); // total tracks + avio_rb16(pb); // total tracks/discs return 0; } @@ -140,15 +140,18 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) const char *key = NULL; uint16_t str_size, langcode = 0; uint32_t data_type = 0; - int (*parse)(MOVContext*, AVIOContext*, unsigned) = NULL; + int (*parse)(MOVContext*, AVIOContext*, unsigned, const char *) = NULL; switch (atom.type) { case MKTAG(0xa9,'n','a','m'): key = "title"; break; case MKTAG(0xa9,'a','u','t'): case MKTAG(0xa9,'A','R','T'): key = "artist"; break; + case MKTAG( 'a','A','R','T'): key = "album_artist";break; case MKTAG(0xa9,'w','r','t'): key = "composer"; break; case MKTAG( 'c','p','r','t'): case MKTAG(0xa9,'c','p','y'): key = "copyright"; break; + case MKTAG(0xa9,'g','r','p'): key = "grouping"; break; + case MKTAG(0xa9,'l','y','r'): key = "lyrics"; break; case MKTAG(0xa9,'c','m','t'): case MKTAG(0xa9,'i','n','f'): key = "comment"; break; case MKTAG(0xa9,'a','l','b'): key = "album"; break; @@ -163,7 +166,9 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) case MKTAG( 't','v','e','n'): key = "episode_id";break; case MKTAG( 't','v','n','n'): key = "network"; break; case MKTAG( 't','r','k','n'): key = "track"; - parse = mov_metadata_trkn; break; + parse = mov_metadata_track_or_disc_number; break; + case MKTAG( 'd','i','s','k'): key = "disc"; + parse = mov_metadata_track_or_disc_number; break; } if (c->itunes_metadata && atom.size > 8) { @@ -198,7 +203,7 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) str_size = FFMIN3(sizeof(str)-1, str_size, atom.size); if (parse) - parse(c, pb, str_size); + parse(c, pb, str_size, key); else { if (data_type == 3 || (data_type == 0 && langcode < 0x800)) { // MAC Encoded mov_read_mac_string(c, pb, str_size, str, sizeof(str)); @@ -259,7 +264,7 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (atom.size < 0) atom.size = INT64_MAX; - while (total_size + 8 < atom.size && !pb->eof_reached) { + while (total_size + 8 < atom.size && !url_feof(pb)) { int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL; a.size = atom.size; a.type=0; @@ -728,7 +733,7 @@ static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; st = c->fc->streams[c->fc->nb_streams-1]; - little_endian = avio_rb16(pb); + little_endian = avio_rb16(pb) & 0xFF; av_dlog(c->fc, "enda %d\n", little_endian); if (little_endian == 1) { switch (st->codec->codec_id) { @@ -1511,7 +1516,7 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->ctts_data[i].count = count; sc->ctts_data[i].duration= duration; - if (duration < 0) + if (duration < 0 && i+1<entries) sc->dts_shift = FFMAX(sc->dts_shift, -duration); } @@ -1538,7 +1543,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st) sc->time_offset = av_rescale(sc->time_offset, sc->time_scale, mov->time_scale); current_dts = -sc->time_offset; if (sc->ctts_data && sc->stts_data && - sc->ctts_data[0].duration / sc->stts_data[0].duration > 16) { + sc->ctts_data[0].duration / FFMAX(sc->stts_data[0].duration, 1) > 16) { /* more than 16 frames delay, dts are likely wrong this happens with files created by iMovie */ sc->wrong_dts = 1; @@ -1700,13 +1705,13 @@ static void mov_build_index(MOVContext *mov, AVStream *st) } } -static int mov_open_dref(AVIOContext **pb, char *src, MOVDref *ref) +static int mov_open_dref(AVIOContext **pb, const char *src, MOVDref *ref) { /* try relative path, we do not try the absolute because it can leak information about our system to an attacker */ if (ref->nlvl_to > 0 && ref->nlvl_from > 0) { char filename[1024]; - char *src_path; + const char *src_path; int i, l; /* find a source dir */ @@ -1924,6 +1929,10 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->width = width >> 16; sc->height = height >> 16; + if (display_matrix[0][0] == -65536 && display_matrix[1][1] == -65536) { + av_dict_set(&st->metadata, "rotate", "180", 0); + } + // transform the display width/height according to the matrix // skip this if the display matrix is the default identity matrix // or if it is rotating the picture, ex iPhone 3GS @@ -2211,6 +2220,15 @@ static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static int mov_read_chan(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + if (atom.size < 16) + return AVERROR_INVALIDDATA; + avio_skip(pb, 4); + ff_mov_read_chan(c->fc, atom.size - 4, c->fc->streams[0]->codec); + return 0; +} + static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('a','v','s','s'), mov_read_extradata }, { MKTAG('c','h','p','l'), mov_read_chpl }, @@ -2265,6 +2283,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */ { MKTAG('w','f','e','x'), mov_read_wfex }, { MKTAG('c','m','o','v'), mov_read_cmov }, +{ MKTAG('c','h','a','n'), mov_read_chan }, { 0, NULL } }; @@ -2365,7 +2384,7 @@ static void mov_read_chapters(AVFormatContext *s) avio_get_str16le(sc->pb, len, title, title_len); else { AV_WB16(title, ch); - avio_get_str(sc->pb, len - 2, title + 2, title_len - 2); + get_strz(sc->pb, title + 2, len - 1); } ff_new_chapter(s, i, st->time_base, sample->timestamp, end, title); @@ -2445,7 +2464,7 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) mov->found_mdat = 0; if (s->pb->seekable|| mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX }) < 0 || - s->pb->eof_reached) + url_feof(s->pb)) return AVERROR_EOF; av_dlog(s, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb)); goto retry; @@ -2476,7 +2495,7 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) } #if CONFIG_DV_DEMUXER if (mov->dv_demux && sc->dv_audio_container) { - dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size); + dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size, pkt->pos); av_free(pkt->data); pkt->size = 0; ret = dv_get_packet(mov->dv_demux, pkt); |