音视频开发是个非常复杂的,庞大的开发话题,初涉其中,先看一下结合 OEIP(开源项目) 新增例子.

  

  可以打开flv,mp4类型文件,以及rtmp协议音视频数据,声音的播放使用SDL。

  

  把采集的麦/声卡数据混合并与采集的视频信息写入媒体文件或是RMTP协议中。

图片主要属性

  包含长/宽/通道数/像素格式(U8/U16/F32),以及排列格式RGBA/YUV。其中通道与像素格式,如在opencv中,CV_8UC1/CV_8UC4,表示1个通道与4个通道的U8格式。而排列格式,简单的分为RGBA类的,如BGRA,BGR,R这些,一般用于游戏里的纹理,RGBA/BGR/R本身有表示通道格式的意思,所以后面组合RGBA32,RGBAF32用来表示通道像素里数据格式。而YUV类型,一般用在媒体类型,如采集设备,音视频文件,推拉流传输等,YUV格式有二个组成部分。一是UV对应像素个数,如YUV420,YUV422,YUV444,他们的相同点就是一个像素点对应一个Y,不同点是,如YUV420表示一个U/V对应4个像素点,422一个UV对应二个像素点,UV444则表示一个UV对应一个像素点,YUV像素点数据格式一般是U8。

  我们可以来比较一些常用格式最终占用字节大小,如1080P下。

  • RGBA32 1920*1080*4=8,294,400‬ 其中4是每个像素包含RGBA四个通道。
  • YUV420 1920*1080 + 980*540*2 前面是Y占用大小,后面是UV占用大小。
  • YUV422 1920*1080 + 980*1080*2 前面是Y占用大小,后面是UV占用大小
  • YUV444 1920*1080*3 每个像素一个YUV三通道。

  第二是排序格式,如YUV420可以细分YUV420I,YUV420P,YUV420SP(NV12),简单来说,后缀是P是表示YUV这三个分开存放,而SP是Y单独分开,UV交织在一起,而I就更简单了,YUV交织在一起,简单来说,和RGBA格式差不多排列。
YUV420P/YUV422P 一般用来视频文件与推拉流传输上,我想可能原因是Y用来表示亮度,人眼最敏感部分,早期黑白电视只有Y大家一样能看,这种格式最方便兼容,直接把UV丢弃就行,Y/U/V可能在内存分布上不连续。其中YUV420I/YUV422I 这种交织的一般是采集设备所用,内存上连续,方便处理,YUV420SP(NV12) 这种一般也是采集设备所有,这种格式简单来说,一是方便只使用Y,二是UV可以和Y的宽度统一,后面align的话,YUV也是统一一个,内存上也方便连续。

音频基本属性如下

  采样率:如人耳听到最高频率是22kHz,如要完全重现频率,需要采样率是频率*2,所以一般来说44100是很常见的采样率。

  声道数:常见单声道,双声道,也有不常见的更多声道。

  数据格式:一般是S16(16位有符号整合),F32(32位浮点),别的不算常用如U8,D64,这二个表示的分贝范围一个太小,一个太大。

  和图像类型,多个声道的表示方法也有P(平面),I(交织),类似,音频采集数据一般是I,传输P,在OEIP项目中,相应格式一般都转成单声道S16,也就不需要管理是P还是I。

音视频开发基本概念

  有了上面基本认识,我们再来认识一些概念(以下是本人的一些基本理解,如果有错,欢迎大家指出)。

  编码:把原始音视频数据压缩,简单来说,1080PYUV420的大小1920*1080*3/2=3,110,400 Byte,1秒25桢的话就有差不多78M。视频如YUV->H264,音频PCM->ACC过程就是编码。在FFmpeg中,类似过程就是AVFrame->AVPacket

  解码:把压缩后的音视频转换成原始音视频数据,H264->YUV,ACC->PCM过程。在FFmpeg中,就是AVPacket->AVFrame.

  在编码与解码中,图像每桢原始大小取决原始图像大小根据长宽,像素排序和格式组成,而音频每桢对于特定编解码器是每个通道固定多少采样点,如AAC是1024(也有特殊情况2048的),MP3是1152,相应字段在AVFrame.nb_sampes,AVCodecContext.frame_size里表示.这样AAC中双通道 U16每桢数据量就在2*sizeof(U16)*1024.而码率决定了编码质量,一般情况下,码率高质量好,但是生成文件或是网络占用就好,合适的码率网上有介绍,1080P下一般用4M的码率,你用1M也行,但是画面动的时候可能就糊了,码率控制也有不同的控制策略,根据需求选择自己的控制策略,这部分网上有详细的讲解。

  媒体文件:FLV/MP4这些,不同媒体格式把编码的信息用不同的方式保存,不同媒体格式支持不同的编码格式,大部媒体格式都支持h264/acc编码信息,所以这二个编码格式比较常用。

  多媒体协议:RTMP/RTSP这些,在媒体文件之上封装网络传输与控制的相关信息。

  音视频流:流分为音频流,视频流,字幕流等等这些,其中 媒体文件里可能包含一个或多个音视频流,而每个视频流是相同属性(长宽,像素格式等)的原始视频数据编码成的信息流。

  复用:举个例子,把一个音频流与一个视频流合成一个媒体文件,就是复用。

  解复用:如上,把一个媒体文件分解成相应的音频流与视频流。

FFmpeg主要对象

  AVFormatContext:多媒体协议或是媒体文件,如果是协议,会解析出协议里包含的媒体文件信息,这个类主要如今读/写压缩包,读/写文件头与文件尾等方法。你可以把这对象认为是一个媒体文件。

  AVCodec:编解码,注意编码与解码或是用同一codecId,但是对象不同,这个对象主要包含一些函数指针,告诉如何把frame->packet/packet->frame.

  AVCodecContext:编解码环境,简单来说,AVCodec是说如何编解码,这个就是告诉他相应属性设置,如对应视频来说,长宽,以及编码相应设置是否包含B桢,GOP是多少都在这,可以这么理解,我们假设AVCodec与AVCodecContext如果是一个类,那么AVCodec相当于里面的方法集合,AVCodecContext相当于里面的变量集合。

  AVStream:媒体文件一般来说至少包含一个音频流或是视频流,在复用/解复用到编解码之间是个承上启下的关系。你可以理解AVStream包含音视频编码的信息列表。AVStream也要包含相应的AVCodecContext包含的编解码信息,后面会讲这二者信息在复用与解复用从那复制到那。

  AVFrame:音视频原始信息,包含一个定长的数据信息。

  AVPacket:音视频编码信息,包含一个不定长的数据信息。

FFmpeg常见API分析

  读一个媒体文件相应动作与API解析。

  avformat_open_input 根据媒体文件/协议地址打开AVFormatContext。

  avformat_find_stream_info 查找AVFormatContext里对应的音视频流索引。

  avcodec_find_decoder 根据索引打开对应音频与视频流解码器。

  avcodec_alloc_context3 根据解码器生成解码器环境。

  avcodec_parameters_to_context 把流的解码器参数(图像长宽,音频基本属性以及frame_size)复制到解码器环境.

  avcodec_open2 打开解码器环境。

  av_read_frame 从媒体文件AVFormatContext读每个AVPacket。

  avcodec_send_packet 根据对应AVPacket的索引,发给对应流的解码器解码。

  avcodec_receive_frame 得到解码器解码后的原始数据,如在视频流中,因P桢B桢关系,一个AVPacket并不一定能得到一个AVFrame,比如P桢要考虑前后,所以可能到后几个Packet的时候,一下读出多桢数据,所以avcodec_send_packet/avcodec_receive_frame的写法会是这样一个情况。

  写入媒体文件相应动作与API解析(非IO模式):

  avformat_alloc_output_context2 根据对应格式生成一个AVFormatContext,不同格式会固定一些数据,比如上FLV格式,音频流与视频流的时间基就是毫秒,我试着改过这值,后面也会在avformat_write_header之后重新改回来。

  avcodec_find_encoder/avcodec_find_encoder_by_name 选择自己想要的编码器。

  avcodec_alloc_context3 选择选择的编码器生成编码器环境,不同与上面 的解码过程,这里我们要自己填充相应信息,如图像编码需要知道长宽,码率,gop等设置。

  avcodec_open2 打开解码器环境。

  avformat_new_stream 生成相应音视频流信息,填充对应编码器到AVFormatContext里。

  avcodec_parameters_from_context 把编码器设置的参数复制到流中。

  avio_open 协议的解析以及协议的操作指针,如何读写协议信息,协议头,协议内容等。

  avformat_write_header 写入头信息。

  avcodec_send_frame 把末压缩数据给编码器。

  avcodec_receive_packet 拿到编码后的数据,和解码类似,P桢决定不可能一Frame一packet,可能要前后几个Frame,才能得到一系列的packet.

  av_interleaved_write_frame 把编码后的音视频数据交叉写入媒体文件中

  av_write_trailer 结束写入,根据写入的所有数据填充一部分需要计算的值。

  还有一种IO模式,可以利用关键桢图像与音频数据直接写入IO中,然后直接从桢中读取相应音视频流的属性拿来直接用,用来不确定视频流长宽等情况下使用。

  从API可以看读写的差异,读的媒体文件AVFormatContext里面的信息全有,读到流,从流里得到解码信息,打开解码器,从AVFormatContext读每个包,用解码器解码包。写入媒体文件就是生成一个空白的AVFormatContext,然后打开选择的编码器,生成流,然后写入流中每桢数据,使用编码器编码后定稿文件。

  图像上相关的坑,媒体文件一般使用是YUV的P格式,这个格式YUV分块保存,还有相应align的概念,举个例子,假设你宽是1080,但是在YUV分块中,Y宽度可能是1088(假设当时使用32定齐),其中每行数据索引处1080-1087以0填充,相应的图像处理我全部提出来在OEIP处理,在OEIP中图像数据全给GPU处理,需要的是紧湊数据,所以需要用av_image_copy_to_buffer/av_image_fill_arrays处理。

  音频上相关的坑,媒体文件多声道也是用的P格式,而音频采集与播放设备一般用的I格式,所以一般要用swr_convert转换,音频播放使用SDL库,就几个API调用就行,在这就不说了,可以查看相应OEIP里的代码处理,音频采集Winodws用的是WASAPI。

  时间基的概念:音视频流都有一个时间基的概念,这个比较重要,flv的音视频都是(1,1000),如果是mp4,视频的时间基为(1,90000),音频一般设为对应采样率。时间基,你可以简单理解为1秒内刻度,flv的流对应就是毫秒,而mp4视频流的时间基对应的是1/90毫秒,什么意义了,比如你视频对应的是25桢,在flv里,每桢相隔40个时间基,而在mp4里,相隔360个时间基,在编码时,我们需要把frams上的pts/dts/duration以对应时间基为单位,注意转换,在OEIP中,我们把所有转出/转入与用户有关的时间全是毫秒,其中转换我们内部自己处理。

  故到此 OEIP 中,可用的输入输出源新增媒体文件/协议,同样,这些功能在Unity3D/UE4里很方便展示,比如把媒体文件/协议里的内容直接展示成对应Unity3D/UE4里的Texture2D显示,或是把Unity3D/UE4里的Texture2D/RTT里的数据保存视频或是推送出去。

  参考:
  https://www.cnblogs.com/leisure_chn/category/1351812.html 叶余 FFmpeg开发

