[FFmpeg-devel] [PATCH] Electronic Arts CMV decoder

Michael Niedermayer michaelni
Wed Jul 2 20:27:01 CEST 2008


On Tue, Jul 01, 2008 at 10:36:41PM +1000, pross at xvid.org wrote:
> Hi,
> 
> This patch adds EA CMV support to FFmpeg.
> 
> Apply the decoder patch first, then the demuxer patch.
> 
> Samples: http://samples.mplayerhq.hu/game-formats/ea-cmv/
> Information: http://wiki.multimedia.cx/index.php?title=Electronic_Arts_CMV

[...]
> +typedef struct CmvContext {
> +    AVCodecContext *avctx;
> +    AVFrame frame;        // current
> +    AVFrame last_frame;   // last
> +    AVFrame last2_frame;  // second-last
> +} CmvContext;

comments should be doxygen compatible


> +
> +static int cmv_decode_init(AVCodecContext *avctx){

should be av_cold


> +    CmvContext *s = avctx->priv_data;
> +    s->avctx = avctx;
> +    if (s->avctx->palctrl == NULL) {
> +        av_log(avctx, AV_LOG_ERROR, "cmv: palette expected.\n");
> +        return -1;
> +    }
> +    avctx->pix_fmt = PIX_FMT_PAL8;

> +    if (avcodec_check_dimensions(avctx, avctx->width, avctx->height))
> +        return -1;

that should be unneeded, avcodec_open() already checks it


[...]
> +static void cmv_decode_inter(CmvContext * s, const unsigned char *buf, int buf_size){
> +    const unsigned char *raw = buf + (s->avctx->width*s->avctx->height/16);
> +    int x,y,i;
> +
> +    i = 0;
> +    for(y=0; y<s->avctx->height/4; y++)
> +    for(x=0; x<s->avctx->width/4; x++) {
> +        if (buf[i]==0xFF) {
> +            unsigned char *dst = s->frame.data[0] + (y*4)*s->frame.linesize[0] + x*4;
> +            if (*raw==0xFF) { /* intra */
> +                raw++;
> +                memcpy(dst, raw, 4);
> +                memcpy(dst+s->frame.linesize[0], raw+4, 4);
> +                memcpy(dst+2*s->frame.linesize[0], raw+8, 4);
> +                memcpy(dst+3*s->frame.linesize[0], raw+12, 4);
> +                raw+=16;
> +            }else{  /* inter using second-last frame as reference */
> +                int xoffset = (*raw & 0x0F) - 7;
> +                int yoffset = ((*raw >> 4) & 0x0F) - 7;
> +                cmv_motcomp(s->frame.data[0], s->frame.linesize[0],
> +                            s->last2_frame.data[0], s->last2_frame.linesize[0],
> +                            x*4, y*4, xoffset, yoffset, s->avctx->width, s->avctx->height);
> +                raw++;
> +            }
> +        }else{  /* inter using last frame as reference */
> +            int xoffset = (buf[i] & 0x0F) - 7;

> +            int yoffset = ((buf[i] >> 4) & 0x0F) - 7;

the & 15 is unneeded


> +            cmv_motcomp(s->frame.data[0], s->frame.linesize[0],
> +                      s->last_frame.data[0], s->last_frame.linesize[0],
> +                      x*4, y*4, xoffset, yoffset, s->avctx->width, s->avctx->height);
> +        }
> +        i++;
> +    }
> +}
> +

> +static int cmv_decode_frame(AVCodecContext *avctx,
> +                            void *data, int *data_size,
> +                            uint8_t *buf, int buf_size)
> +{
> +    CmvContext *s = avctx->priv_data;
> +

> +    s->frame.data[0] = 0;

this looks wrong, this should not be needed


> +    if (avctx->get_buffer(avctx, &s->frame)) {
> +        av_log(avctx, AV_LOG_ERROR, "cmv: get_buffer() failed\n");
> +        return -1;
> +    }
> +

> +    memcpy(s->frame.data[1], avctx->palctrl->palette, AVPALETTE_SIZE);
> +    if (avctx->palctrl->palette_changed) {
> +        s->frame.palette_has_changed = 1;
> +        avctx->palctrl->palette_changed = 0;
> +    }

this way of passing the pallette around is deprecated and not thread safe.
Decoder and Demuxer can run in seperate threads and there can be a delay
of several frames between them ...


> +
> +    switch(buf[0]) {  // subtype
> +    case 0: cmv_decode_intra(s, buf+2, buf_size-2); break;
> +    case 1: cmv_decode_inter(s, buf+2, buf_size-2); break;
> +    default :
> +        return -1;
> +    }

doesnt this return leak some frames?


[...]
> @@ -241,6 +245,34 @@
>      return 1;
>  }
>  
> +/* Process CMV video header
> + * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx
> + */
> +static int process_video_header_cmv(AVFormatContext *s)

doxygen


> +{
> +    EaDemuxContext *ea = s->priv_data;
> +    ByteIOContext *pb = s->pb;
> +    int pal_start, pal_size, i;
> +
> +    url_fskip(pb, 4);

> +    ea->width = get_le16(pb);
> +    ea->height = get_le16(pb);

these could be vertically aligned

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

The greatest way to live with honor in this world is to be what we pretend
to be. -- Socrates
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080702/c4c6b03c/attachment.pgp>



More information about the ffmpeg-devel mailing list