[FFmpeg-devel] [PATCH] VQA-highcolor (15 bit rgb555) decoder by Adam Iglewski

Michael Niedermayer michaelni at gmx.at
Tue Jan 14 02:52:06 CET 2014


On Mon, Jan 13, 2014 at 10:28:30AM +0000, u-owvm at aetey.se wrote:
> Hello,
> 
> Adjusted to the current master:
> 
> VQA-highcolor (15 bit rgb555) decoder based on patches from June 2009
> by Adam Iglewski <szwagros at szwagros-desktop.(none)>.
> 
> Hope it may make it through this time.
> 
> Regards,
> Rl

[...]
> @@ -155,6 +154,11 @@ static av_cold int vqa_decode_init(AVCodecContext *avctx)
>      s->vector_height = s->avctx->extradata[11];
>      s->partial_count = s->partial_countdown = s->avctx->extradata[13];
>  
> +    if(!AV_RL16(&s->avctx->extradata[14]))
> +        avctx->pix_fmt = PIX_FMT_RGB555;
> +    else
> +        avctx->pix_fmt = PIX_FMT_PAL8;

AV_PIX_FMT_*

also this patch doesnt work on big endian (yes i tested it)


[...]
> +static void vqa_decode_hc_video_chunk(VqaContext *s, const unsigned char *src,
> +                                      unsigned int src_size, AVFrame *frame)
> +{
> +    int block_x, block_y;          /* block width and height iterators */
> +    int blocks_wide, blocks_high;  /* width and height in 4x4|2 blocks */
> +    int block_inc;
> +    int index_shift;
> +    int i;
> +
> +    /* decoding parameters */
> +    uint16_t *pixels,*frame_end;
> +    uint16_t *codebook = (uint16_t *)s->codebook;
> +    int stride = frame->linesize[0] >> 1;
> +
> +    int type,code;
> +    int vector_index = 0;
> +
> +    blocks_wide = s->width >> 2;
> +    blocks_high = s->height / s->vector_height;
> +    block_inc = 4;
> +    frame_end = (uint16_t *)frame->data[0] + s->height * stride + s->width;

stride can be negative, which would break this code


> +
> +    if (s->vector_height == 4)
> +        index_shift = 4;
> +    else
> +        index_shift = 3;
> +
> +    for(block_y=0; block_y < blocks_high; block_y ++) {
> +        pixels = (uint16_t *)frame->data[0] + (block_y * s->vector_height * stride);
> +
> +        for(block_x=0; block_x < blocks_wide; ) {
> +            int blocks_done;
> +            code = bytestream_get_le16(&src);
> +            type = code >> 13;
> +            code &= 0x1fff;
> +
> +            if(!type) {
> +                    blocks_done = code;
> +                    block_x += blocks_done;
> +                    pixels += blocks_done * block_inc;
> +                    continue;
> +            } else if (type < 3) {
> +                    vector_index = (code & 0xff) << index_shift;
> +                    blocks_done = ((code & 0x1f00) >> 7) + 1 + type;
> +            } else if (type == 3 || type == 5) {
> +                    vector_index = code << index_shift;
> +                    if (type == 3)
> +                        blocks_done = 1;
> +                    else
> +                        blocks_done = *src++;
> +            } else {
> +                    av_log(s->avctx, AV_LOG_ERROR, " unknown type in VPTR chunk (%d)\n",type);
> +                    return;

this should return some error code like AVERROR_INVALIDDATA or AVERROR_PATCHWELCOME


> +            }
> +
> +            if(pixels + s->vector_height * stride + blocks_done * block_inc > frame_end) {  

this can overflow, consider that the frame would be at  the end of
the address space so pixels + some big number would return a small
pointer


[...]
> @@ -173,12 +183,39 @@ static int wsvqa_read_packet(AVFormatContext *s,
>  
>          skip_byte = chunk_size & 0x01;
>  
> -        if ((chunk_type == SND0_TAG) || (chunk_type == SND1_TAG) ||
> -            (chunk_type == SND2_TAG) || (chunk_type == VQFR_TAG)) {
> +        if (chunk_type == VQFL_TAG) {
> + 
> +            wsvqa->vqfl_chunk_size = chunk_size;
> +            wsvqa->vqfl_chunk_data = av_mallocz(chunk_size);
> +            if (!wsvqa->vqfl_chunk_data)
> +                return AVERROR(ENOMEM);
> +            ret = avio_read(pb, wsvqa->vqfl_chunk_data, chunk_size);
> +            if (ret != chunk_size)
> +                return AVERROR(EIO);
> +            if (skip_byte)
> +                avio_seek(pb, 1, SEEK_CUR);
> +            continue;
> +
> +        } else if ((chunk_type == SND0_TAG) || (chunk_type == SND1_TAG) ||
> +                   (chunk_type == SND2_TAG) || (chunk_type == VQFR_TAG)) {
> +
> +            if ((chunk_type == VQFR_TAG) && wsvqa->vqfl_chunk_size) {

> +                if (av_new_packet(pkt, chunk_size + wsvqa->vqfl_chunk_size))

the addition could overflow, allocating a too small packet


> +                    return AVERROR(EIO);
> +                ret = avio_read(pb, pkt->data, chunk_size);
> +                if (ret != chunk_size) {
> +                    av_free_packet(pkt);
> +                    return AVERROR(EIO);
> +                }
> +                memcpy(pkt->data + chunk_size,wsvqa->vqfl_chunk_data,wsvqa->vqfl_chunk_size);
> +                wsvqa->vqfl_chunk_size=0;

> +                av_free(wsvqa->vqfl_chunk_data);

av_freep() is safer to ensure that no stale pointers remain

[...]


-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Its not that you shouldnt use gotos but rather that you should write
readable code and code with gotos often but not always is less readable
-------------- 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/20140114/bcbb0ec3/attachment.asc>


More information about the ffmpeg-devel mailing list