From: Andrew D'Addesio <[email protected]>
Signed-off-by: Justin Ruggles <[email protected]>
---
libavcodec/alac.c | 183 +++++++++++++++++++++++++++++++---------------------
1 files changed, 109 insertions(+), 74 deletions(-)
diff --git a/libavcodec/alac.c b/libavcodec/alac.c
index ab9fb81..8e2b803 100644
--- a/libavcodec/alac.c
+++ b/libavcodec/alac.c
@@ -46,6 +46,7 @@
*/
+#include "libavutil/audioconvert.h"
#include "avcodec.h"
#include "get_bits.h"
#include "bytestream.h"
@@ -53,7 +54,7 @@
#include "mathops.h"
#define ALAC_EXTRADATA_SIZE 36
-#define MAX_CHANNELS 2
+#define MAX_CHANNELS 8
typedef struct {
@@ -64,11 +65,11 @@ typedef struct {
int numchannels;
/* buffers */
- int32_t *predicterror_buffer[MAX_CHANNELS];
+ int32_t *predicterror_buffer[2];
- int32_t *outputsamples_buffer[MAX_CHANNELS];
+ int32_t *outputsamples_buffer[2];
- int32_t *extra_bits_buffer[MAX_CHANNELS];
+ int32_t *extra_bits_buffer[2];
/* stuff from setinfo */
uint32_t setinfo_max_samples_per_frame; /* 0x1000 = 4096 */ /* max
samples per frame? */
@@ -81,6 +82,40 @@ typedef struct {
int extra_bits; /**< number of extra bits beyond
16-bit */
} ALACContext;
+enum RawDataBlockType {
+ /* At the moment, only SCE, CPE, LFE, and END are recognized. */
+ TYPE_SCE,
+ TYPE_CPE,
+ TYPE_CCE,
+ TYPE_LFE,
+ TYPE_DSE,
+ TYPE_PCE,
+ TYPE_FIL,
+ TYPE_END
+};
+
+static const uint8_t alac_channel_layout_offsets[8][8] = {
+ { 0 },
+ { 0, 1 },
+ { 2, 0, 1 },
+ { 2, 0, 1, 3 },
+ { 2, 0, 1, 3, 4 },
+ { 2, 0, 1, 4, 5, 3 },
+ { 2, 0, 1, 4, 5, 6, 3 },
+ { 2, 6, 7, 0, 1, 4, 5, 3 }
+};
+
+static const uint16_t alac_channel_layouts[8] = {
+ AV_CH_LAYOUT_MONO,
+ AV_CH_LAYOUT_STEREO,
+ AV_CH_LAYOUT_SURROUND,
+ AV_CH_LAYOUT_4POINT0,
+ AV_CH_LAYOUT_5POINT0_BACK,
+ AV_CH_LAYOUT_5POINT1_BACK,
+ AV_CH_LAYOUT_6POINT1_BACK,
+ AV_CH_LAYOUT_7POINT1_WIDE_BACK
+};
+
static inline int decode_scalar(GetBitContext *gb, int k, int limit, int
readsamplesize){
/* read x - number of 1s before 0 represent the rice */
int x = get_unary_0_9(gb);
@@ -294,7 +329,7 @@ static void predictor_decompress_fir_adapt(int32_t
*error_buffer,
}
}
-static void decorrelate_stereo(int32_t *buffer[MAX_CHANNELS],
+static void decorrelate_stereo(int32_t *buffer[2],
int numsamples, uint8_t interlacing_shift,
uint8_t interlacing_leftweight)
{
@@ -314,39 +349,17 @@ static void decorrelate_stereo(int32_t
*buffer[MAX_CHANNELS],
}
}
-static void append_extra_bits(int32_t *buffer[MAX_CHANNELS],
- int32_t *extra_bits_buffer[MAX_CHANNELS],
- int extra_bits, int numchannels, int numsamples)
+static void append_extra_bits(int32_t *buffer[2],
+ int32_t *extra_bits_buffer[2],
+ int extra_bits, int paired, int numsamples)
{
int i, ch;
- for (ch = 0; ch < numchannels; ch++)
+ for (ch = 0; ch <= paired; ch++)
for (i = 0; i < numsamples; i++)
buffer[ch][i] = (buffer[ch][i] << extra_bits) |
extra_bits_buffer[ch][i];
}
-static void interleave_stereo_16(int32_t *buffer[MAX_CHANNELS],
- int16_t *buffer_out, int numsamples)
-{
- int i;
-
- for (i = 0; i < numsamples; i++) {
- *buffer_out++ = buffer[0][i];
- *buffer_out++ = buffer[1][i];
- }
-}
-
-static void interleave_stereo_24(int32_t *buffer[MAX_CHANNELS],
- int32_t *buffer_out, int numsamples)
-{
- int i;
-
- for (i = 0; i < numsamples; i++) {
- *buffer_out++ = buffer[0][i] << 8;
- *buffer_out++ = buffer[1][i] << 8;
- }
-}
-
static int alac_decode_frame(AVCodecContext *avctx, void *data,
int *got_frame_ptr, AVPacket *avpkt)
{
@@ -354,20 +367,31 @@ static int alac_decode_frame(AVCodecContext *avctx, void
*data,
int input_buffer_size = avpkt->size;
ALACContext *alac = avctx->priv_data;
- int channels;
- unsigned int outputsamples;
+ int channels = avctx->channels;
+ unsigned int outputsamples = 0;
int hassize;
unsigned int readsamplesize;
int isnotcompressed;
uint8_t interlacing_shift;
uint8_t interlacing_leftweight;
int i, ch, ret;
+ int offsetL, offsetR;
init_get_bits(&alac->gb, inbuffer, input_buffer_size * 8);
- channels = get_bits(&alac->gb, 3) + 1;
- if (channels != avctx->channels) {
- av_log(avctx, AV_LOG_ERROR, "frame header channel count mismatch\n");
+ while (channels > 0) {
+ enum RawDataBlockType element;
+ int paired;
+
+ element = get_bits(&alac->gb, 3);
+ if (element > TYPE_CPE && element != TYPE_LFE) {
+ av_log(avctx, AV_LOG_ERROR, "syntax element unsupported: %d", element);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ paired = (element == TYPE_CPE);
+ if (paired && channels < 2) {
+ av_log(avctx, AV_LOG_ERROR, "stereo frame in mono audio track\n");
return AVERROR_INVALIDDATA;
}
@@ -386,6 +410,7 @@ static int alac_decode_frame(AVCodecContext *avctx, void
*data,
/* whether the frame is compressed */
isnotcompressed = get_bits1(&alac->gb);
+ if (outputsamples == 0) {
if (hassize) {
/* now read the number of samples as a 32bit integer */
outputsamples = get_bits_long(&alac->gb, 32);
@@ -393,7 +418,8 @@ static int alac_decode_frame(AVCodecContext *avctx, void
*data,
av_log(avctx, AV_LOG_ERROR, "outputsamples %d > %d\n",
outputsamples, alac->setinfo_max_samples_per_frame);
return -1;
}
- } else
+ }
+ if (outputsamples == 0)
outputsamples = alac->setinfo_max_samples_per_frame;
/* get output buffer */
@@ -406,8 +432,14 @@ static int alac_decode_frame(AVCodecContext *avctx, void
*data,
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret;
}
+ } else {
+ if (hassize && get_bits_long(&alac->gb, 32) != outputsamples) {
+ av_log(avctx, AV_LOG_ERROR, "sample count disparity between
channels\n");
+ return AVERROR_INVALIDDATA;
+ }
+ }
- readsamplesize = alac->setinfo_sample_size - alac->extra_bits + channels -
1;
+ readsamplesize = alac->setinfo_sample_size - alac->extra_bits + paired;
if (readsamplesize > MIN_CACHE_BITS) {
av_log(avctx, AV_LOG_ERROR, "readsamplesize too big (%d)\n",
readsamplesize);
return -1;
@@ -415,16 +447,16 @@ static int alac_decode_frame(AVCodecContext *avctx, void
*data,
if (!isnotcompressed) {
/* so it is compressed */
- int16_t predictor_coef_table[MAX_CHANNELS][32];
- int predictor_coef_num[MAX_CHANNELS];
- int prediction_type[MAX_CHANNELS];
- int prediction_quantitization[MAX_CHANNELS];
- int ricemodifier[MAX_CHANNELS];
+ int16_t predictor_coef_table[2][32];
+ int predictor_coef_num[2];
+ int prediction_type[2];
+ int prediction_quantitization[2];
+ int ricemodifier[2];
interlacing_shift = get_bits(&alac->gb, 8);
interlacing_leftweight = get_bits(&alac->gb, 8);
- for (ch = 0; ch < channels; ch++) {
+ for (ch = 0; ch <= paired; ch++) {
prediction_type[ch] = get_bits(&alac->gb, 4);
prediction_quantitization[ch] = get_bits(&alac->gb, 4);
@@ -438,11 +470,11 @@ static int alac_decode_frame(AVCodecContext *avctx, void
*data,
if (alac->extra_bits) {
for (i = 0; i < outputsamples; i++) {
- for (ch = 0; ch < channels; ch++)
+ for (ch = 0; ch <= paired; ch++)
alac->extra_bits_buffer[ch][i] = get_bits(&alac->gb,
alac->extra_bits);
}
}
- for (ch = 0; ch < channels; ch++) {
+ for (ch = 0; ch <= paired; ch++) {
bastardized_rice_decompress(alac,
alac->predicterror_buffer[ch],
outputsamples,
@@ -479,7 +511,7 @@ static int alac_decode_frame(AVCodecContext *avctx, void
*data,
} else {
/* not compressed, easy case */
for (i = 0; i < outputsamples; i++) {
- for (ch = 0; ch < channels; ch++) {
+ for (ch = 0; ch <= paired; ch++) {
alac->outputsamples_buffer[ch][i] = get_sbits_long(&alac->gb,
alac->setinfo_sample_size);
}
@@ -488,45 +520,46 @@ static int alac_decode_frame(AVCodecContext *avctx, void
*data,
interlacing_shift = 0;
interlacing_leftweight = 0;
}
- if (get_bits(&alac->gb, 3) != 7)
- av_log(avctx, AV_LOG_ERROR, "Error : Wrong End Of Frame\n");
- if (channels == 2 && interlacing_leftweight) {
+ if (paired && interlacing_leftweight) {
decorrelate_stereo(alac->outputsamples_buffer, outputsamples,
interlacing_shift, interlacing_leftweight);
}
+ offsetL = alac_channel_layout_offsets[avctx->channels - 1][avctx->channels
- channels];
+ if (paired)
+ offsetR = alac_channel_layout_offsets[avctx->channels -
1][avctx->channels - channels + 1];
if (alac->extra_bits) {
append_extra_bits(alac->outputsamples_buffer, alac->extra_bits_buffer,
- alac->extra_bits, alac->numchannels, outputsamples);
+ alac->extra_bits, paired, outputsamples);
}
switch(alac->setinfo_sample_size) {
- case 16:
- if (channels == 2) {
- interleave_stereo_16(alac->outputsamples_buffer,
- (int16_t *)alac->frame.data[0],
outputsamples);
- } else {
- int16_t *outbuffer = (int16_t *)alac->frame.data[0];
- for (i = 0; i < outputsamples; i++) {
- outbuffer[i] = alac->outputsamples_buffer[0][i];
- }
- }
+ case 16: {
+ int16_t *outbuffer = (int16_t *)alac->frame.data[0];
+ for (i = 0; i < outputsamples; i++) {
+ outbuffer[i * avctx->channels + offsetL] =
alac->outputsamples_buffer[0][i];
+ if (paired)
+ outbuffer[i * avctx->channels + offsetR] =
alac->outputsamples_buffer[1][i];
+ }}
break;
- case 24:
- if (channels == 2) {
- interleave_stereo_24(alac->outputsamples_buffer,
- (int32_t *)alac->frame.data[0],
outputsamples);
- } else {
- int32_t *outbuffer = (int32_t *)alac->frame.data[0];
- for (i = 0; i < outputsamples; i++)
- outbuffer[i] = alac->outputsamples_buffer[0][i] << 8;
- }
+ case 24: {
+ int32_t *outbuffer = (int32_t *)alac->frame.data[0];
+ for (i = 0; i < outputsamples; i++) {
+ outbuffer[i * avctx->channels + offsetL] =
alac->outputsamples_buffer[0][i] << 8;
+ if (paired)
+ outbuffer[i * avctx->channels + offsetR] =
alac->outputsamples_buffer[1][i] << 8;
+ }}
break;
}
- if (input_buffer_size * 8 - get_bits_count(&alac->gb) > 8)
- av_log(avctx, AV_LOG_ERROR, "Error : %d bits left\n",
input_buffer_size * 8 - get_bits_count(&alac->gb));
+ channels -= (paired) ? 2 : 1;
+ }
+
+ if (get_bits(&alac->gb, 3) != TYPE_END)
+ av_log(avctx, AV_LOG_ERROR, "Error : Missing frame epilogue\n");
+ if (input_buffer_size * 8 - get_bits_count(&alac->gb) >= 8)
+ av_log(avctx, AV_LOG_ERROR, "Error : %d unused bits in frame\n",
input_buffer_size * 8 - get_bits_count(&alac->gb));
*got_frame_ptr = 1;
*(AVFrame *)data = alac->frame;
@@ -539,7 +572,7 @@ static av_cold int alac_decode_close(AVCodecContext *avctx)
ALACContext *alac = avctx->priv_data;
int ch;
- for (ch = 0; ch < alac->numchannels; ch++) {
+ for (ch = 0; ch < 2; ch++) {
av_freep(&alac->predicterror_buffer[ch]);
av_freep(&alac->outputsamples_buffer[ch]);
av_freep(&alac->extra_bits_buffer[ch]);
@@ -551,7 +584,7 @@ static av_cold int alac_decode_close(AVCodecContext *avctx)
static int allocate_buffers(ALACContext *alac)
{
int ch;
- for (ch = 0; ch < alac->numchannels; ch++) {
+ for (ch = 0; ch < 2; ch++) {
int buf_size = alac->setinfo_max_samples_per_frame * sizeof(int32_t);
FF_ALLOC_OR_GOTO(alac->avctx, alac->predicterror_buffer[ch],
@@ -596,6 +629,8 @@ static int alac_set_info(ALACContext *alac)
bytestream2_get_be32u(&gb); // average bitrate
bytestream2_get_be32u(&gb); // samplerate
+ alac->avctx->channel_layout = alac_channel_layouts[alac->numchannels - 1];
+
return 0;
}
--
1.7.1
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel