ffmpeg管道推流_csharp

概述:基于目前网上通过pipe调用ffmpeg的资料较少,特把自己研究的成果共享给大家。

需求:从相机拿图算法识别后,图片加入了算法效果图,又需要把图片重新推流成rtmp在前端播放。

实现手段:通过c#调用ffmpeg控制台传参,通过管道pipe无缝传图给ffmpeg,最后ffmpeg推流给nginx rtmp服务器。

说明:延时大改在5秒左右。

弊端:目前直播的画面不忍直视,写博客的目的只是说可以借鉴实现方式。

最终ffmpeg打印贴图

ffmpeg version N-99925-g96443ab4b0 Copyright (c) 2000-2020 the FFmpeg developers
  built with gcc 9.3-win32 (GCC) 20200320
  configuration: --prefix=/ffbuild/prefix --pkg-config-flags=--static --pkg-config=pkg-config --cross-prefix=x86_64-w64-mingw32- --arch=x86_64 --target-os=mingw32 --enable-gpl --enable-version3 --disable-debug --enable-shared --disable-static --disable-debug --disable-w32threads --enable-pthreads --enable-iconv --enable-zlib --enable-libxml2 --enable-libfreetype --enable-libfribidi --enable-gmp --enable-lzma --enable-fontconfig --enable-opencl --enable-libvmaf --enable-vulkan --enable-libvorbis --enable-amf --enable-libaom --enable-avisynth --enable-libdav1d --enable-libdavs2 --enable-ffnvcodec --enable-cuda-llvm --enable-libglslang --enable-libass --enable-libbluray --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvpx --enable-libwebp --enable-libmfx --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librav1e --enable-librubberband --enable-schannel --enable-sdl2 --enable-libsoxr --enable-libsrt --enable-libsvtav1 --enable-libtwolame --enable-libuavs3d --enable-libvidstab --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libzimg --extra-cflags=-DLIBTWOLAME_STATIC --extra-cxxflags= --extra-ldflags=-pthread --extra-libs=-lgomp
  libavutil      56. 60.100 / 56. 60.100
  libavcodec     58.112.103 / 58.112.103
  libavformat    58. 64.100 / 58. 64.100
  libavdevice    58. 11.102 / 58. 11.102
  libavfilter     7. 90.100 /  7. 90.100
  libswscale      5.  8.100 /  5.  8.100
  libswresample   3.  8.100 /  3.  8.100
  libpostproc    55.  8.100 / 55.  8.100
Loading Complete!
Input #0, rawvideo, from '\\.\pipe\pusher9':
  Duration: N/A, start: 0.000000, bitrate: 199065 kb/s
    Stream #0:0: Video: rawvideo (BGR[24] / 0x18524742), bgr24, 1280x720, 199065 kb/s, 9 tbr, 9 tbn, 9 tbc
Please use -b:a or -b:v, -b is ambiguous
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (libx264))
Press [q] to stop, [?] for help
[libx264 @ 000001932742b480] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[libx264 @ 000001932742b480] profile Constrained Baseline, level 3.1, 4:2:0, 8-bit
[libx264 @ 000001932742b480] 264 - core 161 - H.264/MPEG-4 AVC codec - Copyleft 2003-2020 - http://www.videolan.org/x264.html - options: cabac=0 ref=1 deblock=0:0:0 analyse=0:0 me=dia subme=0 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=0 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0 keyint=2 keyint_min=1 scenecut=0 intra_refresh=0 rc=abr mbtree=0 bitrate=7000 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=0
Output #0, flv, to 'rtmp://192.168.1.202/live/9':
  Metadata:
    encoder         : Lavf58.64.100
    Stream #0:0: Video: h264 (libx264) ([7][0][0][0] / 0x0007), yuv420p(tv, progressive), 1280x720, q=-1--1, 7000 kb/s, 9 fps, 1k tbn, 9 tbc
    Metadata:
      encoder         : Lavc58.112.103 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/7000000 buffer size: 0 vbv_delay: N/A
