]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/matroskadec.c
Rework link property configuration system.
[ffmpeg] / libavformat / matroskadec.c
index 19dcdfac49aadf716bf1ed4333abd04a55d689c9..d9fdcec283f64ecf8e6828eda0a88f5721364264 100644 (file)
@@ -94,8 +94,6 @@ typedef struct MatroskaAudioTrack {
 
 typedef struct MatroskaSubtitleTrack {
     MatroskaTrack track;
-
-    int ass;
     //..
 } MatroskaSubtitleTrack;
 
@@ -846,6 +844,24 @@ matroska_queue_packet (MatroskaDemuxContext *matroska,
     matroska->num_packets++;
 }
 
+/*
+ * Free all packets in our internal queue.
+ */
+static void
+matroska_clear_queue (MatroskaDemuxContext *matroska)
+{
+    if (matroska->packets) {
+        int n;
+        for (n = 0; n < matroska->num_packets; n++) {
+            av_free_packet(matroska->packets[n]);
+            av_free(matroska->packets[n]);
+        }
+        av_free(matroska->packets);
+        matroska->packets = NULL;
+        matroska->num_packets = 0;
+    }
+}
+
 
 /*
  * Autodetecting...
@@ -1201,7 +1217,7 @@ matroska_add_stream (MatroskaDemuxContext *matroska)
 
                         /* colorspace (only matters for raw video)
                          * fourcc */
-                        case MATROSKA_ID_VIDEOCOLOURSPACE: {
+                        case MATROSKA_ID_VIDEOCOLORSPACE: {
                             uint64_t num;
                             if ((res = ebml_read_uint(matroska, &id,
                                                       &num)) < 0)
@@ -1849,6 +1865,119 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska)
     return res;
 }
 
+static int
+matroska_parse_attachments(AVFormatContext *s)
+{
+    MatroskaDemuxContext *matroska = s->priv_data;
+    int res = 0;
+    uint32_t id;
+
+    av_log(matroska->ctx, AV_LOG_DEBUG, "parsing attachments...\n");
+
+    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) {
+        case MATROSKA_ID_ATTACHEDFILE: {
+            char* name = NULL;
+            char* mime = NULL;
+            uint8_t* data = NULL;
+            int i, data_size = 0;
+            AVStream *st;
+
+            if ((res = ebml_read_master(matroska, &id)) < 0)
+                break;
+
+            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) {
+                case MATROSKA_ID_FILENAME:
+                    res = ebml_read_utf8 (matroska, &id, &name);
+                    break;
+
+                case MATROSKA_ID_FILEMIMETYPE:
+                    res = ebml_read_ascii (matroska, &id, &mime);
+                    break;
+
+                case MATROSKA_ID_FILEDATA:
+                    res = ebml_read_binary(matroska, &id, &data, &data_size);
+                    break;
+
+                default:
+                    av_log(matroska->ctx, AV_LOG_INFO,
+                           "Unknown attachedfile ID 0x%x\n", id);
+                case EBML_ID_VOID:
+                    res = ebml_read_skip(matroska);
+                    break;
+                }
+
+                if (matroska->level_up) {
+                    matroska->level_up--;
+                    break;
+                }
+            }
+
+            if (!(name && mime && data && data_size > 0)) {
+                av_log(matroska->ctx, AV_LOG_ERROR, "incomplete attachment\n");
+                break;
+            }
+
+            st = av_new_stream(s, matroska->num_streams++);
+            if (st == NULL)
+                return AVERROR(ENOMEM);
+            st->filename = av_strdup(name);
+            st->codec->codec_id = CODEC_ID_NONE;
+            st->codec->codec_type = CODEC_TYPE_ATTACHMENT;
+            st->codec->extradata = av_malloc(data_size);
+            if(st->codec->extradata == NULL)
+                return AVERROR(ENOMEM);
+            st->codec->extradata_size = data_size;
+            memcpy(st->codec->extradata, data, data_size);
+
+            for (i=0; ff_mkv_mime_tags[i].id != CODEC_ID_NONE; i++) {
+                if (!strncmp(ff_mkv_mime_tags[i].str, mime,
+                             strlen(ff_mkv_mime_tags[i].str))) {
+                    st->codec->codec_id = ff_mkv_mime_tags[i].id;
+                    break;
+                }
+            }
+
+            av_log(matroska->ctx, AV_LOG_DEBUG, "new attachment: %s, %s, size %d \n", name, mime, data_size);
+            break;
+        }
+
+        default:
+            av_log(matroska->ctx, AV_LOG_INFO,
+                   "Unknown attachments 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;
+        }
+    }
+
+    return res;
+}
+
 #define ARRAY_SIZE(x)  (sizeof(x)/sizeof(*x))
 
 static int
