Commit f078bc4c authored by Paul B Mahol's avatar Paul B Mahol

avcodec/dnxhdenc: DNxHR 444 and HQX support

Signed-off-by: 's avatarPaul B Mahol <onemda@gmail.com>
parent 507a85b9
...@@ -112,6 +112,65 @@ void dnxhd_10bit_get_pixels_8x4_sym(int16_t *av_restrict block, ...@@ -112,6 +112,65 @@ void dnxhd_10bit_get_pixels_8x4_sym(int16_t *av_restrict block,
memcpy(block + 4 * 8, pixels + 3 * line_size, 8 * sizeof(*block)); memcpy(block + 4 * 8, pixels + 3 * line_size, 8 * sizeof(*block));
} }
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;
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, static int dnxhd_10bit_dct_quantize(MpegEncContext *ctx, int16_t *block,
int n, int qscale, int *overflow) int n, int qscale, int *overflow)
{ {
...@@ -146,7 +205,7 @@ static int dnxhd_10bit_dct_quantize(MpegEncContext *ctx, int16_t *block, ...@@ -146,7 +205,7 @@ static int dnxhd_10bit_dct_quantize(MpegEncContext *ctx, int16_t *block,
static av_cold int dnxhd_init_vlc(DNXHDEncContext *ctx) static av_cold int dnxhd_init_vlc(DNXHDEncContext *ctx)
{ {
int i, j, level, run; 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_ARRAY_OR_GOTO(ctx->m.avctx, ctx->vlc_codes, FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->vlc_codes,
max_level, 4 * sizeof(*ctx->vlc_codes), fail); max_level, 4 * sizeof(*ctx->vlc_codes), fail);
...@@ -223,7 +282,7 @@ static av_cold int dnxhd_init_qmat(DNXHDEncContext *ctx, int lbias, int cbias) ...@@ -223,7 +282,7 @@ static av_cold int dnxhd_init_qmat(DNXHDEncContext *ctx, int lbias, int cbias)
(ctx->m.avctx->qmax + 1), 64 * 2 * sizeof(uint16_t), (ctx->m.avctx->qmax + 1), 64 * 2 * sizeof(uint16_t),
fail); fail);
if (ctx->cid_table->bit_depth == 8) { if (ctx->bit_depth == 8) {
for (i = 1; i < 64; i++) { for (i = 1; i < 64; i++) {
int j = ctx->m.idsp.idct_permutation[ff_zigzag_direct[i]]; int j = ctx->m.idsp.idct_permutation[ff_zigzag_direct[i]];
weight_matrix[j] = ctx->cid_table->luma_weight[i]; weight_matrix[j] = ctx->cid_table->luma_weight[i];
...@@ -309,17 +368,20 @@ static int dnxhd_get_hr_frame_size(const CIDEntry* profile, int mb_num) ...@@ -309,17 +368,20 @@ static int dnxhd_get_hr_frame_size(const CIDEntry* profile, int mb_num)
result = (result + 2048) / 4096 * 4096; result = (result + 2048) / 4096 * 4096;
return FFMAX(result, 8192); return FFMAX(result, 8192);
} }
static av_cold int dnxhd_encode_init(AVCodecContext *avctx) static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
{ {
DNXHDEncContext *ctx = avctx->priv_data; DNXHDEncContext *ctx = avctx->priv_data;
int i, index, bit_depth, ret; int i, index, ret;
switch (avctx->pix_fmt) { switch (avctx->pix_fmt) {
case AV_PIX_FMT_YUV422P: case AV_PIX_FMT_YUV422P:
bit_depth = 8; ctx->bit_depth = 8;
break; break;
case AV_PIX_FMT_YUV422P10: case AV_PIX_FMT_YUV422P10:
bit_depth = 10; case AV_PIX_FMT_YUV444P10:
case AV_PIX_FMT_GBRP10:
ctx->bit_depth = 10;
break; break;
default: default:
av_log(avctx, AV_LOG_ERROR, av_log(avctx, AV_LOG_ERROR,
...@@ -327,15 +389,32 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) ...@@ -327,15 +389,32 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
if (ctx->profile == FF_PROFILE_DNXHR_444 || if ((ctx->profile == FF_PROFILE_DNXHR_444 && (avctx->pix_fmt != AV_PIX_FMT_YUV444P10 &&
ctx->profile == FF_PROFILE_DNXHR_HQX) { avctx->pix_fmt != AV_PIX_FMT_GBRP10)) ||
avpriv_report_missing_feature(avctx, (ctx->profile != FF_PROFILE_DNXHR_444 && (avctx->pix_fmt == AV_PIX_FMT_YUV444P10 ||
"dnxhr_444 or dnxhr_hqx profile"); avctx->pix_fmt == AV_PIX_FMT_GBRP10))) {
return AVERROR_PATCHWELCOME; 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);
}
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; avctx->profile = ctx->profile;
ctx->cid = ff_dnxhd_find_cid(avctx, bit_depth); ctx->cid = ff_dnxhd_find_cid(avctx, ctx->bit_depth);
if (!ctx->cid) { if (!ctx->cid) {
av_log(avctx, AV_LOG_ERROR, av_log(avctx, AV_LOG_ERROR,
"video parameters incompatible with DNxHD. Valid DNxHD profiles:\n"); "video parameters incompatible with DNxHD. Valid DNxHD profiles:\n");
...@@ -362,7 +441,7 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) ...@@ -362,7 +441,7 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
ctx->m.mb_intra = 1; ctx->m.mb_intra = 1;
ctx->m.h263_aic = 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, avctx); ff_blockdsp_init(&ctx->bdsp, avctx);
ff_fdctdsp_init(&ctx->m.fdsp, avctx); ff_fdctdsp_init(&ctx->m.fdsp, avctx);
...@@ -372,12 +451,16 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) ...@@ -372,12 +451,16 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
ff_dct_encode_init(&ctx->m); ff_dct_encode_init(&ctx->m);
if (ctx->profile != FF_PROFILE_DNXHD) if (ctx->profile != FF_PROFILE_DNXHD)
ff_videodsp_init(&ctx->m.vdsp, bit_depth); ff_videodsp_init(&ctx->m.vdsp, ctx->bit_depth);
if (!ctx->m.dct_quantize) if (!ctx->m.dct_quantize)
ctx->m.dct_quantize = ff_dct_quantize_c; 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->m.dct_quantize = dnxhd_10bit_dct_quantize;
ctx->get_pixels_8x4_sym = dnxhd_10bit_get_pixels_8x4_sym; ctx->get_pixels_8x4_sym = dnxhd_10bit_get_pixels_8x4_sym;
ctx->block_width_l2 = 4; ctx->block_width_l2 = 4;
...@@ -490,10 +573,10 @@ static int dnxhd_write_header(AVCodecContext *avctx, uint8_t *buf) ...@@ -490,10 +573,10 @@ static int dnxhd_write_header(AVCodecContext *avctx, uint8_t *buf)
AV_WB16(buf + 0x1a, avctx->width); // SPL AV_WB16(buf + 0x1a, avctx->width); // SPL
AV_WB16(buf + 0x1d, avctx->height >> ctx->interlaced); // NAL 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); buf[0x22] = 0x88 + (ctx->interlaced << 2);
AV_WB32(buf + 0x28, ctx->cid); // CID 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[0x5f] = 0x01; // UDL
...@@ -554,8 +637,13 @@ void dnxhd_unquantize_c(DNXHDEncContext *ctx, int16_t *block, int n, ...@@ -554,8 +637,13 @@ void dnxhd_unquantize_c(DNXHDEncContext *ctx, int16_t *block, int n,
int level; int level;
int i; int i;
weight_matrix = (n & 2) ? ctx->cid_table->chroma_weight if (ctx->is_444) {
: ctx->cid_table->luma_weight; 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++) { for (i = 1; i <= last_index; i++) {
int j = ctx->m.intra_scantable.permutated[i]; int j = ctx->m.intra_scantable.permutated[i];
...@@ -563,7 +651,7 @@ void dnxhd_unquantize_c(DNXHDEncContext *ctx, int16_t *block, int n, ...@@ -563,7 +651,7 @@ void dnxhd_unquantize_c(DNXHDEncContext *ctx, int16_t *block, int n,
if (level) { if (level) {
if (level < 0) { if (level < 0) {
level = (1 - 2 * level) * qscale * weight_matrix[i]; 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) if (weight_matrix[i] != 8)
level += 8; level += 8;
level >>= 4; level >>= 4;
...@@ -575,7 +663,7 @@ void dnxhd_unquantize_c(DNXHDEncContext *ctx, int16_t *block, int n, ...@@ -575,7 +663,7 @@ void dnxhd_unquantize_c(DNXHDEncContext *ctx, int16_t *block, int n,
level = -level; level = -level;
} else { } else {
level = (2 * level + 1) * qscale * weight_matrix[i]; 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) if (weight_matrix[i] != 8)
level += 8; level += 8;
level >>= 4; level >>= 4;
...@@ -630,14 +718,14 @@ void dnxhd_get_blocks(DNXHDEncContext *ctx, int mb_x, int mb_y) ...@@ -630,14 +718,14 @@ void dnxhd_get_blocks(DNXHDEncContext *ctx, int mb_x, int mb_y)
const uint8_t *ptr_y = ctx->thread[0]->src[0] + const uint8_t *ptr_y = ctx->thread[0]->src[0] +
((mb_y << 4) * ctx->m.linesize) + (mb_x << bs + 1); ((mb_y << 4) * ctx->m.linesize) + (mb_x << bs + 1);
const uint8_t *ptr_u = ctx->thread[0]->src[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] + 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; PixblockDSPContext *pdsp = &ctx->m.pdsp;
VideoDSPContext *vdsp = &ctx->m.vdsp; VideoDSPContext *vdsp = &ctx->m.vdsp;
if (vdsp->emulated_edge_mc && ((mb_x << 4) + 16 > ctx->m.avctx->width || 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)) { (mb_y << 4) + 16 > ctx->m.avctx->height)) {
int y_w = ctx->m.avctx->width - (mb_x << 4); int y_w = ctx->m.avctx->width - (mb_x << 4);
int y_h = ctx->m.avctx->height - (mb_y << 4); int y_h = ctx->m.avctx->height - (mb_y << 4);
int uv_w = (y_w + 1) / 2; int uv_w = (y_w + 1) / 2;
...@@ -658,6 +746,33 @@ void dnxhd_get_blocks(DNXHDEncContext *ctx, int mb_x, int mb_y) ...@@ -658,6 +746,33 @@ void dnxhd_get_blocks(DNXHDEncContext *ctx, int mb_x, int mb_y)
uvlinesize, 16, uvlinesize, 16,
0, 0, uv_w, uv_h); 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 << 3) + 8 > ctx->m.avctx->width ||
(mb_y << 3) + 8 > ctx->m.avctx->height)) {
int y_w = ctx->m.avctx->width - (mb_x << 3);
int y_h = ctx->m.avctx->height - (mb_y << 3);
int uv_w = ctx->is_444 ? y_w : (y_w + 1) / 2;
int uv_h = y_h;
linesize = 16;
uvlinesize = 8 + 8 * 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; dct_y_offset = bw * linesize;
dct_uv_offset = bw * uvlinesize; dct_uv_offset = bw * uvlinesize;
ptr_y = &ctx->edge_buf_y[0]; ptr_y = &ctx->edge_buf_y[0];
...@@ -665,48 +780,72 @@ void dnxhd_get_blocks(DNXHDEncContext *ctx, int mb_x, int mb_y) ...@@ -665,48 +780,72 @@ void dnxhd_get_blocks(DNXHDEncContext *ctx, int mb_x, int mb_y)
ptr_v = &ctx->edge_buf_uv[1][0]; ptr_v = &ctx->edge_buf_uv[1][0];
} }
pdsp->get_pixels(ctx->blocks[0], ptr_y, linesize); if (!ctx->is_444) {
pdsp->get_pixels(ctx->blocks[1], ptr_y + bw, linesize); pdsp->get_pixels(ctx->blocks[0], ptr_y, linesize);
pdsp->get_pixels(ctx->blocks[2], ptr_u, uvlinesize); pdsp->get_pixels(ctx->blocks[1], ptr_y + bw, linesize);
pdsp->get_pixels(ctx->blocks[3], ptr_v, uvlinesize); 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) { if (mb_y + 1 == ctx->m.mb_height && ctx->m.avctx->height == 1080) {
ctx->get_pixels_8x4_sym(ctx->blocks[4], if (ctx->interlaced) {
ptr_y + dct_y_offset, ctx->get_pixels_8x4_sym(ctx->blocks[4],
linesize); ptr_y + dct_y_offset,
ctx->get_pixels_8x4_sym(ctx->blocks[5], linesize);
ptr_y + dct_y_offset + bw, ctx->get_pixels_8x4_sym(ctx->blocks[5],
linesize); ptr_y + dct_y_offset + bw,
ctx->get_pixels_8x4_sym(ctx->blocks[6], linesize);
ptr_u + dct_uv_offset, ctx->get_pixels_8x4_sym(ctx->blocks[6],
uvlinesize); ptr_u + dct_uv_offset,
ctx->get_pixels_8x4_sym(ctx->blocks[7], uvlinesize);
ptr_v + dct_uv_offset, ctx->get_pixels_8x4_sym(ctx->blocks[7],
uvlinesize); 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 { } else {
ctx->bdsp.clear_block(ctx->blocks[4]); pdsp->get_pixels(ctx->blocks[4],
ctx->bdsp.clear_block(ctx->blocks[5]); ptr_y + dct_y_offset, linesize);
ctx->bdsp.clear_block(ctx->blocks[6]); pdsp->get_pixels(ctx->blocks[5],
ctx->bdsp.clear_block(ctx->blocks[7]); 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 { } else {
pdsp->get_pixels(ctx->blocks[4], pdsp->get_pixels(ctx->blocks[0], ptr_y, linesize);
ptr_y + dct_y_offset, linesize); pdsp->get_pixels(ctx->blocks[1], ptr_y + bw, linesize);
pdsp->get_pixels(ctx->blocks[5], pdsp->get_pixels(ctx->blocks[6], ptr_y + dct_y_offset, linesize);
ptr_y + dct_y_offset + bw, linesize); pdsp->get_pixels(ctx->blocks[7], ptr_y + dct_y_offset + bw, linesize);
pdsp->get_pixels(ctx->blocks[6],
ptr_u + dct_uv_offset, uvlinesize); pdsp->get_pixels(ctx->blocks[2], ptr_u, uvlinesize);
pdsp->get_pixels(ctx->blocks[7], pdsp->get_pixels(ctx->blocks[3], ptr_u + bw, uvlinesize);
ptr_v + dct_uv_offset, 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 static av_always_inline
int dnxhd_switch_matrix(DNXHDEncContext *ctx, int i) int dnxhd_switch_matrix(DNXHDEncContext *ctx, int i)
{ {
const static uint8_t component[8]={0,0,1,2,0,0,1,2}; int x;
return component[i];
if (ctx->is_444) {
x = (i >> 1) % 3;
} else {
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, static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg,
...@@ -720,7 +859,7 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, ...@@ -720,7 +859,7 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg,
ctx->m.last_dc[0] = ctx->m.last_dc[0] =
ctx->m.last_dc[1] = 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++) { for (mb_x = 0; mb_x < ctx->m.mb_width; mb_x++) {
unsigned mb = mb_y * ctx->m.mb_width + mb_x; unsigned mb = mb_y * ctx->m.mb_width + mb_x;
...@@ -731,13 +870,14 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, ...@@ -731,13 +870,14 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg,
dnxhd_get_blocks(ctx, mb_x, mb_y); 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]; int16_t *src_block = ctx->blocks[i];
int overflow, nbits, diff, last_index; int overflow, nbits, diff, last_index;
int n = dnxhd_switch_matrix(ctx, i); int n = dnxhd_switch_matrix(ctx, i);
memcpy(block, src_block, 64 * sizeof(*block)); memcpy(block, src_block, 64 * sizeof(*block));
last_index = ctx->m.dct_quantize(&ctx->m, block, 4 & (2*i), last_index = ctx->m.dct_quantize(&ctx->m, block,
ctx->is_444 ? 4 * (n > 0): 4 & (2*i),
qscale, &overflow); qscale, &overflow);
ac_bits += dnxhd_calc_ac_bits(ctx, block, last_index); ac_bits += dnxhd_calc_ac_bits(ctx, block, last_index);
...@@ -747,7 +887,7 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, ...@@ -747,7 +887,7 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg,
else else
nbits = av_log2_16bit(2 * diff); nbits = av_log2_16bit(2 * diff);
av_assert1(nbits < ctx->cid_table->bit_depth + 4); av_assert1(nbits < ctx->bit_depth + 4);
dc_bits += ctx->cid_table->dc_bits[nbits] + nbits; dc_bits += ctx->cid_table->dc_bits[nbits] + nbits;
ctx->m.last_dc[n] = block[0]; ctx->m.last_dc[n] = block[0];
...@@ -760,7 +900,7 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, ...@@ -760,7 +900,7 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg,
} }
ctx->mb_rc[(qscale * ctx->m.mb_num) + mb].ssd = ssd; 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 + ctx->mb_rc[(qscale * ctx->m.mb_num) + mb].bits = ac_bits + dc_bits + 12 +
8 * ctx->vlc_bits[0]; (1 + ctx->is_444) * 8 * ctx->vlc_bits[0];
} }
return 0; return 0;
} }
...@@ -776,20 +916,22 @@ static int dnxhd_encode_thread(AVCodecContext *avctx, void *arg, ...@@ -776,20 +916,22 @@ static int dnxhd_encode_thread(AVCodecContext *avctx, void *arg,
ctx->m.last_dc[0] = ctx->m.last_dc[0] =
ctx->m.last_dc[1] = 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++) { for (mb_x = 0; mb_x < ctx->m.mb_width; mb_x++) {
unsigned mb = mb_y * ctx->m.mb_width + mb_x; unsigned mb = mb_y * ctx->m.mb_width + mb_x;
int qscale = ctx->mb_qscale[mb]; int qscale = ctx->mb_qscale[mb];
int i; 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); 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]; int16_t *block = ctx->blocks[i];
int overflow, n = dnxhd_switch_matrix(ctx, i); int overflow, n = dnxhd_switch_matrix(ctx, i);
int last_index = ctx->m.dct_quantize(&ctx->m, block, 4 & (2*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); qscale, &overflow);
// START_TIMER; // START_TIMER;
dnxhd_encode_block(ctx, block, last_index, n); dnxhd_encode_block(ctx, block, last_index, n);
...@@ -830,7 +972,7 @@ static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg, ...@@ -830,7 +972,7 @@ static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg,
((avctx->height >> ctx->interlaced) & 0xF); ((avctx->height >> ctx->interlaced) & 0xF);
ctx = ctx->thread[threadnr]; 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); 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) { for (mb_x = 0; mb_x < ctx->m.mb_width; ++mb_x, pix += 16) {
unsigned mb = mb_y * ctx->m.mb_width + mb_x; unsigned mb = mb_y * ctx->m.mb_width + mb_x;
...@@ -1214,7 +1356,7 @@ FF_ENABLE_DEPRECATION_WARNINGS ...@@ -1214,7 +1356,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
static av_cold int dnxhd_encode_end(AVCodecContext *avctx) static av_cold int dnxhd_encode_end(AVCodecContext *avctx)
{ {
DNXHDEncContext *ctx = avctx->priv_data; 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; int i;
av_free(ctx->vlc_codes - max_level * 2); av_free(ctx->vlc_codes - max_level * 2);
...@@ -1259,6 +1401,8 @@ AVCodec ff_dnxhd_encoder = { ...@@ -1259,6 +1401,8 @@ AVCodec ff_dnxhd_encoder = {
.pix_fmts = (const enum AVPixelFormat[]) { .pix_fmts = (const enum AVPixelFormat[]) {
AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P,
AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P10,
AV_PIX_FMT_YUV444P10,
AV_PIX_FMT_GBRP10,
AV_PIX_FMT_NONE AV_PIX_FMT_NONE
}, },
.priv_class = &dnxhd_class, .priv_class = &dnxhd_class,
......
...@@ -48,6 +48,8 @@ typedef struct DNXHDEncContext { ...@@ -48,6 +48,8 @@ typedef struct DNXHDEncContext {
int cid; int cid;
int profile; int profile;
int bit_depth;
int is_444;
const CIDEntry *cid_table; const CIDEntry *cid_table;
uint8_t *msip; ///< Macroblock Scan Indexes Payload uint8_t *msip; ///< Macroblock Scan Indexes Payload
uint32_t *slice_size; uint32_t *slice_size;
...@@ -72,9 +74,9 @@ typedef struct DNXHDEncContext { ...@@ -72,9 +74,9 @@ typedef struct DNXHDEncContext {
unsigned min_padding; unsigned min_padding;
int intra_quant_bias; int intra_quant_bias;
DECLARE_ALIGNED(16, int16_t, blocks)[8][64]; DECLARE_ALIGNED(16, int16_t, blocks)[12][64];
DECLARE_ALIGNED(16, uint8_t, edge_buf_y)[256]; DECLARE_ALIGNED(16, uint8_t, edge_buf_y)[256];
DECLARE_ALIGNED(16, uint8_t, edge_buf_uv)[2][128]; DECLARE_ALIGNED(16, uint8_t, edge_buf_uv)[2][256];
int (*qmatrix_c) [64]; int (*qmatrix_c) [64];
int (*qmatrix_l) [64]; int (*qmatrix_l) [64];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment