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 { ...@@ -78,6 +78,18 @@ typedef struct {
int nb_samples; /**< number of samples in the current frame */ int nb_samples; /**< number of samples in the current frame */
} ALACContext; } 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, static inline unsigned int decode_scalar(GetBitContext *gb, int k,
int readsamplesize) int readsamplesize)
{ {
...@@ -268,27 +280,18 @@ static void append_extra_bits(int32_t *buffer[MAX_CHANNELS], ...@@ -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]; buffer[ch][i] = (buffer[ch][i] << extra_bits) | extra_bits_buffer[ch][i];
} }
static int alac_decode_frame(AVCodecContext *avctx, void *data, static int decode_element(AVCodecContext *avctx, void *data, int ch_index,
int *got_frame_ptr, AVPacket *avpkt) int channels)
{ {
ALACContext *alac = avctx->priv_data; ALACContext *alac = avctx->priv_data;
int channels;
int hassize; int hassize;
unsigned int readsamplesize; unsigned int readsamplesize;
int is_compressed; int is_compressed;
uint8_t interlacing_shift; uint8_t interlacing_shift;
uint8_t interlacing_leftweight; uint8_t interlacing_leftweight;
uint32_t output_samples;
int i, ch, ret; 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, 4); /* element instance tag */
skip_bits(&alac->gb, 12); /* unused header bits */ skip_bits(&alac->gb, 12); /* unused header bits */
...@@ -305,28 +308,32 @@ static int alac_decode_frame(AVCodecContext *avctx, void *data, ...@@ -305,28 +308,32 @@ static int alac_decode_frame(AVCodecContext *avctx, void *data,
/* whether the frame is compressed */ /* whether the frame is compressed */
is_compressed = !get_bits1(&alac->gb); is_compressed = !get_bits1(&alac->gb);
if (hassize) { if (hassize)
/* now read the number of samples as a 32bit integer */ output_samples = get_bits_long(&alac->gb, 32);
uint32_t output_samples = get_bits_long(&alac->gb, 32); else
if (!output_samples || output_samples > alac->max_samples_per_frame) { output_samples = alac->max_samples_per_frame;
av_log(avctx, AV_LOG_ERROR, "invalid samples per frame: %d\n", if (!output_samples || output_samples > alac->max_samples_per_frame) {
output_samples); av_log(avctx, AV_LOG_ERROR, "invalid samples per frame: %d\n",
return AVERROR_INVALIDDATA; 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 (alac->sample_size > 16) { if (!alac->nb_samples) {
for (ch = 0; ch < alac->channels; ch++) /* get output buffer */
alac->output_samples_buffer[ch] = (int32_t *)alac->frame.data[ch]; 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) { if (is_compressed) {
int16_t predictor_coef_table[MAX_CHANNELS][32]; int16_t predictor_coef_table[MAX_CHANNELS][32];
...@@ -391,16 +398,13 @@ static int alac_decode_frame(AVCodecContext *avctx, void *data, ...@@ -391,16 +398,13 @@ static int alac_decode_frame(AVCodecContext *avctx, void *data,
/* not compressed, easy case */ /* not compressed, easy case */
for (i = 0; i < alac->nb_samples; i++) { for (i = 0; i < alac->nb_samples; i++) {
for (ch = 0; ch < channels; ch++) { for (ch = 0; ch < channels; ch++) {
alac->output_samples_buffer[ch][i] = get_sbits_long(&alac->gb, alac->output_samples_buffer[ch][i] = get_sbits_long(&alac->gb, alac->sample_size);
alac->sample_size);
} }
} }
alac->extra_bits = 0; alac->extra_bits = 0;
interlacing_shift = 0; interlacing_shift = 0;
interlacing_leftweight = 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 (channels == 2 && interlacing_leftweight) {
decorrelate_stereo(alac->output_samples_buffer, alac->nb_samples, decorrelate_stereo(alac->output_samples_buffer, alac->nb_samples,
...@@ -409,25 +413,62 @@ static int alac_decode_frame(AVCodecContext *avctx, void *data, ...@@ -409,25 +413,62 @@ static int alac_decode_frame(AVCodecContext *avctx, void *data,
if (alac->extra_bits) { if (alac->extra_bits) {
append_extra_bits(alac->output_samples_buffer, alac->extra_bits_buffer, 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) { switch(alac->sample_size) {
case 16: { case 16: {
for (ch = 0; ch < alac->channels; ch++) { for (ch = 0; ch < channels; ch++) {
int16_t *outbuffer = (int16_t *)alac->frame.data[ch]; int16_t *outbuffer = (int16_t *)alac->frame.data[ch_index + ch];
for (i = 0; i < alac->nb_samples; i++) for (i = 0; i < alac->nb_samples; i++)
*outbuffer++ = alac->output_samples_buffer[ch][i]; *outbuffer++ = alac->output_samples_buffer[ch][i];
}} }}
break; break;
case 24: { case 24: {
for (ch = 0; ch < alac->channels; ch++) { for (ch = 0; ch < channels; ch++) {
for (i = 0; i < alac->nb_samples; i++) for (i = 0; i < alac->nb_samples; i++)
alac->output_samples_buffer[ch][i] <<= 8; alac->output_samples_buffer[ch][i] <<= 8;
}} }}
break; 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) if (avpkt->size * 8 - get_bits_count(&alac->gb) > 8)
av_log(avctx, AV_LOG_ERROR, "Error : %d bits left\n", av_log(avctx, AV_LOG_ERROR, "Error : %d bits left\n",
avpkt->size * 8 - get_bits_count(&alac->gb)); 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