最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - How to run encoding and decoding sequentially with ffmpeg - Stack Overflow

programmeradmin2浏览0评论

After creating FFmpeg processes for encoding and decoding in C#, I tried to handle the following process. I also applied Thread.Sleep(1000/30) because I wanted to do it in 1/30 second intervals instead of 1 second.

  1. Get dummy raw data
  2. Stream to ffmpeg process for encoding
  3. Read encoded data and stream it to the ffmpeg process for decoding
  4. Outputting byte size to the console

Here's my actual code, why doesn't it work?

internal byte[] GetFrame(int width, int height)
        {
            int frameSize = width * height * 3;

            byte[] frameData = new byte[frameSize];

            Random random = new Random();

            for(int i = 0; i < frameData.Length; i++)
            {
                frameData[i] = (byte)random.Next(256);
            }

            return frameData;
        }

internal void EncodeAndDecode(int width, int height, int fps, int bitrate, string codec, string preset, string tune)
        {
            Process ffmpegEncodeProcess = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName = "ffmpeg",
                    Arguments = $"-f rawvideo -pixel_format rgb24 -s 540x720 -r 30 " +
                                $"-i - -c:v libx264 -preset ultrafast -tune zerolatency -maxrate 1500k -b:v 1500k " +
                                $"-f h264 pipe:1",
                    RedirectStandardInput = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,      
                    CreateNoWindow = true  
                }
            };

            Process ffmpegDecodeProcess = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName = "ffmpeg",
                    Arguments = $"-f h264 -i pipe:0 " +
                                $"-f rawvideo -pixel_format rgb24 -s 540x720 pipe:1",
                    RedirectStandardInput = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true
                }
            };

            //start process
            ffmpegEncodeProcess.Start();
            ffmpegDecodeProcess.Start();

            //input stream
            var ffmpegEncodeInput = ffmpegEncodeProcess.StandardInput.BaseStream;
            var ffmpegDecodeInput = ffmpegDecodeProcess.StandardInput.BaseStream;

            //output stream
            var ffmpegEncodeOutput = ffmpegEncodeProcess.StandardOutput.BaseStream;
            var ffmpegDecodeOutput = ffmpegDecodeProcess.StandardOutput.BaseStream;

            new Thread(async () =>
            {
                try
                {
                    while(true)
                    {
                        byte[] encodedChunk = new byte[width * height * 3];
                        byte[] decodedChunk = new byte[width * height * 3];

                        byte[] frameData = GetFrame(width, height);

                        Console.WriteLine($"[INFO] Original frame size: {frameData.Length}bytes.");
                        
                        if(frameData.Length == 0)
                        {
                            break;
                        }

                        await ffmpegEncodeInput.WriteAsync(frameData, 0, frameData.Length);
                        await ffmpegEncodeInput.FlushAsync();

                        int encodedBytesRead = await ffmpegEncodeOutput.ReadAsync(encodedChunk, 0, encodedChunk.Length);
                        
                        Console.WriteLine($"[INFO] Encoded frame size: {encodedBytesRead}bytes.");

                        if(encodedBytesRead > 0)
                        {
                            await ffmpegDecodeInput.WriteAsync(encodedChunk, 0, encodedBytesRead);
                            await ffmpegDecodeInput.FlushAsync();

                            int decodedBytesRead = await ffmpegDecodeOutput.ReadAsync(decodedChunk, 0, decodedChunk.Length);

                            Console.WriteLine($"[INFO] Decoded frame size: {decodedBytesRead}bytes.");

                            if(decodedBytesRead > 0)
                            {
                                //do something...
                            }
                        }

                        Thread.Sleep(1000 / fps); //1/30s
                    }
                }
                catch(Exception e)
                {
                    Console.WriteLine(e);
                }
                finally
                {
                    ffmpegEncodeInput.Close();
                    ffmpegDecodeInput.Close();

                    if(!ffmpegEncodeProcess.HasExited)
                    {
                        ffmpegEncodeProcess.Kill();
                    }

                    if(!ffmpegDecodeProcess.HasExited)
                    {
                        ffmpegDecodeProcess.Kill();
                    }

                    Console.WriteLine("[INFO]: FFmpeg process clean up.");
                }
            }).Start();
        }

To be precise, it only outputs the "Original" and "Encoded" sizes once to the console and then doesn't do anything. What am I doing wrong?

发布评论

评论列表(0)

  1. 暂无评论