Skip to content

Commit

Permalink
Добавлена поддержка дополнительных декодеров HEVC Intel для режима D3…
Browse files Browse the repository at this point in the history
…D11 copy back.

Добавлена поддержка декодирования HEVC YUV422 8-бит с помощью декодера HEVC_VLD_Main422_10_Intel.
  • Loading branch information
Aleksoid1978 authored and v0lt committed Feb 20, 2024
1 parent 1dc0307 commit 4b39c78
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 24 deletions.
84 changes: 84 additions & 0 deletions src/ExtLib/ffmpeg/libavcodec/dxva2.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ DEFINE_GUID(ff_DXVA2_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x0
DEFINE_GUID(ff_GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
DEFINE_GUID(ff_IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);

// ==> Start patch MPC
DEFINE_GUID(ff_DXVA2_HEVC_VLD_Main12_Intel, 0x8FF8A3AA, 0xC456, 0x4132, 0xB6, 0xEF, 0x69, 0xD9, 0xDD, 0x72, 0x57, 0x1D);
DEFINE_GUID(ff_DXVA2_HEVC_VLD_Main422_10_Intel, 0xE484DCB8, 0xCAC9, 0x4859, 0x99, 0xF5, 0x5C, 0x0D, 0x45, 0x06, 0x90, 0x89);
DEFINE_GUID(ff_DXVA2_HEVC_VLD_Main422_12_Intel, 0xC23DD857, 0x874B, 0x423C, 0xB6, 0xE0, 0x82, 0xCE, 0xAA, 0x9B, 0x11, 0x8A);
DEFINE_GUID(ff_DXVA2_HEVC_VLD_Main444_Intel, 0x41A5AF96, 0xE415, 0x4B0C, 0x9D, 0x03, 0x90, 0x78, 0x58, 0xE2, 0x3E, 0x78);
DEFINE_GUID(ff_DXVA2_HEVC_VLD_Main444_10_Intel, 0x6A6A81BA, 0x912A, 0x485D, 0xB5, 0x7F, 0xCC, 0xD2, 0xD3, 0x7B, 0x8D, 0x94);
DEFINE_GUID(ff_DXVA2_HEVC_VLD_Main444_12_Intel, 0x5B08E35D, 0x0C66, 0x4C51, 0xA6, 0xF1, 0x89, 0xD0, 0x0C, 0xB2, 0xC1, 0x97);
// ==> End patch MPC

typedef struct dxva_mode {
const GUID *guid;
enum AVCodecID codec;
Expand Down Expand Up @@ -87,6 +96,11 @@ static const int prof_vp9_profile2[] = {AV_PROFILE_VP9_2,
static const int prof_av1_profile0[] = {AV_PROFILE_AV1_MAIN,
AV_PROFILE_UNKNOWN};

// ==> Start patch MPC
static const int prof_hevc_rext[] = {AV_PROFILE_HEVC_REXT,
AV_PROFILE_UNKNOWN};
// ==> End patch MPC

static const dxva_mode dxva_modes[] = {
/* MPEG-2 */
{ &ff_DXVA2_ModeMPEG2_VLD, AV_CODEC_ID_MPEG2VIDEO, prof_mpeg2_main },
Expand Down Expand Up @@ -115,6 +129,16 @@ static const dxva_mode dxva_modes[] = {
/* AV1 */
{ &ff_DXVA2_ModeAV1_VLD_Profile0, AV_CODEC_ID_AV1, prof_av1_profile0 },

// ==> Start patch MPC
/* HEVC/H.265 Rext */
{ &ff_DXVA2_HEVC_VLD_Main12_Intel, AV_CODEC_ID_HEVC, prof_hevc_rext },
{ &ff_DXVA2_HEVC_VLD_Main422_10_Intel, AV_CODEC_ID_HEVC, prof_hevc_rext },
{ &ff_DXVA2_HEVC_VLD_Main422_12_Intel, AV_CODEC_ID_HEVC, prof_hevc_rext },
{ &ff_DXVA2_HEVC_VLD_Main444_Intel, AV_CODEC_ID_HEVC, prof_hevc_rext },
{ &ff_DXVA2_HEVC_VLD_Main444_10_Intel, AV_CODEC_ID_HEVC, prof_hevc_rext },
{ &ff_DXVA2_HEVC_VLD_Main444_12_Intel, AV_CODEC_ID_HEVC, prof_hevc_rext },
// ==> End patch MPC

{ NULL, 0 },
};

Expand Down Expand Up @@ -312,6 +336,16 @@ static int dxva_get_decoder_guid(AVCodecContext *avctx, void *service, void *sur
if (IsEqualGUID(decoder_guid, &ff_DXVADDI_Intel_ModeH264_E))
sctx->workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO;

// ==> Start patch MPC
av_log(avctx, AV_LOG_VERBOSE,
"Used guid : {%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x}",
(unsigned)decoder_guid->Data1, decoder_guid->Data2, decoder_guid->Data3,
decoder_guid->Data4[0], decoder_guid->Data4[1],
decoder_guid->Data4[2], decoder_guid->Data4[3],
decoder_guid->Data4[4], decoder_guid->Data4[5],
decoder_guid->Data4[6], decoder_guid->Data4[7]);
// ==> End patch MPC

return 0;
}

Expand Down Expand Up @@ -469,6 +503,15 @@ static DXGI_FORMAT d3d11va_map_sw_to_hw_format(enum AVPixelFormat pix_fmt)
case AV_PIX_FMT_NV12: return DXGI_FORMAT_NV12;
case AV_PIX_FMT_P010: return DXGI_FORMAT_P010;
case AV_PIX_FMT_YUV420P: return DXGI_FORMAT_420_OPAQUE;
// ==> Start patch MPC
case AV_PIX_FMT_P016: return DXGI_FORMAT_P016;
case AV_PIX_FMT_YUYV422: return DXGI_FORMAT_YUY2;
case AV_PIX_FMT_Y210: return DXGI_FORMAT_Y210;
case AV_PIX_FMT_Y212: return DXGI_FORMAT_Y216;
case AV_PIX_FMT_VUYX: return DXGI_FORMAT_AYUV;
case AV_PIX_FMT_XV30: return DXGI_FORMAT_Y410;
case AV_PIX_FMT_XV36: return DXGI_FORMAT_Y416;
// ==> End patch MPC
default: return DXGI_FORMAT_UNKNOWN;
}
}
Expand Down Expand Up @@ -600,6 +643,41 @@ static void ff_dxva2_unlock(AVCodecContext *avctx)
#endif
}

// ==> Start patch MPC
static enum AVPixelFormat map_sw_pix_format(enum AVPixelFormat pix_fmt, enum AVPixelFormat hw_pix_fmt)
{
#if CONFIG_D3D11VA
if (hw_pix_fmt == AV_PIX_FMT_D3D11) {
switch (pix_fmt)
{
case AV_PIX_FMT_YUV420P10:
case AV_PIX_FMT_P010:
return AV_PIX_FMT_P010;
case AV_PIX_FMT_YUV420P12:
return AV_PIX_FMT_P016;
case AV_PIX_FMT_YUV422P:
return AV_PIX_FMT_YUYV422;
case AV_PIX_FMT_YUV422P10:
return AV_PIX_FMT_Y210;
case AV_PIX_FMT_YUV444P:
return AV_PIX_FMT_VUYX;
case AV_PIX_FMT_YUV444P10:
return AV_PIX_FMT_XV30;
case AV_PIX_FMT_YUV422P12:
return AV_PIX_FMT_Y212;
case AV_PIX_FMT_YUV444P12:
return AV_PIX_FMT_XV36;
case AV_PIX_FMT_NV12:
default:
return AV_PIX_FMT_NV12;
}
}
#endif
return pix_fmt == AV_PIX_FMT_YUV420P10 ?
AV_PIX_FMT_P010 : AV_PIX_FMT_NV12;
}
// ==> End patch MPC

int ff_dxva2_common_frame_params(AVCodecContext *avctx,
AVBufferRef *hw_frames_ctx)
{
Expand Down Expand Up @@ -637,8 +715,14 @@ int ff_dxva2_common_frame_params(AVCodecContext *avctx,
else
num_surfaces += 2;

// ==> Start patch MPC
/*
frames_ctx->sw_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
AV_PIX_FMT_P010 : AV_PIX_FMT_NV12;
*/
frames_ctx->sw_format = map_sw_pix_format(avctx->sw_pix_fmt, frames_ctx->format);
// ==> End patch MPC

frames_ctx->width = FFALIGN(avctx->coded_width, surface_alignment);
frames_ctx->height = FFALIGN(avctx->coded_height, surface_alignment);
frames_ctx->initial_pool_size = num_surfaces;
Expand Down
20 changes: 14 additions & 6 deletions src/ExtLib/ffmpeg/libavutil/hwcontext_d3d11va.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,21 +86,29 @@ static const struct {
} supported_formats[] = {
{ DXGI_FORMAT_NV12, AV_PIX_FMT_NV12 },
{ DXGI_FORMAT_P010, AV_PIX_FMT_P010 },
{ DXGI_FORMAT_B8G8R8A8_UNORM, AV_PIX_FMT_BGRA },
{ DXGI_FORMAT_R10G10B10A2_UNORM, AV_PIX_FMT_X2BGR10 },
{ DXGI_FORMAT_R16G16B16A16_FLOAT, AV_PIX_FMT_RGBAF16 },
{ DXGI_FORMAT_AYUV, AV_PIX_FMT_VUYX },
{ DXGI_FORMAT_YUY2, AV_PIX_FMT_YUYV422 },
{ DXGI_FORMAT_Y210, AV_PIX_FMT_Y210 },
{ DXGI_FORMAT_Y410, AV_PIX_FMT_XV30 },
{ DXGI_FORMAT_P016, AV_PIX_FMT_P012 },
{ DXGI_FORMAT_Y216, AV_PIX_FMT_Y212 },
{ DXGI_FORMAT_Y416, AV_PIX_FMT_XV36 },
// Special opaque formats. The pix_fmt is merely a place holder, as the
// opaque format cannot be accessed directly.
{ DXGI_FORMAT_420_OPAQUE, AV_PIX_FMT_YUV420P },
// ==> Start patch MPC
// 420 12bit
{ DXGI_FORMAT_P016, AV_PIX_FMT_P016 },
{ DXGI_FORMAT_P016, AV_PIX_FMT_YUV420P12 },
// 422 8/10/12 bit
{ DXGI_FORMAT_YUY2, AV_PIX_FMT_YUV422P },
{ DXGI_FORMAT_Y210, AV_PIX_FMT_YUV422P10 },
{ DXGI_FORMAT_Y216, AV_PIX_FMT_YUV422P12 },
// 444 8/10/12 bit
{ DXGI_FORMAT_AYUV, AV_PIX_FMT_YUV444P },
{ DXGI_FORMAT_Y410, AV_PIX_FMT_YUV444P10 },
{ DXGI_FORMAT_Y416, AV_PIX_FMT_YUV444P12 },
// ==> End patch MPC
// Special opaque formats. The pix_fmt is merely a place holder, as the
// opaque format cannot be accessed directly.
{ DXGI_FORMAT_420_OPAQUE, AV_PIX_FMT_YUV420P },
};

static void d3d11va_default_lock(void *ctx)
Expand Down
53 changes: 35 additions & 18 deletions src/filters/transform/MPCVideoDec/MPCVideoDec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ struct {
{ AV_CODEC_ID_H264, DXVA2_H264_VLD_Intel, false },
// HEVC Intel
{ AV_CODEC_ID_HEVC, DXVA2_HEVC_VLD_Main12_Intel, false, AV_PIX_FMT_YUV420P12 },
{ AV_CODEC_ID_HEVC, DXVA2_HEVC_VLD_Main422_10_Intel, false, AV_PIX_FMT_YUV422P },
{ AV_CODEC_ID_HEVC, DXVA2_HEVC_VLD_Main422_10_Intel, false, AV_PIX_FMT_YUV422P10 },
{ AV_CODEC_ID_HEVC, DXVA2_HEVC_VLD_Main422_12_Intel, false, AV_PIX_FMT_YUV422P12 },
{ AV_CODEC_ID_HEVC, DXVA2_HEVC_VLD_Main444_Intel, false, AV_PIX_FMT_YUV444P },
Expand Down Expand Up @@ -3652,27 +3653,25 @@ HRESULT CMPCVideoDecFilter::DecodeInternal(AVPacket *avpkt, REFERENCE_TIME rtSta
auto frames_ctx = (AVHWFramesContext*)hw_frame->hw_frames_ctx->data;

if (frames_ctx->format == AV_PIX_FMT_D3D11) {
const auto dxgi_format =
(frames_ctx->sw_format == AV_PIX_FMT_P010) ? DXGI_FORMAT_P010 :
(frames_ctx->sw_format == AV_PIX_FMT_NV12) ? DXGI_FORMAT_NV12 :
DXGI_FORMAT_UNKNOWN; // formal assignment

auto device_hwctx = reinterpret_cast<AVD3D11VADeviceContext*>(frames_ctx->device_ctx->hwctx);
auto texture = reinterpret_cast<ID3D11Texture2D*>(hw_frame->data[0]);
auto index = reinterpret_cast<intptr_t>(hw_frame->data[1]);

D3D11_TEXTURE2D_DESC inputTexDesc = {};
texture->GetDesc(&inputTexDesc);

D3D11_TEXTURE2D_DESC texDesc = {};
if (m_pStagingD3D11Texture2D) {
m_pStagingD3D11Texture2D->GetDesc(&texDesc);
if (texDesc.Format != dxgi_format || texDesc.Width != frames_ctx->width || texDesc.Height != frames_ctx->height) {
if (texDesc.Format != inputTexDesc.Format || texDesc.Width != inputTexDesc.Width || texDesc.Height != inputTexDesc.Height) {
m_pStagingD3D11Texture2D.Release();
}
}
if (!m_pStagingD3D11Texture2D) {
texDesc.Width = frames_ctx->width;
texDesc.Height = frames_ctx->height;
texDesc.Width = inputTexDesc.Width;
texDesc.Height = inputTexDesc.Height;
texDesc.MipLevels = 1;
texDesc.Format = dxgi_format;
texDesc.Format = inputTexDesc.Format;
texDesc.SampleDesc = { 1, 0 };
texDesc.ArraySize = 1;
texDesc.Usage = D3D11_USAGE_STAGING;
Expand All @@ -3694,17 +3693,35 @@ HRESULT CMPCVideoDecFilter::DecodeInternal(AVPacket *avpkt, REFERENCE_TIME rtSta
DLog(L"CMPCVideoDecFilter::DecodeInternal() : ID3D11DeviceContext::Map() failed : %s", HR2Str(hr));
CLEAR_AND_CONTINUE;
}
m_pFrame->data[0] = (BYTE*)mappedResource.pData;
m_pFrame->data[1] = m_pFrame->data[0] + texDesc.Height * mappedResource.RowPitch;
m_pFrame->linesize[0] = mappedResource.RowPitch;
m_pFrame->linesize[1] = mappedResource.RowPitch;
m_pFrame->format = frames_ctx->sw_format;
m_pFrame->width = hw_frame->width;
m_pFrame->height = hw_frame->height;

m_FormatConverter.Converting(pDataOut, m_pFrame);
int codedbytes = 1;
switch (frames_ctx->sw_format) {
case AV_PIX_FMT_P010:
case AV_PIX_FMT_P016:
case AV_PIX_FMT_YUYV422:
codedbytes = 2;
break;
case AV_PIX_FMT_Y210:
case AV_PIX_FMT_Y212:
case AV_PIX_FMT_VUYX:
case AV_PIX_FMT_XV30:
codedbytes = 4;
break;
case AV_PIX_FMT_XV36:
codedbytes = 8;
break;
}

auto width = mappedResource.RowPitch / codedbytes;

av_image_fill_linesizes(m_pFrame->linesize, frames_ctx->sw_format, width);
av_image_fill_pointers(m_pFrame->data, frames_ctx->sw_format, texDesc.Height, reinterpret_cast<uint8_t*>(mappedResource.pData), m_pFrame->linesize);

m_pFrame->data[0] = m_pFrame->data[1] = nullptr;
m_pFrame->format = frames_ctx->sw_format;
m_pFrame->width = hw_frame->width;
m_pFrame->height = hw_frame->height;

m_FormatConverter.Converting(pDataOut, m_pFrame);

device_hwctx->device_context->Unmap(m_pStagingD3D11Texture2D, 0);

Expand Down

0 comments on commit 4b39c78

Please sign in to comment.