您的位置:首页 > 其它

H.264/H.265/VP8/VP9视频格式,lame/x264/aac等编码器解码器(音视频)

2016-08-16 11:20 966 查看
    FFmpeg自带了H264、AAC、MP3的解码器,但却没有(或没有好的)相应的编码器。相应的编码器需要使用第三方库。推荐使用的第三方库为x264(H264编码) 、FDK_AAC(AAC编码),lame(MP3编码)。LAME-MP3编码引擎(音频)。

openh264(https://github.com/cisco/openh264)则是由思科开源的另外一个h264编码器。

Google开源的一个YUV处理库,上面只针对1080p->540p视频帧缩放的算法,而对于通用的压缩处理,可以直接使用这里的实现,对比起ffmpeg的速度快上不少。https://chromium.googlesource.com/libyuv/libyuv/

官网lame- https://sourceforge.net/projects/lame/files/lame/

官网x264编码的源代码- http://www.videolan.org/developers/x264.html

官网(fdk-aac)opencore-amr- https://sourceforge.net/projects/opencore-amr/files/fdk-aac/

fdk-aac编码的库地址是- https://github.com/Arcen/fdk-aac https://github.com/mstorsjo/fdk-aac

 Android NDK 编译 FFmpeg + x264 + fdk-aac (arm/x86)的配置脚本- http://blog.csdn.net/panda1234lee/article/details/53099203
> 即时通信IM中语音格式可以使用amr;视频格式可以使用mp4

常见的音频压缩格式有:MP3、AAC、OGG、WMA、Opus、FLAC、APE、m4a和AMR等。

常见的视频封装格式有:MP4、3GP、AVI、MKV、WMV、MPG、VOB、FLV、SWF、MOV、RMVB和WebM等。

--音频格式有:1、CD;2、OGG;3、MP3;4、ASF、WMA;5、WAV;6、MP3PRO;7、RM;8、REAL;9、APE;10、MODULE;11、MIDI;12、VQF
http://baike.baidu.com/link?url=tmkYau9u-YKkCiszIW540P4SBglTEos4fdV_32AXKvGlxEdS_1sDklaV2IVFG3afF2jLRq3Mit7J_9lUkFOMtK
--视频格式有:rm,rmvb,mpeg1-4 mov mtv dat wmv avi 3gp amv dmv
http://zhidao.baidu.com/link?url=JDNs5AynU63rpqUtglCCSyTuEQfG00f3J1lW_Pq5rUfDfrd-YHna8GTGP1VUCIjK1qqkutl1zpSccIKbehv4_a http://baike.baidu.com/link?url=JDNs5AynU63rpqUtglCCS6jXiHuTdqajUguPF_o54IgNZ4ba4bjWA5vdqlJJCt7R680FtghgUj_nSwAh3qqr5K
Android录音支持的格式有amr、aac
> 直播中可用的音视频数据涉及技术或协议:编码方式:CBR、VBR编码格式

视频:H.265、H.264、MPEG-4等,封装容器有TS、MKV、AVI、MP4等

音频:G.711μ、AAC、Opus等,封装有MP3、OGG、AAC等

> 视频编码器

 最简单的视频编码器:编译(libx264,libx265,libvpx)- http://blog.csdn.net/leixiaohua1020/article/details/42069383
x264,x265,vpx这三个开源的视频编码器可以说是当今“最火”的视频编码器。x264现在占据着H.264视频编码器的半壁江山;x265则是目前实现H.265标准最好的开源视频编码器,并且在未来可能接替x264;而vpx则是Google推出的开源视频编码器,它提出的VP9编码标准的性能也不错。

 视频转码技术就不得不提到两个开源工程:ffmpeg和x264。

> 语音处理三方开源:

  Speex在Android上的实现。Speex是一套主要针对语音的开源免费,无专利保护的音频压缩格式。Speex工程着力于通过提供一个可以替代高性能语音编解码来降低语音应用输入门槛 。另外,相对于其它编解码,Speex也很适合网络应用,在网络应用上有着自己独特的优势。同时,Speex还是GNU工程的一部分,在改版的BSD协议中得到了很好的支持。Speex是基于CELP并且专门为码率在2-44kbps的语音压缩而设计的。Speex源码是基于c语音实现的(也有Java实现,效率相对较低)。

  iLBC算法也是开源算法,在GitHub可以下载到,源地址如下https://github.com/bjdodson/iLBC-Android ,同时code.google(http://code.google.com/p/android-ilbc/)上也有一份,code.google.上的比较清晰.iLBC 算法为数据包网络实现了尖端的固定比特率编码,在质量与比特率之间取得了非常出色的平衡。

  Silk编解码是Skype向第三方开发人员和硬件制造商提供免版税认证(RF)的Silk宽带音频编码器。Skype已将其开源,可以访问http://developer.skype.com/silk获取最新动向。SILK Codec是一个语音和音频编解码算法, 对于音频带宽、网络带宽和算法复杂度都具有很好的弹性。支持4种采样率:8KHz、12KHz、16KHz、24KHz;三种复杂度:低、中、高。编码码率在 6~40kbps(不同采样率具有不同的码率范围)以及还支持VAD、DTX、FEC等模块,感觉还是比较全面。最重要的一点是提供了定点C代码,非常有利于向ARM、DSP移植和优化。

   OpenH264 则是由思科开源的另外一个 H264 编码器,项目在 2013 年开源,对比起 x264 来说略显年轻,不过由于思科支付买了 H.264 的年度专利费,所以对于外部用户来说,相当于可以直接免费使用了。另外,firefox 直接内置了 OpenH264,作为其在 WebRTC 中的视频编解码器使用。

    https://chromium.googlesource.com/libyuv/libyuv/ Google 开源的一个 YUV 处理库,上面只针对 1080p->540p 视频帧缩放的算法,而对于通用的压缩处理,可以直接使用这里的实现,对比起 FFmpeg 的速度快上不少。

> Lame的官方网址:http://lame.sourceforge.net/  https://sourceforge.net/projects/lame/files/lame/

  LAME是目前最好的MP3编码引擎。LAME编码出来的MP3音色纯厚、空间宽广、低音清晰、细节表现良好,它独创的心理音响模型技术保证了CD音频还原的真实性,配合VBR和ABR参数,音质几乎可以媲美CD音频,但文件体积却非常小。WAV格式本身,就等于PCM码流.

LAME的版本3.99.5-http://download.csdn.net/detail/lee_tianya/8332357

Android录音--AudioRecord、MediaRecorder (音频文件格式处理) http://www.cnblogs.com/MMLoveMeMM/articles/3444718.html
Android NDK开发(六)——使用开源LAME转码mp3-- http://blog.csdn.net/allen315410/article/details/42456661
Android libmp3lame详解-- http://blog.csdn.net/gf771115/article/details/37112533
Android下使用lamemp3库将PCM录音数据压缩为MP3格式-- http://blog.csdn.net/gf771115/article/details/37113143
android录音格式raw转mp3 http://blog.csdn.net/fans1108/article/details/25914703
 Android MP3Recorder(lame)-- https://github.com/GavinCT/AndroidMP3Recorder

> Android提供了两个API用于实现录音功能:android.media.AudioRecord、android.media.MediaRecorder。--http://www.cnblogs.com/MMLoveMeMM/articles/3444718.html

  使用AudioRecord类录音,并实现WAV格式封装。录音20s,输出的音频文件大概为3.5M左右.

  使用MediaRecorder类录音,输出amr格式文件。录音20s,输出的音频文件大概为33K

  WAV格式:录音质量高,但是压缩率小,文件大

  AAC格式:相对于mp3,AAC格式的音质更佳,文件更小;有损压缩;一般苹果或者Android SDK4.1.2(API 16)及以上版本支持播放

  AMR格式:压缩比比较大,但相对其他的压缩格式质量比较差,多用于人声,通话录音

即时通讯。acc跟ios可以互通:AudioRecord 获取 sample 然后用 ffmpeg 转成 AAC;录制成amr,使用第三方的东西,例如ffmpeg、speex自己转换为aac

> 关于ios 和 android 录音(语音)对聊文件格式问题-- http://blog.163.com/zhuowh2006@126/blog/static/1018237242013629104918230/ 在做语音对讲的时候,将会碰到录制语音格式的问题,这些需要跨平台我们可能需要使用双方平台都支持的格式,或者执行编码转换.最终最合适的解决办法就是  android  使用amr ios使用 libOpenCore第三方库进行转换。

-------------------------------------------------------------------

> h264硬编解码(Android)

从技术下游(SDK 使用方)跑到了技术上游(SDK 提供方)。

H264编码片,I/P/B/SP/SI帧;普通视频的I/P/B帧。I帧内预测,P帧间预测,B双向预测帧。

> 如果是mp4parser支持的格式就好办,若不支持就用ffmpeg

 使用Android原生的MediaExtractor和MediaMuxer可以实现音视频的合成。不过有几个缺点:

1.MediaMuxer是在4.3(API18)中新增的类,无法兼容低版本;

2.音频如果是MP3的话需要使用MediaCodec重新编码,因此建议直接使用m4a的音频文件,可以直接合成;

3.音视频长度不同时的处理措施。

> 将H264转为MP4

 mp4parser- https://github.com/sannies/mp4parser/releases

> android MediaCodec 实现h264硬编解码全过程- http://download.csdn.net/detail/b_xjie/8744773
MediaCodec 实现h264硬编解码全过程,视频数据(onPreviewFrame)从摄像头读出 yv12格式,转换为I420,投递给encoder,再从encoder取出编码后的h264数据投递给decoder后显示到surfaceView; 实现了udp将h264数据发送到指定主机,可通过vlc播放; 备有可以读取本地264文件流投递给解码器播放; 小米 4.4.2 测试通过.

/**
* H264编码
* @param input
* @param output
* @return
*/
private int offerEncoder(byte[] input, byte[] output) {

int pos = 0;
try {
ByteBuffer[] inputBuffers = mMediaEncoder.getInputBuffers();
ByteBuffer[] outputBuffers = mMediaEncoder.getOutputBuffers();
int inputBufferIndex = mMediaEncoder.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
Log.d(TAG, "offerEncoder InputBufSize: " + inputBuffer.capacity() + " inputSize: " + input.length
+ " bytes");
inputBuffer.clear();
inputBuffer.put(input);
mMediaEncoder.queueInputBuffer(inputBufferIndex, 0, input.length, 0, 0);

}

MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = mMediaEncoder.dequeueOutputBuffer(bufferInfo, 0);
while (outputBufferIndex >= 0) {
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];

byte[] data = new byte[bufferInfo.size];
outputBuffer.get(data);

Log.d(TAG, "offerEncoder InputBufSize:" + outputBuffer.capacity() + " outputSize:" + data.length
+ " bytes written");

if (mMediaHead != null) {
System.arraycopy(data, 0, output, pos, data.length);
pos += data.length;
} else // 保存pps sps 只有开始时 第一个帧里有, 保存起来后面用
{
Log.d(TAG, "offer Encoder save sps head,len:" + data.length);
ByteBuffer spsPpsBuffer = ByteBuffer.wrap(data);
if (spsPpsBuffer.getInt() == 0x00000001) {
mMediaHead = new byte[data.length];
System.arraycopy(data, 0, mMediaHead, 0, data.length);
} else {
Log.e(TAG, "not found media head.");
return -1;
}
}

mMediaEncoder.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = mMediaEncoder.dequeueOutputBuffer(bufferInfo, 0);

}

if (output[4] == 0x65) // key frame 编码器生成关键帧时只有 00 00 00 01 65 没有pps
// sps, 要加上
{
System.arraycopy(output, 0, input, 0, pos);
System.arraycopy(mMediaHead, 0, output, 0, mMediaHead.length);
System.arraycopy(input, 0, output, mMediaHead.length, pos);
pos += mMediaHead.length;
}

} catch (Throwable t) {
t.printStackTrace();
}
return pos;
}
/**
* H264解码
* @param input
* @param length
*/
private void offerDecoder(byte[] input, int length) {
try {
ByteBuffer[] inputBuffers = mMediaDecoder.getInputBuffers();
int inputBufferIndex = mMediaDecoder.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
long timestamp = mFrameIndex++ * 1000000 / FRAME_RATE;
Log.d(TAG, "offerDecoder timestamp: " + timestamp + " inputSize: " + length + " bytes");
inputBuffer.clear();
inputBuffer.put(input, 0, length);
mMediaDecoder.queueInputBuffer(inputBufferIndex, 0, length, timestamp, 0);
}

MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = mMediaDecoder.dequeueOutputBuffer(bufferInfo, 0);
while (outputBufferIndex >= 0) {
Log.d(TAG, "offerDecoder OutputBufSize:" + bufferInfo.size + " bytes written");

// If a valid surface was specified when configuring the codec,
// passing true renders this output buffer to the surface.
mMediaDecoder.releaseOutputBuffer(outputBufferIndex, true);
outputBufferIndex = mMediaDecoder.dequeueOutputBuffer(bufferInfo, 0);
}
} catch (Throwable t) {
t.printStackTrace();
}
}

