1. /**
  2.  * stream_client.c:
  3.  * OpenCV video streaming client
  4.  *
  5.  * Author Nash <me_at_nashruddin.com>
  6.  *
  7.  * See the tutorial at
  8.  * http://nashruddin.com/StrEAMinG_oPENcv_vIdEos_ovER_tHe_nEtWoRk
  9.  */
  10.  
  11. #include <sys/socket.h>
  12. #include <netinet/in.h>
  13. #include <arpa/inet.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <unistd.h>
  17. #include <pthread.h>
  18. #include "cv.h"
  19. #include "highgui.h"
  20.  
  21. IplImage* img;
  22. int is_data_ready = 0;
  23. int sock;
  24. char* server_ip;
  25. int server_port;
  26.  
  27. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  28.  
  29. void* streamClient(void* arg);
  30. void quit(char* msg, int retval);
  31.  
  32. int main(int argc, char** argv)
  33. {
  34. pthread_t thread_c;
  35. int width, height, key;
  36.  
  37. if (argc != 5) {
  38. quit("Usage: stream_client <server_ip> <server_port> <width> <height>", 0);
  39. }
  40.  
  41. /* get the parameters */
  42. server_ip = argv[1];
  43. server_port = atoi(argv[2]);
  44. width = atoi(argv[3]);
  45. height = atoi(argv[4]);
  46.  
  47. /* create image */
  48. img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
  49. cvZero(img);
  50.  
  51. /* run the streaming client as a separate thread */
  52. if (pthread_create(&thread_c, NULL, streamClient, NULL)) {
  53. quit("pthread_create failed.", 1);
  54. }
  55.  
  56. fprintf(stdout, "Press 'q' to quit.\n\n");
  57. cvNamedWindow("stream_client", CV_WINDOW_AUTOSIZE);
  58.  
  59. while(key != 'q') {
  60. /**
  61.   * Display the received image, make it thread safe
  62.   * by enclosing it using pthread_mutex_lock
  63.   */
  64. pthread_mutex_lock(&mutex);
  65. if (is_data_ready) {
  66. cvShowImage("stream_client", img);
  67. is_data_ready = 0;
  68. }
  69. pthread_mutex_unlock(&mutex);
  70.  
  71. key = cvWaitKey(10);
  72. }
  73.  
  74. /* user has pressed 'q', terminate the streaming client */
  75. if (pthread_cancel(thread_c)) {
  76. quit("pthread_cancel failed.", 1);
  77. }
  78.  
  79. /* free memory */
  80. cvDestroyWindow("stream_client");
  81. quit(NULL, 0);
  82. }
  83.  
  84. /**
  85.  * This is the streaming client, run as separate thread
  86.  */
  87. void* streamClient(void* arg)
  88. {
  89. struct sockaddr_in server;
  90.  
  91. /* make this thread cancellable using pthread_cancel() */
  92. pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
  93. pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
  94.  
  95. /* create socket */
  96. if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
  97. quit("socket() failed.", 1);
  98. }
  99.  
  100. /* setup server parameters */
  101. memset(&server, 0, sizeof(server));
  102. server.sin_family = AF_INET;
  103. server.sin_addr.s_addr = inet_addr(server_ip);
  104. server.sin_port = htons(server_port);
  105.  
  106. /* connect to server */
  107. if (connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {
  108. quit("connect() failed.", 1);
  109. }
  110.  
  111. int imgsize = img->imageSize;
  112. char sockdata[imgsize];
  113. int i, j, k, bytes;
  114.  
  115. /* start receiving images */
  116. while(1)
  117. {
  118. /* get raw data */
  119. for (i = 0; i < imgsize; i += bytes) {
  120. if ((bytes = recv(sock, sockdata + i, imgsize - i, 0)) == -1) {
  121. quit("recv failed", 1);
  122. }
  123. }
  124.  
  125. /* convert the received data to OpenCV's IplImage format, thread safe */
  126. pthread_mutex_lock(&mutex);
  127.  
  128. for (i = 0, k = 0; i < img->height; i++) {
  129. for (j = 0; j < img->width; j++) {
  130. ((uchar*)(img->imageData + i * img->widthStep))[j] = sockdata[k++];
  131. }
  132. }
  133.  
  134. is_data_ready = 1;
  135. pthread_mutex_unlock(&mutex);
  136.  
  137. /* have we terminated yet? */
  138. pthread_testcancel();
  139.  
  140. /* no, take a rest for a while */
  141. usleep(1000);
  142. }
  143. }
  144.  
  145. /**
  146.  * This function provides a way to exit nicely from the system
  147.  */
  148. void quit(char* msg, int retval)
  149. {
  150. if (retval == 0) {
  151. fprintf(stdout, (msg == NULL ? "" : msg));
  152. fprintf(stdout, "\n");
  153. } else {
  154. fprintf(stderr, (msg == NULL ? "" : msg));
  155. fprintf(stderr, "\n");
  156. }
  157.  
  158. if (sock) close(sock);
  159. if (img) cvReleaseImage(&img);
  160.  
  161. pthread_mutex_destroy(&mutex);
  162.  
  163. exit(retval);
  164. }