]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/matroska.c
correct implementation of "try with auto_guess if first detection fails"
[ffmpeg] / libavformat / matroska.c
index 32572c78610cfea69b0773c41c85af002cad4874..eaf4ceb953fdb17570b181a0889e39448589a442 100644 (file)
@@ -212,6 +212,7 @@ static CodecTags codec_tags[]={
     {"V_REAL/RV20"      , CODEC_ID_RV20},
     {"V_REAL/RV30"      , CODEC_ID_RV30},
     {"V_REAL/RV40"      , CODEC_ID_RV40},
+    {"V_THEORA"         , CODEC_ID_THEORA},
 /* TODO: Real/Quicktime */
 
 //    {"A_MS/ACM"         , CODEC_ID_NONE},
@@ -253,7 +254,7 @@ typedef struct Track {
     unsigned char *codec_priv;
     int codec_priv_size;
 
-    int64_t default_duration;
+    uint64_t default_duration;
     MatroskaTrackFlags flags;
 } MatroskaTrack;
 
@@ -319,9 +320,6 @@ typedef struct MatroskaDemuxContext {
     /* timescale in the file */
     int64_t time_scale;
 
-    /* position (time, ns) */
-    int64_t pos;
-
     /* num_streams is the number of streams that av_new_stream() was called
      * for ( = that are available to the calling program). */
     int num_tracks, num_streams;
@@ -345,6 +343,10 @@ typedef struct MatroskaDemuxContext {
     /* The index for seeking. */
     int num_indexes;
     MatroskaDemuxIndex *index;
+
+    /* What to skip before effectively reading a packet. */
+    int skip_to_keyframe;
+    AVStream *skip_to_stream;
 } MatroskaDemuxContext;
 
 /*
@@ -976,6 +978,21 @@ ebml_read_header (MatroskaDemuxContext *matroska,
     return 0;
 }
 
+
+static int
+matroska_find_track_by_num (MatroskaDemuxContext *matroska,
+                            int                   num)
+{
+    int i;
+
+    for (i = 0; i < matroska->num_tracks; i++)
+        if (matroska->tracks[i]->num == num)
+            return i;
+
+    return -1;
+}
+
+
 /*
  * Put one packet in an application-supplied AVPacket struct.
  * Returns 0 on success or -1 on failure.
@@ -1020,6 +1037,7 @@ matroska_queue_packet (MatroskaDemuxContext *matroska,
     matroska->num_packets++;
 }
 
+
 /*
  * Autodetecting...
  */
@@ -1031,9 +1049,6 @@ matroska_probe (AVProbeData *p)
     int len_mask = 0x80, size = 1, n = 1;
     uint8_t probe_data[] = { 'm', 'a', 't', 'r', 'o', 's', 'k', 'a' };
 
-    if (p->buf_size < 5)
-        return 0;
-
     /* ebml header? */
     if ((p->buf[0] << 24 | p->buf[1] << 16 |
          p->buf[2] << 8 | p->buf[3]) != EBML_ID_HEADER)
@@ -1265,7 +1280,7 @@ matroska_add_stream (MatroskaDemuxContext *matroska)
                             if ((res = ebml_read_uint (matroska, &id,
                                                        &num)) < 0)
                                 break;
-                            track->default_duration = num;
+                            track->default_duration = num/matroska->time_scale;
                             break;
                         }
 
@@ -1275,7 +1290,7 @@ matroska_add_stream (MatroskaDemuxContext *matroska)
                             if ((res = ebml_read_float(matroska, &id,
                                                        &num)) < 0)
                                 break;
-                            track->default_duration = 1000000000 * (1. / num);
+                            track->default_duration = 1000000000/(matroska->time_scale*num);
                             break;
                         }
 
@@ -1578,7 +1593,7 @@ matroska_add_stream (MatroskaDemuxContext *matroska)
                 uint64_t num;
                 if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
                     break;
-                track->default_duration = num;
+                track->default_duration = num / matroska->time_scale;
                 break;
             }
 
@@ -1731,7 +1746,7 @@ matroska_parse_index (MatroskaDemuxContext *matroska)
                                         if ((res = ebml_read_uint(matroska,
                                                           &id, &num)) < 0)
                                             break;
-                                        idx.pos = num;
+                                        idx.pos = num+matroska->segment_start;
                                         break;
                                     }
 
@@ -2263,6 +2278,7 @@ matroska_read_header (AVFormatContext    *s,
                 } else {
                     extradata_size = 2;
                 }
