[FFmpeg-devel] [PATCH] PAF demuxer and decoder

Michael Niedermayer michaelni at gmx.at
Tue Jul 3 18:14:52 CEST 2012


On Mon, Jul 02, 2012 at 02:28:32AM +0000, Paul B Mahol wrote:
> Signed-off-by: Paul B Mahol <onemda at gmail.com>
[...]
> +static int decode_0(AVCodecContext *avctx, uint8_t code, uint8_t *pkt)
> +{
> +    PAFVideoDecContext *c = avctx->priv_data;
> +    uint32_t opcode_size, offset;
> +    uint8_t *dst, *dend, mask = 0, color = 0, a, b, p;
> +    const uint8_t *src, *send, *opcodes;
> +    int cnt, i, j, x = 0;
> +
> +    cnt = bytestream2_get_byte(&c->gb);
> +    if (cnt) {
> +        if (code & 0x10) {
> +            int align;
> +
> +            align = bytestream2_tell(&c->gb) & 3;
> +            if (align)
> +                bytestream2_skip(&c->gb, 4 - align);
> +        }
> +        do {
> +            uint32_t cnt;
> +
> +            a      = bytestream2_get_byte(&c->gb);
> +            b      = bytestream2_get_byte(&c->gb);
> +            p      = (a & 0xC0) >> 6;
> +            dst    = c->frame[p] + get_video_page_offset(avctx, a, b);
> +            dend   = c->frame[p] + c->frame_size;
> +            offset = (b & 0x7F) * 2;
> +            cnt = bytestream2_get_le16(&c->gb) + offset;
> +
> +            do {
> +                offset++;
> +                if (dst + 3 * avctx->width + 4 > dend)
> +                    return AVERROR_INVALIDDATA;
> +                copy4h(avctx, dst);
> +                if ((offset & 0x3F) == 0)
> +                    dst += avctx->width * 3;
> +                dst += 4;
> +            } while (offset < cnt);
> +        } while (--cnt);
> +    }
> +
> +    dst = c->frame[c->current_frame];
> +    do {
> +        a    = bytestream2_get_byte(&c->gb);
> +        b    = bytestream2_get_byte(&c->gb);
> +        p    = (a & 0xC0) >> 6;
> +        src  = c->frame[p] + get_video_page_offset(avctx, a, b);
> +        send = c->frame[p] + c->frame_size;
> +        if (src + 3 * avctx->width + 4 > send)
> +            return AVERROR_INVALIDDATA;
> +        copy_block4(dst, src, avctx->width, avctx->width, 4);
> +        cnt++;
> +        if ((cnt & 0x3F) == 0)
> +            dst += avctx->width * 3;
> +        dst += 4;
> +    } while (cnt < c->video_size / 16);
> +
> +    opcode_size = bytestream2_get_le16(&c->gb);
> +    bytestream2_skip(&c->gb, 2);
> +
> +    if (bytestream2_get_bytes_left(&c->gb) < opcode_size)
> +        return AVERROR_INVALIDDATA;
> +
> +    opcodes = pkt + bytestream2_tell(&c->gb);
> +    bytestream2_skipu(&c->gb, opcode_size);
> +
> +    dst = c->frame[c->current_frame];
> +
> +    for (i = 0; i < avctx->height; i += 4, dst += avctx->width * 3) {
> +        for (j = 0; j < avctx->width; j += 4, dst += 4) {

this seems to assume dimensions are a multiple of 4, paf_vid_init
should check this so not too much is written


[...]
> +AVCodec ff_paf_video_decoder = {
> +    .name           = "paf_video",
> +    .type           = AVMEDIA_TYPE_VIDEO,
> +    .id             = CODEC_ID_PAF_VIDEO,
> +    .priv_data_size = sizeof(PAFVideoDecContext),
> +    .init           = paf_vid_init,
> +    .close          = paf_vid_close,
> +    .decode         = paf_vid_decode,
> +    .long_name      = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Video"),
> +};
> +
> +AVCodec ff_paf_audio_decoder = {
> +    .name           = "paf_audio",
> +    .type           = AVMEDIA_TYPE_AUDIO,
> +    .id             = CODEC_ID_PAF_AUDIO,
> +    .priv_data_size = sizeof(PAFAudioDecContext),
> +    .init           = paf_aud_init,
> +    .decode         = paf_aud_decode,
> +    .capabilities   = CODEC_CAP_DR1,
> +    .long_name      = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Audio"),
> +};

the audio decoder could be split into a seperate file


[...]
> +static int read_header(AVFormatContext *s)
> +{
> +    PAFDemuxContext *p = s->priv_data;
> +    AVIOContext     *pb = s->pb;
> +    AVStream        *ast, *vst;
> +    int             ret = 0;
> +
> +    avio_skip(pb, 132);
> +
> +    vst = avformat_new_stream(s, 0);
> +    if (!vst)
> +        return AVERROR(ENOMEM);
> +
> +    vst->start_time = 0;
> +    vst->nb_frames  =
> +    vst->duration   =
> +    p->nb_frames = avio_rl32(pb);
> +    avio_skip(pb, 4);
> +    vst->codec->width  = avio_rl32(pb);
> +    vst->codec->height = avio_rl32(pb);
> +    avio_skip(pb, 4);
> +    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
> +    vst->codec->codec_tag  = 0;
> +    vst->codec->codec_id   = CODEC_ID_PAF_VIDEO;
> +    avpriv_set_pts_info(vst, 64, 1, 10);
> +
> +    ast = avformat_new_stream(s, 0);
> +    if (!ast)
> +        return AVERROR(ENOMEM);
> +
> +    ast->start_time         = 0;
> +    ast->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
> +    ast->codec->codec_tag   = 0;
> +    ast->codec->codec_id    = CODEC_ID_PAF_AUDIO;
> +    ast->codec->channels    = 2;
> +    ast->codec->sample_rate = 22050;
> +    avpriv_set_pts_info(ast, 64, 1, 22050);
> +
> +    p->buffer_size     = avio_rl32(pb);
> +    if (p->buffer_size < 175 || p->buffer_size > 2048)
> +        return AVERROR_INVALIDDATA;
> +
> +    p->preload_count  = avio_rl32(pb);
> +    p->frame_blks     = avio_rl32(pb);
> +    p->start_offset   = avio_rl32(pb);
> +    p->max_video_blks = avio_rl32(pb);
> +    p->max_audio_blks = avio_rl32(pb);
> +    if (p->max_audio_blks < 1 ||
> +        p->max_video_blks < 1 ||
> +        p->frame_blks     < 1 ||
> +        p->nb_frames      < 1 ||
> +        p->preload_count  < 1)
> +        return AVERROR_INVALIDDATA;
> +

> +    p->blocks_count_table  = av_mallocz(p->nb_frames  * sizeof(uint32_t));
> +    p->frames_offset_table = av_mallocz(p->nb_frames  * sizeof(uint32_t));
> +    p->blocks_offset_table = av_mallocz(p->frame_blks * sizeof(uint32_t));

possibke interger overflows in the multiplication can lead to out of
array writes later


[...]
> +    size = p->video_size - p->frames_offset_table[p->current_frame];
> +    if (size < 0)
> +        return AVERROR_INVALIDDATA;
> +
> +    if (av_new_packet(pkt, size) < 0)
> +        return AVERROR(ENOMEM);
> +
> +    pkt->stream_index = 0;
> +    pkt->duration     = 1;
> +    memcpy(pkt->data, p->video_frame + p->frames_offset_table[p->current_frame], size);

this creates video frames that are much larger than needed

rest looks ok
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Many things microsoft did are stupid, but not doing something just because
microsoft did it is even more stupid. If everything ms did were stupid they
would be bankrupt already.
-------------- 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/20120703/4ad3d8bf/attachment.asc>


More information about the ffmpeg-devel mailing list