[FFmpeg-devel] [PATCH] au: add duration info

Stefano Sabatini stefano.sabatini-lala at poste.it
Sun Jul 17 15:14:33 CEST 2011


On date Saturday 2011-07-16 17:36:55 +0200, Stefano Sabatini encoded:
> On date Thursday 2011-07-14 12:06:17 +0200, ami_stuff encoded:
> > Modified.
> > 
> > Regards
> 
> > diff --git a/libavformat/au.c b/libavformat/au.c
> > index 23365c4..f361a71 100644
> > --- a/libavformat/au.c
> > +++ b/libavformat/au.c
> > @@ -120,7 +120,7 @@ static int au_probe(AVProbeData *p)
> >  static int au_read_header(AVFormatContext *s,
> >                            AVFormatParameters *ap)
> >  {
> > -    int size;
> > +    int size, data_size = 0;
> >      unsigned int tag;
> >      AVIOContext *pb = s->pb;
> >      unsigned int id, channels, rate;
> > @@ -132,7 +132,12 @@ static int au_read_header(AVFormatContext *s,
> >      if (tag != MKTAG('.', 's', 'n', 'd'))
> >          return -1;
> >      size = avio_rb32(pb); /* header size */
> > -    avio_rb32(pb); /* data size */
> > +    data_size = avio_rb32(pb); /* size in bytes */
> > +
> > +    if (data_size < 0) {
> > +        av_log(s, AV_LOG_ERROR, "negative data_size\n");
> > +        return AVERROR_INVALIDDATA;
> > +    }
> >  
> >      id = avio_rb32(pb);
> >      rate = avio_rb32(pb);
> > @@ -159,6 +164,10 @@ static int au_read_header(AVFormatContext *s,
> >      st->codec->codec_id = codec;
> >      st->codec->channels = channels;
> >      st->codec->sample_rate = rate;
> > +
> > +    if (data_size)
> > +        st->duration = (int64_t)(data_size) / (st->codec->channels * (uint64_t)(av_get_bits_per_sample(st->codec->codec_id)>>3));

Re-reading the comment from Michael, I realived this was not what he
meant.

In case of coded samples, av_get_bits_per_sample(st->codec->codec_id)
can be < 8 so if you shift by >>3 you get a 0 in the denominator.

Also data_size << 3 may overflow, but if you cast the int to a
variable with a greater number of bits *before* to shift, then you're
sure it won't.

So you can write it as:

if (data_size) // data size expressed in bits
    st->duration = (((int64_t)data_size) << 3) / (st->codec->channels * (uint64_t)(av_get_bits_per_sample(st->codec->codec_id));

Also the "if (data_size)" check can be avoided since it will return
the same value of 0 if the expression is evaluated.

BTW I'm not totally sure that the int -> int64_t cast is to be
considered correct, e.g. it may happen that:
sizeof(int64_t) == sizeof(int)
in this case the two types have the same "numerability", (and in
general it could be even happen that sizeof(int64_t) < sizeof(int),
right?).

So a possibly safer alternative would be to use floating point
arithmetic:

bpp = av_get_bits_per_sample(st->codec->codec_id);
if (bpp) {
    double duration = (double)(data_size*8) / (st->codec->channels * bpp);
    st->duration = FFMAX((((int64_t)1)<<63)-1, duration); // trunc duration to its maximum admitted value
}

-- 
FFmpeg = Frightening and Fierce Multimedia Portentous Extensive Geisha


More information about the ffmpeg-devel mailing list