C#利用ffmpeg和opencv进行视频的解码播放

news2024/9/22 19:28:44

目录

说明

效果

项目 

代码

下载


说明

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

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

效果

C#利用ffmpeg和opencv进行视频的解码播放

项目 

代码

using OpenCvSharp;
using Sdcb.FFmpeg.Codecs;
using Sdcb.FFmpeg.Formats;
using Sdcb.FFmpeg.Raw;
using Sdcb.FFmpeg.Toolboxs.Extensions;
using System;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

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

        CancellationTokenSource cts;

        ConcurrentQueue<Mat> matQueue = new ConcurrentQueue<Mat>();

        /// <summary>
        /// 播放
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            cts = new CancellationTokenSource();

            //string rtsp_url = "test_car_person_1080P.mp4";
            string rtsp_url = "rtsp://192.168.3.62/ch1";

            Task.Run(() => DecodeRTSP(rtsp_url, cts.Token));

            Task.Run(() =>
            {
                Mat mat = new Mat();
                while (true)
                {
                    if (cts.IsCancellationRequested) break;
                    //Console.WriteLine("matQueue.Count:" + matQueue.Count);
                    if (matQueue.TryDequeue(out mat))
                    {
                        Cv2.ImShow(rtsp_url, mat);
                        Cv2.WaitKey(1);
                        mat.Dispose();
                    }
                }
                Cv2.DestroyAllWindows();
            });
        }

        void DecodeRTSP(string url, CancellationToken cancellationToken = default)
        {
            FormatContext fc = FormatContext.OpenInputUrl(url);
            fc.LoadStreamInfo();
            MediaStream videoStream = fc.GetVideoStream();

            CodecContext videoDecoder = new CodecContext(Codec.FindDecoderByName("h264"));
            videoDecoder.FillParameters(videoStream.Codecpar);
            videoDecoder.Open();

            foreach (Sdcb.FFmpeg.Utils.Frame frame in fc
                .ReadPackets(videoStream.Index)
                .DecodePackets(videoDecoder)
                .ConvertVideoFrames(() => (videoDecoder.Width, videoDecoder.Height), AVPixelFormat.Bgr24))
            {
                if (cancellationToken.IsCancellationRequested) break;

                try
                {
                    byte[] data = new byte[frame.Linesize[0] * frame.Height];
                    Marshal.Copy(frame.Data._0, data, 0, data.Length);
                    OpenCvSharp.Mat mat = new OpenCvSharp.Mat(frame.Height, frame.Width, MatType.CV_8UC3, data); ;
                    matQueue.Enqueue(mat);
                }
                finally
                {
                    frame.Unref();
                }
            }
            cts.Cancel();
            videoDecoder.Dispose();
            fc.Dispose();
        }


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

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

}

using OpenCvSharp;
using Sdcb.FFmpeg.Codecs;
using Sdcb.FFmpeg.Formats;
using Sdcb.FFmpeg.Raw;
using Sdcb.FFmpeg.Toolboxs.Extensions;
using System;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

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

        CancellationTokenSource cts;

        ConcurrentQueue<Mat> matQueue = new ConcurrentQueue<Mat>();

        /// <summary>
        /// 播放
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            cts = new CancellationTokenSource();

            //string rtsp_url = "test_car_person_1080P.mp4";
            string rtsp_url = "rtsp://192.168.3.62/ch1";

            Task.Run(() => DecodeRTSP(rtsp_url, cts.Token));

            Task.Run(() =>
            {
                Mat mat = new Mat();
                while (true)
                {
                    if (cts.IsCancellationRequested) break;
                    //Console.WriteLine("matQueue.Count:" + matQueue.Count);
                    if (matQueue.TryDequeue(out mat))
                    {
                        Cv2.ImShow(rtsp_url, mat);
                        Cv2.WaitKey(1);
                        mat.Dispose();
                    }
                }
                Cv2.DestroyAllWindows();
            });
        }

        void DecodeRTSP(string url, CancellationToken cancellationToken = default)
        {
            FormatContext fc = FormatContext.OpenInputUrl(url);
            fc.LoadStreamInfo();
            MediaStream videoStream = fc.GetVideoStream();

            CodecContext videoDecoder = new CodecContext(Codec.FindDecoderByName("h264"));
            videoDecoder.FillParameters(videoStream.Codecpar);
            videoDecoder.Open();

            foreach (Sdcb.FFmpeg.Utils.Frame frame in fc
                .ReadPackets(videoStream.Index)
                .DecodePackets(videoDecoder)
                .ConvertVideoFrames(() => (videoDecoder.Width, videoDecoder.Height), AVPixelFormat.Bgr24))
            {
                if (cancellationToken.IsCancellationRequested) break;

                try
                {
                    byte[] data = new byte[frame.Linesize[0] * frame.Height];
                    Marshal.Copy(frame.Data._0, data, 0, data.Length);
                    OpenCvSharp.Mat mat = new OpenCvSharp.Mat(frame.Height, frame.Width, MatType.CV_8UC3, data); ;
                    matQueue.Enqueue(mat);
                }
                finally
                {
                    frame.Unref();
                }
            }
            cts.Cancel();
            videoDecoder.Dispose();
            fc.Dispose();
        }


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

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

}

