Commit fe15d689 authored by Andrey Filippov's avatar Andrey Filippov

added single write thread option

parent 67643efd
...@@ -364,16 +364,16 @@ int camogm_start(camogm_state *state, bool restart) ...@@ -364,16 +364,16 @@ int camogm_start(camogm_state *state, bool restart)
next_state_path(state); // increment path so next time will use different one. next_state_path(state); // increment path so next time will use different one.
} else { } else {
if (state->prog_state == STATE_STARTING) { if (state->prog_state == STATE_STARTING) {
D1(fprintf(debug_file, "Continue starting, state->path='%s'\n", state->path)); D0(fprintf(debug_file, "Continue starting, state->path='%s'\n", state->path));
D1(syslog (LOG_INFO, "Continue starting, state->path='%s'\n", state->path)); D0(syslog (LOG_INFO, "Continue starting, state->path='%s'\n", state->path));
} else { } else {
D1(fprintf(debug_file, "Re-starting raw data recording, using the same state file, next will be %s, state->path='%s'\n", get_state_path(state), state->path)); D0(fprintf(debug_file, "Re-starting raw data recording, using the same state file, next will be %s, state->path='%s'\n", get_state_path(state), state->path));
D1(syslog (LOG_INFO, "Re-starting raw data recording, next will be %s", get_state_path(state))); D0(syslog (LOG_INFO, "Re-starting raw data recording, next will be %s", get_state_path(state)));
} }
} }
} else { } else {
D1(fprintf(debug_file, "Starting file system recording to %s\n", state->path)); D0(fprintf(debug_file, "Starting file system recording to %s\n", state->path));
D1(syslog (LOG_INFO, "Starting file system recording to %s", state->path)); D0(syslog (LOG_INFO, "Starting file system recording to %s", state->path));
} }
double dtime_stamp; double dtime_stamp;
...@@ -409,14 +409,23 @@ int camogm_start(camogm_state *state, bool restart) ...@@ -409,14 +409,23 @@ int camogm_start(camogm_state *state, bool restart)
pthread_mutex_unlock(&state->mutex); pthread_mutex_unlock(&state->mutex);
D6(fprintf(debug_file, "Starting recording-1\n")); D6(fprintf(debug_file, "Starting recording-1\n"));
#ifdef MIN_USED_SIZE #ifdef MIN_USED_SIZE
state->greedy = 1; state->greedy = 1; // not used
#endif #endif
FOR_EACH_PORT(int, chn) { FOR_EACH_PORT(int, chn) {
if (is_chn_active(state, chn)) { if (is_chn_active(state, chn)) {
// Check/set circbuf read pointer // Check/set circbuf read pointer
D3(fprintf(debug_file, "1: state->cirbuf_rp=0x%x\n", state->cirbuf_rp[chn])); D3(fprintf(debug_file, "1: state->cirbuf_rp=0x%x\n", state->cirbuf_rp[chn]));
D3(fprintf(debug_file, "1a: compressed frame number = %li\n", lseek(state->fd_circ[chn], LSEEK_CIRC_GETFRAME, SEEK_END))); D3(fprintf(debug_file, "1a: compressed frame number = %li\n", lseek(state->fd_circ[chn], LSEEK_CIRC_GETFRAME, SEEK_END)));
if ((state->cirbuf_rp[chn] < 0) || (lseek(state->fd_circ[chn], state->cirbuf_rp[chn], SEEK_SET) < 0) || (lseek(state->fd_circ[chn], LSEEK_CIRC_VALID, SEEK_END) < 0 )) { D3(fprintf(debug_file, "1a: compressed frame number = %li\n", lseek(state->fd_circ[chn], LSEEK_CIRC_GETFRAME, SEEK_END)));
if ( (restart) || // restart - always flush buffer (will loose frames, but not continue broken frames)
(state->cirbuf_rp[chn] < 0) ||
(lseek(state->fd_circ[chn], state->cirbuf_rp[chn], SEEK_SET) < 0) ||
(lseek(state->fd_circ[chn], LSEEK_CIRC_VALID, SEEK_END) < 0 )) {
D0(fprintf(debug_file, "Flushing buffer and rebuilding new\n"));
D0(syslog (LOG_INFO, "Flushing buffer and rebuilding new"));
// reset bufer
D3(fprintf(debug_file, "2: state->cirbuf_rp=0x%x\n", state->cirbuf_rp[chn])); D3(fprintf(debug_file, "2: state->cirbuf_rp=0x%x\n", state->cirbuf_rp[chn]));
/* In "greedy" mode try to save as many frames from the circbuf as possible */ /* In "greedy" mode try to save as many frames from the circbuf as possible */
// state->cirbuf_rp[chn] = lseek(state->fd_circ[chn], state->greedy ? LSEEK_CIRC_SCND : LSEEK_CIRC_LAST, SEEK_END); // state->cirbuf_rp[chn] = lseek(state->fd_circ[chn], state->greedy ? LSEEK_CIRC_SCND : LSEEK_CIRC_LAST, SEEK_END);
...@@ -442,13 +451,17 @@ int camogm_start(camogm_state *state, bool restart) ...@@ -442,13 +451,17 @@ int camogm_start(camogm_state *state, bool restart)
// file pointer here should match state->rp; so no need to do lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET); // file pointer here should match state->rp; so no need to do lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET);
state->buf_min[chn] = getGPValue(chn, G_FREECIRCBUF); state->buf_min[chn] = getGPValue(chn, G_FREECIRCBUF);
#endif #endif
} else { } else { // reuse the same buffer
#if ERRORS_FROM_START == 0 #if ERRORS_FROM_START == 0
if (state->buf_min[chn] > getGPValue(chn, G_FREECIRCBUF)) { if (state->buf_min[chn] > getGPValue(chn, G_FREECIRCBUF)) {
state->buf_min[chn] = getGPValue(chn, G_FREECIRCBUF); state->buf_min[chn] = getGPValue(chn, G_FREECIRCBUF);
} }
#endif #endif
} }
lseek(state->fd_circ[chn], state->cirbuf_rp[chn], SEEK_SET); // just in case - restore pointer
#if ERRORS_FROM_START #if ERRORS_FROM_START
if (!restart) { // only reset errors and minimal buffer size during slient-initiated start (not after buffer overrun) if (!restart) { // only reset errors and minimal buffer size during slient-initiated start (not after buffer overrun)
state->buf_mmin = state->circ_buff_size[0] - MIN_USED_SIZE;; state->buf_mmin = state->circ_buff_size[0] - MIN_USED_SIZE;;
...@@ -464,6 +477,8 @@ int camogm_start(camogm_state *state, bool restart) ...@@ -464,6 +477,8 @@ int camogm_start(camogm_state *state, bool restart)
} else { // restart only after buffer overrun } else { // restart only after buffer overrun
if (state->prog_state != STATE_STARTING) { // during STATE_STARTING it continuously gets here if if (state->prog_state != STATE_STARTING) { // during STATE_STARTING it continuously gets here if
state->error_restarts ++; state->error_restarts ++;
D0(fprintf(debug_file, "Incremented restart errors = %d\n", state->error_restarts));
D0(syslog (LOG_INFO, "Incremented restart errors = %d", state->error_restarts));
} }
} }
#endif #endif
...@@ -906,7 +921,7 @@ int camogm_stop(camogm_state *state) ...@@ -906,7 +921,7 @@ int camogm_stop(camogm_state *state)
{ {
int rslt = 0; int rslt = 0;
if (state->prog_state != STATE_RUNNING) { if ((state->prog_state != STATE_RUNNING) && (state->prog_state != STATE_RESTARTING)) {
if (state->prog_state != STATE_STARTING) { if (state->prog_state != STATE_STARTING) {
D2(fprintf(debug_file, "Recording was not running, nothing to stop\n")); D2(fprintf(debug_file, "Recording was not running, nothing to stop\n"));
} else { } else {
...@@ -918,6 +933,8 @@ int camogm_stop(camogm_state *state) ...@@ -918,6 +933,8 @@ int camogm_stop(camogm_state *state)
return 0; return 0;
} }
D1(fprintf(debug_file, "Ending recording\n")); D1(fprintf(debug_file, "Ending recording\n"));
D0(syslog (LOG_INFO,"%s:line %d - Ending recording, state = %d", __FILE__, __LINE__, state->prog_state));
if (state->kml_used) camogm_end_kml(state); if (state->kml_used) camogm_end_kml(state);
switch (state->format) { switch (state->format) {
case CAMOGM_FORMAT_NONE: rslt = 0; break; case CAMOGM_FORMAT_NONE: rslt = 0; break;
...@@ -932,7 +949,9 @@ int camogm_stop(camogm_state *state) ...@@ -932,7 +949,9 @@ int camogm_stop(camogm_state *state)
if (rslt) return rslt; if (rslt) return rslt;
state->last = 1; state->last = 1;
pthread_mutex_lock(&state->mutex); pthread_mutex_lock(&state->mutex);
state->prog_state = STATE_STOPPED; if (state->prog_state != STATE_RESTARTING) {
state->prog_state = STATE_STOPPED;
}
pthread_mutex_unlock(&state->mutex); pthread_mutex_unlock(&state->mutex);
D1(fprintf(debug_file, "Ended recording\n")); D1(fprintf(debug_file, "Ended recording\n"));
DFLUSH; DFLUSH;
...@@ -1894,6 +1913,7 @@ int listener_loop(camogm_state *state) ...@@ -1894,6 +1913,7 @@ int listener_loop(camogm_state *state)
state->writer_params.circbuf_many = false; // will be set when main (preparing) thread is ahead of the writer threads by more than NUM_NEED_NEMPTY state->writer_params.circbuf_many = false; // will be set when main (preparing) thread is ahead of the writer threads by more than NUM_NEED_NEMPTY
if ((rslt=get_write_page(&state->writer_params) > 0)) { // still some prepared pages left if ((rslt=get_write_page(&state->writer_params) > 0)) { // still some prepared pages left
pthread_cond_signal(&state->writer_params.writer_cond); // wake up other writer threads? pthread_cond_signal(&state->writer_params.writer_cond); // wake up other writer threads?
#if NUM_WRITER_THREADS > 1
D3(fprintf(debug_file, "listener_loop(): some prepared pages remain (%d)[%d%d:%d%d] MANY=%d EMPTY=%d BUSY=%d [%d%d%d%d%d%d%d%d], SIGNALLED @ %07d\n",\ D3(fprintf(debug_file, "listener_loop(): some prepared pages remain (%d)[%d%d:%d%d] MANY=%d EMPTY=%d BUSY=%d [%d%d%d%d%d%d%d%d], SIGNALLED @ %07d\n",\
rslt, \ rslt, \
state->writer_params.writev_run[0],state->writer_params.writev_run[1], \ state->writer_params.writev_run[0],state->writer_params.writev_run[1], \
...@@ -1902,6 +1922,16 @@ int listener_loop(camogm_state *state) ...@@ -1902,6 +1922,16 @@ int listener_loop(camogm_state *state)
state->writer_params.chunk_page_state[0],state->writer_params.chunk_page_state[1],state->writer_params.chunk_page_state[2],state->writer_params.chunk_page_state[3], \ state->writer_params.chunk_page_state[0],state->writer_params.chunk_page_state[1],state->writer_params.chunk_page_state[2],state->writer_params.chunk_page_state[3], \
state->writer_params.chunk_page_state[4],state->writer_params.chunk_page_state[5],state->writer_params.chunk_page_state[6],state->writer_params.chunk_page_state[7], \ state->writer_params.chunk_page_state[4],state->writer_params.chunk_page_state[5],state->writer_params.chunk_page_state[6],state->writer_params.chunk_page_state[7], \
get_fpga_usec(state->fd_fparmsall[0], 0))); get_fpga_usec(state->fd_fparmsall[0], 0)));
#else
D3(fprintf(debug_file, "listener_loop(): some prepared pages remain (%d)[%d:%d] MANY=%d EMPTY=%d BUSY=%d [%d%d%d%d%d%d%d%d], SIGNALLED @ %07d\n",\
rslt, \
state->writer_params.writev_run[0], \
state->writer_params.write_waits_sig[0], \
state->writer_params.circbuf_many, get_num_empty(&state->writer_params), get_num_busy(&state->writer_params), \
state->writer_params.chunk_page_state[0],state->writer_params.chunk_page_state[1],state->writer_params.chunk_page_state[2],state->writer_params.chunk_page_state[3], \
state->writer_params.chunk_page_state[4],state->writer_params.chunk_page_state[5],state->writer_params.chunk_page_state[6],state->writer_params.chunk_page_state[7], \
get_fpga_usec(state->fd_fparmsall[0], 0)));
#endif
} }
pthread_mutex_unlock(&state->writer_params.writer_mutex); pthread_mutex_unlock(&state->writer_params.writer_mutex);
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include <syslog.h> #include <syslog.h>
#include <malloc.h> // debugging #include <malloc.h> // debugging
#define NUM_WRITER_THREADS 2 #define NUM_WRITER_THREADS 1+0 // 2
#define NUM_NEED_EMPTY (NUM_WRITER_THREADS + 1) // run main thread to prepage more pages if >= empty #define NUM_NEED_EMPTY (NUM_WRITER_THREADS + 1) // run main thread to prepage more pages if >= empty
#define NUM_NEED_NEMPTY (NUM_WRITER_THREADS + 0) // wake up main thread if there are at least this number of empty pages #define NUM_NEED_NEMPTY (NUM_WRITER_THREADS + 0) // wake up main thread if there are at least this number of empty pages
#define NUM_FREE_MANY (NUM_WRITER_THREADS + 1) // Set many if get_num_empty() < NUM_FREE_MANY #define NUM_FREE_MANY (NUM_WRITER_THREADS + 1) // Set many if get_num_empty() < NUM_FREE_MANY
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
#define CAMOGM_FORMAT_OGM 1 ///< output as Ogg Media file #define CAMOGM_FORMAT_OGM 1 ///< output as Ogg Media file
#define CAMOGM_FORMAT_JPEG 2 ///< output as individual JPEG files #define CAMOGM_FORMAT_JPEG 2 ///< output as individual JPEG files
#define CAMOGM_FORMAT_MOV 3 ///< output as Apple Quicktime #define CAMOGM_FORMAT_MOV 3 ///< output as Apple Quicktime
#define CAMOGM_MIN_BUF_FRAMES 2 ///< buffer should accomodate at list this number of frames #define CAMOGM_MIN_BUF_FRAMES 4 ///< buffer should accommodate at least this number of frames
#define FLUSH_DEBUG 1 ///< flush debug file after each print #define FLUSH_DEBUG 1 ///< flush debug file after each print
#define USE_OGG_PACKET_TYPE 0 /// do not prepend image with packet type, such as PACKET_IS_SYNCPOINT #define USE_OGG_PACKET_TYPE 0 /// do not prepend image with packet type, such as PACKET_IS_SYNCPOINT
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment