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

Reply via email to