OK, here is an improved version of my previous patch of matroskadec.c that 
manages the palette itself without calling code in mov.c. I have borrowed some 
code from it, though, and I'm including qtpalette.h. One thing I don't 
understand is why the minimum private data size for V_QUICKTIME has been the 
mysterioius value 21 so far, since 86 is the minimum size for a video sample 
description without a palette. So I changed that. As I said before, I have also 
changed the minimum private data size for A_QUICKTIME from 86 to 36, since 36 
is the size of a version 0 sound sample description.
MatsĀ -- 
Mats Peterson
http://matsp888.no-ip.org/~mats/
--- matroskadec.c.orig	2015-12-08 11:01:40.640478749 +0100
+++ matroskadec.c	2015-12-11 12:00:13.000000000 +0100
@@ -62,10 +62,12 @@
 #endif
 #if CONFIG_ZLIB
 #include <zlib.h>
 #endif
 
+#include "qtpalette.h"
+
 typedef enum {
     EBML_NONE,
     EBML_UINT,
     EBML_FLOAT,
     EBML_STR,
@@ -310,10 +312,12 @@
     /* File has SSA subtitles which prevent incremental cluster parsing. */
     int contains_ssa;
 
     /* WebM DASH Manifest live flag/ */
     int is_live;
+
+    uint32_t *pal;
 } MatroskaDemuxContext;
 
 typedef struct MatroskaBlock {
     uint64_t duration;
     int64_t  reference;
@@ -1853,22 +1857,23 @@
             if (ret < 0)
                 return ret;
             codec_id         = st->codec->codec_id;
             extradata_offset = FFMIN(track->codec_priv.size, 18);
         } else if (!strcmp(track->codec_id, "A_QUICKTIME")
-                   && (track->codec_priv.size >= 86)
-                   && (track->codec_priv.data)) {
+                    && (track->codec_priv.size >= 36)
+                    && (track->codec_priv.data)) {
             fourcc = AV_RL32(track->codec_priv.data + 4);
             codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc);
             if (ff_codec_get_id(ff_codec_movaudio_tags, AV_RL32(track->codec_priv.data))) {
                 fourcc = AV_RL32(track->codec_priv.data);
                 codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc);
             }
         } 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);
+                    (track->codec_priv.size >= 86)         &&
+                    (track->codec_priv.data)) {
+            int tmp, greyscale;
+            fourcc = AV_RL32(track->codec_priv.data + 4);
             codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc);
             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);
             }
@@ -1878,10 +1883,80 @@
                 char buf[32];
                 av_get_codec_tag_string(buf, sizeof(buf), fourcc);
                 av_log(matroska->ctx, AV_LOG_ERROR,
                        "mov FourCC not found %s.\n", buf);
             }
+            /* Figure out the palette situation */
+            tmp = AV_RB16(track->codec_priv.data + 82);
+            bit_depth = tmp & 0x1F;
+            greyscale = tmp & 0x20;
+            /* If the depth is 2, 4, or 8 bpp, file is palettized.
+             * Do not create a greyscale palette for Cinepak. */
+            if ((bit_depth == 2 || bit_depth == 4 || bit_depth == 8) &&
+                        !(greyscale && st->codec->codec_id == AV_CODEC_ID_CINEPAK)) {
+                int color_table_id, color_count;
+                uint32_t a, r, g, b;
+                if (! (matroska->pal = av_malloc(AVPALETTE_SIZE)))
+                    return AVERROR(ENOMEM);
+                color_table_id = AV_RB16(track->codec_priv.data + 84);
+                if (greyscale) {
+                    int color_index, color_dec;
+                    /* compute the greyscale palette */
+                    color_count = 1 << bit_depth;
+                    color_index = 255;
+                    color_dec   = 256 / (color_count - 1);
+                    for (i = 0; i < color_count; i++) {
+                        r = g = b = color_index;
+                        matroska->pal[i] = (0xFFU << 24) | (r << 16) | (g << 8) | (b);
+                        color_index -= color_dec;
+                        if (color_index < 0)
+                            color_index = 0;
+                    }
+                } else if (color_table_id) {
+                    /* The color table ID is non-zero. Interpret this as
+                     * being -1, which means use the default Macintosh
+                     * color table */
+                    const uint8_t *color_table;
+                    color_count = 1 << bit_depth;
+                    if (bit_depth == 2)
+                        color_table = ff_qt_default_palette_4;
+                    else if (bit_depth == 4)
+                        color_table = ff_qt_default_palette_16;
+                    else
+                        color_table = ff_qt_default_palette_256;
+                    for (i = 0; i < color_count; i++) {
+                        r = color_table[i * 3 + 0];
+                        g = color_table[i * 3 + 1];
+                        b = color_table[i * 3 + 2];
+                        matroska->pal[i] = (0xFFU << 24) | (r << 16) | (g << 8) | (b);
+                    }
+                } else {
+                    /* The color table ID is 0; the color table is in the
+                     * private data */
+                    color_count = AV_RB16(track->codec_priv.data + 92) + 1;
+                    if (color_count <= 256) {
+                        uint8_t *p = track->codec_priv.data + 94;
+                        for (i = 0; i < color_count; i++) {
+                            /* each A, R, G, or B component is 16 bits;
+                               only use the top 8 bits */
+                            a = *p++; p++;
+                            r = *p++; p++;
+                            g = *p++; p++;
+                            b = *p++; p++;
+                            matroska->pal[i] = (a << 24 ) | (r << 16) | (g << 8) | (b);
+                        }
+                    }
+                }
+                /* Behave like V_MS/VFW/FOURCC; copy the palette to
+                 * extradata */
+                if (! (extradata = av_malloc(AVPALETTE_SIZE))) {
+                    av_freep(&matroska->pal);
+                    return AVERROR(ENOMEM);
+                }
+                memcpy(extradata, matroska->pal, AVPALETTE_SIZE);
+                extradata_size = AVPALETTE_SIZE;
+            }
         } else if (codec_id == AV_CODEC_ID_PCM_S16BE) {
             switch (track->audio.bitdepth) {
             case  8:
                 codec_id = AV_CODEC_ID_PCM_U8;
                 break;
@@ -2322,10 +2397,19 @@
                                    AVPacket *pkt)
 {
     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],
                     (matroska->num_packets - 1) * sizeof(AVPacket *));
             newpackets = av_realloc(matroska->packets,
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to