1.HEVC开源编解码器HM编译及使用方法
2.图像格式--FFMPEG代码走读-TIFF格式编码
3.UVC Camera使ç¨ç®åè®°å½
4.音视频开发项目:H.265播放器:视频解码篇
5.音视频流媒体开发系列(78)ffmpeg实战教程(一)Mp4,mkv等格式解码为h264和yuv数据
HEVC开源编解码器HM编译及使用方法
HM (HEVC Test Model)是一个开源软件,用于帮助我们理解HEVC编码标准。它包括编码器TAppEncoder和解码器TAppDecoder,能实现HEVC标准中的所有功能,但性能不如商用编码器。源码指的是该项目由JVET维护。本文记录了笔者在Ubuntu下根据HM项目的README,编译并运行一个小demo的过程。
JVET并未将HM托管到GitHub,而是将其托管在gitlab仓库vcgit.hhi.fraunhofer.de...中。我们可以在该页面找到仓库的git URL,然后在Ubuntu中使用git clone命令克隆源代码:
进入代码目录后,创建名为build的文件夹,并进入该文件夹:
在build目录下运行以下指令:
注意,执行上述指令前需要预先安装cmake工具。
执行cmake后,在当前目录下应该会看到一个Makefile,然后我们可以使用make进行编译:
编译过程可能较长:
编译过程中,如果没有错误,几分钟内即可完成。如果读者在编译过程中遇到依赖问题,可以自行搜索并安装,HM的编译过程相对顺利,没有太多难点。
当make的进度达到%时,说明编译完成。盒子源码最后几行输出表明编译出的可执行文件位于相应位置,可以在“HM/bin/umake/gcc-9.4/x_/release”目录下找到“MCTSExtractor”“parcat”“SEIRemovalApp”“TAppDecoder”“TAppDecoderAnalyser”“TAppEncoder”等可执行文件。
接下来,我们使用TAppEncoder进行测试,将一个未压缩的yuv序列编码成HEVC视频序列。我们使用的是Derf's Test Media Collection数据集中的akiyo视频序列。下载akiyo_cif.y4m文件后,将其与TAppEncoder可执行文件放在同一文件夹中。
在HM项目的doc目录下,有一个名为software-manual.pdf的说明文档,详细介绍了HM软件的使用方法。通过阅读该文档,我们可以了解TAppEncoder通过-c参数指定配置文件,并在项目的cfg目录下找到示例配置文件。我们将其中一个配置文件拷贝到工作目录下,并执行代码。如果出现错误,可能是因为配置文件中没有指定帧率和编码总帧数。这是一个HM项目的小坑,需要仔细调试。
修改配置文件后,再次执行指令,即可正常编码。编码完成后,可以在当前目录下找到输出文件akiyo_hevc.bin,使用PotPlayer播放,网站源码网显示输入格式为HEVC。但可能存在一些播放异常,需要进一步检查。
我们可以使用开源软件GitlHEVCAnalyzer对akiyo_hevc.bin进行分析,该软件可以显示视频中的CU、PU等单元以及分块信息。
--更新:使用HM的TAppEncoder对akiyo_cif.y4m进行编码时,编码后的视频画面会发生色彩异常和抖动异常。目前,已找到原因并成功解决。在解决此问题之前,我们需要了解y4m文件格式。Y4M是一种保存原始YUV序列的文件封装格式,包含视频属性信息。而HM的TAppEncoder编码器需要接收仅由视频帧组成的像素矩阵数据。因此,直接将akiyo_cif.y4m文件输入到HM编码器中可能导致帧不对齐,造成抖动。解决方法是提取视频每一帧像素矩阵,丢弃视频属性信息,并将它们写入新文件。使用ffmpeg进行视频内容提取后,将得到的akiyo_yuv.yuv文件输入到TAppEncoder中,以相同方式进行编码,即可正常播放视频。
图像格式--FFMPEG代码走读-TIFF格式编码
本文从FFMPEG源码角度解读TIFF编码内容,日源码无需过多介绍,直接开启解读。TIFF编码涉及到的结构体TiffEncoderContext,用于存储与TIFF编码相关的上下文信息,包括编码上下文信息、长宽信息、压缩信息、yuv数据信息、缓冲区信息、Strip信息,以及编解码算法和级别信息等。
TIFF文件使用标签(Tags)存储图像的元数据和其他信息,每个标签存储特定类型的信息,如图像宽度、高度、颜色深度等。在FFMPEG中包含的所有tag相关数据可参照下图查看。
此外,还存在特定的补充标签,如DNG和CinemaDNG格式。DNG是由Adobe开发的一种开放的RAW图像格式,基于TIFF/EP标准,在TIFF基础上增加了存储更多摄影信息和元数据的特定标签。CinemaDNG是一个基于DNG的开放标准,专为**和视频制作中的RAW图像序列设计,包含与静态图像DNG类似的桃源码头标签,同时增加了一些特定于视频和**制作的标签,用于管理处理高动态范围的RAW视频数据。
TIFF编码代码位于libavcodec\tiffenc.c文件中。ff_tiff_encoder描述了一个TIFF图像编码器,采用标准FFmpeg库的API封装,包含TIFF编码器的各种信息和函数指针,便于对接到FFMPEG框架。
encode_init函数用于初始化TIFF编码器上下文,并进行必要的检查和设置。encode_close函数在编码器关闭时进行资源清理,确保无内存泄漏。add_entry将一个条目添加到TIFF文件目录中。encode_strip用于将图像数据编码为TIFF文件的一个条带。pack_yuv将YUV图像数据打包成适合TIFF格式的条带。
encode_frame函数主要作用是将一帧图像编码为TIFF格式。具体步骤包括初始化上下文和变量、设置编码器上下文参数、处理不同像素格式、计算每行字节数和数据包大小、分配内存、处理图像数据、写入TIFF文件头、添加TIFF标签、写入目录偏移量并完成编码。
至此,TIFF编码过程解析完毕。源码编译与调试有助于深入理解,增进对TIFF编码的认识。
UVC Camera使ç¨ç®åè®°å½
ç¨åºæ¯æ ¹æ® UVCCamera å»ä¿®æ¹çã
使ç¨è¿ç¨ä¸éå°çå ç¹å ³é®é®é¢ï¼
1.YUV æ ¼å¼ï¼NVçæ ¼å¼ã
2.YUV转RGBæçé®é¢ã
3.Bitmapå åæ³æ¼é®é¢ã
4.Handlerå åæ³æ¼çé®é¢
é¦å onFrame(è¿æ¯cameraåå¾çcallBackå½æ°ï¼byte[] dataå°±æ¯cameraçæ°æ®)ä¸ä¸è½åèæ¶æä½ï¼ä¾å¦å°data转bitmapçæä½ï¼ï¼ä¸ç¶ä¼é»å¡ï¼ä¹åæè¿ä¸ªæä½æ¾å°è¿éç¶åç´æ¥å°bitmapä¼ åºï¼å¯¼è´å¡é¡¿ã
å¨ä¼ è¾byte[]æ°æ®ä¹åï¼éè¦å°byte[]转bitmapã
å¨byte[] 转bitmapçè¿ç¨ä¸ï¼ç±äºå建äºè¿å¤çBitmapï¼ä¼å¯¼è´å åæ³æ¼ï¼ç¨åºå´©æºã
å æ¤1.å°Bitmap设置为éæåéï¼é¿å éå¤å建çé®é¢ã2.ä¿®æ¹byte[] 转bitmapçå½æ°ï¼åæ¥å½æ°æ¯è¿åBitmapï¼ç°å¨æ¯å°Bitmapä½ä¸ºåæ°ä¼ å ¥å½æ°ä¸ï¼ç´æ¥å°Bitmapæ°æ®ä¼ éåºå»ãåå°äºä¸ä¸ªè¿åçæ¥éª¤ã
ä¹åæ¯è¿æ ·çï¼
ç°å¨æ¯è¿æ ·çï¼
åé¢å°±æ¯éè¿handleImageå°Bitmapæ¾ç¤ºå¨ImageViewä¸ã
NV转bitmapçé®é¢ã
æçç¨åºåºæ¬æ¯æ ¹æ® UVCCamera å»ä¿®æ¹çï¼UVCCameraä¸æ²¡æåæ¯ä¸å¸§ï¼ä½æ¯çææ¥å£ï¼æè¿é设å®æ¯ä¸å¸§çæ°æ®ä¸ºNVæ ¼å¼ã
并ä¸å¨onFrameä¸ååºçdataæ ¼å¼æ¯NVï¼NVæ¯YUVä¸çä¸ä¸ªï¼YUVæå¾å¤æ ¼å¼ï¼ï¼å æ¤å¨è½¬æbitmapçæ¶åï¼éè¦æ ¹æ®å ¬å¼å»è½¬åãç¨ç³»ç»èªå¸¦çRenderScriptå»è½¬æ¢ï¼åç°å¾çè½ç¶æ¸ æ°ä½æ¯é¢è²ä¸å¯¹ã
æ¥æ¾yuv转bitmapå½æ°ï¼æ¾å°çæ¯è¿ä¸ªãä¾æ§æ¯è½¬åºæ¥çå¾çï¼é常ææ¾ï¼æåå¾æ¸ æ°ï¼ä½æ¯å°±æ¯é¢è²ä¸å¯¹ã
å æ¤å¯¹å½æ°è¿è¡äºä¿®æ¹ãä¿®æ¹åå¦ä¸æ示ã
ç±äºå¯¹YUVä¸RGBè¿ä¸ªæ¦å¿µæ¨¡ç³ä¸æ¸ ï¼èæç´¢å¾å°çYUV转bitmapå½æ°æ¯è½ç¶çç¡®æ¯NV转bitmapï¼ä½è½¬æ¢åæè²å·®ãåä¿®æ¹rgba[]çèµå¼é¡ºåºåï¼é¢è²ææ£å¸¸ãå ¶å®å°±æ¯å¨ç±YUVç¼ç 转RGBç¼ç çè¿ç¨ä¸ï¼æ°æ®ä¼ éåºç°é®é¢æ导è´è²å½©å¼å¸¸ï¼è¿ç§æ åµå°±éè¦ä¸æ¥æ¥åæYUVå°RGBçæ°æ®è½¬æ¢ä¸åªéåºç°äºé®é¢ãä¹åæ¯åå¨ä¸ºABGRï¼åé¢ææ¯åå¨ä¸ºARGBã
å ·ä½åæå¯ä»¥çè¿ç¯ï¼
RGBåYUVç®åå¦ä¹ è®°å½
ä½æ¯ä¸é¢è¿ç§æ¹å¼å®é 使ç¨ä¸åç°æçè¿ä½ãå æ¤éè¦ä½¿ç¨soçæ¹å¼å»è½¬æ¢ã
å ·ä½åèé¾æ¥ï¼
libyuvâlibyuvæµè¯ä½¿ç¨ARGBToIåConvertToARGBæ¥å£
_example_libyuv_Test_convertToArgbå½æ°ä¸çFOURCC_IYUVæ¹ä¸ºFOURCC_NVã
Handleå åæ³æ¼çé®é¢ã
ä¹åå 为æ³å·ææ以没æå¤çAndroid studioå ³äºHandleå åæ³æ¼çæ示ãç¶å让ç¨åºè·äºä¸å¤©æç¶å´©äºã
ä¹åæ¯å¦ä¸æ示ï¼è¿ç§åæ³Android Studioä¼æç¤ºä½ è¿æ¯æé£é©çã
ç°å¨æ¹æå¦ä¸æ示
å ¶å®è¿å¯éè¿å¨activityçdestroyä¸è°ç¨ handler.removeCallbacksAndMessages(null) ï¼æ¥è¾¾å°é¿å å åæ³æ¼çç®ç,android ç³»ç»æºç ä¸ä¹åºæ¬æ¯ä½¿ç¨è¿ä¸ªæ¹æ³ã
åè®°ï¼è¿ç¯æç« å§äºå¹´ï¼å½æ¶æ¯ç¨äºåç®USBæå头ä¸ï¼æè¿å¨æ´çä¸è¥¿æ以å®åäºä¸ä¸ã
åèé¾æ¥ï¼
Android yuv转æ¢æbitmap
å¾æ详解YUVæ°æ®æ ¼å¼
Androidä¸çYUVæ ¼å¼è§£æ
Nv转Bitmapï¼é«æç转åï¼
Android ä¹ Bitmap
Android解æä¹Handler为ä»ä¹éè¦æ¯staticç
音视频开发项目:H.播放器:视频解码篇
探索音视频开发的前沿技术,让我们深入剖析一款H.播放器的视频解码优化过程。在这款高性能播放器中,新版以惊人的效率展示了其解码能力,1分钟内处理p/fps的H. MP4视频,内存占用仅为4.6GB,而CPU占用率在极限条件下也保持在+。单帧解码p的速度已经优化到了惊人的毫秒,相较于旧版p的毫秒,无疑展示了技术的飞跃。
播放器的架构设计巧妙,由Loader、Demuxer、Renderer(核心模块)和UI View等模块构成,各部分独立却又协同工作。让我们走进DEMO架构示例:Loader负责从Annex-B码流中读取数据,WASM技术则高效地解码YUV数据,而FFmpeg经过精简编译后,被转化为轻量级的WASM包,实现资源优化。
要实现这一优化,首先从FFmpeg官网获取emsdk和源码版本(4.1),然后通过定制的make_decoder.sh脚本,去除不必要的模块,如swresample和postproc,专注于关键的hevc-decoder模块。这个过程包括禁用非必要的FFmpeg功能,生成简化库和.h文件,为后续的WASM编译做准备。
接下来,编写自定义的C语言入口文件(如decoder.c),运用C语言基础,创建一个初始化解码器的接口,如init_decoder,它接受一个JS回调函数,传递解码数据的地址、长度,以及可选的时间戳(pts)。附赠的学习资料包,包含FFmpeg、webRTC等技术,可通过企鹅裙获取,助你快速上手。
解码的核心在于处理AVPacket和AVFrame,视频中每个压缩帧需要通过demuxers和decoders逐一解析。decode_buffer函数负责数据解析和解码,将解码后的AVPacket传递给解码器,可能需要多次循环以接收完整的AVFrame。而在3.x和4.x版本中,avcodec_send_packet和avcodec_decode_video2/avcodec_decode_audio4的调用方法有所不同。
解码后的YUV数据通常以紧缩格式(如YUVp)和平面格式存储,需要转换后供JS使用。在这个过程中,采样率决定了数据处理的复杂度,例如4个Y分量对应1个U和V分量。将解码后的AVFrame复制到yuv_buffer,然后通过decoder_callback传递给JavaScript。
通过Emscripten构建WASM包,我们编写build_decoder.sh脚本,设置出口函数和内存配置,最终生成wasm/libffmpeg.js。在JS和Worker中,我们加载并调用WASM函数,构建Decoder类,扩展EventEmitter,处理数据的异步加载和解码。在主线程中,通过webpack和worker-loader,数据从主线程传输到Worker,解码器负责解码并返回处理后的数据。
H.视频解码的挑战在于高效处理AVPacket和AVFrame,音频解码则可能需要复用解码链路或者利用浏览器内置的解码器。音频播放则依赖于AudioContext,确保主流音频编码格式在浏览器中的兼容性。通过这个案例,我们了解了如何避免常见问题,以及FFmpeg在视频处理中的强大能力。H.播放器的应用场景广泛,为创新提供无限可能。
音视频流媒体开发系列()ffmpeg实战教程(一)Mp4,mkv等格式解码为h和yuv数据
在这个FFmpeg实战教程中,我们将探索如何将常见的视频格式如MP4和MKV解码为H和YUV数据。首先,让我们来看一个实例,通过运行解码过程,你将看到两个文件的生成,分别对应解码后的h和YUV数据,其中h由于采用了高效的压缩技术,文件大小明显小于YUV文件。 解码流程包括以下步骤:首先,将ws.mp4文件复制到项目目录,然后创建两个输出文件。接下来,初始化所需的组件,接着打开视频文件,获取视频信息并选择合适的解码器。在解码过程中,要注意av_read_frame()循环结束后可能遗留少量帧数据,这时需要调用flush_decoder函数,将这些帧数据完整输出。 下面是源代码示例,展示如何执行这些操作:拷贝ws.mp4并创建输出文件
初始化解码器和相关组件
打开和解码视频
使用flush_decoder确保所有帧数据都被处理
运行程序后,你将看到生成的h和YUV文件。如果你对音视频开发感兴趣,可以关注我们的免费学习资源,包括FFmpeg、WebRTC、RTMP、NDK和Android高级开发等内容。群文件中提供了详细的面试题、学习资料和教学视频,以及学习路线图,点击加群获取,希望能对你有所帮助。 对于Windows用户,需要配置FFmpeg环境。首先从ffmpeg.zeranoe.com下载相应版本的shared和dev版本,然后将include和lib文件夹分别复制到指定位置,最后在MinGW命令行中执行命令。而对于Linux或MacOS用户,可以在GCC命令行环境中进行操作。