On 03/31/2012 07:49 PM, Andrew D'Addesio wrote:
> This is the GSoC 2012 qualification task for Andrew D'Addesio (Fatbag).
>
> The indents and cosmetic changes have been split away from the functional
> changes in this version of the patch.
> ---
> libavcodec/alac.c | 219 ++++++++++++++++++++++++++++++----------------------
> 1 files changed, 126 insertions(+), 93 deletions(-)
>
> diff --git a/libavcodec/alac.c b/libavcodec/alac.c
> index e2ec6a4..f4b308b 100644
> --- a/libavcodec/alac.c
> +++ b/libavcodec/alac.c
> @@ -45,7 +45,7 @@
> * 32bit samplerate
> */
>
> -
> +#include "libavutil/audioconvert.h"
> #include "avcodec.h"
> #include "get_bits.h"
> #include "bytestream.h"
> @@ -53,7 +53,7 @@
> #include "mathops.h"
>
> #define ALAC_EXTRADATA_SIZE 36
> -#define MAX_CHANNELS 2
> +#define MAX_CHANNELS 8
>
> typedef struct {
>
> @@ -64,11 +64,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 +81,40 @@ typedef struct {
> int extra_bits; /**< number of extra bits beyond
> 16-bit */
> } ALACContext;
>
> +enum RawDataBlockType {
> + /* At the moment, only SCE and CPE read support are implemented. */
> + TYPE_SCE,
> + TYPE_CPE,
> + TYPE_CCE,
> + TYPE_LFE,
> + TYPE_DSE,
> + TYPE_PCE,
> + TYPE_FIL,
> + TYPE_END
> +};
It supports TYPE_END too. Also, from what I can tell the Apple ALAC
encoder does use TYPE_LFE for the LFE channel, and the decoder just
treats it the same as TYPE_SCE.
> +
> +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 int64_t alac_channel_layouts[8] = {
Based on the highest mask value used, these can be uint16_t to save some
space.
[...]
> @@ -386,28 +410,36 @@ static int alac_decode_frame(AVCodecContext *avctx,
> void *data,
> /* whether the frame is compressed */
> isnotcompressed = get_bits1(&alac->gb);
>
> - if (hassize) {
> - /* now read the number of samples as a 32bit integer */
> - outputsamples = get_bits_long(&alac->gb, 32);
> - if(outputsamples > alac->setinfo_max_samples_per_frame){
> - av_log(avctx, AV_LOG_ERROR, "outputsamples %d > %d\n",
> outputsamples, alac->setinfo_max_samples_per_frame);
> - return -1;
> + if (outputsamples == 0) {
> + if (hassize) {
> + outputsamples = get_bits_long(&alac->gb, 32);
> + if (outputsamples > alac->setinfo_max_samples_per_frame) {
> + av_log(avctx, AV_LOG_ERROR, "outputsamples %d > %d\n",
> + outputsamples, alac->setinfo_max_samples_per_frame);
> + return -1;
> + }
most of that looks cosmetic
> }
> - } else
> - outputsamples = alac->setinfo_max_samples_per_frame;
> + if (outputsamples == 0)
> + outputsamples = alac->setinfo_max_samples_per_frame;
>
> - /* get output buffer */
> - if (outputsamples > INT32_MAX) {
> - av_log(avctx, AV_LOG_ERROR, "unsupported block size: %u\n",
> outputsamples);
> - return AVERROR_INVALIDDATA;
> - }
> - alac->frame.nb_samples = outputsamples;
> - if ((ret = avctx->get_buffer(avctx, &alac->frame)) < 0) {
> - av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
> - return ret;
> + /* get output buffer */
> + if (outputsamples > INT32_MAX) {
> + av_log(avctx, AV_LOG_ERROR, "unsupported block size: %u\n",
> outputsamples);
> + return AVERROR_INVALIDDATA;
> + }
> + alac->frame.nb_samples = outputsamples;
> + if ((ret = avctx->get_buffer(avctx, &alac->frame)) < 0) {
> + 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;
> + }
> }
a lot of that is cosmetic as well.
[...]
> + 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: {
> + 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;
These could probably be optimized or simplified somewhat, but it's not
really the ideal situation anyway. We'll output the audio as planar in
the hopefully-near-future, so I'm ok with this as it is for now.
> }
>
> - 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;
nit: channels -= 1 << paired;
The rest looks good.
Thanks,
Justin
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel