summaryrefslogtreecommitdiff
path: root/libavcodec/dnxhdenc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/dnxhdenc.c')
-rw-r--r--libavcodec/dnxhdenc.c147
1 files changed, 85 insertions, 62 deletions
diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c
index 990c3b21b4..fb37a9d3e2 100644
--- a/libavcodec/dnxhdenc.c
+++ b/libavcodec/dnxhdenc.c
@@ -6,20 +6,20 @@
* VC-3 encoder funded by the British Broadcasting Corporation
* 10 bit support added by MirriAd Ltd, Joseph Artsimovich <joseph@mirriad.com>
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * 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.
*
- * Libav is distributed in the hope that it will be useful,
+ * 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 Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -42,11 +42,17 @@ static const AVOption options[]={
{"nitris_compat", "encode with Avid Nitris compatibility", offsetof(DNXHDEncContext, nitris_compat), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, VE},
{NULL}
};
-static const AVClass class = { "dnxhd", av_default_item_name, options, LIBAVUTIL_VERSION_INT };
+
+static const AVClass dnxhd_class = {
+ .class_name = "dnxhd",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
#define LAMBDA_FRAC_BITS 10
-static void dnxhd_8bit_get_pixels_8x4_sym(int16_t *restrict block, const uint8_t *pixels, int line_size)
+static void dnxhd_8bit_get_pixels_8x4_sym(int16_t *av_restrict block, const uint8_t *pixels, int line_size)
{
int i;
for (i = 0; i < 4; i++) {
@@ -63,23 +69,31 @@ static void dnxhd_8bit_get_pixels_8x4_sym(int16_t *restrict block, const uint8_t
memcpy(block + 24, block - 32, sizeof(*block) * 8);
}
-static av_always_inline void dnxhd_10bit_get_pixels_8x4_sym(int16_t *restrict block, const uint8_t *pixels, int line_size)
+static av_always_inline void dnxhd_10bit_get_pixels_8x4_sym(int16_t *av_restrict block, const uint8_t *pixels, int line_size)
{
int i;
-
- block += 32;
+ const uint16_t* pixels16 = (const uint16_t*)pixels;
+ line_size >>= 1;
for (i = 0; i < 4; i++) {
- memcpy(block + i * 8, pixels + i * line_size, 8 * sizeof(*block));
- memcpy(block - (i+1) * 8, pixels + i * line_size, 8 * sizeof(*block));
+ block[0] = pixels16[0]; block[1] = pixels16[1];
+ block[2] = pixels16[2]; block[3] = pixels16[3];
+ block[4] = pixels16[4]; block[5] = pixels16[5];
+ block[6] = pixels16[6]; block[7] = pixels16[7];
+ pixels16 += line_size;
+ block += 8;
}
+ memcpy(block, block - 8, sizeof(*block) * 8);
+ memcpy(block + 8, block - 16, sizeof(*block) * 8);
+ memcpy(block + 16, block - 24, sizeof(*block) * 8);
+ memcpy(block + 24, block - 32, sizeof(*block) * 8);
}
static int dnxhd_10bit_dct_quantize(MpegEncContext *ctx, int16_t *block,
int n, int qscale, int *overflow)
{
const uint8_t *scantable= ctx->intra_scantable.scantable;
- const int *qmat = ctx->q_intra_matrix[qscale];
+ const int *qmat = n<4 ? ctx->q_intra_matrix[qscale] : ctx->q_chroma_intra_matrix[qscale];
int last_non_zero = 0;
int i;
@@ -124,10 +138,10 @@ static av_cold int dnxhd_init_vlc(DNXHDEncContext *ctx)
alevel -= offset<<6;
}
for (j = 0; j < 257; j++) {
- if (ctx->cid_table->ac_level[j] == alevel &&
- (!offset || (ctx->cid_table->ac_index_flag[j] && offset)) &&
- (!run || (ctx->cid_table->ac_run_flag [j] && run))) {
- assert(!ctx->vlc_codes[index]);
+ if (ctx->cid_table->ac_level[j] >> 1 == alevel &&
+ (!offset || (ctx->cid_table->ac_flags[j] & 1) && offset) &&
+ (!run || (ctx->cid_table->ac_flags[j] & 2) && run)) {
+ av_assert1(!ctx->vlc_codes[index]);
if (alevel) {
ctx->vlc_codes[index] = (ctx->cid_table->ac_codes[j]<<1)|(sign&1);
ctx->vlc_bits [index] = ctx->cid_table->ac_bits[j]+1;
@@ -138,7 +152,7 @@ static av_cold int dnxhd_init_vlc(DNXHDEncContext *ctx)
break;
}
}
- assert(!alevel || j < 257);
+ av_assert0(!alevel || j < 257);
if (offset) {
ctx->vlc_codes[index] = (ctx->vlc_codes[index]<<ctx->cid_table->index_bits)|offset;
ctx->vlc_bits [index]+= ctx->cid_table->index_bits;
@@ -147,13 +161,13 @@ static av_cold int dnxhd_init_vlc(DNXHDEncContext *ctx)
}
for (i = 0; i < 62; i++) {
int run = ctx->cid_table->run[i];
- assert(run < 63);
+ av_assert0(run < 63);
ctx->run_codes[run] = ctx->cid_table->run_codes[i];
ctx->run_bits [run] = ctx->cid_table->run_bits[i];
}
return 0;
fail:
- return -1;
+ return AVERROR(ENOMEM);
}
static av_cold int dnxhd_init_qmat(DNXHDEncContext *ctx, int lbias, int cbias)
@@ -210,14 +224,19 @@ static av_cold int dnxhd_init_qmat(DNXHDEncContext *ctx, int lbias, int cbias)
}
}
+ ctx->m.q_chroma_intra_matrix16 = ctx->qmatrix_c16;
+ ctx->m.q_chroma_intra_matrix = ctx->qmatrix_c;
+ ctx->m.q_intra_matrix16 = ctx->qmatrix_l16;
+ ctx->m.q_intra_matrix = ctx->qmatrix_l;
+
return 0;
fail:
- return -1;
+ return AVERROR(ENOMEM);
}
static av_cold int dnxhd_init_rc(DNXHDEncContext *ctx)
{
- FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_rc, 8160*ctx->m.avctx->qmax*sizeof(RCEntry), fail);
+ FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_rc, 8160*(ctx->m.avctx->qmax + 1)*sizeof(RCEntry), fail);
if (ctx->m.avctx->mb_decision != FF_MB_DECISION_RD)
FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_cmp, ctx->m.mb_num*sizeof(RCCMPEntry), fail);
@@ -226,13 +245,13 @@ static av_cold int dnxhd_init_rc(DNXHDEncContext *ctx)
ctx->lambda = 2<<LAMBDA_FRAC_BITS; // qscale 2
return 0;
fail:
- return -1;
+ return AVERROR(ENOMEM);
}
static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
{
DNXHDEncContext *ctx = avctx->priv_data;
- int i, index, bit_depth;
+ int i, index, bit_depth, ret;
switch (avctx->pix_fmt) {
case AV_PIX_FMT_YUV422P:
@@ -243,17 +262,19 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
break;
default:
av_log(avctx, AV_LOG_ERROR, "pixel format is incompatible with DNxHD\n");
- return -1;
+ return AVERROR(EINVAL);
}
ctx->cid = ff_dnxhd_find_cid(avctx, bit_depth);
if (!ctx->cid) {
- av_log(avctx, AV_LOG_ERROR, "video parameters incompatible with DNxHD\n");
- return -1;
+ av_log(avctx, AV_LOG_ERROR, "video parameters incompatible with DNxHD. Valid DNxHD profiles:\n");
+ ff_dnxhd_print_profiles(avctx, AV_LOG_ERROR);
+ return AVERROR(EINVAL);
}
av_log(avctx, AV_LOG_DEBUG, "cid %d\n", ctx->cid);
index = ff_dnxhd_get_cid_table(ctx->cid);
+ av_assert0(index >= 0);
ctx->cid_table = &ff_dnxhd_cid_table[index];
ctx->m.avctx = avctx;
@@ -262,8 +283,9 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
avctx->bits_per_raw_sample = ctx->cid_table->bit_depth;
- ff_dsputil_init(&ctx->m.dsp, avctx);
ff_dct_common_init(&ctx->m);
+ ff_dct_encode_init(&ctx->m);
+
if (!ctx->m.dct_quantize)
ctx->m.dct_quantize = ff_dct_quantize_c;
@@ -291,17 +313,17 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
if (avctx->intra_quant_bias != FF_DEFAULT_QUANT_BIAS)
ctx->m.intra_quant_bias = avctx->intra_quant_bias;
- if (dnxhd_init_qmat(ctx, ctx->m.intra_quant_bias, 0) < 0) // XXX tune lbias/cbias
- return -1;
+ if ((ret = dnxhd_init_qmat(ctx, ctx->m.intra_quant_bias, 0)) < 0) // XXX tune lbias/cbias
+ return ret;
// Avid Nitris hardware decoder requires a minimum amount of padding in the coding unit payload
if (ctx->nitris_compat)
ctx->min_padding = 1600;
- if (dnxhd_init_vlc(ctx) < 0)
- return -1;
- if (dnxhd_init_rc(ctx) < 0)
- return -1;
+ if ((ret = dnxhd_init_vlc(ctx)) < 0)
+ return ret;
+ if ((ret = dnxhd_init_rc(ctx)) < 0)
+ return ret;
FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->slice_size, ctx->m.mb_height*sizeof(uint32_t), fail);
FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->slice_offs, ctx->m.mb_height*sizeof(uint32_t), fail);
@@ -317,7 +339,12 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
if (avctx->thread_count > MAX_THREADS) {
av_log(avctx, AV_LOG_ERROR, "too many threads\n");
- return -1;
+ return AVERROR(EINVAL);
+ }
+
+ if (avctx->qmax <= 1) {
+ av_log(avctx, AV_LOG_ERROR, "qmax must be at least 2\n");
+ return AVERROR(EINVAL);
}
ctx->thread[0] = ctx;
@@ -328,13 +355,13 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
return 0;
fail: //for FF_ALLOCZ_OR_GOTO
- return -1;
+ return AVERROR(ENOMEM);
}
static int dnxhd_write_header(AVCodecContext *avctx, uint8_t *buf)
{
DNXHDEncContext *ctx = avctx->priv_data;
- const uint8_t header_prefix[5] = { 0x00,0x00,0x02,0x80,0x01 };
+ static const uint8_t header_prefix[5] = { 0x00,0x00,0x02,0x80,0x01 };
memset(buf, 0, 640);
@@ -501,15 +528,8 @@ static av_always_inline void dnxhd_get_blocks(DNXHDEncContext *ctx, int mb_x, in
static av_always_inline int dnxhd_switch_matrix(DNXHDEncContext *ctx, int i)
{
- if (i&2) {
- ctx->m.q_intra_matrix16 = ctx->qmatrix_c16;
- ctx->m.q_intra_matrix = ctx->qmatrix_c;
- return 1 + (i&1);
- } else {
- ctx->m.q_intra_matrix16 = ctx->qmatrix_l16;
- ctx->m.q_intra_matrix = ctx->qmatrix_l;
- return 0;
- }
+ const static uint8_t component[8]={0,0,1,2,0,0,1,2};
+ return component[i];
}
static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr)
@@ -539,14 +559,14 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, int jobnr, i
int n = dnxhd_switch_matrix(ctx, i);
memcpy(block, src_block, 64*sizeof(*block));
- last_index = ctx->m.dct_quantize(&ctx->m, block, i, qscale, &overflow);
+ last_index = ctx->m.dct_quantize(&ctx->m, block, 4&(2*i), qscale, &overflow);
ac_bits += dnxhd_calc_ac_bits(ctx, block, last_index);
diff = block[0] - ctx->m.last_dc[n];
if (diff < 0) nbits = av_log2_16bit(-2*diff);
else nbits = av_log2_16bit( 2*diff);
- assert(nbits < ctx->cid_table->bit_depth + 4);
+ av_assert1(nbits < ctx->cid_table->bit_depth + 4);
dc_bits += ctx->cid_table->dc_bits[nbits] + nbits;
ctx->m.last_dc[n] = block[0];
@@ -585,8 +605,7 @@ static int dnxhd_encode_thread(AVCodecContext *avctx, void *arg, int jobnr, int
for (i = 0; i < 8; i++) {
int16_t *block = ctx->blocks[i];
int overflow, n = dnxhd_switch_matrix(ctx, i);
- int last_index = ctx->m.dct_quantize(&ctx->m, block, i,
- qscale, &overflow);
+ int last_index = ctx->m.dct_quantize(&ctx->m, block, 4&(2*i), qscale, &overflow);
//START_TIMER;
dnxhd_encode_block(ctx, block, last_index, n);
//STOP_TIMER("encode_block");
@@ -726,7 +745,7 @@ static int dnxhd_encode_rdo(AVCodecContext *avctx, DNXHDEncContext *ctx)
// lambda, last_higher, last_lower, bits, ctx->frame_bits);
if (end) {
if (bits > ctx->frame_bits)
- return -1;
+ return AVERROR(EINVAL);
break;
}
if (bits < ctx->frame_bits) {
@@ -745,7 +764,7 @@ static int dnxhd_encode_rdo(AVCodecContext *avctx, DNXHDEncContext *ctx)
if (last_lower != INT_MAX)
lambda = (lambda+last_lower)>>1;
else if ((int64_t)lambda + up_step > INT_MAX)
- return -1;
+ return AVERROR(EINVAL);
else
lambda += up_step;
up_step = FFMIN((int64_t)up_step*5, INT_MAX);
@@ -807,7 +826,7 @@ static int dnxhd_find_qscale(DNXHDEncContext *ctx)
qscale += up_step++;
down_step = 1;
if (qscale >= ctx->m.avctx->qmax)
- return -1;
+ return AVERROR(EINVAL);
}
}
//av_dlog(ctx->m.avctx, "out qscale %d\n", qscale);
@@ -836,13 +855,13 @@ static void radix_count(const RCCMPEntry *data, int size, int buckets[RADIX_PASS
buckets[j][get_bucket(v, 0)]++;
v >>= BUCKET_BITS;
}
- assert(!v);
+ av_assert1(!v);
}
for (j = 0; j < RADIX_PASSES; j++) {
int offset = size;
for (i = NBUCKETS - 1; i >= 0; i--)
buckets[j][i] = offset -= buckets[j][i];
- assert(!buckets[j][0]);
+ av_assert1(!buckets[j][0]);
}
}
@@ -876,7 +895,7 @@ static int dnxhd_encode_fast(AVCodecContext *avctx, DNXHDEncContext *ctx)
int max_bits = 0;
int ret, x, y;
if ((ret = dnxhd_find_qscale(ctx)) < 0)
- return -1;
+ return ret;
for (y = 0; y < ctx->m.mb_height; y++) {
for (x = 0; x < ctx->m.mb_width; x++) {
int mb = y*ctx->m.mb_width+x;
@@ -931,10 +950,8 @@ static int dnxhd_encode_picture(AVCodecContext *avctx, AVPacket *pkt,
int offset, i, ret;
uint8_t *buf;
- if ((ret = ff_alloc_packet(pkt, ctx->cid_table->frame_size)) < 0) {
- av_log(avctx, AV_LOG_ERROR, "output buffer is too small to compress picture\n");
+ if ((ret = ff_alloc_packet2(avctx, pkt, ctx->cid_table->frame_size)) < 0)
return ret;
- }
buf = pkt->data;
dnxhd_load_picture(ctx, frame);
@@ -955,7 +972,7 @@ static int dnxhd_encode_picture(AVCodecContext *avctx, AVPacket *pkt,
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR,
"picture could not fit ratecontrol constraints, increase qmax\n");
- return -1;
+ return ret;
}
dnxhd_setup_threads_slices(ctx);
@@ -964,12 +981,12 @@ static int dnxhd_encode_picture(AVCodecContext *avctx, AVPacket *pkt,
for (i = 0; i < ctx->m.mb_height; i++) {
AV_WB32(ctx->msip + i * 4, offset);
offset += ctx->slice_size[i];
- assert(!(ctx->slice_size[i] & 3));
+ av_assert1(!(ctx->slice_size[i] & 3));
}
avctx->execute2(avctx, dnxhd_encode_thread, buf, NULL, ctx->m.mb_height);
- assert(640 + offset + 4 <= ctx->cid_table->coding_unit_size);
+ av_assert1(640 + offset + 4 <= ctx->cid_table->coding_unit_size);
memset(buf + 640 + offset, 0, ctx->cid_table->coding_unit_size - 4 - offset - 640);
AV_WB32(buf + ctx->cid_table->coding_unit_size - 4, 0x600DC0DE); // EOF
@@ -1019,6 +1036,11 @@ static av_cold int dnxhd_encode_end(AVCodecContext *avctx)
return 0;
}
+static const AVCodecDefault dnxhd_defaults[] = {
+ { "qmax", "1024" }, /* Maximum quantization scale factor allowed for VC-3 */
+ { NULL },
+};
+
AVCodec ff_dnxhd_encoder = {
.name = "dnxhd",
.long_name = NULL_IF_CONFIG_SMALL("VC3/DNxHD"),
@@ -1032,5 +1054,6 @@ AVCodec ff_dnxhd_encoder = {
.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P,
AV_PIX_FMT_YUV422P10,
AV_PIX_FMT_NONE },
- .priv_class = &class,
+ .priv_class = &dnxhd_class,
+ .defaults = dnxhd_defaults,
};