[Ffmpeg-devel] [PATCH] C93 demuxer and decoder (GSoC qualification task)

Michael Niedermayer michaelni
Fri Apr 6 14:34:54 CEST 2007


Hi

On Fri, Apr 06, 2007 at 01:36:22PM +0300, Anssi Hannula wrote:
[...]
> +static inline void c93_draw_4x4_colorblock(uint8_t *out, uint8_t **buf,
> +                          int bpp, int colcnt, int stride, C93BlockType bt)
> +{
> +    unsigned int y_off, x_off, colmask, i, j, colbit;
> +    uint8_t allcols[4];
> +    uint8_t curcols[2];
> +    uint8_t *cols = bt == C93_4X4_4COLOR_GRP ? curcols : allcols;
> +    int bit = 1 + (bpp & 2);
> +
> +    for (y_off = 0; y_off < 8; y_off += 4) {
> +        uint8_t *to = &out[y_off*stride];
> +        for (x_off = 0; x_off < 8; x_off += 4) {
> +            colbit = 0;
> +            bytestream_get_buffer(buf, allcols, colcnt);
> +            if (bt == C93_4X4_4COLOR)
> +                colmask = bytestream_get_le32(buf);
> +            else
> +                colmask = bytestream_get_le16(buf);
> +            if (bt == C93_4X4_4COLOR_GRP)
> +                curcols[0] = allcols[0];
> +
> +            for (j = 0; j < 4; j++) {
> +                if (bt == C93_4X4_4COLOR_GRP) {
> +                    if (j == 2)
> +                        curcols[0] = allcols[3];
> +                    curcols[1] = allcols[1];
> +                }
> +                for (i = 0; i < 4; i++) {
> +                    if (bt == C93_4X4_4COLOR_GRP && i == 2)
> +                        curcols[1] = allcols[2];
> +                    to[j*stride+i] = cols[(colmask >> colbit) & bit];
> +                    colbit += bpp;
> +                }
> +            }
> +            to += 4;
> +        }
> +    }
> +}
> +
> +static int c93_decode_frame(AVCodecContext *avctx, void *data,
> +                            int *data_size, uint8_t * buf, int buf_size)
> +{
> +    C93DecoderContext * const c93 = avctx->priv_data;
> +    AVFrame * const newpic = &c93->pictures[c93->currentpic];
> +    AVFrame * const oldpic = &c93->pictures[c93->currentpic^1];
> +    AVFrame *picture = data;
> +    uint8_t *out;
> +    int stride, i, x, y;
> +    C93BlockType bt = 0;
> +
> +    c93->currentpic ^= 1;
> +
> +    newpic->reference = 1;
> +    newpic->buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
> +                         FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
> +    if (avctx->reget_buffer(avctx, newpic)) {
> +        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
> +        return -1;
> +    }
> +
> +    stride = newpic->linesize[0];
> +
> +    if (buf[0] & C93_FIRST_FRAME) {
> +        newpic->pict_type = FF_I_TYPE;
> +        newpic->key_frame = 1;
> +    } else {
> +        newpic->pict_type = FF_P_TYPE;
> +        newpic->key_frame = 0;
> +    }
> +
> +    if (*buf++ & C93_HAS_PALETTE) {
> +        uint32_t *palette = (uint32_t *) newpic->data[1];
> +        uint8_t *palbuf = buf + buf_size - 768 - 1;
> +        for (i = 0; i < 256; i++) {
> +            palette[i] = bytestream_get_be24(&palbuf);
> +        }
> +    } else {
> +        if (oldpic->data[1])
> +            memcpy(newpic->data[1], oldpic->data[1], 256 * 4);
> +    }
> +
> +    for (y = 0; y < HEIGHT; y += 8) {
> +        out = newpic->data[0] + y * stride;
> +        for (x = 0; x < WIDTH; x += 8) {
> +            uint8_t *copy_from = oldpic->data[0];
> +            unsigned int offset, j;
> +            uint8_t cols[2];
> +
> +            if (!bt)
> +                bt = *buf++;
> +
> +            switch (bt & 0x0F) {
> +            case C93_8X8_FROM_PREV:
> +                offset = bytestream_get_le16(&buf);
> +                if (c93_copy_block(avctx, out, copy_from, offset, 8, stride))
> +                    return -1;
> +                break;
> +
> +            case C93_4X4_FROM_CURR:
> +                copy_from = newpic->data[0];
> +            case C93_4X4_FROM_PREV:
> +                for (j = 0; j < 8; j += 4) {
> +                    for (i = 0; i < 8; i += 4) {
> +                        offset = bytestream_get_le16(&buf);
> +                        if (c93_copy_block(avctx, &out[j*stride+i],
> +                                           copy_from, offset, 4, stride))
> +                            return -1;
> +                    }
> +                }
> +                break;
> +
> +            case C93_8X8_2COLOR:
> +                cols[0] = *buf++;
> +                cols[1] = *buf++;
> +                for (j = 0; j < 8; j++) {
> +                    for (i = 0; i < 8; i++) {
> +                        out[j*stride+i] = cols[(buf[0] >> i) & 1];
> +                    }
> +                    buf++;
> +                }
> +                break;
> +
> +            case C93_4X4_2COLOR:
> +                c93_draw_4x4_colorblock(out, &buf, 1, 2, stride, bt & 0x0F);
> +                break;
> +
> +            case C93_4X4_4COLOR_GRP:
> +                c93_draw_4x4_colorblock(out, &buf, 1, 4, stride, bt & 0x0F);
> +                break;
> +
> +            case C93_4X4_4COLOR:
> +                c93_draw_4x4_colorblock(out, &buf, 2, 4, stride, bt & 0x0F);
> +                break;

i think the following is more readable and simpler

static inline void draw_n_color(uint8_t *out, int stride, int width, int height,
                                int bpp, uint8_t cols[2], uint8_t grps[4], uint32_t col){
    int x,y;
    for(y=0; y<height; y++){
        if(grps)
            cols[1]= grps[3*(y>>1)];
        for(x=0; x<width; x++){
            if(grps)
                cols[0]= grps[(x>>1)+1];
            out[x + y*stride] = cols[col >> (32-bpp)];
            col<<=bpp;
        }
    }
}
case C93_8X8_2COLOR:
    bytestream_get_buffer(buf, cols, 2);
    for(i=0; i<8; i++){
        draw_n_color(out, stride, 8, 1, 1, cols, NULL, *buf++);
    }
    break;
case C93_4x4_2COLOR:
case C93_4X4_4COLOR:
case C93_4X4_4COLOR_GRP:
    for(i=0; i<8; i+=4){
        for(j=0; j<8; j+=4){
            if(C93_4x4_2COLOR){
                bytestream_get_buffer(buf, cols, 2);
                draw_n_color(out + i + j*stride, stride, 4, 4, 1, cols, NULL, bytestream_get_le16(buf));
            }else if(C93_4X4_4COLOR){
                bytestream_get_buffer(buf, cols, 4);
                draw_n_color(out + i + j*stride, stride, 4, 4, 2, cols, NULL, bytestream_get_le32(buf));
            }else{
                bytestream_get_buffer(buf, grps, 4);
                draw_n_color(out + i + j*stride, stride, 4, 4, 1, cols, grps, bytestream_get_le16(buf));
            }
        }
    }
    break;


> +
> +            case C93_NOOP:
> +                break;
> +
> +            case C93_8X8_INTRA:
> +                for (j = 0; j < 8; j++) {

> +                    memcpy(&out[j*stride], buf, 8);
> +                    buf += 8;

bytestream_get_buffer()



[...]
> +    if (ret < datasize) {
> +        av_free_packet(pkt);
> +        return AVERROR_IO;
> +    }
> +
> +    datasize = get_le16(pb); /* palette size */
> +    if (datasize) {
> +        if (datasize != 768) {
> +            av_log(s, AV_LOG_ERROR, "invalid palette size %u\n", datasize);
> +            av_free_packet(pkt);
> +            return AVERROR_INVALIDDATA;
> +        }
> +        pkt->data[0] |= C93_HAS_PALETTE;
> +        ret = get_buffer(pb, pkt->data + pkt->size, datasize);
> +        if (ret < datasize) {
> +            av_free_packet(pkt);
> +            return AVERROR_IO;

there are 3 av_free_packet(pkt); maybe a goto fail ... would be simpler


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

No human being will ever know the Truth, for even if they happen to say it
by chance, they would not even known they had done so. -- Xenophanes
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20070406/1ced2ca3/attachment.pgp>



More information about the ffmpeg-devel mailing list