X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fflacenc.c;h=2277cf3f5fb9bd9401154e755ee50735f3c14117;hb=3a651f599a18b023602370b67a77eb0efa309b20;hp=b00df9580bc6a58c1938d4235ab200c4670b99f9;hpb=13e1ee6c84f095b052026b18611ce68c76666474;p=ffmpeg diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c index b00df9580bc..2277cf3f5fb 100644 --- a/libavcodec/flacenc.c +++ b/libavcodec/flacenc.c @@ -24,7 +24,7 @@ #include "libavutil/md5.h" #include "libavutil/opt.h" #include "avcodec.h" -#include "dsputil.h" +#include "bswapdsp.h" #include "get_bits.h" #include "golomb.h" #include "internal.h" @@ -43,7 +43,11 @@ #define MAX_PARTITIONS (1 << MAX_PARTITION_ORDER) #define MAX_LPC_PRECISION 15 #define MAX_LPC_SHIFT 15 -#define MAX_RICE_PARAM 14 + +enum CodingMode { + CODING_MODE_RICE = 4, + CODING_MODE_RICE2 = 5, +}; typedef struct CompressionOptions { int compression_level; @@ -60,6 +64,7 @@ typedef struct CompressionOptions { } CompressionOptions; typedef struct RiceContext { + enum CodingMode coding_mode; int porder; int params[MAX_PARTITIONS]; } RiceContext; @@ -107,8 +112,11 @@ typedef struct FlacEncodeContext { struct AVMD5 *md5ctx; uint8_t *md5_buffer; unsigned int md5_buffer_size; - DSPContext dsp; + BswapDSPContext bdsp; FLACDSPContext flac_dsp; + + int flushed; + int64_t next_pts; } FlacEncodeContext; @@ -389,16 +397,10 @@ static av_cold int flac_encode_init(AVCodecContext *avctx) s->frame_count = 0; s->min_framesize = s->max_framesize; -#if FF_API_OLD_ENCODE_AUDIO - avctx->coded_frame = avcodec_alloc_frame(); - if (!avctx->coded_frame) - return AVERROR(ENOMEM); -#endif - ret = ff_lpc_init(&s->lpc_ctx, avctx->frame_size, s->options.max_prediction_order, FF_LPC_TYPE_LEVINSON); - ff_dsputil_init(&s->dsp, avctx); + ff_bswapdsp_init(&s->bdsp); ff_flacdsp_init(&s->flac_dsp, avctx->sample_fmt, avctx->bits_per_raw_sample); @@ -435,8 +437,15 @@ static void init_frame(FlacEncodeContext *s, int nb_samples) } for (ch = 0; ch < s->channels; ch++) { - frame->subframes[ch].wasted = 0; - frame->subframes[ch].obits = s->avctx->bits_per_raw_sample; + 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; @@ -518,7 +527,7 @@ static uint64_t subframe_count_exact(FlacEncodeContext *s, FlacSubframe *sub, part_end = psize; for (p = 0; p < 1 << porder; p++) { int k = sub->rc.params[p]; - count += 4; + 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); @@ -534,7 +543,7 @@ static uint64_t subframe_count_exact(FlacEncodeContext *s, FlacSubframe *sub, /** * Solve for d/dk(rice_encode_count) = n-((sum-(n>>1))>>(k+1)) = 0. */ -static int find_optimal_param(uint64_t sum, int n) +static int find_optimal_param(uint64_t sum, int n, int max_param) { int k; uint64_t sum2; @@ -543,7 +552,7 @@ static int find_optimal_param(uint64_t sum, int n) return 0; sum2 = sum - (n >> 1); k = av_log2(av_clipl_int32(sum2 / n)); - return FFMIN(k, MAX_RICE_PARAM); + return FFMIN(k, max_param); } @@ -551,15 +560,17 @@ static uint64_t calc_optimal_rice_params(RiceContext *rc, int porder, uint64_t *sums, int n, int pred_order) { int i; - int k, cnt, part; + int k, cnt, part, max_param; uint64_t all_bits; + max_param = (1 << rc->coding_mode) - 2; + part = (1 << porder); all_bits = 4 * part; cnt = (n >> porder) - pred_order; for (i = 0; i < part; i++) { - k = find_optimal_param(sums[i], cnt); + k = find_optimal_param(sums[i], cnt, max_param); rc->params[i] = k; all_bits += rice_encode_count(sums[i], cnt, k); cnt = n >> porder; @@ -606,12 +617,14 @@ static uint64_t calc_rice_params(RiceContext *rc, int pmin, int pmax, int opt_porder; RiceContext tmp_rc; uint32_t *udata; - uint64_t sums[MAX_PARTITION_ORDER+1][MAX_PARTITIONS]; + uint64_t sums[MAX_PARTITION_ORDER + 1][MAX_PARTITIONS] = { { 0 } }; assert(pmin >= 0 && pmin <= MAX_PARTITION_ORDER); assert(pmax >= 0 && pmax <= MAX_PARTITION_ORDER); assert(pmin <= pmax); + tmp_rc.coding_mode = rc->coding_mode; + udata = av_malloc(n * sizeof(uint32_t)); for (i = 0; i < n; i++) udata[i] = (2*data[i]) ^ (data[i]>>31); @@ -650,7 +663,7 @@ static uint64_t find_subframe_rice_params(FlacEncodeContext *s, 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 + 4; + 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, pmin, pmax, sub->residual, @@ -783,14 +796,16 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch) omethod == ORDER_METHOD_8LEVEL) { int levels = 1 << omethod; uint64_t bits[1 << ORDER_METHOD_8LEVEL]; - int order; + 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; - if (order < 0) - order = 0; + order = av_clip(order, min_order - 1, max_order - 1); + if (order == last_order) + continue; s->flac_dsp.lpc_encode(res, smp, n, order+1, coefs[order], shift[order]); bits[i] = find_subframe_rice_params(s, sub, order+1); @@ -925,12 +940,18 @@ static void remove_wasted_bits(FlacEncodeContext *s) sub->wasted = v; sub->obits -= v; + + /* 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(int32_t *left_ch, int32_t *right_ch, int n) +static int estimate_stereo_mode(int32_t *left_ch, int32_t *right_ch, int n, + int max_rice_param) { int i, best; int32_t lt, rt; @@ -950,7 +971,7 @@ static int estimate_stereo_mode(int32_t *left_ch, int32_t *right_ch, int n) } /* estimate bit counts */ for (i = 0; i < 4; i++) { - k = find_optimal_param(2 * sum[i], n); + k = find_optimal_param(2 * sum[i], n, max_rice_param); sum[i] = rice_encode_count( 2 * sum[i], n, k); } @@ -989,9 +1010,10 @@ static void channel_decorrelation(FlacEncodeContext *s) return; } - if (s->options.ch_mode < 0) - frame->ch_mode = estimate_stereo_mode(left, right, n); - else + 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); + } else frame->ch_mode = s->options.ch_mode; /* perform decorrelation and adjust bits-per-sample */ @@ -1100,7 +1122,7 @@ static void write_subframes(FlacEncodeContext *s) } /* rice-encoded block */ - put_bits(&s->pb, 2, 0); + put_bits(&s->pb, 2, sub->rc.coding_mode - 4); /* partition order */ porder = sub->rc.porder; @@ -1111,7 +1133,7 @@ static void write_subframes(FlacEncodeContext *s) part_end = &sub->residual[psize]; for (p = 0; p < 1 << porder; p++) { int k = sub->rc.params[p]; - put_bits(&s->pb, 4, k); + put_bits(&s->pb, sub->rc.coding_mode, k); while (res < part_end) set_sr_golomb_flac(&s->pb, *res++, k, INT32_MAX, 0); part_end = FFMIN(frame_end, part_end + psize); @@ -1157,8 +1179,8 @@ static int update_md5_sum(FlacEncodeContext *s, const void *samples) if (s->avctx->bits_per_raw_sample <= 16) { buf = (const uint8_t *)samples; #if HAVE_BIGENDIAN - s->dsp.bswap16_buf((uint16_t *)s->md5_buffer, - (const uint16_t *)samples, buf_size / 2); + s->bdsp.bswap16_buf((uint16_t *) s->md5_buffer, + (const uint16_t *) samples, buf_size / 2); buf = s->md5_buffer; #endif } else { @@ -1193,6 +1215,20 @@ static int flac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, s->max_framesize = s->max_encoded_framesize; av_md5_final(s->md5ctx, s->md5sum); write_streaminfo(s, avctx->extradata); + + if (avctx->side_data_only_packets && !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; } @@ -1213,7 +1249,7 @@ static int flac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, frame_bytes = encode_frame(s); - /* fallback to verbatim mode if the compressed frame is larger than it + /* 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; @@ -1245,6 +1281,9 @@ static int flac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, avpkt->pts = frame->pts; avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples); avpkt->size = out_bytes; + + s->next_pts = avpkt->pts + avpkt->duration; + *got_packet_ptr = 1; return 0; } @@ -1260,9 +1299,6 @@ static av_cold int flac_encode_close(AVCodecContext *avctx) } av_freep(&avctx->extradata); avctx->extradata_size = 0; -#if FF_API_OLD_ENCODE_AUDIO - av_freep(&avctx->coded_frame); -#endif return 0; } @@ -1274,7 +1310,7 @@ static const AVOption options[] = { { "fixed", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LPC_TYPE_FIXED }, INT_MIN, INT_MAX, FLAGS, "lpc_type" }, { "levinson", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LPC_TYPE_LEVINSON }, INT_MIN, INT_MAX, FLAGS, "lpc_type" }, { "cholesky", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LPC_TYPE_CHOLESKY }, INT_MIN, INT_MAX, FLAGS, "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 = -1 }, INT_MIN, INT_MAX, FLAGS }, +{ "lpc_passes", "Number of passes to use for Cholesky factorization during LPC analysis", offsetof(FlacEncodeContext, options.lpc_passes), AV_OPT_TYPE_INT, {.i64 = 1 }, 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, "predm" }, @@ -1302,6 +1338,7 @@ static const AVClass flac_encoder_class = { AVCodec ff_flac_encoder = { .name = "flac", + .long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"), .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_FLAC, .priv_data_size = sizeof(FlacEncodeContext), @@ -1312,6 +1349,5 @@ AVCodec ff_flac_encoder = { .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, - .long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"), .priv_class = &flac_encoder_class, };