(三)ffmpeg 解码流程以及函数介绍
一、视频解码流程

二、函数介绍
1.avformat_network_init
函数作用:
执行网络库的全局初始化。这是可选的,不再推荐。
此函数仅用于解决旧GnuTLS或OpenSSL库的线程安全问题。如果libavformat链接到这些库的较新版本,或者不使用它们,则不需要调用此函数。否则,您需要在启动使用该函数的任何其他线程之前调用该函数。 一旦删除对旧GnuTLS和OpenSSL库的支持,此函数将被弃用,并且此函数没有任何用途。
2.av_dict_set
函数作用:
用于向字典中添加键值对。它可以被用来传递多种数据,例如视频解码参数、音频参数、字幕参数等等。
函数原型:
int av_dict_set(AVDictionary **pm,const char *key, const char *value, int flags);
参数说明:
pm:指向AVDictionary结构的指针,该结构将被填充以包含新的键值对。
key:要添加到字典中的键。
value:与键关联的值。
flags:可选参数,指定如何处理重复的键。0:默认,默认情况下,如果键已经存在,则新值将覆盖旧值。AV_DICT_DONT_OVERWRITE:如果已经存在键名,则不会执行任何操作,避免覆盖。AV_DICT_APPEND:如果关键字已经定义,则将其与新的值合并。
返回值:
返回值为整数类型。如果成功,返回0;否则返回一个负数错误码。
常见用法:
av_dict_set(&options, "rtsp_transport", "tcp", 0); //使用 TCP 方式
av_dict_set(&options, "buffer_size", "1024", 0); // 设置缓冲区大小为1024字节av_dict_set(&options, "max_delay", "200", 0);//设置接收包间隔最大延迟,微秒av_dict_set(&options, "timeout", "5000000", 0); // 设置超时时间为5秒(单位为微秒)
av_dict_set(&options, "stimeout", "3000000", 0);//设置阻塞超时,否则可能在流断开时连接发生阻塞,微秒
3.avformat_open_input
函数作用:
用于打开多媒体文件或流并初始化用于读取数据的结构。这个函数是FFmpeg多媒体处理流程的起点,通常用于设置后续的解码、编码或其他处理步骤。
函数原型:
int avformat_open_input(AVFormatContext **ps,const char *url, AVInputFormat *fmt, AVDictionary **options);
参数说明:
ps:指向AVFormatContext结构的指针,该结构将被填充以包含媒体文件的信息和IO上下文。本函数如果打开媒体成功,会返回一个AVFormatContext的实例。
url:要打开的文件名或流的URL。
fmt:可选参数,指定要尝试探测的特定输入格式。如果为NULL,则自动探测。
options:可选参数,一个字典,包含一些特定的选项。这些选项可以影响解析过程或被用来设置特定格式的私有选项。
返回值:
返回值为整数类型。如果成功,返回0;否则返回一个负数错误码。
4.avformat_find_stream_info
函数作用:
用于获取媒体文件的流信息。它通过解析媒体文件的头部数据来确定每个流的类型、编码格式和其他相关信息。
函数原型:
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
参数说明:
ic:指向AVFormatContext结构的指针,该结构包含媒体文件的信息和IO上下文。
options:可选参数,一个字典,包含一些特定的选项。这些选项可以影响解析过程或被用来设置特定格式的私有选项。
返回值:
返回值为整数类型。如果成功,返回0;否则返回一个负数错误码。
5.av_find_best_stream
函数作用:
用于在给定的媒体文件中查找最佳流。它可以根据指定的条件(如编码格式、类型等)来选择最佳的流。
函数原型:
int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, int wanted_stream_nb, int related_stream, AVCodec **decoder_ret, int flags);
参数说明:
ic:指向AVFormatContext结构的指针,该结构包含媒体文件的信息和IO上下文。
type:要查找的流的类型,可以是音频、视频或字幕等。
wanted_stream_nb:可选参数,指定要查找的流的索引号。如果为-1,则自动选择最佳流。
related_stream:可选参数,指定与要查找的流相关的流的索引号。例如,如果要查找的视频流与音频流相关联,可以设置此参数为音频流的索引号。
decoder_ret:可选参数,一个指向AVCodec结构的指针,用于返回找到的最佳流的解码器。
flags:可选参数,用于控制查找过程的行为。可以使用AVFMT_FLAG_GENPTS标志来生成时间戳。默认为0
返回值:
返回值为整数类型。如果成功,返回找到的最佳流的索引号;否则返回一个负数错误码。
6.avcodec_find_decoder
函数作用:
用于查找指定编码格式的解码器。它可以根据给定的编码格式或编解码器ID来查找相应的解码器。(新版本返回值必须使用const)
函数原型:
AVCodec *avcodec_find_decoder(enum AVCodecID id);
参数说明:
id:要查找的编解码器ID,可以是音频、视频或字幕等类型的编解码器ID。
返回值:
返回值为指向
AVCodec结构的指针。如果成功找到解码器,则返回该解码器的指针;否则返回NULL。
7.avcodec_alloc_context3
函数作用:
用于分配编解码器上下文结构。它为指定的编解码器分配内存并初始化其字段。
函数原型:
AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);
参数说明:
codec:指向要为其分配上下文结构的编解码器的指针。
返回值:
返回值为指向
AVCodecContext结构的指针。如果成功分配和初始化上下文结构,则返回该结构的指针;否则返回NULL。
8.avcodec_parameters_to_context
函数作用:
用于将编解码器参数复制到编解码器上下文中。
函数原型:
int avcodec_parameters_to_context(AVCodecContext *ctx, const AVCodecParameters *par_out());
参数说明:
ctx:指向要设置参数的编解码器上下文的指针。
par_out():指向要复制的编解码器参数的指针。
返回值:
返回值为整数类型。如果成功,返回0;否则返回一个负数错误码。
9.avcodec_open2
函数作用:
用于打开编解码器并初始化其上下文。
函数原型:
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
参数说明:
avctx:指向要打开的编解码器上下文的指针。
codec:指向要打开的编解码器的指针。
options:可选参数,一个字典,包含一些特定的选项。这些选项可以影响编解码器的打开过程或被用来设置特定格式的私有选项。
返回值:
返回值为整数类型。如果成功,返回0;否则返回一个负数错误码。
10.av_read_frame
函数作用:
用于从媒体文件中读取一帧数据。
函数原型:
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
参数说明:
s:指向要读取数据的媒体文件的格式上下文的指针。
pkt:指向一个AVPacket结构的指针,该结构将被填充以包含读取到的数据。
返回值:
返回值为整数类型。如果成功,返回0;否则返回一个负数错误码。
11.avcodec_send_packet
函数作用:
用于将数据包发送到编解码器进行编码或解码。
函数原型:
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
参数说明:
avctx:指向要发送数据包的编解码器上下文的指针。
avpkt:指向要发送的数据包的指针。
返回值:
返回值为整数类型。如果成功,返回0;否则返回一个负数错误码。
12.avcodec_receive_frame
函数作用:
用于从编解码器接收编码或解码后的数据帧。
函数原型:
int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
参数说明:
avctx:指向要接收数据帧的编解码器上下文的指针。
frame:指向一个AVFrame结构的指针,该结构将被填充以包含接收到的数据帧。
返回值:
返回值为整数类型。如果成功,返回0;否则返回一个负数错误码。
13.sws_getContext
函数作用:
用于创建一个缩放和转换上下文。在调用该函数时,需要先确定源图像和目标图像的尺寸、像素格式以及是否需要进行某些特定的处理(例如缩放、裁剪、旋转等),然后根据这些信息来设置相应的参数。
函数原型:
SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat, int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param);
参数说明:
srcW和srcH表示源图像的宽度和高度;
srcFormat表示源图像的像素格式;
dstW和dstH表示目标图像的宽度和高度;
dstFormat表示目标图像的像素格式;
flags表示一些选项,例如是否使用多线程等;
srcFilter和dstFilter表示源图像和目标图像的滤波器;
param是一个可选参数,用于指定一些特定的参数
返回值:
返回值为一个指向新创建的缩放和转换上下文的指针。如果创建失败,则返回NULL。
14.av_image_get_buffer_size
函数作用:
用于计算图像缓冲区所需的内存大小。
函数原型:
int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align);
参数说明:
pix_fmt:指定像素格式,例如YUV420P、RGB24等。
width:指定图像的宽度。
height:指定图像的高度。
align:指定内存对齐的大小,通常为1或2。
返回值:
返回值为整数值,表示所需缓冲区的大小(以字节为单位)。
15.av_image_fill_arrays
函数作用:用于将图像数据填充到指定的缓冲区中。
函数原型:
int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],const uint8_t *src,enum AVPixelFormat pix_fmt, int width, int height, int align);
参数说明:
dst_data:指向目标缓冲区的指针数组,每个元素对应一个平面的数据指针。
dst_linesize:指向目标缓冲区的行大小数组,每个元素对应一个平面的行大小。
src:指向源数据的指针。
pix_fmt:指定像素格式,例如YUV420P、RGB24等。
width:指定图像的宽度。
height:指定图像的高度。
align:指定内存对齐的大小,通常为1或2。
返回值:
返回值为填充后的行大小数组;否则返回一个负数错误码。
16.av_strerror
函数作用:
用于将错误码转换为对应的错误信息字符串。
函数原型:
int av_strerror(int errnum, char *errbuf, size_t errbuf_size);
参数说明:
errnum:表示错误码的整数。
errbuf:指向存储错误信息的字符数组的指针。
errbuf_size:指定errbuf的大小。
返回值:
返回一个整数值,表示转换后的错误信息字符串的长度。如果转换成功,则返回非负值;如果转换失败,则返回负值。
17.av_packet_alloc
函数作用:
分配AVPacket内存空间并将其字段设置为默认值。
函数原型:
AVPacket *av_packet_alloc(void);
参数说明:无
返回值:
返回一个AVPacket,填充了默认值或失败时为NULL。
这只分配AVPacket本身,而不是数据缓冲区。那些必须通过诸如av_new_packet之类的其他方式进行分配。
使用示例:
int ret = -5;char *error = new char[1024];
memset(error, 0, 1024);// 将数组置零av_strerror(ret, error, 1024);
qDebug()<<"错误原因:"<<QString::fromStdString(error)<<" 返回值:"<<ret;delete[] error;
error = NULL;
18.av_new_packet
函数作用:
初始化AVPacket结构体的字段。
函数原型:
int av_new_packet(AVPacket *pkt, int size);
参数说明:
pkt:指向要分配的AVPacket结构体的指针。
size:指定AVPacket结构体的大小。
返回值:
返回一个整数值,表示操作的结果。如果成功,则返回0;否则,返回负数表示错误码。
19.一些创建函数
avformat_alloc_context:分配一个新的AVFormatContext结构体,并初始化其字段为默认值。
avcodec_alloc_context3:分配一个新的AVCodecContext结构体,并设置其字段为默认值。
av_packet_alloc:分配一个新的AVPacket结构体,并设置其字段为默认值。
av_frame_alloc:分配一个新的AVFrame结构体并将其字段设置为默认值,用于存储视频帧或音频帧的数据。
av_malloc:分配一块内存,该内存块可以用于存储多媒体数据或其他用途
20.一些释放资源函数
av_free(void *ptr):这个函数用于释放之前通过
av_malloc、av_realloc、av_mallocz或av_calloc等函数分配的内存。
av_freep(void * * ptr):这个函数与
av_free类似,但它还会将指针设置为NULL,以避免悬挂指针的问题。
avformat_close_input(AVFormatContext **s):关闭媒体文件格式上下文,并释放与之相关的资源。
avcodec_close(AVCodecContext *avctx):关闭编解码器上下文,并释放其中的资源。
av_packet_unref(AVPacket *pkt):用于释放AVPacket结构体占用的内存。
av_free_packet(AVPacket *pkt):用于释放数据包,主要用于网络传输。
avformat_flush(AVFormatContext *s):用于清空
AVFormatContext中的输入/输出缓冲区中的数据。
av_frame_free(AVFrame **frame):用于释放AVFrame结构体占用的内存。
sws_freeContext(SwsContext *sws):用于释放
SwsContext结构体占用的内存。
在使用这些函数时,需要注意以下几点:
正确配对:确保使用
av_malloc等分配的内存使用av_free或av_freep来释放。避免泄漏:在释放资源后,确保不再使用已释放的资源,以防止内存泄漏。
按顺序释放:如果多个资源之间存在依赖关系,应按照正确的顺序释放资源,以避免未定义的行为。
21.avformat_flush和av_frame_free区别
avformat_flush:这个函数用于清空输入/输出缓冲区中的数据,确保所有的数据都已经读取或者写入。这对于同步多媒体流非常重要,尤其是在关闭文件之前确保所有数据都已经被处理完毕。它不会影响已经分配的内存,只是清空了数据内容。av_frame_free:这个函数用于释放一个AVFrame结构体及其相关的数据所占用的所有内存。AVFrame是FFmpeg中表示音频或视频帧的结构体,当不再需要这个结构体时,应当使用av_frame_free来释放它,以防止内存泄漏。总的来说,
avformat_flush与av_frame_free在功能上是不同的。前者是清空缓冲区数据,后者是释放帧结构体内存。
22.av_packet_unref和av_free_packet区别
av_packet_unref:该函数减少AVPacket的引用计数。如果引用计数减到0,则该函数会释放AVPacket及其数据缓冲区。通常用于解码过程中,当一个AVPacket不再被需要时,可以调用这个函数来避免内存泄露。av_free_packet:该函数释放AVPacket结构体本身以及它所包含的数据。与av_packet_unref不同,av_free_packet不仅释放了AVPacket结构体,还释放了与它关联的所有数据。总的来说,如果你只想释放
AVPacket的数据部分而不是整个结构体,可以使用av_packet_unref。而如果你想要彻底地释放AVPacket结构体以及其数据,那么应该使用av_free_packet。
相关文章:
(三)ffmpeg 解码流程以及函数介绍
一、视频解码流程 二、函数介绍 1.avformat_network_init 函数作用: 执行网络库的全局初始化。这是可选的,不再推荐。 此函数仅用于解决旧GnuTLS或OpenSSL库的线程安全问题。如果libavformat链接到这些库的较新版本,或者不使用它们&#…...
go work模块与go mod包管理是的注意事项
如下图所示目录结构 cmd中是服务的包,显然auth,dbtables,pkg都是为cmd服务的。 首先需要需要将auth,dbtables,pkg定义到go.work中,如下: 在这样在各个单独的go mod管理的模块就可以互相调用了。一般情况下这些都是IDE自动进行的,…...
华为OD-C卷-最长子字符串的长度(一)[100分]
题目描述 给你一个字符串 s,首尾相连成一个环形,请你在环中找出 o 字符出现了偶数次最长子字符串的长度。 输入描述 输入是一个小写字母组成的字符串 输出描述 输出是一个整数 备注 1 ≤ s.length ≤ 500000s 只包含小写英文字母用例1 输入 alolobo输出 6说明 最长子字…...
实战小项目 | ESP32-S3和ESP32-C3通过ESP-Mesh-Lite组网 温湿度传感器案例
传统Wi-Fi网络所有终端设备都需要直接与路由器相连,这使得Wi-Fi的覆盖区域受到路由器位置的限制,可接入终端设备的数量也受到路由器容量的限制。而乐鑫ESP-Mesh-Lite Wi-Fi组网方案,所有终端设备都可以与相邻设备连接,摆脱了对路由…...
SiLM5350系列带米勒钳位的单通道隔离驱动器 助力汽车与工业应用实现稳定与高效的解决方案
带米勒钳位的隔离驱动SiLM5350系列 单通道 30V,10A 带米勒钳位的隔离驱动 具有驱动电流更大、传输延时更低、抗干扰能力更强、封装体积更小等优势, 为提高电源转换效率、安全性和可靠性提供理想之选。 SiLM5350系列产品描述: SiLM5350系列是单通道隔离驱…...
c#中怎么自动下载软件
以下是一个简单的 C# 示例,演示如何使用 WebClient 类下载软件: using System; using System.Net; class Program { static void Main(string[] args) { // 要下载的文件 URL string fileUrl "https://example.com/path/to/file"; // 本地保…...
Unity笔记之下拉刷新列表
这样的效果; 代码: using System; using System.Collections; using System.Collections.Generic; using Sirenix.OdinInspector; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI;public class ScrollRectUpdateView : Mon…...
防火墙操作!
当小编在Linux服务器上部署好程序以后,但是输入URL出现下述情况,原来是防火墙的原因!! 下面是一些防火墙操作! 为保证系统安全,服务器的防火墙不建议关闭!! 但是,我们可…...
代码随想录算法训练营第四十一天| 343. 整数拆分,96.不同的二叉搜索树
题目与题解 343. 整数拆分 题目链接:343. 整数拆分 代码随想录题解:343. 整数拆分 视频讲解:动态规划,本题关键在于理解递推公式!| LeetCode:343. 整数拆分_哔哩哔哩_bilibili 解题思路: 一眼懵…...
【MATLAB源码-第53期】m代码基于粒子群算法(PSO)的三维路径规划,显示最优路径和适应度曲线。
操作环境: MATLAB 2022a 1、算法描述 粒子群算法(Particle Swarm Optimization,简称PSO)是一种模拟鸟群觅食行为的启发式优化方法。以下是其详细描述: 基本思想: 鸟群在寻找食物时,每只鸟都…...
el-table多行合并
背景 前端统计列表,数据乱序。按日期、产品、阶段、DD项(所有header名称乱写)排序,列表如下。 示例 日期产品阶段DDEEFFGG20240414产品1阶段1场景1A01场景2B01其他A0120240410产品1阶段1场景2B01其他A0120240402产品2阶段1场景3…...
Vue3 + Element-Plus 使用 Table 插槽时数据未及时更新
Vue3 Element-Plus 使用 Table 插槽时数据未及时更新 问题重现解决方法最终效果 问题重现 这里我已经通过二级分类 id 查询到一级分类和二级分类,但是使用插槽和 v-for 渲染出来还是之前的分类 id,但是一点击表格或者保存代码他又能正常刷新出来。 <…...
vue 2 怎么把2024-04-13T17:42:19转换成短日期格式
我们在日常开发过程中,通常会将日期格式在entity中设置成LocalDateTime。这样就有一个麻烦,我们在前端展示这个日期的时候就会变成2024-04-13T17:42:19。这显然不是我们所要的效果,所以我们今天来解决这个问题,让前端展示正确的日…...
网络IO模型以及实际应用
网络IO模型 本文主要介绍了几种不同的网络IO模型,以及实际应用中使用到的Reactor模型等。 我们常说的网络IO模型,主要包含阻塞IO、非阻塞IO、多路复用IO、信号驱动IO、异步IO。 根据第一个阶段:是否需要阻塞,分为阻塞和非阻塞IO。…...
一文详解MES、ERP、SCM、WMS、APS、SCADA、PLM、QMS、CRM、EAM及其关系
经常遇到很多系统,比如:MES、ERP、SCM、WMS、APS、SCADA、PLM、QMS、CRM、EAM,这些都是什么系统?有什么功能和作用?它们之间的关系是怎样的? 今天就一文详细分享给大家。 10大系统之间的关系 ERP 和其他…...
《Kubernetes部署篇:基于Kylin V10+ARM架构CPU使用containerd部署K8S 1.26.15集群(一主多从)》
总结:整理不易,如果对你有帮助,可否点赞关注一下? 更多详细内容请参考:企业级K8s集群运维实战 1、在当前实验环境中安装K8S1.25.14版本,出现了一个问题,就是在pod中访问百度网站,大概时间有10s多,这个时间太长了,尝试了各种办法,都解决不了,后面尝试安装了了1.26.…...
maven命令
mvn archetype:generate 创建 Maven 项目 mvn compile 编译源代码 mvn deploy 发布项目 mvn test-compile 编译测试源代码 mvn test 运行应用程序中的单元测试 mvn site 生成项目相关信息的网站 mvn clean 清除项目目录中的生成结果 mvn package 根据项目生成的 jar mvn instal…...
jetson系列开发板使用虚拟机烧录系统时,遇见无法识别开发板的情况
在双系统中的ubuntu系统烧录没问题,但是电脑Ubuntu系统由于版本低,所以没有网络,烧录起来还的连网线,所以问了开发板的工程师,所幸,解决了问题,很感谢工程师的指导,特此记录一下&…...
【数据结构】树与二叉树、树与森林部分习题以及算法设计例题 2
目录 【数据结构】树与二叉树、树与森林部分习题以及算法设计例题一、交换二叉树每个结点的左右孩子Swap 函数(先序遍历):Swap 函数(中序遍历) 不可行:Swap 函数(后序遍历)ÿ…...
Cesium之home键开关及相机位置设置
显隐控制 设置代码中的homeButton var TDT_IMG_C "https://{s}.tianditu.gov.cn/img_c/wmts?servicewmts&requestGetTile&version1.0.0" "&LAYERimg&tileMatrixSetc&TileMatrix{TileMatrix}&TileRow{TileRow}&TileCol{TileCol}…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