@@ -1991,6 +2120,13 @@ matroska_read_header (AVFormatContext    *s,
                 break;
             }
 
+            case MATROSKA_ID_ATTACHMENTS: {
+                if ((res = ebml_read_master(matroska, &id)) < 0)
+                    break;
+                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. */
@@ -2032,7 +2168,7 @@ matroska_read_header (AVFormatContext    *s,
             if (track->codec_id == NULL)
                 continue;
 
-            for(j=0; ff_mkv_codec_tags[j].str; j++){
+            for(j=0; ff_mkv_codec_tags[j].id != CODEC_ID_NONE; j++){
                 if(!strncmp(ff_mkv_codec_tags[j].str, track->codec_id,
                             strlen(ff_mkv_codec_tags[j].str))){
                     codec_id= ff_mkv_codec_tags[j].id;
@@ -2098,7 +2234,7 @@ matroska_read_header (AVFormatContext    *s,
                     return AVERROR(ENOMEM);
                 init_put_byte(&b, extradata, extradata_size, 1,
                               NULL, NULL, NULL, NULL);
-                put_buffer(&b, (uint8_t *) "TTA1", 4);
+                put_buffer(&b, "TTA1", 4);
                 put_le16(&b, 1);
                 put_le16(&b, audiotrack->channels);
                 put_le16(&b, audiotrack->bitdepth);
@@ -2143,15 +2279,6 @@ matroska_read_header (AVFormatContext    *s,
                 }
             }
 
-            else if (codec_id == CODEC_ID_TEXT) {
-                MatroskaSubtitleTrack *subtrack=(MatroskaSubtitleTrack *)track;
-                if (!strcmp(track->codec_id, "S_TEXT/ASS") ||
-                    !strcmp(track->codec_id, "S_TEXT/SSA") ||
-                    !strcmp(track->codec_id, "S_ASS") ||
-                    !strcmp(track->codec_id, "S_SSA"))
-                    subtrack->ass = 1;
-            }
-
             if (codec_id == CODEC_ID_NONE) {
                 av_log(matroska->ctx, AV_LOG_INFO,
                        "Unknown/unsupported CodecID %s.\n",
@@ -2268,8 +2395,10 @@ matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size,
         av_free(origdata);
         return res;
     }
-    if (matroska->tracks[track]->stream_index < 0)
+    if (matroska->tracks[track]->stream_index < 0) {
+        av_free(origdata);
         return res;
+    }
     st = matroska->ctx->streams[matroska->tracks[track]->stream_index];
     if (st->discard >= AVDISCARD_ALL) {
         av_free(origdata);
@@ -2287,8 +2416,10 @@ matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size,
         is_keyframe = flags & 0x80 ? PKT_FLAG_KEY : 0;
 
     if (matroska->skip_to_keyframe) {
-        if (!is_keyframe || st != matroska->skip_to_stream)
+        if (!is_keyframe || st != matroska->skip_to_stream) {
+            av_free(origdata);
             return res;
+        }
         matroska->skip_to_keyframe = 0;
     }
 
@@ -2417,14 +2548,6 @@ matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size,
             } else {
                 int offset = 0;
 
-                if (st->codec->codec_id == CODEC_ID_TEXT
-                    && ((MatroskaSubtitleTrack *)(matroska->tracks[track]))->ass) {
-                    int i;
-                    for (i=0; i<8 && data[offset]; offset++)
-                        if (data[offset] == ',')
-                            i++;
-                }
-
                 pkt = av_mallocz(sizeof(AVPacket));
                 /* XXX: prevent data copy... */
                 if (av_new_packet(pkt, lace_size[n]-offset) < 0) {
@@ -2667,11 +2790,12 @@ matroska_read_seek (AVFormatContext *s, int stream_index, int64_t timestamp,
     if (index < 0)
         return 0;
 
+    matroska_clear_queue(matroska);
+
     /* 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;
 }
@@ -2686,13 +2810,7 @@ matroska_read_close (AVFormatContext *s)
     av_free(matroska->muxing_app);
     av_free(matroska->index);
 
-    if (matroska->packets != NULL) {
-        for (n = 0; n < matroska->num_packets; n++) {
-            av_free_packet(matroska->packets[n]);
-            av_free(matroska->packets[n]);
-        }
-        av_free(matroska->packets);
-    }
+    matroska_clear_queue(matroska);
 
     for (n = 0; n < matroska->num_tracks; n++) {
         MatroskaTrack *track = matroska->tracks[n];