mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-16 21:40:38 +01:00
d3d12: Add HEVC Decode/Encode
Reviewed-by: Giancarlo Devich <gdevich@microsoft.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18328>
This commit is contained in:
parent
f2d172a8be
commit
da11684e9d
27 changed files with 4601 additions and 98 deletions
|
|
@ -467,8 +467,10 @@ d3d12_convert_pipe_video_profile_to_dxgi_format(enum pipe_video_profile profile)
|
||||||
case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
|
case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
|
||||||
case PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED:
|
case PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED:
|
||||||
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
|
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
|
||||||
|
case PIPE_VIDEO_PROFILE_HEVC_MAIN:
|
||||||
return DXGI_FORMAT_NV12;
|
return DXGI_FORMAT_NV12;
|
||||||
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10:
|
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10:
|
||||||
|
case PIPE_VIDEO_PROFILE_HEVC_MAIN_10:
|
||||||
return DXGI_FORMAT_P010;
|
return DXGI_FORMAT_P010;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
#include "d3d12_surface.h"
|
#include "d3d12_surface.h"
|
||||||
#include "d3d12_video_dec.h"
|
#include "d3d12_video_dec.h"
|
||||||
#include "d3d12_video_dec_h264.h"
|
#include "d3d12_video_dec_h264.h"
|
||||||
|
#include "d3d12_video_dec_hevc.h"
|
||||||
#include "d3d12_video_buffer.h"
|
#include "d3d12_video_buffer.h"
|
||||||
#include "d3d12_residency.h"
|
#include "d3d12_residency.h"
|
||||||
|
|
||||||
|
|
@ -298,14 +299,20 @@ d3d12_video_decoder_store_upper_layer_references(struct d3d12_video_decoder *pD3
|
||||||
struct pipe_video_buffer *target,
|
struct pipe_video_buffer *target,
|
||||||
struct pipe_picture_desc *picture)
|
struct pipe_picture_desc *picture)
|
||||||
{
|
{
|
||||||
|
pD3D12Dec->m_pCurrentDecodeTarget = target;
|
||||||
switch (pD3D12Dec->m_d3d12DecProfileType) {
|
switch (pD3D12Dec->m_d3d12DecProfileType) {
|
||||||
case d3d12_video_decode_profile_type_h264:
|
case d3d12_video_decode_profile_type_h264:
|
||||||
{
|
{
|
||||||
pipe_h264_picture_desc *pPicControlH264 = (pipe_h264_picture_desc *) picture;
|
pipe_h264_picture_desc *pPicControlH264 = (pipe_h264_picture_desc *) picture;
|
||||||
pD3D12Dec->m_pCurrentDecodeTarget = target;
|
|
||||||
pD3D12Dec->m_pCurrentReferenceTargets = pPicControlH264->ref;
|
pD3D12Dec->m_pCurrentReferenceTargets = pPicControlH264->ref;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case d3d12_video_decode_profile_type_hevc:
|
||||||
|
{
|
||||||
|
pipe_h265_picture_desc *pPicControlHevc = (pipe_h265_picture_desc *) picture;
|
||||||
|
pD3D12Dec->m_pCurrentReferenceTargets = pPicControlHevc->ref;
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported d3d12_video_decode_profile_type");
|
unreachable("Unsupported d3d12_video_decode_profile_type");
|
||||||
|
|
@ -493,7 +500,7 @@ d3d12_video_decoder_end_frame(struct pipe_video_codec *codec,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pD3D12Dec->m_InverseQuantMatrixBuffer.size() > 0) {
|
if (pD3D12Dec->qp_matrix_frame_argument_enabled && (pD3D12Dec->m_InverseQuantMatrixBuffer.size() > 0)) {
|
||||||
d3d12InputArguments.NumFrameArguments++;
|
d3d12InputArguments.NumFrameArguments++;
|
||||||
d3d12InputArguments.FrameArguments[d3d12InputArguments.NumFrameArguments - 1] = {
|
d3d12InputArguments.FrameArguments[d3d12InputArguments.NumFrameArguments - 1] = {
|
||||||
D3D12_VIDEO_DECODE_ARGUMENT_TYPE_INVERSE_QUANTIZATION_MATRIX,
|
D3D12_VIDEO_DECODE_ARGUMENT_TYPE_INVERSE_QUANTIZATION_MATRIX,
|
||||||
|
|
@ -992,6 +999,13 @@ d3d12_video_decoder_prepare_for_decode_frame(struct d3d12_video_decoder *pD3D12D
|
||||||
currentFrameDPBEntrySubresource);
|
currentFrameDPBEntrySubresource);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case d3d12_video_decode_profile_type_hevc:
|
||||||
|
{
|
||||||
|
d3d12_video_decoder_prepare_current_frame_references_hevc(pD3D12Dec,
|
||||||
|
pCurrentFrameDPBEntry,
|
||||||
|
currentFrameDPBEntrySubresource);
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported d3d12_video_decode_profile_type");
|
unreachable("Unsupported d3d12_video_decode_profile_type");
|
||||||
|
|
@ -1024,7 +1038,7 @@ d3d12_video_decoder_reconfigure_dpb(struct d3d12_video_decoder *pD3D12Dec,
|
||||||
D3D12_VIDEO_DECODER_DESC decoderDesc = pD3D12Dec->m_decoderDesc;
|
D3D12_VIDEO_DECODER_DESC decoderDesc = pD3D12Dec->m_decoderDesc;
|
||||||
decoderDesc.Configuration.InterlaceType = interlaceTypeRequested;
|
decoderDesc.Configuration.InterlaceType = interlaceTypeRequested;
|
||||||
decoderDesc.Configuration.DecodeProfile =
|
decoderDesc.Configuration.DecodeProfile =
|
||||||
d3d12_video_decoder_resolve_profile(pD3D12Dec->m_d3d12DecProfileType);
|
d3d12_video_decoder_resolve_profile(pD3D12Dec->m_d3d12DecProfileType, pD3D12Dec->m_decodeFormat);
|
||||||
pD3D12Dec->m_spVideoDecoder.Reset();
|
pD3D12Dec->m_spVideoDecoder.Reset();
|
||||||
HRESULT hr =
|
HRESULT hr =
|
||||||
pD3D12Dec->m_spD3D12VideoDevice->CreateVideoDecoder(&decoderDesc,
|
pD3D12Dec->m_spD3D12VideoDevice->CreateVideoDecoder(&decoderDesc,
|
||||||
|
|
@ -1105,6 +1119,11 @@ d3d12_video_decoder_refresh_dpb_active_references(struct d3d12_video_decoder *pD
|
||||||
d3d12_video_decoder_refresh_dpb_active_references_h264(pD3D12Dec);
|
d3d12_video_decoder_refresh_dpb_active_references_h264(pD3D12Dec);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case d3d12_video_decode_profile_type_hevc:
|
||||||
|
{
|
||||||
|
d3d12_video_decoder_refresh_dpb_active_references_hevc(pD3D12Dec);
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported d3d12_video_decode_profile_type");
|
unreachable("Unsupported d3d12_video_decode_profile_type");
|
||||||
|
|
@ -1127,6 +1146,11 @@ d3d12_video_decoder_get_frame_info(
|
||||||
d3d12_video_decoder_get_frame_info_h264(pD3D12Dec, pWidth, pHeight, pMaxDPB, isInterlaced);
|
d3d12_video_decoder_get_frame_info_h264(pD3D12Dec, pWidth, pHeight, pMaxDPB, isInterlaced);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case d3d12_video_decode_profile_type_hevc:
|
||||||
|
{
|
||||||
|
d3d12_video_decoder_get_frame_info_hevc(pD3D12Dec, pWidth, pHeight, pMaxDPB, isInterlaced);
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported d3d12_video_decode_profile_type");
|
unreachable("Unsupported d3d12_video_decode_profile_type");
|
||||||
|
|
@ -1183,13 +1207,14 @@ d3d12_video_decoder_store_converted_dxva_picparams_from_pipe_input(
|
||||||
|
|
||||||
d3d12_video_decode_profile_type profileType =
|
d3d12_video_decode_profile_type profileType =
|
||||||
d3d12_video_decoder_convert_pipe_video_profile_to_profile_type(codec->base.profile);
|
d3d12_video_decoder_convert_pipe_video_profile_to_profile_type(codec->base.profile);
|
||||||
|
ID3D12Resource *pPipeD3D12DstResource = d3d12_resource_resource(pD3D12VideoBuffer->texture);
|
||||||
|
D3D12_RESOURCE_DESC outputResourceDesc = GetDesc(pPipeD3D12DstResource);
|
||||||
|
pD3D12Dec->qp_matrix_frame_argument_enabled = false;
|
||||||
switch (profileType) {
|
switch (profileType) {
|
||||||
case d3d12_video_decode_profile_type_h264:
|
case d3d12_video_decode_profile_type_h264:
|
||||||
{
|
{
|
||||||
size_t dxvaPicParamsBufferSize = sizeof(DXVA_PicParams_H264);
|
size_t dxvaPicParamsBufferSize = sizeof(DXVA_PicParams_H264);
|
||||||
pipe_h264_picture_desc *pPicControlH264 = (pipe_h264_picture_desc *) picture;
|
pipe_h264_picture_desc *pPicControlH264 = (pipe_h264_picture_desc *) picture;
|
||||||
ID3D12Resource *pPipeD3D12DstResource = d3d12_resource_resource(pD3D12VideoBuffer->texture);
|
|
||||||
D3D12_RESOURCE_DESC outputResourceDesc = GetDesc(pPipeD3D12DstResource);
|
|
||||||
DXVA_PicParams_H264 dxvaPicParamsH264 =
|
DXVA_PicParams_H264 dxvaPicParamsH264 =
|
||||||
d3d12_video_decoder_dxva_picparams_from_pipe_picparams_h264(pD3D12Dec->m_fenceValue,
|
d3d12_video_decoder_dxva_picparams_from_pipe_picparams_h264(pD3D12Dec->m_fenceValue,
|
||||||
codec->base.profile,
|
codec->base.profile,
|
||||||
|
|
@ -1205,8 +1230,32 @@ d3d12_video_decoder_store_converted_dxva_picparams_from_pipe_input(
|
||||||
DXVA_Qmatrix_H264 dxvaQmatrixH264 = {};
|
DXVA_Qmatrix_H264 dxvaQmatrixH264 = {};
|
||||||
d3d12_video_decoder_dxva_qmatrix_from_pipe_picparams_h264((pipe_h264_picture_desc *) picture,
|
d3d12_video_decoder_dxva_qmatrix_from_pipe_picparams_h264((pipe_h264_picture_desc *) picture,
|
||||||
dxvaQmatrixH264);
|
dxvaQmatrixH264);
|
||||||
|
pD3D12Dec->qp_matrix_frame_argument_enabled = true; // We don't have a way of knowing from the pipe params so send always
|
||||||
d3d12_video_decoder_store_dxva_qmatrix_in_qmatrix_buffer(codec, &dxvaQmatrixH264, dxvaQMatrixBufferSize);
|
d3d12_video_decoder_store_dxva_qmatrix_in_qmatrix_buffer(codec, &dxvaQmatrixH264, dxvaQMatrixBufferSize);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case d3d12_video_decode_profile_type_hevc:
|
||||||
|
{
|
||||||
|
size_t dxvaPicParamsBufferSize = sizeof(DXVA_PicParams_HEVC);
|
||||||
|
pipe_h265_picture_desc *pPicControlHEVC = (pipe_h265_picture_desc *) picture;
|
||||||
|
DXVA_PicParams_HEVC dxvaPicParamsHEVC =
|
||||||
|
d3d12_video_decoder_dxva_picparams_from_pipe_picparams_hevc(pD3D12Dec->m_fenceValue,
|
||||||
|
codec->base.profile,
|
||||||
|
pPicControlHEVC);
|
||||||
|
|
||||||
|
d3d12_video_decoder_store_dxva_picparams_in_picparams_buffer(codec,
|
||||||
|
&dxvaPicParamsHEVC,
|
||||||
|
dxvaPicParamsBufferSize);
|
||||||
|
|
||||||
|
size_t dxvaQMatrixBufferSize = sizeof(DXVA_Qmatrix_HEVC);
|
||||||
|
DXVA_Qmatrix_HEVC dxvaQmatrixHEVC = {};
|
||||||
|
pD3D12Dec->qp_matrix_frame_argument_enabled = false;
|
||||||
|
d3d12_video_decoder_dxva_qmatrix_from_pipe_picparams_hevc((pipe_h265_picture_desc *) picture,
|
||||||
|
dxvaQmatrixHEVC,
|
||||||
|
pD3D12Dec->qp_matrix_frame_argument_enabled);
|
||||||
|
d3d12_video_decoder_store_dxva_qmatrix_in_qmatrix_buffer(codec, &dxvaQmatrixHEVC, dxvaQMatrixBufferSize);
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported d3d12_video_decode_profile_type");
|
unreachable("Unsupported d3d12_video_decode_profile_type");
|
||||||
|
|
@ -1238,6 +1287,22 @@ d3d12_video_decoder_prepare_dxva_slices_control(
|
||||||
DXVAStructSize);
|
DXVAStructSize);
|
||||||
assert(pD3D12Dec->m_SliceControlBuffer.size() == DXVAStructSize);
|
assert(pD3D12Dec->m_SliceControlBuffer.size() == DXVAStructSize);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case d3d12_video_decode_profile_type_hevc:
|
||||||
|
{
|
||||||
|
|
||||||
|
std::vector<DXVA_Slice_HEVC_Short> pOutSliceControlBuffers;
|
||||||
|
struct pipe_h265_picture_desc* picture_hevc = (struct pipe_h265_picture_desc*) picture;
|
||||||
|
d3d12_video_decoder_prepare_dxva_slices_control_hevc(pD3D12Dec, pOutSliceControlBuffers, picture_hevc);
|
||||||
|
|
||||||
|
assert(sizeof(pOutSliceControlBuffers.front()) == sizeof(DXVA_Slice_HEVC_Short));
|
||||||
|
uint64_t DXVAStructSize = pOutSliceControlBuffers.size() * sizeof((pOutSliceControlBuffers.front()));
|
||||||
|
assert((DXVAStructSize % sizeof(DXVA_Slice_HEVC_Short)) == 0);
|
||||||
|
d3d12_video_decoder_store_dxva_slicecontrol_in_slicecontrol_buffer(pD3D12Dec,
|
||||||
|
pOutSliceControlBuffers.data(),
|
||||||
|
DXVAStructSize);
|
||||||
|
assert(pD3D12Dec->m_SliceControlBuffer.size() == DXVAStructSize);
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported d3d12_video_decode_profile_type");
|
unreachable("Unsupported d3d12_video_decode_profile_type");
|
||||||
|
|
@ -1291,6 +1356,7 @@ d3d12_video_decoder_supports_aot_dpb(D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT dec
|
||||||
bool supportedProfile = false;
|
bool supportedProfile = false;
|
||||||
switch (profileType) {
|
switch (profileType) {
|
||||||
case d3d12_video_decode_profile_type_h264:
|
case d3d12_video_decode_profile_type_h264:
|
||||||
|
case d3d12_video_decode_profile_type_hevc:
|
||||||
supportedProfile = true;
|
supportedProfile = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -1312,6 +1378,9 @@ d3d12_video_decoder_convert_pipe_video_profile_to_profile_type(enum pipe_video_p
|
||||||
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
|
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
|
||||||
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10:
|
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10:
|
||||||
return d3d12_video_decode_profile_type_h264;
|
return d3d12_video_decode_profile_type_h264;
|
||||||
|
case PIPE_VIDEO_PROFILE_HEVC_MAIN:
|
||||||
|
case PIPE_VIDEO_PROFILE_HEVC_MAIN_10:
|
||||||
|
return d3d12_video_decode_profile_type_hevc;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported pipe video profile");
|
unreachable("Unsupported pipe video profile");
|
||||||
|
|
@ -1330,18 +1399,23 @@ d3d12_video_decoder_convert_pipe_video_profile_to_d3d12_profile(enum pipe_video_
|
||||||
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
|
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
|
||||||
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10:
|
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10:
|
||||||
return D3D12_VIDEO_DECODE_PROFILE_H264;
|
return D3D12_VIDEO_DECODE_PROFILE_H264;
|
||||||
|
case PIPE_VIDEO_PROFILE_HEVC_MAIN:
|
||||||
|
return D3D12_VIDEO_DECODE_PROFILE_HEVC_MAIN;
|
||||||
|
case PIPE_VIDEO_PROFILE_HEVC_MAIN_10:
|
||||||
|
return D3D12_VIDEO_DECODE_PROFILE_HEVC_MAIN10;
|
||||||
default:
|
default:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GUID
|
GUID
|
||||||
d3d12_video_decoder_resolve_profile(d3d12_video_decode_profile_type profileType)
|
d3d12_video_decoder_resolve_profile(d3d12_video_decode_profile_type profileType, DXGI_FORMAT decode_format)
|
||||||
{
|
{
|
||||||
switch (profileType) {
|
switch (profileType) {
|
||||||
case d3d12_video_decode_profile_type_h264:
|
case d3d12_video_decode_profile_type_h264:
|
||||||
return D3D12_VIDEO_DECODE_PROFILE_H264;
|
return D3D12_VIDEO_DECODE_PROFILE_H264;
|
||||||
break;
|
case d3d12_video_decode_profile_type_hevc:
|
||||||
|
return (decode_format == DXGI_FORMAT_NV12) ? D3D12_VIDEO_DECODE_PROFILE_HEVC_MAIN : D3D12_VIDEO_DECODE_PROFILE_HEVC_MAIN10;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported d3d12_video_decode_profile_type");
|
unreachable("Unsupported d3d12_video_decode_profile_type");
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,9 @@ struct d3d12_video_decoder
|
||||||
std::vector<uint8_t> m_picParamsBuffer; // size() has the byte size of the currently held picparams ; capacity()
|
std::vector<uint8_t> m_picParamsBuffer; // size() has the byte size of the currently held picparams ; capacity()
|
||||||
// has the underlying container allocation size
|
// has the underlying container allocation size
|
||||||
|
|
||||||
|
// Set for each frame indicating whether to send VIDEO_DECODE_BUFFER_TYPE_INVERSE_QUANTIZATION_MATRIX
|
||||||
|
bool qp_matrix_frame_argument_enabled = false;
|
||||||
|
|
||||||
// Holds a buffer for the DXVA struct layout of the VIDEO_DECODE_BUFFER_TYPE_INVERSE_QUANTIZATION_MATRIX of the
|
// Holds a buffer for the DXVA struct layout of the VIDEO_DECODE_BUFFER_TYPE_INVERSE_QUANTIZATION_MATRIX of the
|
||||||
// current frame m_InverseQuantMatrixBuffer.size() == 0 means no quantization matrix buffer is set for current frame
|
// current frame m_InverseQuantMatrixBuffer.size() == 0 means no quantization matrix buffer is set for current frame
|
||||||
std::vector<uint8_t> m_InverseQuantMatrixBuffer; // size() has the byte size of the currently held
|
std::vector<uint8_t> m_InverseQuantMatrixBuffer; // size() has the byte size of the currently held
|
||||||
|
|
@ -214,7 +217,7 @@ d3d12_video_decoder_supports_aot_dpb(D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT dec
|
||||||
d3d12_video_decode_profile_type
|
d3d12_video_decode_profile_type
|
||||||
d3d12_video_decoder_convert_pipe_video_profile_to_profile_type(enum pipe_video_profile profile);
|
d3d12_video_decoder_convert_pipe_video_profile_to_profile_type(enum pipe_video_profile profile);
|
||||||
GUID
|
GUID
|
||||||
d3d12_video_decoder_resolve_profile(d3d12_video_decode_profile_type profileType);
|
d3d12_video_decoder_resolve_profile(d3d12_video_decode_profile_type profileType, DXGI_FORMAT decode_format);
|
||||||
void
|
void
|
||||||
d3d12_video_decoder_store_dxva_picparams_in_picparams_buffer(struct d3d12_video_decoder *codec,
|
d3d12_video_decoder_store_dxva_picparams_in_picparams_buffer(struct d3d12_video_decoder *codec,
|
||||||
void * pDXVABuffer,
|
void * pDXVABuffer,
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "d3d12_video_dec.h"
|
#include "d3d12_video_dec.h"
|
||||||
#include "d3d12_video_dec_h264.h"
|
#include "d3d12_video_dec_h264.h"
|
||||||
|
#include "vl/vl_zscan.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
|
@ -594,11 +595,11 @@ d3d12_video_decoder_dxva_qmatrix_from_pipe_picparams_h264(pipe_h264_picture_desc
|
||||||
unsigned i, j;
|
unsigned i, j;
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
for (j = 0; j < 16; j++) {
|
for (j = 0; j < 16; j++) {
|
||||||
outMatrixBuffer.bScalingLists4x4[i][j] = pPipeDesc->pps->ScalingList4x4[i][d3d12_video_zigzag_scan[j]];
|
outMatrixBuffer.bScalingLists4x4[i][j] = pPipeDesc->pps->ScalingList4x4[i][vl_zscan_normal_16[j]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < 64; i++) {
|
for (i = 0; i < 64; i++) {
|
||||||
outMatrixBuffer.bScalingLists8x8[0][i] = pPipeDesc->pps->ScalingList8x8[0][d3d12_video_zigzag_direct[i]];
|
outMatrixBuffer.bScalingLists8x8[0][i] = pPipeDesc->pps->ScalingList8x8[0][vl_zscan_normal[i]];
|
||||||
outMatrixBuffer.bScalingLists8x8[1][i] = pPipeDesc->pps->ScalingList8x8[1][d3d12_video_zigzag_direct[i]];
|
outMatrixBuffer.bScalingLists8x8[1][i] = pPipeDesc->pps->ScalingList8x8[1][vl_zscan_normal[i]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -184,26 +184,6 @@ typedef struct _DXVA_Qmatrix_H264
|
||||||
} DXVA_Qmatrix_H264, *LPDXVA_Qmatrix_H264;
|
} DXVA_Qmatrix_H264, *LPDXVA_Qmatrix_H264;
|
||||||
#pragma pack(pop, BeforeDXVApacking)
|
#pragma pack(pop, BeforeDXVApacking)
|
||||||
|
|
||||||
// For translating the QP matrices from VA to DXVA
|
|
||||||
const uint8_t d3d12_video_zigzag_direct[64] = {
|
|
||||||
0, 1, 8, 16, 9, 2, 3, 10,
|
|
||||||
17, 24, 32, 25, 18, 11, 4, 5,
|
|
||||||
12, 19, 26, 33, 40, 48, 41, 34,
|
|
||||||
27, 20, 13, 6, 7, 14, 21, 28,
|
|
||||||
35, 42, 49, 56, 57, 50, 43, 36,
|
|
||||||
29, 22, 15, 23, 30, 37, 44, 51,
|
|
||||||
58, 59, 52, 45, 38, 31, 39, 46,
|
|
||||||
53, 60, 61, 54, 47, 55, 62, 63
|
|
||||||
};
|
|
||||||
|
|
||||||
// For translating the QP matrices from VA to DXVA
|
|
||||||
const uint8_t d3d12_video_zigzag_scan[16+1] = {
|
|
||||||
0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4,
|
|
||||||
1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4,
|
|
||||||
1 + 2 * 4, 0 + 3 * 4, 1 + 3 * 4, 2 + 2 * 4,
|
|
||||||
3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* H.264/AVC slice control data structure - short form */
|
/* H.264/AVC slice control data structure - short form */
|
||||||
/* If including new DXVA structs in this header, check the byte-alignment packing pragma declarations that need to be included with them */
|
/* If including new DXVA structs in this header, check the byte-alignment packing pragma declarations that need to be included with them */
|
||||||
#pragma pack(push, BeforeDXVApacking, 1)
|
#pragma pack(push, BeforeDXVApacking, 1)
|
||||||
|
|
|
||||||
546
src/gallium/drivers/d3d12/d3d12_video_dec_hevc.cpp
Normal file
546
src/gallium/drivers/d3d12/d3d12_video_dec_hevc.cpp
Normal file
|
|
@ -0,0 +1,546 @@
|
||||||
|
/*
|
||||||
|
* Copyright © Microsoft Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "d3d12_video_dec.h"
|
||||||
|
#include "d3d12_video_dec_hevc.h"
|
||||||
|
#include "d3d12_resource.h"
|
||||||
|
#include "d3d12_video_buffer.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_decoder_refresh_dpb_active_references_hevc(struct d3d12_video_decoder *pD3D12Dec)
|
||||||
|
{
|
||||||
|
// Method overview
|
||||||
|
// 1. Codec specific strategy in switch statement regarding reference frames eviction policy. Should only mark active
|
||||||
|
// DPB references, leaving evicted ones as unused
|
||||||
|
// 2. Call release_unused_references_texture_memory(); at the end of this method. Any references (and texture
|
||||||
|
// allocations associated)
|
||||||
|
// that were left not marked as used in m_spDPBManager by step (2) are lost.
|
||||||
|
|
||||||
|
// Assign DXVA original Index7Bits indices to current frame and references
|
||||||
|
DXVA_PicParams_HEVC *pCurrPicParams = d3d12_video_decoder_get_current_dxva_picparams<DXVA_PicParams_HEVC>(pD3D12Dec);
|
||||||
|
for (uint8_t i = 0; i < _countof(pCurrPicParams->RefPicList); i++) {
|
||||||
|
// From HEVC DXVA spec:
|
||||||
|
// Index7Bits
|
||||||
|
// An index that identifies an uncompressed surface for the CurrPic or RefPicList member of the picture parameters structure (section 4.0).
|
||||||
|
// When Index7Bits is used in the CurrPic and RefPicList members of the picture parameters structure, the value directly specifies the DXVA index of an uncompressed surface.
|
||||||
|
// When Index7Bits is 127 (0x7F), this indicates that it does not contain a valid index.
|
||||||
|
|
||||||
|
// AssociatedFlag
|
||||||
|
// Optional 1-bit flag associated with the surface. It specifies whether the reference picture is a long-term reference or a short-term reference for RefPicList, and it has no meaning when used for CurrPic.
|
||||||
|
// bPicEntry
|
||||||
|
// Accesses the entire 8 bits of the union.
|
||||||
|
|
||||||
|
if (pCurrPicParams->RefPicList[i].bPicEntry != DXVA_HEVC_INVALID_PICTURE_ENTRY_VALUE) {
|
||||||
|
pCurrPicParams->RefPicList[i].Index7Bits =
|
||||||
|
pD3D12Dec->m_spDPBManager->get_index7bits(pD3D12Dec->m_pCurrentReferenceTargets[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pD3D12Dec->m_spDPBManager->mark_all_references_as_unused();
|
||||||
|
pD3D12Dec->m_spDPBManager->mark_references_in_use(pCurrPicParams->RefPicList);
|
||||||
|
|
||||||
|
// Releases the underlying reference picture texture objects of all references that were not marked as used in this
|
||||||
|
// method.
|
||||||
|
pD3D12Dec->m_spDPBManager->release_unused_references_texture_memory();
|
||||||
|
|
||||||
|
pCurrPicParams->CurrPic.Index7Bits = pD3D12Dec->m_spDPBManager->get_index7bits(pD3D12Dec->m_pCurrentDecodeTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int
|
||||||
|
LengthFromMinCb(int length, int cbsize)
|
||||||
|
{
|
||||||
|
return length * (1 << cbsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_decoder_get_frame_info_hevc(
|
||||||
|
struct d3d12_video_decoder *pD3D12Dec, uint32_t *pWidth, uint32_t *pHeight, uint16_t *pMaxDPB, bool &isInterlaced)
|
||||||
|
{
|
||||||
|
auto pPicParams = d3d12_video_decoder_get_current_dxva_picparams<DXVA_PicParams_HEVC>(pD3D12Dec);
|
||||||
|
UINT log2_min_luma_coding_block_size = pPicParams->log2_min_luma_coding_block_size_minus3 + 3;
|
||||||
|
*pWidth = LengthFromMinCb(pPicParams->PicWidthInMinCbsY, log2_min_luma_coding_block_size);
|
||||||
|
*pHeight = LengthFromMinCb(pPicParams->PicHeightInMinCbsY, log2_min_luma_coding_block_size);
|
||||||
|
*pMaxDPB = pPicParams->sps_max_dec_pic_buffering_minus1 + 1;
|
||||||
|
isInterlaced = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Pushes the current frame as next reference, updates the DXVA HEVC structure with the indices of the DPB and
|
||||||
|
/// transitions the references
|
||||||
|
///
|
||||||
|
void
|
||||||
|
d3d12_video_decoder_prepare_current_frame_references_hevc(struct d3d12_video_decoder *pD3D12Dec,
|
||||||
|
ID3D12Resource *pTexture2D,
|
||||||
|
uint32_t subresourceIndex)
|
||||||
|
{
|
||||||
|
DXVA_PicParams_HEVC *pPicParams = d3d12_video_decoder_get_current_dxva_picparams<DXVA_PicParams_HEVC>(pD3D12Dec);
|
||||||
|
pPicParams->CurrPic.Index7Bits = pD3D12Dec->m_spDPBManager->store_future_reference(pPicParams->CurrPic.Index7Bits,
|
||||||
|
pD3D12Dec->m_spVideoDecoderHeap,
|
||||||
|
pTexture2D,
|
||||||
|
subresourceIndex);
|
||||||
|
// From HEVC DXVA spec:
|
||||||
|
// Index7Bits
|
||||||
|
// An index that identifies an uncompressed surface for the CurrPic or RefPicList member of the picture parameters structure (section 4.0).
|
||||||
|
// When Index7Bits is used in the CurrPic and RefPicList members of the picture parameters structure, the value directly specifies the DXVA index of an uncompressed surface.
|
||||||
|
// When Index7Bits is 127 (0x7F), this indicates that it does not contain a valid index.
|
||||||
|
|
||||||
|
std::vector<D3D12_RESOURCE_BARRIER>
|
||||||
|
neededStateTransitions; // Returned by update_entries to perform by the method caller
|
||||||
|
pD3D12Dec->m_spDPBManager->update_entries(
|
||||||
|
d3d12_video_decoder_get_current_dxva_picparams<DXVA_PicParams_HEVC>(pD3D12Dec)->RefPicList,
|
||||||
|
neededStateTransitions);
|
||||||
|
|
||||||
|
pD3D12Dec->m_spDecodeCommandList->ResourceBarrier(neededStateTransitions.size(), neededStateTransitions.data());
|
||||||
|
|
||||||
|
// Schedule reverse (back to common) transitions before command list closes for current frame
|
||||||
|
for (auto BarrierDesc : neededStateTransitions) {
|
||||||
|
std::swap(BarrierDesc.Transition.StateBefore, BarrierDesc.Transition.StateAfter);
|
||||||
|
pD3D12Dec->m_transitionsBeforeCloseCmdList.push_back(BarrierDesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_printf(
|
||||||
|
"[d3d12_video_decoder_prepare_current_frame_references_hevc] DXVA_PicParams_HEVC after index remapping)\n");
|
||||||
|
d3d12_video_decoder_log_pic_params_hevc(
|
||||||
|
d3d12_video_decoder_get_current_dxva_picparams<DXVA_PicParams_HEVC>(pD3D12Dec));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_decoder_prepare_dxva_slices_control_hevc(struct d3d12_video_decoder *pD3D12Dec,
|
||||||
|
std::vector<DXVA_Slice_HEVC_Short> &pOutSliceControlBuffers,
|
||||||
|
struct pipe_h265_picture_desc *picture_hevc)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(!picture_hevc->slice_parameter.slice_info_present)
|
||||||
|
{
|
||||||
|
unreachable("Unsupported - need pipe_h265_picture_desc.slice_parameter.slice_info_present");
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_printf("[d3d12_video_decoder_hevc] Upper layer reported %d slices for this frame, parsing them below...\n",
|
||||||
|
picture_hevc->slice_parameter.slice_count);
|
||||||
|
|
||||||
|
for (uint32_t sliceIdx = 0; sliceIdx < picture_hevc->slice_parameter.slice_count; sliceIdx++)
|
||||||
|
{
|
||||||
|
DXVA_Slice_HEVC_Short currentSliceEntry = {};
|
||||||
|
// From HEVC DXVA Spec
|
||||||
|
// wBadSliceChopping
|
||||||
|
// 0 All bits for the slice are located within the corresponding bitstream data buffer.
|
||||||
|
// 1 The bitstream data buffer contains the start of the slice, but not the entire slice, because the buffer is full.
|
||||||
|
// 2 The bitstream data buffer contains the end of the slice. It does not contain the start of the slice, because the start of the slice was located in the previous bitstream data buffer.
|
||||||
|
// 3 The bitstream data buffer does not contain the start of the slice (because the start of the slice was located in the previous bitstream data buffer),
|
||||||
|
// and it does not contain the end of the slice (because the current bitstream data buffer is also full).
|
||||||
|
|
||||||
|
switch (picture_hevc->slice_parameter.slice_data_flag[sliceIdx]) {
|
||||||
|
/* whole slice is in the buffer */
|
||||||
|
case PIPE_SLICE_BUFFER_PLACEMENT_TYPE_WHOLE:
|
||||||
|
currentSliceEntry.wBadSliceChopping = 0u;
|
||||||
|
break;
|
||||||
|
/* The beginning of the slice is in the buffer but the end is not */
|
||||||
|
case PIPE_SLICE_BUFFER_PLACEMENT_TYPE_BEGIN:
|
||||||
|
currentSliceEntry.wBadSliceChopping = 1u;
|
||||||
|
break;
|
||||||
|
/* Neither beginning nor end of the slice is in the buffer */
|
||||||
|
case PIPE_SLICE_BUFFER_PLACEMENT_TYPE_MIDDLE:
|
||||||
|
currentSliceEntry.wBadSliceChopping = 3u;
|
||||||
|
break;
|
||||||
|
/* end of the slice is in the buffer */
|
||||||
|
case PIPE_SLICE_BUFFER_PLACEMENT_TYPE_END:
|
||||||
|
currentSliceEntry.wBadSliceChopping = 2u;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
unreachable("Unsupported pipe_slice_buffer_placement_type");
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentSliceEntry.SliceBytesInBuffer = picture_hevc->slice_parameter.slice_data_size[sliceIdx];
|
||||||
|
currentSliceEntry.BSNALunitDataLocation = picture_hevc->slice_parameter.slice_data_offset[sliceIdx];
|
||||||
|
|
||||||
|
debug_printf("[d3d12_video_decoder_hevc] Detected slice index %" PRIu32 " with SliceBytesInBuffer %d - BSNALunitDataLocation %d - wBadSliceChopping: %" PRIu16
|
||||||
|
" for frame with "
|
||||||
|
"fenceValue: %d\n",
|
||||||
|
sliceIdx,
|
||||||
|
currentSliceEntry.SliceBytesInBuffer,
|
||||||
|
currentSliceEntry.BSNALunitDataLocation,
|
||||||
|
currentSliceEntry.wBadSliceChopping,
|
||||||
|
pD3D12Dec->m_fenceValue);
|
||||||
|
|
||||||
|
pOutSliceControlBuffers.push_back(currentSliceEntry);
|
||||||
|
}
|
||||||
|
assert(pOutSliceControlBuffers.size() == picture_hevc->slice_parameter.slice_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
d3d12_video_decoder_log_pic_entry_hevc(DXVA_PicEntry_HEVC &picEntry)
|
||||||
|
{
|
||||||
|
debug_printf("\t\tIndex7Bits: %d\n"
|
||||||
|
"\t\tAssociatedFlag: %d\n"
|
||||||
|
"\t\tbPicEntry: %d\n",
|
||||||
|
picEntry.Index7Bits,
|
||||||
|
picEntry.AssociatedFlag,
|
||||||
|
picEntry.bPicEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_decoder_log_pic_params_hevc(DXVA_PicParams_HEVC *pPicParams)
|
||||||
|
{
|
||||||
|
debug_printf("\n=============================================\n");
|
||||||
|
debug_printf("PicWidthInMinCbsY = %d\n", pPicParams->PicWidthInMinCbsY);
|
||||||
|
debug_printf("PicHeightInMinCbsY = %d\n", pPicParams->PicHeightInMinCbsY);
|
||||||
|
debug_printf("chroma_format_idc = %d\n", pPicParams->chroma_format_idc);
|
||||||
|
debug_printf("separate_colour_plane_flag = %d\n", pPicParams->separate_colour_plane_flag);
|
||||||
|
debug_printf("bit_depth_luma_minus8 = %d\n", pPicParams->bit_depth_luma_minus8);
|
||||||
|
debug_printf("bit_depth_chroma_minus8 = %d\n", pPicParams->bit_depth_chroma_minus8);
|
||||||
|
debug_printf("log2_max_pic_order_cnt_lsb_minus4 = %d\n", pPicParams->log2_max_pic_order_cnt_lsb_minus4);
|
||||||
|
debug_printf("NoPicReorderingFlag = %d\n", pPicParams->NoPicReorderingFlag);
|
||||||
|
debug_printf("NoBiPredFlag = %d\n", pPicParams->NoBiPredFlag);
|
||||||
|
debug_printf("ReservedBits1 = %d\n", pPicParams->ReservedBits1);
|
||||||
|
debug_printf("wFormatAndSequenceInfoFlags = %d\n", pPicParams->wFormatAndSequenceInfoFlags);
|
||||||
|
debug_printf("CurrPic.Index7Bits = %d\n", pPicParams->CurrPic.Index7Bits);
|
||||||
|
debug_printf("CurrPic.AssociatedFlag = %d\n", pPicParams->CurrPic.AssociatedFlag);
|
||||||
|
debug_printf("sps_max_dec_pic_buffering_minus1 = %d\n", pPicParams->sps_max_dec_pic_buffering_minus1);
|
||||||
|
debug_printf("log2_min_luma_coding_block_size_minus3 = %d\n", pPicParams->log2_min_luma_coding_block_size_minus3);
|
||||||
|
debug_printf("log2_diff_max_min_luma_coding_block_size = %d\n", pPicParams->log2_diff_max_min_luma_coding_block_size);
|
||||||
|
debug_printf("log2_min_transform_block_size_minus2 = %d\n", pPicParams->log2_min_transform_block_size_minus2);
|
||||||
|
debug_printf("log2_diff_max_min_transform_block_size = %d\n", pPicParams->log2_diff_max_min_transform_block_size);
|
||||||
|
debug_printf("max_transform_hierarchy_depth_inter = %d\n", pPicParams->max_transform_hierarchy_depth_inter);
|
||||||
|
debug_printf("max_transform_hierarchy_depth_intra = %d\n", pPicParams->max_transform_hierarchy_depth_intra);
|
||||||
|
debug_printf("num_short_term_ref_pic_sets = %d\n", pPicParams->num_short_term_ref_pic_sets);
|
||||||
|
debug_printf("num_long_term_ref_pics_sps = %d\n", pPicParams->num_long_term_ref_pics_sps);
|
||||||
|
debug_printf("num_ref_idx_l0_default_active_minus1 = %d\n", pPicParams->num_ref_idx_l0_default_active_minus1);
|
||||||
|
debug_printf("num_ref_idx_l1_default_active_minus1 = %d\n", pPicParams->num_ref_idx_l1_default_active_minus1);
|
||||||
|
debug_printf("init_qp_minus26 = %d\n", pPicParams->init_qp_minus26);
|
||||||
|
debug_printf("ucNumDeltaPocsOfRefRpsIdx = %d\n", pPicParams->ucNumDeltaPocsOfRefRpsIdx);
|
||||||
|
debug_printf("wNumBitsForShortTermRPSInSlice = %d\n", pPicParams->wNumBitsForShortTermRPSInSlice);
|
||||||
|
debug_printf("ReservedBits2 = %d\n", pPicParams->ReservedBits2);
|
||||||
|
debug_printf("scaling_list_enabled_flag = %d\n", pPicParams->scaling_list_enabled_flag);
|
||||||
|
debug_printf("amp_enabled_flag = %d\n", pPicParams->amp_enabled_flag);
|
||||||
|
debug_printf("sample_adaptive_offset_enabled_flag = %d\n", pPicParams->sample_adaptive_offset_enabled_flag);
|
||||||
|
debug_printf("pcm_enabled_flag = %d\n", pPicParams->pcm_enabled_flag);
|
||||||
|
debug_printf("pcm_sample_bit_depth_luma_minus1 = %d\n", pPicParams->pcm_sample_bit_depth_luma_minus1);
|
||||||
|
debug_printf("pcm_sample_bit_depth_chroma_minus1 = %d\n", pPicParams->pcm_sample_bit_depth_chroma_minus1);
|
||||||
|
debug_printf("log2_min_pcm_luma_coding_block_size_minus3 = %d\n", pPicParams->log2_min_pcm_luma_coding_block_size_minus3);
|
||||||
|
debug_printf("log2_diff_max_min_pcm_luma_coding_block_size = %d\n", pPicParams->log2_diff_max_min_pcm_luma_coding_block_size);
|
||||||
|
debug_printf("pcm_loop_filter_disabled_flag = %d\n", pPicParams->pcm_loop_filter_disabled_flag);
|
||||||
|
debug_printf("long_term_ref_pics_present_flag = %d\n", pPicParams->long_term_ref_pics_present_flag);
|
||||||
|
debug_printf("sps_temporal_mvp_enabled_flag = %d\n", pPicParams->sps_temporal_mvp_enabled_flag);
|
||||||
|
debug_printf("strong_intra_smoothing_enabled_flag = %d\n", pPicParams->strong_intra_smoothing_enabled_flag);
|
||||||
|
debug_printf("dependent_slice_segments_enabled_flag = %d\n", pPicParams->dependent_slice_segments_enabled_flag);
|
||||||
|
debug_printf("output_flag_present_flag = %d\n", pPicParams->output_flag_present_flag);
|
||||||
|
debug_printf("num_extra_slice_header_bits = %d\n", pPicParams->num_extra_slice_header_bits);
|
||||||
|
debug_printf("sign_data_hiding_enabled_flag = %d\n", pPicParams->sign_data_hiding_enabled_flag);
|
||||||
|
debug_printf("cabac_init_present_flag = %d\n", pPicParams->cabac_init_present_flag);
|
||||||
|
debug_printf("ReservedBits3 = %d\n", pPicParams->ReservedBits3);
|
||||||
|
debug_printf("dwCodingParamToolFlags = %d\n", pPicParams->dwCodingParamToolFlags);
|
||||||
|
debug_printf("constrained_intra_pred_flag = %d\n", pPicParams->constrained_intra_pred_flag);
|
||||||
|
debug_printf("transform_skip_enabled_flag = %d\n", pPicParams->transform_skip_enabled_flag);
|
||||||
|
debug_printf("cu_qp_delta_enabled_flag = %d\n", pPicParams->cu_qp_delta_enabled_flag);
|
||||||
|
debug_printf("pps_slice_chroma_qp_offsets_present_flag = %d\n", pPicParams->pps_slice_chroma_qp_offsets_present_flag);
|
||||||
|
debug_printf("weighted_pred_flag = %d\n", pPicParams->weighted_pred_flag);
|
||||||
|
debug_printf("weighted_bipred_flag = %d\n", pPicParams->weighted_bipred_flag);
|
||||||
|
debug_printf("transquant_bypass_enabled_flag = %d\n", pPicParams->transquant_bypass_enabled_flag);
|
||||||
|
debug_printf("tiles_enabled_flag = %d\n", pPicParams->tiles_enabled_flag);
|
||||||
|
debug_printf("entropy_coding_sync_enabled_flag = %d\n", pPicParams->entropy_coding_sync_enabled_flag);
|
||||||
|
debug_printf("uniform_spacing_flag = %d\n", pPicParams->uniform_spacing_flag);
|
||||||
|
debug_printf("loop_filter_across_tiles_enabled_flag = %d\n", pPicParams->loop_filter_across_tiles_enabled_flag);
|
||||||
|
debug_printf("pps_loop_filter_across_slices_enabled_flag = %d\n", pPicParams->pps_loop_filter_across_slices_enabled_flag);
|
||||||
|
debug_printf("deblocking_filter_override_enabled_flag = %d\n", pPicParams->deblocking_filter_override_enabled_flag);
|
||||||
|
debug_printf("pps_deblocking_filter_disabled_flag = %d\n", pPicParams->pps_deblocking_filter_disabled_flag);
|
||||||
|
debug_printf("lists_modification_present_flag = %d\n", pPicParams->lists_modification_present_flag);
|
||||||
|
debug_printf("slice_segment_header_extension_present_flag = %d\n", pPicParams->slice_segment_header_extension_present_flag);
|
||||||
|
debug_printf("IrapPicFlag = %d\n", pPicParams->IrapPicFlag);
|
||||||
|
debug_printf("IdrPicFlag = %d\n", pPicParams->IdrPicFlag);
|
||||||
|
debug_printf("IntraPicFlag = %d\n", pPicParams->IntraPicFlag);
|
||||||
|
debug_printf("ReservedBits4 = %d\n", pPicParams->ReservedBits4);
|
||||||
|
debug_printf("dwCodingSettingPicturePropertyFlags = %d\n", pPicParams->dwCodingSettingPicturePropertyFlags);
|
||||||
|
debug_printf("pps_cb_qp_offset = %d\n", pPicParams->pps_cb_qp_offset);
|
||||||
|
debug_printf("pps_cr_qp_offset = %d\n", pPicParams->pps_cr_qp_offset);
|
||||||
|
debug_printf("num_tile_columns_minus1 = %d\n", pPicParams->num_tile_columns_minus1);
|
||||||
|
debug_printf("num_tile_rows_minus1 = %d\n", pPicParams->num_tile_rows_minus1);
|
||||||
|
for (uint32_t i = 0; i < std::min((unsigned) pPicParams->num_tile_columns_minus1 + 1u, (unsigned) _countof(DXVA_PicParams_HEVC::column_width_minus1)); i++) {
|
||||||
|
debug_printf("column_width_minus1[%d]; = %d\n", i, pPicParams->column_width_minus1[i]);
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < std::min((unsigned) pPicParams->num_tile_rows_minus1 + 1u, (unsigned) _countof(DXVA_PicParams_HEVC::row_height_minus1)); i++) {
|
||||||
|
debug_printf("row_height_minus1[%d]; = %d\n", i, pPicParams->row_height_minus1[i]);
|
||||||
|
}
|
||||||
|
debug_printf("diff_cu_qp_delta_depth = %d\n", pPicParams->diff_cu_qp_delta_depth);
|
||||||
|
debug_printf("pps_beta_offset_div2 = %d\n", pPicParams->pps_beta_offset_div2);
|
||||||
|
debug_printf("pps_tc_offset_div2 = %d\n", pPicParams->pps_tc_offset_div2);
|
||||||
|
debug_printf("log2_parallel_merge_level_minus2 = %d\n", pPicParams->log2_parallel_merge_level_minus2);
|
||||||
|
debug_printf("CurrPicOrderCntVal = %d\n", pPicParams->CurrPicOrderCntVal);
|
||||||
|
debug_printf("ReservedBits5 = %d\n", pPicParams->ReservedBits5);
|
||||||
|
debug_printf("ReservedBits6 = %d\n", pPicParams->ReservedBits6);
|
||||||
|
debug_printf("ReservedBits7 = %d\n", pPicParams->ReservedBits7);
|
||||||
|
debug_printf("StatusReportFeedbackNumber = %d\n", pPicParams->StatusReportFeedbackNumber);
|
||||||
|
|
||||||
|
debug_printf("[D3D12 Video Decoder HEVC DXVA PicParams info]\n"
|
||||||
|
"\t[Current Picture Entry]\n");
|
||||||
|
d3d12_video_decoder_log_pic_entry_hevc(pPicParams->CurrPic);
|
||||||
|
|
||||||
|
debug_printf("[D3D12 Video Decoder HEVC DXVA PicParams info]\n"
|
||||||
|
"\t[Current Picture Reference sets, hiding entries with bPicEntry 0xFF]\n");
|
||||||
|
|
||||||
|
for (uint32_t refIdx = 0; refIdx < _countof(DXVA_PicParams_HEVC::RefPicSetStCurrBefore); refIdx++) {
|
||||||
|
if(pPicParams->RefPicSetStCurrBefore[refIdx] != DXVA_HEVC_INVALID_PICTURE_ENTRY_VALUE) {
|
||||||
|
debug_printf("\tRefPicSetStCurrBefore[%d] = %d \n PicEntry RefPicList[%d]\n", refIdx, pPicParams->RefPicSetStCurrBefore[refIdx], pPicParams->RefPicSetStCurrBefore[refIdx]);
|
||||||
|
d3d12_video_decoder_log_pic_entry_hevc(pPicParams->RefPicList[pPicParams->RefPicSetStCurrBefore[refIdx]]);
|
||||||
|
debug_printf("\t\tPicOrderCntValList: %d\n",
|
||||||
|
pPicParams->PicOrderCntValList[pPicParams->RefPicSetStCurrBefore[refIdx]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (uint32_t refIdx = 0; refIdx < _countof(DXVA_PicParams_HEVC::RefPicSetStCurrAfter); refIdx++) {
|
||||||
|
if(pPicParams->RefPicSetStCurrAfter[refIdx] != DXVA_HEVC_INVALID_PICTURE_ENTRY_VALUE) {
|
||||||
|
debug_printf("\tRefPicSetStCurrAfter[%d] = %d \n PicEntry RefPicList[%d]\n", refIdx, pPicParams->RefPicSetStCurrAfter[refIdx], pPicParams->RefPicSetStCurrAfter[refIdx]);
|
||||||
|
d3d12_video_decoder_log_pic_entry_hevc(pPicParams->RefPicList[pPicParams->RefPicSetStCurrAfter[refIdx]]);
|
||||||
|
debug_printf("\t\tPicOrderCntValList: %d\n",
|
||||||
|
pPicParams->PicOrderCntValList[pPicParams->RefPicSetStCurrAfter[refIdx]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (uint32_t refIdx = 0; refIdx < _countof(DXVA_PicParams_HEVC::RefPicSetLtCurr); refIdx++) {
|
||||||
|
if(pPicParams->RefPicSetLtCurr[refIdx] != DXVA_HEVC_INVALID_PICTURE_ENTRY_VALUE) {
|
||||||
|
debug_printf("\tRefPicSetLtCurr[%d] = %d \n PicEntry RefPicList[%d]\n", refIdx, pPicParams->RefPicSetLtCurr[refIdx], pPicParams->RefPicSetLtCurr[refIdx]);
|
||||||
|
d3d12_video_decoder_log_pic_entry_hevc(pPicParams->RefPicList[pPicParams->RefPicSetLtCurr[refIdx]]);
|
||||||
|
debug_printf("\t\tPicOrderCntValList: %d\n",
|
||||||
|
pPicParams->PicOrderCntValList[pPicParams->RefPicSetLtCurr[refIdx]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_decoder_sort_rps_lists_by_refpoc(DXVA_PicParams_HEVC* pDXVAStruct, pipe_h265_picture_desc *pPipeDesc)
|
||||||
|
{
|
||||||
|
// Sort the RPS lists in pDXVAStruct in order by pPipeDesc->PicOrderCntVal for DXVA expectations.
|
||||||
|
// Both arrays have parallel indices
|
||||||
|
struct RPSEntryWithPOC {
|
||||||
|
uint8_t refpicset_index;
|
||||||
|
int32_t poc_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<RPSEntryWithPOC> tmpVec;
|
||||||
|
for (uint8_t i = 0; i < pPipeDesc->NumPocStCurrBefore; i++)
|
||||||
|
tmpVec.push_back({ pDXVAStruct->RefPicSetStCurrBefore[i], pPipeDesc->PicOrderCntVal[pDXVAStruct->RefPicSetStCurrBefore[i]] });
|
||||||
|
|
||||||
|
std::sort(std::begin(tmpVec), std::end(tmpVec), [](RPSEntryWithPOC entryI, RPSEntryWithPOC entryJ)
|
||||||
|
{ return entryI.poc_value /*desc order*/ > entryJ.poc_value; });
|
||||||
|
for (uint8_t i = 0; i < pPipeDesc->NumPocStCurrBefore; i++)
|
||||||
|
pDXVAStruct->RefPicSetStCurrBefore[i] = tmpVec[i].refpicset_index;
|
||||||
|
|
||||||
|
tmpVec.clear();
|
||||||
|
for (uint8_t i = 0; i < pPipeDesc->NumPocStCurrAfter; i++)
|
||||||
|
tmpVec.push_back({ pDXVAStruct->RefPicSetStCurrAfter[i], pPipeDesc->PicOrderCntVal[pDXVAStruct->RefPicSetStCurrAfter[i]] });
|
||||||
|
|
||||||
|
std::sort(std::begin(tmpVec), std::end(tmpVec), [](RPSEntryWithPOC entryI, RPSEntryWithPOC entryJ)
|
||||||
|
{ return entryI.poc_value /*ascending order*/ < entryJ.poc_value; });
|
||||||
|
for (uint8_t i = 0; i < pPipeDesc->NumPocStCurrAfter; i++)
|
||||||
|
pDXVAStruct->RefPicSetStCurrAfter[i] = tmpVec[i].refpicset_index;
|
||||||
|
|
||||||
|
tmpVec.clear();
|
||||||
|
for (uint8_t i = 0; i < pPipeDesc->NumPocLtCurr; i++)
|
||||||
|
tmpVec.push_back({ pDXVAStruct->RefPicSetLtCurr[i], pPipeDesc->PicOrderCntVal[pDXVAStruct->RefPicSetLtCurr[i]] });
|
||||||
|
|
||||||
|
// The ordering of RefPicSetLtCurr is unclear from the DXVA spec, might need to be changed
|
||||||
|
std::sort(std::begin(tmpVec), std::end(tmpVec), [](RPSEntryWithPOC entryI, RPSEntryWithPOC entryJ)
|
||||||
|
{ return entryI.poc_value /*ascending order*/ < entryJ.poc_value; });
|
||||||
|
for (uint8_t i = 0; i < pPipeDesc->NumPocLtCurr; i++)
|
||||||
|
pDXVAStruct->RefPicSetLtCurr[i] = tmpVec[i].refpicset_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
DXVA_PicParams_HEVC
|
||||||
|
d3d12_video_decoder_dxva_picparams_from_pipe_picparams_hevc(
|
||||||
|
uint32_t frameNum,
|
||||||
|
pipe_video_profile profile,
|
||||||
|
pipe_h265_picture_desc *pPipeDesc)
|
||||||
|
{
|
||||||
|
pipe_h265_pps *pps = pPipeDesc->pps;
|
||||||
|
pipe_h265_sps *sps = pPipeDesc->pps->sps;
|
||||||
|
|
||||||
|
DXVA_PicParams_HEVC dxvaStructure;
|
||||||
|
memset(&dxvaStructure, 0, sizeof(dxvaStructure));
|
||||||
|
|
||||||
|
uint8_t log2_min_cb_size = sps->log2_min_luma_coding_block_size_minus3 + 3;
|
||||||
|
dxvaStructure.PicWidthInMinCbsY = sps->pic_width_in_luma_samples >> log2_min_cb_size;
|
||||||
|
dxvaStructure.PicHeightInMinCbsY = sps->pic_height_in_luma_samples >> log2_min_cb_size;
|
||||||
|
dxvaStructure.chroma_format_idc = sps->chroma_format_idc;
|
||||||
|
dxvaStructure.separate_colour_plane_flag = sps->separate_colour_plane_flag;
|
||||||
|
dxvaStructure.bit_depth_luma_minus8 = sps->bit_depth_luma_minus8;
|
||||||
|
dxvaStructure.bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8;
|
||||||
|
dxvaStructure.log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4;
|
||||||
|
dxvaStructure.NoPicReorderingFlag = sps->no_pic_reordering_flag;
|
||||||
|
dxvaStructure.NoBiPredFlag = sps->no_bi_pred_flag;
|
||||||
|
|
||||||
|
dxvaStructure.CurrPic.bPicEntry = 0; // No semantic for this flag in HEVC DXVA spec
|
||||||
|
// CurrPic.Index7Bits is handled by d3d12_video_decoder_refresh_dpb_active_references_hevc
|
||||||
|
|
||||||
|
dxvaStructure.sps_max_dec_pic_buffering_minus1 = sps->sps_max_dec_pic_buffering_minus1;
|
||||||
|
dxvaStructure.log2_min_luma_coding_block_size_minus3 = sps->log2_min_luma_coding_block_size_minus3;
|
||||||
|
dxvaStructure.log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_luma_coding_block_size;
|
||||||
|
dxvaStructure.log2_min_transform_block_size_minus2 = sps->log2_min_transform_block_size_minus2;
|
||||||
|
dxvaStructure.log2_diff_max_min_transform_block_size = sps->log2_diff_max_min_transform_block_size;
|
||||||
|
dxvaStructure.max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter;
|
||||||
|
dxvaStructure.max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra;
|
||||||
|
dxvaStructure.num_short_term_ref_pic_sets = sps->num_short_term_ref_pic_sets;
|
||||||
|
dxvaStructure.num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps;
|
||||||
|
|
||||||
|
dxvaStructure.num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active_minus1;
|
||||||
|
dxvaStructure.num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active_minus1;
|
||||||
|
dxvaStructure.init_qp_minus26 = pps->init_qp_minus26;
|
||||||
|
|
||||||
|
// NumDeltaPocsOfRefRpsIdx is not passed from VA to pipe, and VA doesn't have it defined in their va_dec_hevc header.
|
||||||
|
// DXVA drivers should use wNumBitsForShortTermRPSInSlice (st_rps_bits in VA) to derive the slice header info instead
|
||||||
|
dxvaStructure.ucNumDeltaPocsOfRefRpsIdx = pPipeDesc->NumDeltaPocsOfRefRpsIdx;
|
||||||
|
dxvaStructure.wNumBitsForShortTermRPSInSlice = pps->st_rps_bits;
|
||||||
|
|
||||||
|
dxvaStructure.scaling_list_enabled_flag = sps->scaling_list_enabled_flag;
|
||||||
|
dxvaStructure.amp_enabled_flag = sps->amp_enabled_flag;
|
||||||
|
dxvaStructure.sample_adaptive_offset_enabled_flag = sps->sample_adaptive_offset_enabled_flag;
|
||||||
|
dxvaStructure.pcm_enabled_flag = sps->pcm_enabled_flag;
|
||||||
|
dxvaStructure.pcm_sample_bit_depth_luma_minus1 = sps->pcm_sample_bit_depth_luma_minus1;
|
||||||
|
dxvaStructure.pcm_sample_bit_depth_chroma_minus1 = sps->pcm_sample_bit_depth_chroma_minus1;
|
||||||
|
dxvaStructure.log2_min_pcm_luma_coding_block_size_minus3 = sps->log2_min_pcm_luma_coding_block_size_minus3;
|
||||||
|
dxvaStructure.log2_diff_max_min_pcm_luma_coding_block_size = sps->log2_diff_max_min_pcm_luma_coding_block_size;
|
||||||
|
dxvaStructure.pcm_loop_filter_disabled_flag = sps->pcm_loop_filter_disabled_flag;
|
||||||
|
dxvaStructure.long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag;
|
||||||
|
dxvaStructure.sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag;
|
||||||
|
dxvaStructure.strong_intra_smoothing_enabled_flag = sps->strong_intra_smoothing_enabled_flag;
|
||||||
|
dxvaStructure.dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag;
|
||||||
|
dxvaStructure.output_flag_present_flag = pps->output_flag_present_flag;
|
||||||
|
dxvaStructure.num_extra_slice_header_bits = pps->num_extra_slice_header_bits;
|
||||||
|
dxvaStructure.sign_data_hiding_enabled_flag = pps->sign_data_hiding_enabled_flag;
|
||||||
|
dxvaStructure.cabac_init_present_flag = pps->cabac_init_present_flag;
|
||||||
|
dxvaStructure.ReservedBits3 = 0;
|
||||||
|
|
||||||
|
dxvaStructure.constrained_intra_pred_flag = pps->constrained_intra_pred_flag;
|
||||||
|
dxvaStructure.transform_skip_enabled_flag = pps->transform_skip_enabled_flag;
|
||||||
|
dxvaStructure.cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag;
|
||||||
|
dxvaStructure.pps_slice_chroma_qp_offsets_present_flag = pps->pps_slice_chroma_qp_offsets_present_flag;
|
||||||
|
dxvaStructure.weighted_pred_flag = pps->weighted_pred_flag;
|
||||||
|
dxvaStructure.weighted_bipred_flag = pps->weighted_bipred_flag;
|
||||||
|
dxvaStructure.transquant_bypass_enabled_flag = pps->transquant_bypass_enabled_flag;
|
||||||
|
dxvaStructure.tiles_enabled_flag = pps->tiles_enabled_flag;
|
||||||
|
dxvaStructure.entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag;
|
||||||
|
dxvaStructure.uniform_spacing_flag = pps->uniform_spacing_flag;
|
||||||
|
dxvaStructure.loop_filter_across_tiles_enabled_flag = (pps->tiles_enabled_flag ? pps->loop_filter_across_tiles_enabled_flag : 0);
|
||||||
|
dxvaStructure.pps_loop_filter_across_slices_enabled_flag = pps->pps_loop_filter_across_slices_enabled_flag;
|
||||||
|
dxvaStructure.deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag;
|
||||||
|
dxvaStructure.pps_deblocking_filter_disabled_flag = pps->pps_deblocking_filter_disabled_flag;
|
||||||
|
dxvaStructure.lists_modification_present_flag = pps->lists_modification_present_flag;
|
||||||
|
dxvaStructure.slice_segment_header_extension_present_flag = pps->slice_segment_header_extension_present_flag;
|
||||||
|
dxvaStructure.IrapPicFlag = pPipeDesc->RAPPicFlag;
|
||||||
|
dxvaStructure.IdrPicFlag = pPipeDesc->IDRPicFlag;
|
||||||
|
dxvaStructure.IntraPicFlag = pPipeDesc->IntraPicFlag;
|
||||||
|
dxvaStructure.pps_cb_qp_offset = pps->pps_cb_qp_offset;
|
||||||
|
dxvaStructure.pps_cr_qp_offset = pps->pps_cr_qp_offset;
|
||||||
|
if (pps->tiles_enabled_flag) {
|
||||||
|
dxvaStructure.num_tile_columns_minus1 = pps->num_tile_columns_minus1;
|
||||||
|
dxvaStructure.num_tile_rows_minus1 = pps->num_tile_rows_minus1;
|
||||||
|
if (!pps->uniform_spacing_flag) {
|
||||||
|
for (uint8_t i = 0; i < _countof(dxvaStructure.column_width_minus1); i++)
|
||||||
|
dxvaStructure.column_width_minus1[i] = pps->column_width_minus1[i];
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < _countof(dxvaStructure.row_height_minus1); i++)
|
||||||
|
dxvaStructure.row_height_minus1[i] = pps->row_height_minus1[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dxvaStructure.diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth;
|
||||||
|
dxvaStructure.pps_beta_offset_div2 = pps->pps_beta_offset_div2;
|
||||||
|
dxvaStructure.pps_tc_offset_div2 = pps->pps_tc_offset_div2;
|
||||||
|
dxvaStructure.log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level_minus2;
|
||||||
|
dxvaStructure.CurrPicOrderCntVal = pPipeDesc->CurrPicOrderCntVal;
|
||||||
|
|
||||||
|
// Update RefPicList with the DPB pictures to be kept alive for current or future frames
|
||||||
|
for (uint8_t refIdx = 0; refIdx < _countof(DXVA_PicParams_HEVC::PicOrderCntValList); refIdx++)
|
||||||
|
{
|
||||||
|
if (pPipeDesc->ref[refIdx] != nullptr) {
|
||||||
|
// Mark as used so d3d12_video_decoder_refresh_dpb_active_references_hevc will assign the correct Index7Bits
|
||||||
|
dxvaStructure.RefPicList[refIdx].Index7Bits = 0;
|
||||||
|
// Mark refpic as LTR if necessary.
|
||||||
|
dxvaStructure.RefPicList[refIdx].AssociatedFlag = pPipeDesc->IsLongTerm[refIdx] ? 1u : 0u;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dxvaStructure.RefPicList[refIdx].bPicEntry = DXVA_HEVC_INVALID_PICTURE_ENTRY_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy POC values for the references
|
||||||
|
memcpy(dxvaStructure.PicOrderCntValList, pPipeDesc->PicOrderCntVal, sizeof(dxvaStructure.PicOrderCntValList));
|
||||||
|
|
||||||
|
// Copy RPS Sets to DXVA or mark them as 0xFF if unused in current frame
|
||||||
|
for (uint8_t i = 0; i < DXVA_RPS_COUNT; i++) {
|
||||||
|
dxvaStructure.RefPicSetStCurrBefore[i] = (i < pPipeDesc->NumPocStCurrBefore) ? pPipeDesc->RefPicSetStCurrBefore[i] : DXVA_HEVC_INVALID_PICTURE_ENTRY_VALUE;
|
||||||
|
dxvaStructure.RefPicSetStCurrAfter[i] = (i < pPipeDesc->NumPocStCurrAfter) ? pPipeDesc->RefPicSetStCurrAfter[i] : DXVA_HEVC_INVALID_PICTURE_ENTRY_VALUE;
|
||||||
|
dxvaStructure.RefPicSetLtCurr[i] = (i < pPipeDesc->NumPocLtCurr) ? pPipeDesc->RefPicSetLtCurr[i] : DXVA_HEVC_INVALID_PICTURE_ENTRY_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DXVA drivers expect these in POC order, VA/pipe sends them out of order.
|
||||||
|
d3d12_video_decoder_sort_rps_lists_by_refpoc(&dxvaStructure, pPipeDesc);
|
||||||
|
|
||||||
|
for (uint32_t refIdx = 0; refIdx < DXVA_RPS_COUNT; refIdx++) {
|
||||||
|
if ((refIdx < pPipeDesc->NumPocStCurrBefore) && (pPipeDesc->RefPicSetStCurrBefore[refIdx] != DXVA_HEVC_INVALID_PICTURE_ENTRY_VALUE)) {
|
||||||
|
debug_printf("pPipeDesc->RefPicSetStCurrBefore[%d]: %d (index into RefPicList) Refs[%d] pipe buffer ptr = %p - d3d12 resource %p POC: %d\n",
|
||||||
|
refIdx, pPipeDesc->RefPicSetStCurrBefore[refIdx], pPipeDesc->RefPicSetStCurrBefore[refIdx], pPipeDesc->ref[pPipeDesc->RefPicSetStCurrBefore[refIdx]],
|
||||||
|
d3d12_resource_resource(((struct d3d12_video_buffer *)(pPipeDesc->ref[pPipeDesc->RefPicSetStCurrBefore[refIdx]]))->texture),
|
||||||
|
dxvaStructure.PicOrderCntValList[pPipeDesc->RefPicSetStCurrBefore[refIdx]]);
|
||||||
|
}
|
||||||
|
if ((refIdx < pPipeDesc->NumPocStCurrAfter) && (pPipeDesc->RefPicSetStCurrAfter[refIdx] != DXVA_HEVC_INVALID_PICTURE_ENTRY_VALUE)) {
|
||||||
|
debug_printf("pPipeDesc->RefPicSetStCurrAfter[%d]: %d (index into RefPicList) Refs[%d] pipe buffer ptr = %p - d3d12 resource %p POC: %d\n",
|
||||||
|
refIdx, pPipeDesc->RefPicSetStCurrAfter[refIdx], pPipeDesc->RefPicSetStCurrAfter[refIdx], pPipeDesc->ref[pPipeDesc->RefPicSetStCurrAfter[refIdx]],
|
||||||
|
d3d12_resource_resource(((struct d3d12_video_buffer *)(pPipeDesc->ref[pPipeDesc->RefPicSetStCurrAfter[refIdx]]))->texture),
|
||||||
|
dxvaStructure.PicOrderCntValList[pPipeDesc->RefPicSetStCurrAfter[refIdx]]);
|
||||||
|
}
|
||||||
|
if ((refIdx < pPipeDesc->NumPocLtCurr) && (pPipeDesc->RefPicSetLtCurr[refIdx] != DXVA_HEVC_INVALID_PICTURE_ENTRY_VALUE)) {
|
||||||
|
debug_printf("pPipeDesc->RefPicSetLtCurr[%d]: %d (index into RefPicList) Refs[%d] pipe buffer ptr = %p - d3d12 resource %p POC: %d\n",
|
||||||
|
refIdx, pPipeDesc->RefPicSetLtCurr[refIdx], pPipeDesc->RefPicSetLtCurr[refIdx], pPipeDesc->ref[pPipeDesc->RefPicSetLtCurr[refIdx]],
|
||||||
|
d3d12_resource_resource(((struct d3d12_video_buffer *)(pPipeDesc->ref[pPipeDesc->RefPicSetLtCurr[refIdx]]))->texture),
|
||||||
|
dxvaStructure.PicOrderCntValList[pPipeDesc->RefPicSetLtCurr[refIdx]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DXVA spec: Arbitrary number set by the host decoder to use as a tag in the status report
|
||||||
|
// feedback data. The value should not equal 0, and should be different in each call to
|
||||||
|
// Execute. For more information, see section 12.0, Status Report Data Structure.
|
||||||
|
dxvaStructure.StatusReportFeedbackNumber = frameNum;
|
||||||
|
assert(dxvaStructure.StatusReportFeedbackNumber > 0);
|
||||||
|
return dxvaStructure;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_decoder_dxva_qmatrix_from_pipe_picparams_hevc(pipe_h265_picture_desc *pPipeDesc,
|
||||||
|
DXVA_Qmatrix_HEVC &outMatrixBuffer,
|
||||||
|
bool &outScalingListEnabled)
|
||||||
|
{
|
||||||
|
// VA is already converting hevc scaling lists to zigzag order
|
||||||
|
// https://gitlab.freedesktop.org/mesa/mesa/-/commit/63dcfed81f011dae5ca68af3369433be28135415
|
||||||
|
|
||||||
|
outScalingListEnabled = (pPipeDesc->pps->sps->scaling_list_enabled_flag != 0);
|
||||||
|
if (outScalingListEnabled) {
|
||||||
|
memcpy(outMatrixBuffer.ucScalingLists0, pPipeDesc->pps->sps->ScalingList4x4, 6 * 16);
|
||||||
|
memcpy(outMatrixBuffer.ucScalingLists1, pPipeDesc->pps->sps->ScalingList8x8, 6 * 64);
|
||||||
|
memcpy(outMatrixBuffer.ucScalingLists2, pPipeDesc->pps->sps->ScalingList16x16, 6 * 64);
|
||||||
|
memcpy(outMatrixBuffer.ucScalingLists3, pPipeDesc->pps->sps->ScalingList32x32, 2 * 64);
|
||||||
|
memcpy(outMatrixBuffer.ucScalingListDCCoefSizeID2, pPipeDesc->pps->sps->ScalingListDCCoeff16x16, 6);
|
||||||
|
memcpy(outMatrixBuffer.ucScalingListDCCoefSizeID3, pPipeDesc->pps->sps->ScalingListDCCoeff32x32, 2);
|
||||||
|
} else {
|
||||||
|
memset(&outMatrixBuffer, 0, sizeof(outMatrixBuffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
247
src/gallium/drivers/d3d12/d3d12_video_dec_hevc.h
Normal file
247
src/gallium/drivers/d3d12/d3d12_video_dec_hevc.h
Normal file
|
|
@ -0,0 +1,247 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright © Microsoft Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of uint8_tge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef D3D12_VIDEO_DEC_HEVC_H
|
||||||
|
#define D3D12_VIDEO_DEC_HEVC_H
|
||||||
|
|
||||||
|
#include "d3d12_video_types.h"
|
||||||
|
|
||||||
|
// From DXVA spec regarding DXVA_PicEntry_HEVC entries:
|
||||||
|
// Entries that will not be used for decoding the current picture, or any subsequent pictures,
|
||||||
|
// are indicated by setting bPicEntry to 0xFF.
|
||||||
|
// If bPicEntry is not 0xFF, the entry may be used as a reference surface for decoding the current picture or
|
||||||
|
// a subsequent picture (in decoding order).
|
||||||
|
constexpr uint16_t DXVA_HEVC_INVALID_PICTURE_INDEX =
|
||||||
|
0x7F; // This corresponds to DXVA_PicEntry_HEVC.Index7Bits ; Not to be confused with the invalid value for
|
||||||
|
// DXVA_PicEntry_HEVC.bPicEntry full uint8_t value
|
||||||
|
constexpr uint16_t DXVA_HEVC_INVALID_PICTURE_ENTRY_VALUE = 0xFF; // This corresponds to DXVA_PicEntry_HEVC.bPicEntry
|
||||||
|
|
||||||
|
constexpr unsigned int DXVA_HEVC_START_CODE = 0x000001; // 3 byte start code
|
||||||
|
constexpr unsigned int DXVA_HEVC_START_CODE_LEN_BITS = 24; // 3 byte start code
|
||||||
|
#define DXVA_RPS_COUNT 8
|
||||||
|
|
||||||
|
/* HEVC picture entry data structure */
|
||||||
|
/* If including new DXVA structs in this header, check the byte-alignment packing pragma declarations that need to be included with them */
|
||||||
|
#pragma pack(push, BeforeDXVApacking, 1)
|
||||||
|
typedef struct _DXVA_PicEntry_HEVC
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t Index7Bits : 7;
|
||||||
|
uint8_t AssociatedFlag : 1;
|
||||||
|
};
|
||||||
|
uint8_t bPicEntry;
|
||||||
|
};
|
||||||
|
} DXVA_PicEntry_HEVC, *LPDXVA_PicEntry_HEVC; /* 1 byte */
|
||||||
|
#pragma pack(pop, BeforeDXVApacking)
|
||||||
|
|
||||||
|
/* HEVC picture parameters structure */
|
||||||
|
/* If including new DXVA structs in this header, check the byte-alignment packing pragma declarations that need to be included with them */
|
||||||
|
#pragma pack(push, BeforeDXVApacking, 1)
|
||||||
|
/* HEVC Picture Parameter structure */
|
||||||
|
typedef struct _DXVA_PicParams_HEVC {
|
||||||
|
uint16_t PicWidthInMinCbsY;
|
||||||
|
uint16_t PicHeightInMinCbsY;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint16_t chroma_format_idc : 2;
|
||||||
|
uint16_t separate_colour_plane_flag : 1;
|
||||||
|
uint16_t bit_depth_luma_minus8 : 3;
|
||||||
|
uint16_t bit_depth_chroma_minus8 : 3;
|
||||||
|
uint16_t log2_max_pic_order_cnt_lsb_minus4 : 4;
|
||||||
|
uint16_t NoPicReorderingFlag : 1;
|
||||||
|
uint16_t NoBiPredFlag : 1;
|
||||||
|
uint16_t ReservedBits1 : 1;
|
||||||
|
};
|
||||||
|
uint16_t wFormatAndSequenceInfoFlags;
|
||||||
|
};
|
||||||
|
DXVA_PicEntry_HEVC CurrPic;
|
||||||
|
uint8_t sps_max_dec_pic_buffering_minus1;
|
||||||
|
uint8_t log2_min_luma_coding_block_size_minus3;
|
||||||
|
uint8_t log2_diff_max_min_luma_coding_block_size;
|
||||||
|
uint8_t log2_min_transform_block_size_minus2;
|
||||||
|
uint8_t log2_diff_max_min_transform_block_size;
|
||||||
|
uint8_t max_transform_hierarchy_depth_inter;
|
||||||
|
uint8_t max_transform_hierarchy_depth_intra;
|
||||||
|
uint8_t num_short_term_ref_pic_sets;
|
||||||
|
uint8_t num_long_term_ref_pics_sps;
|
||||||
|
uint8_t num_ref_idx_l0_default_active_minus1;
|
||||||
|
uint8_t num_ref_idx_l1_default_active_minus1;
|
||||||
|
uint8_t init_qp_minus26;
|
||||||
|
uint8_t ucNumDeltaPocsOfRefRpsIdx;
|
||||||
|
uint16_t wNumBitsForShortTermRPSInSlice;
|
||||||
|
uint16_t ReservedBits2;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint32_t scaling_list_enabled_flag : 1;
|
||||||
|
uint32_t amp_enabled_flag : 1;
|
||||||
|
uint32_t sample_adaptive_offset_enabled_flag : 1;
|
||||||
|
uint32_t pcm_enabled_flag : 1;
|
||||||
|
uint32_t pcm_sample_bit_depth_luma_minus1 : 4;
|
||||||
|
uint32_t pcm_sample_bit_depth_chroma_minus1 : 4;
|
||||||
|
uint32_t log2_min_pcm_luma_coding_block_size_minus3 : 2;
|
||||||
|
uint32_t log2_diff_max_min_pcm_luma_coding_block_size : 2;
|
||||||
|
uint32_t pcm_loop_filter_disabled_flag : 1;
|
||||||
|
uint32_t long_term_ref_pics_present_flag : 1;
|
||||||
|
uint32_t sps_temporal_mvp_enabled_flag : 1;
|
||||||
|
uint32_t strong_intra_smoothing_enabled_flag : 1;
|
||||||
|
uint32_t dependent_slice_segments_enabled_flag : 1;
|
||||||
|
uint32_t output_flag_present_flag : 1;
|
||||||
|
uint32_t num_extra_slice_header_bits : 3;
|
||||||
|
uint32_t sign_data_hiding_enabled_flag : 1;
|
||||||
|
uint32_t cabac_init_present_flag : 1;
|
||||||
|
uint32_t ReservedBits3 : 5;
|
||||||
|
};
|
||||||
|
uint32_t dwCodingParamToolFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint32_t constrained_intra_pred_flag : 1;
|
||||||
|
uint32_t transform_skip_enabled_flag : 1;
|
||||||
|
uint32_t cu_qp_delta_enabled_flag : 1;
|
||||||
|
uint32_t pps_slice_chroma_qp_offsets_present_flag : 1;
|
||||||
|
uint32_t weighted_pred_flag : 1;
|
||||||
|
uint32_t weighted_bipred_flag : 1;
|
||||||
|
uint32_t transquant_bypass_enabled_flag : 1;
|
||||||
|
uint32_t tiles_enabled_flag : 1;
|
||||||
|
uint32_t entropy_coding_sync_enabled_flag : 1;
|
||||||
|
uint32_t uniform_spacing_flag : 1;
|
||||||
|
uint32_t loop_filter_across_tiles_enabled_flag : 1;
|
||||||
|
uint32_t pps_loop_filter_across_slices_enabled_flag : 1;
|
||||||
|
uint32_t deblocking_filter_override_enabled_flag : 1;
|
||||||
|
uint32_t pps_deblocking_filter_disabled_flag : 1;
|
||||||
|
uint32_t lists_modification_present_flag : 1;
|
||||||
|
uint32_t slice_segment_header_extension_present_flag : 1;
|
||||||
|
uint32_t IrapPicFlag : 1;
|
||||||
|
uint32_t IdrPicFlag : 1;
|
||||||
|
uint32_t IntraPicFlag : 1;
|
||||||
|
uint32_t ReservedBits4 : 13;
|
||||||
|
};
|
||||||
|
uint32_t dwCodingSettingPicturePropertyFlags;
|
||||||
|
};
|
||||||
|
uint8_t pps_cb_qp_offset;
|
||||||
|
uint8_t pps_cr_qp_offset;
|
||||||
|
uint8_t num_tile_columns_minus1;
|
||||||
|
uint8_t num_tile_rows_minus1;
|
||||||
|
uint16_t column_width_minus1[19];
|
||||||
|
uint16_t row_height_minus1[21];
|
||||||
|
uint8_t diff_cu_qp_delta_depth;
|
||||||
|
uint8_t pps_beta_offset_div2;
|
||||||
|
uint8_t pps_tc_offset_div2;
|
||||||
|
uint8_t log2_parallel_merge_level_minus2;
|
||||||
|
int32_t CurrPicOrderCntVal;
|
||||||
|
DXVA_PicEntry_HEVC RefPicList[15];
|
||||||
|
uint8_t ReservedBits5;
|
||||||
|
int32_t PicOrderCntValList[15];
|
||||||
|
uint8_t RefPicSetStCurrBefore[8];
|
||||||
|
uint8_t RefPicSetStCurrAfter[8];
|
||||||
|
uint8_t RefPicSetLtCurr[8];
|
||||||
|
uint16_t ReservedBits6;
|
||||||
|
uint16_t ReservedBits7;
|
||||||
|
uint32_t StatusReportFeedbackNumber;
|
||||||
|
} DXVA_PicParams_HEVC, *LPDXVA_PicParams_HEVC;
|
||||||
|
#pragma pack(pop, BeforeDXVApacking)
|
||||||
|
|
||||||
|
static_assert(_countof(DXVA_PicParams_HEVC::RefPicSetStCurrBefore) == DXVA_RPS_COUNT,
|
||||||
|
"DXVA_PicParams_HEVC::RefPicSetStCurrBefore must have DXVA_RPS_COUNT elements");
|
||||||
|
static_assert(_countof(DXVA_PicParams_HEVC::RefPicSetStCurrAfter) == DXVA_RPS_COUNT,
|
||||||
|
"DXVA_PicParams_HEVC::RefPicSetStCurrAfter must have DXVA_RPS_COUNT elements");
|
||||||
|
static_assert(_countof(DXVA_PicParams_HEVC::RefPicSetLtCurr) == DXVA_RPS_COUNT,
|
||||||
|
"DXVA_PicParams_HEVC::RefPicSetLtCurr must have DXVA_RPS_COUNT elements");
|
||||||
|
|
||||||
|
/* HEVC Quantization Matrix structure */
|
||||||
|
/* If including new DXVA structs in this header, check the byte-alignment packing pragma declarations that need to be included with them */
|
||||||
|
#pragma pack(push, BeforeDXVApacking, 1)
|
||||||
|
typedef struct _DXVA_Qmatrix_HEVC
|
||||||
|
{
|
||||||
|
uint8_t ucScalingLists0[6][16];
|
||||||
|
uint8_t ucScalingLists1[6][64];
|
||||||
|
uint8_t ucScalingLists2[6][64];
|
||||||
|
uint8_t ucScalingLists3[2][64];
|
||||||
|
uint8_t ucScalingListDCCoefSizeID2[6];
|
||||||
|
uint8_t ucScalingListDCCoefSizeID3[2];
|
||||||
|
} DXVA_Qmatrix_HEVC, *LPDXVA_Qmatrix_HEVC;
|
||||||
|
#pragma pack(pop, BeforeDXVApacking)
|
||||||
|
|
||||||
|
/* HEVC slice control data structure - short form */
|
||||||
|
/* If including new DXVA structs in this header, check the byte-alignment packing pragma declarations that need to be included with them */
|
||||||
|
#pragma pack(push, BeforeDXVApacking, 1)
|
||||||
|
typedef struct _DXVA_Slice_HEVC_Short
|
||||||
|
{
|
||||||
|
uint32_t BSNALunitDataLocation; /* type 1..5 */
|
||||||
|
uint32_t SliceBytesInBuffer; /* for off-host parse */
|
||||||
|
uint16_t wBadSliceChopping; /* for off-host parse */
|
||||||
|
} DXVA_Slice_HEVC_Short, *LPDXVA_Slice_HEVC_Short;
|
||||||
|
#pragma pack(pop, BeforeDXVApacking)
|
||||||
|
|
||||||
|
#pragma pack(push, BeforeDXVApacking, 1)
|
||||||
|
typedef struct _DXVA_Status_HEVC {
|
||||||
|
uint16_t StatusReportFeedbackNumber;
|
||||||
|
DXVA_PicEntry_HEVC CurrPic;
|
||||||
|
uint8_t bBufType;
|
||||||
|
uint8_t bStatus;
|
||||||
|
uint8_t bReserved8Bits;
|
||||||
|
uint16_t wNumMbsAffected;
|
||||||
|
} DXVA_Status_HEVC, *LPDXVA_Status_HEVC;
|
||||||
|
#pragma pack(pop, BeforeDXVApacking)
|
||||||
|
|
||||||
|
DXVA_PicParams_HEVC
|
||||||
|
d3d12_video_decoder_dxva_picparams_from_pipe_picparams_hevc(uint32_t frameNum,
|
||||||
|
pipe_video_profile profile,
|
||||||
|
pipe_h265_picture_desc *pipeDesc);
|
||||||
|
void
|
||||||
|
d3d12_video_decoder_get_frame_info_hevc(
|
||||||
|
struct d3d12_video_decoder *pD3D12Dec, uint32_t *pWidth, uint32_t *pHeight, uint16_t *pMaxDPB, bool &isInterlaced);
|
||||||
|
void
|
||||||
|
d3d12_video_decoder_prepare_current_frame_references_hevc(struct d3d12_video_decoder *pD3D12Dec,
|
||||||
|
ID3D12Resource * pTexture2D,
|
||||||
|
uint32_t subresourceIndex);
|
||||||
|
void
|
||||||
|
d3d12_video_decoder_dxva_qmatrix_from_pipe_picparams_hevc(pipe_h265_picture_desc *pPipeDesc,
|
||||||
|
DXVA_Qmatrix_HEVC & outMatrixBuffer,
|
||||||
|
bool &outScalingListEnabled);
|
||||||
|
void
|
||||||
|
d3d12_video_decoder_refresh_dpb_active_references_hevc(struct d3d12_video_decoder *pD3D12Dec);
|
||||||
|
bool
|
||||||
|
d3d12_video_decoder_get_next_slice_size_and_offset_hevc(std::vector<uint8_t> &buf,
|
||||||
|
unsigned int bufferOffset,
|
||||||
|
uint32_t & outSliceSize,
|
||||||
|
uint32_t & outSliceOffset);
|
||||||
|
|
||||||
|
uint
|
||||||
|
d3d12_video_decoder_get_slice_count_hevc(std::vector<uint8_t> &buf);
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_decoder_prepare_dxva_slices_control_hevc(struct d3d12_video_decoder * pD3D12Dec,
|
||||||
|
std::vector<DXVA_Slice_HEVC_Short> &pOutSliceControlBuffers,
|
||||||
|
struct pipe_h265_picture_desc* picture_hevc);
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_decoder_log_pic_params_hevc(DXVA_PicParams_HEVC * pPicParams);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "d3d12_video_dec_references_mgr.h"
|
#include "d3d12_video_dec_references_mgr.h"
|
||||||
#include "d3d12_video_dec_h264.h"
|
#include "d3d12_video_dec_h264.h"
|
||||||
|
#include "d3d12_video_dec_hevc.h"
|
||||||
#include "d3d12_video_texture_array_dpb_manager.h"
|
#include "d3d12_video_texture_array_dpb_manager.h"
|
||||||
#include "d3d12_video_array_of_textures_dpb_manager.h"
|
#include "d3d12_video_array_of_textures_dpb_manager.h"
|
||||||
#include "d3d12_screen.h"
|
#include "d3d12_screen.h"
|
||||||
|
|
@ -40,6 +41,8 @@ GetInvalidReferenceIndex(d3d12_video_decode_profile_type DecodeProfileType)
|
||||||
switch (DecodeProfileType) {
|
switch (DecodeProfileType) {
|
||||||
case d3d12_video_decode_profile_type_h264:
|
case d3d12_video_decode_profile_type_h264:
|
||||||
return DXVA_H264_INVALID_PICTURE_INDEX;
|
return DXVA_H264_INVALID_PICTURE_INDEX;
|
||||||
|
case d3d12_video_decode_profile_type_hevc:
|
||||||
|
return DXVA_HEVC_INVALID_PICTURE_INDEX;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -31,10 +31,12 @@
|
||||||
#include "d3d12_surface.h"
|
#include "d3d12_surface.h"
|
||||||
#include "d3d12_video_enc.h"
|
#include "d3d12_video_enc.h"
|
||||||
#include "d3d12_video_enc_h264.h"
|
#include "d3d12_video_enc_h264.h"
|
||||||
|
#include "d3d12_video_enc_hevc.h"
|
||||||
#include "d3d12_video_buffer.h"
|
#include "d3d12_video_buffer.h"
|
||||||
#include "d3d12_video_texture_array_dpb_manager.h"
|
#include "d3d12_video_texture_array_dpb_manager.h"
|
||||||
#include "d3d12_video_array_of_textures_dpb_manager.h"
|
#include "d3d12_video_array_of_textures_dpb_manager.h"
|
||||||
#include "d3d12_video_encoder_references_manager_h264.h"
|
#include "d3d12_video_encoder_references_manager_h264.h"
|
||||||
|
#include "d3d12_video_encoder_references_manager_hevc.h"
|
||||||
#include "d3d12_residency.h"
|
#include "d3d12_residency.h"
|
||||||
|
|
||||||
#include "vl/vl_video_buffer.h"
|
#include "vl/vl_video_buffer.h"
|
||||||
|
|
@ -183,13 +185,18 @@ d3d12_video_encoder_update_picparams_tracking(struct d3d12_video_encoder *pD3D12
|
||||||
d3d12_video_encoder_update_current_frame_pic_params_info_h264(pD3D12Enc, srcTexture, picture, currentPicParams, bUsedAsReference);
|
d3d12_video_encoder_update_current_frame_pic_params_info_h264(pD3D12Enc, srcTexture, picture, currentPicParams, bUsedAsReference);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PIPE_VIDEO_FORMAT_HEVC:
|
||||||
|
{
|
||||||
|
d3d12_video_encoder_update_current_frame_pic_params_info_hevc(pD3D12Enc, srcTexture, picture, currentPicParams, bUsedAsReference);
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported pipe_video_format");
|
unreachable("Unsupported pipe_video_format");
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pD3D12Enc->m_upDPBManager->begin_frame(currentPicParams, bUsedAsReference);
|
pD3D12Enc->m_upDPBManager->begin_frame(currentPicParams, bUsedAsReference, picture);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -415,6 +422,24 @@ d3d12_video_encoder_create_reference_picture_manager(struct d3d12_video_encoder
|
||||||
pD3D12Enc->m_upBitstreamBuilder = std::make_unique<d3d12_video_bitstream_builder_h264>();
|
pD3D12Enc->m_upBitstreamBuilder = std::make_unique<d3d12_video_bitstream_builder_h264>();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PIPE_VIDEO_FORMAT_HEVC:
|
||||||
|
{
|
||||||
|
bool gopHasPFrames =
|
||||||
|
(pD3D12Enc->m_currentEncodeConfig.m_encoderGOPConfigDesc.m_HEVCGroupOfPictures.PPicturePeriod > 0) &&
|
||||||
|
((pD3D12Enc->m_currentEncodeConfig.m_encoderGOPConfigDesc.m_HEVCGroupOfPictures.GOPLength == 0) ||
|
||||||
|
(pD3D12Enc->m_currentEncodeConfig.m_encoderGOPConfigDesc.m_HEVCGroupOfPictures.PPicturePeriod <
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderGOPConfigDesc.m_HEVCGroupOfPictures.GOPLength));
|
||||||
|
|
||||||
|
pD3D12Enc->m_upDPBManager = std::make_unique<d3d12_video_encoder_references_manager_hevc>(
|
||||||
|
gopHasPFrames,
|
||||||
|
*pD3D12Enc->m_upDPBStorageManager,
|
||||||
|
// Max number of frames to be used as a reference, without counting the current recon picture
|
||||||
|
d3d12_video_encoder_get_current_max_dpb_capacity(pD3D12Enc)
|
||||||
|
);
|
||||||
|
|
||||||
|
pD3D12Enc->m_upBitstreamBuilder = std::make_unique<d3d12_video_bitstream_builder_hevc>();
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported pipe_video_format");
|
unreachable("Unsupported pipe_video_format");
|
||||||
|
|
@ -439,6 +464,18 @@ d3d12_video_encoder_get_current_slice_param_settings(struct d3d12_video_encoder
|
||||||
return subregionData;
|
return subregionData;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PIPE_VIDEO_FORMAT_HEVC:
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA subregionData = {};
|
||||||
|
if (pD3D12Enc->m_currentEncodeConfig.m_encoderSliceConfigMode !=
|
||||||
|
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME) {
|
||||||
|
subregionData.pSlicesPartition_HEVC =
|
||||||
|
&pD3D12Enc->m_currentEncodeConfig.m_encoderSliceConfigDesc.m_SlicesPartition_HEVC;
|
||||||
|
subregionData.DataSize = sizeof(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_SLICES);
|
||||||
|
}
|
||||||
|
return subregionData;
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported pipe_video_format");
|
unreachable("Unsupported pipe_video_format");
|
||||||
|
|
@ -459,6 +496,14 @@ d3d12_video_encoder_get_current_picture_param_settings(struct d3d12_video_encode
|
||||||
return curPicParamsData;
|
return curPicParamsData;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PIPE_VIDEO_FORMAT_HEVC:
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA curPicParamsData = {};
|
||||||
|
curPicParamsData.pHEVCPicData = &pD3D12Enc->m_currentEncodeConfig.m_encoderPicParamsDesc.m_HEVCPicData;
|
||||||
|
curPicParamsData.DataSize = sizeof(pD3D12Enc->m_currentEncodeConfig.m_encoderPicParamsDesc.m_HEVCPicData);
|
||||||
|
return curPicParamsData;
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported pipe_video_format");
|
unreachable("Unsupported pipe_video_format");
|
||||||
|
|
@ -530,6 +575,14 @@ d3d12_video_encoder_get_current_level_desc(struct d3d12_video_encoder *pD3D12Enc
|
||||||
return curLevelDesc;
|
return curLevelDesc;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PIPE_VIDEO_FORMAT_HEVC:
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODER_LEVEL_SETTING curLevelDesc = {};
|
||||||
|
curLevelDesc.pHEVCLevelSetting = &pD3D12Enc->m_currentEncodeConfig.m_encoderLevelDesc.m_HEVCLevelSetting;
|
||||||
|
curLevelDesc.DataSize = sizeof(pD3D12Enc->m_currentEncodeConfig.m_encoderLevelDesc.m_HEVCLevelSetting);
|
||||||
|
return curLevelDesc;
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported pipe_video_format");
|
unreachable("Unsupported pipe_video_format");
|
||||||
|
|
@ -548,6 +601,12 @@ d3d12_video_encoder_build_codec_headers(struct d3d12_video_encoder *pD3D12Enc)
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PIPE_VIDEO_FORMAT_HEVC:
|
||||||
|
{
|
||||||
|
return d3d12_video_encoder_build_codec_headers_hevc(pD3D12Enc);
|
||||||
|
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported pipe_video_format");
|
unreachable("Unsupported pipe_video_format");
|
||||||
|
|
@ -570,6 +629,15 @@ d3d12_video_encoder_get_current_gop_desc(struct d3d12_video_encoder *pD3D12Enc)
|
||||||
return curGOPDesc;
|
return curGOPDesc;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PIPE_VIDEO_FORMAT_HEVC:
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE curGOPDesc = {};
|
||||||
|
curGOPDesc.pHEVCGroupOfPictures =
|
||||||
|
&pD3D12Enc->m_currentEncodeConfig.m_encoderGOPConfigDesc.m_HEVCGroupOfPictures;
|
||||||
|
curGOPDesc.DataSize = sizeof(pD3D12Enc->m_currentEncodeConfig.m_encoderGOPConfigDesc.m_HEVCGroupOfPictures);
|
||||||
|
return curGOPDesc;
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported pipe_video_format");
|
unreachable("Unsupported pipe_video_format");
|
||||||
|
|
@ -591,6 +659,15 @@ d3d12_video_encoder_get_current_codec_config_desc(struct d3d12_video_encoder *pD
|
||||||
return codecConfigDesc;
|
return codecConfigDesc;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PIPE_VIDEO_FORMAT_HEVC:
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION codecConfigDesc = {};
|
||||||
|
codecConfigDesc.pHEVCConfig = &pD3D12Enc->m_currentEncodeConfig.m_encoderCodecSpecificConfigDesc.m_HEVCConfig;
|
||||||
|
codecConfigDesc.DataSize =
|
||||||
|
sizeof(pD3D12Enc->m_currentEncodeConfig.m_encoderCodecSpecificConfigDesc.m_HEVCConfig);
|
||||||
|
return codecConfigDesc;
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported pipe_video_format");
|
unreachable("Unsupported pipe_video_format");
|
||||||
|
|
@ -607,6 +684,10 @@ d3d12_video_encoder_get_current_codec(struct d3d12_video_encoder *pD3D12Enc)
|
||||||
{
|
{
|
||||||
return D3D12_VIDEO_ENCODER_CODEC_H264;
|
return D3D12_VIDEO_ENCODER_CODEC_H264;
|
||||||
} break;
|
} break;
|
||||||
|
case PIPE_VIDEO_FORMAT_HEVC:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_CODEC_HEVC;
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported pipe_video_format");
|
unreachable("Unsupported pipe_video_format");
|
||||||
|
|
@ -750,6 +831,18 @@ bool d3d12_video_encoder_query_d3d12_driver_caps(struct d3d12_video_encoder *pD3
|
||||||
sizeof(pD3D12Enc->m_currentEncodeCapabilities.m_encoderLevelSuggestedDesc.m_H264LevelSetting);
|
sizeof(pD3D12Enc->m_currentEncodeCapabilities.m_encoderLevelSuggestedDesc.m_H264LevelSetting);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PIPE_VIDEO_FORMAT_HEVC:
|
||||||
|
{
|
||||||
|
capEncoderSupportData.SuggestedProfile.pHEVCProfile =
|
||||||
|
&pD3D12Enc->m_currentEncodeCapabilities.m_encoderSuggestedProfileDesc.m_HEVCProfile;
|
||||||
|
capEncoderSupportData.SuggestedProfile.DataSize =
|
||||||
|
sizeof(pD3D12Enc->m_currentEncodeCapabilities.m_encoderSuggestedProfileDesc.m_HEVCProfile);
|
||||||
|
capEncoderSupportData.SuggestedLevel.pHEVCLevelSetting =
|
||||||
|
&pD3D12Enc->m_currentEncodeCapabilities.m_encoderLevelSuggestedDesc.m_HEVCLevelSetting;
|
||||||
|
capEncoderSupportData.SuggestedLevel.DataSize =
|
||||||
|
sizeof(pD3D12Enc->m_currentEncodeCapabilities.m_encoderLevelSuggestedDesc.m_HEVCLevelSetting);
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported pipe_video_format");
|
unreachable("Unsupported pipe_video_format");
|
||||||
|
|
@ -803,6 +896,14 @@ d3d12_video_encoder_get_current_profile_desc(struct d3d12_video_encoder *pD3D12E
|
||||||
return curProfDesc;
|
return curProfDesc;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PIPE_VIDEO_FORMAT_HEVC:
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODER_PROFILE_DESC curProfDesc = {};
|
||||||
|
curProfDesc.pHEVCProfile = &pD3D12Enc->m_currentEncodeConfig.m_encoderProfileDesc.m_HEVCProfile;
|
||||||
|
curProfDesc.DataSize = sizeof(pD3D12Enc->m_currentEncodeConfig.m_encoderProfileDesc.m_HEVCProfile);
|
||||||
|
return curProfDesc;
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported pipe_video_format");
|
unreachable("Unsupported pipe_video_format");
|
||||||
|
|
@ -828,6 +929,11 @@ d3d12_video_encoder_update_current_encoder_config_state(struct d3d12_video_encod
|
||||||
return d3d12_video_encoder_update_current_encoder_config_state_h264(pD3D12Enc, srcTexture, picture);
|
return d3d12_video_encoder_update_current_encoder_config_state_h264(pD3D12Enc, srcTexture, picture);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PIPE_VIDEO_FORMAT_HEVC:
|
||||||
|
{
|
||||||
|
return d3d12_video_encoder_update_current_encoder_config_state_hevc(pD3D12Enc, srcTexture, picture);
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported pipe_video_format");
|
unreachable("Unsupported pipe_video_format");
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
#include "d3d12_video_encoder_references_manager.h"
|
#include "d3d12_video_encoder_references_manager.h"
|
||||||
#include "d3d12_video_dpb_storage_manager.h"
|
#include "d3d12_video_dpb_storage_manager.h"
|
||||||
#include "d3d12_video_encoder_bitstream_builder_h264.h"
|
#include "d3d12_video_encoder_bitstream_builder_h264.h"
|
||||||
|
#include "d3d12_video_encoder_bitstream_builder_hevc.h"
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Pipe video interface starts
|
/// Pipe video interface starts
|
||||||
|
|
@ -161,6 +162,12 @@ struct d3d12_video_encoder
|
||||||
D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC m_HEVCLevelSetting;
|
D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC m_HEVCLevelSetting;
|
||||||
} m_encoderLevelSuggestedDesc = {};
|
} m_encoderLevelSuggestedDesc = {};
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_H264 m_H264CodecCaps;
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC m_HEVCCodecCaps;
|
||||||
|
} m_encoderCodecSpecificConfigCaps = {};
|
||||||
|
|
||||||
// Required size for the layout-resolved metadata buffer of current frame to be encoded
|
// Required size for the layout-resolved metadata buffer of current frame to be encoded
|
||||||
size_t m_resolvedLayoutMetadataBufferRequiredSize;
|
size_t m_resolvedLayoutMetadataBufferRequiredSize;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ d3d12_video_encoder_update_current_frame_pic_params_info_h264(struct d3d12_video
|
||||||
|
|
||||||
picParams.pH264PicData->pic_parameter_set_id = pH264BitstreamBuilder->get_active_pps_id();
|
picParams.pH264PicData->pic_parameter_set_id = pH264BitstreamBuilder->get_active_pps_id();
|
||||||
picParams.pH264PicData->idr_pic_id = h264Pic->idr_pic_id;
|
picParams.pH264PicData->idr_pic_id = h264Pic->idr_pic_id;
|
||||||
picParams.pH264PicData->FrameType = d3d12_video_encoder_convert_frame_type(h264Pic->picture_type);
|
picParams.pH264PicData->FrameType = d3d12_video_encoder_convert_frame_type_h264(h264Pic->picture_type);
|
||||||
picParams.pH264PicData->PictureOrderCountNumber = h264Pic->pic_order_cnt;
|
picParams.pH264PicData->PictureOrderCountNumber = h264Pic->pic_order_cnt;
|
||||||
picParams.pH264PicData->FrameDecodingOrderNumber = h264Pic->frame_num;
|
picParams.pH264PicData->FrameDecodingOrderNumber = h264Pic->frame_num;
|
||||||
|
|
||||||
|
|
@ -141,7 +141,7 @@ d3d12_video_encoder_update_current_frame_pic_params_info_h264(struct d3d12_video
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D12_VIDEO_ENCODER_FRAME_TYPE_H264
|
D3D12_VIDEO_ENCODER_FRAME_TYPE_H264
|
||||||
d3d12_video_encoder_convert_frame_type(enum pipe_h2645_enc_picture_type picType)
|
d3d12_video_encoder_convert_frame_type_h264(enum pipe_h2645_enc_picture_type picType)
|
||||||
{
|
{
|
||||||
switch (picType) {
|
switch (picType) {
|
||||||
case PIPE_H2645_ENC_PICTURE_TYPE_P:
|
case PIPE_H2645_ENC_PICTURE_TYPE_P:
|
||||||
|
|
@ -518,8 +518,10 @@ d3d12_video_encoder_update_h264_gop_configuration(struct d3d12_video_encoder *pD
|
||||||
|
|
||||||
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264
|
||||||
d3d12_video_encoder_convert_h264_codec_configuration(struct d3d12_video_encoder *pD3D12Enc,
|
d3d12_video_encoder_convert_h264_codec_configuration(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
pipe_h264_enc_picture_desc *picture)
|
pipe_h264_enc_picture_desc *picture,
|
||||||
|
bool &is_supported)
|
||||||
{
|
{
|
||||||
|
is_supported = true;
|
||||||
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264 config = {
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264 config = {
|
||||||
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264_FLAG_NONE,
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264_FLAG_NONE,
|
||||||
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264_DIRECT_MODES_DISABLED,
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264_DIRECT_MODES_DISABLED,
|
||||||
|
|
@ -530,6 +532,41 @@ d3d12_video_encoder_convert_h264_codec_configuration(struct d3d12_video_encoder
|
||||||
config.ConfigurationFlags |= D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264_FLAG_ENABLE_CABAC_ENCODING;
|
config.ConfigurationFlags |= D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264_FLAG_ENABLE_CABAC_ENCODING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pD3D12Enc->m_currentEncodeCapabilities.m_encoderCodecSpecificConfigCaps.m_H264CodecCaps =
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_H264_FLAG_NONE,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264_SLICES_DEBLOCKING_MODE_FLAG_NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT capCodecConfigData = { };
|
||||||
|
capCodecConfigData.NodeIndex = pD3D12Enc->m_NodeIndex;
|
||||||
|
capCodecConfigData.Codec = D3D12_VIDEO_ENCODER_CODEC_H264;
|
||||||
|
D3D12_VIDEO_ENCODER_PROFILE_H264 prof = d3d12_video_encoder_convert_profile_to_d3d12_enc_profile_h264(pD3D12Enc->base.profile);
|
||||||
|
capCodecConfigData.Profile.pH264Profile = &prof;
|
||||||
|
capCodecConfigData.Profile.DataSize = sizeof(prof);
|
||||||
|
capCodecConfigData.CodecSupportLimits.pH264Support = &pD3D12Enc->m_currentEncodeCapabilities.m_encoderCodecSpecificConfigCaps.m_H264CodecCaps;
|
||||||
|
capCodecConfigData.CodecSupportLimits.DataSize = sizeof(pD3D12Enc->m_currentEncodeCapabilities.m_encoderCodecSpecificConfigCaps.m_H264CodecCaps);
|
||||||
|
|
||||||
|
if(FAILED(pD3D12Enc->m_spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT, &capCodecConfigData, sizeof(capCodecConfigData))
|
||||||
|
|| !capCodecConfigData.IsSupported))
|
||||||
|
{
|
||||||
|
debug_printf("D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION arguments not supported - DisableDeblockingFilterConfig (value %d) "
|
||||||
|
"not allowed by DisableDeblockingFilterSupportedModes 0x%x cap reporting.",
|
||||||
|
config.DisableDeblockingFilterConfig,
|
||||||
|
capCodecConfigData.CodecSupportLimits.pH264Support->DisableDeblockingFilterSupportedModes);
|
||||||
|
is_supported = false;
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(((config.ConfigurationFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264_FLAG_ENABLE_CABAC_ENCODING) != 0)
|
||||||
|
&& ((capCodecConfigData.CodecSupportLimits.pH264Support->SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_H264_FLAG_CABAC_ENCODING_SUPPORT) == 0))
|
||||||
|
{
|
||||||
|
debug_printf("D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION arguments are not supported - CABAC encoding mode not supported."
|
||||||
|
" Ignoring the request for this feature flag on this encode session");
|
||||||
|
// Disable it and keep going with a warning
|
||||||
|
config.ConfigurationFlags &= ~D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264_FLAG_ENABLE_CABAC_ENCODING;
|
||||||
|
}
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -603,7 +640,12 @@ d3d12_video_encoder_update_current_encoder_config_state_h264(struct d3d12_video_
|
||||||
pD3D12Enc->m_currentEncodeConfig.m_encoderLevelDesc.m_H264LevelSetting = targetLevel;
|
pD3D12Enc->m_currentEncodeConfig.m_encoderLevelDesc.m_H264LevelSetting = targetLevel;
|
||||||
|
|
||||||
// Set codec config
|
// Set codec config
|
||||||
auto targetCodecConfig = d3d12_video_encoder_convert_h264_codec_configuration(pD3D12Enc, h264Pic);
|
bool is_supported = false;
|
||||||
|
auto targetCodecConfig = d3d12_video_encoder_convert_h264_codec_configuration(pD3D12Enc, h264Pic, is_supported);
|
||||||
|
if (!is_supported) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (memcmp(&pD3D12Enc->m_currentEncodeConfig.m_encoderCodecSpecificConfigDesc.m_H264Config,
|
if (memcmp(&pD3D12Enc->m_currentEncodeConfig.m_encoderCodecSpecificConfigDesc.m_H264Config,
|
||||||
&targetCodecConfig,
|
&targetCodecConfig,
|
||||||
sizeof(D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264)) != 0) {
|
sizeof(D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264)) != 0) {
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,8 @@ D3D12_VIDEO_ENCODER_LEVELS_H264
|
||||||
d3d12_video_encoder_convert_level_h264(uint32_t h264SpecLevel);
|
d3d12_video_encoder_convert_level_h264(uint32_t h264SpecLevel);
|
||||||
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264
|
||||||
d3d12_video_encoder_convert_h264_codec_configuration(struct d3d12_video_encoder *pD3D12Enc,
|
d3d12_video_encoder_convert_h264_codec_configuration(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
pipe_h264_enc_picture_desc *picture);
|
pipe_h264_enc_picture_desc *picture,
|
||||||
|
bool &is_supported);
|
||||||
void
|
void
|
||||||
d3d12_video_encoder_update_current_frame_pic_params_info_h264(struct d3d12_video_encoder *pD3D12Enc,
|
d3d12_video_encoder_update_current_frame_pic_params_info_h264(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
struct pipe_video_buffer * srcTexture,
|
struct pipe_video_buffer * srcTexture,
|
||||||
|
|
@ -54,7 +55,7 @@ d3d12_video_encoder_update_current_frame_pic_params_info_h264(struct d3d12_video
|
||||||
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA &picParams,
|
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA &picParams,
|
||||||
bool &bUsedAsReference);
|
bool &bUsedAsReference);
|
||||||
D3D12_VIDEO_ENCODER_FRAME_TYPE_H264
|
D3D12_VIDEO_ENCODER_FRAME_TYPE_H264
|
||||||
d3d12_video_encoder_convert_frame_type(enum pipe_h2645_enc_picture_type picType);
|
d3d12_video_encoder_convert_frame_type_h264(enum pipe_h2645_enc_picture_type picType);
|
||||||
uint32_t
|
uint32_t
|
||||||
d3d12_video_encoder_build_codec_headers_h264(struct d3d12_video_encoder *pD3D12Enc);
|
d3d12_video_encoder_build_codec_headers_h264(struct d3d12_video_encoder *pD3D12Enc);
|
||||||
bool
|
bool
|
||||||
|
|
|
||||||
768
src/gallium/drivers/d3d12/d3d12_video_enc_hevc.cpp
Normal file
768
src/gallium/drivers/d3d12/d3d12_video_enc_hevc.cpp
Normal file
|
|
@ -0,0 +1,768 @@
|
||||||
|
/*
|
||||||
|
* Copyright © Microsoft Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "d3d12_video_enc.h"
|
||||||
|
#include "d3d12_video_enc_hevc.h"
|
||||||
|
#include "util/u_video.h"
|
||||||
|
#include "d3d12_screen.h"
|
||||||
|
#include "d3d12_format.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_encoder_update_current_rate_control_hevc(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
|
pipe_h265_enc_picture_desc *picture)
|
||||||
|
{
|
||||||
|
auto previousConfig = pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc;
|
||||||
|
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc = {};
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_FrameRate.Numerator =
|
||||||
|
picture->rc.frame_rate_num;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_FrameRate.Denominator =
|
||||||
|
picture->rc.frame_rate_den;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Flags = D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_NONE;
|
||||||
|
|
||||||
|
switch (picture->rc.rate_ctrl_method) {
|
||||||
|
case PIPE_H2645_ENC_RATE_CONTROL_METHOD_VARIABLE_SKIP:
|
||||||
|
case PIPE_H2645_ENC_RATE_CONTROL_METHOD_VARIABLE:
|
||||||
|
{
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Mode = D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_VBR;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Config.m_Configuration_VBR.TargetAvgBitRate =
|
||||||
|
picture->rc.target_bitrate;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Config.m_Configuration_VBR.PeakBitRate =
|
||||||
|
picture->rc.peak_bitrate;
|
||||||
|
} break;
|
||||||
|
case PIPE_H2645_ENC_RATE_CONTROL_METHOD_CONSTANT_SKIP:
|
||||||
|
case PIPE_H2645_ENC_RATE_CONTROL_METHOD_CONSTANT:
|
||||||
|
{
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Mode = D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CBR;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Config.m_Configuration_CBR.TargetBitRate =
|
||||||
|
picture->rc.target_bitrate;
|
||||||
|
|
||||||
|
/* For CBR mode, to guarantee bitrate of generated stream complies with
|
||||||
|
* target bitrate (e.g. no over +/-10%), vbv_buffer_size should be same
|
||||||
|
* as target bitrate. Controlled by OS env var D3D12_VIDEO_ENC_CBR_FORCE_VBV_EQUAL_BITRATE
|
||||||
|
*/
|
||||||
|
if (D3D12_VIDEO_ENC_CBR_FORCE_VBV_EQUAL_BITRATE) {
|
||||||
|
debug_printf("[d3d12_video_encoder_hevc] d3d12_video_encoder_update_current_rate_control_hevc D3D12_VIDEO_ENC_CBR_FORCE_VBV_EQUAL_BITRATE environment variable is set, "
|
||||||
|
", forcing VBV Size = Target Bitrate = %" PRIu64 " (bits)\n", pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Config.m_Configuration_CBR.TargetBitRate/2);
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Flags |=
|
||||||
|
D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_VBV_SIZES;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Config.m_Configuration_CBR.VBVCapacity =
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Config.m_Configuration_CBR.TargetBitRate/2;
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case PIPE_H2645_ENC_RATE_CONTROL_METHOD_DISABLE:
|
||||||
|
{
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Mode = D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Config.m_Configuration_CQP
|
||||||
|
.ConstantQP_FullIntracodedFrame = picture->rc.quant_i_frames;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Config.m_Configuration_CQP
|
||||||
|
.ConstantQP_InterPredictedFrame_PrevRefOnly = picture->rc.quant_p_frames;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Config.m_Configuration_CQP
|
||||||
|
.ConstantQP_InterPredictedFrame_BiDirectionalRef = picture->rc.quant_b_frames;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
debug_printf("[d3d12_video_encoder_hevc] d3d12_video_encoder_update_current_rate_control_hevc invalid RC "
|
||||||
|
"config, using default RC CQP mode\n");
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Mode = D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Config.m_Configuration_CQP
|
||||||
|
.ConstantQP_FullIntracodedFrame = 30;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Config.m_Configuration_CQP
|
||||||
|
.ConstantQP_InterPredictedFrame_PrevRefOnly = 30;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc.m_Config.m_Configuration_CQP
|
||||||
|
.ConstantQP_InterPredictedFrame_BiDirectionalRef = 30;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(&previousConfig,
|
||||||
|
&pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc,
|
||||||
|
sizeof(pD3D12Enc->m_currentEncodeConfig.m_encoderRateControlDesc)) != 0) {
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_ConfigDirtyFlags |= d3d12_video_encoder_config_dirty_flag_rate_control;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_encoder_update_current_frame_pic_params_info_hevc(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
|
struct pipe_video_buffer *srcTexture,
|
||||||
|
struct pipe_picture_desc *picture,
|
||||||
|
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA &picParams,
|
||||||
|
bool &bUsedAsReference)
|
||||||
|
{
|
||||||
|
struct pipe_h265_enc_picture_desc *hevcPic = (struct pipe_h265_enc_picture_desc *) picture;
|
||||||
|
d3d12_video_bitstream_builder_hevc *pHEVCBitstreamBuilder =
|
||||||
|
static_cast<d3d12_video_bitstream_builder_hevc *>(pD3D12Enc->m_upBitstreamBuilder.get());
|
||||||
|
assert(pHEVCBitstreamBuilder != nullptr);
|
||||||
|
|
||||||
|
bUsedAsReference = !hevcPic->not_referenced;
|
||||||
|
|
||||||
|
picParams.pHEVCPicData->slice_pic_parameter_set_id = pHEVCBitstreamBuilder->get_active_pps_id();
|
||||||
|
picParams.pHEVCPicData->FrameType = d3d12_video_encoder_convert_frame_type_hevc(hevcPic->picture_type);
|
||||||
|
picParams.pHEVCPicData->PictureOrderCountNumber = hevcPic->pic_order_cnt;
|
||||||
|
|
||||||
|
picParams.pHEVCPicData->List0ReferenceFramesCount = 0;
|
||||||
|
picParams.pHEVCPicData->pList0ReferenceFrames = nullptr;
|
||||||
|
picParams.pHEVCPicData->List1ReferenceFramesCount = 0;
|
||||||
|
picParams.pHEVCPicData->pList1ReferenceFrames = nullptr;
|
||||||
|
|
||||||
|
if (picParams.pHEVCPicData->FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_P_FRAME) {
|
||||||
|
picParams.pHEVCPicData->List0ReferenceFramesCount = hevcPic->num_ref_idx_l0_active_minus1 + 1;
|
||||||
|
picParams.pHEVCPicData->pList0ReferenceFrames = hevcPic->ref_idx_l0_list;
|
||||||
|
} else if (picParams.pHEVCPicData->FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_B_FRAME) {
|
||||||
|
picParams.pHEVCPicData->List0ReferenceFramesCount = hevcPic->num_ref_idx_l0_active_minus1 + 1;
|
||||||
|
picParams.pHEVCPicData->pList0ReferenceFrames = hevcPic->ref_idx_l0_list;
|
||||||
|
picParams.pHEVCPicData->List1ReferenceFramesCount = hevcPic->num_ref_idx_l1_active_minus1 + 1;
|
||||||
|
picParams.pHEVCPicData->pList1ReferenceFrames = hevcPic->ref_idx_l1_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pD3D12Enc->m_currentEncodeConfig.m_encoderCodecSpecificConfigDesc.m_HEVCConfig.ConfigurationFlags
|
||||||
|
& D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ALLOW_REQUEST_INTRA_CONSTRAINED_SLICES) != 0)
|
||||||
|
picParams.pHEVCPicData->Flags |= D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_HEVC_FLAG_REQUEST_INTRA_CONSTRAINED_SLICES;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC
|
||||||
|
d3d12_video_encoder_convert_frame_type_hevc(enum pipe_h2645_enc_picture_type picType)
|
||||||
|
{
|
||||||
|
switch (picType) {
|
||||||
|
case PIPE_H2645_ENC_PICTURE_TYPE_P:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_P_FRAME;
|
||||||
|
} break;
|
||||||
|
case PIPE_H2645_ENC_PICTURE_TYPE_B:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_B_FRAME;
|
||||||
|
} break;
|
||||||
|
case PIPE_H2645_ENC_PICTURE_TYPE_I:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_I_FRAME;
|
||||||
|
} break;
|
||||||
|
case PIPE_H2645_ENC_PICTURE_TYPE_IDR:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_IDR_FRAME;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
unreachable("Unsupported pipe_h2645_enc_picture_type");
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Tries to configurate the encoder using the requested slice configuration
|
||||||
|
/// or falls back to single slice encoding.
|
||||||
|
///
|
||||||
|
bool
|
||||||
|
d3d12_video_encoder_negotiate_current_hevc_slices_configuration(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
|
pipe_h265_enc_picture_desc *picture)
|
||||||
|
{
|
||||||
|
///
|
||||||
|
/// Initialize single slice by default
|
||||||
|
///
|
||||||
|
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE requestedSlicesMode =
|
||||||
|
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME;
|
||||||
|
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_SLICES requestedSlicesConfig = {};
|
||||||
|
requestedSlicesConfig.NumberOfSlicesPerFrame = 1;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Try to see if can accomodate for multi-slice request by user
|
||||||
|
///
|
||||||
|
if (picture->num_slice_descriptors > 1) {
|
||||||
|
/* Last slice can be less for rounding frame size and leave some error for mb rounding */
|
||||||
|
bool bUniformSizeSlices = true;
|
||||||
|
const double rounding_delta = 1.0;
|
||||||
|
for (uint32_t sliceIdx = 1; (sliceIdx < picture->num_slice_descriptors - 1) && bUniformSizeSlices; sliceIdx++) {
|
||||||
|
int64_t curSlice = picture->slices_descriptors[sliceIdx].num_ctu_in_slice;
|
||||||
|
int64_t prevSlice = picture->slices_descriptors[sliceIdx - 1].num_ctu_in_slice;
|
||||||
|
bUniformSizeSlices = bUniformSizeSlices && (std::abs(curSlice - prevSlice) <= rounding_delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t subregion_block_pixel_size = pD3D12Enc->m_currentEncodeCapabilities.m_currentResolutionSupportCaps.SubregionBlockPixelsSize;
|
||||||
|
uint32_t num_subregions_per_scanline =
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_currentResolution.Width / subregion_block_pixel_size;
|
||||||
|
|
||||||
|
/* m_currentResolutionSupportCaps.SubregionBlockPixelsSize can be a multiple of MinCUSize to accomodate for HW requirements
|
||||||
|
So, if the allowed subregion (slice) pixel size partition is bigger (a multiple) than the CTU size, we have to adjust
|
||||||
|
num_subregions_per_slice by this factor respect from slices_descriptors[X].num_ctu_in_slice
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This assert should always be true according to the spec
|
||||||
|
https://github.com/microsoft/DirectX-Specs/blob/master/d3d/D3D12VideoEncoding.md#3150-struct-d3d12_feature_data_video_encoder_resolution_support_limits
|
||||||
|
*/
|
||||||
|
uint8_t minCUSize = d3d12_video_encoder_convert_12cusize_to_pixel_size_hevc(pD3D12Enc->m_currentEncodeConfig.m_encoderCodecSpecificConfigDesc.m_HEVCConfig.MinLumaCodingUnitSize);
|
||||||
|
assert((pD3D12Enc->m_currentEncodeCapabilities.m_currentResolutionSupportCaps.SubregionBlockPixelsSize
|
||||||
|
% minCUSize) == 0);
|
||||||
|
|
||||||
|
uint32_t subregionsize_to_ctu_factor = pD3D12Enc->m_currentEncodeCapabilities.m_currentResolutionSupportCaps.SubregionBlockPixelsSize /
|
||||||
|
minCUSize;
|
||||||
|
uint32_t num_subregions_per_slice = picture->slices_descriptors[0].num_ctu_in_slice / (subregionsize_to_ctu_factor*subregionsize_to_ctu_factor);
|
||||||
|
|
||||||
|
bool bSliceAligned = ((num_subregions_per_slice % num_subregions_per_scanline) == 0);
|
||||||
|
|
||||||
|
if (!bUniformSizeSlices &&
|
||||||
|
d3d12_video_encoder_check_subregion_mode_support(
|
||||||
|
pD3D12Enc,
|
||||||
|
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME)) {
|
||||||
|
|
||||||
|
if (D3D12_VIDEO_ENC_FALLBACK_SLICE_CONFIG) { // Check if fallback mode is enabled, or we should just fail
|
||||||
|
// without support
|
||||||
|
// Not supported to have custom slice sizes in D3D12 Video Encode fallback to uniform multi-slice
|
||||||
|
debug_printf(
|
||||||
|
"[d3d12_video_encoder_hevc] WARNING: Requested slice control mode is not supported: All slices must "
|
||||||
|
"have the same number of macroblocks. Falling back to encoding uniform %d slices per frame.\n",
|
||||||
|
picture->num_slice_descriptors);
|
||||||
|
requestedSlicesMode =
|
||||||
|
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME;
|
||||||
|
requestedSlicesConfig.NumberOfSlicesPerFrame = picture->num_slice_descriptors;
|
||||||
|
debug_printf("[d3d12_video_encoder_hevc] Using multi slice encoding mode: "
|
||||||
|
"D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME "
|
||||||
|
"with %d slices per frame.\n",
|
||||||
|
requestedSlicesConfig.NumberOfSlicesPerFrame);
|
||||||
|
} else {
|
||||||
|
debug_printf("[d3d12_video_encoder_hevc] Requested slice control mode is not supported: All slices must "
|
||||||
|
"have the same number of macroblocks. To continue with uniform slices as a fallback, must "
|
||||||
|
"enable the OS environment variable D3D12_VIDEO_ENC_FALLBACK_SLICE_CONFIG");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (bUniformSizeSlices && bSliceAligned &&
|
||||||
|
d3d12_video_encoder_check_subregion_mode_support(
|
||||||
|
pD3D12Enc,
|
||||||
|
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_ROWS_PER_SUBREGION)) {
|
||||||
|
|
||||||
|
// Number of subregion block per slice is aligned to a scanline width, in which case we can
|
||||||
|
// use D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_ROWS_PER_SUBREGION
|
||||||
|
requestedSlicesMode = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_ROWS_PER_SUBREGION;
|
||||||
|
requestedSlicesConfig.NumberOfRowsPerSlice = (num_subregions_per_slice / num_subregions_per_scanline);
|
||||||
|
debug_printf("[d3d12_video_encoder_hevc] Using multi slice encoding mode: "
|
||||||
|
"D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_ROWS_PER_SUBREGION with "
|
||||||
|
"%d subregion block rows (%d pix scanlines) per slice.\n",
|
||||||
|
requestedSlicesConfig.NumberOfRowsPerSlice,
|
||||||
|
pD3D12Enc->m_currentEncodeCapabilities.m_currentResolutionSupportCaps.SubregionBlockPixelsSize);
|
||||||
|
} else if (bUniformSizeSlices &&
|
||||||
|
d3d12_video_encoder_check_subregion_mode_support(
|
||||||
|
pD3D12Enc,
|
||||||
|
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME)) {
|
||||||
|
requestedSlicesMode =
|
||||||
|
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME;
|
||||||
|
requestedSlicesConfig.NumberOfSlicesPerFrame = picture->num_slice_descriptors;
|
||||||
|
debug_printf("[d3d12_video_encoder_hevc] Using multi slice encoding mode: "
|
||||||
|
"D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME "
|
||||||
|
"with %d slices per frame.\n",
|
||||||
|
requestedSlicesConfig.NumberOfSlicesPerFrame);
|
||||||
|
} else if (D3D12_VIDEO_ENC_FALLBACK_SLICE_CONFIG) { // Check if fallback mode is enabled, or we should just fail
|
||||||
|
// without support
|
||||||
|
// Fallback to single slice encoding (assigned by default when initializing variables requestedSlicesMode,
|
||||||
|
// requestedSlicesConfig)
|
||||||
|
debug_printf(
|
||||||
|
"[d3d12_video_encoder_hevc] WARNING: Slice mode for %d slices with bUniformSizeSlices: %d - bSliceAligned "
|
||||||
|
"%d not supported by the D3D12 driver, falling back to encoding a single slice per frame.\n",
|
||||||
|
picture->num_slice_descriptors,
|
||||||
|
bUniformSizeSlices,
|
||||||
|
bSliceAligned);
|
||||||
|
} else {
|
||||||
|
debug_printf("[d3d12_video_encoder_hevc] Requested slice control mode is not supported: All slices must "
|
||||||
|
"have the same number of macroblocks. To continue with uniform slices as a fallback, must "
|
||||||
|
"enable the OS environment variable D3D12_VIDEO_ENC_FALLBACK_SLICE_CONFIG\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!d3d12_video_encoder_isequal_slice_config_hevc(
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderSliceConfigMode,
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderSliceConfigDesc.m_SlicesPartition_HEVC,
|
||||||
|
requestedSlicesMode,
|
||||||
|
requestedSlicesConfig)) {
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_ConfigDirtyFlags |= d3d12_video_encoder_config_dirty_flag_slices;
|
||||||
|
}
|
||||||
|
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderSliceConfigDesc.m_SlicesPartition_HEVC = requestedSlicesConfig;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderSliceConfigMode = requestedSlicesMode;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12_VIDEO_ENCODER_MOTION_ESTIMATION_PRECISION_MODE
|
||||||
|
d3d12_video_encoder_convert_hevc_motion_configuration(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
|
pipe_h265_enc_picture_desc *picture)
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_MOTION_ESTIMATION_PRECISION_MODE_MAXIMUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
d3d12_video_encoder_update_hevc_gop_configuration(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
|
pipe_h265_enc_picture_desc *picture)
|
||||||
|
{
|
||||||
|
// Only update GOP when it begins
|
||||||
|
// This triggers DPB/encoder/heap re-creation, so only check on IDR when a GOP might change
|
||||||
|
if (picture->picture_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR) {
|
||||||
|
uint32_t GOPLength = picture->seq.intra_period;
|
||||||
|
uint32_t PPicturePeriod = picture->seq.ip_period;
|
||||||
|
|
||||||
|
const uint32_t max_pic_order_cnt_lsb = MAX2(16, util_next_power_of_two(GOPLength));
|
||||||
|
double log2_max_pic_order_cnt_lsb_minus4 = std::max(0.0, std::ceil(std::log2(max_pic_order_cnt_lsb)) - 4);
|
||||||
|
assert(log2_max_pic_order_cnt_lsb_minus4 < UCHAR_MAX);
|
||||||
|
|
||||||
|
// Set dirty flag if m_HEVCGroupOfPictures changed
|
||||||
|
auto previousGOPConfig = pD3D12Enc->m_currentEncodeConfig.m_encoderGOPConfigDesc.m_HEVCGroupOfPictures;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderGOPConfigDesc.m_HEVCGroupOfPictures = {
|
||||||
|
GOPLength,
|
||||||
|
PPicturePeriod,
|
||||||
|
static_cast<uint8_t>(log2_max_pic_order_cnt_lsb_minus4)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (memcmp(&previousGOPConfig,
|
||||||
|
&pD3D12Enc->m_currentEncodeConfig.m_encoderGOPConfigDesc.m_HEVCGroupOfPictures,
|
||||||
|
sizeof(D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE_HEVC)) != 0) {
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_ConfigDirtyFlags |= d3d12_video_encoder_config_dirty_flag_gop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC
|
||||||
|
d3d12_video_encoder_convert_hevc_codec_configuration(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
|
pipe_h265_enc_picture_desc *picture,
|
||||||
|
bool&is_supported)
|
||||||
|
{
|
||||||
|
is_supported = true;
|
||||||
|
uint32_t min_cu_size = (1 << (picture->seq.log2_min_luma_coding_block_size_minus3 + 3));
|
||||||
|
uint32_t max_cu_size = (1 << (picture->seq.log2_min_luma_coding_block_size_minus3 + 3 + picture->seq.log2_diff_max_min_luma_coding_block_size));
|
||||||
|
|
||||||
|
uint32_t min_tu_size = (1 << (picture->seq.log2_min_transform_block_size_minus2 + 2));
|
||||||
|
uint32_t max_tu_size = (1 << (picture->seq.log2_min_transform_block_size_minus2 + 2 + picture->seq.log2_diff_max_min_transform_block_size));
|
||||||
|
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC config = {
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_NONE,
|
||||||
|
d3d12_video_encoder_convert_pixel_size_hevc_to_12cusize(min_cu_size),
|
||||||
|
d3d12_video_encoder_convert_pixel_size_hevc_to_12cusize(max_cu_size),
|
||||||
|
d3d12_video_encoder_convert_pixel_size_hevc_to_12tusize(min_tu_size),
|
||||||
|
d3d12_video_encoder_convert_pixel_size_hevc_to_12tusize(max_tu_size),
|
||||||
|
picture->seq.max_transform_hierarchy_depth_inter,
|
||||||
|
picture->seq.max_transform_hierarchy_depth_intra,
|
||||||
|
};
|
||||||
|
|
||||||
|
pD3D12Enc->m_currentEncodeCapabilities.m_encoderCodecSpecificConfigCaps.m_HEVCCodecCaps =
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
|
||||||
|
config.MinLumaCodingUnitSize,
|
||||||
|
config.MaxLumaCodingUnitSize,
|
||||||
|
config.MinLumaTransformUnitSize,
|
||||||
|
config.MaxLumaTransformUnitSize,
|
||||||
|
config.max_transform_hierarchy_depth_inter,
|
||||||
|
config.max_transform_hierarchy_depth_intra
|
||||||
|
};
|
||||||
|
|
||||||
|
D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT capCodecConfigData = { };
|
||||||
|
capCodecConfigData.NodeIndex = pD3D12Enc->m_NodeIndex;
|
||||||
|
capCodecConfigData.Codec = D3D12_VIDEO_ENCODER_CODEC_HEVC;
|
||||||
|
D3D12_VIDEO_ENCODER_PROFILE_HEVC prof = d3d12_video_encoder_convert_profile_to_d3d12_enc_profile_hevc(pD3D12Enc->base.profile);
|
||||||
|
capCodecConfigData.Profile.pHEVCProfile = &prof;
|
||||||
|
capCodecConfigData.Profile.DataSize = sizeof(prof);
|
||||||
|
capCodecConfigData.CodecSupportLimits.pHEVCSupport = &pD3D12Enc->m_currentEncodeCapabilities.m_encoderCodecSpecificConfigCaps.m_HEVCCodecCaps;
|
||||||
|
capCodecConfigData.CodecSupportLimits.DataSize = sizeof(pD3D12Enc->m_currentEncodeCapabilities.m_encoderCodecSpecificConfigCaps.m_HEVCCodecCaps);
|
||||||
|
|
||||||
|
if(FAILED(pD3D12Enc->m_spD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT, &capCodecConfigData, sizeof(capCodecConfigData))
|
||||||
|
|| !capCodecConfigData.IsSupported))
|
||||||
|
{
|
||||||
|
debug_printf("D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION arguments are not supported - "
|
||||||
|
"Call to CheckFeatureCaps (D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT, ...) returned failure "
|
||||||
|
"or not supported for Codec HEVC - MinLumaSize %d - MaxLumaSize %d - MinTransformSize %d - "
|
||||||
|
"MaxTransformSize %d - Depth_inter %d - Depth intra %d\n",
|
||||||
|
config.MinLumaCodingUnitSize,
|
||||||
|
config.MaxLumaCodingUnitSize,
|
||||||
|
config.MinLumaTransformUnitSize,
|
||||||
|
config.MaxLumaTransformUnitSize,
|
||||||
|
config.max_transform_hierarchy_depth_inter,
|
||||||
|
config.max_transform_hierarchy_depth_intra);
|
||||||
|
|
||||||
|
is_supported = false;
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (picture->seq.amp_enabled_flag)
|
||||||
|
config.ConfigurationFlags |= D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_USE_ASYMETRIC_MOTION_PARTITION;
|
||||||
|
|
||||||
|
if (picture->seq.sample_adaptive_offset_enabled_flag)
|
||||||
|
config.ConfigurationFlags |= D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ENABLE_SAO_FILTER;
|
||||||
|
|
||||||
|
if (picture->pic.pps_loop_filter_across_slices_enabled_flag)
|
||||||
|
config.ConfigurationFlags |= D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_DISABLE_LOOP_FILTER_ACROSS_SLICES;
|
||||||
|
|
||||||
|
if (picture->pic.transform_skip_enabled_flag)
|
||||||
|
config.ConfigurationFlags |= D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ENABLE_TRANSFORM_SKIPPING;
|
||||||
|
|
||||||
|
if (picture->pic.constrained_intra_pred_flag)
|
||||||
|
config.ConfigurationFlags |= D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_USE_CONSTRAINED_INTRAPREDICTION;
|
||||||
|
|
||||||
|
if(((config.ConfigurationFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_DISABLE_LOOP_FILTER_ACROSS_SLICES) != 0)
|
||||||
|
&& ((pD3D12Enc->m_currentEncodeCapabilities.m_encoderCodecSpecificConfigCaps.m_HEVCCodecCaps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_DISABLING_LOOP_FILTER_ACROSS_SLICES_SUPPORT) == 0))
|
||||||
|
{
|
||||||
|
debug_printf("D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION arguments are not supported - Disable deblocking across slice boundary mode not supported."
|
||||||
|
" Ignoring the request for this feature flag on this encode session\n");
|
||||||
|
// Disable it and keep going with a warning
|
||||||
|
config.ConfigurationFlags &= ~D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_DISABLE_LOOP_FILTER_ACROSS_SLICES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(((config.ConfigurationFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ALLOW_REQUEST_INTRA_CONSTRAINED_SLICES) != 0)
|
||||||
|
&& ((pD3D12Enc->m_currentEncodeCapabilities.m_encoderCodecSpecificConfigCaps.m_HEVCCodecCaps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_INTRA_SLICE_CONSTRAINED_ENCODING_SUPPORT) == 0))
|
||||||
|
{
|
||||||
|
debug_printf("D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION arguments are not supported - Intra slice constrained mode not supported."
|
||||||
|
" Ignoring the request for this feature flag on this encode session\n");
|
||||||
|
// Disable it and keep going with a warning
|
||||||
|
config.ConfigurationFlags &= ~D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ALLOW_REQUEST_INTRA_CONSTRAINED_SLICES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(((config.ConfigurationFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ENABLE_SAO_FILTER) != 0)
|
||||||
|
&& ((pD3D12Enc->m_currentEncodeCapabilities.m_encoderCodecSpecificConfigCaps.m_HEVCCodecCaps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_SAO_FILTER_SUPPORT) == 0))
|
||||||
|
{
|
||||||
|
debug_printf("D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION arguments are not supported - SAO Filter mode not supported."
|
||||||
|
" Ignoring the request for this feature flag on this encode session\n");
|
||||||
|
// Disable it and keep going with a warning
|
||||||
|
config.ConfigurationFlags &= ~D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ENABLE_SAO_FILTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(((config.ConfigurationFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_USE_ASYMETRIC_MOTION_PARTITION) != 0)
|
||||||
|
&& ((pD3D12Enc->m_currentEncodeCapabilities.m_encoderCodecSpecificConfigCaps.m_HEVCCodecCaps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_ASYMETRIC_MOTION_PARTITION_SUPPORT) == 0))
|
||||||
|
{
|
||||||
|
debug_printf("D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION arguments are not supported - Asymetric motion partition not supported."
|
||||||
|
" Ignoring the request for this feature flag on this encode session\n");
|
||||||
|
// Disable it and keep going with a warning
|
||||||
|
config.ConfigurationFlags &= ~D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_USE_ASYMETRIC_MOTION_PARTITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(((config.ConfigurationFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_USE_ASYMETRIC_MOTION_PARTITION) == 0)
|
||||||
|
&& ((pD3D12Enc->m_currentEncodeCapabilities.m_encoderCodecSpecificConfigCaps.m_HEVCCodecCaps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_ASYMETRIC_MOTION_PARTITION_REQUIRED) != 0))
|
||||||
|
{
|
||||||
|
debug_printf("D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION arguments are not supported - Asymetric motion partition is required to be set."
|
||||||
|
" Enabling this HW required feature flag on this encode session\n");
|
||||||
|
// HW doesn't support otherwise, so set it
|
||||||
|
config.ConfigurationFlags |= D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_USE_ASYMETRIC_MOTION_PARTITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(((config.ConfigurationFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ENABLE_TRANSFORM_SKIPPING) != 0)
|
||||||
|
&& ((pD3D12Enc->m_currentEncodeCapabilities.m_encoderCodecSpecificConfigCaps.m_HEVCCodecCaps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_TRANSFORM_SKIP_SUPPORT) == 0))
|
||||||
|
{
|
||||||
|
debug_printf("D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION arguments are not supported - Allow transform skipping is not supported."
|
||||||
|
" Ignoring the request for this feature flag on this encode session\n");
|
||||||
|
// Disable it and keep going with a warning
|
||||||
|
config.ConfigurationFlags &= ~D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ENABLE_TRANSFORM_SKIPPING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(((config.ConfigurationFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_USE_CONSTRAINED_INTRAPREDICTION) != 0)
|
||||||
|
&& ((pD3D12Enc->m_currentEncodeCapabilities.m_encoderCodecSpecificConfigCaps.m_HEVCCodecCaps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_CONSTRAINED_INTRAPREDICTION_SUPPORT) == 0))
|
||||||
|
{
|
||||||
|
debug_printf("D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION arguments are not supported - Constrained intra-prediction use is not supported."
|
||||||
|
" Ignoring the request for this feature flag on this encode session\n");
|
||||||
|
// Disable it and keep going with a warning
|
||||||
|
config.ConfigurationFlags &= ~D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_USE_CONSTRAINED_INTRAPREDICTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
d3d12_video_encoder_update_current_encoder_config_state_hevc(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
|
struct pipe_video_buffer *srcTexture,
|
||||||
|
struct pipe_picture_desc *picture)
|
||||||
|
{
|
||||||
|
struct pipe_h265_enc_picture_desc *hevcPic = (struct pipe_h265_enc_picture_desc *) picture;
|
||||||
|
|
||||||
|
// Reset reconfig dirty flags
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_ConfigDirtyFlags = d3d12_video_encoder_config_dirty_flag_none;
|
||||||
|
// Reset sequence changes flags
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_seqFlags = D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAG_NONE;
|
||||||
|
|
||||||
|
// Set codec
|
||||||
|
if (pD3D12Enc->m_currentEncodeConfig.m_encoderCodecDesc != D3D12_VIDEO_ENCODER_CODEC_HEVC) {
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_ConfigDirtyFlags |= d3d12_video_encoder_config_dirty_flag_codec;
|
||||||
|
}
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderCodecDesc = D3D12_VIDEO_ENCODER_CODEC_HEVC;
|
||||||
|
|
||||||
|
// Set input format
|
||||||
|
DXGI_FORMAT targetFmt = d3d12_convert_pipe_video_profile_to_dxgi_format(pD3D12Enc->base.profile);
|
||||||
|
if (pD3D12Enc->m_currentEncodeConfig.m_encodeFormatInfo.Format != targetFmt) {
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_ConfigDirtyFlags |= d3d12_video_encoder_config_dirty_flag_input_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encodeFormatInfo = {};
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encodeFormatInfo.Format = targetFmt;
|
||||||
|
HRESULT hr = pD3D12Enc->m_pD3D12Screen->dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO,
|
||||||
|
&pD3D12Enc->m_currentEncodeConfig.m_encodeFormatInfo,
|
||||||
|
sizeof(pD3D12Enc->m_currentEncodeConfig.m_encodeFormatInfo));
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
debug_printf("CheckFeatureSupport failed with HR %x\n", hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set resolution
|
||||||
|
if ((pD3D12Enc->m_currentEncodeConfig.m_currentResolution.Width != srcTexture->width) ||
|
||||||
|
(pD3D12Enc->m_currentEncodeConfig.m_currentResolution.Height != srcTexture->height)) {
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_ConfigDirtyFlags |= d3d12_video_encoder_config_dirty_flag_resolution;
|
||||||
|
}
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_currentResolution.Width = srcTexture->width;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_currentResolution.Height = srcTexture->height;
|
||||||
|
|
||||||
|
// Set resolution codec dimensions (ie. cropping)
|
||||||
|
memset(&pD3D12Enc->m_currentEncodeConfig.m_FrameCroppingCodecConfig, 0,
|
||||||
|
sizeof(pD3D12Enc->m_currentEncodeConfig.m_FrameCroppingCodecConfig));
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_FrameCroppingCodecConfig.front = hevcPic->seq.pic_width_in_luma_samples;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_FrameCroppingCodecConfig.back = hevcPic->seq.pic_height_in_luma_samples;
|
||||||
|
if (hevcPic->seq.conformance_window_flag) {
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_FrameCroppingCodecConfig.left = hevcPic->seq.conf_win_left_offset;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_FrameCroppingCodecConfig.right = hevcPic->seq.conf_win_right_offset;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_FrameCroppingCodecConfig.top = hevcPic->seq.conf_win_top_offset;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_FrameCroppingCodecConfig.bottom = hevcPic->seq.conf_win_bottom_offset;
|
||||||
|
}
|
||||||
|
// Set profile
|
||||||
|
auto targetProfile = d3d12_video_encoder_convert_profile_to_d3d12_enc_profile_hevc(pD3D12Enc->base.profile);
|
||||||
|
if (pD3D12Enc->m_currentEncodeConfig.m_encoderProfileDesc.m_HEVCProfile != targetProfile) {
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_ConfigDirtyFlags |= d3d12_video_encoder_config_dirty_flag_profile;
|
||||||
|
}
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderProfileDesc.m_HEVCProfile = targetProfile;
|
||||||
|
|
||||||
|
// Set level
|
||||||
|
auto targetLevel = d3d12_video_encoder_convert_level_hevc(hevcPic->seq.general_level_idc);
|
||||||
|
auto targetTier = (hevcPic->seq.general_tier_flag == 0) ? D3D12_VIDEO_ENCODER_TIER_HEVC_MAIN : D3D12_VIDEO_ENCODER_TIER_HEVC_HIGH;
|
||||||
|
if ( (pD3D12Enc->m_currentEncodeConfig.m_encoderLevelDesc.m_HEVCLevelSetting.Level != targetLevel)
|
||||||
|
|| (pD3D12Enc->m_currentEncodeConfig.m_encoderLevelDesc.m_HEVCLevelSetting.Tier != targetTier)) {
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_ConfigDirtyFlags |= d3d12_video_encoder_config_dirty_flag_level;
|
||||||
|
}
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderLevelDesc.m_HEVCLevelSetting.Tier = targetTier;
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderLevelDesc.m_HEVCLevelSetting.Level = targetLevel;
|
||||||
|
|
||||||
|
// Set codec config
|
||||||
|
bool is_supported = true;
|
||||||
|
auto targetCodecConfig = d3d12_video_encoder_convert_hevc_codec_configuration(pD3D12Enc, hevcPic, is_supported);
|
||||||
|
if(!is_supported) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(&pD3D12Enc->m_currentEncodeConfig.m_encoderCodecSpecificConfigDesc.m_HEVCConfig,
|
||||||
|
&targetCodecConfig,
|
||||||
|
sizeof(D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC)) != 0) {
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_ConfigDirtyFlags |= d3d12_video_encoder_config_dirty_flag_codec_config;
|
||||||
|
}
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderCodecSpecificConfigDesc.m_HEVCConfig = targetCodecConfig;
|
||||||
|
|
||||||
|
// Set rate control
|
||||||
|
d3d12_video_encoder_update_current_rate_control_hevc(pD3D12Enc, hevcPic);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Check for video encode support detailed capabilities
|
||||||
|
///
|
||||||
|
|
||||||
|
// Will call for d3d12 driver support based on the initial requested features, then
|
||||||
|
// try to fallback if any of them is not supported and return the negotiated d3d12 settings
|
||||||
|
D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT capEncoderSupportData = {};
|
||||||
|
if (!d3d12_video_encoder_negotiate_requested_features_and_d3d12_driver_caps(pD3D12Enc, capEncoderSupportData)) {
|
||||||
|
debug_printf("[d3d12_video_encoder_hevc] After negotiating caps, D3D12_FEATURE_VIDEO_ENCODER_SUPPORT "
|
||||||
|
"arguments are not supported - "
|
||||||
|
"ValidationFlags: 0x%x - SupportFlags: 0x%x\n",
|
||||||
|
capEncoderSupportData.ValidationFlags,
|
||||||
|
capEncoderSupportData.SupportFlags);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
// Calculate current settings based on the returned values from the caps query
|
||||||
|
//
|
||||||
|
pD3D12Enc->m_currentEncodeCapabilities.m_MaxSlicesInOutput =
|
||||||
|
d3d12_video_encoder_calculate_max_slices_count_in_output(
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderSliceConfigMode,
|
||||||
|
&pD3D12Enc->m_currentEncodeConfig.m_encoderSliceConfigDesc.m_SlicesPartition_HEVC,
|
||||||
|
pD3D12Enc->m_currentEncodeCapabilities.m_currentResolutionSupportCaps.MaxSubregionsNumber,
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_currentResolution,
|
||||||
|
pD3D12Enc->m_currentEncodeCapabilities.m_currentResolutionSupportCaps.SubregionBlockPixelsSize);
|
||||||
|
|
||||||
|
// Set slices config
|
||||||
|
if(!d3d12_video_encoder_negotiate_current_hevc_slices_configuration(pD3D12Enc, hevcPic)) {
|
||||||
|
debug_printf("d3d12_video_encoder_negotiate_current_hevc_slices_configuration failed!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set GOP config
|
||||||
|
if(!d3d12_video_encoder_update_hevc_gop_configuration(pD3D12Enc, hevcPic)) {
|
||||||
|
debug_printf("d3d12_video_encoder_update_hevc_gop_configuration failed!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_currentEncodeConfig.m_encoderPicParamsDesc pic params are set in d3d12_video_encoder_reconfigure_encoder_objects
|
||||||
|
// after re-allocating objects if needed
|
||||||
|
|
||||||
|
// Set motion estimation config
|
||||||
|
auto targetMotionLimit = d3d12_video_encoder_convert_hevc_motion_configuration(pD3D12Enc, hevcPic);
|
||||||
|
if (pD3D12Enc->m_currentEncodeConfig.m_encoderMotionPrecisionLimit != targetMotionLimit) {
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_ConfigDirtyFlags |=
|
||||||
|
d3d12_video_encoder_config_dirty_flag_motion_precision_limit;
|
||||||
|
}
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderMotionPrecisionLimit = targetMotionLimit;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Validate caps support returned values against current settings
|
||||||
|
//
|
||||||
|
if (pD3D12Enc->m_currentEncodeConfig.m_encoderProfileDesc.m_HEVCProfile !=
|
||||||
|
pD3D12Enc->m_currentEncodeCapabilities.m_encoderSuggestedProfileDesc.m_HEVCProfile) {
|
||||||
|
debug_printf("[d3d12_video_encoder_hevc] Warning: Requested D3D12_VIDEO_ENCODER_PROFILE_HEVC by upper layer: %d "
|
||||||
|
"mismatches UMD suggested D3D12_VIDEO_ENCODER_PROFILE_HEVC: %d\n",
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderProfileDesc.m_HEVCProfile,
|
||||||
|
pD3D12Enc->m_currentEncodeCapabilities.m_encoderSuggestedProfileDesc.m_HEVCProfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pD3D12Enc->m_currentEncodeConfig.m_encoderLevelDesc.m_HEVCLevelSetting.Tier !=
|
||||||
|
pD3D12Enc->m_currentEncodeCapabilities.m_encoderLevelSuggestedDesc.m_HEVCLevelSetting.Tier) {
|
||||||
|
debug_printf("[d3d12_video_encoder_hevc] Warning: Requested D3D12_VIDEO_ENCODER_LEVELS_HEVC.Tier by upper layer: %d "
|
||||||
|
"mismatches UMD suggested D3D12_VIDEO_ENCODER_LEVELS_HEVC.Tier: %d\n",
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderLevelDesc.m_HEVCLevelSetting.Tier,
|
||||||
|
pD3D12Enc->m_currentEncodeCapabilities.m_encoderLevelSuggestedDesc.m_HEVCLevelSetting.Tier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pD3D12Enc->m_currentEncodeConfig.m_encoderLevelDesc.m_HEVCLevelSetting.Level !=
|
||||||
|
pD3D12Enc->m_currentEncodeCapabilities.m_encoderLevelSuggestedDesc.m_HEVCLevelSetting.Level) {
|
||||||
|
debug_printf("[d3d12_video_encoder_hevc] Warning: Requested D3D12_VIDEO_ENCODER_LEVELS_HEVC.Level by upper layer: %d "
|
||||||
|
"mismatches UMD suggested D3D12_VIDEO_ENCODER_LEVELS_HEVC.Level: %d\n",
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderLevelDesc.m_HEVCLevelSetting.Level,
|
||||||
|
pD3D12Enc->m_currentEncodeCapabilities.m_encoderLevelSuggestedDesc.m_HEVCLevelSetting.Level);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pD3D12Enc->m_currentEncodeCapabilities.m_MaxSlicesInOutput >
|
||||||
|
pD3D12Enc->m_currentEncodeCapabilities.m_currentResolutionSupportCaps.MaxSubregionsNumber) {
|
||||||
|
debug_printf("[d3d12_video_encoder_hevc] Desired number of subregions is not supported (higher than max "
|
||||||
|
"reported slice number in query caps)\n.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12_VIDEO_ENCODER_PROFILE_HEVC
|
||||||
|
d3d12_video_encoder_convert_profile_to_d3d12_enc_profile_hevc(enum pipe_video_profile profile)
|
||||||
|
{
|
||||||
|
switch (profile) {
|
||||||
|
case PIPE_VIDEO_PROFILE_HEVC_MAIN:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_PROFILE_HEVC_MAIN;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case PIPE_VIDEO_PROFILE_HEVC_MAIN_10:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_PROFILE_HEVC_MAIN10;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
unreachable("Unsupported pipe_video_profile");
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
d3d12_video_encoder_isequal_slice_config_hevc(
|
||||||
|
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE targetMode,
|
||||||
|
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_SLICES targetConfig,
|
||||||
|
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE otherMode,
|
||||||
|
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_SLICES otherConfig)
|
||||||
|
{
|
||||||
|
return (targetMode == otherMode) &&
|
||||||
|
(memcmp(&targetConfig,
|
||||||
|
&otherConfig,
|
||||||
|
sizeof(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_SLICES)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
d3d12_video_encoder_build_codec_headers_hevc(struct d3d12_video_encoder *pD3D12Enc)
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA currentPicParams =
|
||||||
|
d3d12_video_encoder_get_current_picture_param_settings(pD3D12Enc);
|
||||||
|
|
||||||
|
auto profDesc = d3d12_video_encoder_get_current_profile_desc(pD3D12Enc);
|
||||||
|
auto levelDesc = d3d12_video_encoder_get_current_level_desc(pD3D12Enc);
|
||||||
|
auto codecConfigDesc = d3d12_video_encoder_get_current_codec_config_desc(pD3D12Enc);
|
||||||
|
auto MaxDPBCapacity = d3d12_video_encoder_get_current_max_dpb_capacity(pD3D12Enc);
|
||||||
|
|
||||||
|
size_t writtenSPSBytesCount = 0;
|
||||||
|
size_t writtenVPSBytesCount = 0;
|
||||||
|
bool isFirstFrame = (pD3D12Enc->m_fenceValue == 1);
|
||||||
|
bool writeNewSPS = isFirstFrame // on first frame
|
||||||
|
|| ((pD3D12Enc->m_currentEncodeConfig.m_seqFlags & // also on resolution change
|
||||||
|
D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAG_RESOLUTION_CHANGE) != 0);
|
||||||
|
|
||||||
|
d3d12_video_bitstream_builder_hevc *pHEVCBitstreamBuilder =
|
||||||
|
static_cast<d3d12_video_bitstream_builder_hevc *>(pD3D12Enc->m_upBitstreamBuilder.get());
|
||||||
|
assert(pHEVCBitstreamBuilder);
|
||||||
|
|
||||||
|
uint32_t active_seq_parameter_set_id = pHEVCBitstreamBuilder->get_active_sps_id();
|
||||||
|
uint32_t active_video_parameter_set_id = pHEVCBitstreamBuilder->get_active_vps_id();
|
||||||
|
|
||||||
|
bool writeNewVPS = isFirstFrame;
|
||||||
|
|
||||||
|
if (writeNewVPS) {
|
||||||
|
bool gopHasBFrames = (pD3D12Enc->m_currentEncodeConfig.m_encoderGOPConfigDesc.m_HEVCGroupOfPictures.PPicturePeriod > 1);
|
||||||
|
pHEVCBitstreamBuilder->build_vps(*profDesc.pHEVCProfile,
|
||||||
|
*levelDesc.pHEVCLevelSetting,
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encodeFormatInfo.Format,
|
||||||
|
MaxDPBCapacity, // max_num_ref_frames
|
||||||
|
gopHasBFrames,
|
||||||
|
active_video_parameter_set_id,
|
||||||
|
pD3D12Enc->m_BitstreamHeadersBuffer,
|
||||||
|
pD3D12Enc->m_BitstreamHeadersBuffer.begin(),
|
||||||
|
writtenVPSBytesCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writeNewSPS) {
|
||||||
|
// For every new SPS for reconfiguration, increase the active_sps_id
|
||||||
|
if (!isFirstFrame) {
|
||||||
|
active_seq_parameter_set_id++;
|
||||||
|
pHEVCBitstreamBuilder->set_active_sps_id(active_seq_parameter_set_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
pHEVCBitstreamBuilder->build_sps(
|
||||||
|
pHEVCBitstreamBuilder->get_latest_vps(),
|
||||||
|
active_seq_parameter_set_id,
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_currentResolution,
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_FrameCroppingCodecConfig,
|
||||||
|
pD3D12Enc->m_currentEncodeCapabilities.m_currentResolutionSupportCaps.SubregionBlockPixelsSize,
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encodeFormatInfo.Format,
|
||||||
|
*codecConfigDesc.pHEVCConfig,
|
||||||
|
pD3D12Enc->m_currentEncodeConfig.m_encoderGOPConfigDesc.m_HEVCGroupOfPictures,
|
||||||
|
pD3D12Enc->m_BitstreamHeadersBuffer,
|
||||||
|
pD3D12Enc->m_BitstreamHeadersBuffer.begin() + writtenVPSBytesCount,
|
||||||
|
writtenSPSBytesCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t writtenPPSBytesCount = 0;
|
||||||
|
|
||||||
|
pHEVCBitstreamBuilder->build_pps(pHEVCBitstreamBuilder->get_latest_sps(),
|
||||||
|
currentPicParams.pHEVCPicData->slice_pic_parameter_set_id,
|
||||||
|
*codecConfigDesc.pHEVCConfig,
|
||||||
|
*currentPicParams.pHEVCPicData,
|
||||||
|
pD3D12Enc->m_BitstreamHeadersBuffer,
|
||||||
|
pD3D12Enc->m_BitstreamHeadersBuffer.begin() + writtenSPSBytesCount + writtenVPSBytesCount,
|
||||||
|
writtenPPSBytesCount);
|
||||||
|
|
||||||
|
// Shrink buffer to fit the headers
|
||||||
|
if (pD3D12Enc->m_BitstreamHeadersBuffer.size() > (writtenPPSBytesCount + writtenSPSBytesCount + writtenVPSBytesCount)) {
|
||||||
|
pD3D12Enc->m_BitstreamHeadersBuffer.resize(writtenPPSBytesCount + writtenSPSBytesCount + writtenVPSBytesCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pD3D12Enc->m_BitstreamHeadersBuffer.size();
|
||||||
|
}
|
||||||
68
src/gallium/drivers/d3d12/d3d12_video_enc_hevc.h
Normal file
68
src/gallium/drivers/d3d12/d3d12_video_enc_hevc.h
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright © Microsoft Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef D3D12_VIDEO_ENC_HEVC_H
|
||||||
|
#define D3D12_VIDEO_ENC_HEVC_H
|
||||||
|
#include "d3d12_video_types.h"
|
||||||
|
|
||||||
|
bool
|
||||||
|
d3d12_video_encoder_update_current_encoder_config_state_hevc(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
|
struct pipe_video_buffer * srcTexture,
|
||||||
|
struct pipe_picture_desc * picture);
|
||||||
|
void
|
||||||
|
d3d12_video_encoder_update_current_rate_control_hevc(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
|
pipe_h265_enc_picture_desc *picture);
|
||||||
|
bool
|
||||||
|
d3d12_video_encoder_negotiate_current_hevc_slices_configuration(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
|
pipe_h265_enc_picture_desc *picture);
|
||||||
|
bool
|
||||||
|
d3d12_video_encoder_update_hevc_gop_configuration(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
|
pipe_h265_enc_picture_desc *picture);
|
||||||
|
D3D12_VIDEO_ENCODER_MOTION_ESTIMATION_PRECISION_MODE
|
||||||
|
d3d12_video_encoder_convert_hevc_motion_configuration(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
|
pipe_h265_enc_picture_desc *picture);
|
||||||
|
D3D12_VIDEO_ENCODER_LEVELS_HEVC
|
||||||
|
d3d12_video_encoder_convert_level_hevc(uint32_t hevcSpecLevel);
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC
|
||||||
|
d3d12_video_encoder_convert_hevc_codec_configuration(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
|
pipe_h265_enc_picture_desc *picture,
|
||||||
|
bool &is_supported);
|
||||||
|
void
|
||||||
|
d3d12_video_encoder_update_current_frame_pic_params_info_hevc(struct d3d12_video_encoder *pD3D12Enc,
|
||||||
|
struct pipe_video_buffer * srcTexture,
|
||||||
|
struct pipe_picture_desc * picture,
|
||||||
|
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA &picParams,
|
||||||
|
bool &bUsedAsReference);
|
||||||
|
D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC
|
||||||
|
d3d12_video_encoder_convert_frame_type_hevc(enum pipe_h2645_enc_picture_type picType);
|
||||||
|
uint32_t
|
||||||
|
d3d12_video_encoder_build_codec_headers_hevc(struct d3d12_video_encoder *pD3D12Enc);
|
||||||
|
bool
|
||||||
|
d3d12_video_encoder_isequal_slice_config_hevc(
|
||||||
|
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE targetMode,
|
||||||
|
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_SLICES targetConfig,
|
||||||
|
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE otherMode,
|
||||||
|
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_SLICES otherConfig);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,732 @@
|
||||||
|
/*
|
||||||
|
* Copyright © Microsoft Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "d3d12_video_encoder_bitstream_builder_hevc.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
static uint8_t
|
||||||
|
convert_profile12_to_stdprofile(D3D12_VIDEO_ENCODER_PROFILE_HEVC profile)
|
||||||
|
{
|
||||||
|
// Main is 1, Main10 is 2, one more than the D3D12 enum definition
|
||||||
|
return static_cast<uint8_t>(profile) + 1u;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_bitstream_builder_hevc::init_profile_tier_level(HEVCProfileTierLevel *ptl,
|
||||||
|
uint8_t HEVCProfileIdc,
|
||||||
|
uint8_t HEVCLevelIdc,
|
||||||
|
bool isHighTier)
|
||||||
|
{
|
||||||
|
memset(ptl, 0, sizeof(HEVCProfileTierLevel));
|
||||||
|
|
||||||
|
ptl->general_profile_space = 0; // must be 0
|
||||||
|
ptl->general_tier_flag = isHighTier ? 1 : 0;
|
||||||
|
ptl->general_profile_idc = HEVCProfileIdc;
|
||||||
|
|
||||||
|
memset(ptl->general_profile_compatibility_flag, 0, sizeof(ptl->general_profile_compatibility_flag));
|
||||||
|
ptl->general_profile_compatibility_flag[ptl->general_profile_idc] = 1;
|
||||||
|
|
||||||
|
ptl->general_progressive_source_flag = 1; // yes
|
||||||
|
ptl->general_interlaced_source_flag = 0; // no
|
||||||
|
ptl->general_non_packed_constraint_flag = 1; // no frame packing arrangement SEI messages
|
||||||
|
ptl->general_frame_only_constraint_flag = 1;
|
||||||
|
ptl->general_level_idc = HEVCLevelIdc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_encoder_convert_from_d3d12_level_hevc(D3D12_VIDEO_ENCODER_LEVELS_HEVC level12,
|
||||||
|
uint32_t &specLevel)
|
||||||
|
{
|
||||||
|
specLevel = 3u;
|
||||||
|
switch(level12)
|
||||||
|
{
|
||||||
|
case D3D12_VIDEO_ENCODER_LEVELS_HEVC_1:
|
||||||
|
{
|
||||||
|
specLevel *= 10;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_LEVELS_HEVC_2:
|
||||||
|
{
|
||||||
|
specLevel *= 20;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_LEVELS_HEVC_21:
|
||||||
|
{
|
||||||
|
specLevel *= 21;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_LEVELS_HEVC_3:
|
||||||
|
{
|
||||||
|
specLevel *= 30;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_LEVELS_HEVC_31:
|
||||||
|
{
|
||||||
|
specLevel *= 31;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_LEVELS_HEVC_4:
|
||||||
|
{
|
||||||
|
specLevel *= 40;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_LEVELS_HEVC_41:
|
||||||
|
{
|
||||||
|
specLevel *= 41;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_LEVELS_HEVC_5:
|
||||||
|
{
|
||||||
|
specLevel *= 50;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_LEVELS_HEVC_51:
|
||||||
|
{
|
||||||
|
specLevel *= 51;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_LEVELS_HEVC_52:
|
||||||
|
{
|
||||||
|
specLevel *= 52;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_LEVELS_HEVC_6 :
|
||||||
|
{
|
||||||
|
specLevel *= 60;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_LEVELS_HEVC_61 :
|
||||||
|
{
|
||||||
|
specLevel *= 61;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_LEVELS_HEVC_62 :
|
||||||
|
{
|
||||||
|
specLevel *= 62;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
unreachable("Unsupported D3D12_VIDEO_ENCODER_LEVELS_HEVC value");
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12_VIDEO_ENCODER_LEVELS_HEVC
|
||||||
|
d3d12_video_encoder_convert_level_hevc(uint32_t hevcSpecLevel)
|
||||||
|
{
|
||||||
|
hevcSpecLevel = hevcSpecLevel / 3u;
|
||||||
|
switch(hevcSpecLevel)
|
||||||
|
{
|
||||||
|
case 10:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_LEVELS_HEVC_1;
|
||||||
|
} break;
|
||||||
|
case 20:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_LEVELS_HEVC_2;
|
||||||
|
} break;
|
||||||
|
case 21:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_LEVELS_HEVC_21;
|
||||||
|
} break;
|
||||||
|
case 30:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_LEVELS_HEVC_3;
|
||||||
|
} break;
|
||||||
|
case 31:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_LEVELS_HEVC_31;
|
||||||
|
} break;
|
||||||
|
case 40:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_LEVELS_HEVC_4;
|
||||||
|
} break;
|
||||||
|
case 41:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_LEVELS_HEVC_41;
|
||||||
|
} break;
|
||||||
|
case 50:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_LEVELS_HEVC_5;
|
||||||
|
} break;
|
||||||
|
case 51:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_LEVELS_HEVC_51;
|
||||||
|
} break;
|
||||||
|
case 52:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_LEVELS_HEVC_52;
|
||||||
|
} break;
|
||||||
|
case 60:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_LEVELS_HEVC_6;
|
||||||
|
} break;
|
||||||
|
case 61:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_LEVELS_HEVC_61;
|
||||||
|
} break;
|
||||||
|
case 62:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_LEVELS_HEVC_62;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
unreachable("Unsupported D3D12_VIDEO_ENCODER_LEVELS_HEVC value");
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
d3d12_video_encoder_convert_12cusize_to_pixel_size_hevc(const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE& cuSize)
|
||||||
|
{
|
||||||
|
switch(cuSize)
|
||||||
|
{
|
||||||
|
case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8:
|
||||||
|
{
|
||||||
|
return 8u;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_16x16:
|
||||||
|
{
|
||||||
|
return 16u;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_32x32:
|
||||||
|
{
|
||||||
|
return 32u;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_64x64:
|
||||||
|
{
|
||||||
|
return 64u;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
unreachable(L"Not a supported cu size");
|
||||||
|
return 0u;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE
|
||||||
|
d3d12_video_encoder_convert_pixel_size_hevc_to_12cusize(const uint32_t& cuSize)
|
||||||
|
{
|
||||||
|
switch(cuSize)
|
||||||
|
{
|
||||||
|
case 8u:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8;
|
||||||
|
} break;
|
||||||
|
case 16u:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_16x16;
|
||||||
|
} break;
|
||||||
|
case 32u:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_32x32;
|
||||||
|
} break;
|
||||||
|
case 64u:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_64x64;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
unreachable(L"Not a supported cu size");
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
d3d12_video_encoder_convert_12tusize_to_pixel_size_hevc(const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE& TUSize)
|
||||||
|
{
|
||||||
|
switch(TUSize)
|
||||||
|
{
|
||||||
|
case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4:
|
||||||
|
{
|
||||||
|
return 4u;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_8x8:
|
||||||
|
{
|
||||||
|
return 8u;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_16x16:
|
||||||
|
{
|
||||||
|
return 16u;
|
||||||
|
} break;
|
||||||
|
case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32:
|
||||||
|
{
|
||||||
|
return 32u;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
unreachable(L"Not a supported TU size");
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE
|
||||||
|
d3d12_video_encoder_convert_pixel_size_hevc_to_12tusize(const uint32_t& TUSize)
|
||||||
|
{
|
||||||
|
switch(TUSize)
|
||||||
|
{
|
||||||
|
case 4u:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4;
|
||||||
|
} break;
|
||||||
|
case 8u:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_8x8;
|
||||||
|
} break;
|
||||||
|
case 16u:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_16x16;
|
||||||
|
} break;
|
||||||
|
case 32u:
|
||||||
|
{
|
||||||
|
return D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
unreachable(L"Not a supported TU size");
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_bitstream_builder_hevc::build_vps(const D3D12_VIDEO_ENCODER_PROFILE_HEVC& profile,
|
||||||
|
const D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC& level,
|
||||||
|
const DXGI_FORMAT inputFmt,
|
||||||
|
uint8_t maxRefFrames,
|
||||||
|
bool gopHasBFrames,
|
||||||
|
uint8_t vps_video_parameter_set_id,
|
||||||
|
std::vector<BYTE> &headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator placingPositionStart,
|
||||||
|
size_t &writtenBytes,
|
||||||
|
HevcVideoParameterSet* pVPSStruct)
|
||||||
|
{
|
||||||
|
uint8_t HEVCProfileIdc = convert_profile12_to_stdprofile(profile);
|
||||||
|
uint32_t HEVCLevelIdc = 0u;
|
||||||
|
d3d12_video_encoder_convert_from_d3d12_level_hevc(level.Level, HEVCLevelIdc);
|
||||||
|
bool isHighTier = (level.Tier == D3D12_VIDEO_ENCODER_TIER_HEVC_HIGH);
|
||||||
|
|
||||||
|
memset(&m_latest_vps, 0, sizeof(HevcVideoParameterSet));
|
||||||
|
m_latest_vps.nalu = {
|
||||||
|
// forbidden_zero_bit
|
||||||
|
0u,
|
||||||
|
// nal_unit_type
|
||||||
|
HEVC_NALU_VPS_NUT,
|
||||||
|
// nuh_layer_id
|
||||||
|
0u,
|
||||||
|
// nuh_temporal_id_plus1
|
||||||
|
1u
|
||||||
|
};
|
||||||
|
|
||||||
|
m_latest_vps.vps_video_parameter_set_id = vps_video_parameter_set_id,
|
||||||
|
m_latest_vps.vps_reserved_three_2bits = 3u;
|
||||||
|
m_latest_vps.vps_max_layers_minus1 = 0u;
|
||||||
|
m_latest_vps.vps_max_sub_layers_minus1 = 0u;
|
||||||
|
m_latest_vps.vps_temporal_id_nesting_flag = 1u;
|
||||||
|
m_latest_vps.vps_reserved_0xffff_16bits = 0xFFFF;
|
||||||
|
init_profile_tier_level(&m_latest_vps.ptl, HEVCProfileIdc, HEVCLevelIdc, isHighTier);
|
||||||
|
m_latest_vps.vps_sub_layer_ordering_info_present_flag = 0u;
|
||||||
|
for (int i = (m_latest_vps.vps_sub_layer_ordering_info_present_flag ? 0 : m_latest_vps.vps_max_sub_layers_minus1); i <= m_latest_vps.vps_max_sub_layers_minus1; i++) {
|
||||||
|
m_latest_vps.vps_max_dec_pic_buffering_minus1[i] = (maxRefFrames/*previous reference frames*/ + 1 /*additional current frame recon pic*/) - 1/**minus1 for header*/;
|
||||||
|
m_latest_vps.vps_max_num_reorder_pics[i] = gopHasBFrames ? m_latest_vps.vps_max_dec_pic_buffering_minus1[i] : 0;
|
||||||
|
m_latest_vps.vps_max_latency_increase_plus1[i] = 0; // When vps_max_latency_increase_plus1[ i ] is equal to 0, no corresponding limit is expressed.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print built VPS structure
|
||||||
|
debug_printf("[HEVCBitstreamBuilder] HevcVideoParameterSet Structure generated before writing to bitstream:\n");
|
||||||
|
print_vps(m_latest_vps);
|
||||||
|
|
||||||
|
m_hevcEncoder.vps_to_nalu_bytes(&m_latest_vps, headerBitstream, placingPositionStart, writtenBytes);
|
||||||
|
|
||||||
|
if(pVPSStruct != nullptr)
|
||||||
|
{
|
||||||
|
*pVPSStruct = m_latest_vps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_bitstream_builder_hevc::build_sps(const HevcVideoParameterSet& parentVPS,
|
||||||
|
uint8_t seq_parameter_set_id,
|
||||||
|
const D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC& encodeResolution,
|
||||||
|
const D3D12_BOX& crop_window_upper_layer,
|
||||||
|
const UINT picDimensionMultipleRequirement,
|
||||||
|
const DXGI_FORMAT& inputFmt,
|
||||||
|
const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC& codecConfig,
|
||||||
|
const D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE_HEVC& hevcGOP,
|
||||||
|
std::vector<BYTE> &headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator placingPositionStart,
|
||||||
|
size_t &writtenBytes,
|
||||||
|
HevcSeqParameterSet* outputSPS)
|
||||||
|
{
|
||||||
|
memset(&m_latest_sps, 0, sizeof(HevcSeqParameterSet));
|
||||||
|
|
||||||
|
// In case is 420 10 bits
|
||||||
|
if(inputFmt == DXGI_FORMAT_P010)
|
||||||
|
{
|
||||||
|
m_latest_sps.bit_depth_luma_minus8 = 2;
|
||||||
|
m_latest_sps.bit_depth_chroma_minus8 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t minCuSize = d3d12_video_encoder_convert_12cusize_to_pixel_size_hevc(codecConfig.MinLumaCodingUnitSize);
|
||||||
|
uint8_t maxCuSize = d3d12_video_encoder_convert_12cusize_to_pixel_size_hevc(codecConfig.MaxLumaCodingUnitSize);
|
||||||
|
uint8_t minTuSize = d3d12_video_encoder_convert_12tusize_to_pixel_size_hevc(codecConfig.MinLumaTransformUnitSize);
|
||||||
|
uint8_t maxTuSize = d3d12_video_encoder_convert_12tusize_to_pixel_size_hevc(codecConfig.MaxLumaTransformUnitSize);
|
||||||
|
|
||||||
|
m_latest_sps.nalu.nal_unit_type = HEVC_NALU_SPS_NUT;
|
||||||
|
m_latest_sps.nalu.nuh_temporal_id_plus1 = 1;
|
||||||
|
|
||||||
|
m_latest_sps.sps_seq_parameter_set_id = seq_parameter_set_id;
|
||||||
|
m_latest_sps.sps_max_sub_layers_minus1 = parentVPS.vps_max_sub_layers_minus1;
|
||||||
|
m_latest_sps.sps_temporal_id_nesting_flag = parentVPS.vps_temporal_id_nesting_flag;
|
||||||
|
|
||||||
|
// inherit PTL from parentVPS fully
|
||||||
|
m_latest_sps.ptl = parentVPS.ptl;
|
||||||
|
|
||||||
|
m_latest_sps.chroma_format_idc = 1; // 420
|
||||||
|
|
||||||
|
// Codec spec dictates pic_width/height_in_luma_samples must be divisible by minCuSize but HW might have higher req pow 2 multiples
|
||||||
|
assert((picDimensionMultipleRequirement % minCuSize) == 0u);
|
||||||
|
|
||||||
|
// upper layer passes the viewport, can calculate the difference between it and pic_width_in_luma_samples
|
||||||
|
D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC viewport = { };
|
||||||
|
viewport.Width = crop_window_upper_layer.front /* passes height */ - ((crop_window_upper_layer.left + crop_window_upper_layer.right) << 1);
|
||||||
|
viewport.Height = crop_window_upper_layer.back /* passes width */- ((crop_window_upper_layer.top + crop_window_upper_layer.bottom) << 1);
|
||||||
|
|
||||||
|
m_latest_sps.pic_width_in_luma_samples = ALIGN(encodeResolution.Width, picDimensionMultipleRequirement);
|
||||||
|
m_latest_sps.pic_height_in_luma_samples = ALIGN(encodeResolution.Height, picDimensionMultipleRequirement);
|
||||||
|
m_latest_sps.conf_win_right_offset = (m_latest_sps.pic_width_in_luma_samples - viewport.Width) >> 1;
|
||||||
|
m_latest_sps.conf_win_bottom_offset = (m_latest_sps.pic_height_in_luma_samples - viewport.Height) >> 1;
|
||||||
|
m_latest_sps.conformance_window_flag = m_latest_sps.conf_win_left_offset || m_latest_sps.conf_win_right_offset || m_latest_sps.conf_win_top_offset || m_latest_sps.conf_win_bottom_offset;
|
||||||
|
|
||||||
|
m_latest_sps.log2_max_pic_order_cnt_lsb_minus4 = hevcGOP.log2_max_pic_order_cnt_lsb_minus4;
|
||||||
|
m_latest_sps.maxPicOrderCntLsb = 1 << (m_latest_sps.log2_max_pic_order_cnt_lsb_minus4 + 4);
|
||||||
|
|
||||||
|
m_latest_sps.sps_sub_layer_ordering_info_present_flag = parentVPS.vps_sub_layer_ordering_info_present_flag;
|
||||||
|
for (int i = (m_latest_sps.sps_sub_layer_ordering_info_present_flag ? 0 : m_latest_sps.sps_max_sub_layers_minus1); i <= m_latest_sps.sps_max_sub_layers_minus1; i++) {
|
||||||
|
m_latest_sps.sps_max_dec_pic_buffering_minus1[i] = parentVPS.vps_max_dec_pic_buffering_minus1[i];
|
||||||
|
m_latest_sps.sps_max_num_reorder_pics[i] = parentVPS.vps_max_num_reorder_pics[i];
|
||||||
|
m_latest_sps.sps_max_latency_increase_plus1[i] = parentVPS.vps_max_latency_increase_plus1[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
m_latest_sps.log2_min_luma_coding_block_size_minus3 = static_cast<uint8_t>(std::log2(minCuSize) - 3);
|
||||||
|
m_latest_sps.log2_diff_max_min_luma_coding_block_size = static_cast<uint8_t>(std::log2(maxCuSize) - std::log2(minCuSize));
|
||||||
|
m_latest_sps.log2_min_transform_block_size_minus2 = static_cast<uint8_t>(std::log2(minTuSize) - 2);
|
||||||
|
m_latest_sps.log2_diff_max_min_transform_block_size = static_cast<uint8_t>(std::log2(maxTuSize) - std::log2(minTuSize));
|
||||||
|
|
||||||
|
m_latest_sps.max_transform_hierarchy_depth_inter = codecConfig.max_transform_hierarchy_depth_inter;
|
||||||
|
m_latest_sps.max_transform_hierarchy_depth_intra = codecConfig.max_transform_hierarchy_depth_intra;
|
||||||
|
|
||||||
|
m_latest_sps.scaling_list_enabled_flag = 0;
|
||||||
|
m_latest_sps.amp_enabled_flag = ((codecConfig.ConfigurationFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_USE_ASYMETRIC_MOTION_PARTITION) != 0) ? 1u : 0u;
|
||||||
|
m_latest_sps.sample_adaptive_offset_enabled_flag = ((codecConfig.ConfigurationFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ENABLE_SAO_FILTER) != 0) ? 1u : 0u;
|
||||||
|
m_latest_sps.pcm_enabled_flag = 0;
|
||||||
|
|
||||||
|
m_latest_sps.num_short_term_ref_pic_sets = 0;
|
||||||
|
|
||||||
|
m_latest_sps.long_term_ref_pics_present_flag = ((codecConfig.ConfigurationFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ENABLE_LONG_TERM_REFERENCES) != 0) ? 1u : 0u;
|
||||||
|
m_latest_sps.num_long_term_ref_pics_sps = 0; // signal through slice header for now
|
||||||
|
|
||||||
|
m_latest_sps.sps_temporal_mvp_enabled_flag = 0;
|
||||||
|
m_latest_sps.strong_intra_smoothing_enabled_flag = 0;
|
||||||
|
|
||||||
|
m_latest_sps.vui_parameters_present_flag = 0;
|
||||||
|
m_latest_sps.sps_extension_flag = 0;
|
||||||
|
|
||||||
|
// Print built SPS structure
|
||||||
|
debug_printf("[HEVCBitstreamBuilder] HevcSeqParameterSet Structure generated before writing to bitstream:\n");
|
||||||
|
print_sps(m_latest_sps);
|
||||||
|
|
||||||
|
m_hevcEncoder.sps_to_nalu_bytes(&m_latest_sps, headerBitstream, placingPositionStart, writtenBytes);
|
||||||
|
|
||||||
|
if(outputSPS != nullptr)
|
||||||
|
{
|
||||||
|
*outputSPS = m_latest_sps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_bitstream_builder_hevc::build_pps(const HevcSeqParameterSet& parentSPS,
|
||||||
|
uint8_t pic_parameter_set_id,
|
||||||
|
const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC& codecConfig,
|
||||||
|
const D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_HEVC& pictureControl,
|
||||||
|
std::vector<BYTE> &headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator placingPositionStart,
|
||||||
|
size_t &writtenBytes,
|
||||||
|
HevcPicParameterSet* outputPPS)
|
||||||
|
{
|
||||||
|
memset(&m_latest_pps, 0, sizeof(HevcPicParameterSet));
|
||||||
|
|
||||||
|
m_latest_pps.nalu.nal_unit_type = HEVC_NALU_PPS_NUT;
|
||||||
|
m_latest_pps.nalu.nuh_temporal_id_plus1 = 1;
|
||||||
|
|
||||||
|
m_latest_pps.pps_pic_parameter_set_id = pic_parameter_set_id;
|
||||||
|
m_latest_pps.pps_seq_parameter_set_id = parentSPS.sps_seq_parameter_set_id;
|
||||||
|
|
||||||
|
m_latest_pps.weighted_pred_flag = 0u; // no weighted prediction in D3D12
|
||||||
|
|
||||||
|
m_latest_pps.num_ref_idx_lx_default_active_minus1[0] = static_cast<uint8_t>(std::max(static_cast<INT>(pictureControl.List0ReferenceFramesCount) - 1, 0));
|
||||||
|
m_latest_pps.num_ref_idx_lx_default_active_minus1[1] = static_cast<uint8_t>(std::max(static_cast<INT>(pictureControl.List1ReferenceFramesCount) - 1, 0));
|
||||||
|
|
||||||
|
m_latest_pps.num_tile_columns_minus1 = 0u; // no tiling in D3D12
|
||||||
|
m_latest_pps.num_tile_rows_minus1 = 0u; // no tiling in D3D12
|
||||||
|
m_latest_pps.tiles_enabled_flag = 0u; // no tiling in D3D12
|
||||||
|
m_latest_pps.loop_filter_across_tiles_enabled_flag = 0;
|
||||||
|
|
||||||
|
m_latest_pps.lists_modification_present_flag = 0;
|
||||||
|
m_latest_pps.log2_parallel_merge_level_minus2 = 0;
|
||||||
|
|
||||||
|
m_latest_pps.deblocking_filter_control_present_flag = 1;
|
||||||
|
m_latest_pps.deblocking_filter_override_enabled_flag = 0;
|
||||||
|
m_latest_pps.pps_deblocking_filter_disabled_flag = 0;
|
||||||
|
m_latest_pps.pps_scaling_list_data_present_flag = 0;
|
||||||
|
m_latest_pps.pps_beta_offset_div2 = 0;
|
||||||
|
m_latest_pps.pps_tc_offset_div2 = 0;
|
||||||
|
m_latest_pps.pps_loop_filter_across_slices_enabled_flag = ((codecConfig.ConfigurationFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_DISABLE_LOOP_FILTER_ACROSS_SLICES) != 0) ? 0 : 1;
|
||||||
|
m_latest_pps.transform_skip_enabled_flag = ((codecConfig.ConfigurationFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ENABLE_TRANSFORM_SKIPPING) != 0) ? 1 : 0;
|
||||||
|
m_latest_pps.constrained_intra_pred_flag = ((codecConfig.ConfigurationFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_USE_CONSTRAINED_INTRAPREDICTION) != 0) ? 1 : 0;
|
||||||
|
m_latest_pps.cabac_init_present_flag = 1;
|
||||||
|
m_latest_pps.pps_slice_chroma_qp_offsets_present_flag = 1;
|
||||||
|
m_latest_pps.cu_qp_delta_enabled_flag = 1;
|
||||||
|
|
||||||
|
// Print built PPS structure
|
||||||
|
debug_printf("[HEVCBitstreamBuilder] HevcPicParameterSet Structure generated before writing to bitstream:\n");
|
||||||
|
print_pps(m_latest_pps);
|
||||||
|
|
||||||
|
m_hevcEncoder.pps_to_nalu_bytes(&m_latest_pps, headerBitstream, placingPositionStart, writtenBytes);
|
||||||
|
|
||||||
|
if(outputPPS != nullptr)
|
||||||
|
{
|
||||||
|
*outputPPS = m_latest_pps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_bitstream_builder_hevc::write_end_of_stream_nalu(std::vector<uint8_t> & headerBitstream,
|
||||||
|
std::vector<uint8_t>::iterator placingPositionStart,
|
||||||
|
size_t & writtenBytes)
|
||||||
|
{
|
||||||
|
m_hevcEncoder.write_end_of_stream_nalu(headerBitstream, placingPositionStart, writtenBytes);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
d3d12_video_bitstream_builder_hevc::write_end_of_sequence_nalu(std::vector<uint8_t> & headerBitstream,
|
||||||
|
std::vector<uint8_t>::iterator placingPositionStart,
|
||||||
|
size_t & writtenBytes)
|
||||||
|
{
|
||||||
|
m_hevcEncoder.write_end_of_sequence_nalu(headerBitstream, placingPositionStart, writtenBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_bitstream_builder_hevc::print_vps(const HevcVideoParameterSet& VPS)
|
||||||
|
{
|
||||||
|
debug_printf("--------------------------------------\nHevcVideoParameterSet values below:\n");
|
||||||
|
|
||||||
|
debug_printf("vps_video_parameter_set_id: %d\n", VPS.vps_video_parameter_set_id);
|
||||||
|
debug_printf("vps_reserved_three_2bits: %d\n", VPS.vps_reserved_three_2bits);
|
||||||
|
debug_printf("vps_max_layers_minus1: %d\n", VPS.vps_max_layers_minus1);
|
||||||
|
debug_printf("vps_max_sub_layers_minus1: %d\n", VPS.vps_max_sub_layers_minus1);
|
||||||
|
debug_printf("vps_temporal_id_nesting_flag: %d\n", VPS.vps_temporal_id_nesting_flag);
|
||||||
|
|
||||||
|
debug_printf("general_profile_space: %d\n", VPS.ptl.general_profile_space);
|
||||||
|
debug_printf("general_tier_flag: %d\n", VPS.ptl.general_tier_flag);
|
||||||
|
debug_printf("general_profile_idc: %d\n", VPS.ptl.general_profile_idc);
|
||||||
|
debug_printf("general_progressive_source_flag: %d\n", VPS.ptl.general_progressive_source_flag);
|
||||||
|
debug_printf("general_interlaced_source_flag: %d\n", VPS.ptl.general_interlaced_source_flag);
|
||||||
|
debug_printf("general_non_packed_constraint_flag: %d\n", VPS.ptl.general_non_packed_constraint_flag);
|
||||||
|
debug_printf("general_frame_only_constraint_flag: %d\n", VPS.ptl.general_frame_only_constraint_flag);
|
||||||
|
debug_printf("general_level_idc: %d\n", VPS.ptl.general_level_idc);
|
||||||
|
|
||||||
|
debug_printf("vps_sub_layer_ordering_info_present_flag: %d\n", VPS.vps_sub_layer_ordering_info_present_flag);
|
||||||
|
debug_printf("vps_max_dec_pic_buffering_minus1[%d]: %d\n", (0u), VPS.vps_max_dec_pic_buffering_minus1[0u]);
|
||||||
|
debug_printf("vps_max_num_reorder_pics[%d]: %d\n", (0u), VPS.vps_max_num_reorder_pics[0u]);
|
||||||
|
debug_printf("vps_max_latency_increase_plus1[%d]: %d\n", (0u), VPS.vps_max_latency_increase_plus1[0u]);
|
||||||
|
debug_printf("vps_max_layer_id: %d\n", VPS.vps_max_layer_id);
|
||||||
|
debug_printf("vps_num_layer_sets_minus1: %d\n", VPS.vps_num_layer_sets_minus1);
|
||||||
|
debug_printf("vps_timing_info_present_flag: %d\n", VPS.vps_timing_info_present_flag);
|
||||||
|
debug_printf("vps_num_units_in_tick: %d\n", VPS.vps_num_units_in_tick);
|
||||||
|
debug_printf("vps_time_scale: %d\n", VPS.vps_time_scale);
|
||||||
|
debug_printf("vps_poc_proportional_to_timing_flag: %d\n", VPS.vps_poc_proportional_to_timing_flag);
|
||||||
|
debug_printf("vps_num_ticks_poc_diff_one_minus1: %d\n", VPS.vps_num_ticks_poc_diff_one_minus1);
|
||||||
|
debug_printf("vps_num_hrd_parameters: %d\n", VPS.vps_num_hrd_parameters);
|
||||||
|
debug_printf("vps_extension_flag: %d\n", VPS.vps_extension_flag);
|
||||||
|
debug_printf("vps_extension_data_flag: %d\n", VPS.vps_extension_data_flag);
|
||||||
|
|
||||||
|
debug_printf("HevcVideoParameterSet values end\n--------------------------------------\n");
|
||||||
|
}
|
||||||
|
void
|
||||||
|
d3d12_video_bitstream_builder_hevc::print_sps(const HevcSeqParameterSet& SPS)
|
||||||
|
{
|
||||||
|
debug_printf("--------------------------------------\nHevcSeqParameterSet values below:\n");
|
||||||
|
|
||||||
|
debug_printf("sps_video_parameter_set_id: %d\n", SPS.sps_video_parameter_set_id);
|
||||||
|
debug_printf("sps_max_sub_layers_minus1: %d\n", SPS.sps_max_sub_layers_minus1);
|
||||||
|
debug_printf("sps_temporal_id_nesting_flag: %d\n", SPS.sps_temporal_id_nesting_flag);
|
||||||
|
|
||||||
|
debug_printf("general_profile_space: %d\n", SPS.ptl.general_profile_space);
|
||||||
|
debug_printf("general_tier_flag: %d\n", SPS.ptl.general_tier_flag);
|
||||||
|
debug_printf("general_profile_idc: %d\n", SPS.ptl.general_profile_idc);
|
||||||
|
debug_printf("general_progressive_source_flag: %d\n", SPS.ptl.general_progressive_source_flag);
|
||||||
|
debug_printf("general_interlaced_source_flag: %d\n", SPS.ptl.general_interlaced_source_flag);
|
||||||
|
debug_printf("general_non_packed_constraint_flag: %d\n", SPS.ptl.general_non_packed_constraint_flag);
|
||||||
|
debug_printf("general_frame_only_constraint_flag: %d\n", SPS.ptl.general_frame_only_constraint_flag);
|
||||||
|
debug_printf("general_level_idc: %d\n", SPS.ptl.general_level_idc);
|
||||||
|
|
||||||
|
debug_printf("sps_seq_parameter_set_id: %d\n", SPS.sps_seq_parameter_set_id);
|
||||||
|
debug_printf("chroma_format_idc: %d\n", SPS.chroma_format_idc);
|
||||||
|
debug_printf("separate_colour_plane_flag: %d\n", SPS.separate_colour_plane_flag);
|
||||||
|
debug_printf("pic_width_in_luma_samples: %d\n", SPS.pic_width_in_luma_samples);
|
||||||
|
debug_printf("pic_height_in_luma_samples: %d\n", SPS.pic_height_in_luma_samples);
|
||||||
|
debug_printf("conformance_window_flag: %d\n", SPS.conformance_window_flag);
|
||||||
|
debug_printf("conf_win_left_offset: %d\n", SPS.conf_win_left_offset);
|
||||||
|
debug_printf("conf_win_right_offset: %d\n", SPS.conf_win_right_offset);
|
||||||
|
debug_printf("conf_win_top_offset: %d\n", SPS.conf_win_top_offset);
|
||||||
|
debug_printf("conf_win_bottom_offset: %d\n", SPS.conf_win_bottom_offset);
|
||||||
|
debug_printf("bit_depth_luma_minus8: %d\n", SPS.bit_depth_luma_minus8);
|
||||||
|
debug_printf("bit_depth_chroma_minus8: %d\n", SPS.bit_depth_chroma_minus8);
|
||||||
|
debug_printf("log2_max_pic_order_cnt_lsb_minus4: %d\n", SPS.log2_max_pic_order_cnt_lsb_minus4);
|
||||||
|
debug_printf("maxPicOrderCntLsb: %d\n", SPS.maxPicOrderCntLsb);
|
||||||
|
debug_printf("sps_sub_layer_ordering_info_present_flag: %d\n", SPS.sps_sub_layer_ordering_info_present_flag);
|
||||||
|
|
||||||
|
debug_printf("sps_max_dec_pic_buffering_minus1[%d]: %d\n", (0u), SPS.sps_max_dec_pic_buffering_minus1[0u]);
|
||||||
|
debug_printf("sps_max_num_reorder_pics[%d]: %d\n", (0u), SPS.sps_max_num_reorder_pics[0u]);
|
||||||
|
debug_printf("sps_max_latency_increase_plus1[%d]: %d\n", (0u), SPS.sps_max_latency_increase_plus1[0u]);
|
||||||
|
|
||||||
|
debug_printf("log2_min_luma_coding_block_size_minus3: %d\n", SPS.log2_min_luma_coding_block_size_minus3);
|
||||||
|
debug_printf("log2_diff_max_min_luma_coding_block_size: %d\n", SPS.log2_diff_max_min_luma_coding_block_size);
|
||||||
|
debug_printf("log2_min_transform_block_size_minus2: %d\n", SPS.log2_min_transform_block_size_minus2);
|
||||||
|
debug_printf("log2_diff_max_min_transform_block_size: %d\n", SPS.log2_diff_max_min_transform_block_size);
|
||||||
|
debug_printf("max_transform_hierarchy_depth_inter: %d\n", SPS.max_transform_hierarchy_depth_inter);
|
||||||
|
debug_printf("max_transform_hierarchy_depth_intra: %d\n", SPS.max_transform_hierarchy_depth_intra);
|
||||||
|
debug_printf("scaling_list_enabled_flag: %d\n", SPS.scaling_list_enabled_flag);
|
||||||
|
debug_printf("sps_scaling_list_data_present_flag: %d\n", SPS.sps_scaling_list_data_present_flag);
|
||||||
|
debug_printf("amp_enabled_flag: %d\n", SPS.amp_enabled_flag);
|
||||||
|
debug_printf("sample_adaptive_offset_enabled_flag: %d\n", SPS.sample_adaptive_offset_enabled_flag);
|
||||||
|
debug_printf("pcm_enabled_flag: %d\n", SPS.pcm_enabled_flag);
|
||||||
|
debug_printf("pcm_sample_bit_depth_luma_minus1: %d\n", SPS.pcm_sample_bit_depth_luma_minus1);
|
||||||
|
debug_printf("pcm_sample_bit_depth_chroma_minus1: %d\n", SPS.pcm_sample_bit_depth_chroma_minus1);
|
||||||
|
debug_printf("log2_min_pcm_luma_coding_block_size_minus3: %d\n", SPS.log2_min_pcm_luma_coding_block_size_minus3);
|
||||||
|
debug_printf("log2_diff_max_min_pcm_luma_coding_block_size: %d\n", SPS.log2_diff_max_min_pcm_luma_coding_block_size);
|
||||||
|
debug_printf("pcm_loop_filter_disabled_flag: %d\n", SPS.pcm_loop_filter_disabled_flag);
|
||||||
|
debug_printf("num_short_term_ref_pic_sets: %d\n", SPS.num_short_term_ref_pic_sets);
|
||||||
|
|
||||||
|
for(UINT idx = 0; idx < SPS.num_short_term_ref_pic_sets ; idx++)
|
||||||
|
{
|
||||||
|
print_rps(&SPS, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_printf("long_term_ref_pics_present_flag: %d\n", SPS.long_term_ref_pics_present_flag);
|
||||||
|
debug_printf("num_long_term_ref_pics_sps: %d\n", SPS.num_long_term_ref_pics_sps);
|
||||||
|
|
||||||
|
for(UINT idx = 0; idx < SPS.num_long_term_ref_pics_sps ; idx++)
|
||||||
|
{
|
||||||
|
debug_printf("lt_ref_pic_poc_lsb_sps[%d]: %d\n", idx, SPS.lt_ref_pic_poc_lsb_sps[idx]);
|
||||||
|
debug_printf("used_by_curr_pic_lt_sps_flag[%d]: %d\n", idx, SPS.used_by_curr_pic_lt_sps_flag[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_printf("sps_temporal_mvp_enabled_flag: %d\n", SPS.sps_temporal_mvp_enabled_flag);
|
||||||
|
debug_printf("strong_intra_smoothing_enabled_flag: %d\n", SPS.strong_intra_smoothing_enabled_flag);
|
||||||
|
debug_printf("vui_parameters_present_flag: %d\n", SPS.vui_parameters_present_flag);
|
||||||
|
debug_printf("sps_extension_flag: %d\n", SPS.sps_extension_flag);
|
||||||
|
debug_printf("sps_extension_data_flag: %d\n", SPS.sps_extension_data_flag);
|
||||||
|
|
||||||
|
|
||||||
|
debug_printf("HevcSeqParameterSet values end\n--------------------------------------\n");
|
||||||
|
}
|
||||||
|
void
|
||||||
|
d3d12_video_bitstream_builder_hevc::print_pps(const HevcPicParameterSet& PPS)
|
||||||
|
{
|
||||||
|
debug_printf("--------------------------------------\nHevcPicParameterSet values below:\n");
|
||||||
|
debug_printf("pps_pic_parameter_set_id: %d\n", PPS.pps_pic_parameter_set_id);
|
||||||
|
debug_printf("pps_seq_parameter_set_id: %d\n", PPS.pps_seq_parameter_set_id);
|
||||||
|
debug_printf("dependent_slice_segments_enabled_flag: %d\n", PPS.dependent_slice_segments_enabled_flag);
|
||||||
|
debug_printf("output_flag_present_flag: %d\n", PPS.output_flag_present_flag);
|
||||||
|
debug_printf("num_extra_slice_header_bits: %d\n", PPS.num_extra_slice_header_bits);
|
||||||
|
debug_printf("sign_data_hiding_enabled_flag: %d\n", PPS.sign_data_hiding_enabled_flag);
|
||||||
|
debug_printf("cabac_init_present_flag: %d\n", PPS.cabac_init_present_flag);
|
||||||
|
debug_printf("num_ref_idx_l0_default_active_minus1: %d\n", PPS.num_ref_idx_lx_default_active_minus1[0]);
|
||||||
|
debug_printf("num_ref_idx_l1_default_active_minus1: %d\n", PPS.num_ref_idx_lx_default_active_minus1[1]);
|
||||||
|
debug_printf("init_qp_minus26: %d\n", PPS.init_qp_minus26);
|
||||||
|
debug_printf("constrained_intra_pred_flag: %d\n", PPS.constrained_intra_pred_flag);
|
||||||
|
debug_printf("transform_skip_enabled_flag: %d\n", PPS.transform_skip_enabled_flag);
|
||||||
|
debug_printf("cu_qp_delta_enabled_flag: %d\n", PPS.cu_qp_delta_enabled_flag);
|
||||||
|
debug_printf("diff_cu_qp_delta_depth: %d\n", PPS.diff_cu_qp_delta_depth);
|
||||||
|
debug_printf("pps_cb_qp_offset: %d\n", PPS.pps_cb_qp_offset);
|
||||||
|
debug_printf("pps_cr_qp_offset: %d\n", PPS.pps_cr_qp_offset);
|
||||||
|
debug_printf("pps_slice_chroma_qp_offsets_present_flag: %d\n", PPS.pps_slice_chroma_qp_offsets_present_flag);
|
||||||
|
debug_printf("weighted_pred_flag: %d\n", PPS.weighted_pred_flag);
|
||||||
|
debug_printf("weighted_bipred_flag: %d\n", PPS.weighted_bipred_flag);
|
||||||
|
debug_printf("transquant_bypass_enabled_flag: %d\n", PPS.transquant_bypass_enabled_flag);
|
||||||
|
debug_printf("tiles_enabled_flag: %d\n", PPS.tiles_enabled_flag);
|
||||||
|
debug_printf("entropy_coding_sync_enabled_flag: %d\n", PPS.entropy_coding_sync_enabled_flag);
|
||||||
|
debug_printf("num_tile_columns_minus1: %d\n", PPS.num_tile_columns_minus1);
|
||||||
|
debug_printf("num_tile_rows_minus1: %d\n", PPS.num_tile_rows_minus1);
|
||||||
|
debug_printf("uniform_spacing_flag: %d\n", PPS.uniform_spacing_flag);
|
||||||
|
debug_printf("column_width_minus1[0]: %d\n", PPS.column_width_minus1[0]); // no tiles in D3D12)
|
||||||
|
debug_printf("row_height_minus1[0]: %d\n", PPS.row_height_minus1[0]); // no tiles in D3D12)
|
||||||
|
debug_printf("loop_filter_across_tiles_enabled_flag: %d\n", PPS.loop_filter_across_tiles_enabled_flag);
|
||||||
|
debug_printf("pps_loop_filter_across_slices_enabled_flag: %d\n", PPS.pps_loop_filter_across_slices_enabled_flag);
|
||||||
|
debug_printf("deblocking_filter_control_present_flag: %d\n", PPS.deblocking_filter_control_present_flag);
|
||||||
|
debug_printf("deblocking_filter_override_enabled_flag: %d\n", PPS.deblocking_filter_override_enabled_flag);
|
||||||
|
debug_printf("pps_deblocking_filter_disabled_flag: %d\n", PPS.pps_deblocking_filter_disabled_flag);
|
||||||
|
debug_printf("pps_beta_offset_div2: %d\n", PPS.pps_beta_offset_div2);
|
||||||
|
debug_printf("pps_tc_offset_div2: %d\n", PPS.pps_tc_offset_div2);
|
||||||
|
debug_printf("pps_scaling_list_data_present_flag: %d\n", PPS.pps_scaling_list_data_present_flag);
|
||||||
|
debug_printf("lists_modification_present_flag: %d\n", PPS.lists_modification_present_flag);
|
||||||
|
debug_printf("log2_parallel_merge_level_minus2: %d\n", PPS.log2_parallel_merge_level_minus2);
|
||||||
|
debug_printf("slice_segment_header_extension_present_flag: %d\n", PPS.slice_segment_header_extension_present_flag);
|
||||||
|
debug_printf("pps_extension_flag: %d\n", PPS.pps_extension_flag);
|
||||||
|
debug_printf("pps_extension_data_flag: %d\n", PPS.pps_extension_data_flag);
|
||||||
|
debug_printf("HevcPicParameterSet values end\n--------------------------------------\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_bitstream_builder_hevc::print_rps(const HevcSeqParameterSet* sps, UINT stRpsIdx)
|
||||||
|
{
|
||||||
|
const HEVCReferencePictureSet* rps = &(sps->rpsShortTerm[stRpsIdx]);
|
||||||
|
|
||||||
|
debug_printf("--------------------------------------\nHEVCReferencePictureSet[%d] values below:\n", stRpsIdx);
|
||||||
|
|
||||||
|
debug_printf("inter_ref_pic_set_prediction_flag: %d\n", rps->inter_ref_pic_set_prediction_flag);
|
||||||
|
|
||||||
|
if(rps->inter_ref_pic_set_prediction_flag)
|
||||||
|
{
|
||||||
|
debug_printf("delta_idx_minus1: %d\n", rps->delta_idx_minus1);
|
||||||
|
debug_printf("delta_rps_sign: %d\n", rps->delta_rps_sign);
|
||||||
|
debug_printf("abs_delta_rps_minus1: %d\n", rps->abs_delta_rps_minus1);
|
||||||
|
debug_printf("num_negative_pics: %d\n", rps->num_negative_pics);
|
||||||
|
debug_printf("num_positive_pics: %d\n", rps->num_positive_pics);
|
||||||
|
|
||||||
|
int32_t RefRpsIdx = stRpsIdx - 1 - rps->delta_idx_minus1;
|
||||||
|
const HEVCReferencePictureSet* rpsRef = &(sps->rpsShortTerm[RefRpsIdx]);
|
||||||
|
auto numberOfPictures = rpsRef->num_negative_pics + rpsRef->num_positive_pics;
|
||||||
|
for (uint8_t j = 0; j <= numberOfPictures; j++) {
|
||||||
|
debug_printf("used_by_curr_pic_flag[%d]: %d\n", j, rps->used_by_curr_pic_flag[j]);
|
||||||
|
if (!rps->used_by_curr_pic_flag[j]) {
|
||||||
|
debug_printf("use_delta_flag[%d]: %d\n", j, rps->use_delta_flag[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debug_printf("num_negative_pics: %d\n", rps->num_negative_pics);
|
||||||
|
for (uint8_t i = 0; i < rps->num_negative_pics; i++) {
|
||||||
|
debug_printf("delta_poc_s0_minus1[%d]: %d\n", i, rps->delta_poc_s0_minus1[i]);
|
||||||
|
debug_printf("used_by_curr_pic_s0_flag[%d]: %d\n", i, rps->used_by_curr_pic_s0_flag[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_printf("num_positive_pics: %d\n", rps->num_positive_pics);
|
||||||
|
for (int32_t i = 0; i < rps->num_positive_pics; i++) {
|
||||||
|
debug_printf("delta_poc_s1_minus1[%d]: %d\n", i, rps->delta_poc_s1_minus1[i]);
|
||||||
|
debug_printf("used_by_curr_pic_s1_flag[%d]: %d\n", i, rps->used_by_curr_pic_s1_flag[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_printf("HEVCReferencePictureSet values end\n--------------------------------------\n");
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* Copyright © Microsoft Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef D3D12_VIDEO_ENC_BITSTREAM_BUILDER_HEVC_H
|
||||||
|
#define D3D12_VIDEO_ENC_BITSTREAM_BUILDER_HEVC_H
|
||||||
|
|
||||||
|
#include "d3d12_video_encoder_nalu_writer_hevc.h"
|
||||||
|
#include "d3d12_video_encoder_bitstream_builder.h"
|
||||||
|
|
||||||
|
class d3d12_video_bitstream_builder_hevc : public d3d12_video_bitstream_builder_interface
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
d3d12_video_bitstream_builder_hevc() {};
|
||||||
|
~d3d12_video_bitstream_builder_hevc() {};
|
||||||
|
|
||||||
|
void build_vps(const D3D12_VIDEO_ENCODER_PROFILE_HEVC& profile,
|
||||||
|
const D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC& level,
|
||||||
|
const DXGI_FORMAT inputFmt,
|
||||||
|
uint8_t maxRefFrames,
|
||||||
|
bool gopHasBFrames,
|
||||||
|
uint8_t vps_video_parameter_set_id,
|
||||||
|
std::vector<BYTE> &headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator placingPositionStart,
|
||||||
|
size_t &writtenBytes,
|
||||||
|
HevcVideoParameterSet* pVPSStruct = nullptr);
|
||||||
|
|
||||||
|
void build_sps(const HevcVideoParameterSet& parentVPS,
|
||||||
|
uint8_t seq_parameter_set_id,
|
||||||
|
const D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC& encodeResolution,
|
||||||
|
const D3D12_BOX& crop_window_upper_layer,
|
||||||
|
const UINT picDimensionMultipleRequirement,
|
||||||
|
const DXGI_FORMAT& inputFmt,
|
||||||
|
const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC& codecConfig,
|
||||||
|
const D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE_HEVC& hevcGOP,
|
||||||
|
std::vector<BYTE> &headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator placingPositionStart,
|
||||||
|
size_t &writtenBytes,
|
||||||
|
HevcSeqParameterSet* outputSPS = nullptr);
|
||||||
|
|
||||||
|
void build_pps(const HevcSeqParameterSet& parentSPS,
|
||||||
|
uint8_t pic_parameter_set_id,
|
||||||
|
const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC& codecConfig,
|
||||||
|
const D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_HEVC& pictureControl,
|
||||||
|
std::vector<BYTE> &headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator placingPositionStart,
|
||||||
|
size_t &writtenBytes,
|
||||||
|
HevcPicParameterSet* outputPPS = nullptr);
|
||||||
|
|
||||||
|
void write_end_of_stream_nalu(std::vector<uint8_t> & headerBitstream,
|
||||||
|
std::vector<uint8_t>::iterator placingPositionStart,
|
||||||
|
size_t & writtenBytes);
|
||||||
|
void write_end_of_sequence_nalu(std::vector<uint8_t> & headerBitstream,
|
||||||
|
std::vector<uint8_t>::iterator placingPositionStart,
|
||||||
|
size_t & writtenBytes);
|
||||||
|
|
||||||
|
void print_vps(const HevcVideoParameterSet& vps);
|
||||||
|
void print_sps(const HevcSeqParameterSet& sps);
|
||||||
|
void print_pps(const HevcPicParameterSet& pps);
|
||||||
|
void print_rps(const HevcSeqParameterSet* sps, UINT stRpsIdx);
|
||||||
|
|
||||||
|
uint32_t m_activeVPSIndex = 0;
|
||||||
|
uint32_t m_activeSPSIndex = 0;
|
||||||
|
uint32_t m_activePPSIndex = 0;
|
||||||
|
HevcVideoParameterSet m_latest_vps = {};
|
||||||
|
HevcSeqParameterSet m_latest_sps = {};
|
||||||
|
HevcPicParameterSet m_latest_pps = {};
|
||||||
|
|
||||||
|
HevcVideoParameterSet get_latest_vps()
|
||||||
|
{
|
||||||
|
return m_latest_vps;
|
||||||
|
}
|
||||||
|
|
||||||
|
HevcSeqParameterSet get_latest_sps()
|
||||||
|
{
|
||||||
|
return m_latest_sps;
|
||||||
|
}
|
||||||
|
|
||||||
|
HevcPicParameterSet get_latest_pps()
|
||||||
|
{
|
||||||
|
return m_latest_pps;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_active_vps_id()
|
||||||
|
{
|
||||||
|
return m_activeVPSIndex;
|
||||||
|
};
|
||||||
|
uint32_t get_active_sps_id()
|
||||||
|
{
|
||||||
|
return m_activeSPSIndex;
|
||||||
|
};
|
||||||
|
uint32_t get_active_pps_id()
|
||||||
|
{
|
||||||
|
return m_activePPSIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
void set_active_vps_id(uint32_t active_vps_id)
|
||||||
|
{
|
||||||
|
m_activeVPSIndex = active_vps_id;
|
||||||
|
debug_printf("[d3d12_video_bitstream_builder_hevc] Setting new active VPS ID: %d ", m_activeVPSIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
void set_active_sps_id(uint32_t active_sps_id)
|
||||||
|
{
|
||||||
|
m_activeSPSIndex = active_sps_id;
|
||||||
|
debug_printf("[d3d12_video_bitstream_builder_hevc] Setting new active SPS ID: %d ", m_activeSPSIndex);
|
||||||
|
};
|
||||||
|
void set_active_pps_id(uint32_t active_pps_id)
|
||||||
|
{
|
||||||
|
m_activePPSIndex = active_pps_id;
|
||||||
|
debug_printf("[d3d12_video_bitstream_builder_hevc] Setting new active PPS ID: %d ", m_activePPSIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
d3d12_video_nalu_writer_hevc m_hevcEncoder;
|
||||||
|
|
||||||
|
void init_profile_tier_level(HEVCProfileTierLevel *ptl, uint8_t HEVCProfileIdc, uint8_t HEVCLevelIdc, bool isHighTier);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,520 @@
|
||||||
|
/*
|
||||||
|
* Copyright © Microsoft Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "d3d12_video_encoder_nalu_writer_hevc.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
// Writes the HEVC VPS structure into a bitstream passed in headerBitstream
|
||||||
|
// Function resizes bitstream accordingly and puts result in byte vector
|
||||||
|
void
|
||||||
|
d3d12_video_nalu_writer_hevc::vps_to_nalu_bytes(HevcVideoParameterSet *pVPS,
|
||||||
|
std::vector<BYTE> &headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator placingPositionStart,
|
||||||
|
size_t &writtenBytes) {
|
||||||
|
generic_write_bytes(headerBitstream, placingPositionStart, writtenBytes, pVPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes the HEVC pSPS structure into a bitstream passed in headerBitstream
|
||||||
|
// Function resizes bitstream accordingly and puts result in byte vector
|
||||||
|
void
|
||||||
|
d3d12_video_nalu_writer_hevc::sps_to_nalu_bytes(HevcSeqParameterSet *pSPS,
|
||||||
|
std::vector<BYTE> &headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator placingPositionStart,
|
||||||
|
size_t &writtenBytes) {
|
||||||
|
generic_write_bytes(headerBitstream, placingPositionStart, writtenBytes, pSPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes the HEVC PPS structure into a bitstream passed in headerBitstream
|
||||||
|
// Function resizes bitstream accordingly and puts result in byte vector
|
||||||
|
void
|
||||||
|
d3d12_video_nalu_writer_hevc::pps_to_nalu_bytes(HevcPicParameterSet *pPPS,
|
||||||
|
std::vector<BYTE> &headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator placingPositionStart,
|
||||||
|
size_t &writtenBytes) {
|
||||||
|
generic_write_bytes(headerBitstream, placingPositionStart, writtenBytes, pPPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_nalu_writer_hevc::write_end_of_stream_nalu(std::vector<BYTE> &headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator placingPositionStart,
|
||||||
|
size_t &writtenBytes) {
|
||||||
|
HEVCNaluHeader endOfStreamNALU =
|
||||||
|
{
|
||||||
|
// uint8_t forbidden_zero_bit;
|
||||||
|
static_cast<uint8_t>(0u),
|
||||||
|
// uint8_t nal_unit_type
|
||||||
|
static_cast<uint8_t>(HEVC_NALU_EOB_NUT),
|
||||||
|
// uint8_t nuh_layer_id
|
||||||
|
static_cast<uint8_t>(0u),
|
||||||
|
// uint8_t nuh_temporal_id_plus1
|
||||||
|
static_cast<uint8_t>(1u)
|
||||||
|
};
|
||||||
|
generic_write_bytes(headerBitstream, placingPositionStart, writtenBytes, &endOfStreamNALU);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_nalu_writer_hevc::write_end_of_sequence_nalu(std::vector<BYTE> &headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator placingPositionStart,
|
||||||
|
size_t &writtenBytes) {
|
||||||
|
HEVCNaluHeader endOfSeqNALU =
|
||||||
|
{
|
||||||
|
// uint8_t forbidden_zero_bit;
|
||||||
|
static_cast<uint8_t>(0u),
|
||||||
|
// uint8_t nal_unit_type
|
||||||
|
static_cast<uint8_t>(HEVC_NALU_EOS_NUT),
|
||||||
|
// uint8_t nuh_layer_id
|
||||||
|
static_cast<uint8_t>(0u),
|
||||||
|
// uint8_t nuh_temporal_id_plus1
|
||||||
|
static_cast<uint8_t>(1u)
|
||||||
|
};
|
||||||
|
generic_write_bytes(headerBitstream, placingPositionStart, writtenBytes, &endOfSeqNALU);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_nalu_writer_hevc::generic_write_bytes( std::vector<BYTE> &headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator placingPositionStart,
|
||||||
|
size_t &writtenBytes,
|
||||||
|
void *pStructure)
|
||||||
|
{
|
||||||
|
// Wrap pSPS into NALU and copy full NALU into output byte array
|
||||||
|
d3d12_video_encoder_bitstream rbsp, nalu;
|
||||||
|
|
||||||
|
/*HEVCNaluHeader nalu is in all Hevc*ParameterSet structures at the beggining*/
|
||||||
|
HEVCNaluHeader* nal_header = ((HEVCNaluHeader *) pStructure);
|
||||||
|
|
||||||
|
if (!rbsp.create_bitstream(MAX_COMPRESSED_NALU)) {
|
||||||
|
debug_printf("rbsp.create_bitstream(MAX_COMPRESSED_NALU) failed\n");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nalu.create_bitstream(2 * MAX_COMPRESSED_NALU)) {
|
||||||
|
debug_printf("nalu.create_bitstream(2 * MAX_COMPRESSED_NALU) failed\n");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
rbsp.set_start_code_prevention(TRUE);
|
||||||
|
if (write_bytes_from_struct(&rbsp, pStructure, nal_header->nal_unit_type) <= 0u) {
|
||||||
|
debug_printf("write_bytes_from_struct(&rbsp, pStructure, nal_header->nal_unit_type) didn't write any bytes.\n");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wrap_rbsp_into_nalu(&nalu, &rbsp, nal_header) <= 0u) {
|
||||||
|
debug_printf("wrap_rbsp_into_nalu(&nalu, &rbsp, nal_header) didn't write any bytes.\n");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deep copy nalu into headerBitstream, nalu gets out of scope here and its destructor frees the nalu object buffer
|
||||||
|
// memory.
|
||||||
|
uint8_t *naluBytes = nalu.get_bitstream_buffer();
|
||||||
|
size_t naluByteSize = nalu.get_byte_count();
|
||||||
|
|
||||||
|
auto startDstIndex = std::distance(headerBitstream.begin(), placingPositionStart);
|
||||||
|
if (headerBitstream.size() < (startDstIndex + naluByteSize)) {
|
||||||
|
headerBitstream.resize(startDstIndex + naluByteSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::copy_n(&naluBytes[0], naluByteSize, &headerBitstream.data()[startDstIndex]);
|
||||||
|
|
||||||
|
writtenBytes = naluByteSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
d3d12_video_nalu_writer_hevc::write_bytes_from_struct(d3d12_video_encoder_bitstream *pBitstream, void *pData, uint8_t nal_unit_type)
|
||||||
|
{
|
||||||
|
switch(nal_unit_type)
|
||||||
|
{
|
||||||
|
case HEVC_NALU_VPS_NUT:
|
||||||
|
{
|
||||||
|
return write_vps_bytes(pBitstream, (HevcVideoParameterSet *) pData);
|
||||||
|
} break;
|
||||||
|
case HEVC_NALU_SPS_NUT:
|
||||||
|
{
|
||||||
|
return write_sps_bytes(pBitstream, (HevcSeqParameterSet *) pData);
|
||||||
|
} break;
|
||||||
|
case HEVC_NALU_PPS_NUT:
|
||||||
|
{
|
||||||
|
return write_pps_bytes(pBitstream, (HevcPicParameterSet *) pData);
|
||||||
|
} break;
|
||||||
|
case HEVC_NALU_EOS_NUT:
|
||||||
|
case HEVC_NALU_EOB_NUT:
|
||||||
|
{
|
||||||
|
// Do nothing for these two, just the header suffices
|
||||||
|
return 1;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
unreachable("Unsupported NALU value");
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
d3d12_video_nalu_writer_hevc::write_vps_bytes(d3d12_video_encoder_bitstream *pBitstream, HevcVideoParameterSet *vps)
|
||||||
|
{
|
||||||
|
int32_t iBytesWritten = pBitstream->get_byte_count();
|
||||||
|
|
||||||
|
pBitstream->put_bits(4, vps->vps_video_parameter_set_id);
|
||||||
|
pBitstream->put_bits(2, 3); //vps_reserved_three_2bits
|
||||||
|
pBitstream->put_bits(6, vps->vps_max_layers_minus1);
|
||||||
|
pBitstream->put_bits(3, vps->vps_max_sub_layers_minus1);
|
||||||
|
pBitstream->put_bits(1, vps->vps_temporal_id_nesting_flag);
|
||||||
|
pBitstream->put_bits(16, 0xffff); //vps_reserved_ffff_16bits
|
||||||
|
|
||||||
|
write_profile_tier_level(pBitstream, &vps->ptl);
|
||||||
|
|
||||||
|
pBitstream->put_bits(1,vps->vps_sub_layer_ordering_info_present_flag);
|
||||||
|
|
||||||
|
for (int i = 0; i <= vps->vps_max_sub_layers_minus1; i++) {
|
||||||
|
pBitstream->exp_Golomb_ue(vps->vps_max_dec_pic_buffering_minus1[i]);
|
||||||
|
pBitstream->exp_Golomb_ue(vps->vps_max_num_reorder_pics[i]);
|
||||||
|
pBitstream->exp_Golomb_ue(vps->vps_max_latency_increase_plus1[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pBitstream->put_bits(6, vps->vps_max_layer_id);
|
||||||
|
pBitstream->exp_Golomb_ue(vps->vps_num_layer_sets_minus1);
|
||||||
|
pBitstream->put_bits(1, vps->vps_timing_info_present_flag);
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, 0); // vps_extension_flag
|
||||||
|
|
||||||
|
rbsp_trailing(pBitstream);
|
||||||
|
pBitstream->flush();
|
||||||
|
|
||||||
|
iBytesWritten = pBitstream->get_byte_count() - iBytesWritten;
|
||||||
|
return (uint32_t) iBytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
d3d12_video_nalu_writer_hevc::write_sps_bytes(d3d12_video_encoder_bitstream *pBitstream,
|
||||||
|
HevcSeqParameterSet *pSPS)
|
||||||
|
{
|
||||||
|
int32_t iBytesWritten = pBitstream->get_byte_count();
|
||||||
|
|
||||||
|
pBitstream->put_bits(4, pSPS->sps_video_parameter_set_id);
|
||||||
|
pBitstream->put_bits(3, pSPS->sps_max_sub_layers_minus1);
|
||||||
|
pBitstream->put_bits(1, pSPS->sps_temporal_id_nesting_flag);
|
||||||
|
|
||||||
|
write_profile_tier_level(pBitstream, &pSPS->ptl);
|
||||||
|
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->sps_seq_parameter_set_id);
|
||||||
|
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->chroma_format_idc);
|
||||||
|
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->pic_width_in_luma_samples);
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->pic_height_in_luma_samples);
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pSPS->conformance_window_flag);
|
||||||
|
if (pSPS->conformance_window_flag) {
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->conf_win_left_offset);
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->conf_win_right_offset);
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->conf_win_top_offset);
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->conf_win_bottom_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->bit_depth_luma_minus8);
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->bit_depth_chroma_minus8);
|
||||||
|
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->log2_max_pic_order_cnt_lsb_minus4);
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pSPS->sps_sub_layer_ordering_info_present_flag);
|
||||||
|
|
||||||
|
for (int i = 0; i <= pSPS->sps_max_sub_layers_minus1; i++) {
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->sps_max_dec_pic_buffering_minus1[i]);
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->sps_max_num_reorder_pics[i]);
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->sps_max_latency_increase_plus1[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->log2_min_luma_coding_block_size_minus3);
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->log2_diff_max_min_luma_coding_block_size);
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->log2_min_transform_block_size_minus2);
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->log2_diff_max_min_transform_block_size);
|
||||||
|
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->max_transform_hierarchy_depth_inter);
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->max_transform_hierarchy_depth_intra);
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pSPS->scaling_list_enabled_flag);
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pSPS->amp_enabled_flag);
|
||||||
|
pBitstream->put_bits(1, pSPS->sample_adaptive_offset_enabled_flag);
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pSPS->pcm_enabled_flag);
|
||||||
|
if (pSPS->pcm_enabled_flag) {
|
||||||
|
pBitstream->put_bits(4, pSPS->bit_depth_luma_minus8 + 7);
|
||||||
|
pBitstream->put_bits(4, pSPS->bit_depth_chroma_minus8 + 7);
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->log2_min_luma_coding_block_size_minus3);
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->log2_diff_max_min_luma_coding_block_size);
|
||||||
|
pBitstream->put_bits(1, pSPS->pcm_loop_filter_disabled_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->num_short_term_ref_pic_sets);
|
||||||
|
for (int i = 0; i < pSPS->num_short_term_ref_pic_sets; i++) {
|
||||||
|
write_rps(pBitstream, pSPS, i, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pSPS->long_term_ref_pics_present_flag);
|
||||||
|
if (pSPS->long_term_ref_pics_present_flag) {
|
||||||
|
pBitstream->exp_Golomb_ue(pSPS->num_long_term_ref_pics_sps);
|
||||||
|
for (int i = 0; i < pSPS->num_long_term_ref_pics_sps; i++) {
|
||||||
|
pBitstream->put_bits(pSPS->log2_max_pic_order_cnt_lsb_minus4 + 4, pSPS->lt_ref_pic_poc_lsb_sps[i]);
|
||||||
|
pBitstream->put_bits(1, pSPS->used_by_curr_pic_lt_sps_flag[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pSPS->sps_temporal_mvp_enabled_flag);
|
||||||
|
pBitstream->put_bits(1, pSPS->strong_intra_smoothing_enabled_flag);
|
||||||
|
pBitstream->put_bits(1, pSPS->vui_parameters_present_flag);
|
||||||
|
assert (pSPS->vui_parameters_present_flag == 0);
|
||||||
|
|
||||||
|
// pSps_extension_flag
|
||||||
|
pBitstream->put_bits(1, 0);
|
||||||
|
|
||||||
|
rbsp_trailing(pBitstream);
|
||||||
|
pBitstream->flush();
|
||||||
|
|
||||||
|
iBytesWritten = pBitstream->get_byte_count() - iBytesWritten;
|
||||||
|
return (uint32_t) iBytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
d3d12_video_nalu_writer_hevc::write_pps_bytes(d3d12_video_encoder_bitstream *pBitstream,
|
||||||
|
HevcPicParameterSet *pPPS)
|
||||||
|
{
|
||||||
|
int32_t iBytesWritten = pBitstream->get_byte_count();
|
||||||
|
|
||||||
|
pBitstream->exp_Golomb_ue(pPPS->pps_pic_parameter_set_id);
|
||||||
|
pBitstream->exp_Golomb_ue(pPPS->pps_seq_parameter_set_id);
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pPPS->dependent_slice_segments_enabled_flag);
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pPPS->output_flag_present_flag);
|
||||||
|
pBitstream->put_bits(3, pPPS->num_extra_slice_header_bits);
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pPPS->sign_data_hiding_enabled_flag);
|
||||||
|
pBitstream->put_bits(1, pPPS->cabac_init_present_flag);
|
||||||
|
|
||||||
|
pBitstream->exp_Golomb_ue(pPPS->num_ref_idx_lx_default_active_minus1[0]);
|
||||||
|
pBitstream->exp_Golomb_ue(pPPS->num_ref_idx_lx_default_active_minus1[1]);
|
||||||
|
|
||||||
|
pBitstream->exp_Golomb_se(pPPS->init_qp_minus26);
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pPPS->constrained_intra_pred_flag);
|
||||||
|
pBitstream->put_bits(1, pPPS->transform_skip_enabled_flag);
|
||||||
|
pBitstream->put_bits(1, pPPS->cu_qp_delta_enabled_flag);
|
||||||
|
|
||||||
|
if (pPPS->cu_qp_delta_enabled_flag) {
|
||||||
|
pBitstream->exp_Golomb_se(pPPS->diff_cu_qp_delta_depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
pBitstream->exp_Golomb_se(pPPS->pps_cb_qp_offset);
|
||||||
|
pBitstream->exp_Golomb_se(pPPS->pps_cr_qp_offset);
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pPPS->pps_slice_chroma_qp_offsets_present_flag);
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pPPS->weighted_pred_flag);
|
||||||
|
pBitstream->put_bits(1, pPPS->weighted_bipred_flag);
|
||||||
|
pBitstream->put_bits(1, pPPS->transquant_bypass_enabled_flag);
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pPPS->tiles_enabled_flag);
|
||||||
|
pBitstream->put_bits(1, pPPS->entropy_coding_sync_enabled_flag);
|
||||||
|
|
||||||
|
if (pPPS->tiles_enabled_flag) {
|
||||||
|
pBitstream->exp_Golomb_ue(pPPS->num_tile_columns_minus1);
|
||||||
|
pBitstream->exp_Golomb_ue(pPPS->num_tile_rows_minus1);
|
||||||
|
pBitstream->put_bits(1, pPPS->uniform_spacing_flag);
|
||||||
|
if (!pPPS->uniform_spacing_flag) {
|
||||||
|
for (int i = 0; i < pPPS->num_tile_columns_minus1; i++) {
|
||||||
|
pBitstream->exp_Golomb_ue(pPPS->column_width_minus1[i]);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < pPPS->num_tile_rows_minus1; i++) {
|
||||||
|
pBitstream->exp_Golomb_ue(pPPS->row_height_minus1[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pBitstream->put_bits(1, pPPS->loop_filter_across_tiles_enabled_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pPPS->pps_loop_filter_across_slices_enabled_flag);
|
||||||
|
pBitstream->put_bits(1, pPPS->deblocking_filter_control_present_flag);
|
||||||
|
if (pPPS->deblocking_filter_control_present_flag) {
|
||||||
|
pBitstream->put_bits(1, pPPS->deblocking_filter_override_enabled_flag);
|
||||||
|
pBitstream->put_bits(1, pPPS->pps_deblocking_filter_disabled_flag);
|
||||||
|
if (!pPPS->pps_deblocking_filter_disabled_flag) {
|
||||||
|
pBitstream->exp_Golomb_se(pPPS->pps_beta_offset_div2);
|
||||||
|
pBitstream->exp_Golomb_se(pPPS->pps_tc_offset_div2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pPPS->pps_scaling_list_data_present_flag);
|
||||||
|
if (pPPS->pps_scaling_list_data_present_flag) {
|
||||||
|
assert(0); //, "scaling list syntax is not implemented yet");
|
||||||
|
}
|
||||||
|
|
||||||
|
pBitstream->put_bits(1, pPPS->lists_modification_present_flag);
|
||||||
|
pBitstream->exp_Golomb_ue(pPPS->log2_parallel_merge_level_minus2);
|
||||||
|
pBitstream->put_bits(1, pPPS->slice_segment_header_extension_present_flag);
|
||||||
|
|
||||||
|
//pps_extension_flag
|
||||||
|
pBitstream->put_bits(1, 0);
|
||||||
|
|
||||||
|
rbsp_trailing(pBitstream);
|
||||||
|
pBitstream->flush();
|
||||||
|
|
||||||
|
iBytesWritten = pBitstream->get_byte_count() - iBytesWritten;
|
||||||
|
return (uint32_t) iBytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
d3d12_video_nalu_writer_hevc::wrap_rbsp_into_nalu(d3d12_video_encoder_bitstream *pNALU,
|
||||||
|
d3d12_video_encoder_bitstream *pRBSP,
|
||||||
|
HEVCNaluHeader *pHeader)
|
||||||
|
{
|
||||||
|
bool isAligned = pRBSP->is_byte_aligned(); // causes side-effects in object state, don't put inside assert()
|
||||||
|
assert(isAligned);
|
||||||
|
|
||||||
|
int32_t iBytesWritten = pNALU->get_byte_count();
|
||||||
|
|
||||||
|
pNALU->set_start_code_prevention(FALSE);
|
||||||
|
|
||||||
|
// NAL start code
|
||||||
|
pNALU->put_bits(24, 0);
|
||||||
|
pNALU->put_bits(8, 1);
|
||||||
|
|
||||||
|
// NAL header
|
||||||
|
pNALU->put_bits(1, pHeader->forbidden_zero_bit);
|
||||||
|
pNALU->put_bits(6, pHeader->nal_unit_type);
|
||||||
|
pNALU->put_bits(6, pHeader->nuh_layer_id);
|
||||||
|
pNALU->put_bits(3, pHeader->nuh_temporal_id_plus1);
|
||||||
|
pNALU->flush();
|
||||||
|
|
||||||
|
// NAL body
|
||||||
|
pRBSP->flush();
|
||||||
|
|
||||||
|
if (pRBSP->get_start_code_prevention_status()) {
|
||||||
|
// Direct copying.
|
||||||
|
pNALU->append_byte_stream(pRBSP);
|
||||||
|
} else {
|
||||||
|
// Copy with start code prevention.
|
||||||
|
pNALU->set_start_code_prevention(TRUE);
|
||||||
|
int32_t iLength = pRBSP->get_byte_count();
|
||||||
|
uint8_t *pBuffer = pRBSP->get_bitstream_buffer();
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < iLength; i++) {
|
||||||
|
pNALU->put_bits(8, pBuffer[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isAligned = pNALU->is_byte_aligned(); // causes side-effects in object state, don't put inside assert()
|
||||||
|
assert(isAligned);
|
||||||
|
write_nalu_end(pNALU);
|
||||||
|
|
||||||
|
pNALU->flush();
|
||||||
|
|
||||||
|
iBytesWritten = pNALU->get_byte_count() - iBytesWritten;
|
||||||
|
return (uint32_t) iBytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_nalu_writer_hevc::write_nalu_end(d3d12_video_encoder_bitstream *pNALU)
|
||||||
|
{
|
||||||
|
pNALU->flush();
|
||||||
|
pNALU->set_start_code_prevention(FALSE);
|
||||||
|
int32_t iNALUnitLen = pNALU->get_byte_count();
|
||||||
|
|
||||||
|
if (FALSE == pNALU->m_bBufferOverflow && 0x00 == pNALU->get_bitstream_buffer()[iNALUnitLen - 1]) {
|
||||||
|
pNALU->put_bits(8, 0x03);
|
||||||
|
pNALU->flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_nalu_writer_hevc::rbsp_trailing(d3d12_video_encoder_bitstream *pBitstream)
|
||||||
|
{
|
||||||
|
pBitstream->put_bits(1, 1);
|
||||||
|
int32_t iLeft = pBitstream->get_num_bits_for_byte_align();
|
||||||
|
|
||||||
|
if (iLeft) {
|
||||||
|
pBitstream->put_bits(iLeft, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isAligned = pBitstream->is_byte_aligned(); // causes side-effects in object state, don't put inside assert()
|
||||||
|
assert(isAligned);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_nalu_writer_hevc::write_profile_tier_level(d3d12_video_encoder_bitstream* rbsp, HEVCProfileTierLevel* ptl)
|
||||||
|
{
|
||||||
|
rbsp->put_bits(2, ptl->general_profile_space);
|
||||||
|
rbsp->put_bits(1, ptl->general_tier_flag);
|
||||||
|
rbsp->put_bits(5, ptl->general_profile_idc);
|
||||||
|
|
||||||
|
for (int j = 0; j < 32; j++) {
|
||||||
|
rbsp->put_bits(1, ptl->general_profile_compatibility_flag[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
rbsp->put_bits(1, ptl->general_progressive_source_flag);
|
||||||
|
rbsp->put_bits(1, ptl->general_interlaced_source_flag);
|
||||||
|
rbsp->put_bits(1, ptl->general_non_packed_constraint_flag);
|
||||||
|
rbsp->put_bits(1, ptl->general_frame_only_constraint_flag);
|
||||||
|
rbsp->put_bits(31, 0); //first 31 bits of general_reserved_zero_44bits
|
||||||
|
rbsp->put_bits(13, 0); //last 13 bits of general_reserved_zero_44bits
|
||||||
|
rbsp->put_bits(8, ptl->general_level_idc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_nalu_writer_hevc::write_rps(d3d12_video_encoder_bitstream* rbsp, HevcSeqParameterSet* pSPS, int stRpsIdx, bool sliceRPS)
|
||||||
|
{
|
||||||
|
HEVCReferencePictureSet* rps = &(pSPS->rpsShortTerm[stRpsIdx]);
|
||||||
|
|
||||||
|
if (stRpsIdx != 0) {
|
||||||
|
rbsp->put_bits(1, rps->inter_ref_pic_set_prediction_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rps->inter_ref_pic_set_prediction_flag) {
|
||||||
|
if (sliceRPS) {
|
||||||
|
rbsp->exp_Golomb_ue(rps->delta_idx_minus1);
|
||||||
|
}
|
||||||
|
int RefRpsIdx = stRpsIdx - (rps->delta_idx_minus1 + 1);
|
||||||
|
rbsp->put_bits(1, rps->delta_rps_sign);
|
||||||
|
rbsp->exp_Golomb_ue(rps->abs_delta_rps_minus1);
|
||||||
|
|
||||||
|
HEVCReferencePictureSet* rpsRef = &(pSPS->rpsShortTerm[RefRpsIdx]);
|
||||||
|
auto numDeltaPocs = rpsRef->num_negative_pics + rpsRef->num_positive_pics;
|
||||||
|
for (int j = 0; j <= numDeltaPocs; j++) {
|
||||||
|
rbsp->put_bits(1, rps->used_by_curr_pic_flag[j]);
|
||||||
|
if (!rps->used_by_curr_pic_flag[j]) {
|
||||||
|
rbsp->put_bits(1, rps->use_delta_flag[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rbsp->exp_Golomb_ue(rps->num_negative_pics);
|
||||||
|
rbsp->exp_Golomb_ue(rps->num_positive_pics);
|
||||||
|
|
||||||
|
for (int i = 0; i < rps->num_negative_pics; i++) {
|
||||||
|
rbsp->exp_Golomb_ue(rps->delta_poc_s0_minus1[i]);
|
||||||
|
rbsp->put_bits(1, rps->used_by_curr_pic_s0_flag[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < rps->num_positive_pics; i++) {
|
||||||
|
rbsp->exp_Golomb_ue(rps->delta_poc_s1_minus1[i]);
|
||||||
|
rbsp->put_bits(1, rps->used_by_curr_pic_s1_flag[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
347
src/gallium/drivers/d3d12/d3d12_video_encoder_nalu_writer_hevc.h
Normal file
347
src/gallium/drivers/d3d12/d3d12_video_encoder_nalu_writer_hevc.h
Normal file
|
|
@ -0,0 +1,347 @@
|
||||||
|
/*
|
||||||
|
* Copyright © Microsoft Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef D3D12_VIDEO_ENC_NALU_WRITER_HEVC_H
|
||||||
|
#define D3D12_VIDEO_ENC_NALU_WRITER_HEVC_H
|
||||||
|
|
||||||
|
#include "d3d12_video_encoder_bitstream.h"
|
||||||
|
|
||||||
|
#define HEVC_MAX_REF_PICS 16
|
||||||
|
#define HEVC_MAX_SUB_LAYERS_NUM 7
|
||||||
|
#define HEVC_MAX_TILE_NUM 64
|
||||||
|
|
||||||
|
#define MAX_COMPRESSED_NALU (10*1024)
|
||||||
|
|
||||||
|
enum HEVCNaluType {
|
||||||
|
HEVC_NALU_TRAIL_N = 0,
|
||||||
|
HEVC_NALU_TRAIL_R = 1,
|
||||||
|
HEVC_NALU_TSA_N = 2,
|
||||||
|
HEVC_NALU_TSA_R = 3,
|
||||||
|
HEVC_NALU_STSA_N = 4,
|
||||||
|
HEVC_NALU_STSA_R = 5,
|
||||||
|
HEVC_NALU_RADL_N = 6,
|
||||||
|
HEVC_NALU_RADL_R = 7,
|
||||||
|
HEVC_NALU_RASL_N = 8,
|
||||||
|
HEVC_NALU_RASL_R = 9,
|
||||||
|
HEVC_NALU_RSV_VCL_N10 = 10,
|
||||||
|
HEVC_NALU_RSV_VCL_N12 = 12,
|
||||||
|
HEVC_NALU_RSV_VCL_N14 = 14,
|
||||||
|
HEVC_NALU_RSV_VCL_R11 = 11,
|
||||||
|
HEVC_NALU_RSV_VCL_R13 = 13,
|
||||||
|
HEVC_NALU_RSV_VCL_R15 = 15,
|
||||||
|
HEVC_NALU_BLA_W_LP = 16,
|
||||||
|
HEVC_NALU_BLA_W_RADL = 17,
|
||||||
|
HEVC_NALU_BLA_N_LP = 18,
|
||||||
|
HEVC_NALU_IDR_W_RADL = 19,
|
||||||
|
HEVC_NALU_IDR_N_LP = 20,
|
||||||
|
HEVC_NALU_CRA_NUT = 21,
|
||||||
|
HEVC_NALU_RSV_IRAP_VCL22 = 22,
|
||||||
|
HEVC_NALU_RSV_IRAP_VCL23 = 23,
|
||||||
|
HEVC_NALU_RSV_VCL_24 = 24,
|
||||||
|
HEVC_NALU_RSV_VCL_25 = 25,
|
||||||
|
HEVC_NALU_RSV_VCL_26 = 26,
|
||||||
|
HEVC_NALU_RSV_VCL_27 = 27,
|
||||||
|
HEVC_NALU_RSV_VCL_28 = 28,
|
||||||
|
HEVC_NALU_RSV_VCL_29 = 29,
|
||||||
|
HEVC_NALU_RSV_VCL_30 = 30,
|
||||||
|
HEVC_NALU_RSV_VCL_31 = 31,
|
||||||
|
HEVC_NALU_VPS_NUT = 32,
|
||||||
|
HEVC_NALU_SPS_NUT = 33,
|
||||||
|
HEVC_NALU_PPS_NUT = 34,
|
||||||
|
HEVC_NALU_AUD_NUT = 35,
|
||||||
|
HEVC_NALU_EOS_NUT = 36,
|
||||||
|
HEVC_NALU_EOB_NUT = 37,
|
||||||
|
HEVC_NALU_FD_NUT = 38,
|
||||||
|
HEVC_NALU_PREFIX_SEI_NUT = 39,
|
||||||
|
HEVC_NALU_SUFFIX_SEI_NUT = 40,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HEVCNaluHeader {
|
||||||
|
uint8_t forbidden_zero_bit;
|
||||||
|
uint8_t nal_unit_type;
|
||||||
|
uint8_t nuh_layer_id;
|
||||||
|
uint8_t nuh_temporal_id_plus1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HEVCProfileTierLevel {
|
||||||
|
uint8_t general_profile_space;
|
||||||
|
uint8_t general_tier_flag;
|
||||||
|
uint8_t general_profile_idc;
|
||||||
|
uint8_t general_profile_compatibility_flag[32];
|
||||||
|
uint8_t general_progressive_source_flag;
|
||||||
|
uint8_t general_interlaced_source_flag;
|
||||||
|
uint8_t general_non_packed_constraint_flag;
|
||||||
|
uint8_t general_frame_only_constraint_flag;
|
||||||
|
uint8_t general_level_idc;
|
||||||
|
uint8_t sub_layer_profile_present_flag[HEVC_MAX_SUB_LAYERS_NUM - 1];
|
||||||
|
uint8_t sub_layer_level_present_flag[HEVC_MAX_SUB_LAYERS_NUM - 1];
|
||||||
|
uint8_t sub_layer_profile_space[HEVC_MAX_SUB_LAYERS_NUM - 1];
|
||||||
|
uint8_t sub_layer_tier_flag[HEVC_MAX_SUB_LAYERS_NUM - 1];
|
||||||
|
uint8_t sub_layer_profile_idc[HEVC_MAX_SUB_LAYERS_NUM - 1];
|
||||||
|
uint8_t sub_layer_profile_compatibility_flag[HEVC_MAX_SUB_LAYERS_NUM - 1][32];
|
||||||
|
uint8_t sub_layer_progressive_source_flag[HEVC_MAX_SUB_LAYERS_NUM - 1];
|
||||||
|
uint8_t sub_layer_interlaced_source_flag[HEVC_MAX_SUB_LAYERS_NUM - 1];
|
||||||
|
uint8_t sub_layer_non_packed_constraint_flag[HEVC_MAX_SUB_LAYERS_NUM - 1];
|
||||||
|
uint8_t sub_layer_frame_only_constraint_flag[HEVC_MAX_SUB_LAYERS_NUM - 1];
|
||||||
|
int32_t sub_layer_level_idc[HEVC_MAX_SUB_LAYERS_NUM - 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ReferencePictureSet {
|
||||||
|
int32_t numberOfPictures;
|
||||||
|
int32_t numberOfNegativePictures;
|
||||||
|
int32_t numberOfPositivePictures;
|
||||||
|
int32_t numberOfLongtermPictures;
|
||||||
|
int32_t deltaPOC[HEVC_MAX_REF_PICS];
|
||||||
|
int32_t POC[HEVC_MAX_REF_PICS];
|
||||||
|
uint8_t used[HEVC_MAX_REF_PICS];
|
||||||
|
uint8_t interRPSPrediction;
|
||||||
|
int32_t deltaRIdxMinus1;
|
||||||
|
int32_t deltaRPS;
|
||||||
|
int32_t numRefIdc;
|
||||||
|
int32_t refIdc[HEVC_MAX_REF_PICS + 1];
|
||||||
|
uint8_t bCheckLTMSB[HEVC_MAX_REF_PICS];
|
||||||
|
int32_t pocLSBLT[HEVC_MAX_REF_PICS];
|
||||||
|
int32_t deltaPOCMSBCycleLT[HEVC_MAX_REF_PICS];
|
||||||
|
uint8_t deltaPocMSBPresentFlag[HEVC_MAX_REF_PICS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HEVCReferencePictureSet {
|
||||||
|
uint8_t inter_ref_pic_set_prediction_flag;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint32_t delta_idx_minus1;
|
||||||
|
uint8_t delta_rps_sign;
|
||||||
|
uint32_t abs_delta_rps_minus1;
|
||||||
|
uint8_t used_by_curr_pic_flag[HEVC_MAX_REF_PICS];
|
||||||
|
uint8_t use_delta_flag[HEVC_MAX_REF_PICS];
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
int32_t num_negative_pics;
|
||||||
|
int32_t num_positive_pics;
|
||||||
|
int32_t delta_poc_s0_minus1[HEVC_MAX_REF_PICS];
|
||||||
|
uint8_t used_by_curr_pic_s0_flag[HEVC_MAX_REF_PICS];
|
||||||
|
int32_t delta_poc_s1_minus1[HEVC_MAX_REF_PICS];
|
||||||
|
uint8_t used_by_curr_pic_s1_flag[HEVC_MAX_REF_PICS];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HevcSeqParameterSet {
|
||||||
|
HEVCNaluHeader nalu;
|
||||||
|
uint8_t sps_video_parameter_set_id;
|
||||||
|
uint8_t sps_max_sub_layers_minus1;
|
||||||
|
uint8_t sps_temporal_id_nesting_flag;
|
||||||
|
HEVCProfileTierLevel ptl;
|
||||||
|
uint8_t sps_seq_parameter_set_id;
|
||||||
|
uint8_t chroma_format_idc;
|
||||||
|
uint8_t separate_colour_plane_flag;
|
||||||
|
int32_t pic_width_in_luma_samples;
|
||||||
|
int32_t pic_height_in_luma_samples;
|
||||||
|
uint8_t conformance_window_flag;
|
||||||
|
int32_t conf_win_left_offset;
|
||||||
|
int32_t conf_win_right_offset;
|
||||||
|
int32_t conf_win_top_offset;
|
||||||
|
int32_t conf_win_bottom_offset;
|
||||||
|
uint8_t bit_depth_luma_minus8;
|
||||||
|
uint8_t bit_depth_chroma_minus8;
|
||||||
|
uint8_t log2_max_pic_order_cnt_lsb_minus4;
|
||||||
|
int maxPicOrderCntLsb;
|
||||||
|
uint8_t sps_sub_layer_ordering_info_present_flag;
|
||||||
|
int32_t sps_max_dec_pic_buffering_minus1[HEVC_MAX_SUB_LAYERS_NUM];
|
||||||
|
int32_t sps_max_num_reorder_pics[HEVC_MAX_SUB_LAYERS_NUM];
|
||||||
|
int32_t sps_max_latency_increase_plus1[HEVC_MAX_SUB_LAYERS_NUM];
|
||||||
|
uint8_t log2_min_luma_coding_block_size_minus3;
|
||||||
|
uint8_t log2_diff_max_min_luma_coding_block_size;
|
||||||
|
uint8_t log2_min_transform_block_size_minus2;
|
||||||
|
uint8_t log2_diff_max_min_transform_block_size;
|
||||||
|
uint8_t max_transform_hierarchy_depth_inter;
|
||||||
|
uint8_t max_transform_hierarchy_depth_intra;
|
||||||
|
uint8_t scaling_list_enabled_flag;
|
||||||
|
uint8_t sps_scaling_list_data_present_flag;
|
||||||
|
uint8_t scaling_list_pred_mode_flag[4][6];
|
||||||
|
uint32_t scaling_list_pred_matrix_id_delta[4][6];
|
||||||
|
int32_t scaling_list_dc_coef_minus8[2][6];
|
||||||
|
int32_t scaling_list_delta_coef;
|
||||||
|
int32_t ScalingList[4][6][64];
|
||||||
|
uint8_t amp_enabled_flag;
|
||||||
|
uint8_t sample_adaptive_offset_enabled_flag;
|
||||||
|
uint8_t pcm_enabled_flag;
|
||||||
|
uint8_t pcm_sample_bit_depth_luma_minus1;
|
||||||
|
uint8_t pcm_sample_bit_depth_chroma_minus1;
|
||||||
|
int32_t log2_min_pcm_luma_coding_block_size_minus3;
|
||||||
|
int32_t log2_diff_max_min_pcm_luma_coding_block_size;
|
||||||
|
uint8_t pcm_loop_filter_disabled_flag;
|
||||||
|
uint8_t num_short_term_ref_pic_sets;
|
||||||
|
HEVCReferencePictureSet rpsShortTerm[64];
|
||||||
|
uint8_t long_term_ref_pics_present_flag;
|
||||||
|
uint8_t num_long_term_ref_pics_sps;
|
||||||
|
int32_t lt_ref_pic_poc_lsb_sps[32];
|
||||||
|
uint8_t used_by_curr_pic_lt_sps_flag[32];
|
||||||
|
uint8_t sps_temporal_mvp_enabled_flag;
|
||||||
|
uint8_t strong_intra_smoothing_enabled_flag;
|
||||||
|
uint8_t vui_parameters_present_flag;
|
||||||
|
uint8_t sps_extension_flag;
|
||||||
|
uint8_t sps_extension_data_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HevcPicParameterSet {
|
||||||
|
HEVCNaluHeader nalu;
|
||||||
|
uint8_t pps_pic_parameter_set_id;
|
||||||
|
uint8_t pps_seq_parameter_set_id;
|
||||||
|
uint8_t dependent_slice_segments_enabled_flag;
|
||||||
|
uint8_t output_flag_present_flag;
|
||||||
|
uint8_t num_extra_slice_header_bits;
|
||||||
|
uint8_t sign_data_hiding_enabled_flag;
|
||||||
|
uint8_t cabac_init_present_flag;
|
||||||
|
uint8_t num_ref_idx_lx_default_active_minus1[2];
|
||||||
|
int8_t init_qp_minus26;
|
||||||
|
uint8_t constrained_intra_pred_flag;
|
||||||
|
uint8_t transform_skip_enabled_flag;
|
||||||
|
uint8_t cu_qp_delta_enabled_flag;
|
||||||
|
uint8_t diff_cu_qp_delta_depth;
|
||||||
|
int8_t pps_cb_qp_offset;
|
||||||
|
int8_t pps_cr_qp_offset;
|
||||||
|
uint8_t pps_slice_chroma_qp_offsets_present_flag;
|
||||||
|
uint8_t weighted_pred_flag;
|
||||||
|
uint8_t weighted_bipred_flag;
|
||||||
|
uint8_t transquant_bypass_enabled_flag;
|
||||||
|
uint8_t tiles_enabled_flag;
|
||||||
|
uint8_t entropy_coding_sync_enabled_flag;
|
||||||
|
int32_t num_tile_columns_minus1;
|
||||||
|
int32_t num_tile_rows_minus1;
|
||||||
|
uint8_t uniform_spacing_flag;
|
||||||
|
int32_t column_width_minus1[HEVC_MAX_TILE_NUM];
|
||||||
|
int32_t row_height_minus1[HEVC_MAX_TILE_NUM];
|
||||||
|
uint8_t loop_filter_across_tiles_enabled_flag;
|
||||||
|
uint8_t pps_loop_filter_across_slices_enabled_flag;
|
||||||
|
uint8_t deblocking_filter_control_present_flag;
|
||||||
|
uint8_t deblocking_filter_override_enabled_flag;
|
||||||
|
uint8_t pps_deblocking_filter_disabled_flag;
|
||||||
|
int8_t pps_beta_offset_div2;
|
||||||
|
int8_t pps_tc_offset_div2;
|
||||||
|
uint8_t pps_scaling_list_data_present_flag;
|
||||||
|
uint8_t lists_modification_present_flag;
|
||||||
|
uint8_t log2_parallel_merge_level_minus2;
|
||||||
|
uint8_t slice_segment_header_extension_present_flag;
|
||||||
|
uint8_t pps_extension_flag;
|
||||||
|
uint8_t pps_extension_data_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HevcVideoParameterSet {
|
||||||
|
HEVCNaluHeader nalu;
|
||||||
|
uint8_t vps_video_parameter_set_id;
|
||||||
|
uint8_t vps_reserved_three_2bits;
|
||||||
|
uint8_t vps_max_layers_minus1;
|
||||||
|
uint8_t vps_max_sub_layers_minus1;
|
||||||
|
uint8_t vps_temporal_id_nesting_flag;
|
||||||
|
int32_t vps_reserved_0xffff_16bits;
|
||||||
|
HEVCProfileTierLevel ptl;
|
||||||
|
uint8_t vps_sub_layer_ordering_info_present_flag;
|
||||||
|
uint8_t vps_max_dec_pic_buffering_minus1[HEVC_MAX_SUB_LAYERS_NUM];
|
||||||
|
uint8_t vps_max_num_reorder_pics[HEVC_MAX_SUB_LAYERS_NUM];
|
||||||
|
uint8_t vps_max_latency_increase_plus1[HEVC_MAX_SUB_LAYERS_NUM];
|
||||||
|
uint8_t vps_max_layer_id;
|
||||||
|
uint8_t vps_num_layer_sets_minus1;
|
||||||
|
uint8_t layer_id_included_flag[1024][1];
|
||||||
|
uint8_t vps_timing_info_present_flag;
|
||||||
|
uint32_t vps_num_units_in_tick;
|
||||||
|
uint32_t vps_time_scale;
|
||||||
|
uint8_t vps_poc_proportional_to_timing_flag;
|
||||||
|
uint32_t vps_num_ticks_poc_diff_one_minus1;
|
||||||
|
uint32_t vps_num_hrd_parameters;
|
||||||
|
uint32_t hrd_layer_set_idx[1024];
|
||||||
|
uint8_t cprms_present_flag[1024];
|
||||||
|
uint8_t vps_extension_flag;
|
||||||
|
uint8_t vps_extension_data_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
class d3d12_video_nalu_writer_hevc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
d3d12_video_nalu_writer_hevc() { }
|
||||||
|
~d3d12_video_nalu_writer_hevc() { }
|
||||||
|
|
||||||
|
// Writes the HEVC VPS structure into a bitstream passed in headerBitstream
|
||||||
|
// Function resizes bitstream accordingly and puts result in byte vector
|
||||||
|
void vps_to_nalu_bytes(HevcVideoParameterSet *pVPS,
|
||||||
|
std::vector<BYTE>
|
||||||
|
&headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator
|
||||||
|
placingPositionStart,
|
||||||
|
size_t &writtenBytes);
|
||||||
|
|
||||||
|
// Writes the HEVC SPS structure into a bitstream passed in headerBitstream
|
||||||
|
// Function resizes bitstream accordingly and puts result in byte vector
|
||||||
|
void sps_to_nalu_bytes(HevcSeqParameterSet *pSPS,
|
||||||
|
std::vector<BYTE>
|
||||||
|
&headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator
|
||||||
|
placingPositionStart,
|
||||||
|
size_t &writtenBytes);
|
||||||
|
|
||||||
|
// Writes the HEVC PPS structure into a bitstream passed in headerBitstream
|
||||||
|
// Function resizes bitstream accordingly and puts result in byte vector
|
||||||
|
void pps_to_nalu_bytes(HevcPicParameterSet *pPPS,
|
||||||
|
std::vector<BYTE>
|
||||||
|
&headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator
|
||||||
|
placingPositionStart,
|
||||||
|
size_t &writtenBytes);
|
||||||
|
|
||||||
|
void write_end_of_stream_nalu(std::vector<BYTE> &headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator
|
||||||
|
placingPositionStart,
|
||||||
|
size_t
|
||||||
|
&writtenBytes);
|
||||||
|
void write_end_of_sequence_nalu(std::vector<BYTE>
|
||||||
|
&headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator
|
||||||
|
placingPositionStart,
|
||||||
|
size_t &writtenBytes);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Writes from structure into bitstream with RBSP trailing but WITHOUT NAL unit wrap (eg. nal_idc_type, etc)
|
||||||
|
uint32_t write_vps_bytes(d3d12_video_encoder_bitstream *pBitstream, HevcVideoParameterSet *pSPS);
|
||||||
|
uint32_t write_sps_bytes(d3d12_video_encoder_bitstream *pBitstream, HevcSeqParameterSet *pSPS);
|
||||||
|
uint32_t write_pps_bytes(d3d12_video_encoder_bitstream *pBitstream, HevcPicParameterSet *pPPS);
|
||||||
|
|
||||||
|
// Adds NALU wrapping into structures and ending NALU control bits
|
||||||
|
uint32_t wrap_rbsp_into_nalu(d3d12_video_encoder_bitstream *pNALU, d3d12_video_encoder_bitstream *pRBSP, HEVCNaluHeader *pHeader);
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
void write_nalu_end(d3d12_video_encoder_bitstream *pNALU);
|
||||||
|
void rbsp_trailing(d3d12_video_encoder_bitstream *pBitstream);
|
||||||
|
void write_profile_tier_level(d3d12_video_encoder_bitstream* rbsp, HEVCProfileTierLevel* ptl);
|
||||||
|
|
||||||
|
void generic_write_bytes(std::vector<BYTE> &headerBitstream,
|
||||||
|
std::vector<BYTE>::iterator placingPositionStart,
|
||||||
|
size_t &writtenBytes,
|
||||||
|
void *pStructure);
|
||||||
|
uint32_t
|
||||||
|
write_bytes_from_struct(d3d12_video_encoder_bitstream *pBitstream, void *pData, uint8_t nal_unit_type);
|
||||||
|
|
||||||
|
void write_rps(d3d12_video_encoder_bitstream* rbsp, HevcSeqParameterSet* sps, int stRpsIdx, bool sliceRPS);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
class d3d12_video_encoder_references_manager_interface
|
class d3d12_video_encoder_references_manager_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void begin_frame(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA, bool bUsedAsReference) = 0;
|
virtual void begin_frame(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA, bool bUsedAsReference, struct pipe_picture_desc* picture) = 0;
|
||||||
virtual void end_frame() = 0;
|
virtual void end_frame() = 0;
|
||||||
virtual D3D12_VIDEO_ENCODER_RECONSTRUCTED_PICTURE get_current_frame_recon_pic_output_allocation() = 0;
|
virtual D3D12_VIDEO_ENCODER_RECONSTRUCTED_PICTURE get_current_frame_recon_pic_output_allocation() = 0;
|
||||||
virtual void
|
virtual void
|
||||||
|
|
|
||||||
|
|
@ -398,11 +398,12 @@ d3d12_video_encoder_references_manager_h264::is_current_frame_used_as_reference(
|
||||||
|
|
||||||
void
|
void
|
||||||
d3d12_video_encoder_references_manager_h264::begin_frame(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA curFrameData,
|
d3d12_video_encoder_references_manager_h264::begin_frame(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA curFrameData,
|
||||||
bool bUsedAsReference)
|
bool bUsedAsReference, struct pipe_picture_desc* picture)
|
||||||
{
|
{
|
||||||
m_curFrameState = *curFrameData.pH264PicData;
|
m_curFrameState = *curFrameData.pH264PicData;
|
||||||
m_isCurrentFrameUsedAsReference = bUsedAsReference;
|
m_isCurrentFrameUsedAsReference = bUsedAsReference;
|
||||||
debug_printf("Marking frame_num %d (POC %d) as reference ? %d\n",
|
debug_printf("[Entrypoint: %d] - Marking frame_num %d (POC %d) as reference ? %d\n",
|
||||||
|
picture->entry_point,
|
||||||
curFrameData.pH264PicData->FrameDecodingOrderNumber,
|
curFrameData.pH264PicData->FrameDecodingOrderNumber,
|
||||||
curFrameData.pH264PicData->PictureOrderCountNumber,
|
curFrameData.pH264PicData->PictureOrderCountNumber,
|
||||||
bUsedAsReference);
|
bUsedAsReference);
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ class d3d12_video_encoder_references_manager_h264 : public d3d12_video_encoder_r
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void end_frame();
|
void end_frame();
|
||||||
void begin_frame(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA curFrameData, bool bUsedAsReference);
|
void begin_frame(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA curFrameData, bool bUsedAsReference, struct pipe_picture_desc* picture);
|
||||||
D3D12_VIDEO_ENCODER_RECONSTRUCTED_PICTURE get_current_frame_recon_pic_output_allocation();
|
D3D12_VIDEO_ENCODER_RECONSTRUCTED_PICTURE get_current_frame_recon_pic_output_allocation();
|
||||||
void get_current_frame_picture_control_data(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA &codecAllocation);
|
void get_current_frame_picture_control_data(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA &codecAllocation);
|
||||||
bool is_current_frame_used_as_reference();
|
bool is_current_frame_used_as_reference();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,463 @@
|
||||||
|
/*
|
||||||
|
* Copyright © Microsoft Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "d3d12_video_encoder_references_manager_hevc.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
#include "d3d12_screen.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
d3d12_video_encoder_references_manager_hevc::d3d12_video_encoder_references_manager_hevc(
|
||||||
|
bool gopHasIorPFrames, d3d12_video_dpb_storage_manager_interface &rDpbStorageManager, uint32_t MaxDPBCapacity)
|
||||||
|
: m_MaxDPBCapacity(MaxDPBCapacity),
|
||||||
|
m_rDPBStorageManager(rDpbStorageManager),
|
||||||
|
m_CurrentFrameReferencesData({}),
|
||||||
|
m_gopHasInterFrames(gopHasIorPFrames)
|
||||||
|
{
|
||||||
|
assert((m_MaxDPBCapacity + 1 /*extra for cur frame output recon pic*/) ==
|
||||||
|
m_rDPBStorageManager.get_number_of_tracked_allocations());
|
||||||
|
|
||||||
|
debug_printf("[D3D12 Video Encoder Picture Manager HEVC] Completed construction of "
|
||||||
|
"d3d12_video_encoder_references_manager_hevc instance, settings are\n");
|
||||||
|
debug_printf("[D3D12 Video Encoder Picture Manager HEVC] m_MaxDPBCapacity: %d\n", m_MaxDPBCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_encoder_references_manager_hevc::reset_gop_tracking_and_dpb()
|
||||||
|
{
|
||||||
|
// Reset m_CurrentFrameReferencesData tracking
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.clear();
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.reserve(m_MaxDPBCapacity);
|
||||||
|
m_curFrameStateDescriptorStorage.reserve(m_MaxDPBCapacity);
|
||||||
|
m_CurrentFrameReferencesData.ReconstructedPicTexture = { nullptr, 0 };
|
||||||
|
|
||||||
|
// Reset DPB storage
|
||||||
|
uint32_t numPicsBeforeClearInDPB = m_rDPBStorageManager.get_number_of_pics_in_dpb();
|
||||||
|
uint32_t cFreedResources = m_rDPBStorageManager.clear_decode_picture_buffer();
|
||||||
|
assert(numPicsBeforeClearInDPB == cFreedResources);
|
||||||
|
|
||||||
|
// Initialize if needed the reconstructed picture allocation for the first IDR picture in the GOP
|
||||||
|
// This needs to be done after initializing the GOP tracking state above since it makes decisions based on the
|
||||||
|
// current picture type.
|
||||||
|
prepare_current_frame_recon_pic_allocation();
|
||||||
|
|
||||||
|
// After clearing the DPB, outstanding used allocations should be 1u only for the first allocation for the
|
||||||
|
// reconstructed picture of the initial IDR in the GOP
|
||||||
|
assert(m_rDPBStorageManager.get_number_of_in_use_allocations() == (m_gopHasInterFrames ? 1u : 0u));
|
||||||
|
assert(m_rDPBStorageManager.get_number_of_tracked_allocations() <=
|
||||||
|
(m_MaxDPBCapacity + 1)); // pool is not extended beyond maximum expected usage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates the picture control structure for the current frame
|
||||||
|
void
|
||||||
|
d3d12_video_encoder_references_manager_hevc::get_current_frame_picture_control_data(
|
||||||
|
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA &codecAllocation)
|
||||||
|
{
|
||||||
|
// Update reference picture control structures (L0/L1 and DPB descriptors lists based on current frame and next frame
|
||||||
|
// in GOP) for next frame
|
||||||
|
|
||||||
|
debug_printf("[D3D12 Video Encoder Picture Manager HEVC] %d resources IN USE out of a total of %d ALLOCATED "
|
||||||
|
"resources at frame with POC: %d\n",
|
||||||
|
m_rDPBStorageManager.get_number_of_in_use_allocations(),
|
||||||
|
m_rDPBStorageManager.get_number_of_tracked_allocations(),
|
||||||
|
m_curFrameState.PictureOrderCountNumber);
|
||||||
|
|
||||||
|
// See casts below
|
||||||
|
assert(m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.size() < UINT32_MAX);
|
||||||
|
|
||||||
|
bool needsL0List = (m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_P_FRAME) ||
|
||||||
|
(m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_B_FRAME);
|
||||||
|
bool needsL1List = (m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_B_FRAME);
|
||||||
|
|
||||||
|
// (in HEVC I pics might contain following pics, ref not used in curr)
|
||||||
|
bool needsRefPicDescriptors = (m_curFrameState.FrameType != D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_IDR_FRAME);
|
||||||
|
|
||||||
|
assert(codecAllocation.DataSize == sizeof(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_HEVC));
|
||||||
|
|
||||||
|
// See D3D12 Encode spec below
|
||||||
|
// pList0ReferenceFrames
|
||||||
|
// List of past frame reference frames to be used for this frame. Each integer value in this array indices into
|
||||||
|
// pReferenceFramesReconPictureDescriptors to reference pictures kept in the DPB.
|
||||||
|
// pList1ReferenceFrames
|
||||||
|
// List of future frame reference frames to be used for this frame. Each integer value in this array indices into
|
||||||
|
// pReferenceFramesReconPictureDescriptors to reference pictures kept in the DPB.
|
||||||
|
|
||||||
|
// Need to map from frame_num in the receiving ref_idx_l0_list/ref_idx_l1_list to the position with that
|
||||||
|
// reference_lists_frame_idx in the DPB descriptor
|
||||||
|
|
||||||
|
// L0 and L1 need to be ordered by POC (ie. different RefPicSets). The upper layers building the lists should but might not be following this
|
||||||
|
|
||||||
|
// Set all in the DPB as unused for the current frame, then below just mark as used the ones references by L0 and L1
|
||||||
|
for(UINT idx = 0 ; idx < m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.size() ; idx++)
|
||||||
|
{
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[idx].base.IsRefUsedByCurrentPic = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsL0List && (m_curFrameState.List0ReferenceFramesCount > 0)) {
|
||||||
|
std::vector<uint32_t> tmpL0(m_curFrameState.List0ReferenceFramesCount, 0);
|
||||||
|
memcpy(tmpL0.data(),
|
||||||
|
m_curFrameState.pList0ReferenceFrames,
|
||||||
|
m_curFrameState.List0ReferenceFramesCount * sizeof(m_curFrameState.pList0ReferenceFrames[0]));
|
||||||
|
|
||||||
|
for (size_t l0Idx = 0; l0Idx < m_curFrameState.List0ReferenceFramesCount; l0Idx++) {
|
||||||
|
// tmpL0[l0Idx] has frame_num's (reference_lists_frame_idx)
|
||||||
|
// m_curFrameState.pList0ReferenceFrames[l0Idx] needs to have the index j of
|
||||||
|
// pReferenceFramesReconPictureDescriptors where
|
||||||
|
// pReferenceFramesReconPictureDescriptors[j].reference_lists_frame_idx == tmpL0[l0Idx]
|
||||||
|
|
||||||
|
auto value = tmpL0[l0Idx];
|
||||||
|
auto foundItemIt = std::find_if(m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.begin(),
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.end(),
|
||||||
|
[&value](const D3D12_VIDEO_ENCODER_REFERENCE_PICTURE_DESCRIPTOR_HEVC_EX &p) {
|
||||||
|
return p.reference_lists_frame_idx == value;
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(foundItemIt != m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.end());
|
||||||
|
m_curFrameState.pList0ReferenceFrames[l0Idx] =
|
||||||
|
std::distance(m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.begin(), foundItemIt);
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[m_curFrameState.pList0ReferenceFrames[l0Idx]].base.IsRefUsedByCurrentPic = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsL1List && (m_curFrameState.List1ReferenceFramesCount > 0)) {
|
||||||
|
std::vector<uint32_t> tmpL1(m_curFrameState.List1ReferenceFramesCount, 0);
|
||||||
|
memcpy(tmpL1.data(),
|
||||||
|
m_curFrameState.pList1ReferenceFrames,
|
||||||
|
m_curFrameState.List1ReferenceFramesCount * sizeof(m_curFrameState.pList1ReferenceFrames[0]));
|
||||||
|
|
||||||
|
for (size_t l1Idx = 0; l1Idx < m_curFrameState.List1ReferenceFramesCount; l1Idx++) {
|
||||||
|
// tmpL1[l1Idx] has frame_num's (reference_lists_frame_idx)
|
||||||
|
// m_curFrameState.pList1ReferenceFrames[l1Idx] needs to have the index j of
|
||||||
|
// pReferenceFramesReconPictureDescriptors where
|
||||||
|
// pReferenceFramesReconPictureDescriptors[j].reference_lists_frame_idx == tmpL1[l1Idx]
|
||||||
|
|
||||||
|
auto value = tmpL1[l1Idx];
|
||||||
|
auto foundItemIt = std::find_if(m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.begin(),
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.end(),
|
||||||
|
[&value](const D3D12_VIDEO_ENCODER_REFERENCE_PICTURE_DESCRIPTOR_HEVC_EX &p) {
|
||||||
|
return p.reference_lists_frame_idx == value;
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(foundItemIt != m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.end());
|
||||||
|
m_curFrameState.pList1ReferenceFrames[l1Idx] =
|
||||||
|
std::distance(m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.begin(), foundItemIt);
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[m_curFrameState.pList1ReferenceFrames[l1Idx]].base.IsRefUsedByCurrentPic = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_curFrameState.List0ReferenceFramesCount = needsL0List ? m_curFrameState.List0ReferenceFramesCount : 0;
|
||||||
|
m_curFrameState.pList0ReferenceFrames = needsL0List ? m_curFrameState.pList0ReferenceFrames : nullptr,
|
||||||
|
m_curFrameState.List1ReferenceFramesCount = needsL1List ? m_curFrameState.List1ReferenceFramesCount : 0,
|
||||||
|
m_curFrameState.pList1ReferenceFrames = needsL1List ? m_curFrameState.pList1ReferenceFrames : nullptr;
|
||||||
|
|
||||||
|
if (!needsRefPicDescriptors) {
|
||||||
|
m_curFrameState.ReferenceFramesReconPictureDescriptorsCount = 0;
|
||||||
|
m_curFrameState.pReferenceFramesReconPictureDescriptors = nullptr;
|
||||||
|
} else {
|
||||||
|
m_curFrameState.ReferenceFramesReconPictureDescriptorsCount = static_cast<uint32_t>(m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.size());
|
||||||
|
m_curFrameStateDescriptorStorage.resize(m_curFrameState.ReferenceFramesReconPictureDescriptorsCount);
|
||||||
|
for(uint32_t idx = 0; idx < m_curFrameState.ReferenceFramesReconPictureDescriptorsCount ; idx++) {
|
||||||
|
m_curFrameStateDescriptorStorage[idx] = m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[idx].base;
|
||||||
|
}
|
||||||
|
m_curFrameState.pReferenceFramesReconPictureDescriptors = m_curFrameStateDescriptorStorage.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
*codecAllocation.pHEVCPicData = m_curFrameState;
|
||||||
|
|
||||||
|
print_l0_l1_lists();
|
||||||
|
print_dpb();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the resource allocation for a reconstructed picture output for the current frame
|
||||||
|
D3D12_VIDEO_ENCODER_RECONSTRUCTED_PICTURE
|
||||||
|
d3d12_video_encoder_references_manager_hevc::get_current_frame_recon_pic_output_allocation()
|
||||||
|
{
|
||||||
|
return m_CurrentFrameReferencesData.ReconstructedPicTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12_VIDEO_ENCODE_REFERENCE_FRAMES
|
||||||
|
d3d12_video_encoder_references_manager_hevc::get_current_reference_frames()
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODE_REFERENCE_FRAMES retVal = { 0,
|
||||||
|
// ppTexture2Ds
|
||||||
|
nullptr,
|
||||||
|
// pSubresources
|
||||||
|
nullptr };
|
||||||
|
|
||||||
|
// Return nullptr for fully intra frames (eg IDR)
|
||||||
|
// and return references information for inter frames (eg.P/B) and I frame that doesn't flush DPB
|
||||||
|
|
||||||
|
if ((m_curFrameState.FrameType != D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_IDR_FRAME) && m_gopHasInterFrames) {
|
||||||
|
auto curRef = m_rDPBStorageManager.get_current_reference_frames();
|
||||||
|
retVal.NumTexture2Ds = curRef.NumTexture2Ds;
|
||||||
|
retVal.ppTexture2Ds = curRef.ppTexture2Ds;
|
||||||
|
retVal.pSubresources = curRef.pSubresources;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_encoder_references_manager_hevc::prepare_current_frame_recon_pic_allocation()
|
||||||
|
{
|
||||||
|
m_CurrentFrameReferencesData.ReconstructedPicTexture = { nullptr, 0 };
|
||||||
|
|
||||||
|
// If all GOP are intra frames, no point in doing reference pic allocations
|
||||||
|
if (is_current_frame_used_as_reference() && m_gopHasInterFrames) {
|
||||||
|
auto reconPic = m_rDPBStorageManager.get_new_tracked_picture_allocation();
|
||||||
|
m_CurrentFrameReferencesData.ReconstructedPicTexture.pReconstructedPicture = reconPic.pReconstructedPicture;
|
||||||
|
m_CurrentFrameReferencesData.ReconstructedPicTexture.ReconstructedPictureSubresource =
|
||||||
|
reconPic.ReconstructedPictureSubresource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_encoder_references_manager_hevc::update_fifo_dpb_push_front_cur_recon_pic()
|
||||||
|
{
|
||||||
|
// Keep the order of the dpb storage and dpb descriptors in a circular buffer
|
||||||
|
// order such that the DPB array consists of a sequence of frames in DECREASING encoding order
|
||||||
|
// eg. last frame encoded at first, followed by one to last frames encoded, and at the end
|
||||||
|
// the most distant frame encoded (currentFrameEncodeOrderNumber - MaxDPBSize)
|
||||||
|
|
||||||
|
// If current pic was not used as reference, current reconstructed picture resource is empty,
|
||||||
|
// No need to to anything in that case.
|
||||||
|
// Otherwise extract the reconstructed picture result and add it to the DPB
|
||||||
|
|
||||||
|
// If GOP are all intra frames, do nothing also.
|
||||||
|
if (is_current_frame_used_as_reference() && m_gopHasInterFrames) {
|
||||||
|
debug_printf("[D3D12 Video Encoder Picture Manager HEVC] MaxDPBCapacity is %d - Number of pics in DPB is %d "
|
||||||
|
"when trying to put frame with POC %d (frame_num %d) at front of the DPB\n",
|
||||||
|
m_MaxDPBCapacity,
|
||||||
|
m_rDPBStorageManager.get_number_of_pics_in_dpb(),
|
||||||
|
m_curFrameState.PictureOrderCountNumber,
|
||||||
|
m_current_frame_idx);
|
||||||
|
|
||||||
|
// Release least recently used in DPB if we filled the m_MaxDPBCapacity allowed
|
||||||
|
if (m_rDPBStorageManager.get_number_of_pics_in_dpb() == m_MaxDPBCapacity) {
|
||||||
|
bool untrackedRes = false;
|
||||||
|
m_rDPBStorageManager.remove_reference_frame(m_rDPBStorageManager.get_number_of_pics_in_dpb() - 1,
|
||||||
|
&untrackedRes); // Remove last entry
|
||||||
|
// Verify that resource was untracked since this class is using the pool completely for allocations
|
||||||
|
assert(untrackedRes);
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.pop_back(); // Remove last entry
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new dpb to front of DPB
|
||||||
|
D3D12_VIDEO_ENCODER_RECONSTRUCTED_PICTURE recAlloc = get_current_frame_recon_pic_output_allocation();
|
||||||
|
d3d12_video_reconstructed_picture refFrameDesc = {};
|
||||||
|
refFrameDesc.pReconstructedPicture = recAlloc.pReconstructedPicture;
|
||||||
|
refFrameDesc.ReconstructedPictureSubresource = recAlloc.ReconstructedPictureSubresource;
|
||||||
|
refFrameDesc.pVideoHeap = nullptr; // D3D12 Video Encode does not need the D3D12VideoEncoderHeap struct for HEVC
|
||||||
|
// (used for no-key-frame resolution change in VC1, AV1, etc)
|
||||||
|
m_rDPBStorageManager.insert_reference_frame(refFrameDesc, 0);
|
||||||
|
|
||||||
|
// Prepare D3D12_VIDEO_ENCODER_REFERENCE_PICTURE_DESCRIPTOR_HEVC_EX for added DPB member
|
||||||
|
D3D12_VIDEO_ENCODER_REFERENCE_PICTURE_DESCRIPTOR_HEVC_EX newDPBDescriptor =
|
||||||
|
{
|
||||||
|
// D3D12_VIDEO_ENCODER_REFERENCE_PICTURE_DESCRIPTOR_HEVC
|
||||||
|
{
|
||||||
|
// UINT ReconstructedPictureResourceIndex;
|
||||||
|
0, // the associated reconstructed picture is also being pushed_front in m_rDPBStorageManager
|
||||||
|
// BOOL IsRefUsedByCurrentPic;
|
||||||
|
false, // usage is determined in method AdvanceFrame according to picture type to be encoded
|
||||||
|
// BOOL IsLongTermReference
|
||||||
|
false, // not implemented - neither FFMPEG or GSTREAMER use LTR for HEVC VAAPI
|
||||||
|
// UINT PictureOrderCountNumber;
|
||||||
|
m_curFrameState.PictureOrderCountNumber,
|
||||||
|
// UINT TemporalLayerIndex;
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// reference_lists_frame_idx
|
||||||
|
m_current_frame_idx,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add DPB entry
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.insert(
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.begin(),
|
||||||
|
newDPBDescriptor);
|
||||||
|
|
||||||
|
// Update the indices for ReconstructedPictureResourceIndex in pReferenceFramesReconPictureDescriptors
|
||||||
|
// to be in identity mapping with m_rDPBStorageManager indices
|
||||||
|
// after pushing the elements to the right in the push_front operation
|
||||||
|
for (uint32_t dpbResIdx = 1;
|
||||||
|
dpbResIdx < m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.size();
|
||||||
|
dpbResIdx++) {
|
||||||
|
auto &dpbDesc = m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[dpbResIdx];
|
||||||
|
dpbDesc.base.ReconstructedPictureResourceIndex = dpbResIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number of allocations, disregarding if they are used or not, should not exceed this limit due to reuse policies on
|
||||||
|
// DPB items removal.
|
||||||
|
assert(m_rDPBStorageManager.get_number_of_tracked_allocations() <= (m_MaxDPBCapacity + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_encoder_references_manager_hevc::print_l0_l1_lists()
|
||||||
|
{
|
||||||
|
if ((D3D12_DEBUG_VERBOSE & d3d12_debug) &&
|
||||||
|
((m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_P_FRAME) ||
|
||||||
|
(m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_B_FRAME))) {
|
||||||
|
std::string list0ContentsString;
|
||||||
|
for (uint32_t idx = 0; idx < m_curFrameState.List0ReferenceFramesCount; idx++) {
|
||||||
|
uint32_t value = m_curFrameState.pList0ReferenceFrames[idx];
|
||||||
|
list0ContentsString += "{ DPBidx: ";
|
||||||
|
list0ContentsString += std::to_string(value);
|
||||||
|
list0ContentsString += " - POC: ";
|
||||||
|
list0ContentsString += std::to_string(
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].base.PictureOrderCountNumber);
|
||||||
|
list0ContentsString += " - IsRefUsedByCurrentPic: ";
|
||||||
|
list0ContentsString += std::to_string(
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].base.IsRefUsedByCurrentPic);
|
||||||
|
list0ContentsString += " - IsLongTermReference: ";
|
||||||
|
list0ContentsString += std::to_string(
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].base.IsLongTermReference);
|
||||||
|
list0ContentsString += " - reference_lists_frame_idx: ";
|
||||||
|
list0ContentsString += std::to_string(
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].reference_lists_frame_idx);
|
||||||
|
list0ContentsString += "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_printf(
|
||||||
|
"[D3D12 Video Encoder Picture Manager HEVC] L0 list for frame with POC %d (frame_num %d) is: \n %s \n",
|
||||||
|
m_curFrameState.PictureOrderCountNumber,
|
||||||
|
m_current_frame_idx,
|
||||||
|
list0ContentsString.c_str());
|
||||||
|
|
||||||
|
std::string list1ContentsString;
|
||||||
|
for (uint32_t idx = 0; idx < m_curFrameState.List1ReferenceFramesCount; idx++) {
|
||||||
|
uint32_t value = m_curFrameState.pList1ReferenceFrames[idx];
|
||||||
|
list1ContentsString += "{ DPBidx: ";
|
||||||
|
list1ContentsString += std::to_string(value);
|
||||||
|
list1ContentsString += " - POC: ";
|
||||||
|
list1ContentsString += std::to_string(
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].base.PictureOrderCountNumber);
|
||||||
|
list1ContentsString += " - IsRefUsedByCurrentPic: ";
|
||||||
|
list1ContentsString += std::to_string(
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].base.IsRefUsedByCurrentPic);
|
||||||
|
list1ContentsString += " - IsLongTermReference: ";
|
||||||
|
list1ContentsString += std::to_string(
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].base.IsLongTermReference);
|
||||||
|
list1ContentsString += " - reference_lists_frame_idx: ";
|
||||||
|
list1ContentsString += std::to_string(
|
||||||
|
m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[value].reference_lists_frame_idx);
|
||||||
|
list1ContentsString += "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_printf(
|
||||||
|
"[D3D12 Video Encoder Picture Manager HEVC] L1 list for frame with POC %d (frame_num %d) is: \n %s \n",
|
||||||
|
m_curFrameState.PictureOrderCountNumber,
|
||||||
|
m_current_frame_idx,
|
||||||
|
list1ContentsString.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_encoder_references_manager_hevc::print_dpb()
|
||||||
|
{
|
||||||
|
if (D3D12_DEBUG_VERBOSE & d3d12_debug) {
|
||||||
|
std::string dpbContents;
|
||||||
|
for (uint32_t dpbResIdx = 0;
|
||||||
|
dpbResIdx < m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors.size();
|
||||||
|
dpbResIdx++) {
|
||||||
|
auto &dpbDesc = m_CurrentFrameReferencesData.pReferenceFramesReconPictureDescriptors[dpbResIdx];
|
||||||
|
auto dpbEntry = m_rDPBStorageManager.get_reference_frame(dpbDesc.base.ReconstructedPictureResourceIndex);
|
||||||
|
|
||||||
|
dpbContents += "{ DPBidx: ";
|
||||||
|
dpbContents += std::to_string(dpbResIdx);
|
||||||
|
dpbContents += " - POC: ";
|
||||||
|
dpbContents += std::to_string(dpbDesc.base.PictureOrderCountNumber);
|
||||||
|
dpbContents += " - IsRefUsedByCurrentPic: ";
|
||||||
|
dpbContents += std::to_string(dpbDesc.base.IsRefUsedByCurrentPic);
|
||||||
|
dpbContents += " - DPBStorageIdx: ";
|
||||||
|
dpbContents += std::to_string(dpbDesc.base.ReconstructedPictureResourceIndex);
|
||||||
|
dpbContents += " - reference_lists_frame_idx: ";
|
||||||
|
dpbContents += std::to_string(dpbDesc.reference_lists_frame_idx);
|
||||||
|
dpbContents += " - DPBStorageResourcePtr: ";
|
||||||
|
char strBuf[256];
|
||||||
|
memset(&strBuf, '\0', 256);
|
||||||
|
sprintf(strBuf, "%p", dpbEntry.pReconstructedPicture);
|
||||||
|
dpbContents += std::string(strBuf);
|
||||||
|
dpbContents += " - DPBStorageSubresource: ";
|
||||||
|
dpbContents += std::to_string(dpbEntry.ReconstructedPictureSubresource);
|
||||||
|
dpbContents += "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_printf("[D3D12 Video Encoder Picture Manager HEVC] DPB has %d frames - DPB references for frame with POC "
|
||||||
|
"%d are: \n %s \n",
|
||||||
|
m_rDPBStorageManager.get_number_of_pics_in_dpb(),
|
||||||
|
m_curFrameState.PictureOrderCountNumber,
|
||||||
|
dpbContents.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advances state to next frame in GOP; subsequent calls to GetCurrentFrame* point to the advanced frame status
|
||||||
|
void
|
||||||
|
d3d12_video_encoder_references_manager_hevc::end_frame()
|
||||||
|
{
|
||||||
|
debug_printf("[D3D12 Video Encoder Picture Manager HEVC] %d resources IN USE out of a total of %d ALLOCATED "
|
||||||
|
"resources at end_frame for frame with POC: %d\n",
|
||||||
|
m_rDPBStorageManager.get_number_of_in_use_allocations(),
|
||||||
|
m_rDPBStorageManager.get_number_of_tracked_allocations(),
|
||||||
|
m_curFrameState.PictureOrderCountNumber);
|
||||||
|
|
||||||
|
// Adds last used (if not null) get_current_frame_recon_pic_output_allocation to DPB for next EncodeFrame if
|
||||||
|
// necessary updates pReferenceFramesReconPictureDescriptors and updates the dpb storage
|
||||||
|
|
||||||
|
update_fifo_dpb_push_front_cur_recon_pic();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
d3d12_video_encoder_references_manager_hevc::is_current_frame_used_as_reference()
|
||||||
|
{
|
||||||
|
return m_isCurrentFrameUsedAsReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
d3d12_video_encoder_references_manager_hevc::begin_frame(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA curFrameData,
|
||||||
|
bool bUsedAsReference, struct pipe_picture_desc* picture)
|
||||||
|
{
|
||||||
|
pipe_h265_enc_picture_desc * pPipeDesc = (pipe_h265_enc_picture_desc*) picture;
|
||||||
|
|
||||||
|
m_curFrameState = *curFrameData.pHEVCPicData;
|
||||||
|
m_isCurrentFrameUsedAsReference = bUsedAsReference;
|
||||||
|
m_current_frame_idx = pPipeDesc->frame_num;
|
||||||
|
debug_printf("Marking POC %d (frame_num %d) as reference ? %d\n",
|
||||||
|
curFrameData.pHEVCPicData->PictureOrderCountNumber,
|
||||||
|
m_current_frame_idx,
|
||||||
|
bUsedAsReference);
|
||||||
|
|
||||||
|
// Advance the GOP tracking state
|
||||||
|
bool isDPBFlushNeeded = (m_curFrameState.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_IDR_FRAME);
|
||||||
|
if (isDPBFlushNeeded) {
|
||||||
|
reset_gop_tracking_and_dpb();
|
||||||
|
} else {
|
||||||
|
// Get new allocation from DPB storage for reconstructed picture
|
||||||
|
// This is only necessary for the frames that come after an IDR
|
||||||
|
// since in the initial state already has this initialized
|
||||||
|
// and re-initialized by reset_gop_tracking_and_dpb above
|
||||||
|
|
||||||
|
prepare_current_frame_recon_pic_allocation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* Copyright © Microsoft Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef D3D12_VIDEO_ENCODE_FIFO_REFERENCES_MANAGER_HEVC_H
|
||||||
|
#define D3D12_VIDEO_ENCODE_FIFO_REFERENCES_MANAGER_HEVC_H
|
||||||
|
|
||||||
|
#include "d3d12_video_types.h"
|
||||||
|
#include "d3d12_video_encoder_references_manager.h"
|
||||||
|
#include "d3d12_video_dpb_storage_manager.h"
|
||||||
|
|
||||||
|
class d3d12_video_encoder_references_manager_hevc : public d3d12_video_encoder_references_manager_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void end_frame();
|
||||||
|
void begin_frame(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA curFrameData, bool bUsedAsReference, struct pipe_picture_desc* picture);
|
||||||
|
D3D12_VIDEO_ENCODER_RECONSTRUCTED_PICTURE get_current_frame_recon_pic_output_allocation();
|
||||||
|
void get_current_frame_picture_control_data(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA &codecAllocation);
|
||||||
|
bool is_current_frame_used_as_reference();
|
||||||
|
D3D12_VIDEO_ENCODE_REFERENCE_FRAMES get_current_reference_frames();
|
||||||
|
|
||||||
|
d3d12_video_encoder_references_manager_hevc(bool gopHasInterCodedFrames,
|
||||||
|
d3d12_video_dpb_storage_manager_interface &rDpbStorageManager,
|
||||||
|
uint32_t MaxDPBCapacity);
|
||||||
|
|
||||||
|
~d3d12_video_encoder_references_manager_hevc()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Class helpers
|
||||||
|
void prepare_current_frame_recon_pic_allocation();
|
||||||
|
void reset_gop_tracking_and_dpb();
|
||||||
|
void update_fifo_dpb_push_front_cur_recon_pic();
|
||||||
|
void print_dpb();
|
||||||
|
void print_l0_l1_lists();
|
||||||
|
|
||||||
|
// Class members
|
||||||
|
|
||||||
|
uint32_t m_MaxDPBCapacity = 0;
|
||||||
|
|
||||||
|
struct D3D12_VIDEO_ENCODER_REFERENCE_PICTURE_DESCRIPTOR_HEVC_EX {
|
||||||
|
D3D12_VIDEO_ENCODER_REFERENCE_PICTURE_DESCRIPTOR_HEVC base;
|
||||||
|
/* the upper layer uses pipe_h265_enc_picture_desc.frame_num to identify frames
|
||||||
|
in the L0 and L1 reference lists. This frame_num is different than POC
|
||||||
|
so let's save it in this variable to be able to reverse-map the L0/L1 lists from
|
||||||
|
these indices into POCs */
|
||||||
|
unsigned int reference_lists_frame_idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct current_frame_references_data
|
||||||
|
{
|
||||||
|
std::vector<D3D12_VIDEO_ENCODER_REFERENCE_PICTURE_DESCRIPTOR_HEVC_EX> pReferenceFramesReconPictureDescriptors;
|
||||||
|
D3D12_VIDEO_ENCODER_RECONSTRUCTED_PICTURE ReconstructedPicTexture;
|
||||||
|
};
|
||||||
|
|
||||||
|
d3d12_video_dpb_storage_manager_interface &m_rDPBStorageManager;
|
||||||
|
|
||||||
|
current_frame_references_data m_CurrentFrameReferencesData;
|
||||||
|
|
||||||
|
bool m_gopHasInterFrames = false;
|
||||||
|
|
||||||
|
bool m_isCurrentFrameUsedAsReference = false;
|
||||||
|
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_HEVC m_curFrameState = {};
|
||||||
|
std::vector<D3D12_VIDEO_ENCODER_REFERENCE_PICTURE_DESCRIPTOR_HEVC> m_curFrameStateDescriptorStorage;
|
||||||
|
unsigned int m_current_frame_idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -26,12 +26,29 @@
|
||||||
#include "d3d12_format.h"
|
#include "d3d12_format.h"
|
||||||
#include "util/u_video.h"
|
#include "util/u_video.h"
|
||||||
#include <directx/d3d12video.h>
|
#include <directx/d3d12video.h>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include <wrl/client.h>
|
#include <wrl/client.h>
|
||||||
using Microsoft::WRL::ComPtr;
|
using Microsoft::WRL::ComPtr;
|
||||||
|
|
||||||
#include "d3d12_video_types.h"
|
#include "d3d12_video_types.h"
|
||||||
|
|
||||||
|
struct d3d12_encode_codec_support {
|
||||||
|
enum pipe_video_profile profile;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
enum pipe_h265_enc_pred_direction prediction_direction;
|
||||||
|
union pipe_h265_enc_cap_features hevc_features;
|
||||||
|
union pipe_h265_enc_cap_block_sizes hevc_block_sizes;
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC d3d12_caps;
|
||||||
|
} hevc_support;
|
||||||
|
// Can add more codecs for each codec specific caps here, for example:
|
||||||
|
// struct {
|
||||||
|
// D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_H264;
|
||||||
|
// } h264_support;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
d3d12_video_buffer_is_format_supported(struct pipe_screen *screen,
|
d3d12_video_buffer_is_format_supported(struct pipe_screen *screen,
|
||||||
enum pipe_format format,
|
enum pipe_format format,
|
||||||
|
|
@ -134,6 +151,8 @@ d3d12_has_video_decode_support(struct pipe_screen *pscreen, enum pipe_video_prof
|
||||||
case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
|
case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
|
||||||
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
|
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
|
||||||
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10:
|
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10:
|
||||||
|
case PIPE_VIDEO_PROFILE_HEVC_MAIN:
|
||||||
|
case PIPE_VIDEO_PROFILE_HEVC_MAIN_10:
|
||||||
{
|
{
|
||||||
supportsProfile = true;
|
supportsProfile = true;
|
||||||
} break;
|
} break;
|
||||||
|
|
@ -207,18 +226,18 @@ d3d12_video_encode_max_supported_resolution(const D3D12_VIDEO_ENCODER_CODEC &arg
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
d3d12_video_encode_supported_references_per_frame_structures(const D3D12_VIDEO_ENCODER_CODEC &codec,
|
d3d12_video_encode_supported_references_per_frame_structures(const D3D12_VIDEO_ENCODER_CODEC &codec,
|
||||||
D3D12_VIDEO_ENCODER_PROFILE_H264 profile,
|
D3D12_VIDEO_ENCODER_PROFILE_DESC profile,
|
||||||
D3D12_VIDEO_ENCODER_LEVELS_H264 level,
|
|
||||||
ID3D12VideoDevice3 *pD3D12VideoDevice)
|
ID3D12VideoDevice3 *pD3D12VideoDevice)
|
||||||
{
|
{
|
||||||
uint32_t supportedMaxRefFrames = 0u;
|
uint32_t supportedMaxRefFrames = 0u;
|
||||||
|
|
||||||
D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_H264 h264PictureControl = {};
|
|
||||||
D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT capPictureControlData = {};
|
D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT capPictureControlData = {};
|
||||||
capPictureControlData.NodeIndex = 0;
|
capPictureControlData.NodeIndex = 0;
|
||||||
capPictureControlData.Codec = codec;
|
capPictureControlData.Codec = codec;
|
||||||
capPictureControlData.Profile.pH264Profile = &profile;
|
|
||||||
capPictureControlData.Profile.DataSize = sizeof(profile);
|
if(codec == D3D12_VIDEO_ENCODER_CODEC_H264) {
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_H264 h264PictureControl = {};
|
||||||
|
capPictureControlData.Profile = profile;
|
||||||
capPictureControlData.PictureSupport.pH264Support = &h264PictureControl;
|
capPictureControlData.PictureSupport.pH264Support = &h264PictureControl;
|
||||||
capPictureControlData.PictureSupport.DataSize = sizeof(h264PictureControl);
|
capPictureControlData.PictureSupport.DataSize = sizeof(h264PictureControl);
|
||||||
HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT,
|
HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT,
|
||||||
|
|
@ -241,14 +260,40 @@ d3d12_video_encode_supported_references_per_frame_structures(const D3D12_VIDEO_E
|
||||||
uint32_t maxRefForL1 = capPictureControlData.PictureSupport.pH264Support->MaxL1ReferencesForB;
|
uint32_t maxRefForL1 = capPictureControlData.PictureSupport.pH264Support->MaxL1ReferencesForB;
|
||||||
supportedMaxRefFrames = (maxRefForL0 & 0xffff) | ((maxRefForL1 & 0xffff) << 16);
|
supportedMaxRefFrames = (maxRefForL0 & 0xffff) | ((maxRefForL1 & 0xffff) << 16);
|
||||||
}
|
}
|
||||||
|
} else if(codec == D3D12_VIDEO_ENCODER_CODEC_HEVC) {
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_HEVC hevcPictureControl = {};
|
||||||
|
capPictureControlData.Profile = profile;
|
||||||
|
capPictureControlData.PictureSupport.pHEVCSupport = &hevcPictureControl;
|
||||||
|
capPictureControlData.PictureSupport.DataSize = sizeof(hevcPictureControl);
|
||||||
|
HRESULT hr = pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT,
|
||||||
|
&capPictureControlData,
|
||||||
|
sizeof(capPictureControlData));
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
debug_printf("CheckFeatureSupport failed with HR %x\n", hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (capPictureControlData.IsSupported) {
|
||||||
|
/* This attribute determines the maximum number of reference
|
||||||
|
* frames supported for encoding.
|
||||||
|
*
|
||||||
|
* Note: for H.265 encoding, the value represents the maximum number
|
||||||
|
* of reference frames for both the reference picture list 0 (bottom
|
||||||
|
* 16 bits) and the reference picture list 1 (top 16 bits).
|
||||||
|
*/
|
||||||
|
uint32_t maxRefForL0 = std::min(capPictureControlData.PictureSupport.pHEVCSupport->MaxL0ReferencesForP,
|
||||||
|
capPictureControlData.PictureSupport.pHEVCSupport->MaxL0ReferencesForB);
|
||||||
|
uint32_t maxRefForL1 = capPictureControlData.PictureSupport.pHEVCSupport->MaxL1ReferencesForB;
|
||||||
|
supportedMaxRefFrames = (maxRefForL0 & 0xffff) | ((maxRefForL1 & 0xffff) << 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return supportedMaxRefFrames;
|
return supportedMaxRefFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
d3d12_video_encode_supported_slice_structures(const D3D12_VIDEO_ENCODER_CODEC &codec,
|
d3d12_video_encode_supported_slice_structures(const D3D12_VIDEO_ENCODER_CODEC &codec,
|
||||||
D3D12_VIDEO_ENCODER_PROFILE_H264 profile,
|
D3D12_VIDEO_ENCODER_PROFILE_DESC profile,
|
||||||
D3D12_VIDEO_ENCODER_LEVELS_H264 level,
|
D3D12_VIDEO_ENCODER_LEVEL_SETTING level,
|
||||||
ID3D12VideoDevice3 *pD3D12VideoDevice)
|
ID3D12VideoDevice3 *pD3D12VideoDevice)
|
||||||
{
|
{
|
||||||
uint32_t supportedSliceStructuresBitMask = PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE;
|
uint32_t supportedSliceStructuresBitMask = PIPE_VIDEO_CAP_SLICE_STRUCTURE_NONE;
|
||||||
|
|
@ -256,10 +301,8 @@ d3d12_video_encode_supported_slice_structures(const D3D12_VIDEO_ENCODER_CODEC &c
|
||||||
D3D12_FEATURE_DATA_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE capDataSubregionLayout = {};
|
D3D12_FEATURE_DATA_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE capDataSubregionLayout = {};
|
||||||
capDataSubregionLayout.NodeIndex = 0;
|
capDataSubregionLayout.NodeIndex = 0;
|
||||||
capDataSubregionLayout.Codec = codec;
|
capDataSubregionLayout.Codec = codec;
|
||||||
capDataSubregionLayout.Profile.pH264Profile = &profile;
|
capDataSubregionLayout.Profile = profile;
|
||||||
capDataSubregionLayout.Profile.DataSize = sizeof(profile);
|
capDataSubregionLayout.Level = level;
|
||||||
capDataSubregionLayout.Level.pH264LevelSetting = &level;
|
|
||||||
capDataSubregionLayout.Level.DataSize = sizeof(level);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pipe_video_cap_slice_structure
|
* pipe_video_cap_slice_structure
|
||||||
|
|
@ -273,6 +316,10 @@ d3d12_video_encode_supported_slice_structures(const D3D12_VIDEO_ENCODER_CODEC &c
|
||||||
* determines the range of accepted values to
|
* determines the range of accepted values to
|
||||||
* h264_slice_descriptor::macroblock_address and
|
* h264_slice_descriptor::macroblock_address and
|
||||||
* h264_slice_descriptor::num_macroblocks.
|
* h264_slice_descriptor::num_macroblocks.
|
||||||
|
*
|
||||||
|
* For HEVC, similarly determines the ranges for
|
||||||
|
* slice_segment_address
|
||||||
|
* num_ctu_in_slice
|
||||||
*/
|
*/
|
||||||
capDataSubregionLayout.SubregionMode =
|
capDataSubregionLayout.SubregionMode =
|
||||||
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME;
|
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME;
|
||||||
|
|
@ -331,7 +378,8 @@ d3d12_video_encode_max_supported_slices(const D3D12_VIDEO_ENCODER_CODEC &argTarg
|
||||||
D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC maxResolution,
|
D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC maxResolution,
|
||||||
DXGI_FORMAT encodeFormat,
|
DXGI_FORMAT encodeFormat,
|
||||||
uint32_t &outMaxSlices,
|
uint32_t &outMaxSlices,
|
||||||
ID3D12VideoDevice3 *pD3D12VideoDevice)
|
ID3D12VideoDevice3 *pD3D12VideoDevice,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT codecSupport)
|
||||||
{
|
{
|
||||||
D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT capEncoderSupportData = {};
|
D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT capEncoderSupportData = {};
|
||||||
capEncoderSupportData.NodeIndex = 0;
|
capEncoderSupportData.NodeIndex = 0;
|
||||||
|
|
@ -351,13 +399,22 @@ d3d12_video_encode_max_supported_slices(const D3D12_VIDEO_ENCODER_CODEC &argTarg
|
||||||
capEncoderSupportData.SubregionFrameEncoding =
|
capEncoderSupportData.SubregionFrameEncoding =
|
||||||
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME;
|
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_SUBREGIONS_PER_FRAME;
|
||||||
|
|
||||||
|
/*
|
||||||
|
All codec structures must be declared outside the switch statement to be
|
||||||
|
present in memory (stack scope) when calling CheckFeatureSupport below
|
||||||
|
*/
|
||||||
D3D12_VIDEO_ENCODER_PROFILE_H264 h264prof = {};
|
D3D12_VIDEO_ENCODER_PROFILE_H264 h264prof = {};
|
||||||
D3D12_VIDEO_ENCODER_LEVELS_H264 h264lvl = {};
|
D3D12_VIDEO_ENCODER_LEVELS_H264 h264lvl = {};
|
||||||
D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE_H264 h264Gop = { 1, 0, 0, 0, 0 };
|
D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE_H264 h264Gop = { 1, 0, 0, 0, 0 };
|
||||||
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264 h264Config = {};
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264 h264Config = {};
|
||||||
|
D3D12_VIDEO_ENCODER_PROFILE_HEVC hevcprof = D3D12_VIDEO_ENCODER_PROFILE_HEVC_MAIN;
|
||||||
|
D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC hevcLvl = { D3D12_VIDEO_ENCODER_LEVELS_HEVC_62, D3D12_VIDEO_ENCODER_TIER_HEVC_HIGH };
|
||||||
|
D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE_HEVC hevcGop = { 1, 0, 0 };
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC hevcConfig = {};
|
||||||
switch (argTargetCodec) {
|
switch (argTargetCodec) {
|
||||||
case D3D12_VIDEO_ENCODER_CODEC_H264:
|
case D3D12_VIDEO_ENCODER_CODEC_H264:
|
||||||
{
|
{
|
||||||
|
// assert(codecSupport.pH264Support); // Fill this in caller if ever used
|
||||||
capEncoderSupportData.SuggestedProfile.pH264Profile = &h264prof;
|
capEncoderSupportData.SuggestedProfile.pH264Profile = &h264prof;
|
||||||
capEncoderSupportData.SuggestedProfile.DataSize = sizeof(h264prof);
|
capEncoderSupportData.SuggestedProfile.DataSize = sizeof(h264prof);
|
||||||
capEncoderSupportData.SuggestedLevel.pH264LevelSetting = &h264lvl;
|
capEncoderSupportData.SuggestedLevel.pH264LevelSetting = &h264lvl;
|
||||||
|
|
@ -368,6 +425,29 @@ d3d12_video_encode_max_supported_slices(const D3D12_VIDEO_ENCODER_CODEC &argTarg
|
||||||
capEncoderSupportData.CodecConfiguration.pH264Config = &h264Config;
|
capEncoderSupportData.CodecConfiguration.pH264Config = &h264Config;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case D3D12_VIDEO_ENCODER_CODEC_HEVC:
|
||||||
|
{
|
||||||
|
/* Only read from codecSupport.pHEVCSupport in this case (union of pointers definition) */
|
||||||
|
assert(codecSupport.pHEVCSupport);
|
||||||
|
hevcConfig = {
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_NONE,
|
||||||
|
codecSupport.pHEVCSupport->MinLumaCodingUnitSize,
|
||||||
|
codecSupport.pHEVCSupport->MaxLumaCodingUnitSize,
|
||||||
|
codecSupport.pHEVCSupport->MinLumaTransformUnitSize,
|
||||||
|
codecSupport.pHEVCSupport->MaxLumaTransformUnitSize,
|
||||||
|
codecSupport.pHEVCSupport->max_transform_hierarchy_depth_inter,
|
||||||
|
codecSupport.pHEVCSupport->max_transform_hierarchy_depth_intra,
|
||||||
|
};
|
||||||
|
capEncoderSupportData.SuggestedProfile.pHEVCProfile = &hevcprof;
|
||||||
|
capEncoderSupportData.SuggestedProfile.DataSize = sizeof(hevcprof);
|
||||||
|
capEncoderSupportData.SuggestedLevel.pHEVCLevelSetting = &hevcLvl;
|
||||||
|
capEncoderSupportData.SuggestedLevel.DataSize = sizeof(hevcLvl);
|
||||||
|
capEncoderSupportData.CodecGopSequence.pHEVCGroupOfPictures = &hevcGop;
|
||||||
|
capEncoderSupportData.CodecGopSequence.DataSize = sizeof(hevcGop);
|
||||||
|
capEncoderSupportData.CodecConfiguration.DataSize = sizeof(hevcConfig);
|
||||||
|
capEncoderSupportData.CodecConfiguration.pHEVCConfig = &hevcConfig;
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
unreachable("Unsupported D3D12_VIDEO_ENCODER_CODEC");
|
unreachable("Unsupported D3D12_VIDEO_ENCODER_CODEC");
|
||||||
|
|
@ -394,6 +474,86 @@ d3d12_video_encode_max_supported_slices(const D3D12_VIDEO_ENCODER_CODEC &argTarg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC
|
||||||
|
static d3d12_video_encode_get_hevc_codec_support ( const D3D12_VIDEO_ENCODER_CODEC &argCodec,
|
||||||
|
const D3D12_VIDEO_ENCODER_PROFILE_DESC &argTargetProfile,
|
||||||
|
ID3D12VideoDevice3 *pD3D12VideoDevice)
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr unsigned c_hevcConfigurationSets = 5u;
|
||||||
|
const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC hevcConfigurationSets[c_hevcConfigurationSets] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_32x32,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32,
|
||||||
|
3u,
|
||||||
|
3u,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_32x32,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32,
|
||||||
|
0u,
|
||||||
|
0u,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_32x32,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32,
|
||||||
|
2u,
|
||||||
|
2u,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_64x64,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32,
|
||||||
|
2u,
|
||||||
|
2u,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_64x64,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4,
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32,
|
||||||
|
4u,
|
||||||
|
4u,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC hevcCodecCaps = { };
|
||||||
|
D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT capCodecConfigData = { };
|
||||||
|
capCodecConfigData.NodeIndex = 0;
|
||||||
|
capCodecConfigData.Codec = D3D12_VIDEO_ENCODER_CODEC_HEVC;
|
||||||
|
capCodecConfigData.Profile = argTargetProfile;
|
||||||
|
capCodecConfigData.CodecSupportLimits.pHEVCSupport = &hevcCodecCaps;
|
||||||
|
capCodecConfigData.CodecSupportLimits.DataSize = sizeof(hevcCodecCaps);
|
||||||
|
|
||||||
|
for (auto hevc_config : hevcConfigurationSets) {
|
||||||
|
hevcCodecCaps = hevc_config;
|
||||||
|
if(SUCCEEDED(pD3D12VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT, &capCodecConfigData, sizeof(capCodecConfigData))
|
||||||
|
&& capCodecConfigData.IsSupported)) {
|
||||||
|
hevc_config.SupportFlags = hevcCodecCaps.SupportFlags;
|
||||||
|
return hevc_config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we reach this point, the underlying HW/Driver might need a new configuration
|
||||||
|
added to the table and be iterated above */
|
||||||
|
unreachable("D3D12: Couldn't find HEVC supported configuration arguments.");
|
||||||
|
return hevcCodecCaps;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
d3d12_has_video_encode_support(struct pipe_screen *pscreen,
|
d3d12_has_video_encode_support(struct pipe_screen *pscreen,
|
||||||
enum pipe_video_profile profile,
|
enum pipe_video_profile profile,
|
||||||
|
|
@ -401,7 +561,8 @@ d3d12_has_video_encode_support(struct pipe_screen *pscreen,
|
||||||
D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC &maxRes,
|
D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC &maxRes,
|
||||||
uint32_t &maxSlices,
|
uint32_t &maxSlices,
|
||||||
uint32_t &supportedSliceStructures,
|
uint32_t &supportedSliceStructures,
|
||||||
uint32_t &maxReferencesPerFrame)
|
uint32_t &maxReferencesPerFrame,
|
||||||
|
struct d3d12_encode_codec_support& codecSupport)
|
||||||
{
|
{
|
||||||
ComPtr<ID3D12VideoDevice3> spD3D12VideoDevice;
|
ComPtr<ID3D12VideoDevice3> spD3D12VideoDevice;
|
||||||
struct d3d12_screen *pD3D12Screen = (struct d3d12_screen *) pscreen;
|
struct d3d12_screen *pD3D12Screen = (struct d3d12_screen *) pscreen;
|
||||||
|
|
@ -416,7 +577,7 @@ d3d12_has_video_encode_support(struct pipe_screen *pscreen,
|
||||||
sizeof(VideoFeatureAreaSupport)))) {
|
sizeof(VideoFeatureAreaSupport)))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT d3d12_codec_support = { };
|
||||||
bool supportsProfile = false;
|
bool supportsProfile = false;
|
||||||
switch (profile) {
|
switch (profile) {
|
||||||
case PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE:
|
case PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE:
|
||||||
|
|
@ -458,18 +619,174 @@ d3d12_has_video_encode_support(struct pipe_screen *pscreen,
|
||||||
maxRes,
|
maxRes,
|
||||||
encodeFormat,
|
encodeFormat,
|
||||||
maxSlices,
|
maxSlices,
|
||||||
spD3D12VideoDevice.Get());
|
spD3D12VideoDevice.Get(),
|
||||||
|
d3d12_codec_support);
|
||||||
|
|
||||||
|
D3D12_VIDEO_ENCODER_PROFILE_DESC profile;
|
||||||
|
profile.pH264Profile = &profH264;
|
||||||
|
profile.DataSize = sizeof(profH264);
|
||||||
|
D3D12_VIDEO_ENCODER_LEVEL_SETTING level;
|
||||||
|
level.pH264LevelSetting = &maxLvlSettingH264;
|
||||||
|
level.DataSize = sizeof(maxLvlSettingH264);
|
||||||
supportedSliceStructures = d3d12_video_encode_supported_slice_structures(codecDesc,
|
supportedSliceStructures = d3d12_video_encode_supported_slice_structures(codecDesc,
|
||||||
profH264,
|
profile,
|
||||||
maxLvlSettingH264,
|
level,
|
||||||
spD3D12VideoDevice.Get());
|
spD3D12VideoDevice.Get());
|
||||||
maxReferencesPerFrame =
|
maxReferencesPerFrame =
|
||||||
d3d12_video_encode_supported_references_per_frame_structures(codecDesc,
|
d3d12_video_encode_supported_references_per_frame_structures(codecDesc,
|
||||||
profH264,
|
profile,
|
||||||
maxLvlSettingH264,
|
|
||||||
spD3D12VideoDevice.Get());
|
spD3D12VideoDevice.Get());
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case PIPE_VIDEO_PROFILE_HEVC_MAIN:
|
||||||
|
case PIPE_VIDEO_PROFILE_HEVC_MAIN_10:
|
||||||
|
{
|
||||||
|
supportsProfile = true;
|
||||||
|
D3D12_VIDEO_ENCODER_PROFILE_DESC profDesc = {};
|
||||||
|
D3D12_VIDEO_ENCODER_PROFILE_HEVC profHEVC =
|
||||||
|
d3d12_video_encoder_convert_profile_to_d3d12_enc_profile_hevc(profile);
|
||||||
|
profDesc.DataSize = sizeof(profHEVC);
|
||||||
|
profDesc.pHEVCProfile = &profHEVC;
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC codecDesc = d3d12_video_encoder_convert_codec_to_d3d12_enc_codec(profile);
|
||||||
|
D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC minLvlSettingHEVC = { };
|
||||||
|
D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC maxLvlSettingHEVC = { };
|
||||||
|
D3D12_VIDEO_ENCODER_LEVEL_SETTING minLvl = {};
|
||||||
|
D3D12_VIDEO_ENCODER_LEVEL_SETTING maxLvl = {};
|
||||||
|
minLvl.pHEVCLevelSetting = &minLvlSettingHEVC;
|
||||||
|
minLvl.DataSize = sizeof(minLvlSettingHEVC);
|
||||||
|
maxLvl.pHEVCLevelSetting = &maxLvlSettingHEVC;
|
||||||
|
maxLvl.DataSize = sizeof(maxLvlSettingHEVC);
|
||||||
|
if (d3d12_video_encode_max_supported_level_for_profile(codecDesc,
|
||||||
|
profDesc,
|
||||||
|
minLvl,
|
||||||
|
maxLvl,
|
||||||
|
spD3D12VideoDevice.Get())) {
|
||||||
|
d3d12_video_encoder_convert_from_d3d12_level_hevc(maxLvlSettingHEVC.Level, maxLvlSpec);
|
||||||
|
supportsProfile = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportsProfile) {
|
||||||
|
|
||||||
|
D3D12_VIDEO_ENCODER_PROFILE_DESC d3d12_profile;
|
||||||
|
d3d12_profile.pHEVCProfile = &profHEVC;
|
||||||
|
d3d12_profile.DataSize = sizeof(profHEVC);
|
||||||
|
D3D12_VIDEO_ENCODER_LEVEL_SETTING level;
|
||||||
|
level.pHEVCLevelSetting = &maxLvlSettingHEVC;
|
||||||
|
level.DataSize = sizeof(maxLvlSettingHEVC);
|
||||||
|
supportedSliceStructures = d3d12_video_encode_supported_slice_structures(codecDesc,
|
||||||
|
d3d12_profile,
|
||||||
|
level,
|
||||||
|
spD3D12VideoDevice.Get());
|
||||||
|
|
||||||
|
maxReferencesPerFrame =
|
||||||
|
d3d12_video_encode_supported_references_per_frame_structures(codecDesc,
|
||||||
|
d3d12_profile,
|
||||||
|
spD3D12VideoDevice.Get());
|
||||||
|
|
||||||
|
codecSupport.hevc_support.d3d12_caps = d3d12_video_encode_get_hevc_codec_support(codecDesc,
|
||||||
|
profDesc,
|
||||||
|
spD3D12VideoDevice.Get());
|
||||||
|
d3d12_codec_support.DataSize = sizeof(codecSupport.hevc_support.d3d12_caps);
|
||||||
|
d3d12_codec_support.pHEVCSupport = &codecSupport.hevc_support.d3d12_caps;
|
||||||
|
|
||||||
|
/* get_video_param sets pipe_features.bits.config_supported = 1
|
||||||
|
to distinguish between supported cap with all bits off and unsupported by driver
|
||||||
|
with value = 0
|
||||||
|
*/
|
||||||
|
codecSupport.hevc_support.hevc_block_sizes.bits.config_supported = 1;
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.config_supported = 1;
|
||||||
|
|
||||||
|
// Fill codecSupport.hevc_support
|
||||||
|
|
||||||
|
uint8_t minCuSize = d3d12_video_encoder_convert_12cusize_to_pixel_size_hevc(codecSupport.hevc_support.d3d12_caps.MinLumaCodingUnitSize);
|
||||||
|
uint8_t maxCuSize = d3d12_video_encoder_convert_12cusize_to_pixel_size_hevc(codecSupport.hevc_support.d3d12_caps.MaxLumaCodingUnitSize);
|
||||||
|
uint8_t MinCbLog2SizeY = std::log2(minCuSize);
|
||||||
|
uint8_t CtbLog2SizeY = std::log2(maxCuSize);
|
||||||
|
uint8_t minTuSize = d3d12_video_encoder_convert_12tusize_to_pixel_size_hevc(codecSupport.hevc_support.d3d12_caps.MinLumaTransformUnitSize);
|
||||||
|
uint8_t maxTuSize = d3d12_video_encoder_convert_12tusize_to_pixel_size_hevc(codecSupport.hevc_support.d3d12_caps.MaxLumaTransformUnitSize);
|
||||||
|
|
||||||
|
codecSupport.hevc_support.hevc_block_sizes.bits.log2_max_coding_tree_block_size_minus3
|
||||||
|
= static_cast<uint8_t>(CtbLog2SizeY - 3);
|
||||||
|
codecSupport.hevc_support.hevc_block_sizes.bits.log2_min_coding_tree_block_size_minus3
|
||||||
|
= static_cast<uint8_t>(CtbLog2SizeY - 3);
|
||||||
|
|
||||||
|
codecSupport.hevc_support.hevc_block_sizes.bits.log2_min_luma_coding_block_size_minus3
|
||||||
|
= static_cast<uint8_t>(MinCbLog2SizeY - 3);
|
||||||
|
|
||||||
|
codecSupport.hevc_support.hevc_block_sizes.bits.log2_max_luma_transform_block_size_minus2
|
||||||
|
= static_cast<uint8_t>(std::log2(maxTuSize) - 2);
|
||||||
|
|
||||||
|
codecSupport.hevc_support.hevc_block_sizes.bits.log2_min_luma_transform_block_size_minus2
|
||||||
|
= static_cast<uint8_t>(std::log2(minTuSize) - 2);
|
||||||
|
|
||||||
|
codecSupport.hevc_support.hevc_block_sizes.bits.max_max_transform_hierarchy_depth_inter
|
||||||
|
= codecSupport.hevc_support.d3d12_caps.max_transform_hierarchy_depth_inter;
|
||||||
|
|
||||||
|
codecSupport.hevc_support.hevc_block_sizes.bits.min_max_transform_hierarchy_depth_inter
|
||||||
|
= codecSupport.hevc_support.d3d12_caps.max_transform_hierarchy_depth_inter;
|
||||||
|
|
||||||
|
codecSupport.hevc_support.hevc_block_sizes.bits.max_max_transform_hierarchy_depth_intra
|
||||||
|
= codecSupport.hevc_support.d3d12_caps.max_transform_hierarchy_depth_intra;
|
||||||
|
|
||||||
|
codecSupport.hevc_support.hevc_block_sizes.bits.min_max_transform_hierarchy_depth_intra
|
||||||
|
= codecSupport.hevc_support.d3d12_caps.max_transform_hierarchy_depth_intra;
|
||||||
|
|
||||||
|
codecSupport.hevc_support.hevc_block_sizes.bits.log2_max_pcm_coding_block_size_minus3 = 0; // No PCM Supported
|
||||||
|
codecSupport.hevc_support.hevc_block_sizes.bits.log2_min_pcm_coding_block_size_minus3 = 0; // No PCM Supported
|
||||||
|
|
||||||
|
// Feature flags
|
||||||
|
|
||||||
|
uint32_t ref_l0 = maxReferencesPerFrame & 0xffff;
|
||||||
|
uint32_t ref_l1 = maxReferencesPerFrame >> 16 & 0xffff;
|
||||||
|
|
||||||
|
codecSupport.hevc_support.prediction_direction = PIPE_H265_PRED_DIRECTION_ALL;
|
||||||
|
if(ref_l0)
|
||||||
|
codecSupport.hevc_support.prediction_direction |= PIPE_H265_PRED_DIRECTION_PREVIOUS;
|
||||||
|
if(ref_l1)
|
||||||
|
codecSupport.hevc_support.prediction_direction |= PIPE_H265_PRED_DIRECTION_FUTURE;
|
||||||
|
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.separate_colour_planes = PIPE_H265_ENC_FEATURE_NOT_SUPPORTED;
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.scaling_lists = PIPE_H265_ENC_FEATURE_NOT_SUPPORTED;
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.pcm = PIPE_H265_ENC_FEATURE_NOT_SUPPORTED;
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.temporal_mvp = PIPE_H265_ENC_FEATURE_NOT_SUPPORTED;
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.strong_intra_smoothing = PIPE_H265_ENC_FEATURE_NOT_SUPPORTED;
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.dependent_slices = PIPE_H265_ENC_FEATURE_NOT_SUPPORTED;
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.sign_data_hiding = PIPE_H265_ENC_FEATURE_NOT_SUPPORTED;
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.weighted_prediction = PIPE_H265_ENC_FEATURE_NOT_SUPPORTED;
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.transquant_bypass = PIPE_H265_ENC_FEATURE_NOT_SUPPORTED;
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.deblocking_filter_disable = PIPE_H265_ENC_FEATURE_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
/* cu_qp_delta always required to be 1 in https://github.com/microsoft/DirectX-Specs/blob/master/d3d/D3D12VideoEncoding.md */
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.cu_qp_delta = (PIPE_H265_ENC_FEATURE_SUPPORTED | PIPE_H265_ENC_FEATURE_REQUIRED);
|
||||||
|
|
||||||
|
if ((codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_P_FRAMES_IMPLEMENTED_AS_LOW_DELAY_B_FRAMES) != 0)
|
||||||
|
codecSupport.hevc_support.prediction_direction |= PIPE_H265_PRED_DIRECTION_BI_NOT_EMPTY;
|
||||||
|
|
||||||
|
if ((codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_ASYMETRIC_MOTION_PARTITION_SUPPORT) != 0)
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.amp = PIPE_H265_ENC_FEATURE_SUPPORTED;
|
||||||
|
|
||||||
|
if ((codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_ASYMETRIC_MOTION_PARTITION_REQUIRED) != 0)
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.amp = (PIPE_H265_ENC_FEATURE_SUPPORTED | PIPE_H265_ENC_FEATURE_REQUIRED);
|
||||||
|
|
||||||
|
if ((codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_SAO_FILTER_SUPPORT) != 0)
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.sao = PIPE_H265_ENC_FEATURE_SUPPORTED;
|
||||||
|
|
||||||
|
if ((codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_CONSTRAINED_INTRAPREDICTION_SUPPORT) != 0)
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.constrained_intra_pred = PIPE_H265_ENC_FEATURE_SUPPORTED;
|
||||||
|
if ((codecSupport.hevc_support.d3d12_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_TRANSFORM_SKIP_SUPPORT) != 0)
|
||||||
|
codecSupport.hevc_support.hevc_features.bits.transform_skip = PIPE_H265_ENC_FEATURE_SUPPORTED;
|
||||||
|
|
||||||
|
DXGI_FORMAT encodeFormat = d3d12_convert_pipe_video_profile_to_dxgi_format(profile);
|
||||||
|
supportsProfile = supportsProfile &&
|
||||||
|
d3d12_video_encode_max_supported_resolution(codecDesc, maxRes, spD3D12VideoDevice.Get());
|
||||||
|
supportsProfile = supportsProfile && d3d12_video_encode_max_supported_slices(codecDesc,
|
||||||
|
maxRes,
|
||||||
|
encodeFormat,
|
||||||
|
maxSlices,
|
||||||
|
spD3D12VideoDevice.Get(),
|
||||||
|
d3d12_codec_support);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
supportsProfile = false;
|
supportsProfile = false;
|
||||||
}
|
}
|
||||||
|
|
@ -716,6 +1033,8 @@ d3d12_screen_get_video_param_encode(struct pipe_screen *pscreen,
|
||||||
uint32_t maxSlices = 0u;
|
uint32_t maxSlices = 0u;
|
||||||
uint32_t supportedSliceStructures = 0u;
|
uint32_t supportedSliceStructures = 0u;
|
||||||
uint32_t maxReferencesPerFrame = 0u;
|
uint32_t maxReferencesPerFrame = 0u;
|
||||||
|
struct d3d12_encode_codec_support codec_specific_support;
|
||||||
|
memset(&codec_specific_support, 0, sizeof(codec_specific_support));
|
||||||
switch (param) {
|
switch (param) {
|
||||||
case PIPE_VIDEO_CAP_NPOT_TEXTURES:
|
case PIPE_VIDEO_CAP_NPOT_TEXTURES:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -726,6 +1045,9 @@ d3d12_screen_get_video_param_encode(struct pipe_screen *pscreen,
|
||||||
case PIPE_VIDEO_CAP_ENC_MAX_SLICES_PER_FRAME:
|
case PIPE_VIDEO_CAP_ENC_MAX_SLICES_PER_FRAME:
|
||||||
case PIPE_VIDEO_CAP_ENC_SLICES_STRUCTURE:
|
case PIPE_VIDEO_CAP_ENC_SLICES_STRUCTURE:
|
||||||
case PIPE_VIDEO_CAP_ENC_MAX_REFERENCES_PER_FRAME:
|
case PIPE_VIDEO_CAP_ENC_MAX_REFERENCES_PER_FRAME:
|
||||||
|
case PIPE_VIDEO_CAP_ENC_HEVC_FEATURE_FLAGS:
|
||||||
|
case PIPE_VIDEO_CAP_ENC_HEVC_BLOCK_SIZES:
|
||||||
|
case PIPE_VIDEO_CAP_ENC_HEVC_PREDICTION_DIRECTION:
|
||||||
{
|
{
|
||||||
if (d3d12_has_video_encode_support(pscreen,
|
if (d3d12_has_video_encode_support(pscreen,
|
||||||
profile,
|
profile,
|
||||||
|
|
@ -733,7 +1055,13 @@ d3d12_screen_get_video_param_encode(struct pipe_screen *pscreen,
|
||||||
maxResEncode,
|
maxResEncode,
|
||||||
maxSlices,
|
maxSlices,
|
||||||
supportedSliceStructures,
|
supportedSliceStructures,
|
||||||
maxReferencesPerFrame)) {
|
maxReferencesPerFrame,
|
||||||
|
codec_specific_support)) {
|
||||||
|
|
||||||
|
DXGI_FORMAT format = d3d12_convert_pipe_video_profile_to_dxgi_format(profile);
|
||||||
|
auto pipeFmt = d3d12_get_pipe_format(format);
|
||||||
|
bool formatSupported = pscreen->is_video_format_supported(pscreen, pipeFmt, profile, entrypoint);
|
||||||
|
if (formatSupported) {
|
||||||
if (param == PIPE_VIDEO_CAP_MAX_WIDTH) {
|
if (param == PIPE_VIDEO_CAP_MAX_WIDTH) {
|
||||||
return maxResEncode.Width;
|
return maxResEncode.Width;
|
||||||
} else if (param == PIPE_VIDEO_CAP_MAX_HEIGHT) {
|
} else if (param == PIPE_VIDEO_CAP_MAX_HEIGHT) {
|
||||||
|
|
@ -748,6 +1076,21 @@ d3d12_screen_get_video_param_encode(struct pipe_screen *pscreen,
|
||||||
return supportedSliceStructures;
|
return supportedSliceStructures;
|
||||||
} else if (param == PIPE_VIDEO_CAP_ENC_MAX_REFERENCES_PER_FRAME) {
|
} else if (param == PIPE_VIDEO_CAP_ENC_MAX_REFERENCES_PER_FRAME) {
|
||||||
return maxReferencesPerFrame;
|
return maxReferencesPerFrame;
|
||||||
|
} else if (param == PIPE_VIDEO_CAP_ENC_HEVC_FEATURE_FLAGS) {
|
||||||
|
/* get_video_param sets hevc_features.bits.config_supported = 1
|
||||||
|
to distinguish between supported cap with all bits off and unsupported by driver
|
||||||
|
with value = 0
|
||||||
|
*/
|
||||||
|
return codec_specific_support.hevc_support.hevc_features.value;
|
||||||
|
} else if (param == PIPE_VIDEO_CAP_ENC_HEVC_BLOCK_SIZES) {
|
||||||
|
/* get_video_param sets hevc_block_sizes.bits.config_supported = 1
|
||||||
|
to distinguish between supported cap with all bits off and unsupported by driver
|
||||||
|
with value = 0
|
||||||
|
*/
|
||||||
|
return codec_specific_support.hevc_support.hevc_block_sizes.value;
|
||||||
|
} else if (param == PIPE_VIDEO_CAP_ENC_HEVC_PREDICTION_DIRECTION) {
|
||||||
|
return codec_specific_support.hevc_support.prediction_direction;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@ enum d3d12_video_decode_profile_type
|
||||||
{
|
{
|
||||||
d3d12_video_decode_profile_type_none,
|
d3d12_video_decode_profile_type_none,
|
||||||
d3d12_video_decode_profile_type_h264,
|
d3d12_video_decode_profile_type_h264,
|
||||||
|
d3d12_video_decode_profile_type_hevc,
|
||||||
d3d12_video_decode_profile_type_max_valid
|
d3d12_video_decode_profile_type_max_valid
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -125,11 +126,27 @@ void
|
||||||
d3d12_video_encoder_convert_from_d3d12_level_h264(D3D12_VIDEO_ENCODER_LEVELS_H264 level12,
|
d3d12_video_encoder_convert_from_d3d12_level_h264(D3D12_VIDEO_ENCODER_LEVELS_H264 level12,
|
||||||
uint32_t & specLevel,
|
uint32_t & specLevel,
|
||||||
uint32_t & constraint_set3_flag);
|
uint32_t & constraint_set3_flag);
|
||||||
|
void
|
||||||
|
d3d12_video_encoder_convert_from_d3d12_level_hevc(D3D12_VIDEO_ENCODER_LEVELS_HEVC level12,
|
||||||
|
uint32_t & specLevel);
|
||||||
D3D12_VIDEO_ENCODER_PROFILE_H264
|
D3D12_VIDEO_ENCODER_PROFILE_H264
|
||||||
d3d12_video_encoder_convert_profile_to_d3d12_enc_profile_h264(enum pipe_video_profile profile);
|
d3d12_video_encoder_convert_profile_to_d3d12_enc_profile_h264(enum pipe_video_profile profile);
|
||||||
|
D3D12_VIDEO_ENCODER_PROFILE_HEVC
|
||||||
|
d3d12_video_encoder_convert_profile_to_d3d12_enc_profile_hevc(enum pipe_video_profile profile);
|
||||||
D3D12_VIDEO_ENCODER_CODEC
|
D3D12_VIDEO_ENCODER_CODEC
|
||||||
d3d12_video_encoder_convert_codec_to_d3d12_enc_codec(enum pipe_video_profile profile);
|
d3d12_video_encoder_convert_codec_to_d3d12_enc_codec(enum pipe_video_profile profile);
|
||||||
GUID
|
GUID
|
||||||
d3d12_video_decoder_convert_pipe_video_profile_to_d3d12_profile(enum pipe_video_profile profile);
|
d3d12_video_decoder_convert_pipe_video_profile_to_d3d12_profile(enum pipe_video_profile profile);
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE
|
||||||
|
d3d12_video_encoder_convert_pixel_size_hevc_to_12tusize(const uint32_t& TUSize);
|
||||||
|
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE
|
||||||
|
d3d12_video_encoder_convert_pixel_size_hevc_to_12cusize(const uint32_t& cuSize);
|
||||||
|
uint8_t
|
||||||
|
d3d12_video_encoder_convert_12cusize_to_pixel_size_hevc(const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE& cuSize);
|
||||||
|
uint8_t
|
||||||
|
d3d12_video_encoder_convert_12tusize_to_pixel_size_hevc(const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE& TUSize);
|
||||||
|
|
||||||
|
DEFINE_ENUM_FLAG_OPERATORS(pipe_h265_enc_feature);
|
||||||
|
DEFINE_ENUM_FLAG_OPERATORS(pipe_h265_enc_pred_direction);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,11 @@ if with_gallium_d3d12_video
|
||||||
'd3d12_video_array_of_textures_dpb_manager.cpp',
|
'd3d12_video_array_of_textures_dpb_manager.cpp',
|
||||||
'd3d12_video_screen.cpp',
|
'd3d12_video_screen.cpp',
|
||||||
'd3d12_video_proc.cpp',
|
'd3d12_video_proc.cpp',
|
||||||
|
'd3d12_video_dec_hevc.cpp',
|
||||||
|
'd3d12_video_enc_hevc.cpp',
|
||||||
|
'd3d12_video_encoder_bitstream_builder_hevc.cpp',
|
||||||
|
'd3d12_video_encoder_nalu_writer_hevc.cpp',
|
||||||
|
'd3d12_video_encoder_references_manager_hevc.cpp',
|
||||||
]
|
]
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
@ -80,5 +85,5 @@ libd3d12 = static_library(
|
||||||
|
|
||||||
driver_d3d12 = declare_dependency(
|
driver_d3d12 = declare_dependency(
|
||||||
compile_args : '-DGALLIUM_D3D12',
|
compile_args : '-DGALLIUM_D3D12',
|
||||||
link_with : [libd3d12],
|
link_with : [libd3d12, libgalliumvl],
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ libgallium_wgl = shared_library(
|
||||||
],
|
],
|
||||||
link_whole : [libwgl],
|
link_whole : [libwgl],
|
||||||
link_with : [
|
link_with : [
|
||||||
libgallium, libglsl, libmesa, libwsgdi, libglapi_static, libglapi
|
libgallium, libglsl, libmesa, libwsgdi, libglapi_static, libglapi, libgalliumvl
|
||||||
],
|
],
|
||||||
dependencies : [
|
dependencies : [
|
||||||
dep_ws2_32, idep_nir, idep_mesautil, driver_swrast,
|
dep_ws2_32, idep_nir, idep_mesautil, driver_swrast,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue