*/
/**
- * @file flacdec.c
+ * @file libavcodec/flacdec.c
* FLAC (Free Lossless Audio Codec) decoder
* @author Alex Beregszaszi
*
#define MAX_CHANNELS 8
#define MAX_BLOCKSIZE 65535
-#define FLAC_STREAMINFO_SIZE 34
enum decorrelation_type {
INDEPENDENT,
typedef struct FLACContext {
FLACSTREAMINFO
- AVCodecContext *avctx;
- GetBitContext gb;
+ AVCodecContext *avctx; ///< parent AVCodecContext
+ GetBitContext gb; ///< GetBitContext initialized to start at the current frame
- int blocksize/*, last_blocksize*/;
- int curr_bps;
- enum decorrelation_type decorrelation;
+ int blocksize; ///< number of samples in the current frame
+ int curr_bps; ///< bps for current subframe, adjusted for channel correlation and wasted bits
+ int sample_shift; ///< shift required to make output samples 16-bit or 32-bit
+ int is32; ///< flag to indicate if output should be 32-bit instead of 16-bit
+ enum decorrelation_type decorrelation; ///< channel decorrelation type in the current frame
- int32_t *decoded[MAX_CHANNELS];
+ int32_t *decoded[MAX_CHANNELS]; ///< decoded samples
uint8_t *bitstream;
unsigned int bitstream_size;
unsigned int bitstream_index;
}
static void allocate_buffers(FLACContext *s);
-static int metadata_parse(FLACContext *s);
+
+int ff_flac_is_extradata_valid(AVCodecContext *avctx,
+ enum FLACExtradataFormat *format,
+ uint8_t **streaminfo_start)
+{
+ if (!avctx->extradata || avctx->extradata_size < FLAC_STREAMINFO_SIZE) {
+ av_log(avctx, AV_LOG_ERROR, "extradata NULL or too small.\n");
+ return 0;
+ }
+ if (AV_RL32(avctx->extradata) != MKTAG('f','L','a','C')) {
+ /* extradata contains STREAMINFO only */
+ if (avctx->extradata_size != FLAC_STREAMINFO_SIZE) {
+ av_log(avctx, AV_LOG_WARNING, "extradata contains %d bytes too many.\n",
+ FLAC_STREAMINFO_SIZE-avctx->extradata_size);
+ }
+ *format = FLAC_EXTRADATA_FORMAT_STREAMINFO;
+ *streaminfo_start = avctx->extradata;
+ } else {
+ if (avctx->extradata_size < 8+FLAC_STREAMINFO_SIZE) {
+ av_log(avctx, AV_LOG_ERROR, "extradata too small.\n");
+ return 0;
+ }
+ *format = FLAC_EXTRADATA_FORMAT_FULL_HEADER;
+ *streaminfo_start = &avctx->extradata[8];
+ }
+ return 1;
+}
static av_cold int flac_decode_init(AVCodecContext *avctx)
{
+ enum FLACExtradataFormat format;
+ uint8_t *streaminfo;
FLACContext *s = avctx->priv_data;
s->avctx = avctx;
- if (avctx->extradata_size > 4) {
- /* initialize based on the demuxer-supplied streamdata header */
- if (avctx->extradata_size == FLAC_STREAMINFO_SIZE) {
- ff_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s,
- avctx->extradata);
- allocate_buffers(s);
- } else {
- init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size*8);
- metadata_parse(s);
- }
- }
-
avctx->sample_fmt = SAMPLE_FMT_S16;
+
+ /* for now, the raw FLAC header is allowed to be passed to the decoder as
+ frame data instead of extradata. */
+ if (!avctx->extradata)
+ return 0;
+
+ if (!ff_flac_is_extradata_valid(avctx, &format, &streaminfo))
+ return -1;
+
+ /* initialize based on the demuxer-supplied streamdata header */
+ ff_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo);
+ allocate_buffers(s);
+
return 0;
}
avctx->channels = s->channels;
avctx->sample_rate = s->samplerate;
+ avctx->bits_per_raw_sample = s->bps;
+ if (s->bps > 16)
+ avctx->sample_fmt = SAMPLE_FMT_S32;
+ else
+ avctx->sample_fmt = SAMPLE_FMT_S16;
- skip_bits(&gb, 36); /* total num of samples */
+ s->samples = get_bits_long(&gb, 32) << 4;
+ s->samples |= get_bits(&gb, 4);
- skip_bits(&gb, 64); /* md5 sum */
- skip_bits(&gb, 64); /* md5 sum */
+ skip_bits_long(&gb, 64); /* md5 sum */
+ skip_bits_long(&gb, 64); /* md5 sum */
dump_headers(avctx, s);
}
int initial_pos= get_bits_count(&s->gb);
if (show_bits_long(&s->gb, 32) == MKBETAG('f','L','a','C')) {
- skip_bits(&s->gb, 32);
+ skip_bits_long(&s->gb, 32);
do {
metadata_last = get_bits1(&s->gb);
if (tmp == (method_type == 0 ? 15 : 31)) {
tmp = get_bits(&s->gb, 5);
for (; i < samples; i++, sample++)
- s->decoded[channel][sample] = get_sbits(&s->gb, tmp);
+ s->decoded[channel][sample] = get_sbits_long(&s->gb, tmp);
} else {
for (; i < samples; i++, sample++) {
s->decoded[channel][sample] = get_sr_golomb_flac(&s->gb, tmp, INT_MAX, 0);
{
const int blocksize = s->blocksize;
int32_t *decoded = s->decoded[channel];
- int a, b, c, d, i;
+ int av_uninit(a), av_uninit(b), av_uninit(c), av_uninit(d), i;
/* warm up samples */
for (i = 0; i < pred_order; i++) {
- decoded[i] = get_sbits(&s->gb, s->curr_bps);
+ decoded[i] = get_sbits_long(&s->gb, s->curr_bps);
}
if (decode_residuals(s, channel, pred_order) < 0)
/* warm up samples */
for (i = 0; i < pred_order; i++) {
- decoded[i] = get_sbits(&s->gb, s->curr_bps);
+ decoded[i] = get_sbits_long(&s->gb, s->curr_bps);
}
coeff_prec = get_bits(&s->gb, 4) + 1;
//FIXME use av_log2 for types
if (type == 0) {
- tmp = get_sbits(&s->gb, s->curr_bps);
+ tmp = get_sbits_long(&s->gb, s->curr_bps);
for (i = 0; i < s->blocksize; i++)
s->decoded[channel][i] = tmp;
} else if (type == 1) {
for (i = 0; i < s->blocksize; i++)
- s->decoded[channel][i] = get_sbits(&s->gb, s->curr_bps);
+ s->decoded[channel][i] = get_sbits_long(&s->gb, s->curr_bps);
} else if ((type >= 8) && (type <= 12)) {
if (decode_subframe_fixed(s, channel, type & ~0x8) < 0)
return -1;
sample_size_code);
return -1;
}
+ if (bps > 16) {
+ s->avctx->sample_fmt = SAMPLE_FMT_S32;
+ s->sample_shift = 32 - bps;
+ s->is32 = 1;
+ } else {
+ s->avctx->sample_fmt = SAMPLE_FMT_S16;
+ s->sample_shift = 16 - bps;
+ s->is32 = 0;
+ }
+ s->bps = s->avctx->bits_per_raw_sample = bps;
if (get_bits1(&s->gb)) {
av_log(s->avctx, AV_LOG_ERROR, "broken stream, invalid padding\n");
{
FLACContext *s = avctx->priv_data;
int tmp = 0, i, j = 0, input_buf_size = 0;
- int16_t *samples = data;
+ int16_t *samples_16 = data;
+ int32_t *samples_32 = data;
int alloc_data_size= *data_size;
*data_size=0;
for (i = 0; i < s->blocksize; i++) {\
int a= s->decoded[0][i];\
int b= s->decoded[1][i];\
- *samples++ = ((left) << (24 - s->bps)) >> 8;\
- *samples++ = ((right) << (24 - s->bps)) >> 8;\
+ if (s->is32) {\
+ *samples_32++ = (left) << s->sample_shift;\
+ *samples_32++ = (right) << s->sample_shift;\
+ } else {\
+ *samples_16++ = (left) << s->sample_shift;\
+ *samples_16++ = (right) << s->sample_shift;\
+ }\
}\
break;
switch (s->decorrelation) {
case INDEPENDENT:
for (j = 0; j < s->blocksize; j++) {
- for (i = 0; i < s->channels; i++)
- *samples++ = (s->decoded[i][j] << (24 - s->bps)) >> 8;
+ for (i = 0; i < s->channels; i++) {
+ if (s->is32)
+ *samples_32++ = s->decoded[i][j] << s->sample_shift;
+ else
+ *samples_16++ = s->decoded[i][j] << s->sample_shift;
+ }
}
break;
case LEFT_SIDE:
DECORRELATE( (a-=b>>1) + b, a)
}
- *data_size = (int8_t *)samples - (int8_t *)data;
+ *data_size = s->blocksize * s->channels * (s->is32 ? 4 : 2);
end:
i= (get_bits_count(&s->gb)+7)/8;