Commit 7d1c3fc1 authored by Michael Niedermayer's avatar Michael Niedermayer

rate distortion mb decision support

fix decoding of old %16!=0 divx
fix assertion failure in motion_est.c

Originally committed as revision 2094 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 80adda8e
......@@ -113,7 +113,7 @@ static int video_disable = 0;
static int video_codec_id = CODEC_ID_NONE;
static int same_quality = 0;
static int b_frames = 0;
static int use_hq = 0;
static int mb_decision = FF_MB_DECISION_SIMPLE;
static int use_4mv = 0;
/* Fx */
static int use_aic = 0;
......@@ -1751,6 +1751,11 @@ static void opt_b_frames(const char *arg)
}
}
static void opt_mb_decision(const char *arg)
{
mb_decision = atoi(arg);
}
static void opt_qscale(const char *arg)
{
video_qscale = atoi(arg);
......@@ -2222,9 +2227,8 @@ static void opt_output_file(const char *filename)
if(bitexact)
video_enc->flags |= CODEC_FLAG_BITEXACT;
if (use_hq) {
video_enc->flags |= CODEC_FLAG_HQ;
}
video_enc->mb_decision = mb_decision;
/* Fx */
if (use_umv) {
video_enc->flags |= CODEC_FLAG_H263P_UMV;
......@@ -2234,7 +2238,7 @@ static void opt_output_file(const char *filename)
}
/* /Fx */
if (use_4mv) {
video_enc->flags |= CODEC_FLAG_HQ;
video_enc->mb_decision = FF_MB_DECISION_BITS; //FIXME remove
video_enc->flags |= CODEC_FLAG_4MV;
}
......@@ -2679,7 +2683,8 @@ const OptionDef options[] = {
{ "er", HAS_ARG | OPT_EXPERT, {(void*)opt_error_resilience}, "set error resilience", "" },
{ "ec", HAS_ARG | OPT_EXPERT, {(void*)opt_error_concealment}, "set error concealment", "" },
{ "bf", HAS_ARG | OPT_EXPERT, {(void*)opt_b_frames}, "use 'frames' B frames (only MPEG-4)", "frames" },
{ "hq", OPT_BOOL | OPT_EXPERT, {(void*)&use_hq}, "activate high quality settings" },
{ "hq", OPT_BOOL | OPT_EXPERT, {(void*)&mb_decision}, "activate high quality settings" },
{ "mbd", HAS_ARG | OPT_EXPERT, {(void*)opt_mb_decision}, "macroblock decision", "mode" },
{ "4mv", OPT_BOOL | OPT_EXPERT, {(void*)&use_4mv}, "use four motion vector by macroblock (only MPEG-4)" },
{ "part", OPT_BOOL | OPT_EXPERT, {(void*)&use_part}, "use data partitioning (only MPEG-4)" },
{ "bug", HAS_ARG | OPT_EXPERT, {(void*)opt_workaround_bugs}, "workaround not auto detected encoder bugs", "param" },
......
......@@ -4220,11 +4220,11 @@ static int parse_ffconfig(const char *filename)
}
} else if (!strcasecmp(cmd, "VideoHighQuality")) {
if (stream) {
video_enc.flags |= CODEC_FLAG_HQ;
video_enc.mb_decision = FF_MB_DECISION_BITS;
}
} else if (!strcasecmp(cmd, "Video4MotionVector")) {
if (stream) {
video_enc.flags |= CODEC_FLAG_HQ;
video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
video_enc.flags |= CODEC_FLAG_4MV;
}
} else if (!strcasecmp(cmd, "VideoQDiff")) {
......
......@@ -15,8 +15,8 @@ extern "C" {
#define LIBAVCODEC_VERSION_INT 0x000406
#define LIBAVCODEC_VERSION "0.4.6"
#define LIBAVCODEC_BUILD 4672
#define LIBAVCODEC_BUILD_STR "4672"
#define LIBAVCODEC_BUILD 4673
#define LIBAVCODEC_BUILD_STR "4673"
#define LIBAVCODEC_IDENT "FFmpeg" LIBAVCODEC_VERSION "b" LIBAVCODEC_BUILD_STR
......@@ -169,7 +169,6 @@ static const int Motion_Est_QTab[] = { ME_ZERO, ME_PHODS, ME_LOG,
Note: note not everything is supported yet
*/
#define CODEC_FLAG_HQ 0x0001 ///< brute force MB-type decission mode (slow)
#define CODEC_FLAG_QSCALE 0x0002 ///< use fixed qscale
#define CODEC_FLAG_4MV 0x0004 ///< 4 MV per MB allowed
#define CODEC_FLAG_QPEL 0x0010 ///< use qpel MC
......@@ -1173,7 +1172,17 @@ typedef struct AVCodecContext {
* - decoding: set by decoder
*/
int xvmc_acceleration;
/**
* macroblock decision mode
* - encoding: set by user.
* - decoding: unused
*/
int mb_decision;
#define FF_MB_DECISION_SIMPLE 0 ///< uses mb_cmp
#define FF_MB_DECISION_BITS 1 ///< chooses the one which needs the fewest bits
#define FF_MB_DECISION_RD 2 ///< rate distoration
} AVCodecContext;
......
......@@ -30,6 +30,14 @@
#include "mpegvideo.h"
#include "common.h"
static void decode_mb(MpegEncContext *s){
s->dest[0] = s->current_picture.data[0] + (s->mb_y * 16* s->linesize ) + s->mb_x * 16;
s->dest[1] = s->current_picture.data[1] + (s->mb_y * 8 * s->uvlinesize) + s->mb_x * 8;
s->dest[2] = s->current_picture.data[2] + (s->mb_y * 8 * s->uvlinesize) + s->mb_x * 8;
MPV_decode_mb(s, s->block);
}
/**
* replaces the current MB with a flat dc only version.
*/
......@@ -346,7 +354,7 @@ static void guess_mv(MpegEncContext *s){
s->mb_y= mb_y;
s->mv[0][0][0]= 0;
s->mv[0][0][1]= 0;
MPV_decode_mb(s, s->block);
decode_mb(s);
}
}
return;
......@@ -480,7 +488,7 @@ int score_sum=0;
s->motion_val[mot_index][0]= s->mv[0][0][0]= mv_predictor[j][0];
s->motion_val[mot_index][1]= s->mv[0][0][1]= mv_predictor[j][1];
MPV_decode_mb(s, s->block);
decode_mb(s);
if(mb_x>0 && fixed[mb_xy-1]){
int k;
......@@ -513,7 +521,7 @@ score_sum+= best_score;
s->motion_val[mot_index][0]= s->mv[0][0][0]= mv_predictor[best_pred][0];
s->motion_val[mot_index][1]= s->mv[0][0][1]= mv_predictor[best_pred][1];
MPV_decode_mb(s, s->block);
decode_mb(s);
if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){
......@@ -848,7 +856,7 @@ void ff_er_frame_end(MpegEncContext *s){
s->mb_x= mb_x;
s->mb_y= mb_y;
MPV_decode_mb(s, s->block);
decode_mb(s);
}
}
......@@ -888,7 +896,7 @@ void ff_er_frame_end(MpegEncContext *s){
s->dsp.clear_blocks(s->block[0]);
s->mb_x= mb_x;
s->mb_y= mb_y;
MPV_decode_mb(s, s->block);
decode_mb(s);
}
}
}else
......
......@@ -512,6 +512,53 @@ int ff_mpeg4_set_direct_mv(MpegEncContext *s, int mx, int my){
}
}
void ff_h263_update_motion_val(MpegEncContext * s){
const int mb_xy = s->mb_y * s->mb_stride + s->mb_x;
//FIXME a lot of thet is only needed for !low_delay
const int wrap = s->block_wrap[0];
const int xy = s->block_index[0];
s->current_picture.mbskip_table[mb_xy]= s->mb_skiped;
if(s->mv_type != MV_TYPE_8X8){
int motion_x, motion_y;
if (s->mb_intra) {
motion_x = 0;
motion_y = 0;
} else if (s->mv_type == MV_TYPE_16X16) {
motion_x = s->mv[0][0][0];
motion_y = s->mv[0][0][1];
} else /*if (s->mv_type == MV_TYPE_FIELD)*/ {
int i;
motion_x = s->mv[0][0][0] + s->mv[0][1][0];
motion_y = s->mv[0][0][1] + s->mv[0][1][1];
motion_x = (motion_x>>1) | (motion_x&1);
for(i=0; i<2; i++){
s->field_mv_table[mb_xy][i][0]= s->mv[0][i][0];
s->field_mv_table[mb_xy][i][1]= s->mv[0][i][1];
s->field_select_table[mb_xy][i]= s->field_select[0][i];
}
}
/* no update if 8X8 because it has been done during parsing */
s->motion_val[xy][0] = motion_x;
s->motion_val[xy][1] = motion_y;
s->motion_val[xy + 1][0] = motion_x;
s->motion_val[xy + 1][1] = motion_y;
s->motion_val[xy + wrap][0] = motion_x;
s->motion_val[xy + wrap][1] = motion_y;
s->motion_val[xy + 1 + wrap][0] = motion_x;
s->motion_val[xy + 1 + wrap][1] = motion_y;
}
if(s->encoding){ //FIXME encoding MUST be cleaned up
if (s->mv_type == MV_TYPE_8X8)
s->current_picture.mb_type[mb_xy]= MB_TYPE_L0 | MB_TYPE_8x8;
else
s->current_picture.mb_type[mb_xy]= MB_TYPE_L0 | MB_TYPE_16x16;
}
}
#ifdef CONFIG_ENCODERS
void mpeg4_encode_mb(MpegEncContext * s,
DCTELEM block[6][64],
......
......@@ -209,6 +209,9 @@ static int decode_slice(MpegEncContext *s){
//printf("%d %d %06X\n", ret, get_bits_count(&s->gb), show_bits(&s->gb, 24));
ret= s->decode_mb(s, s->block);
if (s->pict_type!=B_TYPE)
ff_h263_update_motion_val(s);
if(ret<0){
const int xy= s->mb_x + s->mb_y*s->mb_stride;
if(ret==SLICE_END){
......@@ -533,6 +536,9 @@ retry:
if(s->divx_version && s->divx_version<500){
s->workaround_bugs|= FF_BUG_EDGE;
}
if(s->avctx->codec_tag == ff_get_fourcc("DIVX") && s->divx_version==0 && s->lavc_build==0 && s->xvid_build==0 && s->vo_type==0 && s->vol_control_parameters==0 && s->low_delay)
s->workaround_bugs|= FF_BUG_EDGE;
#if 0
if(s->divx_version==500)
......
......@@ -1083,7 +1083,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s,
printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",
varc, s->avg_mb_var, sum, vard, mx - xx, my - yy);
#endif
if(s->flags&CODEC_FLAG_HQ){
if(s->avctx->mb_decision > FF_MB_DECISION_SIMPLE){
if (vard <= 64 || vard < varc)
s->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
else
......@@ -1315,8 +1315,8 @@ static inline int check_bidir_mv(MpegEncContext * s,
dxy = ((motion_fy & 3) << 2) | (motion_fx & 3);
src_x = mb_x * 16 + (motion_fx >> 2);
src_y = mb_y * 16 + (motion_fy >> 2);
assert(src_x >=-16 && src_x<=s->width);
assert(src_y >=-16 && src_y<=s->height);
assert(src_x >=-16 && src_x<=s->h_edge_pos);
assert(src_y >=-16 && src_y<=s->v_edge_pos);
ptr = s->last_picture.data[0] + (src_y * s->linesize) + src_x;
s->dsp.put_qpel_pixels_tab[0][dxy](dest_y , ptr , s->linesize);
......@@ -1324,8 +1324,8 @@ static inline int check_bidir_mv(MpegEncContext * s,
dxy = ((motion_by & 3) << 2) | (motion_bx & 3);
src_x = mb_x * 16 + (motion_bx >> 2);
src_y = mb_y * 16 + (motion_by >> 2);
assert(src_x >=-16 && src_x<=s->width);
assert(src_y >=-16 && src_y<=s->height);
assert(src_x >=-16 && src_x<=s->h_edge_pos);
assert(src_y >=-16 && src_y<=s->v_edge_pos);
ptr = s->next_picture.data[0] + (src_y * s->linesize) + src_x;
s->dsp.avg_qpel_pixels_tab[0][dxy](dest_y , ptr , s->linesize);
......@@ -1333,8 +1333,8 @@ static inline int check_bidir_mv(MpegEncContext * s,
dxy = ((motion_fy & 1) << 1) | (motion_fx & 1);
src_x = mb_x * 16 + (motion_fx >> 1);
src_y = mb_y * 16 + (motion_fy >> 1);
assert(src_x >=-16 && src_x<=s->width);
assert(src_y >=-16 && src_y<=s->height);
assert(src_x >=-16 && src_x<=s->h_edge_pos);
assert(src_y >=-16 && src_y<=s->v_edge_pos);
ptr = s->last_picture.data[0] + (src_y * s->linesize) + src_x;
s->dsp.put_pixels_tab[0][dxy](dest_y , ptr , s->linesize, 16);
......@@ -1342,8 +1342,8 @@ static inline int check_bidir_mv(MpegEncContext * s,
dxy = ((motion_by & 1) << 1) | (motion_bx & 1);
src_x = mb_x * 16 + (motion_bx >> 1);
src_y = mb_y * 16 + (motion_by >> 1);
assert(src_x >=-16 && src_x<=s->width);
assert(src_y >=-16 && src_y<=s->height);
assert(src_x >=-16 && src_x<=s->h_edge_pos);
assert(src_y >=-16 && src_y<=s->v_edge_pos);
ptr = s->next_picture.data[0] + (src_y * s->linesize) + src_x;
s->dsp.avg_pixels_tab[0][dxy](dest_y , ptr , s->linesize, 16);
......@@ -1523,7 +1523,7 @@ void ff_estimate_b_frame_motion(MpegEncContext * s,
s->current_picture.mc_mb_var[mb_y*s->mb_stride + mb_x] = score; //FIXME use SSE
}
if(s->flags&CODEC_FLAG_HQ){
if(s->avctx->mb_decision > FF_MB_DECISION_SIMPLE){
type= MB_TYPE_FORWARD | MB_TYPE_BACKWARD | MB_TYPE_BIDIR | MB_TYPE_DIRECT; //FIXME something smarter
if(dmin>256*256*16) type&= ~MB_TYPE_DIRECT; //dont try direct mode if its invalid for this MB
}
......
......@@ -1924,6 +1924,7 @@ static int mpeg_decode_slice(AVCodecContext *avctx,
s->resync_mb_x= s->mb_x;
s->resync_mb_y= s->mb_y = start_code;
s->mb_skip_run= 0;
ff_init_block_index(s);
for(;;) {
s->dsp.clear_blocks(s->block[0]);
......@@ -1959,8 +1960,12 @@ static int mpeg_decode_slice(AVCodecContext *avctx,
s->motion_val[xy + 1 + wrap][1] = motion_y;
}
MPV_decode_mb(s, s->block);
s->dest[0] += 16;
s->dest[1] += 8;
s->dest[2] += 8;
MPV_decode_mb(s, s->block);
if (++s->mb_x >= s->mb_width) {
if(s->avctx->codec_tag == ff_get_fourcc("VCR2"))
exchange_uv((AVFrame*)s->current_picture_ptr);
......@@ -1983,6 +1988,8 @@ static int mpeg_decode_slice(AVCodecContext *avctx,
}else
goto eos;
}
ff_init_block_index(s);
}
/* skip mb handling */
......
This diff is collapsed.
......@@ -430,6 +430,7 @@ typedef struct MpegEncContext {
int block_index[6]; ///< index to current MB in block based arrays with edges
int block_wrap[6];
uint8_t *dest[3];
int *mb_index2xy; ///< mb_index -> mb_x + mb_y*mb_stride
......@@ -723,14 +724,7 @@ void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int en
extern enum PixelFormat ff_yuv420p_list[2];
static inline void ff_init_block_index(MpegEncContext *s){
s->block_index[0]= s->block_wrap[0]*(s->mb_y*2 + 1) - 1 + s->mb_x*2;
s->block_index[1]= s->block_wrap[0]*(s->mb_y*2 + 1) + s->mb_x*2;
s->block_index[2]= s->block_wrap[0]*(s->mb_y*2 + 2) - 1 + s->mb_x*2;
s->block_index[3]= s->block_wrap[0]*(s->mb_y*2 + 2) + s->mb_x*2;
s->block_index[4]= s->block_wrap[4]*(s->mb_y + 1) + s->block_wrap[0]*(s->mb_height*2 + 2) + s->mb_x;
s->block_index[5]= s->block_wrap[4]*(s->mb_y + 1 + s->mb_height + 2) + s->block_wrap[0]*(s->mb_height*2 + 2) + s->mb_x;
}
void ff_init_block_index(MpegEncContext *s);
static inline void ff_update_block_index(MpegEncContext *s){
s->block_index[0]+=2;
......@@ -739,6 +733,9 @@ static inline void ff_update_block_index(MpegEncContext *s){
s->block_index[3]+=2;
s->block_index[4]++;
s->block_index[5]++;
s->dest[0]+= 16;
s->dest[1]+= 8;
s->dest[2]+= 8;
}
static inline int get_bits_diff(MpegEncContext *s){
......@@ -833,6 +830,7 @@ void h263_decode_init_vlc(MpegEncContext *s);
int h263_decode_picture_header(MpegEncContext *s);
int ff_h263_decode_gob_header(MpegEncContext *s);
int ff_mpeg4_decode_picture_header(MpegEncContext * s, GetBitContext *gb);
void ff_h263_update_motion_val(MpegEncContext * s);
int intel_h263_decode_picture_header(MpegEncContext *s);
......
......@@ -466,6 +466,7 @@ static int rv10_decode_packet(AVCodecContext *avctx,
fprintf(stderr, "ERROR at MB %d %d\n", s->mb_x, s->mb_y);
return -1;
}
ff_h263_update_motion_val(s);
MPV_decode_mb(s, s->block);
if (++s->mb_x == s->mb_width) {
s->mb_x = 0;
......
......@@ -489,7 +489,7 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
case CODEC_TYPE_VIDEO:
snprintf(buf, buf_size,
"Video: %s%s",
codec_name, enc->flags & CODEC_FLAG_HQ ? " (hq)" : "");
codec_name, enc->mb_decision ? " (hq)" : "");
if (enc->codec_id == CODEC_ID_RAWVIDEO) {
snprintf(buf + strlen(buf), buf_size - strlen(buf),
", %s",
......
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