How to run OpenCV Videocapture in a separate posix thread in C++ for cross-platform?
<p>In my code, I want to run a <code>Videocapture</code> in a separate <code>pthread</code> continuously, while the main thread will act as a <code>socket server</code> to communicate to any client (or vice versa).</p><p>When the <code>client</code> communicates to the <code>server</code>, the <code>server</code> will immediately send the latest <code>Videocapture</code> frame to the client and close the connection and again wait for another connection.</p><p>I am currently using <code>OpenCV 2.3.0</code> in <code>mingw32</code> environment.</p><p>After looking some possible solutions on <code>StackOverflow</code>, I tried following them, but, however may I place the OpenCV <code>variables</code> either <code>locally</code> or <code>globally</code> or <code>swapping the threads</code> i.e. keeping <code>Videocapture</code> thread in <code>main thread</code> or <code>in the 2nd thread</code>, the program just hangs silently at the <code>mutex locked area</code> of the <code>VideoCapture</code> thread when the client gets connected.</p><p>I suppose this is happening when the <code>server</code> thread starts locking the <code>mutex</code> after connecting to a client.</p><p>Any <strong>reasoning</strong> or <strong>possible solution</strong> will be highly appreciated. Also, I am using <strong>prebuilt</strong> OpenCV version 2.3.0 and I need the code to be cross platform. In any case, if it points to a bug, I can obviously switch to some other version.</p><hr /><p><strong>Server code</strong></p><p><strong>mynet.h</strong></p><pre><br /><code>#ifndef __MYNET__<br />#define __MYNET__<br />#ifdef _WIN32<br />#ifndef _WIN32_WINNT<br />#define _WIN32_WINNT 0x0501 /* Windows XP. */<br />#endif<br />#include <winsock2.h><br />#include <Ws2tcpip.h><br />#else<br />/* Assume that any non-Windows platform uses POSIX-style sockets instead. */<br />#include <sys/socket.h><br />#include <arpa/inet.h><br />#include <netdb.h> /* Needed for getaddrinfo() and freeaddrinfo() */<br />#include <unistd.h> /* Needed for close() */<br />#endif<br /><br />int sockInit(void)<br />{<br />#ifdef _WIN32<br /> WSADATA wsa_data;<br /> return WSAStartup(MAKEWORD(1,1), &wsa_data);<br />#else<br /> return 0;<br />#endif<br />}<br /><br />int sockQuit(void)<br />{<br />#ifdef _WIN32<br /> return WSACleanup();<br />#else<br /> return 0;<br />#endif<br />}<br /><br />/* Note: For POSIX, typedef SOCKET as an int. */<br />#ifndef _WIN32<br />typedef int SOCKET;<br />#else<br />typedef unsigned int SOCKET;<br />#endif<br /><br />int sockClose(SOCKET sock)<br />{<br /> int status = 0;<br />#ifdef _WIN32<br /> status = shutdown(sock, SD_BOTH);<br /> if (status == 0) { status = closesocket(sock); }<br />#else<br /> status = shutdown(sock, SHUT_RDWR);<br /> if (status == 0) { status = close(sock); }<br />#endif<br /> return status;<br />}<br /><br /><br />#if(defined(_WIN32) || defined(WIN32))<br />#include <windows.h><br />#define mysleep(x) Sleep((x))<br />#else<br />#include <unistd.h><br />#define mysleep(x) usleep((x)*1000)<br />#endif<br /><br />#endif<br /></code><br /></pre><p><strong>netserver.cpp</strong></p><pre><br /><code>#define _GLIBCXX_USE_CXX11_ABI 0<br />#undef _GLIBCXX_DEBUG<br />#include "../mynet.h"<br />#include <stdio.h><br />#include <stdlib.h><br />#include <errno.h><br />#include <string.h><br />#include <sys/types.h><br />#include <opencv/cv.h><br />#include <opencv/highgui.h><br />#include <pthread.h><br /><br />using namespace cv;<br />Mat frame(120, 160, CV_8UC3);;<br />pthread_mutex_t mutex;<br />pthread_t thread;<br /><br />void *myfunc(void *threadid)<br />{<br /> int n;<br /> int listenfd = 0,connfd = 0;<br /> struct sockaddr_in serv_addr;<br /> unsigned char sendBuff[160*120*3];<br /> Mat hereframe;<br /><br /> listenfd = socket(AF_INET, SOCK_STREAM, 0);<br /> printf("socket retrieve success\n");<br /><br /> memset(&serv_addr, '0', sizeof(serv_addr));<br /> memset(sendBuff, '0', sizeof(sendBuff));<br /><br /> serv_addr.sin_family = AF_INET;<br /> serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);<br /> serv_addr.sin_port = htons(5000);<br /> bind(listenfd, (struct sockaddr*)&serv_addr,sizeof(serv_addr));<br /> if(listen(listenfd, 10) == -1)<br /> {<br /> printf("Failed to listen\n");<br /> }<br /> else<br /> {<br /> connfd = accept(listenfd, (struct sockaddr*)NULL,NULL); // accept awaiting request<br /> if(connfd<=0) printf("Something went wrong with write()! %s\n", strerror(errno));<br /> else<br /> {<br /> while(1)<br /> {<br /> printf("Got client...\n");<br /> pthread_mutex_lock (&mutex);<br /> printf("Copying data...\n");<br /> frame.copyTo(hereframe);<br /> pthread_mutex_unlock (&mutex);<br /> printf("Hereframe size: %dX%d\n", hereframe.rows, hereframe.cols);<br /> memcpy(sendBuff, hereframe.data, 120*160*3);<br /> printf("Sending data...\n");<br /> n = send(connfd, (char*)sendBuff, 120*160*3,0);<br /> if(n<0) printf("Something went wrong with write()! %s\n", strerror(errno));<br /> printf("Closing client after writing %d bytes...\n", n);<br /> printf("Closed...\n");<br /> mysleep(40);<br /> printf("Restartng data...\n");<br /> }<br /> sockClose(connfd);<br /> }<br /> }<br /> sockQuit();<br /><br /> pthread_exit(NULL);<br />}<br /><br />int main(void)<br />{<br /> //cvNamedWindow("Sisplay", CV_WINDOW_AUTOSIZE);<br /> sockInit();<br /> pthread_mutex_init(&mutex,NULL);<br /> VideoCapture cap;<br /> Mat hereframe1;<br /> cap.open(0);<br /> cap.set( CV_CAP_PROP_FRAME_WIDTH, 160 );<br /> cap.set( CV_CAP_PROP_FRAME_HEIGHT, 120 );<br /><br /> if( !cap.isOpened()) printf("Fukced up\n");<br /> int rc;<br /> long t;<br /> rc = pthread_create(&thread, NULL, myfunc, (void *)t);<br /> if (rc)<br /> {<br /> printf("ERROR; return code from pthread_create() is %d\n", rc);<br /> exit(-1);<br /> }<br /><br /> for(;;)<br /> {<br /> cap >> hereframe1;<br /> // printf("Video size: %dX%d\n", hereframe1.rows, hereframe1.cols);<br /><br /> pthread_mutex_lock(&mutex);<br /> hereframe1.copyTo(frame); /* hangs here*/<br /> pthread_mutex_unlock(&mutex);<br /> // cvtColor(frame, gray, CV_BGR2GRAY);<br /><br /> Scalar tempVal = mean(hereframe1);<br /> // printf("Mean = %f\n", tempVal.val[0]);<br /> mysleep(30);<br /> //if(waitKey(30)=='q') break;<br /> // std::swap(prevgray, gray);<br /> }<br /> char *b;<br /> pthread_join(thread,(void**)&b);<br /> return 0;<br />}<br /></code><br /></pre><hr /><p><strong>Client code</strong></p><p><strong>receiver.cpp</strong></p><pre><br /><code>#define _GLIBCXX_USE_CXX11_ABI 0<br />#include "../mynet.h"<br />#include <stdio.h><br />#include <string.h><br />#include <stdlib.h><br />#include <unistd.h><br />#include <errno.h><br />#include <opencv/cv.h><br />#include <opencv/highgui.h><br /><br />using namespace cv;<br /><br />int main(int argc, char *argv[])<br />{<br /> int sockfd = 0,n = 0;<br /> unsigned char recvBuff[120*160*3];<br /> struct sockaddr_in serv_addr;<br /> sockInit();<br /> memset(recvBuff, '0',sizeof(recvBuff));<br /> if((sockfd = socket(AF_INET, SOCK_STREAM, 0))< 0)<br /> {<br /> printf("\n Error : Could not create socket \n");<br /> return 1;<br /> }<br /><br /> serv_addr.sin_family = AF_INET;<br /> serv_addr.sin_port = htons(5000);<br /> serv_addr.sin_addr.s_addr = inet_addr(argv[1]);<br /><br /> if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))<0)<br /> {<br /> printf("\n Error : Connect Failed \n");<br /> return 1;<br /> }<br /> printf("Connected to server...\n");<br /> Mat frame(120, 160, CV_8UC3);<br /> int csz = 0;<br /> cvNamedWindow("Display", CV_WINDOW_AUTOSIZE);<br /> printf("OK here 0\n");<br /> for(;;)<br /> {<br /> csz = 0;<br /> while((n = recv(sockfd, (char*)recvBuff, sizeof(recvBuff), 0)) > 0)<br /> {<br /> printf("OK here 2\n");<br /><br /> printf("Read %d bytes...\n", n);<br /> csz += n;<br /> if(csz<=120*160*3)<br /> {<br /> memcpy(frame.data+(csz-n), recvBuff, n);<br /> }<br /> if(csz>= 120*160*3) break;<br /> }<br /> printf("OK here 3\n");<br /><br /> printf("Got data of size %d bytes...\n", csz);<br /> imshow("Display", frame);<br /> if(csz < 120*160*3)<br /> {<br /> printf("\n Read Error \n");<br /> }<br /> if(waitKey(30)=='q') break;<br /> // std::swap(prevgray, gray);<br /> }<br /> sockClose(sockfd);<br /><br /> sockQuit();<br /> return 0;<br />}<br /></code><br /></pre><br /><h2>Click here view more answers <a href="%20http://stackoverflow.com/questions/34469844/how-to-run-opencv-videocapture-in-a-separate-posix-thread-in-c-for-cross-platf">http://ift.tt/1Ivhb6k</a></h2>
Nhận xét
Đăng nhận xét