mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
790f793844
There are lots of files that don't need it: The number of object files that actually need it went down from 2011 to 884 here. Keep it for external users in order to not cause breakages. Also improve the other headers a bit while just at it. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
1770 lines
61 KiB
C
1770 lines
61 KiB
C
/*
|
|
* FLAC audio encoder
|
|
* Copyright (c) 2006 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
|
|
*/
|
|
|
|
#include "libavutil/avassert.h"
|
|
#include "libavutil/channel_layout.h"
|
|
#include "libavutil/crc.h"
|
|
#include "libavutil/intmath.h"
|
|
#include "libavutil/md5.h"
|
|
#include "libavutil/mem.h"
|
|
#include "libavutil/opt.h"
|
|
|
|
#include "avcodec.h"
|
|
#include "bswapdsp.h"
|
|
#include "codec_internal.h"
|
|
#include "encode.h"
|
|
#include "put_bits.h"
|
|
#include "lpc.h"
|
|
#include "flac.h"
|
|
#include "flacdata.h"
|
|
#include "flacencdsp.h"
|
|
|
|
#define FLAC_SUBFRAME_CONSTANT 0
|
|
#define FLAC_SUBFRAME_VERBATIM 1
|
|
#define FLAC_SUBFRAME_FIXED 8
|
|
#define FLAC_SUBFRAME_LPC 32
|
|
|
|
#define MAX_FIXED_ORDER 4
|
|
#define MAX_PARTITION_ORDER 8
|
|
#define MAX_PARTITIONS (1 << MAX_PARTITION_ORDER)
|
|
#define MAX_LPC_PRECISION 15
|
|
#define MIN_LPC_SHIFT 0
|
|
#define MAX_LPC_SHIFT 15
|
|
|
|
enum CodingMode {
|
|
CODING_MODE_RICE = 4,
|
|
CODING_MODE_RICE2 = 5,
|
|
};
|
|
|
|
typedef struct CompressionOptions {
|
|
int compression_level;
|
|
int block_time_ms;
|
|
enum FFLPCType lpc_type;
|
|
int lpc_passes;
|
|
int lpc_coeff_precision;
|
|
int min_prediction_order;
|
|
int max_prediction_order;
|
|
int prediction_order_method;
|
|
int min_partition_order;
|
|
int max_partition_order;
|
|
int ch_mode;
|
|
int exact_rice_parameters;
|
|
int multi_dim_quant;
|
|
} CompressionOptions;
|
|
|
|
typedef struct RiceContext {
|
|
enum CodingMode coding_mode;
|
|
int porder;
|
|
int params[MAX_PARTITIONS];
|
|
} RiceContext;
|
|
|
|
typedef struct FlacSubframe {
|
|
int type;
|
|
int type_code;
|
|
int obits;
|
|
int wasted;
|
|
int order;
|
|
int32_t coefs[MAX_LPC_ORDER];
|
|
int shift;
|
|
|
|
RiceContext rc;
|
|
uint32_t rc_udata[FLAC_MAX_BLOCKSIZE];
|
|
uint64_t rc_sums[32][MAX_PARTITIONS];
|
|
|
|
int32_t samples[FLAC_MAX_BLOCKSIZE];
|
|
int32_t residual[FLAC_MAX_BLOCKSIZE+11];
|
|
} FlacSubframe;
|
|
|
|
typedef struct FlacFrame {
|
|
FlacSubframe subframes[FLAC_MAX_CHANNELS];
|
|
int64_t samples_33bps[FLAC_MAX_BLOCKSIZE];
|
|
int blocksize;
|
|
int bs_code[2];
|
|
uint8_t crc8;
|
|
int ch_mode;
|
|
int verbatim_only;
|
|
} FlacFrame;
|
|
|
|
typedef struct FlacEncodeContext {
|
|
AVClass *class;
|
|
PutBitContext pb;
|
|
int channels;
|
|
int samplerate;
|
|
int sr_code[2];
|
|
int bps_code;
|
|
int max_blocksize;
|
|
int min_framesize;
|
|
int max_framesize;
|
|
int max_encoded_framesize;
|
|
uint32_t frame_count;
|
|
uint64_t sample_count;
|
|
uint8_t md5sum[16];
|
|
FlacFrame frame;
|
|
CompressionOptions options;
|
|
AVCodecContext *avctx;
|
|
LPCContext lpc_ctx;
|
|
struct AVMD5 *md5ctx;
|
|
uint8_t *md5_buffer;
|
|
unsigned int md5_buffer_size;
|
|
BswapDSPContext bdsp;
|
|
FLACEncDSPContext flac_dsp;
|
|
|
|
int flushed;
|
|
int64_t next_pts;
|
|
} FlacEncodeContext;
|
|
|
|
|
|
/**
|
|
* Write streaminfo metadata block to byte array.
|
|
*/
|
|
static void write_streaminfo(FlacEncodeContext *s, uint8_t *header)
|
|
{
|
|
PutBitContext pb;
|
|
|
|
memset(header, 0, FLAC_STREAMINFO_SIZE);
|
|
init_put_bits(&pb, header, FLAC_STREAMINFO_SIZE);
|
|
|
|
/* streaminfo metadata block */
|
|
put_bits(&pb, 16, s->max_blocksize);
|
|
put_bits(&pb, 16, s->max_blocksize);
|
|
put_bits(&pb, 24, s->min_framesize);
|
|
put_bits(&pb, 24, s->max_framesize);
|
|
put_bits(&pb, 20, s->samplerate);
|
|
put_bits(&pb, 3, s->channels-1);
|
|
put_bits(&pb, 5, s->avctx->bits_per_raw_sample - 1);
|
|
/* write 36-bit sample count in 2 put_bits() calls */
|
|
put_bits(&pb, 24, (s->sample_count & 0xFFFFFF000LL) >> 12);
|
|
put_bits(&pb, 12, s->sample_count & 0x000000FFFLL);
|
|
flush_put_bits(&pb);
|
|
memcpy(&header[18], s->md5sum, 16);
|
|
}
|
|
|
|
|
|
/**
|
|
* Calculate an estimate for the maximum frame size based on verbatim mode.
|
|
* @param blocksize block size, in samples
|
|
* @param ch number of channels
|
|
* @param bps bits-per-sample
|
|
*/
|
|
static int flac_get_max_frame_size(int blocksize, int ch, int bps)
|
|
{
|
|
/* Technically, there is no limit to FLAC frame size, but an encoder
|
|
should not write a frame that is larger than if verbatim encoding mode
|
|
were to be used. */
|
|
|
|
int count;
|
|
|
|
count = 16; /* frame header */
|
|
count += ch * ((7+bps+7)/8); /* subframe headers */
|
|
if (ch == 2) {
|
|
/* for stereo, need to account for using decorrelation */
|
|
count += (( 2*bps+1) * blocksize + 7) / 8;
|
|
} else {
|
|
count += ( ch*bps * blocksize + 7) / 8;
|
|
}
|
|
count += 2; /* frame footer */
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set blocksize based on samplerate.
|
|
* Choose the closest predefined blocksize >= BLOCK_TIME_MS milliseconds.
|
|
*/
|
|
static int select_blocksize(int samplerate, int block_time_ms)
|
|
{
|
|
int i;
|
|
int target;
|
|
int blocksize;
|
|
|
|
av_assert0(samplerate > 0);
|
|
blocksize = ff_flac_blocksize_table[1];
|
|
target = (samplerate * block_time_ms) / 1000;
|
|
for (i = 0; i < 16; i++) {
|
|
if (target >= ff_flac_blocksize_table[i] &&
|
|
ff_flac_blocksize_table[i] > blocksize) {
|
|
blocksize = ff_flac_blocksize_table[i];
|
|
}
|
|
}
|
|
return blocksize;
|
|
}
|
|
|
|
|
|
static av_cold void dprint_compression_options(FlacEncodeContext *s)
|
|
{
|
|
AVCodecContext *avctx = s->avctx;
|
|
CompressionOptions *opt = &s->options;
|
|
|
|
av_log(avctx, AV_LOG_DEBUG, " compression: %d\n", opt->compression_level);
|
|
|
|
switch (opt->lpc_type) {
|
|
case FF_LPC_TYPE_NONE:
|
|
av_log(avctx, AV_LOG_DEBUG, " lpc type: None\n");
|
|
break;
|
|
case FF_LPC_TYPE_FIXED:
|
|
av_log(avctx, AV_LOG_DEBUG, " lpc type: Fixed pre-defined coefficients\n");
|
|
break;
|
|
case FF_LPC_TYPE_LEVINSON:
|
|
av_log(avctx, AV_LOG_DEBUG, " lpc type: Levinson-Durbin recursion with Welch window\n");
|
|
break;
|
|
case FF_LPC_TYPE_CHOLESKY:
|
|
av_log(avctx, AV_LOG_DEBUG, " lpc type: Cholesky factorization, %d pass%s\n",
|
|
opt->lpc_passes, opt->lpc_passes == 1 ? "" : "es");
|
|
break;
|
|
}
|
|
|
|
av_log(avctx, AV_LOG_DEBUG, " prediction order: %d, %d\n",
|
|
opt->min_prediction_order, opt->max_prediction_order);
|
|
|
|
switch (opt->prediction_order_method) {
|
|
case ORDER_METHOD_EST:
|
|
av_log(avctx, AV_LOG_DEBUG, " order method: %s\n", "estimate");
|
|
break;
|
|
case ORDER_METHOD_2LEVEL:
|
|
av_log(avctx, AV_LOG_DEBUG, " order method: %s\n", "2-level");
|
|
break;
|
|
case ORDER_METHOD_4LEVEL:
|
|
av_log(avctx, AV_LOG_DEBUG, " order method: %s\n", "4-level");
|
|
break;
|
|
case ORDER_METHOD_8LEVEL:
|
|
av_log(avctx, AV_LOG_DEBUG, " order method: %s\n", "8-level");
|
|
break;
|
|
case ORDER_METHOD_SEARCH:
|
|
av_log(avctx, AV_LOG_DEBUG, " order method: %s\n", "full search");
|
|
break;
|
|
case ORDER_METHOD_LOG:
|
|
av_log(avctx, AV_LOG_DEBUG, " order method: %s\n", "log search");
|
|
break;
|
|
}
|
|
|
|
|
|
av_log(avctx, AV_LOG_DEBUG, " partition order: %d, %d\n",
|
|
opt->min_partition_order, opt->max_partition_order);
|
|
|
|
av_log(avctx, AV_LOG_DEBUG, " block size: %d\n", avctx->frame_size);
|
|
|
|
av_log(avctx, AV_LOG_DEBUG, " lpc precision: %d\n",
|
|
opt->lpc_coeff_precision);
|
|
}
|
|
|
|
|
|
static av_cold int flac_encode_init(AVCodecContext *avctx)
|
|
{
|
|
int freq = avctx->sample_rate;
|
|
int channels = avctx->ch_layout.nb_channels;
|
|
FlacEncodeContext *s = avctx->priv_data;
|
|
int i, level, ret;
|
|
uint8_t *streaminfo;
|
|
|
|
s->avctx = avctx;
|
|
|
|
switch (avctx->sample_fmt) {
|
|
case AV_SAMPLE_FMT_S16:
|
|
avctx->bits_per_raw_sample = 16;
|
|
s->bps_code = 4;
|
|
break;
|
|
case AV_SAMPLE_FMT_S32:
|
|
if (avctx->bits_per_raw_sample <= 24) {
|
|
if (avctx->bits_per_raw_sample < 24)
|
|
av_log(avctx, AV_LOG_WARNING, "encoding as 24 bits-per-sample\n");
|
|
avctx->bits_per_raw_sample = 24;
|
|
s->bps_code = 6;
|
|
} else if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
|
|
av_log(avctx, AV_LOG_WARNING,
|
|
"encoding as 24 bits-per-sample, more is considered "
|
|
"experimental. Add -strict experimental if you want "
|
|
"to encode more than 24 bits-per-sample\n");
|
|
avctx->bits_per_raw_sample = 24;
|
|
s->bps_code = 6;
|
|
} else {
|
|
avctx->bits_per_raw_sample = 32;
|
|
s->bps_code = 7;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (channels < 1 || channels > FLAC_MAX_CHANNELS) {
|
|
av_log(avctx, AV_LOG_ERROR, "%d channels not supported (max %d)\n",
|
|
channels, FLAC_MAX_CHANNELS);
|
|
return AVERROR(EINVAL);
|
|
}
|
|
s->channels = channels;
|
|
|
|
/* find samplerate in table */
|
|
if (freq < 1)
|
|
return AVERROR(EINVAL);
|
|
for (i = 1; i < 12; i++) {
|
|
if (freq == ff_flac_sample_rate_table[i]) {
|
|
s->samplerate = ff_flac_sample_rate_table[i];
|
|
s->sr_code[0] = i;
|
|
s->sr_code[1] = 0;
|
|
break;
|
|
}
|
|
}
|
|
/* if not in table, samplerate is non-standard */
|
|
if (i == 12) {
|
|
if (freq % 1000 == 0 && freq < 255000) {
|
|
s->sr_code[0] = 12;
|
|
s->sr_code[1] = freq / 1000;
|
|
} else if (freq % 10 == 0 && freq < 655350) {
|
|
s->sr_code[0] = 14;
|
|
s->sr_code[1] = freq / 10;
|
|
} else if (freq < 65535) {
|
|
s->sr_code[0] = 13;
|
|
s->sr_code[1] = freq;
|
|
} else if (freq < 1048576) {
|
|
s->sr_code[0] = 0;
|
|
s->sr_code[1] = 0;
|
|
} else {
|
|
av_log(avctx, AV_LOG_ERROR, "%d Hz not supported\n", freq);
|
|
return AVERROR(EINVAL);
|
|
}
|
|
s->samplerate = freq;
|
|
}
|
|
|
|
/* set compression option defaults based on avctx->compression_level */
|
|
if (avctx->compression_level < 0)
|
|
s->options.compression_level = 5;
|
|
else
|
|
s->options.compression_level = avctx->compression_level;
|
|
|
|
level = s->options.compression_level;
|
|
if (level > 12) {
|
|
av_log(avctx, AV_LOG_ERROR, "invalid compression level: %d\n",
|
|
s->options.compression_level);
|
|
return AVERROR(EINVAL);
|
|
}
|
|
|
|
s->options.block_time_ms = ((int[]){ 27, 27, 27,105,105,105,105,105,105,105,105,105,105})[level];
|
|
|
|
if (s->options.lpc_type == FF_LPC_TYPE_DEFAULT)
|
|
s->options.lpc_type = ((int[]){ FF_LPC_TYPE_FIXED, FF_LPC_TYPE_FIXED, FF_LPC_TYPE_FIXED,
|
|
FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_LEVINSON,
|
|
FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_LEVINSON,
|
|
FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_LEVINSON,
|
|
FF_LPC_TYPE_LEVINSON})[level];
|
|
|
|
if (s->options.min_prediction_order < 0)
|
|
s->options.min_prediction_order = ((int[]){ 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1})[level];
|
|
if (s->options.max_prediction_order < 0)
|
|
s->options.max_prediction_order = ((int[]){ 3, 4, 4, 6, 8, 8, 8, 8, 12, 12, 12, 32, 32})[level];
|
|
|
|
if (s->options.prediction_order_method < 0)
|
|
s->options.prediction_order_method = ((int[]){ ORDER_METHOD_EST, ORDER_METHOD_EST, ORDER_METHOD_EST,
|
|
ORDER_METHOD_EST, ORDER_METHOD_EST, ORDER_METHOD_EST,
|
|
ORDER_METHOD_4LEVEL, ORDER_METHOD_LOG, ORDER_METHOD_4LEVEL,
|
|
ORDER_METHOD_LOG, ORDER_METHOD_SEARCH, ORDER_METHOD_LOG,
|
|
ORDER_METHOD_SEARCH})[level];
|
|
|
|
if (s->options.min_partition_order > s->options.max_partition_order) {
|
|
av_log(avctx, AV_LOG_ERROR, "invalid partition orders: min=%d max=%d\n",
|
|
s->options.min_partition_order, s->options.max_partition_order);
|
|
return AVERROR(EINVAL);
|
|
}
|
|
if (s->options.min_partition_order < 0)
|
|
s->options.min_partition_order = ((int[]){ 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})[level];
|
|
if (s->options.max_partition_order < 0)
|
|
s->options.max_partition_order = ((int[]){ 2, 2, 3, 3, 3, 8, 8, 8, 8, 8, 8, 8, 8})[level];
|
|
|
|
if (s->options.lpc_type == FF_LPC_TYPE_NONE) {
|
|
s->options.min_prediction_order = 0;
|
|
s->options.max_prediction_order = 0;
|
|
} else if (s->options.lpc_type == FF_LPC_TYPE_FIXED) {
|
|
if (s->options.min_prediction_order > MAX_FIXED_ORDER) {
|
|
av_log(avctx, AV_LOG_WARNING,
|
|
"invalid min prediction order %d, clamped to %d\n",
|
|
s->options.min_prediction_order, MAX_FIXED_ORDER);
|
|
s->options.min_prediction_order = MAX_FIXED_ORDER;
|
|
}
|
|
if (s->options.max_prediction_order > MAX_FIXED_ORDER) {
|
|
av_log(avctx, AV_LOG_WARNING,
|
|
"invalid max prediction order %d, clamped to %d\n",
|
|
s->options.max_prediction_order, MAX_FIXED_ORDER);
|
|
s->options.max_prediction_order = MAX_FIXED_ORDER;
|
|
}
|
|
}
|
|
|
|
if (s->options.max_prediction_order < s->options.min_prediction_order) {
|
|
av_log(avctx, AV_LOG_ERROR, "invalid prediction orders: min=%d max=%d\n",
|
|
s->options.min_prediction_order, s->options.max_prediction_order);
|
|
return AVERROR(EINVAL);
|
|
}
|
|
|
|
if (avctx->frame_size > 0) {
|
|
if (avctx->frame_size < FLAC_MIN_BLOCKSIZE ||
|
|
avctx->frame_size > FLAC_MAX_BLOCKSIZE) {
|
|
av_log(avctx, AV_LOG_ERROR, "invalid block size: %d\n",
|
|
avctx->frame_size);
|
|
return AVERROR(EINVAL);
|
|
}
|
|
} else {
|
|
s->avctx->frame_size = select_blocksize(s->samplerate, s->options.block_time_ms);
|
|
}
|
|
s->max_blocksize = s->avctx->frame_size;
|
|
|
|
/* set maximum encoded frame size in verbatim mode */
|
|
s->max_framesize = flac_get_max_frame_size(s->avctx->frame_size,
|
|
s->channels,
|
|
s->avctx->bits_per_raw_sample);
|
|
|
|
/* initialize MD5 context */
|
|
s->md5ctx = av_md5_alloc();
|
|
if (!s->md5ctx)
|
|
return AVERROR(ENOMEM);
|
|
av_md5_init(s->md5ctx);
|
|
|
|
streaminfo = av_malloc(FLAC_STREAMINFO_SIZE);
|
|
if (!streaminfo)
|
|
return AVERROR(ENOMEM);
|
|
write_streaminfo(s, streaminfo);
|
|
avctx->extradata = streaminfo;
|
|
avctx->extradata_size = FLAC_STREAMINFO_SIZE;
|
|
|
|
s->frame_count = 0;
|
|
s->min_framesize = s->max_framesize;
|
|
|
|
if ((channels == 3 &&
|
|
av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_SURROUND)) ||
|
|
(channels == 4 &&
|
|
av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_2_2) &&
|
|
av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_QUAD)) ||
|
|
(channels == 5 &&
|
|
av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0) &&
|
|
av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0_BACK)) ||
|
|
(channels == 6 &&
|
|
av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1) &&
|
|
av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK))) {
|
|
if (avctx->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) {
|
|
av_log(avctx, AV_LOG_ERROR, "Channel layout not supported by Flac, "
|
|
"output stream will have incorrect "
|
|
"channel layout.\n");
|
|
} else {
|
|
av_log(avctx, AV_LOG_WARNING, "No channel layout specified. The encoder "
|
|
"will use Flac channel layout for "
|
|
"%d channels.\n", channels);
|
|
}
|
|
}
|
|
|
|
ret = ff_lpc_init(&s->lpc_ctx, avctx->frame_size,
|
|
s->options.max_prediction_order, FF_LPC_TYPE_LEVINSON);
|
|
|
|
ff_bswapdsp_init(&s->bdsp);
|
|
ff_flacencdsp_init(&s->flac_dsp);
|
|
|
|
dprint_compression_options(s);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static void init_frame(FlacEncodeContext *s, int nb_samples)
|
|
{
|
|
int i, ch;
|
|
FlacFrame *frame;
|
|
|
|
frame = &s->frame;
|
|
|
|
for (i = 0; i < 16; i++) {
|
|
if (nb_samples == ff_flac_blocksize_table[i]) {
|
|
frame->blocksize = ff_flac_blocksize_table[i];
|
|
frame->bs_code[0] = i;
|
|
frame->bs_code[1] = 0;
|
|
break;
|
|
}
|
|
}
|
|
if (i == 16) {
|
|
frame->blocksize = nb_samples;
|
|
if (frame->blocksize <= 256) {
|
|
frame->bs_code[0] = 6;
|
|
frame->bs_code[1] = frame->blocksize-1;
|
|
} else {
|
|
frame->bs_code[0] = 7;
|
|
frame->bs_code[1] = frame->blocksize-1;
|
|
}
|
|
}
|
|
|
|
for (ch = 0; ch < s->channels; ch++) {
|
|
FlacSubframe *sub = &frame->subframes[ch];
|
|
|
|
sub->wasted = 0;
|
|
sub->obits = s->avctx->bits_per_raw_sample;
|
|
|
|
if (sub->obits > 16)
|
|
sub->rc.coding_mode = CODING_MODE_RICE2;
|
|
else
|
|
sub->rc.coding_mode = CODING_MODE_RICE;
|
|
}
|
|
|
|
frame->verbatim_only = 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Copy channel-interleaved input samples into separate subframes.
|
|
*/
|
|
static void copy_samples(FlacEncodeContext *s, const void *samples)
|
|
{
|
|
int i, j, ch;
|
|
FlacFrame *frame;
|
|
int shift = av_get_bytes_per_sample(s->avctx->sample_fmt) * 8 -
|
|
s->avctx->bits_per_raw_sample;
|
|
|
|
#define COPY_SAMPLES(bits) do { \
|
|
const int ## bits ## _t *samples0 = samples; \
|
|
frame = &s->frame; \
|
|
for (i = 0, j = 0; i < frame->blocksize; i++) \
|
|
for (ch = 0; ch < s->channels; ch++, j++) \
|
|
frame->subframes[ch].samples[i] = samples0[j] >> shift; \
|
|
} while (0)
|
|
|
|
if (s->avctx->sample_fmt == AV_SAMPLE_FMT_S16)
|
|
COPY_SAMPLES(16);
|
|
else
|
|
COPY_SAMPLES(32);
|
|
}
|
|
|
|
|
|
static uint64_t rice_count_exact(const int32_t *res, int n, int k)
|
|
{
|
|
int i;
|
|
uint64_t count = 0;
|
|
|
|
for (i = 0; i < n; i++) {
|
|
unsigned v = ((unsigned)(res[i]) << 1) ^ (res[i] >> 31);
|
|
count += (v >> k) + 1 + k;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
|
|
static uint64_t subframe_count_exact(FlacEncodeContext *s, FlacSubframe *sub,
|
|
int pred_order)
|
|
{
|
|
int p, porder, psize;
|
|
int i, part_end;
|
|
uint64_t count = 0;
|
|
|
|
/* subframe header */
|
|
count += 8;
|
|
|
|
if (sub->wasted)
|
|
count += sub->wasted;
|
|
|
|
/* subframe */
|
|
if (sub->type == FLAC_SUBFRAME_CONSTANT) {
|
|
count += sub->obits;
|
|
} else if (sub->type == FLAC_SUBFRAME_VERBATIM) {
|
|
count += s->frame.blocksize * sub->obits;
|
|
} else {
|
|
/* warm-up samples */
|
|
count += pred_order * sub->obits;
|
|
|
|
/* LPC coefficients */
|
|
if (sub->type == FLAC_SUBFRAME_LPC)
|
|
count += 4 + 5 + pred_order * s->options.lpc_coeff_precision;
|
|
|
|
/* rice-encoded block */
|
|
count += 2;
|
|
|
|
/* partition order */
|
|
porder = sub->rc.porder;
|
|
psize = s->frame.blocksize >> porder;
|
|
count += 4;
|
|
|
|
/* residual */
|
|
i = pred_order;
|
|
part_end = psize;
|
|
for (p = 0; p < 1 << porder; p++) {
|
|
int k = sub->rc.params[p];
|
|
count += sub->rc.coding_mode;
|
|
count += rice_count_exact(&sub->residual[i], part_end - i, k);
|
|
i = part_end;
|
|
part_end = FFMIN(s->frame.blocksize, part_end + psize);
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
#define rice_encode_count(sum, n, k) (((n)*((k)+1))+((sum-(n>>1))>>(k)))
|
|
|
|
/**
|
|
* Solve for d/dk(rice_encode_count) = n-((sum-(n>>1))>>(k+1)) = 0.
|
|
*/
|
|
static int find_optimal_param(uint64_t sum, int n, int max_param)
|
|
{
|
|
int k;
|
|
uint64_t sum2;
|
|
|
|
if (sum <= n >> 1)
|
|
return 0;
|
|
sum2 = sum - (n >> 1);
|
|
k = av_log2(av_clipl_int32(sum2 / n));
|
|
return FFMIN(k, max_param);
|
|
}
|
|
|
|
static int find_optimal_param_exact(uint64_t sums[32][MAX_PARTITIONS], int i, int max_param)
|
|
{
|
|
int bestk = 0;
|
|
int64_t bestbits = INT64_MAX;
|
|
int k;
|
|
|
|
for (k = 0; k <= max_param; k++) {
|
|
int64_t bits = sums[k][i];
|
|
if (bits < bestbits) {
|
|
bestbits = bits;
|
|
bestk = k;
|
|
}
|
|
}
|
|
|
|
return bestk;
|
|
}
|
|
|
|
static uint64_t calc_optimal_rice_params(RiceContext *rc, int porder,
|
|
uint64_t sums[32][MAX_PARTITIONS],
|
|
int n, int pred_order, int max_param, int exact)
|
|
{
|
|
int i;
|
|
int k, cnt, part;
|
|
uint64_t all_bits;
|
|
|
|
part = (1 << porder);
|
|
all_bits = 4 * part;
|
|
|
|
cnt = (n >> porder) - pred_order;
|
|
for (i = 0; i < part; i++) {
|
|
if (exact) {
|
|
k = find_optimal_param_exact(sums, i, max_param);
|
|
all_bits += sums[k][i];
|
|
} else {
|
|
k = find_optimal_param(sums[0][i], cnt, max_param);
|
|
all_bits += rice_encode_count(sums[0][i], cnt, k);
|
|
}
|
|
rc->params[i] = k;
|
|
cnt = n >> porder;
|
|
}
|
|
|
|
rc->porder = porder;
|
|
|
|
return all_bits;
|
|
}
|
|
|
|
|
|
static void calc_sum_top(int pmax, int kmax, const uint32_t *data, int n, int pred_order,
|
|
uint64_t sums[32][MAX_PARTITIONS])
|
|
{
|
|
int i, k;
|
|
int parts;
|
|
const uint32_t *res, *res_end;
|
|
|
|
/* sums for highest level */
|
|
parts = (1 << pmax);
|
|
|
|
for (k = 0; k <= kmax; k++) {
|
|
res = &data[pred_order];
|
|
res_end = &data[n >> pmax];
|
|
for (i = 0; i < parts; i++) {
|
|
if (kmax) {
|
|
uint64_t sum = (1LL + k) * (res_end - res);
|
|
while (res < res_end)
|
|
sum += *(res++) >> k;
|
|
sums[k][i] = sum;
|
|
} else {
|
|
uint64_t sum = 0;
|
|
while (res < res_end)
|
|
sum += *(res++);
|
|
sums[k][i] = sum;
|
|
}
|
|
res_end += n >> pmax;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void calc_sum_next(int level, uint64_t sums[32][MAX_PARTITIONS], int kmax)
|
|
{
|
|
int i, k;
|
|
int parts = (1 << level);
|
|
for (i = 0; i < parts; i++) {
|
|
for (k=0; k<=kmax; k++)
|
|
sums[k][i] = sums[k][2*i] + sums[k][2*i+1];
|
|
}
|
|
}
|
|
|
|
static uint64_t calc_rice_params(RiceContext *rc,
|
|
uint32_t udata[FLAC_MAX_BLOCKSIZE],
|
|
uint64_t sums[32][MAX_PARTITIONS],
|
|
int pmin, int pmax,
|
|
const int32_t *data, int n, int pred_order, int exact)
|
|
{
|
|
int i;
|
|
uint64_t bits[MAX_PARTITION_ORDER+1];
|
|
int opt_porder;
|
|
RiceContext tmp_rc;
|
|
int kmax = (1 << rc->coding_mode) - 2;
|
|
|
|
av_assert1(pmin >= 0 && pmin <= MAX_PARTITION_ORDER);
|
|
av_assert1(pmax >= 0 && pmax <= MAX_PARTITION_ORDER);
|
|
av_assert1(pmin <= pmax);
|
|
|
|
tmp_rc.coding_mode = rc->coding_mode;
|
|
|
|
for (i = pred_order; i < n; i++)
|
|
udata[i] = ((unsigned)(data[i]) << 1) ^ (data[i] >> 31);
|
|
|
|
calc_sum_top(pmax, exact ? kmax : 0, udata, n, pred_order, sums);
|
|
|
|
opt_porder = pmin;
|
|
bits[pmin] = UINT32_MAX;
|
|
for (i = pmax; ; ) {
|
|
bits[i] = calc_optimal_rice_params(&tmp_rc, i, sums, n, pred_order, kmax, exact);
|
|
if (bits[i] < bits[opt_porder] || pmax == pmin) {
|
|
opt_porder = i;
|
|
*rc = tmp_rc;
|
|
}
|
|
if (i == pmin)
|
|
break;
|
|
calc_sum_next(--i, sums, exact ? kmax : 0);
|
|
}
|
|
|
|
return bits[opt_porder];
|
|
}
|
|
|
|
|
|
static int get_max_p_order(int max_porder, int n, int order)
|
|
{
|
|
int porder = FFMIN(max_porder, av_log2(n^(n-1)));
|
|
if (order > 0)
|
|
porder = FFMIN(porder, av_log2(n/order));
|
|
return porder;
|
|
}
|
|
|
|
|
|
static uint64_t find_subframe_rice_params(FlacEncodeContext *s,
|
|
FlacSubframe *sub, int pred_order)
|
|
{
|
|
int pmin = get_max_p_order(s->options.min_partition_order,
|
|
s->frame.blocksize, pred_order);
|
|
int pmax = get_max_p_order(s->options.max_partition_order,
|
|
s->frame.blocksize, pred_order);
|
|
|
|
uint64_t bits = 8 + pred_order * sub->obits + 2 + sub->rc.coding_mode;
|
|
if (sub->type == FLAC_SUBFRAME_LPC)
|
|
bits += 4 + 5 + pred_order * s->options.lpc_coeff_precision;
|
|
bits += calc_rice_params(&sub->rc, sub->rc_udata, sub->rc_sums, pmin, pmax, sub->residual,
|
|
s->frame.blocksize, pred_order, s->options.exact_rice_parameters);
|
|
return bits;
|
|
}
|
|
|
|
|
|
static void encode_residual_fixed(int32_t *res, const int32_t *smp, int n,
|
|
int order)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < order; i++)
|
|
res[i] = smp[i];
|
|
|
|
if (order == 0) {
|
|
for (i = order; i < n; i++)
|
|
res[i] = smp[i];
|
|
} else if (order == 1) {
|
|
for (i = order; i < n; i++)
|
|
res[i] = smp[i] - smp[i-1];
|
|
} else if (order == 2) {
|
|
int a = smp[order-1] - smp[order-2];
|
|
for (i = order; i < n; i += 2) {
|
|
int b = smp[i ] - smp[i-1];
|
|
res[i] = b - a;
|
|
a = smp[i+1] - smp[i ];
|
|
res[i+1] = a - b;
|
|
}
|
|
} else if (order == 3) {
|
|
int a = smp[order-1] - smp[order-2];
|
|
int c = smp[order-1] - 2*smp[order-2] + smp[order-3];
|
|
for (i = order; i < n; i += 2) {
|
|
int b = smp[i ] - smp[i-1];
|
|
int d = b - a;
|
|
res[i] = d - c;
|
|
a = smp[i+1] - smp[i ];
|
|
c = a - b;
|
|
res[i+1] = c - d;
|
|
}
|
|
} else {
|
|
int a = smp[order-1] - smp[order-2];
|
|
int c = smp[order-1] - 2*smp[order-2] + smp[order-3];
|
|
int e = smp[order-1] - 3*smp[order-2] + 3*smp[order-3] - smp[order-4];
|
|
for (i = order; i < n; i += 2) {
|
|
int b = smp[i ] - smp[i-1];
|
|
int d = b - a;
|
|
int f = d - c;
|
|
res[i ] = f - e;
|
|
a = smp[i+1] - smp[i ];
|
|
c = a - b;
|
|
e = c - d;
|
|
res[i+1] = e - f;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* These four functions check for every residual whether it can be
|
|
* contained in <INT32_MIN,INT32_MAX]. In case it doesn't, the
|
|
* function that called this function has to try something else.
|
|
* Each function is duplicated, once for int32_t input, once for
|
|
* int64_t input */
|
|
#define ENCODE_RESIDUAL_FIXED_WITH_RESIDUAL_LIMIT() \
|
|
{ \
|
|
for (int i = 0; i < order; i++) \
|
|
res[i] = smp[i]; \
|
|
if (order == 0) { \
|
|
for (int i = order; i < n; i++) { \
|
|
if (smp[i] == INT32_MIN) \
|
|
return 1; \
|
|
res[i] = smp[i]; \
|
|
} \
|
|
} else if (order == 1) { \
|
|
for (int i = order; i < n; i++) { \
|
|
int64_t res64 = (int64_t)smp[i] - smp[i-1]; \
|
|
if (res64 <= INT32_MIN || res64 > INT32_MAX) \
|
|
return 1; \
|
|
res[i] = res64; \
|
|
} \
|
|
} else if (order == 2) { \
|
|
for (int i = order; i < n; i++) { \
|
|
int64_t res64 = (int64_t)smp[i] - 2*(int64_t)smp[i-1] + smp[i-2]; \
|
|
if (res64 <= INT32_MIN || res64 > INT32_MAX) \
|
|
return 1; \
|
|
res[i] = res64; \
|
|
} \
|
|
} else if (order == 3) { \
|
|
for (int i = order; i < n; i++) { \
|
|
int64_t res64 = (int64_t)smp[i] - 3*(int64_t)smp[i-1] + 3*(int64_t)smp[i-2] - smp[i-3]; \
|
|
if (res64 <= INT32_MIN || res64 > INT32_MAX) \
|
|
return 1; \
|
|
res[i] = res64; \
|
|
} \
|
|
} else { \
|
|
for (int i = order; i < n; i++) { \
|
|
int64_t res64 = (int64_t)smp[i] - 4*(int64_t)smp[i-1] + 6*(int64_t)smp[i-2] - 4*(int64_t)smp[i-3] + smp[i-4]; \
|
|
if (res64 <= INT32_MIN || res64 > INT32_MAX) \
|
|
return 1; \
|
|
res[i] = res64; \
|
|
} \
|
|
} \
|
|
return 0; \
|
|
}
|
|
|
|
static int encode_residual_fixed_with_residual_limit(int32_t *res, const int32_t *smp,
|
|
int n, int order)
|
|
{
|
|
ENCODE_RESIDUAL_FIXED_WITH_RESIDUAL_LIMIT();
|
|
}
|
|
|
|
|
|
static int encode_residual_fixed_with_residual_limit_33bps(int32_t *res, const int64_t *smp,
|
|
int n, int order)
|
|
{
|
|
ENCODE_RESIDUAL_FIXED_WITH_RESIDUAL_LIMIT();
|
|
}
|
|
|
|
#define LPC_ENCODE_WITH_RESIDUAL_LIMIT() \
|
|
{ \
|
|
for (int i = 0; i < order; i++) \
|
|
res[i] = smp[i]; \
|
|
for (int i = order; i < len; i++) { \
|
|
int64_t p = 0, tmp; \
|
|
for (int j = 0; j < order; j++) \
|
|
p += (int64_t)coefs[j]*smp[(i-1)-j]; \
|
|
p >>= shift; \
|
|
tmp = smp[i] - p; \
|
|
if (tmp <= INT32_MIN || tmp > INT32_MAX) \
|
|
return 1; \
|
|
res[i] = tmp; \
|
|
} \
|
|
return 0; \
|
|
}
|
|
|
|
static int lpc_encode_with_residual_limit(int32_t *res, const int32_t *smp, int len,
|
|
int order, int32_t *coefs, int shift)
|
|
{
|
|
LPC_ENCODE_WITH_RESIDUAL_LIMIT();
|
|
}
|
|
|
|
static int lpc_encode_with_residual_limit_33bps(int32_t *res, const int64_t *smp, int len,
|
|
int order, int32_t *coefs, int shift)
|
|
{
|
|
LPC_ENCODE_WITH_RESIDUAL_LIMIT();
|
|
}
|
|
|
|
static int lpc_encode_choose_datapath(FlacEncodeContext *s, int32_t bps,
|
|
int32_t *res, const int32_t *smp,
|
|
const int64_t *smp_33bps, int len,
|
|
int order, int32_t *coefs, int shift)
|
|
{
|
|
uint64_t max_residual_value = 0;
|
|
int64_t max_sample_value = ((int64_t)(1) << (bps-1));
|
|
/* This calculates the max size of any residual with the current
|
|
* predictor, so we know whether we need to check the residual */
|
|
for (int i = 0; i < order; i++)
|
|
max_residual_value += FFABS(max_sample_value * coefs[i]);
|
|
max_residual_value >>= shift;
|
|
max_residual_value += max_sample_value;
|
|
if (bps > 32) {
|
|
if (lpc_encode_with_residual_limit_33bps(res, smp_33bps, len, order, coefs, shift))
|
|
return 1;
|
|
} else if (max_residual_value > INT32_MAX) {
|
|
if (lpc_encode_with_residual_limit(res, smp, len, order, coefs, shift))
|
|
return 1;
|
|
} else if (bps + s->options.lpc_coeff_precision + av_log2(order) <= 32) {
|
|
s->flac_dsp.lpc16_encode(res, smp, len, order, coefs, shift);
|
|
} else {
|
|
s->flac_dsp.lpc32_encode(res, smp, len, order, coefs, shift);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#define DEFAULT_TO_VERBATIM() \
|
|
{ \
|
|
sub->type = sub->type_code = FLAC_SUBFRAME_VERBATIM; \
|
|
if (sub->obits <= 32) \
|
|
memcpy(res, smp, n * sizeof(int32_t)); \
|
|
return subframe_count_exact(s, sub, 0); \
|
|
}
|
|
|
|
static int encode_residual_ch(FlacEncodeContext *s, int ch)
|
|
{
|
|
int i, n;
|
|
int min_order, max_order, opt_order, omethod;
|
|
FlacFrame *frame;
|
|
FlacSubframe *sub;
|
|
int32_t coefs[MAX_LPC_ORDER][MAX_LPC_ORDER];
|
|
int shift[MAX_LPC_ORDER];
|
|
int32_t *res, *smp;
|
|
int64_t *smp_33bps;
|
|
|
|
frame = &s->frame;
|
|
sub = &frame->subframes[ch];
|
|
res = sub->residual;
|
|
smp = sub->samples;
|
|
smp_33bps = frame->samples_33bps;
|
|
n = frame->blocksize;
|
|
|
|
/* CONSTANT */
|
|
if (sub->obits > 32) {
|
|
for (i = 1; i < n; i++)
|
|
if(smp_33bps[i] != smp_33bps[0])
|
|
break;
|
|
if (i == n) {
|
|
sub->type = sub->type_code = FLAC_SUBFRAME_CONSTANT;
|
|
return subframe_count_exact(s, sub, 0);
|
|
}
|
|
} else {
|
|
for (i = 1; i < n; i++)
|
|
if(smp[i] != smp[0])
|
|
break;
|
|
if (i == n) {
|
|
sub->type = sub->type_code = FLAC_SUBFRAME_CONSTANT;
|
|
res[0] = smp[0];
|
|
return subframe_count_exact(s, sub, 0);
|
|
}
|
|
}
|
|
|
|
/* VERBATIM */
|
|
if (frame->verbatim_only || n < 5) {
|
|
DEFAULT_TO_VERBATIM();
|
|
}
|
|
|
|
min_order = s->options.min_prediction_order;
|
|
max_order = s->options.max_prediction_order;
|
|
omethod = s->options.prediction_order_method;
|
|
|
|
/* FIXED */
|
|
sub->type = FLAC_SUBFRAME_FIXED;
|
|
if (s->options.lpc_type == FF_LPC_TYPE_NONE ||
|
|
s->options.lpc_type == FF_LPC_TYPE_FIXED || n <= max_order) {
|
|
uint64_t bits[MAX_FIXED_ORDER+1];
|
|
if (max_order > MAX_FIXED_ORDER)
|
|
max_order = MAX_FIXED_ORDER;
|
|
opt_order = 0;
|
|
bits[0] = UINT32_MAX;
|
|
for (i = min_order; i <= max_order; i++) {
|
|
if (sub->obits == 33) {
|
|
if (encode_residual_fixed_with_residual_limit_33bps(res, smp_33bps, n, i))
|
|
continue;
|
|
} else if (sub->obits + i >= 32) {
|
|
if (encode_residual_fixed_with_residual_limit(res, smp, n, i))
|
|
continue;
|
|
} else
|
|
encode_residual_fixed(res, smp, n, i);
|
|
bits[i] = find_subframe_rice_params(s, sub, i);
|
|
if (bits[i] < bits[opt_order])
|
|
opt_order = i;
|
|
}
|
|
if (opt_order == 0 && bits[0] == UINT32_MAX) {
|
|
/* No predictor found with residuals within <INT32_MIN,INT32_MAX],
|
|
* so encode a verbatim subframe instead */
|
|
DEFAULT_TO_VERBATIM();
|
|
}
|
|
sub->order = opt_order;
|
|
sub->type_code = sub->type | sub->order;
|
|
if (sub->order != max_order) {
|
|
if (sub->obits == 33)
|
|
encode_residual_fixed_with_residual_limit_33bps(res, smp_33bps, n, sub->order);
|
|
else if (sub->obits + i >= 32)
|
|
encode_residual_fixed_with_residual_limit(res, smp, n, sub->order);
|
|
else
|
|
encode_residual_fixed(res, smp, n, sub->order);
|
|
find_subframe_rice_params(s, sub, sub->order);
|
|
}
|
|
return subframe_count_exact(s, sub, sub->order);
|
|
}
|
|
|
|
/* LPC */
|
|
sub->type = FLAC_SUBFRAME_LPC;
|
|
if (sub->obits == 33)
|
|
/* As ff_lpc_calc_coefs is shared with other codecs and the LSB
|
|
* probably isn't predictable anyway, throw away LSB for analysis
|
|
* so it fits 32 bit int and existing function can be used
|
|
* unmodified */
|
|
for (i = 0; i < n; i++)
|
|
smp[i] = smp_33bps[i] >> 1;
|
|
|
|
opt_order = ff_lpc_calc_coefs(&s->lpc_ctx, smp, n, min_order, max_order,
|
|
s->options.lpc_coeff_precision, coefs, shift, s->options.lpc_type,
|
|
s->options.lpc_passes, omethod,
|
|
MIN_LPC_SHIFT, MAX_LPC_SHIFT, 0);
|
|
|
|
if (omethod == ORDER_METHOD_2LEVEL ||
|
|
omethod == ORDER_METHOD_4LEVEL ||
|
|
omethod == ORDER_METHOD_8LEVEL) {
|
|
int levels = 1 << omethod;
|
|
uint64_t bits[1 << ORDER_METHOD_8LEVEL];
|
|
int order = -1;
|
|
int opt_index = levels-1;
|
|
opt_order = max_order-1;
|
|
bits[opt_index] = UINT32_MAX;
|
|
for (i = levels-1; i >= 0; i--) {
|
|
int last_order = order;
|
|
order = min_order + (((max_order-min_order+1) * (i+1)) / levels)-1;
|
|
order = av_clip(order, min_order - 1, max_order - 1);
|
|
if (order == last_order)
|
|
continue;
|
|
if(lpc_encode_choose_datapath(s, sub->obits, res, smp, smp_33bps, n, order+1, coefs[order], shift[order]))
|
|
continue;
|
|
bits[i] = find_subframe_rice_params(s, sub, order+1);
|
|
if (bits[i] < bits[opt_index]) {
|
|
opt_index = i;
|
|
opt_order = order;
|
|
}
|
|
}
|
|
opt_order++;
|
|
} else if (omethod == ORDER_METHOD_SEARCH) {
|
|
// brute-force optimal order search
|
|
uint64_t bits[MAX_LPC_ORDER];
|
|
opt_order = 0;
|
|
bits[0] = UINT32_MAX;
|
|
for (i = min_order-1; i < max_order; i++) {
|
|
if(lpc_encode_choose_datapath(s, sub->obits, res, smp, smp_33bps, n, i+1, coefs[i], shift[i]))
|
|
continue;
|
|
bits[i] = find_subframe_rice_params(s, sub, i+1);
|
|
if (bits[i] < bits[opt_order])
|
|
opt_order = i;
|
|
}
|
|
opt_order++;
|
|
} else if (omethod == ORDER_METHOD_LOG) {
|
|
uint64_t bits[MAX_LPC_ORDER];
|
|
int step;
|
|
|
|
opt_order = min_order - 1 + (max_order-min_order)/3;
|
|
memset(bits, -1, sizeof(bits));
|
|
|
|
for (step = 16; step; step >>= 1) {
|
|
int last = opt_order;
|
|
for (i = last-step; i <= last+step; i += step) {
|
|
if (i < min_order-1 || i >= max_order || bits[i] < UINT32_MAX)
|
|
continue;
|
|
if(lpc_encode_choose_datapath(s, sub->obits, res, smp, smp_33bps, n, i+1, coefs[i], shift[i]))
|
|
continue;
|
|
bits[i] = find_subframe_rice_params(s, sub, i+1);
|
|
if (bits[i] < bits[opt_order])
|
|
opt_order = i;
|
|
}
|
|
}
|
|
opt_order++;
|
|
}
|
|
|
|
if (s->options.multi_dim_quant) {
|
|
int allsteps = 1;
|
|
int i, step, improved;
|
|
int64_t best_score = INT64_MAX;
|
|
int32_t qmax;
|
|
|
|
qmax = (1 << (s->options.lpc_coeff_precision - 1)) - 1;
|
|
|
|
for (i=0; i<opt_order; i++)
|
|
allsteps *= 3;
|
|
|
|
do {
|
|
improved = 0;
|
|
for (step = 0; step < allsteps; step++) {
|
|
int tmp = step;
|
|
int32_t lpc_try[MAX_LPC_ORDER];
|
|
int64_t score = 0;
|
|
int diffsum = 0;
|
|
|
|
for (i=0; i<opt_order; i++) {
|
|
int diff = ((tmp + 1) % 3) - 1;
|
|
lpc_try[i] = av_clip(coefs[opt_order - 1][i] + diff, -qmax, qmax);
|
|
tmp /= 3;
|
|
diffsum += !!diff;
|
|
}
|
|
if (diffsum >8)
|
|
continue;
|
|
|
|
if(lpc_encode_choose_datapath(s, sub->obits, res, smp, smp_33bps, n, opt_order, lpc_try, shift[opt_order-1]))
|
|
continue;
|
|
score = find_subframe_rice_params(s, sub, opt_order);
|
|
if (score < best_score) {
|
|
best_score = score;
|
|
memcpy(coefs[opt_order-1], lpc_try, sizeof(*coefs));
|
|
improved=1;
|
|
}
|
|
}
|
|
} while(improved);
|
|
}
|
|
|
|
sub->order = opt_order;
|
|
sub->type_code = sub->type | (sub->order-1);
|
|
sub->shift = shift[sub->order-1];
|
|
for (i = 0; i < sub->order; i++)
|
|
sub->coefs[i] = coefs[sub->order-1][i];
|
|
|
|
if(lpc_encode_choose_datapath(s, sub->obits, res, smp, smp_33bps, n, sub->order, sub->coefs, sub->shift)) {
|
|
/* No predictor found with residuals within <INT32_MIN,INT32_MAX],
|
|
* so encode a verbatim subframe instead */
|
|
DEFAULT_TO_VERBATIM();
|
|
}
|
|
|
|
find_subframe_rice_params(s, sub, sub->order);
|
|
|
|
return subframe_count_exact(s, sub, sub->order);
|
|
}
|
|
|
|
|
|
static int count_frame_header(FlacEncodeContext *s)
|
|
{
|
|
uint8_t av_unused tmp;
|
|
int count;
|
|
|
|
/*
|
|
<14> Sync code
|
|
<1> Reserved
|
|
<1> Blocking strategy
|
|
<4> Block size in inter-channel samples
|
|
<4> Sample rate
|
|
<4> Channel assignment
|
|
<3> Sample size in bits
|
|
<1> Reserved
|
|
*/
|
|
count = 32;
|
|
|
|
/* coded frame number */
|
|
PUT_UTF8(s->frame_count, tmp, count += 8;)
|
|
|
|
/* explicit block size */
|
|
if (s->frame.bs_code[0] == 6)
|
|
count += 8;
|
|
else if (s->frame.bs_code[0] == 7)
|
|
count += 16;
|
|
|
|
/* explicit sample rate */
|
|
count += ((s->sr_code[0] == 12) + (s->sr_code[0] > 12) * 2) * 8;
|
|
|
|
/* frame header CRC-8 */
|
|
count += 8;
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
static int encode_frame(FlacEncodeContext *s)
|
|
{
|
|
int ch;
|
|
uint64_t count;
|
|
|
|
count = count_frame_header(s);
|
|
|
|
for (ch = 0; ch < s->channels; ch++)
|
|
count += encode_residual_ch(s, ch);
|
|
|
|
count += (8 - (count & 7)) & 7; // byte alignment
|
|
count += 16; // CRC-16
|
|
|
|
count >>= 3;
|
|
if (count > INT_MAX)
|
|
return AVERROR_BUG;
|
|
return count;
|
|
}
|
|
|
|
|
|
static void remove_wasted_bits(FlacEncodeContext *s)
|
|
{
|
|
int ch, i, wasted_bits;
|
|
|
|
for (ch = 0; ch < s->channels; ch++) {
|
|
FlacSubframe *sub = &s->frame.subframes[ch];
|
|
|
|
if (sub->obits > 32) {
|
|
int64_t v = 0;
|
|
for (i = 0; i < s->frame.blocksize; i++) {
|
|
v |= s->frame.samples_33bps[i];
|
|
if (v & 1)
|
|
break;
|
|
}
|
|
|
|
if (!v || (v & 1))
|
|
return;
|
|
|
|
v = ff_ctzll(v);
|
|
|
|
/* If any wasted bits are found, samples are moved
|
|
* from frame.samples_33bps to frame.subframes[ch] */
|
|
for (i = 0; i < s->frame.blocksize; i++)
|
|
sub->samples[i] = s->frame.samples_33bps[i] >> v;
|
|
wasted_bits = v;
|
|
} else {
|
|
int32_t v = 0;
|
|
for (i = 0; i < s->frame.blocksize; i++) {
|
|
v |= sub->samples[i];
|
|
if (v & 1)
|
|
break;
|
|
}
|
|
|
|
if (!v || (v & 1))
|
|
return;
|
|
|
|
v = ff_ctz(v);
|
|
|
|
for (i = 0; i < s->frame.blocksize; i++)
|
|
sub->samples[i] >>= v;
|
|
wasted_bits = v;
|
|
}
|
|
|
|
sub->wasted = wasted_bits;
|
|
sub->obits -= wasted_bits;
|
|
|
|
/* for 24-bit, check if removing wasted bits makes the range better
|
|
* suited for using RICE instead of RICE2 for entropy coding */
|
|
if (sub->obits <= 17)
|
|
sub->rc.coding_mode = CODING_MODE_RICE;
|
|
}
|
|
}
|
|
|
|
|
|
static int estimate_stereo_mode(const int32_t *left_ch, const int32_t *right_ch, int n,
|
|
int max_rice_param, int bps)
|
|
{
|
|
int best;
|
|
uint64_t sum[4];
|
|
uint64_t score[4];
|
|
int k;
|
|
|
|
/* calculate sum of 2nd order residual for each channel */
|
|
sum[0] = sum[1] = sum[2] = sum[3] = 0;
|
|
if(bps < 30) {
|
|
int32_t lt, rt;
|
|
for (int i = 2; i < n; i++) {
|
|
lt = left_ch[i] - 2*left_ch[i-1] + left_ch[i-2];
|
|
rt = right_ch[i] - 2*right_ch[i-1] + right_ch[i-2];
|
|
sum[2] += FFABS((lt + rt) >> 1);
|
|
sum[3] += FFABS(lt - rt);
|
|
sum[0] += FFABS(lt);
|
|
sum[1] += FFABS(rt);
|
|
}
|
|
} else {
|
|
int64_t lt, rt;
|
|
for (int i = 2; i < n; i++) {
|
|
lt = (int64_t)left_ch[i] - 2*(int64_t)left_ch[i-1] + left_ch[i-2];
|
|
rt = (int64_t)right_ch[i] - 2*(int64_t)right_ch[i-1] + right_ch[i-2];
|
|
sum[2] += FFABS((lt + rt) >> 1);
|
|
sum[3] += FFABS(lt - rt);
|
|
sum[0] += FFABS(lt);
|
|
sum[1] += FFABS(rt);
|
|
}
|
|
}
|
|
/* estimate bit counts */
|
|
for (int i = 0; i < 4; i++) {
|
|
k = find_optimal_param(2 * sum[i], n, max_rice_param);
|
|
sum[i] = rice_encode_count( 2 * sum[i], n, k);
|
|
}
|
|
|
|
/* calculate score for each mode */
|
|
score[0] = sum[0] + sum[1];
|
|
score[1] = sum[0] + sum[3];
|
|
score[2] = sum[1] + sum[3];
|
|
score[3] = sum[2] + sum[3];
|
|
|
|
/* return mode with lowest score */
|
|
best = 0;
|
|
for (int i = 1; i < 4; i++)
|
|
if (score[i] < score[best])
|
|
best = i;
|
|
|
|
return best;
|
|
}
|
|
|
|
|
|
/**
|
|
* Perform stereo channel decorrelation.
|
|
*/
|
|
static void channel_decorrelation(FlacEncodeContext *s)
|
|
{
|
|
FlacFrame *frame;
|
|
int32_t *left, *right;
|
|
int64_t *side_33bps;
|
|
int n;
|
|
|
|
frame = &s->frame;
|
|
n = frame->blocksize;
|
|
left = frame->subframes[0].samples;
|
|
right = frame->subframes[1].samples;
|
|
side_33bps = frame->samples_33bps;
|
|
|
|
if (s->channels != 2) {
|
|
frame->ch_mode = FLAC_CHMODE_INDEPENDENT;
|
|
return;
|
|
}
|
|
|
|
if (s->options.ch_mode < 0) {
|
|
int max_rice_param = (1 << frame->subframes[0].rc.coding_mode) - 2;
|
|
frame->ch_mode = estimate_stereo_mode(left, right, n, max_rice_param, s->avctx->bits_per_raw_sample);
|
|
} else
|
|
frame->ch_mode = s->options.ch_mode;
|
|
|
|
/* perform decorrelation and adjust bits-per-sample */
|
|
if (frame->ch_mode == FLAC_CHMODE_INDEPENDENT)
|
|
return;
|
|
if(s->avctx->bits_per_raw_sample == 32) {
|
|
if (frame->ch_mode == FLAC_CHMODE_MID_SIDE) {
|
|
int64_t tmp;
|
|
for (int i = 0; i < n; i++) {
|
|
tmp = left[i];
|
|
left[i] = (tmp + right[i]) >> 1;
|
|
side_33bps[i] = tmp - right[i];
|
|
}
|
|
frame->subframes[1].obits++;
|
|
} else if (frame->ch_mode == FLAC_CHMODE_LEFT_SIDE) {
|
|
for (int i = 0; i < n; i++)
|
|
side_33bps[i] = (int64_t)left[i] - right[i];
|
|
frame->subframes[1].obits++;
|
|
} else {
|
|
for (int i = 0; i < n; i++)
|
|
side_33bps[i] = (int64_t)left[i] - right[i];
|
|
frame->subframes[0].obits++;
|
|
}
|
|
} else {
|
|
if (frame->ch_mode == FLAC_CHMODE_MID_SIDE) {
|
|
int32_t tmp;
|
|
for (int i = 0; i < n; i++) {
|
|
tmp = left[i];
|
|
left[i] = (tmp + right[i]) >> 1;
|
|
right[i] = tmp - right[i];
|
|
}
|
|
frame->subframes[1].obits++;
|
|
} else if (frame->ch_mode == FLAC_CHMODE_LEFT_SIDE) {
|
|
for (int i = 0; i < n; i++)
|
|
right[i] = left[i] - right[i];
|
|
frame->subframes[1].obits++;
|
|
} else {
|
|
for (int i = 0; i < n; i++)
|
|
left[i] -= right[i];
|
|
frame->subframes[0].obits++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void write_utf8(PutBitContext *pb, uint32_t val)
|
|
{
|
|
uint8_t tmp;
|
|
PUT_UTF8(val, tmp, put_bits(pb, 8, tmp);)
|
|
}
|
|
|
|
|
|
static void write_frame_header(FlacEncodeContext *s)
|
|
{
|
|
FlacFrame *frame;
|
|
int crc;
|
|
|
|
frame = &s->frame;
|
|
|
|
put_bits(&s->pb, 16, 0xFFF8);
|
|
put_bits(&s->pb, 4, frame->bs_code[0]);
|
|
put_bits(&s->pb, 4, s->sr_code[0]);
|
|
|
|
if (frame->ch_mode == FLAC_CHMODE_INDEPENDENT)
|
|
put_bits(&s->pb, 4, s->channels-1);
|
|
else
|
|
put_bits(&s->pb, 4, frame->ch_mode + FLAC_MAX_CHANNELS - 1);
|
|
|
|
put_bits(&s->pb, 3, s->bps_code);
|
|
put_bits(&s->pb, 1, 0);
|
|
write_utf8(&s->pb, s->frame_count);
|
|
|
|
if (frame->bs_code[0] == 6)
|
|
put_bits(&s->pb, 8, frame->bs_code[1]);
|
|
else if (frame->bs_code[0] == 7)
|
|
put_bits(&s->pb, 16, frame->bs_code[1]);
|
|
|
|
if (s->sr_code[0] == 12)
|
|
put_bits(&s->pb, 8, s->sr_code[1]);
|
|
else if (s->sr_code[0] > 12)
|
|
put_bits(&s->pb, 16, s->sr_code[1]);
|
|
|
|
flush_put_bits(&s->pb);
|
|
crc = av_crc(av_crc_get_table(AV_CRC_8_ATM), 0, s->pb.buf,
|
|
put_bytes_output(&s->pb));
|
|
put_bits(&s->pb, 8, crc);
|
|
}
|
|
|
|
|
|
static inline void set_sr_golomb_flac(PutBitContext *pb, int i, int k)
|
|
{
|
|
unsigned v, e;
|
|
|
|
v = ((unsigned)(i) << 1) ^ (i >> 31);
|
|
|
|
e = (v >> k) + 1;
|
|
while (e > 31) {
|
|
put_bits(pb, 31, 0);
|
|
e -= 31;
|
|
}
|
|
put_bits(pb, e, 1);
|
|
if (k) {
|
|
unsigned mask = UINT32_MAX >> (32-k);
|
|
put_bits(pb, k, v & mask);
|
|
}
|
|
}
|
|
|
|
|
|
static void write_subframes(FlacEncodeContext *s)
|
|
{
|
|
int ch;
|
|
|
|
for (ch = 0; ch < s->channels; ch++) {
|
|
FlacSubframe *sub = &s->frame.subframes[ch];
|
|
int p, porder, psize;
|
|
int32_t *part_end;
|
|
int32_t *res = sub->residual;
|
|
int32_t *frame_end = &sub->residual[s->frame.blocksize];
|
|
|
|
/* subframe header */
|
|
put_bits(&s->pb, 1, 0);
|
|
put_bits(&s->pb, 6, sub->type_code);
|
|
put_bits(&s->pb, 1, !!sub->wasted);
|
|
if (sub->wasted)
|
|
put_bits(&s->pb, sub->wasted, 1);
|
|
|
|
/* subframe */
|
|
if (sub->type == FLAC_SUBFRAME_CONSTANT) {
|
|
if(sub->obits == 33)
|
|
put_sbits63(&s->pb, 33, s->frame.samples_33bps[0]);
|
|
else if(sub->obits == 32)
|
|
put_bits32(&s->pb, res[0]);
|
|
else
|
|
put_sbits(&s->pb, sub->obits, res[0]);
|
|
} else if (sub->type == FLAC_SUBFRAME_VERBATIM) {
|
|
if (sub->obits == 33) {
|
|
int64_t *res64 = s->frame.samples_33bps;
|
|
int64_t *frame_end64 = &s->frame.samples_33bps[s->frame.blocksize];
|
|
while (res64 < frame_end64)
|
|
put_sbits63(&s->pb, 33, (*res64++));
|
|
} else if (sub->obits == 32) {
|
|
while (res < frame_end)
|
|
put_bits32(&s->pb, *res++);
|
|
} else {
|
|
while (res < frame_end)
|
|
put_sbits(&s->pb, sub->obits, *res++);
|
|
}
|
|
} else {
|
|
/* warm-up samples */
|
|
if (sub->obits == 33) {
|
|
for (int i = 0; i < sub->order; i++)
|
|
put_sbits63(&s->pb, 33, s->frame.samples_33bps[i]);
|
|
res += sub->order;
|
|
} else if (sub->obits == 32) {
|
|
for (int i = 0; i < sub->order; i++)
|
|
put_bits32(&s->pb, *res++);
|
|
} else {
|
|
for (int i = 0; i < sub->order; i++)
|
|
put_sbits(&s->pb, sub->obits, *res++);
|
|
}
|
|
|
|
/* LPC coefficients */
|
|
if (sub->type == FLAC_SUBFRAME_LPC) {
|
|
int cbits = s->options.lpc_coeff_precision;
|
|
put_bits( &s->pb, 4, cbits-1);
|
|
put_sbits(&s->pb, 5, sub->shift);
|
|
for (int i = 0; i < sub->order; i++)
|
|
put_sbits(&s->pb, cbits, sub->coefs[i]);
|
|
}
|
|
|
|
/* rice-encoded block */
|
|
put_bits(&s->pb, 2, sub->rc.coding_mode - 4);
|
|
|
|
/* partition order */
|
|
porder = sub->rc.porder;
|
|
psize = s->frame.blocksize >> porder;
|
|
put_bits(&s->pb, 4, porder);
|
|
|
|
/* residual */
|
|
part_end = &sub->residual[psize];
|
|
for (p = 0; p < 1 << porder; p++) {
|
|
int k = sub->rc.params[p];
|
|
put_bits(&s->pb, sub->rc.coding_mode, k);
|
|
while (res < part_end)
|
|
set_sr_golomb_flac(&s->pb, *res++, k);
|
|
part_end = FFMIN(frame_end, part_end + psize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void write_frame_footer(FlacEncodeContext *s)
|
|
{
|
|
int crc;
|
|
flush_put_bits(&s->pb);
|
|
crc = av_bswap16(av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, s->pb.buf,
|
|
put_bytes_output(&s->pb)));
|
|
put_bits(&s->pb, 16, crc);
|
|
flush_put_bits(&s->pb);
|
|
}
|
|
|
|
|
|
static int write_frame(FlacEncodeContext *s, AVPacket *avpkt)
|
|
{
|
|
init_put_bits(&s->pb, avpkt->data, avpkt->size);
|
|
write_frame_header(s);
|
|
write_subframes(s);
|
|
write_frame_footer(s);
|
|
return put_bytes_output(&s->pb);
|
|
}
|
|
|
|
|
|
static int update_md5_sum(FlacEncodeContext *s, const void *samples)
|
|
{
|
|
const uint8_t *buf;
|
|
int buf_size = s->frame.blocksize * s->channels *
|
|
((s->avctx->bits_per_raw_sample + 7) / 8);
|
|
|
|
if (s->avctx->bits_per_raw_sample > 16 || HAVE_BIGENDIAN) {
|
|
av_fast_malloc(&s->md5_buffer, &s->md5_buffer_size, buf_size);
|
|
if (!s->md5_buffer)
|
|
return AVERROR(ENOMEM);
|
|
}
|
|
|
|
if (s->avctx->bits_per_raw_sample <= 16) {
|
|
buf = (const uint8_t *)samples;
|
|
#if HAVE_BIGENDIAN
|
|
s->bdsp.bswap16_buf((uint16_t *) s->md5_buffer,
|
|
(const uint16_t *) samples, buf_size / 2);
|
|
buf = s->md5_buffer;
|
|
#endif
|
|
} else if (s->avctx->bits_per_raw_sample <= 24) {
|
|
int i;
|
|
const int32_t *samples0 = samples;
|
|
uint8_t *tmp = s->md5_buffer;
|
|
|
|
for (i = 0; i < s->frame.blocksize * s->channels; i++) {
|
|
int32_t v = samples0[i] >> 8;
|
|
AV_WL24(tmp + 3*i, v);
|
|
}
|
|
buf = s->md5_buffer;
|
|
} else {
|
|
/* s->avctx->bits_per_raw_sample <= 32 */
|
|
int i;
|
|
const int32_t *samples0 = samples;
|
|
uint8_t *tmp = s->md5_buffer;
|
|
|
|
for (i = 0; i < s->frame.blocksize * s->channels; i++)
|
|
AV_WL32(tmp + 4*i, samples0[i]);
|
|
buf = s->md5_buffer;
|
|
}
|
|
av_md5_update(s->md5ctx, buf, buf_size);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int flac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
|
|
const AVFrame *frame, int *got_packet_ptr)
|
|
{
|
|
FlacEncodeContext *s;
|
|
int frame_bytes, out_bytes, ret;
|
|
|
|
s = avctx->priv_data;
|
|
|
|
/* when the last block is reached, update the header in extradata */
|
|
if (!frame) {
|
|
s->max_framesize = s->max_encoded_framesize;
|
|
av_md5_final(s->md5ctx, s->md5sum);
|
|
write_streaminfo(s, avctx->extradata);
|
|
|
|
if (!s->flushed) {
|
|
uint8_t *side_data = av_packet_new_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA,
|
|
avctx->extradata_size);
|
|
if (!side_data)
|
|
return AVERROR(ENOMEM);
|
|
memcpy(side_data, avctx->extradata, avctx->extradata_size);
|
|
|
|
avpkt->pts = s->next_pts;
|
|
|
|
*got_packet_ptr = 1;
|
|
s->flushed = 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* change max_framesize for small final frame */
|
|
if (frame->nb_samples < s->frame.blocksize) {
|
|
s->max_framesize = flac_get_max_frame_size(frame->nb_samples,
|
|
s->channels,
|
|
avctx->bits_per_raw_sample);
|
|
}
|
|
|
|
init_frame(s, frame->nb_samples);
|
|
|
|
copy_samples(s, frame->data[0]);
|
|
|
|
channel_decorrelation(s);
|
|
|
|
remove_wasted_bits(s);
|
|
|
|
frame_bytes = encode_frame(s);
|
|
|
|
/* Fall back on verbatim mode if the compressed frame is larger than it
|
|
would be if encoded uncompressed. */
|
|
if (frame_bytes < 0 || frame_bytes > s->max_framesize) {
|
|
s->frame.verbatim_only = 1;
|
|
frame_bytes = encode_frame(s);
|
|
if (frame_bytes < 0) {
|
|
av_log(avctx, AV_LOG_ERROR, "Bad frame count\n");
|
|
return frame_bytes;
|
|
}
|
|
}
|
|
|
|
if ((ret = ff_get_encode_buffer(avctx, avpkt, frame_bytes, 0)) < 0)
|
|
return ret;
|
|
|
|
out_bytes = write_frame(s, avpkt);
|
|
|
|
s->frame_count++;
|
|
s->sample_count += frame->nb_samples;
|
|
if ((ret = update_md5_sum(s, frame->data[0])) < 0) {
|
|
av_log(avctx, AV_LOG_ERROR, "Error updating MD5 checksum\n");
|
|
return ret;
|
|
}
|
|
if (out_bytes > s->max_encoded_framesize)
|
|
s->max_encoded_framesize = out_bytes;
|
|
if (out_bytes < s->min_framesize)
|
|
s->min_framesize = out_bytes;
|
|
|
|
s->next_pts = frame->pts + ff_samples_to_time_base(avctx, frame->nb_samples);
|
|
|
|
av_shrink_packet(avpkt, out_bytes);
|
|
|
|
*got_packet_ptr = 1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
static av_cold int flac_encode_close(AVCodecContext *avctx)
|
|
{
|
|
FlacEncodeContext *s = avctx->priv_data;
|
|
|
|
av_freep(&s->md5ctx);
|
|
av_freep(&s->md5_buffer);
|
|
ff_lpc_end(&s->lpc_ctx);
|
|
return 0;
|
|
}
|
|
|
|
#define FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
|
|
static const AVOption options[] = {
|
|
{ "lpc_coeff_precision", "LPC coefficient precision", offsetof(FlacEncodeContext, options.lpc_coeff_precision), AV_OPT_TYPE_INT, {.i64 = 15 }, 0, MAX_LPC_PRECISION, FLAGS },
|
|
{ "lpc_type", "LPC algorithm", offsetof(FlacEncodeContext, options.lpc_type), AV_OPT_TYPE_INT, {.i64 = FF_LPC_TYPE_DEFAULT }, FF_LPC_TYPE_DEFAULT, FF_LPC_TYPE_NB-1, FLAGS, .unit = "lpc_type" },
|
|
{ "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LPC_TYPE_NONE }, INT_MIN, INT_MAX, FLAGS, .unit = "lpc_type" },
|
|
{ "fixed", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LPC_TYPE_FIXED }, INT_MIN, INT_MAX, FLAGS, .unit = "lpc_type" },
|
|
{ "levinson", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LPC_TYPE_LEVINSON }, INT_MIN, INT_MAX, FLAGS, .unit = "lpc_type" },
|
|
{ "cholesky", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LPC_TYPE_CHOLESKY }, INT_MIN, INT_MAX, FLAGS, .unit = "lpc_type" },
|
|
{ "lpc_passes", "Number of passes to use for Cholesky factorization during LPC analysis", offsetof(FlacEncodeContext, options.lpc_passes), AV_OPT_TYPE_INT, {.i64 = 2 }, 1, INT_MAX, FLAGS },
|
|
{ "min_partition_order", NULL, offsetof(FlacEncodeContext, options.min_partition_order), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, MAX_PARTITION_ORDER, FLAGS },
|
|
{ "max_partition_order", NULL, offsetof(FlacEncodeContext, options.max_partition_order), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, MAX_PARTITION_ORDER, FLAGS },
|
|
{ "prediction_order_method", "Search method for selecting prediction order", offsetof(FlacEncodeContext, options.prediction_order_method), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, ORDER_METHOD_LOG, FLAGS, .unit = "predm" },
|
|
{ "estimation", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = ORDER_METHOD_EST }, INT_MIN, INT_MAX, FLAGS, .unit = "predm" },
|
|
{ "2level", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = ORDER_METHOD_2LEVEL }, INT_MIN, INT_MAX, FLAGS, .unit = "predm" },
|
|
{ "4level", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = ORDER_METHOD_4LEVEL }, INT_MIN, INT_MAX, FLAGS, .unit = "predm" },
|
|
{ "8level", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = ORDER_METHOD_8LEVEL }, INT_MIN, INT_MAX, FLAGS, .unit = "predm" },
|
|
{ "search", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = ORDER_METHOD_SEARCH }, INT_MIN, INT_MAX, FLAGS, .unit = "predm" },
|
|
{ "log", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = ORDER_METHOD_LOG }, INT_MIN, INT_MAX, FLAGS, .unit = "predm" },
|
|
{ "ch_mode", "Stereo decorrelation mode", offsetof(FlacEncodeContext, options.ch_mode), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, FLAC_CHMODE_MID_SIDE, FLAGS, .unit = "ch_mode" },
|
|
{ "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX, FLAGS, .unit = "ch_mode" },
|
|
{ "indep", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FLAC_CHMODE_INDEPENDENT }, INT_MIN, INT_MAX, FLAGS, .unit = "ch_mode" },
|
|
{ "left_side", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FLAC_CHMODE_LEFT_SIDE }, INT_MIN, INT_MAX, FLAGS, .unit = "ch_mode" },
|
|
{ "right_side", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FLAC_CHMODE_RIGHT_SIDE }, INT_MIN, INT_MAX, FLAGS, .unit = "ch_mode" },
|
|
{ "mid_side", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FLAC_CHMODE_MID_SIDE }, INT_MIN, INT_MAX, FLAGS, .unit = "ch_mode" },
|
|
{ "exact_rice_parameters", "Calculate rice parameters exactly", offsetof(FlacEncodeContext, options.exact_rice_parameters), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
|
|
{ "multi_dim_quant", "Multi-dimensional quantization", offsetof(FlacEncodeContext, options.multi_dim_quant), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
|
|
{ "min_prediction_order", NULL, offsetof(FlacEncodeContext, options.min_prediction_order), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, MAX_LPC_ORDER, FLAGS },
|
|
{ "max_prediction_order", NULL, offsetof(FlacEncodeContext, options.max_prediction_order), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, MAX_LPC_ORDER, FLAGS },
|
|
|
|
{ NULL },
|
|
};
|
|
|
|
static const AVClass flac_encoder_class = {
|
|
.class_name = "FLAC encoder",
|
|
.item_name = av_default_item_name,
|
|
.option = options,
|
|
.version = LIBAVUTIL_VERSION_INT,
|
|
};
|
|
|
|
const FFCodec ff_flac_encoder = {
|
|
.p.name = "flac",
|
|
CODEC_LONG_NAME("FLAC (Free Lossless Audio Codec)"),
|
|
.p.type = AVMEDIA_TYPE_AUDIO,
|
|
.p.id = AV_CODEC_ID_FLAC,
|
|
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
|
|
AV_CODEC_CAP_SMALL_LAST_FRAME |
|
|
AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
|
|
.priv_data_size = sizeof(FlacEncodeContext),
|
|
.init = flac_encode_init,
|
|
FF_CODEC_ENCODE_CB(flac_encode_frame),
|
|
.close = flac_encode_close,
|
|
.p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
|
|
AV_SAMPLE_FMT_S32,
|
|
AV_SAMPLE_FMT_NONE },
|
|
.p.priv_class = &flac_encoder_class,
|
|
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_EOF_FLUSH,
|
|
};
|