From d8039ef8d221ea273aa4f1e62e5df21bf618c772 Mon Sep 17 00:00:00 2001 From: Steve Lhomme Date: Mon, 11 May 2015 10:52:47 +0200 Subject: D3D11va: add a Direct3D11 video decoder similar to DXVA2 Signed-off-by: Luca Barbato --- libavcodec/dxva2_h264.c | 138 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 98 insertions(+), 40 deletions(-) (limited to 'libavcodec/dxva2_h264.c') diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c index a5e9705005..a4a88ce61d 100644 --- a/libavcodec/dxva2_h264.c +++ b/libavcodec/dxva2_h264.c @@ -42,7 +42,7 @@ static void fill_picture_entry(DXVA_PicEntry_H264 *pic, pic->bPicEntry = index | (flag << 7); } -static void fill_picture_parameters(struct dxva_context *ctx, const H264Context *h, +static void fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, const H264Context *h, DXVA_PicParams_H264 *pp) { const H264Picture *current_picture = h->cur_pic_ptr; @@ -51,7 +51,7 @@ static void fill_picture_parameters(struct dxva_context *ctx, const H264Context memset(pp, 0, sizeof(*pp)); /* Configure current picture */ fill_picture_entry(&pp->CurrPic, - ff_dxva2_get_surface_index(ctx, current_picture->f), + ff_dxva2_get_surface_index(avctx, ctx, current_picture->f), h->picture_structure == PICT_BOTTOM_FIELD); /* Configure the set of references */ pp->UsedForReferenceFlags = 0; @@ -67,7 +67,7 @@ static void fill_picture_parameters(struct dxva_context *ctx, const H264Context } if (r) { fill_picture_entry(&pp->RefFrameList[i], - ff_dxva2_get_surface_index(ctx, r->f), + ff_dxva2_get_surface_index(avctx, ctx, r->f), r->long_ref != 0); if ((r->reference & PICT_TOP_FIELD) && r->field_poc[0] != INT_MAX) @@ -114,13 +114,13 @@ static void fill_picture_parameters(struct dxva_context *ctx, const H264Context pp->bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8; pp->bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8; - if (ctx->workaround & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) + if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) pp->Reserved16Bits = 0; - else if (ctx->workaround & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO) + else if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO) pp->Reserved16Bits = 0x34c; else pp->Reserved16Bits = 3; /* FIXME is there a way to detect the right mode ? */ - pp->StatusReportFeedbackNumber = 1 + ctx->report_id++; + pp->StatusReportFeedbackNumber = 1 + DXVA_CONTEXT_REPORT_ID(avctx, ctx)++; pp->CurrFieldOrderCnt[0] = 0; if ((h->picture_structure & PICT_TOP_FIELD) && current_picture->field_poc[0] != INT_MAX) @@ -156,11 +156,11 @@ static void fill_picture_parameters(struct dxva_context *ctx, const H264Context //pp->SliceGroupMap[810]; /* XXX not implemented by Libav */ } -static void fill_scaling_lists(struct dxva_context *ctx, const H264Context *h, DXVA_Qmatrix_H264 *qm) +static void fill_scaling_lists(const AVCodecContext *avctx, AVDXVAContext *ctx, const H264Context *h, DXVA_Qmatrix_H264 *qm) { unsigned i, j; memset(qm, 0, sizeof(*qm)); - if (ctx->workaround & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) { + if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) { for (i = 0; i < 6; i++) for (j = 0; j < 16; j++) qm->bScalingLists4x4[i][j] = h->pps.scaling_matrix4[i][j]; @@ -181,11 +181,11 @@ static void fill_scaling_lists(struct dxva_context *ctx, const H264Context *h, D } } -static int is_slice_short(struct dxva_context *ctx) +static int is_slice_short(const AVCodecContext *avctx, AVDXVAContext *ctx) { - assert(ctx->cfg->ConfigBitstreamRaw == 1 || - ctx->cfg->ConfigBitstreamRaw == 2); - return ctx->cfg->ConfigBitstreamRaw == 2; + assert(DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) == 1 || + DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) == 2); + return DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) == 2; } static void fill_slice_short(DXVA_Slice_H264_Short *slice, @@ -212,7 +212,7 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, { const H264Context *h = avctx->priv_data; H264SliceContext *sl = &h->slice_ctx[0]; - struct dxva_context *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = avctx->hwaccel_context; unsigned list; memset(slice, 0, sizeof(*slice)); @@ -243,10 +243,10 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, const H264Picture *r = sl->ref_list[list][i].parent; unsigned plane; unsigned index; - if (ctx->workaround & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO) - index = ff_dxva2_get_surface_index(ctx, r->f); + if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO) + index = ff_dxva2_get_surface_index(avctx, ctx, r->f); else - index = get_refpic_index(pp, ff_dxva2_get_surface_index(ctx, r->f)); + index = get_refpic_index(pp, ff_dxva2_get_surface_index(avctx, ctx, r->f)); fill_picture_entry(&slice->RefPicList[list][i], index, r->reference == PICT_BOTTOM_FIELD); for (plane = 0; plane < 3; plane++) { @@ -289,12 +289,12 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, } static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, - DXVA2_DecodeBufferDesc *bs, - DXVA2_DecodeBufferDesc *sc) + DECODER_BUFFER_DESC *bs, + DECODER_BUFFER_DESC *sc) { const H264Context *h = avctx->priv_data; const unsigned mb_count = h->mb_width * h->mb_height; - struct dxva_context *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = avctx->hwaccel_context; const H264Picture *current_picture = h->cur_pic_ptr; struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; DXVA_Slice_H264_Short *slice = NULL; @@ -305,12 +305,28 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, unsigned slice_size; unsigned padding; unsigned i; + unsigned type; /* Create an annex B bitstream buffer with only slice NAL and finalize slice */ - if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, - DXVA2_BitStreamDateBufferType, - &dxva_data_ptr, &dxva_size))) - return -1; +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM; + if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, + D3D11VA_CONTEXT(ctx)->decoder, + type, + &dxva_size, &dxva_data_ptr))) + return -1; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + type = DXVA2_BitStreamDateBufferType; + if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder, + type, + &dxva_data_ptr, &dxva_size))) + return -1; + } +#endif dxva_data = dxva_data_ptr; current = dxva_data; @@ -326,7 +342,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, assert(offsetof(DXVA_Slice_H264_Short, SliceBytesInBuffer) == offsetof(DXVA_Slice_H264_Long, SliceBytesInBuffer)); - if (is_slice_short(ctx)) + if (is_slice_short(avctx, ctx)) slice = &ctx_pic->slice_short[i]; else slice = (DXVA_Slice_H264_Short*)&ctx_pic->slice_long[i]; @@ -341,7 +357,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, slice->BSNALunitDataLocation = current - dxva_data; slice->SliceBytesInBuffer = start_code_size + size; - if (!is_slice_short(ctx)) { + if (!is_slice_short(avctx, ctx)) { DXVA_Slice_H264_Long *slice_long = (DXVA_Slice_H264_Long*)slice; if (i < ctx_pic->slice_count - 1) slice_long->NumMbsForSlice = @@ -363,18 +379,43 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, slice->SliceBytesInBuffer += padding; } - if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, - DXVA2_BitStreamDateBufferType))) - return -1; +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) + if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type))) + return -1; +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) + if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type))) + return -1; +#endif if (i < ctx_pic->slice_count) return -1; - memset(bs, 0, sizeof(*bs)); - bs->CompressedBufferType = DXVA2_BitStreamDateBufferType; - bs->DataSize = current - dxva_data; - bs->NumMBsInBuffer = mb_count; +#if CONFIG_D3D11VA + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs; + memset(dsc11, 0, sizeof(*dsc11)); + dsc11->BufferType = type; + dsc11->DataSize = current - dxva_data; + dsc11->NumMBsInBuffer = mb_count; - if (is_slice_short(ctx)) { + type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + DXVA2_DecodeBufferDesc *dsc2 = bs; + memset(dsc2, 0, sizeof(*dsc2)); + dsc2->CompressedBufferType = type; + dsc2->DataSize = current - dxva_data; + dsc2->NumMBsInBuffer = mb_count; + + type = DXVA2_SliceControlBufferType; + } +#endif + + if (is_slice_short(avctx, ctx)) { slice_data = ctx_pic->slice_short; slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_short); } else { @@ -383,7 +424,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, } assert((bs->DataSize & 127) == 0); return ff_dxva2_commit_buffer(avctx, ctx, sc, - DXVA2_SliceControlBufferType, + type, slice_data, slice_size, mb_count); } @@ -393,18 +434,20 @@ static int dxva2_h264_start_frame(AVCodecContext *avctx, av_unused uint32_t size) { const H264Context *h = avctx->priv_data; - struct dxva_context *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = avctx->hwaccel_context; struct dxva2_picture_context *ctx_pic = h->cur_pic_ptr->hwaccel_picture_private; - if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0) + if (DXVA_CONTEXT_DECODER(avctx, ctx) == NULL || + DXVA_CONTEXT_CFG(avctx, ctx) == NULL || + DXVA_CONTEXT_COUNT(avctx, ctx) <= 0) return -1; assert(ctx_pic); /* Fill up DXVA_PicParams_H264 */ - fill_picture_parameters(ctx, h, &ctx_pic->pp); + fill_picture_parameters(avctx, ctx, h, &ctx_pic->pp); /* Fill up DXVA_Qmatrix_H264 */ - fill_scaling_lists(ctx, h, &ctx_pic->qm); + fill_scaling_lists(avctx, ctx, h, &ctx_pic->qm); ctx_pic->slice_count = 0; ctx_pic->bitstream_size = 0; @@ -418,7 +461,7 @@ static int dxva2_h264_decode_slice(AVCodecContext *avctx, { const H264Context *h = avctx->priv_data; const H264SliceContext *sl = &h->slice_ctx[0]; - struct dxva_context *ctx = avctx->hwaccel_context; + AVDXVAContext *ctx = avctx->hwaccel_context; const H264Picture *current_picture = h->cur_pic_ptr; struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; unsigned position; @@ -431,7 +474,7 @@ static int dxva2_h264_decode_slice(AVCodecContext *avctx, ctx_pic->bitstream_size += size; position = buffer - ctx_pic->bitstream; - if (is_slice_short(ctx)) + if (is_slice_short(avctx, ctx)) fill_slice_short(&ctx_pic->slice_short[ctx_pic->slice_count], position, size); else @@ -463,6 +506,7 @@ static int dxva2_h264_end_frame(AVCodecContext *avctx) return ret; } +#if CONFIG_H264_DXVA2_HWACCEL AVHWAccel ff_h264_dxva2_hwaccel = { .name = "h264_dxva2", .type = AVMEDIA_TYPE_VIDEO, @@ -473,3 +517,17 @@ AVHWAccel ff_h264_dxva2_hwaccel = { .end_frame = dxva2_h264_end_frame, .frame_priv_data_size = sizeof(struct dxva2_picture_context), }; +#endif + +#if CONFIG_H264_D3D11VA_HWACCEL +AVHWAccel ff_h264_d3d11va_hwaccel = { + .name = "h264_d3d11va", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .pix_fmt = AV_PIX_FMT_D3D11VA_VLD, + .start_frame = dxva2_h264_start_frame, + .decode_slice = dxva2_h264_decode_slice, + .end_frame = dxva2_h264_end_frame, + .frame_priv_data_size = sizeof(struct dxva2_picture_context), +}; +#endif -- cgit v1.2.3