/* * 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. */ #pragma once #define UNICODE #include "util/u_video.h" #include "vl/vl_winsys.h" #include "pipe_headers.h" #include #include #include "idl/dx12enchmft.h" #include #include #include #include #include #include #include #include #include // For IMFD3D12SynchronizationObjectCommands #include #include // For IMFRealTimeClientEx, IMFShutdown #include // For IMFActivate, IMFObjectInformation, IMFMediaEventGenerator #include // For IMFTransform #include #include // For ICodecAPI #include #include #include #include "macros.h" #include "mfd3dmanager.h" #include #include #include #include #include "context.h" #include "encoder_capabilities.h" #include "reference_frames_tracker.h" using namespace concurrency; using namespace Microsoft::WRL; using Microsoft::WRL::ComPtr; #define ENCODE_WITH_TWO_PASS_LOWEST_RES 1 #define NUM_INPUT_TYPES 3 extern MFT_REGISTER_TYPE_INFO rgOutputInfo; extern MFT_REGISTER_TYPE_INFO rgInputInfo[NUM_INPUT_TYPES]; extern const wchar_t *g_pMFTFriendlyName; #ifndef FOURCC_H264 #define FOURCC_H264 MAKEFOURCC( 'H', '2', '6', '4' ) #endif #ifndef FOURCC_H265 #define FOURCC_H265 MAKEFOURCC( 'H', '2', '6', '5' ) #endif #ifndef FOURCC_HEVC #define FOURCC_HEVC MAKEFOURCC( 'H', 'E', 'V', 'C' ) #endif #ifndef FOURCC_avc1 #define FOURCC_avc1 MAKEFOURCC( 'a', 'v', 'c', '1' ) #endif #ifndef FOURCC_AV01 #define FOURCC_AV01 MAKEFOURCC( 'A', 'V', '0', '1' ) #endif #ifndef FOURCC_NV12 #define FOURCC_NV12 MAKEFOURCC( 'N', 'V', '1', '2' ) #endif #ifndef FOURCC_P010 #define FOURCC_P010 MAKEFOURCC( 'P', '0', '1', '0' ) #endif #ifndef FOURCC_AYUV #define FOURCC_AYUV MAKEFOURCC( 'A', 'Y', 'U', 'V' ) #endif #ifndef FOURCC_Y210 #define FOURCC_Y210 MAKEFOURCC( 'Y', '2', '1', '0' ) #endif #ifndef FOURCC_Y410 #define FOURCC_Y410 MAKEFOURCC( 'Y', '4', '1', '0' ) #endif #ifndef FOURCC_YUY2 #define FOURCC_YUY2 MAKEFOURCC( 'Y', 'U', 'Y', '2' ) #endif #ifdef SUPPORT_BFRAMES #define HMFT_MAX_BFRAMES 1 #else #define HMFT_MAX_BFRAMES 0 #endif #define HMFT_MIN_WIDTH 34 #define HMFT_MIN_HEIGHT 34 #define HMFT_MIN_BITS_PER_SLICE 256 #define AVC_MAX_QP 51 #define AVC_DEFAULT_QP 26 #define HMFT_MAX_TEMPORAL_LAYERS 2 constexpr const eAVEncH265VProfile eAVEncH265VProfile_Main_422_8 = (eAVEncH265VProfile) 23; typedef enum tVideoFormat { VIDFMT_COMPONENT = 0, VIDFMT_PAL, VIDFMT_NTSC, VIDFMT_SECAM, VIDFMT_MAC, VIDFMT_UNSPECIFIED, VIDFMT_MAX } VideoFormat; typedef enum tColorPrimary { COLORPRIM_BT709_5 = 0, COLORPRIM_UNSPECIFIED, COLORPRIM_BT470_6M, COLORPRIM_BT470_6BG, COLORPRIM_SMPTE_170M, COLORPRIM_SMPTE_240M, COLORPRIM_FILM, COLORPRIM_MAX } ColorPrimary; typedef enum tColorTransfer { COLORXFER_BT709_5 = 0, COLORXFER_UNSPECIFIED, COLORXFER_BT470_6M, COLORXFER_BT470_6BG, COLORXFER_SMPTE_170M, COLORXFER_SMPTE_240M, COLORXFER_LINEAR, COLORXFER_LOG100, COLORXFER_LOG316, COLORXFER_IEC, COLORXFER_BT1361, COLORXFER_MAX } ColorTransfer; typedef enum tColorMatrix { COLORMATRIX_GBR = 0, COLORMATRIX_BT709_5, COLORMATRIX_UNSPECIFIED, COLORMATRIX_FCC47, COLORMATRIX_BT470_6BG, COLORMATRIX_SMPTE170M, COLORMATRIX_SMPTE240M, COLORMATRIX_YCgCo, COLORMATRIX_MAX } ColorMatrix; typedef struct tSampleAspectRatio { unsigned short usWidth; unsigned short usHeight; } SampleAspectRatio; typedef struct tVideoSignalType { VideoFormat eVideoFormat; BOOL bVideoFullRangeFlag; BOOL bColorInfoPresent; ColorPrimary eColorPrimary; ColorTransfer eColorTransfer; ColorMatrix eColorMatrix; } VideoSignalType; // VUI typedef struct tVUInfo { BOOL bEnableSAR; SampleAspectRatio stSARInfo; BOOL bEnableVST; VideoSignalType stVidSigType; } VUInfo; // Slice control modes supported by the encoder. typedef enum tSliceControlMode { SLICE_CONTROL_MODE_MB = 0, SLICE_CONTROL_MODE_BITS = 1, SLICE_CONTROL_MODE_MB_ROW = 2, SLICE_CONTROL_MODE_MAX } SliceControlMode; // DirtyRect modes supported by the encoder. typedef enum tDirtyRectMode { DIRTY_RECT_MODE_OFF = 0, DIRTY_RECT_MODE_USE_FRAME_NUM = 1, DIRTY_RECT_MODE_IGNORE_FRAME_NUM = 2, DIRTY_RECT_MODE_MAX } DirtyRectMode; // Gradual intra refresh modes supported by the encoder. typedef enum IntraRefreshMode { HMFT_INTRA_REFRESH_MODE_NONE = 0, HMFT_INTRA_REFRESH_MODE_PERIODIC = 1, HMFT_INTRA_REFRESH_MODE_CONTINUAL = 2, HMFT_INTRA_REFRESH_MODE_MAX } IntraRefreshMode; #ifndef CODECAPI_AVEncVideoD3D12ReconstructedPictureOutputMode // MFSampleExtension_VideoEncodeD3D12ReconstructedPicture {3E8A1B7F-5C92-4D6E-B834-F0A729E65C48} // Type: IMFMediaBuffer // The reconstructed picture data of an encoded video frame from a D3D12-based MFT (Experimental). DEFINE_GUID( MFSampleExtension_VideoEncodeD3D12ReconstructedPicture, 0x3e8a1b7f, 0x5c92, 0x4d6e, 0xb8, 0x34, 0xf0, 0xa7, 0x29, 0xe6, 0x5c, 0x48 ); enum eAVEncVideoD3D12ReconstructedPictureOutputMode { eAVEncVideoEncodeD3D12ReconstructedPictureMode_None = 0, // Does not return a D3D12 reconstructed buffer. eAVEncVideoEncodeD3D12ReconstructedPictureMode_Copy = 1, // Returns a copy of the D3D12 reconstructed buffer used by the encoder. eAVEncVideoEncodeD3D12ReconstructedPictureMode_Shared = 2 // Returns the D3D12 reconstructed buffer written by the encoder without a copy. }; // AVEncVideoD3D12ReconstructedPictureOutputMode (VT_UI4) (Experimental, Testing only) // This property controls the output of D3D12 reconstructed picture data from a D3D12-based encoder. // ulVal must be a value from the eAVEncVideoD3D12ReconstructedPictureOutputMode enumeration. DEFINE_CODECAPI_GUID( AVEncVideoD3D12ReconstructedPictureOutputMode, "4A7B2E8F-1D93-4C6A-B548-91E2F8C5A7D3", 0x4a7b2e8f, 0x1d93, 0x4c6a, 0xb5, 0x48, 0x91, 0xe2, 0xf8, 0xc5, 0xa7, 0xd3 ) #define CODECAPI_AVEncVideoD3D12ReconstructedPictureOutputMode \ DEFINE_CODECAPI_GUIDNAMED( AVEncVideoD3D12ReconstructedPictureOutputMode ) #endif #ifndef CODECAPI_AVEncVideoRateControlFramePreAnalysis // AVEncVideoRateControlFramePreAnalysis (VT_BOOL) (Experimental, Testing only) // Indicates whether to enable or disable rate control frame preanalysis // VARIANT_FALSE: disable; VARIANT_TRUE: enable DEFINE_CODECAPI_GUID( AVEncVideoRateControlFramePreAnalysis, "CF229C1D-FA9A-4BBA-9E08-269F3CF5D621", 0xcf229c1d, 0xfa9a, 0x4bba, 0x9e, 0x8, 0x26, 0x9f, 0x3c, 0xf5, 0xd6, 0x21 ) #define CODECAPI_AVEncVideoRateControlFramePreAnalysis DEFINE_CODECAPI_GUIDNAMED( AVEncVideoRateControlFramePreAnalysis ) #endif #ifndef CODECAPI_AVEncVideoRateControlFramePreAnalysisExternalReconDownscale // CODECAPI_AVEncVideoRateControlFramePreAnalysisExternalReconDownscale (VT_BOOL) (Experimental, Testing only) // Indicates whether to enable or disable external recon downscale in rate control frame preanalysis // VARIANT_FALSE: disable; VARIANT_TRUE: enable DEFINE_CODECAPI_GUID( AVEncVideoRateControlFramePreAnalysisExternalReconDownscale, "C53DEFA4-138A-4310-864F-4516661C56E7", 0xc53defa4, 0x138a, 0x4310, 0x86, 0x4f, 0x45, 0x16, 0x66, 0x1c, 0x56, 0xe7 ) #define CODECAPI_AVEncVideoRateControlFramePreAnalysisExternalReconDownscale \ DEFINE_CODECAPI_GUIDNAMED( AVEncVideoRateControlFramePreAnalysisExternalReconDownscale ) #endif #if MFT_CODEC_H264ENC #define HMFT_GUID "8994db7c-288a-4c62-a136-a3c3c2a208a8" #elif MFT_CODEC_H265ENC #define HMFT_GUID "e7ffb8eb-fa0b-4fb0-acdf-1202f663cde5" #elif MFT_CODEC_AV1ENC #define HMFT_GUID "1a6f3150-b121-4ce9-9497-50fedb3dcb70" #endif #define MFT_INPUT_QUEUE_DEPTH 8 // For low latency mode we should only need 2 if we have guarantee that the output sample is returned quickly. However, // when using mp4 sink via SinkWriter, it buffers the input sample so we will hit no resource sample and error out, choosing 11 to // be safe. #define MFT_STAT_POOL_MIN_SIZE 11 class __declspec( uuid( HMFT_GUID ) ) CDX12EncHMFT : CMFD3DManager, public RuntimeClass, IMFTransform, IMFRealTimeClientEx, ICodecAPI, IMFMediaEventGenerator, IMFShutdown> { InspectableClass( RuntimeClass_DX12Encoder_CDX12EncHMFT, BaseTrust ) protected : enum { EVENT_QUIT, EVENT_INPUT, MAX_EVENTS }; static void WINAPI xThreadProc( void *pCtx ); HANDLE m_hThread = NULL; DWORD m_dwThreadId = 0; private: ~CDX12EncHMFT(); HRESULT InitializeEncoder( pipe_video_profile VideoProfile, UINT32 Width, UINT32 Height ); void CleanupEncoder(); HRESULT CreateGOPTracker( uint32_t textureWidth, uint32_t textureHeight ); event m_eventHaveInput; // signal that the queue has data via m_eventHaveInput concurrent_queue m_EncodingQueue; // (MFT_INPUT_QUEUE_DEPTH) concurrent_queue m_OutputQueue; std::mutex m_OutputQueueLock; HRESULT SetEncodingParameters( IMFAttributes *pMFAttributes ); HRESULT GetCodecPrivateData( LPBYTE pSPSPPSData, DWORD dwSPSPPSDataLen, LPDWORD lpdwSPSPPSDataLen ); // ProcessMessage Event Handlers HRESULT OnDrain(); HRESULT OnFlush(); HRESULT ConfigureSampleAllocator(); HRESULT ConfigureBitstreamOutputSampleAttributes( IMFSample *pSample, const LPDX12EncodeContext pDX12EncodeContext, DWORD dwReceivedInput, BOOL bIsLastSlice, struct codec_unit_location_t *pCodecUnitMetadata, unsigned CodecUnitMetadataCount ); HRESULT ConfigureAsyncStatsMetadataOutputSampleAttributes( IMFSample *pSample, pipe_resource *pPipeResourcePSNRStats, pipe_resource *pPipeResourceQPMapStats, pipe_resource *pPipeResourceRCBitAllocMapStats, pipe_resource *pPipeResourceSATDMapStats, ComPtr &pResolveStatsCompletionFence, UINT64 ResolveStatsCompletionFenceValue, pipe_resource *pPipeResourceReconstructedPicture, UINT PipeResourceReconstructedPictureSubresource, ComPtr &spReconstructedPictureCompletionFence, UINT64 ReconstructedPictureCompletionFenceValue, ID3D12CommandQueue *pSyncObjectQueue ); bool GetSliceBitstreamMetadata( LPDX12EncodeContext pDX12EncodeContext, uint32_t slice_idx, std::vector &codec_unit_metadata ); bool ProcessSliceBitstreamZeroCopy( LPDX12EncodeContext pDX12EncodeContext, uint32_t slice_idx, ComPtr &spMediaBuffer, std::vector &mfsample_codec_unit_metadata ); void FinalizeAndEmitOutputSample( LPDX12EncodeContext pDX12EncodeContext, ComPtr &spMediaBuffer, ComPtr &spOutputSample, struct codec_unit_location_t *pCodecUnitMetadata, unsigned CodecUnitMetadataCount, DWORD dwReceivedInput, BOOL bIsLastSlice, uint64_t ResolveStatsCompletionFenceValue ); HRESULT UpdateAvailableInputType(); HRESULT InternalCheckInputType( IMFMediaType *pType ); HRESULT InternalCheckOutputType( IMFMediaType *pType ); HRESULT CheckMediaType( IMFMediaType *pmt, bool bInputType ); #if MFT_CODEC_H264ENC HRESULT CheckMediaTypeLevel( IMFMediaType *pmt, int width, int height, const encoder_capabilities &encoderCapabilities, eAVEncH264VLevel *pLevel ) const; #elif MFT_CODEC_H265ENC HRESULT CheckMediaTypeLevel( IMFMediaType *pmt, int width, int height, const encoder_capabilities &encoderCapabilities, eAVEncH265VLevel *pLevel ) const; #elif MFT_CODEC_AV1ENC HRESULT CheckMediaTypeLevel( IMFMediaType *pmt, int width, int height, const encoder_capabilities &encoderCapabilities, eAVEncAV1VLevel *pLevel ) const; #endif HRESULT ValidateDirtyRects( const LPDX12EncodeContext pDX12EncodeContext, const DIRTYRECT_INFO *pDirtyRectInfo ); UINT32 GetMaxReferences( unsigned int width, unsigned int height ); HRESULT CheckShutdown(); // MFT Attributes ComPtr m_spMFAttributes; // MFT event-queue ComPtr m_spEventQueue; // input stream ComPtr m_spAvailableInputType; ComPtr m_spInputType; DWORD m_dwInputTypeStride; DWORD m_dwInputOffsetX; DWORD m_dwInputOffsetY; BOOL m_bEncodingStarted = FALSE; GUID m_InputSubType; VUInfo m_VUIInfo = {}; // output stream ComPtr m_spAvailableOutputType; ComPtr m_spOutputType; UINT32 m_uiOutputWidth = 0; UINT32 m_uiOutputHeight = 0; UINT32 m_uiOutputBitrate = 0; MFRatio m_FrameRate = { 30, 1 }; // default to 30fps MFRatio m_PixelAspectRatio = { 1, 1 }; // default to 1:1 MFNominalRange m_eNominalRange = MFNominalRange_16_235; BOOL m_bFrameCroppingFlag = FALSE; UINT32 m_uiFrameCropRightOffset = 0; UINT32 m_uiFrameCropBottomOffset = 0; BOOL m_bForceKeyFrame = FALSE; UINT32 m_uiRateControlMode = eAVEncCommonRateControlMode_CBR; BOOL m_bRateControlModeSet = FALSE; UINT32 m_uiMaxLongTermReferences = 0; UINT32 m_uiTrustModeLongTermReferences = 0; BOOL m_bLayerCountSet = FALSE; UINT32 m_uiLayerCount = 1; UINT32 m_uiSelectedLayer = 0; UINT32 m_uiQualityVsSpeed = 33; UINT32 m_uiMeanBitRate; BOOL m_bMeanBitRateSet = FALSE; UINT32 m_uiPeakBitRate = 0; BOOL m_bPeakBitRateSet = FALSE; UINT32 m_uiBufferSize = 0; BOOL m_bBufferSizeSet = FALSE; UINT32 m_uiBufferInLevel = 0; BOOL m_bBufferInLevelSet = FALSE; UINT32 m_uiGopSize = 30; // ~1s worth as a default BOOL m_bGopSizeSet = FALSE; UINT32 m_uiBFrameCount = 0; UINT32 m_uiContentType = eAVEncVideoContentType_Unknown; BOOL m_bContentTypeSet = FALSE; UINT32 m_uiMinQP = 0; BOOL m_bMinQPSet = FALSE; UINT32 m_uiMaxQP = AVC_MAX_QP; BOOL m_bMaxQPSet = FALSE; UINT32 m_uiSPSID = 0; BOOL m_bSPSIDSet = FALSE; UINT32 m_uiPPSID = 0; BOOL m_bPPSIDSet = FALSE; UINT32 m_uiLTRBufferControl = 0; BOOL m_bLTRBufferControlSet = FALSE; UINT32 m_uiMarkLTRFrame; BOOL m_bMarkLTRFrameSet = FALSE; UINT32 m_uiUseLTRFrame; BOOL m_bUseLTRFrameSet = FALSE; UINT32 m_uiSliceControlMode = SLICE_CONTROL_MODE_MB; BOOL m_bSliceControlModeSet = FALSE; UINT32 m_uiSliceControlSize = 0; BOOL m_bSliceControlSizeSet = FALSE; BOOL m_bMaxNumRefFrameSet = FALSE; #if MFT_CODEC_H264ENC UINT32 m_uiMaxNumRefFrame = PIPE_H264_MAX_REFERENCES; #elif MFT_CODEC_H265ENC UINT32 m_uiMaxNumRefFrame = PIPE_H265_MAX_REFERENCES; #elif MFT_CODEC_AV1ENC UINT32 m_uiMaxNumRefFrame = PIPE_AV1_MAX_REFERENCES; #endif #if MFT_CODEC_H264ENC eAVEncH264VProfile m_uiProfile = eAVEncH264VProfile_Main; eAVEncH264VLevel m_uiLevel = eAVEncH264VLevel5; const D3D12_VIDEO_ENCODER_CODEC m_Codec = D3D12_VIDEO_ENCODER_CODEC_H264; enum pipe_video_profile m_outputPipeProfile = PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; #elif MFT_CODEC_H265ENC eAVEncH265VProfile m_uiProfile = eAVEncH265VProfile_Main_420_8; eAVEncH265VLevel m_uiLevel = eAVEncH265VLevel5; const D3D12_VIDEO_ENCODER_CODEC m_Codec = D3D12_VIDEO_ENCODER_CODEC_HEVC; enum pipe_video_profile m_outputPipeProfile = PIPE_VIDEO_PROFILE_HEVC_MAIN; #elif MFT_CODEC_AV1ENC eAVEncAV1VProfile m_uiProfile = eAVEncAV1VProfile_Main_420_8; eAVEncAV1VLevel m_uiLevel = eAVEncAV1VLevel5; const D3D12_VIDEO_ENCODER_CODEC m_Codec = D3D12_VIDEO_ENCODER_CODEC_AV1; enum pipe_video_profile m_outputPipeProfile = PIPE_VIDEO_PROFILE_AV1_MAIN; #endif UINT32 m_uiMeanAbsoluteDifference = 0; UINT32 m_uiIntraRefreshMode = 0; UINT32 m_uiIntraRefreshSize = 0; eAVScenarioInfo m_eScenarioInfo = eAVScenarioInfo_Unknown; UINT32 m_uiEnableInLoopBlockFilter = 0; BOOL m_bVideoROIEnabled = FALSE; UINT32 m_uiDirtyRectEnabled = 0; UINT32 m_uiQuality[3] = { 65, 65, 65 }; // Default value for AVEncCommonQuality is 65 uint32_t m_uiEncodeFrameTypeIQP[3] = { AVC_DEFAULT_QP, AVC_DEFAULT_QP, AVC_DEFAULT_QP }; uint32_t m_uiEncodeFrameTypePQP[3] = { AVC_DEFAULT_QP, AVC_DEFAULT_QP, AVC_DEFAULT_QP }; uint32_t m_uiEncodeFrameTypeBQP[3] = { AVC_DEFAULT_QP, AVC_DEFAULT_QP, AVC_DEFAULT_QP }; BOOL m_bEncodeQPSet = FALSE; BOOL m_bLowLatency = FALSE; BOOL m_bCabacEnable = TRUE; BOOL m_bVideoEnableFramePsnrYuv = FALSE; BOOL m_bVideoEnableSpatialAdaptiveQuantization = FALSE; UINT32 m_uiVideoOutputQPMapBlockSize = 0; UINT32 m_uiVideoOutputBitsUsedMapBlockSize = 0; UINT32 m_uiVideoSatdMapBlockSize = 0; typedef enum RECON_PIC_OUTPUT_MODE { RECON_PIC_OUTPUT_MODE_DISABLED = 0, RECON_PIC_OUTPUT_MODE_BLIT_COPY = 1, RECON_PIC_OUTPUT_MODE_READ_ONLY_SHARED_RESOURCE = 2, } RECON_PIC_OUTPUT_MODE; RECON_PIC_OUTPUT_MODE m_VideoReconstructedPictureMode = RECON_PIC_OUTPUT_MODE_DISABLED; UINT32 m_uiSliceGenerationMode = 0; BOOL m_bSliceGenerationModeSet = FALSE; BOOL m_bRateControlFramePreAnalysis = FALSE; BOOL m_bRateControlFramePreAnalysisExternalReconDownscale = FALSE; UINT m_uiMaxOutputBitstreamSize = 0u; struct pipe_video_codec *m_pPipeVideoCodec = nullptr; struct pipe_video_codec *m_pPipeVideoBlitter = nullptr; reference_frames_tracker *m_pGOPTracker = nullptr; enum pipe_format m_inputPipeFormat = PIPE_FORMAT_NV12; // Fences used to synchronize different upstream textures // types (e.g DX12, DX11, CPU buffer) with the pipe interface ComPtr m_spStagingFence11; ComPtr m_spStagingFence12; struct pipe_fence_handle *m_pPipeFenceHandle = nullptr; HANDLE m_hSharedFenceHandle = nullptr; uint64_t m_CurrentSyncFenceValue = 1; // Cached encoder capabilities class encoder_capabilities m_EncoderCapabilities { this }; // state management bool m_bShutdown = false; bool m_bInitialized = false; bool m_bStreaming = false; bool m_bDraining = false; bool m_bFlushing = false; event m_eventInputDrained; DWORD m_dwNeedInputCount = 0; DWORD m_dwProcessInputCount = 0; DWORD m_dwHaveOutputCount = 0; DWORD m_dwProcessOutputCount = 0; class std::mutex m_lock; class std::mutex m_lockShutdown; class std::mutex m_encoderLock; bool m_bExitThread = false; bool m_bUnlocked = false; HRESULT IsUnlocked( void ); #if MFT_CODEC_H264ENC HRESULT UpdateH264EncPictureDesc( pipe_h264_enc_picture_desc *pPicInfo, const uint32_t intra_period, const uint32_t ip_period ); #endif #if MFT_CODEC_H265ENC HRESULT UpdateH265EncPictureDesc( pipe_h265_enc_picture_desc *pPicInfo, const uint32_t intra_period, const uint32_t ip_period, const uint8_t log2_max_pic_order_cnt_lsb_minus4, const uint16_t pic_width_in_luma_samples, const uint16_t pic_height_in_luma_samples ); #endif #if MFT_CODEC_AV1ENC HRESULT UpdateAV1EncPictureDesc( pipe_av1_enc_picture_desc *pPicInfo ); #endif HRESULT PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bool dirtyRectFrameNumSet, uint32_t dirtyRectFrameNum, bool moveRegionFrameNumSet, uint32_t moveRegionFrameNum ); HRESULT PrepareForEncode( IMFSample *pSample, LPDX12EncodeContext *ppDX12EncodeContext ); std::vector m_pDirtyRectBlob = std::vector( sizeof( DIRTYRECT_INFO ) ); std::vector m_pMoveRegionBlob = std::vector( sizeof( MOVEREGION_INFO ) ); public: CDX12EncHMFT(); CDX12EncHMFT( LPUNKNOWN pUnk, HRESULT *phr ); STDMETHOD( RuntimeClassInitialize )(); HRESULT Initialize(); HRESULT OnInputTypeChanged(); HRESULT OnOutputTypeChanged(); public: static HRESULT CreateInstance( __deref_out CDX12EncHMFT **ppDX12EncHMFT ); // --------------------------------------------------------------------------------------------------------- // IMFTransform (https://learn.microsoft.com/en-us/windows/win32/api/mftransform/nn-mftransform-imftransform) // --------------------------------------------------------------------------------------------------------- STDMETHOD( GetAttributes )( IMFAttributes **ppAttributes ); STDMETHOD( GetOutputStreamAttributes )( DWORD dwOutputStreamID, IMFAttributes **ppAttributes ); STDMETHOD( GetOutputStreamInfo )( DWORD dwOutputStreamIndex, MFT_OUTPUT_STREAM_INFO *pStreamInfo ); STDMETHOD( GetInputStreamAttributes )( DWORD dwInputStreamID, IMFAttributes **ppAttributes ); STDMETHOD( GetInputStreamInfo )( DWORD dwInputStreamIndex, MFT_INPUT_STREAM_INFO *pStreamInfo ); STDMETHOD( GetStreamCount )( DWORD *pcInputStreams, DWORD *pcOutputStreams ); STDMETHOD( GetStreamIDs )( DWORD dwInputIDArraySize, DWORD *pdwInputIDs, DWORD dwOutputIDArraySize, DWORD *pdwOutputIDs ); STDMETHOD( GetStreamLimits )( DWORD *pdwInputMinimum, DWORD *pdwInputMaximum, DWORD *pdwOutputMinimum, DWORD *pdwOutputMaximum ); STDMETHOD( DeleteInputStream )( DWORD dwStreamIndex ); STDMETHOD( AddInputStreams )( DWORD cStreams, DWORD *adwStreamIDs ); STDMETHOD( GetInputAvailableType )( DWORD dwInputStreamIndex, DWORD dwTypeIndex, IMFMediaType **ppType ); STDMETHOD( GetOutputAvailableType )( DWORD dwOutputStreamIndex, DWORD dwTypeIndex, IMFMediaType **ppType ); STDMETHOD( SetInputType )( DWORD dwInputStreamIndex, IN IMFMediaType *pType, DWORD dwFlags ); STDMETHOD( SetOutputType )( DWORD dwOutputStreamIndex, IN IMFMediaType *pType, DWORD dwFlags ); STDMETHOD( GetInputCurrentType )( DWORD dwInputStreamIndex, IMFMediaType **ppType ); STDMETHOD( GetOutputCurrentType )( DWORD dwOutputStreamIndex, IMFMediaType **ppType ); STDMETHOD( SetOutputBounds )( LONGLONG hnsLowerBound, LONGLONG hnsUpperBound ); STDMETHOD( GetInputStatus )( DWORD dwInputStreamIndex, DWORD *pdwFlags ); STDMETHOD( GetOutputStatus )( DWORD *pdwFlags ); STDMETHOD( ProcessEvent )( DWORD dwInputStreamIndex, IMFMediaEvent *pEvent ); STDMETHOD( ProcessMessage )( MFT_MESSAGE_TYPE eMessage, ULONG_PTR ulParam ); STDMETHOD( ProcessInput )( DWORD dwInputStreamIndex, IMFSample *pSample, DWORD dwFlags ); STDMETHOD( ProcessOutput )( DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER *pOutputSamples, DWORD *pdwStatus ); // -------------------------------------------------------------------------------------------------------------------------- // IMFMediaEventGenerator (https://learn.microsoft.com/en-us/windows/win32/api/mfobjects/nn-mfobjects-imfmediaeventgenerator) // -------------------------------------------------------------------------------------------------------------------------- STDMETHOD( BeginGetEvent )( IMFAsyncCallback *pCallback, IUnknown *punkState ); STDMETHOD( EndGetEvent )( IMFAsyncResult *pResult, IMFMediaEvent **ppEvent ); STDMETHOD( GetEvent )( DWORD dwFlags, IMFMediaEvent **ppEvent ); STDMETHOD( QueueEvent )( MediaEventType met, REFGUID guidExtendedType, HRESULT hrStatus, const PROPVARIANT *pvValue ); // -------------------------------------------------------------------------------------------- // IMFShutdown (https://learn.microsoft.com/en-us/windows/win32/api/mfidl/nn-mfidl-imfshutdown) // -------------------------------------------------------------------------------------------- STDMETHOD( GetShutdownStatus )( MFSHUTDOWN_STATUS *pStatus ); STDMETHOD( Shutdown )( void ); // -------------------------------------------------------------------------------------------- // ICodecAPI (https://learn.microsoft.com/en-us/windows/win32/api/strmif/nn-strmif-icodecapi) // -------------------------------------------------------------------------------------------- STDMETHOD( IsSupported )( const GUID *Api ); STDMETHOD( IsModifiable )( const GUID *Api ); STDMETHOD( GetParameterRange )( const GUID *Api, VARIANT *ValueMin, VARIANT *ValueMax, VARIANT *SteppingDelta ); STDMETHOD( GetParameterValues )( const GUID *Api, VARIANT **Values, ULONG *ValuesCount ); STDMETHOD( GetValue )( const GUID *Api, VARIANT *Value ); STDMETHOD( SetValue )( const GUID *Api, VARIANT *Value ); STDMETHOD( GetDefaultValue )( const GUID *Api, VARIANT *Value ); STDMETHOD( RegisterForEvent )( const GUID *Api, LONG_PTR userData ); STDMETHOD( UnregisterForEvent )( const GUID *Api ); STDMETHOD( SetAllDefaults )( void ); STDMETHOD( SetValueWithNotify )( const GUID *Api, VARIANT *Value, GUID **ChangedParam, ULONG *ChangedParamCount ); STDMETHOD( SetAllDefaultsWithNotify )( GUID **ChangedParam, ULONG *ChangedParamCount ); STDMETHOD( GetAllSettings )( IStream *pStream ); STDMETHOD( SetAllSettings )( IStream *pStream ); STDMETHOD( SetAllSettingsWithNotify )( IStream *pStream, GUID **ChangedParam, ULONG *ChangedParamCount ); // ------------------------------------------------------------------------------------------------------------ // IMFRealTimeClientEx (https://learn.microsoft.com/en-us/windows/win32/api/mfidl/nn-mfidl-imfrealtimeclientex) // ------------------------------------------------------------------------------------------------------------ STDMETHOD( RegisterThreadsEx )( DWORD *pdwTaskIndex, LPCWSTR wszClassName, LONG lBasePriority ); STDMETHOD( UnregisterThreads )( void ); STDMETHOD( SetWorkQueueEx )( DWORD dwMultithreadedWorkQueueId, LONG lWorkItemBasePriority ); }; ActivatableClass( CDX12EncHMFT ); CoCreatableClass( CDX12EncHMFT );