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