c# - Why when using ffmpeg to create video file in real time the ffmpeg.exe take over 1GB of memory? -


this class i'm using ffmpeg.exe.

using system; using system.windows.forms; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; using system.drawing; using system.io.pipes; using system.runtime.interopservices; using system.diagnostics; using system.io; using dannygeneral;  namespace manager {     public class ffmpeg     {         namedpipeserverstream p;         string pipename = "mytestpipe";         system.diagnostics.process process;         string ffmpegfilename = "ffmpeg.exe";         string workingdirectory;          public ffmpeg()         {             workingdirectory = path.getdirectoryname(application.executablepath);             logger.write("workingdirectory: " + workingdirectory);             if (!directory.exists(workingdirectory))             {                 directory.createdirectory(workingdirectory);             }             ffmpegfilename = path.combine(workingdirectory, ffmpegfilename);             logger.write("ffmpegfilename: " + ffmpegfilename);         }          public void start(string pathfilename, int bitmaprate)         {             try             {                  string outpath = pathfilename;                 p = new namedpipeserverstream(pipename, pipedirection.out, 1, pipetransmissionmode.byte);                  processstartinfo psi = new processstartinfo();                 psi.windowstyle = processwindowstyle.hidden;                 psi.useshellexecute = false;                 psi.createnowindow = false;                 psi.filename = ffmpegfilename;                 psi.workingdirectory = workingdirectory;                 psi.arguments = @"-f rawvideo -pix_fmt bgra -video_size 1920x1080 -i \\.\pipe\mytestpipe -c:v libx264 -crf 20 -r " + bitmaprate + " " + outpath;                 process = process.start(psi);                 process.enableraisingevents = false;                 psi.redirectstandarderror = true;                 p.waitforconnection();             }             catch (exception err)             {                 logger.write("exception error: " + err.tostring());             }         }          public void pushframe(bitmap bmp)         {             try             {                 int length;                 // lock bitmap's bits.                 //bmp = new bitmap(1920, 1080);                 rectangle rect = new rectangle(0, 0, bmp.width, bmp.height);                 //rectangle rect = new rectangle(0, 0, 1280, 720);                 system.drawing.imaging.bitmapdata bmpdata =                     bmp.lockbits(rect, system.drawing.imaging.imagelockmode.readonly,                     bmp.pixelformat);                  int absstride = math.abs(bmpdata.stride);                 // address of first line.                 intptr ptr = bmpdata.scan0;                  // declare array hold bytes of bitmap.                 //length = 3 * bmp.width * bmp.height;                 length = absstride * bmpdata.height;                 byte[] rgbvalues = new byte[length];                  //marshal.copy(ptr, rgbvalues, 0, length);                 int j = bmp.height - 1;                 (int = 0; < bmp.height; i++)                 {                     intptr pointer = new intptr(bmpdata.scan0.toint32() + (bmpdata.stride * j));                     system.runtime.interopservices.marshal.copy(pointer, rgbvalues, absstride * (bmp.height - - 1), absstride);                     j--;                 }                 p.write(rgbvalues, 0, length);                 bmp.unlockbits(bmpdata);             }             catch(exception err)             {                 logger.write("error: " + err.tostring());             }          }          public void close()         {             p.close();         }     } } 

ffmpegfilename contain ffmpeg.exe

then have timer tick event in form:

screenshot shot = new screenshot();     public static int counter = 0;     private void timer1_tick(object sender, eventargs e)     {         counter++;         shot.getscreenshot(@"e:\screenshots\", "screenshot");         if (counter == 1200)         {             timer1.stop();             screenshot.fmpeg.close();             this.close();             screenshotsplayer ssp = new screenshotsplayer();             ssp.show();         }     } 

this timer interval set 100ms. it's taking screenshot every 100ms.

in class screenshot i'm using ffmpeg class: in top:

public static ffmpeg fmpeg; 

in constructor:

fmpeg = new ffmpeg(); fmpeg.start(@"e:\screenshots\test.mp4", 25); 

then in getscreenshot method i'm calling ffmpeg pushframe method:

public bitmap getscreenshot(string folder, string name)     {         _screenshot = new bitmap(getscreen());         system.gc.collect();         system.gc.waitforpendingfinalizers();         string ingname = folder + name + elgato_video_capture.counter.tostring("d6") + ".bmp";         _screenshot.save(ingname,system.drawing.imaging.imageformat.bmp);         fmpeg.pushframe(_screenshot);         _screenshot.dispose();         return _screenshot;     } 

i can't figure out why once start timer take screenshots ffmpeg.exe eat memory hard disk working 53mb/s , memory on 90% , on 1gb.

i'm doing memory leak somehow ?

ffmpeg memory

in screenshot class when i'm making instance once ffmpeg class ffmpeg.exe on low memory usage , hard disk usage low.

the ffmpeg.exe 0.1mb of memory usage.

fmpeg.start(@"e:\screenshots\test.mp4", 25); 

but when i'm clicking button start timer , taking screenshots every 100ms , calling pushframe method ffmpeg.exe fast after few seconds getting on 1gb of memory usage.

edit

i tried arguments:

psi.arguments = @"-f rawvideo -pix_fmt bgra -video_size 1920x1080 -i \\.\pipe\mytestpipe -c:v libx264 -crf 20 -r 750k e:\screenshots\test.mp4"; 

the memory usage 1gb of ffmpeg.exe , cpu usage 99-100% hard disk on 0 cpu usage got 100% , memory on 1gb.

and didn't create video file got warnings/errors:

warnings/errors

it seems you're endlessly encoding 1920x1080 video (referring to: -f rawvideo -pix_fmt bgra -video_size 1920x1080 -i \\.\pipe\mytestpipe). encoding (and decoding) h264 high quality video takes lot of cpu power. recommend reading more h.264 encoding.

answering question not possible as:

  1. the ffmpeg piece hidden in code implementation (which run system shell command). export full ffmpeg command being executing start. ffmpeg command should ffmpeg -f rawvideo -pix_fmt bgra -video_size 1920x1080 -i \\.\pipe\mytestpipe -c:v libx264 -crf 20 -r 750k e:\screenshots\test.mp4.

  2. ffmpeg changes depending on input , output streams. if example, choose different encoder (say change: -c:v libx264 to: -c:v mpeg2video) can promise significant performance improvment mpeg2video light encoder, yet file size 20 times bigger.

good luck. -e


Comments

Popular posts from this blog

round image using picasso in android -

OpenCV OpenCL: Convert Mat to Bitmap in JNI Layer for Android -

python - How to remove the Xframe Options header in django? -