From 502890dea614256b8926834db8cf3d40f908c380 Mon Sep 17 00:00:00 2001 From: wangchunlin Date: Wed, 6 Sep 2023 00:05:10 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E9=80=81=E7=AB=AF=E5=9F=BA=E6=9C=AC?= =?UTF-8?q?=E4=B8=8A=E6=AD=A3=E7=A1=AE=E4=BA=86=EF=BC=8C=E6=8E=A5=E6=94=B6?= =?UTF-8?q?=E7=AB=AF=E7=9A=84=E5=A4=9A=E7=BA=BF=E7=A8=8B=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E8=BF=98=E5=AD=98=E5=9C=A8=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=8C=E8=AE=A1=E7=AE=97=E5=87=BA=E6=9D=A5=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E9=99=85=E7=AD=89=E5=BE=85=E6=97=B6=E9=97=B4=E8=BF=98=E6=98=AF?= =?UTF-8?q?=E5=A4=AA=E7=9F=AD=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- receiver.cpp | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++ sender.cpp | 65 ++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 receiver.cpp create mode 100644 sender.cpp diff --git a/receiver.cpp b/receiver.cpp new file mode 100644 index 0000000..76d8bd6 --- /dev/null +++ b/receiver.cpp @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include + +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(message.data()) + sizeof(int), sizeof(int)); + memcpy(&type, static_cast(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(message.data()) + sizeof(int) * 3); + + // 获取帧率信息 + double fps; + memcpy(&fps, static_cast(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 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(std::round(actualInterval)))); + + // 更新起始时间点 + startTime = currentTime; + } + + // 关闭套接字 + socket.close(); + + // 关闭 ZeroMQ 上下文 + context.close(); + + return 0; +} diff --git a/sender.cpp b/sender.cpp new file mode 100644 index 0000000..f5ea35b --- /dev/null +++ b/sender.cpp @@ -0,0 +1,65 @@ +#include +#include +#include + +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(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; +}