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

server/2024/10/21 10:08:20/

 

目录

说明

效果

项目 

代码

下载


说明

利用周杰的开源项目 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.ppmy.cn/server/110438.html

相关文章

web api 文件上传下载帮助类

web api调用 using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using YiSha.Util; using YiSha.Util.Extension; using YiSha.Util.Mo…

【机器学习】循环神经网络(RNN)介绍

引言 在现代人工智能(AI)和机器学习领域,循环神经网络(Recurrent Neural Networks, RNNs)作为一种能够处理序列数据的神经网络架构,已经成为众多应用的核心技术之一。RNNs的出现为处理时间序列数据和自然语言处理等任务提供了强大的工具,使得计算机能够理解和生成具有时…

推荐一款灵活,可靠和快速的开源分布式任务调度平台

今天给大家推荐一款灵活&#xff0c;可靠和快速的开源分布式任务调度平台——SnailJob。 前言 什么是任务调度&#xff1f; 任务调度&#xff0c;是指在多任务的环境下&#xff0c;合理地分配系统资源&#xff0c;调度各个任务在什么时候&#xff0c;由哪一个处理器处理&…

如何利用智能文档处理技术,搭建供应链金融智能审单系统?

供应链金融业务的风控逻辑在于业务流、信息流、物流、现金流的数据整合及交叉验证&#xff0c;在产业端数字化水平有限以及合规审核要求严格的背景下&#xff0c;审单人员需要对合同、物流单证、财务单证、权属证明文件等文档的关键信息进行细致的审核校验。这些单证是确保交易…

私有云仓库Harbor,docker-compose容器编排

一、私有云仓库 1.pip工具 是python的包管理工具&#xff0c;和yum对rehat的关系是一样的 pip install --upgrade pip 升级版本&#xff0c;会报错&#xff0c;需要指定源 pip install --upgrade pip20.3 -i https://mirrors.aliyun.com/pypi/simple pip …

linux-基础知识2

目录和文件的权限 修改目录和文件的拥有者 用root用户执行&#xff1a; chown -R 用户:组 目录和文件列表 -R选项表示连同各子目录一起修改 创建aa目录mkdir aa ,查看 ls -l 普通用户没有权限&#xff0c;不能删除 转移权限&#xff0c;chown -R mysal:deb /aa/aa 加上-R…

坐牢第三十天(c++)

1.作业&#xff1a; 提示并输入一个字符串&#xff0c;统计该字符串中字母个数、数字个数、空格个数、其他字符的个数 #include <iostream> #include <stdio.h> #include <string> using namespace std; int main(int argc, char const *argv[]) {string st…

springboot+vue+mybatis计算机毕业设计房屋租赁管理系统+PPT+论文+讲解+售后

随着社会的不断进步与发展&#xff0c;人们经济水平也不断的提高&#xff0c;于是对各行各业需求也越来越高。特别是从2019年新型冠状病毒爆发以来&#xff0c;利用计算机网络来处理各行业事务这一概念更深入人心&#xff0c;由于工作繁忙以及疫情的原因&#xff0c;房屋租赁也…