三:FFMPEG拉流读取模块的讲解

devtools/2025/3/16 5:01:17/

        FFMPEG拉流读取模块在远程监控项目最核心的作用是读取UVC摄像头传输的H264码流,并对其码流进行帧的提取,提取完成之后则把数据传输到VDEC解码模块进行解码。而在我们这个项目中,UVC推流的功能由FFMPEG的命令完成。 

FFMPEG拉流读取模块的API

        在FFMPEG里面提供了一系列的API对码流进行读取和提取帧,下面我们来看看远程监控项目用到了什么API。

FFMPEG读取模块初始化的API

        在FFMPEG里面,读取模块的初始化用的是avformat_open_input

       int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);

第一个参数:

        AVFormatContext的结构体二级指针,这个结构体是FFMPEG非常重要的内部桥梁,结构体内部包含有AVInputFormat、AVOutputFormat、AVCodec、AVStream、AVDictionary 、AVClass等重要结构体。

第二个参数:

        url是需要读取的流媒体文件名,这个地址可以是文件如(xxx.mp4、xxx.ts、xxx.flv);也可以是网络流媒体地址,如:(rtmp://192.168.100.22.22:1935/live/01、rtsp://192.168.100.22.22:1935/live/01、udp://192.168.100.66:8080)

第三个参数:

        AVInputFormat结构体指针,AVInputFormat是FFMPEG解复用器对象,它表示的是输入文件容器的格式。通常设置为 NULL,让 FFmpeg 自动检测

第四个参数:

        AVDictionary的二级地址,AVDictionary是FFMPEG的字典结构体,它主要是设置FFMPEG内部的参数,如:video_size分辨率、max_delay最大延迟数等,并且以key-value的方式进行存储。options: 用于传递额外的选项,通常设置为 NULL


FFMPEG获取流媒体具体信息的API

        在FFMPEG里面,获取流媒体具体信息的API是avformat_find_stream_info

        int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);

第一个参数:

        AVFormatContext结构体指针,这个结构体是FFMPEG非常重要的内部桥梁,它的主要功能是获取FFMPEG解封装的数据,如(flv/mp4/ts)等。

第二个参数:

        AVDictionary的二级地址,AVDictionary是FFMPEG的字典结构体,它主要是设置FFMPEG内部的参数,如:video_size分辨率、max_delay最大延迟数等,并且以key-value的方式进行存储。


FFMPEG查找最佳匹配的流媒体函数API

        这个函数的最主要作用是获取音视频的索引值,就是stream_index。stream_index可以是音频索引也可以是视频索引

int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type,int wanted_stream_nb,int related_stream,AVCodec **decoder_ret,int flags);

第一个参数:AVFormatContext结构体指针,它表示的是输入流媒体的上下文

第二个参数:type类型,这里指的是要查找类型的索引,分别是AVMEDIA_TYPE_VIDEO视频类型、AVMEDIA_TYPE_AUDIO音频类型、AVMEDIA_TYPE_SUBTITLE字幕类型

第三个参数:wanted_stream_nb期望的流媒体索引号,默认是-1

第四个参数:related_stream前一个流媒体索引号,默认-1

第五个参数:返回decoder_ret解码器的指针

第六个参数:flags查找最佳流的标志位,默认是0

返回值:返回最佳的流媒体索引值,也就是音视频的索引值


 FFMPEG读取压缩码流并抽取帧数据的API 

        在FFMPEG里面,使用av_read_frame对压缩裸流进行帧数据的提取,av_read_frame的工作流程如上图,这里重点说一下它的工作流程。H264(或者H265)的裸流数据,一般是以StartCode+NALU(SPS)+StartCode+NALU(PPS)+StartCode+NALU(I)+StartCode+NALU(P)....这种连续的数据表示的,但是对于解码器来说它只能解码一帧单独的数据不能解码连续的数据。

        所以此时,av_read_frame就可以把这一连串的码流进行分割。如上图:第一个StartCode+NALU(SPS),第二个StartCode+NALU(PPS),第三个StartCode+NALU(I),第四个StartCode+NALU(P)被一个一个分割出来,并把这一帧帧分割出来的数据传输到解码器。此时解码器才能够正确解码出数据。

int av_read_frame(AVFormatContext *s, AVPacket *pkt);

第一个参数:AVFormatContext结构体指针

第二个参数:AVPacket结构体指针


远程监控项目FFMPEG拉流输入模块初始化的代码实现

读取json文件并解析url地址 

        是获取摄像头参数和URL地址的实现过程,是通过JSON文件获取URL地址的实现。这个代码非常简单,利用fopen打开json文件FILE *file = fopen("/www/cjson_dir/network_detail.json", "r"), 并调用fread读取里面的内容, 然后用cJSON的API来解析JSON数据,具体的实现是cJSON *json = cJSON_Parse(data), 并获取JSON文件的URL地址, 具体的实现是cJSON *url_address_json = cJSON_GetObjectItem(json, "url_address"); char *network_address = url_address_json->valuestring。经过这几步,就可以获取URL地址了。

avformat_network_init初始化网络配置

    /*** 第二步:* 初始化网络库,使用网络库时,必须调用此函数非常重要。*/av_format_network_init();

        用于初始化网络协议。在某些情况下,当你需要通过网络访问音视频资源时,可能需要调用这个函数来确保网络协议的正确初始化.。

