changeset 3651:57c346e50442 libavformat

matroskadec: use generic parser to parse matroska from toplevel
author aurel
date Tue, 05 Aug 2008 00:40:58 +0000
parents f31190f3d234
children a22da874fc50
files matroskadec.c
diffstat 1 files changed, 24 insertions(+), 153 deletions(-) [+]
line wrap: on
line diff
--- a/matroskadec.c	Tue Aug 05 00:40:55 2008 +0000
+++ b/matroskadec.c	Tue Aug 05 00:40:58 2008 +0000
@@ -209,6 +209,7 @@
     int metadata_parsed;
     int index_parsed;
     int done;
+    int has_cluster_id;
 
     /* What to skip before effectively reading a packet. */
     int skip_to_keyframe;
@@ -407,6 +408,24 @@
     { 0 }
 };
 
+static EbmlSyntax matroska_segment[] = {
+    { MATROSKA_ID_INFO,           EBML_NEST, 0, 0, {.n=matroska_info       } },
+    { MATROSKA_ID_TRACKS,         EBML_NEST, 0, 0, {.n=matroska_tracks     } },
+    { MATROSKA_ID_ATTACHMENTS,    EBML_NEST, 0, 0, {.n=matroska_attachments} },
+    { MATROSKA_ID_CHAPTERS,       EBML_NEST, 0, 0, {.n=matroska_chapters   } },
+    { MATROSKA_ID_CUES,           EBML_NEST, 0, 0, {.n=matroska_index      } },
+    { MATROSKA_ID_TAGS,           EBML_NEST, 0, 0, {.n=matroska_tags       } },
+    { MATROSKA_ID_SEEKHEAD,       EBML_NEST, 0, 0, {.n=matroska_seekhead   } },
+    { MATROSKA_ID_CLUSTER,        EBML_STOP, 0, offsetof(MatroskaDemuxContext,has_cluster_id) },
+    { EBML_ID_VOID,               EBML_NONE },
+    { 0 }
+};
+
+static EbmlSyntax matroska_segments[] = {
+    { MATROSKA_ID_SEGMENT,        EBML_NEST, 0, 0, {.n=matroska_segment    } },
+    { 0 }
+};
+
 /*
  * The first few functions handle EBML file parsing. The rest
  * is the document interpretation. Matroska really just is a
@@ -1152,14 +1171,6 @@
 }
 
 static int
-matroska_parse_info (MatroskaDemuxContext *matroska)
-{
-    int res = ebml_parse(matroska, matroska_info, matroska, MATROSKA_ID_INFO, 0);
-
-    return res;
-}
-
-static int
 matroska_decode_buffer(uint8_t** buf, int* buf_size, MatroskaTrack *track)
 {
     MatroskaTrackEncoding *encodings = track->encodings.elem;
@@ -1237,16 +1248,6 @@
 }
 
 static int
-matroska_parse_tracks (MatroskaDemuxContext *matroska)
-{
-    int i, res;
-
-    res = ebml_parse(matroska, matroska_tracks, matroska, MATROSKA_ID_TRACKS, 0);
-
-    return res;
-}
-
-static int
 matroska_parse_index (MatroskaDemuxContext *matroska)
 {
     return ebml_parse(matroska, matroska_index, matroska, MATROSKA_ID_CUES, 0);
@@ -1258,12 +1259,6 @@
     return ebml_parse(matroska, matroska_tags, matroska, MATROSKA_ID_TAGS, 0);
 }
 
-static int
-matroska_parse_seekhead (MatroskaDemuxContext *matroska)
-{
-    return ebml_parse(matroska, matroska_seekhead, matroska, MATROSKA_ID_SEEKHEAD, 0);
-}
-
 static void
 matroska_execute_seekhead(MatroskaDemuxContext *matroska)
 {
@@ -1348,28 +1343,6 @@
 }
 
 static int
-matroska_parse_attachments(AVFormatContext *s)
-{
-    MatroskaDemuxContext *matroska = s->priv_data;
-    int i, j, res;
-
-    res = ebml_parse(matroska, matroska_attachments, matroska, MATROSKA_ID_ATTACHMENTS, 0);
-
-    return res;
-}
-
-static int
-matroska_parse_chapters(AVFormatContext *s)
-{
-    MatroskaDemuxContext *matroska = s->priv_data;
-    int i, res;
-
-    res = ebml_parse(matroska, matroska_chapters, matroska, MATROSKA_ID_CHAPTERS, 0);
-
-    return res;
-}
-
-static int
 matroska_aac_profile (char *codec_id)
 {
     static const char *aac_profiles[] = {
@@ -1406,10 +1379,9 @@
     MatroskaTrack *tracks;
     EbmlList *index_list;
     MatroskaIndex *index;
-    int i, j, last_level, res = 0;
     Ebml ebml = { 0 };
     AVStream *st;
-    uint32_t id;
+    int i, j;
 
     matroska->ctx = s;
 
@@ -1427,107 +1399,8 @@
     ebml_free(ebml_syntax, &ebml);
 
     /* The next thing is a segment. */
-    while (1) {
-        if (!(id = ebml_peek_id(matroska, &last_level)))
-            return AVERROR(EIO);
-        if (id == MATROSKA_ID_SEGMENT)
-            break;
-
-        /* oi! */
-        av_log(matroska->ctx, AV_LOG_INFO,
-               "Expected a Segment ID (0x%x), but received 0x%x!\n",
-               MATROSKA_ID_SEGMENT, id);
-        if ((res = ebml_read_skip(matroska)) < 0)
-            return res;
-    }
-
-    /* We now have a Matroska segment.
-     * Seeks are from the beginning of the segment,
-     * after the segment ID/length. */
-    if ((res = ebml_read_master(matroska, &id)) < 0)
-        return res;
-    matroska->segment_start = url_ftell(s->pb);
-
-    matroska->time_scale = 1000000;
-    /* we've found our segment, start reading the different contents in here */
-    while (res == 0) {
-        if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
-            res = AVERROR(EIO);
-            break;
-        } else if (matroska->level_up) {
-            matroska->level_up--;
-            break;
-        }
-
-        switch (id) {
-            /* stream info */
-            case MATROSKA_ID_INFO: {
-                res = matroska_parse_info(matroska);
-                break;
-            }
-
-            /* track info headers */
-            case MATROSKA_ID_TRACKS: {
-                res = matroska_parse_tracks(matroska);
-                break;
-            }
-
-            /* stream index */
-            case MATROSKA_ID_CUES: {
-                if (!matroska->index_parsed) {
-                    res = matroska_parse_index(matroska);
-                } else
-                    res = ebml_read_skip(matroska);
-                break;
-            }
-
-            /* metadata */
-            case MATROSKA_ID_TAGS: {
-                if (!matroska->metadata_parsed) {
-                    res = matroska_parse_metadata(matroska);
-                } else
-                    res = ebml_read_skip(matroska);
-                break;
-            }
-
-            /* file index (if seekable, seek to Cues/Tags to parse it) */
-            case MATROSKA_ID_SEEKHEAD: {
-                res = matroska_parse_seekhead(matroska);
-                break;
-            }
-
-            case MATROSKA_ID_ATTACHMENTS: {
-                res = matroska_parse_attachments(s);
-                break;
-            }
-
-            case MATROSKA_ID_CLUSTER: {
-                /* Do not read the master - this will be done in the next
-                 * call to matroska_read_packet. */
-                res = 1;
-                break;
-            }
-
-            case MATROSKA_ID_CHAPTERS: {
-                res = matroska_parse_chapters(s);
-                break;
-            }
-
-            default:
-                av_log(matroska->ctx, AV_LOG_INFO,
-                       "Unknown matroska file header ID 0x%x\n", id);
-            /* fall-through */
-
-            case EBML_ID_VOID:
-                res = ebml_read_skip(matroska);
-                break;
-        }
-
-        if (matroska->level_up) {
-            matroska->level_up--;
-            break;
-        }
-    }
+    if (ebml_parse(matroska, matroska_segments, matroska, 0, 1) < 0)
+        return -1;
     matroska_execute_seekhead(matroska);
 
     /* Have we found a cluster? */
@@ -1781,7 +1654,6 @@
 
         /* What do we do with private data? E.g. for Vorbis. */
     }
-    res = 0;
 
     attachements = attachements_list->elem;
     for (j=0; j<attachements_list->nb_elem; j++) {
@@ -1834,7 +1706,7 @@
         }
     }
 
-    return res;
+    return 0;
 }
 
 static int
@@ -2291,8 +2163,7 @@
     for (n=0; n < matroska->tracks.nb_elem; n++)
         if (tracks[n].type == MATROSKA_TRACK_TYPE_AUDIO)
             av_free(tracks[n].audio.buf);
-    ebml_free(matroska_tracks, matroska);
-    ebml_free(matroska_index, matroska);
+    ebml_free(matroska_segment, matroska);
 
     return 0;
 }