音视频标准:MEPG阵营(x264,x265等)和Google阵营(vp8,vp9等),中国标准(XAVS2)

    xiaoxiao2026-03-19  12

      视频标准:MEPG阵营和Google开源阵营。   MPEG-2,VC1,H.263,H.264/AVC,H.265/HEVC,VP9,AV1——所有这些标准都建立在基于块的混合视频编码结构上。   通用视频编码标准(VVC,Versatile Video Coding)。   FFmpeg自带了H264、AAC、MP3的解码器,但却没有(或没有好的)相应的编码器。相应的编码器需要使用第三方库。推荐使用的第三方库为x264(H264编码) 、FDK_AAC(AAC编码),lame(MP3编码)。LAME-MP3编码引擎(音频)。

    > 音视频格式  即时通信IM中语音格式可以使用amr;视频格式可以使用mp4。 -- 音频格式有:1、CD;2、OGG;3、MP3;4、ASF、WMA;5、WAV;6、MP3PRO;7、RM;8、REAL;9、APE;10、MODULE;11、MIDI;12、VQFhttp://baike.baidu.com/link?url=tmkYau9u-YKkCiszIW540P4SBglTEos4fdV_32AXKvGlxEdS_1sDklaV2IVFG3afF2jLRq3Mit7J_9lUkFOMtK

    -- 视频格式有:rm,rmvb,mpeg1-4 mov mtv dat wmv avi 3gp amv dmvhttp://zhidao.baidu.com/link?url=JDNs5AynU63rpqUtglCCSyTuEQfG00f3J1lW_Pq5rUfDfrd-YHna8GTGP1VUCIjK1qqkutl1zpSccIKbehv4_a http://baike.baidu.com/link?url=JDNs5AynU63rpqUtglCCS6jXiHuTdqajUguPF_o54IgNZ4ba4bjWA5vdqlJJCt7R680FtghgUj_nSwAh3qqr5K

    -- 直播中可用的音视频数据涉及技术或协议:编码方式:CBR、VBR编码格式 视频:H.265、H.264、MPEG-4等,封装容器有TS、MKV、AVI、MP4等 音频:G.711μ、AAC、Opus等,封装有MP3、OGG、AAC等

    常见的音频压缩格式有:MP3、AAC、OGG、WMA、Opus、FLAC、APE、m4a和AMR等。 常见的视频封装格式有:MP4、3GP、AVI、MKV、WMV、MPG、VOB、FLV、SWF、MOV、RMVB和WebM等。 Android录音支持的格式有amr、aac

    > 中国的音视频标准 中国XAVS2实时编码器开源地址- https://github.com/pkuvcl/xavs2 中国XAVS2实时编码器开源地址- https://gitee.com/pkuvcl/xavs2

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

    -- VP8 的开源实现:libvpx:   libvpx 是 VP8 的唯一开源实现,由 On2 Technologies 开发,Google 收购后将其开放源码,License 非常宽松可以自由使用。 编码器的选择之VP8:   VP8 是一个开放的视频压缩格式,最早由 On2 Technologies 开发,随后由 Google 发布。同时 Google 也发布了 VP8 编码的实做库:libvpx,以 BSD 授权条款的方式发行,随后也附加了专利使用权。而在经过一些争论之后,最终 VP8 的授权确认为一个开放源代码授权。   目前支持 VP8 的网页浏览器有 Opera、Firefox 和 Chrome。

    -- VP9 的开源实现:ibvpx:   libvpx 是 VP9 的唯一开源实现,由 Google 开发维护,里面有部分代码是 VP8 和 VP9 公用的,其余分别是 VP8 和 VP9 的编解码实现。   vpx则是Google推出的开源视频编码器,它提出的VP9编码标准的性能也不错。

      Google已在几年前已经决定Chrome浏览里放弃H.264标准的支持,转而只支持自家的VP8(最新版是VP9)编码格式。而且,2011年被Google收购的著名实时音视频方案GIPS——已被Google开源多年并取名为WebRTC,WebRTC中的实时音视频编码默认使用的就是VP8标准。   H.264(下一代是H.265)和VP8(下一代是VP9)编码两种: 1.采用 H.264 视频编码和 AAC 音频编码的 MP4 文件(H.264/AAC/MP4 组合); 2.采用 VP8 视频编码和 Vorbis 音频编码的 WebM 文件(VP8/Vorbis/WebM 组合);

      通常「H.264」指代 H.264/AAC/MP4 这个组合,而「WebM」指代 VP8/Vorbis/WebM 这个组合。   2010 年中的时候 Google 宣布将 VP8 永久免费。Google 又基于开源容器格式 Matroska 开发了 WebM 容器格式,用以封装 VP8 编码的视频和 Vorbis 编码的音频。随后 Google 连同 Mozilla 和 Opera,准备将 VP8/Vorbis/WebM (统称为 WebM)推广为网络视频的通用格式。Google Chrome 浏览器在 WebM 发布后迅速更新为同时支持 Theora、H.264、WebM 三种格式。Mozilla 和 Opera 也宣布将在其浏览器的后续版本(主要是 Firefox 4)中原生支持 WebM。   MPEG LA 将 H.264 专利许可分为两种:H.264 编码器和解码器(不论软硬件)厂商需要购买一种 H.264 的专利许可协议,H.264 编码的视频的分发商(如电视台等)需要购买另外一种 H.264 的专利许可协议。

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

    > MEPG阵营 -- x264 openh264思科开源的另外一个h264编码器- https://github.com/cisco/openh264 官网x264编码的源代码- http://www.videolan.org/developers/x264.html Android NDK 编译 FFmpeg + x264 + fdk-aac (arm/x86)的配置脚本- http://blog.csdn.net/panda1234lee/article/details/53099203 x264的开源库在android中的调用方法-- http://www.yanfaw.com/technology/201108/16/435.html

     最简单的视频编码器:编译(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。

    -- h264硬编解码(Android) 从技术下游(SDK 使用方)跑到了技术上游(SDK 提供方)。 H264编码片,I/P/B/SP/SI帧;普通视频的I/P/B帧。I帧内预测,P帧间预测,B双向预测帧。

    -- OpenH264;x264 H.264 的开源实现:OpenH264;x264   OpenH264 是思科实现的开源 H.264 编码,项目在 2013 年开源,虽然 H.264 需要交纳不菲的专利费用,但是专利费有一个年度上限,思科把 OpenH264 实现的年度专利费交满后,另外,firefox 直接内置了 OpenH264,作为其在 WebRTC 中的视频编解码器使用。OpenH264 事实上就可以免费自由的使用了。   x264 是一个采用 GPL 授权的视频编码自由软件。x264 的主要功能在于进行 H.264/MPEG-4 AVC 的视频编码,而不是作为解码器(decoder)之用。

    除去费用问题比较来看: OpenH264 CPU 的占用相对 x264低很多;OpenH264 只支持 baseline profile,x264 支持更多 profile。

    -- H.265 的开源实现:libde265、x265:   libde265 HEVC 由 struktur 公司以开源许可证 GNU LesserGeneral Public License (LGPL) 提供,观众可以较慢的网速下欣赏到最高品质的影像。跟以前基于H.264标准的解码器相比,libde265 HEVC 解码器可以将您的全高清内容带给多达两倍的受众,或者,减少 50%流媒体播放所需要的带宽。高清或者 4K/8K 超高清流媒体播放,低延迟/低带宽视频会议,以及完整的移动设备覆盖。具有「拥塞感知」视频编码的稳定性,十分适合应用在 3/4G 和 LTE 网络。   x265 是由 MulticoreWare 开发,并开源。采用 GPL 协议,但是资助这个项目的几个公司组成了联盟可以在非 GPL 协议下使用这个软件。

    -- FFmpeg   FFmpeg 是一个自由软件,可以运行音频和视频多种格式的录影、转换、流功能,包含了 libavcodec -这是一个用于多个项目中音频和视频的解码器库,以及 libavformat -一个音频与视频格式转换库。   FFmpeg 这个单词中的 FF 指的是 Fast Forward。这个项目最初是由 Fabrice Bellard 发起的,而现在是由 Michael Niedermayer 在进行维护。许多 FFmpeg 的开发者同时也是 MPlayer 项目的成员,FFmpeg 在 MPlayer 项目中是被设计为服务器版本进行开发。

      所谓容器,就是把编码器生成的多媒体内容(视频,音频,字幕,章节信息等)混合封装在一起的标准。容器使得不同多媒体内容同步播放变得很简单,而容器的另一个作用就是为多媒体内容提供索引,也就是说如果没有容器存在的话一部影片你只能从一开始看到最后,不能拖动进度条(当然这种情况下有的播放器会话比较长的时间临时创建索引),而且如果你不自己去手动另外载入音频就没有声音。   我们在流媒体传输,尤其是直播中主要采用的就是 FLV 和 MPEG2-TS 格式,分别用于 RTMP/HTTP-FLV 和 HLS 协议。   实时音视频通讯 = 音视频处理 + 网络传输。包括采集、编码、网络传输、解码、播放等环节。音视频处理中最为关键的视频编解码是个头等重要的问题,对于开发者来说,以目前所能找到的技术资源以及应用的普及程度,因为背靠巨头,H.264(最新版是H.265,微软和苹果一直都在背后力推)和VP8(最新版是VP9,由Google力推)是最为主流的两种编码。

    -- 将H264转为MP4  mp4parser- https://github.com/sannies/mp4parser/releases

    -- 实时视频传输的关键技术 H.264 全解析- http://blog.csdn.net/Byeweiyang/article/details/78134674   H.264 码流传输的基本单元是 NAL 单元,NAL 单元内携带的最关键的数据是参数集和片数据;解码的基本单元是宏块,解码器根据预测信息和残差数据,解码出原始数据;宏块解码之后拼接成片,片拼接成图像,而一幅幅图像则构成了视频!   编码基本框架:预测编码、变换编码、熵编码。   无论编码器的结构如何,相应的视频编码的控制都是编码器实现的核心问题。在编码过程中,并没有直接控制编码数据大小的方式,只能通过调整量化过程的量化参数 QP 值间接控制,而由于 QP 和编码数据大小并没有确定的关系,所以编码器的码率控制无法做到很精细,基本都靠试。要么是中途改变后续宏块的质量,要么是重新编码改变所有宏块的质量。

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

    -- 可伸缩编码(Scalable Video Coding, SVC)实质上是将视频信息按照重要性分解,对分解的各个部分按照其自身的统计特性进行编码。一般它会将视频编码为一个基本层和一组增强层。基本层包含基本信息,可以独立解码,增强层依赖于基本层,可以对基本层的信息进行增强,增强层越多,视频信息的恢复质量也就越高。  SVC 通常有三种:  1.空域可伸缩:可以解码出多种分辨率的视频;  2.时域可伸缩:可以解码出多种帧率的视频,分辨率相同;  3.质量可伸缩:可以解码出多种码率的视频,分辨率、帧率相同;

    > 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();         }     }

    转载请注明原文地址: https://ju.6miu.com/read-1308138.html
    最新回复(0)