Baseflow / XamarinMediaManager

Cross platform Xamarin plugin to play and control Audio and Video
https://baseflow.com
MIT License
769 stars 306 forks source link

[UWP] Main Thread Error playing Mp3 when extracting mp3 album cover. #694

Open MichaelPeter opened 4 years ago

MichaelPeter commented 4 years ago

πŸ› Bug Report

Hi, I have some issue with the player. I am making a Xamarin Forms app completly running async I am testing on a UWP App for the desktop.

System.Exception: The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))\r\n at Windows.UI.Xaml.Media.Imaging.BitmapImage..ctor()\r\n at MediaManager.Platforms.Uap.Media.StorageFileProvider.ProvideImage(IMediaItem mediaItem)\r\n at MediaManager.Media.MediaExtractorBase.GetMediaImage(IMediaItem mediaItem)\r\n at MediaManager.Media.MediaExtractorBase.UpdateMediaItem(IMediaItem mediaItem)\r\n at MediaManager.Media.MediaExtractorBase.CreateMediaItem(String url)\r\n at MediaManager.Media.MediaExtractorBase.CreateMediaItem(FileInfo file)\r\n at MediaManager.MediaManagerBase.Play(FileInfo file)\r\n at ...

Now I looked a bit in the sourcecode and the Problem seems to be when extracting the album cover the BitmapImage is created asyncronusly but the BitmapImage is a old Windows class which needs to be executed on the main thread.

I already tried calling it from MainThread.InvokeOnMainThreadAsync but that doesn't help since the bitmap is extracted asyncronosly.

Now I am suprised that this error hasn't happend before. Also it seems not to happen with all mp3s which have covers only with certain.

Here is a mp3 where the error can be reproduced: https://1drv.ms/u/s!AkY5QCCnUjHgiOYzAzWc3Lybpav3gw?e=mKipiD

Expected behavior

Plays

Reproduction steps

Create a new UWP App. Calll player.Play(new FileInfo(contentFullPath)); with the mp3 with album cover proced before.

Try multiple times to quickly after each other to play one file

Configuration

Version: 0.96 - not the 0.97 since I still use Android 9.0 and UWP Build 18362 not 10.0 since I cannot use it.

Platform:

MichaelPeter commented 4 years ago

I have a possible solution, but I think maybe it is better to look for a more fitting solution, maybe another class than Bitmap image:

First I copied the code from the UWP StorageFileProvider into a own custom class in the UWP project:

https://github.com/Baseflow/XamarinMediaManager/blob/c7ef228247198072e4ce6122ac73c6b0ce98e300/MediaManager/Platforms/Uap/Media/StorageFileProvider.cs

There I changed that the BitmapImage is called inside the dispatcher - again very rough solution. Seems slow on, the song needs longer to load than others:

await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    //await Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    {
                        BitmapSource bitmap = new BitmapImage();
                        //await bitmap.SetSourceAsync(thumbnail);
                        bitmap.SetSource(thumbnail);
                        image = bitmap;
                    });

Then I replaced the extractor with my own provider.

global::MediaManager.CrossMediaManager.Current.Init();
IList<IMediaExtractorProvider> provs = MediaManager.CrossMediaManager.Current.Extractor.Providers;
            provs.Clear();
            provs.Add(new CustomMediaExtractor());

Working but seems very slow needs more investigation.

venetasoft commented 3 years ago

I have a possible solution, but I think maybe it is better to look for a more fitting solution, maybe another class than Bitmap image:

First I copied the code from the UWP StorageFileProvider into a own custom class in the UWP project:

https://github.com/Baseflow/XamarinMediaManager/blob/c7ef228247198072e4ce6122ac73c6b0ce98e300/MediaManager/Platforms/Uap/Media/StorageFileProvider.cs

There I changed that the BitmapImage is called inside the dispatcher - again very rough solution. Seems slow on, the song needs longer to load than others:

await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    //await Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    {
                        BitmapSource bitmap = new BitmapImage();
                        //await bitmap.SetSourceAsync(thumbnail);
                        bitmap.SetSource(thumbnail);
                        image = bitmap;
                    });

Then I replaced the extractor with my own provider.

global::MediaManager.CrossMediaManager.Current.Init();
IList<IMediaExtractorProvider> provs = MediaManager.CrossMediaManager.Current.Extractor.Providers;
            provs.Clear();
            provs.Add(new CustomMediaExtractor());

Working but seems very slow needs more investigation.

You are a F***** GENIUS !!!