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 ?
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:
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:
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
.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
Post a Comment