[Ffmpeg-devel] [PATCH] Tiertex .SEQ files support
Michael Niedermayer
michaelni
Tue Sep 19 01:01:15 CEST 2006
Hi
On Sun, Sep 17, 2006 at 02:32:12PM +0200, Gregory Montoir wrote:
>
> Hi,
>
> The attached patch adds support for Tiertex .seq files demuxer / video
> decoding. As far as I know, this file format was only used in the DOS
> CDROM version of the game Flashback [1,2].
>
> If there's interest, I can upload samples files for testing and/or
> reference.
>
> Regards,
> Gregory
>
> [1]
> http://www.mobygames.com/game/dos/flashback-the-quest-for-identity/screenshots/gameShotId,74055/
> [2]
> http://www.mobygames.com/game/dos/flashback-the-quest-for-identity/screenshots/gameShotId,74057/
>
[...]
> +static unsigned char *seq_decode_unpack_rle_frame(unsigned char *src, unsigned char *dst)
> +{
> + static const int code_table[] = { 0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1 };
> +
> + int i, sz;
> + int code;
> + int rle_code_table[65];
> +
> + i = 0;
> + sz = 0;
> + do {
> + code = *src++;
> + rle_code_table[i++] = code_table[code & 15];
> + sz += ABS(code_table[code & 15]);
> + rle_code_table[i++] = code_table[code >> 4];
> + sz += ABS(code_table[code >> 4]);
> + } while (sz < 64);
> + rle_code_table[i] = 0;
this code looks exploitable
and it seems this is equivakent to a loop with get_sbits() which would be
much simpler
> +
> + for (i = 0; rle_code_table[i] != 0; ++i) {
> + code = rle_code_table[i];
> + if (code < 0) {
> + code = -code;
> + memset(dst, *src++, code);
> + dst += code;
> + } else {
> + memcpy(dst, src, code);
> + dst += code;
> + src += code;
> + }
> + }
this also looks exploitable
[...]
> + if (flags & 2) {
> + for (i = 0; i < 64; ++i) {
> + code = LE_16(data); data += 2;
> + for (b = 0; b < 8; ++b) {
> + seq->operations_table[i * 8 + b] = code & 3;
> + code >>= 2;
> + }
this should use the bitstream reader too
[...]
> +static int seqvideo_decode_init(AVCodecContext *avctx)
> +{
> + SeqVideoContext *seq = (SeqVideoContext *)avctx->priv_data;
> +
> + seq->avctx = avctx;
> + avctx->pix_fmt = PIX_FMT_PAL8;
> + avctx->has_b_frames = 0;
> +
> + seq->current_frame.data[0] = NULL;
> + seq->previous_frame.data[0] = NULL;
> +
> + memset(seq->palette, 0, sizeof(seq->palette));
> + memset(seq->operations_table, 0, sizeof(seq->operations_table));
> + memset(seq->unpack_buffer, 0, sizeof(seq->unpack_buffer));
you can generally assume that things are set to zero if they where allocated
by lavc, and if you allocate them then allocate them with av_mallocz() instead
of doing a memset(0) afterwards
> +
> + return 0;
> +}
> +
> +static int seqvideo_decode_frame(AVCodecContext *avctx,
> + void *data, int *data_size,
> + uint8_t *buf, int buf_size)
> +{
> +
> + SeqVideoContext *seq = (SeqVideoContext *)avctx->priv_data;
> +
> + seq->current_frame.reference = 1;
> + if (avctx->get_buffer(avctx, &seq->current_frame)) {
> + av_log(seq->avctx, AV_LOG_ERROR, "tiertexseqvideo: get_buffer() failed to allocate a frame\n");
> + return -1;
> + }
> +
> + if (seq->previous_frame.data[0])
> + memcpy(seq->current_frame.data[0],
> + seq->previous_frame.data[0],
> + seq->avctx->height * seq->current_frame.linesize[0]);
you should set the correct FF_BUFFER_HINTS* then this memcpy shouldnt
be needed
[...]
> +static int seq_init_frame_buffers(SeqDemuxContext *seq, const unsigned char *frame_data)
> +{
> + int i, sz;
> + TiertexSeqFrameBuffer *seq_buffer;
> +
> + frame_data += 256;
> +
> + memset(seq->frame_buffers, 0, sizeof(seq->frame_buffers));
i think this is unneeded
[...]
> +static int seq_read_header(AVFormatContext *s, AVFormatParameters *ap)
> +{
> + int i, rc;
> + SeqDemuxContext *seq = (SeqDemuxContext *)s->priv_data;
> + ByteIOContext *pb = &s->pb;
> + AVStream *st;
> +
> + if (get_buffer(pb, seq->current_frame_data, SEQ_FRAME_SIZE) != SEQ_FRAME_SIZE)
> + return AVERROR_IO;
why do you read the data into a buffer instead of using get_le*() everywhere?
if theres no reason then please change it to use get_le*()
[...]
> + av_set_pts_info(st, 33, 1, 90000);
[...]
> + av_set_pts_info(st, 33, 1, 90000);
this is wrong, set the correct timebase
[...]
> + if (seq->audio_buffer_full) {
> + if (av_new_packet(pkt, seq->current_audio_pkt_size))
> + return AVERROR_NOMEM;
> +
> + pkt->stream_index = seq->audio_stream_index;
messed up indention
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
In the past you could go to a library and read, borrow or copy any book
Today you'd get arrested for mere telling someone where the library is
More information about the ffmpeg-devel
mailing list