00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "dxva2_internal.h"
00024 #include "vc1.h"
00025 #include "vc1data.h"
00026
00027 struct dxva2_picture_context {
00028 DXVA_PictureParameters pp;
00029 DXVA_SliceInfo si;
00030
00031 const uint8_t *bitstream;
00032 unsigned bitstream_size;
00033 };
00034
00035 static void fill_picture_parameters(AVCodecContext *avctx,
00036 struct dxva_context *ctx, const VC1Context *v,
00037 DXVA_PictureParameters *pp)
00038 {
00039 const MpegEncContext *s = &v->s;
00040 const Picture *current_picture = s->current_picture_ptr;
00041
00042 memset(pp, 0, sizeof(*pp));
00043 pp->wDecodedPictureIndex =
00044 pp->wDeblockedPictureIndex = ff_dxva2_get_surface_index(ctx, current_picture);
00045 if (s->pict_type != AV_PICTURE_TYPE_I)
00046 pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, &s->last_picture);
00047 else
00048 pp->wForwardRefPictureIndex = 0xffff;
00049 if (s->pict_type == AV_PICTURE_TYPE_B)
00050 pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, &s->next_picture);
00051 else
00052 pp->wBackwardRefPictureIndex = 0xffff;
00053 if (v->profile == PROFILE_ADVANCED) {
00054
00055 pp->wPicWidthInMBminus1 = avctx->width - 1;
00056 pp->wPicHeightInMBminus1= avctx->height - 1;
00057 } else {
00058
00059 pp->wPicWidthInMBminus1 = s->mb_width - 1;
00060 pp->wPicHeightInMBminus1= s->mb_height - 1;
00061 }
00062 pp->bMacroblockWidthMinus1 = 15;
00063 pp->bMacroblockHeightMinus1 = 15;
00064 pp->bBlockWidthMinus1 = 7;
00065 pp->bBlockHeightMinus1 = 7;
00066 pp->bBPPminus1 = 7;
00067 if (s->picture_structure & PICT_TOP_FIELD)
00068 pp->bPicStructure |= 0x01;
00069 if (s->picture_structure & PICT_BOTTOM_FIELD)
00070 pp->bPicStructure |= 0x02;
00071 pp->bSecondField = v->interlace && v->fcm != 0x03 && !s->first_field;
00072 pp->bPicIntra = s->pict_type == AV_PICTURE_TYPE_I;
00073 pp->bPicBackwardPrediction = s->pict_type == AV_PICTURE_TYPE_B;
00074 pp->bBidirectionalAveragingMode = (1 << 7) |
00075 ((ctx->cfg->ConfigIntraResidUnsigned != 0) << 6) |
00076 ((ctx->cfg->ConfigResidDiffAccelerator != 0) << 5) |
00077 ((v->lumscale != 32 || v->lumshift != 0) << 4) |
00078 ((v->profile == PROFILE_ADVANCED) << 3);
00079 pp->bMVprecisionAndChromaRelation = ((v->mv_mode == MV_PMODE_1MV_HPEL_BILIN) << 3) |
00080 (1 << 2) |
00081 (0 << 1) |
00082 (!s->quarter_sample );
00083 pp->bChromaFormat = v->chromaformat;
00084 ctx->report_id++;
00085 if (ctx->report_id >= (1 << 16))
00086 ctx->report_id = 1;
00087 pp->bPicScanFixed = ctx->report_id >> 8;
00088 pp->bPicScanMethod = ctx->report_id & 0xff;
00089 pp->bPicReadbackRequests = 0;
00090 pp->bRcontrol = v->rnd;
00091 pp->bPicSpatialResid8 = (v->panscanflag << 7) |
00092 (v->refdist_flag << 6) |
00093 (s->loop_filter << 5) |
00094 (v->fastuvmc << 4) |
00095 (v->extended_mv << 3) |
00096 (v->dquant << 1) |
00097 (v->vstransform );
00098 pp->bPicOverflowBlocks = (v->quantizer_mode << 6) |
00099 (v->multires << 5) |
00100 (s->resync_marker << 4) |
00101 (v->rangered << 3) |
00102 (s->max_b_frames );
00103 pp->bPicExtrapolation = (!v->interlace || v->fcm == 0x00) ? 1 : 2;
00104 pp->bPicDeblocked = ((v->profile != PROFILE_ADVANCED && v->rangeredfrm) << 5) |
00105 (s->loop_filter << 1);
00106 pp->bPicDeblockConfined = (v->postprocflag << 7) |
00107 (v->broadcast << 6) |
00108 (v->interlace << 5) |
00109 (v->tfcntrflag << 4) |
00110 (v->finterpflag << 3) |
00111 ((s->pict_type != AV_PICTURE_TYPE_B) << 2) |
00112 (v->psf << 1) |
00113 (v->extended_dmv );
00114 if (s->pict_type != AV_PICTURE_TYPE_I)
00115 pp->bPic4MVallowed = v->mv_mode == MV_PMODE_MIXED_MV ||
00116 (v->mv_mode == MV_PMODE_INTENSITY_COMP &&
00117 v->mv_mode2 == MV_PMODE_MIXED_MV);
00118 if (v->profile == PROFILE_ADVANCED)
00119 pp->bPicOBMC = (v->range_mapy_flag << 7) |
00120 (v->range_mapy << 4) |
00121 (v->range_mapuv_flag << 3) |
00122 (v->range_mapuv );
00123 pp->bPicBinPB = 0;
00124 pp->bMV_RPS = 0;
00125 pp->bReservedBits = 0;
00126 if (s->picture_structure == PICT_FRAME) {
00127 pp->wBitstreamFcodes = v->lumscale;
00128 pp->wBitstreamPCEelements = v->lumshift;
00129 } else {
00130
00131 pp->wBitstreamFcodes = (v->lumscale << 8) | v->lumscale;
00132 pp->wBitstreamPCEelements = (v->lumshift << 8) | v->lumshift;
00133 }
00134 pp->bBitstreamConcealmentNeed = 0;
00135 pp->bBitstreamConcealmentMethod = 0;
00136 }
00137
00138 static void fill_slice(AVCodecContext *avctx, DXVA_SliceInfo *slice,
00139 unsigned position, unsigned size)
00140 {
00141 const VC1Context *v = avctx->priv_data;
00142 const MpegEncContext *s = &v->s;
00143
00144 memset(slice, 0, sizeof(*slice));
00145 slice->wHorizontalPosition = 0;
00146 slice->wVerticalPosition = s->mb_y;
00147 slice->dwSliceBitsInBuffer = 8 * size;
00148 slice->dwSliceDataLocation = position;
00149 slice->bStartCodeBitOffset = 0;
00150 slice->bReservedBits = 0;
00151 slice->wMBbitOffset = get_bits_count(&s->gb);
00152 slice->wNumberMBsInSlice = s->mb_width * s->mb_height;
00153 slice->wQuantizerScaleCode = v->pq;
00154 slice->wBadSliceChopping = 0;
00155 }
00156
00157 static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
00158 DXVA2_DecodeBufferDesc *bs,
00159 DXVA2_DecodeBufferDesc *sc)
00160 {
00161 const VC1Context *v = avctx->priv_data;
00162 struct dxva_context *ctx = avctx->hwaccel_context;
00163 const MpegEncContext *s = &v->s;
00164 struct dxva2_picture_context *ctx_pic = s->current_picture_ptr->hwaccel_picture_private;
00165
00166 DXVA_SliceInfo *slice = &ctx_pic->si;
00167
00168 static const uint8_t start_code[] = { 0, 0, 1, 0x0d };
00169 const unsigned start_code_size = avctx->codec_id == CODEC_ID_VC1 ? sizeof(start_code) : 0;
00170 const unsigned slice_size = slice->dwSliceBitsInBuffer / 8;
00171 const unsigned padding = 128 - ((start_code_size + slice_size) & 127);
00172 const unsigned data_size = start_code_size + slice_size + padding;
00173
00174 uint8_t *dxva_data;
00175 unsigned dxva_size;
00176 int result;
00177
00178 if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder,
00179 DXVA2_BitStreamDateBufferType,
00180 &dxva_data, &dxva_size)))
00181 return -1;
00182
00183 result = data_size <= dxva_size ? 0 : -1;
00184 if (!result) {
00185 if (start_code_size > 0)
00186 memcpy(dxva_data, start_code, start_code_size);
00187 memcpy(dxva_data + start_code_size,
00188 ctx_pic->bitstream + slice->dwSliceDataLocation, slice_size);
00189 if (padding > 0)
00190 memset(dxva_data + start_code_size + slice_size, 0, padding);
00191 slice->dwSliceBitsInBuffer = 8 * data_size;
00192 }
00193 if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder,
00194 DXVA2_BitStreamDateBufferType)))
00195 return -1;
00196 if (result)
00197 return result;
00198
00199 memset(bs, 0, sizeof(*bs));
00200 bs->CompressedBufferType = DXVA2_BitStreamDateBufferType;
00201 bs->DataSize = data_size;
00202 bs->NumMBsInBuffer = s->mb_width * s->mb_height;
00203 assert((bs->DataSize & 127) == 0);
00204
00205 return ff_dxva2_commit_buffer(avctx, ctx, sc,
00206 DXVA2_SliceControlBufferType,
00207 slice, sizeof(*slice), bs->NumMBsInBuffer);
00208 }
00209
00210 static int start_frame(AVCodecContext *avctx,
00211 av_unused const uint8_t *buffer,
00212 av_unused uint32_t size)
00213 {
00214 const VC1Context *v = avctx->priv_data;
00215 struct dxva_context *ctx = avctx->hwaccel_context;
00216 struct dxva2_picture_context *ctx_pic = v->s.current_picture_ptr->hwaccel_picture_private;
00217
00218 if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0)
00219 return -1;
00220 assert(ctx_pic);
00221
00222 fill_picture_parameters(avctx, ctx, v, &ctx_pic->pp);
00223
00224 ctx_pic->bitstream_size = 0;
00225 ctx_pic->bitstream = NULL;
00226 return 0;
00227 }
00228
00229 static int decode_slice(AVCodecContext *avctx,
00230 const uint8_t *buffer, uint32_t size)
00231 {
00232 const VC1Context *v = avctx->priv_data;
00233 const Picture *current_picture = v->s.current_picture_ptr;
00234 struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private;
00235
00236 if (ctx_pic->bitstream_size > 0)
00237 return -1;
00238
00239 if (avctx->codec_id == CODEC_ID_VC1 &&
00240 size >= 4 && IS_MARKER(AV_RB32(buffer))) {
00241 buffer += 4;
00242 size -= 4;
00243 }
00244
00245 ctx_pic->bitstream_size = size;
00246 ctx_pic->bitstream = buffer;
00247
00248 fill_slice(avctx, &ctx_pic->si, 0, size);
00249 return 0;
00250 }
00251
00252 static int end_frame(AVCodecContext *avctx)
00253 {
00254 VC1Context *v = avctx->priv_data;
00255 struct dxva2_picture_context *ctx_pic = v->s.current_picture_ptr->hwaccel_picture_private;
00256
00257 if (ctx_pic->bitstream_size <= 0)
00258 return -1;
00259
00260 return ff_dxva2_common_end_frame(avctx, &v->s,
00261 &ctx_pic->pp, sizeof(ctx_pic->pp),
00262 NULL, 0,
00263 commit_bitstream_and_slice_buffer);
00264 }
00265
00266 #if CONFIG_WMV3_DXVA2_HWACCEL
00267 AVHWAccel ff_wmv3_dxva2_hwaccel = {
00268 .name = "wmv3_dxva2",
00269 .type = AVMEDIA_TYPE_VIDEO,
00270 .id = CODEC_ID_WMV3,
00271 .pix_fmt = PIX_FMT_DXVA2_VLD,
00272 .capabilities = 0,
00273 .start_frame = start_frame,
00274 .decode_slice = decode_slice,
00275 .end_frame = end_frame,
00276 .priv_data_size = sizeof(struct dxva2_picture_context),
00277 };
00278 #endif
00279
00280 AVHWAccel ff_vc1_dxva2_hwaccel = {
00281 .name = "vc1_dxva2",
00282 .type = AVMEDIA_TYPE_VIDEO,
00283 .id = CODEC_ID_VC1,
00284 .pix_fmt = PIX_FMT_DXVA2_VLD,
00285 .capabilities = 0,
00286 .start_frame = start_frame,
00287 .decode_slice = decode_slice,
00288 .end_frame = end_frame,
00289 .priv_data_size = sizeof(struct dxva2_picture_context),
00290 };
00291