1/* 2 * MPEG-2 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 "libavutil/log.h" 26 27#include "dxva2_internal.h" 28#include "mpegutils.h" 29#include "mpegvideodec.h" 30 31#define MAX_SLICES 1024 32struct dxva2_picture_context { 33 DXVA_PictureParameters pp; 34 DXVA_QmatrixData qm; 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, 44 const struct MpegEncContext *s, 45 DXVA_PictureParameters *pp) 46{ 47 const Picture *current_picture = s->current_picture_ptr; 48 int is_field = s->picture_structure != PICT_FRAME; 49 50 memset(pp, 0, sizeof(*pp)); 51 pp->wDecodedPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, current_picture->f); 52 pp->wDeblockedPictureIndex = 0; 53 if (s->pict_type != AV_PICTURE_TYPE_I) 54 pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->last_picture.f); 55 else 56 pp->wForwardRefPictureIndex = 0xffff; 57 if (s->pict_type == AV_PICTURE_TYPE_B) 58 pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->next_picture.f); 59 else 60 pp->wBackwardRefPictureIndex = 0xffff; 61 pp->wPicWidthInMBminus1 = s->mb_width - 1; 62 pp->wPicHeightInMBminus1 = (s->mb_height >> is_field) - 1; 63 pp->bMacroblockWidthMinus1 = 15; 64 pp->bMacroblockHeightMinus1 = 15; 65 pp->bBlockWidthMinus1 = 7; 66 pp->bBlockHeightMinus1 = 7; 67 pp->bBPPminus1 = 7; 68 pp->bPicStructure = s->picture_structure; 69 pp->bSecondField = is_field && !s->first_field; 70 pp->bPicIntra = s->pict_type == AV_PICTURE_TYPE_I; 71 pp->bPicBackwardPrediction = s->pict_type == AV_PICTURE_TYPE_B; 72 pp->bBidirectionalAveragingMode = 0; 73 pp->bMVprecisionAndChromaRelation= 0; /* FIXME */ 74 pp->bChromaFormat = s->chroma_format; 75 pp->bPicScanFixed = 1; 76 pp->bPicScanMethod = s->alternate_scan ? 1 : 0; 77 pp->bPicReadbackRequests = 0; 78 pp->bRcontrol = 0; 79 pp->bPicSpatialResid8 = 0; 80 pp->bPicOverflowBlocks = 0; 81 pp->bPicExtrapolation = 0; 82 pp->bPicDeblocked = 0; 83 pp->bPicDeblockConfined = 0; 84 pp->bPic4MVallowed = 0; 85 pp->bPicOBMC = 0; 86 pp->bPicBinPB = 0; 87 pp->bMV_RPS = 0; 88 pp->bReservedBits = 0; 89 pp->wBitstreamFcodes = (s->mpeg_f_code[0][0] << 12) | 90 (s->mpeg_f_code[0][1] << 8) | 91 (s->mpeg_f_code[1][0] << 4) | 92 (s->mpeg_f_code[1][1] ); 93 pp->wBitstreamPCEelements = (s->intra_dc_precision << 14) | 94 (s->picture_structure << 12) | 95 (s->top_field_first << 11) | 96 (s->frame_pred_frame_dct << 10) | 97 (s->concealment_motion_vectors << 9) | 98 (s->q_scale_type << 8) | 99 (s->intra_vlc_format << 7) | 100 (s->alternate_scan << 6) | 101 (s->repeat_first_field << 5) | 102 (s->chroma_420_type << 4) | 103 (s->progressive_frame << 3); 104 pp->bBitstreamConcealmentNeed = 0; 105 pp->bBitstreamConcealmentMethod = 0; 106} 107 108static void fill_quantization_matrices(AVCodecContext *avctx, 109 AVDXVAContext *ctx, 110 const struct MpegEncContext *s, 111 DXVA_QmatrixData *qm) 112{ 113 int i; 114 for (i = 0; i < 4; i++) 115 qm->bNewQmatrix[i] = 1; 116 for (i = 0; i < 64; i++) { 117 int n = s->idsp.idct_permutation[ff_zigzag_direct[i]]; 118 qm->Qmatrix[0][i] = s->intra_matrix[n]; 119 qm->Qmatrix[1][i] = s->inter_matrix[n]; 120 qm->Qmatrix[2][i] = s->chroma_intra_matrix[n]; 121 qm->Qmatrix[3][i] = s->chroma_inter_matrix[n]; 122 } 123} 124 125static void fill_slice(AVCodecContext *avctx, 126 const struct MpegEncContext *s, 127 DXVA_SliceInfo *slice, 128 unsigned position, 129 const uint8_t *buffer, unsigned size) 130{ 131 int is_field = s->picture_structure != PICT_FRAME; 132 GetBitContext gb; 133 134 memset(slice, 0, sizeof(*slice)); 135 slice->wHorizontalPosition = s->mb_x; 136 slice->wVerticalPosition = s->mb_y >> is_field; 137 slice->dwSliceBitsInBuffer = 8 * size; 138 slice->dwSliceDataLocation = position; 139 slice->bStartCodeBitOffset = 0; 140 slice->bReservedBits = 0; 141 /* XXX We store the index of the first MB and it will be fixed later */ 142 slice->wNumberMBsInSlice = (s->mb_y >> is_field) * s->mb_width + s->mb_x; 143 slice->wBadSliceChopping = 0; 144 145 init_get_bits(&gb, &buffer[4], 8 * (size - 4)); 146 147 slice->wQuantizerScaleCode = get_bits(&gb, 5); 148 skip_1stop_8data_bits(&gb); 149 150 slice->wMBbitOffset = 4 * 8 + get_bits_count(&gb); 151} 152static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, 153 DECODER_BUFFER_DESC *bs, 154 DECODER_BUFFER_DESC *sc) 155{ 156 const struct MpegEncContext *s = avctx->priv_data; 157 AVDXVAContext *ctx = DXVA_CONTEXT(avctx); 158 struct dxva2_picture_context *ctx_pic = 159 s->current_picture_ptr->hwaccel_picture_private; 160 const int is_field = s->picture_structure != PICT_FRAME; 161 const unsigned mb_count = s->mb_width * (s->mb_height >> is_field); 162 void *dxva_data_ptr; 163 uint8_t *dxva_data, *current, *end; 164 unsigned dxva_size; 165 unsigned i; 166 unsigned type; 167 168#if CONFIG_D3D11VA 169 if (ff_dxva2_is_d3d11(avctx)) { 170 type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM; 171 if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, 172 D3D11VA_CONTEXT(ctx)->decoder, 173 type, 174 &dxva_size, &dxva_data_ptr))) 175 return -1; 176 } 177#endif 178#if CONFIG_DXVA2 179 if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { 180 type = DXVA2_BitStreamDateBufferType; 181 if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder, 182 type, 183 &dxva_data_ptr, &dxva_size))) 184 return -1; 185 } 186#endif 187 188 dxva_data = dxva_data_ptr; 189 current = dxva_data; 190 end = dxva_data + dxva_size; 191 192 for (i = 0; i < ctx_pic->slice_count; i++) { 193 DXVA_SliceInfo *slice = &ctx_pic->slice[i]; 194 unsigned position = slice->dwSliceDataLocation; 195 unsigned size = slice->dwSliceBitsInBuffer / 8; 196 if (size > end - current) { 197 av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream"); 198 break; 199 } 200 slice->dwSliceDataLocation = current - dxva_data; 201 202 if (i < ctx_pic->slice_count - 1) 203 slice->wNumberMBsInSlice = 204 slice[1].wNumberMBsInSlice - slice[0].wNumberMBsInSlice; 205 else 206 slice->wNumberMBsInSlice = 207 mb_count - slice[0].wNumberMBsInSlice; 208 209 memcpy(current, &ctx_pic->bitstream[position], size); 210 current += size; 211 } 212#if CONFIG_D3D11VA 213 if (ff_dxva2_is_d3d11(avctx)) 214 if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type))) 215 return -1; 216#endif 217#if CONFIG_DXVA2 218 if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) 219 if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type))) 220 return -1; 221#endif 222 if (i < ctx_pic->slice_count) 223 return -1; 224 225#if CONFIG_D3D11VA 226 if (ff_dxva2_is_d3d11(avctx)) { 227 D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs; 228 memset(dsc11, 0, sizeof(*dsc11)); 229 dsc11->BufferType = type; 230 dsc11->DataSize = current - dxva_data; 231 dsc11->NumMBsInBuffer = mb_count; 232 233 type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL; 234 } 235#endif 236#if CONFIG_DXVA2 237 if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { 238 DXVA2_DecodeBufferDesc *dsc2 = bs; 239 memset(dsc2, 0, sizeof(*dsc2)); 240 dsc2->CompressedBufferType = type; 241 dsc2->DataSize = current - dxva_data; 242 dsc2->NumMBsInBuffer = mb_count; 243 244 type = DXVA2_SliceControlBufferType; 245 } 246#endif 247 248 return ff_dxva2_commit_buffer(avctx, ctx, sc, 249 type, 250 ctx_pic->slice, 251 ctx_pic->slice_count * sizeof(*ctx_pic->slice), 252 mb_count); 253} 254 255static int dxva2_mpeg2_start_frame(AVCodecContext *avctx, 256 av_unused const uint8_t *buffer, 257 av_unused uint32_t size) 258{ 259 const struct MpegEncContext *s = avctx->priv_data; 260 AVDXVAContext *ctx = DXVA_CONTEXT(avctx); 261 struct dxva2_picture_context *ctx_pic = 262 s->current_picture_ptr->hwaccel_picture_private; 263 264 if (!DXVA_CONTEXT_VALID(avctx, ctx)) 265 return -1; 266 assert(ctx_pic); 267 268 fill_picture_parameters(avctx, ctx, s, &ctx_pic->pp); 269 fill_quantization_matrices(avctx, ctx, s, &ctx_pic->qm); 270 271 ctx_pic->slice_count = 0; 272 ctx_pic->bitstream_size = 0; 273 ctx_pic->bitstream = NULL; 274 return 0; 275} 276 277static int dxva2_mpeg2_decode_slice(AVCodecContext *avctx, 278 const uint8_t *buffer, uint32_t size) 279{ 280 const struct MpegEncContext *s = avctx->priv_data; 281 struct dxva2_picture_context *ctx_pic = 282 s->current_picture_ptr->hwaccel_picture_private; 283 unsigned position; 284 285 if (ctx_pic->slice_count >= MAX_SLICES) { 286 avpriv_request_sample(avctx, "%d slices in dxva2", 287 ctx_pic->slice_count); 288 return -1; 289 } 290 if (!ctx_pic->bitstream) 291 ctx_pic->bitstream = buffer; 292 ctx_pic->bitstream_size += size; 293 294 position = buffer - ctx_pic->bitstream; 295 fill_slice(avctx, s, &ctx_pic->slice[ctx_pic->slice_count++], position, 296 buffer, size); 297 return 0; 298} 299 300static int dxva2_mpeg2_end_frame(AVCodecContext *avctx) 301{ 302 struct MpegEncContext *s = avctx->priv_data; 303 struct dxva2_picture_context *ctx_pic = 304 s->current_picture_ptr->hwaccel_picture_private; 305 int ret; 306 307 if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0) 308 return -1; 309 ret = ff_dxva2_common_end_frame(avctx, s->current_picture_ptr->f, 310 &ctx_pic->pp, sizeof(ctx_pic->pp), 311 &ctx_pic->qm, sizeof(ctx_pic->qm), 312 commit_bitstream_and_slice_buffer); 313 if (!ret) 314 ff_mpeg_draw_horiz_band(s, 0, avctx->height); 315 return ret; 316} 317 318#if CONFIG_MPEG2_DXVA2_HWACCEL 319const AVHWAccel ff_mpeg2_dxva2_hwaccel = { 320 .name = "mpeg2_dxva2", 321 .type = AVMEDIA_TYPE_VIDEO, 322 .id = AV_CODEC_ID_MPEG2VIDEO, 323 .pix_fmt = AV_PIX_FMT_DXVA2_VLD, 324 .init = ff_dxva2_decode_init, 325 .uninit = ff_dxva2_decode_uninit, 326 .start_frame = dxva2_mpeg2_start_frame, 327 .decode_slice = dxva2_mpeg2_decode_slice, 328 .end_frame = dxva2_mpeg2_end_frame, 329 .frame_params = ff_dxva2_common_frame_params, 330 .frame_priv_data_size = sizeof(struct dxva2_picture_context), 331 .priv_data_size = sizeof(FFDXVASharedContext), 332}; 333#endif 334 335#if CONFIG_MPEG2_D3D11VA_HWACCEL 336const AVHWAccel ff_mpeg2_d3d11va_hwaccel = { 337 .name = "mpeg2_d3d11va", 338 .type = AVMEDIA_TYPE_VIDEO, 339 .id = AV_CODEC_ID_MPEG2VIDEO, 340 .pix_fmt = AV_PIX_FMT_D3D11VA_VLD, 341 .init = ff_dxva2_decode_init, 342 .uninit = ff_dxva2_decode_uninit, 343 .start_frame = dxva2_mpeg2_start_frame, 344 .decode_slice = dxva2_mpeg2_decode_slice, 345 .end_frame = dxva2_mpeg2_end_frame, 346 .frame_params = ff_dxva2_common_frame_params, 347 .frame_priv_data_size = sizeof(struct dxva2_picture_context), 348 .priv_data_size = sizeof(FFDXVASharedContext), 349}; 350#endif 351 352#if CONFIG_MPEG2_D3D11VA2_HWACCEL 353const AVHWAccel ff_mpeg2_d3d11va2_hwaccel = { 354 .name = "mpeg2_d3d11va2", 355 .type = AVMEDIA_TYPE_VIDEO, 356 .id = AV_CODEC_ID_MPEG2VIDEO, 357 .pix_fmt = AV_PIX_FMT_D3D11, 358 .init = ff_dxva2_decode_init, 359 .uninit = ff_dxva2_decode_uninit, 360 .start_frame = dxva2_mpeg2_start_frame, 361 .decode_slice = dxva2_mpeg2_decode_slice, 362 .end_frame = dxva2_mpeg2_end_frame, 363 .frame_params = ff_dxva2_common_frame_params, 364 .frame_priv_data_size = sizeof(struct dxva2_picture_context), 365 .priv_data_size = sizeof(FFDXVASharedContext), 366}; 367#endif 368