Commit 786c0e75 authored by Mikhail Karpenko's avatar Mikhail Karpenko

Fix formatting

Fix source code formatting with 'uncrustify' command-line utility
parent 045b76e0
/*!*************************************************************************** /*!***************************************************************************
*! FILE NAME : camogm.c *! FILE NAME : camogm.c
*! DESCRIPTION: Program to write captured video (and audio) to camera file system *! DESCRIPTION: Program to write captured video (and audio) to camera file system
*! using Ogg container. *! using Ogg container.
*! Original implementation will copy package data to a buffer to use library calls? *! Original implementation will copy package data to a buffer to use library calls?
*! Copyright (C) 2007 Elphel, Inc. *! Copyright (C) 2007 Elphel, Inc.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify *! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by *! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or *! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version. *! (at your option) any later version.
*! *!
*! This program is distributed in the hope that it will be useful, *! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of *! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details. *! GNU General Public License for more details.
*! *!
*! You should have received a copy of the GNU General Public License *! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>. *! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! *!
*! $Log: camogm.c,v $ *! $Log: camogm.c,v $
*! Revision 1.13 2011/04/22 22:38:30 elphel *! Revision 1.13 2011/04/22 22:38:30 elphel
*! added "greedy" and "ignore_fps" options *! added "greedy" and "ignore_fps" options
*! *!
*! Revision 1.12 2010/08/16 17:10:59 elphel *! Revision 1.12 2010/08/16 17:10:59 elphel
*! typo *! typo
*! *!
*! Revision 1.11 2010/08/08 21:14:04 elphel *! Revision 1.11 2010/08/08 21:14:04 elphel
*! 8.0.8.38 *! 8.0.8.38
*! *!
*! Revision 1.10 2010/08/07 23:38:01 elphel *! Revision 1.10 2010/08/07 23:38:01 elphel
*! fixed skipping (sometimes) frames at start recording *! fixed skipping (sometimes) frames at start recording
*! *!
*! Revision 1.9 2010/08/03 06:19:57 elphel *! Revision 1.9 2010/08/03 06:19:57 elphel
*! more debug for debug-level>=3 *! more debug for debug-level>=3
*! *!
*! Revision 1.8 2010/08/02 01:26:42 elphel *! Revision 1.8 2010/08/02 01:26:42 elphel
*! error tracking *! error tracking
*! *!
*! Revision 1.7 2010/08/01 19:30:24 elphel *! Revision 1.7 2010/08/01 19:30:24 elphel
*! new readonly parameter FRAME_SIZE and it support in the applications *! new readonly parameter FRAME_SIZE and it support in the applications
*! *!
*! Revision 1.6 2010/07/18 16:59:09 elphel *! Revision 1.6 2010/07/18 16:59:09 elphel
*! 8.0.8.31 - added parameters to camogm (one is to start at certain absolute time, helps to synchronize multiple cameras) *! 8.0.8.31 - added parameters to camogm (one is to start at certain absolute time, helps to synchronize multiple cameras)
*! *!
*! Revision 1.5 2010/07/04 19:06:02 elphel *! Revision 1.5 2010/07/04 19:06:02 elphel
*! moved acknowledge earlier *! moved acknowledge earlier
*! *!
*! Revision 1.4 2010/06/22 18:27:26 elphel *! Revision 1.4 2010/06/22 18:27:26 elphel
*! bug fix *! bug fix
*! *!
*! Revision 1.3 2010/06/22 16:53:30 elphel *! Revision 1.3 2010/06/22 16:53:30 elphel
*! camogm acknowledges received command by copying G_THIS_FRAME value to G_DAEMON_ERR+3 (default number for camogm) *! camogm acknowledges received command by copying G_THIS_FRAME value to G_DAEMON_ERR+3 (default number for camogm)
*! *!
*! Revision 1.2 2009/02/25 17:50:02 spectr_rain *! Revision 1.2 2009/02/25 17:50:02 spectr_rain
*! removed deprecated dependency *! removed deprecated dependency
*! *!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel *! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*! *!
*! *!
*! Revision 1.6 2008/11/21 01:52:53 elphel *! Revision 1.6 2008/11/21 01:52:53 elphel
*! updated for 8.0 *! updated for 8.0
*! *!
*! Revision 1.5 2008/11/20 23:21:32 elphel *! Revision 1.5 2008/11/20 23:21:32 elphel
*! Put FIXME notes and removed parameters that are not used anymore *! Put FIXME notes and removed parameters that are not used anymore
*! *!
*! Revision 1.4 2008/10/29 04:18:28 elphel *! Revision 1.4 2008/10/29 04:18:28 elphel
*! v.8.0.alpha10 made a separate structure for global parameters (not related to particular frames in a frame queue) *! v.8.0.alpha10 made a separate structure for global parameters (not related to particular frames in a frame queue)
*! *!
*! Revision 1.3 2008/10/13 16:55:53 elphel *! Revision 1.3 2008/10/13 16:55:53 elphel
*! removed (some) obsolete P_* parameters, renamed CIRCLSEEK to LSEEK_CIRC constants (same as other similar) *! removed (some) obsolete P_* parameters, renamed CIRCLSEEK to LSEEK_CIRC constants (same as other similar)
*! *!
*! Revision 1.2 2008/09/07 19:48:08 elphel *! Revision 1.2 2008/09/07 19:48:08 elphel
*! snapshot *! snapshot
*! *!
*! Revision 1.9 2008/04/13 21:05:19 elphel *! Revision 1.9 2008/04/13 21:05:19 elphel
*! Fixing KML generation *! Fixing KML generation
*! *!
*! Revision 1.8 2008/04/11 23:09:33 elphel *! Revision 1.8 2008/04/11 23:09:33 elphel
*! modified to handle kml generation *! modified to handle kml generation
*! *!
*! Revision 1.7 2008/04/07 09:13:34 elphel *! Revision 1.7 2008/04/07 09:13:34 elphel
*! Changes related to new Exif generation/processing *! Changes related to new Exif generation/processing
*! *!
*! Revision 1.6 2008/01/14 22:59:00 elphel *! Revision 1.6 2008/01/14 22:59:00 elphel
*! 7.1.7.4 - added timelapse mode to camogm *! 7.1.7.4 - added timelapse mode to camogm
*! *!
*! Revision 1.5 2007/12/03 08:28:45 elphel *! Revision 1.5 2007/12/03 08:28:45 elphel
*! Multiple changes, mostly cleanup *! Multiple changes, mostly cleanup
*! *!
*! Revision 1.4 2007/11/29 00:38:57 elphel *! Revision 1.4 2007/11/29 00:38:57 elphel
*! fixed timescale bug *! fixed timescale bug
*! *!
*! Revision 1.3 2007/11/19 05:07:19 elphel *! Revision 1.3 2007/11/19 05:07:19 elphel
*! fixed 2 typos *! fixed 2 typos
*! *!
*! Revision 1.2 2007/11/19 03:23:21 elphel *! Revision 1.2 2007/11/19 03:23:21 elphel
*! 7.1.5.5 Added support for *.mov files in camogm. *! 7.1.5.5 Added support for *.mov files in camogm.
*! *!
*! Revision 1.1 2007/11/16 08:49:56 elphel *! Revision 1.1 2007/11/16 08:49:56 elphel
*! Initial release of camogm - program to record video/image to the camera hard drive (or other storage) *! Initial release of camogm - program to record video/image to the camera hard drive (or other storage)
*! *!
*/ */
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -126,7 +125,6 @@ ...@@ -126,7 +125,6 @@
#include <exifa.h> #include <exifa.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 <>?
...@@ -138,22 +136,21 @@ ...@@ -138,22 +136,21 @@
#include "camogm.h" #include "camogm.h"
#define TRAILER_SIZE 0x02 #define TRAILER_SIZE 0x02
#define MAP_OPTIONS MAP_FILE|MAP_PRIVATE #define MAP_OPTIONS MAP_FILE | MAP_PRIVATE
char trailer[TRAILER_SIZE] = {0xff,0xd9}; char trailer[TRAILER_SIZE] = { 0xff, 0xd9 };
const char ExifFileName[]="/dev/exif_exif"; const char ExifFileName[] = "/dev/exif_exif";
const char HeadFileName[]="/dev/jpeghead"; const char HeadFileName[] = "/dev/jpeghead";
const char ctlFileName[]="/dev/frameparsall"; const char ctlFileName[] = "/dev/frameparsall";
unsigned long * ccam_dma_buf; /* mmapped array */ unsigned long * ccam_dma_buf; /* mmapped array */
int lastDaemonBit= DAEMON_BIT_CAMOGM; int lastDaemonBit = DAEMON_BIT_CAMOGM;
struct framepars_all_t *frameParsAll; struct framepars_all_t *frameParsAll;
struct framepars_t *framePars; struct framepars_t *framePars;
unsigned long *globalPars; /// parameters that are not frame-related, their changes do not initiate any actions unsigned long *globalPars; /// parameters that are not frame-related, their changes do not initiate any actions
int buff_size; int buff_size;
#define DEFAULT_DURATION 60 /*!default segment duration (seconds) */ #define DEFAULT_DURATION 60 /*!default segment duration (seconds) */
...@@ -170,8 +167,8 @@ int buff_size; ...@@ -170,8 +167,8 @@ int buff_size;
#define DEFAULT_EXIF 1 /* use Exif */ #define DEFAULT_EXIF 1 /* use Exif */
static char cmdbuf[1024]; 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;
camogm_state * state; camogm_state * state;
...@@ -179,15 +176,8 @@ camogm_state * state; ...@@ -179,15 +176,8 @@ camogm_state * state;
int debug_level; int debug_level;
FILE* debug_file; FILE* debug_file;
int camogm_init(void); int camogm_init(void);
int camogm_start(void); int camogm_start(void);
int camogm_stop(void); int camogm_stop(void);
int camogm_reset(void); //! reset circbuf read pointer int camogm_reset(void); //! reset circbuf read pointer
int camogm_debug(const char * fname); int camogm_debug(const char * fname);
...@@ -198,25 +188,24 @@ void camogm_set_greedy(int d); ...@@ -198,25 +188,24 @@ void camogm_set_greedy(int d);
void camogm_set_ignore_fps(int d); void camogm_set_ignore_fps(int d);
void camogm_set_save_gp(int d); void camogm_set_save_gp(int d);
void camogm_set_prefix (const char * p); void camogm_set_prefix(const char * p);
void camogm_set_exif(int d); void camogm_set_exif(int d);
void camogm_set_timescale(double d); //! set timescale, default=1.0 void camogm_set_timescale(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(int d); //! set number of frames to skip, if negative - seconds between frames
void camogm_set_format(int d); void camogm_set_format(int d);
void camogm_kml_set_enable(int d); void camogm_kml_set_enable(int d);
void camogm_kml_set_horHalfFov (double dd); void camogm_kml_set_horHalfFov(double dd);
void camogm_kml_set_vertHalfFov(double dd); void camogm_kml_set_vertHalfFov(double dd);
void camogm_kml_set_height_mode(int d); void camogm_kml_set_height_mode(int d);
void camogm_kml_set_height(double dd); void camogm_kml_set_height(double dd);
void camogm_kml_set_period(int d); void camogm_kml_set_period(int d);
void camogm_kml_set_near(double dd); // distance to PhotoOverlay void camogm_kml_set_near(double dd); // distance to PhotoOverlay
int parse_cmd(FILE* npipe); int parse_cmd(FILE* npipe);
char * getLineFromPipe(FILE* npipe); char * getLineFromPipe(FILE* npipe);
int sendImageFrame (void); int sendImageFrame(void);
void camogm_set_start_after_timestamp(double d); void camogm_set_start_after_timestamp(double d);
void camogm_set_max_frames(int d); void camogm_set_max_frames(int d);
...@@ -228,7 +217,7 @@ void put_uint16(void *buf, u_int16_t val) ...@@ -228,7 +217,7 @@ void put_uint16(void *buf, u_int16_t val)
{ {
unsigned char *tmp; unsigned char *tmp;
tmp = (unsigned char *) buf; tmp = (unsigned char*)buf;
tmp[0] = val & 0xff; tmp[0] = val & 0xff;
tmp[1] = (val >>= 8) & 0xff; tmp[1] = (val >>= 8) & 0xff;
...@@ -238,7 +227,7 @@ void put_uint32(void *buf, u_int32_t val) ...@@ -238,7 +227,7 @@ void put_uint32(void *buf, u_int32_t val)
{ {
unsigned char *tmp; unsigned char *tmp;
tmp = (unsigned char *) buf; tmp = (unsigned char*)buf;
tmp[0] = val & 0xff; tmp[0] = val & 0xff;
tmp[1] = (val >>= 8) & 0xff; tmp[1] = (val >>= 8) & 0xff;
...@@ -250,7 +239,7 @@ void put_uint64(void *buf, u_int64_t val) ...@@ -250,7 +239,7 @@ void put_uint64(void *buf, u_int64_t val)
{ {
unsigned char *tmp; unsigned char *tmp;
tmp = (unsigned char *) buf; tmp = (unsigned char*)buf;
tmp[0] = val & 0xff; tmp[0] = val & 0xff;
tmp[1] = (val >>= 8) & 0xff; tmp[1] = (val >>= 8) & 0xff;
...@@ -262,12 +251,14 @@ void put_uint64(void *buf, u_int64_t val) ...@@ -262,12 +251,14 @@ 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(void)
const char sserial[]="elp0"; {
int * ipser= (int*) sserial; const char sserial[] = "elp0";
state->running=0; // mo int * ipser = (int*)sserial;
state->starting=0; // mo
state->vf=NULL; state->running = 0; // mo
state->starting = 0; // mo
state->vf = NULL;
camogm_set_segment_duration(DEFAULT_DURATION); camogm_set_segment_duration(DEFAULT_DURATION);
camogm_set_segment_length(DEFAULT_LENGTH); camogm_set_segment_length(DEFAULT_LENGTH);
camogm_set_greedy(DEFAULT_GREEDY); camogm_set_greedy(DEFAULT_GREEDY);
...@@ -275,640 +266,670 @@ int camogm_init(void) { ...@@ -275,640 +266,670 @@ int camogm_init(void) {
camogm_set_max_frames(DEFAULT_FRAMES); camogm_set_max_frames(DEFAULT_FRAMES);
camogm_set_frames_per_chunk(DEFAULT_FRAMES_PER_CHUNK); camogm_set_frames_per_chunk(DEFAULT_FRAMES_PER_CHUNK);
camogm_set_start_after_timestamp(0.0); /// start any time camogm_set_start_after_timestamp(0.0); /// start any time
camogm_set_prefix ("\0"); camogm_set_prefix("\0");
camogm_set_save_gp(0); camogm_set_save_gp(0);
camogm_reset(); //! sets state->buf_overruns=-1; //!first does not count camogm_reset(); //! 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(1.0);
camogm_set_frames_skip(0); //! don't skip camogm_set_frames_skip(0); //! don't skip
camogm_set_format(CAMOGM_FORMAT_OGM); camogm_set_format(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;
state->frameno=0; state->frameno = 0;
state->formats=0; state->formats = 0;
state->last_error_code=0; state->last_error_code = 0;
///kml stuff ///kml stuff
camogm_kml_set_enable(0); camogm_kml_set_enable(0);
state->kml_file=NULL; state->kml_file = NULL;
camogm_kml_set_horHalfFov (20.0); camogm_kml_set_horHalfFov(20.0);
camogm_kml_set_vertHalfFov(15.0); camogm_kml_set_vertHalfFov(15.0);
camogm_kml_set_height_mode(0); camogm_kml_set_height_mode(0);
camogm_kml_set_height(10.0); camogm_kml_set_height(10.0);
camogm_kml_set_period(2); // 2 sec camogm_kml_set_period(2); // 2 sec
camogm_kml_set_near(40.0); // 40 m (distance to PhotoOverlay) camogm_kml_set_near(40.0); // 40 m (distance to PhotoOverlay)
state->kml_path[0]='\0'; state->kml_path[0] = '\0';
return 0; return 0;
} }
int camogm_debug(const char * fname) { int camogm_debug(const char * fname)
int none=1; {
if (fname && strlen(fname) && strcmp(fname, "none") && strcmp(fname, "null") && strcmp(fname, "/dev/null")) none=0; int none = 1;
if (debug_file){
if (strcmp(state->debug_name, "stdout") && strcmp(state->debug_name, "stderr")) fclose (debug_file); if (fname && strlen(fname) && strcmp(fname, "none") && strcmp(fname, "null") && strcmp(fname, "/dev/null")) none = 0;
debug_file=NULL; if (debug_file) {
state->debug_name[0]='\0'; if (strcmp(state->debug_name, "stdout") && strcmp(state->debug_name, "stderr")) fclose(debug_file);
debug_file = NULL;
state->debug_name[0] = '\0';
} }
if (!none) { if (!none) {
if (strcmp(fname, "stdout") ==0) debug_file=stdout; if (strcmp(fname, "stdout") == 0) debug_file = stdout;
else if (strcmp(fname, "stderr") ==0) debug_file=stderr; else if (strcmp(fname, "stderr") == 0) debug_file = stderr;
else debug_file=fopen(fname,"w+"); else debug_file = fopen(fname, "w+");
} }
if (debug_file) { if (debug_file) {
strncpy(state->debug_name,fname,sizeof(state->debug_name)-1); strncpy(state->debug_name, fname, sizeof(state->debug_name) - 1);
state->debug_name[sizeof(state->debug_name)-1]='\0'; state->debug_name[sizeof(state->debug_name) - 1] = '\0';
} }
return 0; return 0;
} }
int camogm_debug_level(int d) { int camogm_debug_level(int d)
debug_level=d; {
debug_level = d;
return 0; return 0;
} }
int camogm_start(void)
{
int camogm_start(void) {
int timestamp_start; int timestamp_start;
int rslt; int rslt;
int next_metadata_start, next_jpeg_len, fp; int next_metadata_start, next_jpeg_len, fp;
D1(fprintf (debug_file,"Starting recording\n"));
D1(fprintf(debug_file, "Starting recording\n"));
double dtime_stamp; double dtime_stamp;
state->frameno=0; state->frameno = 0;
state->timescale= state->set_timescale;//! current timescale, default 1 state->timescale = state->set_timescale; //! current timescale, default 1
///debug ///debug
int * ifp = (int *) &(state->frame_params) ; int * ifp = (int*)&(state->frame_params);
int * ifp_this = (int *) &(state->this_frame_params) ; int * ifp_this = (int*)&(state->this_frame_params);
if (state->kml_enable) camogm_init_kml() ; // do nothing if (state->kml_enable) camogm_init_kml(); // do nothing
if (state->format != state->set_format) { if (state->format != state->set_format) {
state->format= state->set_format; state->format = state->set_format;
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_init_ogm(); break; case CAMOGM_FORMAT_OGM: rslt = camogm_init_ogm(); break;
case CAMOGM_FORMAT_JPEG: rslt= camogm_init_jpeg();break; case CAMOGM_FORMAT_JPEG: rslt = camogm_init_jpeg(); break;
case CAMOGM_FORMAT_MOV: rslt= camogm_init_mov(); break; case CAMOGM_FORMAT_MOV: rslt = camogm_init_mov(); break;
} }
state->formats |= 1 << (state->format); state->formats |= 1 << (state->format);
//! 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->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));
if ((state->cirbuf_rp <0) || (lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET) < 0) || (lseek(state->fd_circ,LSEEK_CIRC_VALID,SEEK_END) < 0 )) { if ((state->cirbuf_rp < 0) || (lseek(state->fd_circ, state->cirbuf_rp, SEEK_SET) < 0) || (lseek(state->fd_circ, LSEEK_CIRC_VALID, SEEK_END) < 0 )) {
D3(fprintf (debug_file,"2: state->cirbuf_rp=0x%x\n",state->cirbuf_rp)); D3(fprintf(debug_file, "2: state->cirbuf_rp=0x%x\n", state->cirbuf_rp));
// state->cirbuf_rp=lseek(state->fd_circ,LSEEK_CIRC_LAST,SEEK_END); // state->cirbuf_rp=lseek(state->fd_circ,LSEEK_CIRC_LAST,SEEK_END);
/* 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=lseek(state->fd_circ, state->greedy?LSEEK_CIRC_SCND:LSEEK_CIRC_LAST,SEEK_END); state->cirbuf_rp = lseek(state->fd_circ, state->greedy ? LSEEK_CIRC_SCND : LSEEK_CIRC_LAST, SEEK_END);
if (!state->ignore_fps) { // don't even try in ignore mode if (!state->ignore_fps) { // don't even try in ignore mode
if (((fp=lseek(state->fd_circ,LSEEK_CIRC_PREV,SEEK_END)))>=0) state->cirbuf_rp=fp; //!try to have 2 frames available for fps if (((fp = lseek(state->fd_circ, LSEEK_CIRC_PREV, SEEK_END))) >= 0) state->cirbuf_rp = fp; //!try to have 2 frames available for fps
} }
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(G_FREECIRCBUF);
} else { } else {
if (state->buf_min > getGPValue(G_FREECIRCBUF)) state->buf_min=getGPValue(G_FREECIRCBUF); if (state->buf_min > getGPValue(G_FREECIRCBUF)) state->buf_min = getGPValue(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));
D3(fprintf (debug_file,"4:lseek(state->fd_circ,LSEEK_CIRC_READY,SEEK_END)=%d\n",(int) lseek(state->fd_circ,LSEEK_CIRC_READY,SEEK_END))); D3(fprintf(debug_file, "4:lseek(state->fd_circ,LSEEK_CIRC_READY,SEEK_END)=%d\n", (int)lseek(state->fd_circ, LSEEK_CIRC_READY, SEEK_END)));
//! is this frame ready? //! is this frame ready?
if (lseek(state->fd_circ,LSEEK_CIRC_READY,SEEK_END) <0) return -CAMOGM_FRAME_NOT_READY; //! frame pointer valid, but no frames yet if (lseek(state->fd_circ, LSEEK_CIRC_READY, SEEK_END) < 0) return -CAMOGM_FRAME_NOT_READY; //! frame pointer valid, but no frames yet
D3(fprintf (debug_file,"5: state->cirbuf_rp=0x%x\n",state->cirbuf_rp)); D3(fprintf(debug_file, "5: state->cirbuf_rp=0x%x\n", state->cirbuf_rp));
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->frame_params), (unsigned long * ) &ccam_dma_buf[state->metadata_start>>2],32); memcpy(&(state->frame_params), (unsigned long* )&ccam_dma_buf[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
if (state->frame_params.signffff !=0xffff) { if (state->frame_params.signffff != 0xffff) {
D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n",__FILE__,__LINE__,(int) state->frame_params.signffff)); D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n", __FILE__, __LINE__, (int)state->frame_params.signffff));
state->cirbuf_rp=-1; state->cirbuf_rp = -1;
D1(fprintf(debug_file, "state->cirbuf_rp=0x%x\r\n",(int) state->cirbuf_rp)); D1(fprintf(debug_file, "state->cirbuf_rp=0x%x\r\n", (int)state->cirbuf_rp));
D1(fprintf(debug_file, "%08x %08x %08x %08x %08x %08x %08x %08x\r\n",ifp[0],ifp[1],ifp[2],ifp[3],ifp[4],ifp[5],ifp[6],ifp[7])); D1(fprintf(debug_file, "%08x %08x %08x %08x %08x %08x %08x %08x\r\n", ifp[0], ifp[1], ifp[2], ifp[3], ifp[4], ifp[5], ifp[6], ifp[7]));
return -CAMOGM_FRAME_BROKEN; return -CAMOGM_FRAME_BROKEN;
} }
//! 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=(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[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;
if (dtime_stamp < state->start_after_timestamp) { if (dtime_stamp < state->start_after_timestamp) {
state->cirbuf_rp=-1; state->cirbuf_rp = -1;
D3(fprintf (debug_file,"Too early to start, %f < %f\n",dtime_stamp,state->start_after_timestamp)); D3(fprintf(debug_file, "Too early to start, %f < %f\n", dtime_stamp, state->start_after_timestamp));
return -CAMOGM_TOO_EARLY; return -CAMOGM_TOO_EARLY;
} }
} }
D3(fprintf (debug_file,"6: state->cirbuf_rp=0x%x\n",state->cirbuf_rp)); D3(fprintf(debug_file, "6: state->cirbuf_rp=0x%x\n", state->cirbuf_rp));
//! see if next frame is available //! see if next frame is available
if ((lseek(state->fd_circ,LSEEK_CIRC_NEXT,SEEK_END) < 0 ) || if ((lseek(state->fd_circ, LSEEK_CIRC_NEXT, SEEK_END) < 0 ) ||
//! is that next frame ready? //! is that next frame ready?
(((fp=lseek(state->fd_circ,LSEEK_CIRC_READY,SEEK_END))) < 0)) { (((fp = lseek(state->fd_circ, LSEEK_CIRC_READY, SEEK_END))) < 0)) {
D3(fprintf (debug_file,"6a:lseek(state->fd_circ,LSEEK_CIRC_NEXT,SEEK_END)=0x%x, fp=0x%x\n", (int) lseek(state->fd_circ,LSEEK_CIRC_NEXT,SEEK_END), (int) lseek(state->fd_circ,LSEEK_CIRC_READY,SEEK_END))); D3(fprintf(debug_file, "6a:lseek(state->fd_circ,LSEEK_CIRC_NEXT,SEEK_END)=0x%x, fp=0x%x\n", (int)lseek(state->fd_circ, LSEEK_CIRC_NEXT, SEEK_END), (int)lseek(state->fd_circ, LSEEK_CIRC_READY, SEEK_END)));
lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET); //!just in case - restore pointer lseek(state->fd_circ, state->cirbuf_rp, SEEK_SET); //!just in case - restore pointer
return -CAMOGM_FRAME_NOT_READY; //! frame pointer valid, but no frames yet return -CAMOGM_FRAME_NOT_READY; //! frame pointer valid, but no frames yet
} }
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[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));
D1(fprintf(debug_file, "fp=0x%x\r\n",(int) fp)); D1(fprintf(debug_file, "fp=0x%x\r\n", (int)fp));
D1(fprintf(debug_file, "%08x %08x %08x %08x %08x %08x %08x %08x\r\n",ifp_this[0],ifp_this[1],ifp_this[2],ifp_this[3],ifp_this[4],ifp_this[5],ifp_this[6],ifp_this[7])); D1(fprintf(debug_file, "%08x %08x %08x %08x %08x %08x %08x %08x\r\n", ifp_this[0], ifp_this[1], ifp_this[2], ifp_this[3], ifp_this[4], ifp_this[5], ifp_this[6], ifp_this[7]));
// int * ifp = (int *) &(state->this_frame_params) ; // int * ifp = (int *) &(state->this_frame_params) ;
// int * ifp_this = (int *) &(state->this_frame_params) ; // int * ifp_this = (int *) &(state->this_frame_params) ;
state->cirbuf_rp=-1; state->cirbuf_rp = -1;
return -CAMOGM_FRAME_BROKEN; return -CAMOGM_FRAME_BROKEN;
} }
D3(fprintf (debug_file,"7: state->cirbuf_rp=0x%x\n",state->cirbuf_rp)); D3(fprintf(debug_file, "7: state->cirbuf_rp=0x%x\n", state->cirbuf_rp));
//! 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[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))) {
//! Advance frame pointer to the next (caller should try again) //! Advance frame pointer to the next (caller should try again)
state->cirbuf_rp=fp; state->cirbuf_rp = fp;
return -CAMOGM_FRAME_CHANGED; // no yet checking for the FPS return -CAMOGM_FRAME_CHANGED; // no yet checking for the FPS
} }
D3(fprintf (debug_file,"8: state->cirbuf_rp=0x%x\n",state->cirbuf_rp)); D3(fprintf(debug_file, "8: state->cirbuf_rp=0x%x\n", state->cirbuf_rp));
//! calcualte the frame period - time difference (in microseconds) //! calcualte the frame period - time difference (in microseconds)
state->frame_period=(state->this_frame_params.timestamp_usec - state->frame_params.timestamp_usec)+ state->frame_period = (state->this_frame_params.timestamp_usec - state->frame_params.timestamp_usec) +
1000000*(state->this_frame_params.timestamp_sec - state->frame_params.timestamp_sec); 1000000 * (state->this_frame_params.timestamp_sec - state->frame_params.timestamp_sec);
//! correct for timelapse modes: //! correct for timelapse modes:
state->frames_skip= state->set_frames_skip; state->frames_skip = state->set_frames_skip;
if (state->frames_skip > 0) { if (state->frames_skip > 0) {
state->frames_skip_left=0; state->frames_skip_left = 0;
state->frame_period *= (state->frames_skip+1); state->frame_period *= (state->frames_skip + 1);
// state->frames_skip_left= state->set_frames_skip; // state->frames_skip_left= state->set_frames_skip;
} else if (state->frames_skip < 0) { } else if (state->frames_skip < 0) {
state->frame_period=-(state->frames_skip) ; //! actual frame period will fluctuate to the nearest frame acquired (free running) state->frame_period = -(state->frames_skip); //! actual frame period will fluctuate to the nearest frame acquired (free running)
state->frames_skip_left=state->frame_params.timestamp_sec; state->frames_skip_left = state->frame_params.timestamp_sec;
} }
D3(fprintf (debug_file,"9: state->frame_period=0x%x\n",state->frame_period)); D3(fprintf(debug_file, "9: state->frame_period=0x%x\n", state->frame_period));
state->time_unit= (ogg_int64_t) (((double) state-> frame_period) * ((double) 10) / ((double) state-> timescale)); state->time_unit = (ogg_int64_t)(((double)state->frame_period) * ((double)10) / ((double)state->timescale));
state->width=state->frame_params.width; state->width = state->frame_params.width;
state->height=state->frame_params.height; state->height = state->frame_params.height;
//!read JPEG header - it should stay the same for the whole file (restart new file if any parameters changed) //!read JPEG header - it should stay the same for the whole file (restart new file if any parameters changed)
//!rebuild JPEG header: //!rebuild JPEG header:
lseek(state->fd_head,state->cirbuf_rp+1,SEEK_END); //!+1 to avoid condition when jpeg_start==0. overloaded lseek will ignore 5 LSBs when SEEK_END lseek(state->fd_head, state->cirbuf_rp + 1, SEEK_END); //!+1 to avoid condition when jpeg_start==0. overloaded lseek will ignore 5 LSBs when SEEK_END
state->head_size=lseek(state->fd_head,0,SEEK_END); /// In 8.0 the header size might change for some jp4 modes state->head_size = lseek(state->fd_head, 0, SEEK_END); /// In 8.0 the header size might change for some jp4 modes
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 ));
return -2; return -2;
} }
//! and read it //! and read it
lseek(state->fd_head,0,0); lseek(state->fd_head, 0, 0);
read (state->fd_head,state->jpegHeader,state->head_size); read(state->fd_head, state->jpegHeader, state->head_size);
//! Restore read pointer to the original (now there may be no frame ready there yet) //! Restore read pointer to the original (now there may be no frame ready there yet)
lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET); lseek(state->fd_circ, state->cirbuf_rp, SEEK_SET);
//!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(); break;
case CAMOGM_FORMAT_JPEG: rslt= camogm_start_jpeg(); break; case CAMOGM_FORMAT_JPEG: rslt = camogm_start_jpeg(); break;
case CAMOGM_FORMAT_MOV: rslt= camogm_start_mov(); break; case CAMOGM_FORMAT_MOV: rslt = camogm_start_mov(); 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(); // 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;
D1(fprintf (debug_file,"Started OK\n")); D1(fprintf(debug_file, "Started OK\n"));
return 0; return 0;
} }
int sendImageFrame (void) { int sendImageFrame(void)
{
int rslt; int rslt;
unsigned char frame_packet_type = PACKET_IS_SYNCPOINT; unsigned char frame_packet_type = PACKET_IS_SYNCPOINT;
int timestamp_start; int timestamp_start;
///debugging: ///debugging:
// int * ifp = (int *) &(state->frame_params) ; // int * ifp = (int *) &(state->frame_params) ;
int * ifp_this = (int *) &(state->this_frame_params) ; int * ifp_this = (int*)&(state->this_frame_params);
int fp; int fp;
//! This is probably needed only for Quicktime (not to exceed already allocated frame index) //! This is probably needed only for Quicktime (not to exceed already allocated frame index)
if (state->frameno >= (state->max_frames)) { if (state->frameno >= (state->max_frames)) {
D3(fprintf (debug_file,"sendImageFrame:1: state->frameno(0x%x) >= state->max_frames(0x%x)\n",state->frameno,state->max_frames)); D3(fprintf(debug_file, "sendImageFrame:1: state->frameno(0x%x) >= state->max_frames(0x%x)\n", state->frameno, state->max_frames));
return -CAMOGM_FRAME_CHANGED; return -CAMOGM_FRAME_CHANGED;
} }
//! Format changed? //! Format changed?
// D3(fprintf (debug_file,"sendImageFrame: format=%d, set_format=%d\n", state->format, state->set_format)); // D3(fprintf (debug_file,"sendImageFrame: format=%d, set_format=%d\n", state->format, state->set_format));
if (state->format != state->set_format) { if (state->format != state->set_format) {
D3(fprintf (debug_file,"sendImageFrame:2: state->format(0x%x) != state->set_format(0x%x)\n",state->format,state->set_format)); D3(fprintf(debug_file, "sendImageFrame:2: state->format(0x%x) != state->set_format(0x%x)\n", state->format, state->set_format));
return -CAMOGM_FRAME_CHANGED; return -CAMOGM_FRAME_CHANGED;
} }
//! check if file size is exceeded (assuming fopen),-CAMOGM_FRAME_CHANGED will trigger a new segment //! check if file size is exceeded (assuming fopen),-CAMOGM_FRAME_CHANGED will trigger a new segment
if ((state->vf) && (state->segment_length >=0) && (ftell(state->vf) > state->segment_length)) { if ((state->vf) && (state->segment_length >= 0) && (ftell(state->vf) > state->segment_length)) {
D3(fprintf (debug_file,"sendImageFrame:3: segment length exceeded\n")); D3(fprintf(debug_file, "sendImageFrame:3: segment length exceeded\n"));
return -CAMOGM_FRAME_CHANGED; return -CAMOGM_FRAME_CHANGED;
} }
//!same for open //!same for open
if (((state->ivf)>=0) && (state->segment_length >=0) && (lseek(state->ivf, 0, SEEK_CUR) > state->segment_length)) { if (((state->ivf) >= 0) && (state->segment_length >= 0) && (lseek(state->ivf, 0, SEEK_CUR) > state->segment_length)) {
D3(fprintf (debug_file,"sendImageFrame:4: segment length exceeded\n")); D3(fprintf(debug_file, "sendImageFrame:4: segment length exceeded\n"));
return -CAMOGM_FRAME_CHANGED; return -CAMOGM_FRAME_CHANGED;
} }
//! check the frame pointer is valid //! check the frame pointer is valid
if ((fp=lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET)) <0) { if ((fp = lseek(state->fd_circ, state->cirbuf_rp, SEEK_SET)) < 0) {
D3(fprintf (debug_file,"sendImageFrame:5: invalid frame\n")); D3(fprintf(debug_file, "sendImageFrame:5: invalid frame\n"));
return -CAMOGM_FRAME_INVALID; //!it will probably be that allready return -CAMOGM_FRAME_INVALID; //!it will probably be that allready
} }
//! is the frame ready? //! is the frame ready?
if (lseek(state->fd_circ,LSEEK_CIRC_READY,SEEK_END) <0) { if (lseek(state->fd_circ, LSEEK_CIRC_READY, SEEK_END) < 0) {
D3(fprintf (debug_file,"?6,fp=0x%x ",fp)); //frame not ready, frame pointer seems valid, but not ready D3(fprintf(debug_file, "?6,fp=0x%x ", fp)); //frame not ready, frame pointer seems valid, but not ready
return -CAMOGM_FRAME_NOT_READY; //! frame pointer valid, but no frames yet return -CAMOGM_FRAME_NOT_READY; //! frame pointer valid, but no frames yet
} }
//! process skipping frames. TODO: add - skipping time between frames (or better - actual time period - use the nearest frame) instead of the frame number //! process skipping frames. TODO: add - skipping time between frames (or better - actual time period - use the nearest frame) instead of the frame number
if ( (state->frames_skip > 0) && (state->frames_skip_left > 0 )) { //!skipping frames, not seconds. if ( (state->frames_skip > 0) && (state->frames_skip_left > 0 )) { //!skipping frames, not seconds.
state->cirbuf_rp=lseek(state->fd_circ,LSEEK_CIRC_NEXT,SEEK_END); state->cirbuf_rp = lseek(state->fd_circ, LSEEK_CIRC_NEXT, SEEK_END);
//!optionally save it to global read pointer (i.e. for debugging with imgsrv "/pointers") //!optionally save it to global read pointer (i.e. for debugging with imgsrv "/pointers")
if (state->save_gp) lseek(state->fd_circ,LSEEK_CIRC_SETP,SEEK_END); if (state->save_gp) lseek(state->fd_circ, LSEEK_CIRC_SETP, SEEK_END);
state->frames_skip_left--; state->frames_skip_left--;
D3(fprintf (debug_file,"?7 ")); //frame not ready D3(fprintf(debug_file, "?7 ")); //frame not ready
return -CAMOGM_FRAME_NOT_READY; //! the required frame is not ready return -CAMOGM_FRAME_NOT_READY; //! the required frame is not ready
} }
//! Get metadata //! Get metadata
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->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));
D1(fprintf(debug_file, "state->cirbuf_rp=0x%x\r\n",(int) state->cirbuf_rp)); D1(fprintf(debug_file, "state->cirbuf_rp=0x%x\r\n", (int)state->cirbuf_rp));
D1(fprintf(debug_file, "%08x %08x %08x %08x %08x %08x %08x %08x\r\n",ifp_this[0],ifp_this[1],ifp_this[2],ifp_this[3],ifp_this[4],ifp_this[5],ifp_this[6],ifp_this[7])); D1(fprintf(debug_file, "%08x %08x %08x %08x %08x %08x %08x %08x\r\n", ifp_this[0], ifp_this[1], ifp_this[2], ifp_this[3], ifp_this[4], ifp_this[5], ifp_this[6], ifp_this[7]));
D3(fprintf (debug_file,"sendImageFrame:8: frame broken\n")); D3(fprintf(debug_file, "sendImageFrame:8: frame broken\n"));
return -CAMOGM_FRAME_BROKEN; return -CAMOGM_FRAME_BROKEN;
} }
D3(fprintf (debug_file,"_2_")); D3(fprintf(debug_file, "_2_"));
//! 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=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[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))) {
D3(fprintf (debug_file,"sendImageFrame:9: WOI changed\n")); D3(fprintf(debug_file, "sendImageFrame:9: WOI changed\n"));
return -CAMOGM_FRAME_CHANGED; //! not yet checking for the FPS return -CAMOGM_FRAME_CHANGED; //! not yet checking for the FPS
} }
//! check if file duration (in seconds) exceeded ,-CAMOGM_FRAME_CHANGED will trigger a new segment //! check if file duration (in seconds) exceeded ,-CAMOGM_FRAME_CHANGED will trigger a new segment
if ((state->segment_duration > 0) && if ((state->segment_duration > 0) &&
((state->this_frame_params.timestamp_sec-state->frame_params.timestamp_sec) > state->segment_duration)) { ((state->this_frame_params.timestamp_sec - state->frame_params.timestamp_sec) > state->segment_duration)) {
D3(fprintf (debug_file,"sendImageFrame:10: segment duration in seconds exceeded\n")); D3(fprintf(debug_file, "sendImageFrame:10: segment duration in seconds exceeded\n"));
return -CAMOGM_FRAME_CHANGED; return -CAMOGM_FRAME_CHANGED;
} }
//! check if (in timelapse mode) it is too early for the frame to be stored //! check if (in timelapse mode) it is too early for the frame to be stored
if ((state->frames_skip < 0) && (state->frames_skip_left > state->this_frame_params.timestamp_sec) ) { if ((state->frames_skip < 0) && (state->frames_skip_left > state->this_frame_params.timestamp_sec) ) {
state->cirbuf_rp=lseek(state->fd_circ,LSEEK_CIRC_NEXT,SEEK_END); state->cirbuf_rp = lseek(state->fd_circ, LSEEK_CIRC_NEXT, SEEK_END);
//!optionally save it to global read pointer (i.e. for debugging with imgsrv "/pointers") //!optionally save it to global read pointer (i.e. for debugging with imgsrv "/pointers")
if (state->save_gp) lseek(state->fd_circ,LSEEK_CIRC_SETP,SEEK_END); if (state->save_gp) lseek(state->fd_circ, LSEEK_CIRC_SETP, SEEK_END);
D3(fprintf (debug_file,"sendImageFrame:11: timelapse: frame will be skipped\n")); D3(fprintf(debug_file, "sendImageFrame:11: timelapse: frame will be skipped\n"));
return -CAMOGM_FRAME_NOT_READY; //! the required frame is not ready return -CAMOGM_FRAME_NOT_READY; //! the required frame is not ready
} }
D3(fprintf (debug_file,"_4_")); D3(fprintf(debug_file, "_4_"));
if (state->exif) { if (state->exif) {
D3(fprintf (debug_file,"_5_")); D3(fprintf(debug_file, "_5_"));
//! update the Exif header with the current frame metadata //! update the Exif header with the current frame metadata
// updateExif(ep, state->ed, &(state->frame_params)); // updateExif(ep, state->ed, &(state->frame_params));
state->exifSize=lseek(state->fd_exif,1,SEEK_END); // at the beginning of page 1 - position == page length state->exifSize = lseek(state->fd_exif, 1, SEEK_END); // at the beginning of page 1 - position == page length
// if (state->exifSize < 0) state->exifSize=0; // error from lseek; // if (state->exifSize < 0) state->exifSize=0; // error from lseek;
if (state->exifSize > 0) { if (state->exifSize > 0) {
//state->this_frame_params.meta_index //state->this_frame_params.meta_index
lseek(state->fd_exif,state->this_frame_params.meta_index,SEEK_END); //! select meta page to use (matching frame) lseek(state->fd_exif, state->this_frame_params.meta_index, SEEK_END); //! select meta page to use (matching frame)
rslt=read (state->fd_exif, state->ed, state->exifSize); rslt = read(state->fd_exif, state->ed, state->exifSize);
if (rslt<0) rslt=0; if (rslt < 0) rslt = 0;
state->exifSize=rslt; state->exifSize = rslt;
} else state->exifSize=0; } else state->exifSize = 0;
} else state->exifSize=0; } else state->exifSize = 0;
D3(fprintf (debug_file,"_6_")); D3(fprintf(debug_file, "_6_"));
//! prepare a packet to be sent (a lst of memory chunks) //! prepare a packet to be sent (a lst of memory chunks)
state->chunk_index=0; state->chunk_index = 0;
state->packetchunks[state->chunk_index ].bytes=1; state->packetchunks[state->chunk_index ].bytes = 1;
state->packetchunks[state->chunk_index++].chunk=&frame_packet_type; state->packetchunks[state->chunk_index++].chunk = &frame_packet_type;
if (state->exif>0) {//! insert Exif if (state->exif > 0) { //! insert Exif
D3(fprintf (debug_file,"_7_")); D3(fprintf(debug_file, "_7_"));
state->packetchunks[state->chunk_index ].bytes=2; state->packetchunks[state->chunk_index ].bytes = 2;
state->packetchunks[state->chunk_index++].chunk=state->jpegHeader; state->packetchunks[state->chunk_index++].chunk = state->jpegHeader;
state->packetchunks[state->chunk_index ].bytes=state->exifSize; state->packetchunks[state->chunk_index ].bytes = state->exifSize;
state->packetchunks[state->chunk_index++].chunk= state->ed; state->packetchunks[state->chunk_index++].chunk = state->ed;
state->packetchunks[state->chunk_index ].bytes=state->head_size-2; state->packetchunks[state->chunk_index ].bytes = state->head_size - 2;
state->packetchunks[state->chunk_index++].chunk= &(state->jpegHeader[2]); state->packetchunks[state->chunk_index++].chunk = &(state->jpegHeader[2]);
} else { } else {
D3(fprintf (debug_file,"_8_")); D3(fprintf(debug_file, "_8_"));
state->packetchunks[state->chunk_index ].bytes=state->head_size; state->packetchunks[state->chunk_index ].bytes = state->head_size;
state->packetchunks[state->chunk_index++].chunk= state->jpegHeader; state->packetchunks[state->chunk_index++].chunk = state->jpegHeader;
} }
D3(fprintf (debug_file,"_9_")); D3(fprintf(debug_file, "_9_"));
/*! JPEG image data may be split in two segments (rolled over buffer end) - process both variants */ /*! JPEG image data may be split in two segments (rolled over buffer end) - process both variants */
if ((state->cirbuf_rp + state->jpeg_len) > state->circ_buff_size) { //! two segments if ((state->cirbuf_rp + state->jpeg_len) > state->circ_buff_size) { //! two segments
/*! 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->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];
} else { // single segment } else { // single segment
D3(fprintf (debug_file,"_11_")); D3(fprintf(debug_file, "_11_"));
/*! 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->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;
state->packetchunks[state->chunk_index++].chunk= (unsigned char*) trailer; state->packetchunks[state->chunk_index++].chunk = (unsigned char*)trailer;
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(); break;
case CAMOGM_FORMAT_JPEG: rslt=camogm_frame_jpeg(); break; case CAMOGM_FORMAT_JPEG: rslt = camogm_frame_jpeg(); break;
case CAMOGM_FORMAT_MOV: rslt=camogm_frame_mov(); break; case CAMOGM_FORMAT_MOV: rslt = camogm_frame_mov(); 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(); // 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_"));
//!advance frame pointer //!advance frame pointer
state->frameno++; state->frameno++;
state->cirbuf_rp=lseek(state->fd_circ,LSEEK_CIRC_NEXT,SEEK_END); state->cirbuf_rp = lseek(state->fd_circ, LSEEK_CIRC_NEXT, SEEK_END);
//!optionally save it to global read pointer (i.e. for debugging with imgsrv "/pointers") //!optionally save it to global read pointer (i.e. for debugging with imgsrv "/pointers")
if (state->save_gp) lseek(state->fd_circ,LSEEK_CIRC_SETP,SEEK_END); if (state->save_gp) lseek(state->fd_circ, LSEEK_CIRC_SETP, SEEK_END);
D3(fprintf (debug_file,"_15_\n")); D3(fprintf(debug_file, "_15_\n"));
if (state->frames_skip > 0) { if (state->frames_skip > 0) {
state->frames_skip_left= state->frames_skip; state->frames_skip_left = state->frames_skip;
} else if (state->frames_skip < 0) { } else if (state->frames_skip < 0) {
state->frames_skip_left+= -(state->frames_skip); state->frames_skip_left += -(state->frames_skip);
} }
return 0; return 0;
} }
int camogm_stop(void) { int camogm_stop(void)
int rslt=0; {
int rslt = 0;
if (!state->running) { if (!state->running) {
if (!state->starting) { if (!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 {
state->starting=0; state->starting = 0;
D1(fprintf (debug_file,"Dropping attempt to start\n")); D1(fprintf(debug_file, "Dropping attempt to start\n"));
} }
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();
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(); 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(); 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)
if (state->vf) fclose (state->vf); if (state->vf) fclose(state->vf);
state->vf=NULL; state->vf = NULL;
if (rslt) return rslt; if (rslt) return rslt;
state->last=1; state->last = 1;
//!state->running=0 should be output after file is finished and closed //!state->running=0 should be output after file is finished and closed
state->running=0; state->running = 0;
state->starting=0; state->starting = 0;
return 0; return 0;
} }
void camogm_free() { void camogm_free()
{
int f; int f;
//! free all file format handlers that were used //! free all file format handlers that were used
//add kml when needed //add kml when needed
for (f=0;f<31;f++) { for (f = 0; f < 31; f++) {
if (state->formats & ( 1 << (state->format))) { if (state->formats & ( 1 << (state->format))) {
switch (f) { switch (f) {
case CAMOGM_FORMAT_NONE: break; case CAMOGM_FORMAT_NONE: break;
case CAMOGM_FORMAT_OGM: camogm_free_ogm(); break; case CAMOGM_FORMAT_OGM: camogm_free_ogm(); break;
case CAMOGM_FORMAT_JPEG: camogm_free_jpeg();break; case CAMOGM_FORMAT_JPEG: camogm_free_jpeg(); break;
case CAMOGM_FORMAT_MOV: camogm_free_mov(); break; case CAMOGM_FORMAT_MOV: camogm_free_mov(); break;
} }
} }
} }
state->formats=0; state->formats = 0;
} }
int camogm_reset(void) { //! reset circbuf read pointer int camogm_reset(void) //! reset circbuf read pointer
state->cirbuf_rp=-1; {
state->buf_overruns=-1; //!first will not count state->cirbuf_rp = -1;
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(int d)
state->kml_enable=d; {
state->kml_enable = d;
} }
void camogm_kml_set_horHalfFov (double dd) { void camogm_kml_set_horHalfFov(double dd)
state->kml_horHalfFov=dd; {
state->kml_horHalfFov = dd;
} }
void camogm_kml_set_vertHalfFov(double dd) { void camogm_kml_set_vertHalfFov(double dd)
state->kml_vertHalfFov=dd; {
state->kml_vertHalfFov = dd;
} }
void camogm_kml_set_height_mode(int d) { void camogm_kml_set_height_mode(int d)
state->kml_height_mode=d; {
state->kml_height_mode = d;
} }
void camogm_kml_set_height(double dd) { void camogm_kml_set_height(double dd)
state->kml_height=dd; {
state->kml_height = dd;
} }
void camogm_kml_set_period(int d) { void camogm_kml_set_period(int d)
state->kml_period=d; {
state->kml_last_ts=0; state->kml_period = d;
state->kml_last_uts=0; state->kml_last_ts = 0;
state->kml_last_uts = 0;
} }
void camogm_kml_set_near(double dd) { // distance to PhotoOverlay void camogm_kml_set_near(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(int sd)
state->segment_duration=sd; {
state->segment_duration = sd;
} }
void camogm_set_segment_length(int sl) { void camogm_set_segment_length(int sl)
state->segment_length= sl; {
state->segment_length = sl;
} }
void camogm_set_save_gp(int d) { void camogm_set_save_gp(int d)
state->save_gp= d; {
state->save_gp = d;
} }
void camogm_set_exif(int d) { void camogm_set_exif(int d)
state->exif= d; {
state->exif = d;
} }
void camogm_set_greedy(int d) { void camogm_set_greedy(int d)
state->greedy= d?1:0; {
state->greedy = d ? 1 : 0;
} }
void camogm_set_ignore_fps(int d){ void camogm_set_ignore_fps(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(const char * p)
strncpy(state->path_prefix, p, sizeof(state->path_prefix)-1); {
state->path_prefix[sizeof(state->path_prefix)-1]='\0'; strncpy(state->path_prefix, p, sizeof(state->path_prefix) - 1);
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(double d) //! set timescale, default=1,000,000
state->set_timescale= d; {
if ((state->running==0) && (state->starting==0)) { state->set_timescale = d;
state->timescale=state->set_timescale; if ((state->running == 0) && (state->starting == 0)) {
state->timescale = state->set_timescale;
} }
} }
void camogm_set_frames_skip(int d) { //! set frames to skip (for time lapse) void camogm_set_frames_skip(int d) //! set frames to skip (for time lapse)
state->set_frames_skip= d; {
if ((state->running==0) && (state->starting==0)) { state->set_frames_skip = d;
state->frames_skip= state->set_frames_skip; if ((state->running == 0) && (state->starting == 0)) {
state->frames_skip = state->set_frames_skip;
// state->frames_skip_left= state->set_frames_skip; // state->frames_skip_left= state->set_frames_skip;
state->frames_skip_left= 0; state->frames_skip_left = 0;
} }
} }
void camogm_set_format(int d) { void camogm_set_format(int d)
int rslt=0; {
state->set_format= d; int rslt = 0;
if ((state->running==0) && (state->starting==0)) {
state->format= state->set_format; state->set_format = d;
if ((state->running == 0) && (state->starting == 0)) {
state->format = state->set_format;
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_init_ogm(); break; case CAMOGM_FORMAT_OGM: rslt = camogm_init_ogm(); break;
case CAMOGM_FORMAT_JPEG: rslt= camogm_init_jpeg();break; case CAMOGM_FORMAT_JPEG: rslt = camogm_init_jpeg(); break;
case CAMOGM_FORMAT_MOV: rslt= camogm_init_mov(); break; case CAMOGM_FORMAT_MOV: rslt = camogm_init_mov(); break;
} }
if (rslt) { if (rslt) {
D0(fprintf (debug_file,"%s:%d: Error setting format to=%d\n",__FILE__,__LINE__, state->format)); D0(fprintf(debug_file, "%s:%d: Error setting format to=%d\n", __FILE__, __LINE__, state->format));
} }
state->formats |= 1 << (state->format); state->formats |= 1 << (state->format);
} }
} }
//! needed for Quicktime - maybe something else? //! needed for Quicktime - maybe something else?
void camogm_set_max_frames(int d) { void camogm_set_max_frames(int d)
state->set_max_frames= d; {
if ((state->running==0) && (state->starting==0)) state->max_frames= d; state->set_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(int d)
state->set_frames_per_chunk= d; {
if ((state->running==0) && (state->starting==0)) state->frames_per_chunk= d; state->set_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(double d)
state->start_after_timestamp= d; {
state->start_after_timestamp = d;
} }
void camogm_status(char * fn, int xml) { void camogm_status(char * fn, int xml)
int _len=0; {
int _dur,_udur; int _len = 0;
int _dur, _udur;
//TODO:make it XML file //TODO:make it XML file
FILE* f; FILE* f;
char *_state, *_output_format, *_using_exif, *_using_global_pointer, *_compressor_state; char *_state, *_output_format, *_using_exif, *_using_global_pointer, *_compressor_state;
int _b_free, _b_used, _b_size; // , save_p; int _b_free, _b_used, _b_size; // , save_p;
int _frames_remain=0; int _frames_remain = 0;
int _sec_remain=0; int _sec_remain = 0;
int _frames_skip=0; int _frames_skip = 0;
int _sec_skip=0; int _sec_skip = 0;
char *_kml_enable, *_kml_used, *_kml_height_mode; char *_kml_enable, *_kml_used, *_kml_height_mode;
_kml_enable= state->kml_enable?"yes":"no"; _kml_enable = state->kml_enable ? "yes" : "no";
_kml_used= state->kml_used?"yes":"no"; _kml_used = state->kml_used ? "yes" : "no";
_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(G_FREECIRCBUF);
_b_used=getGPValue(G_CIRCBUFSIZE)-getGPValue(G_FREECIRCBUF); _b_used = getGPValue(G_CIRCBUFSIZE) - getGPValue(G_FREECIRCBUF);
_b_size=getGPValue(G_FRAME_SIZE); _b_size = getGPValue(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;
else if (strcmp(fn, "stderr")==0) f=stderr; else if (strcmp(fn, "stderr") == 0) f = stderr;
else { else {
if (!((f=fopen (fn,"w")))) { if (!((f = fopen(fn, "w")))) {
D0(fprintf (debug_file,"Error opening %s\n", fn)); D0(fprintf(debug_file, "Error opening %s\n", fn));
return; return;
} }
} }
if (state->vf) _len=ftell(state->vf); //! for ogm if (state->vf) _len = ftell(state->vf); //! for ogm
else if ((state->ivf)>=0) _len=lseek(state->ivf, 0, SEEK_CUR); //!for mov else if ((state->ivf) >= 0) _len = lseek(state->ivf, 0, SEEK_CUR); //!for mov
_dur= state->this_frame_params.timestamp_sec-state->frame_params.timestamp_sec; _dur = state->this_frame_params.timestamp_sec - state->frame_params.timestamp_sec;
_udur=state->this_frame_params.timestamp_usec-state->frame_params.timestamp_usec; _udur = state->this_frame_params.timestamp_usec - state->frame_params.timestamp_usec;
if (_udur<0) { if (_udur < 0) {
_dur-=1; _dur -= 1;
_udur+=1000000; _udur += 1000000;
} else if (_udur>=1000000) { } else if (_udur >= 1000000) {
_dur+=1; _dur += 1;
_udur-=1000000; _udur -= 1000000;
} }
_state= state->running? "running":(state->starting?"starting":"stopped"); _state = state->running ? "running" : (state->starting ? "starting" : "stopped");
_output_format= state->format?((state->format==CAMOGM_FORMAT_OGM)?"ogm": _output_format = state->format ? ((state->format == CAMOGM_FORMAT_OGM) ? "ogm" :
((state->format==CAMOGM_FORMAT_JPEG)?"jpeg": ((state->format == CAMOGM_FORMAT_JPEG) ? "jpeg" :
((state->format==CAMOGM_FORMAT_MOV)?"mov": ((state->format == CAMOGM_FORMAT_MOV) ? "mov" :
"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(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;
} else if ( state->frames_skip <0 ) { } else if ( state->frames_skip < 0 ) {
_sec_remain= (state->frames_skip_left - state->this_frame_params.timestamp_sec); _sec_remain = (state->frames_skip_left - state->this_frame_params.timestamp_sec);
_sec_skip=-(state->frames_skip); _sec_skip = -(state->frames_skip);
} }
if (xml) { if (xml) {
fprintf (f,"<?xml version=\"1.0\"?>\n" \ fprintf(f, "<?xml version=\"1.0\"?>\n" \
"<camogm_state>\n" \ "<camogm_state>\n" \
" <state>\"%s\"</state>\n" \ " <state>\"%s\"</state>\n" \
" <compressor_state>\"%s\"</compressor_state>\n" \ " <compressor_state>\"%s\"</compressor_state>\n" \
...@@ -955,101 +976,103 @@ void camogm_status(char * fn, int xml) { ...@@ -955,101 +976,103 @@ void camogm_status(char * fn, int xml) {
" <greedy>\"%s\"</greedy>\n" \ " <greedy>\"%s\"</greedy>\n" \
" <ignore_fps>\"%s\"</ignore_fps>\n" \ " <ignore_fps>\"%s\"</ignore_fps>\n" \
"</camogm_state>\n", "</camogm_state>\n",
_state,_compressor_state,state->path,state->frameno,_b_size,state->start_after_timestamp,_dur,_udur,_len,state->frame_period, \ _state, _compressor_state, state->path, state->frameno, _b_size, state->start_after_timestamp, _dur, _udur, _len, state->frame_period, \
_frames_skip,_sec_skip,_frames_remain, _sec_remain, \ _frames_skip, _sec_skip, _frames_remain, _sec_remain, \
state->width,state->height,_output_format,_using_exif, \ state->width, state->height, _output_format, _using_exif, \
state->path_prefix, state->segment_duration, state->segment_length, state->max_frames, state->timescale, \ state->path_prefix, state->segment_duration, state->segment_length, state->max_frames, state->timescale, \
state->frames_per_chunk, state->last_error_code, state->buf_overruns, state->buf_min, _b_free, _b_used, state->cirbuf_rp, \ state->frames_per_chunk, state->last_error_code, state->buf_overruns, state->buf_min, _b_free, _b_used, state->cirbuf_rp, \
state->debug_name, debug_level, _using_global_pointer, \ state->debug_name, debug_level, _using_global_pointer, \
_kml_enable,_kml_used,state->kml_path,state->kml_horHalfFov,state->kml_vertHalfFov,state->kml_near,\ _kml_enable, _kml_used, state->kml_path, state->kml_horHalfFov, state->kml_vertHalfFov, state->kml_near, \
_kml_height_mode,state->kml_height,state->kml_period,state->kml_last_ts,state->kml_last_uts,\ _kml_height_mode, state->kml_height, state->kml_period, state->kml_last_ts, state->kml_last_uts, \
state->greedy?"yes":"no",state->ignore_fps?"yes":"no"); state->greedy ? "yes" : "no", state->ignore_fps ? "yes" : "no");
} else { } else {
fprintf (f,"state %s\n", _state); fprintf(f, "state %s\n", _state);
fprintf (f,"compressor state %s\n", _compressor_state); fprintf(f, "compressor state %s\n", _compressor_state);
fprintf (f,"file %s\n", state->path); fprintf(f, "file %s\n", state->path);
fprintf (f,"frame %d\n", state->frameno); fprintf(f, "frame %d\n", state->frameno);
fprintf (f,"frame size %d\n", _b_size); fprintf(f, "frame size %d\n", _b_size);
fprintf (f,"start_after_timestamp %f\n", state->start_after_timestamp); fprintf(f, "start_after_timestamp %f\n", state->start_after_timestamp);
fprintf (f,"file duration %d.%06d sec\n",_dur,_udur); fprintf(f, "file duration %d.%06d sec\n", _dur, _udur);
fprintf (f,"file length %d B\n", _len); fprintf(f, "file length %d B\n", _len);
fprintf (f,"frame period %d (0x%x)\n", state->frame_period,state->frame_period); fprintf(f, "frame period %d (0x%x)\n", state->frame_period, state->frame_period);
if ( _frames_skip >0 ) fprintf (f,"frames to skip %d (left %d)\n",_frames_skip, _frames_remain); if ( _frames_skip > 0 ) fprintf(f, "frames to skip %d (left %d)\n", _frames_skip, _frames_remain);
if ( _sec_skip <0 ) fprintf (f,"timelapse period %d sec (remaining %d sec)\n", _sec_skip, _sec_remain); if ( _sec_skip < 0 ) fprintf(f, "timelapse period %d sec (remaining %d sec)\n", _sec_skip, _sec_remain);
fprintf (f,"width %d (0x%x)\n", state->width,state->width); fprintf(f, "width %d (0x%x)\n", state->width, state->width);
fprintf (f,"height %d (0x%x)\n", state->height,state->height); fprintf(f, "height %d (0x%x)\n", state->height, state->height);
fprintf (f,"\n"); fprintf(f, "\n");
fprintf (f,"output format %s\n", _output_format); fprintf(f, "output format %s\n", _output_format);
fprintf (f,"using exif %s\n", _using_exif); fprintf(f, "using exif %s\n", _using_exif);
fprintf (f,"path prefix: %s\n", state->path_prefix); fprintf(f, "path prefix: %s\n", state->path_prefix);
fprintf (f,"max file duration: %d sec\n", state->segment_duration); fprintf(f, "max file duration: %d sec\n", state->segment_duration);
fprintf (f,"max file length: %d B\n", state->segment_length); fprintf(f, "max file length: %d B\n", state->segment_length);
fprintf (f,"max frames %d\n", state->max_frames); fprintf(f, "max frames %d\n", state->max_frames);
fprintf (f,"timescale %f\n", state->timescale); fprintf(f, "timescale %f\n", state->timescale);
fprintf (f,"frames per chunk %d\n", state->frames_per_chunk); fprintf(f, "frames per chunk %d\n", state->frames_per_chunk);
fprintf (f,"greedy %s\n", state->greedy?"yes":"no"); fprintf(f, "greedy %s\n", state->greedy ? "yes" : "no");
fprintf (f,"ignore fps %s\n", state->ignore_fps?"yes":"no"); fprintf(f, "ignore fps %s\n", state->ignore_fps ? "yes" : "no");
fprintf (f,"\n"); fprintf(f, "\n");
fprintf (f,"buffer overruns %d\n", state->last_error_code); fprintf(f, "buffer overruns %d\n", state->last_error_code);
fprintf (f,"buffer overruns %d\n", state->buf_overruns); fprintf(f, "buffer overruns %d\n", state->buf_overruns);
fprintf (f,"buffer minimal %d\n", state->buf_min); fprintf(f, "buffer minimal %d\n", state->buf_min);
fprintf (f,"buffer free %d\n", _b_free); fprintf(f, "buffer free %d\n", _b_free);
fprintf (f,"buffer used %d\n", _b_used); fprintf(f, "buffer used %d\n", _b_used);
fprintf (f,"circbuf_rp %d (0x%x)\n", state->cirbuf_rp,state->cirbuf_rp); fprintf(f, "circbuf_rp %d (0x%x)\n", state->cirbuf_rp, state->cirbuf_rp);
fprintf (f,"\n"); fprintf(f, "\n");
fprintf (f,"debug output to %s\n", state->debug_name); fprintf(f, "debug output to %s\n", state->debug_name);
fprintf (f,"debug level %d\n", debug_level); fprintf(f, "debug level %d\n", debug_level);
fprintf (f,"use global pointer %s\n", _using_global_pointer); fprintf(f, "use global pointer %s\n", _using_global_pointer);
fprintf (f,"\n\n"); fprintf(f, "\n\n");
fprintf (f,"kml_enable %s\n", _kml_enable); fprintf(f, "kml_enable %s\n", _kml_enable);
fprintf (f,"kml_used %s\n", _kml_used); fprintf(f, "kml_used %s\n", _kml_used);
fprintf (f,"kml_path %s\n", state->kml_path); fprintf(f, "kml_path %s\n", state->kml_path);
fprintf (f,"kml_horHalfFov %f degrees\n",state->kml_horHalfFov); fprintf(f, "kml_horHalfFov %f degrees\n", state->kml_horHalfFov);
fprintf (f,"kml_vertHalfFov %f degrees\n",state->kml_vertHalfFov); fprintf(f, "kml_vertHalfFov %f degrees\n", state->kml_vertHalfFov);
fprintf (f,"kml_near %f m\n", state->kml_near); fprintf(f, "kml_near %f m\n", state->kml_near);
fprintf (f,"kml height mode %s\n", _kml_height_mode); fprintf(f, "kml height mode %s\n", _kml_height_mode);
fprintf (f,"kml_height (extra) %f m\n", state->kml_height); fprintf(f, "kml_height (extra) %f m\n", state->kml_height);
fprintf (f,"kml_period %d\n", state->kml_period); fprintf(f, "kml_period %d\n", state->kml_period);
fprintf (f,"kml_last_ts %d.%06d\n", state->kml_last_ts,state->kml_last_uts); fprintf(f, "kml_last_ts %d.%06d\n", state->kml_last_ts, state->kml_last_uts);
fprintf (f,"\n\n"); fprintf(f, "\n\n");
} }
if ((f!=stdout) && (f!=stderr)) fclose (f); if ((f != stdout) && (f != stderr)) fclose(f);
if (state->buf_overruns>=0) state->buf_overruns=0; //! resets overruns after reading status , so "overruns" means since last reading status if (state->buf_overruns >= 0) state->buf_overruns = 0; //! resets overruns after reading status , so "overruns" means since last reading status
state->last_error_code=0; //! Reset error state->last_error_code = 0; //! Reset error
state->buf_min=_b_free; state->buf_min = _b_free;
} }
//! will read from pipe, return pointer to null terminated string if available, NULL otherwise //! will read from pipe, return pointer to null terminated string if available, NULL otherwise
char * getLineFromPipe(FILE* npipe) { char * getLineFromPipe(FILE* npipe)
{
int fl; int fl;
char * nlp; char * nlp;
//!remove used string if any //!remove used string if any
if (cmdstrt > 0) { if (cmdstrt > 0) {
//!moving overlapping strings //!moving overlapping strings
memmove(cmdbuf, &cmdbuf[cmdstrt], sizeof(cmdbuf)- cmdstrt); memmove(cmdbuf, &cmdbuf[cmdstrt], sizeof(cmdbuf) - cmdstrt);
cmdbufp-=cmdstrt; cmdbufp -= cmdstrt;
cmdstrt=0; cmdstrt = 0;
} }
//! is there any complete string in a buffer? //! is there any complete string in a buffer?
if (!cmdbufp) cmdbuf[cmdbufp]=0; //!null-terminate first access (probably not needed for the static buffer if (!cmdbufp) cmdbuf[cmdbufp] = 0; //!null-terminate first access (probably not needed for the static buffer
// nlp= strchr(cmdbuf,'\n'); // nlp= strchr(cmdbuf,'\n');
nlp= strpbrk(cmdbuf,";\n"); nlp = strpbrk(cmdbuf, ";\n");
if (!nlp) { //!no complete string, try to read more if (!nlp) { //!no complete string, try to read more
fl=fread(&cmdbuf[cmdbufp], 1,sizeof(cmdbuf)-cmdbufp-1,npipe); fl = fread(&cmdbuf[cmdbufp], 1, sizeof(cmdbuf) - cmdbufp - 1, npipe);
cmdbuf[cmdbufp+fl]=0; cmdbuf[cmdbufp + fl] = 0;
//! is there any complete string in a buffer after reading? //! is there any complete string in a buffer after reading?
// nlp= strchr(&cmdbuf[cmdbufp],'\n'); //! there were no new lines before cmdbufp // nlp= strchr(&cmdbuf[cmdbufp],'\n'); //! there were no new lines before cmdbufp
nlp= strpbrk(&cmdbuf[cmdbufp],";\n"); //! there were no new lines before cmdbufp nlp = strpbrk(&cmdbuf[cmdbufp], ";\n"); //! there were no new lines before cmdbufp
cmdbufp+=fl; //!advance pointer after pipe read cmdbufp += fl; //!advance pointer after pipe read
} }
if (nlp) { if (nlp) {
//printf ("++nlp=%d\n", (int) (nlp-cmdbuf)); //printf ("++nlp=%d\n", (int) (nlp-cmdbuf));
nlp[0]=0; nlp[0] = 0;
cmdstrt=nlp-cmdbuf+1; cmdstrt = nlp - cmdbuf + 1;
//printf ("++cmdstrt=%d\n", cmdstrt); //printf ("++cmdstrt=%d\n", cmdstrt);
//printf ("cmdbuf[0]=%d, cmdbuf[1]=%d, cmdbuf[2]=%d, cmdbuf[3]=%d, \n",cmdbuf[0],cmdbuf[1],cmdbuf[2],cmdbuf[3]); //printf ("cmdbuf[0]=%d, cmdbuf[1]=%d, cmdbuf[2]=%d, cmdbuf[3]=%d, \n",cmdbuf[0],cmdbuf[1],cmdbuf[2],cmdbuf[3]);
for (fl=0; cmdbuf[fl] && strchr(" \t",cmdbuf[fl]); fl++); for (fl = 0; cmdbuf[fl] && strchr(" \t", cmdbuf[fl]); fl++) ;
//printf ("++fl=%d\n", fl); //printf ("++fl=%d\n", fl);
return &cmdbuf[fl]; return &cmdbuf[fl];
} else { } else {
...@@ -1058,148 +1081,150 @@ char * getLineFromPipe(FILE* npipe) { ...@@ -1058,148 +1081,150 @@ char * getLineFromPipe(FILE* npipe) {
} }
} }
// command[= \t]*args[ \t]* // command[= \t]*args[ \t]*
int parse_cmd(FILE* npipe) { int parse_cmd(FILE* npipe)
{
char * cmd; char * cmd;
char * args; char * args;
char * argse; char * argse;
int d; int d;
double dd; double dd;
// if (!((cmd=getLineFromPipe(npipe)))) return 0; //! nothing in the pipe // if (!((cmd=getLineFromPipe(npipe)))) return 0; //! nothing in the pipe
//!skip empty commands //!skip empty commands
while(((cmd=getLineFromPipe(npipe))) && !cmd[0]) ; while (((cmd = getLineFromPipe(npipe))) && !cmd[0]) ;
if (!cmd) return 0; //! nothing in the pipe if (!cmd) return 0; //! nothing in the pipe
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(G_DAEMON_ERR + lastDaemonBit) = GLOBALPARS(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?
if (args) { if (args) {
args[0]=0; args[0] = 0;
args++; args++;
while (strchr("= \t",args[0])) args++; while (strchr("= \t", args[0])) args++;
if (args[0]) { if (args[0]) {
//! ltrim (args) //! ltrim (args)
for (argse=strchr(args,'\0')-1; strchr("= \t",argse[0]);argse--) argse[0]='\0'; for (argse = strchr(args, '\0') - 1; strchr("= \t", argse[0]); argse--) argse[0] = '\0';
} }
if (!args[0]) args=NULL; if (!args[0]) args = NULL;
} }
//! 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();
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();
return 2; return 2;
} else if (strcmp(cmd, "stop")==0) { } else if (strcmp(cmd, "stop") == 0) {
camogm_stop(); camogm_stop();
return 3; return 3;
} else if (strcmp(cmd, "exit")==0) { } else if (strcmp(cmd, "exit") == 0) {
camogm_stop(); camogm_stop();
camogm_free(); camogm_free();
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(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(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(args);
return 6; return 6;
} else if (strcmp(cmd, "status")==0) { } else if (strcmp(cmd, "status") == 0) {
camogm_status(args, 0); camogm_status(args, 0);
return 7; return 7;
} else if (strcmp(cmd, "xstatus")==0) { } else if (strcmp(cmd, "xstatus") == 0) {
camogm_status(args, 1); camogm_status(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(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(d);
return 8; return 8;
} else if (strcmp(cmd, "debug")==0) { } else if (strcmp(cmd, "debug") == 0) {
camogm_debug(args); camogm_debug(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(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
} 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(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(-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(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(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(CAMOGM_FORMAT_JPEG);
else if (strcmp(args, "mov" )==0) camogm_set_format(CAMOGM_FORMAT_MOV); else if (strcmp(args, "mov" ) == 0) camogm_set_format(CAMOGM_FORMAT_MOV);
} }
return 12; return 12;
} else if (strcmp(cmd, "debuglev")==0) { } else if (strcmp(cmd, "debuglev") == 0) {
d= strtol(args, NULL, 10); d = strtol(args, NULL, 10);
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(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(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(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(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(1);
else if (strcmp(args, "ground")==0) camogm_kml_set_height_mode(0); else if (strcmp(args, "ground") == 0) camogm_kml_set_height_mode(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(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(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(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(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(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(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(dd);
return 25; return 25;
} }
...@@ -1208,10 +1233,10 @@ int parse_cmd(FILE* npipe) { ...@@ -1208,10 +1233,10 @@ int parse_cmd(FILE* npipe) {
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
const char circbufFileName[]="/dev/circbuf"; 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" \
"It is designed to run in the background and accept commands through a named pipe.\n\n" \ "It is designed to run in the background and accept commands through a named pipe.\n\n" \
"Usage:\n\n" \ "Usage:\n\n" \
"%s <named_pipe_name>\n\n" \ "%s <named_pipe_name>\n\n" \
...@@ -1229,48 +1254,49 @@ int main(int argc, char *argv[]) ...@@ -1229,48 +1254,49 @@ int main(int argc, char *argv[])
"This program does not control the process of acquisition of the video/images to the camera internal\n" \ "This program does not control the process of acquisition of the video/images to the camera internal\n" \
"buffer, it only retrieves that data from the buffer (waiting when needed), packages it to selected\n" \ "buffer, it only retrieves that data from the buffer (waiting when needed), packages it to selected\n" \
"format and stores the result files.\n\n"; "format and stores the result files.\n\n";
int go=1; int go = 1;
int cmd; int cmd;
int i,rslt; int i, rslt;
int fp0,fp1; // debugging int fp0, fp1; // debugging
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]);
return 0; return 0;
} }
camogm_init(); camogm_init();
//! open Exif header file //! open Exif header file
state->fd_exif = open(ExifFileName, O_RDONLY); state->fd_exif = open(ExifFileName, 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", ExifFileName));
return -1; return -1;
} }
//! open JPEG header file //! open JPEG header file
state->fd_head = open(HeadFileName, O_RDWR); state->fd_head = open(HeadFileName, 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", HeadFileName));
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 ));
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(circbufFileName, 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", circbufFileName));
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 = (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 == -1) {
D0(fprintf (debug_file,"Error in mmap of %s\n",circbufFileName)); D0(fprintf(debug_file, "Error in mmap of %s\n", circbufFileName));
// close (fd_head); // close (fd_head);
close(state->fd_circ); close(state->fd_circ);
return -3; return -3;
...@@ -1280,50 +1306,50 @@ int main(int argc, char *argv[]) ...@@ -1280,50 +1306,50 @@ int main(int argc, char *argv[])
//! 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(ctlFileName, 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__, ctlFileName));
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 = (struct framepars_all_t*)mmap(0, sizeof(struct framepars_all_t), PROT_READ | PROT_WRITE, MAP_SHARED, state->fd_fparmsall, 0);
if((int)frameParsAll == -1) { if ((int)frameParsAll == -1) {
D0(fprintf(debug_file,"%s:%d:%s: Error in mmap in %s\n",__FILE__,__LINE__,__FUNCTION__,ctlFileName)); D0(fprintf(debug_file, "%s:%d:%s: Error in mmap in %s\n", __FILE__, __LINE__, __FUNCTION__, ctlFileName));
close(state->fd_fparmsall); close(state->fd_fparmsall);
close(state->fd_circ); close(state->fd_circ);
return -3; return -3;
} }
framePars=frameParsAll->framePars; framePars = frameParsAll->framePars;
globalPars=frameParsAll->globalPars; globalPars = frameParsAll->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(argv[1]);
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", argv[1], i, errno));
} }
i=mkfifo(argv[1], 0777); //EEXIST i = mkfifo(argv[1], 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", argv[1]));
} 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", argv[1], errno));
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(argv[1], "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", argv[1]));
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", argv[1])); // 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
...@@ -1332,21 +1358,21 @@ int main(int argc, char *argv[]) ...@@ -1332,21 +1358,21 @@ 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(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
// GLOBALPARS(G_DAEMON_ERR+lastDaemonBit)=GLOBALPARS(G_THIS_FRAME); // GLOBALPARS(G_DAEMON_ERR+lastDaemonBit)=GLOBALPARS(G_THIS_FRAME);
} 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())) {
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" \
"state->cirbuf_rp= 0x%x\n",__FILE__,__LINE__,rslt,state->cirbuf_rp)); "state->cirbuf_rp= 0x%x\n",__FILE__,__LINE__,rslt,state->cirbuf_rp));
*/ */
break; //! frame sent OK, nothing to do (TODO: check file length/duration) break; //! frame sent OK, nothing to do (TODO: check file length/duration)
case CAMOGM_FRAME_NOT_READY: //! just wait for the frame to appear at the current pointer case CAMOGM_FRAME_NOT_READY: //! just wait for the frame to appear at the current pointer
//! we'll wait for a frame, not to waste resources. But if the compressor is stopped this program will not respond to any commands //! we'll wait for a frame, not to waste resources. But if the compressor is stopped this program will not respond to any commands
...@@ -1355,17 +1381,17 @@ int main(int argc, char *argv[]) ...@@ -1355,17 +1381,17 @@ int main(int argc, char *argv[])
/* /*
D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned -%d\n" \ D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned -%d\n" \
"state->cirbuf_rp= 0x%x\n",__FILE__,__LINE__,rslt,state->cirbuf_rp)); "state->cirbuf_rp= 0x%x\n",__FILE__,__LINE__,rslt,state->cirbuf_rp));
*/ */
// lseek(state->fd_circ,LSEEK_CIRC_WAIT,SEEK_END); // lseek(state->fd_circ,LSEEK_CIRC_WAIT,SEEK_END);
fp0=lseek(state->fd_circ,0,SEEK_CUR); fp0 = lseek(state->fd_circ, 0, SEEK_CUR);
if (fp0<0) { if (fp0 < 0) {
D0(fprintf (debug_file,"%s:line %d got broken frame (%d) before waiting for ready\n",__FILE__,__LINE__,fp0)); D0(fprintf(debug_file, "%s:line %d got broken frame (%d) before waiting for ready\n", __FILE__, __LINE__, fp0));
rslt=CAMOGM_FRAME_BROKEN; rslt = CAMOGM_FRAME_BROKEN;
} else { } else {
fp1=lseek(state->fd_circ,LSEEK_CIRC_WAIT,SEEK_END); fp1 = lseek(state->fd_circ, LSEEK_CIRC_WAIT, SEEK_END);
if (fp1<0) { if (fp1 < 0) {
D0(fprintf (debug_file,"%s:line %d got broken frame (%d) while waiting for ready. Before that fp0=0x%x\n",__FILE__,__LINE__,fp1,fp0)); D0(fprintf(debug_file, "%s:line %d got broken frame (%d) while waiting for ready. Before that fp0=0x%x\n", __FILE__, __LINE__, fp1, fp0));
rslt=CAMOGM_FRAME_BROKEN; rslt = CAMOGM_FRAME_BROKEN;
} else { } else {
break; break;
} }
...@@ -1382,22 +1408,22 @@ int main(int argc, char *argv[]) ...@@ -1382,22 +1408,22 @@ int main(int argc, char *argv[])
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
D0(fprintf (debug_file,"%s:line %d - error=%d\n",__FILE__,__LINE__,rslt)); D0(fprintf(debug_file, "%s:line %d - error=%d\n", __FILE__, __LINE__, rslt));
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));
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;
} else if (state->starting) { //!no commands in queue,starting (but not started yet) } else if (state->starting) { //!no commands in queue,starting (but not started yet)
// 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())) {
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
lseek(state->fd_circ,LSEEK_CIRC_WAIT,SEEK_END); /// It already passed CAMOGM_FRAME_NOT_READY, so compressor may be running already lseek(state->fd_circ, LSEEK_CIRC_WAIT, SEEK_END); /// It already passed CAMOGM_FRAME_NOT_READY, so compressor may be running already
break; /// no need to wait extra break; /// no need to wait extra
case CAMOGM_FRAME_NOT_READY: //! just wait for the frame to appear at the current pointer case CAMOGM_FRAME_NOT_READY: //! just wait for the frame to appear at the current pointer
//! we'll wait for a frame, not to waste resources. But if the compressor is stopped this program will not respond to any commands //! we'll wait for a frame, not to waste resources. But if the compressor is stopped this program will not respond to any commands
...@@ -1408,20 +1434,20 @@ int main(int argc, char *argv[]) ...@@ -1408,20 +1434,20 @@ int main(int argc, char *argv[])
case CAMOGM_FRAME_INVALID: //! invalid frame pointer case CAMOGM_FRAME_INVALID: //! invalid frame pointer
case CAMOGM_FRAME_BROKEN: //! frame broken (buffer overrun) case CAMOGM_FRAME_BROKEN: //! frame broken (buffer overrun)
// D3(fprintf (debug_file,"%s:line %d - camogm_start() returned -%d, state->cirbuf_rp= 0x%x\n", __FILE__,__LINE__,rslt,state->cirbuf_rp)); // D3(fprintf (debug_file,"%s:line %d - camogm_start() returned -%d, state->cirbuf_rp= 0x%x\n", __FILE__,__LINE__,rslt,state->cirbuf_rp));
usleep( COMMAND_LOOP_DELAY) ; //! it should be not too long so empty buffer will not be overrun usleep( COMMAND_LOOP_DELAY); //! it should be not too long so empty buffer will not be overrun
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
D0(fprintf (debug_file,"%s:line %d - error=%d\n",__FILE__,__LINE__,rslt)); D0(fprintf(debug_file, "%s:line %d - error=%d\n", __FILE__, __LINE__, rslt));
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));
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;
} else { //! not running, not starting } else { //! not running, not starting
usleep( COMMAND_LOOP_DELAY) ; //! make it longer but interruptible by signals? usleep( COMMAND_LOOP_DELAY); //! make it longer but interruptible by signals?
} }
} }
return 0; return 0;
...@@ -1432,9 +1458,10 @@ int main(int argc, char *argv[]) ...@@ -1432,9 +1458,10 @@ int main(int argc, char *argv[])
* @param GPNumber parameter number (as defined in c313a.h), G_* parameters have numbers above FRAMEPAR_GLOBALS, P_* - below) * @param GPNumber parameter number (as defined in c313a.h), G_* parameters have numbers above FRAMEPAR_GLOBALS, P_* - below)
* @return parameter value * @return parameter value
*/ */
unsigned long getGPValue(unsigned long GPNumber) { unsigned long getGPValue(unsigned long GPNumber)
return (GPNumber>=FRAMEPAR_GLOBALS)? {
GLOBALPARS(GPNumber): return (GPNumber >= FRAMEPAR_GLOBALS) ?
GLOBALPARS(GPNumber) :
framePars[GLOBALPARS(G_THIS_FRAME) & PARS_FRAMES_MASK].pars[GPNumber]; framePars[GLOBALPARS(G_THIS_FRAME) & PARS_FRAMES_MASK].pars[GPNumber];
} }
...@@ -1443,8 +1470,9 @@ unsigned long getGPValue(unsigned long GPNumber) { ...@@ -1443,8 +1470,9 @@ unsigned long getGPValue(unsigned long GPNumber) {
* @param GNumber - parameter number (as defined in c313a.h) * @param GNumber - parameter number (as defined in c313a.h)
* @param value - value to set * @param value - value to set
*/ */
void setGValue(unsigned long GNumber, unsigned long value) { void setGValue(unsigned long GNumber, unsigned long value)
GLOBALPARS(GNumber)=value; {
GLOBALPARS(GNumber) = value;
} }
/** /**
...@@ -1453,13 +1481,14 @@ void setGValue(unsigned long GNumber, unsigned long value) { ...@@ -1453,13 +1481,14 @@ void setGValue(unsigned long GNumber, unsigned long value) {
* @param daemonBit - bit number to accept control in P_DAEMON_EN parameter * @param 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(int daemonBit) // <0 - use default
if ((daemonBit>=0) && (daemonBit<32)) lastDaemonBit=daemonBit; {
unsigned long this_frame=this_frame=GLOBALPARS(G_THIS_FRAME); if ((daemonBit >= 0) && (daemonBit < 32)) lastDaemonBit = daemonBit;
unsigned long this_frame = this_frame = GLOBALPARS(G_THIS_FRAME);
/// No semaphors, so it is possible to miss event and wait until the streamer will be re-enabled before sending message, /// 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 /// but it seems not so terrible
lseek(state->fd_circ, LSEEK_DAEMON_CIRCBUF+lastDaemonBit, SEEK_END); /// lseek(state->fd_circ, LSEEK_DAEMON_CIRCBUF + lastDaemonBit, SEEK_END); ///
if (this_frame==GLOBALPARS(G_THIS_FRAME)) return 1; if (this_frame == GLOBALPARS(G_THIS_FRAME)) return 1;
return 0; return 0;
} }
...@@ -1468,7 +1497,8 @@ int waitDaemonEnabled(int daemonBit) { // <0 - use default ...@@ -1468,7 +1497,8 @@ int waitDaemonEnabled(int daemonBit) { // <0 - use default
* @param daemonBit - bit number to accept control in P_DAEMON_EN parameter * @param 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(int daemonBit) // <0 - use default
if ((daemonBit>=0) && (daemonBit<32)) lastDaemonBit=daemonBit; {
return ((framePars[GLOBALPARS(G_THIS_FRAME) & PARS_FRAMES_MASK].pars[P_DAEMON_EN] & (1 <<lastDaemonBit))!=0); if ((daemonBit >= 0) && (daemonBit < 32)) lastDaemonBit = daemonBit;
return ((framePars[GLOBALPARS(G_THIS_FRAME) & PARS_FRAMES_MASK].pars[P_DAEMON_EN] & (1 << lastDaemonBit)) != 0);
} }
...@@ -13,17 +13,17 @@ ...@@ -13,17 +13,17 @@
#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 D(x) {if (debug_file && debug_level){x;fflush(debug_file);}} #define D(x) { if (debug_file && debug_level) { x; fflush(debug_file); } }
#define D0(x) {if (debug_file){x;fflush(debug_file);}} #define D0(x) { if (debug_file) { x; fflush(debug_file); } }
#define D1(x) {if (debug_file && (debug_level > 0)){x;fflush(debug_file);}} #define D1(x) { if (debug_file && (debug_level > 0)) { x; fflush(debug_file); } }
#define D2(x) {if (debug_file && (debug_level > 1)){x;fflush(debug_file);}} #define D2(x) { if (debug_file && (debug_level > 1)) { x; fflush(debug_file); } }
#define D3(x) {if (debug_file && (debug_level > 2)){x;fflush(debug_file);}} #define D3(x) { if (debug_file && (debug_level > 2)) { x; fflush(debug_file); } }
#define D4(x) {if (debug_file && (debug_level > 3)){x;fflush(debug_file);}} #define D4(x) { if (debug_file && (debug_level > 3)) { x; fflush(debug_file); } }
#define D5(x) {if (debug_file && (debug_level > 4)){x;fflush(debug_file);}} #define D5(x) { if (debug_file && (debug_level > 4)) { x; fflush(debug_file); } }
#define D6(x) {if (debug_file && (debug_level > 5)){x;fflush(debug_file);}} #define D6(x) { if (debug_file && (debug_level > 5)) { x; fflush(debug_file); } }
//#define DD(x) //#define DD(x)
#define DD(x) {if (debug_file){fprintf(debug_file,"%s:%d:",__FILE__,__LINE__);x;fflush(debug_file);}} #define DD(x) { if (debug_file) { fprintf(debug_file, "%s:%d:", __FILE__, __LINE__); x; fflush(debug_file); } }
// HEADER_SIZE is defined to be larger than actual header (later - with EXIF) to use compile-time buffer // HEADER_SIZE is defined to be larger than actual header (later - with EXIF) to use compile-time buffer
#define JPEG_HEADER_MAXSIZE 0x300 // will not change #define JPEG_HEADER_MAXSIZE 0x300 // will not change
...@@ -32,43 +32,43 @@ ...@@ -32,43 +32,43 @@
/* /*
#define Exif_Photo_DateTimeOriginal 0x19003 #define Exif_Photo_DateTimeOriginal 0x19003
#define Exif_GPSInfo_GPSLatitudeRef 0x20001 #define Exif_GPSInfo_GPSLatitudeRef 0x20001
#define Exif_GPSInfo_GPSLatitude 0x20002 #define Exif_GPSInfo_GPSLatitude 0x20002
#define Exif_GPSInfo_GPSLongitudeRef 0x20003 #define Exif_GPSInfo_GPSLongitudeRef 0x20003
#define Exif_GPSInfo_GPSLongitude 0x20004 #define Exif_GPSInfo_GPSLongitude 0x20004
#define Exif_GPSInfo_GPSAltitudeRef 0x20005 #define Exif_GPSInfo_GPSAltitudeRef 0x20005
#define Exif_GPSInfo_GPSAltitude 0x20006 #define Exif_GPSInfo_GPSAltitude 0x20006
#define Exif_GPSInfo_GPSTimeStamp 0x20007 #define Exif_GPSInfo_GPSTimeStamp 0x20007
#define Exif_GPSInfo_GPSDateStamp 0x2001D #define Exif_GPSInfo_GPSDateStamp 0x2001D
#define Exif_GPSInfo_CompassDirectionRef 0x20010 #define Exif_GPSInfo_CompassDirectionRef 0x20010
#define Exif_GPSInfo_CompassDirection 0x20011 #define Exif_GPSInfo_CompassDirection 0x20011
#define Exif_GPSInfo_CompassPitchRef 0x20013 #define Exif_GPSInfo_CompassPitchRef 0x20013
#define Exif_GPSInfo_CompassPitch 0x20014 #define Exif_GPSInfo_CompassPitch 0x20014
#define Exif_GPSInfo_CompassRollRef 0x20015 #define Exif_GPSInfo_CompassRollRef 0x20015
#define Exif_GPSInfo_CompassRoll 0x20016 #define Exif_GPSInfo_CompassRoll 0x20016
*/ */
/* /*
/// Exif data (variable, stored with each frame) used for KML (not only) /// Exif data (variable, stored with each frame) used for KML (not only)
#define Exif_Image_ImageDescription_Index 0x00 #define Exif_Image_ImageDescription_Index 0x00
#define Exif_Photo_DateTimeOriginal_Index 0x01 #define Exif_Photo_DateTimeOriginal_Index 0x01
#define Exif_Photo_SubSecTimeOriginal_Index 0x02 #define Exif_Photo_SubSecTimeOriginal_Index 0x02
#define Exif_GPSInfo_GPSLatitudeRef_Index 0x03 #define Exif_GPSInfo_GPSLatitudeRef_Index 0x03
#define Exif_GPSInfo_GPSLatitude_Index 0x04 #define Exif_GPSInfo_GPSLatitude_Index 0x04
#define Exif_GPSInfo_GPSLongitudeRef_Index 0x05 #define Exif_GPSInfo_GPSLongitudeRef_Index 0x05
#define Exif_GPSInfo_GPSLongitude_Index 0x06 #define Exif_GPSInfo_GPSLongitude_Index 0x06
#define Exif_GPSInfo_GPSAltitudeRef_Index 0x07 #define Exif_GPSInfo_GPSAltitudeRef_Index 0x07
#define Exif_GPSInfo_GPSAltitude_Index 0x08 #define Exif_GPSInfo_GPSAltitude_Index 0x08
#define Exif_GPSInfo_GPSTimeStamp_Index 0x09 #define Exif_GPSInfo_GPSTimeStamp_Index 0x09
#define Exif_GPSInfo_GPSDateStamp_Index 0x0a #define Exif_GPSInfo_GPSDateStamp_Index 0x0a
#define Exif_GPSInfo_CompassDirectionRef_Index 0x0b #define Exif_GPSInfo_CompassDirectionRef_Index 0x0b
#define Exif_GPSInfo_CompassDirection_Index 0x0c #define Exif_GPSInfo_CompassDirection_Index 0x0c
#define Exif_GPSInfo_CompassPitchRef_Index 0x0d #define Exif_GPSInfo_CompassPitchRef_Index 0x0d
#define Exif_GPSInfo_CompassPitch_Index 0x0e #define Exif_GPSInfo_CompassPitch_Index 0x0e
#define Exif_GPSInfo_CompassRollRef_Index 0x0f #define Exif_GPSInfo_CompassRollRef_Index 0x0f
#define Exif_GPSInfo_CompassRoll_Index 0x10 #define Exif_GPSInfo_CompassRoll_Index 0x10
#define ExifKmlNumber 0x11 #define ExifKmlNumber 0x11
*/ */
typedef struct { typedef struct {
int segment_duration; int segment_duration;
int segment_length; int segment_length;
...@@ -89,7 +89,7 @@ typedef struct { ...@@ -89,7 +89,7 @@ typedef struct {
struct interframe_params_t frame_params; struct interframe_params_t frame_params;
struct interframe_params_t this_frame_params; struct interframe_params_t this_frame_params;
int jpeg_len; int jpeg_len;
int frame_period ; //!in microseconds (1/10 of what is needed for the Ogm header) int frame_period; //!in microseconds (1/10 of what is needed for the Ogm header)
int width; int width;
int height; int height;
int starting; int starting;
...@@ -153,7 +153,7 @@ typedef struct { ...@@ -153,7 +153,7 @@ typedef struct {
int kml_period; //! generate PhotoOverlay for each kml_period seconds; int kml_period; //! generate PhotoOverlay for each kml_period seconds;
int kml_last_ts; //! last generated kml file timestamp int kml_last_ts; //! last generated kml file timestamp
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
} camogm_state; } camogm_state;
......
/*!*************************************************************************** /*!***************************************************************************
*! FILE NAME : camogm_jpeg.c *! FILE NAME : camogm_jpeg.c
*! DESCRIPTION: Provides writing to series of individual JPEG files for camogm *! DESCRIPTION: Provides writing to series of individual JPEG files for camogm
*! Copyright (C) 2007 Elphel, Inc. *! Copyright (C) 2007 Elphel, Inc.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify *! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by *! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or *! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version. *! (at your option) any later version.
*! *!
*! This program is distributed in the hope that it will be useful, *! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of *! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details. *! GNU General Public License for more details.
*! *!
*! You should have received a copy of the GNU General Public License *! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>. *! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! *!
*! $Log: camogm_jpeg.c,v $ *! $Log: camogm_jpeg.c,v $
*! Revision 1.2 2009/02/25 17:50:51 spectr_rain *! Revision 1.2 2009/02/25 17:50:51 spectr_rain
*! removed deprecated dependency *! removed deprecated dependency
*! *!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel *! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*! *!
*! *!
*! Revision 1.3 2008/04/11 23:09:33 elphel *! Revision 1.3 2008/04/11 23:09:33 elphel
*! modified to handle kml generation *! modified to handle kml generation
*! *!
*! Revision 1.2 2007/11/19 03:23:21 elphel *! Revision 1.2 2007/11/19 03:23:21 elphel
*! 7.1.5.5 Added support for *.mov files in camogm. *! 7.1.5.5 Added support for *.mov files in camogm.
*! *!
*! Revision 1.1 2007/11/16 08:49:57 elphel *! Revision 1.1 2007/11/16 08:49:57 elphel
*! Initial release of camogm - program to record video/image to the camera hard drive (or other storage) *! Initial release of camogm - program to record video/image to the camera hard drive (or other storage)
*! *!
*/ */
//!Not all are needed, just copied from the camogm.c //!Not all are needed, just copied from the camogm.c
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
...@@ -64,64 +64,71 @@ ...@@ -64,64 +64,71 @@
#include "camogm_jpeg.h" #include "camogm_jpeg.h"
#include "camogm.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)
{
return 0; return 0;
} }
void camogm_free_jpeg(void) { void camogm_free_jpeg(void)
{
} }
int camogm_start_jpeg(void) { int camogm_start_jpeg(void)
{
//!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;
int rslt; int rslt;
strcpy (state->path,state->path_prefix); //!make state->path a directory name (will be replaced when the frames will be written)
slash=strrchr(state->path,'/'); strcpy(state->path, state->path_prefix); //!make state->path a directory name (will be replaced when the frames will be written)
D2(fprintf (debug_file, "camogm_start_jpeg\n")); slash = strrchr(state->path, '/');
D2(fprintf(debug_file, "camogm_start_jpeg\n"));
if (slash) { if (slash) {
D3(fprintf (debug_file, "Full path %s\n", state->path)); D3(fprintf(debug_file, "Full path %s\n", state->path));
slash[0]='\0'; //! truncate path to the directory name slash[0] = '\0'; //! truncate path to the directory name
D3(fprintf (debug_file, "directory path %s\n", state->path)); D3(fprintf(debug_file, "directory path %s\n", state->path));
rslt=mkdir(state->path, 0777); rslt = mkdir(state->path, 0777);
D3(fprintf (debug_file, "mkdir (%s, 0777) returned %d, errno=%d\n", state->path, rslt, errno)); D3(fprintf(debug_file, "mkdir (%s, 0777) returned %d, errno=%d\n", state->path, rslt, errno));
if ((rslt<0) && (errno != EEXIST)) { // already exists is OK if ((rslt < 0) && (errno != EEXIST)) { // already exists is OK
D0(fprintf (debug_file, "Error creating directory %s, errno=%d\n", state->path, errno)); D0(fprintf(debug_file, "Error creating directory %s, errno=%d\n", state->path, errno));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
} }
return 0; return 0;
} }
int camogm_frame_jpeg(void){ int camogm_frame_jpeg(void)
int i,j; {
int i, j;
// int fd; // int fd;
ssize_t iovlen,l; ssize_t iovlen, l;
struct iovec chunks_iovec[7]; struct iovec chunks_iovec[7];
l=0;
for (i=0; i< (state->chunk_index)-1; i++) { l = 0;
chunks_iovec[i].iov_base=state->packetchunks[i+1].chunk; for (i = 0; i < (state->chunk_index) - 1; i++) {
chunks_iovec[i].iov_len= state->packetchunks[i+1].bytes; chunks_iovec[i].iov_base = state->packetchunks[i + 1].chunk;
l+=chunks_iovec[i].iov_len; chunks_iovec[i].iov_len = state->packetchunks[i + 1].bytes;
l += chunks_iovec[i].iov_len;
} }
sprintf(state->path,"%s%010ld_%06ld.jpeg",state->path_prefix,state->this_frame_params.timestamp_sec,state->this_frame_params.timestamp_usec); sprintf(state->path, "%s%010ld_%06ld.jpeg", state->path_prefix, state->this_frame_params.timestamp_sec, state->this_frame_params.timestamp_usec);
// if ((devfd = open("/dev/fpgaio", O_RDWR))<0) {printf("error opening /dev/fpgaio\r\n"); return -1;} // if ((devfd = open("/dev/fpgaio", O_RDWR))<0) {printf("error opening /dev/fpgaio\r\n"); return -1;}
//_1__12_Error opening /tmp/z/video1195147018_273452.jpeg for writing //_1__12_Error opening /tmp/z/video1195147018_273452.jpeg for writing
if (((state->ivf=open(state->path,O_RDWR | O_CREAT, 0777)))<0){ if (((state->ivf = open(state->path, O_RDWR | O_CREAT, 0777))) < 0) {
D0(fprintf (debug_file, "Error opening %s for writing, returned %d, errno=%d\n", state->path,state->ivf,errno)); D0(fprintf(debug_file, "Error opening %s for writing, returned %d, errno=%d\n", state->path, state->ivf, errno));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
iovlen=writev(state->ivf,chunks_iovec, (state->chunk_index)-1); iovlen = writev(state->ivf, chunks_iovec, (state->chunk_index) - 1);
if (iovlen < l) { if (iovlen < l) {
j=errno; j = errno;
D0(fprintf(debug_file,"writev error %d (returned %d, expected %d)\n",j,iovlen,l)); D0(fprintf(debug_file, "writev error %d (returned %d, expected %d)\n", j, iovlen, l));
close (state->ivf); close(state->ivf);
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
close (state->ivf); close(state->ivf);
return 0; return 0;
} }
int camogm_end_jpeg(void){ int camogm_end_jpeg(void)
{
return 0; return 0;
} }
/*!*************************************************************************** /*!***************************************************************************
*! FILE NAME : camogm_kml.c *! FILE NAME : camogm_kml.c
*! DESCRIPTION: Provides writing to series of individual JPEG files for camogm *! DESCRIPTION: Provides writing to series of individual JPEG files for camogm
*! Copyright (C) 2007 Elphel, Inc. *! Copyright (C) 2007 Elphel, Inc.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify *! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by *! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or *! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version. *! (at your option) any later version.
*! *!
*! This program is distributed in the hope that it will be useful, *! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of *! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details. *! GNU General Public License for more details.
*! *!
*! You should have received a copy of the GNU General Public License *! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>. *! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! *!
*! $Log: camogm_kml.c,v $ *! $Log: camogm_kml.c,v $
*! Revision 1.3 2011/01/03 22:00:29 elphel *! Revision 1.3 2011/01/03 22:00:29 elphel
*! fixed tilt generation *! fixed tilt generation
*! *!
*! Revision 1.2 2009/02/25 17:50:02 spectr_rain *! Revision 1.2 2009/02/25 17:50:02 spectr_rain
*! removed deprecated dependency *! removed deprecated dependency
*! *!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel *! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*! *!
*! *!
*! Revision 1.2 2008/04/13 21:05:20 elphel *! Revision 1.2 2008/04/13 21:05:20 elphel
*! Fixing KML generation *! Fixing KML generation
*! *!
*! Revision 1.1 2008/04/11 23:06:52 elphel *! Revision 1.1 2008/04/11 23:06:52 elphel
*! files to handle KML generation *! files to handle KML generation
*! *!
*! *!
*/ */
//!Not all are needed, just copied from the camogm.c //!Not all are needed, just copied from the camogm.c
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
...@@ -64,34 +64,37 @@ ...@@ -64,34 +64,37 @@
#include "camogm_kml.h" #include "camogm_kml.h"
#include "camogm.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
int camogm_init_kml(void) { int camogm_init_kml(void)
{
return 0; return 0;
} }
void camogm_free_kml(void) { void camogm_free_kml(void)
{
} }
/* /*
int camogm_start_mov(void) { int camogm_start_mov(void) {
//! allocate memory for the frame index table //! allocate memory for the frame index table
if (!((state->frame_lengths=malloc(4*state->max_frames)))) return -CAMOGM_FRAME_MALLOC ; if (!((state->frame_lengths=malloc(4*state->max_frames)))) return -CAMOGM_FRAME_MALLOC ;
//! open file for writing //! open file for writing
sprintf(state->path,"%s%010ld_%06ld.mov",state->path_prefix,state->frame_params.timestamp_sec,state->frame_params.timestamp_usec); sprintf(state->path,"%s%010ld_%06ld.mov",state->path_prefix,state->frame_params.timestamp_sec,state->frame_params.timestamp_usec);
if (((state->ivf=open(state->path,O_RDWR | O_CREAT, 0777)))<0){ if (((state->ivf=open(state->path,O_RDWR | O_CREAT, 0777)))<0){
D0(fprintf (debug_file, "Error opening %s for writing, returned %d, errno=%d\n", state->path,state->ivf,errno)); D0(fprintf (debug_file, "Error opening %s for writing, returned %d, errno=%d\n", state->path,state->ivf,errno));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
//!skip header (plus extra) //!skip header (plus extra)
//! Quicktime (and else?) - frame data start (0xff 0xd8...) //! Quicktime (and else?) - frame data start (0xff 0xd8...)
state->frame_data_start=QUICKTIME_MIN_HEADER+16+ 4*(state->max_frames)+ ( 4*(state->max_frames))/(state->frames_per_chunk); // 8 bytes for "skip" tag state->frame_data_start=QUICKTIME_MIN_HEADER+16+ 4*(state->max_frames)+ ( 4*(state->max_frames))/(state->frames_per_chunk); // 8 bytes for "skip" tag
lseek(state->ivf, state->frame_data_start, SEEK_SET); lseek(state->ivf, state->frame_data_start, SEEK_SET);
return 0; return 0;
} }
*/ */
int camogm_start_kml(void) { int camogm_start_kml(void)
{
// 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
/// state->kml_exif[i] /// state->kml_exif[i]
...@@ -99,184 +102,187 @@ int camogm_start_kml(void) { ...@@ -99,184 +102,187 @@ int camogm_start_kml(void) {
struct exif_dir_table_t dir_table_entry; struct exif_dir_table_t dir_table_entry;
int fd_ExifDir; int fd_ExifDir;
int indx; int indx;
for (indx=0;indx<ExifKmlNumber;indx++) state->kml_exif[indx].ltag=0;
for (indx = 0; indx < ExifKmlNumber; indx++) state->kml_exif[indx].ltag = 0;
//! open Exif header directory file //! open Exif header directory file
fd_ExifDir=open(ExifDirFileName,O_RDONLY); fd_ExifDir = open(ExifDirFileName, O_RDONLY);
if (fd_ExifDir<0) { // check control OK if (fd_ExifDir < 0) { // check control OK
D0(fprintf (debug_file,"Error opening %s\n", ExifDirFileName)); D0(fprintf(debug_file, "Error opening %s\n", ExifDirFileName));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
while (read(fd_ExifDir, &dir_table_entry, sizeof(dir_table_entry))>0) { while (read(fd_ExifDir, &dir_table_entry, sizeof(dir_table_entry)) > 0) {
switch (dir_table_entry.ltag) { switch (dir_table_entry.ltag) {
case Exif_Photo_DateTimeOriginal: indx= Exif_Photo_DateTimeOriginal_Index; break; case Exif_Photo_DateTimeOriginal: indx = Exif_Photo_DateTimeOriginal_Index; break;
case Exif_GPSInfo_GPSLatitudeRef: indx= Exif_GPSInfo_GPSLatitudeRef_Index; break; case Exif_GPSInfo_GPSLatitudeRef: indx = Exif_GPSInfo_GPSLatitudeRef_Index; break;
case Exif_GPSInfo_GPSLatitude: indx= Exif_GPSInfo_GPSLatitude_Index ; break; case Exif_GPSInfo_GPSLatitude: indx = Exif_GPSInfo_GPSLatitude_Index; break;
case Exif_GPSInfo_GPSLongitudeRef: indx= Exif_GPSInfo_GPSLongitudeRef_Index ; break; case Exif_GPSInfo_GPSLongitudeRef: indx = Exif_GPSInfo_GPSLongitudeRef_Index; break;
case Exif_GPSInfo_GPSLongitude: indx= Exif_GPSInfo_GPSLongitude_Index; break; case Exif_GPSInfo_GPSLongitude: indx = Exif_GPSInfo_GPSLongitude_Index; break;
case Exif_GPSInfo_GPSAltitudeRef: indx= Exif_GPSInfo_GPSAltitudeRef_Index; break; case Exif_GPSInfo_GPSAltitudeRef: indx = Exif_GPSInfo_GPSAltitudeRef_Index; break;
case Exif_GPSInfo_GPSAltitude: indx= Exif_GPSInfo_GPSAltitude_Index; break; case Exif_GPSInfo_GPSAltitude: indx = Exif_GPSInfo_GPSAltitude_Index; break;
case Exif_GPSInfo_GPSTimeStamp: indx= Exif_GPSInfo_GPSTimeStamp_Index; break; case Exif_GPSInfo_GPSTimeStamp: indx = Exif_GPSInfo_GPSTimeStamp_Index; break;
case Exif_GPSInfo_GPSDateStamp: indx= Exif_GPSInfo_GPSDateStamp_Index; break; case Exif_GPSInfo_GPSDateStamp: indx = Exif_GPSInfo_GPSDateStamp_Index; break;
case Exif_GPSInfo_CompassDirectionRef: indx= Exif_GPSInfo_CompassDirectionRef_Index; break; case Exif_GPSInfo_CompassDirectionRef: indx = Exif_GPSInfo_CompassDirectionRef_Index; break;
case Exif_GPSInfo_CompassDirection: indx= Exif_GPSInfo_CompassDirection_Index; break; case Exif_GPSInfo_CompassDirection: indx = Exif_GPSInfo_CompassDirection_Index; break;
case Exif_GPSInfo_CompassPitchRef: indx= Exif_GPSInfo_CompassPitchRef_Index; break; case Exif_GPSInfo_CompassPitchRef: indx = Exif_GPSInfo_CompassPitchRef_Index; break;
case Exif_GPSInfo_CompassPitch: indx= Exif_GPSInfo_CompassPitch_Index; break; case Exif_GPSInfo_CompassPitch: indx = Exif_GPSInfo_CompassPitch_Index; break;
case Exif_GPSInfo_CompassRollRef: indx= Exif_GPSInfo_CompassRollRef_Index; break; case Exif_GPSInfo_CompassRollRef: indx = Exif_GPSInfo_CompassRollRef_Index; break;
case Exif_GPSInfo_CompassRoll: indx= Exif_GPSInfo_CompassRoll_Index; break; case Exif_GPSInfo_CompassRoll: indx = Exif_GPSInfo_CompassRoll_Index; break;
default: indx=-1; default: indx = -1;
} }
if (indx>=0) { if (indx >= 0) {
memcpy(&(state->kml_exif[indx]),&dir_table_entry,sizeof(dir_table_entry)); memcpy(&(state->kml_exif[indx]), &dir_table_entry, sizeof(dir_table_entry));
D2(fprintf(debug_file,"indx=%02d, ltag=0x%05x, len=0x%03x, src=0x%03x, dst=0x%03x\n",indx, \ D2(fprintf(debug_file, "indx=%02d, ltag=0x%05x, len=0x%03x, src=0x%03x, dst=0x%03x\n", indx, \
(int) dir_table_entry.ltag, \ (int)dir_table_entry.ltag, \
(int) dir_table_entry.len, \ (int)dir_table_entry.len, \
(int) dir_table_entry.src, \ (int)dir_table_entry.src, \
(int) dir_table_entry.dst)); (int)dir_table_entry.dst));
} }
} }
close (fd_ExifDir); close(fd_ExifDir);
sprintf(state->kml_path,"%s%010ld_%06ld.kml",state->path_prefix,state->this_frame_params.timestamp_sec,state->this_frame_params.timestamp_usec); sprintf(state->kml_path, "%s%010ld_%06ld.kml", state->path_prefix, state->this_frame_params.timestamp_sec, state->this_frame_params.timestamp_usec);
if (!((state->kml_file=fopen(state->kml_path,"w+"))) ){ if (!((state->kml_file = fopen(state->kml_path, "w+"))) ) {
D0(fprintf (debug_file, "Error opening %s for writing\n", state->kml_path)); D0(fprintf(debug_file, "Error opening %s for writing\n", state->kml_path));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
/// write start of the KML file /// write start of the KML file
fprintf (state->kml_file,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \ fprintf(state->kml_file, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
"<kml xmlns=\"http://earth.google.com/kml/2.2\">\n"); "<kml xmlns=\"http://earth.google.com/kml/2.2\">\n");
fprintf (state->kml_file,"<Document>\n"); fprintf(state->kml_file, "<Document>\n");
state->kml_used= 1; state->kml_used = 1;
return 0; return 0;
} }
int camogm_frame_kml(void){ int camogm_frame_kml(void)
{
char JPEGFileName[300]; char JPEGFileName[300];
char * filename; char * filename;
int fd_JPEG; int fd_JPEG;
int i,j; int i, j;
ssize_t iovlen,l; ssize_t iovlen, l;
struct iovec chunks_iovec[7]; struct iovec chunks_iovec[7];
char datestr[11]; char datestr[11];
double longitude=0.0, latitude=0.0, altitude=0.0, heading=0.0, tilt=0.0, roll=0.0, pitch=0.0; double longitude = 0.0, latitude = 0.0, altitude = 0.0, heading = 0.0, tilt = 0.0, roll = 0.0, pitch = 0.0;
int hours=0, minutes=0; int hours = 0, minutes = 0;
double seconds=0.0; double seconds = 0.0;
int * ip; int * ip;
if (state->kml_file) { // probably not needed if (state->kml_file) { // probably not needed
i=state->this_frame_params.timestamp_sec - (state->kml_last_ts + state->kml_period); i = state->this_frame_params.timestamp_sec - (state->kml_last_ts + state->kml_period);
if ((i>1) || ((i==0) && ( state->this_frame_params.timestamp_usec > state->kml_last_uts ))) { if ((i > 1) || ((i == 0) && ( state->this_frame_params.timestamp_usec > state->kml_last_uts ))) {
// if (state->this_frame_params.timestamp_sec > (state->kml_last_ts + state->kml_period)) { // this way it is safe to put kml_period=1000, then kml_period=1 // if (state->this_frame_params.timestamp_sec > (state->kml_last_ts + state->kml_period)) { // this way it is safe to put kml_period=1000, then kml_period=1
state->kml_last_ts=state->this_frame_params.timestamp_sec; state->kml_last_ts = state->this_frame_params.timestamp_sec;
state->kml_last_uts=state->this_frame_params.timestamp_usec; state->kml_last_uts = state->this_frame_params.timestamp_usec;
if (state->format==CAMOGM_FORMAT_JPEG) { if (state->format == CAMOGM_FORMAT_JPEG) {
strcpy (JPEGFileName, state->path); strcpy(JPEGFileName, state->path);
} else { } else {
sprintf(JPEGFileName,"%s%010ld_%06ld.jpeg",state->path_prefix,state->this_frame_params.timestamp_sec,state->this_frame_params.timestamp_usec); sprintf(JPEGFileName, "%s%010ld_%06ld.jpeg", state->path_prefix, state->this_frame_params.timestamp_sec, state->this_frame_params.timestamp_usec);
if (((fd_JPEG=open(JPEGFileName,O_RDWR | O_CREAT, 0777)))>=0){ if (((fd_JPEG = open(JPEGFileName, O_RDWR | O_CREAT, 0777))) >= 0) {
l=0; l = 0;
for (i=0; i< (state->chunk_index)-1; i++) { for (i = 0; i < (state->chunk_index) - 1; i++) {
chunks_iovec[i].iov_base=state->packetchunks[i+1].chunk; chunks_iovec[i].iov_base = state->packetchunks[i + 1].chunk;
chunks_iovec[i].iov_len= state->packetchunks[i+1].bytes; chunks_iovec[i].iov_len = state->packetchunks[i + 1].bytes;
l+=chunks_iovec[i].iov_len; l += chunks_iovec[i].iov_len;
} }
iovlen=writev(fd_JPEG,chunks_iovec, (state->chunk_index)-1); iovlen = writev(fd_JPEG, chunks_iovec, (state->chunk_index) - 1);
if (iovlen < l) { if (iovlen < l) {
j=errno; j = errno;
D0(fprintf(debug_file,"writev error %d (returned %d, expected %d)\n",j,iovlen,l)); D0(fprintf(debug_file, "writev error %d (returned %d, expected %d)\n", j, iovlen, l));
close (fd_JPEG); close(fd_JPEG);
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
close (fd_JPEG); close(fd_JPEG);
} else { } else {
D0(fprintf (debug_file, "Error opening %s for writing, returned %d, errno=%d\n", JPEGFileName,fd_JPEG,errno)); D0(fprintf(debug_file, "Error opening %s for writing, returned %d, errno=%d\n", JPEGFileName, fd_JPEG, errno));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
} }
/// now we have JPEGFileName written. find realtive (to KML) location: /// now we have JPEGFileName written. find realtive (to KML) location:
filename=strrchr(JPEGFileName, '/'); filename = strrchr(JPEGFileName, '/');
filename[0]='\0'; filename[0] = '\0';
filename++; filename++;
///generating KML itself ///generating KML itself
/// Using GPS time - in the same structure /// Using GPS time - in the same structure
if (state->kml_exif[Exif_GPSInfo_GPSDateStamp_Index].ltag==Exif_GPSInfo_GPSDateStamp) { // Exif_GPSInfo_GPSDateStamp is present in template if (state->kml_exif[Exif_GPSInfo_GPSDateStamp_Index].ltag == Exif_GPSInfo_GPSDateStamp) { // Exif_GPSInfo_GPSDateStamp is present in template
memcpy(datestr, &(state->ed[state->kml_exif[Exif_GPSInfo_GPSDateStamp_Index].dst]) ,10); memcpy(datestr, &(state->ed[state->kml_exif[Exif_GPSInfo_GPSDateStamp_Index].dst]), 10);
datestr[4]='-';datestr[7]='-';datestr[10]='\0'; datestr[4] = '-'; datestr[7] = '-'; datestr[10] = '\0';
} }
if (state->kml_exif[Exif_GPSInfo_GPSTimeStamp_Index].ltag==Exif_GPSInfo_GPSTimeStamp) { // Exif_GPSInfo_GPSTimeStamp is present in template if (state->kml_exif[Exif_GPSInfo_GPSTimeStamp_Index].ltag == Exif_GPSInfo_GPSTimeStamp) { // Exif_GPSInfo_GPSTimeStamp is present in template
ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_GPSTimeStamp_Index].dst]); ip = (int*)&(state->ed[state->kml_exif[Exif_GPSInfo_GPSTimeStamp_Index].dst]);
hours= __cpu_to_be32( ip[0]); hours = __cpu_to_be32( ip[0]);
minutes= __cpu_to_be32( ip[2]); minutes = __cpu_to_be32( ip[2]);
seconds= (1.0*(__cpu_to_be32( ip[4])+1))/__cpu_to_be32( ip[5]); /// GPS likes ".999", let's inc by one - anyway will round that out seconds = (1.0 * (__cpu_to_be32( ip[4]) + 1)) / __cpu_to_be32( ip[5]); /// GPS likes ".999", let's inc by one - anyway will round that out
D2(fprintf (debug_file,"(when) 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",ip[0],ip[1],ip[2],ip[3],ip[4],ip[5])); D2(fprintf(debug_file, "(when) 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", ip[0], ip[1], ip[2], ip[3], ip[4], ip[5]));
D2(fprintf (debug_file,"(when) 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",__cpu_to_be32(ip[0]), \ D2(fprintf(debug_file, "(when) 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", __cpu_to_be32(ip[0]), \
__cpu_to_be32(ip[1]), \ __cpu_to_be32(ip[1]), \
__cpu_to_be32(ip[2]), \ __cpu_to_be32(ip[2]), \
__cpu_to_be32(ip[3]), \ __cpu_to_be32(ip[3]), \
__cpu_to_be32(ip[4]), \ __cpu_to_be32(ip[4]), \
__cpu_to_be32(ip[5]))); __cpu_to_be32(ip[5])));
} }
D1(fprintf (debug_file,"when=%sT%02d:%02d:%05.2fZ\n",datestr, hours, minutes, seconds)); D1(fprintf(debug_file, "when=%sT%02d:%02d:%05.2fZ\n", datestr, hours, minutes, seconds));
/// knowing format provided from GPS - degrees and minuts only, no seconds: /// knowing format provided from GPS - degrees and minuts only, no seconds:
if (state->kml_exif[Exif_GPSInfo_GPSLongitude_Index].ltag==Exif_GPSInfo_GPSLongitude) { // Exif_GPSInfo_GPSLongitude is present in template if (state->kml_exif[Exif_GPSInfo_GPSLongitude_Index].ltag == Exif_GPSInfo_GPSLongitude) { // Exif_GPSInfo_GPSLongitude is present in template
ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_GPSLongitude_Index].dst]); ip = (int*)&(state->ed[state->kml_exif[Exif_GPSInfo_GPSLongitude_Index].dst]);
longitude=__cpu_to_be32( ip[0])/(1.0*__cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2])/(60.0*__cpu_to_be32( ip[3])); longitude = __cpu_to_be32( ip[0]) / (1.0 * __cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2]) / (60.0 * __cpu_to_be32( ip[3]));
if ((state->kml_exif[Exif_GPSInfo_GPSLongitudeRef_Index].ltag==Exif_GPSInfo_GPSLongitudeRef) && if ((state->kml_exif[Exif_GPSInfo_GPSLongitudeRef_Index].ltag == Exif_GPSInfo_GPSLongitudeRef) &&
(state->ed[state->kml_exif[Exif_GPSInfo_GPSLongitudeRef_Index].dst] != 'E')) longitude=-longitude; (state->ed[state->kml_exif[Exif_GPSInfo_GPSLongitudeRef_Index].dst] != 'E')) longitude = -longitude;
D2(fprintf (debug_file,"(longitude) 0x%x 0x%x 0x%x 0x%x '%c'\n",ip[0],ip[1],ip[2],ip[3],state->ed[state->kml_exif[Exif_GPSInfo_GPSLongitudeRef_Index].dst])); D2(fprintf(debug_file, "(longitude) 0x%x 0x%x 0x%x 0x%x '%c'\n", ip[0], ip[1], ip[2], ip[3], state->ed[state->kml_exif[Exif_GPSInfo_GPSLongitudeRef_Index].dst]));
} }
if (state->kml_exif[Exif_GPSInfo_GPSLatitude_Index].ltag==Exif_GPSInfo_GPSLatitude) { // Exif_GPSInfo_GPSLatitude is present in template if (state->kml_exif[Exif_GPSInfo_GPSLatitude_Index].ltag == Exif_GPSInfo_GPSLatitude) { // Exif_GPSInfo_GPSLatitude is present in template
ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_GPSLatitude_Index].dst]); ip = (int*)&(state->ed[state->kml_exif[Exif_GPSInfo_GPSLatitude_Index].dst]);
latitude=__cpu_to_be32( ip[0])/(1.0*__cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2])/(60.0*__cpu_to_be32( ip[3])); latitude = __cpu_to_be32( ip[0]) / (1.0 * __cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2]) / (60.0 * __cpu_to_be32( ip[3]));
if ((state->kml_exif[Exif_GPSInfo_GPSLatitudeRef_Index].ltag==Exif_GPSInfo_GPSLatitudeRef) && if ((state->kml_exif[Exif_GPSInfo_GPSLatitudeRef_Index].ltag == Exif_GPSInfo_GPSLatitudeRef) &&
(state->ed[state->kml_exif[Exif_GPSInfo_GPSLatitudeRef_Index].dst] != 'N')) latitude=-latitude; (state->ed[state->kml_exif[Exif_GPSInfo_GPSLatitudeRef_Index].dst] != 'N')) latitude = -latitude;
D2(fprintf (debug_file,"(latitude) 0x%x 0x%x 0x%x 0x%x '%c'\n",ip[0],ip[1],ip[2],ip[3],state->ed[state->kml_exif[Exif_GPSInfo_GPSLatitudeRef_Index].dst]?'-':'+')); D2(fprintf(debug_file, "(latitude) 0x%x 0x%x 0x%x 0x%x '%c'\n", ip[0], ip[1], ip[2], ip[3], state->ed[state->kml_exif[Exif_GPSInfo_GPSLatitudeRef_Index].dst] ? '-' : '+'));
} }
/// altitude - will be modified/replaced later /// altitude - will be modified/replaced later
if (state->kml_exif[Exif_GPSInfo_GPSAltitude_Index].ltag==Exif_GPSInfo_GPSAltitude) { // Exif_GPSInfo_GPSAltitude is present in template if (state->kml_exif[Exif_GPSInfo_GPSAltitude_Index].ltag == Exif_GPSInfo_GPSAltitude) { // Exif_GPSInfo_GPSAltitude is present in template
ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_GPSAltitude_Index].dst]); ip = (int*)&(state->ed[state->kml_exif[Exif_GPSInfo_GPSAltitude_Index].dst]);
altitude=(1.0*__cpu_to_be32( ip[0]))/__cpu_to_be32( ip[1]); altitude = (1.0 * __cpu_to_be32( ip[0])) / __cpu_to_be32( ip[1]);
if ((state->kml_exif[Exif_GPSInfo_GPSAltitudeRef_Index].ltag==Exif_GPSInfo_GPSAltitudeRef) && if ((state->kml_exif[Exif_GPSInfo_GPSAltitudeRef_Index].ltag == Exif_GPSInfo_GPSAltitudeRef) &&
(state->ed[state->kml_exif[Exif_GPSInfo_GPSAltitudeRef_Index].dst] != '\0')) altitude=-altitude; (state->ed[state->kml_exif[Exif_GPSInfo_GPSAltitudeRef_Index].dst] != '\0')) altitude = -altitude;
D2(fprintf (debug_file,"(altitude) 0x%x 0x%x '%c'\n",ip[0],ip[1],state->ed[state->kml_exif[Exif_GPSInfo_GPSAltitudeRef_Index].dst])); D2(fprintf(debug_file, "(altitude) 0x%x 0x%x '%c'\n", ip[0], ip[1], state->ed[state->kml_exif[Exif_GPSInfo_GPSAltitudeRef_Index].dst]));
} }
D1(fprintf (debug_file,"longitude=%f, latitude=%f, altitude=%f\n",longitude, latitude, altitude)); D1(fprintf(debug_file, "longitude=%f, latitude=%f, altitude=%f\n", longitude, latitude, altitude));
/// Heading - no processing of "True/Magnetic" Exif_GPSInfo_CompassDirectionRef now (always M) /// Heading - no processing of "True/Magnetic" Exif_GPSInfo_CompassDirectionRef now (always M)
if (state->kml_exif[Exif_GPSInfo_CompassDirection_Index].ltag==Exif_GPSInfo_CompassDirection) { // Exif_GPSInfo_CompassDirection is present in template if (state->kml_exif[Exif_GPSInfo_CompassDirection_Index].ltag == Exif_GPSInfo_CompassDirection) { // Exif_GPSInfo_CompassDirection is present in template
ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_CompassDirection_Index].dst]); ip = (int*)&(state->ed[state->kml_exif[Exif_GPSInfo_CompassDirection_Index].dst]);
heading=(1.0*__cpu_to_be32( ip[0]))/__cpu_to_be32( ip[1]); heading = (1.0 * __cpu_to_be32( ip[0])) / __cpu_to_be32( ip[1]);
D2(fprintf (debug_file,"(heading) 0x%x 0x%x\n",ip[0],ip[1])); D2(fprintf(debug_file, "(heading) 0x%x 0x%x\n", ip[0], ip[1]));
} }
///Processing 'hacked' pitch and roll (made of Exif destination latitude/longitude) ///Processing 'hacked' pitch and roll (made of Exif destination latitude/longitude)
if (state->kml_exif[Exif_GPSInfo_CompassRoll_Index].ltag==Exif_GPSInfo_CompassRoll) { // Exif_GPSInfo_CompassRoll is present in template if (state->kml_exif[Exif_GPSInfo_CompassRoll_Index].ltag == Exif_GPSInfo_CompassRoll) { // Exif_GPSInfo_CompassRoll is present in template
ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_CompassRoll_Index].dst]); ip = (int*)&(state->ed[state->kml_exif[Exif_GPSInfo_CompassRoll_Index].dst]);
roll=__cpu_to_be32( ip[0])/(1.0*__cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2])/(60.0*__cpu_to_be32( ip[3])); roll = __cpu_to_be32( ip[0]) / (1.0 * __cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2]) / (60.0 * __cpu_to_be32( ip[3]));
if ((state->kml_exif[Exif_GPSInfo_CompassRollRef_Index].ltag==Exif_GPSInfo_CompassRollRef) && if ((state->kml_exif[Exif_GPSInfo_CompassRollRef_Index].ltag == Exif_GPSInfo_CompassRollRef) &&
(state->ed[state->kml_exif[Exif_GPSInfo_CompassRollRef_Index].dst] != EXIF_COMPASS_ROLL_ASCII[0])) roll=-roll; (state->ed[state->kml_exif[Exif_GPSInfo_CompassRollRef_Index].dst] != EXIF_COMPASS_ROLL_ASCII[0])) roll = -roll;
D2(fprintf (debug_file,"(roll) 0x%x 0x%x '%c'\n",ip[0],ip[1],state->ed[state->kml_exif[Exif_GPSInfo_CompassRollRef_Index].dst])); D2(fprintf(debug_file, "(roll) 0x%x 0x%x '%c'\n", ip[0], ip[1], state->ed[state->kml_exif[Exif_GPSInfo_CompassRollRef_Index].dst]));
} }
if (state->kml_exif[Exif_GPSInfo_CompassPitch_Index].ltag==Exif_GPSInfo_CompassPitch) { // Exif_GPSInfo_CompassPitch is present in template if (state->kml_exif[Exif_GPSInfo_CompassPitch_Index].ltag == Exif_GPSInfo_CompassPitch) { // Exif_GPSInfo_CompassPitch is present in template
ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_CompassPitch_Index].dst]); ip = (int*)&(state->ed[state->kml_exif[Exif_GPSInfo_CompassPitch_Index].dst]);
pitch=__cpu_to_be32( ip[0])/(1.0*__cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2])/(60.0*__cpu_to_be32( ip[3])); pitch = __cpu_to_be32( ip[0]) / (1.0 * __cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2]) / (60.0 * __cpu_to_be32( ip[3]));
if ((state->kml_exif[Exif_GPSInfo_CompassPitchRef_Index].ltag==Exif_GPSInfo_CompassPitchRef) && if ((state->kml_exif[Exif_GPSInfo_CompassPitchRef_Index].ltag == Exif_GPSInfo_CompassPitchRef) &&
(state->ed[state->kml_exif[Exif_GPSInfo_CompassPitchRef_Index].dst] != EXIF_COMPASS_PITCH_ASCII[0])) pitch=-pitch; (state->ed[state->kml_exif[Exif_GPSInfo_CompassPitchRef_Index].dst] != EXIF_COMPASS_PITCH_ASCII[0])) pitch = -pitch;
D2(fprintf (debug_file,"(pitch) 0x%x 0x%x '%c'\n",ip[0],ip[1],state->ed[state->kml_exif[Exif_GPSInfo_CompassPitchRef_Index].dst])); D2(fprintf(debug_file, "(pitch) 0x%x 0x%x '%c'\n", ip[0], ip[1], state->ed[state->kml_exif[Exif_GPSInfo_CompassPitchRef_Index].dst]));
} }
/// convert from GPS heading, pitch, roll to KML heading, tilt, roll /// convert from GPS heading, pitch, roll to KML heading, tilt, roll
tilt=pitch+90.0; tilt = pitch + 90.0;
if (tilt <0.0) tilt=0; if (tilt < 0.0) tilt = 0;
else if (tilt > 180.0) tilt=180.0; else if (tilt > 180.0) tilt = 180.0;
D2(fprintf (debug_file,"heading=%f, roll=%f, pitch=%f, tilt=%f\n",heading, roll, pitch, tilt)); D2(fprintf(debug_file, "heading=%f, roll=%f, pitch=%f, tilt=%f\n", heading, roll, pitch, tilt));
/// modify altitude /// modify altitude
altitude=(state->kml_height_mode?altitude:0.0)+state->kml_height; altitude = (state->kml_height_mode ? altitude : 0.0) + state->kml_height;
/// write to KML /// write to KML
fprintf(state->kml_file,"<PhotoOverlay>\n" \ fprintf(state->kml_file, "<PhotoOverlay>\n" \
" <shape>rectangle</shape>\n" \ " <shape>rectangle</shape>\n" \
" <TimeStamp>\n" \ " <TimeStamp>\n" \
" <when>%sT%02d:%02d:%05.2fZ</when>\n" \ " <when>%sT%02d:%02d:%05.2fZ</when>\n" \
...@@ -302,7 +308,7 @@ int camogm_frame_kml(void){ ...@@ -302,7 +308,7 @@ int camogm_frame_kml(void){
" </ViewVolume>\n" \ " </ViewVolume>\n" \
"</PhotoOverlay>\n", \ "</PhotoOverlay>\n", \
datestr, hours, minutes, seconds, \ datestr, hours, minutes, seconds, \
filename, longitude,latitude,altitude,heading,tilt,roll,state->kml_height_mode?"absolute":"relativeToGround", \ filename, longitude, latitude, altitude, heading, tilt, roll, state->kml_height_mode ? "absolute" : "relativeToGround", \
-(state->kml_horHalfFov), state->kml_horHalfFov, -(state->kml_vertHalfFov), state->kml_vertHalfFov, state->kml_near); -(state->kml_horHalfFov), state->kml_horHalfFov, -(state->kml_vertHalfFov), state->kml_vertHalfFov, state->kml_near);
} }
} }
...@@ -310,13 +316,14 @@ int camogm_frame_kml(void){ ...@@ -310,13 +316,14 @@ int camogm_frame_kml(void){
} }
int camogm_end_kml(void){ int camogm_end_kml(void)
{
if (state->kml_file) { if (state->kml_file) {
fprintf (state->kml_file,"</Document>\n"); fprintf(state->kml_file, "</Document>\n");
fprintf (state->kml_file,"</kml>\n"); fprintf(state->kml_file, "</kml>\n");
fclose(state->kml_file); fclose(state->kml_file);
state->kml_file=NULL; state->kml_file = NULL;
} }
return 0; return 0;
} }
......
...@@ -15,13 +15,13 @@ void camogm_free_kml(void); ...@@ -15,13 +15,13 @@ void camogm_free_kml(void);
/* /*
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2"> <kml xmlns="http://earth.google.com/kml/2.2">
<Document> <Document>
<PhotoOverlay> <PhotoOverlay>
<TimeStamp> <TimeStamp>
<when>2007-01-14T21:05:02Z</when> <when>2007-01-14T21:05:02Z</when>
...@@ -73,9 +73,9 @@ void camogm_free_kml(void); ...@@ -73,9 +73,9 @@ void camogm_free_kml(void);
<coordinates>...</coordinates> <!-- lon,lat[,alt] --> <coordinates>...</coordinates> <!-- lon,lat[,alt] -->
</Point> </Point>
<shape>rectangle</shape> <!-- kml:shape --> <shape>rectangle</shape> <!-- kml:shape -->
</PhotoOverlay> </PhotoOverlay>
<Camera id="ID"> <Camera id="ID">
<longitude>0</longitude> <!-- kml:angle180 --> <longitude>0</longitude> <!-- kml:angle180 -->
<latitude>0</latitude> <!-- kml:angle90 --> <latitude>0</latitude> <!-- kml:angle90 -->
<altitude>0</altitude> <!-- double --> <altitude>0</altitude> <!-- double -->
...@@ -85,4 +85,4 @@ void camogm_free_kml(void); ...@@ -85,4 +85,4 @@ void camogm_free_kml(void);
<altitudeMode>clampToGround</altitudeMode> <altitudeMode>clampToGround</altitudeMode>
<!-- kml:altitudeModeEnum: relativeToGround, clampToGround, or absolute --> <!-- kml:altitudeModeEnum: relativeToGround, clampToGround, or absolute -->
</Camera> </Camera>
*/ */
/*!*************************************************************************** /*!***************************************************************************
*! FILE NAME : camogm_mov.c *! FILE NAME : camogm_mov.c
*! DESCRIPTION: Provides writing to file compatible with Apple Quicktime(R) for camogm *! DESCRIPTION: Provides writing to file compatible with Apple Quicktime(R) for camogm
*!TODO: Nothing yet here, will be added ASAP *!TODO: Nothing yet here, will be added ASAP
*! Copyright (C) 2007 Elphel, Inc. *! Copyright (C) 2007 Elphel, Inc.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify *! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by *! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or *! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version. *! (at your option) any later version.
*! *!
*! This program is distributed in the hope that it will be useful, *! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of *! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details. *! GNU General Public License for more details.
*! *!
*! You should have received a copy of the GNU General Public License *! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>. *! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! *!
*! $Log: camogm_mov.c,v $ *! $Log: camogm_mov.c,v $
*! Revision 1.2 2009/02/25 17:50:02 spectr_rain *! Revision 1.2 2009/02/25 17:50:02 spectr_rain
*! removed deprecated dependency *! removed deprecated dependency
*! *!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel *! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*! *!
*! *!
*! Revision 1.4 2008/04/11 23:09:33 elphel *! Revision 1.4 2008/04/11 23:09:33 elphel
*! modified to handle kml generation *! modified to handle kml generation
*! *!
*! Revision 1.3 2007/11/19 17:00:20 elphel *! Revision 1.3 2007/11/19 17:00:20 elphel
*! removed wrong dependency *! removed wrong dependency
*! *!
*! Revision 1.2 2007/11/19 03:23:21 elphel *! Revision 1.2 2007/11/19 03:23:21 elphel
*! 7.1.5.5 Added support for *.mov files in camogm. *! 7.1.5.5 Added support for *.mov files in camogm.
*! *!
*! Revision 1.1 2007/11/16 08:49:57 elphel *! Revision 1.1 2007/11/16 08:49:57 elphel
*! Initial release of camogm - program to record video/image to the camera hard drive (or other storage) *! Initial release of camogm - program to record video/image to the camera hard drive (or other storage)
*! *!
*/ */
//!Not all are needed, just copied from the camogm.c //!Not all are needed, just copied from the camogm.c
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
...@@ -73,27 +73,27 @@ ...@@ -73,27 +73,27 @@
//! for the parser //! for the parser
const char hexStr[]="0123456789abcdef"; const char hexStr[] = "0123456789abcdef";
const char qtSourceFileName[]= "/etc/qt_source"; const char qtSourceFileName[] = "/etc/qt_source";
char comStr[1024]; char comStr[1024];
int width=1280; int width = 1280;
int height=1024; int height = 1024;
int nframes=100; int nframes = 100;
int sample_dur=80; int sample_dur = 80;
int samplesPerChunk=10; int samplesPerChunk = 10;
int framesize=80000; int framesize = 80000;
int timescale=600; int timescale = 600;
int * sizes; // array of frame sizes int * sizes; // array of frame sizes
int iPos; //!position in the string "iFile" int iPos; //!position in the string "iFile"
//int oPos; //!position in the string "oFile" //int oPos; //!position in the string "oFile"
int ofd; // output file descriptor (file opened by the caller) int ofd; // output file descriptor (file opened by the caller)
int iFileLen; int iFileLen;
char * q_template=NULL; char * q_template = NULL;
long headerSize=0; 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(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,127 +107,135 @@ int quicktime_template_parser (const char * i_iFile, //! now - string containing ...@@ -107,127 +107,135 @@ int quicktime_template_parser (const char * i_iFile, //! now - string containing
); );
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(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)
{
FILE* qt_header; FILE* qt_header;
int size; int size;
if ((qt_header= fopen (qtSourceFileName,"r"))==NULL) {
D0(fprintf (debug_file,"Error opening Quicktime header template %s for reading\n", qtSourceFileName)); if ((qt_header = fopen(qtSourceFileName, "r")) == NULL) {
D0(fprintf(debug_file, "Error opening Quicktime header template %s for reading\n", qtSourceFileName));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
fseek(qt_header, 0, SEEK_END); fseek(qt_header, 0, SEEK_END);
size=ftell(qt_header); size = ftell(qt_header);
//malloc(4*state->max_frames); //malloc(4*state->max_frames);
if (!((q_template=malloc(size+1)))) { if (!((q_template = malloc(size + 1)))) {
D0(fprintf (debug_file,"Could not allocate %d bytes of memory for Quicktime header template\n", (size+1))); D0(fprintf(debug_file, "Could not allocate %d bytes of memory for Quicktime header template\n", (size + 1)));
fclose(qt_header); fclose(qt_header);
return -CAMOGM_FRAME_MALLOC ; return -CAMOGM_FRAME_MALLOC;
} }
fseek(qt_header, 0, SEEK_SET); //rewind fseek(qt_header, 0, SEEK_SET); //rewind
if (fread (q_template,size,1,qt_header)<1) { if (fread(q_template, size, 1, qt_header) < 1) {
D0(fprintf (debug_file,"Could not read %d bytes of Quicktime header template from %s\n", (size+1),qtSourceFileName)); D0(fprintf(debug_file, "Could not read %d bytes of Quicktime header template from %s\n", (size + 1), qtSourceFileName));
free(q_template); free(q_template);
q_template=NULL; q_template = NULL;
fclose(qt_header); fclose(qt_header);
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
q_template[size]=0; q_template[size] = 0;
return 0; return 0;
} }
void camogm_free_mov(void) { void camogm_free_mov(void)
{
if (q_template) { if (q_template) {
free (q_template); free(q_template);
q_template=NULL; q_template = NULL;
} }
} }
int camogm_start_mov(void) { int camogm_start_mov(void)
{
//! allocate memory for the frame index table //! allocate memory for the frame index table
if (!((state->frame_lengths=malloc(4*state->max_frames)))) return -CAMOGM_FRAME_MALLOC ; if (!((state->frame_lengths = malloc(4 * state->max_frames)))) return -CAMOGM_FRAME_MALLOC;
//! open file for writing //! open file for writing
sprintf(state->path,"%s%010ld_%06ld.mov",state->path_prefix,state->frame_params.timestamp_sec,state->frame_params.timestamp_usec); sprintf(state->path, "%s%010ld_%06ld.mov", state->path_prefix, state->frame_params.timestamp_sec, state->frame_params.timestamp_usec);
if (((state->ivf=open(state->path,O_RDWR | O_CREAT, 0777)))<0){ if (((state->ivf = open(state->path, O_RDWR | O_CREAT, 0777))) < 0) {
D0(fprintf (debug_file, "Error opening %s for writing, returned %d, errno=%d\n", state->path,state->ivf,errno)); D0(fprintf(debug_file, "Error opening %s for writing, returned %d, errno=%d\n", state->path, state->ivf, errno));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
//!skip header (plus extra) //!skip header (plus extra)
//! Quicktime (and else?) - frame data start (0xff 0xd8...) //! Quicktime (and else?) - frame data start (0xff 0xd8...)
state->frame_data_start=QUICKTIME_MIN_HEADER+16+ 4*(state->max_frames)+ ( 4*(state->max_frames))/(state->frames_per_chunk); // 8 bytes for "skip" tag state->frame_data_start = QUICKTIME_MIN_HEADER + 16 + 4 * (state->max_frames) + ( 4 * (state->max_frames)) / (state->frames_per_chunk); // 8 bytes for "skip" tag
lseek(state->ivf, state->frame_data_start, SEEK_SET); lseek(state->ivf, state->frame_data_start, SEEK_SET);
return 0; return 0;
} }
int camogm_frame_mov(void){ int camogm_frame_mov(void)
int i,j; {
ssize_t iovlen,l; int i, j;
ssize_t iovlen, l;
struct iovec chunks_iovec[7]; struct iovec chunks_iovec[7];
l=0;
for (i=0; i< (state->chunk_index)-1; i++) { l = 0;
chunks_iovec[i].iov_base=state->packetchunks[i+1].chunk; for (i = 0; i < (state->chunk_index) - 1; i++) {
chunks_iovec[i].iov_len= state->packetchunks[i+1].bytes; chunks_iovec[i].iov_base = state->packetchunks[i + 1].chunk;
l+=chunks_iovec[i].iov_len; chunks_iovec[i].iov_len = state->packetchunks[i + 1].bytes;
l += chunks_iovec[i].iov_len;
} }
iovlen=writev(state->ivf,chunks_iovec, (state->chunk_index)-1); iovlen = writev(state->ivf, chunks_iovec, (state->chunk_index) - 1);
if (iovlen < l) { if (iovlen < l) {
j=errno; j = errno;
D0(fprintf(debug_file,"writev error %d (returned %d, expected %d)\n",j,iovlen,l)); D0(fprintf(debug_file, "writev error %d (returned %d, expected %d)\n", j, iovlen, l));
close (state->ivf); close(state->ivf);
state->ivf=-1; state->ivf = -1;
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
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 //!move to the start of the file and insert generated header
int camogm_end_mov(void){ int camogm_end_mov(void)
{
off_t l/*,he; off_t l/*,he;
unsigned char mdat_tag[8]; unsigned char mdat_tag[8];
unsigned char skip_tag[]="\0\0\0\0skip"*/; unsigned char skip_tag[]="\0\0\0\0skip"*/;
timescale=10000; //! frame period measured in 1/10000 of a second?
timescale = 10000; //! frame period measured in 1/10000 of a second?
//! that was in old code. If that works - try to switch to microseconds //! that was in old code. If that works - try to switch to microseconds
l=lseek(state->ivf, 0, SEEK_CUR) - (state->frame_data_start)+8; //!4-byte length+"mdat" l = lseek(state->ivf, 0, SEEK_CUR) - (state->frame_data_start) + 8; //!4-byte length+"mdat"
// 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(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,
state->frameno, state->frameno,
state->frame_period/ (1000000/timescale), state->frame_period / (1000000 / timescale),
state->frames_per_chunk, state->frames_per_chunk,
0, //!frame size - will look in the table 0, //!frame size - will look in the table
(int) ((float)timescale/(state->timescale)), (int)((float)timescale / (state->timescale)),
state->frame_lengths, //! array of frame lengths to build an index state->frame_lengths, //! array of frame lengths to build an index
state->frame_data_start state->frame_data_start
); );
#if 0 #if 0
//! now we need to overwrite last mdat tag in the header to the skip the gap, instead of the length 'mdat //! now we need to overwrite last mdat tag in the header to the skip the gap, instead of the length 'mdat
//! put length 'skip length 'mdat //! put length 'skip length 'mdat
he=lseek(state->ivf, 0, SEEK_CUR);// just after the original header end he = lseek(state->ivf, 0, SEEK_CUR); // just after the original header end
l=state->frame_data_start-he; //! should be >= l = state->frame_data_start - he; //! should be >=
D4(fprintf (debug_file,"Remaining gap between Quicktime header and the data is %d (it should be>=8) \n", (int) l)); D4(fprintf(debug_file, "Remaining gap between Quicktime header and the data is %d (it should be>=8) \n", (int)l));
lseek(state->ivf, he-8, SEEK_SET); lseek(state->ivf, he - 8, SEEK_SET);
read (state->ivf, mdat_tag,8); //!read calculated length+'mdat' tag read(state->ivf, mdat_tag, 8); //!read calculated length+'mdat' tag
lseek(state->ivf, state->frame_data_start-8, SEEK_SET); lseek(state->ivf, state->frame_data_start - 8, SEEK_SET);
write(state->ivf, mdat_tag,8); write(state->ivf, mdat_tag, 8);
skip_tag[0]=(l >> 24) & 0xff; skip_tag[0] = (l >> 24) & 0xff;
skip_tag[1]=(l >> 16) & 0xff; skip_tag[1] = (l >> 16) & 0xff;
skip_tag[2]=(l >> 8) & 0xff; skip_tag[2] = (l >> 8) & 0xff;
skip_tag[3]=(l ) & 0xff; skip_tag[3] = (l ) & 0xff;
lseek(state->ivf, he-8, SEEK_SET); lseek(state->ivf, he - 8, SEEK_SET);
write(state->ivf, skip_tag,8); write(state->ivf, skip_tag, 8);
#endif #endif
close (state->ivf); close(state->ivf);
state->ivf=-1; state->ivf = -1;
//! free memory used for index //! free memory used for index
if (state->frame_lengths) { if (state->frame_lengths) {
free(state->frame_lengths); free(state->frame_lengths);
state->frame_lengths=NULL; state->frame_lengths = NULL;
} }
return 0; return 0;
} }
...@@ -237,161 +245,187 @@ int camogm_end_mov(void){ ...@@ -237,161 +245,187 @@ int camogm_end_mov(void){
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
*/ */
void putBigEndian(unsigned long d, int l)
{
unsigned char od[4];
void putBigEndian(unsigned long d, int l) { od[3] = d;
unsigned char od[4]; od[2] = d >> 8;
od[3]=d; od[1] = d >> 16;
od[2]=d >> 8; od[0] = d >> 24;
od[1]=d >> 16; if (l) write(ofd, &od[4 - l], l);
od[0]=d >> 24;
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)
{
int l; int l;
const char * eol=strchr(&stream[*pos],'\n'); const char * eol = strchr(&stream[*pos], '\n');
if (!eol) eol=stream+(strlen(stream)-1); //!pointer to last before \0
l=(eol-stream)-(*pos); if (!eol) eol = stream + (strlen(stream) - 1); //!pointer to last before \0
l = (eol - stream) - (*pos);
// if (l >= size) eol=stream+ (*pos+size-1); // if (l >= size) eol=stream+ (*pos+size-1);
if (l >= size) l=size-1; if (l >= size) l = size - 1;
memcpy(str, &stream[*pos],l); memcpy(str, &stream[*pos], l);
str[l]='\0'; str[l] = '\0';
*pos+=l; *pos += l;
return str; return str;
} }
int parse_special(void) { int parse_special(void)
{
time_t ltime; time_t ltime;
int n,j,l; int n, j, l;
char str[256]; char str[256];
char c; char c;
int i=0; int i = 0;
int gap; int gap;
// while (((c=fgetc(infile))!=0x20) && (c!=0x09) && (c!=0x0a) && (c!=0x0d) && (c!=0x0) && (i<255) && ( feof(infile) == 0 )) str[i++]=c; // while (((c=fgetc(infile))!=0x20) && (c!=0x09) && (c!=0x0a) && (c!=0x0d) && (c!=0x0) && (i<255) && ( feof(infile) == 0 )) str[i++]=c;
while (((c=iFile[iPos++])!=0x20) && (c!=0x09) && (c!=0x0a) && (c!=0x0d) && (c!=0x0) && (i<255) && ( iPos<iFileLen )) str[i++]=c; while (((c = iFile[iPos++]) != 0x20) && (c != 0x09) && (c != 0x0a) && (c != 0x0d) && (c != 0x0) && (i < 255) && ( iPos < iFileLen )) str[i++] = c;
str[i]=0; str[i] = 0;
D4(fprintf (debug_file, "parse_special, str=!%s\n",str)); D4(fprintf(debug_file, "parse_special, str=!%s\n", str));
if (strcmp(str,"mdata")==0) {putBigEndian(headerSize, 4);return 0;} // will put zeroes on pass 1 if (strcmp(str, "mdata") == 0) {
if (strcmp(str,"height")==0) {putBigEndian(height,2);return 0;} putBigEndian(headerSize, 4); return 0;
if (strcmp(str,"width")==0) {putBigEndian(width,2);return 0;} } // will put zeroes on pass 1
if (strcmp(str,"width")==0) {putBigEndian(width,2);return 0;} if (strcmp(str, "height") == 0) {
if (strcmp(str,"nframes")==0) {putBigEndian(nframes,4);return 0;} putBigEndian(height, 2); return 0;
if (strcmp(str,"timescale")==0) {putBigEndian(timescale,4);return 0;} }
if (strcmp(str,"duration")==0) {putBigEndian(nframes*sample_dur,4);return 0;} if (strcmp(str, "width") == 0) {
if (strcmp(str,"frame_duration")==0) {putBigEndian(sample_dur,4);return 0;} putBigEndian(width, 2); return 0;
if (strcmp(str,"samples_chunk")==0) {putBigEndian(samplesPerChunk, 4);return 0;} // will put zeroes on pass 1 }
if (strcmp(str,"sample_sizes")==0) { if (strcmp(str, "width") == 0) {
if (sizes!=NULL) for (i=0;i<nframes;i++) putBigEndian(sizes[i],4); putBigEndian(width, 2); return 0;
else for (i=0;i<nframes;i++) putBigEndian(framesize,4); }
if (strcmp(str, "nframes") == 0) {
putBigEndian(nframes, 4); return 0;
}
if (strcmp(str, "timescale") == 0) {
putBigEndian(timescale, 4); return 0;
}
if (strcmp(str, "duration") == 0) {
putBigEndian(nframes * sample_dur, 4); return 0;
}
if (strcmp(str, "frame_duration") == 0) {
putBigEndian(sample_dur, 4); return 0;
}
if (strcmp(str, "samples_chunk") == 0) {
putBigEndian(samplesPerChunk, 4); return 0;
} // will put zeroes on pass 1
if (strcmp(str, "sample_sizes") == 0) {
if (sizes != NULL) for (i = 0; i < nframes; i++) putBigEndian(sizes[i], 4);
else for (i = 0; i < nframes; i++) putBigEndian(framesize, 4);
return 0; return 0;
} }
if (strcmp(str,"chunk_offsets")==0) { if (strcmp(str, "chunk_offsets") == 0) {
n= (nframes-1)/samplesPerChunk +1; n = (nframes - 1) / samplesPerChunk + 1;
putBigEndian(n,4); putBigEndian(n, 4);
if (sizes!=NULL) { if (sizes != NULL) {
l=0;j=0; l = 0; j = 0;
for (i=0; i<nframes;i++) { for (i = 0; i < nframes; i++) {
if (j==0) putBigEndian(headerSize+l,4); if (j == 0) putBigEndian(headerSize + l, 4);
j++; if (j>=samplesPerChunk) j=0; j++; if (j >= samplesPerChunk) j = 0;
l+=sizes[i]; l += sizes[i];
} }
} else for (i=0;i<n;i++) putBigEndian(headerSize+framesize*samplesPerChunk*i,4); } else for (i = 0; i < n; i++) putBigEndian(headerSize + framesize * samplesPerChunk * i, 4);
return 0; return 0;
} }
//! a hack - invlude length'skip if data position (header size is known and there is a gap) //! a hack - invlude length'skip if data position (header size is known and there is a gap)
if (strcmp(str,"data_size")==0) { if (strcmp(str, "data_size") == 0) {
gap=headerSize-lseek(ofd,0,SEEK_CUR)-8; gap = headerSize - lseek(ofd, 0, SEEK_CUR) - 8;
if (gap>0) { //!it should be exactly 0 if there is no gap or >8 if there is if (gap > 0) { //!it should be exactly 0 if there is no gap or >8 if there is
D4(fprintf (debug_file, "Inserting a skip tag to compensate for a gap (%d bytes) between the header and the frame data\n",gap)); D4(fprintf(debug_file, "Inserting a skip tag to compensate for a gap (%d bytes) between the header and the frame data\n", gap));
if (gap<8) { if (gap < 8) {
D0(fprintf (debug_file, "not enough room to insret 'skip' tag - %d (need 8)\n",gap)); D0(fprintf(debug_file, "not enough room to insret 'skip' tag - %d (need 8)\n", gap));
return -1; return -1;
} }
D4(fprintf (debug_file, "writing hex %x, %x bytes\n",gap,4)); D4(fprintf(debug_file, "writing hex %x, %x bytes\n", gap, 4));
putBigEndian(gap, 4); putBigEndian(gap, 4);
D4(fprintf (debug_file, "writing string <%s>\n","skip")); D4(fprintf(debug_file, "writing string <%s>\n", "skip"));
write (ofd, "skip", 4); write(ofd, "skip", 4);
lseek(ofd,gap-8,SEEK_CUR); //! lseek over the gap and proceed as before lseek(ofd, gap - 8, SEEK_CUR); //! lseek over the gap and proceed as before
} }
if (sizes!=NULL) { if (sizes != NULL) {
l=0; l = 0;
for (i=0; i<nframes;i++) l+=sizes[i]; for (i = 0; i < nframes; i++) l += sizes[i];
D4(fprintf (debug_file, "writing hex %x, %x bytes\n",l,4)); D4(fprintf(debug_file, "writing hex %x, %x bytes\n", l, 4));
putBigEndian(l,4); putBigEndian(l, 4);
} else putBigEndian(nframes * framesize,4); } else putBigEndian(nframes * framesize, 4);
return 0; return 0;
} }
if (strcmp(str,"time")==0) { if (strcmp(str, "time") == 0) {
time (&ltime); time(&ltime);
ltime+=2082801600; // 1970->1904// 31,557,600 seconds/year ltime += 2082801600; // 1970->1904// 31,557,600 seconds/year
putBigEndian(ltime,4);return 0; putBigEndian(ltime, 4); return 0;
} }
return -1; return -1;
} }
int parse (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;
unsigned long d,l; unsigned long d, l;
char * cp; char * cp;
D4(fprintf (debug_file,"parse(%x)\n",top));
D4(fprintf(debug_file, "parse(%x)\n", top));
// c=fgetc(infile); // c=fgetc(infile);
c=iFile[iPos++]; c = iFile[iPos++];
D5(fprintf (debug_file,"%c",c)); D5(fprintf(debug_file, "%c", c));
// out_start=ftell (outfile); // out_start=ftell (outfile);
// out_start=oPos; // out_start=oPos;
// out_start=oPos=lseek(ofd,0,SEEK_CUR); // out_start=oPos=lseek(ofd,0,SEEK_CUR);
out_start=lseek(ofd,0,SEEK_CUR); out_start = lseek(ofd, 0, SEEK_CUR);
if (!top) putBigEndian(0, 4); if (!top) putBigEndian(0, 4);
// while (( feof(infile) == 0 ) && (c!='}')) { // while (( feof(infile) == 0 ) && (c!='}')) {
while (( iPos<iFileLen ) && (c!='}')) { while (( iPos < iFileLen ) && (c != '}')) {
// skip white spaces strchr // skip white spaces strchr
if ((c!=' ') && (c!=0x9) && (c!=0xa) && (c!=0xd)) { if ((c != ' ') && (c != 0x9) && (c != 0xa) && (c != 0xd)) {
if (c=='!') { if (c == '!') {
if (parse_special()<0) return -1; if (parse_special() < 0) return -1;
} }
// children atoms // children atoms
else if (c=='{') { else if (c == '{') {
if (parse(0)<0) return -1; if (parse(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);
else if (c=='\'') { else if (c == '\'') {
// fgets ( comStr, sizeof(comStr), infile); // fgets ( comStr, sizeof(comStr), infile);
sfgets( comStr, sizeof(comStr), iFile, &iPos); sfgets( comStr, sizeof(comStr), iFile, &iPos);
if ((cp=strchr(comStr,0x0a))!=NULL) cp[0]=0; if ((cp = strchr(comStr, 0x0a)) != NULL) cp[0] = 0;
if ((cp=strchr(comStr,0x0d))!=NULL) cp[0]=0; if ((cp = strchr(comStr, 0x0d)) != NULL) cp[0] = 0;
if ((cp=strchr(comStr,'#'))!=NULL) cp[0]=0; if ((cp = strchr(comStr, '#')) != NULL) cp[0] = 0;
cp=comStr+strlen(comStr)-1; cp = comStr + strlen(comStr) - 1;
while ((cp>comStr) && ((cp[0]==0x20) || (cp[0]==0x09))) cp--; while ((cp > comStr) && ((cp[0] == 0x20) || (cp[0] == 0x09))) cp--;
cp[1]=0; cp[1] = 0;
// fwrite (comStr,1, strlen(comStr),outfile); // fwrite (comStr,1, strlen(comStr),outfile);
// memcpy(&oFile[oPos],comStr,strlen(comStr)); // memcpy(&oFile[oPos],comStr,strlen(comStr));
write (ofd, comStr, strlen(comStr)); write(ofd, comStr, strlen(comStr));
D4(fprintf (debug_file, "writing string <%s>\n",comStr)); D4(fprintf(debug_file, "writing string <%s>\n", comStr));
} else if (strchr(hexStr,c)) { } else if (strchr(hexStr, c)) {
d=0; d = 0;
l=1; l = 1;
do { do {
d=(d<<4)+(strchr(hexStr,c)-hexStr); d = (d << 4) + (strchr(hexStr, c) - hexStr);
l++; l++;
} while (( iPos<iFileLen ) && (l<=8) && (strchr(hexStr,(c=iFile[iPos++]))) ); } while (( iPos < iFileLen ) && (l <= 8) && (strchr(hexStr, (c = iFile[iPos++]))) );
l=(l)>>1; l = (l) >> 1;
putBigEndian(d, l); putBigEndian(d, l);
D4(fprintf (debug_file, "writing hex %lx, %lx bytes\n",d,l)); D4(fprintf(debug_file, "writing hex %lx, %lx bytes\n", d, l));
} else if ((c=='}')){ } else if ((c == '}')) {
break; break;
} else { } else {
...@@ -400,7 +434,7 @@ int parse (int top) { // if top - will not include length ...@@ -400,7 +434,7 @@ int parse (int top) { // if top - will not include length
} }
// c=fgetc(infile); // c=fgetc(infile);
c=iFile[iPos++]; c = iFile[iPos++];
} }
...@@ -408,20 +442,20 @@ int parse (int top) { // if top - will not include length ...@@ -408,20 +442,20 @@ int parse (int top) { // if top - will not include length
if (!top) { if (!top) {
// out_end=ftell (outfile); // out_end=ftell (outfile);
// out_end=oPos; // out_end=oPos;
out_end=lseek(ofd,0,SEEK_CUR); out_end = lseek(ofd, 0, SEEK_CUR);
// fseek (outfile,out_start,SEEK_SET); // fseek (outfile,out_start,SEEK_SET);
// oPos=out_start; // oPos=out_start;
lseek (ofd,out_start,SEEK_SET); lseek(ofd, out_start, SEEK_SET);
putBigEndian((out_end-out_start), 4); putBigEndian((out_end - out_start), 4);
// fseek (outfile,out_end,SEEK_SET); // fseek (outfile,out_end,SEEK_SET);
// oPos=out_end; // oPos=out_end;
lseek (state->ivf,out_end,SEEK_SET); lseek(state->ivf, out_end, SEEK_SET);
} }
return 0; return 0;
} }
int quicktime_template_parser (const char * i_iFile, //! now - string containing header template int quicktime_template_parser(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,
...@@ -432,23 +466,24 @@ int quicktime_template_parser (const char * i_iFile, //! now - string containing ...@@ -432,23 +466,24 @@ int quicktime_template_parser (const char * i_iFile, //! now - string containing
int i_timescale, int i_timescale,
int * i_sizes, int * i_sizes,
int data_start // zero if dfata is not written yet (will be no gap) int data_start // zero if dfata is not written yet (will be no gap)
) { )
iFile= i_iFile; {
width= i_width; iFile = i_iFile;
height= i_height; width = i_width;
nframes= i_nframes; height = i_height;
sample_dur= i_sample_dur; nframes = i_nframes;
samplesPerChunk= i_samplesPerChunk; sample_dur = i_sample_dur;
framesize= i_framesize; samplesPerChunk = i_samplesPerChunk;
timescale= i_timescale; framesize = i_framesize;
sizes= i_sizes; timescale = i_timescale;
iPos=0; //!position in the string "iFile" sizes = i_sizes;
ofd= i_ofd; iPos = 0; //!position in the string "iFile"
iFileLen= strlen(iFile); ofd = i_ofd;
lseek (ofd,0,SEEK_SET); iFileLen = strlen(iFile);
if (data_start) headerSize=data_start; lseek(ofd, 0, SEEK_SET);
if (data_start) headerSize = data_start;
// int iFileLen=strlen(inFIle); // int iFileLen=strlen(inFIle);
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(1); // pass 1
...@@ -456,12 +491,12 @@ int quicktime_template_parser (const char * i_iFile, //! now - string containing ...@@ -456,12 +491,12 @@ int quicktime_template_parser (const char * i_iFile, //! now - string containing
// 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); //
// headerSize=oPos; // headerSize=oPos;
if (!headerSize) headerSize=lseek(ofd,0,SEEK_CUR); if (!headerSize) headerSize = lseek(ofd, 0, SEEK_CUR);
iPos=0; iPos = 0;
// oPos=0; // oPos=0;
lseek (ofd,0,SEEK_SET); lseek(ofd, 0, SEEK_SET);
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(1); // pass 2
......
/*!*************************************************************************** /*!***************************************************************************
*! FILE NAME : camogm_ogm.c *! FILE NAME : camogm_ogm.c
*! DESCRIPTION: Provides writing to ogm files for camogm *! DESCRIPTION: Provides writing to ogm files for camogm
*! Copyright (C) 2007 Elphel, Inc. *! Copyright (C) 2007 Elphel, Inc.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify *! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by *! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or *! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version. *! (at your option) any later version.
*! *!
*! This program is distributed in the hope that it will be useful, *! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of *! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details. *! GNU General Public License for more details.
*! *!
*! You should have received a copy of the GNU General Public License *! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>. *! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! *!
*! $Log: camogm_ogm.c,v $ *! $Log: camogm_ogm.c,v $
*! Revision 1.2 2009/02/25 17:50:02 spectr_rain *! Revision 1.2 2009/02/25 17:50:02 spectr_rain
*! removed deprecated dependency *! removed deprecated dependency
*! *!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel *! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*! *!
*! *!
*! Revision 1.2 2007/11/19 03:23:21 elphel *! Revision 1.2 2007/11/19 03:23:21 elphel
*! 7.1.5.5 Added support for *.mov files in camogm. *! 7.1.5.5 Added support for *.mov files in camogm.
*! *!
*! Revision 1.1 2007/11/16 08:49:58 elphel *! Revision 1.1 2007/11/16 08:49:58 elphel
*! Initial release of camogm - program to record video/image to the camera hard drive (or other storage) *! Initial release of camogm - program to record video/image to the camera hard drive (or other storage)
*! *!
*/ */
//!Not all are needed, just copied from the camogm.c //!Not all are needed, just copied from the camogm.c
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
...@@ -61,58 +61,62 @@ ...@@ -61,58 +61,62 @@
#include "camogm_ogm.h" #include "camogm_ogm.h"
#include "camogm.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)
{
return 0; return 0;
} }
void camogm_free_ogm(void) { void camogm_free_ogm(void)
{
} }
int camogm_start_ogm(void) { int camogm_start_ogm(void)
char vendor[]= "ElphelOgm v 0.1"; {
char vendor[] = "ElphelOgm v 0.1";
int pos; int pos;
stream_header sh; stream_header sh;
char hdbuf[sizeof(sh)+1]; char hdbuf[sizeof(sh) + 1];
ogg_packet ogg_header; ogg_packet ogg_header;
sprintf(state->path,"%s%010ld_%06ld.ogm",state->path_prefix,state->frame_params.timestamp_sec,state->frame_params.timestamp_usec);
if (!((state->vf=fopen(state->path,"w+"))) ){ sprintf(state->path, "%s%010ld_%06ld.ogm", state->path_prefix, state->frame_params.timestamp_sec, state->frame_params.timestamp_usec);
D0(fprintf (debug_file, "Error opening %s for writing\n", state->path)); if (!((state->vf = fopen(state->path, "w+"))) ) {
D0(fprintf(debug_file, "Error opening %s for writing\n", state->path));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
ogg_stream_init(&(state->os), state->serialno); ogg_stream_init(&(state->os), state->serialno);
state->packetno = 0; state->packetno = 0;
memset(&sh, 0, sizeof(stream_header)); memset(&sh, 0, sizeof(stream_header));
memcpy(sh.streamtype,"video",5); memcpy(sh.streamtype, "video", 5);
memcpy(sh.subtype, "MJPG", 4); memcpy(sh.subtype, "MJPG", 4);
put_uint32(&sh.size, sizeof(sh)); put_uint32(&sh.size, sizeof(sh));
// put_uint64(&sh.time_unit, (ogg_int64_t) 10*state->frame_period); // put_uint64(&sh.time_unit, (ogg_int64_t) 10*state->frame_period);
put_uint64(&sh.time_unit, state->time_unit); put_uint64(&sh.time_unit, state->time_unit);
// put_uint64(&sh.samples_per_unit, 1); // put_uint64(&sh.samples_per_unit, 1);
put_uint64(&sh.samples_per_unit, (ogg_int64_t) state->timescale); put_uint64(&sh.samples_per_unit, (ogg_int64_t)state->timescale);
put_uint32(&sh.default_len, 1); put_uint32(&sh.default_len, 1);
put_uint32(&sh.buffersize, state->width*state->height); put_uint32(&sh.buffersize, state->width * state->height);
// put_uint16(&sh.bits_per_sample, 24); //? // put_uint16(&sh.bits_per_sample, 24); //?
put_uint16(&sh.bits_per_sample, 0); //? put_uint16(&sh.bits_per_sample, 0); //?
put_uint32(&sh.sh.video.width, state->width); put_uint32(&sh.sh.video.width, state->width);
put_uint32(&sh.sh.video.height, state->height); put_uint32(&sh.sh.video.height, state->height);
memcpy(&hdbuf[1], &sh, sizeof(sh)); memcpy(&hdbuf[1], &sh, sizeof(sh));
hdbuf[0]=1; hdbuf[0] = 1;
//! put it into Ogg stream //! put it into Ogg stream
ogg_header.packet = hdbuf; ogg_header.packet = hdbuf;
ogg_header.bytes = sizeof(sh)+1; ogg_header.bytes = sizeof(sh) + 1;
ogg_header.b_o_s = 1; ogg_header.b_o_s = 1;
ogg_header.e_o_s = 0; ogg_header.e_o_s = 0;
ogg_header.packetno = state->packetno++;; ogg_header.packetno = state->packetno++;;
ogg_header.granulepos =0; ogg_header.granulepos = 0;
ogg_stream_packetin(&(state->os), &ogg_header); ogg_stream_packetin(&(state->os), &ogg_header);
// while(ogg_stream_pageout(&(state->os), &(state->og))) { // while(ogg_stream_pageout(&(state->os), &(state->og))) {
while(ogg_stream_flush(&(state->os), &(state->og))) { while (ogg_stream_flush(&(state->os), &(state->og))) {
int i, j; int i, j;
if ((((i = fwrite(state->og.header, 1, state->og.header_len, state->vf))) != state->og.header_len) || if ((((i = fwrite(state->og.header, 1, state->og.header_len, state->vf))) != state->og.header_len) ||
(state->og.body_len && (((i = fwrite(state->og.body, 1, state->og.body_len, state->vf))) != state->og.body_len))) { (state->og.body_len && (((i = fwrite(state->og.body, 1, state->og.body_len, state->vf))) != state->og.body_len))) {
j=errno; j = errno;
D2(fprintf(debug_file,"\n%d %ld %ld\n",i,state->og.header_len,state->og.body_len)); D2(fprintf(debug_file, "\n%d %ld %ld\n", i, state->og.header_len, state->og.body_len));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
} }
...@@ -120,9 +124,9 @@ int camogm_start_ogm(void) { ...@@ -120,9 +124,9 @@ int camogm_start_ogm(void) {
//!create comment //!create comment
//!use fixed minimal one - hdbuf will be enough for that //!use fixed minimal one - hdbuf will be enough for that
memset(hdbuf, 0, sizeof(hdbuf)); memset(hdbuf, 0, sizeof(hdbuf));
hdbuf[0]=PACKET_TYPE_COMMENT; hdbuf[0] = PACKET_TYPE_COMMENT;
memcpy(&hdbuf[1], "vorbis",6); memcpy(&hdbuf[1], "vorbis", 6);
pos=7; pos = 7;
put_uint32(&hdbuf[pos], strlen(vendor)); put_uint32(&hdbuf[pos], strlen(vendor));
pos += 4; pos += 4;
strcpy(&hdbuf[pos], vendor); strcpy(&hdbuf[pos], vendor);
...@@ -148,31 +152,33 @@ int camogm_start_ogm(void) { ...@@ -148,31 +152,33 @@ int camogm_start_ogm(void) {
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
} }
*/ */
//! calculate initial absolute granulepos (from 1970), then increment with each frame. Later try calculating granulepos of each frame //! calculate initial absolute granulepos (from 1970), then increment with each frame. Later try calculating granulepos of each frame
//! from the absolute time (actual timestamp) //! from the absolute time (actual timestamp)
state->granulepos= (ogg_int64_t) ( (((double) state->frame_params.timestamp_usec)+ state->granulepos = (ogg_int64_t)( (((double)state->frame_params.timestamp_usec) +
(((double) 1000000) * ((double)state->frame_params.timestamp_sec))) * (((double)1000000) * ((double)state->frame_params.timestamp_sec))) *
((double) 10) / ((double)10) /
((double) state->time_unit) * ((double)state->time_unit) *
((double) state->timescale)); ((double)state->timescale));
// state->frame_period=(state->this_frame_params.timestamp_usec - state->frame_params.timestamp_usec)+ // state->frame_period=(state->this_frame_params.timestamp_usec - state->frame_params.timestamp_usec)+
// 1000000*(state->this_frame_params.timestamp_sec - state->frame_params.timestamp_sec); // 1000000*(state->this_frame_params.timestamp_sec - state->frame_params.timestamp_sec);
// put_uint64(&sh.time_unit, (ogg_int64_t)((double)10000000.0 / (double)fps)); // put_uint64(&sh.time_unit, (ogg_int64_t)((double)10000000.0 / (double)fps));
//!Temporarily setting granulepos to 0 (suspect they do not process correctly 64 bits) //!Temporarily setting granulepos to 0 (suspect they do not process correctly 64 bits)
state->granulepos=0; state->granulepos = 0;
//! Here - Ogg stream started, both header and comment packets are sent out, next should be just data packets //! Here - Ogg stream started, both header and comment packets are sent out, next should be just data packets
return 0; return 0;
} }
int camogm_frame_ogm(void){ int camogm_frame_ogm(void)
{
int indx; int indx;
elph_ogg_packet elp_packet; elph_ogg_packet elp_packet;
elp_packet.bytes= 0;
for (indx=0; indx<state->chunk_index; indx++) elp_packet.bytes+=state->packetchunks[indx].bytes; elp_packet.bytes = 0;
elp_packet.packet=state->packetchunks; for (indx = 0; indx < state->chunk_index; indx++) elp_packet.bytes += state->packetchunks[indx].bytes;
elp_packet.packet = state->packetchunks;
//D(fprintf (debug_file,"elp_packet.bytes=0x%lx: elp_packet.packet=%p\n",elp_packet.bytes, elp_packet.packet)); //D(fprintf (debug_file,"elp_packet.bytes=0x%lx: elp_packet.packet=%p\n",elp_packet.bytes, elp_packet.packet));
/*D(fprintf (debug_file,"0:0x%lx: %p\n" \ /*D(fprintf (debug_file,"0:0x%lx: %p\n" \
"1:0x%lx: %p\n" \ "1:0x%lx: %p\n" \
...@@ -188,25 +194,25 @@ int camogm_frame_ogm(void){ ...@@ -188,25 +194,25 @@ int camogm_frame_ogm(void){
elp_packet.packet[4].bytes, elp_packet.packet[4].chunk, elp_packet.packet[4].bytes, elp_packet.packet[4].chunk,
elp_packet.packet[5].bytes, elp_packet.packet[5].chunk, elp_packet.packet[5].bytes, elp_packet.packet[5].chunk,
elp_packet.packet[6].bytes, elp_packet.packet[6].chunk)); elp_packet.packet[6].bytes, elp_packet.packet[6].chunk));
*/ */
elp_packet.b_o_s = 0; elp_packet.b_o_s = 0;
elp_packet.e_o_s = 0; elp_packet.e_o_s = 0;
elp_packet.packetno = state->packetno++;; elp_packet.packetno = state->packetno++;;
// tts[0]=state->frame_params.timestamp_usec; // tts[0]=state->frame_params.timestamp_usec;
// tts[1]=state->frame_params.timestamp_sec; // tts[1]=state->frame_params.timestamp_sec;
elp_packet.granulepos=state->granulepos; elp_packet.granulepos = state->granulepos;
//!TODO: If that works, calculate granulepos from timestamp for each frame //!TODO: If that works, calculate granulepos from timestamp for each frame
state->granulepos+= (ogg_int64_t) state->timescale; state->granulepos += (ogg_int64_t)state->timescale;
//D3(fprintf (debug_file,"_121_")); //D3(fprintf (debug_file,"_121_"));
ogg_stream_packetin_elph(&(state->os), &elp_packet); ogg_stream_packetin_elph(&(state->os), &elp_packet);
//D3(fprintf (debug_file,"_13_")); //D3(fprintf (debug_file,"_13_"));
while(ogg_stream_pageout(&(state->os), &(state->og))) { while (ogg_stream_pageout(&(state->os), &(state->og))) {
int i,j; int i, j;
if ((((i = fwrite(state->og.header, 1, state->og.header_len, state->vf))) != state->og.header_len) || if ((((i = fwrite(state->og.header, 1, state->og.header_len, state->vf))) != state->og.header_len) ||
(state->og.body_len && (((i = fwrite(state->og.body, 1, state->og.body_len, state->vf))) != state->og.body_len))) { (state->og.body_len && (((i = fwrite(state->og.body, 1, state->og.body_len, state->vf))) != state->og.body_len))) {
j=errno; j = errno;
D0(fprintf(debug_file,"\n%d %ld %ld\n",i,state->og.header_len,state->og.body_len)); D0(fprintf(debug_file, "\n%d %ld %ld\n", i, state->og.header_len, state->og.body_len));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
} }
...@@ -216,7 +222,8 @@ int camogm_frame_ogm(void){ ...@@ -216,7 +222,8 @@ int camogm_frame_ogm(void){
//!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(void)
{
//! put zero-packet it into stream //! put zero-packet it into stream
ogg_packet ogg_header; ogg_packet ogg_header;
...@@ -227,12 +234,12 @@ int camogm_end_ogm(void){ ...@@ -227,12 +234,12 @@ int camogm_end_ogm(void){
ogg_header.packetno = state->packetno++; ogg_header.packetno = state->packetno++;
ogg_header.granulepos = ++(state->granulepos); ogg_header.granulepos = ++(state->granulepos);
ogg_stream_packetin(&(state->os), &ogg_header); //!+++++++++++++++++++++++++++++++++++++++++++++++++++++ ogg_stream_packetin(&(state->os), &ogg_header); //!+++++++++++++++++++++++++++++++++++++++++++++++++++++
while(ogg_stream_flush(&(state->os), &(state->og))) { while (ogg_stream_flush(&(state->os), &(state->og))) {
int i, j; int i, j;
if ((((i = fwrite(state->og.header, 1, state->og.header_len, state->vf))) != state->og.header_len) || if ((((i = fwrite(state->og.header, 1, state->og.header_len, state->vf))) != state->og.header_len) ||
(state->og.body_len && (((i = fwrite(state->og.body, 1, state->og.body_len, state->vf))) != state->og.body_len))) { (state->og.body_len && (((i = fwrite(state->og.body, 1, state->og.body_len, state->vf))) != state->og.body_len))) {
j=errno; j = errno;
D0(fprintf(debug_file,"\n%d %ld %ld\n",i,state->og.header_len,state->og.body_len)); D0(fprintf(debug_file, "\n%d %ld %ld\n", i, state->og.header_len, state->og.body_len));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
} }
......
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