1/* 2 * DXVA2 WMV3/VC-1 HW acceleration. 3 * 4 * copyright (c) 2010 Laurent Aimar 5 * 6 * This file is part of FFmpeg. 7 * 8 * FFmpeg is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * FFmpeg is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with FFmpeg; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23#include "config_components.h" 24 25#include "dxva2_internal.h" 26#include "mpegutils.h" 27#include "mpegvideodec.h" 28#include "vc1.h" 29#include "vc1data.h" 30 31#define MAX_SLICES 1024 32 33struct dxva2_picture_context { 34 DXVA_PictureParameters pp; 35 unsigned slice_count; 36 DXVA_SliceInfo slice[MAX_SLICES]; 37 38 const uint8_t *bitstream; 39 unsigned bitstream_size; 40}; 41 42static void fill_picture_parameters(AVCodecContext *avctx, 43 AVDXVAContext *ctx, const VC1Context *v, 44 DXVA_PictureParameters *pp) 45{ 46 const MpegEncContext *s = &v->s; 47 const Picture *current_picture = s->current_picture_ptr; 48 int intcomp = 0; 49 50 // determine if intensity compensation is needed 51 if (s->pict_type == AV_PICTURE_TYPE_P) { 52 if ((v->fcm == ILACE_FRAME && v->intcomp) || (v->fcm != ILACE_FRAME && v->mv_mode == MV_PMODE_INTENSITY_COMP)) { 53 if (v->lumscale != 32 || v->lumshift != 0 || (s->picture_structure != PICT_FRAME && (v->lumscale2 != 32 || v->lumshift2 != 0))) 54 intcomp = 1; 55 } 56 } 57 58 memset(pp, 0, sizeof(*pp)); 59 pp->wDecodedPictureIndex = 60 pp->wDeblockedPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, current_picture->f); 61 if (s->pict_type != AV_PICTURE_TYPE_I && !v->bi_type) 62 pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->last_picture.f); 63 else 64 pp->wForwardRefPictureIndex = 0xffff; 65 if (s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type) 66 pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->next_picture.f); 67 else 68 pp->wBackwardRefPictureIndex = 0xffff; 69 if (v->profile == PROFILE_ADVANCED) { 70 /* It is the cropped width/height -1 of the frame */ 71 pp->wPicWidthInMBminus1 = avctx->width - 1; 72 pp->wPicHeightInMBminus1= avctx->height - 1; 73 } else { 74 /* It is the coded width/height in macroblock -1 of the frame */ 75 pp->wPicWidthInMBminus1 = s->mb_width - 1; 76 pp->wPicHeightInMBminus1= s->mb_height - 1; 77 } 78 pp->bMacroblockWidthMinus1 = 15; 79 pp->bMacroblockHeightMinus1 = 15; 80 pp->bBlockWidthMinus1 = 7; 81 pp->bBlockHeightMinus1 = 7; 82 pp->bBPPminus1 = 7; 83 if (s->picture_structure & PICT_TOP_FIELD) 84 pp->bPicStructure |= 0x01; 85 if (s->picture_structure & PICT_BOTTOM_FIELD) 86 pp->bPicStructure |= 0x02; 87 pp->bSecondField = v->interlace && v->fcm == ILACE_FIELD && v->second_field; 88 pp->bPicIntra = s->pict_type == AV_PICTURE_TYPE_I || v->bi_type; 89 pp->bPicBackwardPrediction = s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type; 90 pp->bBidirectionalAveragingMode = (1 << 7) | 91 ((DXVA_CONTEXT_CFG_INTRARESID(avctx, ctx) != 0) << 6) | 92 ((DXVA_CONTEXT_CFG_RESIDACCEL(avctx, ctx) != 0) << 5) | 93 (intcomp << 4) | 94 ((v->profile == PROFILE_ADVANCED) << 3); 95 pp->bMVprecisionAndChromaRelation = ((v->mv_mode == MV_PMODE_1MV_HPEL_BILIN) << 3) | 96 (1 << 2) | 97 (0 << 1) | 98 (!s->quarter_sample ); 99 pp->bChromaFormat = v->chromaformat; 100 DXVA_CONTEXT_REPORT_ID(avctx, ctx)++; 101 if (DXVA_CONTEXT_REPORT_ID(avctx, ctx) >= (1 << 16)) 102 DXVA_CONTEXT_REPORT_ID(avctx, ctx) = 1; 103 pp->bPicScanFixed = DXVA_CONTEXT_REPORT_ID(avctx, ctx) >> 8; 104 pp->bPicScanMethod = DXVA_CONTEXT_REPORT_ID(avctx, ctx) & 0xff; 105 pp->bPicReadbackRequests = 0; 106 pp->bRcontrol = v->rnd; 107 pp->bPicSpatialResid8 = (v->panscanflag << 7) | 108 (v->refdist_flag << 6) | 109 (s->loop_filter << 5) | 110 (v->fastuvmc << 4) | 111 (v->extended_mv << 3) | 112 (v->dquant << 1) | 113 (v->vstransform ); 114 pp->bPicOverflowBlocks = (v->quantizer_mode << 6) | 115 (v->multires << 5) | 116 (v->resync_marker << 4) | 117 (v->rangered << 3) | 118 (s->max_b_frames ); 119 pp->bPicExtrapolation = (!v->interlace || v->fcm == PROGRESSIVE) ? 1 : 2; 120 pp->bPicDeblocked = ((!pp->bPicBackwardPrediction && v->overlap) << 6) | 121 ((v->profile != PROFILE_ADVANCED && v->rangeredfrm) << 5) | 122 (s->loop_filter << 1); 123 pp->bPicDeblockConfined = (v->postprocflag << 7) | 124 (v->broadcast << 6) | 125 (v->interlace << 5) | 126 (v->tfcntrflag << 4) | 127 (v->finterpflag << 3) | 128 ((s->pict_type != AV_PICTURE_TYPE_B) << 2) | 129 (v->psf << 1) | 130 (v->extended_dmv ); 131 if (s->pict_type != AV_PICTURE_TYPE_I) 132 pp->bPic4MVallowed = v->mv_mode == MV_PMODE_MIXED_MV || 133 (v->mv_mode == MV_PMODE_INTENSITY_COMP && 134 v->mv_mode2 == MV_PMODE_MIXED_MV); 135 if (v->profile == PROFILE_ADVANCED) 136 pp->bPicOBMC = (v->range_mapy_flag << 7) | 137 (v->range_mapy << 4) | 138 (v->range_mapuv_flag << 3) | 139 (v->range_mapuv ); 140 pp->bPicBinPB = 0; 141 pp->bMV_RPS = (v->fcm == ILACE_FIELD && pp->bPicBackwardPrediction) ? v->refdist + 9 : 0; 142 pp->bReservedBits = v->pq; 143 if (s->picture_structure == PICT_FRAME) { 144 if (intcomp) { 145 pp->wBitstreamFcodes = v->lumscale; 146 pp->wBitstreamPCEelements = v->lumshift; 147 } else { 148 pp->wBitstreamFcodes = 32; 149 pp->wBitstreamPCEelements = 0; 150 } 151 } else { 152 /* Syntax: (top_field_param << 8) | bottom_field_param */ 153 if (intcomp) { 154 pp->wBitstreamFcodes = (v->lumscale << 8) | v->lumscale2; 155 pp->wBitstreamPCEelements = (v->lumshift << 8) | v->lumshift2; 156 } else { 157 pp->wBitstreamFcodes = (32 << 8) | 32; 158 pp->wBitstreamPCEelements = 0; 159 } 160 } 161 pp->bBitstreamConcealmentNeed = 0; 162 pp->bBitstreamConcealmentMethod = 0; 163} 164 165static void fill_slice(AVCodecContext *avctx, DXVA_SliceInfo *slice, 166 unsigned position, unsigned size) 167{ 168 const VC1Context *v = avctx->priv_data; 169 const MpegEncContext *s = &v->s; 170 171 memset(slice, 0, sizeof(*slice)); 172 slice->wHorizontalPosition = 0; 173 slice->wVerticalPosition = s->mb_y; 174 slice->dwSliceBitsInBuffer = 8 * size; 175 slice->dwSliceDataLocation = position; 176 slice->bStartCodeBitOffset = 0; 177 slice->bReservedBits = (s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type) ? v->bfraction_lut_index + 9 : 0; 178 slice->wMBbitOffset = v->p_frame_skipped ? 0xffff : get_bits_count(&s->gb) + (avctx->codec_id == AV_CODEC_ID_VC1 ? 32 : 0); 179 /* XXX We store the index of the first MB and it will be fixed later */ 180 slice->wNumberMBsInSlice = (s->mb_y >> v->field_mode) * s->mb_width + s->mb_x; 181 slice->wQuantizerScaleCode = v->pq; 182 slice->wBadSliceChopping = 0; 183} 184 185static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, 186 DECODER_BUFFER_DESC *bs, 187 DECODER_BUFFER_DESC *sc) 188{ 189 const VC1Context *v = avctx->priv_data; 190 AVDXVAContext *ctx = DXVA_CONTEXT(avctx); 191 const MpegEncContext *s = &v->s; 192 struct dxva2_picture_context *ctx_pic = s->current_picture_ptr->hwaccel_picture_private; 193 194 static const uint8_t start_code[] = { 0, 0, 1, 0x0d }; 195 const unsigned start_code_size = avctx->codec_id == AV_CODEC_ID_VC1 ? sizeof(start_code) : 0; 196 const unsigned mb_count = s->mb_width * (s->mb_height >> v->field_mode); 197 DXVA_SliceInfo *slice = NULL; 198 void *dxva_data_ptr; 199 uint8_t *dxva_data, *current, *end; 200 unsigned dxva_size; 201 unsigned padding; 202 unsigned i; 203 unsigned type; 204 205#if CONFIG_D3D11VA 206 if (ff_dxva2_is_d3d11(avctx)) { 207 type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM; 208 if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, 209 D3D11VA_CONTEXT(ctx)->decoder, 210 type, 211 &dxva_size, &dxva_data_ptr))) 212 return -1; 213 } 214#endif 215#if CONFIG_DXVA2 216 if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { 217 type = DXVA2_BitStreamDateBufferType; 218 if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder, 219 type, 220 &dxva_data_ptr, &dxva_size))) 221 return -1; 222 } 223#endif 224 225 dxva_data = dxva_data_ptr; 226 current = dxva_data; 227 end = dxva_data + dxva_size; 228 229 for (i = 0; i < ctx_pic->slice_count; i++) { 230 unsigned position, size; 231 slice = &ctx_pic->slice[i]; 232 position = slice->dwSliceDataLocation; 233 size = slice->dwSliceBitsInBuffer / 8; 234 if (start_code_size + size > end - current) { 235 av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream"); 236 break; 237 } 238 slice->dwSliceDataLocation = current - dxva_data; 239 240 if (i < ctx_pic->slice_count - 1) 241 slice->wNumberMBsInSlice = 242 slice[1].wNumberMBsInSlice - slice[0].wNumberMBsInSlice; 243 else 244 slice->wNumberMBsInSlice = 245 mb_count - slice[0].wNumberMBsInSlice; 246 247 /* write the appropriate frame, field or slice start code */ 248 if (start_code_size) { 249 memcpy(current, start_code, start_code_size); 250 if (i == 0 && v->second_field) 251 current[3] = 0x0c; 252 else if (i > 0) 253 current[3] = 0x0b; 254 255 current += start_code_size; 256 slice->dwSliceBitsInBuffer += start_code_size * 8; 257 } 258 259 memcpy(current, &ctx_pic->bitstream[position], size); 260 current += size; 261 } 262 padding = FFMIN(128 - ((current - dxva_data) & 127), end - current); 263 if (slice && padding > 0) { 264 memset(current, 0, padding); 265 current += padding; 266 slice->dwSliceBitsInBuffer += padding * 8; 267 } 268 269#if CONFIG_D3D11VA 270 if (ff_dxva2_is_d3d11(avctx)) 271 if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type))) 272 return -1; 273#endif 274#if CONFIG_DXVA2 275 if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) 276 if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type))) 277 return -1; 278#endif 279 if (i < ctx_pic->slice_count) 280 return -1; 281 282#if CONFIG_D3D11VA 283 if (ff_dxva2_is_d3d11(avctx)) { 284 D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs; 285 memset(dsc11, 0, sizeof(*dsc11)); 286 dsc11->BufferType = type; 287 dsc11->DataSize = current - dxva_data; 288 dsc11->NumMBsInBuffer = mb_count; 289 290 type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL; 291 } 292#endif 293#if CONFIG_DXVA2 294 if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { 295 DXVA2_DecodeBufferDesc *dsc2 = bs; 296 memset(dsc2, 0, sizeof(*dsc2)); 297 dsc2->CompressedBufferType = type; 298 dsc2->DataSize = current - dxva_data; 299 dsc2->NumMBsInBuffer = mb_count; 300 301 type = DXVA2_SliceControlBufferType; 302 } 303#endif 304 305 return ff_dxva2_commit_buffer(avctx, ctx, sc, 306 type, 307 ctx_pic->slice, 308 ctx_pic->slice_count * sizeof(*ctx_pic->slice), 309 mb_count); 310} 311 312static int dxva2_vc1_start_frame(AVCodecContext *avctx, 313 av_unused const uint8_t *buffer, 314 av_unused uint32_t size) 315{ 316 const VC1Context *v = avctx->priv_data; 317 AVDXVAContext *ctx = DXVA_CONTEXT(avctx); 318 struct dxva2_picture_context *ctx_pic = v->s.current_picture_ptr->hwaccel_picture_private; 319 320 if (!DXVA_CONTEXT_VALID(avctx, ctx)) 321 return -1; 322 assert(ctx_pic); 323 324 fill_picture_parameters(avctx, ctx, v, &ctx_pic->pp); 325 326 ctx_pic->slice_count = 0; 327 ctx_pic->bitstream_size = 0; 328 ctx_pic->bitstream = NULL; 329 return 0; 330} 331 332static int dxva2_vc1_decode_slice(AVCodecContext *avctx, 333 const uint8_t *buffer, 334 uint32_t size) 335{ 336 const VC1Context *v = avctx->priv_data; 337 const Picture *current_picture = v->s.current_picture_ptr; 338 struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; 339 unsigned position; 340 341 if (ctx_pic->slice_count >= MAX_SLICES) { 342 avpriv_request_sample(avctx, "%d slices in dxva2", 343 ctx_pic->slice_count); 344 return -1; 345 } 346 347 if (avctx->codec_id == AV_CODEC_ID_VC1 && 348 size >= 4 && IS_MARKER(AV_RB32(buffer))) { 349 buffer += 4; 350 size -= 4; 351 } 352 353 if (!ctx_pic->bitstream) 354 ctx_pic->bitstream = buffer; 355 ctx_pic->bitstream_size += size; 356 357 position = buffer - ctx_pic->bitstream; 358 fill_slice(avctx, &ctx_pic->slice[ctx_pic->slice_count++], position, size); 359 return 0; 360} 361 362static int dxva2_vc1_end_frame(AVCodecContext *avctx) 363{ 364 VC1Context *v = avctx->priv_data; 365 struct dxva2_picture_context *ctx_pic = v->s.current_picture_ptr->hwaccel_picture_private; 366 int ret; 367 368 if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0) 369 return -1; 370 371 ret = ff_dxva2_common_end_frame(avctx, v->s.current_picture_ptr->f, 372 &ctx_pic->pp, sizeof(ctx_pic->pp), 373 NULL, 0, 374 commit_bitstream_and_slice_buffer); 375 if (!ret) 376 ff_mpeg_draw_horiz_band(&v->s, 0, avctx->height); 377 return ret; 378} 379 380#if CONFIG_WMV3_DXVA2_HWACCEL 381const AVHWAccel ff_wmv3_dxva2_hwaccel = { 382 .name = "wmv3_dxva2", 383 .type = AVMEDIA_TYPE_VIDEO, 384 .id = AV_CODEC_ID_WMV3, 385 .pix_fmt = AV_PIX_FMT_DXVA2_VLD, 386 .init = ff_dxva2_decode_init, 387 .uninit = ff_dxva2_decode_uninit, 388 .start_frame = dxva2_vc1_start_frame, 389 .decode_slice = dxva2_vc1_decode_slice, 390 .end_frame = dxva2_vc1_end_frame, 391 .frame_params = ff_dxva2_common_frame_params, 392 .frame_priv_data_size = sizeof(struct dxva2_picture_context), 393 .priv_data_size = sizeof(FFDXVASharedContext), 394}; 395#endif 396 397#if CONFIG_VC1_DXVA2_HWACCEL 398const AVHWAccel ff_vc1_dxva2_hwaccel = { 399 .name = "vc1_dxva2", 400 .type = AVMEDIA_TYPE_VIDEO, 401 .id = AV_CODEC_ID_VC1, 402 .pix_fmt = AV_PIX_FMT_DXVA2_VLD, 403 .init = ff_dxva2_decode_init, 404 .uninit = ff_dxva2_decode_uninit, 405 .start_frame = dxva2_vc1_start_frame, 406 .decode_slice = dxva2_vc1_decode_slice, 407 .end_frame = dxva2_vc1_end_frame, 408 .frame_params = ff_dxva2_common_frame_params, 409 .frame_priv_data_size = sizeof(struct dxva2_picture_context), 410 .priv_data_size = sizeof(FFDXVASharedContext), 411}; 412#endif 413 414#if CONFIG_WMV3_D3D11VA_HWACCEL 415const AVHWAccel ff_wmv3_d3d11va_hwaccel = { 416 .name = "wmv3_d3d11va", 417 .type = AVMEDIA_TYPE_VIDEO, 418 .id = AV_CODEC_ID_WMV3, 419 .pix_fmt = AV_PIX_FMT_D3D11VA_VLD, 420 .init = ff_dxva2_decode_init, 421 .uninit = ff_dxva2_decode_uninit, 422 .start_frame = dxva2_vc1_start_frame, 423 .decode_slice = dxva2_vc1_decode_slice, 424 .end_frame = dxva2_vc1_end_frame, 425 .frame_params = ff_dxva2_common_frame_params, 426 .frame_priv_data_size = sizeof(struct dxva2_picture_context), 427 .priv_data_size = sizeof(FFDXVASharedContext), 428}; 429#endif 430 431#if CONFIG_WMV3_D3D11VA2_HWACCEL 432const AVHWAccel ff_wmv3_d3d11va2_hwaccel = { 433 .name = "wmv3_d3d11va2", 434 .type = AVMEDIA_TYPE_VIDEO, 435 .id = AV_CODEC_ID_WMV3, 436 .pix_fmt = AV_PIX_FMT_D3D11, 437 .init = ff_dxva2_decode_init, 438 .uninit = ff_dxva2_decode_uninit, 439 .start_frame = dxva2_vc1_start_frame, 440 .decode_slice = dxva2_vc1_decode_slice, 441 .end_frame = dxva2_vc1_end_frame, 442 .frame_params = ff_dxva2_common_frame_params, 443 .frame_priv_data_size = sizeof(struct dxva2_picture_context), 444 .priv_data_size = sizeof(FFDXVASharedContext), 445}; 446#endif 447 448#if CONFIG_VC1_D3D11VA_HWACCEL 449const AVHWAccel ff_vc1_d3d11va_hwaccel = { 450 .name = "vc1_d3d11va", 451 .type = AVMEDIA_TYPE_VIDEO, 452 .id = AV_CODEC_ID_VC1, 453 .pix_fmt = AV_PIX_FMT_D3D11VA_VLD, 454 .init = ff_dxva2_decode_init, 455 .uninit = ff_dxva2_decode_uninit, 456 .start_frame = dxva2_vc1_start_frame, 457 .decode_slice = dxva2_vc1_decode_slice, 458 .end_frame = dxva2_vc1_end_frame, 459 .frame_params = ff_dxva2_common_frame_params, 460 .frame_priv_data_size = sizeof(struct dxva2_picture_context), 461 .priv_data_size = sizeof(FFDXVASharedContext), 462}; 463#endif 464 465#if CONFIG_VC1_D3D11VA2_HWACCEL 466const AVHWAccel ff_vc1_d3d11va2_hwaccel = { 467 .name = "vc1_d3d11va2", 468 .type = AVMEDIA_TYPE_VIDEO, 469 .id = AV_CODEC_ID_VC1, 470 .pix_fmt = AV_PIX_FMT_D3D11, 471 .init = ff_dxva2_decode_init, 472 .uninit = ff_dxva2_decode_uninit, 473 .start_frame = dxva2_vc1_start_frame, 474 .decode_slice = dxva2_vc1_decode_slice, 475 .end_frame = dxva2_vc1_end_frame, 476 .frame_params = ff_dxva2_common_frame_params, 477 .frame_priv_data_size = sizeof(struct dxva2_picture_context), 478 .priv_data_size = sizeof(FFDXVASharedContext), 479}; 480#endif 481