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 #include <X11/extensions/XvMC.h>
00024
00025 #include "avcodec.h"
00026 #include "dsputil.h"
00027 #include "mpegvideo.h"
00028
00029 #undef NDEBUG
00030 #include <assert.h>
00031
00032 #include "xvmc.h"
00033 #include "xvmc_internal.h"
00034
00042 void ff_xvmc_init_block(MpegEncContext *s)
00043 {
00044 struct xvmc_pix_fmt *render = (struct xvmc_pix_fmt*)s->current_picture.data[2];
00045 assert(render && render->xvmc_id == AV_XVMC_ID);
00046
00047 s->block = (DCTELEM (*)[64])(render->data_blocks + render->next_free_data_block_num * 64);
00048 }
00049
00054 void ff_xvmc_pack_pblocks(MpegEncContext *s, int cbp)
00055 {
00056 int i, j = 0;
00057 const int mb_block_count = 4 + (1 << s->chroma_format);
00058
00059 cbp <<= 12-mb_block_count;
00060 for (i = 0; i < mb_block_count; i++) {
00061 if (cbp & (1 << 11))
00062 s->pblocks[i] = &s->block[j++];
00063 else
00064 s->pblocks[i] = NULL;
00065 cbp += cbp;
00066 }
00067 }
00068
00074 int ff_xvmc_field_start(MpegEncContext *s, AVCodecContext *avctx)
00075 {
00076 struct xvmc_pix_fmt *last, *next, *render = (struct xvmc_pix_fmt*)s->current_picture.data[2];
00077 const int mb_block_count = 4 + (1 << s->chroma_format);
00078
00079 assert(avctx);
00080 if (!render || render->xvmc_id != AV_XVMC_ID ||
00081 !render->data_blocks || !render->mv_blocks ||
00082 (unsigned int)render->allocated_mv_blocks > INT_MAX/(64*6) ||
00083 (unsigned int)render->allocated_data_blocks > INT_MAX/64 ||
00084 !render->p_surface) {
00085 av_log(avctx, AV_LOG_ERROR,
00086 "Render token doesn't look as expected.\n");
00087 return -1;
00088 }
00089
00090 if (render->filled_mv_blocks_num) {
00091 av_log(avctx, AV_LOG_ERROR,
00092 "Rendering surface contains %i unprocessed blocks.\n",
00093 render->filled_mv_blocks_num);
00094 return -1;
00095 }
00096 if (render->allocated_mv_blocks < 1 ||
00097 render->allocated_data_blocks < render->allocated_mv_blocks*mb_block_count ||
00098 render->start_mv_blocks_num >= render->allocated_mv_blocks ||
00099 render->next_free_data_block_num >
00100 render->allocated_data_blocks -
00101 mb_block_count*(render->allocated_mv_blocks-render->start_mv_blocks_num)) {
00102 av_log(avctx, AV_LOG_ERROR,
00103 "Rendering surface doesn't provide enough block structures to work with.\n");
00104 return -1;
00105 }
00106
00107 render->picture_structure = s->picture_structure;
00108 render->flags = s->first_field ? 0 : XVMC_SECOND_FIELD;
00109 render->p_future_surface = NULL;
00110 render->p_past_surface = NULL;
00111
00112 switch(s->pict_type) {
00113 case FF_I_TYPE:
00114 return 0;
00115 case FF_B_TYPE:
00116 next = (struct xvmc_pix_fmt*)s->next_picture.data[2];
00117 if (!next)
00118 return -1;
00119 if (next->xvmc_id != AV_XVMC_ID)
00120 return -1;
00121 render->p_future_surface = next->p_surface;
00122
00123 case FF_P_TYPE:
00124 last = (struct xvmc_pix_fmt*)s->last_picture.data[2];
00125 if (!last)
00126 last = render;
00127 if (last->xvmc_id != AV_XVMC_ID)
00128 return -1;
00129 render->p_past_surface = last->p_surface;
00130 return 0;
00131 }
00132
00133 return -1;
00134 }
00135
00142 void ff_xvmc_field_end(MpegEncContext *s)
00143 {
00144 struct xvmc_pix_fmt *render = (struct xvmc_pix_fmt*)s->current_picture.data[2];
00145 assert(render);
00146
00147 if (render->filled_mv_blocks_num > 0)
00148 ff_draw_horiz_band(s, 0, 0);
00149 }
00150
00155 void ff_xvmc_decode_mb(MpegEncContext *s)
00156 {
00157 XvMCMacroBlock *mv_block;
00158 struct xvmc_pix_fmt *render;
00159 int i, cbp, blocks_per_mb;
00160
00161 const int mb_xy = s->mb_y * s->mb_stride + s->mb_x;
00162
00163
00164 if (s->encoding) {
00165 av_log(s->avctx, AV_LOG_ERROR, "XVMC doesn't support encoding!!!\n");
00166 return;
00167 }
00168
00169
00170 if (!s->mb_intra) {
00171 s->last_dc[0] =
00172 s->last_dc[1] =
00173 s->last_dc[2] = 128 << s->intra_dc_precision;
00174 }
00175
00176
00177 s->mb_skipped = 0;
00178
00179
00180
00181
00182 s->current_picture.qscale_table[mb_xy] = s->qscale;
00183
00184
00185 render = (struct xvmc_pix_fmt*)s->current_picture.data[2];
00186 assert(render);
00187 assert(render->xvmc_id == AV_XVMC_ID);
00188 assert(render->mv_blocks);
00189
00190
00191 mv_block = &render->mv_blocks[render->start_mv_blocks_num +
00192 render->filled_mv_blocks_num];
00193
00194 mv_block->x = s->mb_x;
00195 mv_block->y = s->mb_y;
00196 mv_block->dct_type = s->interlaced_dct;
00197 if (s->mb_intra) {
00198 mv_block->macroblock_type = XVMC_MB_TYPE_INTRA;
00199 } else {
00200 mv_block->macroblock_type = XVMC_MB_TYPE_PATTERN;
00201
00202 if (s->mv_dir & MV_DIR_FORWARD) {
00203 mv_block->macroblock_type |= XVMC_MB_TYPE_MOTION_FORWARD;
00204
00205 mv_block->PMV[0][0][0] = s->mv[0][0][0];
00206 mv_block->PMV[0][0][1] = s->mv[0][0][1];
00207 mv_block->PMV[1][0][0] = s->mv[0][1][0];
00208 mv_block->PMV[1][0][1] = s->mv[0][1][1];
00209 }
00210 if (s->mv_dir & MV_DIR_BACKWARD) {
00211 mv_block->macroblock_type |= XVMC_MB_TYPE_MOTION_BACKWARD;
00212 mv_block->PMV[0][1][0] = s->mv[1][0][0];
00213 mv_block->PMV[0][1][1] = s->mv[1][0][1];
00214 mv_block->PMV[1][1][0] = s->mv[1][1][0];
00215 mv_block->PMV[1][1][1] = s->mv[1][1][1];
00216 }
00217
00218 switch(s->mv_type) {
00219 case MV_TYPE_16X16:
00220 mv_block->motion_type = XVMC_PREDICTION_FRAME;
00221 break;
00222 case MV_TYPE_16X8:
00223 mv_block->motion_type = XVMC_PREDICTION_16x8;
00224 break;
00225 case MV_TYPE_FIELD:
00226 mv_block->motion_type = XVMC_PREDICTION_FIELD;
00227 if (s->picture_structure == PICT_FRAME) {
00228 mv_block->PMV[0][0][1] <<= 1;
00229 mv_block->PMV[1][0][1] <<= 1;
00230 mv_block->PMV[0][1][1] <<= 1;
00231 mv_block->PMV[1][1][1] <<= 1;
00232 }
00233 break;
00234 case MV_TYPE_DMV:
00235 mv_block->motion_type = XVMC_PREDICTION_DUAL_PRIME;
00236 if (s->picture_structure == PICT_FRAME) {
00237
00238 mv_block->PMV[0][0][0] = s->mv[0][0][0];
00239 mv_block->PMV[0][0][1] = s->mv[0][0][1] << 1;
00240
00241 mv_block->PMV[0][1][0] = s->mv[0][0][0];
00242 mv_block->PMV[0][1][1] = s->mv[0][0][1] << 1;
00243
00244 mv_block->PMV[1][0][0] = s->mv[0][2][0];
00245 mv_block->PMV[1][0][1] = s->mv[0][2][1] << 1;
00246
00247 mv_block->PMV[1][1][0] = s->mv[0][3][0];
00248 mv_block->PMV[1][1][1] = s->mv[0][3][1] << 1;
00249
00250 } else {
00251 mv_block->PMV[0][1][0] = s->mv[0][2][0];
00252 mv_block->PMV[0][1][1] = s->mv[0][2][1];
00253 }
00254 break;
00255 default:
00256 assert(0);
00257 }
00258
00259 mv_block->motion_vertical_field_select = 0;
00260
00261
00262 if (s->mv_type == MV_TYPE_FIELD || s->mv_type == MV_TYPE_16X8) {
00263 mv_block->motion_vertical_field_select |= s->field_select[0][0];
00264 mv_block->motion_vertical_field_select |= s->field_select[1][0] << 1;
00265 mv_block->motion_vertical_field_select |= s->field_select[0][1] << 2;
00266 mv_block->motion_vertical_field_select |= s->field_select[1][1] << 3;
00267 }
00268 }
00269
00270 mv_block->index = render->next_free_data_block_num;
00271
00272 blocks_per_mb = 6;
00273 if (s->chroma_format >= 2) {
00274 blocks_per_mb = 4 + (1 << s->chroma_format);
00275 }
00276
00277
00278 cbp = 0;
00279 for (i = 0; i < blocks_per_mb; i++) {
00280 cbp += cbp;
00281 if (s->block_last_index[i] >= 0)
00282 cbp++;
00283 }
00284
00285 if (s->flags & CODEC_FLAG_GRAY) {
00286 if (s->mb_intra) {
00287 for (i = 4; i < blocks_per_mb; i++) {
00288 memset(s->pblocks[i], 0, sizeof(*s->pblocks[i]));
00289 if (!render->unsigned_intra)
00290 *s->pblocks[i][0] = 1 << 10;
00291 }
00292 } else {
00293 cbp &= 0xf << (blocks_per_mb - 4);
00294 blocks_per_mb = 4;
00295 }
00296 }
00297 mv_block->coded_block_pattern = cbp;
00298 if (cbp == 0)
00299 mv_block->macroblock_type &= ~XVMC_MB_TYPE_PATTERN;
00300
00301 for (i = 0; i < blocks_per_mb; i++) {
00302 if (s->block_last_index[i] >= 0) {
00303
00304 if (s->mb_intra && (render->idct || (!render->idct && !render->unsigned_intra)))
00305 *s->pblocks[i][0] -= 1 << 10;
00306 if (!render->idct) {
00307 s->dsp.idct(*s->pblocks[i]);
00308
00309
00310
00311
00312 }
00313
00314 if (s->avctx->xvmc_acceleration == 1) {
00315 memcpy(&render->data_blocks[render->next_free_data_block_num*64],
00316 s->pblocks[i], sizeof(*s->pblocks[i]));
00317 }
00318 render->next_free_data_block_num++;
00319 }
00320 }
00321 render->filled_mv_blocks_num++;
00322
00323 assert(render->filled_mv_blocks_num <= render->allocated_mv_blocks);
00324 assert(render->next_free_data_block_num <= render->allocated_data_blocks);
00325
00326
00327
00328
00329
00330 if (render->filled_mv_blocks_num == render->allocated_mv_blocks)
00331 ff_draw_horiz_band(s, 0, 0);
00332 }