You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.
Trying to write, in C#, a routine that calls an ffmpeg process, get the piped data inside a named pipe, then give the taken YUV data to SvtHevcEncApp via its stdin stream.
The way I do that works for a lot of external encoders like x264, x265, vvc, aom and xvid.
The shortened code I wrote is at the end of this post.
The behaviour of SvtHevcEncApp is always the same and easily reproductible : After one write is done to the bufferedStream (or directly into the svt_hevc process StandardInput), whichever the amount of data, SvtHevcEncApp will "think" the stream has ended and finishes encoding. It will still encode the number of frames one (and only one) buffer can contain, but the video content has its planes wrong. but I'll post another issue for that. My current problem is about the piping method.
AFAIK, signalling an end of stream to a process is done by closing the writer, that's what I do after receiving a data.Length that is shorter than the buffer (a information telling me ffmpeg has finished sending data to the pipe), but an exception is raised, in the same instruction (bufStream.Write), SvtHevcEncApp received the data, encoded what it can, leaves with exitcode==0, and then the IO exception is raised telling me the channel was closed and it's always in the first run of that loop. When the exception is raised, ffmpeg was still running, but not SvtHevcEncApp.
At this point, I can't be sure if it's something that's wrong in SvtHevcEncApp, but I think it is, since all other standalone encoders are working perfectly well.
static void DoPipe()
{
int buffersize = 100000000;
NamedPipeServerStream sPipe = new NamedPipeServerStream("testpipe.y4m", PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.None, buffersize, buffersize);
string inputFile = @"h:\test_video.mp4";
Process ffmpeg = new Process();
ffmpeg.StartInfo.FileName = "ffmpeg.exe";
ffmpeg.StartInfo.UseShellExecute = false;
ffmpeg.StartInfo.RedirectStandardInput = true;
ffmpeg.StartInfo.RedirectStandardOutput = true;
ffmpeg.StartInfo.RedirectStandardError = true;
ffmpeg.OutputDataReceived += new DataReceivedEventHandler(Output_ffmpeg_Received);
ffmpeg.ErrorDataReceived += new DataReceivedEventHandler(Error_ffmpeg_Received);
ffmpeg.StartInfo.Arguments = "-hide_banner -nostdin -i " + inputFile + " -t 30 -pix_fmt yuv420p -s 1920x1080 -an -y -f yuv4mpegpipe \"\\\\.\\pipe\\testpipe.y4m\"";
ffmpeg.Start();
ffmpeg.BeginErrorReadLine();
ffmpeg.BeginOutputReadLine();
sPipe.WaitForConnection();
BinaryReader reader = new BinaryReader(sPipe);
bool stop = false;
Process svt_hevc = new Process();
svt_hevc.StartInfo.FileName = "SvtHevcEncApp.exe";
svt_hevc.StartInfo.UseShellExecute = false;
svt_hevc.StartInfo.RedirectStandardInput = true;
svt_hevc.StartInfo.RedirectStandardError = true;
svt_hevc.StartInfo.RedirectStandardOutput = true;
svt_hevc.OutputDataReceived += new DataReceivedEventHandler(Output_encoder_Received);
svt_hevc.ErrorDataReceived += new DataReceivedEventHandler(Error_encoder_Received);
svt_hevc.StartInfo.Arguments = "-color-format 1 -bit-depth 8 -w 1920 -h 1080 -fps 25 -i stdin -rc 0 -q 10 -errlog -encMode 6 - b test.svt-hevc.hevc";
svt_hevc.Start();
svt_hevc.BeginErrorReadLine();
svt_hevc.BeginOutputReadLine();
var bufStream = new BufferedStream(svt_hevc.StandardInput.BaseStream, buffersize);
do
{
byte[] data = reader.ReadBytes(buffersize);
if (data.Length > 0)
try { bufStream.Write(data, 0, data.Length); }
catch (ArgumentException e) { Console.WriteLine("Argument Exception {0}", e.Message); }
catch (IOException e) { Console.WriteLine("IO Exception {0}", e.Message); } // SvtHevcEncApp raises an exception here
catch (NotSupportedException e) { Console.WriteLine("NotSupportedException {0}", e.Message); }
catch (ObjectDisposedException e) { Console.WriteLine("Object Disposed Exception {0}",e.Message); }
if (data.Length < buffersize) stop = true; // If data length is not buffersize, ffmpeg has finished. we stop the loop
} while (!svt_hevc.HasExited && !stop); // we dont need to wait for ffmpeg to finish, stop will tell us
sPipe.Close(); // closing ffmpeg pipe
svt_hevc.StandardInput.BaseStream.Close(); // signalling to svt that the stream is EOF
ffmpeg.WaitForExit(); // to be sure
svt_hevc.WaitForExit(); // to be very sure
}
The text was updated successfully, but these errors were encountered:
Unfortunately, the app is not designed similar to other encoders and has a few issues and quirks, one of them is the fact that it does not properly check for eof from stdin. It is pretty much required to use -n to tell the encoder when to stop
So, with the -n option, it now works as expected with good planes, but having to count the number of frames in the source video before encoding isn't a good solution obviously. I'll keep the issue open in order to possibly know if one of the app developpers push that in the "todo queue". thanks for your answer
Sign up for freeto subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Trying to write, in C#, a routine that calls an ffmpeg process, get the piped data inside a named pipe, then give the taken YUV data to SvtHevcEncApp via its stdin stream.
The way I do that works for a lot of external encoders like x264, x265, vvc, aom and xvid.
The shortened code I wrote is at the end of this post.
The behaviour of SvtHevcEncApp is always the same and easily reproductible : After one write is done to the bufferedStream (or directly into the svt_hevc process StandardInput), whichever the amount of data, SvtHevcEncApp will "think" the stream has ended and finishes encoding. It will still encode the number of frames one (and only one) buffer can contain, but the video content has its planes wrong. but I'll post another issue for that. My current problem is about the piping method.
AFAIK, signalling an end of stream to a process is done by closing the writer, that's what I do after receiving a data.Length that is shorter than the buffer (a information telling me ffmpeg has finished sending data to the pipe), but an exception is raised, in the same instruction (bufStream.Write), SvtHevcEncApp received the data, encoded what it can, leaves with exitcode==0, and then the IO exception is raised telling me the channel was closed and it's always in the first run of that loop. When the exception is raised, ffmpeg was still running, but not SvtHevcEncApp.
At this point, I can't be sure if it's something that's wrong in SvtHevcEncApp, but I think it is, since all other standalone encoders are working perfectly well.
The text was updated successfully, but these errors were encountered: