diff options
author | Ivan Kalvachev <ikalvachev@gmail.com> | 2003-07-26 01:28:49 +0000 |
---|---|---|
committer | Ivan Kalvachev <ikalvachev@gmail.com> | 2003-07-26 01:28:49 +0000 |
commit | 2e7b4c8442fd5a39c9bf78ad71b62acfaa6c2d7c (patch) | |
tree | bd0f902d7d4cc7a5ff4eae4d286bffaef1fa9148 /libavcodec/xvmcvideo.c | |
parent | ff862be5ed2d7d6799ee23e04c5fbee0c1e1f987 (diff) | |
download | ffmpeg-2e7b4c8442fd5a39c9bf78ad71b62acfaa6c2d7c.tar.gz |
initial XvMC support
Originally committed as revision 2085 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/xvmcvideo.c')
-rw-r--r-- | libavcodec/xvmcvideo.c | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/libavcodec/xvmcvideo.c b/libavcodec/xvmcvideo.c new file mode 100644 index 0000000000..d6aaee4541 --- /dev/null +++ b/libavcodec/xvmcvideo.c @@ -0,0 +1,267 @@ +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <limits.h> + +//X11 include +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvlib.h> +#include <X11/extensions/XvMClib.h> + +#include "xvmc_render.h" + +//avcodec include +#include "avcodec.h" +#include "dsputil.h" +#include "mpegvideo.h" + +#undef NDEBUG +#include <assert.h> + +#ifdef USE_FASTMEMCPY +#include "fastmemcpy.h" +#endif + +#ifdef HAVE_XVMC +//#include "xvmc_debug.h" + +static int calc_cbp(MpegEncContext *s, int blocknum){ +/* compute cbp */ +// for I420 bit_offset=5 +int i,cbp = 0; + for(i=0; i<blocknum; i++) { + if(s->block_last_index[i] >= 0) + cbp |= 1 << (5 - i); + } + return cbp; +} + + + +//these functions should be called on every new field or/and frame +//They should be safe if they are called few times for same field! +int XVMC_field_start(MpegEncContext*s, AVCodecContext *avctx){ +xvmc_render_state_t * render,* last, * next; + + assert(avctx != NULL); + render = (xvmc_render_state_t*)s->current_picture.data[2]; + assert(render != NULL); + + render->picture_structure = s->picture_structure; + render->flags = (s->first_field)? 0: XVMC_SECOND_FIELD; + +//make sure that all data is drawn by XVMC_end_frame + assert(render->filled_mv_blocks_num==0); + + render->p_future_surface = NULL; + render->p_past_surface = NULL; + + switch(s->pict_type){ + case I_TYPE: + return 0;// no prediction from other frames + case B_TYPE: + next = (xvmc_render_state_t*)s->next_picture.data[2]; + assert(next!=NULL); + assert(next->state & MP_XVMC_STATE_PREDICTION); + render->p_future_surface = next->p_surface; + //no return here, going to set forward prediction + case P_TYPE: + last = (xvmc_render_state_t*)s->last_picture.data[2]; + if(last == NULL)// && !s->first_field) + last = render;//predict second field from the first + assert(last->state & MP_XVMC_STATE_PREDICTION); + render->p_past_surface = last->p_surface; + return 0; + } + +return -1; +} + +void XVMC_field_end(MpegEncContext *s){ +xvmc_render_state_t * render; + render = (xvmc_render_state_t*)s->current_picture.data[2]; + assert(render != NULL); + + if(render->filled_mv_blocks_num > 0){ +// printf("xvmcvideo.c: rendering %d left blocks after last slice!!!\n",render->filled_mv_blocks_num ); + ff_draw_horiz_band(s,0,0); + } +} + +void XVMC_decode_mb(MpegEncContext *s, DCTELEM block[6][64]){ +XvMCMacroBlock * mv_block; +xvmc_render_state_t * render; +int i,cbp,blocks_per_mb; + +const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; + + + if(s->encoding){ + fprintf(stderr,"XVMC doesn't support encoding!!!\n"); + assert(0); + return; + } + + //from MPV_decode_mb(), + /* update DC predictors for P macroblocks */ + if (!s->mb_intra) { + s->last_dc[0] = + s->last_dc[1] = + s->last_dc[2] = 128 << s->intra_dc_precision; + } + + //MC doesn't skip blocks + s->mb_skiped = 0; + + + // do I need to export quant when I could not perform postprocessing? + // anyway, it doesn't hurrt + s->current_picture.qscale_table[mb_xy] = s->qscale; + +//START OF XVMC specific code + render = (xvmc_render_state_t*)s->current_picture.data[2]; + assert(render!=NULL); + assert(render->magic==MP_XVMC_RENDER_MAGIC); + assert(render->mv_blocks); + //take the next free macroblock + mv_block = &render->mv_blocks[render->start_mv_blocks_num + + render->filled_mv_blocks_num ]; + +// memset(mv_block,0,sizeof(XvMCMacroBlock)); + + mv_block->x = s->mb_x; + mv_block->y = s->mb_y; + mv_block->dct_type = s->interlaced_dct;//XVMC_DCT_TYPE_FRAME/FIELD; +// mv_block->motion_type = 0; //zero to silense warnings + if(s->mb_intra){ + mv_block->macroblock_type = XVMC_MB_TYPE_INTRA;//no MC, all done + }else{ + mv_block->macroblock_type = XVMC_MB_TYPE_PATTERN; + + if(s->mv_dir & MV_DIR_FORWARD){ + mv_block->macroblock_type|= XVMC_MB_TYPE_MOTION_FORWARD; + //pmv[n][dir][xy]=mv[dir][n][xy] + mv_block->PMV[0][0][0] = s->mv[0][0][0]; + mv_block->PMV[0][0][1] = s->mv[0][0][1]; + mv_block->PMV[1][0][0] = s->mv[0][1][0]; + mv_block->PMV[1][0][1] = s->mv[0][1][1]; + } + if(s->mv_dir & MV_DIR_BACKWARD){ + mv_block->macroblock_type|=XVMC_MB_TYPE_MOTION_BACKWARD; + mv_block->PMV[0][1][0] = s->mv[1][0][0]; + mv_block->PMV[0][1][1] = s->mv[1][0][1]; + mv_block->PMV[1][1][0] = s->mv[1][1][0]; + mv_block->PMV[1][1][1] = s->mv[1][1][1]; + } + + switch(s->mv_type){ + case MV_TYPE_16X16: + mv_block->motion_type = XVMC_PREDICTION_FRAME; + break; + case MV_TYPE_16X8: + mv_block->motion_type = XVMC_PREDICTION_16x8; + break; + case MV_TYPE_FIELD: + mv_block->motion_type = XVMC_PREDICTION_FIELD; + if(s->picture_structure == PICT_FRAME){ + mv_block->PMV[0][0][1]<<=1; + mv_block->PMV[1][0][1]<<=1; + mv_block->PMV[0][1][1]<<=1; + mv_block->PMV[1][1][1]<<=1; + } + break; + case MV_TYPE_DMV: + mv_block->motion_type = XVMC_PREDICTION_DUAL_PRIME; + if(s->picture_structure == PICT_FRAME){ + + mv_block->PMV[0][0][0] = s->mv[0][0][0];//top from top + mv_block->PMV[0][0][1] = s->mv[0][0][1]<<1; + + mv_block->PMV[0][1][0] = s->mv[0][0][0];//bottom from bottom + mv_block->PMV[0][1][1] = s->mv[0][0][1]<<1; + + mv_block->PMV[1][0][0] = s->mv[0][2][0];//dmv00, top from bottom + mv_block->PMV[1][0][1] = s->mv[0][2][1]<<1;//dmv01 + + mv_block->PMV[1][1][0] = s->mv[0][3][0];//dmv10, bottom from top + mv_block->PMV[1][1][1] = s->mv[0][3][1]<<1;//dmv11 + + }else{ + mv_block->PMV[0][1][0] = s->mv[0][2][0];//dmv00 + mv_block->PMV[0][1][1] = s->mv[0][2][1];//dmv01 + } + break; + default: + assert(0); + } + + mv_block->motion_vertical_field_select = 0; + +//set correct field referenses + if(s->mv_type == MV_TYPE_FIELD || s->mv_type == MV_TYPE_16X8){ + if( s->field_select[0][0] ) mv_block->motion_vertical_field_select|=1; + if( s->field_select[1][0] ) mv_block->motion_vertical_field_select|=2; + if( s->field_select[0][1] ) mv_block->motion_vertical_field_select|=4; + if( s->field_select[1][1] ) mv_block->motion_vertical_field_select|=8; + } + }//!intra +//time to handle data blocks; + mv_block->index = render->next_free_data_block_num; + blocks_per_mb = 6; +/* + switch( s->chroma_format){ + case CHROMA_422: + blocks_per_mb = 8; + break; + case CHROMA_444: + blocks_per_mb = 12; + break; + } +*/ + if(s->flags & CODEC_FLAG_GRAY){ + if(s->mb_intra){//intra frames are alwasy full chroma block + memset(block[4],0,sizeof(short)*8*8);//so we need to clear them + memset(block[5],0,sizeof(short)*8*8); + if(!render->unsigned_intra) + block[4][0] = block[5][0] = 1<<10; + } + else + blocks_per_mb = 4;//Luminance blocks only + }; + cbp = calc_cbp(s,blocks_per_mb); + mv_block->coded_block_pattern = cbp; + if(cbp == 0) + mv_block->macroblock_type &= ~XVMC_MB_TYPE_PATTERN; + + for(i=0; i<blocks_per_mb; i++){ + if(s->block_last_index[i] >= 0){ + // i do not have unsigned_intra MOCO to test, hope it is OK + if( (s->mb_intra) && ( render->idct || (!render->idct && !render->unsigned_intra)) ) + block[i][0]-=1<<10; + if(!render->idct){ + s->dsp.idct(block[i]); + //!!TODO!clip!!! + } +//TODO:avoid block copy by modifying s->block pointer + memcpy(&render->data_blocks[(render->next_free_data_block_num++)*64], + block[i],sizeof(short)*8*8); + } + } + render->filled_mv_blocks_num++; + + assert(render->filled_mv_blocks_num <= render->total_number_of_mv_blocks); + assert(render->next_free_data_block_num <= render->total_number_of_data_blocks); + + + if(render->filled_mv_blocks_num >= render->total_number_of_mv_blocks) + ff_draw_horiz_band(s,0,0); + +// DumpRenderInfo(render); +// DumpMBlockInfo(mv_block); + +} + +#endif |