[FFmpeg-devel] [PATCH] CD+G Demuxer & Decoder

Michael Niedermayer michaelni
Tue Nov 24 17:52:03 CET 2009


On Tue, Nov 24, 2009 at 01:15:06AM -0800, Michael Tison wrote:
[...]
> +static void cdg_border_preset(CDGraphicsContext *cc, CdgPacket *cp)
> +{
> +    int color;
> +    int repeat;
> +    int i, j;
> +    int lsize    = cc->frame.linesize[0];
> +    uint8_t *buf = cc->frame.data[0];
> +
> +    color  = cp->data[0] & 0x0F;
> +    repeat = cp->data[1] & 0x0F;
> +
> +    if(!repeat) {

> +        for(i = 0; i < CDG_FULL_WIDTH; i++) {
> +            for(j = 0; j < CDG_BORDER_HEIGHT; j++)
> +                buf[i + lsize * j] = color;
> +            for(j = CDG_FULL_HEIGHT - CDG_BORDER_HEIGHT; j < CDG_FULL_HEIGHT; j++)
> +                buf[i + lsize * j] = color;
> +        }

painting along vertical columns is inefficient


> +
> +        for(j = 12; j < CDG_FULL_HEIGHT - CDG_BORDER_HEIGHT; j++) {

you mix literals with named constants


[...]
> +static void cdg_tile_block(CDGraphicsContext *cc, CdgPacket* cp, int b)
> +{
> +    int c0, c1;
> +    int ci, ri;
> +    int byte, pix, xor_color, cur_color, new_color;
> +    int x, y;
> +    int lsize    = cc->frame.linesize[0];
> +    uint8_t *buf = cc->frame.data[0];
> +
> +    c0 = cp->data[0] & 0x0F;
> +    c1 = cp->data[1] & 0x0F;
> +    ri = (cp->data[2] & 0x1F) * 12;
> +    ci = (cp->data[3] & 0x3F) * 6;
> +
> +    if(ri > (CDG_FULL_HEIGHT - TILE_HEIGHT)) return;
> +    if(ci > (CDG_FULL_WIDTH - TILE_WIDTH)) return;
> +
> +    for(y = 0; y < 12; y++) {
> +        byte = cp->data[4+y] & 0x3F;
> +        for(x = 0; x < 6; x++) {
> +            pix = (byte >> (5-x)) & 0x01;

> +            if(b) {
> +                if(!pix)
> +                    xor_color = c0;
> +                else
> +                    xor_color = c1;
> +
> +                cur_color = buf[ci + x + (lsize * (ri + y))];
> +                new_color = cur_color ^ xor_color;
> +            } else {
> +                if(!pix)
> +                    new_color = c0;
> +                else
> +                    new_color = c1;
> +            }
> +            buf[ci + x + (lsize * (ri + y))] = new_color;


if(pix) color = c1;
else    color = c0;
if(b)
    color ^= buf[ci + x + (lsize * (ri + y))];
buf[ci + x + (lsize * (ri + y))] = color;




> +        }
> +    }
> +}
> +
> +static void cdg_scroll(CDGraphicsContext *cc, CdgPacket *cp, int roll_over)
> +{

> +    uint8_t temp_surface[CDG_FULL_WIDTH][CDG_FULL_HEIGHT];

some people dislike large arrays on the stack


> +    int color, h_scroll, v_scroll;
> +    int hscmd, h_off, vscmd, v_off;
> +    int v_scroll_pix, h_scroll_pix;
> +    int vinc, hinc, x, y;
> +    int lsize    = cc->frame.linesize[0];
> +    uint8_t *buf = cc->frame.data[0];
> +
> +    color = cp->data[0] & 0x0F;
> +    h_scroll = cp->data[1] & 0x3F;
> +    v_scroll = cp->data[2] & 0x3F;
> +
> +    hscmd = (h_scroll & 0x30) >> 4;
> +    h_off = (h_scroll & 0x07);
> +    vscmd = (v_scroll & 0x30) >> 4;
> +    v_off = (v_scroll & 0x0F);
> +

> +    h_off = h_off < 5 ? h_off : 5;
> +    v_off = v_off < 12 ? v_off : 12;

FFMIN


> +
> +    v_scroll_pix = 0;
> +    if(vscmd == 2)    v_scroll_pix = -12;
> +    if(vscmd == 1)    v_scroll_pix =  12;
> +
> +    h_scroll_pix = 0;
> +    if(hscmd == 2)    h_scroll_pix = -6;
> +    if(hscmd == 1)    h_scroll_pix =  6;
> +
> +    if(!h_scroll_pix && !v_scroll_pix)
> +        return;
> +
> +    vinc = v_scroll_pix + CDG_FULL_HEIGHT;
> +    hinc = h_scroll_pix + CDG_FULL_WIDTH;
> +
> +    for(y = 0; y < CDG_FULL_HEIGHT; y++) {
> +        for(x = 0; x < CDG_FULL_WIDTH; x++) {

> +            temp_surface[(x + hinc) % CDG_FULL_WIDTH][(y + vinc) % CDG_FULL_HEIGHT] =
> +                buf[x + y * lsize];

modulo is a slow operation


> +        }
> +    }
> +
> +    if(!roll_over) {
> +        if(v_scroll_pix > 0)
> +            for(y = 0; y < v_scroll_pix; y++)
> +                for(x = 0; x < CDG_FULL_WIDTH; x++)
> +                    temp_surface[x][y] = color;
> +        else if(v_scroll_pix < 0)
> +            for(y = CDG_FULL_HEIGHT + v_scroll_pix; y < CDG_FULL_HEIGHT; y++)
> +                for(x = 0; x < CDG_FULL_WIDTH; x++)
> +                    temp_surface[x][y] = color;
> +
> +        if(h_scroll_pix > 0)
> +            for(x = 0; x < h_scroll_pix; x++)
> +                for(y = 0; y < CDG_FULL_HEIGHT; y++)
> +                    temp_surface[x][y] = color;
> +        else if(h_scroll_pix < 0)
> +            for(x = CDG_FULL_WIDTH + h_scroll_pix; x < CDG_FULL_WIDTH; x++)
> +                for(y = 0; y < CDG_FULL_HEIGHT; y++)
> +                    temp_surface[x][y] = color;
> +    }
> +

> +    for(y = 0; y < CDG_FULL_HEIGHT; y++)
> +        for(x = 0; x < CDG_FULL_WIDTH; x++)
> +            buf[x + y * lsize] = temp_surface[x][y];

avoidable copy


[...]
> +static int read_header(AVFormatContext *s, AVFormatParameters *ap)
> +{
> +    int64_t result;
> +    AVStream *vst;
> +    ByteIOContext *pb = s->pb;
> +
> +    vst = av_new_stream(s, 0);
> +    if(!vst)
> +        return AVERROR(ENOMEM);
> +

> +    vst->codec->width      = CDG_FULL_WIDTH;
> +    vst->codec->height     = CDG_FULL_HEIGHT;
> +    vst->codec->pix_fmt    = PIX_FMT_PAL8;

these belong in the decoder


> +    vst->codec->codec_type = CODEC_TYPE_VIDEO;
> +    vst->codec->codec_id   = CODEC_ID_CDGRAPHICS;
> +
> +    /// 75 sectors/sec * 4 packets/sector = 300 packets/sec
> +    av_set_pts_info(vst, 32, 1, 300);
> +
> +    result = url_fsize(pb);
> +    vst->duration = (result * vst->time_base.den) / (CDG_PACKET_SIZE * 300);
> +    return 0;
> +}
> +

> +static int read_packet(AVFormatContext *s, AVPacket *pkt)
> +{
> +    int ret;
> +    ByteIOContext *pb = s->pb;
> +
> +    ret = av_get_packet(pb, pkt, CDG_PACKET_SIZE);
> +    if(pb->eof_reached == 1)
> +        return -1;
> +
> +    pkt->stream_index = 0;
> +    return 0;

dont ignore ret


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

Old school: Use the lowest level language in which you can solve the problem
            conveniently.
New school: Use the highest level language in which the latest supercomputer
            can solve the problem without the user falling asleep waiting.
-------------- 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/20091124/c620b176/attachment.pgp>



More information about the ffmpeg-devel mailing list