Commit 31d89b53 authored by Mikhail Karpenko's avatar Mikhail Karpenko

Add basic multichannel support

All functions except a pointer to state struct, but process fork is not
added yet. Code compiles but has not been tested yet.
parent 786c0e75
...@@ -112,6 +112,7 @@ ...@@ -112,6 +112,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <linux/limits.h>
//#include <ctype.h> //#include <ctype.h>
//#include <getopt.h> //#include <getopt.h>
#include <time.h> #include <time.h>
...@@ -135,23 +136,39 @@ ...@@ -135,23 +136,39 @@
#include "camogm_kml.h" #include "camogm_kml.h"
#include "camogm.h" #include "camogm.h"
#define TRAILER_SIZE 0x02 /* debug code follows */
#define MAP_OPTIONS MAP_FILE | MAP_PRIVATE // this will be defined in c313a.h
#define SENSOR_PORTS 4
char trailer[TRAILER_SIZE] = { 0xff, 0xd9 }; #undef GLOBALPARS
#define GLOBALPARS(p, x) (globalPars[(p)][(x)-FRAMEPAR_GLOBALS])
const char ExifFileName[] = "/dev/exif_exif"; /* end of debug code */
const char HeadFileName[] = "/dev/jpeghead"; #define TRAILER_SIZE 0x02
const char ctlFileName[] = "/dev/frameparsall"; #define MAP_OPTIONS MAP_FILE | MAP_PRIVATE
unsigned long * ccam_dma_buf; /* mmapped array */
int lastDaemonBit = DAEMON_BIT_CAMOGM; char trailer[TRAILER_SIZE] = { 0xff, 0xd9 };
struct framepars_all_t *frameParsAll;
struct framepars_t *framePars;
unsigned long *globalPars; /// parameters that are not frame-related, their changes do not initiate any actions
int buff_size; const char *exifFileNames[] = { "/dev/exif_exif0", "/dev/exif_exif1",
"/dev/exif_exif2", "/dev/exif_exif3"
};
const char *headFileNames[] = { "/dev/jpeghead0", "/dev/jpeghead1",
"/dev/jpeghead2", "/dev/jpeghead3"
};
const char *ctlFileNames[] = { "/dev/frameparsall0", "/dev/frameparsall1",
"/dev/frameparsall2", "/de/framepars3"
};
const char *circbufFileNames[] = {"/dev/circbuf0", "/dev/circbuf1",
"/dev/circbuf2", "/dev/circbuf3"
};
unsigned long * ccam_dma_buf[SENSOR_PORTS]; /* mmapped array */
int lastDaemonBit[SENSOR_PORTS] = {DAEMON_BIT_CAMOGM};
struct framepars_all_t *frameParsAll[SENSOR_PORTS];
struct framepars_t *framePars[SENSOR_PORTS];
unsigned long *globalPars[SENSOR_PORTS]; /// parameters that are not frame-related, their changes do not initiate any actions
#define DEFAULT_DURATION 60 /*!default segment duration (seconds) */ #define DEFAULT_DURATION 60 /*!default segment duration (seconds) */
#define DEFAULT_LENGTH 100000000 /*!default segment length (B) */ #define DEFAULT_LENGTH 100000000 /*!default segment length (B) */
...@@ -170,46 +187,46 @@ static char cmdbuf[1024]; ...@@ -170,46 +187,46 @@ static char cmdbuf[1024];
static int cmdbufp = 0; // current input pointer in the command buffer (read from pipe) static int cmdbufp = 0; // current input pointer in the command buffer (read from pipe)
static int cmdstrt = 0; // start of the next partial command static int cmdstrt = 0; // start of the next partial command
camogm_state sstate; camogm_state sstate[SENSOR_PORTS];
camogm_state * state; //camogm_state * state;
int debug_level; int debug_level;
FILE* debug_file; FILE* debug_file;
int camogm_init(void); int camogm_init(camogm_state *state, unsigned int port);
int camogm_start(void); int camogm_start(camogm_state *state);
int camogm_stop(void); int camogm_stop(camogm_state *state);
int camogm_reset(void); //! reset circbuf read pointer int camogm_reset(camogm_state *state); //! reset circbuf read pointer
int camogm_debug(const char * fname); int camogm_debug(camogm_state *state, const char *fname);
int camogm_debug_level(int d); int camogm_debug_level(int d);
void camogm_set_segment_duration(int sd); void camogm_set_segment_duration(camogm_state *state, int sd);
void camogm_set_segment_length(int sl); void camogm_set_segment_length(camogm_state *state, int sl);
void camogm_set_greedy(int d); void camogm_set_greedy(camogm_state *state, int d);
void camogm_set_ignore_fps(int d); void camogm_set_ignore_fps(camogm_state *state, int d);
void camogm_set_save_gp(int d); void camogm_set_save_gp(camogm_state *state, int d);
void camogm_set_prefix(const char * p); void camogm_set_prefix(camogm_state *state, const char * p);
void camogm_set_exif(int d); void camogm_set_exif(camogm_state *state, int d);
void camogm_set_timescale(double d); //! set timescale, default=1.0 void camogm_set_timescale(camogm_state *state, double d); //! set timescale, default=1.0
void camogm_set_frames_skip(int d); //! set number of frames to skip, if negative - seconds between frames void camogm_set_frames_skip(camogm_state *state, int d); //! set number of frames to skip, if negative - seconds between frames
void camogm_set_format(int d); void camogm_set_format(camogm_state *state, int d);
void camogm_kml_set_enable(int d); void camogm_kml_set_enable(camogm_state *state, int d);
void camogm_kml_set_horHalfFov(double dd); void camogm_kml_set_horHalfFov(camogm_state *state, double dd);
void camogm_kml_set_vertHalfFov(double dd); void camogm_kml_set_vertHalfFov(camogm_state *state, double dd);
void camogm_kml_set_height_mode(int d); void camogm_kml_set_height_mode(camogm_state *state, int d);
void camogm_kml_set_height(double dd); void camogm_kml_set_height(camogm_state *state, double dd);
void camogm_kml_set_period(int d); void camogm_kml_set_period(camogm_state *state, int d);
void camogm_kml_set_near(double dd); // distance to PhotoOverlay void camogm_kml_set_near(camogm_state *state, double dd); // distance to PhotoOverlay
int parse_cmd(FILE* npipe); int parse_cmd(camogm_state *state, FILE* npipe);
char * getLineFromPipe(FILE* npipe); char * getLineFromPipe(FILE* npipe);
int sendImageFrame(void); int sendImageFrame(camogm_state *state);
void camogm_set_start_after_timestamp(double d); void camogm_set_start_after_timestamp(camogm_state *state, double d);
void camogm_set_max_frames(int d); void camogm_set_max_frames(camogm_state *state, int d);
void camogm_set_frames_per_chunk(int d); void camogm_set_frames_per_chunk(camogm_state *state, int d);
//!====================================================================================================== //!======================================================================================================
...@@ -251,7 +268,7 @@ void put_uint64(void *buf, u_int64_t val) ...@@ -251,7 +268,7 @@ void put_uint64(void *buf, u_int64_t val)
tmp[7] = (val >>= 8) & 0xff; tmp[7] = (val >>= 8) & 0xff;
} }
int camogm_init(void) int camogm_init(camogm_state *state, unsigned int port)
{ {
const char sserial[] = "elp0"; const char sserial[] = "elp0";
int * ipser = (int*)sserial; int * ipser = (int*)sserial;
...@@ -259,24 +276,24 @@ int camogm_init(void) ...@@ -259,24 +276,24 @@ int camogm_init(void)
state->running = 0; // mo state->running = 0; // mo
state->starting = 0; // mo state->starting = 0; // mo
state->vf = NULL; state->vf = NULL;
camogm_set_segment_duration(DEFAULT_DURATION); camogm_set_segment_duration(state, DEFAULT_DURATION);
camogm_set_segment_length(DEFAULT_LENGTH); camogm_set_segment_length(state, DEFAULT_LENGTH);
camogm_set_greedy(DEFAULT_GREEDY); camogm_set_greedy(state, DEFAULT_GREEDY);
camogm_set_ignore_fps(DEFAULT_IGNORE_FPS); camogm_set_ignore_fps(state, DEFAULT_IGNORE_FPS);
camogm_set_max_frames(DEFAULT_FRAMES); camogm_set_max_frames(state, DEFAULT_FRAMES);
camogm_set_frames_per_chunk(DEFAULT_FRAMES_PER_CHUNK); camogm_set_frames_per_chunk(state, DEFAULT_FRAMES_PER_CHUNK);
camogm_set_start_after_timestamp(0.0); /// start any time camogm_set_start_after_timestamp(state, 0.0); /// start any time
camogm_set_prefix("\0"); camogm_set_prefix(state, "\0");
camogm_set_save_gp(0); camogm_set_save_gp(state, 0);
camogm_reset(); //! sets state->buf_overruns=-1; //!first does not count camogm_reset(state); //! sets state->buf_overruns=-1; //!first does not count
state->serialno = ipser[0]; state->serialno = ipser[0];
state->last = 0; state->last = 0;
debug_file = stderr; debug_file = stderr;
camogm_debug_level(1); camogm_debug_level(1);
strcpy(state->debug_name, "stderr"); strcpy(state->debug_name, "stderr");
camogm_set_timescale(1.0); camogm_set_timescale(state, 1.0);
camogm_set_frames_skip(0); //! don't skip camogm_set_frames_skip(state, 0); //! don't skip
camogm_set_format(CAMOGM_FORMAT_OGM); camogm_set_format(state, CAMOGM_FORMAT_OGM);
state->exifSize = 0; state->exifSize = 0;
state->exif = DEFAULT_EXIF; state->exif = DEFAULT_EXIF;
state->frame_lengths = NULL; state->frame_lengths = NULL;
...@@ -285,21 +302,22 @@ int camogm_init(void) ...@@ -285,21 +302,22 @@ int camogm_init(void)
state->last_error_code = 0; state->last_error_code = 0;
///kml stuff ///kml stuff
camogm_kml_set_enable(0); camogm_kml_set_enable(state, 0);
state->kml_file = NULL; state->kml_file = NULL;
camogm_kml_set_horHalfFov(20.0); camogm_kml_set_horHalfFov(state, 20.0);
camogm_kml_set_vertHalfFov(15.0); camogm_kml_set_vertHalfFov(state, 15.0);
camogm_kml_set_height_mode(0); camogm_kml_set_height_mode(state, 0);
camogm_kml_set_height(10.0); camogm_kml_set_height(state, 10.0);
camogm_kml_set_period(2); // 2 sec camogm_kml_set_period(state, 2); // 2 sec
camogm_kml_set_near(40.0); // 40 m (distance to PhotoOverlay) camogm_kml_set_near(state, 40.0); // 40 m (distance to PhotoOverlay)
state->kml_path[0] = '\0'; state->kml_path[0] = '\0';
state->port_num = port;
return 0; return 0;
} }
int camogm_debug(const char * fname) int camogm_debug(camogm_state *state, const char * fname)
{ {
int none = 1; int none = 1;
...@@ -327,7 +345,7 @@ int camogm_debug_level(int d) ...@@ -327,7 +345,7 @@ int camogm_debug_level(int d)
return 0; return 0;
} }
int camogm_start(void) int camogm_start(camogm_state *state)
{ {
int timestamp_start; int timestamp_start;
int rslt; int rslt;
...@@ -354,7 +372,7 @@ int camogm_start(void) ...@@ -354,7 +372,7 @@ int camogm_start(void)
//! exit on unknown formats? //! exit on unknown formats?
} }
state->max_frames = state->set_max_frames; state->max_frames = state->set_max_frames;
state->frames_per_chunk = state->frames_per_chunk; state->frames_per_chunk = state->set_frames_per_chunk;
state->starting = 1; //!may be already set state->starting = 1; //!may be already set
//! Check/set circbuf read pointer //! Check/set circbuf read pointer
D3(fprintf(debug_file, "1: state->cirbuf_rp=0x%x\n", state->cirbuf_rp)); D3(fprintf(debug_file, "1: state->cirbuf_rp=0x%x\n", state->cirbuf_rp));
...@@ -368,10 +386,10 @@ int camogm_start(void) ...@@ -368,10 +386,10 @@ int camogm_start(void)
} }
state->buf_overruns++; state->buf_overruns++;
//! 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 = getGPValue(G_FREECIRCBUF); state->buf_min = getGPValue(state->port_num, G_FREECIRCBUF);
} else { } else {
if (state->buf_min > getGPValue(G_FREECIRCBUF)) state->buf_min = getGPValue(G_FREECIRCBUF); if (state->buf_min > getGPValue(state->port_num, G_FREECIRCBUF)) state->buf_min = getGPValue(state->port_num, G_FREECIRCBUF);
} }
D3(fprintf(debug_file, "3: state->cirbuf_rp=0x%x\n", state->cirbuf_rp)); D3(fprintf(debug_file, "3: state->cirbuf_rp=0x%x\n", state->cirbuf_rp));
...@@ -385,7 +403,7 @@ int camogm_start(void) ...@@ -385,7 +403,7 @@ int camogm_start(void)
///================================== ///==================================
memcpy(&(state->frame_params), (unsigned long* )&ccam_dma_buf[state->metadata_start >> 2], 32); memcpy(&(state->frame_params), (unsigned long* )&ccam_dma_buf[state->port_num][state->metadata_start >> 2], 32);
state->jpeg_len = state->frame_params.frame_length; //! frame_params.frame_length are now the length of bitstream state->jpeg_len = state->frame_params.frame_length; //! frame_params.frame_length are now the length of bitstream
...@@ -400,7 +418,7 @@ int camogm_start(void) ...@@ -400,7 +418,7 @@ int camogm_start(void)
///================================== ///==================================
timestamp_start = (state->cirbuf_rp) + ((state->jpeg_len + CCAM_MMAP_META + 3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC; //! magic shift - should index first byte of the time stamp timestamp_start = (state->cirbuf_rp) + ((state->jpeg_len + CCAM_MMAP_META + 3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC; //! magic shift - should index first byte of the time stamp
if (timestamp_start >= state->circ_buff_size) timestamp_start -= state->circ_buff_size; if (timestamp_start >= state->circ_buff_size) timestamp_start -= state->circ_buff_size;
memcpy(&(state->frame_params.timestamp_sec), (unsigned long* )&ccam_dma_buf[timestamp_start >> 2], 8); memcpy(&(state->frame_params.timestamp_sec), (unsigned long* )&ccam_dma_buf[state->port_num][timestamp_start >> 2], 8);
/// New - see if current timestamp is later than start one, if not return "CAMOGM_TOO_EARLY" reset read pointer and buffer read pointer /// New - see if current timestamp is later than start one, if not return "CAMOGM_TOO_EARLY" reset read pointer and buffer read pointer
if (state->start_after_timestamp > 0.0) { /// don't bother if it is 0 if (state->start_after_timestamp > 0.0) { /// don't bother if it is 0
dtime_stamp = 0.000001 * state->frame_params.timestamp_usec + state->frame_params.timestamp_sec; dtime_stamp = 0.000001 * state->frame_params.timestamp_usec + state->frame_params.timestamp_sec;
...@@ -422,7 +440,7 @@ int camogm_start(void) ...@@ -422,7 +440,7 @@ int camogm_start(void)
} }
next_metadata_start = fp - 32; next_metadata_start = fp - 32;
if (next_metadata_start < 0) next_metadata_start += state->circ_buff_size; if (next_metadata_start < 0) next_metadata_start += state->circ_buff_size;
memcpy(&(state->this_frame_params), (unsigned long* )&ccam_dma_buf[next_metadata_start >> 2], 32); memcpy(&(state->this_frame_params), (unsigned long* )&ccam_dma_buf[state->port_num][next_metadata_start >> 2], 32);
next_jpeg_len = state->this_frame_params.frame_length; //! frame_params.frame_length are now the length of bitstream next_jpeg_len = state->this_frame_params.frame_length; //! frame_params.frame_length are now the length of bitstream
if (state->this_frame_params.signffff != 0xffff) { //! should not happen ever if (state->this_frame_params.signffff != 0xffff) { //! should not happen ever
D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n", __FILE__, __LINE__, (int)state->this_frame_params.signffff)); D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n", __FILE__, __LINE__, (int)state->this_frame_params.signffff));
...@@ -439,7 +457,7 @@ int camogm_start(void) ...@@ -439,7 +457,7 @@ int camogm_start(void)
//! find location of the timestamp and copy it to the frame_params structure //! find location of the timestamp and copy it to the frame_params structure
timestamp_start = fp + ((next_jpeg_len + CCAM_MMAP_META + 3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC; //! magic shift - should index first byte of the time stamp timestamp_start = fp + ((next_jpeg_len + CCAM_MMAP_META + 3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC; //! magic shift - should index first byte of the time stamp
if (timestamp_start >= state->circ_buff_size) timestamp_start -= state->circ_buff_size; if (timestamp_start >= state->circ_buff_size) timestamp_start -= state->circ_buff_size;
memcpy(&(state->this_frame_params.timestamp_sec), (unsigned long* )&ccam_dma_buf[timestamp_start >> 2], 8); memcpy(&(state->this_frame_params.timestamp_sec), (unsigned long* )&ccam_dma_buf[state->port_num][timestamp_start >> 2], 8);
//! verify that the essential current frame params did not change, if they did - return an error (need new file header) //! verify that the essential current frame params did not change, if they did - return an error (need new file header)
if (!state->ignore_fps && ((state->frame_params.width != state->this_frame_params.width) || if (!state->ignore_fps && ((state->frame_params.width != state->this_frame_params.width) ||
(state->frame_params.height != state->this_frame_params.height))) { (state->frame_params.height != state->this_frame_params.height))) {
...@@ -486,16 +504,16 @@ int camogm_start(void) ...@@ -486,16 +504,16 @@ int camogm_start(void)
//!here we are ready to initialize Ogm (or other) file //!here we are ready to initialize Ogm (or other) file
switch (state->format) { switch (state->format) {
case CAMOGM_FORMAT_NONE: rslt = 0; break; case CAMOGM_FORMAT_NONE: rslt = 0; break;
case CAMOGM_FORMAT_OGM: rslt = camogm_start_ogm(); break; case CAMOGM_FORMAT_OGM: rslt = camogm_start_ogm(state); break;
case CAMOGM_FORMAT_JPEG: rslt = camogm_start_jpeg(); break; case CAMOGM_FORMAT_JPEG: rslt = camogm_start_jpeg(state); break;
case CAMOGM_FORMAT_MOV: rslt = camogm_start_mov(); break; case CAMOGM_FORMAT_MOV: rslt = camogm_start_mov(state); break;
default: rslt = 0; // do nothing default: rslt = 0; // do nothing
} }
if (rslt) { if (rslt) {
D0(fprintf(debug_file, "camogm_start() error, rslt=0x%x\n", rslt)); D0(fprintf(debug_file, "camogm_start() error, rslt=0x%x\n", rslt));
return rslt; return rslt;
} }
if (state->kml_enable) rslt = camogm_start_kml(); // will turn on state->kml_used if it can if (state->kml_enable) rslt = camogm_start_kml(state); // will turn on state->kml_used if it can
if (rslt) return rslt; if (rslt) return rslt;
state->running = 1; state->running = 1;
state->starting = 0; state->starting = 0;
...@@ -504,7 +522,7 @@ int camogm_start(void) ...@@ -504,7 +522,7 @@ int camogm_start(void)
} }
int sendImageFrame(void) int sendImageFrame(camogm_state *state)
{ {
int rslt; int rslt;
unsigned char frame_packet_type = PACKET_IS_SYNCPOINT; unsigned char frame_packet_type = PACKET_IS_SYNCPOINT;
...@@ -562,7 +580,7 @@ int sendImageFrame(void) ...@@ -562,7 +580,7 @@ int sendImageFrame(void)
D3(fprintf(debug_file, "_1_")); D3(fprintf(debug_file, "_1_"));
state->metadata_start = state->cirbuf_rp - 32; state->metadata_start = state->cirbuf_rp - 32;
if (state->metadata_start < 0) state->metadata_start += state->circ_buff_size; if (state->metadata_start < 0) state->metadata_start += state->circ_buff_size;
memcpy(&(state->this_frame_params), (unsigned long* )&ccam_dma_buf[state->metadata_start >> 2], 32); memcpy(&(state->this_frame_params), (unsigned long* )&ccam_dma_buf[state->port_num][state->metadata_start >> 2], 32);
state->jpeg_len = state->this_frame_params.frame_length; //! frame_params.frame_length are now the length of bitstream state->jpeg_len = state->this_frame_params.frame_length; //! frame_params.frame_length are now the length of bitstream
if (state->this_frame_params.signffff != 0xffff) { if (state->this_frame_params.signffff != 0xffff) {
D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n", __FILE__, __LINE__, (int)state->this_frame_params.signffff)); D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n", __FILE__, __LINE__, (int)state->this_frame_params.signffff));
...@@ -577,7 +595,7 @@ int sendImageFrame(void) ...@@ -577,7 +595,7 @@ int sendImageFrame(void)
timestamp_start = state->cirbuf_rp + ((state->jpeg_len + CCAM_MMAP_META + 3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC; //! magic shift - should index first byte of the time stamp timestamp_start = state->cirbuf_rp + ((state->jpeg_len + CCAM_MMAP_META + 3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC; //! magic shift - should index first byte of the time stamp
if (timestamp_start >= state->circ_buff_size) timestamp_start -= state->circ_buff_size; if (timestamp_start >= state->circ_buff_size) timestamp_start -= state->circ_buff_size;
D3(fprintf(debug_file, "_3_")); D3(fprintf(debug_file, "_3_"));
memcpy(&(state->this_frame_params.timestamp_sec), (unsigned long* )&ccam_dma_buf[timestamp_start >> 2], 8); memcpy(&(state->this_frame_params.timestamp_sec), (unsigned long* )&ccam_dma_buf[state->port_num][timestamp_start >> 2], 8);
//! verify that the essential current frame params did not change, if they did - return an error (need new file header) //! verify that the essential current frame params did not change, if they did - return an error (need new file header)
if (!state->ignore_fps && ((state->frame_params.width != state->this_frame_params.width) || if (!state->ignore_fps && ((state->frame_params.width != state->this_frame_params.width) ||
(state->frame_params.height != state->this_frame_params.height))) { (state->frame_params.height != state->this_frame_params.height))) {
...@@ -642,7 +660,7 @@ int sendImageFrame(void) ...@@ -642,7 +660,7 @@ int sendImageFrame(void)
/*! copy from the beginning of the frame to the end of the buffer */ /*! copy from the beginning of the frame to the end of the buffer */
D3(fprintf(debug_file, "_10_")); D3(fprintf(debug_file, "_10_"));
state->packetchunks[state->chunk_index ].bytes = state->circ_buff_size - state->cirbuf_rp; state->packetchunks[state->chunk_index ].bytes = state->circ_buff_size - state->cirbuf_rp;
state->packetchunks[state->chunk_index++].chunk = (unsigned char*)&ccam_dma_buf[state->cirbuf_rp >> 2]; state->packetchunks[state->chunk_index++].chunk = (unsigned char*)&ccam_dma_buf[state->port_num][state->cirbuf_rp >> 2];
/*! copy from the beginning of the buffer to the end of the frame */ /*! copy from the beginning of the buffer to the end of the frame */
state->packetchunks[state->chunk_index ].bytes = state->jpeg_len - (state->circ_buff_size - state->cirbuf_rp); state->packetchunks[state->chunk_index ].bytes = state->jpeg_len - (state->circ_buff_size - state->cirbuf_rp);
state->packetchunks[state->chunk_index++].chunk = (unsigned char*)&ccam_dma_buf[0]; state->packetchunks[state->chunk_index++].chunk = (unsigned char*)&ccam_dma_buf[0];
...@@ -651,7 +669,7 @@ int sendImageFrame(void) ...@@ -651,7 +669,7 @@ int sendImageFrame(void)
/*! copy from the beginning of the frame to the end of the frame (no buffer rollovers) */ /*! copy from the beginning of the frame to the end of the frame (no buffer rollovers) */
state->packetchunks[state->chunk_index ].bytes = state->jpeg_len; state->packetchunks[state->chunk_index ].bytes = state->jpeg_len;
state->packetchunks[state->chunk_index++].chunk = (unsigned char*)&ccam_dma_buf[state->cirbuf_rp >> 2]; state->packetchunks[state->chunk_index++].chunk = (unsigned char*)&ccam_dma_buf[state->port_num][state->cirbuf_rp >> 2];
} }
D3(fprintf(debug_file, "_12_")); D3(fprintf(debug_file, "_12_"));
state->packetchunks[state->chunk_index ].bytes = 2; state->packetchunks[state->chunk_index ].bytes = 2;
...@@ -659,16 +677,16 @@ int sendImageFrame(void) ...@@ -659,16 +677,16 @@ int sendImageFrame(void)
switch (state->format) { switch (state->format) {
case CAMOGM_FORMAT_NONE: rslt = 0; break; case CAMOGM_FORMAT_NONE: rslt = 0; break;
case CAMOGM_FORMAT_OGM: rslt = camogm_frame_ogm(); break; case CAMOGM_FORMAT_OGM: rslt = camogm_frame_ogm(state); break;
case CAMOGM_FORMAT_JPEG: rslt = camogm_frame_jpeg(); break; case CAMOGM_FORMAT_JPEG: rslt = camogm_frame_jpeg(state); break;
case CAMOGM_FORMAT_MOV: rslt = camogm_frame_mov(); break; case CAMOGM_FORMAT_MOV: rslt = camogm_frame_mov(state); break;
default: rslt = 0; // do nothing default: rslt = 0; // do nothing
} }
if (rslt) { if (rslt) {
D3(fprintf(debug_file, "sendImageFrame:12: camogm_frame_***() returned 0x%x\n", rslt)); D3(fprintf(debug_file, "sendImageFrame:12: camogm_frame_***() returned 0x%x\n", rslt));
return rslt; return rslt;
} }
if (state->kml_used) rslt = camogm_frame_kml(); // will turn on state->kml_used if it can if (state->kml_used) rslt = camogm_frame_kml(state); // will turn on state->kml_used if it can
if (rslt) return rslt; if (rslt) return rslt;
D3(fprintf(debug_file, "_14_")); D3(fprintf(debug_file, "_14_"));
...@@ -687,8 +705,7 @@ int sendImageFrame(void) ...@@ -687,8 +705,7 @@ int sendImageFrame(void)
} }
int camogm_stop(camogm_state *state)
int camogm_stop(void)
{ {
int rslt = 0; int rslt = 0;
...@@ -702,12 +719,12 @@ int camogm_stop(void) ...@@ -702,12 +719,12 @@ int camogm_stop(void)
return 0; return 0;
} }
D1(fprintf(debug_file, "Ending recording\n")); D1(fprintf(debug_file, "Ending recording\n"));
if (state->kml_used) camogm_end_kml(); 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;
case CAMOGM_FORMAT_OGM: rslt = camogm_end_ogm(); break; case CAMOGM_FORMAT_OGM: rslt = camogm_end_ogm(state); break;
case CAMOGM_FORMAT_JPEG: rslt = camogm_end_jpeg(); break; case CAMOGM_FORMAT_JPEG: rslt = camogm_end_jpeg(); break;
case CAMOGM_FORMAT_MOV: rslt = camogm_end_mov(); break; case CAMOGM_FORMAT_MOV: rslt = camogm_end_mov(state); break;
/// default: return 0; // do nothing /// default: return 0; // do nothing
} }
//! now close video file (if it is open) //! now close video file (if it is open)
...@@ -721,7 +738,7 @@ int camogm_stop(void) ...@@ -721,7 +738,7 @@ int camogm_stop(void)
return 0; return 0;
} }
void camogm_free() void camogm_free(camogm_state *state)
{ {
int f; int f;
...@@ -740,80 +757,81 @@ void camogm_free() ...@@ -740,80 +757,81 @@ void camogm_free()
state->formats = 0; state->formats = 0;
} }
int camogm_reset(void) //! reset circbuf read pointer int camogm_reset(camogm_state *state) //! reset circbuf read pointer
{ {
state->cirbuf_rp = -1; state->cirbuf_rp = -1;
state->buf_overruns = -1; //!first will not count state->buf_overruns = -1; //!first will not count
return 0; return 0;
} }
///kml stuff ///kml stuff
void camogm_kml_set_enable(int d) void camogm_kml_set_enable(camogm_state *state, int d)
{ {
state->kml_enable = d; state->kml_enable = d;
} }
void camogm_kml_set_horHalfFov(double dd) void camogm_kml_set_horHalfFov(camogm_state *state, double dd)
{ {
state->kml_horHalfFov = dd; state->kml_horHalfFov = dd;
} }
void camogm_kml_set_vertHalfFov(double dd) void camogm_kml_set_vertHalfFov(camogm_state *state, double dd)
{ {
state->kml_vertHalfFov = dd; state->kml_vertHalfFov = dd;
} }
void camogm_kml_set_height_mode(int d) void camogm_kml_set_height_mode(camogm_state *state, int d)
{ {
state->kml_height_mode = d; state->kml_height_mode = d;
} }
void camogm_kml_set_height(double dd) void camogm_kml_set_height(camogm_state *state, double dd)
{ {
state->kml_height = dd; state->kml_height = dd;
} }
void camogm_kml_set_period(int d) void camogm_kml_set_period(camogm_state *state, int d)
{ {
state->kml_period = d; state->kml_period = d;
state->kml_last_ts = 0; state->kml_last_ts = 0;
state->kml_last_uts = 0; state->kml_last_uts = 0;
} }
void camogm_kml_set_near(double dd) // distance to PhotoOverlay void camogm_kml_set_near(camogm_state *state, double dd) // distance to PhotoOverlay
{ {
state->kml_near = dd; state->kml_near = dd;
} }
void camogm_set_segment_duration(int sd) void camogm_set_segment_duration(camogm_state *state, int sd)
{ {
state->segment_duration = sd; state->segment_duration = sd;
} }
void camogm_set_segment_length(int sl) void camogm_set_segment_length(camogm_state *state, int sl)
{ {
state->segment_length = sl; state->segment_length = sl;
} }
void camogm_set_save_gp(int d) void camogm_set_save_gp(camogm_state *state, int d)
{ {
state->save_gp = d; state->save_gp = d;
} }
void camogm_set_exif(int d) void camogm_set_exif(camogm_state *state, int d)
{ {
state->exif = d; state->exif = d;
} }
void camogm_set_greedy(int d) void camogm_set_greedy(camogm_state *state, int d)
{ {
state->greedy = d ? 1 : 0; state->greedy = d ? 1 : 0;
} }
void camogm_set_ignore_fps(int d) void camogm_set_ignore_fps(camogm_state *state, int d)
{ {
state->ignore_fps = d ? 1 : 0; state->ignore_fps = d ? 1 : 0;
} }
void camogm_set_prefix(const char * p) void camogm_set_prefix(camogm_state *state, const char * p)
{ {
strncpy(state->path_prefix, p, sizeof(state->path_prefix) - 1); strncpy(state->path_prefix, p, sizeof(state->path_prefix) - 1);
state->path_prefix[sizeof(state->path_prefix) - 1] = '\0'; state->path_prefix[sizeof(state->path_prefix) - 1] = '\0';
} }
void camogm_set_timescale(double d) //! set timescale, default=1,000,000 void camogm_set_timescale(camogm_state *state, double d) //! set timescale, default=1,000,000
{ {
state->set_timescale = d; state->set_timescale = d;
if ((state->running == 0) && (state->starting == 0)) { if ((state->running == 0) && (state->starting == 0)) {
...@@ -821,18 +839,18 @@ void camogm_set_timescale(double d) //! set timescale, default=1,000,000 ...@@ -821,18 +839,18 @@ void camogm_set_timescale(double d) //! set timescale, default=1,000,000
} }
} }
void camogm_set_frames_skip(int d) //! set frames to skip (for time lapse) void camogm_set_frames_skip(camogm_state *state, int d) //! set frames to skip (for time lapse)
{ {
state->set_frames_skip = d; state->set_frames_skip = d;
if ((state->running == 0) && (state->starting == 0)) { if ((state->running == 0) && (state->starting == 0)) {
state->frames_skip = state->set_frames_skip; state->frames_skip = state->set_frames_skip;
// state->frames_skip_left= state->set_frames_skip; // state->frames_skip_left= state->set_fram_skip;
state->frames_skip_left = 0; state->frames_skip_left = 0;
} }
} }
void camogm_set_format(int d) void camogm_set_format(camogm_state *state, int d)
{ {
int rslt = 0; int rslt = 0;
...@@ -852,23 +870,23 @@ void camogm_set_format(int d) ...@@ -852,23 +870,23 @@ void camogm_set_format(int d)
} }
} }
//! needed for Quicktime - maybe something else? //! needed for Quicktime - maybe something else?
void camogm_set_max_frames(int d) void camogm_set_max_frames(camogm_state *state, int d)
{ {
state->set_max_frames = d; state->set_max_frames = d;
if ((state->running == 0) && (state->starting == 0)) state->max_frames = d; if ((state->running == 0) && (state->starting == 0)) state->max_frames = d;
} }
void camogm_set_frames_per_chunk(int d) void camogm_set_frames_per_chunk(camogm_state *state, int d)
{ {
state->set_frames_per_chunk = d; state->set_frames_per_chunk = d;
if ((state->running == 0) && (state->starting == 0)) state->frames_per_chunk = d; if ((state->running == 0) && (state->starting == 0)) state->frames_per_chunk = d;
} }
void camogm_set_start_after_timestamp(double d) void camogm_set_start_after_timestamp(camogm_state *state, double d)
{ {
state->start_after_timestamp = d; state->start_after_timestamp = d;
} }
void camogm_status(char * fn, int xml) void camogm_status(camogm_state *state, char * fn, int xml)
{ {
int _len = 0; int _len = 0;
int _dur, _udur; int _dur, _udur;
...@@ -887,9 +905,9 @@ void camogm_status(char * fn, int xml) ...@@ -887,9 +905,9 @@ void camogm_status(char * fn, int xml)
_kml_height_mode = state->kml_height_mode ? "GPS altitude" : "map ground level"; //! 1 - actual, 0 - ground _kml_height_mode = state->kml_height_mode ? "GPS altitude" : "map ground level"; //! 1 - actual, 0 - ground
_b_free = getGPValue(G_FREECIRCBUF); _b_free = getGPValue(state->port_num, G_FREECIRCBUF);
_b_used = getGPValue(G_CIRCBUFSIZE) - getGPValue(G_FREECIRCBUF); _b_used = getGPValue(state->port_num, G_CIRCBUFSIZE) - getGPValue(state->port_num, G_FREECIRCBUF);
_b_size = getGPValue(G_FRAME_SIZE); _b_size = getGPValue(state->port_num, G_FRAME_SIZE);
if (!fn) f = stdout; if (!fn) f = stdout;
else if (strcmp(fn, "stdout") == 0) f = stdout; else if (strcmp(fn, "stdout") == 0) f = stdout;
...@@ -918,7 +936,7 @@ void camogm_status(char * fn, int xml) ...@@ -918,7 +936,7 @@ void camogm_status(char * fn, int xml)
"other"))) : "none"; "other"))) : "none";
_using_exif = state->exif ? "yes" : "no"; _using_exif = state->exif ? "yes" : "no";
_using_global_pointer = state->save_gp ? "yes" : "no"; _using_global_pointer = state->save_gp ? "yes" : "no";
_compressor_state = (getGPValue(P_COMPRESSOR_RUN) == 2) ? "running" : "stoppped"; _compressor_state = (getGPValue(state->port_num, P_COMPRESSOR_RUN) == 2) ? "running" : "stoppped";
if ( state->frames_skip > 0 ) { if ( state->frames_skip > 0 ) {
_frames_remain = state->frames_skip_left; _frames_remain = state->frames_skip_left;
_frames_skip = state->frames_skip; _frames_skip = state->frames_skip;
...@@ -1081,7 +1099,7 @@ char * getLineFromPipe(FILE* npipe) ...@@ -1081,7 +1099,7 @@ char * getLineFromPipe(FILE* npipe)
} }
} }
// command[= \t]*args[ \t]* // command[= \t]*args[ \t]*
int parse_cmd(FILE* npipe) int parse_cmd(camogm_state *state, FILE* npipe)
{ {
char * cmd; char * cmd;
char * args; char * args;
...@@ -1096,7 +1114,7 @@ int parse_cmd(FILE* npipe) ...@@ -1096,7 +1114,7 @@ int parse_cmd(FILE* npipe)
D2(fprintf(debug_file, "Got command: '%s'\n", cmd)); D2(fprintf(debug_file, "Got command: '%s'\n", cmd));
/// Acknowledge received command by copying frame number to per-daemon parameter /// Acknowledge received command by copying frame number to per-daemon parameter
GLOBALPARS(G_DAEMON_ERR + lastDaemonBit) = GLOBALPARS(G_THIS_FRAME); GLOBALPARS(state->port_num, G_DAEMON_ERR + lastDaemonBit[state->port_num]) = GLOBALPARS(state->port_num, G_THIS_FRAME);
// printf ("cmd[0]=%d:%s\n",(int) cmd[0],cmd); // printf ("cmd[0]=%d:%s\n",(int) cmd[0],cmd);
args = strpbrk(cmd, "= \t"); args = strpbrk(cmd, "= \t");
//! is it just a single word command or does it have parameters? //! is it just a single word command or does it have parameters?
...@@ -1112,47 +1130,47 @@ int parse_cmd(FILE* npipe) ...@@ -1112,47 +1130,47 @@ int parse_cmd(FILE* npipe)
} }
//! now cmd is trimmed, arg is NULL or a pointer to trimmed command arguments //! now cmd is trimmed, arg is NULL or a pointer to trimmed command arguments
if (strcmp(cmd, "start") == 0) { if (strcmp(cmd, "start") == 0) {
camogm_start(); camogm_start(state);
return 1; return 1;
} else if (strcmp(cmd, "reset") == 0) { //! will reset pointer to the last acquired frame (if any) } else if (strcmp(cmd, "reset") == 0) { //! will reset pointer to the last acquired frame (if any)
camogm_reset(); camogm_reset(state);
return 2; return 2;
} else if (strcmp(cmd, "stop") == 0) { } else if (strcmp(cmd, "stop") == 0) {
camogm_stop(); camogm_stop(state);
return 3; return 3;
} else if (strcmp(cmd, "exit") == 0) { } else if (strcmp(cmd, "exit") == 0) {
camogm_stop(); camogm_stop(state);
camogm_free(); camogm_free(state);
exit(0); exit(0);
} else if (strcmp(cmd, "duration") == 0) { } else if (strcmp(cmd, "duration") == 0) {
if (!(args) || (((d = strtol(args, NULL, 10))) <= 0)) d = DEFAULT_DURATION; if (!(args) || (((d = strtol(args, NULL, 10))) <= 0)) d = DEFAULT_DURATION;
camogm_set_segment_duration(d); camogm_set_segment_duration(state, d);
return 4; return 4;
} else if (strcmp(cmd, "length") == 0) { } else if (strcmp(cmd, "length") == 0) {
if (!(args) || (((d = strtol(args, NULL, 10))) <= 0)) d = DEFAULT_LENGTH; if (!(args) || (((d = strtol(args, NULL, 10))) <= 0)) d = DEFAULT_LENGTH;
camogm_set_segment_length(d); camogm_set_segment_length(state, d);
return 5; return 5;
} else if (strcmp(cmd, "prefix") == 0) { } else if (strcmp(cmd, "prefix") == 0) {
if (args) camogm_set_prefix(args); if (args) camogm_set_prefix(state, args);
return 6; return 6;
} else if (strcmp(cmd, "status") == 0) { } else if (strcmp(cmd, "status") == 0) {
camogm_status(args, 0); camogm_status(state, args, 0);
return 7; return 7;
} else if (strcmp(cmd, "xstatus") == 0) { } else if (strcmp(cmd, "xstatus") == 0) {
camogm_status(args, 1); camogm_status(state, args, 1);
return 7; return 7;
} else if (strcmp(cmd, "save_gp") == 0) { } else if (strcmp(cmd, "save_gp") == 0) {
if ((args) && (((d = strtol(args, NULL, 10))) >= 0)) camogm_set_save_gp(d); if ((args) && (((d = strtol(args, NULL, 10))) >= 0)) camogm_set_save_gp(state, d);
return 8; return 8;
} else if (strcmp(cmd, "exif") == 0) { } else if (strcmp(cmd, "exif") == 0) {
if ((args) && (((d = strtol(args, NULL, 10))) >= 0)) camogm_set_exif(d); if ((args) && (((d = strtol(args, NULL, 10))) >= 0)) camogm_set_exif(state, d);
return 8; return 8;
} else if (strcmp(cmd, "debug") == 0) { } else if (strcmp(cmd, "debug") == 0) {
camogm_debug(args); camogm_debug(state, args);
return 9; return 9;
} else if (strcmp(cmd, "timescale") == 0) { } else if (strcmp(cmd, "timescale") == 0) {
dd = strtod(args, NULL); dd = strtod(args, NULL);
camogm_set_timescale(dd ? dd : 1.0); camogm_set_timescale(state, dd ? dd : 1.0);
return 10; return 10;
//!TODO: fix period calculation/check for frame skipping (just disable in frame skip mode?) //!TODO: fix period calculation/check for frame skipping (just disable in frame skip mode?)
//!TODO: add time period (system clock), not just frame skipping //!TODO: add time period (system clock), not just frame skipping
...@@ -1160,18 +1178,18 @@ int parse_cmd(FILE* npipe) ...@@ -1160,18 +1178,18 @@ int parse_cmd(FILE* npipe)
} else if (strcmp(cmd, "frameskip") == 0) { } else if (strcmp(cmd, "frameskip") == 0) {
d = strtol(args, NULL, 10); d = strtol(args, NULL, 10);
camogm_set_frames_skip(d); camogm_set_frames_skip(state, d);
return 11; return 11;
} else if (strcmp(cmd, "timelapse") == 0) { //! period (in seconds) between stored frames } else if (strcmp(cmd, "timelapse") == 0) { //! period (in seconds) between stored frames
d = strtol(args, NULL, 10); d = strtol(args, NULL, 10);
camogm_set_frames_skip(-d); camogm_set_frames_skip(state, -d);
return 11; return 11;
} else if (strcmp(cmd, "format") == 0) { } else if (strcmp(cmd, "format") == 0) {
if (args) { if (args) {
if (strcmp(args, "none") == 0) camogm_set_format(0); if (strcmp(args, "none") == 0) camogm_set_format(state, 0);
else if ((strcmp(args, "ogm" ) == 0) || (strcmp(args, "ogg") == 0)) camogm_set_format(CAMOGM_FORMAT_OGM); else if ((strcmp(args, "ogm" ) == 0) || (strcmp(args, "ogg") == 0)) camogm_set_format(state, CAMOGM_FORMAT_OGM);
else if ((strcmp(args, "jpeg") == 0) || (strcmp(args, "jpg") == 0)) camogm_set_format(CAMOGM_FORMAT_JPEG); else if ((strcmp(args, "jpeg") == 0) || (strcmp(args, "jpg") == 0)) camogm_set_format(state, CAMOGM_FORMAT_JPEG);
else if (strcmp(args, "mov" ) == 0) camogm_set_format(CAMOGM_FORMAT_MOV); else if (strcmp(args, "mov" ) == 0) camogm_set_format(state, CAMOGM_FORMAT_MOV);
} }
return 12; return 12;
} else if (strcmp(cmd, "debuglev") == 0) { } else if (strcmp(cmd, "debuglev") == 0) {
...@@ -1179,61 +1197,111 @@ int parse_cmd(FILE* npipe) ...@@ -1179,61 +1197,111 @@ int parse_cmd(FILE* npipe)
camogm_debug_level(d ? d : 0); camogm_debug_level(d ? d : 0);
return 13; return 13;
} else if (strcmp(cmd, "kml") == 0) { } else if (strcmp(cmd, "kml") == 0) {
if ((args) && (((d = strtol(args, NULL, 10))) >= 0)) camogm_kml_set_enable(d); if ((args) && (((d = strtol(args, NULL, 10))) >= 0)) camogm_kml_set_enable(state, d);
return 14; return 14;
} else if (strcmp(cmd, "kml_hhf") == 0) { } else if (strcmp(cmd, "kml_hhf") == 0) {
dd = strtod(args, NULL); dd = strtod(args, NULL);
camogm_kml_set_horHalfFov(dd); camogm_kml_set_horHalfFov(state, dd);
return 15; return 15;
} else if (strcmp(cmd, "kml_vhf") == 0) { } else if (strcmp(cmd, "kml_vhf") == 0) {
dd = strtod(args, NULL); dd = strtod(args, NULL);
camogm_kml_set_vertHalfFov(dd); camogm_kml_set_vertHalfFov(state, dd);
return 16; return 16;
} else if (strcmp(cmd, "kml_near") == 0) { } else if (strcmp(cmd, "kml_near") == 0) {
dd = strtod(args, NULL); dd = strtod(args, NULL);
camogm_kml_set_near(dd); camogm_kml_set_near(state, dd);
return 17; return 17;
} else if (strcmp(cmd, "kml_alt") == 0) { } else if (strcmp(cmd, "kml_alt") == 0) {
if (args) { if (args) {
if (strcmp(args, "gps" ) == 0) camogm_kml_set_height_mode(1); if (strcmp(args, "gps" ) == 0) camogm_kml_set_height_mode(state, 1);
else if (strcmp(args, "ground") == 0) camogm_kml_set_height_mode(0); else if (strcmp(args, "ground") == 0) camogm_kml_set_height_mode(state, 0);
} }
return 18; return 18;
} else if (strcmp(cmd, "kml_height") == 0) { } else if (strcmp(cmd, "kml_height") == 0) {
dd = strtod(args, NULL); dd = strtod(args, NULL);
camogm_kml_set_height(dd); camogm_kml_set_height(state, dd);
return 19; return 19;
} else if (strcmp(cmd, "kml_period") == 0) { } else if (strcmp(cmd, "kml_period") == 0) {
d = strtol(args, NULL, 10); d = strtol(args, NULL, 10);
camogm_kml_set_period(d ? d : 1); camogm_kml_set_period(state, d ? d : 1);
return 20; return 20;
} else if (strcmp(cmd, "frames_per_chunk") == 0) { } else if (strcmp(cmd, "frames_per_chunk") == 0) {
d = strtol(args, NULL, 10); d = strtol(args, NULL, 10);
camogm_set_frames_per_chunk(d); camogm_set_frames_per_chunk(state, d);
return 21; return 21;
} else if (strcmp(cmd, "max_frames") == 0) { } else if (strcmp(cmd, "max_frames") == 0) {
d = strtol(args, NULL, 10); d = strtol(args, NULL, 10);
camogm_set_max_frames(d); camogm_set_max_frames(state, d);
return 22; return 22;
} else if (strcmp(cmd, "start_after_timestamp") == 0) { } else if (strcmp(cmd, "start_after_timestamp") == 0) {
dd = strtod(args, NULL); dd = strtod(args, NULL);
camogm_set_start_after_timestamp(dd); camogm_set_start_after_timestamp(state, dd);
return 23; return 23;
} else if (strcmp(cmd, "greedy") == 0) { } else if (strcmp(cmd, "greedy") == 0) {
dd = strtod(args, NULL); dd = strtod(args, NULL);
camogm_set_greedy(dd); camogm_set_greedy(state, dd);
return 24; return 24;
} else if (strcmp(cmd, "ignore_fps") == 0) { } else if (strcmp(cmd, "ignore_fps") == 0) {
dd = strtod(args, NULL); dd = strtod(args, NULL);
camogm_set_ignore_fps(dd); camogm_set_ignore_fps(state, dd);
return 25; return 25;
} }
return -1; return -1;
} }
/**
* @brief Create a list of pipe names from a single name given
*
* This function accepts a pipe name string provided by the user to the program and
* creates a list of #SENSOR_PORTS similar names but with port number added to the end of
* the name.
* @param[in] pipe_name pipe name provided by user
* @param[out] names a list of names with port number added
* return 0 if the list was successfully created or -1 otherwise
*/
int create_pipe_names(const char *pipe_name, char **names)
{
int ret = 0;
unsigned int len = strlen(pipe_name);
for (int i = 0; i < SENSOR_PORTS; i++) {
char *name = malloc(PATH_MAX);
if (name == NULL) {
ret = -1;
break;
}
strncpy(name, pipe_name, PATH_MAX - 1);
snprintf(&name[len], PATH_MAX - len - 1, "%u", i);
names[i] = name;
}
return ret;
}
/**
* @brief This function closes open files and deletes allocated memory.
* @param[in] state pointer to #camogm_state structure for a particular sensor channel
* @param[in] names list of strings containing control pipe names
* return none
*/
void clean_up(camogm_state *state, char **names)
{
if (state->fd_exif > 0)
close(state->fd_exif);
if (state->fd_head > 0)
close(state->fd_head);
if (state->fd_circ > 0)
close(state->fd_circ);
if (state->fd_fparmsall)
close(state->fd_fparmsall);
for (int i = 0; i < SENSOR_PORTS; i++) {
free(names[i]);
names[i] = NULL;
}
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
const char circbufFileName[] = "/dev/circbuf";
// int fd_circ; // int fd_circ;
FILE * cmd_file; FILE * cmd_file;
const char usage[] = "This program allows recording of the video/images acquired by Elphel camera to the storage media.\n" \ const char usage[] = "This program allows recording of the video/images acquired by Elphel camera to the storage media.\n" \
...@@ -1258,98 +1326,108 @@ int main(int argc, char *argv[]) ...@@ -1258,98 +1326,108 @@ int main(int argc, char *argv[])
int cmd; int cmd;
int i, rslt; int i, rslt;
int fp0, fp1; // debugging int fp0, fp1; // debugging
/* debug code follows */
unsigned int port = 2;
/*end of debug code */
camogm_state *state = &sstate[port];
char *pipe_names[SENSOR_PORTS] = {0};
state = &sstate; //extern // state = &sstate; //extern
//! no command line options processing yet //! no command line options processing yet
if ((argc < 2) || (argv[1][1] == '-')) { if ((argc < 2) || (argv[1][1] == '-')) {
printf(usage, argv[0], argv[0]); printf(usage, argv[0], argv[0]);
clean_up(state, pipe_names);
return 0; return 0;
} }
camogm_init(); camogm_init(state, port);
create_pipe_names(argv[1], pipe_names);
//! open Exif header file //! open Exif header file
state->fd_exif = open(ExifFileName, O_RDONLY); state->fd_exif = open(exifFileNames[port], O_RDONLY);
if (state->fd_exif < 0) { // check control OK if (state->fd_exif < 0) { // check control OK
D0(fprintf(debug_file, "Error opening %s\n", ExifFileName)); D0(fprintf(debug_file, "Error opening %s\n", exifFileNames[port]));
return -1; return -1;
} }
//! open JPEG header file //! open JPEG header file
state->fd_head = open(HeadFileName, O_RDWR); state->fd_head = open(headFileNames[port], O_RDWR);
if (state->fd_head < 0) { // check control OK if (state->fd_head < 0) { // check control OK
D0(fprintf(debug_file, "Error opening %s\n", HeadFileName)); D0(fprintf(debug_file, "Error opening %s\n", headFileNames[port]));
clean_up(state, pipe_names);
return -1; return -1;
} }
state->head_size = lseek(state->fd_head, 0, SEEK_END); state->head_size = lseek(state->fd_head, 0, SEEK_END);
if (state->head_size > JPEG_HEADER_MAXSIZE) { if (state->head_size > JPEG_HEADER_MAXSIZE) {
D0(fprintf(debug_file, "%s:%d: Too big JPEG header (%d > %d)", __FILE__, __LINE__, state->head_size, JPEG_HEADER_MAXSIZE )); D0(fprintf(debug_file, "%s:%d: Too big JPEG header (%d > %d)", __FILE__, __LINE__, state->head_size, JPEG_HEADER_MAXSIZE ));
clean_up(state, pipe_names);
return -2; return -2;
} }
//! open circbuf and mmap it (once at startup) //! open circbuf and mmap it (once at startup)
state->fd_circ = open(circbufFileName, O_RDWR); state->fd_circ = open(circbufFileNames[port], O_RDWR);
if (state->fd_circ < 0) { // check control OK if (state->fd_circ < 0) { // check control OK
D0(fprintf(debug_file, "Error opening %s\n", circbufFileName)); D0(fprintf(debug_file, "Error opening %s\n", circbufFileNames[port]));
clean_up(state, pipe_names);
return -2; return -2;
} }
/*! find total buffer length (it is in defines, actually in c313a.h */ /*! find total buffer length (it is in defines, actually in c313a.h */
state->circ_buff_size = lseek(state->fd_circ, 0, SEEK_END); state->circ_buff_size = lseek(state->fd_circ, 0, SEEK_END);
ccam_dma_buf = (unsigned long*)mmap(0, state->circ_buff_size, PROT_READ, MAP_SHARED, state->fd_circ, 0); ccam_dma_buf[port] = (unsigned long*)mmap(0, state->circ_buff_size, PROT_READ, MAP_SHARED, state->fd_circ, 0);
if ((int)ccam_dma_buf == -1) { if ((int)ccam_dma_buf[port] == -1) {
D0(fprintf(debug_file, "Error in mmap of %s\n", circbufFileName)); D0(fprintf(debug_file, "Error in mmap of %s\n", circbufFileNames[port]));
// close (fd_head); clean_up(state, pipe_names);
close(state->fd_circ);
return -3; return -3;
} }
//! Now open/mmap file to read sensor/compressor parameters (currently - just free memory in circbuf and compressor state) //! Now open/mmap file to read sensor/compressor parameters (currently - just free memory in circbuf and compressor state)
//! open circbuf and mmap it (once at startup) //! open circbuf and mmap it (once at startup)
state->fd_fparmsall = open(ctlFileName, O_RDWR); state->fd_fparmsall = open(ctlFileNames[port], O_RDWR);
if (state->fd_fparmsall < 0) { // check control OK if (state->fd_fparmsall < 0) { // check control OK
D0(fprintf(debug_file, "%s:%d:%s: Error opening %s\n", __FILE__, __LINE__, __FUNCTION__, ctlFileName)); D0(fprintf(debug_file, "%s:%d:%s: Error opening %s\n", __FILE__, __LINE__, __FUNCTION__, ctlFileNames[port]));
clean_up(state, pipe_names);
return -2; return -2;
} }
//! now try to mmap //! now try to mmap
/// frameParsAll = (struct framepars_all_t *) mmap(0, sizeof (struct framepars_all_t) , PROT_READ, MAP_SHARED, state->fd_fparmsall, 0); /// frameParsAll = (struct framepars_all_t *) mmap(0, sizeof (struct framepars_all_t) , PROT_READ, MAP_SHARED, state->fd_fparmsall, 0);
/// PROT_WRITE - only to write acknowledge /// PROT_WRITE - only to write acknowledge
frameParsAll = (struct framepars_all_t*)mmap(0, sizeof(struct framepars_all_t), PROT_READ | PROT_WRITE, MAP_SHARED, state->fd_fparmsall, 0); frameParsAll[port] = (struct framepars_all_t*)mmap(0, sizeof(struct framepars_all_t), PROT_READ | PROT_WRITE, MAP_SHARED, state->fd_fparmsall, 0);
if ((int)frameParsAll[port] == -1) {
if ((int)frameParsAll == -1) { D0(fprintf(debug_file, "%s:%d:%s: Error in mmap in %s\n", __FILE__, __LINE__, __FUNCTION__, ctlFileNames[port]));
D0(fprintf(debug_file, "%s:%d:%s: Error in mmap in %s\n", __FILE__, __LINE__, __FUNCTION__, ctlFileName)); clean_up(state, pipe_names);
close(state->fd_fparmsall);
close(state->fd_circ);
return -3; return -3;
} }
framePars = frameParsAll->framePars; framePars[port] = frameParsAll[port]->framePars;
globalPars = frameParsAll->globalPars; globalPars[port] = frameParsAll[port]->globalPars;
//!create a named pipe //!create a named pipe
//!always delete the pipe if it existed, start a fresh one //!always delete the pipe if it existed, start a fresh one
i = unlink(argv[1]); i = unlink(pipe_names[port]);
if (i) { if (i) {
D1(fprintf(debug_file, "Unlink %s returned %d, errno=%d \n", argv[1], i, errno)); D1(fprintf(debug_file, "Unlink %s returned %d, errno=%d \n", pipe_names[port], i, errno));
} }
i = mkfifo(argv[1], 0777); //EEXIST i = mkfifo(pipe_names[port], 0777); //EEXIST
//! now should not exist //! now should not exist
if (i) { if (i) {
if (errno == EEXIST) { if (errno == EEXIST) {
D1(fprintf(debug_file, "Named pipe %s already exists, will use it.\n", argv[1])); D1(fprintf(debug_file, "Named pipe %s already exists, will use it.\n", pipe_names[port]));
} else { } else {
D0(fprintf(debug_file, "Can not create a named pipe %s, errno=%d \n", argv[1], errno)); D0(fprintf(debug_file, "Can not create a named pipe %s, errno=%d \n", pipe_names[port], errno));
clean_up(state, pipe_names);
return -4; return -4;
} }
} }
//!now open the pipe - will block until something will be written (or just open for writing //!now open the pipe - will block until something will be written (or just open for writing
//!Reads themselves will not block //!Reads themselves will not block
if (!((cmd_file = fopen(argv[1], "r")))) { if (!((cmd_file = fopen(pipe_names[port], "r")))) {
D0(fprintf(debug_file, "Can not open command file %s\n", argv[1])); D0(fprintf(debug_file, "Can not open command file %s\n", pipe_names[port]));
clean_up(state, pipe_names);
return -5; return -5;
} }
// D1(fprintf (debug_file,"Pipe %s open for reading\n",argv[1])); // D1(fprintf (debug_file,"Pipe %s open for reading\n",argv[1]));
D0(fprintf(debug_file, "Pipe %s open for reading\n", argv[1])); // to make sure something is sent out D0(fprintf(debug_file, "Pipe %s open for reading\n", pipe_names[port])); // to make sure something is sent out
//! Here is a main loop. If recording is on, it will check for commands after each frame, if it is off - poll with fixed usleep //! Here is a main loop. If recording is on, it will check for commands after each frame, if it is off - poll with fixed usleep
#define COMMAND_LOOP_DELAY 500000 //0.5sec #define COMMAND_LOOP_DELAY 500000 //0.5sec
...@@ -1358,7 +1436,7 @@ int main(int argc, char *argv[]) ...@@ -1358,7 +1436,7 @@ int main(int argc, char *argv[])
// D3(fprintf (debug_file,"%s:%d: format=%d, set_format=%d\n",__FILE__,__LINE__, state->format, state->set_format)); // D3(fprintf (debug_file,"%s:%d: format=%d, set_format=%d\n",__FILE__,__LINE__, state->format, state->set_format));
//! look at command queue first //! look at command queue first
cmd = parse_cmd(cmd_file); cmd = parse_cmd(state, cmd_file);
if (cmd) { if (cmd) {
if (cmd < 0) D0(fprintf(debug_file, "Unrecognized command\n")); if (cmd < 0) D0(fprintf(debug_file, "Unrecognized command\n"));
/// Acknowledge received command by copying frame number to per-daemon parameter /// Acknowledge received command by copying frame number to per-daemon parameter
...@@ -1367,7 +1445,7 @@ int main(int argc, char *argv[]) ...@@ -1367,7 +1445,7 @@ int main(int argc, char *argv[])
} else if (state->running) { //!no commands in queue, started } else if (state->running) { //!no commands in queue, started
// D3(fprintf (debug_file,"%s:%d: format=%d, set_format=%d\n",__FILE__,__LINE__, state->format, state->set_format)); // D3(fprintf (debug_file,"%s:%d: format=%d, set_format=%d\n",__FILE__,__LINE__, state->format, state->set_format));
switch ((rslt = -sendImageFrame())) { switch ((rslt = -sendImageFrame(state))) {
case 0: case 0:
/* /*
D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned %d\n" \ D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned %d\n" \
...@@ -1403,8 +1481,8 @@ int main(int argc, char *argv[]) ...@@ -1403,8 +1481,8 @@ int main(int argc, char *argv[])
case CAMOGM_FRAME_BROKEN: //! frame broken (buffer overrun) case CAMOGM_FRAME_BROKEN: //! frame broken (buffer overrun)
//! restart the file //! restart the file
// D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned -%d\n",__FILE__,__LINE__,rslt)); // D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned -%d\n",__FILE__,__LINE__,rslt));
camogm_stop(); camogm_stop(state);
camogm_start(); camogm_start(state);
break; break;
case CAMOGM_FRAME_FILE_ERR: //! error with file I/O case CAMOGM_FRAME_FILE_ERR: //! error with file I/O
case CAMOGM_FRAME_OTHER: //! other errors case CAMOGM_FRAME_OTHER: //! other errors
...@@ -1412,6 +1490,7 @@ int main(int argc, char *argv[]) ...@@ -1412,6 +1490,7 @@ int main(int argc, char *argv[])
break; break;
default: default:
D0(fprintf(debug_file, "%s:line %d - should not get here (rslt=%d)\n", __FILE__, __LINE__, rslt)); D0(fprintf(debug_file, "%s:line %d - should not get here (rslt=%d)\n", __FILE__, __LINE__, rslt));
clean_up(state, pipe_names);
exit(-1); exit(-1);
} //switch } //switch
if ((rslt != 0) && (rslt != CAMOGM_FRAME_NOT_READY) && (rslt != CAMOGM_FRAME_CHANGED)) state->last_error_code = rslt; if ((rslt != 0) && (rslt != CAMOGM_FRAME_NOT_READY) && (rslt != CAMOGM_FRAME_CHANGED)) state->last_error_code = rslt;
...@@ -1419,7 +1498,7 @@ int main(int argc, char *argv[]) ...@@ -1419,7 +1498,7 @@ int main(int argc, char *argv[])
// D3(fprintf (debug_file,"%s:%d: format=%d, set_format=%d\n",__FILE__,__LINE__, state->format, state->set_format)); // D3(fprintf (debug_file,"%s:%d: format=%d, set_format=%d\n",__FILE__,__LINE__, state->format, state->set_format));
//!retry starting //!retry starting
switch ((rslt = -camogm_start())) { switch ((rslt = -camogm_start(state))) {
case 0: break; //! file started OK, nothing to do case 0: break; //! file started OK, nothing to do
case CAMOGM_TOO_EARLY: case CAMOGM_TOO_EARLY:
lseek(state->fd_circ, LSEEK_CIRC_TOWP, SEEK_END); /// set pointer to the frame to wait for lseek(state->fd_circ, LSEEK_CIRC_TOWP, SEEK_END); /// set pointer to the frame to wait for
...@@ -1442,6 +1521,7 @@ int main(int argc, char *argv[]) ...@@ -1442,6 +1521,7 @@ int main(int argc, char *argv[])
break; break;
default: default:
D0(fprintf(debug_file, "%s:line %d - should not get here (rslt=%d)\n", __FILE__, __LINE__, rslt)); D0(fprintf(debug_file, "%s:line %d - should not get here (rslt=%d)\n", __FILE__, __LINE__, rslt));
clean_up(state, pipe_names);
exit(-1); exit(-1);
} //switch } //switch
if ((rslt != 0) && (rslt != CAMOGM_TOO_EARLY) && (rslt != CAMOGM_FRAME_NOT_READY) && (rslt != CAMOGM_FRAME_CHANGED) ) state->last_error_code = rslt; if ((rslt != 0) && (rslt != CAMOGM_TOO_EARLY) && (rslt != CAMOGM_FRAME_NOT_READY) && (rslt != CAMOGM_FRAME_CHANGED) ) state->last_error_code = rslt;
...@@ -1450,55 +1530,60 @@ int main(int argc, char *argv[]) ...@@ -1450,55 +1530,60 @@ int main(int argc, char *argv[])
usleep( COMMAND_LOOP_DELAY); //! make it longer but interruptible by signals? usleep( COMMAND_LOOP_DELAY); //! make it longer but interruptible by signals?
} }
} }
clean_up(state, pipe_names);
return 0; return 0;
} }
/** /**
* @brief Read either G_* parameter (these are 'regular' values defined by number) or P_* parameter * @brief Read either G_* parameter (these are 'regular' values defined by number) or P_* parameter
* (it can be read for up to 6 frames ahead, but current interface only allows to read last/current value) * (it can be read for up to 6 frames ahead, but current interface only allows to read last/current value)
* @param GPNumber parameter number (as defined in c313a.h), G_* parameters have numbers above FRAMEPAR_GLOBALS, P_* - below) * @param[in] GPNumber parameter number (as defined in c313a.h), G_* parameters have numbers above FRAMEPAR_GLOBALS, P_* - below)
* @param[in] port sensor port number for which a parameter is needed
* @return parameter value * @return parameter value
*/ */
unsigned long getGPValue(unsigned long GPNumber) unsigned long getGPValue(unsigned int port, unsigned long GPNumber)
{ {
return (GPNumber >= FRAMEPAR_GLOBALS) ? return (GPNumber >= FRAMEPAR_GLOBALS) ?
GLOBALPARS(GPNumber) : GLOBALPARS(port, GPNumber) :
framePars[GLOBALPARS(G_THIS_FRAME) & PARS_FRAMES_MASK].pars[GPNumber]; framePars[port][GLOBALPARS(port, G_THIS_FRAME) & PARS_FRAMES_MASK].pars[GPNumber];
} }
/** /**
* @brief Set value of the specified global (G_*) parameter * @brief Set value of the specified global (G_*) parameter
* @param GNumber - parameter number (as defined in c313a.h) * @param[in] GNumber parameter number (as defined in c313a.h)
* @param value - value to set * @param[in] value value to set
* @return none
*/ */
void setGValue(unsigned long GNumber, unsigned long value) void setGValue(unsigned int port, unsigned long GNumber, unsigned long value)
{ {
GLOBALPARS(GNumber) = value; GLOBALPARS(port, GNumber) = value;
} }
/** /**
* @brief check if this application is enabled (by appropriate bit in P_DAEMON_EN), if not - * @brief Check if this application is enabled (by appropriate bit in P_DAEMON_EN), if not -
* and wait until enabled (return false when enabled) * and wait until enabled (return false when enabled)
* @param daemonBit - bit number to accept control in P_DAEMON_EN parameter * @param[in] daemonBit bit number to accept control in P_DAEMON_EN parameter
* @return (after possible waiting) true if there was no waiting, false if there was waiting * @return (after possible waiting) true if there was no waiting, false if there was waiting
*/ */
int waitDaemonEnabled(int daemonBit) // <0 - use default int waitDaemonEnabled(unsigned int port, int daemonBit) // <0 - use default
{ {
if ((daemonBit >= 0) && (daemonBit < 32)) lastDaemonBit = daemonBit; camogm_state *state = &sstate[port];
unsigned long this_frame = this_frame = GLOBALPARS(G_THIS_FRAME); if ((daemonBit >= 0) && (daemonBit < 32)) lastDaemonBit[port] = daemonBit;
/// No semaphors, so it is possible to miss event and wait until the streamer will be re-enabled before sending message, unsigned long this_frame = GLOBALPARS(port, G_THIS_FRAME);
/// but it seems not so terrible // No semaphors, so it is possible to miss event and wait until the streamer will be re-enabled before sending message,
lseek(state->fd_circ, LSEEK_DAEMON_CIRCBUF + lastDaemonBit, SEEK_END); /// // but it seems not so terrible
if (this_frame == GLOBALPARS(G_THIS_FRAME)) return 1; lseek(state->fd_circ, LSEEK_DAEMON_CIRCBUF + lastDaemonBit[port], SEEK_END); ///
if (this_frame == GLOBALPARS(port, G_THIS_FRAME)) return 1;
return 0; return 0;
} }
/** /**
* @brief check if this application is enabled (by appropriate bit in P_DAEMON_EN) * @brief Check if this application is enabled (by appropriate bit in P_DAEMON_EN)
* @param daemonBit - bit number to accept control in P_DAEMON_EN parameter * @param[in] daemonBit bit number to accept control in P_DAEMON_EN parameter
* @return (after possible waiting) true if there was no waiting, false if there was waiting * @return (after possible waiting) true if there was no waiting, false if there was waiting
*/ */
int isDaemonEnabled(int daemonBit) // <0 - use default int isDaemonEnabled(unsigned int port, int daemonBit) // <0 - use default
{ {
if ((daemonBit >= 0) && (daemonBit < 32)) lastDaemonBit = daemonBit; if ((daemonBit >= 0) && (daemonBit < 32)) lastDaemonBit[port] = daemonBit;
return ((framePars[GLOBALPARS(G_THIS_FRAME) & PARS_FRAMES_MASK].pars[P_DAEMON_EN] & (1 << lastDaemonBit)) != 0); return ((framePars[port][GLOBALPARS(port, G_THIS_FRAME) & PARS_FRAMES_MASK].pars[P_DAEMON_EN] & (1 << lastDaemonBit[port])) != 0);
} }
#ifndef _CAMOGM_H
#define _CAMOGM_H
#define CAMOGM_FRAME_NOT_READY 1 // frame pointer valid, but not yet acquired #define CAMOGM_FRAME_NOT_READY 1 // frame pointer valid, but not yet acquired
#define CAMOGM_FRAME_INVALID 2 // invalid frame pointer #define CAMOGM_FRAME_INVALID 2 // invalid frame pointer
#define CAMOGM_FRAME_CHANGED 3 // frame parameters have changed #define CAMOGM_FRAME_CHANGED 3 // frame parameters have changed
...@@ -155,16 +158,18 @@ typedef struct { ...@@ -155,16 +158,18 @@ typedef struct {
int kml_last_uts; //! last generated kml file timestamp, microseconds int kml_last_uts; //! last generated kml file timestamp, microseconds
struct exif_dir_table_t kml_exif[ExifKmlNumber]; //! store locations of the fields needed for KML generations in the Exif block struct exif_dir_table_t kml_exif[ExifKmlNumber]; //! store locations of the fields needed for KML generations in the Exif block
unsigned int port_num;
} camogm_state; } camogm_state;
extern int debug_level; extern int debug_level;
extern FILE* debug_file; extern FILE* debug_file;
extern camogm_state * state; //extern camogm_state * state;
void put_uint16(void *buf, u_int16_t val); void put_uint16(void *buf, u_int16_t val);
void put_uint32(void *buf, u_int32_t val); void put_uint32(void *buf, u_int32_t val);
void put_uint64(void *buf, u_int64_t val); void put_uint64(void *buf, u_int64_t val);
unsigned long getGPValue(unsigned long GPNumber); unsigned long getGPValue(unsigned int port, unsigned long GPNumber);
void setGValue(unsigned long GNumber, unsigned long value); //void setGValue(unsigned long GNumber, unsigned long value);
int waitDaemonEnabled(int daemonBit); // <0 - use default //int waitDaemonEnabled(int daemonBit); // <0 - use default
int isDaemonEnabled(int daemonBit); // <0 - use default //int isDaemonEnabled(int daemonBit); // <0 - use default
#endif /* _CAMOGM_H */
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
#include "ogmstreams.h" // move it to <>? #include "ogmstreams.h" // move it to <>?
#include "camogm_jpeg.h" #include "camogm_jpeg.h"
#include "camogm.h"
//! may add something - called first time format is changed to this one (only once) recording is stopped //! may add something - called first time format is changed to this one (only once) recording is stopped
int camogm_init_jpeg(void) int camogm_init_jpeg(void)
{ {
...@@ -72,7 +72,7 @@ void camogm_free_jpeg(void) ...@@ -72,7 +72,7 @@ void camogm_free_jpeg(void)
{ {
} }
int camogm_start_jpeg(void) int camogm_start_jpeg(camogm_state *state)
{ {
//!TODO: make directory if it does not exist (find the last "/" in the state->path //!TODO: make directory if it does not exist (find the last "/" in the state->path
char * slash; char * slash;
...@@ -94,7 +94,8 @@ int camogm_start_jpeg(void) ...@@ -94,7 +94,8 @@ int camogm_start_jpeg(void)
} }
return 0; return 0;
} }
int camogm_frame_jpeg(void)
int camogm_frame_jpeg(camogm_state *state)
{ {
int i, j; int i, j;
// int fd; // int fd;
......
#ifndef _CAMOGM_JPEG_H
#define _CAMOGM_JPEG_H
#include "camogm.h"
int camogm_init_jpeg(void); int camogm_init_jpeg(void);
int camogm_start_jpeg(void); int camogm_start_jpeg(camogm_state *state);
int camogm_frame_jpeg(void); int camogm_frame_jpeg(camogm_state *state);
int camogm_end_jpeg(void); int camogm_end_jpeg(void);
void camogm_free_jpeg(void); void camogm_free_jpeg(void);
#endif /* _CAMOGM_JPEG_H */
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
#include "ogmstreams.h" // move it to <>? #include "ogmstreams.h" // move it to <>?
#include "camogm_kml.h" #include "camogm_kml.h"
#include "camogm.h"
const char ExifDirFileName[] = "/dev/exif_metadir"; const char ExifDirFileName[] = "/dev/exif_metadir";
//! may add something - called first time format is changed to this one (only once) recording is stopped //! may add something - called first time format is changed to this one (only once) recording is stopped
...@@ -93,7 +93,7 @@ void camogm_free_kml(void) ...@@ -93,7 +93,7 @@ void camogm_free_kml(void)
} }
*/ */
int camogm_start_kml(void) int camogm_start_kml(camogm_state *state)
{ {
// struct exif_dir_table_t kml_exif[ExifKmlNumber] ; //! store locations of the fields needed for KML generations in the Exif block // struct exif_dir_table_t kml_exif[ExifKmlNumber] ; //! store locations of the fields needed for KML generations in the Exif block
///exif_metadir ///exif_metadir
...@@ -152,7 +152,7 @@ int camogm_start_kml(void) ...@@ -152,7 +152,7 @@ int camogm_start_kml(void)
return 0; return 0;
} }
int camogm_frame_kml(void) int camogm_frame_kml(camogm_state *state)
{ {
char JPEGFileName[300]; char JPEGFileName[300];
char * filename; char * filename;
...@@ -316,7 +316,7 @@ int camogm_frame_kml(void) ...@@ -316,7 +316,7 @@ int camogm_frame_kml(void)
} }
int camogm_end_kml(void) int camogm_end_kml(camogm_state *state)
{ {
if (state->kml_file) { if (state->kml_file) {
...@@ -327,4 +327,3 @@ int camogm_end_kml(void) ...@@ -327,4 +327,3 @@ int camogm_end_kml(void)
} }
return 0; return 0;
} }
int camogm_init_kml(void); #ifndef _CAMOGM_KML_H
int camogm_start_kml(void); #define _CAMOGM_KML_H
int camogm_frame_kml(void);
int camogm_end_kml(void);
void camogm_free_kml(void);
#include "camogm.h"
int camogm_init_kml(void);
int camogm_start_kml(camogm_state *state);
int camogm_frame_kml(camogm_state *state);
int camogm_end_kml(camogm_state *state);
void camogm_free_kml(void);
#endif /* _CAMOGM_KML_H */
/* /*
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
......
...@@ -66,7 +66,6 @@ ...@@ -66,7 +66,6 @@
#include "ogmstreams.h" // move it to <>? #include "ogmstreams.h" // move it to <>?
#include "camogm_mov.h" #include "camogm_mov.h"
#include "camogm.h"
#define QUICKTIME_MIN_HEADER 0x300 // Quicktime header length (w/o index tables) enough to accomodate #define QUICKTIME_MIN_HEADER 0x300 // Quicktime header length (w/o index tables) enough to accomodate
// static data . // static data .
...@@ -93,7 +92,8 @@ long headerSize = 0; ...@@ -93,7 +92,8 @@ long headerSize = 0;
const char *iFile = NULL; const char *iFile = NULL;
int quicktime_template_parser(const char * i_iFile, //! now - string containing header template int quicktime_template_parser(camogm_state *state,
const char * i_iFile, //! now - string containing header template
int i_ofd, //!output file descriptor (opened) int i_ofd, //!output file descriptor (opened)
int i_width, // width in pixels int i_width, // width in pixels
int i_height, int i_height,
...@@ -107,7 +107,7 @@ int quicktime_template_parser(const char * i_iFile, //! now - string contain ...@@ -107,7 +107,7 @@ int quicktime_template_parser(const char * i_iFile, //! now - string contain
); );
void putBigEndian(unsigned long d, int l); void putBigEndian(unsigned long d, int l);
int parse_special(void); int parse_special(void);
int parse(int top); int parse(camogm_state *state, int top);
//! called first time format is changed to this one (only once) recording is stopped //! called first time format is changed to this one (only once) recording is stopped
//! read frame template from the file if it is not done yet //! read frame template from the file if it is not done yet
int camogm_init_mov(void) int camogm_init_mov(void)
...@@ -147,7 +147,7 @@ void camogm_free_mov(void) ...@@ -147,7 +147,7 @@ void camogm_free_mov(void)
} }
} }
int camogm_start_mov(void) int camogm_start_mov(camogm_state *state)
{ {
//! allocate memory for the frame index table //! allocate memory for the frame index table
...@@ -165,7 +165,7 @@ int camogm_start_mov(void) ...@@ -165,7 +165,7 @@ int camogm_start_mov(void)
return 0; return 0;
} }
int camogm_frame_mov(void) int camogm_frame_mov(camogm_state *state)
{ {
int i, j; int i, j;
ssize_t iovlen, l; ssize_t iovlen, l;
...@@ -188,8 +188,13 @@ int camogm_frame_mov(void) ...@@ -188,8 +188,13 @@ int camogm_frame_mov(void)
state->frame_lengths[state->frameno] = l; state->frame_lengths[state->frameno] = l;
return 0; return 0;
} }
//!move to the start of the file and insert generated header
int camogm_end_mov(void) /**
* @brief Move to the start of the file and insert generated header
* @param[in] state pointer to the #camogm_state structure for current sensor port
* @return this function is always successful and returns 0
*/
int camogm_end_mov(camogm_state *state)
{ {
off_t l/*,he; off_t l/*,he;
unsigned char mdat_tag[8]; unsigned char mdat_tag[8];
...@@ -201,7 +206,8 @@ int camogm_end_mov(void) ...@@ -201,7 +206,8 @@ int camogm_end_mov(void)
// lseek(state->ivf, state->frame_data_start, SEEK_SET); // lseek(state->ivf, state->frame_data_start, SEEK_SET);
// fill in the header in the beginning of the file // fill in the header in the beginning of the file
lseek(state->ivf, 0, SEEK_SET); lseek(state->ivf, 0, SEEK_SET);
quicktime_template_parser(q_template, //! now - string containing header template quicktime_template_parser(state,
q_template, //! now - string containing header template
state->ivf, //!output file descriptor (opened) state->ivf, //!output file descriptor (opened)
state->width, //! width in pixels state->width, //! width in pixels
state->height, state->height,
...@@ -240,13 +246,14 @@ int camogm_end_mov(void) ...@@ -240,13 +246,14 @@ int camogm_end_mov(void)
return 0; return 0;
} }
/* /**
starts with the input file pointer just after the opening "{", * @brief Starts with the input file pointer just after the opening "{",
and output file - at the beginning of it's output * and output file - at the beginning of it's output
on exit - input pointer - after closing "}", output after it's output * on exit - input pointer - after closing "}", output after it's output
* @param[in] d
* @param[in] l
* @return none
*/ */
void putBigEndian(unsigned long d, int l) void putBigEndian(unsigned long d, int l)
{ {
unsigned char od[4]; unsigned char od[4];
...@@ -258,6 +265,7 @@ void putBigEndian(unsigned long d, int l) ...@@ -258,6 +265,7 @@ void putBigEndian(unsigned long d, int l)
if (l) write(ofd, &od[4 - l], l); if (l) write(ofd, &od[4 - l], l);
// oPos+=l; // oPos+=l;
} }
//!temporary replacement for fgets to read from string //!temporary replacement for fgets to read from string
char * sfgets(char * str, int size, const char * stream, int * pos) char * sfgets(char * str, int size, const char * stream, int * pos)
{ {
...@@ -367,9 +375,7 @@ int parse_special(void) ...@@ -367,9 +375,7 @@ int parse_special(void)
return -1; return -1;
} }
int parse(camogm_state *state, int top) // if top - will not include length
int parse(int top) // if top - will not include length
{ {
long out_start, out_end; long out_start, out_end;
char c; char c;
...@@ -395,7 +401,7 @@ int parse(int top) // if top - will not include length ...@@ -395,7 +401,7 @@ int parse(int top) // if top - will not include length
} }
// children atoms // children atoms
else if (c == '{') { else if (c == '{') {
if (parse(0) < 0) return -1; if (parse(state, 0) < 0) return -1;
// skip comments // skip comments
// } else if (c=='#') fgets( comStr, sizeof(comStr), infile); // } else if (c=='#') fgets( comStr, sizeof(comStr), infile);
} else if (c == '#') sfgets( comStr, sizeof(comStr), iFile, &iPos); } else if (c == '#') sfgets( comStr, sizeof(comStr), iFile, &iPos);
...@@ -455,7 +461,8 @@ int parse(int top) // if top - will not include length ...@@ -455,7 +461,8 @@ int parse(int top) // if top - will not include length
} }
int quicktime_template_parser(const char * i_iFile, //! now - string containing header template int quicktime_template_parser( camogm_state *state,
const char * i_iFile, //! now - string containing header template
int i_ofd, //!output file descriptor (opened) int i_ofd, //!output file descriptor (opened)
int i_width, // width in pixels int i_width, // width in pixels
int i_height, int i_height,
...@@ -486,7 +493,7 @@ int quicktime_template_parser(const char * i_iFile, //! now - string contain ...@@ -486,7 +493,7 @@ int quicktime_template_parser(const char * i_iFile, //! now - string contain
D3(fprintf(debug_file, "PASS I\n")); D3(fprintf(debug_file, "PASS I\n"));
// while ( feof(infile) == 0 ) parse(1); // pass 1 // while ( feof(infile) == 0 ) parse(1); // pass 1
while ( iPos < iFileLen ) parse(1); // pass 1 while ( iPos < iFileLen ) parse(state, 1); // pass 1
// headerSize=ftell (outfile); // headerSize=ftell (outfile);
// fseek (outfile,0,SEEK_SET); // rewind for pass 2 // fseek (outfile,0,SEEK_SET); // rewind for pass 2
// fseek (infile, 0,SEEK_SET); // // fseek (infile, 0,SEEK_SET); //
...@@ -498,7 +505,7 @@ int quicktime_template_parser(const char * i_iFile, //! now - string contain ...@@ -498,7 +505,7 @@ int quicktime_template_parser(const char * i_iFile, //! now - string contain
D3(fprintf(debug_file, "PASS II\n")); D3(fprintf(debug_file, "PASS II\n"));
// while ( feof(infile) == 0 ) parse(1); // pass 2 // while ( feof(infile) == 0 ) parse(1); // pass 2
while ( iPos < iFileLen ) parse(1); // pass 2 while ( iPos < iFileLen ) parse(state, 1); // pass 2
//fclose (infile); //fclose (infile);
//fclose (outfile); //fclose (outfile);
......
#ifndef _CAMOGM_MOV_H
#define _CAMOG_MOV_H
#include "camogm.h"
int camogm_init_mov(void); int camogm_init_mov(void);
int camogm_start_mov(void); int camogm_start_mov(camogm_state *state);
int camogm_frame_mov(void); int camogm_frame_mov(camogm_state *state);
int camogm_end_mov(void); int camogm_end_mov(camogm_state *state);
void camogm_free_mov(void); void camogm_free_mov(void);
#endif /* _CAMOGM_MOV_H */
...@@ -54,12 +54,11 @@ ...@@ -54,12 +54,11 @@
#include <c313a.h> #include <c313a.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <ogg/ogg.h> // has to be before ogmstreams.h #include <ogg/ogg.h> // has to be before ogmstreams.h
#include "ogmstreams.h" // move it to <>? #include "ogmstreams.h" // move it to <>?
#include "camogm_ogm.h" #include "camogm_ogm.h"
#include "camogm.h"
//! may add something - called first time format is changed to this one (only once) recording is stopped //! may add something - called first time format is changed to this one (only once) recording is stopped
int camogm_init_ogm(void) int camogm_init_ogm(void)
{ {
...@@ -69,8 +68,7 @@ void camogm_free_ogm(void) ...@@ -69,8 +68,7 @@ void camogm_free_ogm(void)
{ {
} }
int camogm_start_ogm(camogm_state *state)
int camogm_start_ogm(void)
{ {
char vendor[] = "ElphelOgm v 0.1"; char vendor[] = "ElphelOgm v 0.1";
int pos; int pos;
...@@ -171,7 +169,7 @@ int camogm_start_ogm(void) ...@@ -171,7 +169,7 @@ int camogm_start_ogm(void)
return 0; return 0;
} }
int camogm_frame_ogm(void) int camogm_frame_ogm(camogm_state *state)
{ {
int indx; int indx;
elph_ogg_packet elp_packet; elph_ogg_packet elp_packet;
...@@ -219,10 +217,9 @@ int camogm_frame_ogm(void) ...@@ -219,10 +217,9 @@ int camogm_frame_ogm(void)
return 0; return 0;
} }
//!Zero packets are OK, use them to end file with "last" turned on //!Zero packets are OK, use them to end file with "last" turned on
int camogm_end_ogm(void) int camogm_end_ogm(camogm_state *state)
{ {
//! put zero-packet it into stream //! put zero-packet it into stream
ogg_packet ogg_header; ogg_packet ogg_header;
...@@ -245,6 +242,3 @@ int camogm_end_ogm(void) ...@@ -245,6 +242,3 @@ int camogm_end_ogm(void)
} }
return 0; return 0;
} }
#ifndef _CAMOGM_OGM_H
#define _CAMOGM_OGM_H
#include "camogm.h"
int camogm_init_ogm(void); int camogm_init_ogm(void);
int camogm_start_ogm(void); int camogm_start_ogm(camogm_state *state);
int camogm_frame_ogm(void); int camogm_frame_ogm(camogm_state *state);
int camogm_end_ogm(void); int camogm_end_ogm(camogm_state *state);
void camogm_free_ogm(void); void camogm_free_ogm(void);
#endif /* _CAMOGM_OGM_H */
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