Made some changes based on your comments, Michael. Here's an interesting one. Windows Media Player won't make any palette changes without the xxpc chunks being 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 this patch.
ffmpeg -i TOON.AVI -c:v copy -c:a copy test.avi Mats
>From 44c4c77d7bfbab1ff014192a4812ccbe80c0ca02 Mon Sep 17 00:00:00 2001 From: Mats Peterson <matsp...@yahoo.com> Date: Sat, 12 Mar 2016 16:00:17 +0100 Subject: [PATCH 2/2 v2] lavf/avienc: Add 'xxpc' entries to index --- libavformat/avi.h | 6 ++- libavformat/avienc.c | 97 ++++++++++++++++++++++++++---------------- tests/ref/lavf-fate/avi_cram | 4 +- 3 files changed, 68 insertions(+), 39 deletions(-) diff --git a/libavformat/avi.h b/libavformat/avi.h index 34da76f..af21f2c 100644 --- a/libavformat/avi.h +++ b/libavformat/avi.h @@ -32,7 +32,11 @@ #define AVI_MASTER_INDEX_SIZE 256 #define AVI_MAX_STREAM_COUNT 100 +/* stream header flags */ +#define AVISF_VIDEO_PALCHANGES 0x00010000 + /* index flags */ -#define AVIIF_INDEX 0x10 +#define AVIIF_INDEX 0x00000010 +#define AVIIF_NO_TIME 0x00000100 #endif /* AVFORMAT_AVI_H */ diff --git a/libavformat/avienc.c b/libavformat/avienc.c index ad50379..7ee35ce 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -44,13 +44,14 @@ */ typedef struct AVIIentry { - unsigned int flags, pos, len; + char tag[4]; + unsigned int flags; + unsigned int pos; + unsigned int len; } AVIIentry; #define AVI_INDEX_CLUSTER_SIZE 16384 -#define AVISF_VIDEO_PALCHANGES 0x00010000 - typedef struct AVIIndex { int64_t indx_start; int64_t audio_strm_offset; @@ -96,6 +97,43 @@ static inline AVIIentry *avi_get_ientry(const AVIIndex *idx, int ent_id) return &idx->cluster[cl][id]; } +static int avi_add_ientry(AVFormatContext *s, int stream_index, char *tag, + unsigned int flags, unsigned int size) +{ + AVIContext *avi = s->priv_data; + AVIOContext *pb = s->pb; + AVIStream *avist = s->streams[stream_index]->priv_data; + AVIIndex *idx = &avist->indexes; + int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE; + int 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; + } + + if (tag) + memcpy(idx->cluster[cl][id].tag, tag, 4); + else + *(idx->cluster[cl][id].tag) = '\0'; + idx->cluster[cl][id].flags = flags; + idx->cluster[cl][id].pos = avio_tell(pb) - avi->movi_list; + idx->cluster[cl][id].len = size; + avist->max_size = FFMAX(avist->max_size, size); + idx->entry++; + + return 0; +} + static int64_t avi_start_new_riff(AVFormatContext *s, AVIOContext *pb, const char *riff_tag, const char *list_tag) { @@ -612,9 +650,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); @@ -654,6 +696,7 @@ static int write_skip_frames(AVFormatContext *s, int stream_index, int64_t dts) return 0; } + static int avi_write_packet(AVFormatContext *s, AVPacket *pkt) { const int stream_index = pkt->stream_index; @@ -709,6 +752,17 @@ 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) { + 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; + } + avi_add_ientry(s, stream_index, tag, AVIIF_NO_TIME, + pal_size * 4 + 4); + } pc_tag = ff_start_tag(pb, tag); avio_w8(pb, 0); avio_w8(pb, pal_size & 0xFF); @@ -719,13 +773,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; - } } } } @@ -774,30 +821,8 @@ static int avi_write_packet_internal(AVFormatContext *s, AVPacket *pkt) if (enc->codec_type == AVMEDIA_TYPE_AUDIO) avist->audio_strm_length += size; - if (s->pb->seekable) { - AVIIndex *idx = &avist->indexes; - int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE; - int 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; - } - - idx->cluster[cl][id].flags = flags; - idx->cluster[cl][id].pos = avio_tell(pb) - avi->movi_list; - idx->cluster[cl][id].len = size; - avist->max_size = FFMAX(avist->max_size, size); - idx->entry++; - } + if (s->pb->seekable) + avi_add_ientry(s, stream_index, NULL, flags, size); avio_write(pb, tag, 4); avio_wl32(pb, size); diff --git a/tests/ref/lavf-fate/avi_cram b/tests/ref/lavf-fate/avi_cram index 7b4e69c..82882fb 100644 --- a/tests/ref/lavf-fate/avi_cram +++ b/tests/ref/lavf-fate/avi_cram @@ -1,3 +1,3 @@ -ba77c5c8bd2b0d1e0478d143346cc3b3 *./tests/data/lavf-fate/lavf.avi -928228 ./tests/data/lavf-fate/lavf.avi +6fc88702c23b895c305c5e1f51a0904e *./tests/data/lavf-fate/lavf.avi +928260 ./tests/data/lavf-fate/lavf.avi ./tests/data/lavf-fate/lavf.avi CRC=0xa4770de2 -- 1.7.10.4
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel