On Tue, 23 Oct 2012 17:43:34 -0400, Justin Ruggles <[email protected]> 
wrote:
> Although the libFLAC decoder cannot handle such a change, it is allowed by the
> spec and could potentially occur with live streams.
> ---
>  libavcodec/flac.c        |   19 +++++++++++++++++++
>  libavcodec/flac.h        |    3 +++
>  libavcodec/flac_parser.c |    1 +
>  libavcodec/flacdec.c     |   27 +++++++++------------------
>  4 files changed, 32 insertions(+), 18 deletions(-)
> 
> diff --git a/libavcodec/flac.c b/libavcodec/flac.c
> index d624beb..07da702 100644
> --- a/libavcodec/flac.c
> +++ b/libavcodec/flac.c
> @@ -19,6 +19,7 @@
>   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
>   */
>  
> +#include "libavutil/audioconvert.h"
>  #include "libavutil/crc.h"
>  #include "libavutil/log.h"
>  #include "bytestream.h"
> @@ -28,6 +29,15 @@
>  
>  static const int8_t sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
>  
> +static const int64_t flac_channel_layouts[6] = {
> +    AV_CH_LAYOUT_MONO,
> +    AV_CH_LAYOUT_STEREO,
> +    AV_CH_LAYOUT_SURROUND,
> +    AV_CH_LAYOUT_QUAD,
> +    AV_CH_LAYOUT_5POINT0,
> +    AV_CH_LAYOUT_5POINT1
> +};
> +
>  static int64_t get_utf8(GetBitContext *gb)
>  {
>      int64_t val;
> @@ -181,6 +191,14 @@ int avpriv_flac_is_extradata_valid(AVCodecContext *avctx,
>      return 1;
>  }
>  
> +void ff_flac_set_channel_layout(AVCodecContext *avctx)
> +{
> +    if (avctx->channels <= FF_ARRAY_ELEMS(flac_channel_layouts))
> +        avctx->channel_layout = flac_channel_layouts[avctx->channels - 1];
> +    else
> +        avctx->channel_layout = 0;
> +}
> +
>  void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct 
> FLACStreaminfo *s,
>                                const uint8_t *buffer)
>  {
> @@ -205,6 +223,7 @@ void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, 
> struct FLACStreaminfo *
>      avctx->channels = s->channels;
>      avctx->sample_rate = s->samplerate;
>      avctx->bits_per_raw_sample = s->bps;
> +    ff_flac_set_channel_layout(avctx);
>  
>      s->samples  = get_bits_long(&gb, 32) << 4;
>      s->samples |= get_bits(&gb, 4);
> diff --git a/libavcodec/flac.h b/libavcodec/flac.h
> index 55bacea..63f41c2 100644
> --- a/libavcodec/flac.h
> +++ b/libavcodec/flac.h
> @@ -137,4 +137,7 @@ int ff_flac_get_max_frame_size(int blocksize, int ch, int 
> bps);
>   */
>  int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb,
>                                  FLACFrameInfo *fi, int log_level_offset);
> +
> +void ff_flac_set_channel_layout(AVCodecContext *avctx);
> +
>  #endif /* AVCODEC_FLAC_H */
> diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c
> index 6c8c046..f0a37f3 100644
> --- a/libavcodec/flac_parser.c
> +++ b/libavcodec/flac_parser.c
> @@ -459,6 +459,7 @@ static int get_best_header(FLACParseContext* fpc, const 
> uint8_t **poutbuf,
>  
>      fpc->avctx->sample_rate = header->fi.samplerate;
>      fpc->avctx->channels    = header->fi.channels;
> +    ff_flac_set_channel_layout(fpc->avctx);
>      fpc->pc->duration       = header->fi.blocksize;
>      *poutbuf = flac_fifo_read_wrap(fpc, header->offset, *poutbuf_size,
>                                          &fpc->wrap_buf,
> diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c
> index 4ecf5f2..20af820 100644
> --- a/libavcodec/flacdec.c
> +++ b/libavcodec/flacdec.c
> @@ -66,15 +66,6 @@ typedef struct FLACContext {
>      FLACDSPContext dsp;
>  } FLACContext;
>  
> -static const int64_t flac_channel_layouts[6] = {
> -    AV_CH_LAYOUT_MONO,
> -    AV_CH_LAYOUT_STEREO,
> -    AV_CH_LAYOUT_SURROUND,
> -    AV_CH_LAYOUT_QUAD,
> -    AV_CH_LAYOUT_5POINT0,
> -    AV_CH_LAYOUT_5POINT1
> -};
> -
>  static int allocate_buffers(FLACContext *s);
>  
>  static void flac_set_bps(FLACContext *s)
> @@ -127,9 +118,6 @@ static av_cold int flac_decode_init(AVCodecContext *avctx)
>      avcodec_get_frame_defaults(&s->frame);
>      avctx->coded_frame = &s->frame;
>  
> -    if (avctx->channels <= FF_ARRAY_ELEMS(flac_channel_layouts))
> -        avctx->channel_layout = flac_channel_layouts[avctx->channels - 1];
> -
>      return 0;
>  }
>  
> @@ -421,7 +409,7 @@ static inline int decode_subframe(FLACContext *s, int 
> channel)
>  
>  static int decode_frame(FLACContext *s)
>  {
> -    int i;
> +    int i, ret;
>      GetBitContext *gb = &s->gb;
>      FLACFrameInfo fi;
>  
> @@ -430,12 +418,15 @@ static int decode_frame(FLACContext *s)
>          return -1;
>      }
>  
> -    if (s->channels && fi.channels != s->channels) {
> -        av_log(s->avctx, AV_LOG_ERROR, "switching channel layout mid-stream "
> -                                       "is not supported\n");
> -        return -1;
> +    if (s->channels && fi.channels != s->channels && s->got_streaminfo) {
> +        s->channels = s->avctx->channels = fi.channels;
> +        ff_flac_set_channel_layout(s->avctx);
> +        ret = allocate_buffers(s);
> +        if (ret < 0)
> +            return ret;
>      }
>      s->channels = s->avctx->channels = fi.channels;
> +    ff_flac_set_channel_layout(s->avctx);
>      s->ch_mode = fi.ch_mode;
>  
>      if (!s->bps && !fi.bps) {
> @@ -478,7 +469,7 @@ static int decode_frame(FLACContext *s)
>      s->samplerate = s->avctx->sample_rate = fi.samplerate;
>  
>      if (!s->got_streaminfo) {
> -        int ret = allocate_buffers(s);
> +        ret = allocate_buffers(s);
>          if (ret < 0)
>              return ret;
>          ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps);
> -- 
> 1.7.1
>

Looks ok 

-- 
Anton Khirnov
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to