From ffb791b6ee997fde491d143d10e133d7c8feb6b3 Mon Sep 17 00:00:00 2001 From: Lukas Fellechner Date: Thu, 28 Jul 2022 20:48:38 +0200 Subject: [PATCH 1/2] Fix FFmpegOptions parsing and enable local network access --- Samples/MediaPlayerCPP/MainPage.xaml.cpp | 13 ++++++--- Samples/MediaPlayerCPP/Package.appxmanifest | 1 + Samples/MediaPlayerCS/MainPage.xaml.cs | 9 +++++-- Samples/MediaPlayerCS/Package.appxmanifest | 4 ++- Source/FFmpegMediaSource.cpp | 9 +++---- Source/StringUtils.h | 29 +++++++++++++++++++++ 6 files changed, 53 insertions(+), 12 deletions(-) diff --git a/Samples/MediaPlayerCPP/MainPage.xaml.cpp b/Samples/MediaPlayerCPP/MainPage.xaml.cpp index 7c2a96df2a..87f65d75c9 100644 --- a/Samples/MediaPlayerCPP/MainPage.xaml.cpp +++ b/Samples/MediaPlayerCPP/MainPage.xaml.cpp @@ -175,11 +175,16 @@ void MainPage::URIBoxKeyUp(Platform::Object^ sender, Windows::UI::Xaml::Input::K task MainPage::OpenUriStream(Platform::String^ uri) { - // Set FFmpeg specific options. List of options can be found in https://www.ffmpeg.org/ffmpeg-protocols.html - + // Set FFmpeg specific options: + // https://www.ffmpeg.org/ffmpeg-protocols.html + // https://www.ffmpeg.org/ffmpeg-formats.html + // + // If format cannot be detected, try to increase probesize, max_probe_packets and analyzeduration! + // Below are some sample options that you can set to configure RTSP streaming - // Config->FFmpegOptions->Insert("rtsp_flags", "prefer_tcp"); - // Config->FFmpegOptions->Insert("stimeout", 100000); + //Config->FFmpegOptions->Insert("rtsp_flags", "prefer_tcp"); + Config->FFmpegOptions->Insert("stimeout", 1000000); + Config->FFmpegOptions->Insert("timeout", 1000000); // Instantiate FFmpegMediaSource using the URI mediaPlayer->Source = nullptr; diff --git a/Samples/MediaPlayerCPP/Package.appxmanifest b/Samples/MediaPlayerCPP/Package.appxmanifest index 1a675cada6..4af712cc5a 100644 --- a/Samples/MediaPlayerCPP/Package.appxmanifest +++ b/Samples/MediaPlayerCPP/Package.appxmanifest @@ -44,5 +44,6 @@ + \ No newline at end of file diff --git a/Samples/MediaPlayerCS/MainPage.xaml.cs b/Samples/MediaPlayerCS/MainPage.xaml.cs index bdff6a1726..4a767b2e96 100644 --- a/Samples/MediaPlayerCS/MainPage.xaml.cs +++ b/Samples/MediaPlayerCS/MainPage.xaml.cs @@ -227,11 +227,16 @@ private async void URIBoxKeyUp(object sender, KeyRoutedEventArgs e) try { - // Set FFmpeg specific options. List of options can be found in https://www.ffmpeg.org/ffmpeg-protocols.html + // Set FFmpeg specific options: + // https://www.ffmpeg.org/ffmpeg-protocols.html + // https://www.ffmpeg.org/ffmpeg-formats.html + + // If format cannot be detected, try to increase probesize, max_probe_packets and analyzeduration! // Below are some sample options that you can set to configure RTSP streaming // Config.FFmpegOptions.Add("rtsp_flags", "prefer_tcp"); - // Config.FFmpegOptions.Add("stimeout", 100000); + Config.FFmpegOptions.Add("stimeout", 1000000); + Config.FFmpegOptions.Add("timeout", 1000000); // Instantiate FFmpegMediaSource using the URI mediaPlayer.Source = null; diff --git a/Samples/MediaPlayerCS/Package.appxmanifest b/Samples/MediaPlayerCS/Package.appxmanifest index 4a368eedfa..e0be379f34 100644 --- a/Samples/MediaPlayerCS/Package.appxmanifest +++ b/Samples/MediaPlayerCS/Package.appxmanifest @@ -1,5 +1,5 @@  - + @@ -24,5 +24,7 @@ + + \ No newline at end of file diff --git a/Source/FFmpegMediaSource.cpp b/Source/FFmpegMediaSource.cpp index e8cc8e6ecb..cc1a9a011e 100644 --- a/Source/FFmpegMediaSource.cpp +++ b/Source/FFmpegMediaSource.cpp @@ -1659,13 +1659,12 @@ namespace winrt::FFmpegInteropX::implementation while (options.HasCurrent()) { auto key = StringUtils::PlatformStringToUtf8String(options.Current().Key()); - auto stringValue = options.Current().Value().try_as(); - if (stringValue) + hstring value = StringUtils::ToString(options.Current().Value()); + if (!value.empty()) { - auto value = StringUtils::PlatformStringToUtf8String(stringValue.ToString()); - // Add key and value pair entry - if (av_dict_set(&avDict, key.c_str(), value.c_str(), 0) < 0) + auto valCstr = StringUtils::PlatformStringToUtf8String(value); + if (av_dict_set(&avDict, key.c_str(), valCstr.c_str(), 0) < 0) { hr = E_INVALIDARG; break; diff --git a/Source/StringUtils.h b/Source/StringUtils.h index 31f8e4cb78..aa56a96aa3 100644 --- a/Source/StringUtils.h +++ b/Source/StringUtils.h @@ -44,5 +44,34 @@ namespace FFmpegInteropX return std::string(""); } + inline static winrt::hstring ToString(winrt::Windows::Foundation::IInspectable inspectable) + { + auto valHstring = inspectable.try_as(); + if (valHstring.has_value()) + { + return valHstring.value(); + } + auto valI32 = inspectable.try_as(); + if (valI32.has_value()) + { + return winrt::to_hstring(valI32.value()); + } + auto valI64 = inspectable.try_as(); + if (valI64.has_value()) + { + return winrt::to_hstring(valI64.value()); + } + auto valf = inspectable.try_as(); + if (valf.has_value()) + { + return winrt::to_hstring(valf.value()); + } + auto vald = inspectable.try_as(); + if (vald.has_value()) + { + return winrt::to_hstring(vald.value()); + } + return L""; + } }; } From 9ebbfcb3f80548d4d3cf1ed9275bee994a5f62a3 Mon Sep 17 00:00:00 2001 From: Lukas Fellechner Date: Fri, 29 Jul 2022 00:02:17 +0200 Subject: [PATCH 2/2] Improve EOF handling --- Source/MediaSampleProvider.cpp | 20 +++++++++++++++++--- Source/UncompressedSampleProvider.cpp | 2 ++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Source/MediaSampleProvider.cpp b/Source/MediaSampleProvider.cpp index c4c8423871..5ad9b43a46 100644 --- a/Source/MediaSampleProvider.cpp +++ b/Source/MediaSampleProvider.cpp @@ -261,14 +261,28 @@ MediaStreamSample MediaSampleProvider::GetNextSample() HRESULT MediaSampleProvider::GetNextPacket(AVPacket** avPacket, LONGLONG& packetPts, LONGLONG& packetDuration) { HRESULT hr = S_OK; + unsigned int errorCount = 0; // Continue reading until there is an appropriate packet in the stream while (m_packetQueue.empty()) { - if (m_pReader->ReadPacket() < 0) + auto result = m_pReader->ReadPacket(); + if (result < 0) { - DebugMessage(L"GetNextPacket reaching EOF\n"); - break; + if (result == AVERROR_EOF || (m_pAvFormatCtx->pb && m_pAvFormatCtx->pb->eof_reached)) + { + DebugMessage(L"GetNextPacket reaching EOF\n"); + break; + } + else if (errorCount++ >= m_config.SkipErrors()) + { + DebugMessage(L"Aborting after to too many read errors.\n"); + break; + } + else + { + DebugMessage(L"Read error.\n"); + } } } diff --git a/Source/UncompressedSampleProvider.cpp b/Source/UncompressedSampleProvider.cpp index 66824b5b3d..bd14034e34 100644 --- a/Source/UncompressedSampleProvider.cpp +++ b/Source/UncompressedSampleProvider.cpp @@ -74,6 +74,8 @@ HRESULT UncompressedSampleProvider::CreateNextSampleBuffer(IBuffer* pBuffer, int if (!SUCCEEDED(hr) && errorCount++ < m_config.SkipErrors()) { + DebugMessage(L"Decode error.\n"); + // unref any buffers in old frame av_frame_unref(avFrame);