On 12/21/2015 10:57 PM, Michael Niedermayer wrote:
the patch is corrupted by newlines attaching the patch uncompressed should solve this disabling automatic line/word wraping in your editor instead might as well
Since I've seen others include the patches inline, I thought it would be safe to do so myself. It looks good at my side at least. Anyway, I'll attach it instead. Better luck this time.
Mats -- Mats Peterson http://matsp888.no-ip.org/~mats/
>From 5720c1f2b73fe576b9d09d10c68c662e98300083 Mon Sep 17 00:00:00 2001 From: Mats Peterson <matsp...@yahoo.com> Date: Mon, 21 Dec 2015 18:02:25 +0100 Subject: [PATCH] libavformat/matroskadec.c,mov.c/qtpalette.c: Fix issue with palettized QuickTime video in Matroska --- libavformat/Makefile | 1 + libavformat/matroskadec.c | 30 ++++++++++++- libavformat/mov.c | 95 ++++++++++------------------------------- libavformat/qtpalette.c | 102 +++++++++++++++++++++++++++++++++++++++++++++ libavformat/qtpalette.h | 2 + 5 files changed, 155 insertions(+), 75 deletions(-) create mode 100644 libavformat/qtpalette.c diff --git a/libavformat/Makefile b/libavformat/Makefile index 110e9e3..e03c73e 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -18,6 +18,7 @@ OBJS = allformats.o \ mux.o \ options.o \ os_support.o \ + qtpalette.o \ riff.o \ sdp.o \ url.o \ diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index c574749..f94f7fb 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -64,6 +64,8 @@ #include <zlib.h> #endif +#include "qtpalette.h" + typedef enum { EBML_NONE, EBML_UINT, @@ -312,6 +314,9 @@ typedef struct MatroskaDemuxContext { /* WebM DASH Manifest live flag/ */ int is_live; + + uint32_t palette[256]; + int has_palette; } MatroskaDemuxContext; typedef struct MatroskaBlock { @@ -1856,7 +1861,7 @@ static int matroska_parse_tracks(AVFormatContext *s) fourcc = st->codec->codec_tag; extradata_offset = FFMIN(track->codec_priv.size, 18); } else if (!strcmp(track->codec_id, "A_QUICKTIME") - && (track->codec_priv.size >= 86) + && (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); @@ -1865,7 +1870,7 @@ static int matroska_parse_tracks(AVFormatContext *s) 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.size >= 86) && (track->codec_priv.data)) { fourcc = AV_RL32(track->codec_priv.data + 4); codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc); @@ -1881,6 +1886,18 @@ static int matroska_parse_tracks(AVFormatContext *s) av_log(matroska->ctx, AV_LOG_ERROR, "mov FourCC not found %s.\n", buf); } + bit_depth = AV_RB16(track->codec_priv.data + 82); + if (get_qtpalette(codec_id, track->codec_priv.data + 16, + matroska->palette)) { + bit_depth &= 0x1F; + /* Behave like V_MS/VFW/FOURCC; copy the palette to + * extradata */ + if (! (extradata = av_malloc(AVPALETTE_SIZE))) + return AVERROR(ENOMEM); + memcpy(extradata, matroska->palette, AVPALETTE_SIZE); + extradata_size = AVPALETTE_SIZE; + matroska->has_palette = 1; + } } else if (codec_id == AV_CODEC_ID_PCM_S16BE) { switch (track->audio.bitdepth) { case 8: @@ -2326,6 +2343,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->has_palette) { + 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->palette, AVPALETTE_SIZE); + } + matroska->has_palette = 0; + } if (matroska->num_packets > 1) { void *newpackets; memmove(&matroska->packets[0], &matroska->packets[1], diff --git a/libavformat/mov.c b/libavformat/mov.c index 06e80c8..1c54bb7 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1751,13 +1751,21 @@ static int mov_codec_id(AVStream *st, uint32_t format) return id; } -static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb, - AVStream *st, MOVStreamContext *sc) +static int mov_parse_stsd_video(MOVContext *c, AVIOContext *pb, + AVStream *st, MOVStreamContext *sc, + int size) { + uint8_t *stsd; uint8_t codec_name[32]; - unsigned int color_depth, len, j; - int color_greyscale; - int color_table_id; + int64_t pos; + unsigned int len; + + if (! (stsd = av_malloc(size))) + return AVERROR(ENOMEM); + + pos = avio_tell(pb); + avio_read(pb, stsd, size); + avio_seek(pb, pos, SEEK_SET); avio_rb16(pb); /* version */ avio_rb16(pb); /* revision level */ @@ -1795,76 +1803,15 @@ static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb, st->codec->codec_id = AV_CODEC_ID_FLV1; st->codec->bits_per_coded_sample = avio_rb16(pb); /* depth */ - color_table_id = avio_rb16(pb); /* colortable id */ - av_log(c->fc, AV_LOG_TRACE, "depth %d, ctab id %d\n", - st->codec->bits_per_coded_sample, color_table_id); - /* figure out the palette situation */ - color_depth = st->codec->bits_per_coded_sample & 0x1F; - color_greyscale = st->codec->bits_per_coded_sample & 0x20; - /* Do not create a greyscale palette for cinepak */ - if (color_greyscale && st->codec->codec_id == AV_CODEC_ID_CINEPAK) - return; + avio_rb16(pb); /* colortable id */ - /* if the depth is 2, 4, or 8 bpp, file is palettized */ - if ((color_depth == 2) || (color_depth == 4) || (color_depth == 8)) { - /* for palette traversal */ - unsigned int color_start, color_count, color_end; - unsigned int a, r, g, b; - - if (color_greyscale) { - int color_index, color_dec; - /* compute the greyscale palette */ - st->codec->bits_per_coded_sample = color_depth; - color_count = 1 << color_depth; - color_index = 255; - color_dec = 256 / (color_count - 1); - for (j = 0; j < color_count; j++) { - r = g = b = color_index; - sc->palette[j] = (0xFFU << 24) | (r << 16) | (g << 8) | (b); - color_index -= color_dec; - if (color_index < 0) - color_index = 0; - } - } else if (color_table_id) { - const uint8_t *color_table; - /* if flag bit 3 is set, use the default palette */ - color_count = 1 << color_depth; - if (color_depth == 2) - color_table = ff_qt_default_palette_4; - else if (color_depth == 4) - color_table = ff_qt_default_palette_16; - else - color_table = ff_qt_default_palette_256; - - for (j = 0; j < color_count; j++) { - r = color_table[j * 3 + 0]; - g = color_table[j * 3 + 1]; - b = color_table[j * 3 + 2]; - sc->palette[j] = (0xFFU << 24) | (r << 16) | (g << 8) | (b); - } - } else { - /* load the palette from the file */ - color_start = avio_rb32(pb); - color_count = avio_rb16(pb); - color_end = avio_rb16(pb); - if ((color_start <= 255) && (color_end <= 255)) { - for (j = color_start; j <= color_end; j++) { - /* each A, R, G, or B component is 16 bits; - * only use the top 8 bits */ - a = avio_r8(pb); - avio_r8(pb); - r = avio_r8(pb); - avio_r8(pb); - g = avio_r8(pb); - avio_r8(pb); - b = avio_r8(pb); - avio_r8(pb); - sc->palette[j] = (a << 24 ) | (r << 16) | (g << 8) | (b); - } - } - } + if (get_qtpalette(st->codec->codec_id, stsd, sc->palette)) { + st->codec->bits_per_coded_sample &= 0x1F; sc->has_palette = 1; } + + av_free(stsd); + return 0; } static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb, @@ -2242,7 +2189,9 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) if (st->codec->codec_type==AVMEDIA_TYPE_VIDEO) { st->codec->codec_id = id; - mov_parse_stsd_video(c, pb, st, sc); + ret = mov_parse_stsd_video(c, pb, st, sc, size - 16); + if (ret < 0) + return ret; } else if (st->codec->codec_type==AVMEDIA_TYPE_AUDIO) { st->codec->codec_id = id; mov_parse_stsd_audio(c, pb, st, sc); diff --git a/libavformat/qtpalette.c b/libavformat/qtpalette.c new file mode 100644 index 0000000..373602f --- /dev/null +++ b/libavformat/qtpalette.c @@ -0,0 +1,102 @@ +/* + * QuickTime palette handling + * Copyright (c) 2015 Mats Peterson + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdio.h> +#include <inttypes.h> + +#include "libavcodec/avcodec.h" +#include "libavutil/intreadwrite.h" +#include "qtpalette.h" + +int get_qtpalette(int codec_id, uint8_t *stsd, uint32_t *palette) +{ + int tmp, bit_depth, greyscale, i; + + /* Get the bit depth and greyscale state */ + tmp = AV_RB16(stsd + 66); + bit_depth = tmp & 0x1F; + greyscale = tmp & 0x20; + + /* Do not create a greyscale palette for Cinepak */ + if (greyscale && codec_id == AV_CODEC_ID_CINEPAK) + return 0; + + /* If the depth is 2, 4, or 8 bpp, file is palettized. */ + if ((bit_depth == 2 || bit_depth == 4 || bit_depth == 8)) { + int color_table_id, color_count; + uint32_t a, r, g, b; + + color_table_id = AV_RB16(stsd + 68); + + 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; + palette[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]; + palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | (b); + } + } else { + /* The color table ID is 0; the color table is in the sample + * description */ + color_count = AV_RB16(stsd + 76) + 1; + if (color_count <= 256) { + uint8_t *p = stsd + 78; + 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++; + palette[i] = (a << 24 ) | (r << 16) | (g << 8) | (b); + } + } + } + + return 1; + } + + return 0; +} diff --git a/libavformat/qtpalette.h b/libavformat/qtpalette.h index 7d6802f..f0e92b3 100644 --- a/libavformat/qtpalette.h +++ b/libavformat/qtpalette.h @@ -310,4 +310,6 @@ static const uint8_t ff_qt_default_palette_256[256 * 3] = { /* 255, 0xFF */ 0x00, 0x00, 0x00 }; +int get_qtpalette(int codec_id, uint8_t *stsd, uint32_t *palette); + #endif /* AVFORMAT_QTPALETTE_H */ -- 1.7.10.4
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel