为什么选择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)不用对同一个帧进行操作。当然也可以不用多线程,同一个帧在播放完成后进行,录制。

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

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

[C#] FFmpeg 音视频开发总结的更多相关文章

  1. 音视频开发-FFmpeg

    音视频开发是个非常复杂的,庞大的开发话题,初涉其中,先看一下结合 OEIP(开源项目) 新增例子. 可以打开flv,mp4类型文件,以及rtmp协议音视频数据,声音的播放使用SDL. 把采集的麦/声卡 ...

  2. WebRTC 音视频开发

    WebRTC 音视频开发 webrtc   Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译 ...

  3. Android 音视频开发学习思路

    Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ...

  4. Android 音视频开发入门指南

    Android 音视频从入门到提高 —— 任务列表 http://blog.51cto.com/ticktick/1956269(以这个学习为基础往下面去学习) Android 音视频开发学习思路-- ...

  5. 转:Android IOS WebRTC 音视频开发总结 (系列文章集合)

    随笔分类 - webrtc   Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译和整理的,译 ...

  6. moviepy音视频开发:音频剪辑基类AudioClip

    ☞ ░ 前往老猿Python博文目录 ░ 一.背景知识介绍 1.1.声音三要素: 音调:人耳对声音高低的感觉称为音调(也叫音频).音调主要与声波的频率有关.声波的频率高,则音调也高. 音量:也就是响度 ...

  7. Android 音视频开发(一):PCM 格式音频的播放与采集

    什么是 PCM 格式 声音从模拟信号转化为数字信号的技术,经过采样.量化.编码三个过程将模拟信号数字化. 采样 顾名思义,对模拟信号采集样本,该过程是从时间上对信号进行数字化,例如每秒采集 44100 ...

  8. 【秒懂音视频开发】02_Windows开发环境搭建

    音视频开发库的选择 每个主流平台基本都有自己的音视频开发库(API),用以处理音视频数据,比如: iOS:AVFoundation.AudioUnit等 Android:MediaPlayer.Med ...

  9. Android音视频开发(1):H264 基本原理

    前言 H264 视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的.随着 x264/openh264 以及 ffmpeg 等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大 ...

  10. Android IOS WebRTC 音视频开发总结(八十五)-- 使用WebRTC广播网络摄像头视频(下)

    本文主要介绍WebRTC (我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:bl ...

随机推荐

  1. Kafka 消息送达语义

    更多内容,前往IT-BLOG 消息送达语义是消息系统中一个常见的问题,主要包含三种语义:[1]At most once:消息发送或消费至多一次:[2]At least once:消息发送或消费至少一次 ...

  2. SpringBoot集成海康网络设备SDK

    目录 SDK介绍 概述 功能 下载 对接指南 集成 初始化项目 初始化SDK 初始化SDK概述 新建AppRunner 新建SdkInitService 新建InitSdkTask 新建 HCNetS ...

  3. 在windows系统中设置MySQL数据库

    MySQL搭建 效果图 step1:下载安装包 https://downloads.mysql.com/archives/community/ step2:解压后即完成安装 step3:创建 my.i ...

  4. 机器学习(三):朴素贝叶斯+贝叶斯估计+BP人工神经网络习题手算|手工推导与习题计算

    1.有 1000 个水果样例. 它们可能是香蕉,橙子或其它水果,已知每个水果的 3 种特性:是否偏长.是否甜.颜色是否是黄色 类型 长 不长 甜 不甜 黄色 非黄 Total 香蕉 400 100 3 ...

  5. flask-sqlalchemy入门

    Flask-SQLAlchemy 是一个为 Flask 应用增加 SQLAlchemy 支持的扩展.它致力于简化在 Flask 中 SQLAlchemy 的使用.SQLAlchemy 是目前pytho ...

  6. [数据库]MYSQL之InnoDB存储引擎 VS MYISAM存储引擎

    InnoDB VS MYISAM 参考文献 innoDB与MyISAM的区别 - Zhihu

  7. Python简易学生管理系统

    目录结构: 1. 学生文件 student.py # 学生类 class Student(object): # 存放学生信息 student_info = {} # 学生初始化方法 def __ini ...

  8. [INS-40996] Installer has detected that the Oracle home (/home/grid) is not empty in the following nodes: [rac2] --求助帖?

    问题描述:12c安装grid的时候,一直再报一个[INS-40996] Installer has detected that the Oracle home (/home/grid) is not ...

  9. SMT贴片加工钢网工艺制作方法

    smt贴片加工过程中,首先要进行锡膏印刷,而锡膏印刷的工作原理就是用机器刮刀将锡膏推送到钢网的孔洞中,使锡膏与pcb板的电子元器件接触,为下一步焊接做准备.钢网的作用就是与pcb板焊盘位置固定,使锡膏 ...

  10. 如何训练个人的ChatGpt4

    如何在自己的计算机上安装类似 ChatGPT 的个人 AI 并在没有互联网的情况下运行它 本文旨在为任何人安装此软件.最初它有一个视频,伴随着操作方法,但是事情变化很快,我的三次尝试只是推迟了我发表这 ...