[FFmpeg-devel] Fwd: [PATCH] Psygnosis YOP demuxer

Michael Niedermayer michaelni
Fri Jan 15 01:11:51 CET 2010


On Thu, Jan 14, 2010 at 02:22:04AM +0530, Mohamed Naufal wrote:
> 2010/1/6 Benoit Fouet <benoit.fouet at free.fr>
> 
> 
> [...]
> 
> at least the decoder should be submitted first so that build is not broken
> > :)
> > I've quickly tested the yop files available in the samples directory;
> > they do not crash, the audio plays ok, but seek does not work.
> >
> >
> 
> [...]
> 
> I think seeking works now. Have set PKT_FLAG_KEY for every packet but not
> sure this is the proper method. Have also included the decoder code.
> 
> Naufal
[..]
> +typedef struct YopDecContext {
> +    AVFrame frame;
> +    AVCodecContext *avctx;
> +    AVPacket *avpkt;
> +
> +    int num_pal_colors;
> +    int first_color[2];
> +    int tag_needs_next_byte;

> +    int current_tag_byte;

you dont need that variable

> +    int frame_data_length;
> +    int block_offset_lut[4];
> +    int row_pos;
> +
> +    uint8_t *srcptr;
> +    uint8_t *dstptr;
> +    uint8_t *dstbuf;
> +
> +    uint8_t palette[256][3];
> +} YopDecContext;
> +
> +// These tables are taken directly from:
> +// http://wiki.multimedia.cx/index.php?title=Psygnosis_YOP
[...]
> +/**
> + * Lookup table for copying macroblocks. Each entry contains the respective
> + * x and y pixel offset for the copy source.
> + */
> +static const int8_t copy_lut[16][2] = { {-4, -4},

its called a motion vector


> +                                        {-2, -4},
> +                                        { 0, -4},
> +                                        { 2, -4},
> +                                        {-4, -2},
> +                                        {-4,  0},
> +                                        {-3, -3},
> +                                        {-1, -3},
> +                                        { 1, -3},
> +                                        { 3, -3},
> +                                        {-3, -1},
> +                                        {-2, -2},
> +                                        { 0, -2},
> +                                        { 2, -2},
> +                                        { 4, -2},
> +                                        {-2,  0},
> +                                      };
> +
> +static av_cold int yop_decode_init(AVCodecContext *avctx)
> +{
> +    YopDecContext *s = avctx->priv_data;
> +
> +    s->avctx = avctx;
> +
> +    if (avctx->width & 1 || avctx->height & 1) {
> +        av_log(avctx, AV_LOG_ERROR, "YOP needs even width and height\n");
> +        return -1;
> +    }
> +
> +    avctx->pix_fmt = PIX_FMT_RGB24;
> +
> +    memset(s->palette, 0, sizeof(s->palette));
> +
> +    s->num_pal_colors      = AV_RL8(avctx->extradata);
> +    s->first_color[0]      = AV_RL8(avctx->extradata + 1);
> +    s->first_color[1]      = AV_RL8(avctx->extradata + 2);
> +
> +    if (s->num_pal_colors + s->first_color[0] > 256 ||
> +        s->num_pal_colors + s->first_color[1] > 256) {
> +        av_log(avctx, AV_LOG_ERROR,
> +               "YOP: palette parameters invalid, header probably corrupt\n");
> +        return -1;
> +    }
> +
> +    s->tag_needs_next_byte = 1;
> +

> +    s->block_offset_lut[0] = 0;
> +    s->block_offset_lut[1] = RGB_COLORS;
> +    s->block_offset_lut[2] = avctx->width * RGB_COLORS;
> +    s->block_offset_lut[3] = (avctx->width + 1) * RGB_COLORS;

this is incorrect, you mix width and linesize



> +
> +    return 0;
> +}
> +
> +

