Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stream buffer implementation #270

Merged
merged 36 commits into from
Oct 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
bd24a22
Stream buffer initial implementation
lukasf Jun 23, 2022
3163dad
Reorganize stream buffer files
lukasf Jun 23, 2022
c9fd915
Cleanup solution and editor config
lukasf Jun 23, 2022
8f37cc7
Fine tuning
lukasf Jun 23, 2022
c1a0a1e
Change to task based synchronization
lukasf Jun 24, 2022
4419163
Fix bug in TexturePool
lukasf Jun 24, 2022
cf36315
Fix flush wrong stream after switch streams
lukasf Jun 26, 2022
fed6438
Merge master branch
lukasf Jun 30, 2022
d10392d
Merge master branch
lukasf Jun 30, 2022
6b19a04
Change read ahead to non blocking
lukasf Jun 30, 2022
d34cf7d
Merge master branch
lukasf Jul 18, 2022
62603be
Fix stream buffer for WinRT migration
lukasf Jul 18, 2022
de87a6f
Add deprecation attribute
lukasf Jul 18, 2022
c0e029d
Improve stream buffer for fast seek and normal seek
lukasf Jul 19, 2022
73df120
Work on stream buffer
lukasf Jul 20, 2022
fc55125
Optimize references and seek limit
lukasf Jul 20, 2022
7a4c7b0
Improve config options
lukasf Jul 20, 2022
0e7e3df
Merge master branch
lukasf Jul 24, 2022
4e833a0
Improve buffer and fix possible deadlock after mutex change
lukasf Jul 25, 2022
5d6344f
Merge master branch
lukasf Jul 29, 2022
5d41768
Improve DASH fast seeking
lukasf Jul 29, 2022
efd81c9
Make stream buffer configurable in samples
lukasf Aug 17, 2022
889e7b4
Ignore duplicate seek requests
lukasf Aug 17, 2022
0cfd6ce
Merge master branch
lukasf Aug 21, 2022
5c7f5e5
Simplify MediaSourceConfig
lukasf Aug 18, 2022
d00203a
Optimizations and cleanup for stream buffer
lukasf Aug 21, 2022
f6b67e8
Merge master branch
lukasf Sep 19, 2022
fb61929
Fix RefCue
lukasf Sep 20, 2022
20caef5
Fix bitmap subtitles
lukasf Sep 20, 2022
a278eea
Fix subtitles
lukasf Sep 21, 2022
bfea39b
Disable read ahead buffer by default
lukasf Sep 22, 2022
f271c82
Merge master branch
lukasf Sep 22, 2022
90b2226
Lock on ClearSubtitles
lukasf Sep 22, 2022
7a92a56
Remove unneeded fields
lukasf Sep 22, 2022
0ad52cc
Improve and align sample keyboard shortcuts
lukasf Sep 25, 2022
011b3e1
Fix IsLoopingEnabled not working
lukasf Sep 26, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Samples/MediaPlayerCPP/MainPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@

<ToggleSwitch Header="Fast Seeking (keyframe seeking requires PlaybackSession property to be assigned)" OffContent="OFF" OnContent="ON" IsOn="{x:Bind Mode=TwoWay, Path=Config.FastSeek}" Margin="0,20,0,0" />

<ToggleSwitch Header="Read-ahead buffering" OffContent="OFF" OnContent="ON" IsOn="{x:Bind Mode=TwoWay, Path=Config.ReadAheadBufferEnabled}" Margin="0,20,0,0" />
<Slider Minimum="1" Maximum="100" SnapsTo="StepValues" TickFrequency="10" StepFrequency="1" Header="Read-ahead buffer duration (s)" Value="{x:Bind Path=Config.ReadAheadBufferDuration, Mode=TwoWay, Converter={StaticResource TimeSpanToDoubleConverter}}" />
<Slider Minimum="1" Maximum="100" SnapsTo="StepValues" TickFrequency="10" StepFrequency="1" Header="Read-ahead buffer size (MB)" Value="{x:Bind GetBufferSizeMB(), BindBack=SetBufferSizeMB, Mode=TwoWay}" />

<Button Content="Extract Frame" Click="ExtractFrame" Margin="0,20,10,10" />
<ToggleSwitch x:Name="grabFrameExactSeek" Header="Exact Seek for Extract Frame" OffContent="OFF" OnContent="ON" IsOn="True"/>

Expand Down
62 changes: 55 additions & 7 deletions Samples/MediaPlayerCPP/MainPage.xaml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,20 @@ task<void> MainPage::TryOpenLastFile()
}
}

task<void> MainPage::TryOpenLastUri()
{
try
{
//Try open last uri
auto uri = (String^)ApplicationData::Current->LocalSettings->Values->Lookup("LastUri");
co_await OpenUriStream(uri);
}
catch (Exception^ ex)
{
DisplayErrorMessage(ex->Message);
}
}

void MainPage::OpenLocalFile(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
OpenLocalFile();
Expand Down Expand Up @@ -133,16 +147,15 @@ task<void> MainPage::OpenLocalFile(StorageFile^ file)
// Open StorageFile as IRandomAccessStream to be passed to FFmpegMediaSource
try
{
StorageApplicationPermissions::FutureAccessList->Clear();
StorageApplicationPermissions::FutureAccessList->Add(file);

auto stream = co_await file->OpenAsync(FileAccessMode::Read);
// Instantiate FFmpegMediaSource using the opened local file stream
FFmpegMSS = co_await FFmpegMediaSource::CreateFromStreamAsync(stream, Config);

StorageApplicationPermissions::FutureAccessList->Clear();
StorageApplicationPermissions::FutureAccessList->Add(file);

playbackItem = FFmpegMSS->CreateMediaPlaybackItem();


// Pass MediaPlaybackItem to Media Element
mediaPlayer->Source = playbackItem;

Expand Down Expand Up @@ -181,8 +194,7 @@ task<void> MainPage::OpenUriStream(Platform::String^ uri)
// 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", 1000000);
Config->FFmpegOptions->Insert("timeout", 1000000);
Expand All @@ -191,6 +203,8 @@ task<void> MainPage::OpenUriStream(Platform::String^ uri)
mediaPlayer->Source = nullptr;
try
{
ApplicationData::Current->LocalSettings->Values->Insert("LastUri", uri);

FFmpegMSS = co_await FFmpegMediaSource::CreateFromUriAsync(uri, Config);
playbackItem = FFmpegMSS->CreateMediaPlaybackItem();

Expand Down Expand Up @@ -500,14 +514,38 @@ void MediaPlayerCPP::MainPage::OnKeyDown(Windows::UI::Core::CoreWindow^ sender,
TryOpenLastFile();
}

if (args->VirtualKey == Windows::System::VirtualKey::Enter && (Window::Current->CoreWindow->GetKeyState(Windows::System::VirtualKey::Shift) & Windows::UI::Core::CoreVirtualKeyStates::Down)
== Windows::UI::Core::CoreVirtualKeyStates::Down && ApplicationData::Current->LocalSettings->Values->HasKey("LastUri"))
{
TryOpenLastUri();
}

if (args->Handled)
{
return;
}

if (args->VirtualKey == Windows::System::VirtualKey::V)
{
if (playbackItem && playbackItem->VideoTracks->Size > 1)
{
playbackItem->VideoTracks->SelectedIndex =
bool reverse = (Window::Current->CoreWindow->GetKeyState(Windows::System::VirtualKey::Shift) & Windows::UI::Core::CoreVirtualKeyStates::Down) == Windows::UI::Core::CoreVirtualKeyStates::Down;
int index = reverse ?
(playbackItem->VideoTracks->SelectedIndex - 1) % playbackItem->VideoTracks->Size :
(playbackItem->VideoTracks->SelectedIndex + 1) % playbackItem->VideoTracks->Size;
playbackItem->VideoTracks->SelectedIndex = index;
}
}

if (args->VirtualKey == Windows::System::VirtualKey::Right && FFmpegMSS && mediaPlayer->PlaybackSession->CanSeek)
{
mediaPlayer->PlaybackSession->Position = TimeSpan{ mediaPlayer->PlaybackSession->Position.Duration + 50000000 };
}

if (args->VirtualKey == Windows::System::VirtualKey::Left && FFmpegMSS && mediaPlayer->PlaybackSession->CanSeek)
{
mediaPlayer->PlaybackSession->Position = TimeSpan{ mediaPlayer->PlaybackSession->Position.Duration - 50000000 };
}
}


Expand Down Expand Up @@ -560,3 +598,13 @@ void MediaPlayerCPP::MainPage::ffmpegAudioFilters_KeyDown(Platform::Object^ send
}
}
}

double MediaPlayerCPP::MainPage::GetBufferSizeMB()
{
return (double)Config->ReadAheadBufferSize / (1024*1024);
}

void MediaPlayerCPP::MainPage::SetBufferSizeMB(double value)
{
Config->ReadAheadBufferSize = (long long)(value * (1024 * 1024));
}
7 changes: 6 additions & 1 deletion Samples/MediaPlayerCPP/MainPage.xaml.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//*****************************************************************************
//*****************************************************************************
//
// Copyright 2015 Microsoft Corporation
//
Expand Down Expand Up @@ -39,11 +39,15 @@ namespace MediaPlayerCPP
property FFmpegInteropX::MediaSourceConfig^ Config;
property FFmpegInteropX::VideoEffectConfiguration^ VideoEffectConfiguration;

double GetBufferSizeMB();
void SetBufferSizeMB(double value);

private:
void OpenLocalFile(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
task<void> OpenLocalFile();
task<void> OpenLocalFile(Windows::Storage::StorageFile^ file);
task<void> TryOpenLastFile();
task<void> TryOpenLastUri();
void URIBoxKeyUp(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e);
task<void> OpenUriStream(Platform::String^ uri);
void MediaFailed(Platform::Object^ sender, Windows::UI::Xaml::ExceptionRoutedEventArgs^ e);
Expand Down Expand Up @@ -81,5 +85,6 @@ namespace MediaPlayerCPP
void ffmpegAudioFilters_KeyDown(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e);
void OnMediaOpened(Windows::Media::Playback::MediaPlayer^ sender, Platform::Object^ args);
void OnMediaFailed(Windows::Media::Playback::MediaPlayer^ sender, Windows::Media::Playback::MediaPlayerFailedEventArgs^ args);

};
}
4 changes: 4 additions & 0 deletions Samples/MediaPlayerCS/MainPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@

<ToggleSwitch Header="Fast Seeking (keyframe seeking requires PlaybackSession property to be assigned)" OffContent="OFF" OnContent="ON" IsOn="{x:Bind Mode=TwoWay, Path=Config.FastSeek}" Margin="0,20,0,0" />

<ToggleSwitch Header="Read-ahead buffering" OffContent="OFF" OnContent="ON" IsOn="{x:Bind Mode=TwoWay, Path=Config.ReadAheadBufferEnabled}" Margin="0,20,0,0" />
<Slider Minimum="1" Maximum="100" SnapsTo="StepValues" TickFrequency="10" StepFrequency="1" Header="Read-ahead buffer duration (s)" Value="{x:Bind Path=Config.ReadAheadBufferDuration, Mode=TwoWay, Converter={StaticResource TimeSpanToDoubleConverter}}" />
<Slider Minimum="1" Maximum="100" SnapsTo="StepValues" TickFrequency="10" StepFrequency="1" Header="Read-ahead buffer size (MB)" Value="{x:Bind GetBufferSizeMB(), BindBack=SetBufferSizeMB, Mode=TwoWay}" />

<Button Content="Extract Frame" Click="ExtractFrame" Margin="0,20,10,10" />
<ToggleSwitch x:Name="grabFrameExactSeek" Header="Exact Seek for Extract Frame" OffContent="OFF" OnContent="ON" IsOn="True"/>

Expand Down
95 changes: 74 additions & 21 deletions Samples/MediaPlayerCS/MainPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,38 @@ private async void MainPage_KeyDown(CoreWindow sender, KeyEventArgs args)
{
await TryOpenLastFile();
}
if (args.VirtualKey == VirtualKey.Enter && (Window.Current.CoreWindow.GetKeyState(VirtualKey.Shift) & CoreVirtualKeyStates.Down)
== CoreVirtualKeyStates.Down && ApplicationData.Current.LocalSettings.Values.ContainsKey("LastUri"))
{
await TryOpenLastUri();
}

if (args.Handled)
{
return;
}

if (args.VirtualKey == VirtualKey.V)
{
if (playbackItem != null && playbackItem.VideoTracks.Count > 1)
{
playbackItem.VideoTracks.SelectedIndex =
bool reverse = (Window.Current.CoreWindow.GetKeyState(VirtualKey.Control) & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
int index = reverse ?
(playbackItem.VideoTracks.SelectedIndex - 1) % playbackItem.VideoTracks.Count :
(playbackItem.VideoTracks.SelectedIndex + 1) % playbackItem.VideoTracks.Count;
playbackItem.VideoTracks.SelectedIndex = index;
}
}

if (args.VirtualKey == VirtualKey.Right && FFmpegMSS != null && mediaPlayer.PlaybackSession.CanSeek)
{
mediaPlayer.PlaybackSession.Position += TimeSpan.FromSeconds(5);
}

if (args.VirtualKey == VirtualKey.Left && FFmpegMSS != null && mediaPlayer.PlaybackSession.CanSeek)
{
mediaPlayer.PlaybackSession.Position -= TimeSpan.FromSeconds(5);
}
}

private async void CodecChecker_CodecRequired(object sender, CodecRequiredEventArgs args)
Expand Down Expand Up @@ -152,6 +176,18 @@ private async Task TryOpenLastFile()
{
}
}
private async Task TryOpenLastUri()
{
try
{
//Try open last uri
var uri = (string)ApplicationData.Current.LocalSettings.Values["LastUri"];
await OpenStreamUri(uri);
}
catch (Exception)
{
}
}

public MediaSourceConfig Config { get; set; }

Expand Down Expand Up @@ -227,36 +263,43 @@ private async void URIBoxKeyUp(object sender, KeyRoutedEventArgs e)
// Mark event as handled to prevent duplicate event to re-triggered
e.Handled = true;

