发送端基本上正确了,接收端的多线程时间控制还存在问题,计算出来的实际等待时间还是太短了
commit
502890dea6
@ -0,0 +1,103 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <opencv2/opencv.hpp>
|
||||||
|
#include <zmq.hpp>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// 创建ZeroMQ上下文
|
||||||
|
zmq::context_t context(1);
|
||||||
|
|
||||||
|
// 创建套接字并绑定到接收方
|
||||||
|
zmq::socket_t socket(context, zmq::socket_type::pull);
|
||||||
|
socket.bind("ipc:///tmp/video_socket");
|
||||||
|
|
||||||
|
// 创建窗口用于显示视频
|
||||||
|
cv::namedWindow("Received Video", cv::WINDOW_NORMAL);
|
||||||
|
|
||||||
|
// 统计变量
|
||||||
|
int frameCount = 0;
|
||||||
|
double totalTime = 0.0;
|
||||||
|
double avgFps = 0.0;
|
||||||
|
double avgInterval = 0.0;
|
||||||
|
std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
// 接收并实时播放视频帧
|
||||||
|
while (true) {
|
||||||
|
// 接收图像数据
|
||||||
|
zmq::message_t message;
|
||||||
|
socket.recv(&message);
|
||||||
|
|
||||||
|
// 解析接收到的图像数据
|
||||||
|
int width, height, type;
|
||||||
|
memcpy(&width, message.data(), sizeof(int));
|
||||||
|
memcpy(&height, static_cast<char*>(message.data()) + sizeof(int), sizeof(int));
|
||||||
|
memcpy(&type, static_cast<char*>(message.data()) + sizeof(int) * 2, sizeof(int));
|
||||||
|
|
||||||
|
// 计算图像数据的大小
|
||||||
|
size_t imageDataSize = message.size() - sizeof(int) * 3 - sizeof(double);
|
||||||
|
|
||||||
|
// 创建图像矩阵
|
||||||
|
cv::Mat frame(height, width, type, static_cast<char*>(message.data()) + sizeof(int) * 3);
|
||||||
|
|
||||||
|
// 获取帧率信息
|
||||||
|
double fps;
|
||||||
|
memcpy(&fps, static_cast<char*>(message.data()) + sizeof(int) * 3 + imageDataSize, sizeof(double));
|
||||||
|
|
||||||
|
// 显示图像
|
||||||
|
cv::imshow("Received Video", frame);
|
||||||
|
|
||||||
|
// 获取当前时间点
|
||||||
|
std::chrono::steady_clock::time_point currentTime = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
// 计算已经过去的时间
|
||||||
|
std::chrono::duration<double> elapsedSeconds = currentTime - startTime;
|
||||||
|
|
||||||
|
// 计算应该等待的时间间隔
|
||||||
|
double expectedInterval = 1000 / fps;
|
||||||
|
|
||||||
|
// 计算实际需要等待的时间间隔
|
||||||
|
double actualInterval = expectedInterval - elapsedSeconds.count() * 1000;
|
||||||
|
|
||||||
|
// 更新统计变量
|
||||||
|
frameCount++;
|
||||||
|
totalTime += elapsedSeconds.count();
|
||||||
|
|
||||||
|
// 每秒钟打印一次统计结果
|
||||||
|
if (totalTime >= 1.0) {
|
||||||
|
avgFps = frameCount / totalTime;
|
||||||
|
avgInterval = 1000 / avgFps;
|
||||||
|
std::cout << "Average FPS (last 1 second): " << avgFps << std::endl;
|
||||||
|
std::cout << "Average Interval (last 1 second): " << avgInterval << " ms" << std::endl;
|
||||||
|
|
||||||
|
// 重置统计变量
|
||||||
|
frameCount = 0;
|
||||||
|
totalTime = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按下 ESC 键退出循环
|
||||||
|
if (cv::waitKey(1) == 27)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 打印帧率和时间间隔信息
|
||||||
|
std::cout << "Received FPS: " << fps << std::endl;
|
||||||
|
std::cout << "Expected Interval: " << expectedInterval << " ms" << std::endl;
|
||||||
|
std::cout << "Elapsed Seconds: " << elapsedSeconds.count() << " s" << std::endl;
|
||||||
|
std::cout << "Actual Interval: " << actualInterval << " ms" << std::endl;
|
||||||
|
|
||||||
|
// 等待剩余时间,以实现与原视频完全一致的帧率
|
||||||
|
if (actualInterval > 0)
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<int>(std::round(actualInterval))));
|
||||||
|
|
||||||
|
// 更新起始时间点
|
||||||
|
startTime = currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭套接字
|
||||||
|
socket.close();
|
||||||
|
|
||||||
|
// 关闭 ZeroMQ 上下文
|
||||||
|
context.close();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <opencv2/opencv.hpp>
|
||||||
|
#include <zmq.hpp>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// 创建ZeroMQ上下文
|
||||||
|
zmq::context_t context(1);
|
||||||
|
|
||||||
|
// 创建套接字并连接到接收方
|
||||||
|
zmq::socket_t socket(context, zmq::socket_type::push);
|
||||||
|
socket.connect("ipc:///tmp/video_socket");
|
||||||
|
|
||||||
|
// 打开视频文件
|
||||||
|
cv::VideoCapture cap("1.mp4");
|
||||||
|
if (!cap.isOpened()) {
|
||||||
|
std::cerr << "Failed to open video file" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取视频帧率
|
||||||
|
double fps = cap.get(cv::CAP_PROP_FPS);
|
||||||
|
std::cout << "Original FPS: " << fps << std::endl;
|
||||||
|
|
||||||
|
// 逐帧读取并发送
|
||||||
|
cv::Mat frame;
|
||||||
|
while (cap.read(frame)) {
|
||||||
|
// 获取图像尺寸
|
||||||
|
int width = frame.cols;
|
||||||
|
int height = frame.rows;
|
||||||
|
int type = frame.type();
|
||||||
|
|
||||||
|
// 创建消息
|
||||||
|
zmq::message_t message(sizeof(int) * 3 + frame.total() * frame.elemSize() + sizeof(double));
|
||||||
|
|
||||||
|
// 将图像尺寸复制到消息
|
||||||
|
char* dataPtr = static_cast<char*>(message.data());
|
||||||
|
memcpy(dataPtr, &width, sizeof(int));
|
||||||
|
dataPtr += sizeof(int);
|
||||||
|
memcpy(dataPtr, &height, sizeof(int));
|
||||||
|
dataPtr += sizeof(int);
|
||||||
|
memcpy(dataPtr, &type, sizeof(int));
|
||||||
|
dataPtr += sizeof(int);
|
||||||
|
|
||||||
|
// 将图像数据复制到消息
|
||||||
|
memcpy(dataPtr, frame.data, frame.total() * frame.elemSize());
|
||||||
|
dataPtr += frame.total() * frame.elemSize();
|
||||||
|
|
||||||
|
// 将帧率信息复制到消息
|
||||||
|
memcpy(dataPtr, &fps, sizeof(double));
|
||||||
|
|
||||||
|
// 发送消息
|
||||||
|
socket.send(message);
|
||||||
|
|
||||||
|
// 打印帧率
|
||||||
|
std::cout << "Sent FPS: " << fps << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭套接字
|
||||||
|
socket.close();
|
||||||
|
|
||||||
|
// 关闭 ZeroMQ 上下文
|
||||||
|
context.close();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue