00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <limits.h>
00023
00024
00025 #include "avcodec.h"
00026 #include "dsputil.h"
00027 #include "mpegvideo.h"
00028
00029 #undef NDEBUG
00030 #include <assert.h>
00031 #include <stdio.h>
00032
00033 #ifdef HAVE_XVMC
00034
00035
00036
00037
00038
00039 #include "xvmc_render.h"
00040 #define DEBUG_PICTURE_STRUCTURE_CHANGES
00041
00042 #ifndef FALSE
00043 #define FALSE 0
00044 #endif
00045 #ifndef TRUE
00046 #define TRUE 1
00047 #endif
00048
00049 #define BLKS_SIZE (sizeof(short)*64)
00050
00051
00052 static const int chromaBits[4] = { 6, 6, 4+1<<CHROMA_422, 4+1<<CHROMA_444 };
00053 static const int mv_ffmpeg_to_xvmc[8];
00054 static const char* mv_ffmpeg_to_string[8];
00055
00056 static inline xvmc_render_state_t *render_state(const MpegEncContext *s);
00057 static inline int calc_cbp(MpegEncContext *s);
00058 static void set_block_pattern(const MpegEncContext *, XvMCMacroBlock *);
00059 static void setup_pmv(MpegEncContext *, XvMCMacroBlock *);
00060 static void setup_pmv_frame(MpegEncContext *, XvMCMacroBlock *);
00061 static void setup_pmv_field(MpegEncContext *, XvMCMacroBlock *);
00062 static inline XvMCMacroBlock *macroblock(const xvmc_render_state_t *,
00063 int x, int y, int dct);
00064 static inline void setup_context(MpegEncContext *s);
00065 static inline void DBG_printPictureStructureChanges(int picture_structure);
00066 static inline void handle_intra_block(const MpegEncContext *, const XvMCMacroBlock *,
00067 xvmc_render_state_t *render);
00068 static inline void handle_p_b_block(const MpegEncContext *, const XvMCMacroBlock *,
00069 xvmc_render_state_t *render);
00070
00071 #include "xvmccommon.c"
00072
00073
00074 void XVMC_init_block(MpegEncContext *s){
00075 xvmc_render_state_t *render = render_state(s);
00076 s->block= (DCTELEM*) (render->data_blocks+(render->next_free_data_block_num)*64);
00077 }
00078
00079 void XVMC_pack_pblocks(MpegEncContext *s, int cbp){
00080 int i,j;
00081 const int mb_block_count = 4+(1<<s->chroma_format);
00082
00083 j=0;
00084 cbp<<= 12-mb_block_count;
00085 for(i=0; i<mb_block_count; i++){
00086 if(cbp & (1<<11)) {
00087 s->pblocks[i] = (short *)(&s->block[(j++)]);
00088 }else{
00089 s->pblocks[i] = NULL;
00090 }
00091 cbp+=cbp;
00092
00093 }
00094 }
00095
00096
00097
00098 int XVMC_field_start(MpegEncContext*s, AVCodecContext *avctx){
00099 xvmc_render_state_t * render,* last, * next;
00100
00101 assert(avctx != NULL);
00102
00103 render = (xvmc_render_state_t*)s->current_picture.data[2];
00104 assert(render != NULL);
00105 if( (render == NULL) || (render->magic != MP_XVMC_RENDER_MAGIC) )
00106 return -1;
00107
00108 render->picture_structure = s->picture_structure;
00109 if (render->picture_structure==PICT_FRAME)
00110 render->flags = XVMC_FRAME_PICTURE;
00111 else if (render->picture_structure==PICT_TOP_FIELD)
00112 render->flags = XVMC_TOP_FIELD;
00113 else if (render->picture_structure==PICT_BOTTOM_FIELD)
00114 render->flags = XVMC_BOTTOM_FIELD;
00115 if (!s->first_field)
00116 render->flags |= XVMC_SECOND_FIELD;
00117
00118
00119 assert(render->filled_mv_blocks_num==0);
00120
00121 render->p_future_surface = NULL;
00122 render->p_past_surface = NULL;
00123
00124 render->pict_type=s->pict_type;
00125 switch(s->pict_type){
00126 case I_TYPE:
00127 return 0;
00128 case B_TYPE:
00129 render->p_past_surface = findPastSurface(s, render);
00130 render->p_future_surface = findFutureSurface(s);
00131 if (!render->p_past_surface)
00132 av_log(s->avctx, AV_LOG_ERROR, "XvMC: Error, decoding "
00133 "B frame and past frame is null!\n");
00134 else if (!render->p_future_surface)
00135 av_log(s->avctx, AV_LOG_ERROR, "XvMC: Error, decoding "
00136 "B frame and future frame is null!\n");
00137 else return 0;
00138 return 0;
00139 case P_TYPE:
00140 render->p_past_surface = findPastSurface(s, render);
00141 if (!render->p_past_surface)
00142 av_log(s->avctx, AV_LOG_ERROR, "XvMC: error, decoding "
00143 "P frame and past frame is null!\n");
00144 else return 0;
00145 return 0;
00146 }
00147
00148 return -1;
00149 }
00150
00151 void XVMC_field_end(MpegEncContext *s)
00152 {
00153 if (render_state(s)->filled_mv_blocks_num > 0)
00154 ff_draw_horiz_band(s,0,0);
00155 }
00156
00157 void XVMC_decode_mb(MpegEncContext *s)
00158 {
00159 xvmc_render_state_t * render;
00160 XvMCMacroBlock * mv_block;
00161
00162 setup_context(s);
00163
00164 render = render_state(s);
00165 mv_block = macroblock(render, s->mb_x, s->mb_y, s->interlaced_dct);
00166
00167 DBG_printPictureStructureChanges(render->picture_structure);
00168
00169 if (s->mb_intra)
00170 {
00171 mv_block->macroblock_type = XVMC_MB_TYPE_INTRA;
00172 mv_block->motion_type = 0;
00173 handle_intra_block(s, mv_block, render);
00174 }
00175 else
00176 {
00177 if (PICT_FRAME==render->picture_structure)
00178 setup_pmv_frame(s, mv_block);
00179 else
00180 setup_pmv_field(s, mv_block);
00181 handle_p_b_block(s, mv_block, render);
00182 }
00183 render->filled_mv_blocks_num++;
00184
00185 assert(render->filled_mv_blocks_num <= render->total_number_of_mv_blocks);
00186 assert(render->next_free_data_block_num <= render->total_number_of_data_blocks);
00187
00188
00189 if (render->filled_mv_blocks_num >= render->total_number_of_mv_blocks)
00190 ff_draw_horiz_band(s,0,0);
00191 }
00192
00193
00194
00195 static inline xvmc_render_state_t *render_state(const MpegEncContext *s)
00196 {
00197 xvmc_render_state_t *render = (xvmc_render_state_t*)s->current_picture.data[2];
00198 assert(render!=NULL);
00199 assert(render->magic==MP_XVMC_RENDER_MAGIC);
00200 assert(render->mv_blocks);
00201 return render;
00202 }
00203
00204 static inline int calc_cbp(MpegEncContext *s)
00205 {
00206 int cbp, cbp1;
00207
00208 cbp = (s->block_last_index[0] >= 0) ? (1 << (5)) : 0;
00209 cbp1 = (s->block_last_index[1] >= 0) ? (1 << (4)) : 0;
00210 cbp |= (s->block_last_index[2] >= 0) ? (1 << (3)) : 0;
00211 cbp1 |= (s->block_last_index[3] >= 0) ? (1 << (2)) : 0;
00212 cbp |= cbp1;
00213
00214 if (s->flags & CODEC_FLAG_GRAY)
00215 return cbp;
00216
00217 cbp |= (((s->block_last_index[4] >= 0) ? 1 << (1) : 0) |
00218 ((s->block_last_index[5] >= 0) ? 1 << (0) : 0));
00219
00220 if (s->chroma_format >= 2) {
00221 if (s->chroma_format == 2)
00222 {
00223 cbp |= (((s->block_last_index[4] >= 0) ? 1 << (6+1) : 0) |
00224 ((s->block_last_index[5] >= 0) ? 1 << (6+0) : 0));
00225 }
00226 else
00227 {
00228 cbp |= (s->block_last_index[ 6] >= 0) ? 1 << (6+5) : 0;
00229 cbp1 = (s->block_last_index[ 7] >= 0) ? 1 << (6+3) : 0;
00230 cbp |= (s->block_last_index[ 8] >= 0) ? 1 << (6+4) : 0;
00231 cbp1 |= (s->block_last_index[ 9] >= 0) ? 1 << (6+2) : 0;
00232 cbp |= (s->block_last_index[10] >= 0) ? 1 << (6+1) : 0;
00233 cbp1 |= (s->block_last_index[11] >= 0) ? 1 << (6+0) : 0;
00234 cbp |= cbp1;
00235 }
00236 }
00237 return cbp;
00238 }
00239
00240 static void set_block_pattern(const MpegEncContext *s, XvMCMacroBlock *mv_block)
00241 {
00242 mv_block->coded_block_pattern = calc_cbp(s);
00243 if (!mv_block->coded_block_pattern)
00244 mv_block->macroblock_type &= ~XVMC_MB_TYPE_PATTERN;
00245 }
00246
00247 static inline void setup_context(MpegEncContext *s)
00248 {
00249 if (s->encoding)
00250 {
00251 av_log(s->avctx, AV_LOG_ERROR, "XVMC doesn't support encoding!!!\n");
00252 return;
00253 }
00254
00255
00256 s->current_picture.qscale_table[s->mb_y * s->mb_stride + s->mb_x] = s->qscale;
00257 s->mb_skipped = 0;
00258 }
00259
00260 static inline XvMCMacroBlock *macroblock(const xvmc_render_state_t *render,
00261 int x, int y, int dct)
00262 {
00263
00264 int index = render->start_mv_blocks_num + render->filled_mv_blocks_num;
00265 XvMCMacroBlock *mv_block = &render->mv_blocks[index];
00266
00267 mv_block->x = x;
00268 mv_block->y = y;
00269 mv_block->dct_type = dct;
00270
00271
00272
00273 mv_block->index = render->next_free_data_block_num;
00274 return mv_block;
00275 }
00276
00277 static inline void DBG_printPictureStructureChanges(int picture_structure)
00278 {
00279 #ifdef DEBUG_PICTURE_STRUCTURE_CHANGES
00280 static int oldframe=0xff;
00281 int frame = (PICT_FRAME==picture_structure)? 1 : 0;
00282 if (oldframe != frame)
00283 {
00284 av_log(NULL, AV_LOG_ERROR, "XvMC: picture structure %s\n",
00285 frame ? "FRAME" : "FIELD");
00286 oldframe = frame;
00287 }
00288 #endif
00289 }
00290
00291
00292
00293 static inline void pack_flip_block(const MpegEncContext *s,
00294 xvmc_render_state_t *render,
00295 int blocks_per_mb,
00296 int pack, int flip)
00297 {
00298 int i;
00299 if (pack)
00300 {
00301
00302 if (flip)
00303 {
00304 for (i=0; i<blocks_per_mb; i++)
00305 if (s->block_last_index[i] >= 0)
00306 {
00307 s->pblocks[i][0]-=1<<10;
00308 unsigned int indx = (render->next_free_data_block_num)*64;
00309 memcpy(&render->data_blocks[indx], s->pblocks[i], BLKS_SIZE);
00310 render->next_free_data_block_num++;
00311 }
00312 }
00313 else
00314 {
00315 for (i=0; i<blocks_per_mb; i++)
00316 if (s->block_last_index[i] >= 0)
00317 {
00318 unsigned int indx = (render->next_free_data_block_num)*64;
00319 memcpy(&render->data_blocks[indx], s->pblocks[i], BLKS_SIZE);
00320 render->next_free_data_block_num++;
00321 }
00322 }
00323 }
00324 else
00325 {
00326 int ndbn=0;
00327 if (flip)
00328 {
00329 for (i=0; i<blocks_per_mb; i++)
00330 {
00331 if (s->block_last_index[i] >= 0)
00332 {
00333 s->pblocks[i][0] -= 1<<10;
00334 ndbn++;
00335 }
00336 }
00337 }
00338 else
00339 for (i=0; i<blocks_per_mb; i++)
00340 ndbn += (s->block_last_index[i] >= 0)? 1 : 0;
00341 render->next_free_data_block_num += ndbn;
00342 }
00343 }
00344
00345
00346 static inline void pack_flip_idct_block(const MpegEncContext *s,
00347 xvmc_render_state_t *render,
00348 int blocks_per_mb,
00349 int pack, int flip)
00350 {
00351 int i;
00352
00353 if (flip) {
00354 for (i=0; i<blocks_per_mb; i++)
00355 {
00356 if (s->block_last_index[i] >= 0)
00357 {
00358 s->pblocks[i][0] -= 1<<10;
00359 s->dsp.idct(s->pblocks[i]);
00360 if (pack)
00361 {
00362 unsigned int indx = (render->next_free_data_block_num)*64;
00363 memcpy(&render->data_blocks[indx], s->pblocks[i], BLKS_SIZE);
00364 }
00365 render->next_free_data_block_num++;
00366 }
00367 }
00368 }
00369 else
00370 {
00371 for (i=0; i<blocks_per_mb; i++)
00372 {
00373 if (s->block_last_index[i] >= 0)
00374 {
00375 s->dsp.idct(s->pblocks[i]);
00376 if (pack)
00377 {
00378 unsigned int indx = (render->next_free_data_block_num)*64;
00379 memcpy(&render->data_blocks[indx], s->pblocks[i], BLKS_SIZE);
00380 }
00381 render->next_free_data_block_num++;
00382 }
00383 }
00384 }
00385 }
00386
00387 static inline void clear_chroma(MpegEncContext *s,
00388 int blocks_per_mb,
00389 int flip)
00390 {
00391 int i;
00392
00393 if (flip)
00394 for (i=4; i<blocks_per_mb; i++)
00395 {
00396 memset(s->pblocks[i], 0, BLKS_SIZE);
00397 s->pblocks[i][0] = 1<<10;
00398 }
00399 else
00400 for (i=4; i<blocks_per_mb; i++)
00401 memset(s->pblocks[i], 0, BLKS_SIZE);
00402 }
00403
00404 static inline void handle_intra_block(const MpegEncContext *s,
00405 const XvMCMacroBlock *mv_block,
00406 xvmc_render_state_t *render)
00407 {
00408 const int pack = (1 == s->avctx->xvmc_acceleration);
00409 const int flip = !render->unsigned_intra;
00410 int cb = chromaBits[s->chroma_format];
00411
00412 if (s->flags & CODEC_FLAG_GRAY)
00413 clear_chroma(s, (cb = 6), !flip);
00414
00415 set_block_pattern(s, mv_block);
00416
00417 if (render->idct)
00418 pack_flip_block(s, render, cb, pack, TRUE);
00419 else
00420 pack_flip_idct_block(s, render, cb, pack, flip);
00421 }
00422
00423 static inline void handle_p_b_block(const MpegEncContext *s,
00424 const XvMCMacroBlock *mv_block,
00425 xvmc_render_state_t *render)
00426 {
00427 const int pack = (1 == s->avctx->xvmc_acceleration);
00428 int cb = (s->flags & CODEC_FLAG_GRAY)? 4 : chromaBits[s->chroma_format];
00429
00430 set_block_pattern(s, mv_block);
00431
00432 if (render->idct)
00433 pack_flip_block(s, render, cb, pack, FALSE);
00434 else
00435 pack_flip_idct_block(s, render, cb, pack, FALSE);
00436 }
00437
00438 static void setup_pmv(MpegEncContext *s, XvMCMacroBlock *mv_block)
00439 {
00440 mv_block->macroblock_type = XVMC_MB_TYPE_PATTERN;
00441 mv_block->macroblock_type |=
00442 (s->mv_dir & MV_DIR_FORWARD) ? XVMC_MB_TYPE_MOTION_FORWARD : 0;
00443 mv_block->macroblock_type |=
00444 (s->mv_dir & MV_DIR_BACKWARD) ? XVMC_MB_TYPE_MOTION_BACKWARD : 0;
00445
00446
00447 mv_block->PMV[0][0][0] = s->mv[0][0][0];
00448 mv_block->PMV[0][0][1] = s->mv[0][0][1];
00449 mv_block->PMV[0][1][0] = s->mv[1][0][0];
00450 mv_block->PMV[0][1][1] = s->mv[1][0][1];
00451 mv_block->PMV[1][0][0] = s->mv[0][1][0];
00452 mv_block->PMV[1][0][1] = s->mv[0][1][1];
00453 mv_block->PMV[1][1][0] = s->mv[1][1][0];
00454 mv_block->PMV[1][1][1] = s->mv[1][1][1];
00455 }
00456
00457 static void setup_pmv_frame(MpegEncContext *s,
00458 XvMCMacroBlock *mv_block)
00459 {
00460 assert(s->mv_type>=0 && s->mv_type<=MV_TYPE_DMV);
00461 mv_block->motion_type = mv_ffmpeg_to_xvmc[s->mv_type];
00462
00463 s->last_dc[0] = s->last_dc[1] = s->last_dc[2] =
00464 128 << s->intra_dc_precision;
00465
00466 mv_block->macroblock_type = XVMC_MB_TYPE_PATTERN;
00467 mv_block->macroblock_type |=
00468 (s->mv_dir & MV_DIR_FORWARD) ? XVMC_MB_TYPE_MOTION_FORWARD : 0;
00469 mv_block->macroblock_type |=
00470 (s->mv_dir & MV_DIR_BACKWARD) ? XVMC_MB_TYPE_MOTION_BACKWARD : 0;
00471
00472 if (MV_TYPE_FIELD<=s->mv_type)
00473 {
00474 if (MV_TYPE_FIELD==s->mv_type)
00475 {
00476
00477 int mvfs0 = (s->field_select[0][0]) ? XVMC_SELECT_FIRST_FORWARD : 0;
00478 mv_block->PMV[0][0][0] = s->mv[0][0][0];
00479 mv_block->PMV[0][0][1] = s->mv[0][0][1]<<1;
00480 int mvfs1 = (s->field_select[0][1]) ? XVMC_SELECT_SECOND_FORWARD : 0;
00481 mv_block->PMV[0][1][0] = s->mv[1][0][0];
00482 mv_block->PMV[0][1][1] = s->mv[1][0][1]<<1;
00483 mvfs0 |= (s->field_select[1][0]) ? XVMC_SELECT_FIRST_BACKWARD : 0;
00484 mv_block->PMV[1][0][0] = s->mv[0][1][0];
00485 mv_block->PMV[1][0][1] = s->mv[0][1][1]<<1;
00486 mvfs1 |= (s->field_select[1][1]) ? XVMC_SELECT_SECOND_BACKWARD : 0;
00487 mv_block->PMV[1][1][0] = s->mv[1][1][0];
00488 mv_block->PMV[1][1][1] = s->mv[1][1][1]<<1;
00489 mv_block->motion_vertical_field_select = mvfs0 | mvfs1;
00490 }
00491 else if (MV_TYPE_DMV==s->mv_type)
00492 {
00493 mv_block->PMV[0][0][0] = s->mv[0][0][0];
00494 mv_block->PMV[0][0][1] = s->mv[0][0][1]<<1;
00495 mv_block->PMV[0][1][0] = s->mv[0][0][0];
00496 mv_block->PMV[0][1][1] = s->mv[0][0][1]<<1;
00497 mv_block->PMV[1][0][0] = s->mv[0][2][0];
00498 mv_block->PMV[1][0][1] = s->mv[0][2][1]<<1;
00499 mv_block->PMV[1][1][0] = s->mv[0][3][0];
00500 mv_block->PMV[1][1][1] = s->mv[0][3][1]<<1;
00501 }
00502 else
00503 av_log(s->avctx, AV_LOG_ERROR, "XvMC: Unexpected movement type\n");
00504 }
00505 else
00506 {
00507
00508
00509 setup_pmv(s, mv_block);
00510 }
00511
00512
00513 if (MV_TYPE_16X8 == s->mv_type)
00514 {
00515 av_log(s->avctx, AV_LOG_ERROR,
00516 "XvMC: Field motion vector type with frame picture!\n");
00517 if (s->mv_type == MV_TYPE_16X8)
00518 {
00519 int mvfs0 = (s->field_select[0][0]) ? XVMC_SELECT_FIRST_FORWARD : 0;
00520 int mvfs1 = (s->field_select[0][1]) ? XVMC_SELECT_SECOND_FORWARD : 0;
00521 mvfs0 |= (s->field_select[1][0]) ? XVMC_SELECT_FIRST_BACKWARD : 0;
00522 mvfs1 |= (s->field_select[1][1]) ? XVMC_SELECT_SECOND_BACKWARD : 0;
00523 mv_block->motion_vertical_field_select = mvfs0 | mvfs1;
00524 }
00525 }
00526 if (-1 == mv_block->motion_type)
00527 {
00528 if (MV_TYPE_8X8==s->mv_type)
00529 av_log(s->avctx, AV_LOG_ERROR,
00530 "XvMC: H263/MPEG4 motion vectortype in MPEG2 decoder!\n");
00531 else
00532 av_log(s->avctx, AV_LOG_ERROR,
00533 "XvMC: Unknown motion vector type!\n");
00534 mv_block->motion_type=XVMC_PREDICTION_FRAME;
00535 }
00536 }
00537
00538 static void setup_pmv_field(MpegEncContext *s,
00539 XvMCMacroBlock *mv_block)
00540 {
00541 assert(s->mv_type>=0 && s->mv_type<=MV_TYPE_DMV);
00542 mv_block->motion_type = mv_ffmpeg_to_xvmc[s->mv_type];
00543
00544
00545 s->last_dc[0] = s->last_dc[1] = s->last_dc[2] =
00546 128 << s->intra_dc_precision;
00547 setup_pmv(s, mv_block);
00548
00549 if (MV_TYPE_DMV==s->mv_type)
00550 {
00551
00552
00553 mv_block->PMV[0][1][0] = s->mv[0][2][0];
00554 mv_block->PMV[0][1][1] = s->mv[0][2][1];
00555 }
00556 else
00557 {
00558
00559 if (s->mv_type == MV_TYPE_FIELD || s->mv_type == MV_TYPE_16X8)
00560 {
00561 int mvfs0 = (s->field_select[0][0]) ? XVMC_SELECT_FIRST_FORWARD : 0;
00562 int mvfs1 = (s->field_select[0][1]) ? XVMC_SELECT_SECOND_FORWARD : 0;
00563 mvfs0 |= (s->field_select[1][0]) ? XVMC_SELECT_FIRST_BACKWARD : 0;
00564 mvfs1 |= (s->field_select[1][1]) ? XVMC_SELECT_SECOND_BACKWARD : 0;
00565 mv_block->motion_vertical_field_select = mvfs0 | mvfs1;
00566 }
00567 }
00568
00569
00570 if (-1==mv_block->motion_type)
00571 {
00572 if (MV_TYPE_8X8==s->mv_type)
00573 av_log(s->avctx, AV_LOG_ERROR,
00574 "XvMC: H263/MPEG4 motion vector type in MPEG2 decoder!\n");
00575 else
00576 av_log(s->avctx, AV_LOG_ERROR,
00577 "XvMC: Unknown motion vector type!\n");
00578 mv_block->motion_type = XVMC_PREDICTION_FRAME;
00579 }
00580 }
00581
00582 static const int mv_ffmpeg_to_xvmc[8] =
00583 {
00584 XVMC_PREDICTION_FRAME,
00585 -1,
00586 XVMC_PREDICTION_16x8,
00587 XVMC_PREDICTION_FIELD,
00588 XVMC_PREDICTION_DUAL_PRIME,
00589 -1,
00590 -1,
00591 -1
00592 };
00593
00594 static const char* mv_ffmpeg_to_string[8] =
00595 {
00596 "XVMC_PREDICTION_FRAME",
00597 "MV_TYPE_8x8 -- unsupported",
00598 "XVMC_PREDICTION_16x8",
00599 "XVMC_PREDICTION_FIELD",
00600 "XVMC_PREDICTION_DUAL_PRIME",
00601 "MV_??? 5 unknown",
00602 "MV_??? 6 unknown",
00603 "MV_??? 7 unknown"
00604 };
00605
00606 #endif