apps/camogm/camogm.c

Go to the documentation of this file.
00001  
00002 /*!***************************************************************************
00003 *! FILE NAME  : camogm.c
00004 *! DESCRIPTION: Program to write captured video (and audio) to camera file system
00005 *! using Ogg container.
00006 *! Original implementation will copy package data to a buffer to use library calls?
00007 *! Copyright (C) 2007 Elphel, Inc.
00008 *! -----------------------------------------------------------------------------**
00009 *!  This program is free software: you can redistribute it and/or modify
00010 *!  it under the terms of the GNU General Public License as published by
00011 *!  the Free Software Foundation, either version 3 of the License, or
00012 *!  (at your option) any later version.
00013 *!
00014 *!  This program is distributed in the hope that it will be useful,
00015 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 *!  GNU General Public License for more details.
00018 *!
00019 *!  You should have received a copy of the GNU General Public License
00020 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00021 *! -----------------------------------------------------------------------------**
00022 *!
00023 *!  $Log: camogm.c,v $
00024 *!  Revision 1.9  2008/04/13 21:05:19  elphel
00025 *!  Fixing KML generation
00026 *!
00027 *!  Revision 1.8  2008/04/11 23:09:33  elphel
00028 *!  modified to handle kml generation
00029 *!
00030 *!  Revision 1.7  2008/04/07 09:13:34  elphel
00031 *!  Changes related to new Exif generation/processing
00032 *!
00033 *!  Revision 1.6  2008/01/14 22:59:00  elphel
00034 *!  7.1.7.4 - added timelapse mode to camogm
00035 *!
00036 *!  Revision 1.5  2007/12/03 08:28:45  elphel
00037 *!  Multiple changes, mostly cleanup
00038 *!
00039 *!  Revision 1.4  2007/11/29 00:38:57  elphel
00040 *!  fixed timescale bug
00041 *!
00042 *!  Revision 1.3  2007/11/19 05:07:19  elphel
00043 *!  fixed 2 typos
00044 *!
00045 *!  Revision 1.2  2007/11/19 03:23:21  elphel
00046 *!  7.1.5.5 Added support for *.mov files in camogm.
00047 *!
00048 *!  Revision 1.1  2007/11/16 08:49:56  elphel
00049 *!  Initial release of camogm - program to record video/image to the camera hard drive (or other storage)
00050 *!
00051 */ 
00052 #include <unistd.h>
00053 #include <stdio.h>
00054 #include <stdlib.h>
00055 #include <signal.h>
00056 #include <fcntl.h>
00057 #include <sys/uio.h>
00058 #include <errno.h>
00059 #include <sys/types.h>
00060 #include <sys/socket.h>
00061 #include <sys/stat.h>
00062 //#include <ctype.h>
00063 //#include <getopt.h>
00064 #include <time.h>
00065 #include <string.h>
00066 
00067 #include <netinet/in.h> /*little <-> big endian ?*/
00068 #include <sys/mman.h>           /* mmap */
00069 #include <sys/ioctl.h>
00070 
00071 #include <asm/elphel/c313a.h>
00072 //#include <asm/elphel/exifa.h>
00073 #include <asm/elphel/ext353.h>
00074 #include <asm/byteorder.h>
00075 
00076 
00077 #include <ogg/ogg.h> // has to be before ogmstreams.h
00078 #include "ogmstreams.h" // move it to <>?
00079 
00080 //#include "camogm_exif.h"
00081 #include "camogm_ogm.h"
00082 #include "camogm_jpeg.h"
00083 #include "camogm_mov.h"
00084 #include "camogm_kml.h"
00085 #include "camogm.h"
00086 
00087 #define TRAILER_SIZE   0x02
00088 #define MAP_OPTIONS MAP_FILE|MAP_PRIVATE
00089 
00090 char trailer[TRAILER_SIZE] = {0xff,0xd9};
00091 
00092 const char ExifFileName[]="/dev/exif_exif";
00093 
00094 const char HeadFileName[]="/dev/jpeghead";
00095 const char SensParsFileName[]="/dev/sensorpars";
00096 unsigned long * ccam_dma_buf;           /* mmapped array */
00097 unsigned long * imageParamsR;
00098 int buff_size;
00099 
00100 #define DEFAULT_DURATION 60 
00101 #define DEFAULT_LENGTH 100000000 
00102 
00103 #define DEFAULT_FRAMES           16384 /* Maximal number of frames in file segment (each need 4* (1 + 1/frames_per_chunk) bytes for the frame index */
00104 #define DEFAULT_FRAMES_PER_CHUNK    10 /*second sparse index - for Quicktime fast forward */
00105 
00106 #define DEFAULT_LENGTH 100000000 
00107 #define DEFAULT_EXIF 1 /* use Exif */
00108 
00109 static char cmdbuf[1024];
00110 static int  cmdbufp=0; // current input pointer in the command buffer (read from pipe)
00111 static int  cmdstrt=0; // start of the next partial command
00112 
00113 camogm_state sstate;
00114 camogm_state * state;
00115 
00116 int   debug_level;
00117 FILE* debug_file;
00118 
00119 
00120 int camogm_init(void);
00121 int camogm_start(void);
00122 
00123 
00124 
00125 
00126 
00127 
00128 int camogm_stop(void);
00129 int camogm_reset(void); 
00130 int camogm_debug(const char * fname);
00131 int camogm_debug_level(int d);
00132 void  camogm_set_segment_duration(int sd);
00133 void  camogm_set_segment_length(int sl);
00134 void  camogm_set_save_gp(int d);
00135 void  camogm_set_prefix (const char * p);
00136 void  camogm_set_exif(int d);
00137 void  camogm_set_timescale(double d); 
00138 void  camogm_set_frames_skip(int d); 
00139 void  camogm_set_format(int d);
00140 
00141 void  camogm_kml_set_enable(int d);
00142 void  camogm_kml_set_horHalfFov (double dd);
00143 void  camogm_kml_set_vertHalfFov(double dd);
00144 void  camogm_kml_set_height_mode(int d);
00145 void  camogm_kml_set_height(double dd);
00146 void  camogm_kml_set_period(int d);
00147 void  camogm_kml_set_near(double dd); // distance to PhotoOverlay
00148 
00149 
00150 int   parse_cmd(FILE* npipe);
00151 char * getLineFromPipe(FILE* npipe);
00152 
00153 int  sendImageFrame (void);
00154 
00155 void  camogm_set_max_frames(int d);
00156 void  camogm_set_frames_per_chunk(int d);
00157 
00158 
00160 void put_uint16(void *buf, u_int16_t val)
00161 {
00162         unsigned char  *tmp;
00163 
00164         tmp = (unsigned char *) buf;
00165 
00166         tmp[0] = val & 0xff;
00167         tmp[1] = (val >>= 8) & 0xff;
00168 }
00169 
00170 void put_uint32(void *buf, u_int32_t val)
00171 {
00172         unsigned char  *tmp;
00173 
00174         tmp = (unsigned char *) buf;
00175 
00176         tmp[0] = val & 0xff;
00177         tmp[1] = (val >>= 8) & 0xff;
00178         tmp[2] = (val >>= 8) & 0xff;
00179         tmp[3] = (val >>= 8) & 0xff;
00180 }
00181 
00182 void put_uint64(void *buf, u_int64_t val)
00183 {
00184         unsigned char  *tmp;
00185 
00186         tmp = (unsigned char *) buf;
00187 
00188         tmp[0] = val & 0xff;
00189         tmp[1] = (val >>= 8) & 0xff;
00190         tmp[2] = (val >>= 8) & 0xff;
00191         tmp[3] = (val >>= 8) & 0xff;
00192         tmp[4] = (val >>= 8) & 0xff;
00193         tmp[5] = (val >>= 8) & 0xff;
00194         tmp[6] = (val >>= 8) & 0xff;
00195         tmp[7] = (val >>= 8) & 0xff;
00196 }
00197 
00198 int camogm_init(void) {
00199    const char sserial[]="elp0";
00200    int * ipser= (int*) sserial;
00201    state->running=0; // mo
00202    state->starting=0; // mo
00203    state->vf=NULL;
00204    camogm_set_segment_duration(DEFAULT_DURATION);
00205    camogm_set_segment_length(DEFAULT_LENGTH);
00206    camogm_set_max_frames(DEFAULT_FRAMES);
00207    camogm_set_frames_per_chunk(DEFAULT_FRAMES_PER_CHUNK);
00208    camogm_set_prefix ("\0");
00209    camogm_set_save_gp(0);
00210    camogm_reset(); 
00211    state->serialno= ipser[0];
00212    state->last= 0;
00213    debug_file= stderr;
00214    camogm_debug_level(1);
00215    strcpy(state->debug_name,"stderr");
00216    camogm_set_timescale(1.0);
00217    camogm_set_frames_skip(0); 
00218    camogm_set_format(CAMOGM_FORMAT_OGM);
00219    state->exifSize=0;
00220    state->exif= DEFAULT_EXIF;
00221    state->frame_lengths=NULL;
00222    state->frameno=0;
00223    state->formats=0;
00224 
00226    camogm_kml_set_enable(0);
00227    state->kml_file=NULL;
00228    camogm_kml_set_horHalfFov (20.0);
00229    camogm_kml_set_vertHalfFov(15.0);
00230    camogm_kml_set_height_mode(0);
00231    camogm_kml_set_height(10.0);
00232    camogm_kml_set_period(2); // 2 sec
00233    camogm_kml_set_near(40.0); // 40 m (distance to PhotoOverlay)
00234    state->kml_path[0]='\0';
00235 
00236 
00237 /*
00238 void  camogm_kml_set_enable(int d);
00239 void  camogm_kml_set_horHalfFov (double dd);
00240 void  camogm_kml_set_vertHalfFov(double dd);
00241 void  camogm_kml_set_height_mode(int d);
00242 void  camogm_kml_set_height(double dd);
00243 void  camogm_kml_set_decimate(int d);
00244 
00245   int                   kml_enable;       //! enable KML file generation
00246   FILE*                 kml_file;         //! stream to write kml file
00247   double                kml_horHalfFov;   //! half horizontal Fov (degrees)
00248   double                kml_vertHalfFov;  //! half vertical Fov (degrees)
00249   int                   kml_height_mode;  //! 1 - actual, 0 - ground
00250   double                kml_height;       //! extra height to add
00251   int                   kml_decimate;     //! generate PhotoOverlay for each kml_decimate frame;
00252   int                   kml_decimate_counter; //! counter to skip kml frames
00253   double                kml_near;         //! Use in KML "near" parameter (<=0 - don't use it)
00254 
00255 */
00256 
00257 
00258 
00259    return 0;
00260 }
00261 
00262 
00263 int camogm_debug(const char * fname) {
00264   int none=1;
00265   if (fname && strlen(fname) && strcmp(fname, "none") && strcmp(fname, "null")  && strcmp(fname, "/dev/null")) none=0;
00266   if (debug_file){
00267     if (strcmp(state->debug_name, "stdout") && strcmp(state->debug_name, "stderr")) fclose (debug_file);
00268     debug_file=NULL;
00269     state->debug_name[0]='\0';
00270   }
00271   if (!none) {
00272     if      (strcmp(fname, "stdout") ==0) debug_file=stdout;
00273     else if (strcmp(fname, "stderr") ==0) debug_file=stderr;
00274     else                                  debug_file=fopen(fname,"w+");
00275   }
00276   if (debug_file) {
00277       strncpy(state->debug_name,fname,sizeof(state->debug_name)-1);
00278       state->debug_name[sizeof(state->debug_name)-1]='\0';
00279   }
00280   return 0;
00281 }
00282 
00283 int camogm_debug_level(int d) {
00284   debug_level=d;
00285   return 0;
00286 }
00287 
00288 
00289 
00290 
00291 int camogm_start(void) {
00292   int timestamp_start;
00293   int rslt;
00294   int next_metadata_start, next_jpeg_len, fp;
00295   D1(fprintf (debug_file,"Starting recording\n"));
00296   state->frameno=0;
00297   state->timescale=        state->set_timescale;
00298 
00299   int * ifp =      (int *) &(state->frame_params) ;
00300   int * ifp_this = (int *) &(state->this_frame_params) ;
00301   if (state->kml_enable) camogm_init_kml() ; // do nothing
00302 
00303   if (state->format != state->set_format) {
00304      state->format=  state->set_format;
00305      switch (state->format) {
00306       case CAMOGM_FORMAT_NONE: rslt= 0; break;
00307       case CAMOGM_FORMAT_OGM:  rslt= camogm_init_ogm(); break;
00308       case CAMOGM_FORMAT_JPEG: rslt= camogm_init_jpeg();break;
00309       case CAMOGM_FORMAT_MOV:  rslt= camogm_init_mov(); break;
00310      }
00311      state->formats |= 1 << (state->format);
00313   }
00314   state->max_frames=       state->set_max_frames;
00315   state->frames_per_chunk= state->frames_per_chunk;
00316   state->starting=1; 
00317 
00318 D3(fprintf (debug_file,"1: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00319   if ((state->cirbuf_rp <0) || (lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET) < 0) || (lseek(state->fd_circ,CIRCLSEEK_VALID,SEEK_END) < 0 )) {
00320 D3(fprintf (debug_file,"2: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00321     state->cirbuf_rp=lseek(state->fd_circ,CIRCLSEEK_LAST,SEEK_END);
00322     if (((fp=lseek(state->fd_circ,CIRCLSEEK_PREV,SEEK_END)))>=0) state->cirbuf_rp=fp; 
00323     state->buf_overruns++;
00325 //    state->buf_min=lseek(state->fd_circ,CIRCLSEEK_FREE,SEEK_END);
00326 //    lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET); //! restore after moving (side effect)
00327     state->buf_min=imageParamsR[P_FREECIRCBUF];
00328 
00329   } else {
00330 //      b_free=lseek(state->fd_circ,CIRCLSEEK_FREE,SEEK_END);
00331 //      lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET); //! restore after moving (side effect)
00332 //      if (state->buf_min > b_free) state->buf_min=b_free;
00333       if (state->buf_min > imageParamsR[P_FREECIRCBUF]) state->buf_min=imageParamsR[P_FREECIRCBUF];
00334 
00335   }
00336 D3(fprintf (debug_file,"3: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00337 D3(fprintf (debug_file,"4:lseek(state->fd_circ,CIRCLSEEK_READY,SEEK_END)=%d\n",(int) lseek(state->fd_circ,CIRCLSEEK_READY,SEEK_END)));
00338 
00340   if (lseek(state->fd_circ,CIRCLSEEK_READY,SEEK_END) <0) return -CAMOGM_FRAME_NOT_READY; 
00341 D3(fprintf (debug_file,"5: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00342   state->metadata_start=(state->cirbuf_rp)-32;
00343   if (state->metadata_start<0) state->metadata_start+=state->circ_buff_size;
00344 
00346 
00347   memcpy (&(state->frame_params), (unsigned long * ) &ccam_dma_buf[state->metadata_start>>2],32);
00348   state->jpeg_len=state->frame_params.frame_length; 
00349 
00350 
00351   if (state->frame_params.signffff !=0xffff) {
00352     D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n",__FILE__,__LINE__,(int) state->frame_params.signffff));
00353      state->cirbuf_rp=-1;
00354      D1(fprintf(debug_file, "state->cirbuf_rp=0x%x\r\n",(int) state->cirbuf_rp));
00355      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]));
00356      return -CAMOGM_FRAME_BROKEN;
00357   }
00360   timestamp_start=(state->cirbuf_rp)+((state->jpeg_len+CCAM_MMAP_META+3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC; 
00361   if (timestamp_start >= state->circ_buff_size) timestamp_start-=state->circ_buff_size;
00362   memcpy (&(state->frame_params.timestamp_sec), (unsigned long * ) &ccam_dma_buf[timestamp_start>>2],8);
00363 
00365   if ((lseek(state->fd_circ,CIRCLSEEK_NEXT,SEEK_END) < 0 ) ||
00367       (((fp=lseek(state->fd_circ,CIRCLSEEK_READY,SEEK_END))) < 0)) {
00368         lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET); 
00369         return -CAMOGM_FRAME_NOT_READY; 
00370   }
00371   next_metadata_start=fp-32;
00372   if (next_metadata_start<0) next_metadata_start+= state->circ_buff_size;
00373   memcpy (&(state->this_frame_params), (unsigned long * ) &ccam_dma_buf[next_metadata_start>>2],32);
00374   next_jpeg_len=state->this_frame_params.frame_length; 
00375   if (state->this_frame_params.signffff !=0xffff) { 
00376      D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n",__FILE__,__LINE__,(int) state->this_frame_params.signffff));
00377      D1(fprintf(debug_file, "fp=0x%x\r\n",(int) fp));
00378      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]));
00379 //  int * ifp =      (int *) &(state->this_frame_params) ;
00380 //  int * ifp_this = (int *) &(state->this_frame_params) ;
00381 
00382      state->cirbuf_rp=-1;
00383      return -CAMOGM_FRAME_BROKEN;
00384   }
00386   timestamp_start=fp+((next_jpeg_len+CCAM_MMAP_META+3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC; 
00387   if (timestamp_start >= state->circ_buff_size) timestamp_start-=state->circ_buff_size;
00388   memcpy (&(state->this_frame_params.timestamp_sec), (unsigned long * ) &ccam_dma_buf[timestamp_start>>2],8);
00390   if ((state->frame_params.width  != state->this_frame_params.width) ||
00391       (state->frame_params.height != state->this_frame_params.height)) {
00393      state->cirbuf_rp=fp;
00394      return -CAMOGM_FRAME_CHANGED; // no yet checking for the FPS
00395   }
00397    state->frame_period=(state->this_frame_params.timestamp_usec - state->frame_params.timestamp_usec)+
00398                1000000*(state->this_frame_params.timestamp_sec  - state->frame_params.timestamp_sec);
00399 
00401   state->frames_skip=      state->set_frames_skip;
00402   if (state->frames_skip > 0) {
00403     state->frames_skip_left=0;
00404     state->frame_period *= (state->frames_skip+1);
00405 //    state->frames_skip_left= state->set_frames_skip;
00406   } else if (state->frames_skip < 0) {
00407     state->frame_period=-(state->frames_skip) ; 
00408     state->frames_skip_left=state->frame_params.timestamp_sec;
00409   }
00410    state->time_unit= (ogg_int64_t) (((double) state-> frame_period) * ((double) 10) / ((double) state-> timescale));
00411    state->width=state->frame_params.width;
00412    state->height=state->frame_params.height;
00413 
00416    lseek(state->fd_head,state->cirbuf_rp+1,SEEK_END); 
00417 
00418    lseek(state->fd_head,0,0);
00419    read (state->fd_head,state->jpegHeader,state->head_size);
00421    lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET);
00423    switch (state->format) {
00424     case CAMOGM_FORMAT_NONE: rslt= 0;  break;
00425     case CAMOGM_FORMAT_OGM:  rslt= camogm_start_ogm();  break;
00426     case CAMOGM_FORMAT_JPEG: rslt= camogm_start_jpeg(); break;
00427     case CAMOGM_FORMAT_MOV:  rslt= camogm_start_mov();  break;
00428     default: rslt=0; // do nothing
00429    }
00430    if (rslt) return rslt;
00431    if (state->kml_enable) rslt=camogm_start_kml() ; // will turn on state->kml_used if it can
00432    if (rslt) return rslt;
00433    state->running=1;
00434    state->starting=0;
00435    D1(fprintf (debug_file,"Started OK\n"));
00436    return 0;
00437 }
00438 
00439 
00440 int  sendImageFrame (void) {
00441    int rslt;
00442 //   struct frame_params_t this_frame_params;
00443 //   elph_packet_chunk packetchunks[7];
00444    unsigned char frame_packet_type = PACKET_IS_SYNCPOINT;
00445 //   int chunk_index=0;
00446 //   int i;
00447 //   unsigned long * tts= (unsigned long *) &(state->granulepos); //to word-swap timestamt to granule
00448    int timestamp_start;
00450 //   int * ifp =      (int *) &(state->frame_params) ;
00451    int * ifp_this = (int *) &(state->this_frame_params) ;
00452 
00454    if (state->frameno >= (state->max_frames)) return -CAMOGM_FRAME_CHANGED;
00456 //   D3(fprintf (debug_file,"sendImageFrame: format=%d, set_format=%d\n", state->format, state->set_format));
00457 
00458    if (state->format != state->set_format) return -CAMOGM_FRAME_CHANGED;
00460    if ((state->vf) && (state->segment_length >=0) && (ftell(state->vf) > state->segment_length)) return -CAMOGM_FRAME_CHANGED;
00462    if (((state->ivf)>=0) && (state->segment_length >=0) && (lseek(state->ivf, 0, SEEK_CUR) > state->segment_length)) return -CAMOGM_FRAME_CHANGED;
00464    if (lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET) <0) return -CAMOGM_FRAME_INVALID; 
00465 
00466    if (lseek(state->fd_circ,CIRCLSEEK_READY,SEEK_END) <0) return -CAMOGM_FRAME_NOT_READY; 
00467 /*
00469   state->frames_skip=      state->set_frames_skip;
00470   if (state->frames_skip > 0) {
00471     state->frames_skip_left=0;
00472     state->frame_period *= (state->frames_skip+1);
00473 //    state->frames_skip_left= state->set_frames_skip;
00474   } else if (state->frames_skip < 0) {
00475     state->frame_period=-(state->frames_skip) ; //! actual frame period will fluctuate to the nearest frame acquired (free running)
00476     state->frames_skip_left=state->frame_params.timestamp_sec;
00477   }
00478 */
00479 
00481    if ( (state->frames_skip > 0) && (state->frames_skip_left > 0 )) { 
00482      state->cirbuf_rp=lseek(state->fd_circ,CIRCLSEEK_NEXT,SEEK_END);
00484      if (state->save_gp) lseek(state->fd_circ,CIRCLSEEK_SETP,SEEK_END);
00485      state->frames_skip_left--;
00486      return -CAMOGM_FRAME_NOT_READY; 
00487    }
00488 
00490 //D3(fprintf (debug_file,"_1_"));
00491    state->metadata_start=state->cirbuf_rp-32;
00492    if (state->metadata_start<0) state->metadata_start+=state->circ_buff_size;
00493    memcpy (&(state->this_frame_params), (unsigned long * ) &ccam_dma_buf[state->metadata_start>>2],32);
00494    state->jpeg_len=state->this_frame_params.frame_length; 
00495    if (state->this_frame_params.signffff !=0xffff) {
00496      D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n",__FILE__,__LINE__,(int) state->this_frame_params.signffff));
00497      D1(fprintf(debug_file, "state->cirbuf_rp=0x%x\r\n",(int) state->cirbuf_rp));
00498      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]));
00499 
00500 
00501      return -CAMOGM_FRAME_BROKEN;
00502    }
00503 //D3(fprintf (debug_file,"_2_"));
00505    timestamp_start=state->cirbuf_rp+((state->jpeg_len+CCAM_MMAP_META+3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC; 
00506    if (timestamp_start >= state->circ_buff_size) timestamp_start-=state->circ_buff_size;
00507 //D3(fprintf (debug_file,"_3_"));
00508    memcpy (&(state->this_frame_params.timestamp_sec), (unsigned long * ) &ccam_dma_buf[timestamp_start>>2],8);
00510    if ((state->frame_params.width  != state->this_frame_params.width) ||
00511        (state->frame_params.height != state->this_frame_params.height)) return -CAMOGM_FRAME_CHANGED; 
00512 
00513    if ((state->segment_duration > 0) && 
00514        ((state->this_frame_params.timestamp_sec-state->frame_params.timestamp_sec) > state->segment_duration))
00515            return -CAMOGM_FRAME_CHANGED;
00516 
00518    if ((state->frames_skip < 0) && (state->frames_skip_left > state->this_frame_params.timestamp_sec) ) {
00519      state->cirbuf_rp=lseek(state->fd_circ,CIRCLSEEK_NEXT,SEEK_END);
00521      if (state->save_gp) lseek(state->fd_circ,CIRCLSEEK_SETP,SEEK_END);
00522      return -CAMOGM_FRAME_NOT_READY; 
00523    }
00524 
00525 
00526 //D3(fprintf (debug_file,"_4_"));
00527    if (state->exif) {
00528 D3(fprintf (debug_file,"_5_"));
00530 //     updateExif(ep, state->ed, &(state->frame_params));
00531      state->exifSize=lseek(state->fd_exif,1,SEEK_END); // at the beginning of page 1 - position == page length
00532 //     if (state->exifSize < 0) state->exifSize=0; // error from lseek;
00533      if (state->exifSize > 0) {
00534 //state->this_frame_params.meta_index
00535        lseek(state->fd_exif,state->this_frame_params.meta_index,SEEK_END); 
00536        rslt=read (state->fd_exif, state->ed, state->exifSize);
00537        if (rslt<0) rslt=0;
00538        state->exifSize=rslt;
00539      } else state->exifSize=0;
00540    } else state->exifSize=0;
00541 
00542 //D3(fprintf (debug_file,"_6_"));
00543 
00545    state->chunk_index=0;
00546    state->packetchunks[state->chunk_index  ].bytes=1;
00547    state->packetchunks[state->chunk_index++].chunk=&frame_packet_type;
00548    if (state->exif>0) {
00549 //D3(fprintf (debug_file,"_7_"));
00550      state->packetchunks[state->chunk_index  ].bytes=2;
00551      state->packetchunks[state->chunk_index++].chunk=state->jpegHeader;
00552      state->packetchunks[state->chunk_index  ].bytes=state->exifSize;
00553      state->packetchunks[state->chunk_index++].chunk= state->ed;
00554      state->packetchunks[state->chunk_index  ].bytes=state->head_size-2;
00555      state->packetchunks[state->chunk_index++].chunk= &(state->jpegHeader[2]);
00556    } else {
00557 //D3(fprintf (debug_file,"_8_"));
00558      state->packetchunks[state->chunk_index  ].bytes=state->head_size;
00559      state->packetchunks[state->chunk_index++].chunk= state->jpegHeader;
00560    }
00561 //D3(fprintf (debug_file,"_9_"));
00562 
00564 //     if ((jpeg_start+jpeg_len) > state->circ_buff_size) { // two segments
00565    if ((state->cirbuf_rp + state->jpeg_len) > state->circ_buff_size) { 
00566 
00567 //D3(fprintf (debug_file,"_10_"));
00568 
00569 //        sendBuffer((void *) &ccam_dma_buf[jpeg_start>>2], state->circ_buff_size-state->cirbuf_rp);
00570      state->packetchunks[state->chunk_index  ].bytes=state->circ_buff_size-state->cirbuf_rp;
00571      state->packetchunks[state->chunk_index++].chunk= (unsigned char*) &ccam_dma_buf[state->cirbuf_rp>>2];
00573 //        sendBuffer((void *) &ccam_dma_buf[0], jpeg_len-(state->circ_buff_size-state->cirbuf_rp));
00574      state->packetchunks[state->chunk_index  ].bytes=state->jpeg_len - (state->circ_buff_size-state->cirbuf_rp);
00575      state->packetchunks[state->chunk_index++].chunk= (unsigned char*) &ccam_dma_buf[0];
00576    } else { // single segment
00577 //D3(fprintf (debug_file,"_11_"));
00578 
00580 //        sendBuffer((void *) &ccam_dma_buf[state->cirbuf_rp>>2], state->jpeg_len);
00581      state->packetchunks[state->chunk_index  ].bytes=state->jpeg_len;
00582      state->packetchunks[state->chunk_index++].chunk= (unsigned char*)  &ccam_dma_buf[state->cirbuf_rp>>2];
00583    }
00584 //D3(fprintf (debug_file,"_12_"));
00585    state->packetchunks[state->chunk_index  ].bytes=2;
00586    state->packetchunks[state->chunk_index++].chunk= (unsigned char*) trailer;
00587 
00588    switch (state->format) {
00589     case CAMOGM_FORMAT_NONE: rslt=0; break;
00590     case CAMOGM_FORMAT_OGM:  rslt=camogm_frame_ogm(); break;
00591     case CAMOGM_FORMAT_JPEG: rslt=camogm_frame_jpeg(); break;
00592     case CAMOGM_FORMAT_MOV:  rslt=camogm_frame_mov(); break;
00593     default: rslt=0; // do nothing
00594    }
00595    if (rslt) return rslt;
00596    if (state->kml_used) rslt=camogm_frame_kml() ; // will turn on state->kml_used if it can
00597    if (rslt) return rslt;
00598 
00599 //D3(fprintf (debug_file,"_14_"));
00601    state->frameno++;
00602    state->cirbuf_rp=lseek(state->fd_circ,CIRCLSEEK_NEXT,SEEK_END);
00604    if (state->save_gp) lseek(state->fd_circ,CIRCLSEEK_SETP,SEEK_END);
00605 //D3(fprintf (debug_file,"_15_\n"));
00606 //D3(fprintf (debug_file,"state->cirbuf_rp=0x%08x granulepos=0x%x 0x%x (%d.%06d)\n", state->cirbuf_rp, (int) ((state->granulepos)>>32), (int) (state->granulepos),
00607 //                                                                (int) state->this_frame_params.timestamp_sec, (int)state->this_frame_params.timestamp_usec));
00608   if (state->frames_skip > 0) {
00609      state->frames_skip_left= state->frames_skip;
00610   } else if (state->frames_skip < 0) {
00611      state->frames_skip_left+= -(state->frames_skip);
00612   }
00613    return 0;
00614 }
00615 
00616 
00617 
00618 int camogm_stop(void) {
00619   int rslt=0;
00620   if (!state->running) {
00621     if (!state->starting) {
00622       D2(fprintf (debug_file,"Recording was not running, nothing to stop\n"));
00623     } else {
00624       state->starting=0;
00625       D1(fprintf (debug_file,"Dropping attempt to start\n"));
00626     }
00627     return 0;
00628   }
00629   D1(fprintf (debug_file,"Ending recording\n"));
00630    if (state->kml_used) camogm_end_kml() ;
00631    switch (state->format) {
00632     case CAMOGM_FORMAT_NONE: rslt= 0; break;
00633     case CAMOGM_FORMAT_OGM:  rslt= camogm_end_ogm(); break;
00634     case CAMOGM_FORMAT_JPEG: rslt= camogm_end_jpeg();break;
00635     case CAMOGM_FORMAT_MOV:  rslt= camogm_end_mov(); break;
00637    }
00639   if (state->vf) fclose (state->vf);
00640   state->vf=NULL;
00641   if (rslt) return rslt;
00642   state->last=1;
00644   state->running=0;
00645   state->starting=0;
00646   return 0;
00647 }
00648 
00649 void camogm_free() {
00650    int f;
00652 //add kml when needed
00653    for (f=0;f<31;f++) {
00654      if (state->formats & ( 1 << (state->format))) {
00655        switch (f) {
00656         case CAMOGM_FORMAT_NONE: break;
00657         case CAMOGM_FORMAT_OGM:  camogm_free_ogm(); break;
00658         case CAMOGM_FORMAT_JPEG: camogm_free_jpeg();break;
00659         case CAMOGM_FORMAT_MOV:  camogm_free_mov(); break;
00660        }
00661      }
00662    }
00663    state->formats=0;
00664 }
00665 
00666 int camogm_reset(void) { 
00667    state->cirbuf_rp=-1;
00668    state->buf_overruns=-1; 
00669    return 0;
00670 }
00671 
00673 void  camogm_kml_set_enable(int d) {
00674    state->kml_enable=d;
00675 }
00676 void  camogm_kml_set_horHalfFov (double dd) {
00677    state->kml_horHalfFov=dd;
00678 }
00679 void  camogm_kml_set_vertHalfFov(double dd) {
00680    state->kml_vertHalfFov=dd;
00681 }
00682 void  camogm_kml_set_height_mode(int d) {
00683    state->kml_height_mode=d;
00684 }
00685 void  camogm_kml_set_height(double dd) {
00686    state->kml_height=dd;
00687 }
00688 void  camogm_kml_set_period(int d) {
00689    state->kml_period=d;
00690    state->kml_last_ts=0;
00691    state->kml_last_uts=0;
00692 }
00693 void  camogm_kml_set_near(double dd) { // distance to PhotoOverlay
00694    state->kml_near=dd;
00695 }
00696 
00697 
00698 void  camogm_set_segment_duration(int sd) {
00699    state->segment_duration=sd;
00700 }
00701 void  camogm_set_segment_length(int sl) {
00702    state->segment_length=   sl;
00703 }
00704 void  camogm_set_save_gp(int d) {
00705    state->save_gp=   d;
00706 }
00707 void  camogm_set_exif(int d) {
00708    state->exif=   d;
00709 }
00710 
00711 void  camogm_set_prefix (const char * p) {
00712   strncpy(state->path_prefix, p, sizeof(state->path_prefix)-1);
00713   state->path_prefix[sizeof(state->path_prefix)-1]='\0';
00714 }
00715 
00716 void  camogm_set_timescale(double d) { 
00717    state->set_timescale=  d;
00718    if ((state->running==0) && (state->starting==0)) {
00719      state->timescale=state->set_timescale;
00720    }
00721 }
00722 
00723 void  camogm_set_frames_skip(int d) { 
00724    state->set_frames_skip=  d;
00725    if ((state->running==0) && (state->starting==0)) {
00726      state->frames_skip=      state->set_frames_skip;
00727 //     state->frames_skip_left= state->set_frames_skip;
00728      state->frames_skip_left= 0;
00729    }
00730 }
00731 
00732 
00733 void  camogm_set_format(int d) {
00734    int rslt=0;
00735    state->set_format=  d;
00736    if ((state->running==0) && (state->starting==0)) {
00737      state->format=  state->set_format;
00738      switch (state->format) {
00739       case CAMOGM_FORMAT_NONE: rslt= 0; break;
00740       case CAMOGM_FORMAT_OGM:  rslt= camogm_init_ogm(); break;
00741       case CAMOGM_FORMAT_JPEG: rslt= camogm_init_jpeg();break;
00742       case CAMOGM_FORMAT_MOV:  rslt= camogm_init_mov(); break;
00743      }
00744      if (rslt) {
00745        D0(fprintf (debug_file,"%s:%d: Error setting format to=%d\n",__FILE__,__LINE__, state->format));
00746      }
00747      state->formats |= 1 << (state->format);
00748    }
00749 }
00751 void  camogm_set_max_frames(int d) {
00752    state->set_max_frames=  d;
00753    if ((state->running==0) && (state->starting==0)) state->max_frames=  d;
00754 }
00755 void  camogm_set_frames_per_chunk(int d) {
00756    state->set_frames_per_chunk=  d;
00757    if ((state->running==0) && (state->starting==0)) state->frames_per_chunk=  d;
00758 }
00759 void  camogm_status(char * fn, int xml) {
00760   int _len=0;
00761   int _dur,_udur;
00762 //TODO:make it XML file
00763   FILE* f;
00764   char *_state, *_output_format, *_using_exif, *_using_global_pointer, *_compressor_state;
00765   int _b_free, _b_used; // , save_p;
00766   int _frames_remain=0;
00767   int _sec_remain=0;
00768   int _frames_skip=0;
00769   int _sec_skip=0;
00770   char *_kml_enable, *_kml_used, *_kml_height_mode;
00771 
00772   _kml_enable=      state->kml_enable?"yes":"no";
00773   _kml_used=        state->kml_used?"yes":"no";
00774   _kml_height_mode= state->kml_height_mode?"GPS altitude":"map ground level";  
00775 
00776 
00777   _b_free=imageParamsR[P_FREECIRCBUF];
00778   _b_used=imageParamsR[P_CIRCBUFSIZE]-imageParamsR[P_FREECIRCBUF];
00779 
00780   if (!fn) f=stdout;
00781   else if (strcmp(fn, "stdout")==0) f=stdout;
00782   else if (strcmp(fn, "stderr")==0) f=stderr;
00783   else {
00784     if (!((f=fopen (fn,"w")))) {
00785        D0(fprintf (debug_file,"Error opening %s\n", fn));
00786       return;
00787     }
00788   }
00789   if      (state->vf)       _len=ftell(state->vf); 
00790   else if ((state->ivf)>=0) _len=lseek(state->ivf, 0, SEEK_CUR); 
00791   _dur= state->this_frame_params.timestamp_sec-state->frame_params.timestamp_sec;
00792   _udur=state->this_frame_params.timestamp_usec-state->frame_params.timestamp_usec;
00793   if (_udur<0) {
00794     _dur-=1;
00795     _udur+=1000000;
00796   } else if (_udur>=1000000) {
00797     _dur+=1;
00798     _udur-=1000000;
00799   }
00800   _state=         state->running? "running":(state->starting?"starting":"stopped");
00801   _output_format= state->format?((state->format==CAMOGM_FORMAT_OGM)?"ogm":
00802                                              ((state->format==CAMOGM_FORMAT_JPEG)?"jpeg":
00803                                              ((state->format==CAMOGM_FORMAT_MOV)?"mov":
00804                                               "other"))):"none";
00805   _using_exif=    state->exif?"yes":"no";
00806   _using_global_pointer=state->save_gp?"yes":"no";
00807   _compressor_state=(imageParamsR[P_CAMSEQSTATE]==CAMSEQ_RUN)?"running":
00808                      ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_SINGLE)?"acquiring":
00809                       ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_STOP)?"stoppping":
00810                        ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_JPEG)?"stopped":
00811                         ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_OFF)?"reset":"other"))));
00812     if ( state->frames_skip >0 ) {
00813       _frames_remain= state->frames_skip_left;
00814       _frames_skip=state->frames_skip;
00815     } else if ( state->frames_skip <0 ) {
00816       _sec_remain= (state->frames_skip_left - state->this_frame_params.timestamp_sec);
00817       _sec_skip=-(state->frames_skip);
00818     }
00819 
00820 
00821   if (xml) {
00822     fprintf (f,"<?xml version=\"1.0\"?>\n" \
00823              "<camogm_state>\n" \
00824              "  <state>\"%s\"</state>\n" \
00825              "  <compressor_state>\"%s\"</compressor_state>\n" \
00826              "  <file_name>\"%s\"</file_name>\n" \
00827              "  <frame_number>%d</frame_number>\n" \
00828              "  <file_duration>%d.%06d</file_duration>\n" \
00829              "  <file_length>%d</file_length>\n" \
00830              "  <frame_period>%d</frame_period>\n" \
00831              "  <frames_skip>%d</frames_skip>\n" \
00832              "  <seconds_skip>%d</seconds_skip>\n" \
00833              "  <frames_skip_left>%d</frames_skip_left>\n" \
00834              "  <seconds_skip_left>%d</seconds_skip_left>\n" \
00835              "  <frame_width>%d</frame_width>\n" \
00836              "  <frame_height>%d</frame_height>\n" \
00837              "  <format>\"%s\"</format>\n" \
00838              "  <exif>\"%s\"</exif>\n" \
00839              "  <prefix>\"%s\"</prefix>\n" \
00840              "  <max_duration>%d</max_duration>\n" \
00841              "  <max_length>%d</max_length>\n" \
00842              "  <max_frames>%d</max_frames>\n" \
00843              "  <timescale>%f</timescale>\n" \
00844              "  <frames_per_chunk>%d</frames_per_chunk>\n" \
00845              "  <buffer_overruns>%d</buffer_overruns>\n" \
00846              "  <buffer_minimal>%d</buffer_minimal>\n" \
00847              "  <buffer_free>%d</buffer_free>\n" \
00848              "  <buffer_used>%d</buffer_used>\n" \
00849              "  <circbuf_rp>%d</circbuf_rp>\n" \
00850              "  <debug_output>\"%s\"</debug_output>\n" \
00851              "  <debug_level>%d</debug_level>\n" \
00852              "  <use_global_rp>\"%s\"</use_global_rp>\n" \
00853              "  <kml_enable>\"%s\"</kml_enable>\n" \
00854              "  <kml_used>\"%s\"</kml_used>\n" \
00855              "  <kml_path>\"%s\"</kml_path>\n" \
00856              "  <kml_horHalfFov>\"%f\"</kml_horHalfFov>\n" \
00857              "  <kml_vertHalfFov>\"%f\"</kml_vertHalfFov>\n" \
00858              "  <kml_near>\"%f\"</kml_near>\n" \
00859              "  <kml_height_mode>\"%s\"</kml_height_mode>\n" \
00860              "  <kml_height>\"%f\"</kml_height>\n" \
00861              "  <kml_period>%d</kml_period>\n" \
00862              "  <kml_last_ts>%d.%06d</kml_last_ts>\n" \
00863              "</camogm_state>\n",
00864              _state,_compressor_state,state->path,state->frameno,_dur,_udur,_len,state->frame_period, \
00865              _frames_skip,_sec_skip,_frames_remain, _sec_remain, \
00866              state->width,state->height,_output_format,_using_exif, \
00867              state->path_prefix, state->segment_duration, state->segment_length, state->max_frames, state->timescale, \
00868              state->frames_per_chunk, state->buf_overruns, state->buf_min, _b_free, _b_used, state->cirbuf_rp, \
00869              state->debug_name, debug_level, _using_global_pointer, \
00870              _kml_enable,_kml_used,state->kml_path,state->kml_horHalfFov,state->kml_vertHalfFov,state->kml_near,\
00871              _kml_height_mode,state->kml_height,state->kml_period,state->kml_last_ts,state->kml_last_uts);
00872   } else {
00873     fprintf (f,"state              %s\n",        _state);
00874     fprintf (f,"compressor state   %s\n",        _compressor_state);
00875     fprintf (f,"file               %s\n",        state->path);
00876     fprintf (f,"frame              %d\n",        state->frameno);
00877     fprintf (f,"file duration      %d.%06d sec\n",_dur,_udur);
00878     fprintf (f,"file length        %d B\n",      _len);
00879     fprintf (f,"frame period       %d (0x%x)\n", state->frame_period,state->frame_period);
00880     if ( _frames_skip >0 ) fprintf (f,"frames to skip   %d (left %d)\n",_frames_skip, _frames_remain);
00881     if ( _sec_skip    <0 ) fprintf (f,"timelapse period  %d sec (remaining %d sec)\n", _sec_skip, _sec_remain);
00882     fprintf (f,"width              %d (0x%x)\n", state->width,state->width);
00883     fprintf (f,"height             %d (0x%x)\n", state->height,state->height);
00884     fprintf (f,"\n");
00885     fprintf (f,"output format      %s\n",        _output_format);
00886     fprintf (f,"using exif         %s\n",        _using_exif);
00887     fprintf (f,"path prefix:       %s\n",        state->path_prefix);
00888     fprintf (f,"max file duration: %d sec\n",    state->segment_duration);
00889     fprintf (f,"max file length:   %d B\n",      state->segment_length);
00890     fprintf (f,"max frames         %d\n",        state->max_frames);
00891     fprintf (f,"timescale          %f\n",        state->timescale);
00892     fprintf (f,"frames per chunk   %d\n",        state->frames_per_chunk);
00893     fprintf (f,"\n");
00894     fprintf (f,"buffer overruns    %d\n",        state->buf_overruns);
00895     fprintf (f,"buffer minimal     %d\n",        state->buf_min);
00896     fprintf (f,"buffer free        %d\n",        _b_free);
00897     fprintf (f,"buffer used        %d\n",        _b_used);
00898     fprintf (f,"circbuf_rp         %d (0x%x)\n", state->cirbuf_rp,state->cirbuf_rp);
00899     fprintf (f,"\n");
00900     fprintf (f,"debug output to    %s\n",        state->debug_name);
00901     fprintf (f,"debug level        %d\n",        debug_level);
00902     fprintf (f,"use global pointer %s\n",        _using_global_pointer);
00903     fprintf (f,"\n\n");
00904     fprintf (f,"kml_enable         %s\n",        _kml_enable);
00905     fprintf (f,"kml_used           %s\n",        _kml_used);
00906     fprintf (f,"kml_path           %s\n",        state->kml_path);
00907     fprintf (f,"kml_horHalfFov     %f degrees\n",state->kml_horHalfFov);
00908     fprintf (f,"kml_vertHalfFov    %f degrees\n",state->kml_vertHalfFov);
00909     fprintf (f,"kml_near           %f m\n",      state->kml_near);
00910     fprintf (f,"kml height mode    %s\n",        _kml_height_mode);
00911     fprintf (f,"kml_height (extra) %f m\n",      state->kml_height);
00912     fprintf (f,"kml_period         %d\n",        state->kml_period);
00913     fprintf (f,"kml_last_ts        %d.%06d\n",   state->kml_last_ts,state->kml_last_uts);
00914     fprintf (f,"\n\n");
00915 
00916   }
00917   if ((f!=stdout) && (f!=stderr)) fclose (f);
00918   if (state->buf_overruns>=0) state->buf_overruns=0; 
00919   state->buf_min=_b_free;
00920 }
00921 
00923 char * getLineFromPipe(FILE* npipe) {
00924       int fl;
00925       char * nlp;
00927       if (cmdstrt > 0) {
00929         memmove(cmdbuf, &cmdbuf[cmdstrt], sizeof(cmdbuf)- cmdstrt);
00930         cmdbufp-=cmdstrt;
00931         cmdstrt=0;
00932       }
00934       if (!cmdbufp) cmdbuf[cmdbufp]=0; 
00935 //      nlp= strchr(cmdbuf,'\n');
00936       nlp= strpbrk(cmdbuf,";\n");
00937       if (!nlp) { 
00938         fl=fread(&cmdbuf[cmdbufp], 1,sizeof(cmdbuf)-cmdbufp-1,npipe);
00939         cmdbuf[cmdbufp+fl]=0;
00941 //        nlp= strchr(&cmdbuf[cmdbufp],'\n'); //! there were no new lines before cmdbufp
00942         nlp= strpbrk(&cmdbuf[cmdbufp],";\n"); 
00943         cmdbufp+=fl; 
00944       }
00945       if (nlp) {
00946 //printf ("++nlp=%d\n", (int) (nlp-cmdbuf));
00947         nlp[0]=0;
00948         cmdstrt=nlp-cmdbuf+1;
00949 //printf ("++cmdstrt=%d\n", cmdstrt);
00950 //printf ("cmdbuf[0]=%d, cmdbuf[1]=%d, cmdbuf[2]=%d, cmdbuf[3]=%d, \n",cmdbuf[0],cmdbuf[1],cmdbuf[2],cmdbuf[3]);
00951         for (fl=0; cmdbuf[fl] && strchr(" \t",cmdbuf[fl]); fl++);
00952 //printf ("++fl=%d\n", fl);
00953         return &cmdbuf[fl];
00954       } else {
00955 //printf ("notready: cmdbufp=%d, cmdstrt=%d\n",cmdbufp, cmdstrt);
00956           return NULL;
00957       }
00958 }
00959 // command[= \t]*args[ \t]*
00960 int parse_cmd(FILE* npipe) {
00961   char * cmd;
00962   char * args;
00963   char * argse;
00964   int d;
00965   double dd;
00966 //  if (!((cmd=getLineFromPipe(npipe)))) return 0; //! nothing in the pipe
00968   while(((cmd=getLineFromPipe(npipe))) && !cmd[0]) ;
00969   if (!cmd) return 0; 
00970 //  printf ("cmd[0]=%d:%s\n",(int) cmd[0],cmd);
00971   args=strpbrk(cmd,"= \t");
00973   if (args) {
00974     args[0]=0;
00975     args++;
00976     while (strchr("= \t",args[0])) args++;
00977     if (args[0]) {
00979       for (argse=strchr(args,'\0')-1; strchr("= \t",argse[0]);argse--) argse[0]='\0';
00980     }
00981     if (!args[0]) args=NULL;
00982   }
00984   if      (strcmp(cmd, "start")==0) {
00985      camogm_start();
00986      return 1;
00987   } else if (strcmp(cmd, "reset")==0) { 
00988      camogm_reset();
00989      return 2;
00990   } else if (strcmp(cmd, "stop")==0) {
00991      camogm_stop();
00992      return 3;
00993   } else if (strcmp(cmd, "exit")==0) { 
00994      camogm_stop();
00995      camogm_free();
00996      exit (0);
00997   } else if (strcmp(cmd, "duration")==0) {
00998      if (!(args) || (((d= strtol(args, NULL, 10)))<=0)) d=DEFAULT_DURATION;
00999      camogm_set_segment_duration(d);
01000      return 4;
01001   } else if (strcmp(cmd, "length")==0) {
01002      if (!(args) || (((d= strtol(args, NULL, 10)))<=0)) d=DEFAULT_LENGTH;
01003      camogm_set_segment_length(d);
01004      return 5;
01005   } else if (strcmp(cmd, "prefix")==0) {
01006      if (args) camogm_set_prefix (args);
01007      return 6;
01008   } else if (strcmp(cmd, "status")==0) { 
01009      camogm_status(args, 0);
01010      return 7;
01011   } else if (strcmp(cmd, "xstatus")==0) { 
01012      camogm_status(args, 1);
01013      return 7;
01014   } else if (strcmp(cmd, "save_gp")==0) {
01015      if ((args) && (((d= strtol(args, NULL, 10)))>=0)) camogm_set_save_gp(d);
01016      return 8;
01017   } else if (strcmp(cmd, "exif")==0) {
01018      if ((args) && (((d= strtol(args, NULL, 10)))>=0)) camogm_set_exif(d);
01019      return 8;
01020   } else if (strcmp(cmd, "debug")==0) {
01021      camogm_debug(args);
01022      return 9;
01023   } else if (strcmp(cmd, "timescale")==0) {
01024      dd= strtod(args,NULL);
01025      camogm_set_timescale(dd?dd:1.0);
01026      return 10;
01029 
01030 
01031   } else if (strcmp(cmd, "frameskip")==0) {
01032      d= strtol(args, NULL, 10);
01033      camogm_set_frames_skip(d);
01034      return 11;
01035   } else if (strcmp(cmd, "timelapse")==0) { 
01036      d= strtol(args, NULL, 10);
01037      camogm_set_frames_skip(-d);
01038      return 11;
01039   } else if (strcmp(cmd, "format")==0) {
01040      if (args) {
01041       if      (strcmp(args,  "none")==0) camogm_set_format(0);
01042       else if ((strcmp(args, "ogm" )==0) || (strcmp(args, "ogg")==0)) camogm_set_format(CAMOGM_FORMAT_OGM);
01043       else if ((strcmp(args, "jpeg")==0) || (strcmp(args, "jpg")==0)) camogm_set_format(CAMOGM_FORMAT_JPEG);
01044       else if (strcmp(args,  "mov" )==0)                              camogm_set_format(CAMOGM_FORMAT_MOV);
01045      }
01046      return 12;
01047   } else if (strcmp(cmd, "debuglev")==0) {
01048      d= strtol(args, NULL, 10);
01049      camogm_debug_level(d?d:0);
01050      return 13;
01051   } else if (strcmp(cmd, "kml")==0) {
01052      if ((args) && (((d= strtol(args, NULL, 10)))>=0)) camogm_kml_set_enable(d);
01053      return 14;
01054   } else if (strcmp(cmd, "kml_hhf")==0) {
01055      dd= strtod(args,NULL);
01056      camogm_kml_set_horHalfFov(dd);
01057      return 15;
01058   } else if (strcmp(cmd, "kml_vhf")==0) {
01059      dd= strtod(args,NULL);
01060      camogm_kml_set_vertHalfFov(dd);
01061      return 16;
01062   } else if (strcmp(cmd, "kml_near")==0) {
01063      dd= strtod(args,NULL);
01064      camogm_kml_set_near(dd);
01065      return 17;
01066   } else if (strcmp(cmd, "kml_alt")==0) {
01067      if (args) {
01068       if      (strcmp(args, "gps"   )==0) camogm_kml_set_height_mode(1);
01069       else if (strcmp(args, "ground")==0) camogm_kml_set_height_mode(0);
01070      }
01071      return 18;
01072   } else if (strcmp(cmd, "kml_height")==0) {
01073      dd= strtod(args,NULL);
01074      camogm_kml_set_height(dd);
01075      return 19;
01076   } else if (strcmp(cmd, "kml_period")==0) {
01077      d= strtol(args, NULL, 10);
01078      camogm_kml_set_period(d?d:1);
01079      return 20;
01080   }
01081 
01082   return -1;
01083 }
01084 
01085 int main(int argc, char *argv[])
01086 {
01087    const char circbufFileName[]="/dev/circbuf";
01088 //     int fd_circ;
01089    FILE * cmd_file;
01090    const char usage[]=   "This program allows recording of the video/images acquired by Elphel camera to the storage media.\n" \
01091                          "It is designed to run in the background and accept commands through a named pipe.\n\n" \
01092                          "Usage:\n\n" \
01093                          "%s <named_pipe_name>\n\n" \
01094                          "i.e.:\n\n" \
01095                          "%s /var/state/camogm_cmd\n\n" \
01096                          "When the program is runninig you may send commands by writing strings to the command file\n" \
01097                          "(/var/state/camogm_cmd in the example above). The complete list of available commands is available\n" \
01098                          "on Elphel Wiki (http://wiki.elphel.com/index.php?title=Camogm), here is the example of usage\n" \
01099                          "from the shell prompt in the camera:\n\n" \
01100                          "echo \"status; exif=1; format=jpeg;status=/var/tmp/camogm.status\" > /var/state/camogm_cmd\n\n" \
01101                          "That will print status information on the standard output (may not be visible if the program was not\n" \
01102                          "started from the same session), set exif mode on (each frame will have the full Exif header including\n" \
01103                          "a precise time stamp), set output format to a series of individual JPEG files, and then send status\n" \
01104                          "information to a file /var/tmp/camogm.status in the camera file system.\n\n" \
01105                          "This program does not control the process of acquisition of the video/images to the camera internal\n" \
01106                          "buffer, it only retrieves that data from the buffer (waiting when needed), packages it to selected\n" \
01107                          "format and stores the result files.\n\n";
01108    int go=1;
01109    int cmd;
01110    int i,rslt;
01111    state= &sstate; //extern
01113    if ((argc < 2) || (argv[1][1]=='-'))  { 
01114      printf (usage,argv[0],argv[0]);
01115      return 0;
01116    }
01117    camogm_init();
01118 
01120    state->fd_exif = open(ExifFileName, O_RDONLY);
01121    if (state->fd_exif<0) { // check control OK
01122      D0(fprintf (debug_file,"Error opening %s\n", ExifFileName));
01123      return -1;
01124    }
01125 
01127    state->fd_head = open(HeadFileName, O_RDWR);
01128    if (state->fd_head<0) { // check control OK
01129      D0(fprintf (debug_file,"Error opening %s\n", HeadFileName));
01130      return -1;
01131    }
01132    state->head_size=lseek(state->fd_head,0,SEEK_END);
01133    if (state->head_size>JPEG_HEADER_SIZE) {
01134      D0(fprintf (debug_file,"%s:%d: Too big JPEG header (%d > %d)",__FILE__,__LINE__,state->head_size, JPEG_HEADER_SIZE ));
01135      return -2;
01136    }
01137 
01139    state->fd_circ = open(circbufFileName, O_RDWR);
01140    if (state->fd_circ<0) { // check control OK
01141       D0(fprintf (debug_file,"Error opening %s\n", circbufFileName));
01142       return -2;
01143    }
01145    state->circ_buff_size=lseek(state->fd_circ,0,SEEK_END);
01146    ccam_dma_buf = (unsigned long *) mmap(0, state->circ_buff_size, PROT_READ, MAP_SHARED, state->fd_circ, 0);
01147    if((int)ccam_dma_buf == -1) {
01148      D0(fprintf (debug_file,"Error in mmap of %s\n",circbufFileName));
01149 //     close (fd_head);
01150      close(state->fd_circ);
01151      return -3;
01152    }
01153 
01155 
01157    state->fd_sens = open(SensParsFileName, O_RDWR);
01158    if (state->fd_sens<0) { // check control OK
01159       D0(fprintf (debug_file,"Error opening %s\n", SensParsFileName));
01160       return -2;
01161    }
01163    state->senspars_size=lseek(state->fd_sens,0,SEEK_END);
01164    imageParamsR = (unsigned long *) mmap(0, state->senspars_size, PROT_READ, MAP_SHARED, state->fd_sens, 0);
01165    if((int)imageParamsR == -1) {
01166      D0(fprintf (debug_file,"Error in mmap of %s\n",SensParsFileName));
01167      close(state->fd_sens);
01168      close(state->fd_circ);
01169      return -3;
01170    }
01171 
01172 
01173 
01176    i=unlink (argv[1]);
01177    if (i) {
01178        D1(fprintf (debug_file,"Unlink %s returned %d, errno=%d \n", argv[1], i, errno));
01179    }
01180    i=mkfifo(argv[1], 0777); //EEXIST
01182    if (i) {
01183     if (errno==EEXIST) {
01184        D1(fprintf (debug_file,"Named pipe %s already exists, will use it.\n", argv[1]));
01185     } else {
01186        D0(fprintf (debug_file,"Can not create a named pipe %s, errno=%d \n", argv[1], errno));
01187        return -4;
01188     }
01189    }
01190 
01193    if (!((cmd_file=fopen(argv[1],"r")))) {
01194      D0(fprintf (debug_file,"Can not open command file %s\n",argv[1]));
01195      return -5;
01196    }
01197    D1(fprintf (debug_file,"Pipe %s open for reading\n",argv[1]));
01198 
01200 #define COMMAND_LOOP_DELAY 500000 //0.5sec
01201  
01202    while (go) {
01203 //   D3(fprintf (debug_file,"%s:%d: format=%d, set_format=%d\n",__FILE__,__LINE__, state->format, state->set_format));
01204 
01206      cmd=parse_cmd(cmd_file);
01207      if (cmd) {
01208        if (cmd<0) D0(fprintf (debug_file,"Unrecognized command\n"));
01209      } else if (state->running) { 
01210 //   D3(fprintf (debug_file,"%s:%d: format=%d, set_format=%d\n",__FILE__,__LINE__, state->format, state->set_format));
01211 
01212        switch ((rslt=-sendImageFrame ())) {
01213          case 0:
01214 /*
01215           D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned %d\n" \
01216                                   "state->cirbuf_rp= 0x%x\n",__FILE__,__LINE__,rslt,state->cirbuf_rp));
01217 */
01218                             break; 
01219          case CAMOGM_FRAME_NOT_READY:        
01220 
01221 
01222 //     D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned -%d\n",__FILE__,__LINE__,rslt));
01223 /*
01224      D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned -%d\n" \
01225                                   "state->cirbuf_rp= 0x%x\n",__FILE__,__LINE__,rslt,state->cirbuf_rp));
01226 */
01227 
01228                 lseek(state->fd_circ,CIRCLSEEK_WAIT,SEEK_END);
01229                 break;
01230          case  CAMOGM_FRAME_CHANGED:   
01231          case  CAMOGM_FRAME_NEXTFILE:  
01232          case  CAMOGM_FRAME_INVALID:   
01233          case  CAMOGM_FRAME_BROKEN:    
01234 
01235 //     D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned -%d\n",__FILE__,__LINE__,rslt));
01236                 camogm_stop();
01237                 camogm_start();
01238                 break;
01239          case  CAMOGM_FRAME_FILE_ERR:  
01240          case  CAMOGM_FRAME_OTHER:     
01241                 D0(fprintf (debug_file,"%s:line %d - error=%d\n",__FILE__,__LINE__,rslt));
01242                 break;
01243          default:
01244           D0(fprintf (debug_file,"%s:line %d - should not get here (rslt=%d)\n",__FILE__,__LINE__,rslt));
01245           exit (-1);
01246        } //switch
01247      } else if (state->starting) { 
01248 //   D3(fprintf (debug_file,"%s:%d: format=%d, set_format=%d\n",__FILE__,__LINE__, state->format, state->set_format));
01249 
01251        switch ((rslt=-camogm_start())) {
01252          case 0:                       break; 
01253          case CAMOGM_FRAME_NOT_READY:        
01254 
01255 
01256 //                lseek(state->fd_circ,CIRCLSEEK_WAIT,SEEK_END);
01257          case  CAMOGM_FRAME_CHANGED:   
01258          case  CAMOGM_FRAME_NEXTFILE:
01259          case  CAMOGM_FRAME_INVALID:   
01260          case  CAMOGM_FRAME_BROKEN:    
01261 //     D3(fprintf (debug_file,"%s:line %d - camogm_start() returned -%d,  state->cirbuf_rp= 0x%x\n", __FILE__,__LINE__,rslt,state->cirbuf_rp));
01262                 usleep( COMMAND_LOOP_DELAY) ; 
01263                 break;
01264          case  CAMOGM_FRAME_FILE_ERR:  
01265          case  CAMOGM_FRAME_OTHER:     
01266                 D0(fprintf (debug_file,"%s:line %d - error=%d\n",__FILE__,__LINE__,rslt));
01267                 break;
01268          default:
01269           D0(fprintf (debug_file,"%s:line %d - should not get here (rslt=%d)\n",__FILE__,__LINE__,rslt));
01270           exit (-1);
01271        } //switch
01272      } else { 
01273        usleep( COMMAND_LOOP_DELAY) ; 
01274      }
01275    } 
01276    return 0;
01277 }

Generated on Thu Aug 7 16:18:58 2008 for elphel by  doxygen 1.5.1