Ⅰ android音视频开发——H264的基本概念
ffmpeg常用命令
封装格式 。
编码的本质就是压缩数据
音频编码的作用: 将音频采样数据( PCM 等)压缩成音频码流,从而降低音频的数据量。 常用的音频编码方式有以下几种:
H264压缩技术主要采用了以下几种方法对视频数据进行压缩。包括:
经过压缩后的帧分为:I帧,P帧和B帧:
除了I/P/B帧外,还有图像序列GOP。
组成码流的结构中,包含了以下几个部分,从大到小依次是:
H264视频序列,图像,片组,片,NALU,宏块,像素
H264功能分为两层:
1.H264视频序列包括一系列的NAL单元,每个NAL单元包含一个RBSP。
2.一个原始的H.264由 N个NALU单元组成
3.NALU单元由[StartCode][NALU Header][NALU Payload]三部分组成
5.NAL Header
由三部分组成forbidden_bit(1bit)(禁止位),nal_reference_bit(2bits)(优先级,,值越大,该NAL越重要),nal_unit_type(5bits)(类型)
nal_unit_type
6.NAL的解码单元的流程如下
Ⅱ h264协议帧头数据解析
原文出自 http://blog.csdn.net/season_hangzhou/article/details/51123979
h264常见的帧头数据为:
00 00 00 01 67 (SPS) :SPS即Sequence Paramater Set,又称作序列参数集。SPS中保存了一组编码视频序列(Coded video sequence)的全局参数。所谓的编码视频序列即原始视频的一帧一帧的像素数据经过编码之后的结构组成的序列。而每一帧的编码后数据所依赖的参数保存于图像参数集中。一般情况SPS和PPS的NAL Unit通常位于整个码流的起始位置。但在某些特殊情况下,在码流中间也可能出现这两种结构,主要原因可能为:
1:解码器需要在码流中间开始解码;
2:编码器在编码的过程中改变了码流的参数(如图像分辨率等);
00 00 00 01 68 (PPS) :除了序列参数集SPS之外,H.264中另一重要的参数集合为图雀歼像参数集Picture Paramater Set(PPS)。通常情况下,PPS类似于SPS,在H.264的裸码流中单独保存在一个NAL Unit中,只是PPS NAL Unit的nal_unit_type值为8;而在封装格式中,PPS通常与SPS一起,保存在视频文件的文件头中。
00 00 00 01 65 ( IDR 帧) : I帧表示关键帧,你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)
00 00 00 01 61 (P帧) :P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。(也就是差别帧,P帧没有完整画面数据,只有与前一帧的画面差别的数据)
start code有两种,四个字节的“00 00 00 01”和三个字节的“00 00 01”都是。
H264帧由NALU头和NALU主体组成顷则冲。
NALU头由一个字节组成,它的语法如下:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
F: 1个比特.
forbidden_zero_bit. 在 H.264 规范中规定了这一位必须为 0.
NRI: 2个比特.
nal_ref_idc. 取00~11,似乎指示这个NALU的重要性,如00的NALU解码器可以丢弃它而不影响图像的回放,0~3,取值越大,表示当前NAL越重要,需要优先受到保护。如果当前NAL是属于参考帧的片,或是序列参数集,或是图像参数集这些重要的单位时,本句法元素必需大于0。
Type: 5个比特.
nal_unit_type. 这个NALU单元的类型,1~12由H.264使用,24~31由H.264以外的应用使用,简述如下:
0 没有定义
1-23 NAL单元 单个 NAL 单元包
1 不分区,非IDR图像的片
2 片分区A
3 片分区B
4 片分区C
5 IDR图像中的片
6 补充增强信息单元(SEI)
7 SPS
8 PPS
9 序列结束
10 序列结束
11 码流借宿
12 盯铅 填充
13-23 保留
24 STAP-A 单一时间的组合包
25 STAP-B 单一时间的组合包
26 MTAP16 多个时间的组合包
27 MTAP24 多个时间的组合包
28 FU-A 分片的单元
29 FU-B 分片的单元
30-31 没有定义
Ⅲ Android如何实现h264硬编码
使用Android中的StageFright框架调用御纤衫睁OpenMAX进行硬件编码,OMX部分由硬件厂商镇塌仿实现,无需关注,看好StageFright的调用方法即可
Ⅳ android mediacodec编码h264 怎样调节gop
简单地说。软解码是用软件方式进行解码,需要占用CPU资源,速度相当较慢。硬解码直接用硬件方式解决,不占用CPU资源,速度相对较快。
mov和mp4是两种不同的封装格式,里面的h.264都是一样的
单位用的是视盈,几年来一直很稳定。推荐你联系视盈黄国耀。一三七,一一一四,六六九一。
仅转换可以使用命令,把任一mp4转换成ts
ffmpeg -i input.mp4 -c -bsf h264_mp4toannexb output.ts 很高兴为您解答!
有不明白的可以追问!如果您认可我的回答。
1. 简单介绍
首先激瞎喊是捕获,这里采用了DirectShow的方式,对它进行了一定程度的封装,包括音视频。好处是直接使用native api,你可以做想做的任何修改,坏处是,不能跨平台,采集音视频这种应用,linux平台也是需要滴呀。有跨平台的做法,对视频,可以使用OpenCV,对音频,可以使用OpenAL或PortAudio等,这样就行了。
编码可以选择的余地比较大,对视频来讲,有H264, MPEG-4, WebM/VP8, Theora等,音频有Speex, AAC, Ogg/Vorbis等,它们都有相应的开源项目方案,我采用的是x264进行H264编码,libfaac进行aac编码,之后是否更改编码方案,等具体项目需求再说了。这里提一下WebM,Google牵头的项目,完全开放和自由,使用VP8和Vorbis编码,webm(mkv)封装,有多家巨头支持,目的是想要取代当前的H264视频编码,号称比后者更加优秀,我没有测试过实际效果。不过有商业公司牵头就是不一样,各项支持明野都很全面,有时间了关注一下。
2. 逻辑和流程
基本的思想是实现dshow ISampleGrabberCB接口,通过回调来保存每一个buffer。除了界面线程和dshow自己的线程之外,我们启动了两个线程,AudioEncoderThread和VideoEncoderThread,分别从SampleGrabber中取出数据,调用编码器进行编码,编码后的文件可以直接输出。看图:
程序是用VS2010构建的,看张工程截图:
Base下面的是对系统API的一些简单封装,主要是线程和锁。我这里简单也封装的了一下dshow的捕获过程,包括graph builder的创建,filter的连接等。directshow是出了名的难用,没办法,难用也得用。因为是VS2010,调用的Windows SDK 7.1中的dshow,没有qedit.h这个文件,而它正式定义ISampleGrabberCB的。不急,系统中还是有qedit.dll的,我们要做的就是从Windows SDK 6.0中,把它拷过来,然后在stdafx.h中加入这几行代码,就可以了
1 #pragma include_alias( "dxtrans.h", "qedit.h" )
2 #define __IDxtCompositor_INTERFACE_DEFINED__
3 #define __IDxtAlphaSetter_INTERFACE_DEFINED__
4 #define __IDxtJpeg_INTERFACE_DEFINED__
5 #define __IDxtKey_INTERFACE_DEFINED__
6 #include "qedit.h"
3. 音视频编码
相关文件:
Encoder下就是音视频编码相关的代码。X264Encoder封装了调用x264编码器的神州操作,FAACEncoder封装了调用libfaac编码器的操作,VideoEncoderThread和AudioEncoderThread负责主要的流程。下面我把关键代码贴出来,大家可以参考一下。
A. 视频编码线程
主要流程是首先初始化x264编码器,然后开始循环调用DSVideoGraph,从SampleGrabber中取出视频帧,调用x264进行编码,流程比较简单,调用的频率就是你想要获取的视频帧率。要注意的一点是,x264进行编码比较耗时,在计算线程Sleep时间时,要把这个过程消耗的时间算上,以免采集的视频帧率错误。
B. 音频编码线程
主要流程和视频编码线程相同,也是初始化FAAC编码器,然后循环调用DSAudioGraph,从SampleGrabber中取出视频帧,调用faac进行编码。和视频不同的是,音频的sample的频率是非常快的,所以几乎要不断的进行采集,但前提是SampleGrabber中捕获到新数据了才行,不然你的程序cpu就100%了,下面代码中IsBufferAvailaber()就是做这个检测的。
调用faac进行编码的时候,有点需要注意,大家特别注意下,不然编码出来的音频会很不正常,搞不好的话会很头疼的。先看下faac.h的相关接口
1 faacEncHandle FAACAPI faacEncOpen(unsigned long sampleRate, unsigned int numChannels,2 unsigned long *inputSamples, unsigned long *maxOutputBytes);3 4 int FAACAPI faacEncEncode(faacEncHandle hEncoder, int32_t * inputBuffer, unsigned int samplesInput,5 unsigned char *outputBuffer, unsigned int bufferSize);
faacEncEncode第三个参数指的是传入的sample的个数,这个值要和调用faacEncOpen返回的inputSamples相等。要做到这点,就要在dshow中设置好buffsize,公式是:
BufferSize = aac_frame_len * channels * wBytesPerSample aac_frame_len = 1024
h.264是一种视频压缩标准了,有专门的库对它进行压缩解压的。
我对opencv还算是比较熟悉的,它没有h264之类的库
不能啊,不同格式的,H264跟DVD不一样啊
音频编辑器
1、运行Set-up.exe,会弹出“遇到了以下问题”弹窗,选择忽略;
2、之后会初始化安装程序,请不要进行任何操作,稍等片刻;
3、有安装和试用两种选择,请点击试用
4、安装需要Adobe ID登录验证,没有的话选择"获取Adobe ID"注册一个,只需有邮箱和密码即可(您也可以选择断开网络连接,选择“以后再登录”),同样也能继续安装;这里为您演示登陆安装。
5、接受协议后,选择安装的语言和安装的目录。
6、之后只需耐心等待,软件需要组件已自带,无需另外安装,这样就等安装完Adobe Premiere Pro CC 2015。
7、安装完毕点击立即启动,启动后不是进入软件而是试用版界面,点击开始试用;
8、打开Premiere Pro CC 2015,选择新建项目才算是进入软件。
PS:若是不事先进入一次软件直接破解会导致软件无法打开。
Premiere Pro CC 2015::3322./soft/201507311409.
需要调用av_parser_parse
进行帧查找分解后再送入解码器解码。
编码是不一样的,H.264采用的帧内编码和帧间预测编码技术 比MPEG-2的都要先进,因此压缩效率更高
Ⅳ 哪位高手做过ffmpeg在android下的运用.小弟我只想调用解码H264的帧
用NDK把ffmpeg 编译成动态库SO 文件
再android工程利用JNI生成接口调用这个静态库。
试过videolan的东西么?
olvaffe/ffmpeg/ffmpeg-android/commits/android
Ⅵ android mediarecorder录制的MP4文件,怎么组成H264文件播放起来
Android(java方法)上实现mp4的分割和拼接 (二)
这节谈一下如何在android上实现mp4文件的高效率切割。
业务需求举例:把一段2分钟的mp4文件切割出00:42 至 01:16这段时间的视频,要求足够短的执行时间和尽量少的误差。
分析:mp4Parser只能在关键帧切割,比如,在00:40和00:45分别存在一个可切割关键帧,那么切割视频的头和尾,都应该选择短切割。然后获取到误差的视频短,如果这个误差大于0.5S,用FFmpeg进行一帧一帧编解码切割文件。这样最多会有三段mp4文件,再次将这三段mp4拼接起来就可以了。
下面直接上关键代码,这些代码在PC上新建一个java工程也可以实现。
1.切割文件方法:
/**
Ⅶ H264之帧编码——透析(I帧+P帧+B帧编码)原理与流程
在H.264压缩标准中I帧、P帧、B帧⽤于表⽰传输的视频画⾯。在视频压缩中,每帧都代表着一幅静止的图像。在实际的视频压缩编码时,会采取各种算法减少数据的容量,其中IPB帧就是最常见的一种算法。
I‑frame (Intra-coded picture): 即完整的一张图片
P‑frame (Predicted picture): 与前面一张图片的区别的区域
B‑frame (Bidirectional predicted picture):与前面以及后面的图片的区别区域
I帧⼜称帧内编码帧,又称全帧压缩编码帧,是⼀种⾃带全部信息的独⽴帧,⽆需参考其他图像便可独⽴进⾏解码,可以简单理解为⼀张静态画⾯。视频序列中的第⼀个帧始终都是I帧,因为它是关键帧。I帧通常是每个GOP(MPEG所使用的一种视频压缩技术)的第一个帧,经过适度地压缩,作为随机访问的参考点,可以当成静态图像。
现在有一段影片如下:
该影片总共是20张图片组成的,每一张完整的图片我们都可以叫做I帧。假如每知祥晌张JPEG的图片大小为100KB,那么传输两张图片即为100 * 20 = 2000KB
要知道这个还不到几秒的影片就2M了,要是几个小时的那还得了,所以就有了影片压缩的算法
1.它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;
2.解码时仅用I帧的数据就可重构完整图像;
3.I帧描述了图像背景和运动主体的详情;
4.I帧不需要参考其他画面而生成;
5.I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);
6.I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧;
7.I帧不需要考虑运动矢量;
8.I帧所占数据的信息量比较大。
P帧⼜称帧间预测编码帧,又称前向预测编码帧,需要参考前⾯的I帧才能进⾏编码。表⽰的是当前帧画⾯与前⼀帧(前⼀帧可能是I帧也可能是P帧)的差别。解码时需要⽤之前缓存的画⾯叠加上本帧定义的差别,⽣成最终画⾯。
与I帧相⽐,P帧通常占⽤更少的数据位,但不⾜是,由于P帧对前⾯的P和I参考帧有着复杂的依耐性,因此对传输错误⾮常敏感。通常将图像序列中前面已经编码帧的时间冗余信息充分去除来压缩传输数据量的编码图像,也称为预测帧。通过观察,我们可以看出,实际上每一帧之间其实只有一部分细微的差别而已,如下图提取了6帧
当传输完第一帧以后,第二帧其实我们只需要传输一部分,然后由另外一端进行图片算法来进行组合
用这种方式,在传输第二帧的时候,还不到原来的1/10,只需要传输第一帧的100KB,后续的都是按照这种方式传输部分,这种只传输部分的图片,就是P帧了。最后整个影片的大小即为100KB + 10KB * 19 = 290 KB,比原来缩小了很多。
1.P帧是I帧后面相隔1~2帧的编码帧;
2.P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);
3.解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;
4.P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧宴并;
5.P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧;
6.由于P帧是参考帧,它可能造成解码错误的扩散;
7.由于是差值传送,P帧的压缩比较高。
B帧⼜称双向预测编码帧,又称双向预测内插编码帧,也就是B帧记录的是本帧与前后帧的差别。也就是说要解码B帧,不仅要取得之前的缓存画⾯,还要解码之后的画⾯,通过前后画⾯的与本帧数据的叠加取得最终的画⾯。B帧压缩率⾼,但是对解码性能要求较⾼。既考虑源图像序列前面的已编码帧,又顾及源图像序列后面的已编码帧之间的时间冗余信息搭锋,来压缩传输数据量的编码图像,也称为双向预测帧。B帧其实就是与前后两张图片的区别。如果理解了P帧和I帧,这个就很好理解了。
B帧比P帧更小,更节省空间
假设现在有三张图片,如下图:
在经过编码后,会变成如下:
1.B帧是由前面的I或P帧和后面的P帧来进行预测的;
2.B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量;
3.B帧是双向预测编码帧;
4.B帧压缩比最高,因为它只反映丙参考帧间运动主体的变化情况,预测比较准确;
5.B帧不是参考帧,不会造成解码错误的扩散。
(1) 进行帧内预测,决定所采用的帧内预测模式。
(2) 像素值减去预测值,得到残差。
(3) 对残差进行变换和量化。
(4) 变长编码和算术编码。
(5) 重构图像并滤波,得到的图像作为其它帧的参考帧。
(1) 进行运动估计,计算采用帧间编码模式的率失真函数(节)值。P帧只参考前面的帧,B 帧可参考后面的帧。
(2) 进行帧内预测,选取率失真函数值最小的帧内模式与帧间模式比较,确定采用哪种编码模式。
(3) 计算实际值和预测值的差值。
(4) 对残差进行变换和量化。
(5) 熵编码,如果是帧间编码模式,编码运动矢量
Android音视频工程师必备《全套音视频入门到精通手册》
I帧只需考虑本帧;P帧记录的是与前⼀帧的差别;B帧记录的是前⼀帧及后⼀帧的差别,能节约更多的空间,视频⽂件⼩了,但相对来说解码的时候就⽐较⿇烦。因为在解码时,不仅要⽤之前缓存的画⾯,⽽且要知道下⼀个I或者P的画⾯,对于不⽀持B帧解码的播放器容易卡顿。
Ⅷ 哪位高手做过ffmpeg在android下的运用.小弟我只想调用解码h264的帧
楼主你好!根据你的描述,让我来给你回答!
用NDK把ffmpeg 编译成动态库SO 文件
再android工程利用JNI生成接口调用这个静态库。
希望能帮到你,如果满意,请记得采纳哦~~~
Ⅸ Android -- 音视频基础知识
帧,是视频的一个基本概念,表示一张画面,如上面的翻页动画书中的一页,就是一帧。一个视频就是由许许多多帧组成的。
帧率,即单位时间内帧的数量,单位为:帧/秒 或fps(frames per second)。一握指秒内包含多少张图片,图片越多,画面越顺滑,过渡越自然。 帧率的一般以下几个典型值:
24/25 fps:1秒 24/25 帧,一般的电影帧率。
30/60 fps:1秒 30/60 帧,游戏的帧率,30帧可以接受,60帧会感觉更加流畅逼真。
85 fps以上人眼基本无法察觉出来了,所以更高的帧率在视频里没有太大意义。
这里我们只讲常用到的两种色彩空间。
RGB的颜色模式应该是我们最熟悉的一种,在现在的电子设备中应用广泛。通过R G B三种基础色,可以混合出所有的颜色。
这里着重讲一下YUV,这种色彩空间并不是我们熟悉的。这是一种亮度与色度分离的色彩格式。
早期的电慧谈视都是黑白的,即只有亮度值,即Y。有了彩色电视以后,加入了UV两种色度,形成现在的YUV,也叫YCbCr。
Y:亮度,就是灰度值。除了表示亮度信号外,还含有较多的绿色通道量。
U:蓝色通道与亮度的差值。
V:红色通道与亮度的差值。
音频数据的承载方式最常用的是 脉冲编码调制 ,即 PCM 。
在自然界中,声音是连续不断的,是一种模拟信号,那怎样才能把声音保存下来呢?那就是把声音数字化,即转换为数字信号。
我们知道声音是一种波,有自己的振幅和频率,那么要保存声音,就要保存声音在各个时间点上的振幅。
而数字信号并不能连续保存所有时间点的振幅,事实上,并不需要保存连续的信号,就可以还原到人耳可接受的声音。
根据奈奎斯特采样定理:为了不失真地恢复模拟信号,采样频率应该不小于模拟信号频谱中最高频率的2倍。
根据以上分析,PCM的采集步骤分为以下步骤:
采样率,即采样的频率。
上面提到,采样率要大于原声波频率的2倍,人耳能听到的最高频率为20kHz,所以为了满足人耳的听觉要求,采样率至少为40kHz,通常为44.1kHz,更高的通常为48kHz。
采样位数,涉及到上面提到的振段碧配幅量化。波形振幅在模拟信号上也是连续的样本值,而在数字信号中,信号一般是不连续的,所以模拟信号量化以后,只能取一个近似的整数值,为了记录这些振幅值,采样器会采用一个固定的位数来记录这些振幅值,通常有8位、16位、32位。
位数越多,记录的值越准确,还原度越高。
最后就是编码了。由于数字信号是由0,1组成的,因此,需要将幅度值转换为一系列0和1进行存储,也就是编码,最后得到的数据就是数字信号:一串0和1组成的数据。
整个过程如下:
声道数,是指支持能不同发声(注意是不同声音)的音响的个数。 单声道:1个声道
双声道:2个声道
立体声道:默认为2个声道
立体声道(4声道):4个声道
码率,是指一个数据流中每秒钟能通过的信息量,单位bps(bit per second)
码率 = 采样率 * 采样位数 * 声道数
这里的编码和上面音频中提到的编码不是同个概念,而是指压缩编码。
我们知道,在计算机的世界中,一切都是0和1组成的,音频和视频数据也不例外。由于音视频的数据量庞大,如果按照裸流数据存储的话,那将需要耗费非常大的存储空间,也不利于传送。而音视频中,其实包含了大量0和1的重复数据,因此可以通过一定的算法来压缩这些0和1的数据。
特别在视频中,由于画面是逐渐过渡的,因此整个视频中,包含了大量画面/像素的重复,这正好提供了非常大的压缩空间。
因此,编码可以大大减小音视频数据的大小,让音视频更容易存储和传送。
视频编码格式有很多,比如H26x系列和MPEG系列的编码,这些编码格式都是为了适应时代发展而出现的。
其中,H26x(1/2/3/4/5)系列由ITU(International Telecommunication Union)国际电传视讯联盟主导
MPEG(1/2/3/4)系列由MPEG(Moving Picture Experts Group, ISO旗下的组织)主导。
当然,他们也有联合制定的编码标准,那就是现在主流的编码格式H264,当然还有下一代更先进的压缩编码标准H265。
H264是目前最主流的视频编码标准,所以我们后续的文章中主要以该编码格式为基准。
H264由ITU和MPEG共同定制,属于MPEG-4第十部分内容。
我们已经知道,视频是由一帧一帧画面构成的,但是在视频的数据中,并不是真正按照一帧一帧原始数据保存下来的(如果这样,压缩编码就没有意义了)。
H264会根据一段时间内,画面的变化情况,选取一帧画面作为完整编码,下一帧只记录与上一帧完整数据的差别,是一个动态压缩的过程。
在H264中,三种类型的帧数据分别为
I帧:帧内编码帧。就是一个完整帧。
P帧:前向预测编码帧。是一个非完整帧,通过参考前面的I帧或P帧生成。
B帧:双向预测内插编码帧。参考前后图像帧编码生成。B帧依赖其前最近的一个I帧或P帧及其后最近的一个P帧。
全称:Group of picture。指一组变化不大的视频帧。
GOP的第一帧成为关键帧:IDR
IDR都是I帧,可以防止一帧解码出错,导致后面所有帧解码出错的问题。当解码器在解码到IDR的时候,会将之前的参考帧清空,重新开始一个新的序列,这样,即便前面一帧解码出现重大错误,也不会蔓延到后面的数据中。
DTS全称:Decoding Time Stamp。标示读入内存中数据流在什么时候开始送入解码器中进行解码。也就是解码顺序的时间戳。
PTS全称:Presentation Time Stamp。用于标示解码后的视频帧什么时候被显示出来。
前面我们介绍了RGB和YUV两种图像色彩空间。H264采用的是YUV。
YUV存储方式分为两大类:planar 和 packed。
planar如下:
packed如下:
上面说过,由于人眼对色度敏感度低,所以可以通过省略一些色度信息,即亮度共用一些色度信息,进而节省存储空间。因此,planar又区分了以下几种格式:YUV444、 YUV422、YUV420。
YUV 4:4:4采样,每一个Y对应一组UV分量。
YUV 4:2:2采样,每两个Y共用一组UV分量。
YUV 4:2:0采样,每四个Y共用一组UV分量。
其中,最常用的就是YUV420。
YUV420属于planar存储方式,但是又分两种类型:
YUV420P:三平面存储。数据组成为YYYYYYYYUUVV(如I420)或YYYYYYYYVVUU(如YV12)。
YUV420SP:两平面存储。分为两种类型YYYYYYYYUVUV(如NV12)或YYYYYYYYVUVU(如NV21)
原始的PCM音频数据也是非常大的数据量,因此也需要对其进行压缩编码。
和视频编码一样,音频也有许多的编码格式,如:WAV、MP3、WMA、APE、FLAC等等,音乐发烧友应该对这些格式非常熟悉,特别是后两种无损压缩格式。
但是,我们今天的主角不是他们,而是另外一个叫AAC的压缩格式。
AAC是新一代的音频有损压缩技术,一种高压缩比的音频压缩算法。在MP4视频中的音频数据,大多数时候都是采用AAC压缩格式。
AAC格式主要分为两种:ADIF、ADTS。
ADIF:Audio Data Interchange Format。音频数据交换格式。这种格式的特征是可以确定的找到这个音频数据的开始,不需进行在音频数据流中间开始的解码,即它的解码必须在明确定义的开始处进行。这种格式常用在磁盘文件中。
ADTS:Audio Data Transport Stream。音频数据传输流。这种格式的特征是它是一个有同步字的比特流,解码可以在这个流中任何位置开始。它的特征类似于mp3数据流格式。
ADIF数据格式:
ADTS 一帧 数据格式(中间部分,左右省略号为前后数据帧):
AAC内部结构也不再赘述,可以参考AAC 文件解析及解码流程
细心的读者可能已经发现,前面我们介绍的各种音视频的编码格式,没有一种是我们平时使用到的视频格式,比如:mp4、rmvb、avi、mkv、mov...
没错,这些我们熟悉的视频格式,其实是包裹了音视频编码数据的容器,用来把以特定编码标准编码的视频流和音频流混在一起,成为一个文件。
例如:mp4支持H264、H265等视频编码和AAC、MP3等音频编码。
我们在一些播放器中会看到,有硬解码和软解码两种播放形式给我们选择,但是我们大部分时候并不能感觉出他们的区别,对于普通用户来说,只要能播放就行了。
那么他们内部究竟有什么区别呢?
在手机或者PC上,都会有CPU、GPU或者解码器等硬件。通常,我们的计算都是在CPU上进行的,也就是我们软件的执行芯片,而GPU主要负责画面的显示(是一种硬件加速)。
所谓软解码,就是指利用CPU的计算能力来解码,通常如果CPU的能力不是很强的时候,一则解码速度会比较慢,二则手机可能出现发热现象。但是,由于使用统一的算法,兼容性会很好。
硬解码,指的是利用手机上专门的解码芯片来加速解码。通常硬解码的解码速度会快很多,但是由于硬解码由各个厂家实现,质量参差不齐,非常容易出现兼容性问题。
MediaCodec 是Android 4.1(api 16)版本引入的编解码接口,是所有想在Android上开发音视频的开发人员绕不开的坑。
由于Android碎片化严重,虽然经过多年的发展,Android硬解已经有了很大改观,但实际上各个厂家实现不同, 还是会有一些意想不到的坑。
相对于FFmpeg,Android原生硬解码还是相对容易入门一些,所以接下来,我将会从MediaCodec入手,讲解如何实现视频的编解码,以及引入OpenGL实现对视频的编辑,最后才引入FFmpeg来实现软解,算是一个比较常规的音视频开发入门流程吧。
Ⅹ Android 音视频01 --- H264的基本原理01
H264压缩技术主要采用了以下几种方法对视频数据进行压缩。包括:
解决的是空域数据冗余问题。
解决的是时域数据冗徐问题
将空间上的相关性变为频域上无关的数据然后进行量化。
经过压缩后的帧分为:I帧,P帧和B帧:
关键帧,采用帧内压缩技术。
向前参考帧,在压缩时,只参考前面已经处理的帧。采用帧音压缩技术。
双向参考帧,在压缩时,它即参考前而的帧,又参考它后面的帧。采用帧间压缩技术。
除了I/P/B帧外,还有图像序列GOP。
H264的基本原理其实非常简单,下我们就简单的描述一下H264压缩数据的过程。通过摄像头采集到的视频帧(按每秒 30 帧算),被送到 H264 编码器的缓冲区中。编码器先要为每一幅图片划分宏块。
划分好宏块后,计算宏块的象素值。以此类推,计算一幅图像中每个宏块的像素值。
对于视频数据主要有两类数据冗余,一类是时间上的数据冗余,另一类是空间上的数据冗余。其中时间上的数据冗余是最大的。为什么说时间上的冗余是最大的呢?假设摄像头每秒抓取30帧,这30帧的数据大部分情况下都是相关联的。也有可能不止30帧的的数据,可能几十帧,上百帧的数据都是关联特别密切的。
H264编码器会按顺序,每次取出两幅相邻的帧进行宏块比较,计算两帧的相似度。如下图:
在H264编码器中将帧分组后,就要计算帧组内物体的运动矢量了。
H264编码器首先按顺序从缓冲区头部取出两帧视频数据,然后进行宏块扫描。当发现其中一幅图片中有物体时,就在另一幅图的邻近位置(搜索窗口中)进行搜索。如果此时在另一幅图中找到该物体,那么就可以计算出物体的运动矢量了。
运动矢量计算出来后,将相同部分(也就是绿色部分)减去,就得到了补偿数据。我们最终只需要将补偿数据进行压缩保存,以后在解码时就可以恢复原图了。压缩补偿后的数据只需要记录很少的一点数据。
我们把运动矢量与补偿称为 帧间压缩技术 ,它解决的是视频帧在时间上的数据冗余。除了帧间压缩,帧内也要进行数据压缩,帧内数据压缩解决的是空间上的数据冗余。
人眼对图象都有一个识别度,对低频的亮度很敏感,对高频的亮度不太敏感。所以基于一些研究,可以将一幅图像中人眼不敏感的数据去除掉。这样就提出了帧内预测技术。
一幅图像被划分好宏块后,对每个宏块可以进行 9 种模式的预测。找出与原图最接近的一种预测模式。然后,将原始图像与帧内预测后的图像相减得残差值。再将我们之前得到的预测模式信息一起保存起来,这样我们就可以在解码时恢复原图了,经过帧内与帧间的压缩后,虽然数据有大幅减少,但还有优化的空间。
可以将残差数据做整数离散余弦变换,去掉数据的相关性,进一步压缩数据。
上面的帧内压缩是属于有损压缩技术。也就是说图像被压缩后,无法完全复原。而CABAC属于无损压缩技术。
无损压缩技术大家最熟悉的可能就是哈夫曼编码了,给高频的词一个短码,给低频词一个长码从而达到数据压缩的目的。MPEG-2中使用的VLC就是这种算法,我们以 A-Z 作为例子,A属于高频数据,Z属于低频数据。看看它是如何做的。
CABAC也是给高频数据短码,给低频数据长码。同时还会根据上下文相关性进行压缩,这种方式又比VLC高效很多。
制定了相互传输的格式,将宏快 有组织,有结构,有顺序的形成一系列的码流。这种码流既可 通过 InputStream 网络流的数据进行传输,也可以封装成一个文件进行保存,主要作用是为了传输。
组成H264码流的结构中 包含以下几部分 ,从大到小排序依次是:
H264视频序列,图像,片组,片,NALU,宏块 ,像素。
NAL层:(Network Abstraction Layer,视频数据网络抽象层) : 它的作用是H264只要在网络上传输,在传输的过程每个包以太网是1500字节,而H264的帧往往会大于1500字节,所以要进行拆包,将一个帧拆成多个包进行传输,所有的拆包或者组包都是通过NAL层去处理的。
VCL层:(Video Coding Layer,视频数据编码层) : 对视频原始数据进行压缩
起始码0x 00 00 00 01 或者 0x 00 00 01 作为 分隔符 。
两个 0x 00 00 00 01之间的字节数据 是表示一个NAL Unit。
I 帧的特点:
1.分组:把几帧图像分为一组(GOP,也就是一个序列),为防止运动变化,帧数不宜取多。
2.定义帧:将每组内各帧图像定义为三种类型,即I帧、B帧和P帧;
3.预测帧:以I帧做为基础帧,以I帧预测P帧,再由I帧和P帧预测B帧;
4.数据传输:最后将I帧数据与预测的差值信息进行存储和传输。
1.更高的编码效率:同H.263等标准的特率效率相比,能够平均节省大于50%的码率。
2.高质量的视频画面:H.264能够在低码率情况下提供高质量的视频图像,在较低带宽上提供高质量的图像传输是H.264的应用亮点。
3.提高网络适应能力:H.264可以工作在实时通信应用(如视频会议)低延时模式下,也可以工作在没有延时的视频存储或视频流服务器中。
4.采用混合编码结构:同H.263相同,H.264也使用采用DCT变换编码加DPCM的差分编码的混合编码结构,还增加了如多模式运动估计、帧内预测、多帧预测、基于内容的变长编码、4x4二维整数变换等新的编码方式,提高了编码效率。
5.H.264的编码选项较少:在H.263中编码时往往需要设置相当多选项,增加了编码的难度,而H.264做到了力求简洁的“回归基本”,降低了编码时复杂度。
6.H.264可以应用在不同场合:H.264可以根据不同的环境使用不同的传输和播放速率,并且提供了丰富的错误处理工具,可以很好的控制或消除丢包和误码。
7.错误恢复功能:H.264提供了解决网络传输包丢失的问题的工具,适用于在高误码率传输的无线网络中传输视频数据。
8.较高的复杂度:264性能的改进是以增加复杂性为代价而获得的。据估计,H.264编码的计算复杂度大约相当于H.263的3倍,解码复杂度大约相当于H.263的2倍。
H.264的目标应用涵盖了目前大部分的视频服务,如有线电视远程监控、交互媒体、数字电视、视频会议、视频点播、流媒体服务等。H.264为解决不同应用中的网络传输的差异。定义了两层:视频编码层(VCL:Video Coding Layer)负责高效的视频内容表示,网络提取层(NAL:Network Abstraction Layer)负责以网络所要求的恰当的方式对数据进行打包和传送。