mpeg4 b-frame enoding support removed old, out-commented ratecontrol reuse motion compensation code between encoding & decoding prefix newly added global functions with ff_ to reduce namespace polution b-frame ME (unfinished, but working) added some comments to mpegvideo.h do MC on encoding only once if possible bugs? ;) Originally committed as revision 403 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
| @@ -77,16 +77,20 @@ extern int motion_estimation_method; | |||||
| /* ME algos sorted by quality */ | /* ME algos sorted by quality */ | ||||
| static const int Motion_Est_QTab[] = { 1, 4, 3, 6, 5, 2 }; | static const int Motion_Est_QTab[] = { 1, 4, 3, 6, 5, 2 }; | ||||
| #define FF_MAX_B_FRAMES 4 | |||||
| /* encoding support */ | /* encoding support */ | ||||
| /* note not everything is supported yet */ | /* note not everything is supported yet */ | ||||
| #define CODEC_FLAG_HQ 0x0001 /* high quality (non real time) encoding */ | #define CODEC_FLAG_HQ 0x0001 /* high quality (non real time) encoding */ | ||||
| #define CODEC_FLAG_QSCALE 0x0002 /* use fixed qscale */ | #define CODEC_FLAG_QSCALE 0x0002 /* use fixed qscale */ | ||||
| #define CODEC_FLAG_4MV 0x0004 /* 4 MV per MB allowed */ | #define CODEC_FLAG_4MV 0x0004 /* 4 MV per MB allowed */ | ||||
| #define CODEC_FLAG_B 0x0008 /* use B frames */ | |||||
| #define CODEC_FLAG_QPEL 0x0010 /* use qpel MC */ | #define CODEC_FLAG_QPEL 0x0010 /* use qpel MC */ | ||||
| #define CODEC_FLAG_GMC 0x0020 /* use GMC */ | #define CODEC_FLAG_GMC 0x0020 /* use GMC */ | ||||
| #define CODEC_FLAG_TYPE 0x0040 /* fixed I/P frame type, from avctx->key_frame */ | #define CODEC_FLAG_TYPE 0x0040 /* fixed I/P frame type, from avctx->key_frame */ | ||||
| /* parent program gurantees that the input for b-frame containing streams is not written to | |||||
| for at least s->max_b_frames+1 frames, if this is not set than the input will be copied */ | |||||
| #define CODEC_FLAG_INPUT_PRESERVED 0x0100 | |||||
| /* codec capabilities */ | /* codec capabilities */ | ||||
| @@ -141,7 +145,8 @@ typedef struct AVCodecContext { | |||||
| int qmin; /* min qscale */ | int qmin; /* min qscale */ | ||||
| int qmax; /* max qscale */ | int qmax; /* max qscale */ | ||||
| int max_qdiff; /* max qscale difference between frames */ | int max_qdiff; /* max qscale difference between frames */ | ||||
| int max_b_frames; /* maximum b frames, the output will be delayed by max_b_frames+1 relative to the input */ | |||||
| struct AVCodec *codec; | struct AVCodec *codec; | ||||
| void *priv_data; | void *priv_data; | ||||
| @@ -451,3 +451,7 @@ void free_vlc(VLC *vlc) | |||||
| free(vlc->table_codes); | free(vlc->table_codes); | ||||
| } | } | ||||
| int ff_gcd(int a, int b){ | |||||
| if(b) return ff_gcd(b, a%b); | |||||
| else return a; | |||||
| } | |||||
| @@ -884,4 +884,7 @@ static inline int mid_pred(int a, int b, int c) | |||||
| /* memory */ | /* memory */ | ||||
| void *av_mallocz(int size); | void *av_mallocz(int size); | ||||
| /* math */ | |||||
| int ff_gcd(int a, int b); | |||||
| #endif | #endif | ||||
| @@ -27,6 +27,7 @@ | |||||
| void (*ff_idct)(DCTELEM *block); | void (*ff_idct)(DCTELEM *block); | ||||
| void (*get_pixels)(DCTELEM *block, const UINT8 *pixels, int line_size); | void (*get_pixels)(DCTELEM *block, const UINT8 *pixels, int line_size); | ||||
| void (*diff_pixels)(DCTELEM *block, const UINT8 *s1, const UINT8 *s2, int stride); | |||||
| void (*put_pixels_clamped)(const DCTELEM *block, UINT8 *pixels, int line_size); | void (*put_pixels_clamped)(const DCTELEM *block, UINT8 *pixels, int line_size); | ||||
| void (*add_pixels_clamped)(const DCTELEM *block, UINT8 *pixels, int line_size); | void (*add_pixels_clamped)(const DCTELEM *block, UINT8 *pixels, int line_size); | ||||
| void (*gmc1)(UINT8 *dst, UINT8 *src, int srcStride, int h, int x16, int y16, int rounder); | void (*gmc1)(UINT8 *dst, UINT8 *src, int srcStride, int h, int x16, int y16, int rounder); | ||||
| @@ -181,6 +182,28 @@ void get_pixels_c(DCTELEM *block, const UINT8 *pixels, int line_size) | |||||
| } | } | ||||
| } | } | ||||
| void diff_pixels_c(DCTELEM *block, const UINT8 *s1, const UINT8 *s2, int stride){ | |||||
| DCTELEM *p; | |||||
| int i; | |||||
| /* read the pixels */ | |||||
| p = block; | |||||
| for(i=0;i<8;i++) { | |||||
| p[0] = s1[0] - s2[0]; | |||||
| p[1] = s1[1] - s2[1]; | |||||
| p[2] = s1[2] - s2[2]; | |||||
| p[3] = s1[3] - s2[3]; | |||||
| p[4] = s1[4] - s2[4]; | |||||
| p[5] = s1[5] - s2[5]; | |||||
| p[6] = s1[6] - s2[6]; | |||||
| p[7] = s1[7] - s2[7]; | |||||
| s1 += stride; | |||||
| s2 += stride; | |||||
| p += 8; | |||||
| } | |||||
| } | |||||
| void put_pixels_clamped_c(const DCTELEM *block, UINT8 *pixels, int line_size) | void put_pixels_clamped_c(const DCTELEM *block, UINT8 *pixels, int line_size) | ||||
| { | { | ||||
| const DCTELEM *p; | const DCTELEM *p; | ||||
| @@ -898,6 +921,7 @@ void dsputil_init(void) | |||||
| ff_idct = j_rev_dct; | ff_idct = j_rev_dct; | ||||
| #endif | #endif | ||||
| get_pixels = get_pixels_c; | get_pixels = get_pixels_c; | ||||
| diff_pixels = diff_pixels_c; | |||||
| put_pixels_clamped = put_pixels_clamped_c; | put_pixels_clamped = put_pixels_clamped_c; | ||||
| add_pixels_clamped = add_pixels_clamped_c; | add_pixels_clamped = add_pixels_clamped_c; | ||||
| gmc1= gmc1_c; | gmc1= gmc1_c; | ||||
| @@ -37,6 +37,7 @@ void dsputil_init(void); | |||||
| extern void (*ff_idct)(DCTELEM *block); | extern void (*ff_idct)(DCTELEM *block); | ||||
| extern void (*get_pixels)(DCTELEM *block, const UINT8 *pixels, int line_size); | extern void (*get_pixels)(DCTELEM *block, const UINT8 *pixels, int line_size); | ||||
| extern void (*diff_pixels)(DCTELEM *block, const UINT8 *s1, const UINT8 *s2, int stride); | |||||
| extern void (*put_pixels_clamped)(const DCTELEM *block, UINT8 *pixels, int line_size); | extern void (*put_pixels_clamped)(const DCTELEM *block, UINT8 *pixels, int line_size); | ||||
| extern void (*add_pixels_clamped)(const DCTELEM *block, UINT8 *pixels, int line_size); | extern void (*add_pixels_clamped)(const DCTELEM *block, UINT8 *pixels, int line_size); | ||||
| extern void (*gmc1)(UINT8 *dst, UINT8 *src, int srcStride, int h, int x16, int y16, int rounder); | extern void (*gmc1)(UINT8 *dst, UINT8 *src, int srcStride, int h, int x16, int y16, int rounder); | ||||
| @@ -44,6 +45,7 @@ extern void (*clear_blocks)(DCTELEM *blocks); | |||||
| void get_pixels_c(DCTELEM *block, const UINT8 *pixels, int line_size); | void get_pixels_c(DCTELEM *block, const UINT8 *pixels, int line_size); | ||||
| void diff_pixels_c(DCTELEM *block, const UINT8 *s1, const UINT8 *s2, int stride); | |||||
| void put_pixels_clamped_c(const DCTELEM *block, UINT8 *pixels, int line_size); | void put_pixels_clamped_c(const DCTELEM *block, UINT8 *pixels, int line_size); | ||||
| void add_pixels_clamped_c(const DCTELEM *block, UINT8 *pixels, int line_size); | void add_pixels_clamped_c(const DCTELEM *block, UINT8 *pixels, int line_size); | ||||
| void clear_blocks_c(DCTELEM *blocks); | void clear_blocks_c(DCTELEM *blocks); | ||||
| @@ -36,7 +36,7 @@ | |||||
| static void h263_encode_block(MpegEncContext * s, DCTELEM * block, | static void h263_encode_block(MpegEncContext * s, DCTELEM * block, | ||||
| int n); | int n); | ||||
| static void h263_encode_motion(MpegEncContext * s, int val); | |||||
| static void h263_encode_motion(MpegEncContext * s, int val, int fcode); | |||||
| static void h263p_encode_umotion(MpegEncContext * s, int val); | static void h263p_encode_umotion(MpegEncContext * s, int val); | ||||
| static void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block, | static void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block, | ||||
| int n, int dc, UINT8 *scan_table); | int n, int dc, UINT8 *scan_table); | ||||
| @@ -252,78 +252,167 @@ void mpeg4_encode_mb(MpegEncContext * s, | |||||
| DCTELEM block[6][64], | DCTELEM block[6][64], | ||||
| int motion_x, int motion_y) | int motion_x, int motion_y) | ||||
| { | { | ||||
| int cbpc, cbpy, i, cbp, pred_x, pred_y; | |||||
| int cbpc, cbpy, i, pred_x, pred_y; | |||||
| int bits; | int bits; | ||||
| // printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y); | // printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y); | ||||
| if (!s->mb_intra) { | if (!s->mb_intra) { | ||||
| /* compute cbp */ | /* compute cbp */ | ||||
| cbp = 0; | |||||
| int cbp = 0; | |||||
| for (i = 0; i < 6; i++) { | for (i = 0; i < 6; i++) { | ||||
| if (s->block_last_index[i] >= 0) | |||||
| cbp |= 1 << (5 - i); | |||||
| } | |||||
| if ((cbp | motion_x | motion_y) == 0 && s->mv_type==MV_TYPE_16X16) { | |||||
| /* skip macroblock */ | |||||
| put_bits(&s->pb, 1, 1); | |||||
| s->misc_bits++; | |||||
| s->last_bits++; | |||||
| s->skip_count++; | |||||
| return; | |||||
| if (s->block_last_index[i] >= 0) | |||||
| cbp |= 1 << (5 - i); | |||||
| } | } | ||||
| put_bits(&s->pb, 1, 0); /* mb coded */ | |||||
| if(s->mv_type==MV_TYPE_16X16){ | |||||
| cbpc = cbp & 3; | |||||
| put_bits(&s->pb, | |||||
| inter_MCBPC_bits[cbpc], | |||||
| inter_MCBPC_code[cbpc]); | |||||
| cbpy = cbp >> 2; | |||||
| cbpy ^= 0xf; | |||||
| put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]); | |||||
| if(s->pict_type==B_TYPE){ | |||||
| static const int mb_type_table[8]= {-1, 2, 3, 1,-1,-1,-1, 0}; /* convert from mv_dir to type */ | |||||
| int mb_type= mb_type_table[s->mv_dir]; | |||||
| if(s->mb_x==0){ | |||||
| s->last_mv[0][0][0]= | |||||
| s->last_mv[0][0][1]= | |||||
| s->last_mv[1][0][0]= | |||||
| s->last_mv[1][0][1]= 0; | |||||
| } | |||||
| /* nothing to do if this MB was skiped in the next P Frame */ | |||||
| if(s->mbskip_table[s->mb_y * s->mb_width + s->mb_x]){ | |||||
| s->skip_count++; | |||||
| s->mv[0][0][0]= | |||||
| s->mv[0][0][1]= | |||||
| s->mv[1][0][0]= | |||||
| s->mv[1][0][1]= 0; | |||||
| // s->mv_dir= MV_DIR_FORWARD; //doesnt matter | |||||
| return; | |||||
| } | |||||
| if ((cbp | motion_x | motion_y | mb_type) ==0) { | |||||
| /* direct MB with MV={0,0} */ | |||||
| put_bits(&s->pb, 1, 1); /* mb not coded modb1=1 */ | |||||
| s->misc_bits++; | |||||
| s->last_bits++; | |||||
| s->skip_count++; | |||||
| return; | |||||
| } | |||||
| put_bits(&s->pb, 1, 0); /* mb coded modb1=0 */ | |||||
| put_bits(&s->pb, 1, cbp ? 0 : 1); /* modb2 */ //FIXME merge | |||||
| put_bits(&s->pb, mb_type+1, 1); // this table is so simple that we dont need it :) | |||||
| if(cbp) put_bits(&s->pb, 6, cbp); | |||||
| if(cbp && mb_type) | |||||
| put_bits(&s->pb, 1, 0); /* no q-scale change */ | |||||
| bits= get_bit_count(&s->pb); | bits= get_bit_count(&s->pb); | ||||
| s->misc_bits+= bits - s->last_bits; | s->misc_bits+= bits - s->last_bits; | ||||
| s->last_bits=bits; | s->last_bits=bits; | ||||
| /* motion vectors: 16x16 mode */ | |||||
| h263_pred_motion(s, 0, &pred_x, &pred_y); | |||||
| h263_encode_motion(s, motion_x - pred_x); | |||||
| h263_encode_motion(s, motion_y - pred_y); | |||||
| }else{ | |||||
| cbpc = (cbp & 3)+16; | |||||
| put_bits(&s->pb, | |||||
| inter_MCBPC_bits[cbpc], | |||||
| inter_MCBPC_code[cbpc]); | |||||
| cbpy = cbp >> 2; | |||||
| cbpy ^= 0xf; | |||||
| put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]); | |||||
| switch(mb_type) | |||||
| { | |||||
| case 0: /* direct */ | |||||
| h263_encode_motion(s, motion_x, 1); | |||||
| h263_encode_motion(s, motion_y, 1); | |||||
| break; | |||||
| case 1: /* bidir */ | |||||
| h263_encode_motion(s, s->mv[0][0][0] - s->last_mv[0][0][0], s->f_code); | |||||
| h263_encode_motion(s, s->mv[0][0][1] - s->last_mv[0][0][1], s->f_code); | |||||
| h263_encode_motion(s, s->mv[1][0][0] - s->last_mv[1][0][0], s->b_code); | |||||
| h263_encode_motion(s, s->mv[1][0][1] - s->last_mv[1][0][1], s->b_code); | |||||
| s->last_mv[0][0][0]= s->mv[0][0][0]; | |||||
| s->last_mv[0][0][1]= s->mv[0][0][1]; | |||||
| s->last_mv[1][0][0]= s->mv[1][0][0]; | |||||
| s->last_mv[1][0][1]= s->mv[1][0][1]; | |||||
| break; | |||||
| case 2: /* backward */ | |||||
| h263_encode_motion(s, motion_x - s->last_mv[1][0][0], s->b_code); | |||||
| h263_encode_motion(s, motion_y - s->last_mv[1][0][1], s->b_code); | |||||
| s->last_mv[1][0][0]= motion_x; | |||||
| s->last_mv[1][0][1]= motion_y; | |||||
| break; | |||||
| case 3: /* forward */ | |||||
| h263_encode_motion(s, motion_x - s->last_mv[0][0][0], s->f_code); | |||||
| h263_encode_motion(s, motion_y - s->last_mv[0][0][1], s->f_code); | |||||
| s->last_mv[0][0][0]= motion_x; | |||||
| s->last_mv[0][0][1]= motion_y; | |||||
| break; | |||||
| default: | |||||
| return; | |||||
| } | |||||
| bits= get_bit_count(&s->pb); | bits= get_bit_count(&s->pb); | ||||
| s->misc_bits+= bits - s->last_bits; | |||||
| s->mv_bits+= bits - s->last_bits; | |||||
| s->last_bits=bits; | s->last_bits=bits; | ||||
| for(i=0; i<4; i++){ | |||||
| /* motion vectors: 8x8 mode*/ | |||||
| h263_pred_motion(s, i, &pred_x, &pred_y); | |||||
| /* encode each block */ | |||||
| for (i = 0; i < 6; i++) { | |||||
| mpeg4_encode_block(s, block[i], i, 0, zigzag_direct); | |||||
| } | |||||
| bits= get_bit_count(&s->pb); | |||||
| s->p_tex_bits+= bits - s->last_bits; | |||||
| s->last_bits=bits; | |||||
| }else{ /* s->pict_type==B_TYPE */ | |||||
| if ((cbp | motion_x | motion_y) == 0 && s->mv_type==MV_TYPE_16X16) { | |||||
| /* skip macroblock */ | |||||
| put_bits(&s->pb, 1, 1); | |||||
| s->misc_bits++; | |||||
| s->last_bits++; | |||||
| s->skip_count++; | |||||
| s->mb_skiped=1; // we need that for b-frames | |||||
| return; | |||||
| } | |||||
| put_bits(&s->pb, 1, 0); /* mb coded */ | |||||
| if(s->mv_type==MV_TYPE_16X16){ | |||||
| cbpc = cbp & 3; | |||||
| put_bits(&s->pb, | |||||
| inter_MCBPC_bits[cbpc], | |||||
| inter_MCBPC_code[cbpc]); | |||||
| cbpy = cbp >> 2; | |||||
| cbpy ^= 0xf; | |||||
| put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]); | |||||
| bits= get_bit_count(&s->pb); | |||||
| s->misc_bits+= bits - s->last_bits; | |||||
| s->last_bits=bits; | |||||
| h263_encode_motion(s, s->motion_val[ s->block_index[i] ][0] - pred_x); | |||||
| h263_encode_motion(s, s->motion_val[ s->block_index[i] ][1] - pred_y); | |||||
| /* motion vectors: 16x16 mode */ | |||||
| h263_pred_motion(s, 0, &pred_x, &pred_y); | |||||
| h263_encode_motion(s, motion_x - pred_x, s->f_code); | |||||
| h263_encode_motion(s, motion_y - pred_y, s->f_code); | |||||
| }else{ | |||||
| cbpc = (cbp & 3)+16; | |||||
| put_bits(&s->pb, | |||||
| inter_MCBPC_bits[cbpc], | |||||
| inter_MCBPC_code[cbpc]); | |||||
| cbpy = cbp >> 2; | |||||
| cbpy ^= 0xf; | |||||
| put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]); | |||||
| bits= get_bit_count(&s->pb); | |||||
| s->misc_bits+= bits - s->last_bits; | |||||
| s->last_bits=bits; | |||||
| for(i=0; i<4; i++){ | |||||
| /* motion vectors: 8x8 mode*/ | |||||
| h263_pred_motion(s, i, &pred_x, &pred_y); | |||||
| h263_encode_motion(s, s->motion_val[ s->block_index[i] ][0] - pred_x, s->f_code); | |||||
| h263_encode_motion(s, s->motion_val[ s->block_index[i] ][1] - pred_y, s->f_code); | |||||
| } | |||||
| } | } | ||||
| } | |||||
| bits= get_bit_count(&s->pb); | |||||
| s->mv_bits+= bits - s->last_bits; | |||||
| s->last_bits=bits; | |||||
| bits= get_bit_count(&s->pb); | |||||
| s->mv_bits+= bits - s->last_bits; | |||||
| s->last_bits=bits; | |||||
| /* encode each block */ | |||||
| for (i = 0; i < 6; i++) { | |||||
| mpeg4_encode_block(s, block[i], i, 0, zigzag_direct); | |||||
| /* encode each block */ | |||||
| for (i = 0; i < 6; i++) { | |||||
| mpeg4_encode_block(s, block[i], i, 0, zigzag_direct); | |||||
| } | |||||
| bits= get_bit_count(&s->pb); | |||||
| s->p_tex_bits+= bits - s->last_bits; | |||||
| s->last_bits=bits; | |||||
| s->p_count++; | |||||
| } | } | ||||
| bits= get_bit_count(&s->pb); | |||||
| s->p_tex_bits+= bits - s->last_bits; | |||||
| s->last_bits=bits; | |||||
| s->p_count++; | |||||
| } else { | } else { | ||||
| int cbp; | |||||
| int dc_diff[6]; //dc values with the dc prediction subtracted | int dc_diff[6]; //dc values with the dc prediction subtracted | ||||
| int dir[6]; //prediction direction | int dir[6]; //prediction direction | ||||
| int zigzag_last_index[6]; | int zigzag_last_index[6]; | ||||
| @@ -427,41 +516,41 @@ void h263_encode_mb(MpegEncContext * s, | |||||
| int cbpc, cbpy, i, cbp, pred_x, pred_y; | int cbpc, cbpy, i, cbp, pred_x, pred_y; | ||||
| // printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y); | // printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y); | ||||
| if (!s->mb_intra) { | |||||
| if (!s->mb_intra) { | |||||
| /* compute cbp */ | /* compute cbp */ | ||||
| cbp = 0; | |||||
| for (i = 0; i < 6; i++) { | |||||
| if (s->block_last_index[i] >= 0) | |||||
| cbp |= 1 << (5 - i); | |||||
| } | |||||
| if ((cbp | motion_x | motion_y) == 0) { | |||||
| /* skip macroblock */ | |||||
| put_bits(&s->pb, 1, 1); | |||||
| return; | |||||
| } | |||||
| put_bits(&s->pb, 1, 0); /* mb coded */ | |||||
| cbpc = cbp & 3; | |||||
| put_bits(&s->pb, | |||||
| inter_MCBPC_bits[cbpc], | |||||
| inter_MCBPC_code[cbpc]); | |||||
| cbpy = cbp >> 2; | |||||
| cbpy ^= 0xf; | |||||
| put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]); | |||||
| /* motion vectors: 16x16 mode only now */ | |||||
| h263_pred_motion(s, 0, &pred_x, &pred_y); | |||||
| cbp = 0; | |||||
| for (i = 0; i < 6; i++) { | |||||
| if (s->block_last_index[i] >= 0) | |||||
| cbp |= 1 << (5 - i); | |||||
| } | |||||
| if ((cbp | motion_x | motion_y) == 0) { | |||||
| /* skip macroblock */ | |||||
| put_bits(&s->pb, 1, 1); | |||||
| return; | |||||
| } | |||||
| put_bits(&s->pb, 1, 0); /* mb coded */ | |||||
| cbpc = cbp & 3; | |||||
| put_bits(&s->pb, | |||||
| inter_MCBPC_bits[cbpc], | |||||
| inter_MCBPC_code[cbpc]); | |||||
| cbpy = cbp >> 2; | |||||
| cbpy ^= 0xf; | |||||
| put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]); | |||||
| /* motion vectors: 16x16 mode only now */ | |||||
| h263_pred_motion(s, 0, &pred_x, &pred_y); | |||||
| if (!s->umvplus) { | |||||
| h263_encode_motion(s, motion_x - pred_x); | |||||
| h263_encode_motion(s, motion_y - pred_y); | |||||
| } | |||||
| else { | |||||
| h263p_encode_umotion(s, motion_x - pred_x); | |||||
| h263p_encode_umotion(s, motion_y - pred_y); | |||||
| if (((motion_x - pred_x) == 1) && ((motion_y - pred_y) == 1)) | |||||
| if (!s->umvplus) { | |||||
| h263_encode_motion(s, motion_x - pred_x, s->f_code); | |||||
| h263_encode_motion(s, motion_y - pred_y, s->f_code); | |||||
| } | |||||
| else { | |||||
| h263p_encode_umotion(s, motion_x - pred_x); | |||||
| h263p_encode_umotion(s, motion_y - pred_y); | |||||
| if (((motion_x - pred_x) == 1) && ((motion_y - pred_y) == 1)) | |||||
| /* To prevent Start Code emulation */ | /* To prevent Start Code emulation */ | ||||
| put_bits(&s->pb,1,1); | |||||
| } | |||||
| put_bits(&s->pb,1,1); | |||||
| } | |||||
| } else { | } else { | ||||
| /* compute cbp */ | /* compute cbp */ | ||||
| cbp = 0; | cbp = 0; | ||||
| @@ -603,7 +692,7 @@ INT16 *h263_pred_motion(MpegEncContext * s, int block, | |||||
| return mot_val; | return mot_val; | ||||
| } | } | ||||
| static void h263_encode_motion(MpegEncContext * s, int val) | |||||
| static void h263_encode_motion(MpegEncContext * s, int val, int f_code) | |||||
| { | { | ||||
| int range, l, m, bit_size, sign, code, bits; | int range, l, m, bit_size, sign, code, bits; | ||||
| @@ -612,7 +701,7 @@ static void h263_encode_motion(MpegEncContext * s, int val) | |||||
| code = 0; | code = 0; | ||||
| put_bits(&s->pb, mvtab[code][1], mvtab[code][0]); | put_bits(&s->pb, mvtab[code][1], mvtab[code][0]); | ||||
| } else { | } else { | ||||
| bit_size = s->f_code - 1; | |||||
| bit_size = f_code - 1; | |||||
| range = 1 << bit_size; | range = 1 << bit_size; | ||||
| /* modulo encoding */ | /* modulo encoding */ | ||||
| l = range * 32; | l = range * 32; | ||||
| @@ -893,7 +982,11 @@ static void mpeg4_encode_vol_header(MpegEncContext * s) | |||||
| put_bits(&s->pb, 1, 0); /* vol control parameters= no */ | put_bits(&s->pb, 1, 0); /* vol control parameters= no */ | ||||
| put_bits(&s->pb, 2, RECT_SHAPE); /* vol shape= rectangle */ | put_bits(&s->pb, 2, RECT_SHAPE); /* vol shape= rectangle */ | ||||
| put_bits(&s->pb, 1, 1); /* marker bit */ | put_bits(&s->pb, 1, 1); /* marker bit */ | ||||
| put_bits(&s->pb, 16, s->time_increment_resolution=30000); | |||||
| s->time_increment_resolution= s->frame_rate/ff_gcd(s->frame_rate, FRAME_RATE_BASE); | |||||
| if(s->time_increment_resolution>=256*256) s->time_increment_resolution= 256*128; | |||||
| put_bits(&s->pb, 16, s->time_increment_resolution); | |||||
| s->time_increment_bits = av_log2(s->time_increment_resolution - 1) + 1; | s->time_increment_bits = av_log2(s->time_increment_resolution - 1) + 1; | ||||
| if (s->time_increment_bits < 1) | if (s->time_increment_bits < 1) | ||||
| s->time_increment_bits = 1; | s->time_increment_bits = 1; | ||||
| @@ -936,18 +1029,38 @@ static void mpeg4_encode_vol_header(MpegEncContext * s) | |||||
| /* write mpeg4 VOP header */ | /* write mpeg4 VOP header */ | ||||
| void mpeg4_encode_picture_header(MpegEncContext * s, int picture_number) | void mpeg4_encode_picture_header(MpegEncContext * s, int picture_number) | ||||
| { | { | ||||
| int time_incr; | |||||
| int time_div, time_mod; | |||||
| if(s->pict_type==I_TYPE) mpeg4_encode_vol_header(s); | if(s->pict_type==I_TYPE) mpeg4_encode_vol_header(s); | ||||
| s->time= s->picture_number*(int64_t)FRAME_RATE_BASE*s->time_increment_resolution/s->frame_rate; | |||||
| time_div= s->time/s->time_increment_resolution; | |||||
| time_mod= s->time%s->time_increment_resolution; | |||||
| //printf("num:%d rate:%d base:%d\n", s->picture_number, s->frame_rate, FRAME_RATE_BASE); | |||||
| if(get_bit_count(&s->pb)!=0) mpeg4_stuffing(&s->pb); | if(get_bit_count(&s->pb)!=0) mpeg4_stuffing(&s->pb); | ||||
| put_bits(&s->pb, 16, 0); /* vop header */ | put_bits(&s->pb, 16, 0); /* vop header */ | ||||
| put_bits(&s->pb, 16, 0x1B6); /* vop header */ | put_bits(&s->pb, 16, 0x1B6); /* vop header */ | ||||
| put_bits(&s->pb, 2, s->pict_type - 1); /* pict type: I = 0 , P = 1 */ | put_bits(&s->pb, 2, s->pict_type - 1); /* pict type: I = 0 , P = 1 */ | ||||
| /* XXX: time base + 1 not always correct */ | |||||
| put_bits(&s->pb, 1, 1); | |||||
| if(s->pict_type==B_TYPE){ | |||||
| s->bp_time= s->last_non_b_time - s->time; | |||||
| }else{ | |||||
| s->last_time_base= s->time_base; | |||||
| s->time_base= time_div; | |||||
| s->pp_time= s->time - s->last_non_b_time; | |||||
| s->last_non_b_time= s->time; | |||||
| } | |||||
| time_incr= time_div - s->last_time_base; | |||||
| while(time_incr--) | |||||
| put_bits(&s->pb, 1, 1); | |||||
| put_bits(&s->pb, 1, 0); | put_bits(&s->pb, 1, 0); | ||||
| put_bits(&s->pb, 1, 1); /* marker */ | put_bits(&s->pb, 1, 1); /* marker */ | ||||
| put_bits(&s->pb, s->time_increment_bits, 1); /* XXX: correct time increment */ | |||||
| put_bits(&s->pb, s->time_increment_bits, time_mod); /* time increment */ | |||||
| put_bits(&s->pb, 1, 1); /* marker */ | put_bits(&s->pb, 1, 1); /* marker */ | ||||
| put_bits(&s->pb, 1, 1); /* vop coded */ | put_bits(&s->pb, 1, 1); /* vop coded */ | ||||
| if ( s->pict_type == P_TYPE | if ( s->pict_type == P_TYPE | ||||
| @@ -1361,6 +1474,7 @@ static int mpeg4_resync(MpegEncContext *s) | |||||
| int mb_num_bits= av_log2(s->mb_num - 1) + 1; | int mb_num_bits= av_log2(s->mb_num - 1) + 1; | ||||
| int header_extension=0, mb_num; | int header_extension=0, mb_num; | ||||
| int c_wrap, c_xy, l_wrap, l_xy; | int c_wrap, c_xy, l_wrap, l_xy; | ||||
| int time_increment; | |||||
| //printf("resync at %d %d\n", s->mb_x, s->mb_y); | //printf("resync at %d %d\n", s->mb_x, s->mb_y); | ||||
| //printf("%X\n", show_bits(&s->gb, 24)); | //printf("%X\n", show_bits(&s->gb, 24)); | ||||
| @@ -1415,14 +1529,16 @@ static int mpeg4_resync(MpegEncContext *s) | |||||
| time_incr++; | time_incr++; | ||||
| check_marker(&s->gb, "before time_increment in video packed header"); | check_marker(&s->gb, "before time_increment in video packed header"); | ||||
| s->time_increment= get_bits(&s->gb, s->time_increment_bits); | |||||
| time_increment= get_bits(&s->gb, s->time_increment_bits); | |||||
| if(s->pict_type!=B_TYPE){ | if(s->pict_type!=B_TYPE){ | ||||
| s->last_time_base= s->time_base; | |||||
| s->time_base+= time_incr; | s->time_base+= time_incr; | ||||
| s->last_non_b_time[1]= s->last_non_b_time[0]; | |||||
| s->last_non_b_time[0]= s->time_base*s->time_increment_resolution + s->time_increment; | |||||
| s->time= s->time_base*s->time_increment_resolution + time_increment; | |||||
| s->pp_time= s->time - s->last_non_b_time; | |||||
| s->last_non_b_time= s->time; | |||||
| }else{ | }else{ | ||||
| s->time= (s->last_non_b_time[1]/s->time_increment_resolution + time_incr)*s->time_increment_resolution; | |||||
| s->time+= s->time_increment; | |||||
| s->time= (s->last_time_base + time_incr)*s->time_increment_resolution + time_increment; | |||||
| s->bp_time= s->last_non_b_time - s->time; | |||||
| } | } | ||||
| check_marker(&s->gb, "before vop_coding_type in video packed header"); | check_marker(&s->gb, "before vop_coding_type in video packed header"); | ||||
| @@ -1642,8 +1758,8 @@ int h263_decode_mb(MpegEncContext *s, | |||||
| int modb1; // first bit of modb | int modb1; // first bit of modb | ||||
| int modb2; // second bit of modb | int modb2; // second bit of modb | ||||
| int mb_type; | int mb_type; | ||||
| int time_pp; | |||||
| int time_pb; | |||||
| uint16_t time_pp; | |||||
| uint16_t time_pb; | |||||
| int xy; | int xy; | ||||
| s->mb_intra = 0; //B-frames never contain intra blocks | s->mb_intra = 0; //B-frames never contain intra blocks | ||||
| @@ -1673,7 +1789,6 @@ int h263_decode_mb(MpegEncContext *s, | |||||
| //FIXME is this correct? | //FIXME is this correct? | ||||
| /* s->last_mv[0][0][0]= | /* s->last_mv[0][0][0]= | ||||
| s->last_mv[0][0][1]=0;*/ | s->last_mv[0][0][1]=0;*/ | ||||
| s->mb_skiped = 1; | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -1701,14 +1816,14 @@ int h263_decode_mb(MpegEncContext *s, | |||||
| mx=my=0; //for case 4, we could put this to the mb_type=4 but than gcc compains about uninitalized mx/my | mx=my=0; //for case 4, we could put this to the mb_type=4 but than gcc compains about uninitalized mx/my | ||||
| switch(mb_type) | switch(mb_type) | ||||
| { | { | ||||
| case 0: | |||||
| case 0: /* direct */ | |||||
| mx = h263_decode_motion(s, 0, 1); | mx = h263_decode_motion(s, 0, 1); | ||||
| my = h263_decode_motion(s, 0, 1); | my = h263_decode_motion(s, 0, 1); | ||||
| case 4: | |||||
| case 4: /* direct with mx=my=0 */ | |||||
| s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT; | s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT; | ||||
| xy= s->block_index[0]; | xy= s->block_index[0]; | ||||
| time_pp= s->last_non_b_time[0] - s->last_non_b_time[1]; | |||||
| time_pb= s->time - s->last_non_b_time[1]; | |||||
| time_pp= s->pp_time; | |||||
| time_pb= time_pp - s->bp_time; | |||||
| //if(time_pp>3000 )printf("%d %d ", time_pp, time_pb); | //if(time_pp>3000 )printf("%d %d ", time_pp, time_pb); | ||||
| //FIXME 4MV | //FIXME 4MV | ||||
| //FIXME avoid divides | //FIXME avoid divides | ||||
| @@ -2397,6 +2512,7 @@ printf("%d %d\n", s->sprite_delta[1][1][1], a<<s->sprite_shift[1][1]);*/ | |||||
| int mpeg4_decode_picture_header(MpegEncContext * s) | int mpeg4_decode_picture_header(MpegEncContext * s) | ||||
| { | { | ||||
| int time_incr, startcode, state, v; | int time_incr, startcode, state, v; | ||||
| int time_increment; | |||||
| redo: | redo: | ||||
| /* search next start code */ | /* search next start code */ | ||||
| @@ -2630,20 +2746,23 @@ int mpeg4_decode_picture_header(MpegEncContext * s) | |||||
| } | } | ||||
| s->pict_type = get_bits(&s->gb, 2) + 1; /* pict type: I = 0 , P = 1 */ | s->pict_type = get_bits(&s->gb, 2) + 1; /* pict type: I = 0 , P = 1 */ | ||||
| //printf("pic: %d, qpel:%d\n", s->pict_type, s->quarter_sample); | |||||
| // printf("pic: %d, qpel:%d\n", s->pict_type, s->quarter_sample); | |||||
| time_incr=0; | time_incr=0; | ||||
| while (get_bits1(&s->gb) != 0) | while (get_bits1(&s->gb) != 0) | ||||
| time_incr++; | time_incr++; | ||||
| check_marker(&s->gb, "before time_increment"); | check_marker(&s->gb, "before time_increment"); | ||||
| s->time_increment= get_bits(&s->gb, s->time_increment_bits); | |||||
| time_increment= get_bits(&s->gb, s->time_increment_bits); | |||||
| //printf(" type:%d incr:%d increment:%d\n", s->pict_type, time_incr, time_increment); | |||||
| if(s->pict_type!=B_TYPE){ | if(s->pict_type!=B_TYPE){ | ||||
| s->last_time_base= s->time_base; | |||||
| s->time_base+= time_incr; | s->time_base+= time_incr; | ||||
| s->last_non_b_time[1]= s->last_non_b_time[0]; | |||||
| s->last_non_b_time[0]= s->time_base*s->time_increment_resolution + s->time_increment; | |||||
| s->time= s->time_base*s->time_increment_resolution + time_increment; | |||||
| s->pp_time= s->time - s->last_non_b_time; | |||||
| s->last_non_b_time= s->time; | |||||
| }else{ | }else{ | ||||
| s->time= (s->last_non_b_time[1]/s->time_increment_resolution + time_incr)*s->time_increment_resolution; | |||||
| s->time+= s->time_increment; | |||||
| s->time= (s->last_time_base + time_incr)*s->time_increment_resolution + time_increment; | |||||
| s->bp_time= s->last_non_b_time - s->time; | |||||
| } | } | ||||
| if(check_marker(&s->gb, "before vop_coded")==0 && s->picture_number==0){ | if(check_marker(&s->gb, "before vop_coded")==0 && s->picture_number==0){ | ||||
| @@ -44,7 +44,6 @@ int pix_abs8x8_x2_mmx2(UINT8 *blk1, UINT8 *blk2, int lx); | |||||
| int pix_abs8x8_y2_mmx2(UINT8 *blk1, UINT8 *blk2, int lx); | int pix_abs8x8_y2_mmx2(UINT8 *blk1, UINT8 *blk2, int lx); | ||||
| int pix_abs8x8_xy2_mmx2(UINT8 *blk1, UINT8 *blk2, int lx); | int pix_abs8x8_xy2_mmx2(UINT8 *blk1, UINT8 *blk2, int lx); | ||||
| /* external functions, from idct_mmx.c */ | /* external functions, from idct_mmx.c */ | ||||
| void ff_mmx_idct(DCTELEM *block); | void ff_mmx_idct(DCTELEM *block); | ||||
| void ff_mmxext_idct(DCTELEM *block); | void ff_mmxext_idct(DCTELEM *block); | ||||
| @@ -136,6 +135,34 @@ static void get_pixels_mmx(DCTELEM *block, const UINT8 *pixels, int line_size) | |||||
| } | } | ||||
| } | } | ||||
| static void diff_pixels_mmx(DCTELEM *block, const UINT8 *s1, const UINT8 *s2, int stride) | |||||
| { | |||||
| asm volatile( | |||||
| ".balign 16 \n\t" | |||||
| "movl $-128, %%eax \n\t" | |||||
| "1: \n\t" | |||||
| "movq (%0), %%mm0 \n\t" | |||||
| "movq (%1), %%mm2 \n\t" | |||||
| "movq %%mm0, %%mm1 \n\t" | |||||
| "movq %%mm2, %%mm3 \n\t" | |||||
| "punpcklbw %%mm7, %%mm0 \n\t" | |||||
| "punpckhbw %%mm7, %%mm1 \n\t" | |||||
| "punpcklbw %%mm7, %%mm2 \n\t" | |||||
| "punpckhbw %%mm7, %%mm3 \n\t" | |||||
| "psubw %%mm2, %%mm0 \n\t" | |||||
| "psubw %%mm3, %%mm1 \n\t" | |||||
| "movq %%mm0, (%2, %%eax)\n\t" | |||||
| "movq %%mm1, 8(%2, %%eax)\n\t" | |||||
| "addl %3, %0 \n\t" | |||||
| "addl %3, %1 \n\t" | |||||
| "addl $16, %%eax \n\t" | |||||
| "jnz 1b \n\t" | |||||
| : "+r" (s1), "+r" (s2) | |||||
| : "r" (block+64), "r" (stride) | |||||
| : "%eax" | |||||
| ); | |||||
| } | |||||
| static void put_pixels_clamped_mmx(const DCTELEM *block, UINT8 *pixels, int line_size) | static void put_pixels_clamped_mmx(const DCTELEM *block, UINT8 *pixels, int line_size) | ||||
| { | { | ||||
| const DCTELEM *p; | const DCTELEM *p; | ||||
| @@ -1064,6 +1091,7 @@ void dsputil_init_mmx(void) | |||||
| if (mm_flags & MM_MMX) { | if (mm_flags & MM_MMX) { | ||||
| get_pixels = get_pixels_mmx; | get_pixels = get_pixels_mmx; | ||||
| diff_pixels = diff_pixels_mmx; | |||||
| put_pixels_clamped = put_pixels_clamped_mmx; | put_pixels_clamped = put_pixels_clamped_mmx; | ||||
| add_pixels_clamped = add_pixels_clamped_mmx; | add_pixels_clamped = add_pixels_clamped_mmx; | ||||
| clear_blocks= clear_blocks_mmx; | clear_blocks= clear_blocks_mmx; | ||||
| @@ -32,10 +32,7 @@ | |||||
| static void halfpel_motion_search(MpegEncContext * s, | static void halfpel_motion_search(MpegEncContext * s, | ||||
| int *mx_ptr, int *my_ptr, int dmin, | int *mx_ptr, int *my_ptr, int dmin, | ||||
| int xmin, int ymin, int xmax, int ymax, | int xmin, int ymin, int xmax, int ymax, | ||||
| int pred_x, int pred_y); | |||||
| /* config it to test motion vector encoding (send random vectors) */ | |||||
| //#define CONFIG_TEST_MV_ENCODE | |||||
| int pred_x, int pred_y, uint8_t *ref_picture); | |||||
| static int pix_sum(UINT8 * pix, int line_size) | static int pix_sum(UINT8 * pix, int line_size) | ||||
| { | { | ||||
| @@ -138,7 +135,7 @@ static void no_motion_search(MpegEncContext * s, | |||||
| static int full_motion_search(MpegEncContext * s, | static int full_motion_search(MpegEncContext * s, | ||||
| int *mx_ptr, int *my_ptr, int range, | int *mx_ptr, int *my_ptr, int range, | ||||
| int xmin, int ymin, int xmax, int ymax) | |||||
| int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture) | |||||
| { | { | ||||
| int x1, y1, x2, y2, xx, yy, x, y; | int x1, y1, x2, y2, xx, yy, x, y; | ||||
| int mx, my, dmin, d; | int mx, my, dmin, d; | ||||
| @@ -164,7 +161,7 @@ static int full_motion_search(MpegEncContext * s, | |||||
| my = 0; | my = 0; | ||||
| for (y = y1; y <= y2; y++) { | for (y = y1; y <= y2; y++) { | ||||
| for (x = x1; x <= x2; x++) { | for (x = x1; x <= x2; x++) { | ||||
| d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, | |||||
| d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x, | |||||
| s->linesize); | s->linesize); | ||||
| if (d < dmin || | if (d < dmin || | ||||
| (d == dmin && | (d == dmin && | ||||
| @@ -192,7 +189,7 @@ static int full_motion_search(MpegEncContext * s, | |||||
| static int log_motion_search(MpegEncContext * s, | static int log_motion_search(MpegEncContext * s, | ||||
| int *mx_ptr, int *my_ptr, int range, | int *mx_ptr, int *my_ptr, int range, | ||||
| int xmin, int ymin, int xmax, int ymax) | |||||
| int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture) | |||||
| { | { | ||||
| int x1, y1, x2, y2, xx, yy, x, y; | int x1, y1, x2, y2, xx, yy, x, y; | ||||
| int mx, my, dmin, d; | int mx, my, dmin, d; | ||||
| @@ -229,7 +226,7 @@ static int log_motion_search(MpegEncContext * s, | |||||
| do { | do { | ||||
| for (y = y1; y <= y2; y += range) { | for (y = y1; y <= y2; y += range) { | ||||
| for (x = x1; x <= x2; x += range) { | for (x = x1; x <= x2; x += range) { | ||||
| d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize); | |||||
| d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x, s->linesize); | |||||
| if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) { | if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) { | ||||
| dmin = d; | dmin = d; | ||||
| mx = x; | mx = x; | ||||
| @@ -268,7 +265,7 @@ static int log_motion_search(MpegEncContext * s, | |||||
| static int phods_motion_search(MpegEncContext * s, | static int phods_motion_search(MpegEncContext * s, | ||||
| int *mx_ptr, int *my_ptr, int range, | int *mx_ptr, int *my_ptr, int range, | ||||
| int xmin, int ymin, int xmax, int ymax) | |||||
| int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture) | |||||
| { | { | ||||
| int x1, y1, x2, y2, xx, yy, x, y, lastx, d; | int x1, y1, x2, y2, xx, yy, x, y, lastx, d; | ||||
| int mx, my, dminx, dminy; | int mx, my, dminx, dminy; | ||||
| @@ -309,7 +306,7 @@ static int phods_motion_search(MpegEncContext * s, | |||||
| lastx = x; | lastx = x; | ||||
| for (x = x1; x <= x2; x += range) { | for (x = x1; x <= x2; x += range) { | ||||
| d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize); | |||||
| d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x, s->linesize); | |||||
| if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) { | if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) { | ||||
| dminx = d; | dminx = d; | ||||
| mx = x; | mx = x; | ||||
| @@ -318,7 +315,7 @@ static int phods_motion_search(MpegEncContext * s, | |||||
| x = lastx; | x = lastx; | ||||
| for (y = y1; y <= y2; y += range) { | for (y = y1; y <= y2; y += range) { | ||||
| d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize); | |||||
| d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x, s->linesize); | |||||
| if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) { | if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) { | ||||
| dminy = d; | dminy = d; | ||||
| my = y; | my = y; | ||||
| @@ -554,7 +551,7 @@ if(256*256*256*64%point==0) | |||||
| static int epzs_motion_search(MpegEncContext * s, | static int epzs_motion_search(MpegEncContext * s, | ||||
| int *mx_ptr, int *my_ptr, | int *mx_ptr, int *my_ptr, | ||||
| int P[5][2], int pred_x, int pred_y, | int P[5][2], int pred_x, int pred_y, | ||||
| int xmin, int ymin, int xmax, int ymax) | |||||
| int xmin, int ymin, int xmax, int ymax, uint8_t * ref_picture) | |||||
| { | { | ||||
| int best[2]={0, 0}; | int best[2]={0, 0}; | ||||
| int d, dmin; | int d, dmin; | ||||
| @@ -566,7 +563,7 @@ static int epzs_motion_search(MpegEncContext * s, | |||||
| const int shift= 1+s->quarter_sample; | const int shift= 1+s->quarter_sample; | ||||
| new_pic = s->new_picture[0] + pic_xy; | new_pic = s->new_picture[0] + pic_xy; | ||||
| old_pic = s->last_picture[0] + pic_xy; | |||||
| old_pic = ref_picture + pic_xy; | |||||
| dmin = pix_abs16x16(new_pic, old_pic, pic_stride); | dmin = pix_abs16x16(new_pic, old_pic, pic_stride); | ||||
| if(dmin<Z_THRESHOLD){ | if(dmin<Z_THRESHOLD){ | ||||
| @@ -611,7 +608,7 @@ static int epzs_motion_search(MpegEncContext * s, | |||||
| static int epzs_motion_search4(MpegEncContext * s, int block, | static int epzs_motion_search4(MpegEncContext * s, int block, | ||||
| int *mx_ptr, int *my_ptr, | int *mx_ptr, int *my_ptr, | ||||
| int P[6][2], int pred_x, int pred_y, | int P[6][2], int pred_x, int pred_y, | ||||
| int xmin, int ymin, int xmax, int ymax) | |||||
| int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture) | |||||
| { | { | ||||
| int best[2]={0, 0}; | int best[2]={0, 0}; | ||||
| int d, dmin; | int d, dmin; | ||||
| @@ -623,7 +620,7 @@ static int epzs_motion_search4(MpegEncContext * s, int block, | |||||
| const int shift= 1+s->quarter_sample; | const int shift= 1+s->quarter_sample; | ||||
| new_pic = s->new_picture[0] + pic_xy; | new_pic = s->new_picture[0] + pic_xy; | ||||
| old_pic = s->last_picture[0] + pic_xy; | |||||
| old_pic = ref_picture + pic_xy; | |||||
| dmin = pix_abs8x8(new_pic, old_pic, pic_stride); | dmin = pix_abs8x8(new_pic, old_pic, pic_stride); | ||||
| @@ -679,7 +676,7 @@ static int epzs_motion_search4(MpegEncContext * s, int block, | |||||
| static inline void halfpel_motion_search(MpegEncContext * s, | static inline void halfpel_motion_search(MpegEncContext * s, | ||||
| int *mx_ptr, int *my_ptr, int dmin, | int *mx_ptr, int *my_ptr, int dmin, | ||||
| int xmin, int ymin, int xmax, int ymax, | int xmin, int ymin, int xmax, int ymax, | ||||
| int pred_x, int pred_y) | |||||
| int pred_x, int pred_y, uint8_t *ref_picture) | |||||
| { | { | ||||
| UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame | UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame | ||||
| const int quant= s->qscale; | const int quant= s->qscale; | ||||
| @@ -689,7 +686,7 @@ static inline void halfpel_motion_search(MpegEncContext * s, | |||||
| mx = *mx_ptr; | mx = *mx_ptr; | ||||
| my = *my_ptr; | my = *my_ptr; | ||||
| ptr = s->last_picture[0] + (my * s->linesize) + mx; | |||||
| ptr = ref_picture + (my * s->linesize) + mx; | |||||
| xx = 16 * s->mb_x; | xx = 16 * s->mb_x; | ||||
| yy = 16 * s->mb_y; | yy = 16 * s->mb_y; | ||||
| @@ -735,7 +732,8 @@ static inline void halfpel_motion_search(MpegEncContext * s, | |||||
| static inline void halfpel_motion_search4(MpegEncContext * s, | static inline void halfpel_motion_search4(MpegEncContext * s, | ||||
| int *mx_ptr, int *my_ptr, int dmin, | int *mx_ptr, int *my_ptr, int dmin, | ||||
| int xmin, int ymin, int xmax, int ymax, | int xmin, int ymin, int xmax, int ymax, | ||||
| int pred_x, int pred_y, int block_x, int block_y) | |||||
| int pred_x, int pred_y, int block_x, int block_y, | |||||
| uint8_t *ref_picture) | |||||
| { | { | ||||
| UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame | UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame | ||||
| const int quant= s->qscale; | const int quant= s->qscale; | ||||
| @@ -749,7 +747,7 @@ static inline void halfpel_motion_search4(MpegEncContext * s, | |||||
| mx = *mx_ptr; | mx = *mx_ptr; | ||||
| my = *my_ptr; | my = *my_ptr; | ||||
| ptr = s->last_picture[0] + ((yy+my) * s->linesize) + xx + mx; | |||||
| ptr = ref_picture + ((yy+my) * s->linesize) + xx + mx; | |||||
| dminh = dmin; | dminh = dmin; | ||||
| @@ -788,12 +786,12 @@ static inline void halfpel_motion_search4(MpegEncContext * s, | |||||
| *my_ptr = my; | *my_ptr = my; | ||||
| } | } | ||||
| static inline void set_mv_tables(MpegEncContext * s, int mx, int my) | |||||
| static inline void set_p_mv_tables(MpegEncContext * s, int mx, int my) | |||||
| { | { | ||||
| const int xy= s->mb_x + s->mb_y*s->mb_width; | |||||
| const int xy= s->mb_x + 1 + (s->mb_y + 1)*(s->mb_width + 2); | |||||
| s->mv_table[0][xy] = mx; | |||||
| s->mv_table[1][xy] = my; | |||||
| s->p_mv_table[xy][0] = mx; | |||||
| s->p_mv_table[xy][1] = my; | |||||
| /* has allready been set to the 4 MV if 4MV is done */ | /* has allready been set to the 4 MV if 4MV is done */ | ||||
| if(!(s->flags&CODEC_FLAG_4MV)){ | if(!(s->flags&CODEC_FLAG_4MV)){ | ||||
| @@ -812,45 +810,50 @@ static inline void set_mv_tables(MpegEncContext * s, int mx, int my) | |||||
| } | } | ||||
| } | } | ||||
| #ifndef CONFIG_TEST_MV_ENCODE | |||||
| void estimate_motion(MpegEncContext * s, | |||||
| int mb_x, int mb_y) | |||||
| static inline void get_limits(MpegEncContext *s, int *range, int *xmin, int *ymin, int *xmax, int *ymax, int f_code) | |||||
| { | { | ||||
| UINT8 *pix, *ppix; | |||||
| int sum, varc, vard, mx, my, range, dmin, xx, yy; | |||||
| int xmin, ymin, xmax, ymax; | |||||
| int rel_xmin, rel_ymin, rel_xmax, rel_ymax; | |||||
| int pred_x=0, pred_y=0; | |||||
| int P[6][2]; | |||||
| const int shift= 1+s->quarter_sample; | |||||
| int mb_type=0; | |||||
| //static int skip=0; | |||||
| range = 8 * (1 << (s->f_code - 1)); | |||||
| *range = 8 * (1 << (f_code - 1)); | |||||
| /* XXX: temporary kludge to avoid overflow for msmpeg4 */ | /* XXX: temporary kludge to avoid overflow for msmpeg4 */ | ||||
| if (s->out_format == FMT_H263 && !s->h263_msmpeg4) | if (s->out_format == FMT_H263 && !s->h263_msmpeg4) | ||||
| range = range * 2; | |||||
| *range *= 2; | |||||
| if (s->unrestricted_mv) { | if (s->unrestricted_mv) { | ||||
| xmin = -16; | |||||
| ymin = -16; | |||||
| *xmin = -16; | |||||
| *ymin = -16; | |||||
| if (s->h263_plus) | if (s->h263_plus) | ||||
| range *= 2; | |||||
| *range *= 2; | |||||
| if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){ | if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){ | ||||
| xmax = s->mb_width*16; | |||||
| ymax = s->mb_height*16; | |||||
| *xmax = s->mb_width*16; | |||||
| *ymax = s->mb_height*16; | |||||
| }else { | }else { | ||||
| /* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise | /* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise | ||||
| (cuz the drawn edge isnt large enough))*/ | (cuz the drawn edge isnt large enough))*/ | ||||
| xmax = s->width; | |||||
| ymax = s->height; | |||||
| *xmax = s->width; | |||||
| *ymax = s->height; | |||||
| } | } | ||||
| } else { | } else { | ||||
| xmin = 0; | |||||
| ymin = 0; | |||||
| xmax = s->mb_width*16 - 16; | |||||
| ymax = s->mb_height*16 - 16; | |||||
| *xmin = 0; | |||||
| *ymin = 0; | |||||
| *xmax = s->mb_width*16 - 16; | |||||
| *ymax = s->mb_height*16 - 16; | |||||
| } | } | ||||
| } | |||||
| void ff_estimate_p_frame_motion(MpegEncContext * s, | |||||
| int mb_x, int mb_y) | |||||
| { | |||||
| UINT8 *pix, *ppix; | |||||
| int sum, varc, vard, mx, my, range, dmin, xx, yy; | |||||
| int xmin, ymin, xmax, ymax; | |||||
| int rel_xmin, rel_ymin, rel_xmax, rel_ymax; | |||||
| int pred_x=0, pred_y=0; | |||||
| int P[6][2]; | |||||
| const int shift= 1+s->quarter_sample; | |||||
| int mb_type=0; | |||||
| uint8_t *ref_picture= s->last_picture[0]; | |||||
| get_limits(s, &range, &xmin, &ymin, &xmax, &ymax, s->f_code); | |||||
| switch(s->me_method) { | switch(s->me_method) { | ||||
| case ME_ZERO: | case ME_ZERO: | ||||
| default: | default: | ||||
| @@ -858,13 +861,13 @@ void estimate_motion(MpegEncContext * s, | |||||
| dmin = 0; | dmin = 0; | ||||
| break; | break; | ||||
| case ME_FULL: | case ME_FULL: | ||||
| dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax); | |||||
| dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax, ref_picture); | |||||
| break; | break; | ||||
| case ME_LOG: | case ME_LOG: | ||||
| dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax); | |||||
| dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture); | |||||
| break; | break; | ||||
| case ME_PHODS: | case ME_PHODS: | ||||
| dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax); | |||||
| dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture); | |||||
| break; | break; | ||||
| case ME_X1: | case ME_X1: | ||||
| case ME_EPZS: | case ME_EPZS: | ||||
| @@ -907,7 +910,7 @@ void estimate_motion(MpegEncContext * s, | |||||
| pred_y= P[1][1]; | pred_y= P[1][1]; | ||||
| } | } | ||||
| } | } | ||||
| dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax); | |||||
| dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax, ref_picture); | |||||
| mx+= mb_x*16; | mx+= mb_x*16; | ||||
| my+= mb_y*16; | my+= mb_y*16; | ||||
| @@ -967,10 +970,10 @@ void estimate_motion(MpegEncContext * s, | |||||
| P[5][0]= mx - mb_x*16; | P[5][0]= mx - mb_x*16; | ||||
| P[5][1]= my - mb_y*16; | P[5][1]= my - mb_y*16; | ||||
| dmin4 = epzs_motion_search4(s, block, &mx4, &my4, P, pred_x4, pred_y4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4); | |||||
| dmin4 = epzs_motion_search4(s, block, &mx4, &my4, P, pred_x4, pred_y4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4, ref_picture); | |||||
| halfpel_motion_search4(s, &mx4, &my4, dmin4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4, | halfpel_motion_search4(s, &mx4, &my4, dmin4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4, | ||||
| pred_x4, pred_y4, block_x, block_y); | |||||
| pred_x4, pred_y4, block_x, block_y, ref_picture); | |||||
| s->motion_val[ s->block_index[block] ][0]= mx4; | s->motion_val[ s->block_index[block] ][0]= mx4; | ||||
| s->motion_val[ s->block_index[block] ][1]= my4; | s->motion_val[ s->block_index[block] ][1]= my4; | ||||
| @@ -983,7 +986,7 @@ void estimate_motion(MpegEncContext * s, | |||||
| pix = s->new_picture[0] + (yy * s->linesize) + xx; | pix = s->new_picture[0] + (yy * s->linesize) + xx; | ||||
| /* At this point (mx,my) are full-pell and the absolute displacement */ | /* At this point (mx,my) are full-pell and the absolute displacement */ | ||||
| ppix = s->last_picture[0] + (my * s->linesize) + mx; | |||||
| ppix = ref_picture + (my * s->linesize) + mx; | |||||
| sum = pix_sum(pix, s->linesize); | sum = pix_sum(pix, s->linesize); | ||||
| #if 0 | #if 0 | ||||
| @@ -1009,7 +1012,7 @@ void estimate_motion(MpegEncContext * s, | |||||
| mb_type|= MB_TYPE_INTRA; | mb_type|= MB_TYPE_INTRA; | ||||
| if (varc*2 + 200 > vard){ | if (varc*2 + 200 > vard){ | ||||
| mb_type|= MB_TYPE_INTER; | mb_type|= MB_TYPE_INTER; | ||||
| halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y); | |||||
| halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y, ref_picture); | |||||
| }else{ | }else{ | ||||
| mx = mx*2 - mb_x*32; | mx = mx*2 - mb_x*32; | ||||
| my = my*2 - mb_y*32; | my = my*2 - mb_y*32; | ||||
| @@ -1018,7 +1021,7 @@ void estimate_motion(MpegEncContext * s, | |||||
| if (vard <= 64 || vard < varc) { | if (vard <= 64 || vard < varc) { | ||||
| mb_type|= MB_TYPE_INTER; | mb_type|= MB_TYPE_INTER; | ||||
| if (s->me_method != ME_ZERO) { | if (s->me_method != ME_ZERO) { | ||||
| halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y); | |||||
| halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y, ref_picture); | |||||
| } else { | } else { | ||||
| mx -= 16 * mb_x; | mx -= 16 * mb_x; | ||||
| my -= 16 * mb_y; | my -= 16 * mb_y; | ||||
| @@ -1038,46 +1041,249 @@ void estimate_motion(MpegEncContext * s, | |||||
| } | } | ||||
| s->mb_type[mb_y*s->mb_width + mb_x]= mb_type; | s->mb_type[mb_y*s->mb_width + mb_x]= mb_type; | ||||
| set_mv_tables(s, mx, my); | |||||
| set_p_mv_tables(s, mx, my); | |||||
| } | |||||
| void ff_estimate_motion_b(MpegEncContext * s, | |||||
| int mb_x, int mb_y, int16_t (*mv_table)[2], uint8_t *ref_picture, int f_code) | |||||
| { | |||||
| UINT8 *pix, *ppix; | |||||
| int sum, varc, vard, mx, my, range, dmin, xx, yy; | |||||
| int xmin, ymin, xmax, ymax; | |||||
| int rel_xmin, rel_ymin, rel_xmax, rel_ymax; | |||||
| int pred_x=0, pred_y=0; | |||||
| int P[6][2]; | |||||
| const int shift= 1+s->quarter_sample; | |||||
| int mb_type=0; | |||||
| const int mot_stride = s->mb_width + 2; | |||||
| const int mot_xy = (mb_y + 1)*mot_stride + mb_x + 1; | |||||
| get_limits(s, &range, &xmin, &ymin, &xmax, &ymax, f_code); | |||||
| switch(s->me_method) { | |||||
| case ME_ZERO: | |||||
| default: | |||||
| no_motion_search(s, &mx, &my); | |||||
| dmin = 0; | |||||
| break; | |||||
| case ME_FULL: | |||||
| dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax, ref_picture); | |||||
| break; | |||||
| case ME_LOG: | |||||
| dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture); | |||||
| break; | |||||
| case ME_PHODS: | |||||
| dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture); | |||||
| break; | |||||
| case ME_X1: | |||||
| case ME_EPZS: | |||||
| { | |||||
| rel_xmin= xmin - mb_x*16; | |||||
| rel_xmax= xmax - mb_x*16; | |||||
| rel_ymin= ymin - mb_y*16; | |||||
| rel_ymax= ymax - mb_y*16; | |||||
| P[0][0] = mv_table[mot_xy ][0]; | |||||
| P[0][1] = mv_table[mot_xy ][1]; | |||||
| P[1][0] = mv_table[mot_xy - 1][0]; | |||||
| P[1][1] = mv_table[mot_xy - 1][1]; | |||||
| if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift); | |||||
| /* special case for first line */ | |||||
| if ((mb_y == 0 || s->first_slice_line || s->first_gob_line)) { | |||||
| P[4][0] = P[1][0]; | |||||
| P[4][1] = P[1][1]; | |||||
| } else { | |||||
| P[2][0] = mv_table[mot_xy - mot_stride ][0]; | |||||
| P[2][1] = mv_table[mot_xy - mot_stride ][1]; | |||||
| P[3][0] = mv_table[mot_xy - mot_stride + 1 ][0]; | |||||
| P[3][1] = mv_table[mot_xy - mot_stride + 1 ][1]; | |||||
| if(P[2][1] > (rel_ymax<<shift)) P[2][1]= (rel_ymax<<shift); | |||||
| if(P[3][0] < (rel_xmin<<shift)) P[3][0]= (rel_xmin<<shift); | |||||
| if(P[3][1] > (rel_ymax<<shift)) P[3][1]= (rel_ymax<<shift); | |||||
| P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]); | |||||
| P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]); | |||||
| } | |||||
| pred_x= P[1][0]; | |||||
| pred_y= P[1][1]; | |||||
| } | |||||
| dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax, ref_picture); | |||||
| mx+= mb_x*16; | |||||
| my+= mb_y*16; | |||||
| break; | |||||
| } | |||||
| /* intra / predictive decision */ | |||||
| // xx = mb_x * 16; | |||||
| // yy = mb_y * 16; | |||||
| // pix = s->new_picture[0] + (yy * s->linesize) + xx; | |||||
| /* At this point (mx,my) are full-pell and the absolute displacement */ | |||||
| // ppix = ref_picture + (my * s->linesize) + mx; | |||||
| halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y, ref_picture); | |||||
| // s->mb_type[mb_y*s->mb_width + mb_x]= mb_type; | |||||
| mv_table[mot_xy][0]= mx; | |||||
| mv_table[mot_xy][1]= my; | |||||
| } | } | ||||
| #else | |||||
| /* test version which generates valid random vectors */ | |||||
| int estimate_motion(MpegEncContext * s, | |||||
| int mb_x, int mb_y, | |||||
| int *mx_ptr, int *my_ptr) | |||||
| int ff_decide_type(MpegEncContext * s, | |||||
| int mb_x, int mb_y) | |||||
| { | { | ||||
| int xx, yy, x1, y1, x2, y2, range; | |||||
| if ((random() % 10) >= 5) { | |||||
| range = 8 * (1 << (s->f_code - 1)); | |||||
| if (s->out_format == FMT_H263 && !s->h263_msmpeg4) | |||||
| range = range * 2; | |||||
| xx = 16 * s->mb_x; | |||||
| yy = 16 * s->mb_y; | |||||
| x1 = xx - range; | |||||
| if (x1 < 0) | |||||
| x1 = 0; | |||||
| x2 = xx + range - 1; | |||||
| if (x2 > (s->width - 16)) | |||||
| x2 = s->width - 16; | |||||
| y1 = yy - range; | |||||
| if (y1 < 0) | |||||
| y1 = 0; | |||||
| y2 = yy + range - 1; | |||||
| if (y2 > (s->height - 16)) | |||||
| y2 = s->height - 16; | |||||
| *mx_ptr = (random() % (2 * (x2 - x1 + 1))) + 2 * (x1 - xx); | |||||
| *my_ptr = (random() % (2 * (y2 - y1 + 1))) + 2 * (y1 - yy); | |||||
| return 0; | |||||
| } else { | |||||
| *mx_ptr = 0; | |||||
| *my_ptr = 0; | |||||
| return 1; | |||||
| } | |||||
| void ff_estimate_b_frame_motion(MpegEncContext * s, | |||||
| int mb_x, int mb_y) | |||||
| { | |||||
| const int mot_stride = s->mb_width + 2; | |||||
| const int xy = (mb_y + 1)*mot_stride + mb_x + 1; | |||||
| ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, s->last_picture[0], s->f_code); | |||||
| ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, s->next_picture[0], s->b_code); | |||||
| //printf(" %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]); | |||||
| s->b_bidir_forw_mv_table[xy][0]= s->b_forw_mv_table[xy][0]; | |||||
| s->b_bidir_forw_mv_table[xy][1]= s->b_forw_mv_table[xy][1]; | |||||
| s->b_bidir_back_mv_table[xy][0]= s->b_back_mv_table[xy][0]; | |||||
| s->b_bidir_back_mv_table[xy][1]= s->b_back_mv_table[xy][1]; | |||||
| s->mb_type[mb_y*s->mb_width + mb_x]= MB_TYPE_FORWARD; //FIXME | |||||
| } | |||||
| /* find best f_code for ME which do unlimited searches */ | |||||
| int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type) | |||||
| { | |||||
| int f_code; | |||||
| if(s->me_method>=ME_EPZS){ | |||||
| int mv_num[8]; | |||||
| int i, y; | |||||
| int loose=0; | |||||
| UINT8 * fcode_tab= s->fcode_tab; | |||||
| for(i=0; i<8; i++) mv_num[i]=0; | |||||
| for(y=0; y<s->mb_height; y++){ | |||||
| int x; | |||||
| int xy= (y+1)* (s->mb_width+2) + 1; | |||||
| i= y*s->mb_width; | |||||
| for(x=0; x<s->mb_width; x++){ | |||||
| if(s->mb_type[i] & type){ | |||||
| mv_num[ fcode_tab[mv_table[xy][0] + MAX_MV] ]++; | |||||
| mv_num[ fcode_tab[mv_table[xy][1] + MAX_MV] ]++; | |||||
| //printf("%d %d %d\n", s->mv_table[0][i], fcode_tab[s->mv_table[0][i] + MAX_MV], i); | |||||
| } | |||||
| i++; | |||||
| xy++; | |||||
| } | |||||
| } | |||||
| for(i=MAX_FCODE; i>1; i--){ | |||||
| loose+= mv_num[i]; | |||||
| if(loose > s->mb_num/20) break; //FIXME this is pretty ineffective | |||||
| } | |||||
| // printf("fcode: %d type: %d\n", i, s->pict_type); | |||||
| return i; | |||||
| /* for(i=0; i<=MAX_FCODE; i++){ | |||||
| printf("%d ", mv_num[i]); | |||||
| } | |||||
| printf("\n");*/ | |||||
| }else{ | |||||
| return 1; | |||||
| } | } | ||||
| } | } | ||||
| #endif | |||||
| void ff_fix_long_p_mvs(MpegEncContext * s) | |||||
| { | |||||
| const int f_code= s->f_code; | |||||
| int y; | |||||
| UINT8 * fcode_tab= s->fcode_tab; | |||||
| /* clip / convert to intra 16x16 type MVs */ | |||||
| for(y=0; y<s->mb_height; y++){ | |||||
| int x; | |||||
| int xy= (y+1)* (s->mb_width+2)+1; | |||||
| int i= y*s->mb_width; | |||||
| for(x=0; x<s->mb_width; x++){ | |||||
| if(s->mb_type[i]&MB_TYPE_INTER){ | |||||
| if( fcode_tab[s->p_mv_table[xy][0] + MAX_MV] > f_code | |||||
| || fcode_tab[s->p_mv_table[xy][0] + MAX_MV] == 0 | |||||
| || fcode_tab[s->p_mv_table[xy][1] + MAX_MV] > f_code | |||||
| || fcode_tab[s->p_mv_table[xy][1] + MAX_MV] == 0 ){ | |||||
| s->mb_type[i] &= ~MB_TYPE_INTER; | |||||
| s->mb_type[i] |= MB_TYPE_INTRA; | |||||
| s->p_mv_table[xy][0] = 0; | |||||
| s->p_mv_table[xy][1] = 0; | |||||
| } | |||||
| } | |||||
| xy++; | |||||
| i++; | |||||
| } | |||||
| } | |||||
| if(s->flags&CODEC_FLAG_4MV){ | |||||
| const int wrap= 2+ s->mb_width*2; | |||||
| /* clip / convert to intra 8x8 type MVs */ | |||||
| for(y=0; y<s->mb_height; y++){ | |||||
| int xy= (y*2 + 1)*wrap + 1; | |||||
| int i= y*s->mb_width; | |||||
| int x; | |||||
| for(x=0; x<s->mb_width; x++){ | |||||
| if(s->mb_type[i]&MB_TYPE_INTER4V){ | |||||
| int block; | |||||
| for(block=0; block<4; block++){ | |||||
| int off= (block& 1) + (block>>1)*wrap; | |||||
| int mx= s->motion_val[ xy + off ][0]; | |||||
| int my= s->motion_val[ xy + off ][1]; | |||||
| if( fcode_tab[mx + MAX_MV] > f_code | |||||
| || fcode_tab[mx + MAX_MV] == 0 | |||||
| || fcode_tab[my + MAX_MV] > f_code | |||||
| || fcode_tab[my + MAX_MV] == 0 ){ | |||||
| s->mb_type[i] &= ~MB_TYPE_INTER4V; | |||||
| s->mb_type[i] |= MB_TYPE_INTRA; | |||||
| } | |||||
| } | |||||
| xy+=2; | |||||
| i++; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| void ff_fix_long_b_mvs(MpegEncContext * s, int16_t (*mv_table)[2], int f_code, int type) | |||||
| { | |||||
| int y; | |||||
| UINT8 * fcode_tab= s->fcode_tab; | |||||
| /* clip / convert to intra 16x16 type MVs */ | |||||
| for(y=0; y<s->mb_height; y++){ | |||||
| int x; | |||||
| int xy= (y+1)* (s->mb_width+2)+1; | |||||
| int i= y*s->mb_width; | |||||
| for(x=0; x<s->mb_width; x++){ | |||||
| if(s->mb_type[i]&type){ | |||||
| if( fcode_tab[mv_table[xy][0] + MAX_MV] > f_code | |||||
| || fcode_tab[mv_table[xy][0] + MAX_MV] == 0 | |||||
| || fcode_tab[mv_table[xy][1] + MAX_MV] > f_code | |||||
| || fcode_tab[mv_table[xy][1] + MAX_MV] == 0 ){ | |||||
| s->mb_type[i] &= ~type; | |||||
| if(s->mb_type[i]==0) s->mb_type[i]= MB_TYPE_FORWARD; //FIXME | |||||
| mv_table[xy][0] = 0; | |||||
| mv_table[xy][1] = 0; | |||||
| //this is certainly bad FIXME | |||||
| } | |||||
| } | |||||
| xy++; | |||||
| i++; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -26,7 +26,7 @@ | |||||
| enum OutputFormat { | enum OutputFormat { | ||||
| FMT_MPEG1, | FMT_MPEG1, | ||||
| FMT_H263, | FMT_H263, | ||||
| FMT_MJPEG, | |||||
| FMT_MJPEG, | |||||
| }; | }; | ||||
| #define MPEG_BUF_SIZE (16 * 1024) | #define MPEG_BUF_SIZE (16 * 1024) | ||||
| @@ -36,6 +36,7 @@ enum OutputFormat { | |||||
| #define MAX_FCODE 7 | #define MAX_FCODE 7 | ||||
| #define MAX_MV 2048 | #define MAX_MV 2048 | ||||
| #define REORDER_BUFFER_SIZE (FF_MAX_B_FRAMES+2) | |||||
| typedef struct Predictor{ | typedef struct Predictor{ | ||||
| double coeff; | double coeff; | ||||
| @@ -43,6 +44,15 @@ typedef struct Predictor{ | |||||
| double decay; | double decay; | ||||
| } Predictor; | } Predictor; | ||||
| typedef struct ReorderBuffer{ | |||||
| UINT8 *picture[3]; | |||||
| int pict_type; | |||||
| int qscale; | |||||
| int force_type; | |||||
| int picture_number; | |||||
| int picture_in_gop_number; | |||||
| } ReorderBuffer; | |||||
| typedef struct MpegEncContext { | typedef struct MpegEncContext { | ||||
| struct AVCodecContext *avctx; | struct AVCodecContext *avctx; | ||||
| /* the following parameters must be initialized before encoding */ | /* the following parameters must be initialized before encoding */ | ||||
| @@ -66,7 +76,8 @@ typedef struct MpegEncContext { | |||||
| int max_qdiff; /* max qscale difference between frames */ | int max_qdiff; /* max qscale difference between frames */ | ||||
| int encoding; /* true if we are encoding (vs decoding) */ | int encoding; /* true if we are encoding (vs decoding) */ | ||||
| int flags; /* AVCodecContext.flags (HQ, MV4, ...) */ | int flags; /* AVCodecContext.flags (HQ, MV4, ...) */ | ||||
| int force_type; /* 0= no force, otherwise I_TYPE, P_TYPE, ... */ | |||||
| int force_input_type;/* 0= no force, otherwise I_TYPE, P_TYPE, ... */ | |||||
| int max_b_frames; /* max number of b-frames for encoding */ | |||||
| /* the following fields are managed internally by the encoder */ | /* the following fields are managed internally by the encoder */ | ||||
| /* bit output */ | /* bit output */ | ||||
| @@ -74,45 +85,62 @@ typedef struct MpegEncContext { | |||||
| /* sequence parameters */ | /* sequence parameters */ | ||||
| int context_initialized; | int context_initialized; | ||||
| int input_picture_number; | |||||
| int input_picture_in_gop_number; /* 0-> first pic in gop, ... */ | |||||
| 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 based on fake_pic_num & mpeg1 specific */ | 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 picture_in_gop_number; /* 0-> first pic in gop, ... */ | ||||
| int mb_width, mb_height; | |||||
| int b_frames_since_non_b; /* used for encoding, relative to not yet reordered input */ | |||||
| int mb_width, mb_height; /* number of MBs horizontally & vertically */ | |||||
| 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 */ | ||||
| UINT8 *new_picture[3]; /* picture to be compressed */ | UINT8 *new_picture[3]; /* picture to be compressed */ | ||||
| UINT8 *last_picture[3]; /* previous picture */ | |||||
| UINT8 *picture_buffer[REORDER_BUFFER_SIZE][3]; /* internal buffers used for reordering of input pictures */ | |||||
| int picture_buffer_index; | |||||
| ReorderBuffer coded_order[REORDER_BUFFER_SIZE]; | |||||
| UINT8 *last_picture[3]; /* previous picture */ | |||||
| UINT8 *last_picture_base[3]; /* real start of the picture */ | UINT8 *last_picture_base[3]; /* real start of the picture */ | ||||
| UINT8 *next_picture[3]; /* previous picture (for bidir pred) */ | |||||
| UINT8 *next_picture[3]; /* previous picture (for bidir pred) */ | |||||
| UINT8 *next_picture_base[3]; /* real start of the picture */ | UINT8 *next_picture_base[3]; /* real start of the picture */ | ||||
| UINT8 *aux_picture[3]; /* aux picture (for B frames only) */ | |||||
| UINT8 *aux_picture_base[3]; /* real start of the picture */ | |||||
| UINT8 *current_picture[3]; /* buffer to store the decompressed current picture */ | |||||
| int last_dc[3]; /* last DC values for MPEG1 */ | |||||
| INT16 *dc_val[3]; /* used for mpeg4 DC prediction, all 3 arrays must be continuous */ | |||||
| UINT8 *aux_picture[3]; /* aux picture (for B frames only) */ | |||||
| UINT8 *aux_picture_base[3]; /* real start of the picture */ | |||||
| UINT8 *current_picture[3]; /* buffer to store the decompressed current picture */ | |||||
| int last_dc[3]; /* last DC values for MPEG1 */ | |||||
| INT16 *dc_val[3]; /* used for mpeg4 DC prediction, all 3 arrays must be continuous */ | |||||
| int y_dc_scale, c_dc_scale; | int y_dc_scale, c_dc_scale; | ||||
| UINT8 *coded_block; /* used for coded block pattern prediction */ | |||||
| INT16 (*ac_val[3])[16]; /* used for for mpeg4 AC prediction, all 3 arrays must be continuous */ | |||||
| UINT8 *coded_block; /* used for coded block pattern prediction (msmpeg4v3, wmv1)*/ | |||||
| INT16 (*ac_val[3])[16]; /* used for for mpeg4 AC prediction, all 3 arrays must be continuous */ | |||||
| int ac_pred; | int ac_pred; | ||||
| int mb_skiped; /* MUST BE SET only during DECODING */ | int mb_skiped; /* MUST BE SET only during DECODING */ | ||||
| UINT8 *mbskip_table; /* used to avoid copy if macroblock | |||||
| skipped (for black regions for example) */ | |||||
| UINT8 *mbintra_table; /* used to kill a few memsets */ | |||||
| int qscale; | |||||
| int pict_type; | |||||
| int last_non_b_pict_type; /* used for mpeg4 gmc b-frames */ | |||||
| int last_pict_type; /* used for bit rate stuff (needs that to update the right predictor) */ | |||||
| UINT8 *mbskip_table; /* used to avoid copy if macroblock skipped (for black regions for example) | |||||
| and used for b-frame encoding & decoding (contains skip table of next P Frame) */ | |||||
| UINT8 *mbintra_table; /* used to avoid setting {ac, dc, cbp}-pred stuff to zero on inter MB decoding */ | |||||
| int input_qscale; /* qscale prior to reordering of frames */ | |||||
| int input_pict_type; /* pict_type prior to reordering of frames */ | |||||
| int force_type; /* 0= no force, otherwise I_TYPE, P_TYPE, ... */ | |||||
| int qscale; /* QP */ | |||||
| int pict_type; /* I_TYPE, P_TYPE, B_TYPE, ... */ | |||||
| int last_non_b_pict_type; /* used for mpeg4 gmc b-frames */ | |||||
| int last_pict_type; /* used for bit rate stuff (needs that to update the right predictor) */ | |||||
| int frame_rate_index; | int frame_rate_index; | ||||
| /* motion compensation */ | /* motion compensation */ | ||||
| int unrestricted_mv; | int unrestricted_mv; | ||||
| int h263_long_vectors; /* use horrible h263v1 long vector mode */ | int h263_long_vectors; /* use horrible h263v1 long vector mode */ | ||||
| int f_code; /* resolution */ | |||||
| int b_code; /* backward resolution for B Frames (mpeg4) */ | |||||
| INT16 *mv_table[2]; /* MV table (1MV per MB)*/ | |||||
| INT16 (*motion_val)[2]; /* used for MV prediction (4MV per MB)*/ | |||||
| int f_code; /* forward MV resolution */ | |||||
| int b_code; /* backward MV resolution for B Frames (mpeg4) */ | |||||
| INT16 (*motion_val)[2]; /* used for MV prediction (4MV per MB) */ | |||||
| INT16 (*p_mv_table)[2]; /* MV table (1MV per MB) p-frame encoding */ | |||||
| INT16 (*last_p_mv_table)[2]; /* MV table (1MV per MB) p-frame encoding */ | |||||
| INT16 (*b_forw_mv_table)[2]; /* MV table (1MV per MB) forward mode b-frame encoding */ | |||||
| INT16 (*b_back_mv_table)[2]; /* MV table (1MV per MB) backward mode b-frame encoding */ | |||||
| INT16 (*b_bidir_forw_mv_table)[2]; /* MV table (1MV per MB) bidir mode b-frame encoding */ | |||||
| INT16 (*b_bidir_back_mv_table)[2]; /* MV table (1MV per MB) bidir mode b-frame encoding */ | |||||
| INT16 (*b_direct_forw_mv_table)[2];/* MV table (1MV per MB) direct mode b-frame encoding */ | |||||
| INT16 (*b_direct_back_mv_table)[2];/* MV table (1MV per MB) direct mode b-frame encoding */ | |||||
| INT16 (*b_direct_mv_table)[2]; /* MV table (1MV per MB) direct mode b-frame encoding */ | |||||
| int me_method; /* ME algorithm */ | int me_method; /* ME algorithm */ | ||||
| int mv_dir; | int mv_dir; | ||||
| #define MV_DIR_BACKWARD 1 | #define MV_DIR_BACKWARD 1 | ||||
| @@ -131,12 +159,12 @@ 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]; /* last MV, used for MV prediction in MPEG1 & B-frame MPEG4 */ | |||||
| UINT16 (*mv_penalty)[MAX_MV*2+1]; /* amount of bits needed to encode a MV, used for ME */ | 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 */ | 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 compensation (MPEG4, msmpeg4, ...) */ | |||||
| /* macroblock layer */ | /* macroblock layer */ | ||||
| int mb_x, mb_y; | int mb_x, mb_y; | ||||
| @@ -150,10 +178,10 @@ typedef struct MpegEncContext { | |||||
| #define MB_TYPE_SKIPED 0x08 | #define MB_TYPE_SKIPED 0x08 | ||||
| #define MB_TYPE_DIRECT 0x10 | #define MB_TYPE_DIRECT 0x10 | ||||
| #define MB_TYPE_FORWARD 0x20 | #define MB_TYPE_FORWARD 0x20 | ||||
| #define MB_TYPE_BACKWAD 0x40 | |||||
| #define MB_TYPE_BACKWARD 0x40 | |||||
| #define MB_TYPE_BIDIR 0x80 | #define MB_TYPE_BIDIR 0x80 | ||||
| int block_index[6]; | |||||
| int block_index[6]; /* index to current MB in block based arrays with edges*/ | |||||
| int block_wrap[6]; | int block_wrap[6]; | ||||
| /* matrix transmitted in the bitstream */ | /* matrix transmitted in the bitstream */ | ||||
| @@ -172,8 +200,7 @@ typedef struct MpegEncContext { | |||||
| void *opaque; /* private data for the user */ | void *opaque; /* private data for the user */ | ||||
| /* bit rate control */ | /* bit rate control */ | ||||
| int I_frame_bits; /* wanted number of bits per I frame */ | |||||
| int P_frame_bits; /* same for P frame */ | |||||
| int I_frame_bits; //FIXME used in mpeg12 ... | |||||
| int avg_mb_var; /* average MB variance for current frame */ | int avg_mb_var; /* average MB variance for current frame */ | ||||
| int mc_mb_var; /* motion compensated MB variance for current frame */ | int mc_mb_var; /* motion compensated MB variance for current frame */ | ||||
| int last_mc_mb_var; /* motion compensated MB variance for last frame */ | int last_mc_mb_var; /* motion compensated MB variance for last frame */ | ||||
| @@ -212,11 +239,13 @@ typedef struct MpegEncContext { | |||||
| /* mpeg4 specific */ | /* mpeg4 specific */ | ||||
| int time_increment_resolution; | int time_increment_resolution; | ||||
| int time_increment_bits; | |||||
| int time_increment; | |||||
| int time_base; | |||||
| int time; | |||||
| int last_non_b_time[2]; | |||||
| int time_increment_bits; /* number of bits to represent the fractional part of time */ | |||||
| int last_time_base; | |||||
| int time_base; /* time in seconds of last I,P,S Frame */ | |||||
| int64_t time; /* time of current frame */ | |||||
| int64_t last_non_b_time; | |||||
| uint16_t pp_time; /* time distance between the last 2 p,s,i frames */ | |||||
| uint16_t bp_time; /* time distance between the last b and p,s,i frame */ | |||||
| int shape; | int shape; | ||||
| int vol_sprite_usage; | int vol_sprite_usage; | ||||
| int sprite_width; | int sprite_width; | ||||
| @@ -231,7 +260,7 @@ typedef struct MpegEncContext { | |||||
| int sprite_shift[2][2]; | int sprite_shift[2][2]; | ||||
| int mcsel; | int mcsel; | ||||
| int quant_precision; | int quant_precision; | ||||
| int quarter_sample; | |||||
| int quarter_sample; /* 1->qpel, 0->half pel ME/MC */ | |||||
| int scalability; | int scalability; | ||||
| int new_pred; | int new_pred; | ||||
| int reduced_res_vop; | int reduced_res_vop; | ||||
| @@ -327,9 +356,13 @@ void MPV_common_init_mmx(MpegEncContext *s); | |||||
| #endif | #endif | ||||
| /* motion_est.c */ | /* motion_est.c */ | ||||
| void estimate_motion(MpegEncContext *s, | |||||
| int mb_x, int mb_y); | |||||
| void ff_estimate_p_frame_motion(MpegEncContext * s, | |||||
| int mb_x, int mb_y); | |||||
| void ff_estimate_b_frame_motion(MpegEncContext * s, | |||||
| int mb_x, int mb_y); | |||||
| 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_b_mvs(MpegEncContext * s, int16_t (*mv_table)[2], int f_code, int type); | |||||
| /* mpeg12.c */ | /* mpeg12.c */ | ||||
| extern INT16 default_intra_matrix[64]; | extern INT16 default_intra_matrix[64]; | ||||