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

Anssi Hannula anssi.hannula
Mon Apr 2 14:18:04 CEST 2007


Reimar D?ffinger wrote:
> Hello,

Hi!

> On Sun, Apr 01, 2007 at 11:04:14PM +0300, Anssi Hannula wrote:
>> +static inline int c93_conv_offset(int offset, int x, int y, int size,
>> +                                                    int stride)
>> +{
>> +    int prev_x = offset % 320 + x;
>> +    int prev_y = offset / 320 + y;
>> +    if (prev_x >= 320) {
>> +        prev_x -= 320;
>> +        prev_y += size;
>> +    }
>> +    return prev_y*stride+prev_x;
>> +}
> 
> seems non-obvious enough to me to warrant a doxygen comment...

Indeed, but as Michael said, this should be made more efficient.

>> +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 = (AVFrame*) &(c93->pictures[c93->currentpic]);
>> +    AVFrame * const oldpic = (AVFrame*) &(c93->pictures[1 - c93->currentpic]);
> 
> Hmm... What's the point of those casts? They seem useless to me. Also it
> seems weird to me to cast to (AVFrame*) but actually assigning to
> AVFrame * const.

Right, the casts are unneeded.

>> +    c93->currentpic = c93->currentpic ? 0 : 1;
> 
> c93->currentpic = !c93->currentpic;
> or
> c93->currentpic = 1 - c93->currentpic;
> 
> whichever you choose, IMO make it the same as you use for setting
> oldpic.

OK.

[...]
> 
>> +
>> +        switch (bt1) {
>> +        case C93_8X8_FROM_PREV:
>> +            offset = AV_RL16(buf);
>> +            buf += 2;
>> +            for (j = 0; j < 8; j++)
>> +                for (i = 0; i < 8; i++) {
>> +                    int loc = c93_conv_offset(offset, i, j, 8, stride);
>> +                    if (loc >= 192 * stride + 320) {
>> +                        av_log(avctx, AV_LOG_ERROR, "invalid offset %d for"
>> +                                " mode 2 at %dx%d\n", offset, x, y);
>> +                        return -1;
>> +                    }
>> +                    out[(y+j)*stride+x+i] = oldpic->data[0][loc];
>> +                }
> 
> These two loops look similar enough to those of the other case that you
> should try factoring it out into an extra function.

Indeed.

>> +            break;
>> +
>> +        case C93_4X4_FROM_PREV:
>> +            for (k = 0; k < 4; k++) {
>> +                y_off = k > 1 ? 4 : 0;
>> +                x_off = (k % 2) ? 4 : 0;
> 
> Avoid % where it is pointless. Here k & 1 will do at least as well.

OK.

>> +static int c93_probe(AVProbeData *p)
>> +{
>> +    if (p->buf_size < 13)
>> +        return 0;
>> +
>> +    if (p->buf[0] == 0x01 && p->buf[1] == 0x00 &&
>> +        p->buf[4] == 0x01 + p->buf[2] &&
>> +        p->buf[8] == p->buf[4] + p->buf[6] &&
>> +        p->buf[12] == p->buf[8] + p->buf[10])
>> +        return AVPROBE_SCORE_MAX / 2;
> 
> Did you have any kind of misdetection or is the / 2 just because the
> check seems not too reliable?

The latter.

>> +    videosize = get_le16(pb);
>> +    url_fskip(pb, videosize);
>> +    palettesize = get_le16(pb);
>> +
>> +    ret = av_new_packet(pkt, videosize + palettesize + 1);
>> +    if (ret < 0)
>> +        return ret;
>> +
>> +    pkt->data[0] = palettesize ? 0x01 : 0x00;
> 
> Could use !!palettesize instead...

OK.

>> +
>> +    if (palettesize) {
>> +        if (palettesize != 768) {
>> +            av_log(s, AV_LOG_ERROR, "invalid palette size %u\n", palettesize);
>> +            av_free_packet(pkt);
>> +            return AVERROR_INVALIDDATA;
>> +        }
>> +        ret = get_buffer(pb, pkt->data + 1, palettesize);
>> +        if (ret < palettesize) {
>> +            av_free_packet(pkt);
>> +            return AVERROR_IO;
>> +        }
>> +    }
>> +    url_fskip(pb, -(palettesize + videosize + 2));
> 
> seeking, especially seeking backwards should be avoided where possible.
> Just try playing the file directly from http or ftp and you'll see why.
> I guess this would be a bit simpler if we had a proper way to handle
> palette. As I understand the code sending the palette in a second packet
> is not an option since it is needed already for the frame that's stored
> directly in front of it?

Yes.

However, since the palettesize is always 768 or 0, we could just
allocate the packet with size = videosize + 768 + 1, with the 768 bytes
unused when the palette is not sent. This would allow us to remove the
backward seeking.

>> +    ret = get_buffer(pb, pkt->data + palettesize + 1, videosize);
>> +    if (ret < videosize) {
>> +        av_free_packet(pkt);
>> +        return AVERROR_IO;
>> +    }
>> +    url_fskip(pb, palettesize + 2);
>> +    pkt->size = palettesize + videosize + 1;
> 
> No need to set that since that's exactly the number you gave to
> av_new_packet...

OK.

>> +    pkt->stream_index = 0;
>> +    c93->decode_audio = c93->current_block * 32 + c93->current_frame;
>> +    /* only the first frame is guaranteed to not reference previous frames */
>> +    if (c93->decode_audio == 0) {
>> +        pkt->flags |= PKT_FLAG_KEY;
>> +        pkt->data[0] |= 0x02;
>> +    }
> 
> Can you explain this audio stuff? It seems weird, you create an audio
> stream but never add any packets to it..

In line 134 voc_get_packet() is called (the audio frame is actually a
complete VOC file).

-- 
Anssi Hannula





More information about the ffmpeg-devel mailing list