[FFmpeg-devel] [PATCH] CD+G Demuxer & Decoder
Michael Tison
blackspike
Wed Dec 2 09:44:21 CET 2009
Hi,
Attached is another attempt.
On Tue, Dec 1, 2009 at 9:42 AM, Michael Niedermayer <michaelni at gmx.at> wrote:
> On Tue, Dec 01, 2009 at 12:13:24AM -0800, Michael Tison wrote:
>> + ? ?int color;
>> + ? ?int repeat;
>> +
>> + ? ?color = cp->data[0] & 0x0F;
>> + ? ?repeat = cp->data[1] & 0x0F;
>> + ? ?if (!repeat)
>> + ? ? ? memset(cc->frame.data[0], color,
>> + ? ? ? ? ? ? ?cc->frame.linesize[0] * CDG_FULL_HEIGHT);
>> +}
>> +
>> +static void cdg_border_preset(CDGraphicsContext *cc, CdgPacket *cp)
>> +{
>> + ? ?int color;
>> + ? ?int repeat;
>> + ? ?int y;
>> + ? ?int lsize ? ?= cc->frame.linesize[0];
>> + ? ?uint8_t *buf = cc->frame.data[0];
>> +
>> + ? ?color ?= cp->data[0] & 0x0F;
>> + ? ?repeat = cp->data[1] & 0x0F;
>
> looks duplicated
Separated and put into function.
>> +static void cdg_tile_block(CDGraphicsContext *cc, CdgPacket *cp, int b)
>> +{
>> + ? ?int c0, c1;
>> + ? ?int ci, ri;
>> + ? ?int byte, pix, color;
>> + ? ?int x, y;
>> + ? ?int ai;
>> + ? ?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) * CDG_TILE_HEIGHT;
>> + ? ?ci = (cp->data[3] & 0x3F) * CDG_TILE_WIDTH;
>> +
>> + ? ?if (ri > (CDG_FULL_HEIGHT - CDG_TILE_HEIGHT))
>> + ? ? ? return;
>> + ? ?if (ci > (CDG_FULL_WIDTH - CDG_TILE_WIDTH))
>> + ? ? ? return;
>> +
>> + ? ?for (y = 0; y < CDG_TILE_HEIGHT; y++) {
>> + ? ? ? byte = cp->data[4 + y] & 0x3F;
>> + ? ? ? for (x = 0; x < CDG_TILE_WIDTH; x++) {
>> + ? ? ? ? ? pix = (byte >> (5 - x)) & 0x01;
>> + ? ? ? ? ? ai = ci + x + cc->hscroll + (lsize * (ri + y + cc->vscroll));
>
>> + ? ? ? ? ? assert(ai >> 0 && ai < CDG_FULL_HEIGHT * lsize);
>
> is it certain that no random input can make this fail?
Double negative? Typo with the bitwise shift too :(
I just got rid of the assert and ensured that the index wouldn't go
out of bounds before the for loops.
> [..]
>> +static void cdg_fill_rect_buf(int out_tl_x, int out_tl_y,
>
> copy not fill
Replaced.
>> +static int cdg_decode_frame(AVCodecContext *avctx,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?void *data, int *data_size, AVPacket *avpkt)
>> +{
>> + ? ?const uint8_t *buf = avpkt->data;
>> + ? ?int buf_size = avpkt->size;
>> + ? ?AVFrame new_frame;
>> + ? ?CDGraphicsContext *cc = avctx->priv_data;
>> + ? ?CdgPacket cp;
>> +
>> + ? ?if (avctx->reget_buffer(avctx, &cc->frame)) {
>> + ? ? ? av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
>> + ? ? ? return -1;
>> + ? ?}
>> +
>> + ? ?cp.command ? ? = bytestream_get_byte(&buf);
>> + ? ?cp.instruction = bytestream_get_byte(&buf);
>
>> + ? ?bytestream_get_buffer(&buf, (uint8_t *) & cp.parityQ, 2);
>> + ? ?bytestream_get_buffer(&buf, (uint8_t *) & cp.data, ? 16);
>> + ? ?bytestream_get_buffer(&buf, (uint8_t *) & cp.parityP, 2);
>
> parity is unused, use it or dont read it.
Gone.
> [...]
>> + ? ? ? *data_size = sizeof(AVFrame);
>> + ? ? ? *(AVFrame *) data = cc->frame;
>> + ? ? ? return buf_size;
>> + ? ?}
>> +
>> + ? ?*data_size = 0;
>> + ? ?*(AVFrame *) data = cc->frame;
>> + ? ?return 0;
>
> this looks like it can be done simpler
Simplified.
> [...]
>> +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;
>
> possible memleak, and wrong return code
Corrected I hope:
static int read_packet(AVFormatContext *s, AVPacket *pkt)
{
int ret;
ByteIOContext *pb = s->pb;
ret = av_get_packet(pb, pkt, CDG_PACKET_SIZE);
if (ret != CDG_PACKET_SIZE)
return AVERROR(EIO);
pkt->stream_index = 0;
return 0;
}
I just took this return value from iss.c because I wasn't entirely
sure what to return.
On Tue, Dec 1, 2009 at 5:58 AM, Vitor Sessak <vitor1001 at gmail.com> wrote:
> Michael Tison wrote:
>> +static av_cold int cdg_decode_init(AVCodecContext *avctx)
>> +{
>> + CDGraphicsContext *cc = avctx->priv_data;
>> +
>> + cdg_init_frame(&cc->frame);
>> +
>> + cc->hscroll = 0;
>> + cc->vscroll = 0;
>
> Unneeded, cc is already memset to 0 before calling decode_init().
Removed.
>> +
>> +static void cdg_load_color_table(CDGraphicsContext *cc, CdgPacket *cp,
>> + int low)
>> +{
>
> I think a s/color.table/palette/ would be closer to usual multimedia
> terminology.
Substituted.
>> +static void cdg_fill_rect_buf(int out_tl_x, int out_tl_y,
>> + uint8_t *out,
>> + int in_tl_x, int in_tl_y,
>> + uint8_t *in, int w, int h, int lsize)
>> +{
>> + int x, y;
>> + in = in + in_tl_x + in_tl_y * lsize;
>> + out = out + out_tl_x + out_tl_y * lsize;
>> + for (y = 0; y < h; y++)
>> + for (x = 0; x < w; x++)
>> + out[x + y * lsize] = in[x + y * lsize];
>> +}
>> +
>
> The inner loop is a memcpy().
Done.
>> +static void cdg_fill_rect_preset(int tl_x, int tl_y,
>> + uint8_t *out, int color,
>> + int w, int h, int lsize)
>> +{
>> + int x, y;
>> +
>> + for (y = tl_y; y < tl_y + h; y++)
>> + for (x = tl_x; x < tl_x + w; x++)
>> + out[x + y * lsize] = color;
>> +}
>
> The inner loop is a memset().
Done.
>> + memcpy(new_frame->data[1], cc->frame.data[1],
>> + CDG_COLOR_TABLE_SIZE * 4);
>> +
>> + for (y = 0; y < CDG_FULL_HEIGHT; y++) {
>> + for (x = 0; x < lsize; x++) {
>> + ai = x + hinc + lsize * (y + vinc);
>> + if (ai >= 0 && ai < CDG_FULL_HEIGHT * lsize)
>> + out[ai] = in[x + y * lsize];
>> + }
>> + }
>
> for (x = FFMAX(0, hinc); x < FFMIN(lsize, hinc); x++)
> and similar for y and them there is no need for the slow branch in the inner
> loop.
Changed.
>> +static int cdg_decode_frame(AVCodecContext *avctx,
>> + void *data, int *data_size, AVPacket *avpkt)
>> +{
>> + const uint8_t *buf = avpkt->data;
>> + int buf_size = avpkt->size;
>> + AVFrame new_frame;
>> + CDGraphicsContext *cc = avctx->priv_data;
>> + CdgPacket cp;
>> +
>> + if (avctx->reget_buffer(avctx, &cc->frame)) {
>> + av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
>> + return -1;
>> + }
>> +
>> + cp.command = bytestream_get_byte(&buf);
>> + cp.instruction = bytestream_get_byte(&buf);
>> + bytestream_get_buffer(&buf, (uint8_t *) & cp.parityQ, 2);
>> + bytestream_get_buffer(&buf, (uint8_t *) & cp.data, 16);
>> + bytestream_get_buffer(&buf, (uint8_t *) & cp.parityP, 2);
>
> Are those casts needed?
I get a compiler warning if they aren't there.
On Tue, Dec 1, 2009 at 5:14 AM, Diego Biurrun <diego at biurrun.de> wrote:
> On Tue, Dec 01, 2009 at 12:13:24AM -0800, Michael Tison wrote:
>> --- libavcodec/cdgraphics.c (revision 0)
>> +++ libavcodec/cdgraphics.c (revision 0)
>> @@ -0,0 +1,416 @@
>> + frame->buffer_hints = FF_BUFFER_HINTS_VALID |
>> + FF_BUFFER_HINTS_PRESERVE |
>> + FF_BUFFER_HINTS_REUSABLE;
>
> Align the |.
Aligned.
>> + color = cp->data[0] & 0x0F;
>> + repeat = cp->data[1] & 0x0F;
>
> Align the =.
Aligned.
>> + r = (color >> 8) & 0x000F;
>> + g = (color >> 4) & 0x000F;
>> + b = (color) & 0x000F;
>
> Align the &.
Aligned.
>> + in = in + in_tl_x + in_tl_y * lsize;
>> + out = out + out_tl_x + out_tl_y * lsize;
>
> align
Aligned.
Again, thanks for the feedback!
Michael
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cdgraphicsv3.patch
Type: text/x-diff
Size: 19126 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20091202/6000827c/attachment.patch>
More information about the ffmpeg-devel
mailing list