首页 > 编程语言 >[C#] FFmpeg 音视频开发总结

[C#] FFmpeg 音视频开发总结

时间:2023-06-08 10:47:08浏览次数:77  
标签:编解码 FFmpeg autogen C# 样例 音视频 Usb

为什么选择FFmpeg?

  1. 延迟低,参数可控,相关函数方便查询,是选择FFmpeg作为编解码器最主要原因,如果是处理实时流,要求低延迟,最好选择是FFmpeg。
  2. 如果需要用Opencv或者C#的Emgucv这种库来处理视频流,也多是用FFmpeg做编解码然后再转换图像数据给Opencv去处理。用Opencv编解码延迟很高。
  3. 其他的库多是基于FFmpeg封装,如果做一个视频播放器,像vlc这种库是非常方便的,缺点是臃肿,需要手动剔除一些文件,当然也有一些是基于FFmpeg封装好的视频播放器库,也能快速实现一个播放器。
  4. 如果是加载单Usb接口中的多Usb摄像头,FFmpeg这时就无能为力了,经过测试使用DirectShow能够实现。AForge一个很好的学习样例,它将DirectShow封装的很好,能轻松实现加载单Usb接口中的多Usb摄像头(不过它很久没更新了,目前无法设置摄像头参数,也没有Usb摄像头直接录制,所以我把它重写了),当然使用其他DirectShow的库也是可以的。
  5. 写此文章时才发现CaptureManager这个2023年4月发布的非常简便好用的基于D3D封装的音视频库,它的官方样例非常丰富,能实现很多功能。我尝试了运行了他的官方样例,打开相同规格的Usb摄像头,发觉cpu占用是FFmpeg的两倍。

如何学习FFmpeg?

记录一下我是如何学习FFmpeg。首先是C#使用FFmpeg基本上用的是FFmpeg.autogen这个库。也可以使用FFmpeg.exe,先不谈论FFmpeg.exe的大小,我尝试过从exe中取数据到C#前端显示,相同参数情况下,延迟比使用FFmpeg.autogen高,主要是不能边播放边录制(可以用其它的库来录制,但是效率比不上只使用一个库)。

当然如果只需要部分功能也可以自己封装FFmpeg(太花时间了,我放弃了。如果是专门从事这一行的可以试试)。

学习FFmpeg.autogen可以先去Github上下载它的样例(其实样例有个小问题,后面说),学习基础的编解码。

后面有人把官网的C++的样例用FFmpeg.autogen写了一遍,我把样例压缩好放夸克网盘了:https://pan.quark.cn/s/c579aad1d8e0

然后是查看一些博客和Github上一些项目,了解编解码整体架构,因为FFmpeg很多参考代码都是c++的所以我基本是参考C++写C#,写出整体的编解码代码。

无论是编解码还是开发Fliter都会涉及到很多参数设置。要查找这些参数,我先是去翻博客,最后还是去FFmpeg官网(官网文档,编解码参数很全),当然制作视频滤镜和一些其他功能,也是参考官网的参数。

对于部分基础函数(有些函数会把帧用掉就释放,要注意)查看FFmpeg的源码,理解原理。

对于一些概念性的东西,我是翻阅硕博论文(一般都有总结这些)。

 C#使用FFmpeg需要注意什么?

  1. FFmpeg.autogen是有一个缺点的,它是全静态的,不支持多线程(这个我问作者了),所以用多进程,而用多进程渲染到同一画面,可以参考我上一篇MAF的文章。
  2. 尤其要注意帧释放,编解码的帧如果没有释放是一定会产生内存泄漏的,而且速度很快。
  3. 其次是c# 要将图像数据渲染到界面显示,最最好使用WriteableBitmap,将WriteableBitmap和绑定到一个Image然后更新WriteableBitmap。我记得在一篇博客中提到高性能渲染,使用MoveMemory来填充WriteableBitmap的BackBuffer,核心代码如下。
    [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        private static extern void MoveMemory(IntPtr dest, IntPtr src, uint count);
     writeableBitmap.Lock();
            unsafe
            {
                 fixed (byte* ptr = intPtr)
                  {
                    MoveMemory(writeableBitmap.BackBuffer, new IntPtr(ptr), (uint)intPtr.Length);
                   }
           }
           writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, width, height));
    
    writeableBitmap.Unlock();
    这样处理有个致命的缺点。WriteableBitamp的宽高必须为2的整数倍,即使是修正过大小,当传入数据为特殊尺寸使用此方法时还是会出现显示异常的情况。所以还是老实使用WriteableBitmap的WritePixels。
  4. 对于FFmpeg很多函数都是会返回错误信息,一定要将错误信息记录到日志,方便查找和查看(基本每个函数要加错误信息判断)。
  5. 软编码会占用大量的CPU资源,所以最好采用硬编码。FFmpeg有一个查找编解码器的函数,它并不能查看硬件编码器。如果要使用硬件加速查找编解码器最好是用其他方式获取系统设备或者直接一个一个打开NVDIA和QSV等加速,都失败了再启用软编解码。
  6. QSV硬编码要求输入的像素格式必须为AVPixelFormat.AV_PIX_FMT_NV12,如果是硬解码出的数据,可以直接编码,否则需要添加格式转换。FFmepg.autogen的官方样例中有格式转换函数,但由于它没有指定转换后的格式会出问题(踩坑)。
  7. 尽量少的格式转换,或者帧复制。这两种方式会提高cpu和内存使用率同时也会有更高的延迟。
  8. 在制作FFmpeg的带有文本的Filter时,将需要使用的字体复制到项目目录然后指定字体位置而不是调用系统的字体(不知道是版本原因还是什么问题,一用系统字体就会产生内存泄漏)。
  9.  注意编解码数据的格式。一些老的格式,虽然解码没有什么问题(ffmpeg 会有提示)但是编码是不支持的,出现这种问题,程序会直接死掉(踩坑)。
  10. 解码时可以通过解码数据自动搜寻硬件解码器,而硬件编码需要手动指定编码器(可以通过,查找并自动选择GPU来实现自动选择)。
  11. 多线程实现播放同时录制时,最好采用帧复制ffmpeg.av_frame_clone(hwframe)不用对同一个帧进行操作。当然也可以不用多线程,同一个帧在播放完成后进行,录制。

  暂时只想到这些,有其他的想法再更新     

如果有任何错误欢迎批评指正。

标签:编解码,FFmpeg,autogen,C#,样例,音视频,Usb
From: https://www.cnblogs.com/mrf2233/p/17442871.html

相关文章

  • Protocol Buffers 3 语法
    ProtocolBuffers3语法标签(空格分隔):protocolbuffers本主题介绍如何在项目中使用协议缓冲区版本3官网地址:https://protobuf.dev/programming-guides/proto3/定义消息类型首先,让我们看一个非常简单的例子。假设您要定义一种搜索请求消息格式,其中每个搜索请求都有一个查询......
  • SummerResearch_Log_20230607
    WorkingContent:1.阅读"VariationalContinualLearning"论文及代码关于ContinualLearning(CL)的认识:这是一个贝叶斯推断过程,这里是gpt给出的贝叶斯推断概念和例子:即先确定一个先验分布,需要求的未知参数是θ(当然也可以添加其他类似α,β)的超参数之类的)。接下来我们进行实......
  • 太卷了,史上最简单的监控系统 catpaw 简介
    指标监控的痛点当下比较流行的监控系统,比如Prometheus、Nightingale、VictoriaMetrics,都是基于数值型指标的监控系统,这类监控系统的痛点在于:告警的时候只能拿到异常值,以及有限的几个标签,难以拿到更详细的信息。比如HTTP探测监控,通常用监控值表示不同的错误:Success=......
  • 【转载】configure: error: C compiler cannot create executables 错误解析
    1原文地址configure:error:Ccompilercannotcreateexecutables错误解析-to_be_better_wen-https://blog.csdn.net/to_be_better_wen/article/details/1306507742前言在编译开源软件的时候,有时会遇到"configure:error:Ccompilercannotcreateexecutables"的错......
  • 事务TCL
          ......
  • 初识云平台-3DEXPERIENCE在线课程 硕迪科技
     3DEXPERIENCE平台可以理解为人与人协作、数据与数据关联、人与数据互动的企业运营支撑平台。本期课程为大家介绍第一次进入3DEXPERIENCE所需要做的一些基础准备工作。内容分为两大部分,一部分是作为平台管理员在平台所需做的基础设置;另一部则是作为平台基本用户可以做的自定义设......
  • OpenHarmony系统之Service代码一键生成工具介绍
    作者:苟晶晶前言当开发者为OpenHarmony系统框架开发某些功能时,有时需要将这个功能包装成一个独立的服务进程运行在系统中,为了其它应用进程能够调用此服务,开发人员需要基于系统IPC通信框架编写一套远程接口调用实现。实现Service远程调用接口需要开发人员熟悉IPC通信框架,了解proxy/......
  • 如何快速使用ChatGPT AI语言模型
    如何快速使用ChatGPTAI语言模型测试日期:2023年6月初1.打开浏览器访问:https://gpt.aigcfast.com2.输入问题后,点击“发送”按钮。3.说明:大型语言模型AI答案会随即给出;支持手机和电脑等各种设备请自我考量隐私和信息的正确性,只做一个临时推荐,有效期不确定,本文将持续更新......
  • if [ "$1""xx" != "xx" ];then current_path=$1 fi汉语
     if["$1""xx"!="xx"];thencurrent_path=$1fi这段sh脚本代码是用来检查当前工作目录的。它的作用是,如果用户传递了一个参数(比如"xx"),而且该参数与当前工作目录不同,则将当前工作目录设置为传递的参数(即"xx")。具体来说,代码中的"if"语句判断参数$1是否等......
  • C#使用webview2摸拟网页提交的一些记录
    想要在C#使用中webview2,最好使用VS2019及以上版本,最低支持.net4.5版本,所以在win7系统上就可以进行开发了ReoGrid是一个类Excel的控件,非常好用,两者搭在一起,可以实现一些自动化的输入工作,非常的方便,Excel的内容可以直接粘贴到这个控件里面 下面说说使用过程中遇到的问题:1、安......