[FFmpeg-devel] [RFC] [PATCH] iff: ANIM suppport
Peter Ross
pross at xvid.org
Sun Jul 22 07:21:55 CEST 2012
On Sun, Jul 22, 2012 at 03:31:34AM +0000, Paul B Mahol wrote:
> Signed-off-by: Paul B Mahol <onemda at gmail.com>
> ---
> Currently only first frame is decoded correctly.
>
> The reason I post this patch is to show why rewritting code is required.
>
> No, I do not plan to separate this patch in smaller patches because it
> is mostly pointless.
Tranforming an (already ugly) image demuxer into an image+video demuxer is always
going to be messy. But spliting up patches is never pointless; it simplifies the
review and improves utility of git-bitsect.
> ---
> libavcodec/iff.c | 161 ++++++++++--------------
> libavformat/iff.c | 359 +++++++++++++++++++++++++++++------------------------
> 2 files changed, 261 insertions(+), 259 deletions(-)
>
> diff --git a/libavcodec/iff.c b/libavcodec/iff.c
> index 57ce570..c8f2339 100644
> --- a/libavcodec/iff.c
> +++ b/libavcodec/iff.c
> @@ -42,6 +42,7 @@ typedef struct {
> AVFrame frame;
> int planesize;
> uint8_t * planebuf;
> + int planebuf_size;
> uint8_t * ham_buf; ///< temporary buffer for planar to chunky conversation
> uint32_t *ham_palbuf; ///< HAM decode table
> uint32_t *mask_buf; ///< temporary buffer for palette indices
> @@ -52,7 +53,6 @@ typedef struct {
> unsigned flags; ///< 1 for EHB, 0 is no extra half darkening
> unsigned transparency; ///< TODO: transparency color index in palette
> unsigned masking; ///< TODO: masking method used
> - int init; // 1 if buffer and palette data already initialized, 0 otherwise
> } IffContext;
>
> #define LUT8_PART(plane, v) \
> @@ -135,22 +135,28 @@ static av_always_inline uint32_t gray2rgb(const uint32_t x) {
> }
>
> /**
> - * Convert CMAP buffer (stored in extradata) to lavc palette format
> + * Convert CMAP buffer (stored in packet side data) to lavc palette format
> */
> -static int ff_cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
> +static int ff_cmap_read_palette(AVCodecContext *avctx, AVPacket *avpkt, uint32_t *pal)
> {
> IffContext *s = avctx->priv_data;
> int count, i;
> - const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
> - int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
> + const uint8_t *palette;
> + int palette_size;
> +
> + if (avpkt->side_data_elems <= 0 ||
> + avpkt->side_data[0].type != AV_PKT_DATA_PALETTE)
> + return AVERROR_INVALIDDATA;
>
> + palette = avpkt->side_data[0].data;
> + palette_size = avpkt->side_data[0].size;
> if (avctx->bits_per_coded_sample > 8) {
> - av_log(avctx, AV_LOG_ERROR, "bit_per_coded_sample > 8 not supported\n");
> + av_log(avctx, AV_LOG_ERROR, "bits_per_coded_sample > 8 not supported\n");
Unrelated.
> return AVERROR_INVALIDDATA;
> }
>
> count = 1 << avctx->bits_per_coded_sample;
> - // If extradata is smaller than actually needed, fill the remaining with black.
> + // If palette_size is smaller than actually needed, fill the remaining with black.
> count = FFMIN(palette_size / 3, count);
> if (count) {
> for (i=0; i < count; i++) {
The extradata to side_data changeover ought to have been done in a separate patch.
> @@ -187,49 +193,54 @@ static int ff_cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
> * @return 0 in case of success, a negative error code otherwise
> */
> static int extract_header(AVCodecContext *const avctx,
> - const AVPacket *const avpkt) {
> - const uint8_t *buf;
> + const AVPacket *const avpkt)
> +{
> + const uint8_t *palette;
> unsigned buf_size;
> IffContext *s = avctx->priv_data;
> - int palette_size;
> + int palette_size = 0;
> + GetByteContext gb;
> +
> + s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
> + av_fast_padded_malloc(&s->planebuf, &s->planebuf_size, s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
> + if (!s->planebuf)
> + return AVERROR(ENOMEM);
>
> - if (avctx->extradata_size < 2) {
> - av_log(avctx, AV_LOG_ERROR, "not enough extradata\n");
> + s->bpp = avctx->bits_per_coded_sample;
> + if (avpkt->size < 2)
> return AVERROR_INVALIDDATA;
> +
> + if (avpkt->side_data_elems > 0 &&
> + avpkt->side_data[0].type == AV_PKT_DATA_PALETTE) {
> + palette_size = avpkt->side_data[0].size;
> + palette = avpkt->side_data[0].data;
> }
> - palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
>
> - if (avpkt) {
> - int image_size;
> - if (avpkt->size < 2)
> - return AVERROR_INVALIDDATA;
> - image_size = avpkt->size - AV_RB16(avpkt->data);
> - buf = avpkt->data;
> - buf_size = bytestream_get_be16(&buf);
> - if (buf_size <= 1 || image_size <= 1) {
> - av_log(avctx, AV_LOG_ERROR,
> - "Invalid image size received: %u -> image data offset: %d\n",
> - buf_size, image_size);
> - return AVERROR_INVALIDDATA;
> - }
> + if (avctx->bits_per_coded_sample <= 8) {
> + avctx->pix_fmt = avctx->bits_per_coded_sample < 8 ||
> + palette_size ? PIX_FMT_PAL8 : PIX_FMT_GRAY8;
> + } else if (avctx->bits_per_coded_sample <= 32) {
> + if (avctx->codec_tag != MKTAG('D','E','E','P'))
> + avctx->pix_fmt = PIX_FMT_BGR32;
> } else {
> - buf = avctx->extradata;
> - buf_size = bytestream_get_be16(&buf);
> - if (buf_size <= 1 || palette_size < 0) {
> - av_log(avctx, AV_LOG_ERROR,
> - "Invalid palette size received: %u -> palette data offset: %d\n",
> - buf_size, palette_size);
> - return AVERROR_INVALIDDATA;
> - }
> + return AVERROR_INVALIDDATA;
> + }
> +
> + bytestream2_init(&gb, avctx->extradata, avctx->extradata_size);
> + buf_size = bytestream2_get_be16(&gb);
> + if (buf_size <= 1) {
> + av_log(avctx, AV_LOG_ERROR,
> + "Invalid image size received: %u\n", buf_size);
> + return AVERROR_INVALIDDATA;
> }
>
> if (buf_size > 8) {
> - s->compression = bytestream_get_byte(&buf);
> - s->bpp = bytestream_get_byte(&buf);
> - s->ham = bytestream_get_byte(&buf);
> - s->flags = bytestream_get_byte(&buf);
> - s->transparency = bytestream_get_be16(&buf);
> - s->masking = bytestream_get_byte(&buf);
> + s->compression = bytestream2_get_byte(&gb);
> + s->bpp = bytestream2_get_byte(&gb);
> + s->ham = bytestream2_get_byte(&gb);
> + s->flags = bytestream2_get_byte(&gb);
> + s->transparency = bytestream2_get_be16(&gb);
> + s->masking = bytestream2_get_byte(&gb);
Ditto for the bytestream2 upgrade here.
> if (s->masking == MASK_HAS_MASK) {
> if (s->bpp >= 8) {
> avctx->pix_fmt = PIX_FMT_RGB32;
> @@ -263,7 +274,6 @@ static int extract_header(AVCodecContext *const avctx,
> if (s->ham) {
> int i, count = FFMIN(palette_size / 3, 1 << s->ham);
> int ham_count;
> - const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
>
> s->ham_buf = av_malloc((s->planesize * 8) + FF_INPUT_BUFFER_PADDING_SIZE);
> if (!s->ham_buf)
> @@ -313,36 +323,8 @@ static int extract_header(AVCodecContext *const avctx,
> static av_cold int decode_init(AVCodecContext *avctx)
> {
> IffContext *s = avctx->priv_data;
> - int err;
> -
> - if (avctx->bits_per_coded_sample <= 8) {
> - int palette_size;
> -
> - if (avctx->extradata_size >= 2)
> - palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
> - else
> - palette_size = 0;
> - avctx->pix_fmt = (avctx->bits_per_coded_sample < 8) ||
> - (avctx->extradata_size >= 2 && palette_size) ? PIX_FMT_PAL8 : PIX_FMT_GRAY8;
> - } else if (avctx->bits_per_coded_sample <= 32) {
> - if (avctx->codec_tag != MKTAG('D','E','E','P'))
> - avctx->pix_fmt = PIX_FMT_BGR32;
> - } else {
> - return AVERROR_INVALIDDATA;
> - }
>
> - if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
> - return err;
> - s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
> - s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
> - if (!s->planebuf)
> - return AVERROR(ENOMEM);
> -
> - s->bpp = avctx->bits_per_coded_sample;
> avcodec_get_frame_defaults(&s->frame);
> -
> - if ((err = extract_header(avctx, NULL)) < 0)
> - return err;
> s->frame.reference = 3;
>
> return 0;
> @@ -467,27 +449,22 @@ static int decode_frame_ilbm(AVCodecContext *avctx,
> AVPacket *avpkt)
> {
> IffContext *s = avctx->priv_data;
> - const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
> - const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
> + const uint8_t *buf = avpkt->data;
> + const int buf_size = avpkt->size;
> const uint8_t *buf_end = buf+buf_size;
> int y, plane, res;
>
> if ((res = extract_header(avctx, avpkt)) < 0)
> return res;
>
> - if (s->init) {
> - if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
> - av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
> - return res;
> - }
> - } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
> - av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
> + if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
> + av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
> return res;
> - } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt == PIX_FMT_PAL8) {
> - if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
> + }
> + if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt == PIX_FMT_PAL8) {
> + if ((res = ff_cmap_read_palette(avctx, avpkt, (uint32_t*)s->frame.data[1])) < 0)
> return res;
> }
> - s->init = 1;
>
> if (avctx->codec_tag == MKTAG('A','C','B','M')) {
> if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
> @@ -585,29 +562,25 @@ static int decode_frame_byterun1(AVCodecContext *avctx,
> AVPacket *avpkt)
> {
> IffContext *s = avctx->priv_data;
> - const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
> - const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
> + const uint8_t *buf = avpkt->data;
> + const int buf_size = avpkt->size;
> const uint8_t *buf_end = buf+buf_size;
> int y, plane, res;
>
> if ((res = extract_header(avctx, avpkt)) < 0)
> return res;
> - if (s->init) {
> - if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
> - av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
> - return res;
> - }
> - } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
> - av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
> +
> + if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
> + av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
> return res;
> - } else if (avctx->pix_fmt == PIX_FMT_PAL8) {
> - if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
> + }
> + if (avctx->pix_fmt == PIX_FMT_PAL8) {
> + if ((res = ff_cmap_read_palette(avctx, avpkt, (uint32_t*)s->frame.data[1])) < 0)
> return res;
> } else if (avctx->pix_fmt == PIX_FMT_RGB32 && avctx->bits_per_coded_sample <= 8) {
> - if ((res = ff_cmap_read_palette(avctx, s->mask_palbuf)) < 0)
> + if ((res = ff_cmap_read_palette(avctx, avpkt, s->mask_palbuf)) < 0)
> return res;
> }
> - s->init = 1;
>
> if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
> if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
> diff --git a/libavformat/iff.c b/libavformat/iff.c
> index cd3d5be..d9b043a 100644
> --- a/libavformat/iff.c
> +++ b/libavformat/iff.c
> @@ -61,6 +61,9 @@
> #define ID_BODY MKTAG('B','O','D','Y')
> #define ID_DBOD MKTAG('D','B','O','D')
> #define ID_DPEL MKTAG('D','P','E','L')
> +#define ID_ANIM MKTAG('A','N','I','M')
> +#define ID_ANHD MKTAG('A','N','H','D')
Is ANHD needed for playback?
> +#define ID_DLTA MKTAG('D','L','T','A')
>
> #define LEFT 2
> #define RIGHT 4
> @@ -70,9 +73,7 @@
> * This number of bytes if added at the beginning of each AVPacket
> * which contain additional information about video properties
> * which has to be shared between demuxer and decoder.
> - * This number may change between frames, e.g. the demuxer might
> - * set it to smallest possible size of 2 to indicate that there's
> - * no extradata changing in this frame.
> + * This number may change between frames.
> */
> #define IFF_EXTRA_VIDEO_SIZE 9
>
> @@ -88,16 +89,10 @@ typedef enum {
> } bitmap_compression_type;
>
> typedef struct {
> - uint64_t body_pos;
> - uint32_t body_size;
> - uint32_t sent_bytes;
> - svx8_compression_type svx8_compression;
> - bitmap_compression_type bitmap_compression; ///< delta compression method used
> - unsigned bpp; ///< bits per plane to decode (differs from bits_per_coded_sample if HAM)
> - unsigned ham; ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise)
> - unsigned flags; ///< 1 for EHB, 0 is no extra half darkening
> - unsigned transparency; ///< transparency color index in palette
> - unsigned masking; ///< masking method used
> + int tag;
> + uint32_t form_size;
> + uint8_t *palette;
> + int palette_size;
> } IffDemuxContext;
>
> /* Metadata string read */
> @@ -119,12 +114,27 @@ static int get_metadata(AVFormatContext *s,
> return 0;
> }
>
> +static int create_stream(AVFormatContext *s, AVStream **st)
> +{
> + if (*st)
> + return AVERROR_INVALIDDATA;
> + *st = avformat_new_stream(s, NULL);
> + if (!*st)
> + return AVERROR(ENOMEM);
> + return 0;
> +}
> +
> static int iff_probe(AVProbeData *p)
> {
> const uint8_t *d = p->buf;
>
> - if ( AV_RL32(d) == ID_FORM &&
> - (AV_RL32(d+8) == ID_8SVX || AV_RL32(d+8) == ID_PBM || AV_RL32(d+8) == ID_ACBM || AV_RL32(d+8) == ID_DEEP || AV_RL32(d+8) == ID_ILBM) )
> + if ( AV_RL32(d) == ID_FORM &&
> + (AV_RL32(d+8) == ID_8SVX ||
> + AV_RL32(d+8) == ID_PBM ||
> + AV_RL32(d+8) == ID_ACBM ||
> + AV_RL32(d+8) == ID_DEEP ||
> + AV_RL32(d+8) == ID_ILBM ||
> + AV_RL32(d+8) == ID_ANIM))
Ok. But would have done this separately.
> return AVPROBE_SCORE_MAX;
> return 0;
> }
> @@ -136,127 +146,178 @@ static int iff_read_header(AVFormatContext *s)
> {
> IffDemuxContext *iff = s->priv_data;
> AVIOContext *pb = s->pb;
> - AVStream *st;
> + s->ctx_flags |= AVFMTCTX_NOHEADER;
> +
> + if (avio_rl32(pb) != ID_FORM)
> + return AVERROR_INVALIDDATA;
> + iff->form_size = avio_rb32(pb);
> +
> + iff->tag = avio_rl32(pb);
> + if (iff->tag == ID_ANIM) {
> + if (avio_rl32(pb) != ID_FORM)
> + return AVERROR_INVALIDDATA;
> + iff->form_size = avio_rb32(pb);
> + iff->tag = avio_rl32(pb);
> + if (iff->tag != ID_ILBM)
> + return AVERROR_INVALIDDATA;
> + }
> +
> + return 0;
> +}
> +
> +static int iff_read_packet(AVFormatContext *s, AVPacket *pkt)
> +{
> + bitmap_compression_type bitmap_compression; ///< delta compression method used
> + unsigned bpp; ///< bits per plane to decode (differs from bits_per_coded_sample if HAM)
> + unsigned ham; ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise)
> + unsigned flags; ///< 1 for EHB, 0 is no extra half darkening
> + unsigned transparency = 0; ///< transparency color index in palette
> + IffDemuxContext *iff = s->priv_data;
> + AVIOContext *pb = s->pb;
> + AVStream *st = NULL;
> uint8_t *buf;
> - uint32_t chunk_id, data_size;
> + uint32_t chunk_id, chunk_size, palette_size = 0;
Why s/data_size/chunk_size/g? and s/orig_pos/chunk_pos? This adds a pile of text changes, that could have been done before after.
> + uint64_t chunk_pos;
> uint32_t screenmode = 0;
> - unsigned transparency = 0;
> unsigned masking = 0; // no mask
> uint8_t fmt[16];
> - int fmt_size;
> -
> - st = avformat_new_stream(s, NULL);
> - if (!st)
> - return AVERROR(ENOMEM);
> + int tag, ret, compr = 0, fmt_size, channels = 1;
>
> - st->codec->channels = 1;
> - avio_skip(pb, 8);
> - // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content
> - st->codec->codec_tag = avio_rl32(pb);
> + tag = iff->tag;
> + if (url_feof(pb))
> + return AVERROR_EOF;
>
> - while(!url_feof(pb)) {
> - uint64_t orig_pos;
> - int res;
> + while (!url_feof(pb)) {
> const char *metadata_tag = NULL;
> - chunk_id = avio_rl32(pb);
> - data_size = avio_rb32(pb);
> - orig_pos = avio_tell(pb);
> +
> + chunk_id = avio_rl32(pb);
> + chunk_size = avio_rb32(pb);
> + chunk_pos = avio_tell(pb);
>
> switch(chunk_id) {
> + case ID_FORM:
> + iff->tag = avio_rl32(pb);
> + goto done;
> case ID_VHDR:
> - st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
> -
> - if (data_size < 14)
> + if (chunk_size < 14)
> return AVERROR_INVALIDDATA;
> + if ((ret = create_stream(s, &st)) < 0)
> + return ret;
> + st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
> avio_skip(pb, 12);
> st->codec->sample_rate = avio_rb16(pb);
> - if (data_size >= 16) {
> + if (chunk_size >= 16) {
> avio_skip(pb, 1);
> - iff->svx8_compression = avio_r8(pb);
> + compr = avio_r8(pb);
> }
> + switch (compr) {
> + case COMP_NONE:
> + st->codec->codec_id = CODEC_ID_PCM_S8_PLANAR;
> + break;
> + case COMP_FIB:
> + st->codec->codec_id = CODEC_ID_8SVX_FIB;
> + break;
> + case COMP_EXP:
> + st->codec->codec_id = CODEC_ID_8SVX_EXP;
> + break;
> + default:
> + av_log(s, AV_LOG_ERROR,
> + "Unknown SVX8 compression method '%d'\n", compr);
> + return AVERROR_INVALIDDATA;
> + }
> + st->codec->bits_per_coded_sample = compr == COMP_NONE ? 8 : 4;
> + avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate);
> break;
>
> case ID_ABIT:
> case ID_BODY:
> case ID_DBOD:
> - iff->body_pos = avio_tell(pb);
> - iff->body_size = data_size;
> + pkt->flags |= AV_PKT_FLAG_KEY;
> + case ID_DLTA:
> + av_get_packet(pb, pkt, chunk_size);
> break;
>
> case ID_CHAN:
> - if (data_size < 4)
> + if (chunk_size < 4)
> return AVERROR_INVALIDDATA;
> - st->codec->channels = (avio_rb32(pb) < 6) ? 1 : 2;
> + channels = (avio_rb32(pb) < 6) ? 1 : 2;
> break;
>
> case ID_CAMG:
> - if (data_size < 4)
> + if (chunk_size < 4)
> return AVERROR_INVALIDDATA;
> - screenmode = avio_rb32(pb);
> + screenmode = avio_rb32(pb);
> break;
>
> case ID_CMAP:
> - st->codec->extradata_size = data_size + IFF_EXTRA_VIDEO_SIZE;
> - st->codec->extradata = av_malloc(data_size + IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
> - if (!st->codec->extradata)
> + palette_size = chunk_size;
> + av_fast_padded_malloc(&iff->palette, &iff->palette_size, palette_size);
> + if (!iff->palette)
> return AVERROR(ENOMEM);
> - if (avio_read(pb, st->codec->extradata + IFF_EXTRA_VIDEO_SIZE, data_size) < 0)
> + if (avio_read(pb, iff->palette, palette_size) != palette_size)
> return AVERROR(EIO);
> break;
>
> case ID_BMHD:
> - iff->bitmap_compression = -1;
> + if ((ret = create_stream(s, &st)) < 0)
> + return ret;
> + bitmap_compression = -1;
> st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
> - if (data_size <= 8)
> + if (chunk_size <= 8)
> return AVERROR_INVALIDDATA;
> st->codec->width = avio_rb16(pb);
> st->codec->height = avio_rb16(pb);
> avio_skip(pb, 4); // x, y offset
> st->codec->bits_per_coded_sample = avio_r8(pb);
> - if (data_size >= 10)
> + if (chunk_size >= 10)
> masking = avio_r8(pb);
> - if (data_size >= 11)
> - iff->bitmap_compression = avio_r8(pb);
> - if (data_size >= 14) {
> + if (chunk_size >= 11)
> + bitmap_compression = avio_r8(pb);
> + if (chunk_size >= 14) {
> avio_skip(pb, 1); // padding
> transparency = avio_rb16(pb);
> }
> - if (data_size >= 16) {
> + if (chunk_size >= 16) {
> st->sample_aspect_ratio.num = avio_r8(pb);
> st->sample_aspect_ratio.den = avio_r8(pb);
> }
> break;
>
> case ID_DPEL:
> - if (data_size < 4 || (data_size & 3))
> + if (!st)
> + return AVERROR_INVALIDDATA;
> + if (chunk_size < 16 || (chunk_size & 3))
> return AVERROR_INVALIDDATA;
> if ((fmt_size = avio_read(pb, fmt, sizeof(fmt))) < 0)
> return fmt_size;
> - if (fmt_size == sizeof(deep_rgb24) && !memcmp(fmt, deep_rgb24, sizeof(deep_rgb24)))
> + if (fmt_size == sizeof(deep_rgb24) && !memcmp(fmt, deep_rgb24, sizeof(deep_rgb24))) {
> st->codec->pix_fmt = PIX_FMT_RGB24;
> - else if (fmt_size == sizeof(deep_rgba) && !memcmp(fmt, deep_rgba, sizeof(deep_rgba)))
> + st->codec->bits_per_coded_sample = 24;
> + } else if (fmt_size == sizeof(deep_rgba) && !memcmp(fmt, deep_rgba, sizeof(deep_rgba))) {
> st->codec->pix_fmt = PIX_FMT_RGBA;
> - else {
> + st->codec->bits_per_coded_sample = 32;
> + } else {
> av_log_ask_for_sample(s, "unsupported color format\n");
> return AVERROR_PATCHWELCOME;
> }
> break;
>
> case ID_DGBL:
> - st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
> - if (data_size < 8)
> + if ((ret = create_stream(s, &st)) < 0)
> + return ret;
> + st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
> + if (chunk_size < 8)
> return AVERROR_INVALIDDATA;
> - st->codec->width = avio_rb16(pb);
> - st->codec->height = avio_rb16(pb);
> - iff->bitmap_compression = avio_rb16(pb);
> - if (iff->bitmap_compression != 0) {
> + st->codec->width = avio_rb16(pb);
> + st->codec->height = avio_rb16(pb);
> + bitmap_compression = avio_rb16(pb);
> + if (bitmap_compression) {
> av_log(s, AV_LOG_ERROR,
> - "compression %i not supported\n", iff->bitmap_compression);
> + "compression %i not supported\n", bitmap_compression);
> return AVERROR_PATCHWELCOME;
> }
> - st->sample_aspect_ratio.num = avio_r8(pb);
> - st->sample_aspect_ratio.den = avio_r8(pb);
> - st->codec->bits_per_coded_sample = 24;
> + st->sample_aspect_ratio.num = avio_r8(pb);
> + st->sample_aspect_ratio.den = avio_r8(pb);
> break;
>
> case ID_ANNO:
> @@ -264,122 +325,89 @@ static int iff_read_header(AVFormatContext *s)
> case ID_AUTH: metadata_tag = "artist"; break;
> case ID_COPYRIGHT: metadata_tag = "copyright"; break;
> case ID_NAME: metadata_tag = "title"; break;
> + default:
> + av_log(s, AV_LOG_DEBUG, "unsupported chunk id: %X\n", chunk_id);
> }
>
> if (metadata_tag) {
> - if ((res = get_metadata(s, metadata_tag, data_size)) < 0) {
> - av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!", metadata_tag);
> - return res;
> + if ((ret = get_metadata(s, metadata_tag, chunk_size)) < 0) {
> + av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!\n", metadata_tag);
> + return ret;
> }
> }
> - avio_skip(pb, data_size - (avio_tell(pb) - orig_pos) + (data_size & 1));
> + avio_skip(pb, chunk_size - (avio_tell(pb) - chunk_pos) + (chunk_size & 1));
> }
>
> - avio_seek(pb, iff->body_pos, SEEK_SET);
> -
> - switch(st->codec->codec_type) {
> - case AVMEDIA_TYPE_AUDIO:
> - avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate);
> -
> - switch (iff->svx8_compression) {
> - case COMP_NONE:
> - st->codec->codec_id = CODEC_ID_PCM_S8_PLANAR;
> - break;
> - case COMP_FIB:
> - st->codec->codec_id = CODEC_ID_8SVX_FIB;
> +done:
> + if (!s->nb_streams)
> + return AVERROR_INVALIDDATA;
> + if (st) {
> + switch(st->codec->codec_type) {
> + case AVMEDIA_TYPE_AUDIO:
> + st->codec->channels = channels;
> + st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample;
> + st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
> break;
> - case COMP_EXP:
> - st->codec->codec_id = CODEC_ID_8SVX_EXP;
> - break;
> - default:
> - av_log(s, AV_LOG_ERROR,
> - "Unknown SVX8 compression method '%d'\n", iff->svx8_compression);
> - return -1;
> - }
>
> - st->codec->bits_per_coded_sample = iff->svx8_compression == COMP_NONE ? 8 : 4;
> - st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample;
> - st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
> - break;
> + case AVMEDIA_TYPE_VIDEO:
> + bpp = st->codec->bits_per_coded_sample;
> + if ((screenmode & 0x800 /* Hold And Modify */) && bpp <= 8) {
> + ham = bpp > 6 ? 6 : 4;
> + st->codec->bits_per_coded_sample = 24;
> + } else {
> + ham = 0;
> + }
> + flags = (screenmode & 0x80 /* Extra HalfBrite */) && bpp <= 8;
>
> - case AVMEDIA_TYPE_VIDEO:
> - iff->bpp = st->codec->bits_per_coded_sample;
> - if ((screenmode & 0x800 /* Hold And Modify */) && iff->bpp <= 8) {
> - iff->ham = iff->bpp > 6 ? 6 : 4;
> - st->codec->bits_per_coded_sample = 24;
> - }
> - iff->flags = (screenmode & 0x80 /* Extra HalfBrite */) && iff->bpp <= 8;
> - iff->masking = masking;
> - iff->transparency = transparency;
> + if (!st->codec->extradata) {
> + st->codec->extradata_size = IFF_EXTRA_VIDEO_SIZE;
> + st->codec->extradata = av_malloc(IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
> + if (!st->codec->extradata)
> + return AVERROR(ENOMEM);
> + }
> + buf = st->codec->extradata;
> + bytestream_put_be16(&buf, IFF_EXTRA_VIDEO_SIZE);
> + bytestream_put_byte(&buf, bitmap_compression);
> + bytestream_put_byte(&buf, bpp);
> + bytestream_put_byte(&buf, ham);
> + bytestream_put_byte(&buf, flags);
> + bytestream_put_be16(&buf, transparency);
> + bytestream_put_byte(&buf, masking);
> + st->codec->codec_tag = tag;
IFF_EXTRA_VIDEO_SIZE was require when the 9-byte header and palette were included in extradata.
Since this patch breaks compatbility with earlier LAVF/LAVCs, the value can be omitted, and
extradata_size used instead within libavcodec.
> - if (!st->codec->extradata) {
> - st->codec->extradata_size = IFF_EXTRA_VIDEO_SIZE;
> - st->codec->extradata = av_malloc(IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
> - if (!st->codec->extradata)
> - return AVERROR(ENOMEM);
> - }
> - buf = st->codec->extradata;
> - bytestream_put_be16(&buf, IFF_EXTRA_VIDEO_SIZE);
> - bytestream_put_byte(&buf, iff->bitmap_compression);
> - bytestream_put_byte(&buf, iff->bpp);
> - bytestream_put_byte(&buf, iff->ham);
> - bytestream_put_byte(&buf, iff->flags);
> - bytestream_put_be16(&buf, iff->transparency);
> - bytestream_put_byte(&buf, iff->masking);
> + if (palette_size) {
> + uint8_t *npal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, palette_size);
> + if (!npal) {
> + return AVERROR(ENOMEM);
> + }
> + memcpy(npal, iff->palette, palette_size);
> + }
>
> - switch (iff->bitmap_compression) {
> - case BITMAP_RAW:
> - st->codec->codec_id = CODEC_ID_IFF_ILBM;
> - break;
> - case BITMAP_BYTERUN1:
> - st->codec->codec_id = CODEC_ID_IFF_BYTERUN1;
> + switch (bitmap_compression) {
> + case BITMAP_RAW:
> + st->codec->codec_id = CODEC_ID_IFF_ILBM;
> + break;
> + case BITMAP_BYTERUN1:
> + st->codec->codec_id = CODEC_ID_IFF_BYTERUN1;
> + break;
> + default:
> + av_log(s, AV_LOG_ERROR,
> + "Unknown bitmap compression method '%d'\n", bitmap_compression);
> + return AVERROR_INVALIDDATA;
> + }
> break;
> - default:
> - av_log(s, AV_LOG_ERROR,
> - "Unknown bitmap compression method '%d'\n", iff->bitmap_compression);
> - return AVERROR_INVALIDDATA;
> }
> - break;
> - default:
> - return -1;
> }
>
> - return 0;
> + pkt->stream_index = 0;
> + return pkt->size;
> }
>
> -static int iff_read_packet(AVFormatContext *s,
> - AVPacket *pkt)
> +static int iff_read_close(AVFormatContext *s)
> {
> IffDemuxContext *iff = s->priv_data;
> - AVIOContext *pb = s->pb;
> - AVStream *st = s->streams[0];
> - int ret;
> -
> - if(iff->sent_bytes >= iff->body_size)
> - return AVERROR_EOF;
> -
> - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
> - ret = av_get_packet(pb, pkt, iff->body_size);
> - } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
> - uint8_t *buf;
> -
> - if (av_new_packet(pkt, iff->body_size + 2) < 0) {
> - return AVERROR(ENOMEM);
> - }
> -
> - buf = pkt->data;
> - bytestream_put_be16(&buf, 2);
> - ret = avio_read(pb, buf, iff->body_size);
> - } else {
> - av_abort();
> - }
> -
> - if(iff->sent_bytes == 0)
> - pkt->flags |= AV_PKT_FLAG_KEY;
> - iff->sent_bytes = iff->body_size;
> -
> - pkt->stream_index = 0;
> - return ret;
> + av_freep(&iff->palette);
> + return 0;
> }
>
> AVInputFormat ff_iff_demuxer = {
> @@ -389,4 +417,5 @@ AVInputFormat ff_iff_demuxer = {
> .read_probe = iff_probe,
> .read_header = iff_read_header,
> .read_packet = iff_read_packet,
> + .read_close = iff_read_close,
> };
> --
> 1.7.7
In summary, I see at least three patches here:
- Unrelated/cosmetic/ident changes
- Big change to way header/palette info is passed between the demuxer and decoder
- Mods to handle the IFF ANIM loop
(which btw, is the most interesting part, but obfuscated by the above).
Cheers,
-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20120722/bcf9f983/attachment.asc>
More information about the ffmpeg-devel
mailing list