diff options
Diffstat (limited to 'libavcodec/dnxhdenc.c')
-rw-r--r-- | libavcodec/dnxhdenc.c | 588 |
1 files changed, 422 insertions, 166 deletions
diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c index 639debf..86e71ca 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 */ @@ -34,6 +34,7 @@ #include "internal.h" #include "mpegvideo.h" #include "pixblockdsp.h" +#include "profiles.h" #include "dnxhdenc.h" // The largest value that will not lead to overflow for 10-bit samples. @@ -44,21 +45,36 @@ #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "nitris_compat", "encode with Avid Nitris compatibility", - offsetof(DNXHDEncContext, nitris_compat), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + offsetof(DNXHDEncContext, nitris_compat), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "ibias", "intra quant bias", offsetof(DNXHDEncContext, intra_quant_bias), AV_OPT_TYPE_INT, - { .i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, VE }, + { .i64 = 0 }, INT_MIN, INT_MAX, VE }, + { "profile", NULL, offsetof(DNXHDEncContext, profile), AV_OPT_TYPE_INT, + { .i64 = FF_PROFILE_DNXHD }, + FF_PROFILE_DNXHD, FF_PROFILE_DNXHR_444, VE, "profile" }, + { "dnxhd", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_DNXHD }, + 0, 0, VE, "profile" }, + { "dnxhr_444", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_DNXHR_444 }, + 0, 0, VE, "profile" }, + { "dnxhr_hqx", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_DNXHR_HQX }, + 0, 0, VE, "profile" }, + { "dnxhr_hq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_DNXHR_HQ }, + 0, 0, VE, "profile" }, + { "dnxhr_sq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_DNXHR_SQ }, + 0, 0, VE, "profile" }, + { "dnxhr_lb", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_DNXHR_LB }, + 0, 0, VE, "profile" }, { NULL } }; -static const AVClass class = { +static const AVClass dnxhd_class = { .class_name = "dnxhd", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, }; -static void dnxhd_8bit_get_pixels_8x4_sym(int16_t *restrict block, +static void dnxhd_8bit_get_pixels_8x4_sym(int16_t *av_restrict block, const uint8_t *pixels, ptrdiff_t line_size) { @@ -82,25 +98,84 @@ static void dnxhd_8bit_get_pixels_8x4_sym(int16_t *restrict block, } static av_always_inline -void dnxhd_10bit_get_pixels_8x4_sym(int16_t *restrict block, +void dnxhd_10bit_get_pixels_8x4_sym(int16_t *av_restrict block, const uint8_t *pixels, ptrdiff_t line_size) { - int i; + memcpy(block + 0 * 8, pixels + 0 * line_size, 8 * sizeof(*block)); + memcpy(block + 7 * 8, pixels + 0 * line_size, 8 * sizeof(*block)); + memcpy(block + 1 * 8, pixels + 1 * line_size, 8 * sizeof(*block)); + memcpy(block + 6 * 8, pixels + 1 * line_size, 8 * sizeof(*block)); + memcpy(block + 2 * 8, pixels + 2 * line_size, 8 * sizeof(*block)); + memcpy(block + 5 * 8, pixels + 2 * line_size, 8 * sizeof(*block)); + memcpy(block + 3 * 8, pixels + 3 * line_size, 8 * sizeof(*block)); + memcpy(block + 4 * 8, pixels + 3 * line_size, 8 * sizeof(*block)); +} - block += 32; +static int dnxhd_10bit_dct_quantize_444(MpegEncContext *ctx, int16_t *block, + int n, int qscale, int *overflow) +{ + int i, j, level, last_non_zero, start_i; + const int *qmat; + const uint8_t *scantable= ctx->intra_scantable.scantable; + int bias; + int max = 0; + unsigned int threshold1, threshold2; - 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)); + ctx->fdsp.fdct(block); + + block[0] = (block[0] + 2) >> 2; + start_i = 1; + last_non_zero = 0; + qmat = n < 4 ? ctx->q_intra_matrix[qscale] : ctx->q_chroma_intra_matrix[qscale]; + bias= ctx->intra_quant_bias * (1 << (16 - 8)); + threshold1 = (1 << 16) - bias - 1; + threshold2 = (threshold1 << 1); + + for (i = 63; i >= start_i; i--) { + j = scantable[i]; + level = block[j] * qmat[j]; + + if (((unsigned)(level + threshold1)) > threshold2) { + last_non_zero = i; + break; + } else{ + block[j]=0; + } + } + + for (i = start_i; i <= last_non_zero; i++) { + j = scantable[i]; + level = block[j] * qmat[j]; + + if (((unsigned)(level + threshold1)) > threshold2) { + if (level > 0) { + level = (bias + level) >> 16; + block[j] = level; + } else{ + level = (bias - level) >> 16; + block[j] = -level; + } + max |= level; + } else { + block[j] = 0; + } } + *overflow = ctx->max_qcoeff < max; //overflow might have happened + + /* we need this permutation so that we correct the IDCT, we only permute the !=0 elements */ + if (ctx->idsp.perm_type != FF_IDCT_PERM_NONE) + ff_block_permute(block, ctx->idsp.idct_permutation, + scantable, last_non_zero); + + return last_non_zero; } 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; @@ -119,18 +194,23 @@ static int dnxhd_10bit_dct_quantize(MpegEncContext *ctx, int16_t *block, last_non_zero = i; } + /* we need this permutation so that we correct the IDCT, we only permute the !=0 elements */ + if (ctx->idsp.perm_type != FF_IDCT_PERM_NONE) + ff_block_permute(block, ctx->idsp.idct_permutation, + scantable, last_non_zero); + return last_non_zero; } static av_cold int dnxhd_init_vlc(DNXHDEncContext *ctx) { int i, j, level, run; - int max_level = 1 << (ctx->cid_table->bit_depth + 2); + int max_level = 1 << (ctx->bit_depth + 2); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->vlc_codes, - max_level * 4 * sizeof(*ctx->vlc_codes), fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->vlc_bits, - max_level * 4 * sizeof(*ctx->vlc_bits), fail); + FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->vlc_codes, + max_level, 4 * sizeof(*ctx->vlc_codes), fail); + FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->vlc_bits, + max_level, 4 * sizeof(*ctx->vlc_bits), fail); FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->run_codes, 63 * 2, fail); FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->run_bits, @@ -149,10 +229,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_info[2*j+0] >> 1 == alevel && + (!offset || (ctx->cid_table->ac_info[2*j+1] & 1) && offset) && + (!run || (ctx->cid_table->ac_info[2*j+1] & 2) && run)) { + av_assert1(!ctx->vlc_codes[index]); if (alevel) { ctx->vlc_codes[index] = (ctx->cid_table->ac_codes[j] << 1) | (sign & 1); @@ -164,7 +244,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; @@ -174,7 +254,7 @@ 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]; } @@ -191,18 +271,18 @@ static av_cold int dnxhd_init_qmat(DNXHDEncContext *ctx, int lbias, int cbias) const uint8_t *luma_weight_table = ctx->cid_table->luma_weight; const uint8_t *chroma_weight_table = ctx->cid_table->chroma_weight; - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_l, - (ctx->m.avctx->qmax + 1) * 64 * sizeof(int), fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_c, - (ctx->m.avctx->qmax + 1) * 64 * sizeof(int), fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_l16, - (ctx->m.avctx->qmax + 1) * 64 * 2 * sizeof(uint16_t), + FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->qmatrix_l, + (ctx->m.avctx->qmax + 1), 64 * sizeof(int), fail); + FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->qmatrix_c, + (ctx->m.avctx->qmax + 1), 64 * sizeof(int), fail); + FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->qmatrix_l16, + (ctx->m.avctx->qmax + 1), 64 * 2 * sizeof(uint16_t), fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_c16, - (ctx->m.avctx->qmax + 1) * 64 * 2 * sizeof(uint16_t), + FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->qmatrix_c16, + (ctx->m.avctx->qmax + 1), 64 * 2 * sizeof(uint16_t), fail); - if (ctx->cid_table->bit_depth == 8) { + if (ctx->bit_depth == 8) { for (i = 1; i < 64; i++) { int j = ctx->m.idsp.idct_permutation[ff_zigzag_direct[i]]; weight_matrix[j] = ctx->cid_table->luma_weight[i]; @@ -232,7 +312,7 @@ static av_cold int dnxhd_init_qmat(DNXHDEncContext *ctx, int lbias, int cbias) // 10-bit for (qscale = 1; qscale <= ctx->m.avctx->qmax; qscale++) { for (i = 1; i < 64; i++) { - int j = ctx->m.idsp.idct_permutation[ff_zigzag_direct[i]]; + int j = ff_zigzag_direct[i]; /* The quantization formula from the VC-3 standard is: * quantized = sign(block[i]) * floor(abs(block[i]/s) * p / @@ -253,6 +333,11 @@ 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 AVERROR(ENOMEM); @@ -260,14 +345,16 @@ fail: 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); - 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); - - ctx->frame_bits = (ctx->cid_table->coding_unit_size - - 640 - 4 - ctx->min_padding) * 8; + FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->mb_rc, (ctx->m.avctx->qmax + 1), + ctx->m.mb_num * sizeof(RCEntry), fail); + if (ctx->m.avctx->mb_decision != FF_MB_DECISION_RD) { + FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->mb_cmp, + ctx->m.mb_num, sizeof(RCCMPEntry), fail); + FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->mb_cmp_tmp, + ctx->m.mb_num, sizeof(RCCMPEntry), fail); + } + ctx->frame_bits = (ctx->coding_unit_size - + ctx->data_offset - 4 - ctx->min_padding) * 8; ctx->qscale = 1; ctx->lambda = 2 << LAMBDA_FRAC_BITS; // qscale 2 return 0; @@ -278,50 +365,95 @@ fail: static av_cold int dnxhd_encode_init(AVCodecContext *avctx) { DNXHDEncContext *ctx = avctx->priv_data; - int i, index, bit_depth, ret; + int i, index, ret; switch (avctx->pix_fmt) { case AV_PIX_FMT_YUV422P: - bit_depth = 8; + ctx->bit_depth = 8; break; case AV_PIX_FMT_YUV422P10: - bit_depth = 10; + case AV_PIX_FMT_YUV444P10: + case AV_PIX_FMT_GBRP10: + ctx->bit_depth = 10; break; default: av_log(avctx, AV_LOG_ERROR, - "Pixel format is incompatible with DNxHD, use yuv422p or yuv422p10.\n"); + "pixel format is incompatible with DNxHD\n"); + return AVERROR(EINVAL); + } + + if ((ctx->profile == FF_PROFILE_DNXHR_444 && (avctx->pix_fmt != AV_PIX_FMT_YUV444P10 && + avctx->pix_fmt != AV_PIX_FMT_GBRP10)) || + (ctx->profile != FF_PROFILE_DNXHR_444 && (avctx->pix_fmt == AV_PIX_FMT_YUV444P10 || + avctx->pix_fmt == AV_PIX_FMT_GBRP10))) { + av_log(avctx, AV_LOG_ERROR, + "pixel format is incompatible with DNxHD profile\n"); + return AVERROR(EINVAL); + } + + if (ctx->profile == FF_PROFILE_DNXHR_HQX && avctx->pix_fmt != AV_PIX_FMT_YUV422P10) { + av_log(avctx, AV_LOG_ERROR, + "pixel format is incompatible with DNxHR HQX profile\n"); return AVERROR(EINVAL); } - ctx->cid = ff_dnxhd_find_cid(avctx, bit_depth); + if ((ctx->profile == FF_PROFILE_DNXHR_LB || + ctx->profile == FF_PROFILE_DNXHR_SQ || + ctx->profile == FF_PROFILE_DNXHR_HQ) && avctx->pix_fmt != AV_PIX_FMT_YUV422P) { + av_log(avctx, AV_LOG_ERROR, + "pixel format is incompatible with DNxHR LB/SQ/HQ profile\n"); + return AVERROR(EINVAL); + } + + ctx->is_444 = ctx->profile == FF_PROFILE_DNXHR_444; + avctx->profile = ctx->profile; + ctx->cid = ff_dnxhd_find_cid(avctx, ctx->bit_depth); if (!ctx->cid) { av_log(avctx, AV_LOG_ERROR, - "Video parameters incompatible with DNxHD, available CIDs:\n"); - ff_dnxhd_list_cid(avctx); + "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); + if (ctx->cid >= 1270 && ctx->cid <= 1274) + avctx->codec_tag = MKTAG('A','V','d','h'); + + if (avctx->width < 256 || avctx->height < 120) { + av_log(avctx, AV_LOG_ERROR, + "Input dimensions too small, input must be at least 256x120\n"); + return AVERROR(EINVAL); + } + index = ff_dnxhd_get_cid_table(ctx->cid); - if (index < 0) - return index; + av_assert0(index >= 0); + ctx->cid_table = &ff_dnxhd_cid_table[index]; ctx->m.avctx = avctx; ctx->m.mb_intra = 1; ctx->m.h263_aic = 1; - avctx->bits_per_raw_sample = ctx->cid_table->bit_depth; + avctx->bits_per_raw_sample = ctx->bit_depth; - ff_blockdsp_init(&ctx->bdsp); + ff_blockdsp_init(&ctx->bdsp, avctx); ff_fdctdsp_init(&ctx->m.fdsp, avctx); ff_mpv_idct_init(&ctx->m); ff_mpegvideoencdsp_init(&ctx->m.mpvencdsp, avctx); ff_pixblockdsp_init(&ctx->m.pdsp, avctx); + ff_dct_encode_init(&ctx->m); + + if (ctx->profile != FF_PROFILE_DNXHD) + ff_videodsp_init(&ctx->m.vdsp, ctx->bit_depth); + if (!ctx->m.dct_quantize) ctx->m.dct_quantize = ff_dct_quantize_c; - if (ctx->cid_table->bit_depth == 10) { + if (ctx->is_444 || ctx->profile == FF_PROFILE_DNXHR_HQX) { + ctx->m.dct_quantize = dnxhd_10bit_dct_quantize_444; + ctx->get_pixels_8x4_sym = dnxhd_10bit_get_pixels_8x4_sym; + ctx->block_width_l2 = 4; + } else if (ctx->bit_depth == 10) { ctx->m.dct_quantize = dnxhd_10bit_dct_quantize; ctx->get_pixels_8x4_sym = dnxhd_10bit_get_pixels_8x4_sym; ctx->block_width_l2 = 4; @@ -343,6 +475,21 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) ctx->m.mb_num = ctx->m.mb_height * ctx->m.mb_width; + if (ctx->cid_table->frame_size == DNXHD_VARIABLE) { + ctx->frame_size = ff_dnxhd_get_hr_frame_size(ctx->cid, + avctx->width, avctx->height); + av_assert0(ctx->frame_size >= 0); + ctx->coding_unit_size = ctx->frame_size; + } else { + ctx->frame_size = ctx->cid_table->frame_size; + ctx->coding_unit_size = ctx->cid_table->coding_unit_size; + } + + if (ctx->m.mb_height > 68) + ctx->data_offset = 0x170 + (ctx->m.mb_height << 2); + else + ctx->data_offset = 0x280; + // XXX tune lbias/cbias if ((ret = dnxhd_init_qmat(ctx, ctx->intra_quant_bias, 0)) < 0) return ret; @@ -373,15 +520,24 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif - if (avctx->thread_count > MAX_THREADS) { - av_log(avctx, AV_LOG_ERROR, "too many threads\n"); + if (avctx->active_thread_type == FF_THREAD_SLICE) { + if (avctx->thread_count > MAX_THREADS) { + av_log(avctx, AV_LOG_ERROR, "too many threads\n"); + 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; - for (i = 1; i < avctx->thread_count; i++) { - ctx->thread[i] = av_malloc(sizeof(DNXHDEncContext)); - memcpy(ctx->thread[i], ctx, sizeof(DNXHDEncContext)); + if (avctx->active_thread_type == FF_THREAD_SLICE) { + for (i = 1; i < avctx->thread_count; i++) { + ctx->thread[i] = av_malloc(sizeof(DNXHDEncContext)); + memcpy(ctx->thread[i], ctx, sizeof(DNXHDEncContext)); + } } return 0; @@ -392,11 +548,16 @@ fail: // for FF_ALLOCZ_OR_GOTO static int dnxhd_write_header(AVCodecContext *avctx, uint8_t *buf) { DNXHDEncContext *ctx = avctx->priv_data; - static const uint8_t header_prefix[5] = { 0x00, 0x00, 0x02, 0x80, 0x01 }; - memset(buf, 0, 640); + memset(buf, 0, ctx->data_offset); + + // * write prefix */ + AV_WB16(buf + 0x02, ctx->data_offset); + if (ctx->cid >= 1270 && ctx->cid <= 1274) + buf[4] = 0x03; + else + buf[4] = 0x01; - memcpy(buf, header_prefix, 5); buf[5] = ctx->interlaced ? ctx->cur_field + 2 : 0x01; buf[6] = 0x80; // crc flag off buf[7] = 0xa0; // reserved @@ -404,16 +565,16 @@ static int dnxhd_write_header(AVCodecContext *avctx, uint8_t *buf) AV_WB16(buf + 0x1a, avctx->width); // SPL AV_WB16(buf + 0x1d, avctx->height >> ctx->interlaced); // NAL - buf[0x21] = ctx->cid_table->bit_depth == 10 ? 0x58 : 0x38; + buf[0x21] = ctx->bit_depth == 10 ? 0x58 : 0x38; buf[0x22] = 0x88 + (ctx->interlaced << 2); AV_WB32(buf + 0x28, ctx->cid); // CID - buf[0x2c] = ctx->interlaced ? 0 : 0x80; + buf[0x2c] = (!ctx->interlaced << 7) | (ctx->is_444 << 6) | (avctx->pix_fmt == AV_PIX_FMT_YUV444P10); buf[0x5f] = 0x01; // UDL buf[0x167] = 0x02; // reserved AV_WB16(buf + 0x16a, ctx->m.mb_height * 4 + 4); // MSIPS - buf[0x16d] = ctx->m.mb_height; // Ns + AV_WB16(buf + 0x16c, ctx->m.mb_height); // Ns buf[0x16f] = 0x10; // reserved ctx->msip = buf + 0x170; @@ -431,7 +592,7 @@ static av_always_inline void dnxhd_encode_dc(DNXHDEncContext *ctx, int diff) } put_bits(&ctx->m.pb, ctx->cid_table->dc_bits[nbits] + nbits, (ctx->cid_table->dc_codes[nbits] << nbits) + - (diff & ((1 << nbits) - 1))); + av_mod_uintp2(diff, nbits)); } static av_always_inline @@ -468,8 +629,13 @@ void dnxhd_unquantize_c(DNXHDEncContext *ctx, int16_t *block, int n, int level; int i; - weight_matrix = (n & 2) ? ctx->cid_table->chroma_weight - : ctx->cid_table->luma_weight; + if (ctx->is_444) { + weight_matrix = ((n % 6) < 2) ? ctx->cid_table->luma_weight + : ctx->cid_table->chroma_weight; + } else { + weight_matrix = (n & 2) ? ctx->cid_table->chroma_weight + : ctx->cid_table->luma_weight; + } for (i = 1; i <= last_index; i++) { int j = ctx->m.intra_scantable.permutated[i]; @@ -477,7 +643,7 @@ void dnxhd_unquantize_c(DNXHDEncContext *ctx, int16_t *block, int n, if (level) { if (level < 0) { level = (1 - 2 * level) * qscale * weight_matrix[i]; - if (ctx->cid_table->bit_depth == 10) { + if (ctx->bit_depth == 10) { if (weight_matrix[i] != 8) level += 8; level >>= 4; @@ -489,7 +655,7 @@ void dnxhd_unquantize_c(DNXHDEncContext *ctx, int16_t *block, int n, level = -level; } else { level = (2 * level + 1) * qscale * weight_matrix[i]; - if (ctx->cid_table->bit_depth == 10) { + if (ctx->bit_depth == 10) { if (weight_matrix[i] != 8) level += 8; level >>= 4; @@ -537,63 +703,141 @@ void dnxhd_get_blocks(DNXHDEncContext *ctx, int mb_x, int mb_y) { const int bs = ctx->block_width_l2; const int bw = 1 << bs; + int dct_y_offset = ctx->dct_y_offset; + int dct_uv_offset = ctx->dct_uv_offset; + int linesize = ctx->m.linesize; + int uvlinesize = ctx->m.uvlinesize; const uint8_t *ptr_y = ctx->thread[0]->src[0] + ((mb_y << 4) * ctx->m.linesize) + (mb_x << bs + 1); const uint8_t *ptr_u = ctx->thread[0]->src[1] + - ((mb_y << 4) * ctx->m.uvlinesize) + (mb_x << bs); + ((mb_y << 4) * ctx->m.uvlinesize) + (mb_x << bs + ctx->is_444); const uint8_t *ptr_v = ctx->thread[0]->src[2] + - ((mb_y << 4) * ctx->m.uvlinesize) + (mb_x << bs); + ((mb_y << 4) * ctx->m.uvlinesize) + (mb_x << bs + ctx->is_444); PixblockDSPContext *pdsp = &ctx->m.pdsp; + VideoDSPContext *vdsp = &ctx->m.vdsp; + + if (ctx->bit_depth != 10 && vdsp->emulated_edge_mc && ((mb_x << 4) + 16 > ctx->m.avctx->width || + (mb_y << 4) + 16 > ctx->m.avctx->height)) { + int y_w = ctx->m.avctx->width - (mb_x << 4); + int y_h = ctx->m.avctx->height - (mb_y << 4); + int uv_w = (y_w + 1) / 2; + int uv_h = y_h; + linesize = 16; + uvlinesize = 8; + + vdsp->emulated_edge_mc(&ctx->edge_buf_y[0], ptr_y, + linesize, ctx->m.linesize, + linesize, 16, + 0, 0, y_w, y_h); + vdsp->emulated_edge_mc(&ctx->edge_buf_uv[0][0], ptr_u, + uvlinesize, ctx->m.uvlinesize, + uvlinesize, 16, + 0, 0, uv_w, uv_h); + vdsp->emulated_edge_mc(&ctx->edge_buf_uv[1][0], ptr_v, + uvlinesize, ctx->m.uvlinesize, + uvlinesize, 16, + 0, 0, uv_w, uv_h); + + dct_y_offset = bw * linesize; + dct_uv_offset = bw * uvlinesize; + ptr_y = &ctx->edge_buf_y[0]; + ptr_u = &ctx->edge_buf_uv[0][0]; + ptr_v = &ctx->edge_buf_uv[1][0]; + } else if (ctx->bit_depth == 10 && vdsp->emulated_edge_mc && ((mb_x << 4) + 16 > ctx->m.avctx->width || + (mb_y << 4) + 16 > ctx->m.avctx->height)) { + int y_w = ctx->m.avctx->width - (mb_x << 4); + int y_h = ctx->m.avctx->height - (mb_y << 4); + int uv_w = ctx->is_444 ? y_w : (y_w + 1) / 2; + int uv_h = y_h; + linesize = 32; + uvlinesize = 16 + 16 * ctx->is_444; + + vdsp->emulated_edge_mc(&ctx->edge_buf_y[0], ptr_y, + linesize, ctx->m.linesize, + linesize / 2, 16, + 0, 0, y_w, y_h); + vdsp->emulated_edge_mc(&ctx->edge_buf_uv[0][0], ptr_u, + uvlinesize, ctx->m.uvlinesize, + uvlinesize / 2, 16, + 0, 0, uv_w, uv_h); + vdsp->emulated_edge_mc(&ctx->edge_buf_uv[1][0], ptr_v, + uvlinesize, ctx->m.uvlinesize, + uvlinesize / 2, 16, + 0, 0, uv_w, uv_h); + + dct_y_offset = bw * linesize / 2; + dct_uv_offset = bw * uvlinesize / 2; + ptr_y = &ctx->edge_buf_y[0]; + ptr_u = &ctx->edge_buf_uv[0][0]; + ptr_v = &ctx->edge_buf_uv[1][0]; + } - pdsp->get_pixels(ctx->blocks[0], ptr_y, ctx->m.linesize); - pdsp->get_pixels(ctx->blocks[1], ptr_y + bw, ctx->m.linesize); - pdsp->get_pixels(ctx->blocks[2], ptr_u, ctx->m.uvlinesize); - pdsp->get_pixels(ctx->blocks[3], ptr_v, ctx->m.uvlinesize); - - if (mb_y + 1 == ctx->m.mb_height && ctx->m.avctx->height == 1080) { - if (ctx->interlaced) { - ctx->get_pixels_8x4_sym(ctx->blocks[4], - ptr_y + ctx->dct_y_offset, - ctx->m.linesize); - ctx->get_pixels_8x4_sym(ctx->blocks[5], - ptr_y + ctx->dct_y_offset + bw, - ctx->m.linesize); - ctx->get_pixels_8x4_sym(ctx->blocks[6], - ptr_u + ctx->dct_uv_offset, - ctx->m.uvlinesize); - ctx->get_pixels_8x4_sym(ctx->blocks[7], - ptr_v + ctx->dct_uv_offset, - ctx->m.uvlinesize); + if (!ctx->is_444) { + pdsp->get_pixels(ctx->blocks[0], ptr_y, linesize); + pdsp->get_pixels(ctx->blocks[1], ptr_y + bw, linesize); + pdsp->get_pixels(ctx->blocks[2], ptr_u, uvlinesize); + pdsp->get_pixels(ctx->blocks[3], ptr_v, uvlinesize); + + if (mb_y + 1 == ctx->m.mb_height && ctx->m.avctx->height == 1080) { + if (ctx->interlaced) { + ctx->get_pixels_8x4_sym(ctx->blocks[4], + ptr_y + dct_y_offset, + linesize); + ctx->get_pixels_8x4_sym(ctx->blocks[5], + ptr_y + dct_y_offset + bw, + linesize); + ctx->get_pixels_8x4_sym(ctx->blocks[6], + ptr_u + dct_uv_offset, + uvlinesize); + ctx->get_pixels_8x4_sym(ctx->blocks[7], + ptr_v + dct_uv_offset, + uvlinesize); + } else { + ctx->bdsp.clear_block(ctx->blocks[4]); + ctx->bdsp.clear_block(ctx->blocks[5]); + ctx->bdsp.clear_block(ctx->blocks[6]); + ctx->bdsp.clear_block(ctx->blocks[7]); + } } else { - ctx->bdsp.clear_block(ctx->blocks[4]); - ctx->bdsp.clear_block(ctx->blocks[5]); - ctx->bdsp.clear_block(ctx->blocks[6]); - ctx->bdsp.clear_block(ctx->blocks[7]); + pdsp->get_pixels(ctx->blocks[4], + ptr_y + dct_y_offset, linesize); + pdsp->get_pixels(ctx->blocks[5], + ptr_y + dct_y_offset + bw, linesize); + pdsp->get_pixels(ctx->blocks[6], + ptr_u + dct_uv_offset, uvlinesize); + pdsp->get_pixels(ctx->blocks[7], + ptr_v + dct_uv_offset, uvlinesize); } } else { - pdsp->get_pixels(ctx->blocks[4], - ptr_y + ctx->dct_y_offset, ctx->m.linesize); - pdsp->get_pixels(ctx->blocks[5], - ptr_y + ctx->dct_y_offset + bw, ctx->m.linesize); - pdsp->get_pixels(ctx->blocks[6], - ptr_u + ctx->dct_uv_offset, ctx->m.uvlinesize); - pdsp->get_pixels(ctx->blocks[7], - ptr_v + ctx->dct_uv_offset, ctx->m.uvlinesize); + pdsp->get_pixels(ctx->blocks[0], ptr_y, linesize); + pdsp->get_pixels(ctx->blocks[1], ptr_y + bw, linesize); + pdsp->get_pixels(ctx->blocks[6], ptr_y + dct_y_offset, linesize); + pdsp->get_pixels(ctx->blocks[7], ptr_y + dct_y_offset + bw, linesize); + + pdsp->get_pixels(ctx->blocks[2], ptr_u, uvlinesize); + pdsp->get_pixels(ctx->blocks[3], ptr_u + bw, uvlinesize); + pdsp->get_pixels(ctx->blocks[8], ptr_u + dct_uv_offset, uvlinesize); + pdsp->get_pixels(ctx->blocks[9], ptr_u + dct_uv_offset + bw, uvlinesize); + + pdsp->get_pixels(ctx->blocks[4], ptr_v, uvlinesize); + pdsp->get_pixels(ctx->blocks[5], ptr_v + bw, uvlinesize); + pdsp->get_pixels(ctx->blocks[10], ptr_v + dct_uv_offset, uvlinesize); + pdsp->get_pixels(ctx->blocks[11], ptr_v + dct_uv_offset + bw, uvlinesize); } } 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); + int x; + + if (ctx->is_444) { + x = (i >> 1) % 3; } 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}; + x = component[i]; } + return x; } static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, @@ -607,7 +851,7 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, ctx->m.last_dc[0] = ctx->m.last_dc[1] = - ctx->m.last_dc[2] = 1 << (ctx->cid_table->bit_depth + 2); + ctx->m.last_dc[2] = 1 << (ctx->bit_depth + 2); for (mb_x = 0; mb_x < ctx->m.mb_width; mb_x++) { unsigned mb = mb_y * ctx->m.mb_width + mb_x; @@ -618,13 +862,14 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, dnxhd_get_blocks(ctx, mb_x, mb_y); - for (i = 0; i < 8; i++) { + for (i = 0; i < 8 + 4 * ctx->is_444; i++) { int16_t *src_block = ctx->blocks[i]; int overflow, nbits, diff, last_index; int n = dnxhd_switch_matrix(ctx, i); memcpy(block, src_block, 64 * sizeof(*block)); - last_index = ctx->m.dct_quantize(&ctx->m, block, i, + last_index = ctx->m.dct_quantize(&ctx->m, block, + ctx->is_444 ? 4 * (n > 0): 4 & (2*i), qscale, &overflow); ac_bits += dnxhd_calc_ac_bits(ctx, block, last_index); @@ -634,7 +879,7 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, else nbits = av_log2_16bit(2 * diff); - assert(nbits < ctx->cid_table->bit_depth + 4); + av_assert1(nbits < ctx->bit_depth + 4); dc_bits += ctx->cid_table->dc_bits[nbits] + nbits; ctx->m.last_dc[n] = block[0]; @@ -645,9 +890,9 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, ssd += dnxhd_ssd_block(block, src_block); } } - ctx->mb_rc[qscale][mb].ssd = ssd; - ctx->mb_rc[qscale][mb].bits = ac_bits + dc_bits + 12 + - 8 * ctx->vlc_bits[0]; + ctx->mb_rc[(qscale * ctx->m.mb_num) + mb].ssd = ssd; + ctx->mb_rc[(qscale * ctx->m.mb_num) + mb].bits = ac_bits + dc_bits + 12 + + (1 + ctx->is_444) * 8 * ctx->vlc_bits[0]; } return 0; } @@ -658,25 +903,27 @@ static int dnxhd_encode_thread(AVCodecContext *avctx, void *arg, DNXHDEncContext *ctx = avctx->priv_data; int mb_y = jobnr, mb_x; ctx = ctx->thread[threadnr]; - init_put_bits(&ctx->m.pb, (uint8_t *)arg + 640 + ctx->slice_offs[jobnr], + init_put_bits(&ctx->m.pb, (uint8_t *)arg + ctx->data_offset + ctx->slice_offs[jobnr], ctx->slice_size[jobnr]); ctx->m.last_dc[0] = ctx->m.last_dc[1] = - ctx->m.last_dc[2] = 1 << (ctx->cid_table->bit_depth + 2); + ctx->m.last_dc[2] = 1 << (ctx->bit_depth + 2); for (mb_x = 0; mb_x < ctx->m.mb_width; mb_x++) { unsigned mb = mb_y * ctx->m.mb_width + mb_x; int qscale = ctx->mb_qscale[mb]; int i; - put_bits(&ctx->m.pb, 12, qscale << 1); + put_bits(&ctx->m.pb, 11, qscale); + put_bits(&ctx->m.pb, 1, avctx->pix_fmt == AV_PIX_FMT_YUV444P10); dnxhd_get_blocks(ctx, mb_x, mb_y); - for (i = 0; i < 8; i++) { + for (i = 0; i < 8 + 4 * ctx->is_444; 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, + int last_index = ctx->m.dct_quantize(&ctx->m, block, + ctx->is_444 ? (((i >> 1) % 3) < 1 ? 0 : 4): 4 & (2*i), qscale, &overflow); // START_TIMER; dnxhd_encode_block(ctx, block, last_index, n); @@ -717,14 +964,14 @@ static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg, ((avctx->height >> ctx->interlaced) & 0xF); ctx = ctx->thread[threadnr]; - if (ctx->cid_table->bit_depth == 8) { + if (ctx->bit_depth == 8) { uint8_t *pix = ctx->thread[0]->src[0] + ((mb_y << 4) * ctx->m.linesize); for (mb_x = 0; mb_x < ctx->m.mb_width; ++mb_x, pix += 16) { unsigned mb = mb_y * ctx->m.mb_width + mb_x; int sum; int varc; - if (!partial_last_row && mb_x * 16 <= avctx->width - 16) { + if (!partial_last_row && mb_x * 16 <= avctx->width - 16 && (avctx->width % 16) == 0) { sum = ctx->m.mpvencdsp.pix_sum(pix, ctx->m.linesize); varc = ctx->m.mpvencdsp.pix_norm1(pix, ctx->m.linesize); } else { @@ -752,11 +999,13 @@ static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg, unsigned mb = mb_y * ctx->m.mb_width + mb_x; int sum = 0; int sqsum = 0; + int bw = FFMIN(avctx->width - 16 * mb_x, 16); + int bh = FFMIN((avctx->height >> ctx->interlaced) - 16 * mb_y, 16); int mean, sqmean; int i, j; // Macroblocks are 16x16 pixels, unlike DCT blocks which are 8x8. - for (i = 0; i < 16; ++i) { - for (j = 0; j < 16; ++j) { + for (i = 0; i < bh; ++i) { + for (j = 0; j < bw; ++j) { // Turn 16-bit pixels into 10-bit ones. const int sample = (unsigned) pix[j] >> 6; sum += sample; @@ -800,17 +1049,20 @@ static int dnxhd_encode_rdo(AVCodecContext *avctx, DNXHDEncContext *ctx) unsigned min = UINT_MAX; int qscale = 1; int mb = y * ctx->m.mb_width + x; + int rc = 0; for (q = 1; q < avctx->qmax; q++) { - unsigned score = ctx->mb_rc[q][mb].bits * lambda + - ((unsigned) ctx->mb_rc[q][mb].ssd << LAMBDA_FRAC_BITS); + int i = (q*ctx->m.mb_num) + mb; + unsigned score = ctx->mb_rc[i].bits * lambda + + ((unsigned) ctx->mb_rc[i].ssd << LAMBDA_FRAC_BITS); if (score < min) { min = score; qscale = q; + rc = i; } } - bits += ctx->mb_rc[qscale][mb].bits; + bits += ctx->mb_rc[rc].bits; ctx->mb_qscale[mb] = qscale; - ctx->mb_bits[mb] = ctx->mb_rc[qscale][mb].bits; + ctx->mb_bits[mb] = ctx->mb_rc[rc].bits; } bits = (bits + 31) & ~31; // padding if (bits > ctx->frame_bits) @@ -867,7 +1119,7 @@ static int dnxhd_find_qscale(DNXHDEncContext *ctx) NULL, NULL, ctx->m.mb_height); for (y = 0; y < ctx->m.mb_height; y++) { for (x = 0; x < ctx->m.mb_width; x++) - bits += ctx->mb_rc[qscale][y*ctx->m.mb_width+x].bits; + bits += ctx->mb_rc[(qscale*ctx->m.mb_num) + (y*ctx->m.mb_width+x)].bits; bits = (bits+31)&~31; // padding if (bits > ctx->frame_bits) break; @@ -926,13 +1178,13 @@ static void radix_count(const RCCMPEntry *data, int size, 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]); } } @@ -948,10 +1200,9 @@ static void radix_sort_pass(RCCMPEntry *dst, const RCCMPEntry *data, } } -static void radix_sort(RCCMPEntry *data, int size) +static void radix_sort(RCCMPEntry *data, RCCMPEntry *tmp, int size) { int buckets[RADIX_PASSES][NBUCKETS]; - RCCMPEntry *tmp = av_malloc(sizeof(*tmp) * size); radix_count(data, size, buckets); radix_sort_pass(tmp, data, size, buckets[0], 0); radix_sort_pass(data, tmp, size, buckets[1], 1); @@ -959,7 +1210,6 @@ static void radix_sort(RCCMPEntry *data, int size) radix_sort_pass(tmp, data, size, buckets[2], 2); radix_sort_pass(data, tmp, size, buckets[3], 3); } - av_free(tmp); } static int dnxhd_encode_fast(AVCodecContext *avctx, DNXHDEncContext *ctx) @@ -971,17 +1221,18 @@ static int dnxhd_encode_fast(AVCodecContext *avctx, DNXHDEncContext *ctx) 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; + int rc = (ctx->qscale * ctx->m.mb_num ) + mb; int delta_bits; ctx->mb_qscale[mb] = ctx->qscale; - ctx->mb_bits[mb] = ctx->mb_rc[ctx->qscale][mb].bits; - max_bits += ctx->mb_rc[ctx->qscale][mb].bits; + ctx->mb_bits[mb] = ctx->mb_rc[rc].bits; + max_bits += ctx->mb_rc[rc].bits; if (!RC_VARIANCE) { - delta_bits = ctx->mb_rc[ctx->qscale][mb].bits - - ctx->mb_rc[ctx->qscale + 1][mb].bits; + delta_bits = ctx->mb_rc[rc].bits - + ctx->mb_rc[rc + ctx->m.mb_num].bits; ctx->mb_cmp[mb].mb = mb; ctx->mb_cmp[mb].value = - delta_bits ? ((ctx->mb_rc[ctx->qscale][mb].ssd - - ctx->mb_rc[ctx->qscale + 1][mb].ssd) * 100) / + delta_bits ? ((ctx->mb_rc[rc].ssd - + ctx->mb_rc[rc + ctx->m.mb_num].ssd) * 100) / delta_bits : INT_MIN; // avoid increasing qscale } @@ -992,13 +1243,14 @@ static int dnxhd_encode_fast(AVCodecContext *avctx, DNXHDEncContext *ctx) if (RC_VARIANCE) avctx->execute2(avctx, dnxhd_mb_var_thread, NULL, NULL, ctx->m.mb_height); - radix_sort(ctx->mb_cmp, ctx->m.mb_num); + radix_sort(ctx->mb_cmp, ctx->mb_cmp_tmp, ctx->m.mb_num); for (x = 0; x < ctx->m.mb_num && max_bits > ctx->frame_bits; x++) { int mb = ctx->mb_cmp[x].mb; - max_bits -= ctx->mb_rc[ctx->qscale][mb].bits - - ctx->mb_rc[ctx->qscale + 1][mb].bits; + int rc = (ctx->qscale * ctx->m.mb_num ) + mb; + max_bits -= ctx->mb_rc[rc].bits - + ctx->mb_rc[rc + ctx->m.mb_num].bits; ctx->mb_qscale[mb] = ctx->qscale + 1; - ctx->mb_bits[mb] = ctx->mb_rc[ctx->qscale + 1][mb].bits; + ctx->mb_bits[mb] = ctx->mb_rc[rc + ctx->m.mb_num].bits; } } return 0; @@ -1029,13 +1281,10 @@ static int dnxhd_encode_picture(AVCodecContext *avctx, AVPacket *pkt, DNXHDEncContext *ctx = avctx->priv_data; int first_field = 1; int offset, i, ret; - uint8_t *buf, *sd; + 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->frame_size, 0)) < 0) return ret; - } buf = pkt->data; dnxhd_load_picture(ctx, frame); @@ -1065,21 +1314,21 @@ encode_coding_unit: 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); - memset(buf + 640 + offset, 0, - ctx->cid_table->coding_unit_size - 4 - offset - 640); + av_assert1(ctx->data_offset + offset + 4 <= ctx->coding_unit_size); + memset(buf + ctx->data_offset + offset, 0, + ctx->coding_unit_size - 4 - offset - ctx->data_offset); - AV_WB32(buf + ctx->cid_table->coding_unit_size - 4, 0x600DC0DE); // EOF + AV_WB32(buf + ctx->coding_unit_size - 4, 0x600DC0DE); // EOF if (ctx->interlaced && first_field) { first_field = 0; ctx->cur_field ^= 1; - buf += ctx->cid_table->coding_unit_size; + buf += ctx->coding_unit_size; goto encode_coding_unit; } @@ -1089,10 +1338,7 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif - sd = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, sizeof(int)); - if (!sd) - return AVERROR(ENOMEM); - *(int *)sd = ctx->qscale * FF_QP2LAMBDA; + ff_side_data_set_encoder_stats(pkt, ctx->qscale * FF_QP2LAMBDA, NULL, 0, AV_PICTURE_TYPE_I); pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; @@ -1102,7 +1348,7 @@ FF_ENABLE_DEPRECATION_WARNINGS static av_cold int dnxhd_encode_end(AVCodecContext *avctx) { DNXHDEncContext *ctx = avctx->priv_data; - int max_level = 1 << (ctx->cid_table->bit_depth + 2); + int max_level = 1 << (ctx->bit_depth + 2); int i; av_free(ctx->vlc_codes - max_level * 2); @@ -1114,6 +1360,7 @@ static av_cold int dnxhd_encode_end(AVCodecContext *avctx) av_freep(&ctx->mb_qscale); av_freep(&ctx->mb_rc); av_freep(&ctx->mb_cmp); + av_freep(&ctx->mb_cmp_tmp); av_freep(&ctx->slice_size); av_freep(&ctx->slice_offs); @@ -1128,6 +1375,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"), @@ -1137,11 +1389,15 @@ AVCodec ff_dnxhd_encoder = { .init = dnxhd_encode_init, .encode2 = dnxhd_encode_picture, .close = dnxhd_encode_end, - .capabilities = AV_CODEC_CAP_SLICE_THREADS, + .capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P10, + AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_GBRP10, AV_PIX_FMT_NONE }, - .priv_class = &class, + .priv_class = &dnxhd_class, + .defaults = dnxhd_defaults, + .profiles = NULL_IF_CONFIG_SMALL(ff_dnxhd_profiles), }; |