下载

源码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2036979.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【SpringBoot】【autopoi】java生成word,基于模版生成(文本、图片、表格)

基于模版生成word 1、引入maven2、word模版编写3、java代码4、效果 AutoPoi的主要特点 参考文献 https://help.jeecg.com/autopoi/autopoi/prequel/test.html 1.设计精巧,使用简单 2.接口丰富,扩展简单 3.默认值多,write less do more 4.spring mvc支持,web导出可以简单明了 1、…

【大模型从入门到精通17】openAI API 构建和评估大型语言模型(LLM)应用5

这里写目录标题 理论问题&#xff1a;实践问题&#xff1a;理论实践 理论问题&#xff1a; 1.描述评估LLM应用程序输出的重要性&#xff0c;并提及至少三个维度&#xff0c;这些输出应该在这几个维度上被评估。 2.解释在评估LLM应用程序时开发稳健的性能指标的作用&#xff0c…

uniapp多图上传uni.chooseImage上传照片uni.uploadFile,默认上传9张图

uniapp多图上传uni.chooseImage上传照片uni.uploadFile 代码示例&#xff1a; /**上传照片 多图*/getImage() {uni.chooseImage({count: 9, //默认9sizeType: [original, compressed], //可以指定是原图还是压缩图&#xff0c;默认二者都有sourceType: [album], //从相册选择/…

【论文理解】Pixel-level Extrinsic Calibration LiDAR and Camera

Pixel-level Extrinsic Self Calibration of High Resolution LiDAR and Camera in Targetless Environments 无目标环境中高分辨率激光雷达和相机的像素级外参估计 摘要 Our approach does not require checkerboards but can achieve pixel-level accuracy by aligning na…

数据结构8.13

作业&#xff1a;链栈&#xff0c;自己实现一遍&#xff0c;但是节点存储不是整数&#xff0c;存储学生信息&#xff08;年龄&#xff0c;分数&#xff0c;姓名&#xff09;三级引用。 1、建立学生信息结构体&#xff0c;将data改为学生信息结构体类型。 #include <myhead…

深度学习---------------卷积层

目录 从全连接到卷积分类猫和狗的图片重新考察全连接层原则1------平移不变性原则2------局部性 总结 卷积层二维交叉相关二维卷积层交叉相关 vs 卷积一维和三维交叉相关总结 图像卷积二维互相关运算实现二维卷积层图像中目标的边缘检测该部分总代码该部分总代码 问题 从全连接…

安装MySQL数据库【后端 8】

安装MySQL数据库 MySQL是世界上最流行的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;之一&#xff0c;广泛应用于Web应用程序开发中。无论你是初学者还是有一定经验的开发者&#xff0c;掌握MySQL的安装都是必不可少的技能。本文将指导你如何在不同的操作系统上安装…

在 SOCKS 和 HTTP 代理之间如何选择?

在 SOCKS 和 HTTP 代理之间进行选择需要彻底了解每种代理的工作原理以及它们传达的配置。只有这样&#xff0c;您才能轻松地在不同类型的代理之间进行选择。 本文概述了 HTTP 和 SOCKS 代理是什么、它们如何运作以及它们各自带来的好处。此外&#xff0c;我们将比较这两种代理类…

1、Unity【基础】3D数学

3D数学 文章目录 3D数学1、数学计算公共类Mathf1、Mathf和Math2、区别3、Mathf中的常用方法&#xff08;一般计算一次&#xff09;4、Mathf中的常用方法&#xff08;一般不停计算&#xff09;练习 A物体跟随B物体移动 2、三角函数1、角度和弧度2、三角函数3、反三角函数练习 物…

三、虚拟机安装CentOS 7

