Here's an interesting one. Windows Media Player won't make any palette
changes without the xxpc chunks beeing indexed.
Fixing the logic for reading and seeking with xxpc chunks in the demuxer
is a future task. Now the muxing of video with xxpc chunks works
properly at least.
Try playing the resulting test.avi file from the command line below with
Windows Media Player, with and without patch 2/3 and 3/3 (you'll need
patch 1/3 in order to get the xxpc chunks properly in the demuxer).
ffmpeg -i TOON.AVI -c:v copy -c:a copy test.avi
Mats
--
Mats Peterson
http://matsp888.no-ip.org/~mats/
>From e60e92cc96c50de0fa81195cc8ed8c97702c7d1b Mon Sep 17 00:00:00 2001
From: Mats Peterson <matsp...@yahoo.com>
Date: Wed, 9 Mar 2016 23:20:56 +0100
Subject: [PATCH 3/3] lavf/avienc: Add xxpc entries to index
---
libavformat/avienc.c | 55 +++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 45 insertions(+), 10 deletions(-)
diff --git a/libavformat/avienc.c b/libavformat/avienc.c
index ad50379..cab8e63 100644
--- a/libavformat/avienc.c
+++ b/libavformat/avienc.c
@@ -44,12 +44,16 @@
*/
typedef struct AVIIentry {
- unsigned int flags, pos, len;
+ char tag[5];
+ unsigned int flags;
+ unsigned int pos;
+ unsigned int len;
} AVIIentry;
#define AVI_INDEX_CLUSTER_SIZE 16384
#define AVISF_VIDEO_PALCHANGES 0x00010000
+#define AVIIF_NO_TIME 0x00000100
typedef struct AVIIndex {
int64_t indx_start;
@@ -612,9 +616,13 @@ static int avi_write_idx1(AVFormatContext *s)
}
if (!empty) {
avist = s->streams[stream_id]->priv_data;
- avi_stream2fourcc(tag, stream_id,
+ if (*ie->tag)
+ ffio_wfourcc(pb, ie->tag);
+ else {
+ avi_stream2fourcc(tag, stream_id,
s->streams[stream_id]->codec->codec_type);
- ffio_wfourcc(pb, tag);
+ ffio_wfourcc(pb, tag);
+ }
avio_wl32(pb, ie->flags);
avio_wl32(pb, ie->pos);
avio_wl32(pb, ie->len);
@@ -673,6 +681,7 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
return avi_write_packet_internal(s, pkt); /* Passthrough */
if (enc->codec_type == AVMEDIA_TYPE_VIDEO) {
+ AVIContext *avi = s->priv_data;
AVIStream *avist = s->streams[stream_index]->priv_data;
AVIOContext *pb = s->pb;
AVPacket *opkt = pkt;
@@ -709,6 +718,39 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
unsigned char tag[5];
avi_stream2fourcc(tag, stream_index, enc->codec_type);
tag[2] = 'p'; tag[3] = 'c';
+ if (s->pb->seekable) {
+ AVIIndex *idx;
+ int cl, id;
+ if (avist->strh_flags_offset) {
+ int64_t cur_offset = avio_tell(pb);
+ avio_seek(pb, avist->strh_flags_offset, SEEK_SET);
+ avio_wl32(pb, AVISF_VIDEO_PALCHANGES);
+ avio_seek(pb, cur_offset, SEEK_SET);
+ avist->strh_flags_offset = 0;
+ }
+ idx = &avist->indexes;
+ cl = idx->entry / AVI_INDEX_CLUSTER_SIZE;
+ id = idx->entry % AVI_INDEX_CLUSTER_SIZE;
+ if (idx->ents_allocated <= idx->entry) {
+ idx->cluster = av_realloc_f(idx->cluster, sizeof(void*), cl+1);
+ if (!idx->cluster) {
+ idx->ents_allocated = 0;
+ idx->entry = 0;
+ return AVERROR(ENOMEM);
+ }
+ idx->cluster[cl] =
+ av_malloc(AVI_INDEX_CLUSTER_SIZE * sizeof(AVIIentry));
+ if (!idx->cluster[cl])
+ return AVERROR(ENOMEM);
+ idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE;
+ }
+ strcpy(idx->cluster[cl][id].tag, tag);
+ idx->cluster[cl][id].flags = AVIIF_NO_TIME;
+ idx->cluster[cl][id].pos = avio_tell(pb) - avi->movi_list;
+ idx->cluster[cl][id].len = pal_size * 4 + 4;
+ avist->max_size = FFMAX(avist->max_size, pal_size * 4 + 4);
+ idx->entry++;
+ }
pc_tag = ff_start_tag(pb, tag);
avio_w8(pb, 0);
avio_w8(pb, pal_size & 0xFF);
@@ -719,13 +761,6 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
}
ff_end_tag(pb, pc_tag);
memcpy(avist->old_palette, avist->palette, pal_size * 4);
- if (pb->seekable && avist->strh_flags_offset) {
- int64_t cur_offset = avio_tell(pb);
- avio_seek(pb, avist->strh_flags_offset, SEEK_SET);
- avio_wl32(pb, AVISF_VIDEO_PALCHANGES);
- avio_seek(pb, cur_offset, SEEK_SET);
- avist->strh_flags_offset = 0;
- }
}
}
}
--
1.7.10.4
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel