当前位置: 首页 > news >正文

C#利用ffmpeg借助NVIDIA GPU实现实时RTSP硬解码+硬编码录制MP4

 

目录

说明

效果

项目 

代码

下载


说明

利用周杰的开源项目 Sdcb.FFmpeg

项目地址:https://github.com/sdcb/Sdcb.FFmpeg/

代码实现参考:https://github.com/sdcb/ffmpeg-muxing-video-demo

效果

C#利用ffmpeg借助NVIDIA GPU实现实时RTSP硬解码+硬编码录制MP4

项目 

代码

using Sdcb.FFmpeg.Codecs;
using Sdcb.FFmpeg.Formats;
using Sdcb.FFmpeg.Raw;
using Sdcb.FFmpeg.Toolboxs.Extensions;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Sdcb.FFmpegDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        CancellationTokenSource cts;

        /// <summary>
        /// 播放
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            button2.Enabled = true;
            cts = new CancellationTokenSource();
            string rtsp_url = txtURL.Text;
            //输出视频文件的名称。
            string outputFile = "output.mp4";
            Task.Run(() => Recording(rtsp_url, outputFile, cts.Token));
        }

        void Recording(string url, string outputFile, CancellationToken cancellationToken)
        {
            //输出视频的帧率,帧率设置为每秒25帧
            AVRational frameRate = new AVRational(25, 1);
            
            //输出视频的比特率。
            long bitRate = 16 * 1024 * 1024; // 16M

            //从文件夹读取
            //该字符串指定了源图像的文件夹和命名模式。%03d部分表示图像以三位数字命名(例如,001.jpg,002.jpg等)。
            //string sourceFolder = @".\src\%03d.jpg";
            //FormatContext srcFc = FormatContext.OpenInputUrl(sourceFolder, options: new MediaDictionary
            //{
            //    ["framerate"] = frameRate.ToString()
            //});

            FormatContext srcFc = FormatContext.OpenInputUrl(url);
            srcFc.LoadStreamInfo();
            MediaStream srcVideo = srcFc.GetVideoStream();
            CodecParameters srcCodecParameters = srcVideo.Codecpar;

            CodecContext videoDecoder = new CodecContext(Codec.FindDecoderByName("h264_cuvid"));
            {
            };
            videoDecoder.FillParameters(srcCodecParameters);
            videoDecoder.Open();

            //var d=  Codec.FindDecoders(AVCodecID.H264).Select(x => x.Name);
            //var e = Codec.FindEncoders(AVCodecID.H264).Select(x => x.Name);

            FormatContext dstFc = FormatContext.AllocOutput(OutputFormat.Guess("mp4"));

            dstFc.VideoCodec = Codec.FindEncoderByName("h264_nvenc");
            MediaStream vstream = dstFc.NewStream(dstFc.VideoCodec);

            CodecContext vcodec = new CodecContext(dstFc.VideoCodec)
            {
                Width = srcCodecParameters.Width,
                Height = srcCodecParameters.Height,
                TimeBase = frameRate.Inverse(),
                PixelFormat = AVPixelFormat.Yuv420p,
                Flags = AV_CODEC_FLAG.GlobalHeader,
                BitRate = bitRate,
            };
            vcodec.Open(dstFc.VideoCodec);
            vstream.Codecpar.CopyFrom(vcodec);
            vstream.TimeBase = vcodec.TimeBase;

            IOContext io = IOContext.OpenWrite(outputFile);
            dstFc.Pb = io;
            dstFc.WriteHeader();

            // src        -- srcFc.ReadPackets()          -->
            // src Packet -- DecodePackets(videoDecoder)  -->
            // src Frame  -- ConvertFrames(vcodec)        -->
            // dst Frame  -- EncodeFrames(vcodec)         -->
            // dst Packet -- dstFc.InterleavedWritePacket -->
            // dst

            foreach (Packet packet in srcFc
                .ReadPackets().Where(x => x.StreamIndex == srcVideo.Index)
                .DecodePackets(videoDecoder)
                .ConvertFrames(vcodec)
                .EncodeFrames(vcodec)
                )
            {
                try
                {
                    packet.RescaleTimestamp(vcodec.TimeBase, vstream.TimeBase);
                    packet.StreamIndex = vstream.Index;
                    dstFc.InterleavedWritePacket(packet);

                    if (cancellationToken.IsCancellationRequested) break;
                }
                finally
                {
                    packet.Unref();
                }
            }
            dstFc.WriteTrailer();

            io.Dispose();
            vcodec.Dispose();
            dstFc.Dispose();
            videoDecoder.Dispose();
            srcFc.Dispose();

        }

        /// <summary>
        /// 停止
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            button2.Enabled = false;
            button1.Enabled = true;
            cts.Cancel();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            button2.Enabled = false;
            button1.Enabled = true;
            Sdcb.FFmpeg.Utils.FFmpegLogger.LogWriter = (level, msg) => Console.WriteLine(msg);
        }
    }

}
 

using Sdcb.FFmpeg.Codecs;
using Sdcb.FFmpeg.Formats;
using Sdcb.FFmpeg.Raw;
using Sdcb.FFmpeg.Toolboxs.Extensions;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;namespace Sdcb.FFmpegDemo
{public partial class Form1 : Form{public Form1(){InitializeComponent();}CancellationTokenSource cts;/// <summary>/// 播放/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void button1_Click(object sender, EventArgs e){button1.Enabled = false;button2.Enabled = true;cts = new CancellationTokenSource();string rtsp_url = txtURL.Text;//输出视频文件的名称。string outputFile = "output.mp4";Task.Run(() => Recording(rtsp_url, outputFile, cts.Token));}void Recording(string url, string outputFile, CancellationToken cancellationToken){//输出视频的帧率,帧率设置为每秒25帧AVRational frameRate = new AVRational(25, 1);//输出视频的比特率。long bitRate = 16 * 1024 * 1024; // 16M//从文件夹读取//该字符串指定了源图像的文件夹和命名模式。%03d部分表示图像以三位数字命名(例如,001.jpg,002.jpg等)。//string sourceFolder = @".\src\%03d.jpg";//FormatContext srcFc = FormatContext.OpenInputUrl(sourceFolder, options: new MediaDictionary//{//    ["framerate"] = frameRate.ToString()//});FormatContext srcFc = FormatContext.OpenInputUrl(url);srcFc.LoadStreamInfo();MediaStream srcVideo = srcFc.GetVideoStream();CodecParameters srcCodecParameters = srcVideo.Codecpar;CodecContext videoDecoder = new CodecContext(Codec.FindDecoderByName("h264_cuvid"));{};videoDecoder.FillParameters(srcCodecParameters);videoDecoder.Open();//var d=  Codec.FindDecoders(AVCodecID.H264).Select(x => x.Name);//var e = Codec.FindEncoders(AVCodecID.H264).Select(x => x.Name);FormatContext dstFc = FormatContext.AllocOutput(OutputFormat.Guess("mp4"));dstFc.VideoCodec = Codec.FindEncoderByName("h264_nvenc");MediaStream vstream = dstFc.NewStream(dstFc.VideoCodec);CodecContext vcodec = new CodecContext(dstFc.VideoCodec){Width = srcCodecParameters.Width,Height = srcCodecParameters.Height,TimeBase = frameRate.Inverse(),PixelFormat = AVPixelFormat.Yuv420p,Flags = AV_CODEC_FLAG.GlobalHeader,BitRate = bitRate,};vcodec.Open(dstFc.VideoCodec);vstream.Codecpar.CopyFrom(vcodec);vstream.TimeBase = vcodec.TimeBase;IOContext io = IOContext.OpenWrite(outputFile);dstFc.Pb = io;dstFc.WriteHeader();// src        -- srcFc.ReadPackets()          -->// src Packet -- DecodePackets(videoDecoder)  -->// src Frame  -- ConvertFrames(vcodec)        -->// dst Frame  -- EncodeFrames(vcodec)         -->// dst Packet -- dstFc.InterleavedWritePacket -->// dstforeach (Packet packet in srcFc.ReadPackets().Where(x => x.StreamIndex == srcVideo.Index).DecodePackets(videoDecoder).ConvertFrames(vcodec).EncodeFrames(vcodec)){try{packet.RescaleTimestamp(vcodec.TimeBase, vstream.TimeBase);packet.StreamIndex = vstream.Index;dstFc.InterleavedWritePacket(packet);if (cancellationToken.IsCancellationRequested) break;}finally{packet.Unref();}}dstFc.WriteTrailer();io.Dispose();vcodec.Dispose();dstFc.Dispose();videoDecoder.Dispose();srcFc.Dispose();}/// <summary>/// 停止/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void button2_Click(object sender, EventArgs e){button2.Enabled = false;button1.Enabled = true;cts.Cancel();}private void Form1_Load(object sender, EventArgs e){button2.Enabled = false;button1.Enabled = true;Sdcb.FFmpeg.Utils.FFmpegLogger.LogWriter = (level, msg) => Console.WriteLine(msg);}}}

下载

源码下载

http://www.lryc.cn/news/430918.html

相关文章:

  • 第4章 汇编语言和汇编软件
  • 网络安全在2024好入行吗?
  • C++练习
  • 3. GIS后端工程师岗位职责、技术要求和常见面试题
  • Linux学习笔记(4)----Debian压力测试方法
  • xml详解
  • C140 杨辉三角
  • C++字符串操作中的陷阱
  • 最值求解 | 管理类联考数学专项
  • C++_继承详解
  • 区块链开发解决方案有哪些
  • Express与SQLite集成教程:轻松实现数据库操作
  • Transforms的常见用法
  • js 创建 React 项目
  • WPF 中常用 `Transform` 类的介绍、使用示例和适用场景
  • ElasticSearch-DSL
  • Learn ComputeShader 07 Post Processing
  • 初始QT!
  • 全国大学生数据建模比赛——深度学习
  • Qt技巧(二)-滑动界面,轮询控件,循环操作控件
  • 003——单链表
  • XILINX平台下LINUX DMA驱动调研
  • Oracle数据库安装和配置指南
  • 制造业中工艺路线(工序)与产线(工作中心)关系
  • 目标跟踪算法——ByteTrack算法原理解析
  • C语言编译的过程
  • 前端面试题——栈与队列、动态路由、链表
  • Java算法之计数排序(Counting Sort)
  • 【系统架构设计师-2012年】综合知识-答案及详解
  • webpack4手动搭建Vue项目