frame=    8 fps=0.0 q=10.0 size=     570kB time=00:00:00.00 bitrate=4671040.0kbits/s speed=0.00193x    
frame=   12 fps= 12 q=21.0 size=    2145kB time=00:00:00.44 bitrate=39494.7kbits/s speed=0.433x    
frame=   17 fps= 11 q=10.0 size=    3317kB time=00:00:01.00 bitrate=27146.4kbits/s speed=0.632x    
frame=   22 fps= 10 q=21.0 size=    4822kB time=00:00:01.55 bitrate=25368.4kbits/s speed=0.738x    
frame=   27 fps= 10 q=13.0 size=    5780kB time=00:00:02.11 bitrate=22417.6kbits/s speed=0.797x    
frame=   33 fps= 10 q=14.0 size=    7175kB time=00:00:02.77 bitrate=21151.1kbits/s speed=0.862x    
frame=   38 fps= 10 q=23.0 size=    8492kB time=00:00:03.33 bitrate=20866.8kbits/s speed=0.895x    
frame=   44 fps= 10 q=24.0 size=    9751kB time=00:00:04.00 bitrate=19964.2kbits/s speed=0.93x    
frame=   49 fps= 10 q=17.0 size=   10578kB time=00:00:04.55 bitrate=19016.5kbits/s speed=0.941x    
frame=   55 fps= 10 q=17.0 size=   11782kB time=00:00:05.22 bitrate=18480.0kbits/s speed=0.962x    
frame=   59 fps=9.9 q=18.0 size=   12519kB time=00:00:05.66 bitrate=18094.3kbits/s speed=0.956x    
frame=   64 fps=9.8 q=25.0 size=   13580kB time=00:00:06.22 bitrate=17877.0kbits/s speed=0.958x    
frame=   69 fps=9.8 q=19.0 size=   14298kB time=00:00:06.77 bitrate=17278.3kbits/s speed=0.961x    
frame=   75 fps=9.8 q=20.0 size=   15295kB time=00:00:07.44 bitrate=16829.5kbits/s speed=0.977x    
frame=   80 fps=9.8 q=26.0 size=   16257kB time=00:00:08.00 bitrate=16645.3kbits/s speed=0.984x    
frame=   86 fps=9.9 q=26.0 size=   17186kB time=00:00:08.66 bitrate=16242.3kbits/s speed=0.995x    
frame=   91 fps=9.8 q=21.0 size=   17817kB time=00:00:09.22 bitrate=15825.6kbits/s speed=0.998x    
frame=   97 fps=9.9 q=21.0 size=   18711kB time=00:00:09.89 bitrate=15498.9kbits/s speed=   1x    
frame=  102 fps=9.8 q=27.0 size=   19578kB time=00:00:10.44 bitrate=15355.3kbits/s speed=   1x    
frame=  106 fps=9.7 q=27.0 size=   20170kB time=00:00:10.89 bitrate=15172.7kbits/s speed=0.997x    
frame=  111 fps=9.7 q=22.0 size=   20723kB time=00:00:11.44 bitrate=14833.2kbits/s speed=   1x    
frame=  116 fps=9.7 q=27.0 size=   21527kB time=00:00:12.00 bitrate=14694.4kbits/s speed=1.01x    
frame=  121 fps=9.7 q=22.0 size=   22076kB time=00:00:12.55 bitrate=14401.8kbits/s speed=1.01x    
frame=  126 fps=9.7 q=27.0 size=   22881kB time=00:00:13.11 bitrate=14295.3kbits/s speed=1.01x    
frame=  131 fps=9.7 q=23.0 size=   23390kB time=00:00:13.66 bitrate=14019.2kbits/s speed=1.01x    
frame=  137 fps=9.7 q=23.0 size=   24148kB time=00:00:14.33 bitrate=13800.9kbits/s speed=1.01x    
frame=  143 fps=9.7 q=23.0 size=   24907kB time=00:00:15.00 bitrate=13601.9kbits/s speed=1.02x    
frame=  148 fps=9.7 q=28.0 size=   25658kB time=00:00:15.55 bitrate=13510.8kbits/s speed=1.02x    
frame=  153 fps=9.7 q=24.0 size=   26169kB time=00:00:16.11 bitrate=13305.3kbits/s speed=1.02x    
frame=  158 fps=9.7 q=28.0 size=   26851kB time=00:00:16.66 bitrate=13196.7kbits/s speed=1.02x    
frame=  163 fps=9.7 q=24.0 size=   27322kB time=00:00:17.22 bitrate=12995.4kbits/s speed=1.02x    
frame=  168 fps=9.7 q=28.0 size=   28005kB time=00:00:17.77 bitrate=12903.6kbits/s speed=1.02x    
frame=  174 fps=9.7 q=28.0 size=   28694kB time=00:00:18.44 bitrate=12744.1kbits/s speed=1.03x    
frame=  180 fps=9.7 q=28.0 size=   29385kB time=00:00:19.11 bitrate=12595.2kbits/s speed=1.03x    
frame=  186 fps=9.7 q=28.0 size=   30076kB time=00:00:19.77 bitrate=12456.7kbits/s speed=1.04x    
frame=  190 fps=9.7 q=28.0 size=   30536kB time=00:00:20.22 bitrate=12369.8kbits/s speed=1.03x 
。。。。。。。

上代码:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace IPClient.Core
{
    public class RtmpPusher
    {
        private int height = 720;
        private int width = 1280;
        private int _camId;
        private readonly string _ffmpeg_path;
        private readonly string _rtmp_url;
        private const int BUFFERSIZE = 1280 * 720 * 3;
        private ConcurrentQueue<byte[]> _bgr24Buffer = new ConcurrentQueue<byte[]>();

        public RtmpPusher(int camId)
        {
            this._camId = camId;
            this._ffmpeg_path = @"D:\quickhigh\ffmpeg\bin\ffmpeg.exe";
            this._rtmp_url = string.Format("rtmp://192.168.1.202/live/{0}", camId);
            string pipeName = string.Format("pusher{0}", camId);
            Task.Factory.StartNew((p) => 
            {
                DoWriteWork(p as string);
            }, pipeName, TaskCreationOptions.LongRunning);
            Task.Factory.StartNew((p) => 
            {
                DoRunFFMPEG(p as string);
            }, pipeName, TaskCreationOptions.LongRunning);
        }

        public RtmpPusher StartNew(int camId)
        {
            return new RtmpPusher(camId);
        }
        //输入BMP图片字节,字节以BM开头
        public void AddBuffer(byte[] buffer)
        {
            if (_bgr24Buffer.Count<6)
            {

                int dataLen = width * height * 3;
                byte[] rgb24_buffer = new byte[width * height * 3];
                //54字节是BMP固定信息
                Array.Copy(buffer, 54, rgb24_buffer, 0, dataLen);
                _bgr24Buffer.Enqueue(rgb24_buffer);
            }
        }

        private void DoWriteWork(string pipeName)
        {
            byte[] buffer = null;
            using (NamedPipeServerStream pipeServer =new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.None, BUFFERSIZE, BUFFERSIZE))
            {
                pipeServer.WaitForConnection();
                using (StreamWriter sw = new StreamWriter(pipeServer))
                {
                    sw.AutoFlush = true;
                    do
                    {
                        if (_bgr24Buffer.TryDequeue(out buffer))
                        {
                            char[] cBuffer = Encoding.ASCII.GetChars(buffer);
                            cBuffer = VerticalResverImage(cBuffer);
                            sw.Write(cBuffer, 0, cBuffer.Length);
                        }
                        Thread.Sleep(1);
                    }
                    while (pipeServer.IsConnected);
                }
            }
        }
        //垂直翻转图像
        private char[] VerticalResverImage(char[] bytes)
        {
            char[] newBytes = new char[bytes.Length];
            
            for (int j = 0; j < height; j++)
            {
                for (int i = 0; i < width; i++)
                {
                    newBytes[((height - j - 1) * width + i) * 3] = bytes[(j * width + i) * 3];
                    newBytes[((height - j - 1) * width + i) * 3 + 1]= bytes[(j * width + i) * 3 + 1];
                    newBytes[((height - j - 1) * width + i) * 3 + 2] = bytes[(j * width + i) * 3 + 2];
                }
            }
            return newBytes;
        }

        private void DoRunFFMPEG(string pipeName)
        {
            string args = string.Format(@"-y -f rawvideo -vcodec rawvideo -pix_fmt bgr24 -s 1280x720 -r 9 -i \\.\pipe\{0} -c:v libx264 -pix_fmt yuv420p -preset ultrafast -max_delay 100 -f flv -g 2 -b 7000000 ""{1}""", pipeName, _rtmp_url);
            RunFFMPEG(args);
        }

        private void RunFFMPEG(string args)
        {
            Process p = new Process();
            p.StartInfo.FileName = _ffmpeg_path;
            p.StartInfo.Arguments = args;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.CreateNoWindow = true;//不创建进程窗口
            p.ErrorDataReceived += new DataReceivedEventHandler(ffmpeg_Output);
            p.Start();
            p.BeginErrorReadLine();
            p.WaitForExit();
            p.Close();
            p.Dispose();
        }

        private void ffmpeg_Output(object sender, DataReceivedEventArgs e)
        {
            Trace.WriteLine(e.Data);
        }
    }
}

效果图(花屏现象网上有人说需要重新编译ffmpeg的udp.c文件改大10倍包大小,待研究)。

 

附上一篇国外的链接:

https://mathewsachin.github.io/blog/2017/07/28/ffmpeg-pipe-csharp.html

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值