]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/dnxhdenc.c
vc1: skip motion compensation when data for last picture is invalid
[ffmpeg] / libavcodec / dnxhdenc.c
index 92e69daa958cf9bec393a380fc3cebe761d5e348..639debfa06eacca3b7340311a7a32474c36d769b 100644 (file)
 #include "libavutil/timer.h"
 
 #include "avcodec.h"
-#include "dsputil.h"
+#include "blockdsp.h"
+#include "fdctdsp.h"
 #include "internal.h"
 #include "mpegvideo.h"
+#include "pixblockdsp.h"
 #include "dnxhdenc.h"
 
-// The largest value that will not lead to overflow for 10bit samples.
+// The largest value that will not lead to overflow for 10-bit samples.
 #define DNX10BIT_QMAT_SHIFT 18
 #define RC_VARIANCE 1 // use variance or ssd for fast rc
 #define LAMBDA_FRAC_BITS 10
 static const AVOption options[] = {
     { "nitris_compat", "encode with Avid Nitris compatibility",
         offsetof(DNXHDEncContext, nitris_compat), AV_OPT_TYPE_INT, { .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 },
     { NULL }
 };
 
 static const AVClass class = {
-    "dnxhd",
-    av_default_item_name,
-    options,
-    LIBAVUTIL_VERSION_INT
+    .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,
                                           const uint8_t *pixels,
-                                          int line_size)
+                                          ptrdiff_t line_size)
 {
     int i;
     for (i = 0; i < 4; i++) {
@@ -79,7 +84,7 @@ 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,
                                     const uint8_t *pixels,
-                                    int line_size)
+                                    ptrdiff_t line_size)
 {
     int i;
 
@@ -99,14 +104,14 @@ static int dnxhd_10bit_dct_quantize(MpegEncContext *ctx, int16_t *block,
     int last_non_zero = 0;
     int i;
 
-    ctx->dsp.fdct(block);
+    ctx->fdsp.fdct(block);
 
     // Divide by 4 with rounding, to compensate scaling of DCT coefficients
     block[0] = (block[0] + 2) >> 2;
 
     for (i = 1; i < 64; ++i) {
         int j = scantable[i];
-        int sign = block[j] >> 31;
+        int sign = FF_SIGNBIT(block[j]);
         int level = (block[j] ^ sign) - sign;
         level = level * qmat[j] >> DNX10BIT_QMAT_SHIFT;
         block[j] = (level ^ sign) - sign;
@@ -199,18 +204,18 @@ static av_cold int dnxhd_init_qmat(DNXHDEncContext *ctx, int lbias, int cbias)
 
     if (ctx->cid_table->bit_depth == 8) {
         for (i = 1; i < 64; i++) {
-            int j = ctx->m.dsp.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];
         }
-        ff_convert_matrix(&ctx->m.dsp, ctx->qmatrix_l, ctx->qmatrix_l16,
-                          weight_matrix, ctx->m.intra_quant_bias, 1,
+        ff_convert_matrix(&ctx->m, ctx->qmatrix_l, ctx->qmatrix_l16,
+                          weight_matrix, ctx->intra_quant_bias, 1,
                           ctx->m.avctx->qmax, 1);
         for (i = 1; i < 64; i++) {
-            int j = ctx->m.dsp.idct_permutation[ff_zigzag_direct[i]];
+            int j = ctx->m.idsp.idct_permutation[ff_zigzag_direct[i]];
             weight_matrix[j] = ctx->cid_table->chroma_weight[i];
         }
-        ff_convert_matrix(&ctx->m.dsp, ctx->qmatrix_c, ctx->qmatrix_c16,
-                          weight_matrix, ctx->m.intra_quant_bias, 1,
+        ff_convert_matrix(&ctx->m, ctx->qmatrix_c, ctx->qmatrix_c16,
+                          weight_matrix, ctx->intra_quant_bias, 1,
                           ctx->m.avctx->qmax, 1);
 
         for (qscale = 1; qscale <= ctx->m.avctx->qmax; qscale++) {
@@ -227,7 +232,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.dsp.idct_permutation[ff_zigzag_direct[i]];
+                int j = ctx->m.idsp.idct_permutation[ff_zigzag_direct[i]];
 
                 /* The quantization formula from the VC-3 standard is:
                  * quantized = sign(block[i]) * floor(abs(block[i]/s) * p /
@@ -284,19 +289,22 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
         break;
     default:
         av_log(avctx, AV_LOG_ERROR,
-               "pixel format is incompatible with DNxHD\n");
+               "Pixel format is incompatible with DNxHD, use yuv422p or yuv422p10.\n");
         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");
+               "Video parameters incompatible with DNxHD, available CIDs:\n");
+        ff_dnxhd_list_cid(avctx);
         return AVERROR(EINVAL);
     }
     av_log(avctx, AV_LOG_DEBUG, "cid %d\n", ctx->cid);
 
     index = ff_dnxhd_get_cid_table(ctx->cid);
+    if (index < 0)
+        return index;
     ctx->cid_table = &ff_dnxhd_cid_table[index];
 
     ctx->m.avctx    = avctx;
@@ -305,8 +313,11 @@ 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_blockdsp_init(&ctx->bdsp);
+    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);
     if (!ctx->m.dct_quantize)
         ctx->m.dct_quantize = ff_dct_quantize_c;
 
@@ -325,17 +336,15 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
     ctx->m.mb_height = (avctx->height + 15) / 16;
     ctx->m.mb_width  = (avctx->width  + 15) / 16;
 
-    if (avctx->flags & CODEC_FLAG_INTERLACED_DCT) {
+    if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
         ctx->interlaced   = 1;
         ctx->m.mb_height /= 2;
     }
 
     ctx->m.mb_num = ctx->m.mb_height * ctx->m.mb_width;
 
-    if (avctx->intra_quant_bias != FF_DEFAULT_QUANT_BIAS)
-        ctx->m.intra_quant_bias = avctx->intra_quant_bias;
     // XXX tune lbias/cbias
-    if ((ret = dnxhd_init_qmat(ctx, ctx->m.intra_quant_bias, 0)) < 0)
+    if ((ret = dnxhd_init_qmat(ctx, ctx->intra_quant_bias, 0)) < 0)
         return ret;
 
     /* Avid Nitris hardware decoder requires a minimum amount of padding
@@ -357,12 +366,12 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
     FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_qscale,
                       ctx->m.mb_num * sizeof(uint8_t), fail);
 
-    avctx->coded_frame = av_frame_alloc();
-    if (!avctx->coded_frame)
-        return AVERROR(ENOMEM);
-
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
     avctx->coded_frame->key_frame = 1;
     avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
     if (avctx->thread_count > MAX_THREADS) {
         av_log(avctx, AV_LOG_ERROR, "too many threads\n");
@@ -383,7 +392,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);
 
@@ -534,12 +543,12 @@ void dnxhd_get_blocks(DNXHDEncContext *ctx, int mb_x, int mb_y)
                            ((mb_y << 4) * ctx->m.uvlinesize) + (mb_x << bs);
     const uint8_t *ptr_v = ctx->thread[0]->src[2] +
                            ((mb_y << 4) * ctx->m.uvlinesize) + (mb_x << bs);
-    DSPContext *dsp = &ctx->m.dsp;
+    PixblockDSPContext *pdsp = &ctx->m.pdsp;
 
-    dsp->get_pixels(ctx->blocks[0], ptr_y,      ctx->m.linesize);
-    dsp->get_pixels(ctx->blocks[1], ptr_y + bw, ctx->m.linesize);
-    dsp->get_pixels(ctx->blocks[2], ptr_u,      ctx->m.uvlinesize);
-    dsp->get_pixels(ctx->blocks[3], ptr_v,      ctx->m.uvlinesize);
+    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) {
@@ -556,20 +565,20 @@ void dnxhd_get_blocks(DNXHDEncContext *ctx, int mb_x, int mb_y)
                                     ptr_v + ctx->dct_uv_offset,
                                     ctx->m.uvlinesize);
         } else {
-            dsp->clear_block(ctx->blocks[4]);
-            dsp->clear_block(ctx->blocks[5]);
-            dsp->clear_block(ctx->blocks[6]);
-            dsp->clear_block(ctx->blocks[7]);
+            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 {
-        dsp->get_pixels(ctx->blocks[4],
-                        ptr_y + ctx->dct_y_offset, ctx->m.linesize);
-        dsp->get_pixels(ctx->blocks[5],
-                        ptr_y + ctx->dct_y_offset + bw, ctx->m.linesize);
-        dsp->get_pixels(ctx->blocks[6],
-                        ptr_u + ctx->dct_uv_offset, ctx->m.uvlinesize);
-        dsp->get_pixels(ctx->blocks[7],
-                        ptr_v + ctx->dct_uv_offset, ctx->m.uvlinesize);
+        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);
     }
 }
 
@@ -632,7 +641,7 @@ static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg,
 
             if (avctx->mb_decision == FF_MB_DECISION_RD || !RC_VARIANCE) {
                 dnxhd_unquantize_c(ctx, block, i, qscale, last_index);
-                ctx->m.dsp.idct(block);
+                ctx->m.idsp.idct(block);
                 ssd += dnxhd_ssd_block(block, src_block);
             }
         }
@@ -716,8 +725,8 @@ static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg,
             int varc;
 
             if (!partial_last_row && mb_x * 16 <= avctx->width - 16) {
-                sum  = ctx->m.dsp.pix_sum(pix, ctx->m.linesize);
-                varc = ctx->m.dsp.pix_norm1(pix, ctx->m.linesize);
+                sum  = ctx->m.mpvencdsp.pix_sum(pix, ctx->m.linesize);
+                varc = ctx->m.mpvencdsp.pix_norm1(pix, ctx->m.linesize);
             } else {
                 int bw = FFMIN(avctx->width - 16 * mb_x, 16);
                 int bh = FFMIN((avctx->height >> ctx->interlaced) - 16 * mb_y, 16);
@@ -736,7 +745,7 @@ static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg,
             ctx->mb_cmp[mb].mb    = mb;
         }
     } else { // 10-bit
-        int const linesize = ctx->m.linesize >> 1;
+        const int linesize = ctx->m.linesize >> 1;
         for (mb_x = 0; mb_x < ctx->m.mb_width; ++mb_x) {
             uint16_t *pix = (uint16_t *)ctx->thread[0]->src[0] +
                             ((mb_y << 4) * linesize) + (mb_x << 4);
@@ -749,7 +758,7 @@ static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg,
             for (i = 0; i < 16; ++i) {
                 for (j = 0; j < 16; ++j) {
                     // Turn 16-bit pixels into 10-bit ones.
-                    int const sample = (unsigned) pix[j] >> 6;
+                    const int sample = (unsigned) pix[j] >> 6;
                     sum   += sample;
                     sqsum += sample * sample;
                     // 2^10 * 2^10 * 16 * 16 = 2^28, which is less than INT_MAX
@@ -807,9 +816,6 @@ static int dnxhd_encode_rdo(AVCodecContext *avctx, DNXHDEncContext *ctx)
             if (bits > ctx->frame_bits)
                 break;
         }
-        // av_dlog(ctx->m.avctx,
-        //         "lambda %d, up %u, down %u, bits %d, frame %d\n",
-        //         lambda, last_higher, last_lower, bits, ctx->frame_bits);
         if (end) {
             if (bits > ctx->frame_bits)
                 return AVERROR(EINVAL);
@@ -838,7 +844,6 @@ static int dnxhd_encode_rdo(AVCodecContext *avctx, DNXHDEncContext *ctx)
             down_step = 1<<LAMBDA_FRAC_BITS;
         }
     }
-    //av_dlog(ctx->m.avctx, "out lambda %d\n", lambda);
     ctx->lambda = lambda;
     return 0;
 }
@@ -867,10 +872,6 @@ static int dnxhd_find_qscale(DNXHDEncContext *ctx)
             if (bits > ctx->frame_bits)
                 break;
         }
-        // av_dlog(ctx->m.avctx,
-        //         "%d, qscale %d, bits %d, frame %d, higher %d, lower %d\n",
-        //         ctx->m.avctx->frame_number, qscale, bits, ctx->frame_bits,
-        //         last_higher, last_lower);
         if (bits < ctx->frame_bits) {
             if (qscale == 1)
                 return 1;
@@ -899,7 +900,6 @@ static int dnxhd_find_qscale(DNXHDEncContext *ctx)
                 return AVERROR(EINVAL);
         }
     }
-    //av_dlog(ctx->m.avctx, "out qscale %d\n", qscale);
     ctx->qscale = qscale;
     return 0;
 }
@@ -1015,7 +1015,11 @@ static void dnxhd_load_picture(DNXHDEncContext *ctx, const AVFrame *frame)
         ctx->thread[i]->dct_uv_offset = ctx->m.uvlinesize*8;
     }
 
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
     ctx->m.avctx->coded_frame->interlaced_frame = frame->interlaced_frame;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
     ctx->cur_field = frame->interlaced_frame && !frame->top_field_first;
 }
 
@@ -1025,7 +1029,7 @@ 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;
+    uint8_t *buf, *sd;
 
     if ((ret = ff_alloc_packet(pkt, ctx->cid_table->frame_size)) < 0) {
         av_log(avctx, AV_LOG_ERROR,
@@ -1079,7 +1083,16 @@ encode_coding_unit:
         goto encode_coding_unit;
     }
 
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
     avctx->coded_frame->quality = ctx->qscale * FF_QP2LAMBDA;
+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;
 
     pkt->flags |= AV_PKT_FLAG_KEY;
     *got_packet = 1;
@@ -1112,8 +1125,6 @@ static av_cold int dnxhd_encode_end(AVCodecContext *avctx)
     for (i = 1; i < avctx->thread_count; i++)
         av_freep(&ctx->thread[i]);
 
-    av_frame_free(&avctx->coded_frame);
-
     return 0;
 }
 
@@ -1126,7 +1137,7 @@ AVCodec ff_dnxhd_encoder = {
     .init           = dnxhd_encode_init,
     .encode2        = dnxhd_encode_picture,
     .close          = dnxhd_encode_end,
-    .capabilities   = CODEC_CAP_SLICE_THREADS,
+    .capabilities   = AV_CODEC_CAP_SLICE_THREADS,
     .pix_fmts       = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_YUV422P,
         AV_PIX_FMT_YUV422P10,