一.开发功能描述
在Ubuntu中,编译部署mosquitto的源码,然后用C语言设计一个发布客户端,基于qtcreator用C++设计一个qt程序,作为接收客户端。当打开mqtt代理服务器,发布客户端向代理发送实时视频数据,接收客户端能够接收到实时视频数据并且解码讲它们实时显示出来。
二.开发调试过程
技术方案:基于C语言和v4l2框架,用电脑摄像头获取MJPEG格式的视频流,然后通过v4l2框架的系统调用接口去进行内核缓冲区的管理,包括把视频流放入内核缓存区,用户获取内核缓冲区在用户空间的虚拟地址,用户通知内核缓冲区使用完毕。用户在获取缓冲区中一帧帧的MJPEG数据的地址和数据大小后,可以一帧帧地把MJPEG数据通过mosquitto的publish发送给代理,代理再转发给qt程序,qt程序在接收到这个程序后,对mqtt数据中的MJPEG数据进行解码并且一帧帧地显示在ui界面当中。
注意,这个技术方案没有考虑到音频处理,只能实现视频传输的功能。
在发送客户端(C端)中整体实现思路:
1.open电脑的摄像头设备
2.设置视频格式为 MJPEG (640×480)
3.请求和映射缓冲区
4.启动视频流,开始采集
5.初始化客户端
6.创建mqtt客户端示例
7.与代理服务器连接
8.在回调函数中订阅主题\”video/stream/jpeg\”
9.进入while(!stop)循环,这个stop是一个由信号触发的变量,用于退出while循环
10.在循环中反复取出内核缓冲区的内容,打包成mqtt报文进行发送
11.退出循环后清理资源,包含了停止视频流,取消映射缓冲区,关闭摄像头设备,断开 MQTT 连接
C端的代码:(可以直接运行的)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>//iocontrol设备控制操作
#include <linux/videodev2.h>//用于视频设备(如摄像头)的接口
#include <string.h>
#include <sys/mman.h>
#include <jpeglib.h>//JPEG 图像处理库
#include <linux/fb.h>//帧缓冲区相关
#include <stdio.h>
#include <mosquitto.h>
#include <signal.h>
#define MQTT_BROKER \”localhost\”//定义要连接的代理的ip地址,localhost指连接本地的ip
#define MQTT_PORT 1883//指代理监听的端口号,这也是连接的入口
#define MQTT_TOPIC \”video/stream/jpeg\”//订阅的主题
#define MQTT_QOS 1//消息服务等级
volatile sig_atomic_t stop = 0;
//定义了一个sig_atomic类型的全局变量stop,volatile 表示该变量可能会在程序外部被修改(如通过信号处理函数)
//sig_atomic类型的作用?通常是int类型,确保这些操作是原子性的(即不会被信号中断)
//信号处理函数是在内存的哪里执行的?在栈中吗?信号属于异步事件处理机制,会中断正常的程序执行,并在当前线程的上下文中运行,上下文(context)指的是程序执行时的状态
void handle_sigint(int sig) {
stop = 1;
}//定义了一个信号处理函数,当接收到 SIGINT(通常是通过按下 Ctrl+C 触发)时,将全局变量 stop 设置为 1,以通知程序退出
// 连接回调函数,客户端收到代理的消息后执行,这个执行是在主线程之外的
//回调函数是在栈中执行吗?是否要多开一个进程?这个网络信号的回调处理函数是在后台监听线程中执行的,是同步机制。
void on_connect(struct mosquitto *mosq, void *obj, int reason_code) {
if (reason_code != 0) {
fprintf(stderr, \”Failed to connect to MQTT broker
评论前必须登录!
注册