[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