> +static av_cold int yop_decode_close(AVCodecContext *avctx)
> +{
> +    YopDecContext *s = avctx->priv_data;
> +    if (s->frame.data[0]) {
> +        av_free(s->frame.data[0]);
> +    }

the if is superfous also use av_freep()


> +    return 0;
> +}
> +
> +/**
> + * Paint a macroblock using the pattern in paint_lut.
> + * @param s codec context
> + * @param tag The tag that was in the nibble.
> + */
> +static void yop_paint_block(YopDecContext *s, int tag)
> +{
> +    int i;
> +    int color_num, offset;
> +
> +    for (i = 0; i < 4; i++) {
> +        color_num = *(s->srcptr + paint_lut[tag][i]);
> +        offset    = s->block_offset_lut[i];
> +
> +        *(s->dstptr + offset)     = s->palette[color_num][0];
> +        *(s->dstptr + offset + 1) = s->palette[color_num][1];
> +        *(s->dstptr + offset + 2) = s->palette[color_num][2];
> +    }
> +    // The number of src bytes consumed is in the last part of the lut entry.
> +    s->srcptr += paint_lut[tag][4];
> +}
> +
> +/**
> + * Copy a previously painted macroblock to the current_block.
> + * @param copy_tag The tag that was in the nibble.
> + */
> +static void yop_copy_previous_block(YopDecContext *s, int copy_tag)
> +{
> +    int i;
> +    int offset;
> +    uint8_t *bufptr;
> +
> +    // calculate position for the copy source
> +    bufptr = s->dstptr + copy_lut[copy_tag][0] * RGB_COLORS +
> +             s->frame.linesize[0] * copy_lut[copy_tag][1];
> +
> +    // Each pixel in the macroblock
> +    for (i = 0; i < 4; i++) {
> +        offset = s->block_offset_lut[i];
> +        *(s->dstptr + offset)     = *(bufptr + offset);
> +        *(s->dstptr + offset + 1) = *(bufptr + offset + 1);
> +        *(s->dstptr + offset + 2) = *(bufptr + offset + 2);
> +     }

for(6){
    s->dstptr[i]         = bufptr[i];
    s->dstptr[i+linesize]= bufptr[i+linesize];
}


> +}
> +
> +/**
> + * Return the next nibble in sequence, consuming a new byte on the input
> + * only if necessary.
> + */
> +static int yop_get_next_nibble(YopDecContext *s)
> +{
> +    int ret;
> +
> +    if (s->tag_needs_next_byte) {
> +        s->current_tag_byte = *s->srcptr++;
> +        ret = s->current_tag_byte >> 4;
> +    }else {
> +        ret = s->current_tag_byte & 0x0f;
> +    }
> +
> +    s->tag_needs_next_byte ^= 1;
> +
> +    return ret;
> +}
> +
[...]

> +/**
> + * Update the palette based on the frame number. Consume all of the palette
> + * bytes on the input.
> + */
> +static void yop_update_palette(YopDecContext *s)
> +{
> +    int firstcolor;
> +    int i, j;
> +
> +    firstcolor = s->first_color[s->avctx->frame_number & 1];

this will be wrong with seeking id suspect


> +
> +    for (i = 0; i < s->num_pal_colors; i++) {
> +        for (j = 0; j < RGB_COLORS; j++) {
> +            // shift left by 2 because the encoded palette is 6-bit color
> +            s->palette[i + firstcolor][j] = *s->srcptr++ << 2;
> +        }
> +    }
> +}
> +

> +static int yop_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
> +                        AVPacket *avpkt)
> +{
> +    YopDecContext *s = avctx->priv_data;
> +    int current_nibble;
> +
> +    s->srcptr = avpkt->data;
> +    s->avpkt  = avpkt;
> +
> +    if (!s->frame.data[0]) {
> +        s->frame.data[0] = av_mallocz(avctx->width * RGB_COLORS * avctx->height);
> +        if (!s->frame.data[0])
> +            return AVERROR(ENOMEM);
> +    }

if you allocate a frame like this then you must implement all the logic that
sets up various fields that you skip
look at avcodec_get_frame_defaults() and get_buffer()
also theres an integer overflow in your code


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

Republics decline into democracies and democracies degenerate into
despotisms. -- Aristotle
-------------- 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/20100115/8831eae9/attachment.pgp>



More information about the ffmpeg-devel mailing list