juliusfriedman/net7mma_core

Out of memory when streaming jpg files

aalmik opened this issue · 1 comments

I'm trying to stream jpg files that I am generating with PowerShell script to the directory.
For some reasons after running a while I get out of memory exception.
Streaming works with VLC but only part of the picture is visible.

This is my media type setting.

Media.Rtsp.Server.MediaTypes.RFC2435Media tcpStream =
                       new Media.Rtsp.Server.MediaTypes.RFC2435Media(rtspEndpoint, localPath, true, 656, 492, false, 80)
                           { Loop = false, ForceTCP = true };

This part of code fails to out of memory exception for some reasons.

internal virtual void FileCreated(object sender, System.IO.FileSystemEventArgs e)
        {
            string path = e.FullPath.ToLowerInvariant();

            if (false == SupportedImageFormats.Any(ext => path.EndsWith(ext, StringComparison.OrdinalIgnoreCase))) return;
            Console.WriteLine("File created:" + path);
            try { Packetize(System.Drawing.Image.FromFile(path)); }
            catch { throw; }
        }

I noticed that CreationTime cannot find files for some reasons so I am using filename filter.

public RFC2435Media(string name, string directory = null, bool watch = true)
            : base(name, new Uri("file://" + System.IO.Path.GetDirectoryName(directory)))
        {

            if (Quality <= 0) Quality = DefaultQuality;

            //If we were told to watch and given a directory and the directory exists then make a FileSystemWatcher
            if (System.IO.Directory.Exists(base.Source.LocalPath) && watch)
            {
                // https://stackoverflow.com/questions/52885840/c-sharp-filesystemwatcher-created-event-not-firing-for-all-files-created
                m_Watcher = new System.IO.FileSystemWatcher(base.Source.LocalPath);
                m_Watcher.InternalBufferSize = 65536;
                m_Watcher.EnableRaisingEvents = true;
                m_Watcher.NotifyFilter = System.IO.NotifyFilters.FileName;
                // m_Watcher.NotifyFilter = System.IO.NotifyFilters.CreationTime;
                m_Watcher.Created += FileCreated;
            }
        } 

This PowerShell script code I am using for generating jpg files:

$counter = 1
While($true){
$filename = "c:\pictures\foo" + $counter + ".jpg" 
$counter++
$bmp = new-object System.Drawing.Bitmap 656,492 
$font = new-object System.Drawing.Font Consolas,24 
$brushBg = [System.Drawing.Brushes]::Yellow 
$brushFg = [System.Drawing.Brushes]::Black 
$graphics = [System.Drawing.Graphics]::FromImage($bmp) 
$graphics.FillRectangle($brushBg,0,0,$bmp.Width,$bmp.Height) 
$graphics.DrawString('Hello World',$font,$brushFg,10,10) 
$graphics.Dispose() 
$bmp.Save($filename,[System.Drawing.Imaging.ImageFormat]::Jpeg) 
Start-Sleep -Seconds 1
}

Sorry, having a bit of a hard time understanding what exactly is the problem.

Originally CreationTime was used to allow overwriting of files changing this to use filter should be fine for your use case.

Does the FileSystemWatcher seem to be the issue or something else?

The OOM is interesting, how many files do you have in the directory when this starts to occur? The files are kept in memory for streaming, you may want to adapt a procedure for ejecting ones you don't need or also to follow the pattern used where you don't use the FileSystemWatcher and instead just pass the bit maps to the Packetize method directly as seen in the Mirror example, this will ensure not store each frame in memory and should not lead to OOM.

You can see there are various test cases, one for live images Mirror and the other is for Bandit et al.

None of those exhibit the OOM.

if you can provide a reduced test case I will take a look when I have more time.

If you need to keep a lot of files in memory try calling AddMemoryPressure before calling Packetize