[FFmpeg-devel] [PATCH 1/2] avcodec: Add interface to motion estimation

Michael Niedermayer michaelni at gmx.at
Sun Aug 30 04:23:58 CEST 2015


From: Michael Niedermayer <michael at niedermayer.cc>

This is needed for vf_mcfps, no codec related structs are part of the
public interface

Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>
---
 libavcodec/Makefile   |    2 +-
 libavcodec/avme.c     |  138 +++++++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/avme.h     |   30 +++++++++++
 libavcodec/internal.h |    2 +
 libavcodec/snow.c     |   30 +++++++++++
 libavcodec/version.h  |    2 +-
 6 files changed, 202 insertions(+), 2 deletions(-)
 create mode 100644 libavcodec/avme.c
 create mode 100644 libavcodec/avme.h

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 407c6c3..43079b6 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -468,7 +468,7 @@ OBJS-$(CONFIG_SMC_DECODER)             += smc.o
 OBJS-$(CONFIG_SMVJPEG_DECODER)         += smvjpegdec.o
 OBJS-$(CONFIG_SNOW_DECODER)            += snowdec.o snow.o snow_dwt.o
 OBJS-$(CONFIG_SNOW_ENCODER)            += snowenc.o snow.o snow_dwt.o             \
-                                          h263.o ituh263enc.o
+                                          h263.o ituh263enc.o avme.o
 OBJS-$(CONFIG_SOL_DPCM_DECODER)        += dpcm.o
 OBJS-$(CONFIG_SONIC_DECODER)           += sonic.o
 OBJS-$(CONFIG_SONIC_ENCODER)           += sonic.o
diff --git a/libavcodec/avme.c b/libavcodec/avme.c
new file mode 100644
index 0000000..36a1e57
--- /dev/null
+++ b/libavcodec/avme.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2015 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * 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.
+ *
+ * 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/avassert.h"
+
+#include "avcodec.h"
+#include "avme.h"
+#include "internal.h"
+
+typedef struct AVMEContext {
+    AVCodecContext *avctx;
+    uint8_t *outbuf;
+    int outbuf_size;
+} AVMEContext;
+
+AVMEContext *av_me_init(int width, int height, enum AVPixelFormat pix_fmt, AVDictionary *dict)
+{
+    AVMEContext *c = av_mallocz(sizeof(*c));
+    AVCodecContext *avctx_enc;
+    AVDictionary *opts = NULL;
+    AVDictionaryEntry *e;
+    AVCodec *enc = avcodec_find_encoder(AV_CODEC_ID_SNOW);
+    int ret;
+
+    if (!c)
+        return NULL;
+
+    if (!enc) {
+        av_log(NULL, AV_LOG_ERROR, "SNOW encoder not found.\n");
+        ret = AVERROR(EINVAL);
+        goto fail;
+    }
+
+    av_dict_copy(&opts, dict, 0);
+
+    if (!(c->avctx = avcodec_alloc_context3(NULL))) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    avctx_enc = c->avctx;
+    avctx_enc->width = width;
+    avctx_enc->height = height;
+    avctx_enc->time_base = (AVRational){1,25};
+
+    e = av_dict_get(dict, "g", NULL, 0);
+    if (e) {
+        avctx_enc->gop_size = atoi(e->value);
+    } else
+        avctx_enc->gop_size = INT_MAX;
+
+    avctx_enc->max_b_frames = 0;
+    avctx_enc->pix_fmt = pix_fmt;
+    avctx_enc->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_LOW_DELAY;
+    if (av_dict_get(dict, "qpel", NULL, 0))
+        avctx_enc->flags |= CODEC_FLAG_QPEL;
+    avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
+    avctx_enc->global_quality = 12;
+    avctx_enc->me_method = ME_ITER;
+//         avctx_enc->dia_size = 16;
+    avctx_enc->mb_decision = FF_MB_DECISION_RD;
+    avctx_enc->scenechange_threshold = 2000000000;
+    avctx_enc->me_sub_cmp =
+    avctx_enc->me_cmp = FF_CMP_SATD;
+    avctx_enc->mb_cmp = FF_CMP_SSE;
+
+    av_dict_set(&opts, "no_bitstream", "1", 0);
+    av_dict_set(&opts, "intra_penalty", "500", 0);
+    ret = avcodec_open2(avctx_enc, enc, &opts);
+    av_dict_free(&opts);
+    if (ret < 0)
+        goto fail;
+    av_assert0(avctx_enc->codec);
+
+    c->outbuf_size = (width + 16) * (height + 16) * 10;
+    if (!(c->outbuf = av_malloc(c->outbuf_size)))
+        goto fail;
+
+    return c;
+fail:
+    av_me_free(&c);
+
+    return NULL;
+}
+
+int av_me_add_frame(struct AVMEContext *c, AVFrame *frame, int refonly)
+{
+    int ret;
+    AVPacket pkt = {0};
+    int got_pkt_ptr;
+
+    av_init_packet(&pkt);
+    pkt.data = c->outbuf;
+    pkt.size = c->outbuf_size;
+
+    ret = avcodec_encode_video2(c->avctx, &pkt, frame, &got_pkt_ptr);
+    av_free_packet(&pkt);
+
+    return ret;
+}
+
+int av_me_get_mvs(struct AVMEContext *c, int16_t (*mvs)[2], int8_t *refs, int width, int height)
+{
+    switch (c->avctx->codec_id) {
+    case AV_CODEC_ID_SNOW:
+        return ff_get_mvs_snow(c->avctx, mvs, refs, width, height);
+    default:
+        return AVERROR(EINVAL);
+    }
+}
+
+void av_me_free(struct AVMEContext **c)
+{
+    if (*c) {
+        avcodec_close((*c)->avctx);
+        av_freep(&(*c)->avctx);
+        av_freep(&(*c)->outbuf);
+        (*c)->outbuf_size = 0;
+    }
+    av_freep(c);
+}
diff --git a/libavcodec/avme.h b/libavcodec/avme.h
new file mode 100644
index 0000000..d85144c
--- /dev/null
+++ b/libavcodec/avme.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * 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.
+ *
+ * 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/dict.h"
+#include "libavutil/frame.h"
+
+struct AVMEContext *av_me_init(int width, int height, enum AVPixelFormat pix_fmt, AVDictionary *dict);
+
+int av_me_add_frame(struct AVMEContext *c, AVFrame *frame, int refonly);
+
+int av_me_get_mvs(struct AVMEContext *c, int16_t (*mvs)[2], int8_t *refs, int width, int height);
+
+void av_me_free(struct AVMEContext **c);
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index f93a196..da3c6aa 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -303,4 +303,6 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame);
 
 int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, int error_count, int pict_type);
 
