Skip to content
Permalink
alsenc
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
3538 lines (2969 sloc) 122 KB
/*
* MPEG-4 ALS encoder
* Copyright (c) 2010 Thilo Borgmann <thilo.borgmann _at_ googlemail.com>
* Copyright (c) 2010 Justin Ruggles <justin.ruggles@gmail.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file libavcodec/alsenc.c
* MPEG-4 ALS encoder
* @author Thilo Borgmann <thilo.borgmann _at_ googlemail.com>
* @author Justin Ruggles <justin.ruggles@gmail.com>
*/
#define DEBUG
#include "als.h"
#include "als_data.h"
#include "avcodec.h"
#include "dsputil.h"
#include "put_bits.h"
#define LPC_USE_DOUBLE
#include "lpc.h"
#include "mpeg4audio.h"
#include "audioconvert.h"
#include "bgmc.h"
#include "window.h"
#include "libavutil/crc.h"
#include "libavutil/lls.h"
/** Total size of fixed-size fields in ALSSpecificConfig */
#define ALS_SPECIFIC_CFG_SIZE 30
/** Maximum number of blocks in a frame */
#define ALS_MAX_BLOCKS 32
/** Maximum lag value for LTP */
#define ALS_MAX_LTP_LAG 2048
/** Total number of stages used for allocation */
#define NUM_STAGES 3
/** Give the different stages used for encoding a readable name */
#define STAGE_JOINT_STEREO 0
#define STAGE_BLOCK_SWITCHING 1
#define STAGE_FINAL 2
/** Sets the current stage pointer in the context to the desired stage
* and writes all overriding options into specific config */
#define SET_OPTIONS(stage) \
{ \
ctx->cur_stage = ctx->stages + (stage); \
}
/** Determines entropy coding partitioning level using estimated Rice coding bit counts */
#define EC_SUB_ALGORITHM_RICE_ESTIMATE 0
/** Determines entropy coding partitioning level using exact Rice coding bit counts */
#define EC_SUB_ALGORITHM_RICE_EXACT 1
/** Determines entropy coding partitioning using exact BGMC coding bit counts */
#define EC_SUB_ALGORITHM_BGMC_EXACT 2
/** Estimates Rice parameters using sum of unsigned residual samples */
#define EC_PARAM_ALGORITHM_RICE_ESTIMATE 0
/** Calculates Rice parameters using a search algorithm based on exact bit count */
#define EC_PARAM_ALGORITHM_RICE_EXACT 1
/** Estimates BGMC parameters using mean of unsigned residual samples */
#define EC_PARAM_ALGORITHM_BGMC_ESTIMATE 2
/** Calculates BGMC parameters using a search algorithm based on exact bit count */
#define EC_PARAM_ALGORITHM_BGMC_EXACT 3
/** Uses estimate for returned entropy coding bit count */
#define EC_BIT_COUNT_ALGORITHM_ESTIMATE 0
/** Uses exact calculation for returned entropy coding bit count */
#define EC_BIT_COUNT_ALGORITHM_EXACT 1
/** Find adaptive LPC order by doing a bit count for each order until a probable low point is detected */
#define ADAPT_SEARCH_ALGORITHM_VALLEY_DETECT 0
/** Find adaptive LPC order by doing a bit count for each possible order */
#define ADAPT_SEARCH_ALGORITHM_FULL 1
/** Estimate bit count during adaptive LPC order search using error from the PARCOR coeff calculations */
#define ADAPT_COUNT_ALGORITHM_ESTIMATE 0
/** Do an exact bit count during adaptive LPC order search */
#define ADAPT_COUNT_ALGORITHM_EXACT 1
/** Use fixed values for LTP coefficients */
#define LTP_COEFF_ALGORITHM_FIXED 0
/** Calculate LTP coefficients using Cholesky factorization */
#define LTP_COEFF_ALGORITHM_CHOLESKY 1
/** Find optimal block partitioning using Full-Search */
#define BS_ALGORITHM_FULL_SEARCH 1
/** Find optimal block partitioning using Bottom-Up */
#define BS_ALGORITHM_BOTTOM_UP 0
/** Get the bit at position pos+1 in uint32_t *ptr_bs_info */
#define GET_BS_BIT(ptr_bs_info, pos) ((*ptr_bs_info & (1 << (30 - pos))) > 0)
#define OVERFLOW_PROTECT(pb, bits, ERROR) \
{ \
if (put_bits_count(pb) + (bits) > (pb)->size_in_bits) { \
ERROR \
} \
}
#define PUT_BITS_SAFE(pb, bits, val, ERROR) \
{ \
OVERFLOW_PROTECT(pb, bits, ERROR) \
put_bits(pb, bits, val); \
}
/** grouped encoding algorithms and options */
typedef struct {
// encoding options used during the processing of the stage
int check_constant; ///< check for constant sample value during this stage
int check_lsbs; ///< check for zero LSB values during this stage
int adapt_order; ///< use adaptive order search during this stage
int max_order; ///< max_oder to use during this stage
int sb_part; ///< sb_part to use during this stage
// encoding algorithms used during the processing of the stage
int ecsub_algorithm; ///< algorithm to use to determine entropy coding sub-block partitioning
int param_algorithm; ///< algorithm to use to determine Rice parameters
int count_algorithm; ///< algorithm to use for residual + rice param bit count
int adapt_search_algorithm; ///< algorithm to use for adaptive LPC order search
int adapt_count_algorithm; ///< algorithm to use for adaptive LPC order bit count
int ltp_coeff_algorithm; ///< algorithm to use to determine LTP coefficients
int merge_algorithm; ///< algorithm to use to determine final block partitioning
} ALSEncStage;
typedef struct {
int use_ltp; ///< ltp flag
int lag; ///< lag value for long-term prediction
int gain[5]; ///< gain values for ltp 5-tap filter
int bits_ltp; ///< bit count for LTP lag, gain and use_ltp flag
} ALSLTPInfo;
typedef struct {
unsigned int sub_blocks; ///< number of entropy coding sub-blocks in this block
unsigned int rice_param[8]; ///< rice parameters to encode the residuals
///< of this block
unsigned int bgmc_param[8]; ///< LSB's of estimated Rice parameters in case of BGMC mode
int bits_ec_param_and_res; ///< bit count for Rice/BGMC params and residuals
} ALSEntropyInfo;
// probably mergeable or the very same as ALSBlockData from the decoder
typedef struct {
int ra_block; ///< indicates if this is an RA block
int constant; ///< indicates constant block values
int32_t constant_value; ///< if constant, this is the value
unsigned int length; ///< length of the block in # of samples
int div_block; ///< if > 0, this block length is 1/(1<<div_block) of a full frame
unsigned int opt_order; ///< prediction order for this block
int32_t *q_parcor_coeff; ///< 7-bit quantized PARCOR coefficients
unsigned int js_block; ///< indicates actual usage of joint-stereo coding
unsigned int shift_lsbs; ///< number of bits the samples have been right shifted
ALSLTPInfo ltp_info[2]; ///< one set of LTPInfo for non-js- and js-residuals
ALSEntropyInfo ent_info[2]; ///< one set of EntropyInfo for non-LTP- and LTP-residuals
int32_t *ltp_ptr; ///< points to the first ltp residual for this block
int32_t *res_ptr; ///< points to the first residual for this block
int32_t *smp_ptr; ///< points to the first raw sample for this block
int32_t *dif_ptr; ///< points to the first difference sample for this block
int32_t *lsb_ptr; ///< points to the first LSB shifted sample for this block
int32_t *cur_ptr; ///< points to the current sample buffer for this block
int bits_const_block; ///< bit count for const block params
int bits_misc; ///< bit count for js_block and shift_lsbs
int bits_adapt_order; ///< bit count for LPC order when adaptive order is used
int bits_parcor_coeff[1024]; ///< cumulative bit counts for PARCOR coeffs
} ALSBlock;
typedef struct {
AVCodecContext *avctx;
ALSSpecificConfig sconf;
PutBitContext pb;
DSPContext dsp;
const AVCRC *crc_table;
uint32_t crc; ///< CRC value calculated from decoded data
ALSEncStage *stages; ///< array containing all grouped encoding and algorithm options for each possible stage
ALSEncStage *cur_stage; ///< points to the currently used encoding stage
int ra_counter; ///< counts from zero to ra_distance, equals zero for ra-frames
int js_switch; ///< force joint-stereo in case of MCC
int *independent_bs; ///< array containing independent_bs flag for each channel
int32_t *raw_buffer; ///< buffer containing all raw samples of the frame plus max_order samples from the previous frame (or zeroes) for all channels
int32_t **raw_samples; ///< pointer to the beginning of the current frame's samples in the buffer for each channel
int32_t *raw_dif_buffer; ///< buffer containing all raw difference samples of the frame plus max_order samples from the previous frame (or zeroes) for all channels
int32_t **raw_dif_samples; ///< pointer to the beginning of the current frame's difference samples in the buffer for each channel
int32_t *raw_lsb_buffer; ///< buffer containing all shifted raw samples of the frame plus max_order samples from the previous frame for all channels
int32_t **raw_lsb_samples; ///< pointer to the beginning of the current frame's shifted samples in the buffer for each channel
int32_t *res_buffer; ///< buffer containing all residual samples of the frame plus max_order samples from the previous frame (or zeroes) for all channels
int32_t **res_samples; ///< pointer to the beginning of the current frame's samples in the buffer for each channel
uint32_t *bs_info; ///< block partitioning used for the current frame
int *num_blocks; ///< number of blocks used for the block partitioning
unsigned int *bs_sizes_buffer; ///< buffer containing all block sizes for all channels
unsigned int **bs_sizes; ///< pointer to the beginning of the channel's block sizes for each channel
unsigned int *js_sizes_buffer; ///< buffer containing all block sizes for all channel-pairs of the difference signal
unsigned int **js_sizes; ///< pointer to the beginning of the channel's block sizes for each channel-pair difference signal
uint8_t *js_infos_buffer; ///< buffer containing all joint-stereo flags for all channel-pairs
uint8_t **js_infos; ///< pointer to the beginning of the channel's joint-stereo flags for each channel-pair
ALSBlock *block_buffer; ///< buffer containing all ALSBlocks for each channel
ALSBlock **blocks; ///< array of 32 ALSBlock pointers per channel pointing into the block_buffer
int32_t *q_parcor_coeff_buffer; ///< buffer containing 7-bit PARCOR coefficients for all blocks in all channels
double *acf_coeff; ///< autocorrelation function coefficients for the current block
double *parcor_coeff; ///< double-precision PARCOR coefficients for the current block
int32_t *r_parcor_coeff; ///< scaled 21-bit quantized PARCOR coefficients for the current block
int32_t *lpc_coeff; ///< LPC coefficients for the current block
double *parcor_error; ///< error for each order during PARCOR coeff calculation
unsigned int max_rice_param; ///< maximum Rice param, depends on sample depth
WindowContext acf_window[6]; ///< contexts for pre-autocorrelation windows for each block switching depth
int32_t *ltp_buffer; ///< temporary buffer to store long-term predicted samples
int32_t **ltp_samples; ///< pointer to the beginning of the current frame's ltp residuals in the buffer for each channel
double *corr_buffer; ///< temporary buffer to store the signal during LTP autocorrelation
double *corr_samples; ///< pointer to the beginning of the block in corr_buffer
uint8_t *frame_buffer; ///< buffer containing all already encoded frames of an RA-unit
int frame_buffer_size; ///< size of the frame_buffer in bytes
uint8_t *cur_frame; ///< pointer into frame_buffer to encode the next frame of an RA-unit to
} ALSEncContext;
/** compression level 0 global options **/
static const ALSSpecificConfig spc_config_c0 = {
.adapt_order = 0,
.long_term_prediction = 0,
.max_order = 4,
.block_switching = 0,
.bgmc = 0,
.sb_part = 0,
.joint_stereo = 0,
.mc_coding = 0,
.rlslms = 0,
.crc_enabled = 0,
};
/** compression level 0 joint-stereo options
note: compression level 0 does not use joint-stereo */
static const ALSEncStage stage_js_c0 = {
.check_constant = 0,
.check_lsbs = 0,
.max_order = 0,
.ecsub_algorithm = EC_SUB_ALGORITHM_RICE_ESTIMATE,
.param_algorithm = EC_PARAM_ALGORITHM_RICE_ESTIMATE,
.count_algorithm = EC_BIT_COUNT_ALGORITHM_ESTIMATE,
.adapt_search_algorithm = ADAPT_SEARCH_ALGORITHM_VALLEY_DETECT,
.adapt_count_algorithm = ADAPT_COUNT_ALGORITHM_ESTIMATE,
.ltp_coeff_algorithm = LTP_COEFF_ALGORITHM_FIXED,
.merge_algorithm = BS_ALGORITHM_BOTTOM_UP,
};
/** compression level 0 block switching stage options */
static const ALSEncStage stage_bs_c0 = {
.check_constant = 0,
.check_lsbs = 0,
.max_order = 4,
.ecsub_algorithm = EC_SUB_ALGORITHM_RICE_ESTIMATE,
.param_algorithm = EC_PARAM_ALGORITHM_RICE_ESTIMATE,
.count_algorithm = EC_BIT_COUNT_ALGORITHM_ESTIMATE,
.adapt_search_algorithm = ADAPT_SEARCH_ALGORITHM_VALLEY_DETECT,
.adapt_count_algorithm = ADAPT_COUNT_ALGORITHM_ESTIMATE,
.ltp_coeff_algorithm = LTP_COEFF_ALGORITHM_FIXED,
.merge_algorithm = BS_ALGORITHM_BOTTOM_UP,
};
/** compression level 0 final stage options */
static const ALSEncStage stage_final_c0 = {
.check_constant = 0,
.check_lsbs = 0,
.ecsub_algorithm = EC_SUB_ALGORITHM_RICE_ESTIMATE,
.param_algorithm = EC_PARAM_ALGORITHM_RICE_ESTIMATE,
.count_algorithm = EC_BIT_COUNT_ALGORITHM_ESTIMATE,
.adapt_search_algorithm = ADAPT_SEARCH_ALGORITHM_VALLEY_DETECT,
.adapt_count_algorithm = ADAPT_COUNT_ALGORITHM_ESTIMATE,
.ltp_coeff_algorithm = LTP_COEFF_ALGORITHM_FIXED,
.merge_algorithm = BS_ALGORITHM_BOTTOM_UP,
};
/** compression level 1 global options **/
static const ALSSpecificConfig spc_config_c1 = {
.adapt_order = 0,
.long_term_prediction = 0,
.max_order = 10,
.block_switching = 0,
.bgmc = 0,
.sb_part = 1,
.joint_stereo = 1,
.mc_coding = 0,
.rlslms = 0,
.crc_enabled = 1,
};
/** compression level 1 joint-stereo stage options */
static const ALSEncStage stage_js_c1 = {
.check_constant = 1,
.check_lsbs = 1,
.max_order = 5,
.ecsub_algorithm = EC_SUB_ALGORITHM_RICE_ESTIMATE,
.param_algorithm = EC_PARAM_ALGORITHM_RICE_ESTIMATE,
.count_algorithm = EC_BIT_COUNT_ALGORITHM_EXACT,
.adapt_search_algorithm = ADAPT_SEARCH_ALGORITHM_VALLEY_DETECT,
.adapt_count_algorithm = ADAPT_COUNT_ALGORITHM_ESTIMATE,
.ltp_coeff_algorithm = LTP_COEFF_ALGORITHM_FIXED,
.merge_algorithm = BS_ALGORITHM_FULL_SEARCH,
};
/** compression level 1 block switching stage options */
static const ALSEncStage stage_bs_c1 = {
.check_constant = 1,
.check_lsbs = 1,
.ecsub_algorithm = EC_SUB_ALGORITHM_RICE_EXACT,
.param_algorithm = EC_PARAM_ALGORITHM_RICE_EXACT,
.count_algorithm = EC_BIT_COUNT_ALGORITHM_EXACT,
.adapt_search_algorithm = ADAPT_SEARCH_ALGORITHM_VALLEY_DETECT,
.adapt_count_algorithm = ADAPT_COUNT_ALGORITHM_ESTIMATE,
.ltp_coeff_algorithm = LTP_COEFF_ALGORITHM_FIXED,
.merge_algorithm = BS_ALGORITHM_FULL_SEARCH,
};
/** compression level 1 final stage options */
static const ALSEncStage stage_final_c1 = {
.check_constant = 1,
.check_lsbs = 1,
.ecsub_algorithm = EC_SUB_ALGORITHM_RICE_EXACT,
.param_algorithm = EC_PARAM_ALGORITHM_RICE_EXACT,
.count_algorithm = EC_BIT_COUNT_ALGORITHM_EXACT,
.adapt_search_algorithm = ADAPT_SEARCH_ALGORITHM_VALLEY_DETECT,
.adapt_count_algorithm = ADAPT_COUNT_ALGORITHM_ESTIMATE,
.ltp_coeff_algorithm = LTP_COEFF_ALGORITHM_FIXED,
.merge_algorithm = BS_ALGORITHM_FULL_SEARCH,
};
/** compression level 2 global options **/
static const ALSSpecificConfig spc_config_c2 = {
.adapt_order = 1,
.long_term_prediction = 1,
.max_order = 32,
.block_switching = 1,
.bgmc = 1,
.sb_part = 1,
.joint_stereo = 1,
.mc_coding = 0,
.rlslms = 0,
.crc_enabled = 1,
};
/** compression level 2 joint-stereo stage options */
static const ALSEncStage stage_js_c2 = {
.check_constant = 1,
.check_lsbs = 1,
.ecsub_algorithm = EC_SUB_ALGORITHM_BGMC_EXACT,
.param_algorithm = EC_PARAM_ALGORITHM_BGMC_ESTIMATE,
.count_algorithm = EC_BIT_COUNT_ALGORITHM_EXACT,
.adapt_search_algorithm = ADAPT_SEARCH_ALGORITHM_VALLEY_DETECT,
.adapt_count_algorithm = ADAPT_COUNT_ALGORITHM_ESTIMATE,
.ltp_coeff_algorithm = LTP_COEFF_ALGORITHM_CHOLESKY,
.merge_algorithm = BS_ALGORITHM_FULL_SEARCH,
};
/** compression level 2 block switching stage options */
static const ALSEncStage stage_bs_c2 = {
.check_constant = 1,
.check_lsbs = 1,
.ecsub_algorithm = EC_SUB_ALGORITHM_BGMC_EXACT,
.param_algorithm = EC_PARAM_ALGORITHM_BGMC_ESTIMATE,
.count_algorithm = EC_BIT_COUNT_ALGORITHM_EXACT,
.adapt_search_algorithm = ADAPT_SEARCH_ALGORITHM_VALLEY_DETECT,
.adapt_count_algorithm = ADAPT_COUNT_ALGORITHM_ESTIMATE,
.ltp_coeff_algorithm = LTP_COEFF_ALGORITHM_CHOLESKY,
.merge_algorithm = BS_ALGORITHM_FULL_SEARCH,
};
/** compression level 2 final stage options */
static const ALSEncStage stage_final_c2 = {
.check_constant = 1,
.check_lsbs = 1,
.ecsub_algorithm = EC_SUB_ALGORITHM_BGMC_EXACT,
.param_algorithm = EC_PARAM_ALGORITHM_BGMC_ESTIMATE,
.count_algorithm = EC_BIT_COUNT_ALGORITHM_EXACT,
.adapt_search_algorithm = ADAPT_SEARCH_ALGORITHM_VALLEY_DETECT,
.adapt_count_algorithm = ADAPT_COUNT_ALGORITHM_ESTIMATE,
.ltp_coeff_algorithm = LTP_COEFF_ALGORITHM_CHOLESKY,
.merge_algorithm = BS_ALGORITHM_FULL_SEARCH,
};
/** global options for each compression level */
static const ALSSpecificConfig * const spc_config_settings[3] = {
&spc_config_c0,
&spc_config_c1,
&spc_config_c2,
};
/** joint-stereo stage options for each compression level */
static const ALSEncStage * const stage_js_settings[3] = {
&stage_js_c0,
&stage_js_c1,
&stage_js_c2,
};
/** block switching stage options for each compression level */
static const ALSEncStage * const stage_bs_settings[3] = {
&stage_bs_c0,
&stage_bs_c1,
&stage_bs_c2,
};
/** final stage options for each compression level */
static const ALSEncStage * const stage_final_settings[3] = {
&stage_final_c0,
&stage_final_c1,
&stage_final_c2,
};
static void dprint_stage_options(AVCodecContext *avctx, ALSEncStage *stage)
{
dprintf(avctx, "check_constant = %d\n", stage->check_constant);
dprintf(avctx, "check_lsbs = %d\n", stage->check_lsbs);
dprintf(avctx, "adapt_order = %d\n", stage->adapt_order);
dprintf(avctx, "max_order = %d\n", stage->max_order);
dprintf(avctx, "sb_part = %d\n", stage->sb_part);
switch (stage->ecsub_algorithm) {
case EC_SUB_ALGORITHM_RICE_ESTIMATE: dprintf(avctx, "ecsub_algorithm = rice estimate\n"); break;
case EC_SUB_ALGORITHM_RICE_EXACT: dprintf(avctx, "ecsub_algorithm = rice exact\n"); break;
case EC_SUB_ALGORITHM_BGMC_EXACT: dprintf(avctx, "ecsub_algorithm = bgmc exact\n"); break;
}
switch (stage->param_algorithm) {
case EC_PARAM_ALGORITHM_RICE_ESTIMATE: dprintf(avctx, "param_algorithm = rice estimate\n"); break;
case EC_PARAM_ALGORITHM_RICE_EXACT: dprintf(avctx, "param_algorithm = rice exact\n"); break;
case EC_PARAM_ALGORITHM_BGMC_ESTIMATE: dprintf(avctx, "param_algorithm = bgmc estimate\n"); break;
case EC_PARAM_ALGORITHM_BGMC_EXACT: dprintf(avctx, "param_algorithm = bgmc exact\n"); break;
}
switch (stage->count_algorithm) {
case EC_BIT_COUNT_ALGORITHM_ESTIMATE: dprintf(avctx, "count_algorithm = estimate\n"); break;
case EC_BIT_COUNT_ALGORITHM_EXACT: dprintf(avctx, "count_algorithm = exact\n"); break;
}
switch (stage->adapt_search_algorithm) {
case ADAPT_SEARCH_ALGORITHM_VALLEY_DETECT: dprintf(avctx, "adapt_search_algorithm = valley detect\n"); break;
case ADAPT_SEARCH_ALGORITHM_FULL: dprintf(avctx, "adapt_search_algorithm = full\n"); break;
}
switch (stage->adapt_count_algorithm) {
case ADAPT_COUNT_ALGORITHM_ESTIMATE: dprintf(avctx, "adapt_count_algorithm = estimate\n"); break;
case ADAPT_COUNT_ALGORITHM_EXACT: dprintf(avctx, "adapt_count_algorithm = exact\n"); break;
}
switch (stage->ltp_coeff_algorithm) {
case LTP_COEFF_ALGORITHM_FIXED: dprintf(avctx, "ltp_coeff_algorithm = fixed\n"); break;
case LTP_COEFF_ALGORITHM_CHOLESKY: dprintf(avctx, "ltp_coeff_algorithm = cholesky\n"); break;
}
switch (stage->merge_algorithm) {
case BS_ALGORITHM_FULL_SEARCH: dprintf(avctx, "merge_algorithm = full search\n"); break;
case BS_ALGORITHM_BOTTOM_UP: dprintf(avctx, "merge_algorithm = bottom-up\n"); break;
}
}
/**
* Convert an array of channel-interleaved samples into multiple arrays of
* samples per channel.
*/
static void deinterleave_raw_samples(ALSEncContext *ctx, void *data)
{
unsigned int sample, c, shift;
// transform input into internal format
#define DEINTERLEAVE_INPUT(bps) \
{ \
int##bps##_t *src = (int##bps##_t*) data; \
shift = bps - ctx->avctx->bits_per_raw_sample; \
for (sample = 0; sample < ctx->avctx->frame_size; sample++) \
for (c = 0; c < ctx->avctx->channels; c++) \
ctx->raw_samples[c][sample] = (*src++) >> shift; \
}
if (ctx->avctx->bits_per_raw_sample <= 8) {
uint8_t *src = (uint8_t *)data;
shift = 8 - ctx->avctx->bits_per_raw_sample;
for (sample = 0; sample < ctx->avctx->frame_size; sample++)
for (c = 0; c < ctx->avctx->channels; c++)
ctx->raw_samples[c][sample] = ((int)(*src++) - 128) >> shift;
} else if (ctx->avctx->bits_per_raw_sample <= 16) {
DEINTERLEAVE_INPUT(16)
} else {
DEINTERLEAVE_INPUT(32)
}
}
/**
* Recursively parse a given block partitioning and sum up all block sizes
* according to *bs_sizes to get the overall bit count.
*/
static void bs_get_size(const uint32_t bs_info, unsigned int n,
unsigned int *bs_sizes, unsigned int *bit_count)
{
if (n < 31 && ((bs_info << n) & 0x40000000)) {
// if the level is valid and the investigated bit n is set
// then recursively check both children at bits (2n+1) and (2n+2)
n *= 2;
bs_get_size(bs_info, n + 1, bs_sizes, bit_count);
bs_get_size(bs_info, n + 2, bs_sizes, bit_count);
} else {
// else the bit is not set or the last level has been reached
// (bit implicitly not set)
(*bit_count) += bs_sizes[n];
}
}
/**
* Recursively parse a given block partitioning and set all node bits to zero.
*/
static void bs_set_zero(uint32_t *bs_info, unsigned int n)
{
if (n < 31) {
// if the level is valid set this bit and
// all children to zero
*bs_info &= ~(1 << (30 - n));
n *= 2;
bs_set_zero(bs_info, n + 1);
bs_set_zero(bs_info, n + 2);
}
}
/**
* Recursively parse a given block partitioning and set all joint-stereo
* block flags according to *js_info.
*/
static void bs_set_js(const uint32_t bs_info, unsigned int n,
uint8_t *js_info,
ALSBlock **block_c1, ALSBlock **block_c2)
{
if (n < 31 && ((bs_info << n) & 0x40000000)) {
// if the level is valid and the investigated bit n is set
// then recursively check both children at bits (2n+1) and (2n+2)
n *= 2;
bs_set_js(bs_info, n + 1, js_info, block_c1, block_c2);
bs_set_js(bs_info, n + 2, js_info, block_c1, block_c2);
} else {
// else the bit is not set or the last level has been reached
// (bit implicitly not set)
(*block_c1)->js_block = (js_info[n] == 1);
(*block_c2)->js_block = (js_info[n] == 2);
(*block_c1)++;
(*block_c2)++;
}
}
/**
* Recursively set all block sizes to joint-stereo sizes where difference
* coding pays off for a block.
*/
static void set_js_sizes(ALSEncContext *ctx, unsigned int channel, int stage)
{
ALSSpecificConfig *sconf = &ctx->sconf;
unsigned int num_blocks = sconf->block_switching ? (1 << stage) : 1;
unsigned int b;
for (b = 0; b < num_blocks; b++) {
unsigned int *block_size = ctx->bs_sizes[channel ] + num_blocks - 1;
unsigned int *buddy_size = ctx->bs_sizes[channel + 1] + num_blocks - 1;
unsigned int *js_size = ctx->js_sizes[channel >> 1] + num_blocks - 1;
uint8_t *js_info = ctx->js_infos[channel >> 1] + num_blocks - 1;
// replace independent signal size with
// joint-stereo signal size according to js_info
// store independent value for resetting to independent coding
if (js_info[b] == 1) {
FFSWAP(unsigned int, block_size[b], js_size[b]);
} else if (js_info[b] == 2)
FFSWAP(unsigned int, buddy_size[b], js_size[b]);
}
if (sconf->block_switching && stage < sconf->block_switching)
set_js_sizes(ctx, channel, stage + 1);
}
/**
* Recursively reset all block sizes to independent sizes.
*/
static void reset_js_sizes(ALSEncContext *ctx, unsigned int channel, int stage)
{
ALSSpecificConfig *sconf = &ctx->sconf;
unsigned int num_blocks = sconf->block_switching ? (1 << stage) : 1;
unsigned int b;
for (b = 0; b < num_blocks; b++) {
ALSBlock *blocks = ctx->blocks [channel ] + num_blocks - 1;
ALSBlock *buddys = ctx->blocks [channel + 1] + num_blocks - 1;
unsigned int *block_size = ctx->bs_sizes[channel ] + num_blocks - 1;
unsigned int *buddy_size = ctx->bs_sizes[channel + 1] + num_blocks - 1;
unsigned int *js_size = ctx->js_sizes[channel >> 1] + num_blocks - 1;
uint8_t *js_info = ctx->js_infos[channel >> 1] + num_blocks - 1;
// replace joint-stereo signal size with
// independent signal size accoring to js_info
if (js_info[b] == 1) {
FFSWAP(unsigned int, block_size[b], js_size[b]);
} else if (js_info[b] == 2)
FFSWAP(unsigned int, buddy_size[b], js_size[b]);
js_info[b] = 0;
blocks [b].js_block = 0;
buddys [b].js_block = 0;
}
if (sconf->block_switching && stage < sconf->block_switching)
reset_js_sizes(ctx, channel, stage + 1);
}
/**
* Recursively merge all subblocks of the frame until the minimal bit count is
* found.
* Use Full-Search strategy.
*/
static void bs_merge_fullsearch(ALSEncContext *ctx, unsigned int n,
unsigned int c1, unsigned int c2)
{
uint32_t *bs_info = &ctx->bs_info[c1];
if (n < 31 && ((*bs_info << n) & 0x40000000)) {
// if the level is valid and the investigated bit n is set
// then recursively check both children at bits (2n+1) and (2n+2)
unsigned int *sizes_c1 = ctx->bs_sizes[c1];
unsigned int *sizes_c2 = ctx->bs_sizes[c2];
unsigned int a = 2 * n + 1;
unsigned int b = a + 1;
unsigned int sum_a = 0;
unsigned int sum_b = 0;
unsigned int sum_n = sizes_c1[n];
if (GET_BS_BIT(bs_info, a)) {
bs_merge_fullsearch(ctx, a, c1, c2);
}
if (GET_BS_BIT(bs_info, b)) {
bs_merge_fullsearch(ctx, b, c1, c2);
}
// calculate sizes of both children
bs_get_size(*bs_info, a, sizes_c1, &sum_a);
bs_get_size(*bs_info, b, sizes_c1, &sum_b);
if (c1 != c2) {
// for joint-stereo, also calculate size of
// the children of the buddy channel
sum_n += sizes_c2[n];
bs_get_size(*bs_info, a, sizes_c2, &sum_a);
bs_get_size(*bs_info, b, sizes_c2, &sum_b);
}
// test for merging
if (sum_a + sum_b > sum_n) {
bs_set_zero(bs_info, n);
if (c1 != c2)
ctx->bs_info[c2] = *bs_info;
}
}
}
/**
* Recursively merge all subblocks of the frame until the minimal bit count is
* found.
* Use Bottom-Up strategy.
*/
static void bs_merge_bottomup(ALSEncContext *ctx, unsigned int n,
unsigned int c1, unsigned int c2)
{
uint32_t *bs_info = &ctx->bs_info[c1];
if (n < 31 && ((*bs_info << n) & 0x40000000)) {
// if the level is valid and the investigated bit n is set
// then recursively check both children at bits (2n+1) and (2n+2)
unsigned int *sizes_c1 = ctx->bs_sizes[c1];
unsigned int *sizes_c2 = ctx->bs_sizes[c2];
unsigned int a = 2 * n + 1;
unsigned int b = a + 1;
unsigned int sum_a = 0;
unsigned int sum_b = 0;
unsigned int sum_n = sizes_c1[n];
if (GET_BS_BIT(bs_info, a) && GET_BS_BIT(bs_info, b)) {
bs_merge_bottomup(ctx, a, c1, c2);
bs_merge_bottomup(ctx, b, c1, c2);
}
// test if both children are leaves of the tree only
if (!GET_BS_BIT(bs_info, a) && !GET_BS_BIT(bs_info, b)) {
// get sizes of both children
sum_a += sizes_c1[a];
sum_b += sizes_c1[b];
if (c1 != c2) {
// for joint-stereo, also get size of
// the children of the buddy channel
sum_n += sizes_c2[n];
sum_a += sizes_c2[a];
sum_b += sizes_c2[b];
}
// test for merging
if (sum_a + sum_b > sum_n) {
bs_set_zero(bs_info, n);
if (c1 != c2)
ctx->bs_info[c2] = *bs_info;
}
}
}
}
/**
* Read block partitioning and set actual block sizes and all sample pointers.
* Also assure that the block sizes of the last frame correspond to the
* actual number of samples.
*/
static void set_blocks(ALSEncContext *ctx, uint32_t *bs_info,
unsigned int c1, unsigned int c2)
{
AVCodecContext *avctx = ctx->avctx;
ALSSpecificConfig *sconf = &ctx->sconf;
unsigned int div_blocks[32];
unsigned int *ptr_div_blocks = div_blocks;
unsigned int b;
int ltp = sconf->long_term_prediction;
int32_t *ltp_ptr = ltp ? ctx->ltp_samples[c1] : NULL;
int32_t *res_ptr = ctx->res_samples[c1];
int32_t *smp_ptr = ctx->raw_samples[c1];
int32_t *dif_ptr = ctx->raw_dif_samples[c1 >> 1];
int32_t *lsb_ptr = ctx->raw_lsb_samples[c1];
ALSBlock *block = ctx->blocks[c1];
ctx->num_blocks[c1] = 0;
ff_als_parse_bs_info(*bs_info, 0, 0, &ptr_div_blocks, &ctx->num_blocks[c1]);
// The last frame may have an overdetermined block structure given in
// the bitstream. In that case the defined block structure would need
// more samples than available to be consistent.
// The block structure is actually used but the block sizes are adapted
// to fit the actual number of available samples.
// Example: 5 samples, 2nd level block sizes: 2 2 2 2.
// This results in the actual block sizes: 2 2 1 0.
// This is not specified in 14496-3 but actually done by the reference
// codec RM22 revision 2.
// This appears to happen in case of an odd number of samples in the last
// frame which is actually not allowed by the block length switching part
// of 14496-3.
// The ALS conformance files feature an odd number of samples in the last
// frame.
for (b = 0; b < ctx->num_blocks[c1]; b++) {
block->div_block = div_blocks[b];
div_blocks[b] = ctx->sconf.frame_length >> div_blocks[b];
block->length = div_blocks[b];
block->res_ptr = res_ptr;
block->ltp_ptr = ltp_ptr;
block->smp_ptr = smp_ptr;
block->dif_ptr = dif_ptr;
block->lsb_ptr = lsb_ptr;
res_ptr += block->length;
ltp_ptr += block->length;
smp_ptr += block->length;
dif_ptr += block->length;
lsb_ptr += block->length;
block++;
}
if (avctx->frame_size != sconf->frame_length) {
unsigned int remaining = avctx->frame_size;
for (b = 0; b < ctx->num_blocks[c1]; b++) {
if (remaining <= div_blocks[b]) {
ctx->blocks[c1][b].div_block = -1;
ctx->blocks[c1][b].length = remaining;
ctx->num_blocks[c1] = b + 1;
break;
}
remaining -= ctx->blocks[c1][b].length;
}
}
if (c1 != c2) {
res_ptr = ctx->res_samples[c2];
ltp_ptr = ltp ? ctx->ltp_samples[c2] : NULL;
smp_ptr = ctx->raw_samples[c2];
dif_ptr = ctx->raw_dif_samples[c1 >> 1];
lsb_ptr = ctx->raw_lsb_samples[c2];
block = ctx->blocks[c2];
ctx->num_blocks[c2] = ctx->num_blocks[c1];
for (b = 0; b < ctx->num_blocks[c1]; b++) {
block->div_block = ctx->blocks[c1][b].div_block;
block->length = ctx->blocks[c1][b].length;
block->res_ptr = res_ptr;
block->ltp_ptr = ltp_ptr;
block->smp_ptr = smp_ptr;
block->dif_ptr = dif_ptr;
block->lsb_ptr = lsb_ptr;
res_ptr += block->length;
ltp_ptr += block->length;
smp_ptr += block->length;
dif_ptr += block->length;
lsb_ptr += block->length;
block++;
}
}
}
/**
* Get the best block partitioning for the current frame depending on the
* chosen algorithm and set the block sizes accordingly.
* @return Overall bit count for the partition
*/
static unsigned int get_partition(ALSEncContext *ctx, unsigned int c1, unsigned int c2)
{
ALSEncStage *stage = ctx->cur_stage;
unsigned int *sizes_c1 = ctx->bs_sizes[c1];
unsigned int *sizes_c2 = ctx->bs_sizes[c2];
unsigned int bit_count = 0;
// find best partitioning
if(stage->merge_algorithm == BS_ALGORITHM_BOTTOM_UP) {
bs_merge_bottomup(ctx, 0, c1, c2);
} else {
bs_merge_fullsearch(ctx, 0, c1, c2);
}
set_blocks(ctx, &ctx->bs_info[c1], c1, c2);
if (c1 != c2) {
// set joint-stereo sizes
ALSBlock *ptr_blocks_c1 = ctx->blocks[c1];
ALSBlock *ptr_blocks_c2 = ctx->blocks[c2];
bs_set_js(ctx->bs_info[c1], 0, ctx->js_infos[c1 >> 1], &ptr_blocks_c1,
&ptr_blocks_c2);
}
// get bit count for the chosen partitioning
bs_get_size(ctx->bs_info[c1], 0, sizes_c1, &bit_count);
if (c1 != c2)
bs_get_size(ctx->bs_info[c1], 0, sizes_c2, &bit_count);
return bit_count;
}
/**
* Subdivide the frame into smaller blocks.
*/
static void block_partitioning(ALSEncContext *ctx)
{
AVCodecContext *avctx = ctx->avctx;
ALSSpecificConfig *sconf = &ctx->sconf;
unsigned int c;
// find the best partitioning for each channel
if (!sconf->mc_coding || ctx->js_switch) {
// for each channel pair
for (c = 0; c < avctx->channels - 1; c += 2) {
if (sconf->joint_stereo) {
unsigned int bits_ind, bits_dep;
unsigned int bs_info_len = 1 << FFMAX(3, sconf->block_switching);
int32_t bs_info_c1, bs_info_c2;
int32_t bs_info = ctx->bs_info[c];
// get bit count and bs_info fields
// for independent channels
bits_ind = get_partition(ctx, c , c );
bits_ind += get_partition(ctx, c + 1, c + 1);
bs_info_c1 = ctx->bs_info[c ];
bs_info_c2 = ctx->bs_info[c + 1];
ctx->bs_info[c] = bs_info;
// get bit count and bs_info fields
// for joint-stereo
set_js_sizes(ctx, c, 0);
bits_dep = get_partition(ctx, c, c + 1);
// set to independent coding if necessary
if (bits_ind + bs_info_len < bits_dep) {
reset_js_sizes(ctx, c, 0);
ctx->independent_bs[c ] = 1;
ctx->independent_bs[c + 1] = 1;
ctx->bs_info [c ] = bs_info_c1;
ctx->bs_info [c + 1] = bs_info_c2;
set_blocks(ctx, &ctx->bs_info[c ], c , c );
set_blocks(ctx, &ctx->bs_info[c + 1], c + 1, c + 1);
}
} else {
get_partition(ctx, c , c );
get_partition(ctx, c + 1, c + 1);
}
}
// for the last channel if number of channels is odd
if (c < avctx->channels) {
get_partition(ctx, c, c);
}
} else {
// MCC: to be implemented
}
}
/**
* Count bits needed to write value 'v' using signed Rice coding with
* parameter 'k'.
*/
static inline int rice_count(int v, int k)
{
unsigned int v0 = (unsigned int)((2LL*v) ^ (int64_t)(v>>31));
return (v0 >> k) + 1 + k;
}
/**
* Count bits needed to write value 'v' using unsigned Rice coding with
* parameter 'k'.
*/
static inline int urice_count(unsigned int v, int k)
{
return (v >> k) + 1 + k;
}
/**
* Write the quotient part of a Rice code.
* This is the same for signed and unsigned Rice coding.
* @param[out] q0 quotient
* @return 0 on success, -1 on error
*/
static inline int golomb_write_quotient(PutBitContext *pb, unsigned int v,
int k, int *q0)
{
int q;
*q0 = v >> k;
q = *q0 + 1;
/* protect from buffer overwrite */
OVERFLOW_PROTECT(pb, q+k, return -1;)
while (q > 31) {
put_bits(pb, 31, 0x7FFFFFFF);
q -= 31;
}
put_bits(pb, q, ((1<<q)-1)^1);
return 0;
}
/**
* Write a signed Rice code.
* @return 0 on success, -1 on error
*/
static inline int set_ur_golomb_als(PutBitContext *pb, unsigned int v, int k)
{
int q0;
/* write quotient in zero-terminated unary */
if (golomb_write_quotient(pb, v, k, &q0))
return -1;
/* write remainder using k bits */
if (k)
put_bits(pb, k, v - (q0 << k));
return 0;
}
/**
* Write an unsigned Rice code to the bitstream.
* @return 0 on success, -1 on error
*/
static inline int set_sr_golomb_als(PutBitContext *pb, int v, int k)
{
unsigned int v0;
int q0;
/* remap to unsigned */
v0 = (unsigned int)((2LL*v) ^ (int64_t)(v>>31));
/* write quotient in zero-terminated unary */
if (golomb_write_quotient(pb, v0, k, &q0))
return -1;
/* write remainder using k bits */
if (k)
put_bits(pb, k, (v0 >> 1) - ((q0-(!(v0&1))) << (k-1)));
return 0;
}
/**
* Encode the LSB part of the given symbols.
* @return Overall bit count for all encoded symbols
*/
static int bgmc_encode_lsb(PutBitContext *pb, const int32_t *symbols, unsigned int n,
unsigned int k, unsigned int max, unsigned int s)
{
int count = 0;
int lsb_mask = (1 << k) - 1;
int abs_max = (max + 1) >> 1;
int high_offset = -(abs_max << k);
int low_offset = (abs_max - 1) << k;
for (; n > 0; n--) {
int32_t res = *symbols++;
if ((res >> k) >= abs_max || (res >> k) <= -abs_max) {
res += (res >> k) >= abs_max ? high_offset : low_offset;
if (pb && set_sr_golomb_als(pb, res, s) < 0)
return -1;
count += rice_count(res, s);
} else if (k) {
if (pb) {
OVERFLOW_PROTECT(pb, k, return -1;)
put_sbits(pb, k, res & lsb_mask);
}
count += k;
}
}
return count;
}
/**
* Map LTP gain value to nearest flattened array index.
* @return Nearest array index
*/
static int map_to_index(int gain)
{
int i, diff, min_diff, best_index;
const uint8_t *g_ptr = &ff_als_ltp_gain_values[0][0];
min_diff = abs((int)(*g_ptr++) - gain);
best_index = 0;
for (i = 1; i < 16; i++) {
diff = abs((int)(*g_ptr++) - gain);
if (!diff) {
return i;
} else if (diff < min_diff) {
min_diff = diff;
best_index = i;
} else {
return best_index;
}
}
return best_index;
}
/**
* Generate the long-term predicted residuals for a given block using the
* current set of LTP parameters.
*/
static void gen_ltp_residuals(ALSEncContext *ctx, ALSBlock *block)
{
ALSLTPInfo *ltp = &block->ltp_info[block->js_block];
int32_t *ltp_ptr = block->ltp_ptr;
int offset = FFMAX(ltp->lag - 2, 0);
unsigned int ltp_smp;
int64_t y;
int center, end, base;
memcpy(ltp_ptr, block->cur_ptr, sizeof(*ltp_ptr) * offset);
center = offset - ltp->lag;
end = center + 3;
for (ltp_smp = offset; ltp_smp < block->length; ltp_smp++,center++,end++) {
int begin = FFMAX(0, center - 2);
int tab = 5 - (end - begin);
y = 1 << 6;
for (base = begin; base < end; base++, tab++)
y += MUL64(ltp->gain[tab], block->cur_ptr[base]);
ltp_ptr[ltp_smp] = block->cur_ptr[ltp_smp] - (y >> 7);
}
}
/**
* Write a given block.
* @return 0 on success, -1 otherwise
*/
static int write_block(ALSEncContext *ctx, ALSBlock *block)
{
AVCodecContext *avctx = ctx->avctx;
ALSSpecificConfig *sconf = &ctx->sconf;
PutBitContext *pb = &ctx->pb;
unsigned int i;
int start = 0;
// block_type
PUT_BITS_SAFE(pb, 1, !block->constant, return -1;)
if (block->constant) {
OVERFLOW_PROTECT(pb, 7, return -1;)
// const_block
put_bits(pb, 1, block->constant_value != 0);
// js_block
put_bits(pb, 1, block->js_block);
// reserved
put_bits(pb, 5, 0);
if (block->constant_value) {
int const_val_bits = sconf->floating ? 24 : avctx->bits_per_raw_sample;
OVERFLOW_PROTECT(pb, const_val_bits, return -1;)
if (const_val_bits == 32)
put_bits32(pb, block->constant_value);
else
put_sbits(pb, const_val_bits, block->constant_value);
}
} else {
ALSLTPInfo *ltp = &block->ltp_info[block->js_block];
ALSEntropyInfo *ent = &block->ent_info[ltp->use_ltp];
int32_t *res_ptr;
int sb, sb_length;
unsigned int high;
unsigned int low;
unsigned int follow;
unsigned int delta[8];
unsigned int k [8];
unsigned int max [8];
unsigned int *s = ent->rice_param;
unsigned int *sx = ent->bgmc_param;
// js_block
PUT_BITS_SAFE(pb, 1, block->js_block, return -1;)
// ec_sub
if (sconf->sb_part || sconf->bgmc) {
if (sconf->sb_part && sconf->bgmc)
PUT_BITS_SAFE(pb, 2, av_log2(ent->sub_blocks), return -1;)
else
PUT_BITS_SAFE(pb, 1, ent->sub_blocks > 1, return -1;)
}
// s[k], sx[k]
if (sconf->bgmc) {
unsigned int S[8];
for (sb = 0; sb < ent->sub_blocks; sb++)
S[sb] = (ent->rice_param[sb] << 4) | ent->bgmc_param[sb];
PUT_BITS_SAFE(pb, 8 + (avctx->bits_per_raw_sample > 16), S[0], return -1;)
for (sb = 1; sb < ent->sub_blocks; sb++)
if (set_sr_golomb_als(pb, S[sb] - S[sb-1], 2))
return -1;
} else {
PUT_BITS_SAFE(pb, 4 + (avctx->bits_per_raw_sample > 16), ent->rice_param[0], return -1;)
for (sb = 1; sb < ent->sub_blocks; sb++) {
if (set_sr_golomb_als(pb, ent->rice_param[sb] - ent->rice_param[sb-1], 0))
return -1;
}
}
// shift_lsbs && shift_pos
PUT_BITS_SAFE(pb, 1, block->shift_lsbs > 0, return -1;)
if (block->shift_lsbs)
PUT_BITS_SAFE(pb, 4, block->shift_lsbs - 1, return -1;)
// opt_order && quant_cof
if (!sconf->rlslms) {
// opt_order
if (sconf->adapt_order) {
PUT_BITS_SAFE(pb, block->bits_adapt_order, block->opt_order, return -1;)
}
// for each quant_cof, put(quant_cof) in rice code
if (sconf->coef_table == 3) {
OVERFLOW_PROTECT(pb, block->opt_order * 7, return -1;)
for (i = 0; i < block->opt_order; i++)
put_bits(pb, 7, 64 + block->q_parcor_coeff[i]);
} else {
// write coefficient 0 to 19
int next_max_order = FFMIN(block->opt_order, 20);
for (i = 0; i < next_max_order; i++) {
int rice_param = ff_als_parcor_rice_table[sconf->coef_table][i][1];
int offset = ff_als_parcor_rice_table[sconf->coef_table][i][0];
if (set_sr_golomb_als(pb, block->q_parcor_coeff[i] - offset, rice_param))
return -1;
}
// write coefficients 20 to 126
next_max_order = FFMIN(block->opt_order, 127);
for (; i < next_max_order; i++)
if (set_sr_golomb_als(pb, block->q_parcor_coeff[i] - (i & 1), 2))
return -1;
// write coefficients 127 to opt_order
for (; i < block->opt_order; i++)
if (set_sr_golomb_als(pb, block->q_parcor_coeff[i], 1))
return -1;
}
}
// LPTenable && LTPgain && LTPlag
if (sconf->long_term_prediction) {
PUT_BITS_SAFE(pb, 1, ltp->use_ltp, return -1;)
if (ltp->use_ltp) {
int ltp_lag_length = 8 + (avctx->sample_rate >= 96000) +
(avctx->sample_rate >= 192000);
if (set_sr_golomb_als(pb, ltp->gain[0] >> 3, 1) ||
set_sr_golomb_als(pb, ltp->gain[1] >> 3, 2) ||
set_ur_golomb_als(pb, map_to_index(ltp->gain[2]), 2) ||
set_sr_golomb_als(pb, ltp->gain[3] >> 3, 2) ||
set_sr_golomb_als(pb, ltp->gain[4] >> 3, 1)) {
return -1;
}
PUT_BITS_SAFE(pb, ltp_lag_length,
ltp->lag - FFMAX(4, block->opt_order + 1),
return -1;)
}
}
// write residuals
// for now, all frames are RA frames, so use progressive prediction for
// the first 3 residual samples, up to opt_order
res_ptr = block->cur_ptr;
sb_length = block->length / ent->sub_blocks;
if (sconf->bgmc)
ff_bgmc_encode_init(&high, &low, &follow);
for (sb = 0; sb < ent->sub_blocks; sb++) {
i = 0;
if (!sb && block->ra_block) {
int len = block->opt_order;
int32_t write;
if (len > 0) {
if (set_sr_golomb_als(pb, *res_ptr++, avctx->bits_per_raw_sample-4))
return -1;
i++;
if (len > 1) {
write = sb_length <= 1 ? 0 : *res_ptr++;
if (set_sr_golomb_als(pb, write, FFMIN(ent->rice_param[sb]+3, ctx->max_rice_param)))
return -1;
i++;
if (len > 2) {
write = sb_length <= 2 ? 0 : *res_ptr++;
if (set_sr_golomb_als(pb, write, FFMIN(ent->rice_param[sb]+1, ctx->max_rice_param)))
return -1;
i++;
}
}
}
start = i;
}
if (sconf->bgmc) {
unsigned int b = av_clip((av_ceil_log2(block->length) - 3) >> 1, 0, 5);
k [sb] = s[sb] > b ? s[sb] - b : 0;
delta[sb] = 5 - s[sb] + k[sb];
max [sb] = ff_bgmc_max[sx[sb]] >> delta[sb];
if (ff_bgmc_encode_msb(pb, res_ptr, sb_length - i,
k[sb], delta[sb], max[sb],
s[sb], sx[sb],
&high, &low, &follow) < 0) {
return -1;
}
res_ptr += sb_length - i;
} else {
for (; i < sb_length; i++) {
if (set_sr_golomb_als(pb, *res_ptr++, ent->rice_param[sb]))
return -1;
}
}
}
if (sconf->bgmc) {
if (ff_bgmc_encode_end(pb, &low, &follow) < 0)
return -1;
res_ptr = block->cur_ptr + start;
for (sb = 0; sb < ent->sub_blocks; sb++, start = 0) {
if (bgmc_encode_lsb(pb, res_ptr, sb_length - start, k[sb], max[sb], s[sb]) < 0)
return -1;
res_ptr += sb_length - start;
}
}
}
if (!sconf->mc_coding || ctx->js_switch)
align_put_bits(pb);
return 0;
}
/**
* Write the frame.
* @return Overall bit count for the frame on success, -1 otherwise
*/
static int write_frame(ALSEncContext *ctx, uint8_t *frame, int buf_size)
{
AVCodecContext *avctx = ctx->avctx;
ALSSpecificConfig *sconf = &ctx->sconf;
unsigned int c, b;
int ret;
init_put_bits(&ctx->pb, frame, buf_size);
// make space for ra_unit_size
if (sconf->ra_flag == RA_FLAG_FRAMES && sconf->ra_distance == 1) {
// TODO: maybe keep frame count and allow other RA distances if API will allow
OVERFLOW_PROTECT(&ctx->pb, 32, return -1;)
put_bits32(&ctx->pb, 0);
}
// js_switch
if (ctx->js_switch) {
// to be implemented
// not yet supported anyway
}
// write blocks
if (!sconf->mc_coding || ctx->js_switch) {
for (c = 0; c < avctx->channels; c++) {
if (sconf->block_switching) {
unsigned int bs_info_len = 1 << FFMAX(3, sconf->block_switching);
uint32_t bs_info = ctx->bs_info[c];
if (sconf->joint_stereo && ctx->independent_bs[c])
bs_info |= (1 << 31);
OVERFLOW_PROTECT(&ctx->pb, bs_info_len, return -1;)
if (bs_info_len == 32)
put_bits32(&ctx->pb, bs_info);
else
put_bits(&ctx->pb, bs_info_len, bs_info >> (32 - bs_info_len));
}
for (b= 0; b < ctx->num_blocks[c]; b++) {
if (ctx->independent_bs[c]) {
if (write_block(ctx, &ctx->blocks[c][b]) < 0)
return -1;
} else {
if (write_block(ctx, &ctx->blocks[c ][b]) < 0 ||
write_block(ctx, &ctx->blocks[c+1][b]) < 0) {
return -1;
}
}
}
if(!ctx->independent_bs[c]) c++;
}
} else {
// MCC: to be implemented
}
flush_put_bits(&ctx->pb);
ret = put_bits_count(&ctx->pb) >> 3;
// write ra_unit_size
if (sconf->ra_flag == RA_FLAG_FRAMES && sconf->ra_distance == 1) {
AV_WB32(frame, ret);
}
return ret;
}
/**
* Quantize and rescale a single PARCOR coefficient.
* @param ctx Encoder context
* @param parcor double-precision PARCOR coefficient
* @param index coefficient index number
* @param[out] q_parcor 7-bit quantized coefficient
* @param[out] r_parcor 21-bit reconstructed coefficient
* @return the number of bits used to encode the coefficient
*/
static int quantize_single_parcor_coeff(ALSEncContext *ctx, double parcor,
int index, int32_t *q_parcor,
int32_t *r_parcor)
{
int rice_param, offset;
int sign = !index - index;
// compand coefficient for index 0 or 1
if (index < 2)
parcor = sqrt(2.0 * (sign * parcor + 1.0)) - 1.0;
// quantize to signed 7-bit
*q_parcor = av_clip((int32_t)floor(64.0 * parcor), -64, 63);
// rescale to signed 21-bit
if (index < 2)
*r_parcor = sign * 32 * ff_als_parcor_scaled_values[*q_parcor + 64];
else
*r_parcor = (*q_parcor << 14) + (1 << 13);
// count bits used for this coefficient
if (index < 20) {
rice_param = ff_als_parcor_rice_table[ctx->sconf.coef_table][index][1];
offset = ff_als_parcor_rice_table[ctx->sconf.coef_table][index][0];
} else if (index < 127) {
rice_param = 2;
offset = index & 1;
} else {
rice_param = 1;
offset = 0;
}
return rice_count(*q_parcor - offset, rice_param);
}
/**
* Quantize all PARCOR coefficients up to max_order and set the cumulative
* bit counts for each order.
*/
static void quantize_parcor_coeffs(ALSEncContext *ctx, ALSBlock *block,
const double *parcor, int max_order)
{
int i;
block->bits_parcor_coeff[0] = 0;
for (i = 0; i < max_order; i++) {
block->bits_parcor_coeff[i+1] = block->bits_parcor_coeff[i] +
quantize_single_parcor_coeff(ctx, parcor[i], i,
&block->q_parcor_coeff[i],
&ctx->r_parcor_coeff[i]);
}
}
/**
* Count bits needed to encode all symbols of a given subblock using the
* given parameters.
*/
static unsigned int subblock_ec_count_exact(const int32_t *res_ptr,
int b_length, int sb_length,
int s, int sx, int max_param,
int ra_subblock, int order,
int bgmc)
{
unsigned int count = 0;
unsigned int len = 0;
if (ra_subblock) {
if (order > 0) {
int32_t v = *res_ptr++;
len++;
count += rice_count(v, max_param - 3);
if (order > 1) {
v = sb_length <= 1 ? 0 : *res_ptr++;
len++;
count += rice_count(v, FFMIN(s+3, max_param));
if (order > 2) {
v = sb_length <= 2 ? 0 : *res_ptr++;
len++;
count += rice_count(v, FFMIN(s+1, max_param));
}
}
}
}
if (bgmc) {
unsigned int high, low, follow;
unsigned int delta, k, max, b;
int c;
// count msb's
ff_bgmc_encode_init(&high, &low, &follow);
b = av_clip((av_ceil_log2(b_length) - 3) >> 1, 0, 5);
k = s > b ? s - b : 0;
delta = 5 - s + k;
max = ff_bgmc_max[sx] >> delta;
c = ff_bgmc_encode_msb(NULL, res_ptr, sb_length - len, k, delta, max,
s, sx, &high, &low, &follow);
if (c < 0)
return -1;
count += c;
c = ff_bgmc_encode_end(NULL, &low, &follow);
if (c < 0)
return -1;
count += c;
// count lsb's
c = bgmc_encode_lsb(NULL, res_ptr, sb_length - len, k, max, s);
if (c < 0)
return -1;
count += c;
} else {
int i;
for (i = len; i < sb_length; i++) {
int32_t v = *res_ptr++;
count += rice_count(v, s);
}
}
return count;
}
/**
* Count bits needed to encode all the entropy coding parameters for a block.
*/
static unsigned int block_ec_param_count(ALSEncContext *ctx, ALSBlock *block,
int sub_blocks, int *s, int *sx,
int bgmc)
{
unsigned int count = 0;
int k = bgmc ? 2 : 0;
int sb;
count += (4 << bgmc) + (ctx->max_rice_param > 15);
if (sub_blocks) {
for (sb = 1; sb < sub_blocks; sb++) {
int ep_diff;
if (bgmc)
ep_diff = ((s[sb ] << 4) | sx[sb ]) -
((s[sb - 1] << 4) | sx[sb - 1]);
else
ep_diff = s[sb] - s[sb - 1];
count += rice_count(ep_diff, k);
}
}
count += (!!ctx->sconf.sb_part) << bgmc;
return count;
}
/**
* Count bits needed to encode all symbols and entropy coding parameters of a
* given block using given parameters.
*/
static unsigned int block_ec_count_exact(ALSEncContext *ctx, ALSBlock *block,
int sub_blocks, int *s, int *sx,
int order, int bgmc)
{
int32_t *res_ptr = block->cur_ptr;
unsigned int count = 0;
int sb_length, sb;
sb_length = block->length / sub_blocks;
for (sb = 0; sb < sub_blocks; sb++) {
count += subblock_ec_count_exact(res_ptr, block->length, sb_length,
s[sb], sx?sx[sb]:0,
ctx->max_rice_param,
!sb && block->ra_block, order, bgmc);
res_ptr += sb_length;
}
count += block_ec_param_count(ctx, block, sub_blocks, s, sx, bgmc);
return count;
}
#define rice_encode_count(sum, n, k) (((n)*((k)+1))+((sum-(n>>1))>>(k)))
/**
* Estimate the best Rice parameter using the sum of unsigned residual samples.
*/
static inline int estimate_rice_param(uint64_t sum, int length, int max_param)
{
int k;
if (sum <= length >> 1)
return 0;
if (sum > UINT32_MAX) {
sum = FFMAX((sum - (length >> 1)) / length, 1);
k = (int)floor(log2(sum));
} else {
unsigned int sum1 = sum - (length >> 1);
k = av_log2(length < 256 ? FASTDIV(sum1, length) : sum1 / length);
}
return FFMIN(k, max_param);
}
/**
* Get an estimated Rice parameter and split it into its LSB and MSB for
* further processing in BGMC.
*/
static inline void estimate_bgmc_params(uint64_t sum, unsigned int n, int *s,
int *sx)
{
#define OFFSET 0.97092725747512664825 /* 0.5 + log2(1.386) */
if (!sum) { // avoid log2(0)
*sx = *s = 0;
} else {
int tmp = (int)(16.0 * (log2(sum) - log2(n) + OFFSET));
tmp = FFMAX(tmp, 0);
*sx = tmp & 0x0F;
*s = tmp >> 4;
}
}
static void find_block_rice_params_est(ALSEncContext *ctx, ALSBlock *block,
int order)
{
int i, sb, sb_max, sb_length, p0;
uint64_t sum[5] = {0,};
int param[5];
unsigned int count1, count4;
ALSEncStage *stage = ctx->cur_stage;
ALSLTPInfo *ltp = &block->ltp_info[block->js_block];
ALSEntropyInfo *ent = &block->ent_info[ltp->use_ltp];
const int32_t *res_ptr = block->cur_ptr;
if (!stage->sb_part || block->length & 0x3 || block->length < 16)
sb_max = 1;
else
sb_max = 4;
sb_length = block->length / sb_max;
for (sb = 0; sb < sb_max; sb++) {
for (i = 0; i < sb_length; i++) {
int32_t v = *res_ptr++;
sum[sb] += (unsigned int)((2LL*v) ^ (int64_t)(v>>31));
}
sum[4] += sum[sb];
param[sb] = estimate_rice_param(sum[sb], sb_length, ctx->max_rice_param);
}
param[4] = estimate_rice_param(sum[4], block->length, ctx->max_rice_param);
if (stage->count_algorithm == EC_BIT_COUNT_ALGORITHM_EXACT) {
count1 = block_ec_count_exact(ctx, block, 1, &param[4], NULL, order, 0);
} else {
count1 = rice_encode_count(sum[4], block->length, param[4]);
count1 += 4 + (ctx->max_rice_param > 15);
}
p0 = param[0];
if (sb_max == 1 || ((p0 == param[1]) && (p0 == param[2]) &&
(p0 == param[3]))) {
ent->sub_blocks = 1;
ent->rice_param[0] = param[4];
ent->bits_ec_param_and_res = count1;
return;
}
if (stage->count_algorithm == EC_BIT_COUNT_ALGORITHM_EXACT) {
count4 = block_ec_count_exact(ctx, block, 4, param, NULL, order, 0);
} else {
count4 = 0;
for (sb = 0; sb < sb_max; sb++) {
count4 += rice_encode_count(sum[sb], sb_length, param[sb]);
if (!sb)
count4 += 4 + (ctx->max_rice_param > 15);
else
count4 += rice_count(param[sb] - param[sb-1], 0);
}
}
if (count1 <= count4) {
ent->sub_blocks = 1;
ent->rice_param[0] = param[4];
ent->bits_ec_param_and_res = count1;
} else {
ent->sub_blocks = 4;
ent->rice_param[0] = param[0];
ent->rice_param[1] = param[1];
ent->rice_param[2] = param[2];
ent->rice_param[3] = param[3];
ent->bits_ec_param_and_res = count4;
}
}
/**
* Perform full search for optimal BGMC parameters and sub-block division.
*/
static void find_block_bgmc_params_est(ALSEncContext *ctx, ALSBlock *block,
int order)
{
ALSEncStage *stage = ctx->cur_stage;
ALSLTPInfo *ltp = &block->ltp_info[block->js_block];
ALSEntropyInfo *ent = &block->ent_info[ltp->use_ltp];
int s[4][8], sx[4][8];
int p, sb, i;
int p_max;
int p_best;
unsigned int count_best = UINT_MAX;
uint64_t sum[4][8];
if (!stage->sb_part || block->length & 0x3 || block->length < 16)
p_max = 0;
else
p_max = 3;
p_best = p_max;
for (p = p_max; p >= 0; p--) {
int num_subblocks = 1 << p;
int sb_length = block->length / num_subblocks;
unsigned int count = 0;
int32_t *res_ptr = block->cur_ptr;
for (sb = 0; sb < num_subblocks; sb++) {
if (p == p_max) {
int32_t *r_ptr = res_ptr;
sum[p][sb] = 0;
for (i = 0; i < sb_length; i++)
sum[p][sb] += abs(*r_ptr++);
} else {
sum[p][sb] = sum[p+1][sb<<1] + sum[p+1][(sb<<1)+1];
}
estimate_bgmc_params(sum[p][sb], sb_length, &s[p][sb], &sx[p][sb]);
if (stage->ecsub_algorithm == EC_SUB_ALGORITHM_RICE_ESTIMATE) {
int k = estimate_rice_param (sum[p][sb], sb_length,
ctx->max_rice_param);
count += rice_encode_count(sum[p][sb], sb_length, k);
}
res_ptr += sb_length;
}
if (stage->ecsub_algorithm == EC_SUB_ALGORITHM_BGMC_EXACT) {
count = block_ec_count_exact(ctx, block, num_subblocks,
s[p], sx[p], order, 1);
}
if (count <= count_best) {
count_best = count;
p_best = p;
}
}
ent->sub_blocks = 1 << p_best;
for (sb = 0; sb < ent->sub_blocks; sb++) {
ent->rice_param[sb] = s [p_best][sb];
ent->bgmc_param[sb] = sx[p_best][sb];
}
if (stage->ecsub_algorithm == EC_SUB_ALGORITHM_RICE_ESTIMATE &&
stage->count_algorithm == EC_BIT_COUNT_ALGORITHM_EXACT) {
ent->bits_ec_param_and_res = block_ec_count_exact(ctx, block, ent->sub_blocks,
ent->rice_param, ent->bgmc_param,
order, 1);
} else {
ent->bits_ec_param_and_res = count_best;
}
}
static void find_block_rice_params_exact(ALSEncContext *ctx, ALSBlock *block,
int order)
{
unsigned int count[4] = {0,};
int param[4], p0;
int k, step, sb, sb_max, sb_length;
int best_k;
unsigned int count1, count4;
ALSEncStage *stage = ctx->cur_stage;
ALSLTPInfo *ltp = &block->ltp_info[block->js_block];
ALSEntropyInfo *ent = &block->ent_info[ltp->use_ltp];
if (!stage->sb_part || block->length & 0x3 || block->length < 16)
sb_max = 1;
else
sb_max = 4;
sb_length = block->length / sb_max;
best_k = ctx->max_rice_param / 3;
for (sb = 0; sb < sb_max; sb++) {
int32_t *res_ptr = block->cur_ptr + (sb * sb_length);
unsigned int c1, c2;
k = FFMIN(best_k, ctx->max_rice_param-1);
c1 = subblock_ec_count_exact(res_ptr,
block->length, sb_length, k, 0,
ctx->max_rice_param,
!sb && block->ra_block, order, 0);
k++;
c2 = subblock_ec_count_exact(res_ptr,
block->length, sb_length, k, 0,
ctx->max_rice_param,
!sb && block->ra_block, order, 0);
if (c2 < c1) {
best_k = k;
step = 1;
k++;
} else {
best_k = k - 1;
c2 = c1;
step = -1;
k -= 2;
}
for (; k >= 0 && k <= ctx->max_rice_param; k += step) {
c1 = subblock_ec_count_exact(res_ptr,
block->length, sb_length, k, 0,
ctx->max_rice_param,
!sb && block->ra_block, order, 0);
if (c1 < c2) {
best_k = k;
c2 = c1;
} else {
break;
}
}
param[sb] = best_k;
count[sb] = c2;
}
/* if sub-block partitioning is not used, stop here */
p0 = param[0];
if (sb_max == 1 || (p0 == param[1] && p0 == param[2] && p0 == param[3])) {
ent->sub_blocks = 1;
ent->rice_param[0] = param[0];
ent->bits_ec_param_and_res = block_ec_count_exact(ctx, block, 1,
param, NULL, order, 0);
return;
}
p0 = (param[0] + param[1] + param[2] + param[3]) >> 2;
count1 = block_ec_count_exact(ctx, block, 1, &p0, NULL, order, 0);
count4 = count[0] + count[1] + count[2] + count[3] +
block_ec_param_count(ctx, block, 4, param, NULL, 0);
if (count1 <= count4) {
ent->sub_blocks = 1;
ent->rice_param[0] = p0;
ent->bits_ec_param_and_res = count1;
} else {
ent->sub_blocks = 4;
ent->rice_param[0] = param[0];
ent->rice_param[1] = param[1];
ent->rice_param[2] = param[2];
ent->rice_param[3] = param[3];
ent->bits_ec_param_and_res = count4;
}
}
static void find_block_bgmc_params_exact(ALSEncContext *ctx, ALSBlock *block, int order)
{
ALSEncStage *stage = ctx->cur_stage;
ALSLTPInfo *ltp = &block->ltp_info[block->js_block];
ALSEntropyInfo *ent = &block->ent_info[ltp->use_ltp];
int s[4][8], sx[4][8];
int p, sb;
int p_max;
int p_best;
unsigned int count_best = UINT_MAX;
if (!stage->sb_part || block->length & 0x3 || block->length < 16)
p_max = 0;
else
p_max = 3;
p_best = p_max;
for (p = p_max; p >= 0; p--) {
int num_subblocks = 1 << p;
int sb_length = block->length / num_subblocks;
int32_t *res_ptr = block->cur_ptr;
unsigned int count;
for (sb = 0; sb < num_subblocks; sb++) {
int s0, si, sxi;
int step;
int best_s0 = 0;
unsigned int s0_count[256];
int dc = 0;
/* guess starting point for search */
if (!sb) {
if (p < p_max)
s0 = av_clip((s[p+1][sb>>1] << 4) | sx[p+1][sb>>1], 5, 250);
else
s0 = 127;
} else {
s0 = av_clip((s[p][sb-1] << 4) | sx[p][sb-1], 5, 250);
}
s0_count[s0] = subblock_ec_count_exact(res_ptr, block->length,
sb_length, s0 >> 4, s0 & 0xF,
ctx->max_rice_param, !sb && block->ra_block,
order, 1);
/* determine search direction */
s0 += 5;
s0_count[s0] = subblock_ec_count_exact(res_ptr, block->length,
sb_length, s0 >> 4, s0 & 0xF,
ctx->max_rice_param, !sb && block->ra_block,
order, 1);
s0 -= 10;
s0_count[s0] = subblock_ec_count_exact(res_ptr, block->length,
sb_length, s0 >> 4, s0 & 0xF,
ctx->max_rice_param, !sb && block->ra_block,
order, 1);
s0 += 5;
if (s0_count[s0+5] < s0_count[s0]) {
step = 1;
} else if (s0_count[s0-5] < s0_count[s0]) {
step = -1;
} else {
/* lowest count is likely between s0-4 and s0+4 */
int max_s0 = s0 + 5;
best_s0 = s0;
for (s0 = s0 - 4; s0 < max_s0; s0++) {
s0_count[s0] = subblock_ec_count_exact(res_ptr, block->length,
sb_length, s0 >> 4, s0 & 0xF,
ctx->max_rice_param, !sb && block->ra_block,
order, 1);
if (s0_count[s0] < s0_count[best_s0])
best_s0 = s0;
}
dc = 1;
}
/* search for best parameters */
if (!dc) {
best_s0 = s0;
s0 += step;
for (; s0 >= 0 && s0 < 256; s0 += step) {
si = s0 >> 4;
sxi = s0 & 0xF;
s0_count[s0] = subblock_ec_count_exact(res_ptr,
block->length, sb_length, si, sxi,
ctx->max_rice_param, !sb && block->ra_block,
order, 1);
if (s0_count[s0] < s0_count[best_s0]) {
best_s0 = s0;
dc = 0;
} else {
dc++;
if (dc > 5)
break;
}
}
}
/* save best parameters for this sub-block */
s [p][sb] = best_s0 >> 4;
sx[p][sb] = best_s0 & 0xF;
res_ptr += sb_length;
}
count = block_ec_count_exact(ctx, block, num_subblocks, s[p], sx[p],
order, 1);
if (count < count_best) {
count_best = count;
p_best = p;
}
}
ent->sub_blocks = 1 << p_best;
for (sb = 0; sb < ent->sub_blocks; sb++) {
ent->rice_param[sb] = s [p_best][sb];
ent->bgmc_param[sb] = sx[p_best][sb];
}
ent->bits_ec_param_and_res = count_best;
}
/**
* Calculate optimal sub-block division and Rice parameters for a block.
* @param ctx encoder context
* @param block current block
* @param ra_block indicates if this is a random access block
* @param order LPC order
*/
static void find_block_entropy_params(ALSEncContext *ctx, ALSBlock *block,
int order)
{
ALSEncStage *stage = ctx->cur_stage;
if (stage->param_algorithm == EC_PARAM_ALGORITHM_BGMC_ESTIMATE) {
find_block_bgmc_params_est(ctx, block, order);
} else if (stage->param_algorithm == EC_PARAM_ALGORITHM_BGMC_EXACT) {
find_block_bgmc_params_exact(ctx, block, order);
} else if (stage->param_algorithm == EC_PARAM_ALGORITHM_RICE_ESTIMATE) {
find_block_rice_params_est(ctx, block, order);
} else if (stage->param_algorithm == EC_PARAM_ALGORITHM_RICE_EXACT) {
find_block_rice_params_exact(ctx, block, order);
}
}
static int calc_short_term_prediction(ALSEncContext *ctx, ALSBlock *block,
int order)
{
ALSSpecificConfig *sconf = &ctx->sconf;
int i, j;
int32_t *res_ptr = block->res_ptr;
int32_t *smp_ptr = block->cur_ptr;
assert(order > 0);
#define LPC_PREDICT_SAMPLE(lpc, smp_ptr, res_ptr, order)\
{\
int64_t y = 1 << 19;\
for (j = 1; j <= order; j++)\
y += MUL64(lpc[j-1], (smp_ptr)[-j]);\
*(res_ptr++) = *(smp_ptr++) + (int32_t)(y >> 20);\
}
i = 0;
if (block->ra_block) {
int ra_order = FFMIN(order, block->length);
// copy first residual sample verbatim
*(res_ptr++) = *(smp_ptr++);
// progressive prediction
ff_als_parcor_to_lpc(0, ctx->r_parcor_coeff, ctx->lpc_coeff);
for (i = 1; i < ra_order; i++) {
LPC_PREDICT_SAMPLE(ctx->lpc_coeff, smp_ptr, res_ptr, i);
if (ff_als_parcor_to_lpc(i, ctx->r_parcor_coeff, ctx->lpc_coeff))
return -1;
}
// zero unused coeffs for small frames since they are all written
// to the bitstream if adapt_order is not used.
if (!sconf->adapt_order) {
for (; i < sconf->max_order; i++)
block->q_parcor_coeff[i] = ctx->r_parcor_coeff[i] = 0;
}
} else {
for (j = 0; j < order; j++)
if (ff_als_parcor_to_lpc(j, ctx->r_parcor_coeff, ctx->lpc_coeff))
return -1;
}
// remaining residual samples
for (; i < block->length; i++) {
LPC_PREDICT_SAMPLE(ctx->lpc_coeff, smp_ptr, res_ptr, order);
}
return 0;
}
/**
* Test given block samples to be of constant value.
* Set block->const_block_bits to the number of bits used for encoding the
* constant block, or to zero if the block is not a constant block.
*/
static void test_const_value(ALSEncContext *ctx, ALSBlock *block)
{
if (ctx->cur_stage->check_constant) {
unsigned int n = block->length;
int32_t *smp_ptr = block->cur_ptr;
int32_t val = *smp_ptr++;
block->constant = 1;
while (--n > 0) {
if (*smp_ptr++ != val) {
block->constant = 0;
break;
}
}
block->bits_const_block = 0;
if (block->constant) {
block->constant_value = val;
block->bits_const_block += 6; // const_block + reserved
if (block->constant_value) {
block->bits_const_block += ctx->sconf.floating ? 24 :
ctx->avctx->bits_per_raw_sample;
}
}
} else {
block->constant = 0;
}
}
/**
* Test given block samples to share common zero LSBs.
* Set block->shift_lsbs to the number common zero bits.
*/
static void test_zero_lsb(ALSEncContext *ctx, ALSBlock *block)
{
int i;
int32_t common = 0;
block->shift_lsbs = 0;
if (ctx->cur_stage->check_lsbs) {
// test for zero LSBs
for (i = 0; i < (int)block->length; i++) {
common |= block->cur_ptr[i];
if (common & 1)
return;
}
while (!(common & 1)) {
block->shift_lsbs++;
common >>= 1;
}
// generate shifted signal and point block->cur_ptr to the LSB buffer
if (block->shift_lsbs) {
for (i = -ctx->sconf.max_order; i < (int)block->length; i++)
block->lsb_ptr[i] = block->cur_ptr[i] >> block->shift_lsbs;
block->cur_ptr = block->lsb_ptr;
}
}
}
/**
* Generate a weighted residual signal for autocorrelation detection used in
* LTP mode.
*/
static void get_weighted_signal(ALSEncContext *ctx, ALSBlock *block,
int lag_max)
{
int len = (int)block->length;
int32_t *cur_ptr = block->cur_ptr;
uint64_t sum = 0;
double *corr_ptr = ctx->corr_samples;
double mean_quot;
int i;
// determine absolute mean of residual signal,
// including previous samples
for (i = -lag_max; i < len; i++)
sum += abs(cur_ptr[i]);
mean_quot = (double)(sum) / (block->length + lag_max);
// apply weighting:
// x *= 1 / [ sqrt(abs(x)) / 5*sqrt(mean) + 1 ] // XXX: what weighting function is this?
mean_quot = (sqrt(mean_quot) * 5);
for (i = -lag_max-2; i < len; i++)
corr_ptr[i] = cur_ptr[i] / (sqrt(abs(cur_ptr[i])) / mean_quot + 1.0);
}
/**
* Calculate a generic autocorrelation with optional normalization.
* double source data, no windowing, data-lag assumed to be valid pointer.
*/
static void compute_autocorr_norm(const double *data, int len, int lag,
int normalize, double *autoc)
{
int i, j;
for (j = 0; j < lag; j++) {
double sum = 1.0;
for (i = j; i < len; i++)
sum += data[i] * data[i-j];
autoc[j] = sum;
if (normalize)
autoc[j] /= autoc[0];
}
}
/**
* Generate the autocorrelation function and find its positive maximum value to
* be used for LTP lag.
*/
static void find_best_autocorr(ALSEncContext *ctx, ALSBlock *block,
int lag_max, int start)
{
int i, i_max;
double autoc_max;
double autoc[lag_max];
compute_autocorr_norm(ctx->corr_samples, block->length, lag_max, 1, autoc);
autoc_max = autoc[start];
i_max = start;
for (i = start + 1; i < lag_max; i++) {
// find best positive autocorrelation
if (autoc[i] > 0 && autoc[i] > autoc_max) {
autoc_max = autoc[i];
i_max = i;
}
}
block->ltp_info[block->js_block].lag = i_max;
}
/**
* Set fixed values for LTP coefficients.
*/
static void get_ltp_coeffs_fixed(ALSEncContext *ctx, ALSBlock *block)
{
int *ltp_gain = block->ltp_info[block->js_block].gain;
ltp_gain[0] = 8;
ltp_gain[1] = 8;
ltp_gain[2] = 16;
ltp_gain[3] = 8;
ltp_gain[4] = 8;
}
/**
* Calculate LTP coefficients using Cholesky factorization.
*/
static void get_ltp_coeffs_cholesky(ALSEncContext *ctx, ALSBlock *block)
{
int icc, quant;
int smp, i;
int len = (int)block->length;
int taumax = block->ltp_info[block->js_block].lag;
int *ltp_gain = block->ltp_info[block->js_block].gain;
double *corr_ptr = ctx->corr_samples;
double *corr_ptr_lag;
LLSModel m;
double *c = &m.covariance[0][1];
double *coeff = m.coeff[4];
av_init_lls(&m, 5);
corr_ptr_lag = corr_ptr - 2 - taumax;
for (smp = 0; smp < len - 2; smp++)
av_update_lls(&m, corr_ptr_lag++, 1.0);
corr_ptr_lag = corr_ptr - 2 - taumax;
memset(c, 0, 5 * sizeof(*c));
for (smp = 0; smp < len - 2; smp++) {
double v = *corr_ptr++;
c[0] += v * corr_ptr_lag[0];
c[1] += v * corr_ptr_lag[1];
c[2] += v * corr_ptr_lag[2];
c[3] += v * corr_ptr_lag[3];
c[4] += v * corr_ptr_lag[4];
corr_ptr_lag++;
}
av_solve_lls(&m, 0.0, 0);
// quantize coefficients
// 0,1 and 3,4 (linear quantization)
for (icc = 0; icc < 5; icc++) {
int g = lrint(coeff[icc] * 16.0);
if (icc & 1)
ltp_gain[icc] = av_clip(g, -8, 7) * 8;
else
ltp_gain[icc] = av_clip(g, -6, 5) * 8;
}
// 2 (vector quantization, roughly logarithmic)
quant = lrint(coeff[2] * 256.0);
ltp_gain[2] = 0;
for(i = 15; i > 0; i--) {
uint8_t a = ff_als_ltp_gain_values[ i >> 2][ i & 3];
uint8_t b = ff_als_ltp_gain_values[(i-1) >> 2][(i-1) & 3];
if (quant > a + b) {
ltp_gain[2] = a;
return;
}
}
}
/**
* Select the best set of LTP parameters based on maximum autocorrelation
* value of the weighted residual signal.
*/
static void find_block_ltp_params(ALSEncContext *ctx, ALSBlock *block)
{
AVCodecContext *avctx = ctx->avctx;
int start = FFMAX(4, block->opt_order + 1);
int end = FFMIN(ALS_MAX_LTP_LAG, block->length);
int lag = 256 << ( (avctx->sample_rate >= 96000)
+ (avctx->sample_rate >= 192000));
int lag_max;
if (lag + start > end - 3)
lag = end - start - 3;
lag_max = FFMIN(lag + start, end);
if (block->length <= start || lag <= 0 ) {
memset(block->ltp_info[block->js_block].gain, 0, 5 * sizeof(int));
block->ltp_info[block->js_block].lag = start;
return;
}
get_weighted_signal(ctx, block, lag_max);
find_best_autocorr (ctx, block, lag_max, start);
if (ctx->cur_stage->ltp_coeff_algorithm == LTP_COEFF_ALGORITHM_FIXED)
get_ltp_coeffs_fixed(ctx, block);
else
get_ltp_coeffs_cholesky(ctx, block);
}
static void check_ltp(ALSEncContext *ctx, ALSBlock *block, int *bit_count)
{
ALSLTPInfo *ltp = &block->ltp_info[block->js_block];
int bit_count_ltp;
int32_t *save_ptr = block->cur_ptr;
int ltp_lag_length = 8 + (ctx->avctx->sample_rate >= 96000) +
(ctx->avctx->sample_rate >= 192000);
find_block_ltp_params(ctx, block);
gen_ltp_residuals(ctx, block);
// generate bit count for LTP signal
block->cur_ptr = block->ltp_ptr;
ltp->use_ltp = 1;
find_block_entropy_params(ctx, block, block->opt_order);
ltp->bits_ltp = 1 + ltp_lag_length +
rice_count(ltp->gain[0], 1) +
rice_count(ltp->gain[1], 2) +
urice_count(map_to_index(ltp->gain[2]), 2) +
rice_count(ltp->gain[3], 2) +
rice_count(ltp->gain[4], 1);
// test if LTP pays off
bit_count_ltp = block->bits_misc + block->bits_adapt_order +
block->bits_parcor_coeff[block->opt_order] +
block->ent_info[ltp->use_ltp].bits_ec_param_and_res +
ltp->bits_ltp;
bit_count_ltp += (8 - (bit_count_ltp & 7)) & 7;
if (bit_count_ltp < *bit_count) {
*bit_count = bit_count_ltp;
} else {
ltp->use_ltp = 0;
ltp->bits_ltp = 1;
block->cur_ptr = save_ptr;
}
}
static int calc_block_size_fixed_order(ALSEncContext *ctx, ALSBlock *block,
int order)
{
int32_t count;
int32_t *save_ptr = block->cur_ptr;
ALSLTPInfo *ltp = &block->ltp_info[block->js_block];
ALSEntropyInfo *ent = &block->ent_info[ltp->use_ltp];
if (order) {
if (calc_short_term_prediction(ctx, block, order))
return -1;
block->cur_ptr = block->res_ptr;
}
find_block_entropy_params (ctx, block, order);
count = block->bits_misc + block->bits_adapt_order +
block->bits_parcor_coeff[order] + ent->bits_ec_param_and_res;
count += (8 - (count & 7)) & 7; // byte align
#if 0
if (ctx->sconf.long_term_prediction)
check_ltp(ctx, block, &count);
#endif
block->cur_ptr = save_ptr;
return count;
}
static void find_block_adapt_order(ALSEncContext *ctx, ALSBlock *block,
int max_order)
{
int i;
int32_t count[max_order+1];
int best = 0;
int valley_detect = (ctx->cur_stage->adapt_search_algorithm ==
ADAPT_SEARCH_ALGORITHM_VALLEY_DETECT);
int valley_threshold = FFMAX(2, max_order/6);
int exact_count = (ctx->cur_stage->adapt_count_algorithm ==
ADAPT_COUNT_ALGORITHM_EXACT);
count[0] = INT32_MAX;
for (i = 0; i <= max_order; i++) {
if (exact_count) {
count[i] = calc_block_size_fixed_order(ctx, block, i);
} else {
if (i && ctx->parcor_error[i-1] >= 1.0) {
count[i] = block->bits_misc + block->bits_adapt_order +
block->bits_parcor_coeff[i];
count[i] += 0.5 * log2(ctx->parcor_error[i-1]) * block->length;
} else {
count[i] = INT32_MAX;
}
}
if (count[i] >= 0 && count[i] < count[best])
best = i;
else if (valley_detect && (i - best) > valley_threshold)
break;
}
block->opt_order = best;
}
/**
* Encode a given block of a given channel.
* @return number of bits that will be used to encode the block using the
* determined parameters
*/
static int find_block_params(ALSEncContext *ctx, ALSBlock *block)
{
ALSSpecificConfig *sconf = &ctx->sconf;
int bit_count, max_order;
ALSLTPInfo *ltp = &block->ltp_info[block->js_block];
ALSEntropyInfo *ent = &block->ent_info[ltp->use_ltp];
block->cur_ptr = block->js_block ? block->dif_ptr : block->smp_ptr;
block->bits_misc = 1; // block_type
// check for constant block
test_const_value(ctx, block);
// shifting samples:
// determine if all the samples in this block can be right-shifted without
// any information loss
if (!block->constant) {
test_zero_lsb(ctx, block);
block->bits_misc++; // shift_lsbs
if (block->shift_lsbs)
block->bits_misc += 4; // shift_pos
}
block->bits_misc++; // add one bit for block->js_block
// if this is a constant block, we don't need to find any other parameters
if (block->constant)
return block->bits_misc + block->bits_const_block;
// short-term prediction:
// use the mode chosen at encode_init() to find optimal parameters
//
// LPC / PARCOR coefficients to be stored in context
// they depend on js_block and opt_order which may be changing later on
// calculate bits needed to store adaptive LPC order
if (sconf->adapt_order)
block->bits_adapt_order = av_ceil_log2(av_clip((block->length >> 3) - 1,
2, sconf->max_order + 1));
else
block->bits_adapt_order = 0;
max_order = ctx->cur_stage->max_order;
if (sconf->max_order) {
double *corr_ptr;
if (sconf->adapt_order)
max_order = FFMIN(max_order, (1 << block->bits_adapt_order) - 1);
// calculate PARCOR coefficients
corr_ptr = ctx->corr_buffer;
while (corr_ptr < ctx->corr_samples)
*corr_ptr++ = 0.0;
ff_window_apply(&ctx->acf_window[FFMAX(0, block->div_block)],
block->cur_ptr, corr_ptr, block->length);
ctx->dsp.lpc_compute_autocorr(corr_ptr, block->length, max_order,
ctx->acf_coeff);
compute_ref_coefs(ctx->acf_coeff, max_order, ctx->parcor_coeff,
ctx->parcor_error);
// quantize PARCOR coefficients to 7-bit and reconstruct to 21-bit
quantize_parcor_coeffs(ctx, block, ctx->parcor_coeff, max_order);
}
// Determine optimal LPC order:
//
// quick estimate for LPC order. better searches will give better
// significantly better results.
if (sconf->max_order && sconf->adapt_order && ctx->cur_stage->adapt_order) {
find_block_adapt_order(ctx, block, max_order);
} else {
block->opt_order = max_order;
}
// generate residuals using parameters:
if (block->opt_order) {
if (calc_short_term_prediction(ctx, block, block->opt_order)) {
// if PARCOR to LPC conversion has 32-bit integer overflow,
// fallback to using 1st order prediction
double parcor[block->opt_order];
if (ctx->cur_stage->adapt_order)
block->opt_order = 1;
memset(parcor, 0, sizeof(parcor));
parcor[0] = -0.9;
quantize_parcor_coeffs(ctx, block, parcor, block->opt_order);
calc_short_term_prediction(ctx, block, block->opt_order);
}
block->cur_ptr = block->res_ptr;
}
// search for entropy coding (Rice/BGMC) parameters
ltp->use_ltp = 0;
ent = &block->ent_info[ltp->use_ltp];
find_block_entropy_params(ctx, block, block->opt_order);
ltp->bits_ltp = !!sconf->long_term_prediction;
bit_count = block->bits_misc + block->bits_parcor_coeff[block->opt_order] +
ent->bits_ec_param_and_res + ltp->bits_ltp;
bit_count += (8 - (bit_count & 7)) & 7; // byte align
// determine lag and gain values for long-term prediction and
// check if long-term prediction pays off for this block
// and use LTP for this block if it does
if (sconf->long_term_prediction)
check_ltp(ctx, block, &bit_count);
return bit_count;
}
/**
* Generate all possible block sizes for all possible block-switching stages.
*/
static void gen_block_sizes(ALSEncContext *ctx, unsigned int channel, int stage)
{
ALSSpecificConfig *sconf = &ctx->sconf;
ALSBlock *block = ctx->blocks[channel];
unsigned int num_blocks = sconf->block_switching ? (1 << stage) : 1;
uint32_t bs_info_tmp = 0;
unsigned int b;
ctx->num_blocks[channel] = num_blocks;
if (stage) {
for (b = 1; b < num_blocks; b++) {
bs_info_tmp |= (1 << (31 - b));
}
}
set_blocks(ctx, &bs_info_tmp, channel, channel);
for (b = 0; b < num_blocks; b++) {
unsigned int *bs_sizes = ctx->bs_sizes[channel ] + num_blocks - 1;
unsigned int *js_sizes = ctx->js_sizes[channel >> 1] + num_blocks - 1;
// count residuals + block overhead
block->js_block = 0;
bs_sizes[b] = find_block_params(ctx, block);
if (sconf->joint_stereo && !(channel & 1)) {
block->js_block = 1;
js_sizes[b] = find_block_params(ctx, block);
block->js_block = 0;
}
block++;
}
if (sconf->block_switching && stage < sconf->block_switching)
gen_block_sizes(ctx, channel, stage + 1);
else
ctx->bs_info[channel] = bs_info_tmp;
}
/**
* Generate all suitable difference coding infos for all possible
* block-switching stages.
*/
static void gen_js_infos(ALSEncContext *ctx, unsigned int channel, int stage)
{
ALSSpecificConfig *sconf = &ctx->sconf;
unsigned int num_blocks = sconf->block_switching ? (1 << stage) : 1;
unsigned int b;
for (b = 0; b < num_blocks; b++) {
unsigned int *block_size = ctx->bs_sizes[channel ] + num_blocks - 1;
unsigned int *buddy_size = ctx->bs_sizes[channel + 1] + num_blocks - 1;
unsigned int *js_size = ctx->js_sizes[channel >> 1] + num_blocks - 1;
uint8_t *js_info = ctx->js_infos[channel >> 1] + num_blocks - 1;
// replace normal signal with difference signal if suitable
if (js_size[b] < block_size[b] ||
js_size[b] < buddy_size[b]) {
// mark the larger encoded block with the difference signal
// and update this blocks size in bs_sizes
if (block_size[b] > buddy_size[b]) {
js_info[b] = 1;
} else {
js_info[b] = 2;
}
} else {
js_info[b] = 0;
}
}
if (sconf->block_switching && stage < sconf->block_switching)
gen_js_infos(ctx, channel, stage + 1);
}
/**
* Generate the difference signals for each channel pair channel & channel+1.
*/
static void gen_dif_signal(ALSEncContext *ctx, unsigned int channel)
{
unsigned int n;
unsigned int max_order = (ctx->ra_counter != 1) ? ctx->sconf.max_order : 0;
int32_t *c1 = ctx->raw_samples [channel ] - max_order;
int32_t *c2 = ctx->raw_samples [channel + 1] - max_order;
int32_t *d = ctx->raw_dif_samples[channel >> 1] - max_order;
for (n = 0; n < ctx->avctx->frame_size + max_order; n++) {
*d++ = *c2 - *c1;
c1++;
c2++;
}
}
/**
* Choose the appropriate method for difference channel coding for the current
* frame.
*/
static void select_difference_coding_mode(ALSEncContext *ctx)
{
AVCodecContext *avctx = ctx->avctx;
ALSSpecificConfig *sconf = &ctx->sconf;
unsigned int c;
// to be implemented
// depends on sconf->joint_stereo and sconf->mc_coding
// selects either joint_stereo or mcc mode
// sets js_switch (js && mcc) and/or independent_bs
// both parameters to be added to the context...
// until mcc mode is implemented, syntax could be tested
// by using js_switch all the time if mcc is enabled globally
//
// while not implemented, output most simple mode:
// -> 0 if !mcc and while js is not implemented
// -> 1 if mcc (would require js to be implemented and
// correct output of mcc frames/block)
ctx->js_switch = sconf->mc_coding;
c = 0;
// if joint-stereo is enabled, dependently code each channel pair
if (sconf->joint_stereo) {
for (; c < avctx->channels - 1; c += 2) {
ctx->independent_bs[c ] = 0;
ctx->independent_bs[c + 1] = 0;
}
}
// set (the remaining) channels to independent coding
for (; c < avctx->channels; c++)
ctx->independent_bs[c] = 1;
// generate difference signal if needed
if (sconf->joint_stereo) {
for (c = 0; c < avctx->channels - 1; c+=2) {
gen_dif_signal(ctx, c);
}
}
// generate all block sizes for this frame
for (c = 0; c < avctx->channels; c++) {
gen_block_sizes(ctx, c, 0);
}
// select difference signals wherever suitable
if (sconf->joint_stereo) {
for (c = 0; c < avctx->channels - 1; c+=2) {
gen_js_infos(ctx, c, 0);
}
}
}
/**
* Write an ALSSpecificConfig structure.
* @return 0 on success, AVERROR(x) otherwise
*/
static int write_specific_config(AVCodecContext *avctx)
{
ALSEncContext *ctx = avctx->priv_data;
ALSSpecificConfig *sconf = &ctx->sconf;
PutBitContext pb;
MPEG4AudioConfig m4ac;
int config_offset;
unsigned int header_size = 6; // Maximum size of AudioSpecificConfig before ALSSpecificConfig
// determine header size
// crc & aux_data not yet supported
header_size += ALS_SPECIFIC_CFG_SIZE;
header_size += (sconf->chan_config > 0) << 1; // chan_config_info
header_size += avctx->channels << 1; // chan_pos[c]
header_size += (sconf->crc_enabled > 0) << 2; // crc
if (sconf->ra_flag == RA_FLAG_HEADER && sconf->ra_distance > 0) // ra_unit_size
header_size += (sconf->samples / sconf->frame_length + 1) << 2;
if (avctx->extradata)
av_freep(&avctx->extradata);
avctx->extradata = av_mallocz(header_size + FF_INPUT_BUFFER_PADDING_SIZE);
if (!avctx->extradata)
return AVERROR(ENOMEM);
init_put_bits(&pb, avctx->extradata, header_size);
// AudioSpecificConfig, reference to ISO/IEC 14496-3 section 1.6.2.1 & 1.6.3
memset(&m4ac, 0, sizeof(MPEG4AudioConfig));
m4ac.object_type = AOT_ALS;
m4ac.sampling_index = 0x0f;
m4ac.sample_rate = avctx->sample_rate;
m4ac.chan_config = 0;
m4ac.sbr = -1;
config_offset = ff_mpeg4audio_write_config(&m4ac, avctx->extradata,
avctx->extradata_size);
if (config_offset < 0)
return config_offset;
skip_put_bits(&pb, config_offset);
// switch(AudioObjectType) -> case 36: ALSSpecificConfig
// fillBits (align)
align_put_bits(&pb);
put_bits32(&pb, MKBETAG('A', 'L', 'S', '\0'));
put_bits32(&pb, avctx->sample_rate);
put_bits32(&pb, sconf->samples);
put_bits (&pb, 16, avctx->channels - 1);
put_bits (&pb, 3, 0); // original file_type (0 = unknown, 1 = wav, ...)
put_bits (&pb, 3, sconf->resolution);
put_bits (&pb, 1, sconf->floating);
put_bits (&pb, 1, sconf->msb_first); // msb first (0 = LSB, 1 = MSB)
put_bits (&pb, 16, sconf->frame_length - 1);
put_bits (&pb, 8, sconf->ra_distance);
put_bits (&pb, 2, sconf->ra_flag);
put_bits (&pb, 1, sconf->adapt_order);
put_bits (&pb, 2, sconf->coef_table);
put_bits (&pb, 1, sconf->long_term_prediction);
put_bits (&pb, 10, sconf->max_order);
put_bits (&pb, 2, sconf->block_switching ? FFMAX(1, (sconf->block_switching - 2)) : 0);
put_bits (&pb, 1, sconf->bgmc);
put_bits (&pb, 1, sconf->sb_part);
put_bits (&pb, 1, sconf->joint_stereo);
put_bits (&pb, 1, sconf->mc_coding);
put_bits (&pb, 1, sconf->chan_config);
put_bits (&pb, 1, sconf->chan_sort);
put_bits (&pb, 1, sconf->crc_enabled); // crc_enabled
put_bits (&pb, 1, sconf->rlslms);
put_bits (&pb, 5, 0); // reserved bits
put_bits (&pb, 1, 0); // aux_data_enabled (0 = false)
// align
align_put_bits(&pb);
put_bits32(&pb, 0); // original header size
put_bits32(&pb, 0); // original trailer size
if (sconf->crc_enabled)
put_bits32(&pb, ~ctx->crc); // CRC
// writing in local header finished,
// set the real size
avctx->extradata_size = put_bits_count(&pb) >> 3;
return 0;
}
/**
* Encode a single frame.
* @return Overall bit count for the frame
*/
static int encode_frame(AVCodecContext *avctx, uint8_t *frame,
int buf_size, void *data)
{
ALSEncContext *ctx = avctx->priv_data;
ALSSpecificConfig *sconf = &ctx->sconf;
unsigned int b, c;
int frame_data_size;
// determine if this is an RA frame
if (sconf->ra_distance) {
for (c = 0; c < avctx->channels; c++)
ctx->blocks[c][0].ra_block = !ctx->ra_counter;
ctx->ra_counter++;
if (sconf->ra_distance == ctx->ra_counter)
ctx->ra_counter = 0;
}
// update CRC
if (sconf->crc_enabled) {
if (sconf->resolution != 2) {
frame_data_size = ctx->avctx->bits_per_raw_sample >> 3;
ctx->crc = av_crc(ctx->crc_table, ctx->crc, data,
avctx->frame_size * avctx->channels *
frame_data_size);
} else {
int i;
int frame_values = avctx->frame_size * avctx->channels;
int32_t *samples = data;
for (i = 0; i < frame_values; i++) {
int32_t v = *samples++;
if (!HAVE_BIGENDIAN)
v >>= 8;
ctx->crc = av_crc(ctx->crc_table, ctx->crc, (uint8_t *)(&v), 3);
}
}
}
// preprocessing
deinterleave_raw_samples(ctx, data);
// find optimal encoding parameters
SET_OPTIONS(STAGE_JOINT_STEREO)
select_difference_coding_mode(ctx);
SET_OPTIONS(STAGE_BLOCK_SWITCHING);
block_partitioning(ctx);
SET_OPTIONS(STAGE_FINAL);
if (!sconf->mc_coding || ctx->js_switch) {
for (b = 0; b < ALS_MAX_BLOCKS; b++) {
for (c = 0; c < avctx->channels; c++) {
if (b >= ctx->num_blocks[c])
continue;
if (ctx->independent_bs[c]) {
find_block_params(ctx, &ctx->blocks[c][b]);
} else {
find_block_params(ctx, &ctx->blocks[c ][b]);
find_block_params(ctx, &ctx->blocks[c + 1][b]);
c++;
}
}
}
} else {
// MCC: to be implemented
}
// bitstream assembly
frame_data_size = write_frame(ctx, frame, buf_size);
if (frame_data_size < 0)
av_log(avctx, AV_LOG_ERROR, "Error writing frame\n");
// update sample count
if (frame_data_size >= 0)
sconf->samples += avctx->frame_size;
// store previous samples
for (c = 0; c < avctx->channels; c++) {
memcpy(ctx->raw_samples[c] - sconf->max_order,
ctx->raw_samples[c] + avctx->frame_size - sconf->max_order,
sizeof(*ctx->raw_samples[c]) * sconf->max_order);
}
return frame_data_size;
}
/**
* Encode all frames of a random access unit.
* @return Overall bit count read, AVERROR(x) otherwise
*/
static int encode_ra_unit(AVCodecContext *avctx, uint8_t *frame,
int buf_size, void *data)
{
#define COPY_FRAME_BUFFER(size) { \
if (size <= buf_size) { \
memcpy(frame, ctx->frame_buffer, size); \
} else { \
av_log(avctx, AV_LOG_ERROR, "Output buffer too small.\n"); \
return AVERROR(ENOMEM); \
} \
}
ALSEncContext *ctx = avctx->priv_data;
ALSSpecificConfig *sconf = &ctx->sconf;
unsigned int encoded;
if (!data) {
int ret;
// write remaining samples from the frame buffer
if (sconf->ra_distance > 1 && ctx->cur_frame != ctx->frame_buffer) {
encoded = ctx->cur_frame - ctx->frame_buffer;
COPY_FRAME_BUFFER(encoded);
avctx->coded_frame->pts = sconf->samples;
ctx->cur_frame = ctx->frame_buffer;
} else {
encoded = 0;
}
// last frame has been encoded,
// rewrite AudioSpecificConfig & ALSSpecificConfig to extradata
ret = write_specific_config(avctx);
if (ret) {
av_log(avctx, AV_LOG_ERROR, "Rewriting of extradata failed.\n");
return ret;
}
return encoded;
}
// no need to take special care of always/never using ra-frames
// just encode frame-by-frame
if (sconf->ra_distance < 2)
return encode_frame(avctx, frame, buf_size, data);
encoded = ctx->cur_frame - ctx->frame_buffer;
ctx->cur_frame += encode_frame(avctx, ctx->cur_frame,
ctx->frame_buffer_size - encoded, data);
if (ctx->ra_counter + 1 == sconf->ra_distance ||
avctx->frame_size != sconf->frame_length) {
encoded = ctx->cur_frame - ctx->frame_buffer;
COPY_FRAME_BUFFER(encoded);
avctx->coded_frame->pts = sconf->samples;
ctx->cur_frame = ctx->frame_buffer;
return encoded;
} else {
return 0;
}
}
/**
* Rearrange internal order of channels to optimize joint-channel coding.
*/
static void channel_sorting(ALSEncContext *ctx)
{
// to be implemented...
// just arrange ctx->raw_samples array
// according to specific channel order
}
/**
* Determine the number of samples in each frame, which is constant for all
* frames in the stream except the very last one which may be smaller.
*/
static void frame_partitioning(ALSEncContext *ctx)
{
AVCodecContext *avctx = ctx->avctx;
ALSSpecificConfig *sconf = &ctx->sconf;
// choose default frame size if not specified by the user
if (avctx->frame_size <= 0) {
if (avctx->sample_rate <= 24000)
avctx->frame_size = 1024;
else if(avctx->sample_rate <= 48000)
avctx->frame_size = 2048;
else if(avctx->sample_rate <= 96000)
avctx->frame_size = 4096;
else
avctx->frame_size = 8192;
// increase frame size if block switching is used
if (sconf->block_switching)
avctx->frame_size <<= sconf->block_switching >> 1;
}
// ensure a certain boundary for the frame size
// frame length - 1 in ALSSpecificConfig is 16-bit, so max value is 65536
// frame size == 1 is not allowed because it is used in ffmpeg as a
// special-case value to indicate PCM audio
avctx->frame_size = av_clip(avctx->frame_size, 2, 65536);
sconf->frame_length = avctx->frame_size;
// determine distance between ra-frames. 0 = no ra, 1 = all ra
// defaults to 10s intervals for random access
sconf->ra_distance = avctx->gop_size;
/* There is an API issue where the required output audio buffer size cannot
be known to the user, and the default buffer size in ffmpeg.c is too
small to consistently fit more than about 7 frames. Once this issue
is resolved, the maximum value can be changed from 7 to 255. */
sconf->ra_distance = av_clip(sconf->ra_distance, 0, 7);
}
/**
* Determine the ALSSpecificConfig structure used to encode.
* @return 0 on success, -1 otherwise
*/
static av_cold int get_specific_config(AVCodecContext *avctx)
{
ALSEncContext *ctx = avctx->priv_data;
ALSSpecificConfig *sconf = &ctx->sconf;
// set default compression level and clip to allowed range
if (avctx->compression_level == FF_COMPRESSION_DEFAULT)
avctx->compression_level = 1;
else
avctx->compression_level = av_clip(avctx->compression_level, 0, 2);
// set compression level defaults
*sconf = *spc_config_settings[avctx->compression_level];
// total number of samples unknown
sconf->samples = 0xFFFFFFFF;
// determine sample format
switch (avctx->sample_fmt) {
case SAMPLE_FMT_U8:
sconf->resolution = 0; break;
case SAMPLE_FMT_S16:
sconf->resolution = 1; break;
case SAMPLE_FMT_FLT:
sconf->floating = 1;
av_log_missing_feature(avctx, "floating-point samples\n", 0);
case SAMPLE_FMT_S32:
if (avctx->bits_per_raw_sample <= 24)
sconf->resolution = 2;
else
sconf->resolution = 3;
break;
default:
av_log(avctx, AV_LOG_ERROR, "unsupported sample format: %s\n",
avcodec_get_sample_fmt_name(avctx->sample_fmt));
return -1;
}
if (!avctx->bits_per_raw_sample)
avctx->bits_per_raw_sample = (sconf->resolution + 1) << 3;
ctx->max_rice_param = sconf->resolution > 1 ? 31 : 15;
// user-override for block switching using AVCodecContext.max_partition_order
if (avctx->max_partition_order >= 0) {
sconf->block_switching = FFMIN(5, avctx->max_partition_order);
}
// determine frame length
frame_partitioning(ctx);
// limit the block_switching depth based on whether the full frame length
// is evenly divisible by the minimum block size.
while (sconf->block_switching > 0 &&
sconf->frame_length % (1 << sconf->block_switching)) {
sconf->block_switching--;
}
// determine where to store ra_flag (01: beginning of frame_data)
// default for now = RA_FLAG_NONE.
// Using RA_FLAG_FRAMES would make decoding more robust in case of seeking
// with raw ALS. However, raw ALS is not supported in FFmpeg yet.
sconf->ra_flag = RA_FLAG_NONE;
// determine the coef_table to be used
sconf->coef_table = (avctx->sample_rate > 48000) +
(avctx->sample_rate > 96000);
// user-specified maximum prediction order
if (avctx->max_prediction_order >= 0)
sconf->max_order = av_clip(avctx->max_prediction_order, 0, 1023);
// user-specified use of BGMC entropy coding mode
if (avctx->coder_type == FF_CODER_TYPE_AC)
sconf->bgmc = 1;
// determine manual channel configuration
// using avctx->channel_layout
// to be implemented
sconf->chan_config = 0;
sconf->chan_config_info = 0;
// determine channel sorting
// using avctx->channel_layout
// to be implemented
sconf->chan_sort = 0;
sconf->chan_pos = NULL;
// Use native-endian sample byte order.
// We don't really know the original byte order, so this is only done to
// speed up the CRC calculation.
#if HAVE_BIGENDIAN
sconf->msb_first = 1;
#else
sconf->msb_first = 0;
#endif
// print ALSSpecificConfig info
ff_als_dprint_specific_config(avctx, sconf);
return 0;
}
static av_cold int encode_end(AVCodecContext *avctx)
{
int b;
ALSEncContext *ctx = avctx->priv_data;
av_freep(&ctx->stages);
av_freep(&ctx->independent_bs);
av_freep(&ctx->raw_buffer);
av_freep(&ctx->raw_samples);
av_freep(&ctx->raw_dif_buffer);
av_freep(&ctx->raw_dif_samples);
av_freep(&ctx->raw_lsb_buffer);
av_freep(&ctx->raw_lsb_samples);
av_freep(&ctx->res_buffer);
av_freep(&ctx->res_samples);
av_freep(&ctx->block_buffer);
av_freep(&ctx->blocks);
av_freep(&ctx->bs_info);
av_freep(&ctx->num_blocks);
av_freep(&ctx->bs_sizes_buffer);
av_freep(&ctx->bs_sizes);
av_freep(&ctx->js_sizes_buffer);
av_freep(&ctx->js_sizes);
av_freep(&ctx->js_infos_buffer);
av_freep(&ctx->js_infos);
av_freep(&ctx->q_parcor_coeff_buffer);
av_freep(&ctx->acf_coeff);
av_freep(&ctx->parcor_coeff);
av_freep(&ctx->r_parcor_coeff);
av_freep(&ctx->lpc_coeff);
av_freep(&ctx->parcor_error);
av_freep(&ctx->ltp_buffer);
av_freep(&ctx->ltp_samples);
av_freep(&ctx->corr_buffer);
av_freep(&ctx->frame_buffer);
if (ctx->sconf.max_order) {
for (b = 0; b < 6; b++)
ff_window_close(&ctx->acf_window[b]);
}
av_freep(&avctx->extradata);
avctx->extradata_size = 0;
av_freep(&avctx->coded_frame);
return 0;
}
static av_cold int encode_init(AVCodecContext *avctx)
{
ALSEncContext *ctx = avctx->priv_data;
ALSSpecificConfig *sconf = &ctx->sconf;
unsigned int channel_size, channel_offset;
int ret, b, c;
int num_bs_sizes;
ctx->avctx = avctx;
// determine ALSSpecificConfig
if (get_specific_config(avctx))
return -1;
// write AudioSpecificConfig & ALSSpecificConfig to extradata
ret = write_specific_config(avctx);
if (ret) {
av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n");
encode_end(avctx);
return AVERROR(ENOMEM);
}
// initialize sample count
sconf->samples = 0;
channel_offset = sconf->long_term_prediction ? ALS_MAX_LTP_LAG : sconf->max_order;
if (channel_offset & 3)
channel_offset = (channel_offset & ~3) + 4;
channel_size = sconf->frame_length + channel_offset;
if (channel_size & 3)
channel_size = (channel_size & ~3) + 4;
// set up stage options
AV_PMALLOC(ctx->stages, NUM_STAGES);
if (!ctx->stages) {
av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n");
encode_end(avctx);
return AVERROR(ENOMEM);
}
// fill stage options based on compression level
ctx->stages[STAGE_JOINT_STEREO] = *stage_js_settings[avctx->compression_level];
ctx->stages[STAGE_BLOCK_SWITCHING] = *stage_bs_settings[avctx->compression_level];
ctx->stages[STAGE_FINAL] = *stage_final_settings[avctx->compression_level];
// joint-stereo stage sconf overrides
ctx->stages[STAGE_JOINT_STEREO].adapt_order = sconf->adapt_order;
ctx->stages[STAGE_JOINT_STEREO].sb_part = sconf->sb_part;
if (avctx->compression_level > 1)
ctx->stages[STAGE_JOINT_STEREO].max_order = sconf->max_order;
else
ctx->stages[STAGE_JOINT_STEREO].max_order = FFMIN(sconf->max_order,
ctx->stages[STAGE_JOINT_STEREO].max_order);
// block switching stage sconf overrides
ctx->stages[STAGE_BLOCK_SWITCHING].adapt_order = sconf->adapt_order;
ctx->stages[STAGE_BLOCK_SWITCHING].sb_part = sconf->sb_part;
if (avctx->compression_level > 0)
ctx->stages[STAGE_BLOCK_SWITCHING].max_order = sconf->max_order;
else
ctx->stages[STAGE_BLOCK_SWITCHING].max_order = FFMIN(sconf->max_order,
ctx->stages[STAGE_BLOCK_SWITCHING].max_order);
// final stage sconf overrides
ctx->stages[STAGE_FINAL].adapt_order = sconf->adapt_order;
ctx->stages[STAGE_FINAL].sb_part = sconf->sb_part;
ctx->stages[STAGE_FINAL].max_order = sconf->max_order;
if (sconf->bgmc && avctx->compression_level < 2) {
ctx->stages[STAGE_FINAL].ecsub_algorithm = EC_SUB_ALGORITHM_RICE_ESTIMATE;
ctx->stages[STAGE_FINAL].param_algorithm = EC_PARAM_ALGORITHM_BGMC_ESTIMATE;
}
// debug print stage options
dprintf(avctx, "\n");
if (sconf->joint_stereo) {
dprintf(avctx, "Joint-Stereo:\n");
dprint_stage_options(avctx, &ctx->stages[STAGE_JOINT_STEREO]);
} else {
dprintf(avctx, "Joint-Stereo: N/A\n");
}
dprintf(avctx, "\n");
if (sconf->block_switching) {
dprintf(avctx, "Block-Switching:\n");
dprint_stage_options(avctx, &ctx->stages[STAGE_BLOCK_SWITCHING]);
} else {
dprintf(avctx, "Block-Switching: N/A\n");
}
dprintf(avctx, "\n");
dprintf(avctx, "Final:\n");
dprint_stage_options(avctx, &ctx->stages[STAGE_FINAL]);
dprintf(avctx, "\n");
// set cur_stage pointer to the first stage
ctx->cur_stage = ctx->stages;
// allocate buffers
AV_PMALLOC (ctx->independent_bs, avctx->channels);
AV_PMALLOCZ(ctx->raw_buffer, avctx->channels * channel_size);
AV_PMALLOC (ctx->raw_samples, avctx->channels);
AV_PMALLOCZ(ctx->raw_dif_buffer, (avctx->channels >> 1) * channel_size);
AV_PMALLOC (ctx->raw_dif_samples, (avctx->channels >> 1));
AV_PMALLOCZ(ctx->raw_lsb_buffer, (avctx->channels) * channel_size);
AV_PMALLOC (ctx->raw_lsb_samples, (avctx->channels));
AV_PMALLOCZ(ctx->res_buffer, avctx->channels * channel_size);
AV_PMALLOC (ctx->res_samples, avctx->channels);
AV_PMALLOC (ctx->num_blocks, avctx->channels);
AV_PMALLOC (ctx->bs_info, avctx->channels);
AV_PMALLOCZ(ctx->block_buffer, avctx->channels * ALS_MAX_BLOCKS);
AV_PMALLOC (ctx->blocks, avctx->channels);
// check buffers
if (!ctx->independent_bs ||
!ctx->raw_buffer || !ctx->raw_samples ||
!ctx->raw_dif_buffer || !ctx->raw_dif_samples ||
!ctx->raw_lsb_buffer || !ctx->raw_lsb_samples ||
!ctx->res_buffer || !ctx->res_samples ||
!ctx->num_blocks || !ctx->bs_info ||
!ctx->block_buffer || !ctx->blocks) {
av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n");
encode_end(avctx);
return AVERROR(ENOMEM);
}
ctx->blocks[0] = ctx->block_buffer;
for (c = 1; c < avctx->channels; c++)
ctx->blocks[c] = ctx->blocks[c - 1] + 32;
// allocate short-term prediction coefficient buffers
if (sconf->max_order) {
AV_PMALLOC (ctx->q_parcor_coeff_buffer, avctx->channels * ALS_MAX_BLOCKS * sconf->max_order);
AV_PMALLOC (ctx->acf_coeff, (sconf->max_order + 1));
AV_PMALLOC (ctx->parcor_coeff, sconf->max_order);
AV_PMALLOC (ctx->lpc_coeff, sconf->max_order);
AV_PMALLOC (ctx->parcor_error, sconf->max_order);
AV_PMALLOC (ctx->r_parcor_coeff, sconf->max_order);
if (!ctx->q_parcor_coeff_buffer || !ctx->acf_coeff ||
!ctx->parcor_coeff || !ctx->lpc_coeff ||
!ctx->parcor_error || !ctx->r_parcor_coeff) {
av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n");
encode_end(avctx);
return AVERROR(ENOMEM);
}
ctx->blocks[0][0].q_parcor_coeff = ctx->q_parcor_coeff_buffer;
for (c = 0; c < avctx->channels; c++) {
for (b = 0; b < ALS_MAX_BLOCKS; b++) {
if (b)
ctx->blocks[c][b].q_parcor_coeff = ctx->blocks[c][b-1].q_parcor_coeff + sconf->max_order;
else if (c)
ctx->blocks[c][b].q_parcor_coeff = ctx->blocks[c-1][0].q_parcor_coeff + ALS_MAX_BLOCKS * sconf->max_order;
}
}
}
// allocate long-term prediction buffers
if (sconf->long_term_prediction) {
AV_PMALLOC(ctx->ltp_buffer, avctx->channels * channel_size);
AV_PMALLOC(ctx->ltp_samples, avctx->channels);
if (!ctx->ltp_buffer || !ctx->ltp_samples) {
av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n");
encode_end(avctx);
return AVERROR(ENOMEM);
}
// assign ltp buffer pointers
ctx->ltp_samples[0] = ctx->ltp_buffer + channel_offset;
for (c = 1; c < avctx->channels; c++)
ctx->ltp_samples[c] = ctx->ltp_samples[c - 1] + channel_size;
}
// allocate autocorrelation buffers (used for short-term and long-term prediction)
if (sconf->long_term_prediction || sconf->max_order) {
int corr_pad = FFMIN(ALS_MAX_LTP_LAG, sconf->frame_length);
corr_pad = FFMAX(corr_pad, sconf->max_order + 1);
if (corr_pad & 1)
corr_pad++;
AV_PMALLOCZ(ctx->corr_buffer, sconf->frame_length + 1 + corr_pad);
if (!ctx->corr_buffer) {
av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n");
encode_end(avctx);
return AVERROR(ENOMEM);
}
ctx->corr_samples = ctx->corr_buffer + corr_pad;
}
// assign buffer pointers
ctx->raw_samples [0] = ctx->raw_buffer + channel_offset;
ctx->raw_dif_samples[0] = ctx->raw_dif_buffer + channel_offset;
ctx->raw_lsb_samples[0] = ctx->raw_lsb_buffer + channel_offset;
ctx->res_samples [0] = ctx->res_buffer + channel_offset;
for (c = 1; c < avctx->channels; c++) {
ctx->raw_samples [c] = ctx->raw_samples[c - 1] + channel_size;
ctx->res_samples [c] = ctx->res_samples[c - 1] + channel_size;
ctx->raw_lsb_samples[c] = ctx->raw_lsb_samples[c - 1] + channel_size;
}
for (c = 1; c < (avctx->channels >> 1); c++) {
ctx->raw_dif_samples[c] = ctx->raw_dif_samples[c - 1] + channel_size;
}
// channel sorting
if ((sconf->joint_stereo || sconf->mc_coding) && sconf->chan_sort)
channel_sorting(ctx);
// allocate block-switching and joint-stereo buffers
num_bs_sizes = (2 << sconf->block_switching) - 1;
AV_PMALLOC(ctx->bs_sizes_buffer, num_bs_sizes * avctx->channels);
AV_PMALLOC(ctx->bs_sizes, num_bs_sizes * avctx->channels);
AV_PMALLOC(ctx->js_sizes_buffer, num_bs_sizes * ((avctx->channels + 1) >> 1));
AV_PMALLOC(ctx->js_sizes, num_bs_sizes * avctx->channels);
AV_PMALLOC(ctx->js_infos_buffer, num_bs_sizes * ((avctx->channels + 1) >> 1));
AV_PMALLOC(ctx->js_infos, num_bs_sizes * avctx->channels);
if (!ctx->bs_sizes || !ctx->bs_sizes_buffer ||
!ctx->js_sizes || !ctx->js_sizes_buffer ||
!ctx->js_infos || !ctx->js_infos_buffer) {
av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n");
encode_end(avctx);
return AVERROR(ENOMEM);
}
// assign buffer pointers for block-switching and joint-stereo
for (c = 0; c < avctx->channels; c++) {
ctx->bs_sizes[c] = ctx->bs_sizes_buffer + c * num_bs_sizes;
}
for (c = 0; c < avctx->channels - 1; c += 2) {
ctx->js_sizes[c ] = ctx->js_sizes_buffer + (c ) * num_bs_sizes;
ctx->js_sizes[c + 1] = ctx->js_sizes_buffer + (c + 1) * num_bs_sizes;
ctx->js_infos[c ] = ctx->js_infos_buffer + (c ) * num_bs_sizes;
ctx->js_infos[c + 1] = ctx->js_infos_buffer + (c + 1) * num_bs_sizes;
}
// allocate coded_frame
avctx->coded_frame = avcodec_alloc_frame();
if (!avctx->coded_frame) {
av_log(avctx, AV_LOG_ERROR, "Allocating coded_frame memory failed.\n");
encode_end(avctx);
return AVERROR(ENOMEM);
}
// initialize DSPContext
dsputil_init(&ctx->dsp, avctx);
// initialize autocorrelation window for each block size
if (sconf->max_order) {
for (b = 0; b <= sconf->block_switching; b++) {
int block_length = sconf->frame_length / (1 << b);
if (block_length & 1)
block_length++;
if (avctx->sample_rate <= 48000)
ff_window_init(&ctx->acf_window[b], WINDOW_TYPE_SINERECT, block_length, 4.0);
else
ff_window_init(&ctx->acf_window[b], WINDOW_TYPE_HANNRECT, block_length, 4.0);
if (!sconf->block_switching)
break;
}
}
// initialize CRC calculation
if (sconf->crc_enabled) {
ctx->crc_table = av_crc_get_table(AV_CRC_32_IEEE_LE);
ctx->crc = 0xFFFFFFFF;
}
// allocate local frame buffer if necessary
if (sconf->ra_distance > 1) {
// TODO: use realloc() to increase buffer size if necessary
ctx->frame_buffer_size = sconf->ra_distance * sconf->frame_length *
(avctx->channels * avctx->bits_per_raw_sample / 8) *
5 / 4 + 1024;
AV_PMALLOC(ctx->frame_buffer, ctx->frame_buffer_size);
if (!ctx->frame_buffer) {
av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n");
encode_end(avctx);
return AVERROR(ENOMEM);
}
ctx->cur_frame = ctx->frame_buffer;
}
return 0;
}
AVCodec als_encoder = {
"als",
CODEC_TYPE_AUDIO,
CODEC_ID_MP4ALS,
sizeof(ALSEncContext),
encode_init,
encode_ra_unit,
encode_end,
NULL,
.capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY,
.long_name = NULL_IF_CONFIG_SMALL("MPEG-4 Audio Lossless Coding (ALS)"),
.sample_fmts = (const enum SampleFormat[]){ SAMPLE_FMT_U8, SAMPLE_FMT_S16,
SAMPLE_FMT_S32, SAMPLE_FMT_NONE },
};