Commit 531fbce0 authored by Ramiro Polla's avatar Ramiro Polla Committed by Michael Niedermayer

mpegvideo_enc: add intra_penalty option for p frames

This option allows more control over the use of intra macroblocks in
predictive frames.

By using '-intra_penalty max', intra macroblocks are never used 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.
Signed-off-by: 's avatarMichael Niedermayer <michael@niedermayer.cc>
parent 3d5d0301
...@@ -971,7 +971,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, ...@@ -971,7 +971,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s,
int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20; int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score); 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->intra_penalty)
mb_type|= CANDIDATE_MB_TYPE_INTRA; mb_type|= CANDIDATE_MB_TYPE_INTRA;
if (varc*2 + 200*256 > vard || s->qscale > 24){ if (varc*2 + 200*256 > vard || s->qscale > 24){
// if (varc*2 + 200*256 + 50*(s->lambda2>>FF_LAMBDA_SHIFT) > vard){ // if (varc*2 + 200*256 + 50*(s->lambda2>>FF_LAMBDA_SHIFT) > vard){
...@@ -1040,7 +1040,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, ...@@ -1040,7 +1040,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s,
intra_score= s->mecc.mb_cmp[0](s, c->scratchpad, pix, s->linesize, 16); intra_score= s->mecc.mb_cmp[0](s, c->scratchpad, pix, s->linesize, 16);
} }
intra_score += c->mb_penalty_factor*16; intra_score += c->mb_penalty_factor*16 + s->intra_penalty;
if(intra_score < dmin){ if(intra_score < dmin){
mb_type= CANDIDATE_MB_TYPE_INTRA; mb_type= CANDIDATE_MB_TYPE_INTRA;
...@@ -1648,7 +1648,7 @@ int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type) ...@@ -1648,7 +1648,7 @@ int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type)
} }
} }
void ff_fix_long_p_mvs(MpegEncContext * s) void ff_fix_long_p_mvs(MpegEncContext * s, int type)
{ {
MotionEstContext * const c= &s->me; MotionEstContext * const c= &s->me;
const int f_code= s->f_code; const int f_code= s->f_code;
...@@ -1682,8 +1682,8 @@ void ff_fix_long_p_mvs(MpegEncContext * s) ...@@ -1682,8 +1682,8 @@ void ff_fix_long_p_mvs(MpegEncContext * s)
if( mx >=range || mx <-range if( mx >=range || mx <-range
|| my >=range || my <-range){ || my >=range || my <-range){
s->mb_type[i] &= ~CANDIDATE_MB_TYPE_INTER4V; s->mb_type[i] &= ~CANDIDATE_MB_TYPE_INTER4V;
s->mb_type[i] |= CANDIDATE_MB_TYPE_INTRA; s->mb_type[i] |= type;
s->current_picture.mb_type[i] = CANDIDATE_MB_TYPE_INTRA; s->current_picture.mb_type[i] = type;
} }
} }
} }
......
...@@ -127,7 +127,7 @@ int ff_get_mb_score(struct MpegEncContext *s, int mx, int my, int src_index, ...@@ -127,7 +127,7 @@ int ff_get_mb_score(struct MpegEncContext *s, int mx, int my, int src_index,
int ff_get_best_fcode(struct MpegEncContext *s, int ff_get_best_fcode(struct MpegEncContext *s,
int16_t (*mv_table)[2], int type); int16_t (*mv_table)[2], int type);
void ff_fix_long_p_mvs(struct MpegEncContext *s); void ff_fix_long_p_mvs(struct MpegEncContext *s, int type);
void ff_fix_long_mvs(struct MpegEncContext *s, uint8_t *field_select_table, void ff_fix_long_mvs(struct MpegEncContext *s, uint8_t *field_select_table,
int field_select, int16_t (*mv_table)[2], int f_code, int field_select, int16_t (*mv_table)[2], int f_code,
int type, int truncate); int type, int truncate);
......
...@@ -580,6 +580,8 @@ typedef struct MpegEncContext { ...@@ -580,6 +580,8 @@ typedef struct MpegEncContext {
int scenechange_threshold; int scenechange_threshold;
int noise_reduction; int noise_reduction;
int intra_penalty;
} MpegEncContext; } MpegEncContext;
/* mpegvideo_enc common options */ /* mpegvideo_enc common options */
...@@ -664,6 +666,7 @@ FF_MPV_OPT_CMP_FUNC, \ ...@@ -664,6 +666,7 @@ FF_MPV_OPT_CMP_FUNC, \
{"ps", "RTP payload size in bytes", FF_MPV_OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"ps", "RTP payload size in bytes", FF_MPV_OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \
{"mepc", "Motion estimation bitrate penalty compensation (1.0 = 256)", FF_MPV_OFFSET(me_penalty_compensation), AV_OPT_TYPE_INT, {.i64 = 256 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"mepc", "Motion estimation bitrate penalty compensation (1.0 = 256)", FF_MPV_OFFSET(me_penalty_compensation), AV_OPT_TYPE_INT, {.i64 = 256 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \
{"mepre", "pre motion estimation", FF_MPV_OFFSET(me_pre), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"mepre", "pre motion estimation", FF_MPV_OFFSET(me_pre), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \
{"intra_penalty", "Penalty for intra blocks in block decision", FF_MPV_OFFSET(intra_penalty), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX/2, FF_MPV_OPT_FLAGS }, \
{"a53cc", "Use A53 Closed Captions (if available)", FF_MPV_OFFSET(a53_cc), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FF_MPV_OPT_FLAGS }, \ {"a53cc", "Use A53 Closed Captions (if available)", FF_MPV_OFFSET(a53_cc), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FF_MPV_OPT_FLAGS }, \
extern const AVOption ff_mpv_generic_options[]; extern const AVOption ff_mpv_generic_options[];
......
...@@ -3761,14 +3761,14 @@ static int encode_picture(MpegEncContext *s, int picture_number) ...@@ -3761,14 +3761,14 @@ static int encode_picture(MpegEncContext *s, int picture_number)
s->f_code= FFMAX3(s->f_code, a, b); s->f_code= FFMAX3(s->f_code, a, b);
} }
ff_fix_long_p_mvs(s); ff_fix_long_p_mvs(s, s->intra_penalty ? CANDIDATE_MB_TYPE_INTER : CANDIDATE_MB_TYPE_INTRA);
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, !!s->intra_penalty);
if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) { if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) {
int j; int j;
for(i=0; i<2; i++){ for(i=0; i<2; i++){
for(j=0; j<2; j++) for(j=0; j<2; j++)
ff_fix_long_mvs(s, s->p_field_select_table[i], 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, !!s->intra_penalty);
} }
} }
} }
......
...@@ -345,7 +345,7 @@ static int svq1_encode_plane(SVQ1EncContext *s, int plane, ...@@ -345,7 +345,7 @@ static int svq1_encode_plane(SVQ1EncContext *s, int plane,
s->m.first_slice_line = 0; s->m.first_slice_line = 0;
} }
ff_fix_long_p_mvs(&s->m); ff_fix_long_p_mvs(&s->m, CANDIDATE_MB_TYPE_INTRA);
ff_fix_long_mvs(&s->m, NULL, 0, s->m.p_mv_table, s->m.f_code, ff_fix_long_mvs(&s->m, NULL, 0, s->m.p_mv_table, s->m.f_code,
CANDIDATE_MB_TYPE_INTER, 0); CANDIDATE_MB_TYPE_INTER, 0);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment