/**
* MLP encoder
* Copyright (c) 2008 Ramiro Polla
+ * Copyright (c) 2016-2019 Jai Luthra
*
* This file is part of FFmpeg.
*
} DecodingParams;
typedef struct BestOffset {
- int16_t offset;
+ int32_t offset;
int bitcount;
int lsb_bits;
- int16_t min;
- int16_t max;
+ int32_t min;
+ int32_t max;
} BestOffset;
-#define HUFF_OFFSET_MIN -16384
-#define HUFF_OFFSET_MAX 16383
+#define HUFF_OFFSET_MIN (-16384)
+#define HUFF_OFFSET_MAX ( 16383)
/** Number of possible codebooks (counting "no codebooks") */
#define NUM_CODEBOOKS 4
*/
static int inline number_sbits(int number)
{
- if (number < 0)
+ if (number < -1)
number++;
return av_log2(FFABS(number)) + 1 + !!number;
av_log(avctx, AV_LOG_ERROR, "Unsupported sample rate %d. Supported "
"sample rates are 44100, 88200, 176400, 48000, "
"96000, and 192000.\n", avctx->sample_rate);
- return -1;
+ return AVERROR(EINVAL);
}
ctx->coded_sample_rate[1] = -1 & 0xf;
default:
av_log(avctx, AV_LOG_ERROR, "Sample format not supported. "
"Only 16- and 24-bit samples are supported.\n");
- return -1;
+ return AVERROR(EINVAL);
}
ctx->coded_sample_fmt[1] = -1 & 0xf;
ctx->channel_arrangement = 12; break;
default:
av_log(avctx, AV_LOG_ERROR, "Unsupported channel arrangement\n");
- return -1;
+ return AVERROR(EINVAL);
}
ctx->flags = FLAGS_DVDA;
ctx->channel_occupancy = ff_mlp_ch_info[ctx->channel_arrangement].channel_occupancy;
break;
default:
av_log(avctx, AV_LOG_ERROR, "Unsupported channel arrangement\n");
- return -1;
+ return AVERROR(EINVAL);
}
ctx->flags = 0;
ctx->channel_occupancy = 0;
static void write_restart_header(MLPEncodeContext *ctx, PutBitContext *pb)
{
RestartHeader *rh = ctx->cur_restart_header;
- int32_t lossless_check = xor_32_to_8(rh->lossless_check_data);
+ uint8_t lossless_check = xor_32_to_8(rh->lossless_check_data);
unsigned int start_count = put_bits_count(pb);
PutBitContext tmpb;
uint8_t checksum;
put_bits(pb, 1, 0);
}
}
+ if (cp->codebook > 0 && cp->huff_lsbs > 24) {
+ av_log(ctx->avctx, AV_LOG_ERROR, "Invalid Huff LSBs\n");
+ }
put_bits(pb, 2, cp->codebook );
put_bits(pb, 5, cp->huff_lsbs);
codebook_index [ch] = cp->codebook - 1;
sign_huff_offset[ch] = cp->huff_offset;
- sign_shift = lsb_bits[ch] - 1;
+ sign_shift = lsb_bits[ch] + (cp->codebook ? 2 - cp->codebook : -1);
- if (cp->codebook > 0) {
+ if (cp->codebook > 0)
sign_huff_offset[ch] -= 7 << lsb_bits[ch];
- sign_shift += 3 - cp->codebook;
- }
/* Unsign if needed. */
if (sign_shift >= 0)
for (i = 0; i < dp->blocksize; i++) {
for (ch = rh->min_channel; ch <= rh->max_channel; ch++) {
int32_t sample = *sample_buffer++ >> dp->quant_step_size[ch];
-
sample -= sign_huff_offset[ch];
if (codebook_index[ch] >= 0) {
RestartHeader *rh = &ctx->restart_header [substr];
int substr_restart_frame = restart_frame;
uint8_t parity, checksum;
- PutBitContext pb, tmpb;
+ PutBitContext pb;
int params_changed;
ctx->cur_restart_header = rh;
put_bits(&pb, 32, END_OF_STREAM);
}
- /* Data must be flushed for the checksum and parity to be correct. */
- tmpb = pb;
- flush_put_bits(&tmpb);
+ /* Data must be flushed for the checksum and parity to be correct;
+ * notice that we already are word-aligned here. */
+ flush_put_bits(&pb);
- parity = ff_mlp_calculate_parity(buf, put_bits_count(&pb) >> 3) ^ 0xa9;
- checksum = ff_mlp_checksum8 (buf, put_bits_count(&pb) >> 3);
+ parity = ff_mlp_calculate_parity(buf, put_bytes_output(&pb)) ^ 0xa9;
+ checksum = ff_mlp_checksum8 (buf, put_bytes_output(&pb));
put_bits(&pb, 8, parity );
put_bits(&pb, 8, checksum);
flush_put_bits(&pb);
- end += put_bits_count(&pb) >> 3;
+ end += put_bytes_output(&pb);
substream_data_len[substr] = end;
- buf += put_bits_count(&pb) >> 3;
+ buf += put_bytes_output(&pb);
}
ctx->major_cur_subblock_index += ctx->major_filter_state_subblock + 1;
int total_length;
if (buf_size < 4)
- return -1;
+ return AVERROR(EINVAL);
/* Frame header will be written at the end. */
buf += 4;
if (restart_frame) {
if (buf_size < 28)
- return -1;
+ return AVERROR(EINVAL);
write_major_sync(ctx, buf, buf_size);
buf += 28;
buf_size -= 28;
uint32_t abs_sample;
int32_t sample;
- sample = is24 ? *samples_32++ >> 8 : *samples_16++ << 8;
+ sample = is24 ? *samples_32++ >> 8 : *samples_16++ * 256;
/* TODO Find out if number_sbits can be used for negative values. */
abs_sample = FFABS(sample);
BestOffset *bo)
{
DecodingParams *dp = ctx->cur_decoding_params;
- int32_t unsign;
+ int32_t unsign = 0;
int lsb_bits;
min -= offset;
lsb_bits += !!lsb_bits;
- unsign = 1 << (lsb_bits - 1);
+ if (lsb_bits > 0)
+ unsign = 1 << (lsb_bits - 1);
bo->offset = offset;
bo->lsb_bits = lsb_bits;
{
DecodingParams *dp = ctx->cur_decoding_params;
int16_t offset;
- int32_t unsign;
+ int32_t unsign = 0;
uint32_t diff;
int lsb_bits;
lsb_bits = number_sbits(diff) - 1;
- unsign = 1 << (lsb_bits - 1);
+ if (lsb_bits > 0)
+ unsign = 1 << (lsb_bits - 1);
/* If all samples are the same (lsb_bits == 0), offset must be
* adjusted because of sign_shift. */
offset_min = FFMAX(min, HUFF_OFFSET_MIN);
offset_max = FFMIN(max, HUFF_OFFSET_MAX);
- for (;;) {
+ while (offset <= offset_max && offset >= offset_min) {
BestOffset temp_bo;
codebook_bits_offset(ctx, channel, codebook,
if (direction) {
offset = temp_bo.max + 1;
- if (offset > offset_max)
- break;
} else {
offset = temp_bo.min - 1;
- if (offset < offset_min)
- break;
}
}
}
#define SAMPLE_MAX(bitdepth) ((1 << (bitdepth - 1)) - 1)
#define SAMPLE_MIN(bitdepth) (~SAMPLE_MAX(bitdepth))
-#define MSB_MASK(bits) (-1u << bits)
+#define MSB_MASK(bits) (-(int)(1u << (bits)))
/** Applies the filter to the current samples, and saves the residual back
* into the samples buffer. If the filter is too bad and overflows the
- * maximum amount of bits allowed (16 or 24), the samples buffer is left as is and
+ * maximum amount of bits allowed (24), the samples buffer is left as is and
* the function returns -1.
*/
static int apply_filter(MLPEncodeContext *ctx, unsigned int channel)
{
FilterParams *fp[NUM_FILTERS] = { &ctx->cur_channel_params[channel].filter_params[FIR],
&ctx->cur_channel_params[channel].filter_params[IIR], };
- int32_t *filter_state_buffer[NUM_FILTERS];
+ int32_t *filter_state_buffer[NUM_FILTERS] = { NULL };
int32_t mask = MSB_MASK(ctx->cur_decoding_params->quant_step_size[channel]);
int32_t *sample_buffer = ctx->sample_buffer + channel;
unsigned int number_of_samples = ctx->number_of_samples;
unsigned int filter_shift = fp[FIR]->shift;
int filter;
- int i;
+ int i, ret = 0;
for (i = 0; i < NUM_FILTERS; i++) {
unsigned int size = ctx->number_of_samples;
if (!filter_state_buffer[i]) {
av_log(ctx->avctx, AV_LOG_ERROR,
"Not enough memory for applying filters.\n");
- return -1;
+ ret = AVERROR(ENOMEM);
+ goto free_and_return;
}
}
int32_t sample = *sample_buffer;
unsigned int order;
int64_t accum = 0;
- int32_t residual;
+ int64_t residual;
for (filter = 0; filter < NUM_FILTERS; filter++) {
int32_t *fcoeff = ctx->cur_channel_params[channel].coeff[filter];
accum >>= filter_shift;
residual = sample - (accum & mask);
- if (residual < SAMPLE_MIN(ctx->wordlength) || residual > SAMPLE_MAX(ctx->wordlength))
- return -1;
+ if (residual < SAMPLE_MIN(24) || residual > SAMPLE_MAX(24)) {
+ ret = AVERROR_INVALIDDATA;
+ goto free_and_return;
+ }
filter_state_buffer[FIR][i] = sample;
- filter_state_buffer[IIR][i] = residual;
+ filter_state_buffer[IIR][i] = (int32_t) residual;
sample_buffer += ctx->num_channels;
}
sample_buffer += ctx->num_channels;
}
+free_and_return:
for (i = 0; i < NUM_FILTERS; i++) {
av_freep(&filter_state_buffer[i]);
}
- return 0;
+ return ret;
}
static void apply_filters(MLPEncodeContext *ctx)
for (i = 0; i < ctx->number_of_samples; i++) {
uint16_t seed_shr7 = seed >> 7;
- *sample_buffer++ = ((int8_t)(seed >> 15)) << rh->noise_shift;
- *sample_buffer++ = ((int8_t) seed_shr7) << rh->noise_shift;
+ *sample_buffer++ = ((int8_t)(seed >> 15)) * (1 << rh->noise_shift);
+ *sample_buffer++ = ((int8_t) seed_shr7) * (1 << rh->noise_shift);
seed = (seed << 16) ^ seed_shr7 ^ (seed_shr7 << 5);
****************************************************************************/
typedef struct {
- char path[MAJOR_HEADER_INTERVAL + 3];
+ char path[MAJOR_HEADER_INTERVAL + 2];
+ int cur_idx;
int bitcount;
} PathCounter;
-static const char *path_counter_codebook[] = { "0", "1", "2", "3", };
-
-#define ZERO_PATH '0'
#define CODEBOOK_CHANGE_BITS 21
static void clear_path_counter(PathCounter *path_counter)
{
- unsigned int i;
-
- for (i = 0; i < NUM_CODEBOOKS + 1; i++) {
- path_counter[i].path[0] = ZERO_PATH;
- path_counter[i].path[1] = 0x00;
- path_counter[i].bitcount = 0;
- }
+ memset(path_counter, 0, (NUM_CODEBOOKS + 1) * sizeof(*path_counter));
}
static int compare_best_offset(BestOffset *prev, BestOffset *cur)
static int best_codebook_path_cost(MLPEncodeContext *ctx, unsigned int channel,
PathCounter *src, int cur_codebook)
{
- BestOffset *cur_bo, *prev_bo = restart_best_offset;
+ int idx = src->cur_idx;
+ BestOffset *cur_bo = ctx->best_offset[idx][channel],
+ *prev_bo = idx ? ctx->best_offset[idx - 1][channel] : restart_best_offset;
int bitcount = src->bitcount;
- char *path = src->path + 1;
- int prev_codebook;
- int i;
-
- for (i = 0; path[i]; i++)
- prev_bo = ctx->best_offset[i][channel];
-
- prev_codebook = path[i - 1] - ZERO_PATH;
-
- cur_bo = ctx->best_offset[i][channel];
+ int prev_codebook = src->path[idx];
bitcount += cur_bo[cur_codebook].bitcount;
prev_best_bitcount = temp_bitcount;
if (src_path != dst_path)
memcpy(dst_path, src_path, sizeof(PathCounter));
- av_strlcat(dst_path->path, path_counter_codebook[codebook], sizeof(dst_path->path));
+ if (dst_path->cur_idx < FF_ARRAY_ELEMS(dst_path->path) - 1)
+ dst_path->path[++dst_path->cur_idx] = codebook;
dst_path->bitcount = temp_bitcount;
}
}
for (index = 0; index < ctx->number_of_subblocks; index++) {
ChannelParams *cp = ctx->seq_channel_params + index*(ctx->avctx->channels) + channel;
- best_codebook = *best_path++ - ZERO_PATH;
+ best_codebook = *best_path++;
cur_bo = &ctx->best_offset[index][channel][best_codebook];
- cp->huff_offset = cur_bo->offset;
- cp->huff_lsbs = cur_bo->lsb_bits + dp->quant_step_size[channel];
- cp->codebook = best_codebook;
+ cp->huff_offset = cur_bo->offset;
+ cp->huff_lsbs = cur_bo->lsb_bits + dp->quant_step_size[channel];
+ cp->codebook = best_codebook;
}
}
}
ctx->number_of_samples = ctx->major_frame_size;
for (substr = 0; substr < ctx->num_substreams; substr++) {
- RestartHeader *rh = ctx->cur_restart_header;
- unsigned int channel;
-
ctx->cur_restart_header = &ctx->restart_header[substr];
ctx->cur_decoding_params = &ctx->major_decoding_params[1][substr];
generate_2_noise_channels(ctx);
rematrix_channels (ctx);
- for (channel = rh->min_channel; channel <= rh->max_channel; channel++)
- apply_filter(ctx, channel);
+ apply_filters(ctx);
}
}
if ((ret = ff_alloc_packet2(avctx, avpkt, 87500 * avctx->channels, 0)) < 0)
return ret;
- if (!frame)
- return 1;
-
/* add current frame to queue */
- if (frame) {
- if ((ret = ff_af_queue_add(&ctx->afq, frame)) < 0)
- return ret;
- }
+ if ((ret = ff_af_queue_add(&ctx->afq, frame)) < 0)
+ return ret;
data = frame->data[0];
if (ctx->frame_size[ctx->frame_index] > MAX_BLOCKSIZE) {
av_log(avctx, AV_LOG_ERROR, "Invalid frame size (%d > %d)\n",
ctx->frame_size[ctx->frame_index], MAX_BLOCKSIZE);
- return -1;
+ return AVERROR_INVALIDDATA;
}
restart_frame = !ctx->frame_index;
if (restart_frame) {
set_major_params(ctx);
if (ctx->min_restart_interval != ctx->max_restart_interval)
- process_major_frame(ctx);
+ process_major_frame(ctx);
}
if (ctx->min_restart_interval == ctx->max_restart_interval)
av_freep(&ctx->decoding_params);
av_freep(&ctx->channel_params);
av_freep(&ctx->frame_size);
+ av_freep(&ctx->max_output_bits);
ff_af_queue_close(&ctx->afq);
return 0;
}
#if CONFIG_MLP_ENCODER
-AVCodec ff_mlp_encoder = {
+const AVCodec ff_mlp_encoder = {
.name ="mlp",
.long_name = NULL_IF_CONFIG_SMALL("MLP (Meridian Lossless Packing)"),
.type = AVMEDIA_TYPE_AUDIO,
.init = mlp_encode_init,
.encode2 = mlp_encode_frame,
.close = mlp_encode_close,
- .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL,
+ .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_EXPERIMENTAL,
.sample_fmts = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE},
.supported_samplerates = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0},
.channel_layouts = ff_mlp_channel_layouts,
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
};
#endif
#if CONFIG_TRUEHD_ENCODER
-AVCodec ff_truehd_encoder = {
+const AVCodec ff_truehd_encoder = {
.name ="truehd",
.long_name = NULL_IF_CONFIG_SMALL("TrueHD"),
.type = AVMEDIA_TYPE_AUDIO,
.init = mlp_encode_init,
.encode2 = mlp_encode_frame,
.close = mlp_encode_close,
- .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL,
+ .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_EXPERIMENTAL,
.sample_fmts = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE},
.supported_samplerates = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0},
.channel_layouts = (const uint64_t[]) {AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_5POINT0_BACK, AV_CH_LAYOUT_5POINT1_BACK, 0},
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
};
#endif