Loading src/video.cpp +83 −47 Original line number Diff line number Diff line /** * @file FILENAME * @brief BRIEF DESCRIPTION * @copyright Copyright (C) YEAR Elphel Inc. * @file video.cpp * @brief Provides video interface for streamer * @copyright Copyright (C) 2017 Elphel Inc. * @author AUTHOR <EMAIL> * * @par License: Loading @@ -28,19 +28,21 @@ #include <arpa/inet.h> #include <fcntl.h> #include <unistd.h> #include <asm/elphel/c313a.h> #include <iostream> #include <sstream> #include <string> #include <elphel/x393_devices.h> #include "streamer.h" using namespace std; #undef VIDEO_DEBUG #undef VIDEO_DEBUG_2 // for timestamp monitoring #undef VIDEO_DEBUG_3 // for FPS monitoring //#define VIDEO_DEBUG //#define VIDEO_DEBUG_2 // for timestamp monitoring //#define VIDEO_DEBUG_3 // for FPS monitoring //#undef VIDEO_DEBUG //#undef VIDEO_DEBUG_2 // for timestamp monitoring //#undef VIDEO_DEBUG_3 // for FPS monitoring #define VIDEO_DEBUG #define VIDEO_DEBUG_2 // for timestamp monitoring #define VIDEO_DEBUG_3 // for FPS monitoring #ifdef VIDEO_DEBUG #define D(a) a Loading @@ -64,8 +66,8 @@ using namespace std; #define QTABLES_INCLUDE int fd_circbuf = 0; int fd_jpeghead = 0; /// to get quantization tables //int fd_circbuf = 0; //int fd_jpeghead = 0; /// to get quantization tables //int fd_fparmsall = 0; int lastDaemonBit = DAEMON_BIT_STREAMER; Loading @@ -73,23 +75,50 @@ int lastDaemonBit = DAEMON_BIT_STREAMER; //struct framepars_t *framePars; //unsigned long *globalPars; /// parameters that are not frame-related, their changes do not initiate any actions Video::Video(void) { D( cerr << "Video::Video()" << endl;) static const char *circbuf_file_names[] = { DEV393_PATH(DEV393_CIRCBUF0), DEV393_PATH(DEV393_CIRCBUF1), DEV393_PATH(DEV393_CIRCBUF2), DEV393_PATH(DEV393_CIRCBUF3) }; static const char *jhead_file_names[] = { DEV393_PATH(DEV393_JPEGHEAD0), DEV393_PATH(DEV393_JPEGHEAD1), DEV393_PATH(DEV393_JPEGHEAD2), DEV393_PATH(DEV393_JPEGHEAD3) }; Video::Video(int port, Parameters *pars) { string err_msg; D( cerr << "Video::Video() on port " << port << endl;) D( cerr << __FILE__<< ":"<< __FUNCTION__ << ":" <<__LINE__ << endl;) params = pars; sensor_port = port; stream_name = "video"; params = Parameters::instance(); // params = Parameters::instance(); waitDaemonEnabled(-1); /// <0 - use default fd_circbuf = open("/dev/circbuf", O_RDONLY); if(fd_circbuf < 0) throw("can't open /dev/circbuf"); fd_circbuf = open(circbuf_file_names[sensor_port], O_RDONLY); if (fd_circbuf < 0) { err_msg = "can't open " + static_cast<ostringstream &>(ostringstream() << dec << sensor_port).str(); throw runtime_error(err_msg); } buffer_length = lseek(fd_circbuf, 0, SEEK_END); /// mmap for all the lifetime of the program, not per stream. AF buffer_ptr = (unsigned long *) mmap(0, buffer_length, PROT_READ, MAP_SHARED, fd_circbuf, 0); if((int)buffer_ptr == -1) throw("Error in mmap /dev/circbuf"); buffer_ptr_s = (unsigned long *)mmap(buffer_ptr + (buffer_length >>2 ), buffer_length, PROT_READ, MAP_FIXED | MAP_SHARED, fd_circbuf, 0); /// preventing buffer rollovers if((int)buffer_ptr_s == -1) throw("Error in second mmap /dev/circbuf"); if ((int) buffer_ptr == -1) { err_msg = "can't mmap " + *circbuf_file_names[sensor_port]; throw runtime_error(err_msg); } cout << "<-- 1" << endl; // buffer_ptr_s = (unsigned long *) mmap(buffer_ptr + (buffer_length >> 2), buffer_length, // PROT_READ, MAP_FIXED | MAP_SHARED, fd_circbuf, 0); /// preventing buffer rollovers buffer_ptr_s = (unsigned long *) mmap(buffer_ptr + (buffer_length >> 2), 100 * 4096, PROT_READ, MAP_FIXED | MAP_SHARED, fd_circbuf, 0); /// preventing buffer rollovers cout << "<-- 2" << endl; if ((int) buffer_ptr_s == -1) { err_msg = "can't create second mmap for " + *circbuf_file_names[sensor_port]; throw runtime_error(err_msg); } cout << "<-- 3" << endl; /// Skip several frames if it is just booted /// May get stuck here if compressor is off, it should be enabled externally D( cerr << __FILE__<< ":"<< __FUNCTION__ << ":" <<__LINE__ << " frame=" << params->getGPValue(G_THIS_FRAME) << " buffer_length=" << buffer_length << endl;) Loading @@ -101,9 +130,11 @@ D( cerr << __FILE__<< ":"<< __FUNCTION__ << ":" <<__LINE__ << " frame=" << para lseek(fd_circbuf, LSEEK_CIRC_WAIT, SEEK_END); lseek(fd_circbuf, LSEEK_CIRC_WAIT, SEEK_END); D(cerr << __FILE__<< ":"<< __FUNCTION__ << ":" <<__LINE__ << " frame=" << params->getGPValue(G_THIS_FRAME) << " buffer_length=" << buffer_length <<endl;) fd_jpeghead = open("/dev/jpeghead", O_RDWR); if(fd_jpeghead < 0) throw("can't open /dev/jpeghead"); fd_jpeghead = open(jhead_file_names[sensor_port], O_RDWR); if (fd_jpeghead < 0) { err_msg = "can't open " + *jhead_file_names[sensor_port]; throw runtime_error(err_msg); } qtables_include = true; SSRC = 12; Loading @@ -112,7 +143,6 @@ D( cerr << __FILE__<< ":"<< __FUNCTION__ << ":" <<__LINE__ << " frame=" << para rtcp_socket = NULL; _play = false; prev_jpeg_wp = 0; // buffer_length = 0; f_quality = -1; // create thread... Loading @@ -121,7 +151,15 @@ D( cerr << __FILE__<< ":" << __FUNCTION__ << ":" << __LINE__ << endl;) } Video::~Video(void) { cerr << "Video::~Video()" << endl; cerr << "Video::~Video() on port " << sensor_port << endl; if (buffer_ptr != NULL) { munmap(buffer_ptr, buffer_length); buffer_ptr = NULL; } if (buffer_ptr_s != NULL) { munmap(buffer_ptr_s, buffer_length); buffer_ptr_s = NULL; } if (fd_circbuf > 0) close(fd_circbuf); if (fd_jpeghead > 0) Loading Loading @@ -188,7 +226,7 @@ bool Video::waitDaemonEnabled(int daemonBit) { // <0 - use default unsigned long this_frame = params->getGPValue(G_THIS_FRAME); /// No semaphors, so it is possible to miss event and wait until the streamer will be re-enabled before sending message, /// but it seems not so terrible D(cerr << " lseek(fd_circbuf, LSEEK_DAEMON_CIRCBUF+lastDaemonBit, SEEK_END)... " << endl;) D(cerr << " lseek(fd_circbuf" << fd_circbuf << ", LSEEK_DAEMON_CIRCBUF+lastDaemonBit, SEEK_END)... " << endl;) lseek(fd_circbuf, LSEEK_DAEMON_CIRCBUF + lastDaemonBit, SEEK_END); /// D(cerr << "...done" << endl;) Loading Loading @@ -322,8 +360,6 @@ D3(cerr << "delta == " << _f << endl << endl;) return video_desc; } //#define FRAMES_AHEAD_FPS 3 /// number of frames ahead of current to frite FPS limit //#define FRAMES_SKIP_FPS 3 /// number of frames to wait after target so circbuf will have at least 2 frames with new fps for calculation void Video::fps(float fps) { if(fps < 0.01) return; Loading src/video.h +8 −8 Original line number Diff line number Diff line /** * @file FILENAME * @brief BRIEF DESCRIPTION * @copyright Copyright (C) YEAR Elphel Inc. * @file video.h * @brief Provides video interface for streamer * @copyright Copyright (C) 2017 Elphel Inc. * @author AUTHOR <EMAIL> * * @par License: Loading @@ -28,10 +28,8 @@ using namespace std; #include <asm/elphel/c313a.h> #define FRAMES_AHEAD_FPS 3 /// number of frames ahead of current to frite FPS limit #define FRAMES_SKIP_FPS 3 /// number of frames to wait after target so circbuf will have at least 2 frames with new fps for calculation #define FRAMES_AHEAD_FPS 3 /// number of frames ahead of current to write FPS limit #define FRAMES_SKIP_FPS 3 /// number of frames to wait after target so circbuf will have at least 2 frames with new FPS for calculation /// structure to store current video description struct video_desc_t { Loading @@ -51,7 +49,7 @@ public: SIZE_CHANGE }; Video(void); Video(int port, Parameters *pars); virtual ~Video(void); /// return description of the current frame - i.e. current video parameters Loading Loading @@ -81,6 +79,8 @@ protected: unsigned long *buffer_ptr; unsigned long *buffer_ptr_s; /// Second copy of the circbuf just after the end of the first to prevent rollovers void *frame_ptr; int fd_circbuf; int fd_jpeghead; long capture(void); // bool process(void); Loading Loading
src/video.cpp +83 −47 Original line number Diff line number Diff line /** * @file FILENAME * @brief BRIEF DESCRIPTION * @copyright Copyright (C) YEAR Elphel Inc. * @file video.cpp * @brief Provides video interface for streamer * @copyright Copyright (C) 2017 Elphel Inc. * @author AUTHOR <EMAIL> * * @par License: Loading @@ -28,19 +28,21 @@ #include <arpa/inet.h> #include <fcntl.h> #include <unistd.h> #include <asm/elphel/c313a.h> #include <iostream> #include <sstream> #include <string> #include <elphel/x393_devices.h> #include "streamer.h" using namespace std; #undef VIDEO_DEBUG #undef VIDEO_DEBUG_2 // for timestamp monitoring #undef VIDEO_DEBUG_3 // for FPS monitoring //#define VIDEO_DEBUG //#define VIDEO_DEBUG_2 // for timestamp monitoring //#define VIDEO_DEBUG_3 // for FPS monitoring //#undef VIDEO_DEBUG //#undef VIDEO_DEBUG_2 // for timestamp monitoring //#undef VIDEO_DEBUG_3 // for FPS monitoring #define VIDEO_DEBUG #define VIDEO_DEBUG_2 // for timestamp monitoring #define VIDEO_DEBUG_3 // for FPS monitoring #ifdef VIDEO_DEBUG #define D(a) a Loading @@ -64,8 +66,8 @@ using namespace std; #define QTABLES_INCLUDE int fd_circbuf = 0; int fd_jpeghead = 0; /// to get quantization tables //int fd_circbuf = 0; //int fd_jpeghead = 0; /// to get quantization tables //int fd_fparmsall = 0; int lastDaemonBit = DAEMON_BIT_STREAMER; Loading @@ -73,23 +75,50 @@ int lastDaemonBit = DAEMON_BIT_STREAMER; //struct framepars_t *framePars; //unsigned long *globalPars; /// parameters that are not frame-related, their changes do not initiate any actions Video::Video(void) { D( cerr << "Video::Video()" << endl;) static const char *circbuf_file_names[] = { DEV393_PATH(DEV393_CIRCBUF0), DEV393_PATH(DEV393_CIRCBUF1), DEV393_PATH(DEV393_CIRCBUF2), DEV393_PATH(DEV393_CIRCBUF3) }; static const char *jhead_file_names[] = { DEV393_PATH(DEV393_JPEGHEAD0), DEV393_PATH(DEV393_JPEGHEAD1), DEV393_PATH(DEV393_JPEGHEAD2), DEV393_PATH(DEV393_JPEGHEAD3) }; Video::Video(int port, Parameters *pars) { string err_msg; D( cerr << "Video::Video() on port " << port << endl;) D( cerr << __FILE__<< ":"<< __FUNCTION__ << ":" <<__LINE__ << endl;) params = pars; sensor_port = port; stream_name = "video"; params = Parameters::instance(); // params = Parameters::instance(); waitDaemonEnabled(-1); /// <0 - use default fd_circbuf = open("/dev/circbuf", O_RDONLY); if(fd_circbuf < 0) throw("can't open /dev/circbuf"); fd_circbuf = open(circbuf_file_names[sensor_port], O_RDONLY); if (fd_circbuf < 0) { err_msg = "can't open " + static_cast<ostringstream &>(ostringstream() << dec << sensor_port).str(); throw runtime_error(err_msg); } buffer_length = lseek(fd_circbuf, 0, SEEK_END); /// mmap for all the lifetime of the program, not per stream. AF buffer_ptr = (unsigned long *) mmap(0, buffer_length, PROT_READ, MAP_SHARED, fd_circbuf, 0); if((int)buffer_ptr == -1) throw("Error in mmap /dev/circbuf"); buffer_ptr_s = (unsigned long *)mmap(buffer_ptr + (buffer_length >>2 ), buffer_length, PROT_READ, MAP_FIXED | MAP_SHARED, fd_circbuf, 0); /// preventing buffer rollovers if((int)buffer_ptr_s == -1) throw("Error in second mmap /dev/circbuf"); if ((int) buffer_ptr == -1) { err_msg = "can't mmap " + *circbuf_file_names[sensor_port]; throw runtime_error(err_msg); } cout << "<-- 1" << endl; // buffer_ptr_s = (unsigned long *) mmap(buffer_ptr + (buffer_length >> 2), buffer_length, // PROT_READ, MAP_FIXED | MAP_SHARED, fd_circbuf, 0); /// preventing buffer rollovers buffer_ptr_s = (unsigned long *) mmap(buffer_ptr + (buffer_length >> 2), 100 * 4096, PROT_READ, MAP_FIXED | MAP_SHARED, fd_circbuf, 0); /// preventing buffer rollovers cout << "<-- 2" << endl; if ((int) buffer_ptr_s == -1) { err_msg = "can't create second mmap for " + *circbuf_file_names[sensor_port]; throw runtime_error(err_msg); } cout << "<-- 3" << endl; /// Skip several frames if it is just booted /// May get stuck here if compressor is off, it should be enabled externally D( cerr << __FILE__<< ":"<< __FUNCTION__ << ":" <<__LINE__ << " frame=" << params->getGPValue(G_THIS_FRAME) << " buffer_length=" << buffer_length << endl;) Loading @@ -101,9 +130,11 @@ D( cerr << __FILE__<< ":"<< __FUNCTION__ << ":" <<__LINE__ << " frame=" << para lseek(fd_circbuf, LSEEK_CIRC_WAIT, SEEK_END); lseek(fd_circbuf, LSEEK_CIRC_WAIT, SEEK_END); D(cerr << __FILE__<< ":"<< __FUNCTION__ << ":" <<__LINE__ << " frame=" << params->getGPValue(G_THIS_FRAME) << " buffer_length=" << buffer_length <<endl;) fd_jpeghead = open("/dev/jpeghead", O_RDWR); if(fd_jpeghead < 0) throw("can't open /dev/jpeghead"); fd_jpeghead = open(jhead_file_names[sensor_port], O_RDWR); if (fd_jpeghead < 0) { err_msg = "can't open " + *jhead_file_names[sensor_port]; throw runtime_error(err_msg); } qtables_include = true; SSRC = 12; Loading @@ -112,7 +143,6 @@ D( cerr << __FILE__<< ":"<< __FUNCTION__ << ":" <<__LINE__ << " frame=" << para rtcp_socket = NULL; _play = false; prev_jpeg_wp = 0; // buffer_length = 0; f_quality = -1; // create thread... Loading @@ -121,7 +151,15 @@ D( cerr << __FILE__<< ":" << __FUNCTION__ << ":" << __LINE__ << endl;) } Video::~Video(void) { cerr << "Video::~Video()" << endl; cerr << "Video::~Video() on port " << sensor_port << endl; if (buffer_ptr != NULL) { munmap(buffer_ptr, buffer_length); buffer_ptr = NULL; } if (buffer_ptr_s != NULL) { munmap(buffer_ptr_s, buffer_length); buffer_ptr_s = NULL; } if (fd_circbuf > 0) close(fd_circbuf); if (fd_jpeghead > 0) Loading Loading @@ -188,7 +226,7 @@ bool Video::waitDaemonEnabled(int daemonBit) { // <0 - use default unsigned long this_frame = params->getGPValue(G_THIS_FRAME); /// No semaphors, so it is possible to miss event and wait until the streamer will be re-enabled before sending message, /// but it seems not so terrible D(cerr << " lseek(fd_circbuf, LSEEK_DAEMON_CIRCBUF+lastDaemonBit, SEEK_END)... " << endl;) D(cerr << " lseek(fd_circbuf" << fd_circbuf << ", LSEEK_DAEMON_CIRCBUF+lastDaemonBit, SEEK_END)... " << endl;) lseek(fd_circbuf, LSEEK_DAEMON_CIRCBUF + lastDaemonBit, SEEK_END); /// D(cerr << "...done" << endl;) Loading Loading @@ -322,8 +360,6 @@ D3(cerr << "delta == " << _f << endl << endl;) return video_desc; } //#define FRAMES_AHEAD_FPS 3 /// number of frames ahead of current to frite FPS limit //#define FRAMES_SKIP_FPS 3 /// number of frames to wait after target so circbuf will have at least 2 frames with new fps for calculation void Video::fps(float fps) { if(fps < 0.01) return; Loading
src/video.h +8 −8 Original line number Diff line number Diff line /** * @file FILENAME * @brief BRIEF DESCRIPTION * @copyright Copyright (C) YEAR Elphel Inc. * @file video.h * @brief Provides video interface for streamer * @copyright Copyright (C) 2017 Elphel Inc. * @author AUTHOR <EMAIL> * * @par License: Loading @@ -28,10 +28,8 @@ using namespace std; #include <asm/elphel/c313a.h> #define FRAMES_AHEAD_FPS 3 /// number of frames ahead of current to frite FPS limit #define FRAMES_SKIP_FPS 3 /// number of frames to wait after target so circbuf will have at least 2 frames with new fps for calculation #define FRAMES_AHEAD_FPS 3 /// number of frames ahead of current to write FPS limit #define FRAMES_SKIP_FPS 3 /// number of frames to wait after target so circbuf will have at least 2 frames with new FPS for calculation /// structure to store current video description struct video_desc_t { Loading @@ -51,7 +49,7 @@ public: SIZE_CHANGE }; Video(void); Video(int port, Parameters *pars); virtual ~Video(void); /// return description of the current frame - i.e. current video parameters Loading Loading @@ -81,6 +79,8 @@ protected: unsigned long *buffer_ptr; unsigned long *buffer_ptr_s; /// Second copy of the circbuf just after the end of the first to prevent rollovers void *frame_ptr; int fd_circbuf; int fd_jpeghead; long capture(void); // bool process(void); Loading