音视频开发-FFmpeg的更多相关文章

  1. WebRTC 音视频开发

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 【译文连载】 理解Istio服务网格(第七章 安全)

    全书目录 第一章 概述 第二章 安装 第三章 流控 第四章 服务弹性 第五章 混沌测试 第六章 可观测性 本文目录 第7章 安全 7.1 身份认证 7.1.1 Kubernetes上的Istio的身份 ...

  2. python.五角星

    import turtle turtle.pensize(4)turtle.pencolor("black") turtle.fillcolor("red")t ...

  3. html5 中高级选择器 querySelector

    简介 HTML5向Web API新引入了document.querySelector以及document.querySelectorAll两个方法用来更方便地从DOM选取元素,功能类似于jQuery的 ...

  4. List remove ConcurrentModificationException源码分析

    代码块 Java         Exception in thread "main" java.util.ConcurrentModificationException at j ...

  5. MongoDB TTL索引的使用

    目录 一.TTL索引介绍 二.TTL索引运行逻辑 三.TTL索引的限制 四.TTL索引的使用场景 1. 指定具体的过期时间属性 2. 插入一个具体的过期时间 3. TTL属性的修改(collMod) ...

  6. html5特性简要概括

    1.html5主要的设计目的: 互联网语义化,以便更好地被人类和机器阅读 更好的在移动设备上支持web应用 https://www.w3.org/TR/html5 新增内容: 新的语义标签 <h ...

  7. tkinter学习1

    GUI 用户交互界面 tkinter 介绍 tkinter是 python自带的gui库,对图像处理库tk的封装 #导入tkinter库 import tkinter #创建主窗口对象 root = ...

  8. 交换机三种模式Access、Hybrid和Trunk

    [端口介绍] 种链路类型:access.trunk.hybird 个VLAN,一般用于连接计算机端口: Trunk类型端口:可以允许多个VLAN通过,可以接收和发送多个VLAN 报文, 一般用于交换机 ...

  9. Ext.grid rowexpander的展开与收缩

    这里写Ext.grid.Panel的展开与收缩. 1. 确保在grid存在rowexpander对象: plugins: [{ ptype: 'rowexpander', rowBodyTpl: [' ...

  10. postman集合测试执行

    postman工具可以运用集合管理接口请求,特别适合某业务流程的集合请求管理. 如果单个请求诸葛send,耗时费力,可以直接以集合运行 一,运行方法: 1,选中集合--点击右侧小箭头--显示页面中点击 ...