### C++ Custom Video MFT Implementation Source: https://context7.com/microsoft/media-foundation/llms.txt This C++ code defines a custom Media Foundation Transform (MFT) for video processing. It includes methods for setting input types, processing video samples, and applying custom frame transformations. The `ProcessVideoFrame` function provides an example of a simple brightness adjustment. ```cpp #include #include // MFT processes video frames through transform pipeline class CustomVideoMFT : public IMFTransform { public: // Set input media type (e.g., NV12, YUY2, RGB32) STDMETHODIMP SetInputType(DWORD dwInputStreamID, IMFMediaType* pType, DWORD dwFlags) { if (dwInputStreamID != 0) return MF_E_INVALIDSTREAMNUMBER; // Validate input type GUID subtype = GUID_NULL; pType->GetGUID(MF_MT_SUBTYPE, &subtype); if (subtype == MFVideoFormat_NV12 || subtype == MFVideoFormat_RGB32) { m_inputType = pType; return S_OK; } return MF_E_INVALIDTYPE; } // Process video sample STDMETHODIMP ProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER* pOutputSamples, DWORD* pdwStatus) { if (!m_inputSample) return MF_E_TRANSFORM_NEED_MORE_INPUT; // Lock input buffer winrt::com_ptr inputBuffer; m_inputSample->GetBufferByIndex(0, inputBuffer.put()); BYTE* inputData = nullptr; DWORD inputLength = 0; inputBuffer->Lock(&inputData, nullptr, &inputLength); // Create output sample winrt::com_ptr outputSample; winrt::com_ptr outputBuffer; MFCreateMemoryBuffer(inputLength, outputBuffer.put()); BYTE* outputData = nullptr; outputBuffer->Lock(&outputData, nullptr, nullptr); // Apply custom processing (example: simple copy with effect) ProcessVideoFrame(inputData, outputData, inputLength); outputBuffer->Unlock(); outputBuffer->SetCurrentLength(inputLength); inputBuffer->Unlock(); // Set output sample MFCreateSample(outputSample.put()); outputSample->AddBuffer(outputBuffer.get()); LONGLONG timestamp = 0; m_inputSample->GetSampleTime(×tamp); outputSample->SetSampleTime(timestamp); pOutputSamples[0].pSample = outputSample.detach(); pOutputSamples[0].dwStatus = 0; m_inputSample = nullptr; return S_OK; } private: winrt::com_ptr m_inputType; winrt::com_ptr m_inputSample; void ProcessVideoFrame(BYTE* input, BYTE* output, DWORD length) { // Example: Apply brightness adjustment for (DWORD i = 0; i < length; i++) { output[i] = min(255, input[i] * 1.2f); } } }; // Register and use MFT in pipeline HRESULT RegisterCustomMFT() { MFT_REGISTER_TYPE_INFO inputTypes[] = { { MFMediaType_Video, MFVideoFormat_NV12 }, { MFMediaType_Video, MFVideoFormat_RGB32 } }; MFT_REGISTER_TYPE_INFO outputTypes[] = { { MFMediaType_Video, MFVideoFormat_NV12 }, { MFMediaType_Video, MFVideoFormat_RGB32 } }; return MFTRegisterLocalByCLSID( __uuidof(CustomVideoMFT), MFT_CATEGORY_VIDEO_EFFECT, L"Custom Video Processor", MFT_ENUM_FLAG_SYNCMFT, ARRAYSIZE(inputTypes), inputTypes, ARRAYSIZE(outputTypes), outputTypes ); } ``` -------------------------------- ### Media Foundation Performance Tracing with WPR and MXA (Bash) Source: https://context7.com/microsoft/media-foundation/llms.txt Captures and analyzes Media Foundation performance traces using Windows Performance Recorder (WPR) and Media Experience Analyzer (MXA). This process involves starting a trace with a specific profile, running a media playback scenario, stopping the trace, and then analyzing the resulting .etl file in MXA to diagnose playback issues. ```bash # Download MF_TRACE.WPRP from repository # Open elevated command prompt # Start performance trace capture wpr.exe -start C:\path\to\MF_TRACE.WPRP!MediaPerformance -filemode # Run your media playback test scenario # - Play video content # - Perform seeks, pause/resume # - Test DRM content # - Reproduce any performance issues # Stop trace capture wpr.exe -stop media_trace.etl # Open trace in Media Experience Analyzer (MXA) # MXA is available in Windows ADK: # https://docs.microsoft.com/en-us/windows-hardware/get-started/adk-install # Analyze trace for: # - Frame timing and drops # - Audio/video sync issues # - Decode performance # - GPU utilization # - DRM license acquisition # - Buffer starvation # Common issues to look for: # Stutter: Inconsistent frame delivery timing # Glitch: Frames not displayed at intended time # A/V Sync: Audio ahead/behind video timeline # Corruption: Visual distortion in decoded frames ``` -------------------------------- ### Implement EME MediaKeys and MediaKeySession for DRM Source: https://context7.com/microsoft/media-foundation/llms.txt Shows how to implement W3C Encrypted Media Extensions (EME) for PlayReady DRM using custom MediaKeys and MediaKeySession classes. This includes setting server certificates, creating persistent license sessions, handling license requests and responses, managing key statuses, and session persistence. ```cpp #include "MediaKeys.h" #include "MediaKeySession.h" #include "EmeFactory.h" using namespace media::eme; // Create MediaKeys from CDM winrt::com_ptr cdm; // ... initialize CDM (Content Decryption Module) std::shared_ptr mediaKeys = std::make_shared(cdm.get()); // Set server certificate for license server communication std::vector certificate = {/* certificate data */}; bool certSet = mediaKeys->setServerCertificate(certificate); // Create persistent license session std::shared_ptr session = mediaKeys->createSession(MF_MEDIAKEYSESSION_TYPE_PERSISTENT_LICENSE); // Register message callback for license requests session->onmessage([](MF_MEDIAKEYSESSION_MESSAGETYPE messageType, gsl::span message, LPCWSTR destinationUrl) { if (messageType == MF_MEDIAKEYSESSION_MESSAGETYPE_LICENSE_REQUEST) { std::cout << "License request generated, sending to: " << destinationUrl << "\n"; // Send message to license server // ... HTTP POST message data to destinationUrl } }); // Register key status change callback session->onkeystatuseschange([]() { std::cout << "Key status changed\n"; }); // Generate license request from PSSH init data std::wstring initDataType = L"cenc"; // Common Encryption std::vector initData = {/* PSSH box data from content */}; session->generateRequest(initDataType, initData); // Update session with license response from server std::vector licenseResponse = {/* response from license server */}; gsl::span responseSpan(licenseResponse); session->update(responseSpan); // Check key statuses std::vector keyStatuses = session->keyStatuses(); for (const auto& [keyId, status] : keyStatuses) { if (status == MF_MEDIAKEY_STATUS_USABLE) { std::cout << "Key is usable for decryption\n"; } } // Get session ID for persistence wil::unique_cotaskmem_string sessionId = session->sessionId(); std::wcout << L"Session ID: " << sessionId.get() << L"\n"; // Load existing persistent session bool loaded = session->load(std::wstring(sessionId.get())); // Close session when done session->close(); // Remove all keys and session data session->remove(); ``` -------------------------------- ### Initialize and Control MediaEngine Playback (C++) Source: https://context7.com/microsoft/media-foundation/llms.txt Manages the lifecycle of Media Foundation's MediaEngine, handling initialization, playback control, surface rendering, and event callbacks. It requires MediaFoundationHelpers and D3D11 headers. Inputs include callback functions and an IMFMediaSource. Outputs include playback control and rendering surface handles. ```cpp #include "MediaEngineWrapper.h" #include "MediaFoundationHelpers.h" #include // Initialize MediaEngine with callbacks auto initializedCB = []() { std::cout << "Media engine ready for playback\n"; }; auto errorCB = [](MF_MEDIA_ENGINE_ERR error, HRESULT hr) { std::cerr << "Media engine error: " << hr << "\n"; }; auto bufferingCB = [](MediaEngineWrapper::BufferingState state) { if (state == MediaEngineWrapper::BufferingState::HAVE_NOTHING) { std::cout << "Buffering...\n"; } else { std::cout << "Playing...\n"; } }; auto endedCB = []() { std::cout << "Playback ended\n"; }; auto timeUpdateCB = []() { // Called periodically during playback for time updates }; // Create wrapper instance winrt::com_ptr mediaEngine = winrt::make_self( initializedCB, errorCB, bufferingCB, endedCB, timeUpdateCB ); // Initialize with media source winrt::com_ptr mediaSource; // ... create or obtain your media source mediaEngine->Initialize(mediaSource.get()); // Control playback uint64_t startTimeHns = 0; // Start from beginning (100-nanosecond units) mediaEngine->StartPlayingFrom(startTimeHns); // Adjust playback parameters mediaEngine->SetVolume(0.8f); mediaEngine->SetPlaybackRate(1.0); // Get surface handle for rendering integration HANDLE surfaceHandle = mediaEngine->GetSurfaceHandle(); // Update rendering dimensions uint32_t width = 1920; uint32_t height = 1080; mediaEngine->OnWindowUpdate(width, height); // Query current playback position uint64_t currentTimeHns = mediaEngine->GetMediaTime(); // Cleanup mediaEngine->Pause(); mediaEngine->Shutdown(); ``` -------------------------------- ### Create Custom IMFMediaSource Wrapper with Media Foundation Source: https://context7.com/microsoft/media-foundation/llms.txt Demonstrates how to create a custom IMFMediaSource by wrapping an IMFSourceReader. This allows for advanced control over media streams, playback seeking, pausing, and stopping. It involves creating the source reader from a URL, initializing the custom wrapper, and interacting with its methods. ```cpp #include "MediaFoundationSourceWrapper.h" #include "MediaFoundationStreamWrapper.h" // Create source reader from file winrt::com_ptr sourceReader; HRESULT hr = MFCreateSourceReaderFromURL( L"C:\\video.mp4", nullptr, &sourceReader ); // Create custom source wrapper winrt::com_ptr customSource; hr = MakeAndInitialize(&customSource, sourceReader.get()); // Query source characteristics DWORD characteristics = 0; hr = customSource->GetCharacteristics(&characteristics); if (characteristics & MFMEDIASOURCE_CAN_SEEK) { std::cout << "Source supports seeking\n"; } // Create presentation descriptor winrt::com_ptr presentationDesc; hr = customSource->CreatePresentationDescriptor(&presentationDesc); // Get stream count DWORD streamCount = 0; hr = presentationDesc->GetStreamDescriptorCount(&streamCount); std::cout << "Stream count: " << streamCount << "\n"; // Start playback from beginning PROPVARIANT startPosition; PropVariantInit(&startPosition); startPosition.vt = VT_EMPTY; hr = customSource->Start(presentationDesc.get(), &GUID_NULL, &startPosition); // Seek to specific time (5 seconds = 50,000,000 hundred-nanosecond units) PROPVARIANT seekPosition; PropVariantInit(&seekPosition); seekPosition.vt = VT_I8; seekPosition.hVal.QuadPart = 50000000; hr = customSource->Start(presentationDesc.get(), &GUID_NULL, &seekPosition); // Pause playback hr = customSource->Pause(); // Stop playback hr = customSource->Stop(); // Cleanup hr = customSource->Shutdown(); PropVariantClear(&startPosition); PropVariantClear(&seekPosition); ``` -------------------------------- ### DirectComposition Surface Integration for Video Rendering (C++) Source: https://context7.com/microsoft/media-foundation/llms.txt Integrates MediaEngine's DirectComposition surface into a Windows application's visual tree for hardware-accelerated video rendering. This involves initializing DirectComposition, creating targets and visuals, and associating the MediaEngine's surface handle with a visual for display. It also includes a callback for handling window resize events to update rendering. ```cpp #include #include "MediaEngineWrapper.h" // Initialize DirectComposition winrt::com_ptr dcompDevice; HRESULT hr = DCompositionCreateDevice(nullptr, IID_PPV_ARGS(&dcompDevice)); winrt::com_ptr dcompTarget; hr = dcompDevice->CreateTargetForHwnd(hwnd, TRUE, &dcompTarget); // Create root visual winrt::com_ptr rootVisual; hr = dcompDevice->CreateVisual(&rootVisual); hr = dcompTarget->SetRoot(rootVisual.get()); // Get surface handle from MediaEngine HANDLE surfaceHandle = mediaEngine->GetSurfaceHandle(); // Create surface from handle winrt::com_ptr surfaceUnknown; hr = dcompDevice->CreateSurfaceFromHandle(surfaceHandle, &surfaceUnknown); winrt::com_ptr dcompSurface; hr = surfaceUnknown.As(&dcompSurface); // Create visual for video winrt::com_ptr videoVisual; hr = dcompDevice->CreateVisual(&videoVisual); hr = videoVisual->SetContent(dcompSurface.get()); // Position and size the video visual hr = videoVisual->SetOffsetX(0.0f); hr = videoVisual->SetOffsetY(0.0f); // Add to visual tree hr = rootVisual->AddVisual(videoVisual.get(), TRUE, nullptr); // Commit changes hr = dcompDevice->Commit(); // Update when window resizes auto onWindowResize = [&](uint32_t width, uint32_t height) { mediaEngine->OnWindowUpdate(width, height); dcompDevice->Commit(); }; ``` -------------------------------- ### Initialize D3D11 Device for UWP MediaEngine Source: https://context7.com/microsoft/media-foundation/llms.txt Initializes a Direct3D 11 device with specific creation flags to enable hardware acceleration and support for video rendering. It configures feature levels for broader hardware compatibility and enables multithreaded protection for the device. ```cpp #include #include #include "MediaEngineWrapper.h" // Initialize D3D11 device for hardware acceleration winrt::com_ptr d3d11Device; UINT creationFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT | D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS; constexpr D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1 }; HRESULT hr = D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, creationFlags, featureLevels, ARRAYSIZE(featureLevels), D3D11_SDK_VERSION, d3d11Device.put(), nullptr, nullptr ); // Enable multithreaded protection winrt::com_ptr multithread = d3d11Device.as(); multithread->SetMultithreadProtected(TRUE); ``` -------------------------------- ### Configure MediaEngine Attributes for UWP Source: https://context7.com/microsoft/media-foundation/llms.txt Sets up the necessary attributes for the MediaEngine, including the DXGI device manager, content protection flags, browser compatibility mode, audio category, and a unique application ID for telemetry. These configurations are essential for proper video playback and integration within a UWP application. ```cpp // Create DXGI device manager winrt::com_ptr dxgiDeviceManager; UINT resetToken = 0; hr = MFLockDXGIDeviceManager(&resetToken, dxgiDeviceManager.put()); hr = dxgiDeviceManager->ResetDevice(d3d11Device.get(), resetToken); // Create MediaEngine attributes winrt::com_ptr attributes; hr = MFCreateAttributes(&attributes, 7); // Configure MediaEngine hr = attributes->SetUnknown(MF_MEDIA_ENGINE_DXGI_MANAGER, dxgiDeviceManager.get()); hr = attributes->SetUINT32(MF_MEDIA_ENGINE_CONTENT_PROTECTION_FLAGS, MF_MEDIA_ENGINE_ENABLE_PROTECTED_CONTENT); hr = attributes->SetGUID(MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE, MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE_EDGE); hr = attributes->SetUINT32(MF_MEDIA_ENGINE_AUDIO_CATEGORY, AudioCategory_Media); // Set application ID for telemetry (use unique GUID in production) GUID appId = {0x12345678, 0x1234, 0x1234, {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0}}; hr = attributes->SetGUID(MF_MEDIA_ENGINE_TELEMETRY_APPLICATION_ID, appId); ``` -------------------------------- ### Enable Windowless SwapChain for XAML Integration Source: https://context7.com/microsoft/media-foundation/llms.txt Enables windowless swap chain mode for the MediaEngine, allowing it to render directly to a swap chain managed externally. It retrieves the handle to this swap chain, which can then be attached to a XAML SwapChainPanel for visual display in a UWP application. ```cpp // Create MediaEngine with custom source support // ... continue with MediaEngineWrapper initialization // For XAML integration, get SwapChainPanel winrt::com_ptr mediaEngineEx = mediaEngine.as(); hr = mediaEngineEx->EnableWindowlessSwapchainMode(true); wil::unique_handle swapChainHandle; hr = mediaEngineEx->GetVideoSwapchainHandle(&swapChainHandle); // Attach to XAML SwapChainPanel // xamlSwapChainPanel.SetSwapChainHandle(swapChainHandle.get()); ``` -------------------------------- ### Integrate Custom Media Sources with MediaEngine (C++) Source: https://context7.com/microsoft/media-foundation/llms.txt Implements IMFMediaEngineExtension to integrate custom media sources with MediaEngine, allowing control over media data flow and source creation. It requires MediaEngineExtension.h and uses COM interfaces for Media Sources. The extension is configured via creation attributes and MediaEngine's SetSource method. ```cpp #include "MediaEngineExtension.h" // Create extension instance winrt::com_ptr extension; HRESULT hr = MakeAndInitialize(&extension); // Set custom media source winrt::com_ptr customSource; // ... create your custom IMFMediaSource implementation winrt::com_ptr sourceUnknown; hr = customSource.As(&sourceUnknown); extension->SetMediaSource(sourceUnknown.get()); // Configure MediaEngine with extension winrt::com_ptr creationAttributes; hr = MFCreateAttributes(&creationAttributes, 7); // Add extension to MediaEngine creation attributes hr = creationAttributes->SetUnknown(MF_MEDIA_ENGINE_EXTENSION, extension.get()); // Create MediaEngine with custom source support winrt::com_ptr classFactory; hr = CoCreateInstance(CLSID_MFMediaEngineClassFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&classFactory)); winrt::com_ptr mediaEngine; hr = classFactory->CreateInstance(0, creationAttributes.get(), &mediaEngine); // Set custom source URL identifier wil::unique_bstr sourceUrl = wil::make_bstr(L"customSrc"); hr = mediaEngine->SetSource(sourceUrl.get()); // Extension handles BeginCreateObject callback // Returns the custom media source when MediaEngine requests it // Cleanup when done extension->Shutdown(); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.