Why I'm receiving Access Violation Exception when try to dispose VideoView in LibVLCSharp - c#

I'm using Stylet as MVVM framework and LibVLCSharp.WPF 3.6.5 + VideoLAN.LibVLC.Windows 3.0.16 in my project for streaming camera rtsp streams.
VideoView is included in my VLCPLayer custom user control, and that control is exposed as a property in my view model. I don't know if this is a good thing, but in this way I managed to make some kind of custom full screen video with custom buttons.
Everything works fine until I try to close player, or better to say try to dispose VideoView.
I have something like this:
public void Dispose()
{
//these are custom events in my user control
VlcPlayer.ClosePlayer -= ClosePlayer;
VlcPlayer.RestorePlayer -= RestorePlayer;
VlcPlayer.MinimizePlayer -= MinimizePlayer;
//here I try to dispose player and VideoView
VlcPlayer.VideoView.MediaPlayer.Stop();
VlcPlayer.VideoView.MediaPlayer.Media.Dispose();
VlcPlayer.VideoView.MediaPlayer.Dispose();
//here I'm getting Access Violation Exception
VlcPlayer.VideoView.Dispose();
}
If I don't dispose VideoView it remains in memory and every time I start new stream new VideoView is added to memory, so if I opened and closed one stream and then opened the same or whatever stream, I'll have in memory 2 VideoViews instead of one. I have to release memory of unused VideoViews and players since application will be used for some kind of surveillance, so it will have lot of streams at the same time opened, and lot of VideoViews opened.
Here I found similar issue, but it was reportedly solved updating to newest version of LibVLCSharp, but my version is newer than from mentioned post and I still have similar problem.
I'd appreciate any kind of help on this issue. Thanks.

Related

UWP - DataPackage.OperationCompleted is EMPTY & gets called by nobody

I'm writing a UWP file manager and I've come to a problem with drag&drop. I'm probably just beating my head against the wall since this is obviously another bug in the platform, but this time I can't find any workaround.
When dragging files and dropping them into File Explorer everything is fine. I fill up the DataPackage and listen to the OperationCompleted event, which happens when the files finished moving to another folder. When I drop them into another view within my app, I can call DataPackageView.ReportOperationCompleted, which does work (sort of). The problem is, it's also called AUTOMATICALLY at the same time the drop happens, even though the operation is not finished yet - and I can't do anything about it. The call stack is completely empty when I hit a breakpoint in the event handler.
On top of that, when I actually look into the arguments of OperationCompleted, the Operation in OperationCompletedEventArgs is ALWAYS None! It's None when File Explorer does the job, it's None when it gets called automatically, it's None when I call it manually, NO MATTER WHAT argument I pass in. Any explanation for this, Microsoft? I'm tired of fixing your bugs, especially when I can't actually do it since the platform is so limited.
one other "curiosity" with drag&dropping files in UWP is that if you get files dropped in your app and a requested operation set to move - you can't actually move them - the files are read-only. Try explaining that to the user.
Not sure how you to move files. In general, you should use StorageFile.CopyAsync method. You could use try/catch block to wrap this operation like the follwing:
try
{
var operation = appFile.File.CopyAsync(ApplicationData.Current.LocalFolder, appFile.File.DisplayName, NameCollisionOption.GenerateUniqueName);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("exception msg: "+ex.Message);
}
Then if the file is readonly, you will get exception message, you should use this message to notify user.
I wanted a notification for when the operation is actually done.
You should implemente AsyncOperationWithProgressCompletedHandler for your async operation, then you will get notification when it's completed.
operation.Completed = (tresult,tprogress) => { System.Diagnostics.Debug.WriteLine("progress msg: "+tprogress); };

Audio disposing problems using AudioVideoPlayback library

