Commit 45870f57 authored by Michael Niedermayer's avatar Michael Niedermayer

new motion estimation (epzs) not complete yet but allready pretty good :)

unlimited mv search range
minor bugfix in the mpeg4 header parser
reset picture in gop counter if scene change is detected

Originally committed as revision 344 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent daa57641
...@@ -57,6 +57,8 @@ extern int motion_estimation_method; ...@@ -57,6 +57,8 @@ extern int motion_estimation_method;
#define ME_FULL 1 #define ME_FULL 1
#define ME_LOG 2 #define ME_LOG 2
#define ME_PHODS 3 #define ME_PHODS 3
#define ME_EPZS 4
#define ME_X1 5
/* encoding support */ /* encoding support */
......
...@@ -128,6 +128,7 @@ void init_get_bits(GetBitContext *s, ...@@ -128,6 +128,7 @@ void init_get_bits(GetBitContext *s,
s->bit_cnt += 8; s->bit_cnt += 8;
} }
#endif #endif
s->size= buffer_size;
} }
#ifndef ALT_BITSTREAM_READER #ifndef ALT_BITSTREAM_READER
......
...@@ -197,6 +197,7 @@ typedef struct GetBitContext { ...@@ -197,6 +197,7 @@ typedef struct GetBitContext {
int bit_cnt; int bit_cnt;
UINT8 *buf, *buf_ptr, *buf_end; UINT8 *buf, *buf_ptr, *buf_end;
#endif #endif
int size;
} GetBitContext; } GetBitContext;
typedef struct VLC { typedef struct VLC {
...@@ -787,6 +788,24 @@ static inline int av_log2(unsigned int v) ...@@ -787,6 +788,24 @@ static inline int av_log2(unsigned int v)
return n; return n;
} }
/* median of 3 */
static inline int mid_pred(int a, int b, int c)
{
int vmin, vmax;
vmax = vmin = a;
if (b < vmin)
vmin = b;
else
vmax = b;
if (c < vmin)
vmin = c;
else if (c > vmax)
vmax = c;
return a + b + c - vmin - vmax;
}
/* memory */ /* memory */
void *av_mallocz(int size); void *av_mallocz(int size);
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* ac prediction encoding by Michael Niedermayer <michaelni@gmx.at>
*/ */
#include "common.h" #include "common.h"
#include "dsputil.h" #include "dsputil.h"
...@@ -45,9 +47,11 @@ static int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, ...@@ -45,9 +47,11 @@ static int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
static inline int mpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *dir_ptr); static inline int mpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *dir_ptr);
static void mpeg4_inv_pred_ac(MpegEncContext * s, INT16 *block, int n, static void mpeg4_inv_pred_ac(MpegEncContext * s, INT16 *block, int n,
int dir); int dir);
extern UINT32 inverse[256]; extern UINT32 inverse[256];
static UINT16 mv_penalty[MAX_FCODE][MAX_MV*2+1];
static UINT8 fcode_tab[MAX_MV*2+1];
int h263_get_picture_format(int width, int height) int h263_get_picture_format(int width, int height)
{ {
int format; int format;
...@@ -524,24 +528,6 @@ void h263_pred_acdc(MpegEncContext * s, INT16 *block, int n) ...@@ -524,24 +528,6 @@ void h263_pred_acdc(MpegEncContext * s, INT16 *block, int n)
ac_val1[8 + i] = block[block_permute_op(i)]; ac_val1[8 + i] = block[block_permute_op(i)];
} }
static inline int mid_pred(int a, int b, int c)
{
int vmin, vmax;
vmax = vmin = a;
if (b < vmin)
vmin = b;
else
vmax = b;
if (c < vmin)
vmin = c;
else if (c > vmax)
vmax = c;
return a + b + c - vmin - vmax;
}
INT16 *h263_pred_motion(MpegEncContext * s, int block, INT16 *h263_pred_motion(MpegEncContext * s, int block,
int *px, int *py) int *px, int *py)
{ {
...@@ -648,7 +634,46 @@ static void h263p_encode_umotion(MpegEncContext * s, int val) ...@@ -648,7 +634,46 @@ static void h263p_encode_umotion(MpegEncContext * s, int val)
} }
} }
void h263_encode_init_vlc(MpegEncContext *s) static void init_mv_penalty_and_fcode(MpegEncContext *s)
{
int f_code;
int mv;
for(f_code=1; f_code<=MAX_FCODE; f_code++){
for(mv=-MAX_MV; mv<=MAX_MV; mv++){
int len;
if(mv==0) len= mvtab[0][1];
else{
int val, bit_size, range, code;
bit_size = s->f_code - 1;
range = 1 << bit_size;
val=mv;
if (val < 0)
val = -val;
val--;
code = (val >> bit_size) + 1;
if(code<33){
len= mvtab[code][1] + 1 + bit_size;
}else{
len= mvtab[32][1] + 2 + bit_size;
}
}
mv_penalty[f_code][mv+MAX_MV]= len;
}
}
for(f_code=MAX_FCODE; f_code>0; f_code--){
for(mv=-(16<<f_code); mv<(16<<f_code); mv++){
fcode_tab[mv+MAX_MV]= f_code;
}
}
}
void h263_encode_init(MpegEncContext *s)
{ {
static int done = 0; static int done = 0;
...@@ -656,7 +681,13 @@ void h263_encode_init_vlc(MpegEncContext *s) ...@@ -656,7 +681,13 @@ void h263_encode_init_vlc(MpegEncContext *s)
done = 1; done = 1;
init_rl(&rl_inter); init_rl(&rl_inter);
init_rl(&rl_intra); init_rl(&rl_intra);
init_mv_penalty_and_fcode(s);
} }
s->mv_penalty= mv_penalty;
// use fcodes >1 only for mpeg4 FIXME
if(!s->h263_msmpeg4 && s->h263_pred) s->fcode_tab= fcode_tab;
} }
static void h263_encode_block(MpegEncContext * s, DCTELEM * block, int n) static void h263_encode_block(MpegEncContext * s, DCTELEM * block, int n)
...@@ -2094,9 +2125,8 @@ int mpeg4_decode_picture_header(MpegEncContext * s) ...@@ -2094,9 +2125,8 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
break; break;
} }
state = ((state << 8) | v) & 0xffffff; state = ((state << 8) | v) & 0xffffff;
/* XXX: really detect end of frame */ if( get_bits_count(&s->gb) > s->gb.size*8){
if (state == 0){ printf("no VOP startcode found\n");
printf("illegal zero code found\n");
return -1; return -1;
} }
} }
...@@ -2152,6 +2182,7 @@ int mpeg4_decode_picture_header(MpegEncContext * s) ...@@ -2152,6 +2182,7 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
if(width && height){ /* they should be non zero but who knows ... */ if(width && height){ /* they should be non zero but who knows ... */
s->width = width; s->width = width;
s->height = height; s->height = height;
// printf("%d %d\n", width, height);
} }
} }
......
This diff is collapsed.
...@@ -66,7 +66,7 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) ...@@ -66,7 +66,7 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s)
int n; int n;
UINT64 time_code; UINT64 time_code;
if ((s->picture_number % s->gop_size) == 0) { if (s->picture_in_gop_number == 0) {
/* mpeg1 header repeated every gop */ /* mpeg1 header repeated every gop */
put_header(s, SEQ_START_CODE); put_header(s, SEQ_START_CODE);
......
...@@ -67,6 +67,9 @@ static UINT8 h263_chroma_roundtab[16] = { ...@@ -67,6 +67,9 @@ static UINT8 h263_chroma_roundtab[16] = {
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
}; };
static UINT16 default_mv_penalty[MAX_FCODE][MAX_MV*2+1];
static UINT8 default_fcode_tab[MAX_MV*2+1];
/* default motion estimation */ /* default motion estimation */
int motion_estimation_method = ME_LOG; int motion_estimation_method = ME_LOG;
...@@ -356,8 +359,24 @@ int MPV_encode_init(AVCodecContext *avctx) ...@@ -356,8 +359,24 @@ int MPV_encode_init(AVCodecContext *avctx)
return -1; return -1;
} }
{ /* set up some save defaults, some codecs might override them later */
static int done=0;
if(!done){
int i;
done=1;
memset(default_mv_penalty, 0, sizeof(UINT16)*MAX_FCODE*(2*MAX_MV+1));
memset(default_fcode_tab , 0, sizeof(UINT8)*(2*MAX_MV+1));
for(i=-16; i<16; i++){
default_fcode_tab[i + MAX_MV]= 1;
}
}
}
s->mv_penalty= default_mv_penalty;
s->fcode_tab= default_fcode_tab;
if (s->out_format == FMT_H263) if (s->out_format == FMT_H263)
h263_encode_init_vlc(s); h263_encode_init(s);
s->encoding = 1; s->encoding = 1;
...@@ -375,6 +394,7 @@ int MPV_encode_init(AVCodecContext *avctx) ...@@ -375,6 +394,7 @@ int MPV_encode_init(AVCodecContext *avctx)
rate_control_init(s); rate_control_init(s);
s->picture_number = 0; s->picture_number = 0;
s->picture_in_gop_number = 0;
s->fake_picture_number = 0; s->fake_picture_number = 0;
/* motion detector init */ /* motion detector init */
s->f_code = 1; s->f_code = 1;
...@@ -480,9 +500,10 @@ int MPV_encode_picture(AVCodecContext *avctx, ...@@ -480,9 +500,10 @@ int MPV_encode_picture(AVCodecContext *avctx,
if (!s->intra_only) { if (!s->intra_only) {
/* first picture of GOP is intra */ /* first picture of GOP is intra */
if ((s->picture_number % s->gop_size) == 0) if (s->picture_in_gop_number >= s->gop_size){
s->picture_in_gop_number=0;
s->pict_type = I_TYPE; s->pict_type = I_TYPE;
else }else
s->pict_type = P_TYPE; s->pict_type = P_TYPE;
} else { } else {
s->pict_type = I_TYPE; s->pict_type = I_TYPE;
...@@ -521,6 +542,7 @@ int MPV_encode_picture(AVCodecContext *avctx, ...@@ -521,6 +542,7 @@ int MPV_encode_picture(AVCodecContext *avctx,
MPV_frame_end(s); MPV_frame_end(s);
s->picture_number++; s->picture_number++;
s->picture_in_gop_number++;
if (s->out_format == FMT_MJPEG) if (s->out_format == FMT_MJPEG)
mjpeg_picture_trailer(s); mjpeg_picture_trailer(s);
...@@ -1077,17 +1099,66 @@ static void encode_picture(MpegEncContext *s, int picture_number) ...@@ -1077,17 +1099,66 @@ static void encode_picture(MpegEncContext *s, int picture_number)
s->mv_table[1][xy] = motion_y; s->mv_table[1][xy] = motion_y;
} }
} }
emms_c();
if(s->avg_mb_var < s->mc_mb_var && s->pict_type != B_TYPE){ //FIXME subtract MV bits if(s->avg_mb_var < s->mc_mb_var && s->pict_type != B_TYPE){ //FIXME subtract MV bits
int i; int i;
s->pict_type= I_TYPE; s->pict_type= I_TYPE;
for(i=0; i<s->mb_height*s->mb_width; i++){ s->picture_in_gop_number=0;
s->mb_type[i] = I_TYPE; for(i=0; i<s->mb_num; i++){
s->mb_type[i] = 1;
s->mv_table[0][i] = 0; s->mv_table[0][i] = 0;
s->mv_table[1][i] = 0; s->mv_table[1][i] = 0;
} }
} }
/* find best f_code */
if(s->pict_type==P_TYPE){
int mv_num[8];
int i;
int loose=0;
UINT8 * fcode_tab= s->fcode_tab;
for(i=0; i<8; i++) mv_num[i]=0;
for(i=0; i<s->mb_num; i++){
if(s->mb_type[i] == 0){
mv_num[ fcode_tab[s->mv_table[0][i] + MAX_MV] ]++;
mv_num[ fcode_tab[s->mv_table[1][i] + MAX_MV] ]++;
//printf("%d %d %d\n", s->mv_table[0][i], fcode_tab[s->mv_table[0][i] + MAX_MV], i);
}
//else printf("I");
}
for(i=MAX_FCODE; i>1; i--){
loose+= mv_num[i];
if(loose > 4) break;
}
s->f_code= i;
}else{
s->f_code= 1;
}
//printf("f_code %d ///\n", s->f_code);
/* convert MBs with too long MVs to I-Blocks */
if(s->pict_type==P_TYPE){
int i;
const int f_code= s->f_code;
UINT8 * fcode_tab= s->fcode_tab;
for(i=0; i<s->mb_num; i++){
if(s->mb_type[i] == 0){
if( fcode_tab[s->mv_table[0][i] + MAX_MV] > f_code
|| fcode_tab[s->mv_table[0][i] + MAX_MV] == 0
|| fcode_tab[s->mv_table[1][i] + MAX_MV] > f_code
|| fcode_tab[s->mv_table[1][i] + MAX_MV] == 0 ){
s->mb_type[i] = 1;
s->mv_table[0][i] = 0;
s->mv_table[1][i] = 0;
}
}
}
}
// printf("%d %d\n", s->avg_mb_var, s->mc_mb_var); // printf("%d %d\n", s->avg_mb_var, s->mc_mb_var);
if (!s->fixed_qscale) if (!s->fixed_qscale)
......
...@@ -34,6 +34,9 @@ enum OutputFormat { ...@@ -34,6 +34,9 @@ enum OutputFormat {
#define QMAT_SHIFT_MMX 19 #define QMAT_SHIFT_MMX 19
#define QMAT_SHIFT 25 #define QMAT_SHIFT 25
#define MAX_FCODE 7
#define MAX_MV 2048
typedef struct Predictor{ typedef struct Predictor{
double coeff; double coeff;
double count; double count;
...@@ -71,7 +74,8 @@ typedef struct MpegEncContext { ...@@ -71,7 +74,8 @@ typedef struct MpegEncContext {
int context_initialized; int context_initialized;
int picture_number; int picture_number;
int fake_picture_number; /* picture number at the bitstream frame rate */ int fake_picture_number; /* picture number at the bitstream frame rate */
int gop_picture_number; /* index of the first picture of a GOP */ int gop_picture_number; /* index of the first picture of a GOP based on fake_pic_num & mpeg1 specific */
int picture_in_gop_number; /* 0-> first pic in gop, ... */
int mb_width, mb_height; int mb_width, mb_height;
int mb_num; /* number of MBs of a picture */ int mb_num; /* number of MBs of a picture */
int linesize; /* line size, in bytes, may be different from width */ int linesize; /* line size, in bytes, may be different from width */
...@@ -114,7 +118,7 @@ typedef struct MpegEncContext { ...@@ -114,7 +118,7 @@ typedef struct MpegEncContext {
#define MV_DIRECT 4 // bidirectional mode where the difference equals the MV of the last P/S/I-Frame (mpeg4) #define MV_DIRECT 4 // bidirectional mode where the difference equals the MV of the last P/S/I-Frame (mpeg4)
int mv_type; int mv_type;
#define MV_TYPE_16X16 0 /* 1 vector for the whole mb */ #define MV_TYPE_16X16 0 /* 1 vector for the whole mb */
#define MV_TYPE_8X8 1 /* 4 vectors (h263) */ #define MV_TYPE_8X8 1 /* 4 vectors (h263, mpeg4 4MV) */
#define MV_TYPE_16X8 2 /* 2 vectors, one per 16x8 block */ #define MV_TYPE_16X8 2 /* 2 vectors, one per 16x8 block */
#define MV_TYPE_FIELD 3 /* 2 vectors, one per field */ #define MV_TYPE_FIELD 3 /* 2 vectors, one per field */
#define MV_TYPE_DMV 4 /* 2 vectors, special mpeg2 Dual Prime Vectors */ #define MV_TYPE_DMV 4 /* 2 vectors, special mpeg2 Dual Prime Vectors */
...@@ -126,6 +130,8 @@ typedef struct MpegEncContext { ...@@ -126,6 +130,8 @@ typedef struct MpegEncContext {
int mv[2][4][2]; int mv[2][4][2];
int field_select[2][2]; int field_select[2][2];
int last_mv[2][2][2]; int last_mv[2][2][2];
UINT16 (*mv_penalty)[MAX_MV*2+1]; /* amount of bits needed to encode a MV, used for ME */
UINT8 *fcode_tab; /* smallest fcode needed for each MV */
int has_b_frames; int has_b_frames;
int no_rounding; /* apply no rounding to motion estimation (MPEG4) */ int no_rounding; /* apply no rounding to motion estimation (MPEG4) */
...@@ -350,7 +356,7 @@ INT16 *h263_pred_motion(MpegEncContext * s, int block, ...@@ -350,7 +356,7 @@ INT16 *h263_pred_motion(MpegEncContext * s, int block,
void mpeg4_pred_ac(MpegEncContext * s, INT16 *block, int n, void mpeg4_pred_ac(MpegEncContext * s, INT16 *block, int n,
int dir); int dir);
void mpeg4_encode_picture_header(MpegEncContext *s, int picture_number); void mpeg4_encode_picture_header(MpegEncContext *s, int picture_number);
void h263_encode_init_vlc(MpegEncContext *s); void h263_encode_init(MpegEncContext *s);
void h263_decode_init_vlc(MpegEncContext *s); void h263_decode_init_vlc(MpegEncContext *s);
int h263_decode_picture_header(MpegEncContext *s); int h263_decode_picture_header(MpegEncContext *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