Commit 81c9e2e6 authored by Justin Ruggles's avatar Justin Ruggles

alac: split element parsing into a separate function

This will make multi-channel implementation simpler.
Based partially on a patch by Andrew D'Addesio <modchipv12@gmail.com>.
parent cd632619
......@@ -78,6 +78,18 @@ typedef struct {
int nb_samples; /**< number of samples in the current frame */
} 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 inline unsigned int decode_scalar(GetBitContext *gb, int k,
int readsamplesize)
{
......@@ -268,27 +280,18 @@ static void append_extra_bits(int32_t *buffer[MAX_CHANNELS],
buffer[ch][i] = (buffer[ch][i] << extra_bits) | extra_bits_buffer[ch][i];
}
static int alac_decode_frame(AVCodecContext *avctx, void *data,
int *got_frame_ptr, AVPacket *avpkt)
static int decode_element(AVCodecContext *avctx, void *data, int ch_index,
int channels)
{
ALACContext *alac = avctx->priv_data;
int channels;
int hassize;
unsigned int readsamplesize;
int is_compressed;
uint8_t interlacing_shift;
uint8_t interlacing_leftweight;
uint32_t output_samples;
int i, ch, ret;
init_get_bits(&alac->gb, avpkt->data, avpkt->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");
return AVERROR_INVALIDDATA;
}
skip_bits(&alac->gb, 4); /* element instance tag */
skip_bits(&alac->gb, 12); /* unused header bits */
......@@ -305,28 +308,32 @@ static int alac_decode_frame(AVCodecContext *avctx, void *data,
/* whether the frame is compressed */
is_compressed = !get_bits1(&alac->gb);
if (hassize) {
/* now read the number of samples as a 32bit integer */
uint32_t output_samples = get_bits_long(&alac->gb, 32);
if (!output_samples || output_samples > alac->max_samples_per_frame) {
av_log(avctx, AV_LOG_ERROR, "invalid samples per frame: %d\n",
output_samples);
return AVERROR_INVALIDDATA;
}
alac->nb_samples = output_samples;
} else
alac->nb_samples = alac->max_samples_per_frame;
/* get output buffer */
alac->frame.nb_samples = alac->nb_samples;
if ((ret = avctx->get_buffer(avctx, &alac->frame)) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret;
if (hassize)
output_samples = get_bits_long(&alac->gb, 32);
else
output_samples = alac->max_samples_per_frame;
if (!output_samples || output_samples > alac->max_samples_per_frame) {
av_log(avctx, AV_LOG_ERROR, "invalid samples per frame: %d\n",
output_samples);
return AVERROR_INVALIDDATA;
}
if (alac->sample_size > 16) {
for (ch = 0; ch < alac->channels; ch++)
alac->output_samples_buffer[ch] = (int32_t *)alac->frame.data[ch];
if (!alac->nb_samples) {
/* get output buffer */
alac->frame.nb_samples = output_samples;
if ((ret = avctx->get_buffer(avctx, &alac->frame)) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret;
}
if (alac->sample_size > 16) {
for (ch = 0; ch < channels; ch++)
alac->output_samples_buffer[ch] = (int32_t *)alac->frame.data[ch_index + ch];
}
} else if (output_samples != alac->nb_samples) {
av_log(avctx, AV_LOG_ERROR, "sample count mismatch: %u != %d\n",
output_samples, alac->nb_samples);
return AVERROR_INVALIDDATA;
}
alac->nb_samples = output_samples;
if (is_compressed) {
int16_t predictor_coef_table[MAX_CHANNELS][32];
......@@ -391,16 +398,13 @@ static int alac_decode_frame(AVCodecContext *avctx, void *data,
/* not compressed, easy case */
for (i = 0; i < alac->nb_samples; i++) {
for (ch = 0; ch < channels; ch++) {
alac->output_samples_buffer[ch][i] = get_sbits_long(&alac->gb,
alac->sample_size);
alac->output_samples_buffer[ch][i] = get_sbits_long(&alac->gb, alac->sample_size);
}
}
alac->extra_bits = 0;
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) {
decorrelate_stereo(alac->output_samples_buffer, alac->nb_samples,
......@@ -409,25 +413,62 @@ static int alac_decode_frame(AVCodecContext *avctx, void *data,
if (alac->extra_bits) {
append_extra_bits(alac->output_samples_buffer, alac->extra_bits_buffer,
alac->extra_bits, alac->channels, alac->nb_samples);
alac->extra_bits, channels, alac->nb_samples);
}
switch(alac->sample_size) {
case 16: {
for (ch = 0; ch < alac->channels; ch++) {
int16_t *outbuffer = (int16_t *)alac->frame.data[ch];
for (ch = 0; ch < channels; ch++) {
int16_t *outbuffer = (int16_t *)alac->frame.data[ch_index + ch];
for (i = 0; i < alac->nb_samples; i++)
*outbuffer++ = alac->output_samples_buffer[ch][i];
}}
break;
case 24: {
for (ch = 0; ch < alac->channels; ch++) {
for (ch = 0; ch < channels; ch++) {
for (i = 0; i < alac->nb_samples; i++)
alac->output_samples_buffer[ch][i] <<= 8;
}}
break;
}
return 0;
}
static int alac_decode_frame(AVCodecContext *avctx, void *data,
int *got_frame_ptr, AVPacket *avpkt)
{
ALACContext *alac = avctx->priv_data;
enum RawDataBlockType element;
int channels;
int ch, ret;
init_get_bits(&alac->gb, avpkt->data, avpkt->size * 8);
alac->nb_samples = 0;
ch = 0;
while (get_bits_left(&alac->gb)) {
element = get_bits(&alac->gb, 3);
if (element == TYPE_END)
break;
if (element > TYPE_CPE && element != TYPE_LFE) {
av_log(avctx, AV_LOG_ERROR, "syntax element unsupported: %d", element);
return AVERROR_PATCHWELCOME;
}
channels = (element == TYPE_CPE) ? 2 : 1;
if (ch + channels > alac->channels) {
av_log(avctx, AV_LOG_ERROR, "invalid element channel count\n");
return AVERROR_INVALIDDATA;
}
ret = decode_element(avctx, data, ch, channels);
if (ret < 0)
return ret;
ch += channels;
}
if (avpkt->size * 8 - get_bits_count(&alac->gb) > 8)
av_log(avctx, AV_LOG_ERROR, "Error : %d bits left\n",
avpkt->size * 8 - get_bits_count(&alac->gb));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment