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

Michael Tison blackspike
Tue Dec 15 03:40:17 CET 2009


Revised patch attached.

On Fri, Dec 11, 2009 at 4:51 PM, Reimar D?ffinger
<Reimar.Doeffinger at gmx.de> wrote:
> On Thu, Dec 10, 2009 at 10:59:23PM -0800, Michael Tison wrote:
>> +static int read_packet(AVFormatContext *s, AVPacket *pkt)
>> +{
>> + ? ?int ret;
>> +
>> + ? ?ret = av_get_packet(s->pb, pkt, CDG_PACKET_SIZE);
>> + ? ?if (ret >= 0 && ret < CDG_PACKET_SIZE) {
>> + ? ? ? ?av_free_packet(pkt);
>> + ? ? ? ?ret = AVERROR(EIO);
>> + ? ?}
>> + ? ?pkt->stream_index = 0;
>> + ? ?return ret;
>
> I'd like to restate that I consider this kind of code highly silly, it
> 1) misuses AVERROR(EIO) for something that probably is not an I/O error
> 2) it means a single lost byte which might not make a visible difference
> ? otherwise now drops the whole (last) packet
> 3) it makes it unnecessarily difficult to test the decoder code for robustness
> ? and sufficient buffer end checks (no, those in libavformat are not of any
> ? use, libavcodec is not supposed to be only used with libavformat)
> 4) and all of that at the cost of additional code and complexity
>
> Or to put it succinctly, I think it is adding code to make it behave worse.

Agreed.

On Fri, Dec 11, 2009 at 2:33 PM, Michael Niedermayer <michaelni at gmx.at> wrote:
> On Thu, Dec 10, 2009 at 10:59:23PM -0800, Michael Tison wrote:
> [...]
>> +static int cdg_tile_block(CDGraphicsContext *cc, uint8_t *data, int b)
>> +{
>> +    int ci, ri;
>> +    int color;
>> +    int x, y;
>> +    int ai;
>> +    int stride   = cc->frame.linesize[0];
>> +    uint8_t *buf = cc->frame.data[0];
>> +
>> +    ri = (data[2] & 0x1F) * CDG_TILE_HEIGHT + cc->vscroll;
>> +    ci = (data[3] & 0x3F) * CDG_TILE_WIDTH  + cc->hscroll;
>> +
>> +    if ((unsigned) ri > (CDG_FULL_HEIGHT - CDG_TILE_HEIGHT)) {
>
> you could make ci/ri unsigned which would avoid this cast

Declared unsigned.

>> +        av_log(NULL, AV_LOG_ERROR, "tile is out of height range\n");
>
> NULL is a bad context

Fixed.

> [...]
>> +static void cdg_copy_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 stride)
>> +{
>> +    int y;
>> +
>> +    in  = in  + in_tl_x  + in_tl_y  * stride;
>
> in +=

Ouch. Fixed.

> [...]
>> +static void cdg_fill_wrapper(int out_tl_x, int out_tl_y, uint8_t *out,
>> +                             int in_tl_x, int in_tl_y, uint8_t *in,
>> +                             int color, int w, int h, int stride, int roll)
>> +{
>
>> +    if (roll)
>> +        cdg_copy_rect_buf(out_tl_x, out_tl_y, out, in_tl_x, in_tl_y,
>> +                          in, w, h, stride);
>> +    else
>
> missing {}
> btw, you should try tools/patcheck

Added.

> [...]
>> +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;
>> +    int ret, xor, cpy;
>> +    uint8_t command, inst;
>> +    uint8_t cdg_data[CDG_DATA_SIZE];
>> +    AVFrame new_frame;
>> +    CDGraphicsContext *cc = avctx->priv_data;
>> +
>> +    if (avctx->reget_buffer(avctx, &cc->frame)) {
>> +        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
>> +        return -1;
>> +    }
>> +
>> +    command = bytestream_get_byte(&buf);
>> +    inst    = bytestream_get_byte(&buf);
>> +    buf += 2;  /// skipping 2 unneeded bytes
>> +    bytestream_get_buffer(&buf, cdg_data, CDG_DATA_SIZE);
>> +
>> +    if ((command & CDG_MASK) == CDG_COMMAND) {
>> +        switch (inst & CDG_MASK) {
>> +        case CDG_INST_MEMORY_PRESET:
>> +            if (!(cdg_data[1] & 0x0F))
>> +                memset(cc->frame.data[0], cdg_data[0] & 0x0F,
>> +                       cc->frame.linesize[0] * CDG_FULL_HEIGHT);
>> +            break;
>> +        case CDG_INST_LOAD_PAL_LO:
>> +            cdg_load_palette(cc, cdg_data, 1);
>> +            break;
>> +        case CDG_INST_LOAD_PAL_HIGH:
>> +            cdg_load_palette(cc, cdg_data, 0);
>> +            break;
>> +        case CDG_INST_BORDER_PRESET:
>> +            cdg_border_preset(cc, cdg_data);
>> +            break;
>> +        case CDG_INST_TILE_BLOCK_XOR:
>> +        case CDG_INST_TILE_BLOCK:
>
>> +            xor = (inst & CDG_MASK) == CDG_INST_TILE_BLOCK_XOR ? 1 : 0;
>
> ?1:0 is superflous

Compacted.

> [..]
>> +static int read_header(AVFormatContext *s, AVFormatParameters *ap)
>> +{
>> +    AVStream *vst;
>> +
>> +    vst = av_new_stream(s, 0);
>> +    if (!vst)
>> +        return AVERROR(ENOMEM);
>> +
>> +    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);
>> +
>
>> +    vst->duration = (url_fsize(s->pb) * vst->time_base.den) / (CDG_PACKET_SIZE * 300);
>
> url_fsize() can fail, this is missing error checking

Checked.

Thanks again!

Michael
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cdgraphicsv8.patch
Type: text/x-diff
Size: 18541 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20091214/b1384b13/attachment.patch>



More information about the ffmpeg-devel mailing list