[FFmpeg-devel] [PATCH][RFC] QCP demuxer

Kenan Gillet kenan.gillet
Thu May 14 21:51:35 CEST 2009


Hi,
On May 14, 2009, at 1:14 AM, Reimar D?ffinger wrote:

> On Wed, May 13, 2009 at 03:11:57PM -0700, Kenan Gillet wrote:
>> + * @param guid contains at least 16 bytes
>> + * @return 1 if the guid is a qcelp_13k guid, 0 otherwise
>> + */
>> +static int is_qcelp_13k_quid(const uint8_t *guid) {
>> +    return !memcmp(guid,     guid_qcelp_13k,   16) ||
>> +          (!memcmp(guid + 1, guid_qcelp_13k+1, 15) && guid[0] ==  
>> 0x42);
>
> Some explanation for this would be nice.
> Also both
> return (guid[0] == 0x41 || guid[0] == 0x42) && !memcmp(guid + 1,  
> guid_qcelp_13k_part,
> sizeof(guid_qcelp_13k_part));
>

i like this one the best, also explanation added.

>
>> +static int qcp_probe(AVProbeData *pd)
>> +{
>> +    if (AV_RL32(pd->buf   ) == MKTAG('R', 'I', 'F', 'F') &&
>> +        AV_RL32(pd->buf+ 8) == MKTAG('Q', 'L', 'C', 'M') &&
>> +        AV_RL32(pd->buf+12) == MKTAG('f', 'm', 't', ' '))
>
> Maybe
> AV_RL32(pd->buf    ) == AV_RL32("RIFF") &&
> AV_RL64(pd->buf + 8) == AV_RL64("QLCMfmt ")
> or memcmp for the second part at least would be nicer.

fixed


>
>> +    unsigned char buf[16];
>
> You use uint8_t elsewhere.

fixed


>
>> +    if (is_qcelp_13k_quid(buf)) {
>
> quid?

fixed


>> +    url_fskip(pb, 2 + 80 + 2); // codec-version + codec-name +  
>> average-bps
>
> I think the average bps can be stored somewhere...

stored in AVCodec.bit_rate


>
>> +    c->nb_rates = get_le32(pb);
>> +    for (i=0; i<8; i++) {
>> +        c->rates_mapping[i].size = get_byte(pb);
>> +        c->rates_mapping[i].mode = get_byte(pb);
>> +    }
>> +
>> +    url_fskip(pb, 20 + 4 + 4); // reserved + "vrat" + chunk-size
>
> I'm not sure that skipping all those chunk sizes is such a great idea,
> it makes very strong assumptions about the format, while RIFF is very
> flexible...

moved vrat chunk handling in qcp_read_packet, it fixes the playing of
fix 13k_fixed_full.qcp and 13k_fixed_half.qcp samples which are missing
the mandatory vrat chunk.

>
>> +                int ret = av_new_packet(pkt, buf_size);
>> +
>> +                if (ret < 0)
>> +                    return ret;
>> +
>> +                pkt->pos = url_ftell(pb);
>> +
>> +                ret = get_buffer(pb, pkt->data+1, buf_size-1);
>
>
> Does the decoder really need "mode" when it already has the packet  
> size?

no, the decoder does not really need "mode" but is possible to send an  
empty packet
to the decoder? because qcelp has a SILENCE mode whose packet is empty.


> Because then you could use av_get_packet. Actually I am tempted to  
> say:
> just seek back one byte and use av_get_packet.

that what the code used to do, but i though it was kind of ugly.


>
>> +                if (ret <= 0 || buf_size != ret + 1) {
>> +                    av_free_packet(pkt);
>> +                    av_log(s, AV_LOG_ERROR, "Packet size is too  
>> small.\n");
>> +                    return ret <= 0 ? ret : AVERROR(EIO);
>> +                }
>
> Usually FFmpeg also returns partial packets, to allow e.g. to better
> recover broken or badly cut files.

fixed, i kept the warning though.


>
>> +                c->data_size -= buf_size;
>> +                pkt->data[0] = mode;
>> +                av_shrink_packet(pkt, buf_size);
>
> The packet is already buf_size large, so what is the point of that?

removed


>> +                if (!c->data_size && c->data_has_pad)
>> +                    get_byte(pb);
>
> That data_size stuff is a bit unfortunate, it means that seeking will
> not be possible by using the generic implementation.

I am not sure to understand the issue of "data_size stuff."
Could you elaborate? What would be needed for the generic
implementation to work? a count of data packet is available
in the vrat chunk which should be present in valid file.


> Also why not e.g. just making sure that our position is two-byte
> aligned before reading a tag?
> Either
> if (url_ftell() & 1) get_byte();
> or
> if (c->data_has_pad) {
>  get_byte();
>  c->data_has_pad = 0;
> }
> directly before tag = ...;

fixed


>> +        case MKTAG('o', 'f', 'f', 's'):
>> +            url_fskip(pb, chunk_size);
>> +            break;
>> +        case MKTAG('t', 'e', 'x', 't'):
>> +            url_fskip(pb, chunk_size);
>> +            if (chunk_size & 1)
>> +                get_byte(pb); // 0 padding
>> +            break;
>
> Why not make the default case like that?

good idea, it would make the demuxer more flexible.


> Also you always need to skip padding for odd sizes, though
> you can merge that with the odd data size case if you use either
> of my suggestions above.

padding is only for text and data chunks as the other chunks have
already even sizes.
I used your suggestions above anyway.


>
>> +        case MKTAG('l', 'a', 'b', 'l'):
>> +            get_buffer(pb, c->label, 48);
>> +            break;
>
> What's the point of reading that (and wasting bytes in the context for
> it)?

it is for application use.
removed for now, as well as the config.

>
>> +        case 0:
>> +            if (url_feof(pb))
>> +                break;
>
> Why inside the switch? If it's eof shouldn't you just always return
> AVERROR_EOF?

no longer needed

thanks for the review

will post an updated patch

Kenan





More information about the ffmpeg-devel mailing list