Browse Source

flacdec: allow mid-stream channel layout change

Although the libFLAC decoder cannot handle such a change, it is allowed by the
spec and could potentially occur with live streams.
tags/n1.1
Justin Ruggles 13 years ago
parent
commit
90fcac0e95
4 changed files with 32 additions and 18 deletions
  1. +19
    -0
      libavcodec/flac.c
  2. +3
    -0
      libavcodec/flac.h
  3. +1
    -0
      libavcodec/flac_parser.c
  4. +9
    -18
      libavcodec/flacdec.c

+ 19
- 0
libavcodec/flac.c View File

@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */


#include "libavutil/audioconvert.h"
#include "libavutil/crc.h" #include "libavutil/crc.h"
#include "libavutil/log.h" #include "libavutil/log.h"
#include "bytestream.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 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) static int64_t get_utf8(GetBitContext *gb)
{ {
int64_t val; int64_t val;
@@ -181,6 +191,14 @@ int avpriv_flac_is_extradata_valid(AVCodecContext *avctx,
return 1; 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, void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
const uint8_t *buffer) const uint8_t *buffer)
{ {
@@ -205,6 +223,7 @@ void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *
avctx->channels = s->channels; avctx->channels = s->channels;
avctx->sample_rate = s->samplerate; avctx->sample_rate = s->samplerate;
avctx->bits_per_raw_sample = s->bps; 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_long(&gb, 32) << 4;
s->samples |= get_bits(&gb, 4); s->samples |= get_bits(&gb, 4);


+ 3
- 0
libavcodec/flac.h View File

@@ -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, int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb,
FLACFrameInfo *fi, int log_level_offset); FLACFrameInfo *fi, int log_level_offset);

void ff_flac_set_channel_layout(AVCodecContext *avctx);

#endif /* AVCODEC_FLAC_H */ #endif /* AVCODEC_FLAC_H */

+ 1
- 0
libavcodec/flac_parser.c View File

@@ -459,6 +459,7 @@ static int get_best_header(FLACParseContext* fpc, const uint8_t **poutbuf,


fpc->avctx->sample_rate = header->fi.samplerate; fpc->avctx->sample_rate = header->fi.samplerate;
fpc->avctx->channels = header->fi.channels; fpc->avctx->channels = header->fi.channels;
ff_flac_set_channel_layout(fpc->avctx);
fpc->pc->duration = header->fi.blocksize; fpc->pc->duration = header->fi.blocksize;
*poutbuf = flac_fifo_read_wrap(fpc, header->offset, *poutbuf_size, *poutbuf = flac_fifo_read_wrap(fpc, header->offset, *poutbuf_size,
&fpc->wrap_buf, &fpc->wrap_buf,


+ 9
- 18
libavcodec/flacdec.c View File

@@ -66,15 +66,6 @@ typedef struct FLACContext {
FLACDSPContext dsp; FLACDSPContext dsp;
} FLACContext; } 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 int allocate_buffers(FLACContext *s);


static void flac_set_bps(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); avcodec_get_frame_defaults(&s->frame);
avctx->coded_frame = &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; return 0;
} }


@@ -421,7 +409,7 @@ static inline int decode_subframe(FLACContext *s, int channel)


static int decode_frame(FLACContext *s) static int decode_frame(FLACContext *s)
{ {
int i;
int i, ret;
GetBitContext *gb = &s->gb; GetBitContext *gb = &s->gb;
FLACFrameInfo fi; FLACFrameInfo fi;


@@ -430,12 +418,15 @@ static int decode_frame(FLACContext *s)
return -1; 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; s->channels = s->avctx->channels = fi.channels;
ff_flac_set_channel_layout(s->avctx);
s->ch_mode = fi.ch_mode; s->ch_mode = fi.ch_mode;


if (!s->bps && !fi.bps) { if (!s->bps && !fi.bps) {
@@ -478,7 +469,7 @@ static int decode_frame(FLACContext *s)
s->samplerate = s->avctx->sample_rate = fi.samplerate; s->samplerate = s->avctx->sample_rate = fi.samplerate;


if (!s->got_streaminfo) { if (!s->got_streaminfo) {
int ret = allocate_buffers(s);
ret = allocate_buffers(s);
if (ret < 0) if (ret < 0)
return ret; return ret;
ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps); ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps);


Loading…
Cancel
Save