]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/svq1enc.c
Deprecate avctx.coded_frame
[ffmpeg] / libavcodec / svq1enc.c
index 3cd3a4aaed87c21bba5db6c2f57ded2688ffb2c4..24251ff02c8ac44c366f506ce3d0ad1ac3482ef8 100644 (file)
  */
 
 #include "avcodec.h"
-#include "dsputil.h"
 #include "hpeldsp.h"
+#include "me_cmp.h"
 #include "mpegvideo.h"
 #include "h263.h"
 #include "internal.h"
+#include "mpegutils.h"
 #include "svq1.h"
+#include "svq1enc.h"
 #include "svq1enc_cb.h"
 
 #undef NDEBUG
 #include <assert.h>
 
-typedef struct SVQ1Context {
-    /* FIXME: Needed for motion estimation, should not be used for anything
-     * else, the idea is to make the motion estimation eventually independent
-     * of MpegEncContext, so this will be removed then. */
-    MpegEncContext m;
-    AVCodecContext *avctx;
-    DSPContext dsp;
-    HpelDSPContext hdsp;
-    AVFrame *current_picture;
-    AVFrame *last_picture;
-    PutBitContext pb;
-    GetBitContext gb;
-
-    /* why ooh why this sick breadth first order,
-     * everything is slower and more complex */
-    PutBitContext reorder_pb[6];
-
-    int frame_width;
-    int frame_height;
-
-    /* Y plane block dimensions */
-    int y_block_width;
-    int y_block_height;
-
-    /* U & V plane (C planes) block dimensions */
-    int c_block_width;
-    int c_block_height;
-
-    uint16_t *mb_type;
-    uint32_t *dummy;
-    int16_t (*motion_val8[3])[2];
-    int16_t (*motion_val16[3])[2];
-
-    int64_t rd_total;
-
-    uint8_t *scratchbuf;
-} SVQ1Context;
-
-static void svq1_write_header(SVQ1Context *s, int frame_type)
+static void svq1_write_header(SVQ1EncContext *s, int frame_type)
 {
     int i;
 
@@ -113,7 +77,17 @@ static void svq1_write_header(SVQ1Context *s, int frame_type)
 #define QUALITY_THRESHOLD    100
 #define THRESHOLD_MULTIPLIER 0.6
 
-static int encode_block(SVQ1Context *s, uint8_t *src, uint8_t *ref,
+static int ssd_int8_vs_int16_c(const int8_t *pix1, const int16_t *pix2,
+                               int size)
+{
+    int score = 0, i;
+
+    for (i = 0; i < size; i++)
+        score += (pix1[i] - pix2[i]) * (pix1[i] - pix2[i]);
+    return score;
+}
+
+static int encode_block(SVQ1EncContext *s, uint8_t *src, uint8_t *ref,
                         uint8_t *decoded, int stride, int level,
                         int threshold, int lambda, int intra)
 {
@@ -174,7 +148,7 @@ static int encode_block(SVQ1Context *s, uint8_t *src, uint8_t *ref,
                 int sqr, diff, score;
 
                 vector = codebook + stage * size * 16 + i * size;
-                sqr    = s->dsp.ssd_int8_vs_int16(vector, block[stage], size);
+                sqr    = s->ssd_int8_vs_int16(vector, block[stage], size);
                 diff   = block_sum[stage] - sum;
                 score  = sqr - (diff * (int64_t)diff >> (level + 3)); // FIXME: 64bit slooow
                 if (score < best_vector_score) {
@@ -258,20 +232,19 @@ static int encode_block(SVQ1Context *s, uint8_t *src, uint8_t *ref,
     return best_score;
 }
 
-static int svq1_encode_plane(SVQ1Context *s, int plane,
+static int svq1_encode_plane(SVQ1EncContext *s, int plane,
                              unsigned char *src_plane,
                              unsigned char *ref_plane,
                              unsigned char *decoded_plane,
                              int width, int height, int src_stride, int stride)
 {
-    const AVFrame *f = s->avctx->coded_frame;
     int x, y;
     int i;
     int block_width, block_height;
     int level;
     int threshold[6];
     uint8_t *src     = s->scratchbuf + stride * 16;
-    const int lambda = (f->quality * f->quality) >>
+    const int lambda = (s->quality * s->quality) >>
                        (2 * FF_LAMBDA_SHIFT);
 
     /* figure out the acceptable level thresholds in advance */
@@ -282,15 +255,15 @@ static int svq1_encode_plane(SVQ1Context *s, int plane,
     block_width  = (width  + 15) / 16;
     block_height = (height + 15) / 16;
 
-    if (f->pict_type == AV_PICTURE_TYPE_P) {
+    if (s->pict_type == AV_PICTURE_TYPE_P) {
         s->m.avctx                         = s->avctx;
         s->m.current_picture_ptr           = &s->m.current_picture;
         s->m.last_picture_ptr              = &s->m.last_picture;
-        s->m.last_picture.f.data[0]        = ref_plane;
+        s->m.last_picture.f->data[0]        = ref_plane;
         s->m.linesize                      =
-        s->m.last_picture.f.linesize[0]    =
-        s->m.new_picture.f.linesize[0]     =
-        s->m.current_picture.f.linesize[0] = stride;
+        s->m.last_picture.f->linesize[0]    =
+        s->m.new_picture.f->linesize[0]     =
+        s->m.current_picture.f->linesize[0] = stride;
         s->m.width                         = width;
         s->m.height                        = height;
         s->m.mb_width                      = block_width;
@@ -298,13 +271,12 @@ static int svq1_encode_plane(SVQ1Context *s, int plane,
         s->m.mb_stride                     = s->m.mb_width + 1;
         s->m.b8_stride                     = 2 * s->m.mb_width + 1;
         s->m.f_code                        = 1;
-        s->m.pict_type                     = f->pict_type;
+        s->m.pict_type                     = s->pict_type;
         s->m.me_method                     = s->avctx->me_method;
         s->m.me.scene_change_score         = 0;
-        s->m.flags                         = s->avctx->flags;
         // s->m.out_format                    = FMT_H263;
         // s->m.unrestricted_mv               = 1;
-        s->m.lambda                        = f->quality;
+        s->m.lambda                        = s->quality;
         s->m.qscale                        = s->m.lambda * 139 +
                                              FF_LAMBDA_SCALE * 64 >>
                                              FF_LAMBDA_SHIFT + 7;
@@ -319,6 +291,8 @@ static int svq1_encode_plane(SVQ1Context *s, int plane,
             s->motion_val16[plane] = av_mallocz((s->m.mb_stride *
                                                  (block_height + 2) + 1) *
                                                 2 * sizeof(int16_t));
+            if (!s->motion_val8[plane] || !s->motion_val16[plane])
+                return AVERROR(ENOMEM);
         }
 
         s->m.mb_type = s->mb_type;
@@ -332,13 +306,13 @@ static int svq1_encode_plane(SVQ1Context *s, int plane,
         s->m.current_picture.motion_val[0]   = s->motion_val8[plane] + 2;
         s->m.p_mv_table                      = s->motion_val16[plane] +
                                                s->m.mb_stride + 1;
-        s->m.dsp                             = s->dsp; // move
+        s->m.mecc                            = s->mecc; // move
         ff_init_me(&s->m);
 
         s->m.me.dia_size      = s->avctx->dia_size;
         s->m.first_slice_line = 1;
         for (y = 0; y < block_height; y++) {
-            s->m.new_picture.f.data[0] = src - y * 16 * stride; // ugly
+            s->m.new_picture.f->data[0] = src - y * 16 * stride; // ugly
             s->m.mb_y                  = y;
 
             for (i = 0; i < 16 && i + 16 * y < height; i++) {
@@ -397,13 +371,13 @@ static int svq1_encode_plane(SVQ1Context *s, int plane,
             ff_init_block_index(&s->m);
             ff_update_block_index(&s->m);
 
-            if (f->pict_type == AV_PICTURE_TYPE_I ||
+            if (s->pict_type == AV_PICTURE_TYPE_I ||
                 (s->m.mb_type[x + y * s->m.mb_stride] &
                  CANDIDATE_MB_TYPE_INTRA)) {
                 for (i = 0; i < 6; i++)
                     init_put_bits(&s->reorder_pb[i], reorder_buffer[0][i],
                                   7 * 32);
-                if (f->pict_type == AV_PICTURE_TYPE_P) {
+                if (s->pict_type == AV_PICTURE_TYPE_P) {
                     const uint8_t *vlc = ff_svq1_block_type_vlc[SVQ1_BLOCK_INTRA];
                     put_bits(&s->reorder_pb[5], vlc[1], vlc[0]);
                     score[0] = vlc[1] * lambda;
@@ -419,7 +393,7 @@ static int svq1_encode_plane(SVQ1Context *s, int plane,
 
             best = 0;
 
-            if (f->pict_type == AV_PICTURE_TYPE_P) {
+            if (s->pict_type == AV_PICTURE_TYPE_P) {
                 const uint8_t *vlc = ff_svq1_block_type_vlc[SVQ1_BLOCK_INTER];
                 int mx, my, pred_x, pred_y, dxy;
                 int16_t *motion_ptr;
@@ -457,8 +431,8 @@ static int svq1_encode_plane(SVQ1Context *s, int plane,
                     best      = score[1] <= score[0];
 
                     vlc       = ff_svq1_block_type_vlc[SVQ1_BLOCK_SKIP];
-                    score[2]  = s->dsp.sse[0](NULL, src + 16 * x, ref,
-                                              stride, 16);
+                    score[2]  = s->mecc.sse[0](NULL, src + 16 * x, ref,
+                                               stride, 16);
                     score[2] += vlc[1] * lambda;
                     if (score[2] < score[best] && mx == 0 && my == 0) {
                         best = 2;
@@ -501,13 +475,16 @@ static int svq1_encode_plane(SVQ1Context *s, int plane,
 
 static av_cold int svq1_encode_end(AVCodecContext *avctx)
 {
-    SVQ1Context *const s = avctx->priv_data;
+    SVQ1EncContext *const s = avctx->priv_data;
     int i;
 
     av_log(avctx, AV_LOG_DEBUG, "RD: %f\n",
            s->rd_total / (double)(avctx->width * avctx->height *
                                   avctx->frame_number));
 
+    s->m.mb_type = NULL;
+    ff_mpv_common_end(&s->m);
+
     av_freep(&s->m.me.scratchpad);
     av_freep(&s->m.me.map);
     av_freep(&s->m.me.score_map);
@@ -522,22 +499,22 @@ static av_cold int svq1_encode_end(AVCodecContext *avctx)
 
     av_frame_free(&s->current_picture);
     av_frame_free(&s->last_picture);
-    av_frame_free(&avctx->coded_frame);
 
     return 0;
 }
 
 static av_cold int svq1_encode_init(AVCodecContext *avctx)
 {
-    SVQ1Context *const s = avctx->priv_data;
+    SVQ1EncContext *const s = avctx->priv_data;
+    int ret;
 
-    ff_dsputil_init(&s->dsp, avctx);
     ff_hpeldsp_init(&s->hdsp, avctx->flags);
+    ff_me_cmp_init(&s->mecc, avctx);
+    ff_mpegvideoencdsp_init(&s->m.mpvencdsp, avctx);
 
-    avctx->coded_frame = av_frame_alloc();
     s->current_picture = av_frame_alloc();
     s->last_picture    = av_frame_alloc();
-    if (!avctx->coded_frame || !s->current_picture || !s->last_picture) {
+    if (!s->current_picture || !s->last_picture) {
         svq1_encode_end(avctx);
         return AVERROR(ENOMEM);
     }
@@ -553,6 +530,12 @@ static av_cold int svq1_encode_init(AVCodecContext *avctx)
 
     s->avctx               = avctx;
     s->m.avctx             = avctx;
+
+    if ((ret = ff_mpv_common_init(&s->m)) < 0) {
+        svq1_encode_end(avctx);
+        return ret;
+    }
+
     s->m.picture_structure = PICT_FRAME;
     s->m.me.temp           =
     s->m.me.scratchpad     = av_mallocz((avctx->width + 64) *
@@ -563,6 +546,19 @@ static av_cold int svq1_encode_init(AVCodecContext *avctx)
                                         s->y_block_height * sizeof(int16_t));
     s->dummy               = av_mallocz((s->y_block_width + 1) *
                                         s->y_block_height * sizeof(int32_t));
+    s->ssd_int8_vs_int16   = ssd_int8_vs_int16_c;
+
+    if (!s->m.me.temp || !s->m.me.scratchpad || !s->m.me.map ||
+        !s->m.me.score_map || !s->mb_type || !s->dummy) {
+        svq1_encode_end(avctx);
+        return AVERROR(ENOMEM);
+    }
+
+    if (ARCH_PPC)
+        ff_svq1enc_init_ppc(s);
+    if (ARCH_X86)
+        ff_svq1enc_init_x86(s);
+
     ff_h263_encode_init(&s->m); // mv_penalty
 
     return 0;
@@ -571,9 +567,9 @@ static av_cold int svq1_encode_init(AVCodecContext *avctx)
 static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                              const AVFrame *pict, int *got_packet)
 {
-    SVQ1Context *const s = avctx->priv_data;
-    AVFrame *const p     = avctx->coded_frame;
+    SVQ1EncContext *const s = avctx->priv_data;
     int i, ret;
+    uint8_t *sd;
 
     if (!pkt->data &&
         (ret = av_new_packet(pkt, s->y_block_width * s->y_block_height *
@@ -588,21 +584,44 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     }
 
     if (!s->current_picture->data[0]) {
-        ff_get_buffer(avctx, s->current_picture, 0);
-        ff_get_buffer(avctx, s->last_picture, 0);
+        ret = ff_get_buffer(avctx, s->current_picture, 0);
+        if (ret < 0)
+            return ret;
+    }
+    if (!s->last_picture->data[0]) {
+        ret = ff_get_buffer(avctx, s->last_picture, 0);
+        if (ret < 0)
+            return ret;
+    }
+    if (!s->scratchbuf) {
         s->scratchbuf = av_malloc(s->current_picture->linesize[0] * 16 * 2);
+        if (!s->scratchbuf)
+            return AVERROR(ENOMEM);
     }
 
     FFSWAP(AVFrame*, s->current_picture, s->last_picture);
 
     init_put_bits(&s->pb, pkt->data, pkt->size);
 
-    p->pict_type = avctx->gop_size && avctx->frame_number % avctx->gop_size ?
-                   AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I;
-    p->key_frame = p->pict_type == AV_PICTURE_TYPE_I;
-    p->quality   = pict->quality;
+    if (avctx->gop_size && (avctx->frame_number % avctx->gop_size))
+        s->pict_type = AV_PICTURE_TYPE_P;
+    else
+        s->pict_type = AV_PICTURE_TYPE_I;
+    s->quality = pict->quality;
+
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
+    avctx->coded_frame->pict_type = s->pict_type;
+    avctx->coded_frame->key_frame = s->pict_type == AV_PICTURE_TYPE_I;
+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 = pict->quality;
 
-    svq1_write_header(s, p->pict_type);
+    svq1_write_header(s, s->pict_type);
     for (i = 0; i < 3; i++)
         if (svq1_encode_plane(s, i,
                               pict->data[i],
@@ -611,8 +630,15 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                               s->frame_width  / (i ? 4 : 1),
                               s->frame_height / (i ? 4 : 1),
                               pict->linesize[i],
-                              s->current_picture->linesize[i]) < 0)
+                              s->current_picture->linesize[i]) < 0) {
+            int j;
+            for (j = 0; j < i; j++) {
+                av_freep(&s->motion_val8[j]);
+                av_freep(&s->motion_val16[j]);
+            }
+            av_freep(&s->scratchbuf);
             return -1;
+        }
 
     // avpriv_align_put_bits(&s->pb);
     while (put_bits_count(&s->pb) & 31)
@@ -621,7 +647,7 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     flush_put_bits(&s->pb);
 
     pkt->size = put_bits_count(&s->pb) / 8;
-    if (p->pict_type == AV_PICTURE_TYPE_I)
+    if (s->pict_type == AV_PICTURE_TYPE_I)
         pkt->flags |= AV_PKT_FLAG_KEY;
     *got_packet = 1;
 
@@ -633,7 +659,7 @@ AVCodec ff_svq1_encoder = {
     .long_name      = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1"),
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_SVQ1,
-    .priv_data_size = sizeof(SVQ1Context),
+    .priv_data_size = sizeof(SVQ1EncContext),
     .init           = svq1_encode_init,
     .encode2        = svq1_encode_frame,
     .close          = svq1_encode_end,