[FFmpeg-devel] [PATCH] flac demuxer

Michael Niedermayer michaelni
Tue Apr 29 20:21:42 CEST 2008


On Mon, Apr 28, 2008 at 11:34:01PM -0400, Justin Ruggles wrote:
> Michael Niedermayer wrote:
> > On Mon, Apr 28, 2008 at 05:31:07PM -0400, Justin Ruggles wrote:
> > [...]
> >>>
> >>>> diff --git a/libavcodec/flac.c b/libavcodec/flac.c
> >>>> index b849e7f..ed5b2d2 100644
> >>>> --- a/libavcodec/flac.c
> >>>> +++ b/libavcodec/flac.c
> >>>> @@ -40,13 +40,13 @@
> >>>>  #include "bitstream.h"
> >>>>  #include "golomb.h"
> >>>>  #include "crc.h"
> >>>> +#include "flac.h"
> >>>>  
> >>>>  #undef NDEBUG
> >>>>  #include <assert.h>
> >>>>  
> >>>>  #define MAX_CHANNELS 8
> >>>>  #define MAX_BLOCKSIZE 65535
> >>>> -#define FLAC_STREAMINFO_SIZE 34
> >>>>  
> >>>>  enum decorrelation_type {
> >>>>      INDEPENDENT,
> >>>> @@ -98,6 +98,36 @@ static void metadata_streaminfo(FLACContext *s);
> >>>>  static void allocate_buffers(FLACContext *s);
> >>>>  static int metadata_parse(FLACContext *s);
> >>>>  
> >>>> +int ff_flac_parse_streaminfo(FLACStreaminfo *s, const uint8_t *buffer)
> >>>> +{
> >>>> +    GetBitContext gbc;
> >>>> +    init_get_bits(&gbc, buffer, FLAC_STREAMINFO_SIZE*8);
> >>>> +
> >>>> +    s->min_block_size = get_bits(&gbc, 16);
> >>>> +    s->max_block_size = get_bits(&gbc, 16);
> >>>> +    if(s->max_block_size < 16)
> >>>> +        return -1;
> >>>> +
> >>>> +    skip_bits_long(&gbc, 24); // skip min frame size
> >>>> +    s->max_frame_size = get_bits_long(&gbc, 24);
> >>>> +
> >>>> +    s->sample_rate = get_bits_long(&gbc, 20);
> >>>> +    if(s->sample_rate < 1 || s->sample_rate > 655350)
> >>>> +        return -1;
> >>>> +
> >>>> +    s->channels = get_bits(&gbc, 3) + 1;
> >>>> +
> >>>> +    s->bps = get_bits(&gbc, 5) + 1;
> >>>> +    if(s->bps < 8 || s->bps & 0x3)
> >>>> +        return -1;
> >>>> +
> >>>> +    s->total_samples = get_bits_long(&gbc, 36);
> >>>> +
> >>>> +    // don't need to parse MD5 checksum
> >>>> +
> >>>> +    return 0;
> >>>> +}
> >>> code duplication
> >> How is that code duplication if I'm removing the similar code in the
> >> same commit?  I could try to modify the existing function, maybe in
> >> several steps, if that would make it more obvious what is happening.
> > 
> > Well maybe "duplication" is the wrong word. Senseless bloat is maybe better
> > 
> > diffstat says:
> >  flac.c |   56 +++++++++++++++++++++++++++++++++++++++++++-------------
> >  flac.h |   51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
> >  2 files changed, 93 insertions(+), 14 deletions(-)
> > 
> > This hardly can count as moving code around, if id assume all the removed
> > lines are moved then 14 turn into 93 thats more than 6 times.
> > Also even if one completely ignores flac.h its still huge bloat.
> > 
> > The naive solution of litterally duplicating the code would be less
> > bloated.
> 
> That diffstat makes it look worse than it really is, but still, I was
> too focused on the final result and not on making each step as small and
> clean as possible.  The final code has added checks for header validity
> and more whitespace.  But for now, I'll just take it one step at a time,
> so you can reject the "bloat" later if you wish. :)

:)


[...]
> > 
> >> i was trying to avoid large
> >> patches.  does this sound any better?
> >>
> >> - create and use a common struct for streaminfo data
> >>
> >> - modify streaminfo header parsing in flac.c to be sharable
> >>
> >> - split out the flac demuxer into a new file with same functionality as
> >> it has currently
> >>
> >> - move metadata parsing from the decoder to demuxer (in a single, kinda
> >> big, commit)
> > 
> > I really do not know what is best without seeing the patches. Basically
> > they should be clean, small and definitly not add more code than they
> > remove unless really needed.
> 
> ok. I'll try again with a focus on making the changes as small and clean
> as possible rather than on the final result.
> 
> Here is the first patch which allows for the streaminfo parsing function
> to eventually be shared with the demuxer.
> 
> Thanks,
> Justin
> 
> 
>  libavcodec/flac.c |   77
> +++++++++++++++++++++++++++++++++-------------------
>  libavcodec/flac.h |   43 +++++++++++++++++++++++++++++
>  2 files changed, 92 insertions(+), 28 deletions(-)
> 

