/* 本程序用于视频分流 1.推流摄像头画面至RTSP服务器,交由YOLO模型进行处理 2.接收YOLO传来的坐标,深度,警报等级等等数据 3.根据获取到的数据绘制边框和相应数据 4.将绘制完毕的视频流继续推流至RTSP服务器用于输出 */ #include #include #include using namespace std; using namespace cv; using namespace chrono_literals; int main() { VideoCapture cap(0); // 直接传 MJPEG(本身就是全 I 帧) // FILE *pipe = popen( // "ffmpeg " // "-f rawvideo -pixel_format bgr24 -video_size 640x480 -framerate 30 " // "-i - " // "-c:v h264_rkmpp " // "-rc_mode 2 " // CQP 模式 // "-qp_init 30 " // "-profile baseline " // "-g 1 " // 全 I 帧 // "-bf 0 " // "-coder cavlc " // "-8x8dct false " // "-fflags nobuffer " // "-flags low_delay " // "-max_delay 0 " // "-f rtsp -muxdelay 0.001 -rtsp_transport udp " // "rtsp://192.168.12.1:8554/rtsp/test", "w"); // FILE *pipe = popen( // "ffmpeg " // "-f rawvideo -pixel_format bgr24 -video_size 640x480 -framerate 30 " // "-i - " // "-c:v h264_rkmpp " // "-rc_mode 2 " // CQP 模式(最低延迟) // "-qp_init 32 " // 初始 QP // "-profile baseline " // baseline profile // "-coder cavlc " // CAVLC 编码 // "-8x8dct false " // 禁用 8x8 DCT // "-g 1 " // GOP=1(全 I 帧) // "-bf 0 " // 无 B 帧 // "-fflags nobuffer " // 无缓冲 // "-flags low_delay " // 低延迟标志 // "-max_delay 0 " // 零延迟 // "-f rtsp -rtsp_transport udp " // "rtsp://192.168.12.1:8554/rtsp/test", // "w"); // UDP传输 FILE *pipe = popen( "ffmpeg " "-f rawvideo -pixel_format bgr24 -video_size 640x480 -framerate 30 " "-i - " "-c:v h264_rkmpp " "-rc_mode 2 -qp_init 32 " "-profile baseline -coder cavlc " "-g 1 -bf 0 " "-fflags nobuffer -flags low_delay " "-f h264 udp://192.168.12.1:8888?pkt_size=1316", "w"); if (pipe) { setvbuf(pipe, NULL, _IONBF, 0); // 添加无缓冲模式 } if (!pipe) { cerr << "popen faild\n"; return -1; } if (cap.isOpened() == false) { cerr << "摄像头打开失败,请重试" << endl; return -1; } // 降低分辨率,固定MJPG编码 cap.set(CAP_PROP_FOURCC, VideoWriter::fourcc('M', 'J', 'P', 'G')); cap.set(CAP_PROP_FRAME_WIDTH, 640); cap.set(CAP_PROP_FRAME_HEIGHT, 480); cap.set(CAP_PROP_FPS, 30); cap.set(CAP_PROP_BUFFERSIZE, 1); int64 count = 0; auto t0 = chrono::steady_clock::now(); Mat frame; while (true) { cap.read(frame); if (frame.empty()) { cerr << "读取帧失败" << endl; break; } putText(frame, "press 'q' to quit", Point(0, 20), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(0, 255, 0), 2, LINE_8); ++count; auto now = chrono::steady_clock::now(); string fps; if (chrono::duration_cast(now - t0).count() / 1000.0 > 1.0) { fps = "FPS:" + to_string(count); setWindowTitle("测试画面", fps); count = 0; t0 = now; } fwrite(frame.data, 1, frame.total() * frame.elemSize(), pipe); fflush(pipe); // 立即刷新 // imshow("测试画面", frame); // 按下 'q' 键退出 if (cv::waitKey(1) == 'q') { break; } } // 释放资源 pclose(pipe); cap.release(); destroyAllWindows(); return 0; }