From a28b0587455f1ed4ac9ac955cc95f95656019ce4 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Sun, 1 May 2011 14:34:31 +0200 Subject: [PATCH 01/13] Update URL to fate samples --- doc/fate.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/fate.txt b/doc/fate.txt index f5f3759309..b23d3f6a64 100644 --- a/doc/fate.txt +++ b/doc/fate.txt @@ -7,7 +7,7 @@ that is provided separately from the actual source distribution. Use the following command to get the fate test samples -# rsync -aL rsync://samples.libav.org:/samples/fate-suite/ fate-suite +# rsync -aL rsync://fate-suite.libav.org:/fate-suite/ fate-suite To inform the build system about the testsuite location, pass `--samples=` to configure or set the SAMPLES Make From e0b33d479cf1cb96e4300b82309e26e6f9c50d6c Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 15 Apr 2011 19:22:42 -0400 Subject: [PATCH 02/13] ac3enc: simplify stereo rematrixing decision options --- doc/encoders.texi | 12 ++++++++++++ libavcodec/ac3enc.c | 48 ++++++++++++--------------------------------- 2 files changed, 25 insertions(+), 35 deletions(-) diff --git a/doc/encoders.texi b/doc/encoders.texi index 59337e2abe..2f3cecde66 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -353,4 +353,16 @@ HDCD A/D Converter @end table +@subheading Other AC-3 Encoding Options + +@table @option + +@item -stereo_rematrixing @var{boolean} +Stereo Rematrixing. Enables/Disables use of rematrixing for stereo input. This +is an optional AC-3 feature that increases quality by selectively encoding +the left/right channels as mid/side. This option is enabled by default, and it +is highly recommended that it be left as enabled except for testing purposes. + +@end table + @c man end ENCODERS diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index 1f3c92aa3d..55f065bda1 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -52,12 +52,6 @@ /** Maximum number of exponent groups. +1 for separate DC exponent. */ #define AC3_MAX_EXP_GROUPS 85 -/* stereo rematrixing algorithms */ -#define AC3_REMATRIXING_IS_STATIC 0x1 -#define AC3_REMATRIXING_SUMS 0 -#define AC3_REMATRIXING_NONE 1 -#define AC3_REMATRIXING_ALWAYS 3 - #if CONFIG_AC3ENC_FLOAT #define MAC_COEF(d,a,b) ((d)+=(a)*(b)) typedef float SampleType; @@ -103,6 +97,7 @@ typedef struct AC3EncOptions { /* other encoding options */ int allow_per_frame_metadata; + int stereo_rematrixing; } AC3EncOptions; /** @@ -170,7 +165,7 @@ typedef struct AC3EncodeContext { int bandwidth_code[AC3_MAX_CHANNELS]; ///< bandwidth code (0 to 60) (chbwcod) int nb_coefs[AC3_MAX_CHANNELS]; - int rematrixing; ///< determines how rematrixing strategy is calculated + int rematrixing_enabled; ///< stereo rematrixing enabled int num_rematrixing_bands; ///< number of rematrixing bands /* bitrate allocation control */ @@ -269,6 +264,8 @@ static const AVOption options[] = { {"ad_conv_type", "A/D Converter Type", OFFSET(ad_converter_type), FF_OPT_TYPE_INT, -1, -1, 1, AC3ENC_PARAM, "ad_conv_type"}, {"standard", "Standard (default)", 0, FF_OPT_TYPE_CONST, 0, INT_MIN, INT_MAX, AC3ENC_PARAM, "ad_conv_type"}, {"hdcd", "HDCD", 0, FF_OPT_TYPE_CONST, 1, INT_MIN, INT_MAX, AC3ENC_PARAM, "ad_conv_type"}, +/* Other Encoding Options */ +{"stereo_rematrixing", "Stereo Rematrixing", OFFSET(stereo_rematrixing), FF_OPT_TYPE_INT, 1, 0, 1, AC3ENC_PARAM}, {NULL} }; @@ -430,28 +427,6 @@ static void apply_mdct(AC3EncodeContext *s) } -/** - * Initialize stereo rematrixing. - * If the strategy does not change for each frame, set the rematrixing flags. - */ -static void rematrixing_init(AC3EncodeContext *s) -{ - if (s->channel_mode == AC3_CHMODE_STEREO) - s->rematrixing = AC3_REMATRIXING_SUMS; - else - s->rematrixing = AC3_REMATRIXING_NONE; - /* NOTE: AC3_REMATRIXING_ALWAYS might be used in - the future in conjunction with channel coupling. */ - - if (s->rematrixing & AC3_REMATRIXING_IS_STATIC) { - int flag = (s->rematrixing == AC3_REMATRIXING_ALWAYS); - s->blocks[0].new_rematrixing_strategy = 1; - memset(s->blocks[0].rematrixing_flags, flag, - sizeof(s->blocks[0].rematrixing_flags)); - } -} - - /** * Determine rematrixing flags for each block and band. */ @@ -461,16 +436,18 @@ static void compute_rematrixing_strategy(AC3EncodeContext *s) int blk, bnd, i; AC3Block *block, *block0; - s->num_rematrixing_bands = 4; - - if (s->rematrixing & AC3_REMATRIXING_IS_STATIC) + if (s->channel_mode != AC3_CHMODE_STEREO) return; + s->num_rematrixing_bands = 4; + nb_coefs = FFMIN(s->nb_coefs[0], s->nb_coefs[1]); for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { block = &s->blocks[blk]; block->new_rematrixing_strategy = !blk; + if (!s->rematrixing_enabled) + continue; for (bnd = 0; bnd < s->num_rematrixing_bands; bnd++) { /* calculate calculate sum of squared coeffs for one band in one block */ int start = ff_ac3_rematrix_band_tab[bnd]; @@ -514,7 +491,7 @@ static void apply_rematrixing(AC3EncodeContext *s) int start, end; uint8_t *flags; - if (s->rematrixing == AC3_REMATRIXING_NONE) + if (!s->rematrixing_enabled) return; nb_coefs = FFMIN(s->nb_coefs[0], s->nb_coefs[1]); @@ -2088,6 +2065,9 @@ static av_cold int validate_options(AVCodecContext *avctx, AC3EncodeContext *s) if (ret) return ret; + s->rematrixing_enabled = s->options.stereo_rematrixing && + (s->channel_mode == AC3_CHMODE_STEREO); + return 0; } @@ -2246,8 +2226,6 @@ static av_cold int ac3_encode_init(AVCodecContext *avctx) set_bandwidth(s); - rematrixing_init(s); - exponent_init(s); bit_alloc_init(s); From 6b2636bba68880450749b3d36a99d584c031342e Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 15 Apr 2011 19:51:06 -0400 Subject: [PATCH 03/13] ac3enc: simplify exponent_init() by calculating exponent_group_tab[] based on exponent group sizes. --- libavcodec/ac3enc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index 55f065bda1..f8136327fb 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -521,11 +521,13 @@ static void apply_rematrixing(AC3EncodeContext *s) */ static av_cold void exponent_init(AC3EncodeContext *s) { - int i; - for (i = 73; i < 256; i++) { - exponent_group_tab[0][i] = (i - 1) / 3; - exponent_group_tab[1][i] = (i + 2) / 6; - exponent_group_tab[2][i] = (i + 8) / 12; + int expstr, i, grpsize; + + for (expstr = EXP_D15-1; expstr <= EXP_D45-1; expstr++) { + grpsize = 3 << expstr; + for (i = 73; i < 256; i++) { + exponent_group_tab[expstr][i] = (i + grpsize - 4) / grpsize; + } } /* LFE */ exponent_group_tab[0][7] = 2; From 987fe2dc55c2de4dd798cbd0ebcdae6a066faff7 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 15 Apr 2011 19:55:09 -0400 Subject: [PATCH 04/13] ac3enc: differentiate between current block and reference block in bit_alloc() --- libavcodec/ac3enc.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index f8136327fb..00cb047374 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -1010,7 +1010,8 @@ static int bit_alloc(AC3EncodeContext *s, int snr_offset) reset_block_bap(s); mantissa_bits = 0; for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { - AC3Block *block; + AC3Block *block = &s->blocks[blk]; + AC3Block *ref_block; // initialize grouped mantissa counts. these are set so that they are // padded to the next whole group size when bits are counted in // compute_mantissa_size_final @@ -1022,14 +1023,17 @@ static int bit_alloc(AC3EncodeContext *s, int snr_offset) blocks within a frame are the exponent values. We can take advantage of that by reusing the bit allocation pointers whenever we reuse exponents. */ - block = s->blocks[blk].exp_ref_block[ch]; + ref_block = block->exp_ref_block[ch]; if (s->exp_strategy[ch][blk] != EXP_REUSE) { - s->ac3dsp.bit_alloc_calc_bap(block->mask[ch], block->psd[ch], 0, - s->nb_coefs[ch], snr_offset, - s->bit_alloc.floor, ff_ac3_bap_tab, - block->bap[ch]); + s->ac3dsp.bit_alloc_calc_bap(ref_block->mask[ch], + ref_block->psd[ch], 0, + s->nb_coefs[ch], snr_offset, + s->bit_alloc.floor, ff_ac3_bap_tab, + ref_block->bap[ch]); } - mantissa_bits += s->ac3dsp.compute_mantissa_size(mant_cnt, block->bap[ch], s->nb_coefs[ch]); + mantissa_bits += s->ac3dsp.compute_mantissa_size(mant_cnt, + ref_block->bap[ch], + s->nb_coefs[ch]); } mantissa_bits += compute_mantissa_size_final(mant_cnt); } From 4142487d1cd8c555e13f156d1cc89f838099db10 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 15 Apr 2011 19:56:42 -0400 Subject: [PATCH 05/13] ac3enc: return error if frame+exponent bits are too large instead of using av_assert2(). This can occur in some very rare cases with low bitrates. --- libavcodec/ac3enc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index 00cb047374..47fd9b6a34 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -1052,7 +1052,8 @@ static int cbr_bit_allocation(AC3EncodeContext *s) int snr_offset, snr_incr; bits_left = 8 * s->frame_size - (s->frame_bits + s->exponent_bits); - av_assert2(bits_left >= 0); + if (bits_left < 0) + return AVERROR(EINVAL); snr_offset = s->coarse_snr_offset << 4; From ba6bce5140f09ed84d54f93fd5c816cbcf150c90 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 15 Apr 2011 22:43:25 -0400 Subject: [PATCH 06/13] ac3enc: merge compute_exp_strategy_ch() into compute_exp_strategy() --- libavcodec/ac3enc.c | 75 ++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 42 deletions(-) diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index 47fd9b6a34..b61021f097 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -560,56 +560,47 @@ static void extract_exponents(AC3EncodeContext *s) #define EXP_DIFF_THRESHOLD 500 -/** - * Calculate exponent strategies for all blocks in a single channel. - */ -static void compute_exp_strategy_ch(AC3EncodeContext *s, uint8_t *exp_strategy, - uint8_t *exp) -{ - int blk, blk1; - int exp_diff; - - /* estimate if the exponent variation & decide if they should be - reused in the next frame */ - exp_strategy[0] = EXP_NEW; - exp += AC3_MAX_COEFS; - for (blk = 1; blk < AC3_MAX_BLOCKS; blk++) { - exp_diff = s->dsp.sad[0](NULL, exp, exp - AC3_MAX_COEFS, 16, 16); - if (exp_diff > EXP_DIFF_THRESHOLD) - exp_strategy[blk] = EXP_NEW; - else - exp_strategy[blk] = EXP_REUSE; - exp += AC3_MAX_COEFS; - } - - /* now select the encoding strategy type : if exponents are often - recoded, we use a coarse encoding */ - blk = 0; - while (blk < AC3_MAX_BLOCKS) { - blk1 = blk + 1; - while (blk1 < AC3_MAX_BLOCKS && exp_strategy[blk1] == EXP_REUSE) - blk1++; - switch (blk1 - blk) { - case 1: exp_strategy[blk] = EXP_D45; break; - case 2: - case 3: exp_strategy[blk] = EXP_D25; break; - default: exp_strategy[blk] = EXP_D15; break; - } - blk = blk1; - } -} - - /** * Calculate exponent strategies for all channels. * Array arrangement is reversed to simplify the per-channel calculation. */ static void compute_exp_strategy(AC3EncodeContext *s) { - int ch, blk; + int ch, blk, blk1; for (ch = 0; ch < s->fbw_channels; ch++) { - compute_exp_strategy_ch(s, s->exp_strategy[ch], s->blocks[0].exp[ch]); + uint8_t *exp_strategy = s->exp_strategy[ch]; + uint8_t *exp = s->blocks[0].exp[ch]; + int exp_diff; + + /* estimate if the exponent variation & decide if they should be + reused in the next frame */ + exp_strategy[0] = EXP_NEW; + exp += AC3_MAX_COEFS; + for (blk = 1; blk < AC3_MAX_BLOCKS; blk++) { + exp_diff = s->dsp.sad[0](NULL, exp, exp - AC3_MAX_COEFS, 16, 16); + if (exp_diff > EXP_DIFF_THRESHOLD) + exp_strategy[blk] = EXP_NEW; + else + exp_strategy[blk] = EXP_REUSE; + exp += AC3_MAX_COEFS; + } + + /* now select the encoding strategy type : if exponents are often + recoded, we use a coarse encoding */ + blk = 0; + while (blk < AC3_MAX_BLOCKS) { + blk1 = blk + 1; + while (blk1 < AC3_MAX_BLOCKS && exp_strategy[blk1] == EXP_REUSE) + blk1++; + switch (blk1 - blk) { + case 1: exp_strategy[blk] = EXP_D45; break; + case 2: + case 3: exp_strategy[blk] = EXP_D25; break; + default: exp_strategy[blk] = EXP_D15; break; + } + blk = blk1; + } } if (s->lfe_on) { ch = s->lfe_channel; From a1d0f511fc3a758146d9384ccaab31743d8bd600 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 15 Apr 2011 22:45:05 -0400 Subject: [PATCH 07/13] ac3enc: remove bandwidth reduction as fallback for bit allocation failure. It was only needed at low bitrates, which now already use a low bandwidth, so the bandwidth reduction is no longer needed. --- libavcodec/ac3enc.c | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index b61021f097..6d899f5a24 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -1122,27 +1122,6 @@ static int downgrade_exponents(AC3EncodeContext *s) } -/** - * Reduce the bandwidth to reduce the number of bits used for a given SNR offset. - * This is a second fallback for when bit allocation still fails after exponents - * have been downgraded. - * @return non-zero if bandwidth reduction was unsuccessful - */ -static int reduce_bandwidth(AC3EncodeContext *s, int min_bw_code) -{ - int ch; - - if (s->bandwidth_code[0] > min_bw_code) { - for (ch = 0; ch < s->fbw_channels; ch++) { - s->bandwidth_code[ch]--; - s->nb_coefs[ch] = s->bandwidth_code[ch] * 3 + 73; - } - return 0; - } - return -1; -} - - /** * Perform bit allocation search. * Finds the SNR offset value that maximizes quality and fits in the specified @@ -1168,15 +1147,6 @@ static int compute_bit_allocation(AC3EncodeContext *s) continue; } - /* fallback 2: reduce bandwidth */ - /* only do this if the user has not specified a specific cutoff - frequency */ - if (!s->cutoff && !reduce_bandwidth(s, 0)) { - process_exponents(s); - ret = compute_bit_allocation(s); - continue; - } - /* fallbacks were not enough... */ break; } From 177fed4e9baa43bdcfb6771195eb85f19412c23e Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 15 Apr 2011 22:49:05 -0400 Subject: [PATCH 08/13] ac3enc: do not store a bandwidth code for each channel. Although AC-3 allows it, it's not very useful. The encoder uses the same code for all full-bandwidth channels. --- libavcodec/ac3enc.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index 6d899f5a24..bf106eb22a 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -162,7 +162,7 @@ typedef struct AC3EncodeContext { int loro_surround_mix_level; ///< Lo/Ro surround mix level code int cutoff; ///< user-specified cutoff frequency, in Hz - int bandwidth_code[AC3_MAX_CHANNELS]; ///< bandwidth code (0 to 60) (chbwcod) + int bandwidth_code; ///< bandwidth code (0 to 60) (chbwcod) int nb_coefs[AC3_MAX_CHANNELS]; int rematrixing_enabled; ///< stereo rematrixing enabled @@ -1407,7 +1407,7 @@ static void output_audio_block(AC3EncodeContext *s, int blk) /* bandwidth */ for (ch = 0; ch < s->fbw_channels; ch++) { if (s->exp_strategy[ch][blk] != EXP_REUSE) - put_bits(&s->pb, 6, s->bandwidth_code[ch]); + put_bits(&s->pb, 6, s->bandwidth_code); } /* exponents */ @@ -2047,22 +2047,21 @@ static av_cold int validate_options(AVCodecContext *avctx, AC3EncodeContext *s) */ static av_cold void set_bandwidth(AC3EncodeContext *s) { - int ch, bw_code; + int ch; if (s->cutoff) { /* calculate bandwidth based on user-specified cutoff frequency */ int fbw_coeffs; fbw_coeffs = s->cutoff * 2 * AC3_MAX_COEFS / s->sample_rate; - bw_code = av_clip((fbw_coeffs - 73) / 3, 0, 60); + s->bandwidth_code = av_clip((fbw_coeffs - 73) / 3, 0, 60); } else { /* use default bandwidth setting */ - bw_code = ac3_bandwidth_tab[s->fbw_channels-1][s->bit_alloc.sr_code][s->frame_size_code/2]; + s->bandwidth_code = ac3_bandwidth_tab[s->fbw_channels-1][s->bit_alloc.sr_code][s->frame_size_code/2]; } /* set number of coefficients for each channel */ for (ch = 0; ch < s->fbw_channels; ch++) { - s->bandwidth_code[ch] = bw_code; - s->nb_coefs[ch] = bw_code * 3 + 73; + s->nb_coefs[ch] = s->bandwidth_code * 3 + 73; } if (s->lfe_on) s->nb_coefs[s->lfe_channel] = 7; /* LFE channel always has 7 coefs */ From 63b1866ae1e19ff0d694746a84e2eac859cda462 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 15 Apr 2011 23:18:33 -0400 Subject: [PATCH 09/13] ac3enc: clip large coefficient values and negative exponents rather than using av_assert2(). --- libavcodec/ac3dsp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/ac3dsp.c b/libavcodec/ac3dsp.c index dccad3b3e8..e3ca37ebdd 100644 --- a/libavcodec/ac3dsp.c +++ b/libavcodec/ac3dsp.c @@ -164,8 +164,10 @@ static void ac3_extract_exponents_c(uint8_t *exp, int32_t *coef, int nb_coefs) if (e >= 24) { e = 24; coef[i] = 0; + } else if (e < 0) { + e = 0; + coef[i] = av_clip(coef[i], -16777215, 16777215); } - av_assert2(e >= 0); } exp[i] = e; } From 3777ea13fbf690003f8b0d83a8bffb6e1d71c3df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reimar=20D=C3=B6ffinger?= Date: Fri, 25 Mar 2011 18:58:07 +0100 Subject: [PATCH 10/13] DPX decoder: add buffer size checks. --- libavcodec/dpx.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/libavcodec/dpx.c b/libavcodec/dpx.c index 36a4a39b5d..82891d6b42 100644 --- a/libavcodec/dpx.c +++ b/libavcodec/dpx.c @@ -68,6 +68,11 @@ static int decode_frame(AVCodecContext *avctx, unsigned int rgbBuffer; + if (avpkt->size <= 0x324) { + av_log(avctx, AV_LOG_ERROR, "Packet too small for DPX header\n"); + return AVERROR_INVALIDDATA; + } + magic_num = AV_RB32(buf); buf += 4; @@ -83,6 +88,10 @@ static int decode_frame(AVCodecContext *avctx, } offset = read32(&buf, endian); + if (avpkt->size <= offset) { + av_log(avctx, AV_LOG_ERROR, "Invalid data start offset\n"); + return AVERROR_INVALIDDATA; + } // Need to end in 0x304 offset from start of file buf = avpkt->data + 0x304; w = read32(&buf, endian); @@ -122,7 +131,7 @@ static int decode_frame(AVCodecContext *avctx, case 10: avctx->pix_fmt = PIX_FMT_RGB48; target_packet_size = 6; - source_packet_size = elements * 2; + source_packet_size = 4; break; case 12: case 16: @@ -156,6 +165,10 @@ static int decode_frame(AVCodecContext *avctx, ptr = p->data[0]; stride = p->linesize[0]; + if (source_packet_size*avctx->width*avctx->height > buf_end - buf) { + av_log(avctx, AV_LOG_ERROR, "Overread buffer. Invalid header?\n"); + return -1; + } switch (bits_per_color) { case 10: for (x = 0; x < avctx->height; x++) { @@ -173,10 +186,6 @@ static int decode_frame(AVCodecContext *avctx, case 8: case 12: // Treat 12-bit as 16-bit case 16: - if (source_packet_size*avctx->width*avctx->height > buf_end - buf) { - av_log(avctx, AV_LOG_ERROR, "Overread buffer. Invalid header?\n"); - return -1; - } if (source_packet_size == target_packet_size) { for (x = 0; x < avctx->height; x++) { memcpy(ptr, buf, target_packet_size*avctx->width); From 406629150cae78a15d7c04b049511b03740b6bfc Mon Sep 17 00:00:00 2001 From: Peter Ross Date: Fri, 1 Apr 2011 23:23:28 +1100 Subject: [PATCH 11/13] DPX decoder: read sample aspect ratio Signed-off-by: Michael Niedermayer --- libavcodec/dpx.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavcodec/dpx.c b/libavcodec/dpx.c index 82891d6b42..0722dd07ef 100644 --- a/libavcodec/dpx.c +++ b/libavcodec/dpx.c @@ -68,7 +68,7 @@ static int decode_frame(AVCodecContext *avctx, unsigned int rgbBuffer; - if (avpkt->size <= 0x324) { + if (avpkt->size <= 1634) { av_log(avctx, AV_LOG_ERROR, "Packet too small for DPX header\n"); return AVERROR_INVALIDDATA; } @@ -106,6 +106,10 @@ static int decode_frame(AVCodecContext *avctx, avctx->bits_per_raw_sample = bits_per_color = buf[0]; + buf += 825; + avctx->sample_aspect_ratio.num = read32(&buf, endian); + avctx->sample_aspect_ratio.den = read32(&buf, endian); + switch (descriptor) { case 51: // RGBA elements = 4; From e27ce0eea36b7631ad26a8f41b93855e3ae7e8f9 Mon Sep 17 00:00:00 2001 From: Peter Ross Date: Sat, 26 Mar 2011 15:12:35 +1100 Subject: [PATCH 12/13] DPX image encoder --- Changelog | 2 + doc/general.texi | 2 +- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 2 +- libavcodec/dpxenc.c | 178 +++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 4 +- 6 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 libavcodec/dpxenc.c diff --git a/Changelog b/Changelog index 144f55c12f..b5ceea9444 100644 --- a/Changelog +++ b/Changelog @@ -6,6 +6,8 @@ version : - Lots of deprecated API cruft removed - fft and imdct optimizations for AVX (Sandy Bridge) processors +- DPX image encoder + version 0.7_beta1: diff --git a/doc/general.texi b/doc/general.texi index e68e83e5f2..598b9bc873 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -279,7 +279,7 @@ following image formats are supported: @tab Only uncompressed GIFs are generated. @item BMP @tab X @tab X @tab Microsoft BMP image -@item DPX @tab @tab X +@item DPX @tab X @tab X @tab Digital Picture Exchange @item JPEG @tab X @tab X @tab Progressive JPEG is not supported. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index fad435dee3..1b704126dd 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -110,6 +110,7 @@ OBJS-$(CONFIG_DNXHD_ENCODER) += dnxhdenc.o dnxhddata.o \ ratecontrol.o mpeg12data.o \ mpegvideo.o OBJS-$(CONFIG_DPX_DECODER) += dpx.o +OBJS-$(CONFIG_DPX_ENCODER) += dpxenc.o OBJS-$(CONFIG_DSICINAUDIO_DECODER) += dsicinav.o OBJS-$(CONFIG_DSICINVIDEO_DECODER) += dsicinav.o OBJS-$(CONFIG_DVBSUB_DECODER) += dvbsubdec.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 40a7e23388..694674ce7b 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -90,7 +90,7 @@ void avcodec_register_all(void) REGISTER_DECODER (CYUV, cyuv); REGISTER_DECODER (DFA, dfa); REGISTER_ENCDEC (DNXHD, dnxhd); - REGISTER_DECODER (DPX, dpx); + REGISTER_ENCDEC (DPX, dpx); REGISTER_DECODER (DSICINVIDEO, dsicinvideo); REGISTER_ENCDEC (DVVIDEO, dvvideo); REGISTER_DECODER (DXA, dxa); diff --git a/libavcodec/dpxenc.c b/libavcodec/dpxenc.c new file mode 100644 index 0000000000..bb783e2d9c --- /dev/null +++ b/libavcodec/dpxenc.c @@ -0,0 +1,178 @@ +/* + * DPX (.dpx) image encoder + * Copyright (c) 2011 Peter Ross + * + * This file is part of Libav. + * + * Libav 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. + * + * Libav 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 Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" + +typedef struct DPXContext { + AVFrame picture; + int big_endian; + int bits_per_component; + int descriptor; +} DPXContext; + +static av_cold int encode_init(AVCodecContext *avctx) +{ + DPXContext *s = avctx->priv_data; + + avctx->coded_frame = &s->picture; + avctx->coded_frame->pict_type = FF_I_TYPE; + avctx->coded_frame->key_frame = 1; + + s->big_endian = 1; + s->bits_per_component = 8; + s->descriptor = 50; /* RGB */ + + switch (avctx->pix_fmt) { + case PIX_FMT_RGB24: + break; + case PIX_FMT_RGBA: + s->descriptor = 51; /* RGBA */ + break; + case PIX_FMT_RGB48LE: + s->big_endian = 0; + case PIX_FMT_RGB48BE: + s->bits_per_component = avctx->bits_per_raw_sample ? avctx->bits_per_raw_sample : 16; + break; + default: + av_log(avctx, AV_LOG_INFO, "unsupported pixel format\n"); + return -1; + } + + return 0; +} + +#define write16(p, value) \ +do { \ + if (s->big_endian) AV_WB16(p, value); \ + else AV_WL16(p, value); \ +} while(0) + +#define write32(p, value) \ +do { \ + if (s->big_endian) AV_WB32(p, value); \ + else AV_WL32(p, value); \ +} while(0) + +static void encode_rgb48_10bit(AVCodecContext *avctx, const AVPicture *pic, + uint8_t *dst) +{ + DPXContext *s = avctx->priv_data; + const uint8_t *src = pic->data[0]; + int x, y; + + for (y = 0; y < avctx->height; y++) { + for (x = 0; x < avctx->width; x++) { + int value; + if ((avctx->pix_fmt & 1)) { + value = ((AV_RB16(src + 6*x + 4) & 0xFFC0) >> 4) + | ((AV_RB16(src + 6*x + 2) & 0xFFC0) << 6) + | ((AV_RB16(src + 6*x + 0) & 0xFFC0) << 16); + } else { + value = ((AV_RL16(src + 6*x + 4) & 0xFFC0) >> 4) + | ((AV_RL16(src + 6*x + 2) & 0xFFC0) << 6) + | ((AV_RL16(src + 6*x + 0) & 0xFFC0) << 16); + } + write32(dst, value); + dst += 4; + } + src += pic->linesize[0]; + } +} + +static int encode_frame(AVCodecContext *avctx, unsigned char *buf, + int buf_size, void *data) +{ + DPXContext *s = avctx->priv_data; + int size; + +#define HEADER_SIZE 1664 /* DPX Generic header */ + if (buf_size < HEADER_SIZE) + return -1; + + memset(buf, 0, HEADER_SIZE); + + /* File information header */ + write32(buf, MKBETAG('S','D','P','X')); + write32(buf + 4, HEADER_SIZE); + memcpy (buf + 8, "V1.0", 4); + write32(buf + 20, 1); /* new image */ + write32(buf + 24, HEADER_SIZE); + memcpy (buf + 160, LIBAVCODEC_IDENT, FFMIN(sizeof(LIBAVCODEC_IDENT), 100)); + write32(buf + 660, 0xFFFFFFFF); /* unencrypted */ + + /* Image information header */ + write16(buf + 768, 0); /* orientation; left to right, top to bottom */ + write16(buf + 770, 1); /* number of elements */ + write32(buf + 772, avctx->width); + write32(buf + 776, avctx->height); + buf[800] = s->descriptor; + buf[801] = 2; /* linear transfer */ + buf[802] = 2; /* linear colorimetric */ + buf[803] = s->bits_per_component; + write16(buf + 804, s->bits_per_component == 10 ? 1 : 0); /* packing method */ + + /* Image source information header */ + write32(buf + 1628, avctx->sample_aspect_ratio.num); + write32(buf + 1632, avctx->sample_aspect_ratio.den); + + switch (s->bits_per_component) { + case 8: + case 16: + size = avpicture_layout(data, avctx->pix_fmt, + avctx->width, avctx->height, + buf + HEADER_SIZE, buf_size - HEADER_SIZE); + if (size < 0) + return size; + break; + case 10: + size = avctx->height * avctx->width * 4; + if (buf_size < HEADER_SIZE + size) + return -1; + encode_rgb48_10bit(avctx, data, buf + HEADER_SIZE); + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", s->bits_per_component); + return -1; + } + + size += HEADER_SIZE; + + write32(buf + 16, size); /* file size */ + return size; +} + +AVCodec ff_dpx_encoder = { + .name = "dpx", + .type = AVMEDIA_TYPE_VIDEO, + .id = CODEC_ID_DPX, + .priv_data_size = sizeof(DPXContext), + .init = encode_init, + .decode = encode_frame, + .pix_fmts = (const enum PixelFormat[]){ + PIX_FMT_RGB24, + PIX_FMT_RGBA, + PIX_FMT_RGB48LE, + PIX_FMT_RGB48BE, + PIX_FMT_NONE}, + .long_name = NULL_IF_CONFIG_SMALL("DPX image"), +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 418e2756b9..d840fbe81f 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -21,8 +21,8 @@ #define AVCODEC_VERSION_H #define LIBAVCODEC_VERSION_MAJOR 53 -#define LIBAVCODEC_VERSION_MINOR 1 -#define LIBAVCODEC_VERSION_MICRO 1 +#define LIBAVCODEC_VERSION_MINOR 2 +#define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ From ad1862d64ae28251e2740e437bbc639492a374a0 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 29 Apr 2011 20:15:00 +0200 Subject: [PATCH 13/13] ALPHA: Replace sized int_fast integer types with plain int/unsigned. int/unsigned is the natural memory access type for CPUs, using sized types for temporary variables, counters and similar just increases code size and can possibly cause a slowdown. --- libavcodec/alpha/simple_idct_alpha.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/alpha/simple_idct_alpha.c b/libavcodec/alpha/simple_idct_alpha.c index bb76c1ec29..61bc5f2084 100644 --- a/libavcodec/alpha/simple_idct_alpha.c +++ b/libavcodec/alpha/simple_idct_alpha.c @@ -46,7 +46,7 @@ /* 0: all entries 0, 1: only first entry nonzero, 2: otherwise */ static inline int idct_row(DCTELEM *row) { - int_fast32_t a0, a1, a2, a3, b0, b1, b2, b3, t; + int a0, a1, a2, a3, b0, b1, b2, b3, t; uint64_t l, r, t2; l = ldq(row); r = ldq(row + 4); @@ -154,7 +154,7 @@ static inline int idct_row(DCTELEM *row) static inline void idct_col(DCTELEM *col) { - int_fast32_t a0, a1, a2, a3, b0, b1, b2, b3; + int a0, a1, a2, a3, b0, b1, b2, b3; col[0] += (1 << (COL_SHIFT - 1)) / W4; @@ -235,7 +235,7 @@ static inline void idct_col2(DCTELEM *col) uint64_t l, r; for (i = 0; i < 8; ++i) { - int_fast32_t a0 = col[i] + (1 << (COL_SHIFT - 1)) / W4; + int a0 = col[i] + (1 << (COL_SHIFT - 1)) / W4; a0 *= W4; col[i] = a0 >> COL_SHIFT;