I'm trying to make playlist, where music plays one after another. I need to Dispose() Audio, when it finishes, because memory leak will occur. I wrote this code:
Audio a = new Audio(#"Music\Title.ogg");
a.Ending += new EventHandler((sender, e) => { (sender as Audio).Dispose(); });
a.Play();
The problem is that I have System.AccessViolationException in Application.Run(new MainForm());: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. It happens in ending event handler right after music finishes playing.
So, how can I play some music files one after another and dispose previous audio afer it finishes?
Don't dispose Audio inside it's own event because this class may want to do some bookkeeping work after invoking your handler.
I don't know logic of your applications but here are some idea, try to call Open on this object inside event handler. It should be smart enough to dispose old data and load new.

OutOfMemoryException # WriteableBitmap # background agent

I have a Windows Phone 8 App, which uses Background agent to:
Get data from internet;
Generate image based on a User Control that uses the data from step 1 as data source;
In the User Control I have Grid & StackPanel & some Text and Image controls;
When some of the Images use local resources from the installation folder (/Assets/images/...)
One of them which I used as a background is selected by user from the phone's photo library, so I have to set the source using C# code behind.
However, when it runs under the background, it get the OutOfMemoryException, some troubleshooting so far:
When I run the process in the "front", everything works fine;
If I comment out the update progress, and create the image directly, it also works fine;
If I don't set the background image, it also works fine;
The OutOfMemoryException was thrown out during var bmp = new WriteableBitmap(480, 800);
I already shrink the image size from 1280*768 to 800*480, I think it is the bottom line for a full screen background image, isn't it?
After some research, I found out this problem occurs because it exceeded the 11 MB limitation for a Periodic Task.
I tried use the DeviceStatus.ApplicationCurrentMemoryUsage to track the memory usage:
-- the limitation is 11,534,336 (bit)
-- when background agent started, even without any task in it, the memory usage turns to be 4,648,960
-- When get update from internet, it grew up to 5,079,040
-- when finished, it dropped back to 4,648,960
-- When the invoke started (to generate image from the User Control), it grew up to 8,499,200
Well, I guess that's the problem, there is little memory available for it to render the image via WriteableBitmap.
Any idea how to work out this problem?
Is there a better method to generate an image from a User Control / or anything else?
Actually the original image might only be 100 kb or around, however, when rendering by WriteableBitmap, the file size (as well as the required memory size I guess) might grew up to 1-2MB.
Or can I release the memory from anywhere?
==============================================================
BTW, when this Code Project article says I can use only 11MB memory in a Periodic Task;
However, this MSDN article says that I can use up to 20 MB or 25MB with Windows Phone 8 Update 3;
Which is correct? And why am I in the first situation?
==============================================================
Edit:
Speak of the debugger, it also stated in the MSDN article:
When running under the debugger, memory and timeout restrictions are suspended.
But why would I still hit the limitation?
==============================================================
Edit:
Well, I found something seems to be helpful, I will check on them for now, suggestions are still welcome.
http://writeablebitmapex.codeplex.com/
http://suchan.cz/2012/07/pro-live-tiles-for-windows-phone/
http://notebookheavy.com/2011/12/06/microsoft-style-dynamic-tiles-for-windows-phone-mango/
==============================================================
The code to generate the image:
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
var customBG = new ImageUserControl();
customBG.Measure(new Size(480, 800));
var bmp = new WriteableBitmap(480, 800); //Thrown the **OutOfMemoryException**
bmp.Render(customBG, null);
bmp.Invalidate();
using (var isf = IsolatedStorageFile.GetUserStoreForApplication())
{
filename = "/Shared/NewBackGround.jpg";
using (var stream = isf.OpenFile(filename, System.IO.FileMode.OpenOrCreate))
{
bmp.SaveJpeg(stream, 480, 800, 0, 100);
}
}
}
The XAML code for the ImageUserControl:
<UserControl blabla... d:DesignHeight="800" d:DesignWidth="480">
<Grid x:Name="LayoutRoot">
<Image x:Name="nBackgroundSource" Stretch="UniformToFill"/>
//blabla...
</Grid>
</UserControl>
The C# code behind the ImageUserControl:
public ImageUserControl()
{
InitializeComponent();
LupdateUI();
}
public void LupdateUI()
{
DataInfo _dataInfo = new DataInfo();
LayoutRoot.DataContext = _dataInfo;
try
{
using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var isoFileStream = isoStore.OpenFile("/Shared/BackgroundImage.jpg", FileMode.Open, FileAccess.Read))
{
BitmapImage bi = new BitmapImage();
bi.SetSource(isoFileStream);
nBackgroundSource.Source = bi;
}
}
}
catch (Exception) { }
}
When DataInfo is another Class within the settings page that hold data get from the internet:
public class DataInfo
{
public string Wind1 { get { return GetValueOrDefault<string>("Wind1", "N/A"); } set { if (AddOrUpdateValue("Wind1", value)) { Save(); } } }
public string Wind2 { get { return GetValueOrDefault<string>("Wind2", "N/A"); } set { if (AddOrUpdateValue("Wind2", value)) { Save(); } } }
//blabla...
}
If I comment out the update progress, and create the image directly, it also works fine I think you should focus on that part. It seems to indicate some memory isn't freed after the update. Make sure all the references used during the update process go out of scope before rendering the picture. Forcing a garbage collection can help too:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect(); // Frees the memory that was used by the finalizers
Another thing to consider is that the debugger is also using a lot of memory. Do a real test by compiling your project in "Release" mode and deploying on a phone to make sure you're running out of memory.
Still, I have already been in that situation so I know it may not be enough. The point is: some libraries in the .NET Framework are loaded lazily. For instance, if your update process involves downloading some data, then the background agent will load the network libraries. Those libraries can't be unloaded and will waste some of your agent's memory. That's why, even by freeing all the memory you used during the update process, you won't reach back the same amount of free memory you had when starting the background agent. Seeing this, what I did in one of my app was to span the workload of the background agent across two executions. Basically, when the agents executes:
Check in the isolated storage if there's pending data to be processed. If not, just execute the update process and store all needed data in the isolated storage
If there is pending data (that is, in the next execution), generate the picture and clear the data
It means the picture will be generated only once every hour instead of once every 30 minutes, so use this workaround only if everything else fail.
The larger memory limit is for background audio agents, it clearly states that in the documentation. You're stuck with 11 MB, which can really be a big pain when you're trying to do something smart with pictures in the background.
480x800 adds a MB to your memory because it takes 4 bytes for every pixels, so in the end it's around 1.22MB. When compressed in JPEG, then yes - it makes sense that it's only around 100KB. But whenever you use WriteableBitmap, it gets loaded into memory.
One of the things you could try before forcing the GC.Collect as mentioned in another answer is to null things out even before they go out of scope - whether it's a BitmapImage or a WriteableBitmap. Other than that you can try removing the Image object from the Grid programmatically when you're done and setting the Source of it also to be null.
Are there any other WriteableBitmap, BitmapImage or Image objects you're not showing us?
Also, try without the debugger. I've read somewhere that it adds another 1-2MB which is a lot when you have only 11 MB. Although, if it crashes so quickly with the debugger, I wouldn't risk it even if it suddenly seams OK without the debugger. But just for testing purposes you can give it a shot.
Do you need to use the ImageUserControl? Can you try doing step by step creating Image and all the other objects, without the XAML, so you can measure memory in each and every step to see at which point it goes through the roof?

Forcing MediaElement to Release Stream after playback

I am creating an audio recorder control, with playback functionality.
I use the media element to play the recorded audio like this:
using (var storage = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication())
{
using (System.IO.Stream stream = new System.IO.IsolatedStorage.IsolatedStorageFileStream(filePath, System.IO.FileMode.Open, storage))
{
player.SetSource(stream);
}
}
The problem i am facing is that when I use media element to play the recorded audio. The Stream is locked to the media element. I cannot overwrite the file or even play it again as the SetSource() method throws an exception.
Is there a way to force the media element to release the stream?
Based on #Sheridan answer this it what I came up with that works.
Whenever MediaElement is stopped using Stop() function set the Source Property to null like this:
ResetMediaElement()
{
mediaElement.Stop();
mediaElement.Source = null;
}
This will close the stream attached to the media element, so that the related resource can be used somewhere else.
If you use MediaElement, make sure you don't get bitten by this one:
http://msdn.microsoft.com/en-us/library/cc626563(v=vs.95).aspx
ArgumentNullException - The mediaStreamSource is null.
...
After calling this method, MediaElement.Source returns null. If this
is called and MediaElement.Source is set, the last operation wins.
If a MediaElement is removed from the UI tree while is has an opened
MediaStreamSource, subsequent calls to SetSource may be ignored. To
ensure featureSetSource calls will work, set the Source property to
null before detaching the MediaElement from the UI tree.
naturally one would expect, if they only use SetSource(somestream) to use SetSource(null) to release the resources. Nope, they thought "better", you have to use Source=null instead to release resources and SetSource(null) throws ArgumentNullException
that is what I call a design bug (breaks the rule of "least expected" behavior and causes bugs that bite you at runtime only [unless somebody has made a static analysis rule to catch such a thing - would need metadata of course that some argument can't be null, like in Code Contracts])
I managed to introduce this bug while refactoring some code in ClipFlair Studio's AudioRecorder control the other day :-(
Note that you can’t use at MediaElement something like Source = stream to open a Stream, since that is a Uri property (not an Object property to also accept Stream) and you have to use SetSource(stream) instead, so you’d also expect to be able to use SetSource(null) to release the resources.
Update: Fixed this in AudioRecorderView class (uses MVVM pattern) of AudioRecorderControl, at Audio property’s "set" accessor it needed the following null-guarding pattern:
if (mediaStreamSource != null)
player.SetSource(mediaStreamSource);
//must set the source once, not every time we play the same audio,
//else with Mp3MediaSource it will throw DRM error
else
player.Source = null;
mediaElement.Stop();
mediaElement.ClearValue(MediaElement.SourceProperty);
I had a similar problem with displaying images. In a control with an image, I would get a 'File is in use' error whenever the user tried to update the image. The solution was to set the BitmapImage.CacheOption property to BitmapCacheOption.OnLoad:
MSDN says Set the CacheOption to BitmapCacheOption.OnLoad if you wish to close a stream used to create the BitmapImage. The default OnDemand cache option retains access to the stream until the image is needed, and cleanup is handled by the garbage collector.
After searching for a similar property that you could use for your MediaElement, it turns out that there isn't one. However, according to an answer on the chacheoption for mediaelement post from MSDN, there is a (long winded) way to achieve this... from the relevant answer:
I am not sure if your MediaElement is in an UserControl or not. but
whatever the case you can set the UserControl or Control to
IsEnabled=false, which in turn will trigger the Event Handler
IsEnabledChanged. In it place the necessary code to stop the
MediaElement from playback ME.Stop(), then call ME.Clear() and
ME.Source = null. After that you should find no problems to delete the
source file.
ME.Source = new Uri(MediaFilePath);
ME.Play();
...
private void DeleteButton_Click(object sender, RoutedEventArgs e)
{
ME.IsEnabled = false; // This will call the Event Handler IsEnabledChanged
System.IO.File.Delete(MediaFilePath);
// Now after the player was stopped and cleared and source set to null, it
// won't object to deleting the file
}
private void ME_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
ME.Stop();
ME.Clear();
ME.Source = null;
}
I hope that this helps.

AForge.NET Leaks Handles

i have a program i am working on, we found a memory leak quite some time ago, and have managed to solve the inital issue, however now we have found that our AForge.net video player is leaking Handles, we are disposing the controls but for some reason the handles are never released.
the window that uses the AForge.Net video controls is a bubble that pops up and tells the user some information, and if a video source is available, its displayed, we have found that if we dont provide a video source, the handles are released correctly, however anytime we show a video stream, the handles are not release and eventually we hit 15,000 handles and the application crashes, telling us AForge.NET is the faulting module.
the disposing code is below.
if (videoSourcePlayer != null)
{
if (videoSourcePlayer.VideoSource != null)
{
// clearing the event subscription
videoSourcePlayer.VideoSource.PlayingFinished -= VideoSource_PlayingFinished;
// remove refernce to video source
videoSourcePlayer.VideoSource = null;
}
if (videoSourcePlayer.IsRunning && _openVideoAlarmsCount < 1)
{
videoSourcePlayer.Stop();
}
if (videoSourcePlayer.IsRunning)
{
videoSourcePlayer.VideoSource.Stop();
}
videoSourcePlayer.Click -= videoSourcePlayer_Click;
// dispose video player
videoSourcePlayer.Dispose();
videoSourcePlayer = null;
}
videoSourcePlayer is the name of the control on the WinForm , i beleve its being disposed correctly, but no matter what i try i cannot get it to release the handles correctly, i cannot share to much of the code, but i can try to answer any questions that anyone has that may help in correcting the issue, or atleast identifying the bug.
note: we are using Winforms + .NET 3.5 SP1 and the latest AForge.net from http://www.aforgenet.com/news/2012.02.23.releasing_framework_2.2.4.html
Thank you in advance for the help!

Categories