[FFmpeg-devel] mpegvideo_enc: add option to disable intra mbs in p frames

Submitted by Ramiro Polla on May 9, 2018, 6:44 p.m.

Details

Message ID 20180509184425.18789-1-ramiro.polla@gmail.com
State New
Headers show

Commit Message

Ramiro Polla May 9, 2018, 6:44 p.m.
This option prevents the mpv encoders from using intra macroblocks in
predictive frames.

It is useful for glitch artists to generate input material. This option
allows them to split and merge two video files while maintaining fluid
motion from the second video without having intra macroblocks restoring
chunks of the first video.
---
 libavcodec/motion_est.c    | 4 ++--
 libavcodec/mpegvideo.h     | 2 ++
 libavcodec/mpegvideo_enc.c | 5 +++--
 3 files changed, 7 insertions(+), 4 deletions(-)

Comments

Michael Niedermayer May 10, 2018, 9:01 p.m.
On Wed, May 09, 2018 at 08:44:25PM +0200, Ramiro Polla wrote:
> This option prevents the mpv encoders from using intra macroblocks in
> predictive frames.
> 
> It is useful for glitch artists to generate input material. This option
> allows them to split and merge two video files while maintaining fluid
> motion from the second video without having intra macroblocks restoring
> chunks of the first video.

maybe a continuous variable like snows intra_penalty could achieve this
too but give more flexibility in doing it also just partially if wanted

either solution LGTM

thx

[...]

Patch hide | download patch | download mbox

diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c
index 8b5ce2117a..827e2282f7 100644
--- a/libavcodec/motion_est.c
+++ b/libavcodec/motion_est.c
@@ -971,7 +971,7 @@  void ff_estimate_p_frame_motion(MpegEncContext * s,
         int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
         c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
 
-        if (vard*2 + 200*256 > varc)
+        if (vard*2 + 200*256 > varc && !(s->mpv_flags & FF_MPV_FLAG_NOPIMB))
             mb_type|= CANDIDATE_MB_TYPE_INTRA;
         if (varc*2 + 200*256 > vard || s->qscale > 24){
 //        if (varc*2 + 200*256 + 50*(s->lambda2>>FF_LAMBDA_SHIFT) > vard){
@@ -1042,7 +1042,7 @@  void ff_estimate_p_frame_motion(MpegEncContext * s,
         }
         intra_score += c->mb_penalty_factor*16;
 
-        if(intra_score < dmin){
+        if(intra_score < dmin && !(s->mpv_flags & FF_MPV_FLAG_NOPIMB)){
             mb_type= CANDIDATE_MB_TYPE_INTRA;
             s->current_picture.mb_type[mb_y*s->mb_stride + mb_x] = CANDIDATE_MB_TYPE_INTRA; //FIXME cleanup
         }else
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index e16deb64e7..b7ac2c7b48 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -586,6 +586,7 @@  typedef struct MpegEncContext {
 #define FF_MPV_FLAG_CBP_RD       0x0008
 #define FF_MPV_FLAG_NAQ          0x0010
 #define FF_MPV_FLAG_MV0          0x0020
+#define FF_MPV_FLAG_NOPIMB       0x0040
 
 #define FF_MPV_OPT_CMP_FUNC \
 { "sad",    "Sum of absolute differences, fast", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_SAD }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \
@@ -617,6 +618,7 @@  FF_MPV_OPT_CMP_FUNC, \
 { "cbp_rd",         "use rate distortion optimization for CBP",          0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_CBP_RD }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\
 { "naq",            "normalize adaptive quantization",                   0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_NAQ },    0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\
 { "mv0",            "always try a mb with mv=<0,0>",                     0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_MV0 },    0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\
+{ "nopimb",         "do not use intra mbs for predictive frames",        0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_NOPIMB }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\
 { "luma_elim_threshold",   "single coefficient elimination threshold for luminance (negative values also consider dc coefficient)",\
                                                                       FF_MPV_OFFSET(luma_elim_threshold), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS },\
 { "chroma_elim_threshold", "single coefficient elimination threshold for chrominance (negative values also consider dc coefficient)",\
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index 9fdab31a25..e41a8f40cf 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -3752,6 +3752,7 @@  static int encode_picture(MpegEncContext *s, int picture_number)
 
     if(!s->umvplus){
         if(s->pict_type==AV_PICTURE_TYPE_P || s->pict_type==AV_PICTURE_TYPE_S) {
+            int truncate = s->mpv_flags & FF_MPV_FLAG_NOPIMB;
             s->f_code= ff_get_best_fcode(s, s->p_mv_table, CANDIDATE_MB_TYPE_INTER);
 
             if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) {
@@ -3762,13 +3763,13 @@  static int encode_picture(MpegEncContext *s, int picture_number)
             }
 
             ff_fix_long_p_mvs(s);
-            ff_fix_long_mvs(s, NULL, 0, s->p_mv_table, s->f_code, CANDIDATE_MB_TYPE_INTER, 0);
+            ff_fix_long_mvs(s, NULL, 0, s->p_mv_table, s->f_code, CANDIDATE_MB_TYPE_INTER, truncate);
             if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) {
                 int j;
                 for(i=0; i<2; i++){
                     for(j=0; j<2; j++)
                         ff_fix_long_mvs(s, s->p_field_select_table[i], j,
-                                        s->p_field_mv_table[i][j], s->f_code, CANDIDATE_MB_TYPE_INTER_I, 0);
+                                        s->p_field_mv_table[i][j], s->f_code, CANDIDATE_MB_TYPE_INTER_I, truncate);
                 }
             }
         }