📄 mpegvideo.c
字号:
} sx= motion_x & s_mask; sy= motion_y & s_mask; src_x += motion_x >> (lowres+1); src_y += motion_y >> (lowres+1); src += src_y * stride + src_x; if( (unsigned)src_x > h_edge_pos - (!!sx) - w || (unsigned)src_y >(v_edge_pos >> field_based) - (!!sy) - h){ ff_emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, w+1, (h+1)<<field_based, src_x, src_y<<field_based, h_edge_pos, v_edge_pos); src= s->edge_emu_buffer; emu=1; } sx <<= 2 - lowres; sy <<= 2 - lowres; if(field_select) src += s->linesize; pix_op[lowres](dest, src, stride, h, sx, sy); return emu;}/* apply one mpeg motion vector to the three components */static av_always_inline void mpeg_motion_lowres(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int field_based, int bottom_field, int field_select, uint8_t **ref_picture, h264_chroma_mc_func *pix_op, int motion_x, int motion_y, int h){ uint8_t *ptr_y, *ptr_cb, *ptr_cr; int mx, my, src_x, src_y, uvsrc_x, uvsrc_y, uvlinesize, linesize, sx, sy, uvsx, uvsy; const int lowres= s->avctx->lowres; const int block_s= 8>>lowres; const int s_mask= (2<<lowres)-1; const int h_edge_pos = s->h_edge_pos >> lowres; const int v_edge_pos = s->v_edge_pos >> lowres; linesize = s->current_picture.linesize[0] << field_based; uvlinesize = s->current_picture.linesize[1] << field_based; if(s->quarter_sample){ //FIXME obviously not perfect but qpel wont work in lowres anyway motion_x/=2; motion_y/=2; } if(field_based){ motion_y += (bottom_field - field_select)*((1<<lowres)-1); } sx= motion_x & s_mask; sy= motion_y & s_mask; src_x = s->mb_x*2*block_s + (motion_x >> (lowres+1)); src_y =(s->mb_y*2*block_s>>field_based) + (motion_y >> (lowres+1)); if (s->out_format == FMT_H263) { uvsx = ((motion_x>>1) & s_mask) | (sx&1); uvsy = ((motion_y>>1) & s_mask) | (sy&1); uvsrc_x = src_x>>1; uvsrc_y = src_y>>1; }else if(s->out_format == FMT_H261){//even chroma mv's are full pel in H261 mx = motion_x / 4; my = motion_y / 4; uvsx = (2*mx) & s_mask; uvsy = (2*my) & s_mask; uvsrc_x = s->mb_x*block_s + (mx >> lowres); uvsrc_y = s->mb_y*block_s + (my >> lowres); } else { mx = motion_x / 2; my = motion_y / 2; uvsx = mx & s_mask; uvsy = my & s_mask; uvsrc_x = s->mb_x*block_s + (mx >> (lowres+1)); uvsrc_y =(s->mb_y*block_s>>field_based) + (my >> (lowres+1)); } ptr_y = ref_picture[0] + src_y * linesize + src_x; ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x; ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x; if( (unsigned)src_x > h_edge_pos - (!!sx) - 2*block_s || (unsigned)src_y >(v_edge_pos >> field_based) - (!!sy) - h){ ff_emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, 17, 17+field_based, src_x, src_y<<field_based, h_edge_pos, v_edge_pos); ptr_y = s->edge_emu_buffer; if(!ENABLE_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ uint8_t *uvbuf= s->edge_emu_buffer+18*s->linesize; ff_emulated_edge_mc(uvbuf , ptr_cb, s->uvlinesize, 9, 9+field_based, uvsrc_x, uvsrc_y<<field_based, h_edge_pos>>1, v_edge_pos>>1); ff_emulated_edge_mc(uvbuf+16, ptr_cr, s->uvlinesize, 9, 9+field_based, uvsrc_x, uvsrc_y<<field_based, h_edge_pos>>1, v_edge_pos>>1); ptr_cb= uvbuf; ptr_cr= uvbuf+16; } } if(bottom_field){ //FIXME use this for field pix too instead of the obnoxious hack which changes picture.data dest_y += s->linesize; dest_cb+= s->uvlinesize; dest_cr+= s->uvlinesize; } if(field_select){ ptr_y += s->linesize; ptr_cb+= s->uvlinesize; ptr_cr+= s->uvlinesize; } sx <<= 2 - lowres; sy <<= 2 - lowres; pix_op[lowres-1](dest_y, ptr_y, linesize, h, sx, sy); if(!ENABLE_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ uvsx <<= 2 - lowres; uvsy <<= 2 - lowres; pix_op[lowres](dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy); pix_op[lowres](dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy); } //FIXME h261 lowres loop filter}static inline void chroma_4mv_motion_lowres(MpegEncContext *s, uint8_t *dest_cb, uint8_t *dest_cr, uint8_t **ref_picture, h264_chroma_mc_func *pix_op, int mx, int my){ const int lowres= s->avctx->lowres; const int block_s= 8>>lowres; const int s_mask= (2<<lowres)-1; const int h_edge_pos = s->h_edge_pos >> (lowres+1); const int v_edge_pos = s->v_edge_pos >> (lowres+1); int emu=0, src_x, src_y, offset, sx, sy; uint8_t *ptr; if(s->quarter_sample){ mx/=2; my/=2; } /* In case of 8X8, we construct a single chroma motion vector with a special rounding */ mx= ff_h263_round_chroma(mx); my= ff_h263_round_chroma(my); sx= mx & s_mask; sy= my & s_mask; src_x = s->mb_x*block_s + (mx >> (lowres+1)); src_y = s->mb_y*block_s + (my >> (lowres+1)); offset = src_y * s->uvlinesize + src_x; ptr = ref_picture[1] + offset; if(s->flags&CODEC_FLAG_EMU_EDGE){ if( (unsigned)src_x > h_edge_pos - (!!sx) - block_s || (unsigned)src_y > v_edge_pos - (!!sy) - block_s){ ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, src_x, src_y, h_edge_pos, v_edge_pos); ptr= s->edge_emu_buffer; emu=1; } } sx <<= 2 - lowres; sy <<= 2 - lowres; pix_op[lowres](dest_cb, ptr, s->uvlinesize, block_s, sx, sy); ptr = ref_picture[2] + offset; if(emu){ ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, src_x, src_y, h_edge_pos, v_edge_pos); ptr= s->edge_emu_buffer; } pix_op[lowres](dest_cr, ptr, s->uvlinesize, block_s, sx, sy);}/** * motion compensation of a single macroblock * @param s context * @param dest_y luma destination pointer * @param dest_cb chroma cb/u destination pointer * @param dest_cr chroma cr/v destination pointer * @param dir direction (0->forward, 1->backward) * @param ref_picture array[3] of pointers to the 3 planes of the reference picture * @param pic_op halfpel motion compensation function (average or put normally) * the motion vectors are taken from s->mv and the MV type from s->mv_type */static inline void MPV_motion_lowres(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int dir, uint8_t **ref_picture, h264_chroma_mc_func *pix_op){ int mx, my; int mb_x, mb_y, i; const int lowres= s->avctx->lowres; const int block_s= 8>>lowres; mb_x = s->mb_x; mb_y = s->mb_y; switch(s->mv_type) { case MV_TYPE_16X16: mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, 0, 0, 0, ref_picture, pix_op, s->mv[dir][0][0], s->mv[dir][0][1], 2*block_s); break; case MV_TYPE_8X8: mx = 0; my = 0; for(i=0;i<4;i++) { hpel_motion_lowres(s, dest_y + ((i & 1) + (i >> 1) * s->linesize)*block_s, ref_picture[0], 0, 0, (2*mb_x + (i & 1))*block_s, (2*mb_y + (i >>1))*block_s, s->width, s->height, s->linesize, s->h_edge_pos >> lowres, s->v_edge_pos >> lowres, block_s, block_s, pix_op, s->mv[dir][i][0], s->mv[dir][i][1]); mx += s->mv[dir][i][0]; my += s->mv[dir][i][1]; } if(!ENABLE_GRAY || !(s->flags&CODEC_FLAG_GRAY)) chroma_4mv_motion_lowres(s, dest_cb, dest_cr, ref_picture, pix_op, mx, my); break; case MV_TYPE_FIELD: if (s->picture_structure == PICT_FRAME) { /* top field */ mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, 1, 0, s->field_select[dir][0], ref_picture, pix_op, s->mv[dir][0][0], s->mv[dir][0][1], block_s); /* bottom field */ mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, 1, 1, s->field_select[dir][1], ref_picture, pix_op, s->mv[dir][1][0], s->mv[dir][1][1], block_s); } else { if(s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != FF_B_TYPE && !s->first_field){ ref_picture= s->current_picture_ptr->data; } mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, 0, 0, s->field_select[dir][0], ref_picture, pix_op, s->mv[dir][0][0], s->mv[dir][0][1], 2*block_s); } break; case MV_TYPE_16X8: for(i=0; i<2; i++){ uint8_t ** ref2picture; if(s->picture_structure == s->field_select[dir][i] + 1 || s->pict_type == FF_B_TYPE || s->first_field){ ref2picture= ref_picture; }else{ ref2picture= s->current_picture_ptr->data; } mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, 0, 0, s->field_select[dir][i], ref2picture, pix_op, s->mv[dir][i][0], s->mv[dir][i][1] + 2*block_s*i, block_s); dest_y += 2*block_s*s->linesize; dest_cb+= (2*block_s>>s->chroma_y_shift)*s->uvlinesize; dest_cr+= (2*block_s>>s->chroma_y_shift)*s->uvlinesize; } break; case MV_TYPE_DMV: if(s->picture_structure == PICT_FRAME){ for(i=0; i<2; i++){ int j; for(j=0; j<2; j++){ mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, 1, j, j^i, ref_picture, pix_op, s->mv[dir][2*i + j][0], s->mv[dir][2*i + j][1], block_s); } pix_op = s->dsp.avg_h264_chroma_pixels_tab; } }else{ for(i=0; i<2; i++){ mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, 0, 0, s->picture_structure != i+1, ref_picture, pix_op, s->mv[dir][2*i][0],s->mv[dir][2*i][1],2*block_s); // after put we make avg of the same block pix_op = s->dsp.avg_h264_chroma_pixels_tab; //opposite parity is always in the same frame if this is second field if(!s->first_field){ ref_picture = s->current_picture_ptr->data; } } } break; default: assert(0); }}/* put block[] to dest[] */static inline void put_dct(MpegEncContext *s, DCTELEM *block, int i, uint8_t *dest, int line_size, int qscale){ s->dct_unquantize_intra(s, block, i, qscale); s->dsp.idct_put (dest, line_size, block);}/* add block[] to dest[] */static inline void add_dct(MpegEncContext *s, DCTELEM *block, int i, uint8_t *dest, int line_size){ if (s->block_last_index[i] >= 0) { s->dsp.idct_add (dest, line_size, block); }}static inline void add_dequant_dct(MpegEncContext *s, DCTELEM *block, int i, uint8_t *dest, int line_size, int qscale){ if (s->block_last_index[i] >= 0) { s->dct_unquantize_inter(s, block, i, qscale); s->dsp.idct_add (dest, line_size, block); }}/** * cleans dc, ac, coded_block for the current non intra MB */void ff_clean_intra_table_entries(MpegEncContext *s){ int wrap = s->b8_stride; int xy = s->block_index[0]; s->dc_val[0][xy ] = s->dc_val[0][xy + 1 ] = s->dc_val[0][xy + wrap] = s->dc_val[0][xy + 1 + wrap] = 1024; /* ac pred */ memset(s->ac_val[0][xy ], 0, 32 * sizeof(int16_t)); memset
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -