Possible Memory leak in FFMPEGAutogen Example - c#

I'm using the https://github.com/Ruslan-B/FFmpeg.AutoGen library to connect to an rtsp camera stream and save the frames as png images.
Testing with the FFMPEG.Autogen's example project present in the GitHub repository with no changes I've noticed that the memory usage seems to constantly grow in infinitely. I've made sure to dispose of all bitmaps, pointers etc after use but am unable to pinpoint the source of the issue.
It seems to be coming from their VideoStreamDecoder.TryDecodeNextFrame method as shown below:
public bool TryDecodeNextFrame(out AVFrame frame)
{
ffmpeg.av_frame_unref(_pFrame);
ffmpeg.av_frame_unref(_receivedFrame);
int error;
do
{
try
{
do
{
error = ffmpeg.av_read_frame(_pFormatContext, _pPacket);
if (error == ffmpeg.AVERROR_EOF)
{
frame = *_pFrame;
return false;
}
else if(error < 0)
{
}
error.ThrowExceptionIfError();
} while (_pPacket->stream_index != _streamIndex);
ffmpeg.avcodec_send_packet(_pCodecContext, _pPacket).ThrowExceptionIfError();
}
finally
{
ffmpeg.av_packet_unref(_pPacket);
}
error = ffmpeg.avcodec_receive_frame(_pCodecContext, _pFrame);
} while (error == ffmpeg.AVERROR(ffmpeg.EAGAIN));
error.ThrowExceptionIfError();
if (_pCodecContext->hw_device_ctx != null)
{
ffmpeg.av_hwframe_transfer_data(_receivedFrame, _pFrame, 0).ThrowExceptionIfError();
frame = *_receivedFrame;
}
else
{
frame = *_pFrame;
}
return true;
}

Related

Understand Kinect Facetracker.track() method

I'm Using Kinect v1 with SDK 1.8. I need to pass my data to faceTracker.Track() method.
But in constructor of track() is asking Skeleton parameter at the end.
But cannot take directly skeleton data to skeleton object. It provides as an data array.
How can I pass data to this faceTracker.Track() method as the track method requested?
The following is the way I tried.
using (SkeletonFrame skeletonFrame = allFramesReadyEventArgs.OpenSkeletonFrame())
{
if (skeletonFrame != null && this.skeletonData != null) // check that a frame is available
{
skeletonData = new Skeleton [newSensor.SkeletonStream.FrameSkeletonArrayLength];
skeletonFrame.CopySkeletonDataTo(this.skeletonData); // get the skeletal information in this frame
this.skeletonData = new Skeleton[this.newSensor.SkeletonStream.FrameSkeletonArrayLength];
}
}
track method
if (faceTracker == null)
{
try
{
faceTracker = new FaceTracker(sensorChooser.Kinect);
}
catch (InvalidOperationException)
{
//write something
}
if (faceTracker != null)
{
FaceTrackFrame frame = faceTracker.Track(
sensorChooser.Kinect.ColorStream.Format,
colorImageData,
sensorChooser.Kinect.DepthStream.Format,
colorPixels,
skeletonData);
}
}
i defined Skeleton [] skeletonData ;as this
and follwing is the track method given in Kinect SDK
public FaceTrackFrame Track(
ColorImageFormat colorImageFormat,
byte[] colorImage,
DepthImageFormat depthImageFormat,
short[] depthImage,
Skeleton skeletonOfInterest)
{
return this.Track(colorImageFormat, colorImage, depthImageFormat, depthImage, skeletonOfInterest, Rect.Empty);
}
foreach (Skeleton skeleton in this.skeletonData)
{
if (skeleton.TrackingState == SkeletonTrackingState.Tracked
|| skeleton.TrackingState == SkeletonTrackingState.PositionOnly)
{
// We want keep a record of any skeleton, tracked or untracked.
if (!this.trackedSkeletons.ContainsKey(skeleton.TrackingId))
{
this.trackedSkeletons.Add(skeleton.TrackingId, new SkeletonFaceTracker());
}
// Give each tracker the upated frame.
SkeletonFaceTracker skeletonFaceTracker;
if (this.trackedSkeletons.TryGetValue(skeleton.TrackingId, out skeletonFaceTracker))
{
skeletonFaceTracker.OnFrameReady(this.Kinect, colorImageFormat, colorImage, depthImageFormat, depthImage, skeleton);
skeletonFaceTracker.LastTrackedFrame = skeletonFrame.FrameNumber;
}
}
}
I solved it as above with the help of kinect toolkit 1.8 the project FaceTrackingBasics-WPF application.

.SendMessage Crashes Unity C#

I am using a OverlapSphere to detect all colliders within a certain radius of my object. I then filter out a few I don't care about. With the remaining few, I attempt to send a message to those objects to update their render color. Whenever it sends the message, unity freezes. I tried to do some research and the best thing i could find is that infinite loops can freeze it. But i don't see a potential for that. Here is the code:
Object to send the message:
void sendmyMessage(bool status)
{
Collider[] tiles = Physics.OverlapSphere(gameObject.transform.position, 10);
int i = 0;
while (i < tiles.Length)
{
if(tiles[i].tag == "Tile")
{
//turn light on
if (status == true)
{
tiles[i].SendMessage("Highlight", true);
i++;
}
//turn light off
if (status == false)
{
tiles[i].SendMessage("Highlight", false);
i++;
}
}
}
}
Object Receiving Message:
void Highlight(bool status)
{
//turn light on
if(status == true)
{
gameObject.GetComponent<Renderer>().material.color = new Color(0, 0, 0);
}
//turn light off
if(status == false)
{
gameObject.GetComponent<Renderer>().material.color = new Color(1, 1, 1);
}
}
Any help is much appreciated!
It freezes because of logic if(tiles[i].tag == "Tile") here's your answer. Now imagine that object that you collide with has tag "not a tile"? then the loop never ends.
foreach(var tile in tiles) {
if (tile.tag == "Tile") {
tiles[i].SendMessage("Highlight", status);
}
}
while (i < tiles.Length)
{
if(tiles[i].tag == "Tile")
{
//snip
}
// else - loop forever?
}
Here's your problem. If the tag != "Tile" then you never increment i.

Implement Dispose to my method

I have a Winform application that uses Pcapdot.Net DLLs and plays Pcap files.
When I am playing a file in a loop I can see that the application memory is raised until a crash occurs and in stack trace I can see that this happens in the method that plays the file.
So I was thinking to add dispose method and see if it can solve this crash.
So I added to my class a variable private bool _disposed;
and methods:
public void Dispose()
{
Dispose(true);
}
private virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
}
_disposed = true;
}
}
my play method:
public bool sendBuffer(PacketDevice packetDevice)
{
int count = 0;
bool bContinuePlay = true;
PacketDevice selectedOutputDevice = packetDevice;
_shouldContinue = true;
_isStop = true;
_stopButton = true;
OfflinePacketDevice selectedInputDevice = new OfflinePacketDevice(_filePath.FullName); //open the capture file
DateTime time = DateTime.Now;
double totalTime = 0;
double totalDelayTime = 0;
double deletaTime = 0;
using (inputCommunicator = selectedInputDevice.Open(65536, PacketDeviceOpenAttributes.Promiscuous, 1000))
{
using (OutputCommunicator = selectedOutputDevice.Open(100, PacketDeviceOpenAttributes.Promiscuous, 1000))
{
ThreadStart tStarter = delegate { openAdapterForStatistics(selectedOutputDevice); };
Thread thread = new Thread(tStarter);
thread.IsBackground = true;
thread.Start();
DateTime lastTime = DateTime.MinValue;
double delayTime = 0;
Packet packet;
IEnumerable<Packet> packets;
while (inputCommunicator.ReceivePacket(out packet) == PacketCommunicatorReceiveResult.Ok && _isStop) //fill the buffer with the packets from the file
{
if (count < _numberOfPacketsInfile)
{
using (PacketSendBuffer mSendBuffer = new PacketSendBuffer((uint)packet.Length * 4))
{
if (_isBurst)
{
if (lastTime != DateTime.MinValue)
{
if (packet != null)
{
delayTime = (packet.Timestamp.Subtract(lastTime).TotalMilliseconds) / _playSpeed; //delay between packets
}
if (delayTime > 1000)
{
if (_startTimer != null)
{
_startTimer(delayTime, EventArgs.Empty);
}
_delayForNextPacket = delayTime;
}
totalDelayTime += delayTime;
delayTime = delayTime - deletaTime;
if (delayTime < 0)
{
delayTime = 0;
}
if (evePacketProgress != null)
{
int packetProgressPrecentage = (int)(((double)_numberOfSendPackets / _numberOfPacketsInfile) * 100);
evePacketProgress(packetProgressPrecentage);
}
_mrEvent.WaitOne((int)delayTime);
if (_stopTimer != null)
{
_stopTimer(delayTime, EventArgs.Empty);
}
} //end if
} // end if _brust
if (_fragmentation)
{
foreach (Packet item in splitPacket(packet, 1))
{
mSendBuffer.Enqueue(item);
}
}
else if (packet != null)
{
lastTime = packet.Timestamp;
mSendBuffer.Enqueue(packet);
}
if (evePacketProgress != null)
{
int packetProgressPrecentage = (int)(((double)_numberOfSendPackets / _numberOfPacketsInfile) * 100);
evePacketProgress(packetProgressPrecentage);
}
try
{
OutputCommunicator.Transmit(mSendBuffer, _isBurst); //send the packet
_numberOfSendPackets++;
}
catch (Exception)
{
}
}///
totalTime = DateTime.Now.Subtract(time).TotalMilliseconds;
deletaTime = totalTime - totalDelayTime;
count++;
}
} //end while
}
}
return bContinuePlay;
}
the crash occur in the line DateTime lastTime = DateTime.MinValue;
I am a new developer and do not know how to proceed from here.
Any help is welcome
The Dispose method is used to free unmanaged resources, in other words, what isn't in ".NET World", like a TCP or database connection.
When CLR finds that your program is running out of memory, it automaticaly invokes Garbage Collector, that free the objects you are not using anymore.
You only need to implement IDisposable if you have to free unmanaged resources. For details implementing IDisposable, you can find a lot of articles online. For instace, you are forgeting of implement your class finalizer.
So, if the problem is in the method that play the files, you must first find what is causing the memory to increase and cannot be released by GC.
I don't know Pcapdot.Net, but try to find a method for releasing the file being played, or something like this. Maybe you don't need to implement IDisposable, just add the call for this method.

Can't Beat 'Out Of Memory' Exceptions

I am developing an app with Mono for Android.
I have been struggling with Out of memory exceptions for the last few days and am starting to lose hope!
I have a ListView displaying anything from 200 to 600 items. These items consist of a bitmap thumbnail and some text.
I am decoding the Bitmap asynchronously using an AsyncTask, here is the code:
public class BitmapWorkerTask : AsyncTask
{
private WeakReference imageViewReference;
public string thisURL = "";
private int sampleSize = 0;
private int reqHeight = 0;
private int reqWidht = 0;
public BitmapWorkerTask(ImageView imageView, int pSampleSize, int pReqWidth, int pReqHeight)
{
//_____________________________________________________________________
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference(imageView);
reqHeight = pReqHeight;
reqWidht = pReqWidth;
sampleSize = pSampleSize;
}
protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] #params)
{
string strUrl = #params[0].ToString();
try
{
return DecodeSampleBitmapFromStream(strUrl, reqWidht, reqHeight);
}
catch (Exception ex)
{
return null;
}
}
protected override void OnPostExecute(Java.Lang.Object result)
{
base.OnPostExecute(result);
if (IsCancelled)
{
result = null;
Log.Debug("TT", "OnPostExecute - Task Cancelled");
}
else
{
Bitmap bmpResult = result as Bitmap;
if (imageViewReference != null && bmpResult != null)
{
ImageView view = imageViewReference.Target as ImageView;
if (view != null)
{
view.SetImageBitmap(bmpResult);
}
}
}
}
public static int CalculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight)
{
//_____________________________
// Raw height and width of image
int height = options.OutHeight;
int width = options.OutWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth)
{
if (width > height)
{
inSampleSize = (int)Math.Round((float)height / (float)reqHeight);
}
else
{
inSampleSize = (int)Math.Round((float)width / (float)reqWidth);
}
}
return inSampleSize;
}
public static Bitmap DecodeSampleBitmapFromStream(string URL, int reqWidth, int reqHeight)
{
URL url = new URL(URL);
try
{
//______________________________________________________________
// First decode with inJustDecodeBounds=true to check dimensions
BitmapFactory.Options options = new BitmapFactory.Options();
options.InJustDecodeBounds = true;
BitmapFactory.DecodeStream(url.OpenConnection().InputStream, null, options);
//______________________
// Calculate inSampleSize
options.InSampleSize = CalculateInSampleSize(options, reqWidth, reqHeight);
//____________________________________
// Decode bitmap with inSampleSize set
options.InJustDecodeBounds = false;
return BitmapFactory.DecodeStream(url.OpenConnection().InputStream, null, options);
}
catch (Exception ex)
{
return null;
}
finally
{
url.Dispose();
}
}
I am starting this AsyncTask from the Lists GetView() function using this Method:
public void loadBitmap(string url, ImageView imageView)
{
if (Common.cancelPotentialWork(url, imageView))
{
BitmapWorkerTask task = new BitmapWorkerTask(imageView, 2, 80,80);
AsyncDrawable asyncDrawable = new AsyncDrawable(null, null, task);
imageView.SetImageDrawable(asyncDrawable);
task.Execute(url);
}
}
Everything works as expected for a period of time, but if I continuously scroll up and down through my list I eventually start getting OutOfMemoryExceptions and the app crashes. My understanding of how the Android list works is it disposes of the ListItem views as they move off screen, but it feels as though this is not happening!
It feels like all those bitmaps I am decoding as I scroll through the list are for whatever reason being held in memory? What could I be missing here that is preventing those bitmaps from being disposed of? Where could I implement a call to Bitmap.Recycle() to ensure the bitmaps are cleared?
I did a test whereby I made a call to GC.Collect on every call to GetView which did seem to keep my memory usage fairly consistent, but I know this shouldn't be needed and it affects scrolling performance.
Why when I scroll through my list without the call to GC.Collect() am I not seeing those garbage collection message indicating that the system is, in fact, doing routine collections?
Any help is appreciated, I am losing the will to code!
My understanding of how the Android list works is it disposes of the List item views as they move off screen, but It feels as though this is not happening!
This isn't correct.
What Android does is it hold on to the set of item views and it tries to reuse them after they have gone off screen. This is what the convertView parameter is for.
I can't see your Adapter code posted in the question, so I'm not sure what your code is for using the convertView parameter, but I'd guess what it should do in the case of a convertView is:
it should cancel any existing async image fetch/conversion
it should start a new one
The MvvmCross code may be a little too complicated for you as a reference/example here, but you can at least see convertView in use in MvxBindableListAdapter.cs - see protected virtual View GetBindableView(View convertView, object source, int templateId)

NullReferenceException on OpenSkeletonFrame

Hello, I get a NullReferenceException when running this:
void newSensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
Skeleton first = GetFirstSkeleton(e);
if (first == null)
{
return;
}
/**
* #TODO
* obsluzyc wyjatek null reference na wypadek gdy gubi szkielet
*/
long timestamp = e.OpenSkeletonFrame().Timestamp;
it is in the line of long timestamp
It occurse while 10-15 seconds if same action. For example I'm logging some data standing still. I log them in every frame. After few seconds I get the NullReferenceException.
What is the problem?
Ok so I fouund answer for my problem. It is very simple.
Whe my system/machine is overloaded or it slows down from any other reason frames ain`t analyzed as fast as they sould. That whey when this lag occurs I can't open a frame. Thats why I get null.
Bellow solution of the problem
bool haveSkeletonData = false;
using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
if (skeletonFrame != null)
{
if ((this.skeletonData == null) || (this.skeletonData.Length != skeletonFrame.SkeletonArrayLength))
{
this.skeletonData = new Skeleton[skeletonFrame.SkeletonArrayLength];
}
skeletonFrame.CopySkeletonDataTo(skeletonData);
haveSkeletonData = true;
}
else
{
haveSkeletonData = false;
}
}
if (haveSkeletonData)
{
// here i can put code that is using my timestamp
}
That way I'll be safe from null and I'll be able to use my timestamp as I need to :)

Categories