[FFmpeg-devel] [PATCH]lavf/matroskadec: Parse stsd atom in mkv with the appropriate mov function

Carl Eugen Hoyos cehoyos at ag.or.at
Mon Dec 14 03:40:14 CET 2015


Hi!

Attached patch based on 3ece3e4c by Martin Storsjö fixes ticket #5071 for me.
I can't see how duplicating the code from mov.c could be acceptable.

Please comment, Carl Eugen
-------------- next part --------------
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index b77e7e8..b82f2a2 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -312,6 +312,8 @@ typedef struct MatroskaDemuxContext {
 
     /* WebM DASH Manifest live flag/ */
     int is_live;
+
+    uint8_t *pal;
 } MatroskaDemuxContext;
 
 typedef struct MatroskaBlock {
@@ -1867,14 +1869,46 @@ static int matroska_parse_tracks(AVFormatContext *s)
         } else if (!strcmp(track->codec_id, "V_QUICKTIME") &&
                    (track->codec_priv.size >= 21)          &&
                    (track->codec_priv.data)) {
-            fourcc   = AV_RL32(track->codec_priv.data + 4);
-            codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc);
+            AVIOContext pb;
+            MOVStreamContext *msc;
+            void *priv_data = st->priv_data;
+            int nb_streams = s->nb_streams;
+            MOVContext *mc = av_mallocz(sizeof(*mc));
+            if (!mc)
+                return AVERROR(ENOMEM);
+            mc->fc = s;
+            st->priv_data = msc = av_mallocz(sizeof(*msc));
+            if (!msc) {
+                av_free(mc);
+                st->priv_data = priv_data;
+                return AVERROR(ENOMEM);
+            }
+            ffio_init_context(&pb, track->codec_priv.data, track->codec_priv.size, 0, NULL, NULL, NULL, NULL);
+            /* ff_mov_read_stsd_entries updates stream s->nb_streams-1,
+             * so set it temporarily to indicate which stream to update. */
+            s->nb_streams = st->index + 1;
+            ff_mov_read_stsd_entries(mc, &pb, 1);
+
+            if (msc->has_palette) {
+                matroska->pal = av_malloc(AVPALETTE_SIZE);
+                if (matroska->pal)
+                    memcpy(matroska->pal, msc->palette, AVPALETTE_SIZE);
+            }
+
+            av_free(msc);
+            av_free(mc);
+            st->priv_data = priv_data;
+            s->nb_streams = nb_streams;
+            codec_id = st->codec->codec_id;
+            fourcc   = st->codec->codec_tag;
+            if (fourcc == AV_RL32("SMI ")) {
+                fourcc = AV_RL32("SVQ3");
+                codec_id = AV_CODEC_ID_SVQ3;
+            }
             if (ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(track->codec_priv.data))) {
                 fourcc   = AV_RL32(track->codec_priv.data);
                 codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc);
             }
-            if (codec_id == AV_CODEC_ID_NONE && AV_RL32(track->codec_priv.data+4) == AV_RL32("SMI "))
-                codec_id = AV_CODEC_ID_SVQ3;
             if (codec_id == AV_CODEC_ID_NONE) {
                 char buf[32];
                 av_get_codec_tag_string(buf, sizeof(buf), fourcc);
@@ -2326,6 +2360,15 @@ static int matroska_deliver_packet(MatroskaDemuxContext *matroska,
     if (matroska->num_packets > 0) {
         memcpy(pkt, matroska->packets[0], sizeof(AVPacket));
         av_freep(&matroska->packets[0]);
+        if (matroska->pal) {
+            uint8_t *pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
+            if (!pal) {
+                av_log(matroska->ctx, AV_LOG_ERROR, "Cannot append palette to packet\n");
+            } else {
+                memcpy(pal, matroska->pal, AVPALETTE_SIZE);
+            }
+            av_freep(&matroska->pal);
+        }
         if (matroska->num_packets > 1) {
             void *newpackets;
             memmove(&matroska->packets[0], &matroska->packets[1],


More information about the ffmpeg-devel mailing list