编写目的&#xff1a; 1.做个记录&#xff0c;防止参考的博客被删 2.做个基础的虚拟机镜像&#xff0c;无应用&#xff0c;固定ip&#xff0c;能联网即可。后面直接克隆一个镜像&#xff0c;安装Jenkins等 目录 一、下载CentOS镜像 二、vmware配置CentOS虚拟机 1.打开vmw…

MSF经典attack示范

免责声明:本文仅做分享... 目录 Nessus官网 指定攻击 自动在线攻击 nmap扫 查看扫到的服务 查看主机 离线攻击 Msfvenom 本地快速传递文件的方法-->py 哈希传递攻击 提权 后渗透阶段 1-收集操作系统和版本信息 2-主机名称&环境变量 3-用户账户信息 4-远…

Stable Diffusion绘画 | ControlNet应用-NormalMap(法线贴图)

NormalMap(法线贴图)&#xff0c;指的是一张只有红绿蓝RGB颜色的图片&#xff0c;通过指定的发法线算法&#xff0c;用RGB颜色相互混合搭配来表示物体的凹凸情况&#xff0c;常用于3D贴图模型使用。 整体配置如下&#xff1a; ControlNet 的法线控制可以把任何的图片转化为法线…

Java Web —— 第四天(HTTP协议,Tomcat)

HTTP-概述 概念:Hyper Text Transfer Protocol&#xff0c;超文本传输协议&#xff0c;规定了浏览器和服务器之间数据传输的规则 特点: 1. 基于TCP协议:面向连接&#xff0c;安全 2.基于请求-响应模型的:一次请求对应一次响应 3. HTTP协议是无状态的协议: 对于事务处理没有…

书生浦语大模型全链路开源开放体系学习

书生浦语大模型的开源体系经过一年努力&#xff0c;已实现从数据收集到模型部署的全链路打通。课程介绍了书生浦语的最新进展&#xff0c;包括7B和20B模型的开源及其性能提升。新版本模型在推理能力和上下文处理上表现优异&#xff0c;支持超长上下文和复杂任务解决。开源工具涵…

Java并发类API--Executor与ThreadPoolExecutor

在 Java 中&#xff0c;Executor 和 ThreadPoolExecutor 是用于管理线程和执行任务的工具&#xff0c;帮助开发者更好地控制多线程环境。下面是它们的使用和区别。 1.Executor 简介 Executor 是一个接口&#xff0c;用来创建线程池&#xff0c;它定义了一个 execute(Runnable c…

05 内部类API异常

1.内部类 1.1形参和返回值 1. 类名作为形参和返回值 方法的形参是类名,需要该类的对象 方法的返回值为类名,则返回该类的对象 2.抽象类名作为形参和返回值 方法的形参是抽象类名,需要该类的子类对象 方法的返回值是抽象类名,需要返回是该类的子类对象 3.接口名作为形参和返回值…

打印机维护好帮手 | 闪克打印机修复助手 v2.23.0.0

闪克打印机修复助手是一款专业的打印机修复软件&#xff0c;专为解决打印机相关问题而设计&#xff0c;能够帮助用户轻松识别和处理打印机设备的问题&#xff0c;从而提升工作效率。闪克打印机修复助手集成了错误修复、打印机驱动安装和综合修复三大功能。 它能够安全、快速、高…

C盘磁盘空间不足:VirtualBox的锅

文章目录 一&#xff0c;数据迁移二&#xff0c;修改默认配置三&#xff0c;在VirtualBox上删除原来的虚拟机四&#xff0c;在新的虚拟机目录下五&#xff0c;删除C盘上的虚拟机文件虚拟机消耗磁盘分析 开始在自己的windows电脑上使用Vitualbox虚拟机之后&#xff0c;发现C盘常…

【走迷宫】

题目 DFS代码 #include<bits/stdc.h> using namespace std; const int N 110; int matrix[N][N]; int n, m; int dx[4] {-1, 0, 1, 0}, dy[4] {0, 1, 0, -1}; int dis[N][N]; void dfs(int x, int y, int cnt) {if(cnt > dis[n-1][m-1]) return;if(x n-1 &&a…

Vue2.0 项目实战篇\部署篇

Vue2.0 项目实战篇\部署篇&#x1f4dc; 本篇文章学习记录于&#xff1a; bilibili-黑马程序♞ 104-139集 》》&#x1f3af;目标&#xff1a;冲击前后端全栈&#x1f525;&#xff0c;分享一下学过程&#xff1a; Java.慈祥的博客——个人前端技术栈blog记录&#xff1a;、感…