Here's a somewhat experimental patch with a new AVOption write_keyframe_palette that allows you to write the palette to every keyframe. It is disabled by default, but it is needed for any file that contains palette changes in order to switch palette properly in FFplay (and, in the future, probably MPlayer, unless it manages to solve it in a different way).

It's interesting to note that Windows Media Player doesn't need xxpc chunks at keyframes in order to seek properly in the original file TOON.AVI below from Sierra's King's Quest VI. I have of course no idea how they solve that.

This file doesn't work properly in FFplay for some reason. It generates "stream_ptr out of bounds" messages at the locations of the xxpc chunks.

It seems it has something to do with the index, since if I copy it to a new file with the last part cut off (incorrect but it will play at least), those "stream_ptr out of bounds" messages will disappear, and the palette changes will occur as expected.

TOON.AVI:
https://drive.google.com/open?id=0B3_pEBoLs0faaFY0ME92SDA1VEU

Mats

--
Mats Peterson
http://matsp888.no-ip.org/~mats/
>From 6440fffa2d5b7f8b354c6307baaf506cbe754609 Mon Sep 17 00:00:00 2001
From: Mats Peterson <matsp...@yahoo.com>
Date: Tue, 8 Mar 2016 11:37:34 +0100
Subject: [PATCH 2/2] lavf/avienc: New AVOption write_keyframe_palette

---
 libavformat/avienc.c |   10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/libavformat/avienc.c b/libavformat/avienc.c
index ad50379..2367d80 100644
--- a/libavformat/avienc.c
+++ b/libavformat/avienc.c
@@ -66,6 +66,7 @@ typedef struct AVIContext {
     int64_t frames_hdr_all;
     int riff_id;
     int write_channel_mask;
+    int write_keyframe_palette;
 } AVIContext;
 
 typedef struct AVIStream {
@@ -674,6 +675,7 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
 
     if (enc->codec_type == AVMEDIA_TYPE_VIDEO) {
         AVIStream *avist = s->streams[stream_index]->priv_data;
+        AVIContext *avi  = s->priv_data;
         AVIOContext *pb  = s->pb;
         AVPacket *opkt   = pkt;
         if (enc->codec_id == AV_CODEC_ID_RAWVIDEO && enc->codec_tag == 0) {
@@ -688,13 +690,13 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
             int ret2 = ff_get_packet_palette(s, opkt, ret, avist->palette);
             if (ret2 < 0)
                 return ret2;
-            if (ret2) {
+            if (ret2 || (avi->write_keyframe_palette && (pkt->flags & AV_PKT_FLAG_KEY))) {
                 int pal_size = 1 << enc->bits_per_coded_sample;
                 int pc_tag, i;
 
                 av_assert0(enc->bits_per_coded_sample >= 0 && enc->bits_per_coded_sample <= 8);
 
-                if (pb->seekable && avist->pal_offset) {
+                if (ret2 && pb->seekable && avist->pal_offset) {
                     int64_t cur_offset = avio_tell(pb);
                     avio_seek(pb, avist->pal_offset, SEEK_SET);
                     for (i = 0; i < pal_size; i++) {
@@ -705,7 +707,8 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
                     memcpy(avist->old_palette, avist->palette, pal_size * 4);
                     avist->pal_offset = 0;
                 }
-                if (memcmp(avist->palette, avist->old_palette, pal_size * 4)) {
+                if (memcmp(avist->palette, avist->old_palette, pal_size * 4) ||
+                    (avi->write_keyframe_palette && (pkt->flags & AV_PKT_FLAG_KEY))) {
                     unsigned char tag[5];
                     avi_stream2fourcc(tag, stream_index, enc->codec_type);
                     tag[2] = 'p'; tag[3] = 'c';
@@ -875,6 +878,7 @@ static int avi_write_trailer(AVFormatContext *s)
 #define ENC AV_OPT_FLAG_ENCODING_PARAM
 static const AVOption options[] = {
     { "write_channel_mask", "write channel mask into wave format header", OFFSET(write_channel_mask), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, ENC },
+    { "write_keyframe_palette", "write palette at keyframes", OFFSET(write_keyframe_palette), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC },
     { NULL },
 };
 
-- 
1.7.10.4

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to