I wasn't implying the fault was with ffmpeg. I was saying that ffmpeg was freezing because your code wasn't properly handling the output from ffmpeg, especially when processing many hundreds of images.
Yeah, commenting out objFProcess.StandardError.ReadToEnd won't help because you actually need something to read from standard error before it fills up and so make space for ffmpeg to write more data to it. You just need to read the data while it is being written, i.e. not wait until the end of the process.
Handling the ErrorDataReceived event should do that for you. However, it's not enough to just register the event handler (AddHandler objFProcess.ErrorDataReceived, AddressOf consoleErrorHandler), you also have to call objFProcess.BeginErrorReadLine() in order to start the asynchronous reads:Ok, so based on your original code, the following should allow you to process thousands of images and log the output from standard error:Code:AddHandler objFProcess.ErrorDataReceived, AddressOf consoleErrorHandler objFProcess.Start() objFProcess.BeginErrorReadLine()VB.NET Code:
Dim objFProcess As System.Diagnostics.Process Dim strFiles() As String Dim strEachFile As String objFProcess = New System.Diagnostics.Process objFProcess.StartInfo.FileName = txtFMPEG.Text objFProcess.StartInfo.Arguments = "-y -f image2pipe -r 25 -s 1280x720 -vcodec bmp -i pipe:.bmp -crf 25.0 -vcodec libx264 -vf scale=1280:720 -coder 1 -rc_lookahead 60 -threads 0 g:\test.mp4" objFProcess.StartInfo.UseShellExecute = False objFProcess.StartInfo.CreateNoWindow = True objFProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden objFProcess.StartInfo.RedirectStandardError = True objFProcess.StartInfo.RedirectStandardInput = True AddHandler objFProcess.ErrorDataReceived, AddressOf consoleErrorHandler objFProcess.Start() 'initialise List used to store lines from StandardError (in Sub consoleErrorHandler) 'and start listening to StandardError lstCLIErr = New List(Of String) objFProcess.BeginErrorReadLine() strFiles = System.IO.Directory.GetFiles(txtIMGDir.Text, "*.bmp", IO.SearchOption.TopDirectoryOnly) For Each strEachFile In strFiles Me.Text = System.IO.Path.GetFileNameWithoutExtension(strEachFile) My.Application.DoEvents() 'load bitmap from file Using o2 As New System.Drawing.Bitmap(strEachFile) ' ########################## 'alter bitmap as needed here ' ########################## 'save bitmap to memorystream first, 'then write MemoryStream to StandardInput's stream. 'We can't use the BitMap.Save(stream, format) method 'to write directly to the StandardInput stream 'because that method MUST write to position 0 in the stream. 'StandardInput stream won't be at postion 0 'when we need to save images to it. Using ms As New MemoryStream o2.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp) ms.WriteTo(objFProcess.StandardInput.BaseStream) End Using ' ms End Using ' o2 Next 'finished writing images to StandarInput objFProcess.StandardInput.Close() objFProcess.WaitForExit() objFProcess.Close() objFProcess.Dispose() ' ############################################# 'lstCLIErr now holds output from standard error ' #############################################
The changes I made are:
- Got rid of BinaryWriter (o1) as not being used in code given.
- Create BitMap directly from file instead of explicitly creating a FileStream and then using Image.FromStream method.
- Wrapped BitMap creation in Using...End Using block so it is disposed of properly.
- Save Bitmap to MemoryStream then write MemoryStream to StandardInput's Stream as discussed above in Post#5.
- Removed call to StandardError.ReadToEnd because we are now handling the ErrorDataReceived event.
- Added line to close StandardInput when all images have been written. Was previously being closed when the BinaryWriter was closed.
You should think about getting rid of the call to My.Application.DoEvents(). It can often cause you unexpected problems. Using a BackgroundWorker might be a relatively simple alternative, or an awaitable Task would be preferred and is even simpler to code at a basic level (but can be a concept that is more difficult to wrap your head around).





Reply With Quote