[...]
> +/**
> + * Data needed from the Streaminfo header for use by the raw FLAC demuxer
> + * and/or the FLAC decoder.
> + */
> +#define FLACSTREAMINFO \
> +    int min_blocksize;      /**< minimum block size, in samples          */\
> +    int max_blocksize;      /**< maximum block size, in samples          */\
> +    int max_framesize;      /**< maximum frame size, in bytes            */\
> +    int samplerate;         /**< sample rate                             */\
> +    int channels;           /**< number of channels                      */\
> +    int bps;                /**< bits-per-sample                         */\
> +    uint64_t total_samples; /**< total number of samples, or 0 if unknown*/\
> +
> +typedef struct FLACStreaminfo {
> +    FLACSTREAMINFO
> +} FLACStreaminfo;

Wont these 2 be needed in a header later?


[...]
> @@ -117,13 +133,13 @@ static av_cold int flac_decode_init(AVCodecContext * avctx)
>      return 0;
>  }
>  
> -static void dump_headers(FLACContext *s)
> +static void dump_headers(AVCodecContext *avctx, FLACStreaminfo *s)
>  {
> -    av_log(s->avctx, AV_LOG_DEBUG, "  Blocksize: %d .. %d (%d)\n", s->min_blocksize, s->max_blocksize, s->blocksize);
> -    av_log(s->avctx, AV_LOG_DEBUG, "  Max Framesize: %d\n", s->max_framesize);
> -    av_log(s->avctx, AV_LOG_DEBUG, "  Samplerate: %d\n", s->samplerate);
> -    av_log(s->avctx, AV_LOG_DEBUG, "  Channels: %d\n", s->channels);
> -    av_log(s->avctx, AV_LOG_DEBUG, "  Bits: %d\n", s->bps);
> +    av_log(avctx, AV_LOG_DEBUG, "  Blocksize: %d .. %d\n", s->min_blocksize, s->max_blocksize);
> +    av_log(avctx, AV_LOG_DEBUG, "  Max Framesize: %d\n", s->max_framesize);
> +    av_log(avctx, AV_LOG_DEBUG, "  Samplerate: %d\n", s->samplerate);
> +    av_log(avctx, AV_LOG_DEBUG, "  Channels: %d\n", s->channels);
> +    av_log(avctx, AV_LOG_DEBUG, "  Bits: %d\n", s->bps);
>  }

This could be in a seperate patch


>  
>  static void allocate_buffers(FLACContext *s){
> @@ -143,28 +159,33 @@ static void allocate_buffers(FLACContext *s){
>      s->bitstream= av_fast_realloc(s->bitstream, &s->allocated_bitstream_size, s->max_framesize);
>  }
>  

> -static void metadata_streaminfo(FLACContext *s)
> +int ff_flac_parse_streaminfo(AVCodecContext *avctx, FLACStreaminfo *s,
> +                             const uint8_t *buffer)
>  {
> +    GetBitContext gb;
> +    init_get_bits(&gb, buffer, FLAC_STREAMINFO_SIZE*8);

Why is the change from GetBitContext to uint8_t * done? It does not seem
needed? All callers have a GetBitContext already.


> +
>      /* mandatory streaminfo */
> -    s->min_blocksize = get_bits(&s->gb, 16);
> -    s->max_blocksize = get_bits(&s->gb, 16);
> +    s->min_blocksize = get_bits(&gb, 16);
> +    s->max_blocksize = get_bits(&gb, 16);

This as well could be in a seperate patch


>  
> -    skip_bits(&s->gb, 24); /* skip min frame size */
> -    s->max_framesize = get_bits_long(&s->gb, 24);
> +    skip_bits(&gb, 24); /* skip min frame size */
> +    s->max_framesize = get_bits_long(&gb, 24);
>  
> -    s->samplerate = get_bits_long(&s->gb, 20);
> -    s->channels = get_bits(&s->gb, 3) + 1;
> -    s->bps = get_bits(&s->gb, 5) + 1;
> +    s->samplerate = get_bits_long(&gb, 20);
> +    s->channels = get_bits(&gb, 3) + 1;
> +    s->bps = get_bits(&gb, 5) + 1;
>  
> -    s->avctx->channels = s->channels;
> -    s->avctx->sample_rate = s->samplerate;
> +    avctx->channels = s->channels;
> +    avctx->sample_rate = s->samplerate;
>  
> -    skip_bits(&s->gb, 36); /* total num of samples */
> +    skip_bits(&gb, 36); /* total num of samples */
>  
> -    skip_bits(&s->gb, 64); /* md5 sum */
> -    skip_bits(&s->gb, 64); /* md5 sum */
> +    skip_bits(&gb, 64); /* md5 sum */
> +    skip_bits(&gb, 64); /* md5 sum */
>  
> -    dump_headers(s);
> +    dump_headers(avctx, s);

> +    return 0;

if its always return 0 than it could as well stay void


>  }
>  
>  /**
> @@ -193,9 +214,9 @@ static int metadata_parse(FLACContext *s)
>              if (metadata_size) {
>                  switch (metadata_type) {
>                  case METADATA_TYPE_STREAMINFO:
> -                    metadata_streaminfo(s);
> +                    ff_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s,
> +                            s->gb.buffer+get_bits_count(&s->gb)/8);
>                      streaminfo_updated = 1;
> -                    break;
>  
>                  default:
>                      for (i=0; i<metadata_size; i++)


Is the removed break; intended?


[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Its not that you shouldnt use gotos but rather that you should write
readable code and code with gotos often but not always is less readable
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080429/0cade07a/attachment.pgp>



More information about the ffmpeg-devel mailing list