mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-28 20:53:54 +02:00
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.
This commit is contained in:
parent
268f8ba112
commit
90fcac0e95
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user