+int ff_get_mvs_snow(AVCodecContext *avctx, int16_t (*mvs)[2], int8_t *refs, int w, int h);
+
 #endif /* AVCODEC_INTERNAL_H */
diff --git a/libavcodec/snow.c b/libavcodec/snow.c
index fc2e727..de4d816 100644
--- a/libavcodec/snow.c
+++ b/libavcodec/snow.c
@@ -731,3 +731,33 @@ av_cold void ff_snow_common_end(SnowContext *s)
     av_frame_free(&s->mconly_picture);
     av_frame_free(&s->current_picture);
 }
+
+int ff_get_mvs_snow(AVCodecContext *avctx, int16_t (*mvs)[2], int8_t *refs, int w, int h)
+{
+    SnowContext *s = avctx->priv_data;
+    const int b_width  = s->b_width  << s->block_max_depth;
+    const int b_height = s->b_height << s->block_max_depth;
+    const int b_stride= b_width;
+    int x, y;
+
+    if (w != b_width || h != b_height) {
+        av_log(avctx, AV_LOG_ERROR, "mvs array dimensions mismatch %dx%d != %dx%d\n",
+               w, h, b_width, b_height);
+        return AVERROR(EINVAL);
+    }
+
+    for (y=0; y<h; y++) {
+        for (x=0; x<w; x++) {
+            BlockNode *bn= &s->block[x + y*b_stride];
+            if (bn->type) {
+                refs[x + y*w] = -1;
+            } else {
+                refs[x + y*w] = bn->ref;
+                mvs[x + y*w][0] = bn->mx;
+                mvs[x + y*w][1] = bn->my;
+            }
+        }
+    }
+
+    return 0;
+}
diff --git a/libavcodec/version.h b/libavcodec/version.h
index e098dde..6dbeeff 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,7 +29,7 @@
 #include "libavutil/version.h"
 
 #define LIBAVCODEC_VERSION_MAJOR 56
-#define LIBAVCODEC_VERSION_MINOR 59
+#define LIBAVCODEC_VERSION_MINOR 60
 #define LIBAVCODEC_VERSION_MICRO 100
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
-- 
1.7.9.5



More information about the ffmpeg-devel mailing list