[FFmpeg-devel] [RFC] [PATCH] iff: ANIM suppport
Paul B Mahol
onemda at gmail.com
Sun Jul 22 05:31:34 CEST 2012
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.
---
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");
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++) {
@@ -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);
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')
+#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))
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;
+ 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;
- 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
More information about the ffmpeg-devel
mailing list