video_player_win
video_player_win copied to clipboard
new way to use custom http headers
`HRESULT OpenURL(const std::wstring& url) override { HRESULT hr = S_OK; wil::com_ptr<IMFSourceResolver> resolver; wil::com_ptr<IUnknown> source; wil::com_ptr<IMFMediaSource> mediaSource; wil::com_ptr<IMFPresentationDescriptor> presentationDescriptor;
// Create the source resolver. hr = MFCreateSourceResolver(&resolver); if (!SUCCEEDED(hr)) { std::cout << "MFCreateSourceResolver failed: " << hr << std::endl; return hr; }
// Set custom headers on the resolver. if (!headers.empty()) { wil::com_ptr<IMFNetCredentialManager> credentialManager; hr = MFCreateCredentialManager(&credentialManager); if (SUCCEEDED(hr)) { wil::com_ptr<IMFAttributes> resolverAttributes; hr = MFCreateAttributes(&resolverAttributes, 1); if (SUCCEEDED(hr)) { hr = resolverAttributes->SetUnknown(MFNETSOURCE_CREDENTIAL_MANAGER, credentialManager.get()); if (SUCCEEDED(hr)) { for (const auto& header : headers) { hr = resolverAttributes->SetString(MFNETSOURCE_HTTP_REQUEST_HEADERS, (LPCWSTR)header.first.c_str(), (LPCWSTR)header.second.c_str()); if (!SUCCEEDED(hr)) { std::cout << "Failed to set header: " << header.first << std::endl; } } } } } if (!SUCCEEDED(hr)) { std::cout << "Failed to set credentials manager" << std::endl; return hr; } }
// Use the resolver to create a media source. hr = resolver->CreateObjectFromURL(url.c_str(), MF_RESOLUTION_MEDIASOURCE, nullptr, &source); if (!SUCCEEDED(hr)) { std::cout << "CreateObjectFromURL failed: " << hr << std::endl; return hr; }
hr = source->QueryInterface(IID_PPV_ARGS(&mediaSource)); if (!SUCCEEDED(hr)) { std::cout << "QueryInterface for IMFMediaSource failed: " << hr << std::endl; return hr; }
// Create a presentation descriptor for the media source. hr = mediaSource->CreatePresentationDescriptor(&presentationDescriptor); if (!SUCCEEDED(hr)) { std::cout << "CreatePresentationDescriptor failed: " << hr << std::endl; return hr; }
// ... existing code ... } `
`IMFMediaSource* pSource = NULL; IMFSourceResolver* pSourceResolver = NULL; HRESULT hr = MFCreateSourceResolver(&pSourceResolver); if (FAILED(hr)) { // Handle error }
// Create a property store to hold the HTTP headers IPropertyStore* pPropertyStore = NULL; hr = MFCreatePropertyStore(&pPropertyStore); if (FAILED(hr)) { // Handle error }
// Set the custom HTTP headers PROPVARIANT var; PropVariantInit(&var); var.vt = VT_BSTR; var.bstrVal = SysAllocString(L"Authorization: Bearer TOKEN"); hr = pPropertyStore->SetValue(MF_HTTP_REQUEST_HEADERS, var); if (FAILED(hr)) { // Handle error }
// Create a property store to hold the URL PROPVARIANT varURL; PropVariantInit(&varURL); varURL.vt = VT_BSTR; varURL.bstrVal = SysAllocString(L"http://example.com/video.mp4");
// Create the media source MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID; hr = pSourceResolver->CreateObjectFromURL(varURL.bstrVal, MF_RESOLUTION_MEDIASOURCE, pPropertyStore, &ObjectType, (IUnknown**)&pSource); if (FAILED(hr)) { // Handle error }
// Cleanup PropVariantClear(&var); PropVariantClear(&varURL); SafeRelease(&pSourceResolver); SafeRelease(&pPropertyStore);`
`#include "windows_media_player.h"
#include
#include <winrt/Windows.Foundation.Collections.h> #include <winrt/Windows.Media.Core.h> #include <winrt/Windows.Media.Playback.h> #include <winrt/Windows.Storage.h> #include <winrt/Windows.Web.Http.Headers.h>
namespace {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
}
WindowsMediaPlayer::WindowsMediaPlayer() = default;
WindowsMediaPlayer::~WindowsMediaPlayer() = default;
void WindowsMediaPlayer::CreateMediaSource( const std::string& uri, const std::map<std::string, std::string>& headers, winrt::Windows::Media::Core::MediaSource& media_source) const { auto w_uri = converter.from_bytes(uri); auto uri_obj = winrt::Windows::Foundation::Uri(w_uri);
winrt::Windows::Web::Http::Headers::HttpRequestHeaderCollection header_collection; for (const auto& [key, value] : headers) { auto w_key = converter.from_bytes(key); auto w_value = converter.from_bytes(value); header_collection.TryAppendWithoutValidation(w_key, w_value); }
winrt::Windows::Web::Http::HttpClient client; client.DefaultRequestHeaders().InsertRange(header_collection);
auto response = client.GetAsync(uri_obj).get(); response.EnsureSuccessStatusCode();
auto stream = response.Content().ReadAsInputStreamAsync().get();
auto content_type = response.Content().Headers().ContentType().MediaType();
auto content_type_w = converter.from_bytes(content_type); auto media_stream_type = winrt::Windows::Media::Core::MediaStreamType::FromMediaType(content_type_w);
auto media_stream_source = winrt::Windows::Media::Core::MediaStreamSource::CreateFromInputStream(stream); media_stream_source.AddMediaStream(media_stream_type, stream); media_source = winrt::Windows::Media::Core::MediaSource(media_stream_source); }
void WindowsMediaPlayer::Play(const std::string& uri, const std::map<std::string, std::string>& headers) const { winrt::Windows::Media::Core::MediaSource media_source; CreateMediaSource(uri, headers, media_source);
winrt::Windows::Media::Playback::MediaPlayer player; player.Source(media_source); player.Play(); } `
Hi,
I cannot find the symbols MFNETSOURCE_HTTP_REQUEST_HEADERS
and MFCreateCredentialManager
in your sample code above.
BTW, please don't use ChatGPT without validation.
sorry for that.i have limited knowledge with c++ https://learn.microsoft.com/en-us/windows/win32/api/mfidl/nf-mfidl-imfhttpdownloadrequest-addheader https://learn.microsoft.com/en-us/windows/win32/api/mfidl/nf-mfidl-imfhttpdownloadrequest-queryheader IMFHttpDownloadRequest::BeginSendRequest() can you try this?
Yes there is a class called IMFHttpDownloadRequest. As this page mentioned,
Applications implement this interface to override the default implementation of the HTTP and HTTPS protocols used by Microsoft Media Foundation.
It means this package must to implement a http client to do it.
Not only the IMFHttpDownloadRequest, app should implemet IMFHttpDownloadSession
and IMFHttpDownloadSessionProvider
,
which is a hard work for me.
So I have no plan to do this.