summaryrefslogtreecommitdiff
path: root/libavcodec/mpegvideo.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2002-03-28 04:25:35 +0000
committerMichael Niedermayer <michaelni@gmx.at>2002-03-28 04:25:35 +0000
commitcf8039b2cf590416a6402b31b444b25e593d5d62 (patch)
treebeaca28cae0a5a219b5f01bee79d620ddef29ed8 /libavcodec/mpegvideo.c
parentba6802debf8167f8b9259e83f820dfb53c15a227 (diff)
mpeg4 4MV encoding
Originally committed as revision 363 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/mpegvideo.c')
-rw-r--r--libavcodec/mpegvideo.c198
1 files changed, 161 insertions, 37 deletions
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index c06f51e8af..1c8bcbdfa6 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -15,6 +15,8 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * 4MV & hq encoding stuff by Michael Niedermayer <michaelni@gmx.at>
*/
#include <stdlib.h>
#include <stdio.h>
@@ -362,6 +364,11 @@ int MPV_encode_init(AVCodecContext *avctx)
default:
return -1;
}
+
+ if((s->flags&CODEC_FLAG_4MV) && !(s->flags&CODEC_FLAG_HQ)){
+ printf("4MV is currently only supported in HQ mode\n");
+ return -1;
+ }
{ /* set up some save defaults, some codecs might override them later */
static int done=0;
@@ -815,7 +822,7 @@ static inline void MPV_motion(MpegEncContext *s,
dxy = ((motion_y & 1) << 1) | (motion_x & 1);
src_x = mb_x * 16 + (motion_x >> 1) + (i & 1) * 8;
- src_y = mb_y * 16 + (motion_y >> 1) + ((i >> 1) & 1) * 8;
+ src_y = mb_y * 16 + (motion_y >> 1) + (i >>1) * 8;
/* WARNING: do no forget half pels */
src_x = clip(src_x, -16, s->width);
@@ -1111,38 +1118,92 @@ static void encode_mb(MpegEncContext *s)
/* subtract previous frame if non intra */
if (!s->mb_intra) {
int dxy, offset, mx, my;
-
- dxy = ((motion_y & 1) << 1) | (motion_x & 1);
- ptr = s->last_picture[0] +
- ((mb_y * 16 + (motion_y >> 1)) * s->linesize) +
- (mb_x * 16 + (motion_x >> 1));
-
- sub_pixels_2(s->block[0], ptr, s->linesize, dxy);
- sub_pixels_2(s->block[1], ptr + 8, s->linesize, dxy);
- sub_pixels_2(s->block[2], ptr + s->linesize * 8, s->linesize, dxy);
- sub_pixels_2(s->block[3], ptr + 8 + s->linesize * 8, s->linesize ,dxy);
-
- if (s->out_format == FMT_H263) {
- /* special rounding for h263 */
- dxy = 0;
- if ((motion_x & 3) != 0)
- dxy |= 1;
- if ((motion_y & 3) != 0)
- dxy |= 2;
- mx = motion_x >> 2;
- my = motion_y >> 2;
- } else {
- mx = motion_x / 2;
- my = motion_y / 2;
+
+ if(s->mv_type==MV_TYPE_16X16){
+ dxy = ((motion_y & 1) << 1) | (motion_x & 1);
+ ptr = s->last_picture[0] +
+ ((mb_y * 16 + (motion_y >> 1)) * s->linesize) +
+ (mb_x * 16 + (motion_x >> 1));
+
+ sub_pixels_2(s->block[0], ptr, s->linesize, dxy);
+ sub_pixels_2(s->block[1], ptr + 8, s->linesize, dxy);
+ sub_pixels_2(s->block[2], ptr + s->linesize * 8, s->linesize, dxy);
+ sub_pixels_2(s->block[3], ptr + 8 + s->linesize * 8, s->linesize ,dxy);
+
+ if (s->out_format == FMT_H263) {
+ /* special rounding for h263 */
+ dxy = 0;
+ if ((motion_x & 3) != 0)
+ dxy |= 1;
+ if ((motion_y & 3) != 0)
+ dxy |= 2;
+ mx = motion_x >> 2;
+ my = motion_y >> 2;
+ } else {
+ mx = motion_x / 2;
+ my = motion_y / 2;
+ dxy = ((my & 1) << 1) | (mx & 1);
+ mx >>= 1;
+ my >>= 1;
+ }
+ offset = ((mb_y * 8 + my) * (s->linesize >> 1)) + (mb_x * 8 + mx);
+ ptr = s->last_picture[1] + offset;
+ sub_pixels_2(s->block[4], ptr, s->linesize >> 1, dxy);
+ ptr = s->last_picture[2] + offset;
+ sub_pixels_2(s->block[5], ptr, s->linesize >> 1, dxy);
+ }else{
+ int src_x, src_y;
+
+ for(i=0;i<4;i++) {
+ int motion_x = s->mv[0][i][0];
+ int motion_y = s->mv[0][i][1];
+
+ dxy = ((motion_y & 1) << 1) | (motion_x & 1);
+ src_x = mb_x * 16 + (motion_x >> 1) + (i & 1) * 8;
+ src_y = mb_y * 16 + (motion_y >> 1) + (i >>1) * 8;
+
+ ptr = s->last_picture[0] + (src_y * s->linesize) + (src_x);
+ sub_pixels_2(s->block[i], ptr, s->linesize, dxy);
+ }
+ /* In case of 8X8, we construct a single chroma motion vector
+ with a special rounding */
+ mx = 0;
+ my = 0;
+ for(i=0;i<4;i++) {
+ mx += s->mv[0][i][0];
+ my += s->mv[0][i][1];
+ }
+ if (mx >= 0)
+ mx = (h263_chroma_roundtab[mx & 0xf] + ((mx >> 3) & ~1));
+ else {
+ mx = -mx;
+ mx = -(h263_chroma_roundtab[mx & 0xf] + ((mx >> 3) & ~1));
+ }
+ if (my >= 0)
+ my = (h263_chroma_roundtab[my & 0xf] + ((my >> 3) & ~1));
+ else {
+ my = -my;
+ my = -(h263_chroma_roundtab[my & 0xf] + ((my >> 3) & ~1));
+ }
dxy = ((my & 1) << 1) | (mx & 1);
mx >>= 1;
my >>= 1;
+
+ src_x = mb_x * 8 + mx;
+ src_y = mb_y * 8 + my;
+ src_x = clip(src_x, -8, s->width/2);
+ if (src_x == s->width/2)
+ dxy &= ~1;
+ src_y = clip(src_y, -8, s->height/2);
+ if (src_y == s->height/2)
+ dxy &= ~2;
+
+ offset = (src_y * (s->linesize >> 1)) + src_x;
+ ptr = s->last_picture[1] + offset;
+ sub_pixels_2(s->block[4], ptr, s->linesize >> 1, dxy);
+ ptr = s->last_picture[2] + offset;
+ sub_pixels_2(s->block[5], ptr, s->linesize >> 1, dxy);
}
- offset = ((mb_y * 8 + my) * (s->linesize >> 1)) + (mb_x * 8 + mx);
- ptr = s->last_picture[1] + offset;
- sub_pixels_2(s->block[4], ptr, s->linesize >> 1, dxy);
- ptr = s->last_picture[2] + offset;
- sub_pixels_2(s->block[5], ptr, s->linesize >> 1, dxy);
}
#if 0
@@ -1269,7 +1330,7 @@ static void encode_picture(MpegEncContext *s, int picture_number)
for(i=0; i<8; i++) mv_num[i]=0;
for(i=0; i<s->mb_num; i++){
- if(s->mb_type[i] & (MB_TYPE_INTER|MB_TYPE_INTER4V)){
+ if(s->mb_type[i] & MB_TYPE_INTER){
mv_num[ fcode_tab[s->mv_table[0][i] + MAX_MV] ]++;
mv_num[ fcode_tab[s->mv_table[1][i] + MAX_MV] ]++;
//printf("%d %d %d\n", s->mv_table[0][i], fcode_tab[s->mv_table[0][i] + MAX_MV], i);
@@ -1293,10 +1354,11 @@ static void encode_picture(MpegEncContext *s, int picture_number)
//printf("f_code %d ///\n", s->f_code);
/* convert MBs with too long MVs to I-Blocks */
if(s->pict_type==P_TYPE){
- int i;
+ int i, x, y;
const int f_code= s->f_code;
UINT8 * fcode_tab= s->fcode_tab;
-
+//FIXME try to clip instead of intra izing ;)
+ /* clip / convert to intra 16x16 type MVs */
for(i=0; i<s->mb_num; i++){
if(s->mb_type[i]&MB_TYPE_INTER){
if( fcode_tab[s->mv_table[0][i] + MAX_MV] > f_code
@@ -1309,8 +1371,36 @@ static void encode_picture(MpegEncContext *s, int picture_number)
s->mv_table[1][i] = 0;
}
}
- if(s->mb_type[i]&MB_TYPE_INTER4V){
- //FIXME
+ }
+
+ if(s->flags&CODEC_FLAG_4MV){
+ 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;
+ i= y*s->mb_width;
+
+ 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++;
+ }
+ }
}
}
}
@@ -1420,11 +1510,11 @@ static void encode_picture(MpegEncContext *s, int picture_number)
s->block_index[4]++;
s->block_index[5]++;
- s->mv_type = MV_TYPE_16X16;
s->mv_dir = MV_DIR_FORWARD;
if(mb_type & (mb_type-1)){ // more than 1 MB type possible
pb= s->pb;
if(mb_type&MB_TYPE_INTER){
+ s->mv_type = MV_TYPE_16X16;
s->mb_intra= 0;
s->mv[0][0][0] = s->mv_table[0][mb_y * s->mb_width + mb_x];
s->mv[0][0][1] = s->mv_table[1][mb_y * s->mb_width + mb_x];
@@ -1439,6 +1529,7 @@ static void encode_picture(MpegEncContext *s, int picture_number)
best_s.mv[0][0][0]= s->mv[0][0][0];
best_s.mv[0][0][1]= s->mv[0][0][1];
best_s.mb_intra= 0;
+ best_s.mv_type = MV_TYPE_16X16;
best_s.pb=s->pb;
best_s.block= s->block;
best=1;
@@ -1446,7 +1537,36 @@ static void encode_picture(MpegEncContext *s, int picture_number)
best_s.block_last_index[i]= s->block_last_index[i];
}
}
+ if(mb_type&MB_TYPE_INTER4V){
+ s->mv_type = MV_TYPE_8X8;
+ s->mb_intra= 0;
+ for(i=0; i<4; i++){
+ s->mv[0][i][0] = s->motion_val[s->block_index[i]][0];
+ s->mv[0][i][1] = s->motion_val[s->block_index[i]][1];
+ }
+ init_put_bits(&s->pb, bit_buf[2], 3000, NULL, NULL);
+ s->block= s->inter4v_block;
+
+ encode_mb(s);
+ d= get_bit_count(&s->pb);
+ if(d<dmin){
+ flush_put_bits(&s->pb);
+ dmin=d;
+ for(i=0; i<4; i++){
+ best_s.mv[0][i][0] = s->mv[0][i][0];
+ best_s.mv[0][i][1] = s->mv[0][i][1];
+ }
+ best_s.mb_intra= 0;
+ best_s.mv_type = MV_TYPE_8X8;
+ best_s.pb=s->pb;
+ best_s.block= s->block;
+ best=2;
+ for(i=0; i<6; i++)
+ best_s.block_last_index[i]= s->block_last_index[i];
+ }
+ }
if(mb_type&MB_TYPE_INTRA){
+ s->mv_type = MV_TYPE_16X16;
s->mb_intra= 1;
s->mv[0][0][0] = 0;
s->mv[0][0][1] = 0;
@@ -1461,6 +1581,7 @@ static void encode_picture(MpegEncContext *s, int picture_number)
best_s.mv[0][0][0]= 0;
best_s.mv[0][0][1]= 0;
best_s.mb_intra= 1;
+ best_s.mv_type = MV_TYPE_16X16;
best_s.pb=s->pb;
best_s.block= s->block;
for(i=0; i<6; i++)
@@ -1470,9 +1591,12 @@ static void encode_picture(MpegEncContext *s, int picture_number)
/* force cleaning of ac/dc if needed ... */
s->mbintra_table[mb_x + mb_y*s->mb_width]=1;
}
- s->mv[0][0][0]= best_s.mv[0][0][0];
- s->mv[0][0][1]= best_s.mv[0][0][1];
+ for(i=0; i<4; i++){
+ s->mv[0][i][0] = best_s.mv[0][i][0];
+ s->mv[0][i][1] = best_s.mv[0][i][1];
+ }
s->mb_intra= best_s.mb_intra;
+ s->mv_type= best_s.mv_type;
for(i=0; i<6; i++)
s->block_last_index[i]= best_s.block_last_index[i];
copy_bits(&pb, bit_buf[best], dmin);