speedhq: fix decoding artifacts
[ffmpeg.git] / libavcodec / proresenc_anatoliy.c
index e61e8d7..0516066 100644 (file)
  */
 
 #include "avcodec.h"
+#include "dct.h"
 #include "internal.h"
 #include "put_bits.h"
 #include "bytestream.h"
-#include "dsputil.h"
+#include "fdctdsp.h"
 
 #define DEFAULT_SLICE_MB_WIDTH 8
 
@@ -144,6 +145,7 @@ static const uint8_t QMAT_CHROMA[4][64] = {
 
 
 typedef struct {
+    FDCTDSPContext fdsp;
     uint8_t* fill_y;
     uint8_t* fill_u;
     uint8_t* fill_v;
@@ -154,8 +156,7 @@ typedef struct {
 
 static void encode_codeword(PutBitContext *pb, int val, int codebook)
 {
-    unsigned int rice_order, exp_order, switch_bits, first_exp, exp, zeros,
-            mask;
+    unsigned int rice_order, exp_order, switch_bits, first_exp, exp, zeros;
 
     /* number of bits to switch between rice and exp golomb */
     switch_bits = codebook & 3;
@@ -172,21 +173,20 @@ static void encode_codeword(PutBitContext *pb, int val, int codebook)
         put_bits(pb, zeros, 0);
         put_bits(pb, exp + 1, val);
     } else if (rice_order) {
-        mask = (1 << rice_order) - 1;
         put_bits(pb, (val >> rice_order), 0);
         put_bits(pb, 1, 1);
-        put_bits(pb, rice_order, val & mask);
+        put_sbits(pb, rice_order, val);
     } else {
         put_bits(pb, val, 0);
         put_bits(pb, 1, 1);
     }
 }
 
-#define QSCALE(qmat,ind,val) ((val) / (qmat[ind]))
-#define TO_GOLOMB(val) ((val << 1) ^ (val >> 31))
-#define DIFF_SIGN(val, sign) ((val >> 31) ^ sign)
-#define IS_NEGATIVE(val) (((val >> 31) ^ -1) + 1)
-#define TO_GOLOMB2(val,sign) (val==0 ? 0 : (val << 1) + sign)
+#define QSCALE(qmat,ind,val) ((val) / ((qmat)[ind]))
+#define TO_GOLOMB(val) (((val) << 1) ^ ((val) >> 31))
+#define DIFF_SIGN(val, sign) (((val) >> 31) ^ (sign))
+#define IS_NEGATIVE(val) ((((val) >> 31) ^ -1) + 1)
+#define TO_GOLOMB2(val,sign) ((val)==0 ? 0 : ((val) << 1) + (sign))
 
 static av_always_inline int get_level(int val)
 {
@@ -198,7 +198,7 @@ static av_always_inline int get_level(int val)
 
 static const uint8_t dc_codebook[7] = { 0x04, 0x28, 0x28, 0x4D, 0x4D, 0x70, 0x70};
 
-static void encode_dc_coeffs(PutBitContext *pb, DCTELEM *in,
+static void encode_dc_coeffs(PutBitContext *pb, int16_t *in,
         int blocks_per_slice, int *qmat)
 {
     int prev_dc, code;
@@ -230,7 +230,7 @@ static const uint8_t lev_to_cb[10] = { 0x04, 0x0A, 0x05, 0x06, 0x04, 0x28,
         0x28, 0x28, 0x28, 0x4C };
 
 static void encode_ac_coeffs(AVCodecContext *avctx, PutBitContext *pb,
-        DCTELEM *in, int blocks_per_slice, int *qmat)
+        int16_t *in, int blocks_per_slice, int *qmat)
 {
     int prev_run = 4;
     int prev_level = 2;
@@ -260,42 +260,42 @@ static void encode_ac_coeffs(AVCodecContext *avctx, PutBitContext *pb,
     }
 }
 
-static void get(uint8_t *pixels, int stride, DCTELEM* block)
+static void get(uint8_t *pixels, int stride, int16_t* block)
 {
-    int16_t *p = (int16_t*)pixels;
-    int i, j;
+    int i;
 
-    stride >>= 1;
     for (i = 0; i < 8; i++) {
-        for (j = 0; j < 8; j++) {
-            block[j] = p[j];
-        }
-        p += stride;
+        AV_WN64(block, AV_RN64(pixels));
+        AV_WN64(block+4, AV_RN64(pixels+8));
+        pixels += stride;
         block += 8;
     }
 }
 
-static void fdct_get(uint8_t *pixels, int stride, DCTELEM* block)
+static void fdct_get(FDCTDSPContext *fdsp, uint8_t *pixels, int stride, int16_t* block)
 {
     get(pixels, stride, block);
-    ff_jpeg_fdct_islow_10(block);
+    fdsp->fdct(block);
 }
 
 static int encode_slice_plane(AVCodecContext *avctx, int mb_count,
         uint8_t *src, int src_stride, uint8_t *buf, unsigned buf_size,
         int *qmat, int chroma)
 {
-    DECLARE_ALIGNED(16, DCTELEM, blocks)[DEFAULT_SLICE_MB_WIDTH << 8], *block;
+    ProresContext* ctx = avctx->priv_data;
+    FDCTDSPContext *fdsp = &ctx->fdsp;
+    LOCAL_ALIGNED(16, int16_t, blocks, [DEFAULT_SLICE_MB_WIDTH << 8]);
+    int16_t *block;
     int i, blocks_per_slice;
     PutBitContext pb;
 
     block = blocks;
     for (i = 0; i < mb_count; i++) {
-        fdct_get(src,                  src_stride, block + (0 << 6));
-        fdct_get(src + 8 * src_stride, src_stride, block + ((2 - chroma) << 6));
+        fdct_get(fdsp, src,                  src_stride, block + (0 << 6));
+        fdct_get(fdsp, src + 8 * src_stride, src_stride, block + ((2 - chroma) << 6));
         if (!chroma) {
-            fdct_get(src + 16,                  src_stride, block + (1 << 6));
-            fdct_get(src + 16 + 8 * src_stride, src_stride, block + (3 << 6));
+            fdct_get(fdsp, src + 16,                  src_stride, block + (1 << 6));
+            fdct_get(fdsp, src + 16 + 8 * src_stride, src_stride, block + (3 << 6));
         }
 
         block += (256 >> chroma);
@@ -303,7 +303,7 @@ static int encode_slice_plane(AVCodecContext *avctx, int mb_count,
     }
 
     blocks_per_slice = mb_count << (2 - chroma);
-    init_put_bits(&pb, buf, buf_size << 3);
+    init_put_bits(&pb, buf, buf_size);
 
     encode_dc_coeffs(&pb, blocks, blocks_per_slice, qmat);
     encode_ac_coeffs(avctx, &pb, blocks, blocks_per_slice, qmat);
@@ -323,7 +323,7 @@ static av_always_inline unsigned encode_slice_data(AVCodecContext *avctx,
     *y_data_size = encode_slice_plane(avctx, mb_count, dest_y, luma_stride,
             buf, data_size, ctx->qmat_luma[qp - 1], 0);
 
-    if (!(avctx->flags & CODEC_FLAG_GRAY)) {
+    if (!(avctx->flags & AV_CODEC_FLAG_GRAY)) {
         *u_data_size = encode_slice_plane(avctx, mb_count, dest_u,
                 chroma_stride, buf + *y_data_size, data_size - *y_data_size,
                 ctx->qmat_chroma[qp - 1], 1);
@@ -367,7 +367,7 @@ static void subimage_with_fill(uint16_t *src, unsigned x, unsigned y,
     }
 }
 
-static int encode_slice(AVCodecContext *avctx, AVFrame *pic, int mb_x,
+static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, int mb_x,
         int mb_y, unsigned mb_count, uint8_t *buf, unsigned data_size,
         int unsafe, int *qp)
 {
@@ -437,7 +437,7 @@ static int encode_slice(AVCodecContext *avctx, AVFrame *pic, int mb_x,
     return hdr_size + y_data_size + u_data_size + v_data_size;
 }
 
-static int prores_encode_picture(AVCodecContext *avctx, AVFrame *pic,
+static int prores_encode_picture(AVCodecContext *avctx, const AVFrame *pic,
         uint8_t *buf, const int buf_size)
 {
     int mb_width = (avctx->width + 15) >> 4;
@@ -491,10 +491,10 @@ static int prores_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     int header_size = 148;
     uint8_t *buf;
     int pic_size, ret;
-    int frame_size = FFALIGN(avctx->width, 16) * FFALIGN(avctx->height, 16)*16 + 500 + FF_MIN_BUFFER_SIZE; //FIXME choose tighter limit
+    int frame_size = FFALIGN(avctx->width, 16) * FFALIGN(avctx->height, 16)*16 + 500 + AV_INPUT_BUFFER_MIN_SIZE; //FIXME choose tighter limit
 
 
-    if ((ret = ff_alloc_packet2(avctx, pkt, frame_size + FF_MIN_BUFFER_SIZE)) < 0)
+    if ((ret = ff_alloc_packet2(avctx, pkt, frame_size + AV_INPUT_BUFFER_MIN_SIZE, 0)) < 0)
         return ret;
 
     buf = pkt->data;
@@ -540,14 +540,22 @@ static av_cold int prores_encode_init(AVCodecContext *avctx)
     int i;
     ProresContext* ctx = avctx->priv_data;
 
-    if (avctx->pix_fmt != PIX_FMT_YUV422P10) {
+    if (avctx->pix_fmt != AV_PIX_FMT_YUV422P10) {
         av_log(avctx, AV_LOG_ERROR, "need YUV422P10\n");
-        return -1;
+        return AVERROR_PATCHWELCOME;
     }
+    avctx->bits_per_raw_sample = 10;
+
     if (avctx->width & 0x1) {
         av_log(avctx, AV_LOG_ERROR,
                 "frame width needs to be multiple of 2\n");
-        return -1;
+        return AVERROR(EINVAL);
+    }
+
+    if (avctx->width > 65534 || avctx->height > 65535) {
+        av_log(avctx, AV_LOG_ERROR,
+                "The maximum dimensions are 65534x65535\n");
+        return AVERROR(EINVAL);
     }
 
     if ((avctx->height & 0xf) || (avctx->width & 0xf)) {
@@ -570,9 +578,11 @@ static av_cold int prores_encode_init(AVCodecContext *avctx)
                 AV_LOG_ERROR,
                 "unknown profile %d, use [0 - apco, 1 - apcs, 2 - apcn (default), 3 - apch]\n",
                 avctx->profile);
-        return -1;
+        return AVERROR(EINVAL);
     }
 
+    ff_fdctdsp_init(&ctx->fdsp, avctx);
+
     avctx->codec_tag = AV_RL32((const uint8_t*)profiles[avctx->profile].name);
 
     for (i = 1; i <= 16; i++) {
@@ -580,46 +590,41 @@ static av_cold int prores_encode_init(AVCodecContext *avctx)
         scale_mat(QMAT_CHROMA[avctx->profile], ctx->qmat_chroma[i - 1], i);
     }
 
-    avctx->coded_frame = avcodec_alloc_frame();
-    avctx->coded_frame->key_frame = 1;
-    avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
-
     return 0;
 }
 
 static av_cold int prores_encode_close(AVCodecContext *avctx)
 {
     ProresContext* ctx = avctx->priv_data;
-    av_freep(&avctx->coded_frame);
     av_freep(&ctx->fill_y);
 
     return 0;
 }
 
-AVCodec ff_prores_anatoliy_encoder = {
-    .name           = "prores_anatoliy",
+AVCodec ff_prores_aw_encoder = {
+    .name           = "prores_aw",
+    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes"),
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_PRORES,
     .priv_data_size = sizeof(ProresContext),
     .init           = prores_encode_init,
     .close          = prores_encode_close,
     .encode2        = prores_encode_frame,
-    .pix_fmts       = (const enum PixelFormat[]){PIX_FMT_YUV422P10, PIX_FMT_NONE},
-    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes"),
-    .capabilities   = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY,
+    .pix_fmts       = (const enum AVPixelFormat[]){AV_PIX_FMT_YUV422P10, AV_PIX_FMT_NONE},
+    .capabilities   = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY,
     .profiles       = profiles
 };
 
 AVCodec ff_prores_encoder = {
     .name           = "prores",
+    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes"),
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_PRORES,
     .priv_data_size = sizeof(ProresContext),
     .init           = prores_encode_init,
     .close          = prores_encode_close,
     .encode2        = prores_encode_frame,
-    .pix_fmts       = (const enum PixelFormat[]){PIX_FMT_YUV422P10, PIX_FMT_NONE},
-    .long_name      = NULL_IF_CONFIG_SMALL("Apple ProRes"),
-    .capabilities   = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY,
+    .pix_fmts       = (const enum AVPixelFormat[]){AV_PIX_FMT_YUV422P10, AV_PIX_FMT_NONE},
+    .capabilities   = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY,
     .profiles       = profiles
 };