From 92fec47d69d2c3187bea2f246984e03ec6ca3c3c Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 2 Nov 2012 22:49:04 +0100 Subject: [PATCH 1/6] build: The A64 muxer depends on rawenc.o for ff_raw_write_packet() --- libavformat/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index acf0500de1..ed030bd361 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -24,7 +24,7 @@ OBJS = allformats.o \ OBJS-$(CONFIG_NETWORK) += network.o # muxers/demuxers -OBJS-$(CONFIG_A64_MUXER) += a64.o +OBJS-$(CONFIG_A64_MUXER) += a64.o rawenc.o OBJS-$(CONFIG_AAC_DEMUXER) += aacdec.o rawdec.o OBJS-$(CONFIG_AC3_DEMUXER) += ac3dec.o rawdec.o OBJS-$(CONFIG_AC3_MUXER) += rawenc.o From 2253df76c1913b5fcc71a9f4f254c78acd9be669 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 20 Oct 2012 12:21:41 +0200 Subject: [PATCH 2/6] fate: aac: Place LATM tests and general AAC tests in different groups --- tests/fate/aac.mak | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/fate/aac.mak b/tests/fate/aac.mak index 9d52dae49b..0368798ac5 100644 --- a/tests/fate/aac.mak +++ b/tests/fate/aac.mak @@ -46,7 +46,7 @@ FATE_AAC += fate-aac-al_sbr_ps_06_ur fate-aac-al_sbr_ps_06_ur: CMD = pcm -i $(SAMPLES)/aac/al_sbr_ps_06_new.mp4 fate-aac-al_sbr_ps_06_ur: REF = $(SAMPLES)/aac/al_sbr_ps_06_ur.s16 -FATE_AAC += fate-aac-latm_000000001180bc60 +FATE_AAC_LATM += fate-aac-latm_000000001180bc60 fate-aac-latm_000000001180bc60: CMD = pcm -i $(SAMPLES)/aac/latm_000000001180bc60.mpg fate-aac-latm_000000001180bc60: REF = $(SAMPLES)/aac/latm_000000001180bc60.s16 @@ -54,7 +54,7 @@ FATE_AAC += fate-aac-ap05_48 fate-aac-ap05_48: CMD = pcm -i $(SAMPLES)/aac/ap05_48.mp4 fate-aac-ap05_48: REF = $(SAMPLES)/aac/ap05_48.s16 -FATE_AAC += fate-aac-latm_stereo_to_51 +FATE_AAC_LATM += fate-aac-latm_stereo_to_51 fate-aac-latm_stereo_to_51: CMD = pcm -i $(SAMPLES)/aac/latm_stereo_to_51.ts -channel_layout 5.1 fate-aac-latm_stereo_to_51: REF = $(SAMPLES)/aac/latm_stereo_to_51_ref.s16 @@ -71,7 +71,12 @@ FATE_AAC_CT = sbr_bc-ps_i.3gp \ FATE_AAC += $(FATE_AAC_CT:%=fate-aac-ct-%) -FATE_SAMPLES_AVCONV += $(FATE_AAC) -fate-aac: $(FATE_AAC) -$(FATE_AAC): CMP = oneoff -$(FATE_AAC): FUZZ = 2 +FATE_AAC_ALL = $(FATE_AAC) $(FATE_AAC_LATM) + +$(FATE_AAC_ALL): CMP = oneoff +$(FATE_AAC_ALL): FUZZ = 2 + +FATE_SAMPLES_AVCONV += $(FATE_AAC_ALL) + +fate-aac: $(FATE_AAC_ALL) +fate-aac-latm: $(FATE_AAC_LATM) From 6a744d261930f8101132bc6d207b6eac41d9cf18 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 25 Oct 2012 15:00:10 -0400 Subject: [PATCH 3/6] flacenc: use a separate buffer for byte-swapping for MD5 checksum on big-endian This is much faster than calculating the MD5 one sample at a time. --- libavcodec/flacenc.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c index b135e4a4e5..d32127081b 100644 --- a/libavcodec/flacenc.c +++ b/libavcodec/flacenc.c @@ -23,6 +23,7 @@ #include "libavutil/md5.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "dsputil.h" #include "get_bits.h" #include "golomb.h" #include "internal.h" @@ -100,6 +101,9 @@ typedef struct FlacEncodeContext { AVCodecContext *avctx; LPCContext lpc_ctx; struct AVMD5 *md5ctx; + uint8_t *md5_buffer; + unsigned int md5_buffer_size; + DSPContext dsp; } FlacEncodeContext; @@ -378,6 +382,8 @@ static av_cold int flac_encode_init(AVCodecContext *avctx) 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); + dprint_compression_options(s); return ret; @@ -1176,17 +1182,26 @@ static int write_frame(FlacEncodeContext *s, AVPacket *avpkt) } -static void update_md5_sum(FlacEncodeContext *s, const int16_t *samples) +static int update_md5_sum(FlacEncodeContext *s, const int16_t *samples) { -#if HAVE_BIGENDIAN - int i; - for (i = 0; i < s->frame.blocksize * s->channels; i++) { - int16_t smp = av_le2ne16(samples[i]); - av_md5_update(s->md5ctx, (uint8_t *)&smp, 2); + const uint8_t *buf; + int buf_size = s->frame.blocksize * s->channels * 2; + + if (HAVE_BIGENDIAN) { + av_fast_malloc(&s->md5_buffer, &s->md5_buffer_size, buf_size); + if (!s->md5_buffer) + return AVERROR(ENOMEM); } -#else - av_md5_update(s->md5ctx, (const uint8_t *)samples, s->frame.blocksize*s->channels*2); + + buf = (const uint8_t *)samples; +#if HAVE_BIGENDIAN + s->dsp.bswap16_buf((uint16_t *)s->md5_buffer, + (const uint16_t *)samples, buf_size / 2); + buf = s->md5_buffer; #endif + av_md5_update(s->md5ctx, buf, buf_size); + + return 0; } @@ -1238,7 +1253,10 @@ static int flac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, s->frame_count++; s->sample_count += frame->nb_samples; - update_md5_sum(s, samples); + if ((ret = update_md5_sum(s, samples)) < 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) @@ -1257,6 +1275,7 @@ static av_cold int flac_encode_close(AVCodecContext *avctx) if (avctx->priv_data) { FlacEncodeContext *s = avctx->priv_data; av_freep(&s->md5ctx); + av_freep(&s->md5_buffer); ff_lpc_end(&s->lpc_ctx); } av_freep(&avctx->extradata); From dfde8a34e5419ac99265e3ecc2e82f378674128a Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 26 Oct 2012 14:48:40 -0400 Subject: [PATCH 4/6] lavu: add av_ctz() for trailing zero bit count --- doc/APIchanges | 3 ++ libavutil/Makefile | 2 +- libavutil/{log2.c => intmath.c} | 5 +++ libavutil/intmath.h | 55 +++++++++++++++++++++++++++++++++ libavutil/version.h | 2 +- 5 files changed, 65 insertions(+), 2 deletions(-) rename libavutil/{log2.c => intmath.c} (95%) diff --git a/doc/APIchanges b/doc/APIchanges index 24defe406b..c8b8fbf32a 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2012-10-22 API changes, most recent first: +2012-xx-xx - xxxxxxx - lavu 52.1.0 - intmath.h + Add av_ctz() for trailing zero bit count + 2012-10-18 - xxxxxxx - lavu 51.45.0 - error.h Add AVERROR_EXPERIMENTAL diff --git a/libavutil/Makefile b/libavutil/Makefile index 45f8e9076c..d4ffd5e7d6 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -67,10 +67,10 @@ OBJS = adler32.o \ float_dsp.o \ imgutils.o \ intfloat_readwrite.o \ + intmath.o \ lfg.o \ lls.o \ log.o \ - log2.o \ log2_tab.o \ mathematics.o \ md5.o \ diff --git a/libavutil/log2.c b/libavutil/intmath.c similarity index 95% rename from libavutil/log2.c rename to libavutil/intmath.c index 18c1b40aaa..8db425c6e9 100644 --- a/libavutil/log2.c +++ b/libavutil/intmath.c @@ -32,3 +32,8 @@ int av_log2_16bit(unsigned v) { return ff_log2_16bit(v); } + +int av_ctz(int v) +{ + return ff_ctz(v); +} diff --git a/libavutil/intmath.h b/libavutil/intmath.h index 2cb313240b..a5ee6525ee 100644 --- a/libavutil/intmath.h +++ b/libavutil/intmath.h @@ -85,6 +85,61 @@ static av_always_inline av_const int ff_log2_16bit_c(unsigned int v) #define av_log2 ff_log2 #define av_log2_16bit ff_log2_16bit +/** + * @} + */ + +/** + * @addtogroup lavu_math + * @{ + */ + +#if HAVE_FAST_CLZ && AV_GCC_VERSION_AT_LEAST(3,4) +#ifndef ff_ctz +#define ff_ctz(v) __builtin_ctz(v) +#endif +#endif + +#ifndef ff_ctz +#define ff_ctz ff_ctz_c +static av_always_inline av_const int ff_ctz_c(int v) +{ + int c; + + if (v & 0x1) + return 0; + + c = 1; + if (!(v & 0xffff)) { + v >>= 16; + c += 16; + } + if (!(v & 0xff)) { + v >>= 8; + c += 8; + } + if (!(v & 0xf)) { + v >>= 4; + c += 4; + } + if (!(v & 0x3)) { + v >>= 2; + c += 2; + } + c -= v & 0x1; + + return c; +} +#endif + +/** + * Trailing zero bit count. + * + * @param v input value. If v is 0, the result is undefined. + * @return the number of trailing 0-bits + */ +int av_ctz(int v); + /** * @} */ diff --git a/libavutil/version.h b/libavutil/version.h index ae7fa7abeb..1659dbd537 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -37,7 +37,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 52 -#define LIBAVUTIL_VERSION_MINOR 0 +#define LIBAVUTIL_VERSION_MINOR 1 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From e78331632208a23b285a70b3cdd487dd54617c46 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 25 Oct 2012 15:07:59 -0400 Subject: [PATCH 5/6] flacenc: remove wasted trailing 0 bits --- libavcodec/flacenc.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c index d32127081b..a96fa3ba49 100644 --- a/libavcodec/flacenc.c +++ b/libavcodec/flacenc.c @@ -20,6 +20,7 @@ */ #include "libavutil/crc.h" +#include "libavutil/intmath.h" #include "libavutil/md5.h" #include "libavutil/opt.h" #include "avcodec.h" @@ -66,6 +67,7 @@ typedef struct FlacSubframe { int type; int type_code; int obits; + int wasted; int order; int32_t coefs[MAX_LPC_ORDER]; int shift; @@ -416,8 +418,10 @@ static void init_frame(FlacEncodeContext *s, int nb_samples) } } - for (ch = 0; ch < s->channels; ch++) + for (ch = 0; ch < s->channels; ch++) { + frame->subframes[ch].wasted = 0; frame->subframes[ch].obits = 16; + } frame->verbatim_only = 0; } @@ -972,6 +976,33 @@ static int encode_frame(FlacEncodeContext *s) } +static void remove_wasted_bits(FlacEncodeContext *s) +{ + int ch, i; + + for (ch = 0; ch < s->channels; ch++) { + FlacSubframe *sub = &s->frame.subframes[ch]; + int32_t v = 0; + + for (i = 0; i < s->frame.blocksize; i++) { + v |= sub->samples[i]; + if (v & 1) + break; + } + + if (v && !(v & 1)) { + v = av_ctz(v); + + for (i = 0; i < s->frame.blocksize; i++) + sub->samples[i] >>= v; + + sub->wasted = v; + sub->obits -= v; + } + } +} + + static int estimate_stereo_mode(int32_t *left_ch, int32_t *right_ch, int n) { int i, best; @@ -1117,7 +1148,9 @@ static void write_subframes(FlacEncodeContext *s) /* subframe header */ put_bits(&s->pb, 1, 0); put_bits(&s->pb, 6, sub->type_code); - put_bits(&s->pb, 1, 0); /* no wasted bits */ + put_bits(&s->pb, 1, !!sub->wasted); + if (sub->wasted) + put_bits(&s->pb, sub->wasted, 1); /* subframe */ if (sub->type == FLAC_SUBFRAME_CONSTANT) { @@ -1235,6 +1268,8 @@ static int flac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, channel_decorrelation(s); + remove_wasted_bits(s); + frame_bytes = encode_frame(s); /* fallback to verbatim mode if the compressed frame is larger than it From 5ff998a233d759d0de83ea6f95c383d03d25d88e Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 26 Oct 2012 23:22:38 -0400 Subject: [PATCH 6/6] flacenc: use uint64_t for bit counts Needed to avoid integer overflows for 24-bit encoding. --- libavcodec/flacenc.c | 58 +++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c index a96fa3ba49..115664a779 100644 --- a/libavcodec/flacenc.c +++ b/libavcodec/flacenc.c @@ -442,10 +442,10 @@ static void copy_samples(FlacEncodeContext *s, const int16_t *samples) } -static int rice_count_exact(int32_t *res, int n, int k) +static uint64_t rice_count_exact(int32_t *res, int n, int k) { int i; - int count = 0; + uint64_t count = 0; for (i = 0; i < n; i++) { int32_t v = -2 * res[i] - 1; @@ -456,12 +456,12 @@ static int rice_count_exact(int32_t *res, int n, int k) } -static int subframe_count_exact(FlacEncodeContext *s, FlacSubframe *sub, - int pred_order) +static uint64_t subframe_count_exact(FlacEncodeContext *s, FlacSubframe *sub, + int pred_order) { int p, porder, psize; int i, part_end; - int count = 0; + uint64_t count = 0; /* subframe header */ count += 8; @@ -508,25 +508,25 @@ static int 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(uint32_t sum, int n) +static int find_optimal_param(uint64_t sum, int n) { int k; - uint32_t sum2; + uint64_t sum2; if (sum <= n >> 1) return 0; sum2 = sum - (n >> 1); - k = av_log2(n < 256 ? FASTDIV(sum2, n) : sum2 / n); + k = av_log2(av_clipl_int32(sum2 / n)); return FFMIN(k, MAX_RICE_PARAM); } -static uint32_t calc_optimal_rice_params(RiceContext *rc, int porder, - uint32_t *sums, int n, int pred_order) +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; - uint32_t all_bits; + uint64_t all_bits; part = (1 << porder); all_bits = 4 * part; @@ -546,7 +546,7 @@ static uint32_t calc_optimal_rice_params(RiceContext *rc, int porder, static void calc_sums(int pmin, int pmax, uint32_t *data, int n, int pred_order, - uint32_t sums[][MAX_PARTITIONS]) + uint64_t sums[][MAX_PARTITIONS]) { int i, j; int parts; @@ -557,7 +557,7 @@ static void calc_sums(int pmin, int pmax, uint32_t *data, int n, int pred_order, res = &data[pred_order]; res_end = &data[n >> pmax]; for (i = 0; i < parts; i++) { - uint32_t sum = 0; + uint64_t sum = 0; while (res < res_end) sum += *(res++); sums[pmax][i] = sum; @@ -572,15 +572,15 @@ static void calc_sums(int pmin, int pmax, uint32_t *data, int n, int pred_order, } -static uint32_t calc_rice_params(RiceContext *rc, int pmin, int pmax, +static uint64_t calc_rice_params(RiceContext *rc, int pmin, int pmax, int32_t *data, int n, int pred_order) { int i; - uint32_t bits[MAX_PARTITION_ORDER+1]; + uint64_t bits[MAX_PARTITION_ORDER+1]; int opt_porder; RiceContext tmp_rc; uint32_t *udata; - uint32_t sums[MAX_PARTITION_ORDER+1][MAX_PARTITIONS]; + uint64_t sums[MAX_PARTITION_ORDER+1][MAX_PARTITIONS]; assert(pmin >= 0 && pmin <= MAX_PARTITION_ORDER); assert(pmax >= 0 && pmax <= MAX_PARTITION_ORDER); @@ -616,7 +616,7 @@ static int get_max_p_order(int max_porder, int n, int order) } -static uint32_t find_subframe_rice_params(FlacEncodeContext *s, +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, @@ -624,7 +624,7 @@ static uint32_t find_subframe_rice_params(FlacEncodeContext *s, int pmax = get_max_p_order(s->options.max_partition_order, s->frame.blocksize, pred_order); - uint32_t bits = 8 + pred_order * sub->obits + 2 + 4; + uint64_t bits = 8 + pred_order * sub->obits + 2 + 4; 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, @@ -829,7 +829,7 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch) 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) { - uint32_t bits[MAX_FIXED_ORDER+1]; + uint64_t bits[MAX_FIXED_ORDER+1]; if (max_order > MAX_FIXED_ORDER) max_order = MAX_FIXED_ORDER; opt_order = 0; @@ -860,7 +860,7 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch) omethod == ORDER_METHOD_4LEVEL || omethod == ORDER_METHOD_8LEVEL) { int levels = 1 << omethod; - uint32_t bits[1 << ORDER_METHOD_8LEVEL]; + uint64_t bits[1 << ORDER_METHOD_8LEVEL]; int order; int opt_index = levels-1; opt_order = max_order-1; @@ -879,7 +879,7 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch) opt_order++; } else if (omethod == ORDER_METHOD_SEARCH) { // brute-force optimal order search - uint32_t bits[MAX_LPC_ORDER]; + uint64_t bits[MAX_LPC_ORDER]; opt_order = 0; bits[0] = UINT32_MAX; for (i = min_order-1; i < max_order; i++) { @@ -890,7 +890,7 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch) } opt_order++; } else if (omethod == ORDER_METHOD_LOG) { - uint32_t bits[MAX_LPC_ORDER]; + uint64_t bits[MAX_LPC_ORDER]; int step; opt_order = min_order - 1 + (max_order-min_order)/3; @@ -962,7 +962,8 @@ static int count_frame_header(FlacEncodeContext *s) static int encode_frame(FlacEncodeContext *s) { - int ch, count; + int ch; + uint64_t count; count = count_frame_header(s); @@ -972,7 +973,10 @@ static int encode_frame(FlacEncodeContext *s) count += (8 - (count & 7)) & 7; // byte alignment count += 16; // CRC-16 - return count >> 3; + count >>= 3; + if (count > INT_MAX) + return AVERROR_BUG; + return count; } @@ -1274,9 +1278,13 @@ static int flac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, /* fallback to verbatim mode if the compressed frame is larger than it would be if encoded uncompressed. */ - if (frame_bytes > s->max_framesize) { + 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_alloc_packet(avpkt, frame_bytes))) {