video_player_win icon indicating copy to clipboard operation
video_player_win copied to clipboard

new way to use custom http headers

Open TSCSOftware opened this issue 1 year ago • 3 comments

`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 #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(); } `

TSCSOftware avatar Mar 10 '23 17:03 TSCSOftware

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.

jakky1 avatar Mar 11 '23 00:03 jakky1

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?

TSCSOftware avatar Mar 11 '23 04:03 TSCSOftware

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.

jakky1 avatar Mar 11 '23 07:03 jakky1