summaryrefslogtreecommitdiff
path: root/libavcodec/dnxhdenc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/dnxhdenc.c')
-rw-r--r--libavcodec/dnxhdenc.c114
1 files changed, 66 insertions, 48 deletions
diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c
index e656b6edba..3ad625352a 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
*/
@@ -36,6 +36,7 @@
#include "pixblockdsp.h"
#include "dnxhdenc.h"
+
// The largest value that will not lead to overflow for 10bit samples.
#define DNX10BIT_QMAT_SHIFT 18
#define RC_VARIANCE 1 // use variance or ssd for fast rc
@@ -48,14 +49,14 @@ static const AVOption options[] = {
{ 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,
};
-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)
{
@@ -79,25 +80,33 @@ 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;
-
- 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;
@@ -146,10 +155,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);
@@ -161,7 +170,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;
@@ -171,7 +180,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];
}
@@ -250,6 +259,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);
@@ -257,8 +271,7 @@ 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);
+ 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);
@@ -293,12 +306,14 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
ctx->cid = ff_dnxhd_find_cid(avctx, bit_depth);
if (!ctx->cid) {
av_log(avctx, AV_LOG_ERROR,
- "video parameters incompatible with DNxHD\n");
+ "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;
@@ -313,6 +328,8 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
ff_mpegvideoencdsp_init(&ctx->m.mpvencdsp, avctx);
ff_pixblockdsp_init(&ctx->m.pdsp, 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;
@@ -375,6 +392,11 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
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));
@@ -389,7 +411,7 @@ fail: // for FF_ALLOCZ_OR_GOTO
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);
@@ -582,15 +604,8 @@ void dnxhd_get_blocks(DNXHDEncContext *ctx, int mb_x, int mb_y)
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,
@@ -621,7 +636,7 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg,
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, 4 & (2*i),
qscale, &overflow);
ac_bits += dnxhd_calc_ac_bits(ctx, block, last_index);
@@ -631,7 +646,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->cid_table->bit_depth + 4);
dc_bits += ctx->cid_table->dc_bits[nbits] + nbits;
ctx->m.last_dc[n] = block[0];
@@ -673,7 +688,7 @@ static int dnxhd_encode_thread(AVCodecContext *avctx, void *arg,
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,
+ 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);
@@ -932,13 +947,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]);
}
}
@@ -957,7 +972,7 @@ static void radix_sort_pass(RCCMPEntry *dst, const RCCMPEntry *data,
static void radix_sort(RCCMPEntry *data, int size)
{
int buckets[RADIX_PASSES][NBUCKETS];
- RCCMPEntry *tmp = av_malloc(sizeof(*tmp) * size);
+ RCCMPEntry *tmp = av_malloc_array(size, sizeof(*tmp));
radix_count(data, size, buckets);
radix_sort_pass(tmp, data, size, buckets[0], 0);
radix_sort_pass(data, tmp, size, buckets[1], 1);
@@ -1033,11 +1048,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);
@@ -1067,12 +1079,12 @@ 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);
+ 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);
@@ -1123,6 +1135,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"),
@@ -1138,5 +1155,6 @@ AVCodec ff_dnxhd_encoder = {
AV_PIX_FMT_YUV422P10,
AV_PIX_FMT_NONE
},
- .priv_class = &class,
+ .priv_class = &dnxhd_class,
+ .defaults = dnxhd_defaults,
};