+                track->default_duration = 1024*1000 / audiotrack->internal_samplerate;
             }
 
             else if (codec_id == CODEC_ID_TTA) {
@@ -2304,10 +2320,11 @@ matroska_read_header (AVFormatContext    *s,
             av_set_pts_info(st, 64, matroska->time_scale, 1000*1000*1000); /* 64 bit pts in ns */
 
             st->codec->codec_id = codec_id;
+            st->start_time = 0;
 
             if (track->default_duration)
                 av_reduce(&st->codec->time_base.num, &st->codec->time_base.den,
-                          track->default_duration, 1000000000, 30000);
+                          track->default_duration, 1000, 30000);
 
             if(extradata){
                 st->codec->extradata = extradata;
@@ -2337,6 +2354,7 @@ matroska_read_header (AVFormatContext    *s,
                           st->codec->height * videotrack->display_width,
                           st->codec-> width * videotrack->display_height,
                           255);
+                st->need_parsing = AVSTREAM_PARSE_HEADERS;
             } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
                 MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
 
@@ -2352,20 +2370,19 @@ matroska_read_header (AVFormatContext    *s,
         res = 0;
     }
 
-    return res;
-}
-
-static int
-matroska_find_track_by_num (MatroskaDemuxContext *matroska,
-                            int                   num)
-{
-    int i;
-
-    for (i = 0; i < matroska->num_tracks; i++)
-        if (matroska->tracks[i]->num == num)
-            return i;
+    if (matroska->index_parsed) {
+        int i, track, stream;
+        for (i=0; i<matroska->num_indexes; i++) {
+            MatroskaDemuxIndex *idx = &matroska->index[i];
+            track = matroska_find_track_by_num(matroska, idx->track);
+            stream = matroska->tracks[track]->stream_index;
+            av_add_index_entry(matroska->ctx->streams[stream],
+                               idx->pos, idx->time/matroska->time_scale,
+                               0, 0, AVINDEX_KEYFRAME);
+        }
+    }
 
-    return -1;
+    return res;
 }
 
 static inline int
@@ -2375,24 +2392,19 @@ rv_offset(uint8_t *data, int slice, int slices)
 }
 
 static int
-matroska_parse_block(MatroskaDemuxContext *matroska, uint64_t cluster_time,
-                     int is_keyframe, int *ptrack, AVPacket **ppkt)
+matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size,
+                     int64_t pos, uint64_t cluster_time, uint64_t duration,
+                     int is_keyframe, int is_bframe)
 {
-    int res;
-    uint32_t id;
+    int res = 0;
     int track;
+    AVStream *st;
     AVPacket *pkt;
-    uint8_t *data, *origdata;
-    int size;
+    uint8_t *origdata = data;
     int16_t block_time;
     uint32_t *lace_size = NULL;
     int n, flags, laces = 0;
     uint64_t num;
-    int64_t pos= url_ftell(&matroska->ctx->pb);
-
-    if ((res = ebml_read_binary(matroska, &id, &data, &size)) < 0)
-        return res;
-    origdata = data;
 
     /* first byte(s): tracknum */
     if ((n = matroska_ebmlnum_uint(data, size, &num)) < 0) {
@@ -2405,17 +2417,19 @@ matroska_parse_block(MatroskaDemuxContext *matroska, uint64_t cluster_time,
 
     /* fetch track from num */
     track = matroska_find_track_by_num(matroska, num);
-    if (ptrack)  *ptrack = track;
     if (size <= 3 || track < 0 || track >= matroska->num_tracks) {
         av_log(matroska->ctx, AV_LOG_INFO,
                "Invalid stream %d or size %u\n", track, size);
         av_free(origdata);
         return res;
     }
-    if(matroska->ctx->streams[ matroska->tracks[track]->stream_index ]->discard >= AVDISCARD_ALL){
+    st = matroska->ctx->streams[matroska->tracks[track]->stream_index];
+    if (st->discard >= AVDISCARD_ALL) {
         av_free(origdata);
         return res;
     }
+    if (duration == AV_NOPTS_VALUE)
+        duration = matroska->tracks[track]->default_duration;
 
     /* block_time (relative to cluster time) */
     block_time = (data[0] << 8) | data[1];
@@ -2426,6 +2440,13 @@ matroska_parse_block(MatroskaDemuxContext *matroska, uint64_t cluster_time,
     size -= 1;
     if (is_keyframe == -1)
         is_keyframe = flags & 1 ? PKT_FLAG_KEY : 0;
+
+    if (matroska->skip_to_keyframe) {
+        if (!is_keyframe || st != matroska->skip_to_stream)
+            return res;
+        matroska->skip_to_keyframe = 0;
+    }
+
     switch ((flags & 0x06) >> 1) {
         case 0x0: /* no lacing */
             laces = 1;
@@ -2507,19 +2528,18 @@ matroska_parse_block(MatroskaDemuxContext *matroska, uint64_t cluster_time,
 
     if (res == 0) {
         int real_v = matroska->tracks[track]->flags & MATROSKA_TRACK_REAL_V;
+        uint64_t timecode = AV_NOPTS_VALUE;
+
+        if (cluster_time != (uint64_t)-1 && cluster_time + block_time >= 0)
+            timecode = cluster_time + block_time;
+
         for (n = 0; n < laces; n++) {
-            uint64_t timecode = AV_NOPTS_VALUE;
             int slice, slices = 1;
 
             if (real_v) {
                 slices = *data++ + 1;
                 lace_size[n]--;
             }
-            if (cluster_time != (uint64_t)-1 && n == 0) {
-                if (cluster_time + block_time >= 0)
-                    timecode = (cluster_time + block_time) * matroska->time_scale;
-            }
-            /* FIXME: duration */
 
             for (slice=0; slice<slices; slice++) {
                 int slice_size, slice_offset = 0;
@@ -2530,7 +2550,6 @@ matroska_parse_block(MatroskaDemuxContext *matroska, uint64_t cluster_time,
                 else
                     slice_size = rv_offset(data, slice+1, slices) - slice_offset;
                 pkt = av_mallocz(sizeof(AVPacket));
-                if (ppkt)  *ppkt = pkt;
                 /* XXX: prevent data copy... */
                 if (av_new_packet(pkt, slice_size) < 0) {
                     res = AVERROR_NOMEM;
@@ -2545,8 +2564,12 @@ matroska_parse_block(MatroskaDemuxContext *matroska, uint64_t cluster_time,
 
                 pkt->pts = timecode;
                 pkt->pos = pos;
+                pkt->duration = duration;
 
                 matroska_queue_packet(matroska, pkt);
+
+                if (timecode != AV_NOPTS_VALUE)
+                    timecode = duration ? timecode + duration : AV_NOPTS_VALUE;
             }
             data += lace_size[n];
         }
@@ -2563,10 +2586,12 @@ matroska_parse_blockgroup (MatroskaDemuxContext *matroska,
 {
     int res = 0;
     uint32_t id;
-    AVPacket *pkt = NULL;
+    int is_bframe = 0;
     int is_keyframe = PKT_FLAG_KEY, last_num_packets = matroska->num_packets;
     uint64_t duration = AV_NOPTS_VALUE;
-    int track = -1;
+    uint8_t *data;
+    int size = 0;
+    int64_t pos = 0;
 
     av_log(matroska->ctx, AV_LOG_DEBUG, "parsing blockgroup...\n");
 
@@ -2584,25 +2609,31 @@ matroska_parse_blockgroup (MatroskaDemuxContext *matroska,
              * of the harder things, so this code is a bit complicated.
              * See http://www.matroska.org/ for documentation. */
             case MATROSKA_ID_BLOCK: {
-                res = matroska_parse_block(matroska, cluster_time,
-                                           is_keyframe, &track, &pkt);
+                pos = url_ftell(&matroska->ctx->pb);
+                res = ebml_read_binary(matroska, &id, &data, &size);
                 break;
             }
 
             case MATROSKA_ID_BLOCKDURATION: {
                 if ((res = ebml_read_uint(matroska, &id, &duration)) < 0)
                     break;
+                duration /= matroska->time_scale;
                 break;
             }
 
-            case MATROSKA_ID_BLOCKREFERENCE:
+            case MATROSKA_ID_BLOCKREFERENCE: {
+                int64_t num;
                 /* We've found a reference, so not even the first frame in
                  * the lace is a key frame. */
                 is_keyframe = 0;
                 if (last_num_packets != matroska->num_packets)
                     matroska->packets[last_num_packets]->flags = 0;
-                res = ebml_read_skip(matroska);
+                if ((res = ebml_read_sint(matroska, &id, &num)) < 0)
+                    break;
+                if (num > 0)
+                    is_bframe = 1;
                 break;
+            }
 
             default:
                 av_log(matroska->ctx, AV_LOG_INFO,
@@ -2620,13 +2651,12 @@ matroska_parse_blockgroup (MatroskaDemuxContext *matroska,
         }
     }
 
-    if (pkt)
-    {
-        if (duration != AV_NOPTS_VALUE)
-            pkt->duration = duration;
-        else if (track >= 0 && track < matroska->num_tracks)
-            pkt->duration = matroska->tracks[track]->default_duration / matroska->time_scale;
-    }
+    if (res)
+        return res;
+
+    if (size > 0)
+        res = matroska_parse_block(matroska, data, size, pos, cluster_time,
+                                   duration, is_keyframe, is_bframe);
 
     return res;
 }
@@ -2637,6 +2667,9 @@ matroska_parse_cluster (MatroskaDemuxContext *matroska)
     int res = 0;
     uint32_t id;
     uint64_t cluster_time = 0;
+    uint8_t *data;
+    int64_t pos;
+    int size;
 
     av_log(matroska->ctx, AV_LOG_DEBUG,
            "parsing cluster at %"PRId64"\n", url_ftell(&matroska->ctx->pb));
@@ -2668,7 +2701,12 @@ matroska_parse_cluster (MatroskaDemuxContext *matroska)
                 break;
 
             case MATROSKA_ID_SIMPLEBLOCK:
-                matroska_parse_block(matroska, cluster_time, -1, NULL, NULL);
+                pos = url_ftell(&matroska->ctx->pb);
+                res = ebml_read_binary(matroska, &id, &data, &size);
+                if (res == 0)
+                    res = matroska_parse_block(matroska, data, size, pos,
+                                               cluster_time, AV_NOPTS_VALUE,
+                                               -1, 0);
                 break;
 
             default:
@@ -2701,42 +2739,64 @@ matroska_read_packet (AVFormatContext *s,
     /* Read stream until we have a packet queued. */
     while (matroska_deliver_packet(matroska, pkt)) {
 
-    /* Have we already reached the end? */
-    if (matroska->done)
-        return AVERROR_IO;
-
-    while (res == 0) {
-        if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+        /* Have we already reached the end? */
+        if (matroska->done)
             return AVERROR_IO;
-        } else if (matroska->level_up) {
-            matroska->level_up--;
-            break;
-        }
 
-        switch (id) {
-            case MATROSKA_ID_CLUSTER:
-                if ((res = ebml_read_master(matroska, &id)) < 0)
-                    break;
-                if ((res = matroska_parse_cluster(matroska)) == 0)
-                    res = 1; /* Parsed one cluster, let's get out. */
+        while (res == 0) {
+            if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+                return AVERROR_IO;
+            } else if (matroska->level_up) {
+                matroska->level_up--;
                 break;
+            }
 
-            default:
-            case EBML_ID_VOID:
-                res = ebml_read_skip(matroska);
+            switch (id) {
+                case MATROSKA_ID_CLUSTER:
+                    if ((res = ebml_read_master(matroska, &id)) < 0)
+                        break;
+                    if ((res = matroska_parse_cluster(matroska)) == 0)
+                        res = 1; /* Parsed one cluster, let's get out. */
+                    break;
+
+                default:
+                case EBML_ID_VOID:
+                    res = ebml_read_skip(matroska);
+                    break;
+            }
+
+            if (matroska->level_up) {
+                matroska->level_up--;
                 break;
+            }
         }
 
-        if (matroska->level_up) {
-            matroska->level_up--;
-            break;
-        }
+        if (res == -1)
+            matroska->done = 1;
     }
 
-    if (res == -1)
-        matroska->done = 1;
-    }
+    return 0;
+}
+
+static int
+matroska_read_seek (AVFormatContext *s, int stream_index, int64_t timestamp,
+                    int flags)
+{
+    MatroskaDemuxContext *matroska = s->priv_data;
+    AVStream *st = s->streams[stream_index];
+    int index;
 
+    /* find index entry */
+    index = av_index_search_timestamp(st, timestamp, flags);
+    if (index < 0)
+        return 0;
+
+    /* do the seek */
+    url_fseek(&s->pb, st->index_entries[index].pos, SEEK_SET);
+    matroska->skip_to_keyframe = !(flags & AVSEEK_FLAG_ANY);
+    matroska->skip_to_stream = st;
+    matroska->num_packets = 0;
+    matroska->peek_id = 0;
     return 0;
 }
 
@@ -2780,4 +2840,5 @@ AVInputFormat matroska_demuxer = {
     matroska_read_header,
     matroska_read_packet,
     matroska_read_close,
+    matroska_read_seek,
 };