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 "libavutil/log.h" 24#include "dxva2_internal.h" 25#include "mpegutils.h" 26 27#define MAX_SLICES 1024 28struct dxva2_picture_context { 29 DXVA_PictureParameters pp; 30 DXVA_QmatrixData qm; 31 unsigned slice_count; 32 DXVA_SliceInfo slice[MAX_SLICES]; 33 34 const uint8_t *bitstream; 35 unsigned bitstream_size; 36}; 37 38static void fill_picture_parameters(AVCodecContext *avctx, 39 struct dxva_context *ctx, 40 const struct MpegEncContext *s, 41 DXVA_PictureParameters *pp) 42{ 43 const Picture *current_picture = s->current_picture_ptr; 44 int is_field = s->picture_structure != PICT_FRAME; 45 46 memset(pp, 0, sizeof(*pp)); 47 pp->wDecodedPictureIndex = ff_dxva2_get_surface_index(ctx, current_picture->f); 48 pp->wDeblockedPictureIndex = 0; 49 if (s->pict_type != AV_PICTURE_TYPE_I) 50 pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, s->last_picture.f); 51 else 52 pp->wForwardRefPictureIndex = 0xffff; 53 if (s->pict_type == AV_PICTURE_TYPE_B) 54 pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, s->next_picture.f); 55 else 56 pp->wBackwardRefPictureIndex = 0xffff; 57 pp->wPicWidthInMBminus1 = s->mb_width - 1; 58 pp->wPicHeightInMBminus1 = (s->mb_height >> is_field) - 1; 59 pp->bMacroblockWidthMinus1 = 15; 60 pp->bMacroblockHeightMinus1 = 15; 61 pp->bBlockWidthMinus1 = 7; 62 pp->bBlockHeightMinus1 = 7; 63 pp->bBPPminus1 = 7; 64 pp->bPicStructure = s->picture_structure; 65 pp->bSecondField = is_field && !s->first_field; 66 pp->bPicIntra = s->pict_type == AV_PICTURE_TYPE_I; 67 pp->bPicBackwardPrediction = s->pict_type == AV_PICTURE_TYPE_B; 68 pp->bBidirectionalAveragingMode = 0; 69 pp->bMVprecisionAndChromaRelation= 0; /* FIXME */ 70 pp->bChromaFormat = s->chroma_format; 71 pp->bPicScanFixed = 1; 72 pp->bPicScanMethod = s->alternate_scan ? 1 : 0; 73 pp->bPicReadbackRequests = 0; 74 pp->bRcontrol = 0; 75 pp->bPicSpatialResid8 = 0; 76 pp->bPicOverflowBlocks = 0; 77 pp->bPicExtrapolation = 0; 78 pp->bPicDeblocked = 0; 79 pp->bPicDeblockConfined = 0; 80 pp->bPic4MVallowed = 0; 81 pp->bPicOBMC = 0; 82 pp->bPicBinPB = 0; 83 pp->bMV_RPS = 0; 84 pp->bReservedBits = 0; 85 pp->wBitstreamFcodes = (s->mpeg_f_code[0][0] << 12) | 86 (s->mpeg_f_code[0][1] << 8) | 87 (s->mpeg_f_code[1][0] << 4) | 88 (s->mpeg_f_code[1][1] ); 89 pp->wBitstreamPCEelements = (s->intra_dc_precision << 14) | 90 (s->picture_structure << 12) | 91 (s->top_field_first << 11) | 92 (s->frame_pred_frame_dct << 10) | 93 (s->concealment_motion_vectors << 9) | 94 (s->q_scale_type << 8) | 95 (s->intra_vlc_format << 7) | 96 (s->alternate_scan << 6) | 97 (s->repeat_first_field << 5) | 98 (s->chroma_420_type << 4) | 99 (s->progressive_frame << 3); 100 pp->bBitstreamConcealmentNeed = 0; 101 pp->bBitstreamConcealmentMethod = 0; 102} 103 104static void fill_quantization_matrices(AVCodecContext *avctx, 105 struct dxva_context *ctx, 106 const struct MpegEncContext *s, 107 DXVA_QmatrixData *qm) 108{ 109 int i; 110 for (i = 0; i < 4; i++) 111 qm->bNewQmatrix[i] = 1; 112 for (i = 0; i < 64; i++) { 113 int n = s->idsp.idct_permutation[ff_zigzag_direct[i]]; 114 qm->Qmatrix[0][i] = s->intra_matrix[n]; 115 qm->Qmatrix[1][i] = s->inter_matrix[n]; 116 qm->Qmatrix[2][i] = s->chroma_intra_matrix[n]; 117 qm->Qmatrix[3][i] = s->chroma_inter_matrix[n]; 118 } 119} 120 121static void fill_slice(AVCodecContext *avctx, 122 const struct MpegEncContext *s, 123 DXVA_SliceInfo *slice, 124 unsigned position, 125 const uint8_t *buffer, unsigned size) 126{ 127 int is_field = s->picture_structure != PICT_FRAME; 128 GetBitContext gb; 129 130 memset(slice, 0, sizeof(*slice)); 131 slice->wHorizontalPosition = s->mb_x; 132 slice->wVerticalPosition = s->mb_y >> is_field; 133 slice->dwSliceBitsInBuffer = 8 * size; 134 slice->dwSliceDataLocation = position; 135 slice->bStartCodeBitOffset = 0; 136 slice->bReservedBits = 0; 137 /* XXX We store the index of the first MB and it will be fixed later */ 138 slice->wNumberMBsInSlice = (s->mb_y >> is_field) * s->mb_width + s->mb_x; 139 slice->wBadSliceChopping = 0; 140 141 init_get_bits(&gb, &buffer[4], 8 * (size - 4)); 142 143 slice->wQuantizerScaleCode = get_bits(&gb, 5); 144 skip_1stop_8data_bits(&gb); 145 146 slice->wMBbitOffset = 4 * 8 + get_bits_count(&gb); 147} 148static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, 149 DXVA2_DecodeBufferDesc *bs, 150 DXVA2_DecodeBufferDesc *sc) 151{ 152 const struct MpegEncContext *s = avctx->priv_data; 153 struct dxva_context *ctx = avctx->hwaccel_context; 154 struct dxva2_picture_context *ctx_pic = 155 s->current_picture_ptr->hwaccel_picture_private; 156 const int is_field = s->picture_structure != PICT_FRAME; 157 const unsigned mb_count = s->mb_width * (s->mb_height >> is_field); 158 uint8_t *dxva_data, *current, *end; 159 unsigned dxva_size; 160 unsigned i; 161 162 if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, 163 DXVA2_BitStreamDateBufferType, 164 (void **)&dxva_data, &dxva_size))) 165 return -1; 166 current = dxva_data; 167 end = dxva_data + dxva_size; 168 169 for (i = 0; i < ctx_pic->slice_count; i++) { 170 DXVA_SliceInfo *slice = &ctx_pic->slice[i]; 171 unsigned position = slice->dwSliceDataLocation; 172 unsigned size = slice->dwSliceBitsInBuffer / 8; 173 if (size > end - current) { 174 av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream"); 175 break; 176 } 177 slice->dwSliceDataLocation = current - dxva_data; 178 179 if (i < ctx_pic->slice_count - 1) 180 slice->wNumberMBsInSlice = 181 slice[1].wNumberMBsInSlice - slice[0].wNumberMBsInSlice; 182 else 183 slice->wNumberMBsInSlice = 184 mb_count - slice[0].wNumberMBsInSlice; 185 186 memcpy(current, &ctx_pic->bitstream[position], size); 187 current += size; 188 } 189 if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, 190 DXVA2_BitStreamDateBufferType))) 191 return -1; 192 if (i < ctx_pic->slice_count) 193 return -1; 194 195 memset(bs, 0, sizeof(*bs)); 196 bs->CompressedBufferType = DXVA2_BitStreamDateBufferType; 197 bs->DataSize = current - dxva_data; 198 bs->NumMBsInBuffer = mb_count; 199 200 return ff_dxva2_commit_buffer(avctx, ctx, sc, 201 DXVA2_SliceControlBufferType, 202 ctx_pic->slice, 203 ctx_pic->slice_count * sizeof(*ctx_pic->slice), 204 mb_count); 205} 206 207static int dxva2_mpeg2_start_frame(AVCodecContext *avctx, 208 av_unused const uint8_t *buffer, 209 av_unused uint32_t size) 210{ 211 const struct MpegEncContext *s = avctx->priv_data; 212 struct dxva_context *ctx = avctx->hwaccel_context; 213 struct dxva2_picture_context *ctx_pic = 214 s->current_picture_ptr->hwaccel_picture_private; 215 216 if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0) 217 return -1; 218 assert(ctx_pic); 219 220 fill_picture_parameters(avctx, ctx, s, &ctx_pic->pp); 221 fill_quantization_matrices(avctx, ctx, s, &ctx_pic->qm); 222 223 ctx_pic->slice_count = 0; 224 ctx_pic->bitstream_size = 0; 225 ctx_pic->bitstream = NULL; 226 return 0; 227} 228 229static int dxva2_mpeg2_decode_slice(AVCodecContext *avctx, 230 const uint8_t *buffer, uint32_t size) 231{ 232 const struct MpegEncContext *s = avctx->priv_data; 233 struct dxva2_picture_context *ctx_pic = 234 s->current_picture_ptr->hwaccel_picture_private; 235 unsigned position; 236 237 if (ctx_pic->slice_count >= MAX_SLICES) { 238 avpriv_request_sample(avctx, "%d slices in dxva2", 239 ctx_pic->slice_count); 240 return -1; 241 } 242 if (!ctx_pic->bitstream) 243 ctx_pic->bitstream = buffer; 244 ctx_pic->bitstream_size += size; 245 246 position = buffer - ctx_pic->bitstream; 247 fill_slice(avctx, s, &ctx_pic->slice[ctx_pic->slice_count++], position, 248 buffer, size); 249 return 0; 250} 251 252static int dxva2_mpeg2_end_frame(AVCodecContext *avctx) 253{ 254 struct MpegEncContext *s = avctx->priv_data; 255 struct dxva2_picture_context *ctx_pic = 256 s->current_picture_ptr->hwaccel_picture_private; 257 int ret; 258 259 if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0) 260 return -1; 261 ret = ff_dxva2_common_end_frame(avctx, s->current_picture_ptr->f, 262 &ctx_pic->pp, sizeof(ctx_pic->pp), 263 &ctx_pic->qm, sizeof(ctx_pic->qm), 264 commit_bitstream_and_slice_buffer); 265 if (!ret) 266 ff_mpeg_draw_horiz_band(s, 0, avctx->height); 267 return ret; 268} 269 270AVHWAccel ff_mpeg2_dxva2_hwaccel = { 271 .name = "mpeg2_dxva2", 272 .type = AVMEDIA_TYPE_VIDEO, 273 .id = AV_CODEC_ID_MPEG2VIDEO, 274 .pix_fmt = AV_PIX_FMT_DXVA2_VLD, 275 .start_frame = dxva2_mpeg2_start_frame, 276 .decode_slice = dxva2_mpeg2_decode_slice, 277 .end_frame = dxva2_mpeg2_end_frame, 278 .frame_priv_data_size = sizeof(struct dxva2_picture_context), 279}; 280