How to run OpenCV Videocapture in a separate posix thread in C++ for cross-platform?

In my code, I want to run a Videocapture in a separate pthread continuously, while the main thread will act as a socket server to communicate to any client (or vice versa).

When the client communicates to the server, the server will immediately send the latest Videocapture frame to the client and close the connection and again wait for another connection.

I am currently using OpenCV 2.3.0 in mingw32 environment.

After looking some possible solutions on StackOverflow, I tried following them, but, however may I place the OpenCV variables either locally or globally or swapping the threads i.e. keeping Videocapture thread in main thread or in the 2nd thread, the program just hangs silently at the mutex locked area of the VideoCapture thread when the client gets connected.

I suppose this is happening when the server thread starts locking the mutex after connecting to a client.

Any reasoning or possible solution will be highly appreciated. Also, I am using prebuilt 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.


Server code

mynet.h

#ifndef __MYNET__
#define __MYNET__
#ifdef _WIN32
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501  /* Windows XP. */
#endif
#include <winsock2.h>
#include <Ws2tcpip.h>
#else
/* Assume that any non-Windows platform uses POSIX-style sockets instead. */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>  /* Needed for getaddrinfo() and freeaddrinfo() */
#include <unistd.h> /* Needed for close() */
#endif

int sockInit(void)
{
#ifdef _WIN32
    WSADATA wsa_data;
    return WSAStartup(MAKEWORD(1,1), &wsa_data);
#else
    return 0;
#endif
}

int sockQuit(void)
{
#ifdef _WIN32
    return WSACleanup();
#else
    return 0;
#endif
}

/* Note: For POSIX, typedef SOCKET as an int. */
#ifndef _WIN32
typedef int SOCKET;
#else
typedef unsigned int SOCKET;
#endif

int sockClose(SOCKET sock)
{
    int status = 0;
#ifdef _WIN32
    status = shutdown(sock, SD_BOTH);
    if (status == 0) { status = closesocket(sock); }
#else
    status = shutdown(sock, SHUT_RDWR);
    if (status == 0) { status = close(sock); }
#endif
    return status;
}


#if(defined(_WIN32) || defined(WIN32))
#include <windows.h>
#define mysleep(x) Sleep((x))
#else
#include <unistd.h>
#define mysleep(x) usleep((x)*1000)
#endif

#endif

netserver.cpp

#define _GLIBCXX_USE_CXX11_ABI 0
#undef _GLIBCXX_DEBUG
#include "../mynet.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <pthread.h>

using namespace cv;
Mat frame(120, 160, CV_8UC3);;
pthread_mutex_t mutex;
pthread_t thread;

void *myfunc(void *threadid)
{
    int n;
    int listenfd = 0,connfd = 0;
    struct sockaddr_in serv_addr;
    unsigned char sendBuff[160*120*3];
    Mat hereframe;

    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    printf("socket retrieve success\n");

    memset(&serv_addr, '0', sizeof(serv_addr));
    memset(sendBuff, '0', sizeof(sendBuff));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(5000);
    bind(listenfd, (struct sockaddr*)&serv_addr,sizeof(serv_addr));
    if(listen(listenfd, 10) == -1)
    {
        printf("Failed to listen\n");
    }
    else
    {
        connfd = accept(listenfd, (struct sockaddr*)NULL,NULL);  // accept awaiting request
        if(connfd<=0)  printf("Something went wrong with write()! %s\n", strerror(errno));
        else
        {
            while(1)
            {
                printf("Got client...\n");
                pthread_mutex_lock (&mutex);
                printf("Copying data...\n");
                frame.copyTo(hereframe);
                pthread_mutex_unlock (&mutex);
                printf("Hereframe size: %dX%d\n", hereframe.rows, hereframe.cols);
                memcpy(sendBuff, hereframe.data, 120*160*3);
                printf("Sending data...\n");
                n = send(connfd, (char*)sendBuff, 120*160*3,0);
                if(n<0)  printf("Something went wrong with write()! %s\n", strerror(errno));
                printf("Closing client after writing %d bytes...\n", n);
                printf("Closed...\n");
                mysleep(40);
                printf("Restartng data...\n");
            }
            sockClose(connfd);
        }
    }
    sockQuit();

    pthread_exit(NULL);
}

int main(void)
{
    //cvNamedWindow("Sisplay", CV_WINDOW_AUTOSIZE);
    sockInit();
    pthread_mutex_init(&mutex,NULL);
    VideoCapture cap;
    Mat hereframe1;
    cap.open(0);
    cap.set( CV_CAP_PROP_FRAME_WIDTH, 160 );
    cap.set( CV_CAP_PROP_FRAME_HEIGHT, 120 );

    if( !cap.isOpened()) printf("Fukced up\n");
    int rc;
    long t;
    rc = pthread_create(&thread, NULL, myfunc, (void *)t);
    if (rc)
    {
        printf("ERROR; return code from pthread_create() is %d\n", rc);
        exit(-1);
    }

    for(;;)
    {
        cap >> hereframe1;
        //     printf("Video size: %dX%d\n", hereframe1.rows, hereframe1.cols);

        pthread_mutex_lock(&mutex);
        hereframe1.copyTo(frame); /* hangs here*/
        pthread_mutex_unlock(&mutex);
        // cvtColor(frame, gray, CV_BGR2GRAY);

        Scalar tempVal = mean(hereframe1);
        //  printf("Mean = %f\n", tempVal.val[0]);
        mysleep(30);
        //if(waitKey(30)=='q') break;
        // std::swap(prevgray, gray);
    }
    char *b;
    pthread_join(thread,(void**)&b);
    return 0;
}


Client code

receiver.cpp

#define _GLIBCXX_USE_CXX11_ABI 0
#include "../mynet.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>

using namespace cv;

int main(int argc, char *argv[])
{
    int sockfd = 0,n = 0;
    unsigned char recvBuff[120*160*3];
    struct sockaddr_in serv_addr;
    sockInit();
    memset(recvBuff, '0',sizeof(recvBuff));
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0))< 0)
    {
        printf("\n Error : Could not create socket \n");
        return 1;
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(5000);
    serv_addr.sin_addr.s_addr = inet_addr(argv[1]);

    if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))<0)
    {
        printf("\n Error : Connect Failed \n");
        return 1;
    }
    printf("Connected to server...\n");
    Mat frame(120, 160, CV_8UC3);
    int csz = 0;
    cvNamedWindow("Display", CV_WINDOW_AUTOSIZE);
    printf("OK here 0\n");
    for(;;)
    {
        csz = 0;
        while((n = recv(sockfd, (char*)recvBuff, sizeof(recvBuff), 0)) > 0)
        {
            printf("OK here 2\n");

            printf("Read %d bytes...\n", n);
            csz += n;
            if(csz<=120*160*3)
            {
                memcpy(frame.data+(csz-n), recvBuff, n);
            }
            if(csz>= 120*160*3) break;
        }
        printf("OK here 3\n");

        printf("Got data of size %d bytes...\n", csz);
        imshow("Display", frame);
        if(csz < 120*160*3)
        {
            printf("\n Read Error \n");
        }
        if(waitKey(30)=='q') break;
        // std::swap(prevgray, gray);
    }
    sockClose(sockfd);

    sockQuit();
    return 0;
}


Click here view more answers http://ift.tt/1Ivhb6k