【溯源码的管理】【外卖点餐源码】【java农场游戏源码】yuv 源码

时间:2024-11-13 15:40:28 来源:c语言五子棋源码 分类:探索

1.HEVC开源编解码器HM编译及使用方法
2.图像格式--FFMPEG代码走读-TIFF格式编码
3.UVC Camera使用简单记录
4.音视频开发项目:H.265播放器:视频解码篇
5.音视频流媒体开发系列(78)ffmpeg实战教程(一)Mp4,mkv等格式解码为h264和yuv数据

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播放,java农场游戏源码显示输入格式为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类似的eclipse源码看不了标签,同时增加了一些特定于视频和**制作的标签,用于管理处理高动态范围的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命令行环境中进行操作。