avformat_open_input初始化FFMPEG拉流输入模块

  /*** 第三步:* vformat_open_input,流输入模块*/if ((avformat_open_input(&m_pInFmtCtx, network_address, 0, 0)) < 0){printf("文件读取失败\n");return -1}printf("文件读取成功\n");

        是调用avformat_open_input打开输入的AVFormatContext结构体指针(大管家婆), 这里面传入三个参数。第一个传参:AVFormatContext结构体指针; 第二个传参: URL地址, 这里直接从json文件读取; 第三个传参:fmt这里填0即可; 第四个传参: options填0即可。经过上面open操作后,就可以初始化输入的AVFormatContext结构体。

 avformat_find_stream_info获取输入端的消息

    /*** 第四步:* 找到流的一些消息,采样格式或者分辨率.....* 比如获取视频帧率、视频宽高,重新计算最大分析时长,打开解码器解码获取codec数据*/// 把大管家婆传进去,因为打开问的时候,大管家婆已经获取到了所有的消息avformat_find_stream_info(m_pInFmtCtx, nullptr);printf("流的消息解析完毕\n");

        avformat_find_stream_info获取输入模块的信息,这其中包括视频帧率、视频宽高,重新计算最大分析时长,打开解码器解码获取codec数据。

 av_find_best_stream查找对应的音视频索引值 

/*** 第五步:* 通过av_find_best_stream()函数来获取流的索引* 第二个参数就是代表着要寻找的流* 比如视频的index是0,音频的index是1,后面可能还有字幕流..*/// 把大管家婆传进去,因为打开问的时候,大管家婆已经获取到了所有的消息int nvideo_index = av_find_best_stream(m_pInFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr);if (nvideo_index < 0){avformat_free_context(m_pInFmtCtx);return -1;}// 成功获取视频的索引printf("==> av_find_best_stream!\n");

        av_find_best_stream获取音视频的索引值,由于UVC传来的数据只有视频数据,所以只有视频索引。 

整体框架


http://www.ppmy.cn/devtools/167466.html

相关文章

AWS Bedrock + DeepSeek-R1:开启企业级 AI 开发的新篇章

目录 前言 行业里程碑事件 技术经济性突破 1、训练成本革命 2、推理效率提升 3、模型蒸馏技术 企业级安全架构 1、数据主权保障 2、合规性认证 3、安全护栏系统 4、审计追踪 典型应用场景 1、跨国团队协作 2、智能投研分析 3、教育内容生成 4、科研辅助 客户部…

Python——计算机网络

一.ip 1.ip的定义 IP是“Internet Protocol”的缩写&#xff0c;即“互联网协议”。它是用于计算机网络通信的基础协议之一&#xff0c;属于TCP/IP协议族中的网络层协议。IP协议的主要功能是负责将数据包从源主机传输到目标主机&#xff0c;并确保数据能够在复杂的网络环境中正…

通义万相2.1 图生视频:为AI绘梦插上翅膀,开启ALGC算力领域新纪元

通义万相2.1图生视频大模型 通义万相2.1图生视频技术架构万相2.1的功能特点性能优势与其他工具的集成方案 蓝耘平台部署万相2.1核心目标典型应用场景未来发展方向 通义万相2.1ALGC实战应用操作说明功能测试 为什么选择蓝耘智算蓝耘智算平台的优势如何通过API调用万相2.1 写在最…

ChatGPT课件分享(37页PPT)

资料解读&#xff1a;ChatGPT课件分享 详细资料请看本解读文章的最后内容。 近年来&#xff0c;人工智能技术的迅猛发展引发了全球范围内的广泛关注&#xff0c;尤其是以OpenAI为代表的公司在自然语言处理领域的突破性进展&#xff0c;彻底改变了人机交互的方式。本文将详细解…

计算机网络--访问一个网页的全过程

文章目录 访问一个网页的全过程应用层在浏览器输入URL网址http://www.aspxfans.com:8080/news/index.aspboardID5&ID24618&page1#r_70732423通过DNS获取IP地址生成HTTP请求报文应用层最后 传输层传输层处理应用层报文建立TCP连接传输层最后 网络层网络层对TCP报文进行处…

宇树人形机器人开源模型

1. 下载源码 https://github.com/unitreerobotics/unitree_ros.git2. 启动Gazebo roslaunch h1_description gazebo.launch3. 仿真效果 H1 GO2 B2 Laikago Z1 4. VMware: vmw_ioctl_command error Invalid argument 这个错误通常出现在虚拟机环境中运行需要OpenGL支持的应用…

FlinkCDC3.3 使用 Mysql 8.4 报错

一、报错日志 Caused by: io.debezium.DebeziumException: org.apache.flink.util.FlinkRuntimeException: Cannot read the binlog filename and position via SHOW MASTER STATUS. Make sure your server is correctly configuredat org.apache.flink.cdc.connectors.mysql.…

centos 8安装及相关操作

安装centos 8 在VMware workstation中安装 UEFI对比BIOS有更快的启动速度、支持更大容量硬盘及 GPT 分区、图形化操作界面更友好、安全性更高、对新操作系统支持更好、硬件兼容性不断增强以及扩展性更好等。 按回车确定 重置root管理员密码 这样进入到紧急救援模式 mount -o r…