- 第一个完整版本
用到了多线程、信号量、互斥量。给原始数据开辟了10帧缓冲区,循环使用。
主线程初始化变量,然后启动三个子线程,后面什么也不做,线程退出时的清理工作也没有,所以这只是功能测试版本。
- 源代码4
1 #include <iostream>
2 #include <opencv2/opencv.hpp>
3 #include <cstdio>
4 #include <pthread.h>
5 #include <semaphore.h>
6
7 const int BufBlock = 829440;
8 const int BufSize = 5;
9 unsigned char **buf = NULL;
10 unsigned int wbuf = 0;
11 unsigned int rbuf = 0;
12 pthread_mutex_t mutex_buf[BufSize], mutex_show;
13 sem_t sem_buf;
14
15 cv::Mat yuv(576, 720, CV_8UC3, cv::Scalar(0));
16 cv::Mat frame(576, 720, CV_8UC3, cv::Scalar(0));
17 int counter;
18 char title[10];
19
20 cv::VideoWriter videofile;
21
22 void* capture(void* parameter) {
23 while (true) {
24 pthread_mutex_lock(mutex_buf + (wbuf % BufSize));
25
26 unsigned char *data = buf[wbuf % BufSize];
27 for (int i = 0; i < BufBlock; ++i) {
28 data[i] = getchar();
29 }
30
31 pthread_mutex_unlock(mutex_buf + (wbuf % BufSize));
32
33 sem_post(&sem_buf);
34
35 ++wbuf;
36 }
37 }
38
39 void* record(void* parameter) {
40 while (true) {
41 sem_wait(&sem_buf);
42
43 int cur = 0;
44 sem_getvalue(&sem_buf, &cur);
45 std::cout << "Current buffer: " << cur << ", wbuf = " << wbuf << ", rbuf = " << rbuf << std::endl;
46
47 pthread_mutex_lock(mutex_buf + (rbuf % BufSize));
48
49 sprintf(title, "%d", ++counter);
50 unsigned char *data = buf[rbuf % BufSize];
51
52 int row = 0;
53 int col = 0;
54 for (int i = 0; i < BufBlock; i = i + 4) {
55 yuv.at<cv::Vec3b>(row, col) = cv::Vec3b(data[i + 1], data[i], data[i + 2]); /// Y1, U1, V1
56 yuv.at<cv::Vec3b>(row, col + 1) = cv::Vec3b(data[i + 3], data[i], data[i + 2]); /// Y2, U2=U1, V2=V1
57
58 col = col + 2;
59 if (col >= 720) {
60 col = 0;
61 row = row + 1;
62 }
63 }
64
65 pthread_mutex_unlock(mutex_buf + (rbuf % BufSize));
66
67 pthread_mutex_lock(&mutex_show);
68 cv::cvtColor(yuv, frame, CV_YUV2BGR);
69 cv::putText(frame, title, cv::Point(0, 50), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(255, 255 ,0));
70 pthread_mutex_unlock(&mutex_show);
71 videofile << frame;
72
73 ++rbuf;
74 }
75 }
76
77 void* show(void* parameter) {
78 while (true) {
79 pthread_mutex_lock(&mutex_show);
80 cv::imshow("frame", frame);
81 pthread_mutex_unlock(&mutex_show);
82 cv::waitKey(40);
83 }
84 }
85
86 int main(int argc, char **argv) {
87 buf = new unsigned char * [BufSize];
88 for (int i = 0; i < BufSize; ++i) {
89 buf[i] = new unsigned char [BufBlock];
90 }
91 sem_init(&sem_buf, 0, 0);
92 pthread_t captureid, recordid, showid;
93 counter = 0;
94
95 /// 'D', 'I', 'V', 'X'
96 /// 'F', 'M', 'P', '4'
97 videofile = cv::VideoWriter("test.avi", CV_FOURCC('F', 'M', 'P', '4'), 25.0, cv::Size(720, 576));
98
99 int status = pthread_create(&captureid, NULL, capture, NULL);
100 if (status != 0) {
101 std::cerr << "不能创建capture线程: " << strerror(status);
102 return 0;
103 }
104
105 status = pthread_create(&recordid, NULL, record, NULL);
106 if (status != 0) {
107 std::cerr << "不能创建record线程: " << strerror(status);
108 return 0;
109 }
110
111 status = pthread_create(&showid, NULL, show, NULL);
112 if (status != 0) {
113 std::cerr << "不能创建show线程: " << strerror(status);
114 return 0;
115 }
116
117 pthread_join(recordid, (void **)0);
118 pthread_join(captureid, (void **)0);
119 pthread_join(showid, (void **)0);
120
121 return 0;
122 }
功能基本实现,但是发现画面”破损“很严重。