int ff_dxva2_commit_buffer(AVCodecContext *avctx, struct dxva_context *ctx, DXVA2_DecodeBufferDesc *dsc, unsigned type, const void *data, unsigned size, unsigned mb_count) { void *dxva_data; unsigned dxva_size; int result; if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, type, &dxva_data, &dxva_size))) { av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %d\n", type); return -1; } if (size <= dxva_size) { memcpy(dxva_data, data, size); memset(dsc, 0, sizeof(*dsc)); dsc->CompressedBufferType = type; dsc->DataSize = size; dsc->NumMBsInBuffer = mb_count; result = 0; } else { av_log(avctx, AV_LOG_ERROR, "Buffer for type %d was too small\n", type); result = -1; } if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, type))) { av_log(avctx, AV_LOG_ERROR, "Failed to release buffer type %d\n", type); result = -1; } return result; }
static inline void test_buffer(IDirectXVideoDecoder *decoder, UINT type, const char *name) { void *buffer; UINT size; HRESULT hr; hr = IDirectXVideoDecoder_GetBuffer(decoder, type, &buffer, &size); ok(!hr, "Failed to get buffer %s: %x\n", name, hr); if (!hr) IDirectXVideoDecoder_ReleaseBuffer(decoder, type); }
static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, DXVA2_DecodeBufferDesc *bs, DXVA2_DecodeBufferDesc *sc) { const H264Context *h = avctx->priv_data; const MpegEncContext *s = &h->s; const unsigned mb_count = s->mb_width * s->mb_height; struct dxva_context *ctx = avctx->hwaccel_context; const Picture *current_picture = h->s.current_picture_ptr; struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; DXVA_Slice_H264_Short *slice = NULL; uint8_t *dxva_data, *current, *end; unsigned dxva_size; void *slice_data; unsigned slice_size; unsigned padding; unsigned i; /* Create an annex B bitstream buffer with only slice NAL and finalize slice */ if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, DXVA2_BitStreamDateBufferType, &dxva_data, &dxva_size))) return -1; current = dxva_data; end = dxva_data + dxva_size; for (i = 0; i < ctx_pic->slice_count; i++) { static const uint8_t start_code[] = { 0, 0, 1 }; static const unsigned start_code_size = sizeof(start_code); unsigned position, size; assert(offsetof(DXVA_Slice_H264_Short, BSNALunitDataLocation) == offsetof(DXVA_Slice_H264_Long, BSNALunitDataLocation)); assert(offsetof(DXVA_Slice_H264_Short, SliceBytesInBuffer) == offsetof(DXVA_Slice_H264_Long, SliceBytesInBuffer)); if (is_slice_short(ctx)) slice = &ctx_pic->slice_short[i]; else slice = (DXVA_Slice_H264_Short*)&ctx_pic->slice_long[i]; position = slice->BSNALunitDataLocation; size = slice->SliceBytesInBuffer; if (start_code_size + size > end - current) { av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream"); break; } slice->BSNALunitDataLocation = current - dxva_data; slice->SliceBytesInBuffer = start_code_size + size; if (!is_slice_short(ctx)) { DXVA_Slice_H264_Long *slice_long = (DXVA_Slice_H264_Long*)slice; if (i < ctx_pic->slice_count - 1) slice_long->NumMbsForSlice = slice_long[1].first_mb_in_slice - slice_long[0].first_mb_in_slice; else slice_long->NumMbsForSlice = mb_count - slice_long->first_mb_in_slice; } memcpy(current, start_code, start_code_size); current += start_code_size; memcpy(current, &ctx_pic->bitstream[position], size); current += size; } padding = FFMIN(128 - ((current - dxva_data) & 127), end - current); if (slice && padding > 0) { memset(current, 0, padding); current += padding; slice->SliceBytesInBuffer += padding; } if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, DXVA2_BitStreamDateBufferType))) return -1; 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 (is_slice_short(ctx)) { slice_data = ctx_pic->slice_short; slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_short); } else { slice_data = ctx_pic->slice_long; slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_long); } assert((bs->DataSize & 127) == 0); return ff_dxva2_commit_buffer(avctx, ctx, sc, DXVA2_SliceControlBufferType, slice_data, slice_size, mb_count); }
static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, DECODER_BUFFER_DESC *bs, DECODER_BUFFER_DESC *sc) { const H264Context *h = avctx->priv_data; const unsigned mb_count = h->mb_width * h->mb_height; 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; void *dxva_data_ptr = NULL; uint8_t *dxva_data, *current, *end; unsigned dxva_size = 0; void *slice_data; unsigned slice_size; unsigned padding; unsigned i; unsigned type; /* Create an annex B bitstream buffer with only slice NAL and finalize slice */ #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; end = dxva_data + dxva_size; for (i = 0; i < ctx_pic->slice_count; i++) { static const uint8_t start_code[] = { 0, 0, 1 }; static const unsigned start_code_size = sizeof(start_code); unsigned position, size; assert(offsetof(DXVA_Slice_H264_Short, BSNALunitDataLocation) == offsetof(DXVA_Slice_H264_Long, BSNALunitDataLocation)); assert(offsetof(DXVA_Slice_H264_Short, SliceBytesInBuffer) == offsetof(DXVA_Slice_H264_Long, SliceBytesInBuffer)); if (is_slice_short(avctx, ctx)) slice = &ctx_pic->slice_short[i]; else slice = (DXVA_Slice_H264_Short*)&ctx_pic->slice_long[i]; position = slice->BSNALunitDataLocation; size = slice->SliceBytesInBuffer; if (start_code_size + size > end - current) { av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream"); break; } slice->BSNALunitDataLocation = current - dxva_data; slice->SliceBytesInBuffer = start_code_size + size; 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 = slice_long[1].first_mb_in_slice - slice_long[0].first_mb_in_slice; else slice_long->NumMbsForSlice = mb_count - slice_long->first_mb_in_slice; } memcpy(current, start_code, start_code_size); current += start_code_size; memcpy(current, &ctx_pic->bitstream[position], size); current += size; } padding = FFMIN(128 - ((current - dxva_data) & 127), end - current); if (slice && padding > 0) { memset(current, 0, padding); current += padding; slice->SliceBytesInBuffer += padding; } #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; #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; type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL; av_assert0((dsc11->DataSize & 127) == 0); } #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; av_assert0((dsc2->DataSize & 127) == 0); } #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 { slice_data = ctx_pic->slice_long; slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_long); } return ff_dxva2_commit_buffer(avctx, ctx, sc, type, slice_data, slice_size, mb_count); }
int ff_dxva2_commit_buffer(AVCodecContext *avctx, AVDXVAContext *ctx, DECODER_BUFFER_DESC *dsc, unsigned type, const void *data, unsigned size, unsigned mb_count) { void *dxva_data; unsigned dxva_size; int result; HRESULT hr = 0; #if CONFIG_D3D11VA if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) hr = ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type, &dxva_size, &dxva_data); #endif #if CONFIG_DXVA2 if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) hr = IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder, type, &dxva_data, &dxva_size); #endif if (FAILED(hr)) { av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %u: 0x%lx\n", type, hr); return -1; } if (size <= dxva_size) { memcpy(dxva_data, data, size); #if CONFIG_D3D11VA if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = dsc; memset(dsc11, 0, sizeof(*dsc11)); dsc11->BufferType = type; dsc11->DataSize = size; dsc11->NumMBsInBuffer = mb_count; } #endif #if CONFIG_DXVA2 if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { DXVA2_DecodeBufferDesc *dsc2 = dsc; memset(dsc2, 0, sizeof(*dsc2)); dsc2->CompressedBufferType = type; dsc2->DataSize = size; dsc2->NumMBsInBuffer = mb_count; } #endif result = 0; } else { av_log(avctx, AV_LOG_ERROR, "Buffer for type %u was too small\n", type); result = -1; } #if CONFIG_D3D11VA if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) hr = ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type); #endif #if CONFIG_DXVA2 if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) hr = IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type); #endif if (FAILED(hr)) { av_log(avctx, AV_LOG_ERROR, "Failed to release buffer type %u: 0x%lx\n", type, hr); result = -1; } return result; }