> 视频的yv12,I420

一般来说,直接采集到的视频数据是RGB24的格式,RGB24一帧的大小size=width×heigth×3 Byte,RGB32的size=width×heigth×4,如果是I420(即YUV标准格式4:2:0)的数据量是 size=width×heigth×1.5 Byte。

YV12 : 亮度(行×列) + V(行×列/4) + U(行×列/4)

I420 : 亮度(行×列) + U(行×列/4) + V(行×列/4)

附一个YUV播放器的源代码:http://download.csdn.net/detail/leixiaohua1020/6374065

 

实时视频传输的关键技术 H.264 全解析- http://blog.csdn.net/Byeweiyang/article/details/78134674
  H.264 码流传输的基本单元是 NAL 单元,NAL 单元内携带的最关键的数据是参数集和片数据;解码的基本单元是宏块,解码器根据预测信息和残差数据,解码出原始数据;宏块解码之后拼接成片,片拼接成图像,而一幅幅图像则构成了视频!

  编码基本框架:预测编码、变换编码、熵编码。

  无论编码器的结构如何,相应的视频编码的控制都是编码器实现的核心问题。在编码过程中,并没有直接控制编码数据大小的方式,只能通过调整量化过程的量化参数 QP 值间接控制,而由于 QP 和编码数据大小并没有确定的关系,所以编码器的码率控制无法做到很精细,基本都靠试。要么是中途改变后续宏块的质量,要么是重新编码改变所有宏块的质量。

  解码过程就是编码的逆过程:熵解码、变换解码、预测解码。

  以宏块为单位,依次进行熵解码、反量化、反变换,得到残差数据,再结合宏块里面的预测信息,找到已解码的被参考块,进而结合已解码被参考块和本块残差数据,得到本块的实际数据。宏块解码后,组合出片,片再组合出图像。

  可伸缩编码(Scalable Video Coding, SVC)实质上是将视频信息按照重要性分解,对分解的各个部分按照其自身的统计特性进行编码。一般它会将视频编码为一个基本层和一组增强层。基本层包含基本信息,可以独立解码,增强层依赖于基本层,可以对基本层的信息进行增强,增强层越多,视频信息的恢复质量也就越高。

  SVC 通常有三种:

 空域可伸缩:可以解码出多种分辨率的视频;

 时域可伸缩:可以解码出多种帧率的视频,分辨率相同;

 质量可伸缩:可以解码出多种码率的视频,分辨率、帧率相同;

--------------------------------------------------
H.264 的开源实现:OpenH264;x264

H.265 的开源实现:libde265;x265

VP8 的开源实现:libvpx

VP9 的开源实现:libvpx

《视频直播技术详解》之(三):编码和封装- http://news.sina.com.cn/o/2016-09-13/doc-ifxvukuq4363871.shtml
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: