0

I want to send a stream of video frames using a webcam from a parent process to child process through a named pipe.The parent displays the sent frames while the child displays the received frames.I am using openCV 2.4.12 for accessing and displaying video frames on UBuntu 14.04.However, it only sends one frame and freezes.I cannot figure out what's causing the problem.This code works perfectly fine if I send a single image but freezes on the first frame when I try to send a stream.

Here's the code:

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
using namespace cv;
using namespace std;


void  ChildProcess(void);                /* child process prototype  */
void  ParentProcess(void);               /* parent process prototype */

int  main()
 {

 pid_t  pid;

 pid = fork();
 if (pid == 0)
      ChildProcess();
 else
    ParentProcess();

 }

void  ChildProcess(void)
{

int fd2 = open("/home/eelab/vidpipe",O_RDONLY);

for(;;)
{
int rows = 480;
int cols = 640;
int nchan = 3;
int totalbytes = rows*cols*nchan;
int buflen = cols*nchan;
int ret;
//int fd1 = open("/dev/xillybus_read_32",O_RDONLY);

uchar buf[buflen];
uchar datarray[totalbytes];
Mat img(rows,cols,CV_8UC3);

int j;
int k = 0;
int num = totalbytes/buflen;
int bread = 0;
while(bread<totalbytes)
{

    ret=read(fd2,buf,buflen);
    for ( j = 0 ; j<= (ret-1);j++ )
    {
        datarray[j+k] = buf[j];

    }
        k = k+ret;
    bread = bread+ret;
}

img.data = datarray;

namedWindow( "Received image", WINDOW_AUTOSIZE );
imshow( "Received image", img );
waitKey(0);
}
close(fd2);
}

void  ParentProcess(void)
{

int check;
int fd;
int totalbytes;
int buflen;
int count = 0;
fd = open("/home/eelab/vidpipe",O_WRONLY);
if (fd < 1)
{
    perror("open error");
}

VideoCapture cap(0);

for(;;)
{
    Mat frame;
    cap >> frame;


totalbytes = frame.total()*frame.elemSize();
buflen = (frame.cols*3);

uchar *framepointer = frame.data;



 int bwritten = 0;
 int ret;
 uchar* buf;
 buf = framepointer;
 int num = totalbytes/buflen;
 while(bwritten<totalbytes)
 {
   ret = write(fd,buf,buflen);
   write(fd,NULL,0);
   buf = buf + ret;
   bwritten = bwritten+ret;
  }



    namedWindow( "Sent image", WINDOW_AUTOSIZE );
    imshow( "Sent image", frame );
    waitKey(0);

  }

  close(fd);

  }    

Please help, how can I get a continuous stream?

userXktape
  • 227
  • 3
  • 5
  • 15
  • did you try changing `waitKey(0);` to `waitKey(1);` so that there is no keypress needed to proceed? – Micka Jul 18 '16 at 08:38
  • 1
    Yea this works!! Thanks a lot. – userXktape Jul 18 '16 at 08:52
  • the `fork()` function has three possible returned values: <0 : an error occured ==0 : child process >0 parent process.. The posted code is not handling the returned value from `fork()` correctly. – user3629249 Jul 19 '16 at 21:02
  • for ease of readability and understanding: 1) consistently indent the code. indent after every opening brace '{'. un-indent before every closing brace '}'. (suggest using 4 spaces for each indent level, NEVER use tabs for indenting) 2) separate code blocks (for, if, else, while, do...while, switch, case, default) via a blank line (not no separation and not some random number of blank lines – user3629249 Jul 19 '16 at 21:04
  • the code needs to use the 'mkfifo()` function, to create a named pipe, before opening it. And to avoid later problems. – user3629249 Jul 19 '16 at 21:14
  • a pipe does not know anything about records, fields, nor any other structure, To a pipe, it is just a stream of bytes. so in the loop that is reading the pipe, the number of bytes requested must be reduced to only the number of bytes still to be read for the specific video frame. – user3629249 Jul 19 '16 at 21:15
  • the posted code contains several 'magic' numbers. A 'magic' number is a number with no basis. 'magic' numbers make the code much more difficult to understand, debug, maintain. (3, 480,640) Strongly suggest using a `enum` statement or `#define` statements to give those 'magic' numbers meaningful names. – user3629249 Jul 19 '16 at 21:19
  • It seems the code is expecting a video image of 480 pixels by 640 rows of pixels. However, (usually) a pixel is a multi byte entity, typically of 3 or 4 bytes per pixel. Since you mention `video` rather than `image` the code should be expecting the leading and trailing bytes of each row, and the leading and trailing rows of each frame. However, the 'parentProcess()` is never actually capturing any video frames. – user3629249 Jul 19 '16 at 21:25
  • what is the function: `waitKey()` expected to do? – user3629249 Jul 19 '16 at 21:27
  • regarding this line: `perror("open error");` After the call to `perror()` the code should be cleaning up, waiting on the child process, then exiting. After all, if the pipe/fifo failed to open there is absolutely no reason to be trying to write anything to it. – user3629249 Jul 19 '16 at 21:29
  • the two statements: `using namespace cv;` and `using namespace std;` are not part of the C programming language (they are part of the C++ programming language) the `iostream` is a C++ header file, the rest of the header files are a mix of C and C++ headers. SO, 1) this is not a C program, so the `c` tag should be removed 2) removed the `#include statements for those header files that are ONLY for C programs – user3629249 Jul 19 '16 at 21:38
  • When compiling, always enable all the warnings, then fix those warnings. – user3629249 Jul 19 '16 at 21:39

1 Answers1

1

waitKey(0); will block the process until a key is pressed. If you change to waitKey(1); it will proceed automatically after >= 1 ms. If that's not fast enough (e.g. your fps is very high) you should switch to a different GUI library (Qt for example).

Micka
  • 19,585
  • 4
  • 56
  • 74