Originally committed as revision 344 to svn://svn.ffmpeg.org/ffmpeg/trunk
Michael Niedermayer authored on 2002/03/22 11:21:17... | ... |
@@ -197,6 +197,7 @@ typedef struct GetBitContext { |
197 | 197 |
int bit_cnt; |
198 | 198 |
UINT8 *buf, *buf_ptr, *buf_end; |
199 | 199 |
#endif |
200 |
+ int size; |
|
200 | 201 |
} GetBitContext; |
201 | 202 |
|
202 | 203 |
typedef struct VLC { |
... | ... |
@@ -787,6 +788,24 @@ static inline int av_log2(unsigned int v) |
787 | 787 |
return n; |
788 | 788 |
} |
789 | 789 |
|
790 |
+/* median of 3 */ |
|
791 |
+static inline int mid_pred(int a, int b, int c) |
|
792 |
+{ |
|
793 |
+ int vmin, vmax; |
|
794 |
+ vmax = vmin = a; |
|
795 |
+ if (b < vmin) |
|
796 |
+ vmin = b; |
|
797 |
+ else |
|
798 |
+ vmax = b; |
|
799 |
+ |
|
800 |
+ if (c < vmin) |
|
801 |
+ vmin = c; |
|
802 |
+ else if (c > vmax) |
|
803 |
+ vmax = c; |
|
804 |
+ |
|
805 |
+ return a + b + c - vmin - vmax; |
|
806 |
+} |
|
807 |
+ |
|
790 | 808 |
/* memory */ |
791 | 809 |
void *av_mallocz(int size); |
792 | 810 |
|
... | ... |
@@ -17,6 +17,8 @@ |
17 | 17 |
* You should have received a copy of the GNU General Public License |
18 | 18 |
* along with this program; if not, write to the Free Software |
19 | 19 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 |
+ * |
|
21 |
+ * ac prediction encoding by Michael Niedermayer <michaelni@gmx.at> |
|
20 | 22 |
*/ |
21 | 23 |
#include "common.h" |
22 | 24 |
#include "dsputil.h" |
... | ... |
@@ -45,9 +47,11 @@ static int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, |
45 | 45 |
static inline int mpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *dir_ptr); |
46 | 46 |
static void mpeg4_inv_pred_ac(MpegEncContext * s, INT16 *block, int n, |
47 | 47 |
int dir); |
48 |
- |
|
49 | 48 |
extern UINT32 inverse[256]; |
50 | 49 |
|
50 |
+static UINT16 mv_penalty[MAX_FCODE][MAX_MV*2+1]; |
|
51 |
+static UINT8 fcode_tab[MAX_MV*2+1]; |
|
52 |
+ |
|
51 | 53 |
int h263_get_picture_format(int width, int height) |
52 | 54 |
{ |
53 | 55 |
int format; |
... | ... |
@@ -524,24 +528,6 @@ void h263_pred_acdc(MpegEncContext * s, INT16 *block, int n) |
524 | 524 |
ac_val1[8 + i] = block[block_permute_op(i)]; |
525 | 525 |
} |
526 | 526 |
|
527 |
- |
|
528 |
-static inline int mid_pred(int a, int b, int c) |
|
529 |
-{ |
|
530 |
- int vmin, vmax; |
|
531 |
- vmax = vmin = a; |
|
532 |
- if (b < vmin) |
|
533 |
- vmin = b; |
|
534 |
- else |
|
535 |
- vmax = b; |
|
536 |
- |
|
537 |
- if (c < vmin) |
|
538 |
- vmin = c; |
|
539 |
- else if (c > vmax) |
|
540 |
- vmax = c; |
|
541 |
- |
|
542 |
- return a + b + c - vmin - vmax; |
|
543 |
-} |
|
544 |
- |
|
545 | 527 |
INT16 *h263_pred_motion(MpegEncContext * s, int block, |
546 | 528 |
int *px, int *py) |
547 | 529 |
{ |
... | ... |
@@ -648,7 +634,46 @@ static void h263p_encode_umotion(MpegEncContext * s, int val) |
648 | 648 |
} |
649 | 649 |
} |
650 | 650 |
|
651 |
-void h263_encode_init_vlc(MpegEncContext *s) |
|
651 |
+static void init_mv_penalty_and_fcode(MpegEncContext *s) |
|
652 |
+{ |
|
653 |
+ int f_code; |
|
654 |
+ int mv; |
|
655 |
+ for(f_code=1; f_code<=MAX_FCODE; f_code++){ |
|
656 |
+ for(mv=-MAX_MV; mv<=MAX_MV; mv++){ |
|
657 |
+ int len; |
|
658 |
+ |
|
659 |
+ if(mv==0) len= mvtab[0][1]; |
|
660 |
+ else{ |
|
661 |
+ int val, bit_size, range, code; |
|
662 |
+ |
|
663 |
+ bit_size = s->f_code - 1; |
|
664 |
+ range = 1 << bit_size; |
|
665 |
+ |
|
666 |
+ val=mv; |
|
667 |
+ if (val < 0) |
|
668 |
+ val = -val; |
|
669 |
+ val--; |
|
670 |
+ code = (val >> bit_size) + 1; |
|
671 |
+ if(code<33){ |
|
672 |
+ len= mvtab[code][1] + 1 + bit_size; |
|
673 |
+ }else{ |
|
674 |
+ len= mvtab[32][1] + 2 + bit_size; |
|
675 |
+ } |
|
676 |
+ } |
|
677 |
+ |
|
678 |
+ mv_penalty[f_code][mv+MAX_MV]= len; |
|
679 |
+ } |
|
680 |
+ } |
|
681 |
+ |
|
682 |
+ |
|
683 |
+ for(f_code=MAX_FCODE; f_code>0; f_code--){ |
|
684 |
+ for(mv=-(16<<f_code); mv<(16<<f_code); mv++){ |
|
685 |
+ fcode_tab[mv+MAX_MV]= f_code; |
|
686 |
+ } |
|
687 |
+ } |
|
688 |
+} |
|
689 |
+ |
|
690 |
+void h263_encode_init(MpegEncContext *s) |
|
652 | 691 |
{ |
653 | 692 |
static int done = 0; |
654 | 693 |
|
... | ... |
@@ -656,7 +681,13 @@ void h263_encode_init_vlc(MpegEncContext *s) |
656 | 656 |
done = 1; |
657 | 657 |
init_rl(&rl_inter); |
658 | 658 |
init_rl(&rl_intra); |
659 |
+ |
|
660 |
+ init_mv_penalty_and_fcode(s); |
|
659 | 661 |
} |
662 |
+ s->mv_penalty= mv_penalty; |
|
663 |
+ |
|
664 |
+ // use fcodes >1 only for mpeg4 FIXME |
|
665 |
+ if(!s->h263_msmpeg4 && s->h263_pred) s->fcode_tab= fcode_tab; |
|
660 | 666 |
} |
661 | 667 |
|
662 | 668 |
static void h263_encode_block(MpegEncContext * s, DCTELEM * block, int n) |
... | ... |
@@ -2094,9 +2125,8 @@ int mpeg4_decode_picture_header(MpegEncContext * s) |
2094 | 2094 |
break; |
2095 | 2095 |
} |
2096 | 2096 |
state = ((state << 8) | v) & 0xffffff; |
2097 |
- /* XXX: really detect end of frame */ |
|
2098 |
- if (state == 0){ |
|
2099 |
- printf("illegal zero code found\n"); |
|
2097 |
+ if( get_bits_count(&s->gb) > s->gb.size*8){ |
|
2098 |
+ printf("no VOP startcode found\n"); |
|
2100 | 2099 |
return -1; |
2101 | 2100 |
} |
2102 | 2101 |
} |
... | ... |
@@ -2152,6 +2182,7 @@ int mpeg4_decode_picture_header(MpegEncContext * s) |
2152 | 2152 |
if(width && height){ /* they should be non zero but who knows ... */ |
2153 | 2153 |
s->width = width; |
2154 | 2154 |
s->height = height; |
2155 |
+// printf("%d %d\n", width, height); |
|
2155 | 2156 |
} |
2156 | 2157 |
} |
2157 | 2158 |
|
... | ... |
@@ -16,6 +16,8 @@ |
16 | 16 |
* You should have received a copy of the GNU General Public License |
17 | 17 |
* along with this program; if not, write to the Free Software |
18 | 18 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 |
+ * |
|
20 |
+ * new Motion Estimation (X1/EPZS) by Michael Niedermayer <michaelni@gmx.at> |
|
19 | 21 |
*/ |
20 | 22 |
#include <stdlib.h> |
21 | 23 |
#include <stdio.h> |
... | ... |
@@ -25,7 +27,8 @@ |
25 | 25 |
|
26 | 26 |
static void halfpel_motion_search(MpegEncContext * s, |
27 | 27 |
int *mx_ptr, int *my_ptr, int dmin, |
28 |
- int xmin, int ymin, int xmax, int ymax); |
|
28 |
+ int xmin, int ymin, int xmax, int ymax, |
|
29 |
+ int pred_x, int pred_y); |
|
29 | 30 |
|
30 | 31 |
/* config it to test motion vector encoding (send random vectors) */ |
31 | 32 |
//#define CONFIG_TEST_MV_ENCODE |
... | ... |
@@ -328,67 +331,209 @@ static int phods_motion_search(MpegEncContext * s, |
328 | 328 |
return dminy; |
329 | 329 |
} |
330 | 330 |
|
331 |
+ |
|
332 |
+#define Z_THRESHOLD 256 |
|
333 |
+ |
|
334 |
+#define CHECK_MV(x,y)\ |
|
335 |
+ d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\ |
|
336 |
+ d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\ |
|
337 |
+ if(d<dmin){\ |
|
338 |
+ best[0]=x;\ |
|
339 |
+ best[1]=y;\ |
|
340 |
+ dmin=d;\ |
|
341 |
+ } |
|
342 |
+ |
|
343 |
+#define CHECK_MV_DIR(x,y,new_dir)\ |
|
344 |
+{\ |
|
345 |
+ d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\ |
|
346 |
+ d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\ |
|
347 |
+ if(d<dmin){\ |
|
348 |
+ best[0]=x;\ |
|
349 |
+ best[1]=y;\ |
|
350 |
+ dmin=d;\ |
|
351 |
+ next_dir= new_dir;\ |
|
352 |
+ }\ |
|
353 |
+} |
|
354 |
+ |
|
355 |
+static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin, |
|
356 |
+ UINT8 *new_pic, UINT8 *old_pic, int pic_stride, |
|
357 |
+ int pred_x, int pred_y, UINT16 *mv_penalty, int quant, |
|
358 |
+ int xmin, int ymin, int xmax, int ymax, int shift) |
|
359 |
+{ |
|
360 |
+ int next_dir=-1; |
|
361 |
+ |
|
362 |
+ for(;;){ |
|
363 |
+ int d; |
|
364 |
+ const int dir= next_dir; |
|
365 |
+ const int x= best[0]; |
|
366 |
+ const int y= best[1]; |
|
367 |
+ next_dir=-1; |
|
368 |
+ |
|
369 |
+//printf("%d", dir); |
|
370 |
+ if(dir!=2 && x-1>=xmin) CHECK_MV_DIR(x-1, y , 0) |
|
371 |
+ if(dir!=3 && y-1>=ymin) CHECK_MV_DIR(x , y-1, 1) |
|
372 |
+ if(dir!=0 && x+1<=xmax) CHECK_MV_DIR(x+1, y , 2) |
|
373 |
+ if(dir!=1 && y+1<=ymax) CHECK_MV_DIR(x , y+1, 3) |
|
374 |
+ |
|
375 |
+ if(next_dir==-1){ |
|
376 |
+ return dmin; |
|
377 |
+ } |
|
378 |
+ } |
|
379 |
+} |
|
380 |
+ |
|
381 |
+static int epzs_motion_search(MpegEncContext * s, |
|
382 |
+ int *mx_ptr, int *my_ptr, |
|
383 |
+ int *px_ptr, int *py_ptr, |
|
384 |
+ int xmin, int ymin, int xmax, int ymax) |
|
385 |
+{ |
|
386 |
+ INT16 P_left[2], P_top[2], P_topright[2], P_last[2]; |
|
387 |
+ static const int off[4]= {2, 1, 1, -1}; |
|
388 |
+ int best[2]={0, 0}; |
|
389 |
+ int d, dmin; |
|
390 |
+ UINT8 *new_pic, *old_pic; |
|
391 |
+ const int pic_stride= s->linesize; |
|
392 |
+ const int pic_xy= (s->mb_y*pic_stride + s->mb_x)*16; |
|
393 |
+ const int mot_stride = s->block_wrap[0]; |
|
394 |
+ const int mot_xy = s->block_index[0]; |
|
395 |
+ UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame |
|
396 |
+ int quant= s->qscale; // qscale of the prev frame |
|
397 |
+ int pred_x, pred_y; |
|
398 |
+ const int shift= 1+s->quarter_sample; |
|
399 |
+ |
|
400 |
+ new_pic = s->new_picture[0] + pic_xy; |
|
401 |
+ old_pic = s->last_picture[0] + pic_xy; |
|
402 |
+ |
|
403 |
+ xmin-=s->mb_x*16; |
|
404 |
+ xmax-=s->mb_x*16; |
|
405 |
+ ymin-=s->mb_y*16; |
|
406 |
+ ymax-=s->mb_y*16; |
|
407 |
+ |
|
408 |
+ dmin = pix_abs16x16(new_pic, old_pic, pic_stride, 16); |
|
409 |
+ if(dmin<Z_THRESHOLD){ |
|
410 |
+ *mx_ptr= 0; |
|
411 |
+ *my_ptr= 0; |
|
412 |
+//printf("Z"); |
|
413 |
+ return dmin; |
|
414 |
+ } |
|
415 |
+ |
|
416 |
+ P_last[0] = s->motion_val[mot_xy ][0]; |
|
417 |
+ P_last[1] = s->motion_val[mot_xy ][1]; |
|
418 |
+ P_left[0] = s->motion_val[mot_xy - 1][0]; |
|
419 |
+ P_left[1] = s->motion_val[mot_xy - 1][1]; |
|
420 |
+ if(P_left[0] > (xmax<<shift)) P_left[0]= (xmax<<shift); |
|
421 |
+ |
|
422 |
+ /* special case for first line */ |
|
423 |
+ if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) { |
|
424 |
+ *px_ptr= pred_x = P_left[0]; |
|
425 |
+ *py_ptr= pred_y = P_left[1]; |
|
426 |
+ CHECK_MV(pred_x>>shift, pred_y>>shift) |
|
427 |
+ if(dmin<Z_THRESHOLD){ |
|
428 |
+ *mx_ptr= pred_x>>shift; |
|
429 |
+ *my_ptr= pred_y>>shift; |
|
430 |
+//printf("M"); |
|
431 |
+ return dmin; |
|
432 |
+ } |
|
433 |
+ } else { |
|
434 |
+ P_top [0] = s->motion_val[mot_xy - mot_stride ][0]; |
|
435 |
+ P_top [1] = s->motion_val[mot_xy - mot_stride ][1]; |
|
436 |
+ P_topright[0] = s->motion_val[mot_xy - mot_stride + off[0] ][0]; |
|
437 |
+ P_topright[1] = s->motion_val[mot_xy - mot_stride + off[0] ][1]; |
|
438 |
+ if(P_top [1] > (ymax<<shift)) P_top [1]= (ymax<<shift); |
|
439 |
+ if(P_topright[0] < (xmin<<shift)) P_topright[0]= (xmin<<shift); |
|
440 |
+ if(P_topright[1] > (ymax<<shift)) P_topright[1]= (ymax<<shift); |
|
441 |
+ |
|
442 |
+ *px_ptr= pred_x = mid_pred(P_left[0], P_top[0], P_topright[0]); |
|
443 |
+ *py_ptr= pred_y = mid_pred(P_left[1], P_top[1], P_topright[1]); |
|
444 |
+ |
|
445 |
+ CHECK_MV(pred_x>>shift, pred_y>>shift) |
|
446 |
+ if(dmin<Z_THRESHOLD){ |
|
447 |
+ *mx_ptr= pred_x>>shift; |
|
448 |
+ *my_ptr= pred_y>>shift; |
|
449 |
+//printf("M"); |
|
450 |
+ return dmin; |
|
451 |
+ } |
|
452 |
+ |
|
453 |
+ CHECK_MV(P_left [0]>>shift, P_left [1]>>shift) |
|
454 |
+ CHECK_MV(P_top [0]>>shift, P_top [1]>>shift) |
|
455 |
+ CHECK_MV(P_topright[0]>>shift, P_topright[1]>>shift) |
|
456 |
+ CHECK_MV(P_last [0]>>shift, P_last [1]>>shift) |
|
457 |
+ } |
|
458 |
+ |
|
459 |
+ dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride, |
|
460 |
+ pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift); |
|
461 |
+ *mx_ptr= best[0]; |
|
462 |
+ *my_ptr= best[1]; |
|
463 |
+ |
|
464 |
+// printf("%d %d %d \n", best[0], best[1], dmin); |
|
465 |
+ |
|
466 |
+ return dmin; |
|
467 |
+} |
|
468 |
+ |
|
469 |
+#define CHECK_HALF_MV(suffix, x, y) \ |
|
470 |
+ d= pix_abs16x16_ ## suffix(pix, ptr+((x)>>1), s->linesize, 16);\ |
|
471 |
+ d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*quant;\ |
|
472 |
+ if(d<dminh){\ |
|
473 |
+ dminh= d;\ |
|
474 |
+ mx= mx1 + x;\ |
|
475 |
+ my= my1 + y;\ |
|
476 |
+ } |
|
477 |
+ |
|
331 | 478 |
/* The idea would be to make half pel ME after Inter/Intra decision to |
332 | 479 |
save time. */ |
333 |
-static void halfpel_motion_search(MpegEncContext * s, |
|
480 |
+static inline void halfpel_motion_search(MpegEncContext * s, |
|
334 | 481 |
int *mx_ptr, int *my_ptr, int dmin, |
335 |
- int xmin, int ymin, int xmax, int ymax) |
|
482 |
+ int xmin, int ymin, int xmax, int ymax, |
|
483 |
+ int pred_x, int pred_y) |
|
336 | 484 |
{ |
485 |
+ UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame |
|
486 |
+ const int quant= s->qscale; |
|
487 |
+ int pen_x, pen_y; |
|
337 | 488 |
int mx, my, mx1, my1, d, xx, yy, dminh; |
338 |
- UINT8 *pix; |
|
489 |
+ UINT8 *pix, *ptr; |
|
339 | 490 |
|
340 |
- mx = *mx_ptr << 1; |
|
341 |
- my = *my_ptr << 1; |
|
491 |
+ |
|
492 |
+ mx = *mx_ptr; |
|
493 |
+ my = *my_ptr; |
|
494 |
+ ptr = s->last_picture[0] + (my * s->linesize) + mx; |
|
342 | 495 |
|
343 | 496 |
xx = 16 * s->mb_x; |
344 | 497 |
yy = 16 * s->mb_y; |
345 |
- |
|
498 |
+ pix = s->new_picture[0] + (yy * s->linesize) + xx; |
|
499 |
+ |
|
346 | 500 |
dminh = dmin; |
347 | 501 |
|
348 |
- /* Half pixel search */ |
|
349 |
- mx1 = mx; |
|
350 |
- my1 = my; |
|
351 |
- |
|
352 |
- pix = s->new_picture[0] + (yy * s->linesize) + xx; |
|
502 |
+ if (mx > xmin && mx < xmax && |
|
503 |
+ my > ymin && my < ymax) { |
|
353 | 504 |
|
354 |
- if ((mx > (xmin << 1)) && mx < (xmax << 1) && |
|
355 |
- (my > (ymin << 1)) && my < (ymax << 1)) { |
|
356 |
- int dx, dy, px, py; |
|
357 |
- UINT8 *ptr; |
|
358 |
- for (dy = -1; dy <= 1; dy++) { |
|
359 |
- for (dx = -1; dx <= 1; dx++) { |
|
360 |
- if (dx != 0 || dy != 0) { |
|
361 |
- px = mx1 + dx; |
|
362 |
- py = my1 + dy; |
|
363 |
- ptr = s->last_picture[0] + ((py >> 1) * s->linesize) + (px >> 1); |
|
364 |
- switch (((py & 1) << 1) | (px & 1)) { |
|
365 |
- default: |
|
366 |
- case 0: |
|
367 |
- d = pix_abs16x16(pix, ptr, s->linesize, 16); |
|
368 |
- break; |
|
369 |
- case 1: |
|
370 |
- d = pix_abs16x16_x2(pix, ptr, s->linesize, 16); |
|
371 |
- break; |
|
372 |
- case 2: |
|
373 |
- d = pix_abs16x16_y2(pix, ptr, s->linesize, 16); |
|
374 |
- break; |
|
375 |
- case 3: |
|
376 |
- d = pix_abs16x16_xy2(pix, ptr, s->linesize, 16); |
|
377 |
- break; |
|
378 |
- } |
|
379 |
- if (d < dminh) { |
|
380 |
- dminh = d; |
|
381 |
- mx = px; |
|
382 |
- my = py; |
|
383 |
- } |
|
384 |
- } |
|
385 |
- } |
|
505 |
+ mx= mx1= 2*(mx - xx); |
|
506 |
+ my= my1= 2*(my - yy); |
|
507 |
+ if(dmin < Z_THRESHOLD && mx==0 && my==0){ |
|
508 |
+ *mx_ptr = 0; |
|
509 |
+ *my_ptr = 0; |
|
510 |
+ return; |
|
386 | 511 |
} |
512 |
+ |
|
513 |
+ pen_x= pred_x + mx; |
|
514 |
+ pen_y= pred_y + my; |
|
515 |
+ |
|
516 |
+ ptr-= s->linesize; |
|
517 |
+ CHECK_HALF_MV(xy2, -1, -1) |
|
518 |
+ CHECK_HALF_MV(y2 , 0, -1) |
|
519 |
+ CHECK_HALF_MV(xy2, +1, -1) |
|
520 |
+ |
|
521 |
+ ptr+= s->linesize; |
|
522 |
+ CHECK_HALF_MV(x2 , -1, 0) |
|
523 |
+ CHECK_HALF_MV(x2 , +1, 0) |
|
524 |
+ CHECK_HALF_MV(xy2, -1, +1) |
|
525 |
+ CHECK_HALF_MV(y2 , 0, +1) |
|
526 |
+ CHECK_HALF_MV(xy2, +1, +1) |
|
527 |
+ }else{ |
|
528 |
+ mx= 2*(mx - xx); |
|
529 |
+ my= 2*(my - yy); |
|
387 | 530 |
} |
388 | 531 |
|
389 |
- *mx_ptr = mx - (xx << 1); |
|
390 |
- *my_ptr = my - (yy << 1); |
|
391 |
- //fprintf(stderr,"half - MX: %d\tMY: %d\n",*mx_ptr ,*my_ptr); |
|
532 |
+ *mx_ptr = mx; |
|
533 |
+ *my_ptr = my; |
|
392 | 534 |
} |
393 | 535 |
|
394 | 536 |
#ifndef CONFIG_TEST_MV_ENCODE |
... | ... |
@@ -400,6 +545,7 @@ int estimate_motion(MpegEncContext * s, |
400 | 400 |
UINT8 *pix, *ppix; |
401 | 401 |
int sum, varc, vard, mx, my, range, dmin, xx, yy; |
402 | 402 |
int xmin, ymin, xmax, ymax; |
403 |
+ int pred_x=0, pred_y=0; |
|
403 | 404 |
|
404 | 405 |
range = 8 * (1 << (s->f_code - 1)); |
405 | 406 |
/* XXX: temporary kludge to avoid overflow for msmpeg4 */ |
... | ... |
@@ -426,7 +572,6 @@ int estimate_motion(MpegEncContext * s, |
426 | 426 |
xmax = s->mb_width*16 - 16; |
427 | 427 |
ymax = s->mb_height*16 - 16; |
428 | 428 |
} |
429 |
- |
|
430 | 429 |
switch(s->full_search) { |
431 | 430 |
case ME_ZERO: |
432 | 431 |
default: |
... | ... |
@@ -442,8 +587,13 @@ int estimate_motion(MpegEncContext * s, |
442 | 442 |
case ME_PHODS: |
443 | 443 |
dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax); |
444 | 444 |
break; |
445 |
+ case ME_X1: // just reserving some space for experiments ... |
|
446 |
+ case ME_EPZS: |
|
447 |
+ dmin = epzs_motion_search(s, &mx, &my, &pred_x, &pred_y, xmin, ymin, xmax, ymax); |
|
448 |
+ mx+= s->mb_x*16; |
|
449 |
+ my+= s->mb_y*16; |
|
450 |
+ break; |
|
445 | 451 |
} |
446 |
- emms_c(); |
|
447 | 452 |
|
448 | 453 |
/* intra / predictive decision */ |
449 | 454 |
xx = mb_x * 16; |
... | ... |
@@ -470,7 +620,7 @@ int estimate_motion(MpegEncContext * s, |
470 | 470 |
#endif |
471 | 471 |
if (vard <= 64 || vard < varc) { |
472 | 472 |
if (s->full_search != ME_ZERO) { |
473 |
- halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax); |
|
473 |
+ halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y); |
|
474 | 474 |
} else { |
475 | 475 |
mx -= 16 * s->mb_x; |
476 | 476 |
my -= 16 * s->mb_y; |
... | ... |
@@ -66,7 +66,7 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) |
66 | 66 |
int n; |
67 | 67 |
UINT64 time_code; |
68 | 68 |
|
69 |
- if ((s->picture_number % s->gop_size) == 0) { |
|
69 |
+ if (s->picture_in_gop_number == 0) { |
|
70 | 70 |
/* mpeg1 header repeated every gop */ |
71 | 71 |
put_header(s, SEQ_START_CODE); |
72 | 72 |
|
... | ... |
@@ -67,6 +67,9 @@ static UINT8 h263_chroma_roundtab[16] = { |
67 | 67 |
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, |
68 | 68 |
}; |
69 | 69 |
|
70 |
+static UINT16 default_mv_penalty[MAX_FCODE][MAX_MV*2+1]; |
|
71 |
+static UINT8 default_fcode_tab[MAX_MV*2+1]; |
|
72 |
+ |
|
70 | 73 |
/* default motion estimation */ |
71 | 74 |
int motion_estimation_method = ME_LOG; |
72 | 75 |
|
... | ... |
@@ -356,8 +359,24 @@ int MPV_encode_init(AVCodecContext *avctx) |
356 | 356 |
return -1; |
357 | 357 |
} |
358 | 358 |
|
359 |
+ { /* set up some save defaults, some codecs might override them later */ |
|
360 |
+ static int done=0; |
|
361 |
+ if(!done){ |
|
362 |
+ int i; |
|
363 |
+ done=1; |
|
364 |
+ memset(default_mv_penalty, 0, sizeof(UINT16)*MAX_FCODE*(2*MAX_MV+1)); |
|
365 |
+ memset(default_fcode_tab , 0, sizeof(UINT8)*(2*MAX_MV+1)); |
|
366 |
+ |
|
367 |
+ for(i=-16; i<16; i++){ |
|
368 |
+ default_fcode_tab[i + MAX_MV]= 1; |
|
369 |
+ } |
|
370 |
+ } |
|
371 |
+ } |
|
372 |
+ s->mv_penalty= default_mv_penalty; |
|
373 |
+ s->fcode_tab= default_fcode_tab; |
|
374 |
+ |
|
359 | 375 |
if (s->out_format == FMT_H263) |
360 |
- h263_encode_init_vlc(s); |
|
376 |
+ h263_encode_init(s); |
|
361 | 377 |
|
362 | 378 |
s->encoding = 1; |
363 | 379 |
|
... | ... |
@@ -375,6 +394,7 @@ int MPV_encode_init(AVCodecContext *avctx) |
375 | 375 |
rate_control_init(s); |
376 | 376 |
|
377 | 377 |
s->picture_number = 0; |
378 |
+ s->picture_in_gop_number = 0; |
|
378 | 379 |
s->fake_picture_number = 0; |
379 | 380 |
/* motion detector init */ |
380 | 381 |
s->f_code = 1; |
... | ... |
@@ -480,9 +500,10 @@ int MPV_encode_picture(AVCodecContext *avctx, |
480 | 480 |
|
481 | 481 |
if (!s->intra_only) { |
482 | 482 |
/* first picture of GOP is intra */ |
483 |
- if ((s->picture_number % s->gop_size) == 0) |
|
483 |
+ if (s->picture_in_gop_number >= s->gop_size){ |
|
484 |
+ s->picture_in_gop_number=0; |
|
484 | 485 |
s->pict_type = I_TYPE; |
485 |
- else |
|
486 |
+ }else |
|
486 | 487 |
s->pict_type = P_TYPE; |
487 | 488 |
} else { |
488 | 489 |
s->pict_type = I_TYPE; |
... | ... |
@@ -521,6 +542,7 @@ int MPV_encode_picture(AVCodecContext *avctx, |
521 | 521 |
|
522 | 522 |
MPV_frame_end(s); |
523 | 523 |
s->picture_number++; |
524 |
+ s->picture_in_gop_number++; |
|
524 | 525 |
|
525 | 526 |
if (s->out_format == FMT_MJPEG) |
526 | 527 |
mjpeg_picture_trailer(s); |
... | ... |
@@ -1077,17 +1099,66 @@ static void encode_picture(MpegEncContext *s, int picture_number) |
1077 | 1077 |
s->mv_table[1][xy] = motion_y; |
1078 | 1078 |
} |
1079 | 1079 |
} |
1080 |
+ emms_c(); |
|
1080 | 1081 |
|
1081 | 1082 |
if(s->avg_mb_var < s->mc_mb_var && s->pict_type != B_TYPE){ //FIXME subtract MV bits |
1082 | 1083 |
int i; |
1083 | 1084 |
s->pict_type= I_TYPE; |
1084 |
- for(i=0; i<s->mb_height*s->mb_width; i++){ |
|
1085 |
- s->mb_type[i] = I_TYPE; |
|
1085 |
+ s->picture_in_gop_number=0; |
|
1086 |
+ for(i=0; i<s->mb_num; i++){ |
|
1087 |
+ s->mb_type[i] = 1; |
|
1086 | 1088 |
s->mv_table[0][i] = 0; |
1087 | 1089 |
s->mv_table[1][i] = 0; |
1088 | 1090 |
} |
1089 | 1091 |
} |
1090 |
- |
|
1092 |
+ |
|
1093 |
+ /* find best f_code */ |
|
1094 |
+ if(s->pict_type==P_TYPE){ |
|
1095 |
+ int mv_num[8]; |
|
1096 |
+ int i; |
|
1097 |
+ int loose=0; |
|
1098 |
+ UINT8 * fcode_tab= s->fcode_tab; |
|
1099 |
+ |
|
1100 |
+ for(i=0; i<8; i++) mv_num[i]=0; |
|
1101 |
+ |
|
1102 |
+ for(i=0; i<s->mb_num; i++){ |
|
1103 |
+ if(s->mb_type[i] == 0){ |
|
1104 |
+ mv_num[ fcode_tab[s->mv_table[0][i] + MAX_MV] ]++; |
|
1105 |
+ mv_num[ fcode_tab[s->mv_table[1][i] + MAX_MV] ]++; |
|
1106 |
+//printf("%d %d %d\n", s->mv_table[0][i], fcode_tab[s->mv_table[0][i] + MAX_MV], i); |
|
1107 |
+ } |
|
1108 |
+//else printf("I"); |
|
1109 |
+ } |
|
1110 |
+ |
|
1111 |
+ for(i=MAX_FCODE; i>1; i--){ |
|
1112 |
+ loose+= mv_num[i]; |
|
1113 |
+ if(loose > 4) break; |
|
1114 |
+ } |
|
1115 |
+ s->f_code= i; |
|
1116 |
+ }else{ |
|
1117 |
+ s->f_code= 1; |
|
1118 |
+ } |
|
1119 |
+//printf("f_code %d ///\n", s->f_code); |
|
1120 |
+ /* convert MBs with too long MVs to I-Blocks */ |
|
1121 |
+ if(s->pict_type==P_TYPE){ |
|
1122 |
+ int i; |
|
1123 |
+ const int f_code= s->f_code; |
|
1124 |
+ UINT8 * fcode_tab= s->fcode_tab; |
|
1125 |
+ |
|
1126 |
+ for(i=0; i<s->mb_num; i++){ |
|
1127 |
+ if(s->mb_type[i] == 0){ |
|
1128 |
+ if( fcode_tab[s->mv_table[0][i] + MAX_MV] > f_code |
|
1129 |
+ || fcode_tab[s->mv_table[0][i] + MAX_MV] == 0 |
|
1130 |
+ || fcode_tab[s->mv_table[1][i] + MAX_MV] > f_code |
|
1131 |
+ || fcode_tab[s->mv_table[1][i] + MAX_MV] == 0 ){ |
|
1132 |
+ s->mb_type[i] = 1; |
|
1133 |
+ s->mv_table[0][i] = 0; |
|
1134 |
+ s->mv_table[1][i] = 0; |
|
1135 |
+ } |
|
1136 |
+ } |
|
1137 |
+ } |
|
1138 |
+ } |
|
1139 |
+ |
|
1091 | 1140 |
// printf("%d %d\n", s->avg_mb_var, s->mc_mb_var); |
1092 | 1141 |
|
1093 | 1142 |
if (!s->fixed_qscale) |
... | ... |
@@ -34,6 +34,9 @@ enum OutputFormat { |
34 | 34 |
#define QMAT_SHIFT_MMX 19 |
35 | 35 |
#define QMAT_SHIFT 25 |
36 | 36 |
|
37 |
+#define MAX_FCODE 7 |
|
38 |
+#define MAX_MV 2048 |
|
39 |
+ |
|
37 | 40 |
typedef struct Predictor{ |
38 | 41 |
double coeff; |
39 | 42 |
double count; |
... | ... |
@@ -71,7 +74,8 @@ typedef struct MpegEncContext { |
71 | 71 |
int context_initialized; |
72 | 72 |
int picture_number; |
73 | 73 |
int fake_picture_number; /* picture number at the bitstream frame rate */ |
74 |
- int gop_picture_number; /* index of the first picture of a GOP */ |
|
74 |
+ int gop_picture_number; /* index of the first picture of a GOP based on fake_pic_num & mpeg1 specific */ |
|
75 |
+ int picture_in_gop_number; /* 0-> first pic in gop, ... */ |
|
75 | 76 |
int mb_width, mb_height; |
76 | 77 |
int mb_num; /* number of MBs of a picture */ |
77 | 78 |
int linesize; /* line size, in bytes, may be different from width */ |
... | ... |
@@ -114,7 +118,7 @@ typedef struct MpegEncContext { |
114 | 114 |
#define MV_DIRECT 4 // bidirectional mode where the difference equals the MV of the last P/S/I-Frame (mpeg4) |
115 | 115 |
int mv_type; |
116 | 116 |
#define MV_TYPE_16X16 0 /* 1 vector for the whole mb */ |
117 |
-#define MV_TYPE_8X8 1 /* 4 vectors (h263) */ |
|
117 |
+#define MV_TYPE_8X8 1 /* 4 vectors (h263, mpeg4 4MV) */ |
|
118 | 118 |
#define MV_TYPE_16X8 2 /* 2 vectors, one per 16x8 block */ |
119 | 119 |
#define MV_TYPE_FIELD 3 /* 2 vectors, one per field */ |
120 | 120 |
#define MV_TYPE_DMV 4 /* 2 vectors, special mpeg2 Dual Prime Vectors */ |
... | ... |
@@ -126,6 +130,8 @@ typedef struct MpegEncContext { |
126 | 126 |
int mv[2][4][2]; |
127 | 127 |
int field_select[2][2]; |
128 | 128 |
int last_mv[2][2][2]; |
129 |
+ UINT16 (*mv_penalty)[MAX_MV*2+1]; /* amount of bits needed to encode a MV, used for ME */ |
|
130 |
+ UINT8 *fcode_tab; /* smallest fcode needed for each MV */ |
|
129 | 131 |
|
130 | 132 |
int has_b_frames; |
131 | 133 |
int no_rounding; /* apply no rounding to motion estimation (MPEG4) */ |
... | ... |
@@ -350,7 +356,7 @@ INT16 *h263_pred_motion(MpegEncContext * s, int block, |
350 | 350 |
void mpeg4_pred_ac(MpegEncContext * s, INT16 *block, int n, |
351 | 351 |
int dir); |
352 | 352 |
void mpeg4_encode_picture_header(MpegEncContext *s, int picture_number); |
353 |
-void h263_encode_init_vlc(MpegEncContext *s); |
|
353 |
+void h263_encode_init(MpegEncContext *s); |
|
354 | 354 |
|
355 | 355 |
void h263_decode_init_vlc(MpegEncContext *s); |
356 | 356 |
int h263_decode_picture_header(MpegEncContext *s); |