try
{
// Set FFmpeg specific options:
// https://www.ffmpeg.org/ffmpeg-protocols.html
// https://www.ffmpeg.org/ffmpeg-formats.html
await OpenStreamUri(uri);
}
}

// If format cannot be detected, try to increase probesize, max_probe_packets and analyzeduration!
private async Task OpenStreamUri(string uri)
{
try
{
ApplicationData.Current.LocalSettings.Values["LastUri"] = uri;

// Below are some sample options that you can set to configure RTSP streaming
// Config.FFmpegOptions.Add("rtsp_flags", "prefer_tcp");
Config.FFmpegOptions.Add("stimeout", 1000000);
Config.FFmpegOptions.Add("timeout", 1000000);
// Set FFmpeg specific options:
// https://www.ffmpeg.org/ffmpeg-protocols.html
// https://www.ffmpeg.org/ffmpeg-formats.html

// Instantiate FFmpegMediaSource using the URI
mediaPlayer.Source = null;
FFmpegMSS = await FFmpegMediaSource.CreateFromUriAsync(uri, Config);
// If format cannot be detected, try to increase probesize, max_probe_packets and analyzeduration!

var source = FFmpegMSS.CreateMediaPlaybackItem();
// Config.FFmpegOptions.Add("rtsp_flags", "prefer_tcp");
Config.FFmpegOptions.Add("stimeout", 1000000);
Config.FFmpegOptions.Add("timeout", 1000000);

// Pass MediaStreamSource to Media Element
mediaPlayer.Source = source;
// Instantiate FFmpegMediaSource using the URI
mediaPlayer.Source = null;
FFmpegMSS = await FFmpegMediaSource.CreateFromUriAsync(uri, Config);

// Close control panel after opening media
Splitter.IsPaneOpen = false;
if (AutoCreatePlaybackItem)
{
CreatePlaybackItemAndStartPlaybackInternal();
}
catch (Exception ex)
else
{
await DisplayErrorMessage(ex.Message);
playbackItem = null;
}
}
catch (Exception ex)
{
await DisplayErrorMessage(ex.Message);
}
}

private async void ExtractFrame(object sender, RoutedEventArgs e)
Expand Down Expand Up @@ -585,5 +628,15 @@ private void ffmpegAudioFilters_LostFocus(object sender, RoutedEventArgs e)
Config.FFmpegAudioFilters = ffmpegAudioFilters.Text;
FFmpegMSS?.SetFFmpegAudioFilters(ffmpegAudioFilters.Text);
}

private double GetBufferSizeMB()
{
return Config.ReadAheadBufferSize / (1024 * 1024);
}

private long SetBufferSizeMB(double value)
{
return Config.ReadAheadBufferSize = (long)(value * (1024 * 1024));
}
}
}
18 changes: 1 addition & 17 deletions Samples/MediaPlayerWinUI/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,4 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Microsoft.UI.Xaml.Shapes;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Microsoft.UI.Xaml;

// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
Expand Down
31 changes: 26 additions & 5 deletions Samples/MediaPlayerWinUI/MainPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
Expand Down Expand Up @@ -89,14 +85,39 @@ private async void MainPage_KeyDown(object sender, KeyRoutedEventArgs args)
{
await TryOpenLastFile();
}

if (args.Key == VirtualKey.Enter && (Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Shift) & CoreVirtualKeyStates.Down)
== CoreVirtualKeyStates.Down && StorageApplicationPermissions.FutureAccessList.Entries.Count == 1)
{
await TryOpenLastFile();
}

if (args.Handled)
{
return;
}

if (args.Key == VirtualKey.V && !args.Handled)
{
if (playbackItem != null && playbackItem.VideoTracks.Count > 1)
{
playbackItem.VideoTracks.SelectedIndex =
bool reverse = (Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Control) & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
int index = reverse ?
(playbackItem.VideoTracks.SelectedIndex - 1) % playbackItem.VideoTracks.Count :
(playbackItem.VideoTracks.SelectedIndex + 1) % playbackItem.VideoTracks.Count;
playbackItem.VideoTracks.SelectedIndex = index;
}
}

if (args.Key == VirtualKey.Right && FFmpegMSS != null && mediaPlayer.PlaybackSession.CanSeek)
{
mediaPlayer.PlaybackSession.Position += TimeSpan.FromSeconds(5);
}

if (args.Key == VirtualKey.Left && FFmpegMSS != null && mediaPlayer.PlaybackSession.CanSeek)
{
mediaPlayer.PlaybackSession.Position -= TimeSpan.FromSeconds(5);
}
}

private void CodecChecker_CodecRequired(object sender, CodecRequiredEventArgs args)
Expand Down
Loading