apps/camogm2/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.1.1.1  2008/11/27 20:04:02  elphel
00025 *!
00026 *!
00027 *!  Revision 1.5  2008/11/20 23:21:32  elphel
00028 *!  Put FIXME notes and removed parameters that are not used anymore
00029 *!
00030 *!  Revision 1.4  2008/10/29 04:18:28  elphel
00031 *!  v.8.0.alpha10 made a separate structure for global parameters (not related to particular frames in a frame queue)
00032 *!
00033 *!  Revision 1.3  2008/10/13 16:55:53  elphel
00034 *!  removed (some) obsolete P_* parameters, renamed CIRCLSEEK to LSEEK_CIRC constants (same as other similar)
00035 *!
00036 *!  Revision 1.2  2008/09/07 19:48:07  elphel
00037 *!  snapshot
00038 *!
00039 *!  Revision 1.1  2008/05/02 12:45:57  spectr_rain
00040 *!  initial revision with the sound support
00041 *!
00042 *!  Revision 1.9  2008/04/13 21:05:19  elphel
00043 *!  Fixing KML generation
00044 *!
00045 *!  Revision 1.8  2008/04/11 23:09:33  elphel
00046 *!  modified to handle kml generation
00047 *!
00048 *!  Revision 1.7  2008/04/07 09:13:34  elphel
00049 *!  Changes related to new Exif generation/processing
00050 *!
00051 *!  Revision 1.6  2008/01/14 22:59:00  elphel
00052 *!  7.1.7.4 - added timelapse mode to camogm
00053 *!
00054 *!  Revision 1.5  2007/12/03 08:28:45  elphel
00055 *!  Multiple changes, mostly cleanup
00056 *!
00057 *!  Revision 1.4  2007/11/29 00:38:57  elphel
00058 *!  fixed timescale bug
00059 *!
00060 *!  Revision 1.3  2007/11/19 05:07:19  elphel
00061 *!  fixed 2 typos
00062 *!
00063 *!  Revision 1.2  2007/11/19 03:23:21  elphel
00064 *!  7.1.5.5 Added support for *.mov files in camogm.
00065 *!
00066 *!  Revision 1.1  2007/11/16 08:49:56  elphel
00067 *!  Initial release of camogm - program to record video/image to the camera hard drive (or other storage)
00068 *!
00069 */ 
00070 #include <unistd.h>
00071 #include <stdio.h>
00072 #include <stdlib.h>
00073 #include <signal.h>
00074 #include <fcntl.h>
00075 #include <sys/uio.h>
00076 #include <errno.h>
00077 #include <sys/types.h>
00078 #include <sys/socket.h>
00079 #include <sys/stat.h>
00080 //#include <ctype.h>
00081 //#include <getopt.h>
00082 #include <time.h>
00083 #include <string.h>
00084 
00085 #include <netinet/in.h> /*little <-> big endian ?*/
00086 #include <sys/mman.h>           /* mmap */
00087 #include <sys/ioctl.h>
00088 
00089 #include <asm/elphel/c313a.h>
00090 //#include <asm/elphel/exifa.h>
00091 #include <asm/elphel/ext353.h>
00092 #include <asm/byteorder.h>
00093 
00094 
00095 #include <ogg/ogg.h> // has to be before ogmstreams.h
00096 #include "ogmstreams.h" // move it to <>?
00097 
00098 //#include "camogm_exif.h"
00099 #include "camogm_ogm.h"
00100 #include "camogm_jpeg.h"
00101 #include "camogm_mov.h"
00102 #include "camogm_kml.h"
00103 #include "camogm.h"
00104 #include "camogm_wav.h"
00105 
00106 #include <alsa/asoundlib.h>
00107 
00108 #define TRAILER_SIZE   0x02
00109 #define MAP_OPTIONS MAP_FILE|MAP_PRIVATE
00110 
00111 char trailer[TRAILER_SIZE] = {0xff,0xd9};
00112 
00113 const char ExifFileName[]="/dev/exif_exif";
00114 
00115 const char HeadFileName[]="/dev/jpeghead";
00116 const char SensParsFileName[]="/dev/sensorpars";
00117 unsigned long * ccam_dma_buf;           /* mmapped array */
00118 unsigned long * imageParamsR;           // to be removed
00119 int buff_size;
00120 
00121 #define DEFAULT_DURATION 60 
00122 #define DEFAULT_LENGTH 100000000 
00123 
00124 #define DEFAULT_FRAMES           16384 /* Maximal number of frames in file segment (each need 4* (1 + 1/frames_per_chunk) bytes for the frame index */
00125 #define DEFAULT_FRAMES_PER_CHUNK    10 /*second sparse index - for Quicktime fast forward */
00126 
00127 #define DEFAULT_LENGTH 100000000 
00128 #define DEFAULT_EXIF 1 /* use Exif */
00129 
00130 #define DEFAULT_AUDIO_RATE      44100
00131 #define DEFAULT_AUDIO_CHANNELS  2
00132 
00133 #define AUDIO_RATE_MAX  44100
00134 #define AUDIO_RATE_MIN  11025
00135 #define AUDIO_CHANNELS_MAX      2
00136 #define AUDIO_CHANNELS_MIN      1
00137 
00138 static char cmdbuf[1024];
00139 static int  cmdbufp=0; // current input pointer in the command buffer (read from pipe)
00140 static int  cmdstrt=0; // start of the next partial command
00141 
00142 camogm_state sstate;
00143 camogm_state * state;
00144 
00145 int   debug_level;
00146 FILE* debug_file;
00147 
00148 
00149 int camogm_init(void);
00150 
00151 int camogm_start(int by_command);
00152 int camogm_stop(int by_command);
00153 
00154 int camogm_reset(void); 
00155 int camogm_debug(const char * fname);
00156 int camogm_debug_level(int d);
00157 void  camogm_set_segment_duration(int sd);
00158 void  camogm_set_segment_length(int sl);
00159 void  camogm_set_save_gp(int d);
00160 void  camogm_set_prefix (const char * p);
00161 void  camogm_set_exif(int d);
00162 void  camogm_set_timescale(double d); 
00163 void  camogm_set_frames_skip(int d); 
00164 void  camogm_set_format(int d);
00165 
00166 void  camogm_kml_set_enable(int d);
00167 void  camogm_kml_set_horHalfFov (double dd);
00168 void  camogm_kml_set_vertHalfFov(double dd);
00169 void  camogm_kml_set_height_mode(int d);
00170 void  camogm_kml_set_height(double dd);
00171 void  camogm_kml_set_period(int d);
00172 void  camogm_kml_set_near(double dd); // distance to PhotoOverlay
00173 
00174 
00175 int   parse_cmd(FILE* npipe);
00176 char * getLineFromPipe(FILE* npipe);
00177 
00178 int  sendImageFrame (void);
00179 
00180 void  camogm_set_max_frames(int d);
00181 void  camogm_set_frames_per_chunk(int d);
00182 
00183 
00184 void camogm_set_audio_state(char *args);
00185 void camogm_set_audio_format(char *args);
00186 void camogm_set_sync_state(char *args);
00187 void audio_process(void);
00188 void audio_init(int by_command);
00189 void audio_start(int by_command);
00190 void audio_end(int by_command);
00191 void audio_free(void);
00193 void put_uint16(void *buf, u_int16_t val)
00194 {
00195         unsigned char  *tmp;
00196 
00197         tmp = (unsigned char *) buf;
00198 
00199         tmp[0] = val & 0xff;
00200         tmp[1] = (val >>= 8) & 0xff;
00201 }
00202 
00203 void put_uint32(void *buf, u_int32_t val)
00204 {
00205         unsigned char  *tmp;
00206 
00207         tmp = (unsigned char *) buf;
00208 
00209         tmp[0] = val & 0xff;
00210         tmp[1] = (val >>= 8) & 0xff;
00211         tmp[2] = (val >>= 8) & 0xff;
00212         tmp[3] = (val >>= 8) & 0xff;
00213 }
00214 
00215 void put_uint64(void *buf, u_int64_t val)
00216 {
00217         unsigned char  *tmp;
00218 
00219         tmp = (unsigned char *) buf;
00220 
00221         tmp[0] = val & 0xff;
00222         tmp[1] = (val >>= 8) & 0xff;
00223         tmp[2] = (val >>= 8) & 0xff;
00224         tmp[3] = (val >>= 8) & 0xff;
00225         tmp[4] = (val >>= 8) & 0xff;
00226         tmp[5] = (val >>= 8) & 0xff;
00227         tmp[6] = (val >>= 8) & 0xff;
00228         tmp[7] = (val >>= 8) & 0xff;
00229 }
00230 
00231 int camogm_init(void) {
00232    const char sserial[]="elp0";
00233    int * ipser= (int*) sserial;
00234    state->running=0; // mo
00235    state->starting=0; // mo
00236    state->vf=NULL;
00237    camogm_set_segment_duration(DEFAULT_DURATION);
00238    camogm_set_segment_length(DEFAULT_LENGTH);
00239    camogm_set_max_frames(DEFAULT_FRAMES);
00240    camogm_set_frames_per_chunk(DEFAULT_FRAMES_PER_CHUNK);
00241    camogm_set_prefix ("\0");
00242    camogm_set_save_gp(0);
00243    camogm_reset(); 
00244    state->serialno= ipser[0];
00245    state->last= 0;
00246    debug_file= stderr;
00247    camogm_debug_level(1);
00248    strcpy(state->debug_name,"stderr");
00249    camogm_set_timescale(1.0);
00250    camogm_set_frames_skip(0); 
00251    camogm_set_format(CAMOGM_FORMAT_OGM);
00252    camogm_set_audio_state("off");
00253    camogm_set_audio_format("44100/1");
00254    camogm_set_sync_state("off");
00255    state->exifSize=0;
00256    state->exif= DEFAULT_EXIF;
00257    state->frame_lengths=NULL;
00258    state->frameno=0;
00259    state->formats=0;
00260 
00262    camogm_kml_set_enable(0);
00263    state->kml_file=NULL;
00264    camogm_kml_set_horHalfFov (20.0);
00265    camogm_kml_set_vertHalfFov(15.0);
00266    camogm_kml_set_height_mode(0);
00267    camogm_kml_set_height(10.0);
00268    camogm_kml_set_period(2); // 2 sec
00269    camogm_kml_set_near(40.0); // 40 m (distance to PhotoOverlay)
00270    state->kml_path[0]='\0';
00271 
00272 
00273 /*
00274 void  camogm_kml_set_enable(int d);
00275 void  camogm_kml_set_horHalfFov (double dd);
00276 void  camogm_kml_set_vertHalfFov(double dd);
00277 void  camogm_kml_set_height_mode(int d);
00278 void  camogm_kml_set_height(double dd);
00279 void  camogm_kml_set_decimate(int d);
00280 
00281   int                   kml_enable;       //! enable KML file generation
00282   FILE*                 kml_file;         //! stream to write kml file
00283   double                kml_horHalfFov;   //! half horizontal Fov (degrees)
00284   double                kml_vertHalfFov;  //! half vertical Fov (degrees)
00285   int                   kml_height_mode;  //! 1 - actual, 0 - ground
00286   double                kml_height;       //! extra height to add
00287   int                   kml_decimate;     //! generate PhotoOverlay for each kml_decimate frame;
00288   int                   kml_decimate_counter; //! counter to skip kml frames
00289   double                kml_near;         //! Use in KML "near" parameter (<=0 - don't use it)
00290 
00291 */
00292 
00293 
00294 
00295    return 0;
00296 }
00297 
00298 
00299 int camogm_debug(const char * fname) {
00300   int none=1;
00301   if (fname && strlen(fname) && strcmp(fname, "none") && strcmp(fname, "null")  && strcmp(fname, "/dev/null")) none=0;
00302   if (debug_file){
00303     if (strcmp(state->debug_name, "stdout") && strcmp(state->debug_name, "stderr")) fclose (debug_file);
00304     debug_file=NULL;
00305     state->debug_name[0]='\0';
00306   }
00307   if (!none) {
00308     if      (strcmp(fname, "stdout") ==0) debug_file=stdout;
00309     else if (strcmp(fname, "stderr") ==0) debug_file=stderr;
00310     else                                  debug_file=fopen(fname,"w+");
00311   }
00312   if (debug_file) {
00313       strncpy(state->debug_name,fname,sizeof(state->debug_name)-1);
00314       state->debug_name[sizeof(state->debug_name)-1]='\0';
00315   }
00316   return 0;
00317 }
00318 
00319 int camogm_debug_level(int d) {
00320   debug_level=d;
00321   return 0;
00322 }
00323 
00324 
00325 
00326 
00327 int camogm_start(int by_command) {
00328   int timestamp_start;
00329   int rslt;
00330   int next_metadata_start, next_jpeg_len, fp;
00331   D1(fprintf (debug_file,"Starting recording\n"));
00332   state->frameno=0;
00333   state->timescale=        state->set_timescale;
00334 
00335   int * ifp =      (int *) &(state->frame_params) ;
00336   int * ifp_this = (int *) &(state->this_frame_params) ;
00337   if (state->kml_enable) camogm_init_kml() ; // do nothing
00338 
00339         audio_init(by_command);
00340   if (state->format != state->set_format) {
00341      state->format=  state->set_format;
00342      switch (state->format) {
00343       case CAMOGM_FORMAT_NONE: rslt= 0; break;
00344       case CAMOGM_FORMAT_OGM:  rslt= camogm_init_ogm(); break;
00345       case CAMOGM_FORMAT_JPEG: rslt= camogm_init_jpeg();break;
00346       case CAMOGM_FORMAT_MOV:  rslt= camogm_init_mov(); break;
00347      }
00348      state->formats |= 1 << (state->format);
00350   }
00351   state->max_frames=       state->set_max_frames;
00352   state->frames_per_chunk= state->frames_per_chunk;
00353   state->starting=1; 
00354 
00355 D3(fprintf (debug_file,"1: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00356   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 )) {
00357 D3(fprintf (debug_file,"2: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00358     state->cirbuf_rp=lseek(state->fd_circ,LSEEK_CIRC_LAST,SEEK_END);
00359     if (((fp=lseek(state->fd_circ,LSEEK_CIRC_PREV,SEEK_END)))>=0) state->cirbuf_rp=fp; 
00360     state->buf_overruns++;
00362 //    state->buf_min=lseek(state->fd_circ,LSEEK_CIRC_FREE,SEEK_END);
00363 //    lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET); //! restore after moving (side effect)
00364     state->buf_min=imageParamsR[G_FREECIRCBUF];
00365 
00366   } else {
00367 //      b_free=lseek(state->fd_circ,LSEEK_CIRC_FREE,SEEK_END);
00368 //      lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET); //! restore after moving (side effect)
00369 //      if (state->buf_min > b_free) state->buf_min=b_free;
00370       if (state->buf_min > imageParamsR[G_FREECIRCBUF]) state->buf_min=imageParamsR[G_FREECIRCBUF];
00371 
00372   }
00373 D3(fprintf (debug_file,"3: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00374 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)));
00375 
00377   if (lseek(state->fd_circ,LSEEK_CIRC_READY,SEEK_END) <0) return -CAMOGM_FRAME_NOT_READY; 
00378 D3(fprintf (debug_file,"5: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00379   state->metadata_start=(state->cirbuf_rp)-32;
00380   if (state->metadata_start<0) state->metadata_start+=state->circ_buff_size;
00381 
00383 
00384   memcpy (&(state->frame_params), (unsigned long * ) &ccam_dma_buf[state->metadata_start>>2],32);
00385   state->jpeg_len=state->frame_params.frame_length; 
00386 
00387 
00388   if (state->frame_params.signffff !=0xffff) {
00389     D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n",__FILE__,__LINE__,(int) state->frame_params.signffff));
00390      state->cirbuf_rp=-1;
00391      D1(fprintf(debug_file, "state->cirbuf_rp=0x%x\r\n",(int) state->cirbuf_rp));
00392      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]));
00393      return -CAMOGM_FRAME_BROKEN;
00394   }
00397   timestamp_start=(state->cirbuf_rp)+((state->jpeg_len+CCAM_MMAP_META+3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC; 
00398   if (timestamp_start >= state->circ_buff_size) timestamp_start-=state->circ_buff_size;
00399   memcpy (&(state->frame_params.timestamp_sec), (unsigned long * ) &ccam_dma_buf[timestamp_start>>2],8);
00400 
00402   if ((lseek(state->fd_circ,LSEEK_CIRC_NEXT,SEEK_END) < 0 ) ||
00404       (((fp=lseek(state->fd_circ,LSEEK_CIRC_READY,SEEK_END))) < 0)) {
00405         lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET); 
00406         return -CAMOGM_FRAME_NOT_READY; 
00407   }
00408   next_metadata_start=fp-32;
00409   if (next_metadata_start<0) next_metadata_start+= state->circ_buff_size;
00410   memcpy (&(state->this_frame_params), (unsigned long * ) &ccam_dma_buf[next_metadata_start>>2],32);
00411   next_jpeg_len=state->this_frame_params.frame_length; 
00412   if (state->this_frame_params.signffff !=0xffff) { 
00413      D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n",__FILE__,__LINE__,(int) state->this_frame_params.signffff));
00414      D1(fprintf(debug_file, "fp=0x%x\r\n",(int) fp));
00415      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]));
00416 //  int * ifp =      (int *) &(state->this_frame_params) ;
00417 //  int * ifp_this = (int *) &(state->this_frame_params) ;
00418 
00419      state->cirbuf_rp=-1;
00420      return -CAMOGM_FRAME_BROKEN;
00421   }
00423   timestamp_start=fp+((next_jpeg_len+CCAM_MMAP_META+3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC; 
00424   if (timestamp_start >= state->circ_buff_size) timestamp_start-=state->circ_buff_size;
00425   memcpy (&(state->this_frame_params.timestamp_sec), (unsigned long * ) &ccam_dma_buf[timestamp_start>>2],8);
00427   if ((state->frame_params.width  != state->this_frame_params.width) ||
00428       (state->frame_params.height != state->this_frame_params.height)) {
00430      state->cirbuf_rp=fp;
00431      return -CAMOGM_FRAME_CHANGED; // no yet checking for the FPS
00432   }
00434    state->frame_period=(state->this_frame_params.timestamp_usec - state->frame_params.timestamp_usec)+
00435                1000000*(state->this_frame_params.timestamp_sec  - state->frame_params.timestamp_sec);
00436 
00438   state->frames_skip=      state->set_frames_skip;
00439   if (state->frames_skip > 0) {
00440     state->frames_skip_left=0;
00441     state->frame_period *= (state->frames_skip+1);
00442 //    state->frames_skip_left= state->set_frames_skip;
00443   } else if (state->frames_skip < 0) {
00444     state->frame_period=-(state->frames_skip) ; 
00445     state->frames_skip_left=state->frame_params.timestamp_sec;
00446   }
00447    state->time_unit= (ogg_int64_t) (((double) state-> frame_period) * ((double) 10) / ((double) state-> timescale));
00448    state->width=state->frame_params.width;
00449    state->height=state->frame_params.height;
00450 
00453    lseek(state->fd_head,state->cirbuf_rp+1,SEEK_END); 
00454 
00455    lseek(state->fd_head,0,0);
00456    read (state->fd_head,state->jpegHeader,state->head_size);
00458    lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET);
00460         audio_start(by_command);
00461    switch (state->format) {
00462     case CAMOGM_FORMAT_NONE: rslt= 0;  break;
00463     case CAMOGM_FORMAT_OGM:  rslt= camogm_start_ogm();  break;
00464     case CAMOGM_FORMAT_JPEG: rslt= camogm_start_jpeg(); break;
00465     case CAMOGM_FORMAT_MOV:  rslt= camogm_start_mov();  break;
00466     default: rslt=0; // do nothing
00467    }
00468    if (rslt) return rslt;
00469    if (state->kml_enable) rslt=camogm_start_kml() ; // will turn on state->kml_used if it can
00470    if (rslt) return rslt;
00471    state->running=1;
00472    state->starting=0;
00473    D1(fprintf (debug_file,"Started OK\n"));
00474    return 0;
00475 }
00476 
00477 
00478 int sendImageFrame(void) {
00479         int rslt;
00480 //      struct interframe_params_t this_frame_params;
00481 //      elph_packet_chunk packetchunks[7];
00482         unsigned char frame_packet_type = PACKET_IS_SYNCPOINT;
00483 //      int chunk_index=0;
00484 //      int i;
00485 //      unsigned long * tts= (unsigned long *) &(state->granulepos); //to word-swap timestamt to granule
00486         int timestamp_start;
00487 // debugging:
00488 //      int * ifp =      (int *) &(state->frame_params) ;
00489         int * ifp_this = (int *) &(state->this_frame_params) ;
00490 
00492         if(state->frameno >= (state->max_frames))
00493                 return -CAMOGM_FRAME_CHANGED;
00495 //   D3(fprintf (debug_file,"sendImageFrame: format=%d, set_format=%d\n", state->format, state->set_format));
00496 
00497         if(state->format != state->set_format)
00498                 return -CAMOGM_FRAME_CHANGED;
00500         if((state->vf) && (state->segment_length >=0) && (ftell(state->vf) > state->segment_length))
00501                 return -CAMOGM_FRAME_CHANGED;
00503         if(((state->ivf) >= 0) && (state->segment_length >= 0) && (lseek(state->ivf, 0, SEEK_CUR) > state->segment_length))
00504                 return -CAMOGM_FRAME_CHANGED;
00506         if(lseek(state->fd_circ, state->cirbuf_rp, SEEK_SET) < 0)
00507                 return -CAMOGM_FRAME_INVALID; 
00508 
00509         if(lseek(state->fd_circ, LSEEK_CIRC_READY, SEEK_END) < 0)
00510                 return -CAMOGM_FRAME_NOT_READY; 
00511 /*
00513   state->frames_skip=      state->set_frames_skip;
00514   if (state->frames_skip > 0) {
00515     state->frames_skip_left=0;
00516     state->frame_period *= (state->frames_skip+1);
00517 //    state->frames_skip_left= state->set_frames_skip;
00518   } else if (state->frames_skip < 0) {
00519     state->frame_period=-(state->frames_skip) ; //! actual frame period will fluctuate to the nearest frame acquired (free running)
00520     state->frames_skip_left=state->frame_params.timestamp_sec;
00521   }
00522 */
00523 
00525         if((state->frames_skip > 0) && (state->frames_skip_left > 0 )) { 
00526                 state->cirbuf_rp = lseek(state->fd_circ, LSEEK_CIRC_NEXT, SEEK_END);
00528                 if(state->save_gp)
00529                         lseek(state->fd_circ, LSEEK_CIRC_SETP, SEEK_END);
00530                 state->frames_skip_left--;
00531                 return -CAMOGM_FRAME_NOT_READY; 
00532         }
00533 
00535 //D3(fprintf (debug_file,"_1_"));
00536         state->metadata_start = state->cirbuf_rp - 32;
00537         if(state->metadata_start < 0)
00538                 state->metadata_start += state->circ_buff_size;
00539         memcpy(&(state->this_frame_params), (unsigned long * ) &ccam_dma_buf[state->metadata_start>>2],32);
00540         state->jpeg_len = state->this_frame_params.frame_length; 
00541         if(state->this_frame_params.signffff != 0xffff) {
00542                 D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n",__FILE__,__LINE__,(int) state->this_frame_params.signffff));
00543                 D1(fprintf(debug_file, "state->cirbuf_rp=0x%x\r\n",(int) state->cirbuf_rp));
00544                 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]));
00545                 return -CAMOGM_FRAME_BROKEN;
00546         }
00547 //D3(fprintf (debug_file,"_2_"));
00549         timestamp_start = state->cirbuf_rp + ((state->jpeg_len + CCAM_MMAP_META + 3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC; 
00550         if(timestamp_start >= state->circ_buff_size)
00551                 timestamp_start -= state->circ_buff_size;
00552 //D3(fprintf (debug_file,"_3_"));
00553         memcpy(&(state->this_frame_params.timestamp_sec), (unsigned long *)&ccam_dma_buf[timestamp_start >> 2], 8);
00555         if((state->frame_params.width != state->this_frame_params.width) || (state->frame_params.height != state->this_frame_params.height))
00556                 return -CAMOGM_FRAME_CHANGED; 
00557 
00558         if((state->segment_duration > 0) && ((state->this_frame_params.timestamp_sec-state->frame_params.timestamp_sec) > state->segment_duration))
00559                 return -CAMOGM_FRAME_CHANGED;
00561         if((state->frames_skip < 0) && (state->frames_skip_left > state->this_frame_params.timestamp_sec)) {
00562                 state->cirbuf_rp = lseek(state->fd_circ, LSEEK_CIRC_NEXT, SEEK_END);
00564                 if(state->save_gp)
00565                         lseek(state->fd_circ, LSEEK_CIRC_SETP, SEEK_END);
00566                 return -CAMOGM_FRAME_NOT_READY; 
00567         }
00568 
00569 
00570 //D3(fprintf (debug_file,"_4_"));
00571         if(state->exif) {
00572                 D3(fprintf(debug_file,"_5_"));
00574 //     updateExif(ep, state->ed, &(state->frame_params));
00575                 state->exifSize = lseek(state->fd_exif, 1, SEEK_END); // at the beginning of page 1 - position == page length
00576 //              if (state->exifSize < 0) state->exifSize=0; // error from lseek;
00577                 if(state->exifSize > 0) {
00578 //state->this_frame_params.meta_index
00579                         lseek(state->fd_exif, state->this_frame_params.meta_index, SEEK_END); 
00580                         rslt = read(state->fd_exif, state->ed, state->exifSize);
00581                         if(rslt < 0)
00582                                 rslt = 0;
00583                         state->exifSize = rslt;
00584                 } else state->exifSize = 0;
00585         } else state->exifSize=0;
00586 
00587 //D3(fprintf (debug_file,"_6_"));
00588 
00590         state->chunk_index=0;
00591         state->packetchunks[state->chunk_index  ].bytes=1;
00592         state->packetchunks[state->chunk_index++].chunk=&frame_packet_type;
00593         if(state->exif > 0) {
00594 //D3(fprintf (debug_file,"_7_"));
00595                 state->packetchunks[state->chunk_index  ].bytes = 2;
00596                 state->packetchunks[state->chunk_index++].chunk = state->jpegHeader;
00597                 state->packetchunks[state->chunk_index  ].bytes = state->exifSize;
00598                 state->packetchunks[state->chunk_index++].chunk = state->ed;
00599                 state->packetchunks[state->chunk_index  ].bytes = state->head_size - 2;
00600                 state->packetchunks[state->chunk_index++].chunk = &(state->jpegHeader[2]);
00601         } else {
00602 //D3(fprintf (debug_file,"_8_"));
00603                 state->packetchunks[state->chunk_index  ].bytes = state->head_size;
00604                 state->packetchunks[state->chunk_index++].chunk = state->jpegHeader;
00605         }
00606 //D3(fprintf (debug_file,"_9_"));
00607 
00609 //     if ((jpeg_start+jpeg_len) > state->circ_buff_size) { // two segments
00610         if((state->cirbuf_rp + state->jpeg_len) > state->circ_buff_size) { 
00611 
00612 //D3(fprintf (debug_file,"_10_"));
00613 
00614 //        sendBuffer((void *) &ccam_dma_buf[jpeg_start>>2], state->circ_buff_size-state->cirbuf_rp);
00615                 state->packetchunks[state->chunk_index  ].bytes = state->circ_buff_size-state->cirbuf_rp;
00616                 state->packetchunks[state->chunk_index++].chunk = (unsigned char*) &ccam_dma_buf[state->cirbuf_rp >> 2];
00618 //        sendBuffer((void *) &ccam_dma_buf[0], jpeg_len-(state->circ_buff_size-state->cirbuf_rp));
00619                 state->packetchunks[state->chunk_index  ].bytes = state->jpeg_len - (state->circ_buff_size - state->cirbuf_rp);
00620                 state->packetchunks[state->chunk_index++].chunk = (unsigned char*) &ccam_dma_buf[0];
00621         } else { // single segment
00622 //D3(fprintf (debug_file,"_11_"));
00623 
00625 //        sendBuffer((void *) &ccam_dma_buf[state->cirbuf_rp>>2], state->jpeg_len);
00626                 state->packetchunks[state->chunk_index  ].bytes = state->jpeg_len;
00627                 state->packetchunks[state->chunk_index++].chunk = (unsigned char*)  &ccam_dma_buf[state->cirbuf_rp >> 2];
00628         }
00629 //D3(fprintf (debug_file,"_12_"));
00630         state->packetchunks[state->chunk_index  ].bytes = 2;
00631         state->packetchunks[state->chunk_index++].chunk = (unsigned char*) trailer;
00632 
00633         switch (state->format) {
00634                 case CAMOGM_FORMAT_NONE: rslt=0; break;
00635                 case CAMOGM_FORMAT_OGM:  rslt = camogm_frame_ogm(); break;
00636                 case CAMOGM_FORMAT_JPEG: rslt = camogm_frame_jpeg(); break;
00637                 case CAMOGM_FORMAT_MOV:  rslt = camogm_frame_mov(); break;
00638                 default: rslt = 0; // do nothing
00639         }
00640         if(rslt)
00641                 return rslt;
00642         if(state->kml_used)
00643                 rslt = camogm_frame_kml() ; // will turn on state->kml_used if it can
00644         if(rslt)
00645                 return rslt;
00646 
00647 //D3(fprintf (debug_file,"_14_"));
00649         state->frameno++;
00650         state->cirbuf_rp = lseek(state->fd_circ, LSEEK_CIRC_NEXT, SEEK_END);
00652         if(state->save_gp)
00653                 lseek(state->fd_circ, LSEEK_CIRC_SETP, SEEK_END);
00654 //D3(fprintf (debug_file,"_15_\n"));
00655 //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),
00656 //                                                                (int) state->this_frame_params.timestamp_sec, (int)state->this_frame_params.timestamp_usec));
00657         if(state->frames_skip > 0) {
00658                 state->frames_skip_left = state->frames_skip;
00659         } else {
00660                 if(state->frames_skip < 0) {
00661                         state->frames_skip_left += -(state->frames_skip);
00662                 }
00663         }
00664         return 0;
00665 }
00666 
00667 int camogm_stop(int by_command) {
00668   int rslt=0;
00669   if (!state->running) {
00670     if (!state->starting) {
00671       D2(fprintf (debug_file,"Recording was not running, nothing to stop\n"));
00672     } else {
00673       state->starting=0;
00674       D1(fprintf (debug_file,"Dropping attempt to start\n"));
00675     }
00676     return 0;
00677   }
00678   D1(fprintf (debug_file,"Ending recording\n"));
00679    if (state->kml_used) camogm_end_kml() ;
00680         audio_end(by_command);
00681    switch (state->format) {
00682     case CAMOGM_FORMAT_NONE: rslt= 0; break;
00683     case CAMOGM_FORMAT_OGM:  rslt= camogm_end_ogm(); break;
00684     case CAMOGM_FORMAT_JPEG: rslt= camogm_end_jpeg();break;
00685     case CAMOGM_FORMAT_MOV:  rslt= camogm_end_mov(); break;
00687    }
00689   if (state->vf) fclose (state->vf);
00690   state->vf=NULL;
00691   if (rslt) return rslt;
00692   state->last=1;
00694   state->running=0;
00695   state->starting=0;
00696   return 0;
00697 }
00698 
00699 void camogm_free() {
00700    int f;
00702 //add kml when needed
00703    for (f=0;f<31;f++) {
00704      if (state->formats & ( 1 << (state->format))) {
00705        switch (f) {
00706         case CAMOGM_FORMAT_NONE: break;
00707         case CAMOGM_FORMAT_OGM:  camogm_free_ogm(); break;
00708         case CAMOGM_FORMAT_JPEG: camogm_free_jpeg();break;
00709         case CAMOGM_FORMAT_MOV:  camogm_free_mov(); break;
00710        }
00711      }
00712    }
00713    state->formats=0;
00714 }
00715 
00716 int camogm_reset(void) { 
00717    state->cirbuf_rp=-1;
00718    state->buf_overruns=-1; 
00719    return 0;
00720 }
00721 
00723 void  camogm_kml_set_enable(int d) {
00724    state->kml_enable=d;
00725 }
00726 void  camogm_kml_set_horHalfFov (double dd) {
00727    state->kml_horHalfFov=dd;
00728 }
00729 void  camogm_kml_set_vertHalfFov(double dd) {
00730    state->kml_vertHalfFov=dd;
00731 }
00732 void  camogm_kml_set_height_mode(int d) {
00733    state->kml_height_mode=d;
00734 }
00735 void  camogm_kml_set_height(double dd) {
00736    state->kml_height=dd;
00737 }
00738 void  camogm_kml_set_period(int d) {
00739    state->kml_period=d;
00740    state->kml_last_ts=0;
00741    state->kml_last_uts=0;
00742 }
00743 void  camogm_kml_set_near(double dd) { // distance to PhotoOverlay
00744    state->kml_near=dd;
00745 }
00746 
00747 
00748 void  camogm_set_segment_duration(int sd) {
00749    state->segment_duration=sd;
00750 }
00751 void  camogm_set_segment_length(int sl) {
00752    state->segment_length=   sl;
00753 }
00754 void  camogm_set_save_gp(int d) {
00755    state->save_gp=   d;
00756 }
00757 void  camogm_set_exif(int d) {
00758    state->exif=   d;
00759 }
00760 
00761 void  camogm_set_prefix (const char * p) {
00762   strncpy(state->path_prefix, p, sizeof(state->path_prefix)-1);
00763   state->path_prefix[sizeof(state->path_prefix)-1]='\0';
00764 }
00765 
00766 void  camogm_set_timescale(double d) { 
00767    state->set_timescale=  d;
00768    if ((state->running==0) && (state->starting==0)) {
00769      state->timescale=state->set_timescale;
00770    }
00771 }
00772 
00773 void  camogm_set_frames_skip(int d) { 
00774    state->set_frames_skip=  d;
00775    if ((state->running==0) && (state->starting==0)) {
00776      state->frames_skip=      state->set_frames_skip;
00777 //     state->frames_skip_left= state->set_frames_skip;
00778      state->frames_skip_left= 0;
00779    }
00780 }
00781 
00782 void  camogm_set_format(int d) {
00783    int rslt=0;
00784    state->set_format=  d;
00785    if ((state->running==0) && (state->starting==0)) {
00786      state->format=  state->set_format;
00787      switch (state->format) {
00788       case CAMOGM_FORMAT_NONE: rslt= 0; break;
00789       case CAMOGM_FORMAT_OGM:  rslt= camogm_init_ogm(); break;
00790       case CAMOGM_FORMAT_JPEG: rslt= camogm_init_jpeg();break;
00791       case CAMOGM_FORMAT_MOV:  rslt= camogm_init_mov(); break;
00792      }
00793      if (rslt) {
00794        D0(fprintf (debug_file,"%s:%d: Error setting format to=%d\n",__FILE__,__LINE__, state->format));
00795      }
00796      state->formats |= 1 << (state->format);
00797    }
00798 }
00799 
00801 void  camogm_set_max_frames(int d) {
00802    state->set_max_frames=  d;
00803    if ((state->running==0) && (state->starting==0)) state->max_frames=  d;
00804 }
00805 
00806 void  camogm_set_frames_per_chunk(int d) {
00807    state->set_frames_per_chunk=  d;
00808    if ((state->running==0) && (state->starting==0)) state->frames_per_chunk=  d;
00809 }
00810 
00811 void  camogm_status(char * fn, int xml) {
00812   int _len=0;
00813   int _dur,_udur;
00814 //TODO:make it XML file
00815   FILE* f;
00816   char *_state, *_output_format, *_using_exif, *_using_global_pointer, *_compressor_state;
00817   int _b_free, _b_used; // , save_p;
00818   int _frames_remain=0;
00819   int _sec_remain=0;
00820   int _frames_skip=0;
00821   int _sec_skip=0;
00822   char *_kml_enable, *_kml_used, *_kml_height_mode;
00823 
00824   _kml_enable=      state->kml_enable?"yes":"no";
00825   _kml_used=        state->kml_used?"yes":"no";
00826   _kml_height_mode= state->kml_height_mode?"GPS altitude":"map ground level";  
00827 
00828 
00829   _b_free=imageParamsR[G_FREECIRCBUF];
00830   _b_used=imageParamsR[G_CIRCBUFSIZE]-imageParamsR[G_FREECIRCBUF];
00831 
00832   if (!fn) f=stdout;
00833   else if (strcmp(fn, "stdout")==0) f=stdout;
00834   else if (strcmp(fn, "stderr")==0) f=stderr;
00835   else {
00836     if (!((f=fopen (fn,"w")))) {
00837        D0(fprintf (debug_file,"Error opening %s\n", fn));
00838       return;
00839     }
00840   }
00841   if      (state->vf)       _len=ftell(state->vf); 
00842   else if ((state->ivf)>=0) _len=lseek(state->ivf, 0, SEEK_CUR); 
00843   _dur= state->this_frame_params.timestamp_sec-state->frame_params.timestamp_sec;
00844   _udur=state->this_frame_params.timestamp_usec-state->frame_params.timestamp_usec;
00845   if (_udur<0) {
00846     _dur-=1;
00847     _udur+=1000000;
00848   } else if (_udur>=1000000) {
00849     _dur+=1;
00850     _udur-=1000000;
00851   }
00852   _state=         state->running? "running":(state->starting?"starting":"stopped");
00853   _output_format= state->format?((state->format==CAMOGM_FORMAT_OGM)?"ogm":
00854                                              ((state->format==CAMOGM_FORMAT_JPEG)?"jpeg":
00855                                              ((state->format==CAMOGM_FORMAT_MOV)?"mov":
00856                                               "other"))):"none";
00857   _using_exif=    state->exif?"yes":"no";
00858   _using_global_pointer=state->save_gp?"yes":"no";
00860 #if 0
00861   _compressor_state=(imageParamsR[P_CAMSEQSTATE]==CAMSEQ_RUN)?"running":
00862                      ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_SINGLE)?"acquiring":
00863                       ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_STOP)?"stoppping":
00864                        ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_JPEG)?"stopped":
00865                         ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_OFF)?"reset":"other"))));
00866 #endif
00867     if ( state->frames_skip >0 ) {
00868       _frames_remain= state->frames_skip_left;
00869       _frames_skip=state->frames_skip;
00870     } else if ( state->frames_skip <0 ) {
00871       _sec_remain= (state->frames_skip_left - state->this_frame_params.timestamp_sec);
00872       _sec_skip=-(state->frames_skip);
00873     }
00874 
00875 
00876   if (xml) {
00877     fprintf (f,"<?xml version=\"1.0\"?>\n" \
00878              "<camogm_state>\n" \
00879              "  <state>\"%s\"</state>\n" \
00880              "  <compressor_state>\"%s\"</compressor_state>\n" \
00881              "  <file_name>\"%s\"</file_name>\n" \
00882              "  <frame_number>%d</frame_number>\n" \
00883              "  <file_duration>%d.%06d</file_duration>\n" \
00884              "  <file_length>%d</file_length>\n" \
00885              "  <frame_period>%d</frame_period>\n" \
00886              "  <frames_skip>%d</frames_skip>\n" \
00887              "  <seconds_skip>%d</seconds_skip>\n" \
00888              "  <frames_skip_left>%d</frames_skip_left>\n" \
00889              "  <seconds_skip_left>%d</seconds_skip_left>\n" \
00890              "  <frame_width>%d</frame_width>\n" \
00891              "  <frame_height>%d</frame_height>\n" \
00892              "  <format>\"%s\"</format>\n" \
00893              "  <exif>\"%s\"</exif>\n" \
00894              "  <prefix>\"%s\"</prefix>\n" \
00895              "  <max_duration>%d</max_duration>\n" \
00896              "  <max_length>%d</max_length>\n" \
00897              "  <max_frames>%d</max_frames>\n" \
00898              "  <timescale>%f</timescale>\n" \
00899              "  <frames_per_chunk>%d</frames_per_chunk>\n" \
00900              "  <buffer_overruns>%d</buffer_overruns>\n" \
00901              "  <buffer_minimal>%d</buffer_minimal>\n" \
00902              "  <buffer_free>%d</buffer_free>\n" \
00903              "  <buffer_used>%d</buffer_used>\n" \
00904              "  <circbuf_rp>%d</circbuf_rp>\n" \
00905              "  <debug_output>\"%s\"</debug_output>\n" \
00906              "  <debug_level>%d</debug_level>\n" \
00907              "  <use_global_rp>\"%s\"</use_global_rp>\n" \
00908              "  <kml_enable>\"%s\"</kml_enable>\n" \
00909              "  <kml_used>\"%s\"</kml_used>\n" \
00910              "  <kml_path>\"%s\"</kml_path>\n" \
00911              "  <kml_horHalfFov>\"%f\"</kml_horHalfFov>\n" \
00912              "  <kml_vertHalfFov>\"%f\"</kml_vertHalfFov>\n" \
00913              "  <kml_near>\"%f\"</kml_near>\n" \
00914              "  <kml_height_mode>\"%s\"</kml_height_mode>\n" \
00915              "  <kml_height>\"%f\"</kml_height>\n" \
00916              "  <kml_period>%d</kml_period>\n" \
00917              "  <kml_last_ts>%d.%06d</kml_last_ts>\n" \
00918              "</camogm_state>\n",
00919              _state,_compressor_state,state->path,state->frameno,_dur,_udur,_len,state->frame_period, \
00920              _frames_skip,_sec_skip,_frames_remain, _sec_remain, \
00921              state->width,state->height,_output_format,_using_exif, \
00922              state->path_prefix, state->segment_duration, state->segment_length, state->max_frames, state->timescale, \
00923              state->frames_per_chunk, state->buf_overruns, state->buf_min, _b_free, _b_used, state->cirbuf_rp, \
00924              state->debug_name, debug_level, _using_global_pointer, \
00925              _kml_enable,_kml_used,state->kml_path,state->kml_horHalfFov,state->kml_vertHalfFov,state->kml_near,\
00926              _kml_height_mode,state->kml_height,state->kml_period,state->kml_last_ts,state->kml_last_uts);
00927   } else {
00928     fprintf (f,"state              %s\n",        _state);
00929     fprintf (f,"compressor state   %s\n",        _compressor_state);
00930     fprintf (f,"file               %s\n",        state->path);
00931     fprintf (f,"frame              %d\n",        state->frameno);
00932     fprintf (f,"file duration      %d.%06d sec\n",_dur,_udur);
00933     fprintf (f,"file length        %d B\n",      _len);
00934     fprintf (f,"frame period       %d (0x%x)\n", state->frame_period,state->frame_period);
00935     if ( _frames_skip >0 ) fprintf (f,"frames to skip   %d (left %d)\n",_frames_skip, _frames_remain);
00936     if ( _sec_skip    <0 ) fprintf (f,"timelapse period  %d sec (remaining %d sec)\n", _sec_skip, _sec_remain);
00937     fprintf (f,"width              %d (0x%x)\n", state->width,state->width);
00938     fprintf (f,"height             %d (0x%x)\n", state->height,state->height);
00939     fprintf (f,"\n");
00940     fprintf (f,"output format      %s\n",        _output_format);
00941     fprintf (f,"using exif         %s\n",        _using_exif);
00942     fprintf (f,"path prefix:       %s\n",        state->path_prefix);
00943     fprintf (f,"max file duration: %d sec\n",    state->segment_duration);
00944     fprintf (f,"max file length:   %d B\n",      state->segment_length);
00945     fprintf (f,"max frames         %d\n",        state->max_frames);
00946     fprintf (f,"timescale          %f\n",        state->timescale);
00947     fprintf (f,"frames per chunk   %d\n",        state->frames_per_chunk);
00948     fprintf (f,"\n");
00949     fprintf (f,"buffer overruns    %d\n",        state->buf_overruns);
00950     fprintf (f,"buffer minimal     %d\n",        state->buf_min);
00951     fprintf (f,"buffer free        %d\n",        _b_free);
00952     fprintf (f,"buffer used        %d\n",        _b_used);
00953     fprintf (f,"circbuf_rp         %d (0x%x)\n", state->cirbuf_rp,state->cirbuf_rp);
00954     fprintf (f,"\n");
00955     fprintf (f,"debug output to    %s\n",        state->debug_name);
00956     fprintf (f,"debug level        %d\n",        debug_level);
00957     fprintf (f,"use global pointer %s\n",        _using_global_pointer);
00958     fprintf (f,"\n\n");
00959     fprintf (f,"kml_enable         %s\n",        _kml_enable);
00960     fprintf (f,"kml_used           %s\n",        _kml_used);
00961     fprintf (f,"kml_path           %s\n",        state->kml_path);
00962     fprintf (f,"kml_horHalfFov     %f degrees\n",state->kml_horHalfFov);
00963     fprintf (f,"kml_vertHalfFov    %f degrees\n",state->kml_vertHalfFov);
00964     fprintf (f,"kml_near           %f m\n",      state->kml_near);
00965     fprintf (f,"kml height mode    %s\n",        _kml_height_mode);
00966     fprintf (f,"kml_height (extra) %f m\n",      state->kml_height);
00967     fprintf (f,"kml_period         %d\n",        state->kml_period);
00968     fprintf (f,"kml_last_ts        %d.%06d\n",   state->kml_last_ts,state->kml_last_uts);
00969     fprintf (f,"\n\n");
00970 
00971   }
00972   if ((f!=stdout) && (f!=stderr)) fclose (f);
00973   if (state->buf_overruns>=0) state->buf_overruns=0; 
00974   state->buf_min=_b_free;
00975 }
00976 
00978 char * getLineFromPipe(FILE* npipe) {
00979       int fl;
00980       char * nlp;
00982       if (cmdstrt > 0) {
00984         memmove(cmdbuf, &cmdbuf[cmdstrt], sizeof(cmdbuf)- cmdstrt);
00985         cmdbufp-=cmdstrt;
00986         cmdstrt=0;
00987       }
00989       if (!cmdbufp) cmdbuf[cmdbufp]=0; 
00990 //      nlp= strchr(cmdbuf,'\n');
00991       nlp= strpbrk(cmdbuf,";\n");
00992       if (!nlp) { 
00993         fl=fread(&cmdbuf[cmdbufp], 1,sizeof(cmdbuf)-cmdbufp-1,npipe);
00994         cmdbuf[cmdbufp+fl]=0;
00996 //        nlp= strchr(&cmdbuf[cmdbufp],'\n'); //! there were no new lines before cmdbufp
00997         nlp= strpbrk(&cmdbuf[cmdbufp],";\n"); 
00998         cmdbufp+=fl; 
00999       }
01000       if (nlp) {
01001 //printf ("++nlp=%d\n", (int) (nlp-cmdbuf));
01002         nlp[0]=0;
01003         cmdstrt=nlp-cmdbuf+1;
01004 //printf ("++cmdstrt=%d\n", cmdstrt);
01005 //printf ("cmdbuf[0]=%d, cmdbuf[1]=%d, cmdbuf[2]=%d, cmdbuf[3]=%d, \n",cmdbuf[0],cmdbuf[1],cmdbuf[2],cmdbuf[3]);
01006         for (fl=0; cmdbuf[fl] && strchr(" \t",cmdbuf[fl]); fl++);
01007 //printf ("++fl=%d\n", fl);
01008         return &cmdbuf[fl];
01009       } else {
01010 //printf ("notready: cmdbufp=%d, cmdstrt=%d\n",cmdbufp, cmdstrt);
01011           return NULL;
01012       }
01013 }
01014 // command[= \t]*args[ \t]*
01015 int parse_cmd(FILE* npipe) {
01016   char * cmd;
01017   char * args;
01018   char * argse;
01019   int d;
01020   double dd;
01021 //  if (!((cmd=getLineFromPipe(npipe)))) return 0; //! nothing in the pipe
01023   while(((cmd=getLineFromPipe(npipe))) && !cmd[0]) ;
01024   if (!cmd) return 0; 
01025 //  printf ("cmd[0]=%d:%s\n",(int) cmd[0],cmd);
01026   args=strpbrk(cmd,"= \t");
01028   if (args) {
01029     args[0]=0;
01030     args++;
01031     while (strchr("= \t",args[0])) args++;
01032     if (args[0]) {
01034       for (argse=strchr(args,'\0')-1; strchr("= \t",argse[0]);argse--) argse[0]='\0';
01035     }
01036     if (!args[0]) args=NULL;
01037   }
01039   if      (strcmp(cmd, "start")==0) {
01040      camogm_start(1);
01041      return 1;
01042   } else if (strcmp(cmd, "reset")==0) { 
01043      camogm_reset();
01044      return 2;
01045   } else if (strcmp(cmd, "stop")==0) {
01046      camogm_stop(1);
01047      return 3;
01048   } else if (strcmp(cmd, "exit")==0) { 
01049      camogm_stop(1);
01050      camogm_free();
01051      exit (0);
01052   } else if (strcmp(cmd, "duration")==0) {
01053      if (!(args) || (((d= strtol(args, NULL, 10)))<=0)) d=DEFAULT_DURATION;
01054      camogm_set_segment_duration(d);
01055      return 4;
01056   } else if (strcmp(cmd, "length")==0) {
01057      if (!(args) || (((d= strtol(args, NULL, 10)))<=0)) d=DEFAULT_LENGTH;
01058      camogm_set_segment_length(d);
01059      return 5;
01060   } else if (strcmp(cmd, "prefix")==0) {
01061      if (args) camogm_set_prefix (args);
01062      return 6;
01063   } else if (strcmp(cmd, "status")==0) { 
01064      camogm_status(args, 0);
01065      return 7;
01066   } else if (strcmp(cmd, "xstatus")==0) { 
01067      camogm_status(args, 1);
01068      return 7;
01069   } else if (strcmp(cmd, "save_gp")==0) {
01070      if ((args) && (((d= strtol(args, NULL, 10)))>=0)) camogm_set_save_gp(d);
01071      return 8;
01072   } else if (strcmp(cmd, "exif")==0) {
01073      if ((args) && (((d= strtol(args, NULL, 10)))>=0)) camogm_set_exif(d);
01074      return 8;
01075   } else if (strcmp(cmd, "debug")==0) {
01076      camogm_debug(args);
01077      return 9;
01078   } else if (strcmp(cmd, "timescale")==0) {
01079      dd= strtod(args,NULL);
01080      camogm_set_timescale(dd?dd:1.0);
01081      return 10;
01084 
01085 
01086   } else if (strcmp(cmd, "frameskip")==0) {
01087      d= strtol(args, NULL, 10);
01088      camogm_set_frames_skip(d);
01089      return 11;
01090   } else if (strcmp(cmd, "timelapse")==0) { 
01091      d= strtol(args, NULL, 10);
01092      camogm_set_frames_skip(-d);
01093      return 11;
01094   } else if (strcmp(cmd, "format")==0) {
01095      if (args) {
01096       if      (strcmp(args,  "none")==0) camogm_set_format(0);
01097       else if ((strcmp(args, "ogm" )==0) || (strcmp(args, "ogg")==0)) camogm_set_format(CAMOGM_FORMAT_OGM);
01098       else if ((strcmp(args, "jpeg")==0) || (strcmp(args, "jpg")==0)) camogm_set_format(CAMOGM_FORMAT_JPEG);
01099       else if (strcmp(args,  "mov" )==0)                              camogm_set_format(CAMOGM_FORMAT_MOV);
01100      }
01101      return 12;
01102   } else if (strcmp(cmd, "debuglev")==0) {
01103      d= strtol(args, NULL, 10);
01104      camogm_debug_level(d?d:0);
01105      return 13;
01106   } else if (strcmp(cmd, "kml")==0) {
01107      if ((args) && (((d= strtol(args, NULL, 10)))>=0)) camogm_kml_set_enable(d);
01108      return 14;
01109   } else if (strcmp(cmd, "kml_hhf")==0) {
01110      dd= strtod(args,NULL);
01111      camogm_kml_set_horHalfFov(dd);
01112      return 15;
01113   } else if (strcmp(cmd, "kml_vhf")==0) {
01114      dd= strtod(args,NULL);
01115      camogm_kml_set_vertHalfFov(dd);
01116      return 16;
01117   } else if (strcmp(cmd, "kml_near")==0) {
01118      dd= strtod(args,NULL);
01119      camogm_kml_set_near(dd);
01120      return 17;
01121   } else if (strcmp(cmd, "kml_alt")==0) {
01122      if (args) {
01123       if      (strcmp(args, "gps"   )==0) camogm_kml_set_height_mode(1);
01124       else if (strcmp(args, "ground")==0) camogm_kml_set_height_mode(0);
01125      }
01126      return 18;
01127   } else if (strcmp(cmd, "kml_height")==0) {
01128      dd= strtod(args,NULL);
01129      camogm_kml_set_height(dd);
01130      return 19;
01131   } else if (strcmp(cmd, "kml_period")==0) {
01132      d= strtol(args, NULL, 10);
01133      camogm_kml_set_period(d?d:1);
01134      return 20;
01135   } else if (strcmp(cmd, "audio")==0) {
01136      if (args) {
01137                 camogm_set_audio_state(args);
01138      }
01139      return 21;
01140   } else if (strcmp(cmd, "audio_format")==0) {
01141      if (args) {
01142                 camogm_set_audio_format(args);
01143      }
01144      return 22;
01145   } else if (strcmp(cmd, "allow_sync")==0) {
01146      if (args) {
01147                 camogm_set_sync_state(args);
01148      }
01149      return 23;
01150   }
01151 
01152   return -1;
01153 }
01154 
01155 int main(int argc, char *argv[])
01156 {
01157    const char circbufFileName[]="/dev/circbuf";
01158 //     int fd_circ;
01159    FILE * cmd_file;
01160    const char usage[]=   "This program allows recording of the video/images acquired by Elphel camera to the storage media.\n" \
01161                          "It is designed to run in the background and accept commands through a named pipe.\n\n" \
01162                          "Usage:\n\n" \
01163                          "%s <named_pipe_name>\n\n" \
01164                          "i.e.:\n\n" \
01165                          "%s /var/state/camogm_cmd\n\n" \
01166                          "When the program is runninig you may send commands by writing strings to the command file\n" \
01167                          "(/var/state/camogm_cmd in the example above). The complete list of available commands is available\n" \
01168                          "on Elphel Wiki (http://wiki.elphel.com/index.php?title=Camogm), here is the example of usage\n" \
01169                          "from the shell prompt in the camera:\n\n" \
01170                          "echo \"status; exif=1; format=jpeg;status=/var/tmp/camogm.status\" > /var/state/camogm_cmd\n\n" \
01171                          "That will print status information on the standard output (may not be visible if the program was not\n" \
01172                          "started from the same session), set exif mode on (each frame will have the full Exif header including\n" \
01173                          "a precise time stamp), set output format to a series of individual JPEG files, and then send status\n" \
01174                          "information to a file /var/tmp/camogm.status in the camera file system.\n\n" \
01175                          "This program does not control the process of acquisition of the video/images to the camera internal\n" \
01176                          "buffer, it only retrieves that data from the buffer (waiting when needed), packages it to selected\n" \
01177                          "format and stores the result files.\n\n";
01178    int go=1;
01179    int cmd;
01180    int i,rslt;
01181    state= &sstate; //extern
01183    if ((argc < 2) || (argv[1][1]=='-'))  { 
01184      printf (usage,argv[0],argv[0]);
01185      return 0;
01186    }
01187    camogm_init();
01188 
01190    state->fd_exif = open(ExifFileName, O_RDONLY);
01191    if (state->fd_exif<0) { // check control OK
01192      D0(fprintf (debug_file,"Error opening %s\n", ExifFileName));
01193      return -1;
01194    }
01195 
01197    state->fd_head = open(HeadFileName, O_RDWR);
01198    if (state->fd_head<0) { // check control OK
01199      D0(fprintf (debug_file,"Error opening %s\n", HeadFileName));
01200      return -1;
01201    }
01202    state->head_size=lseek(state->fd_head,0,SEEK_END);
01203    if (state->head_size>JPEG_HEADER_SIZE) {
01204      D0(fprintf (debug_file,"%s:%d: Too big JPEG header (%d > %d)",__FILE__,__LINE__,state->head_size, JPEG_HEADER_SIZE ));
01205      return -2;
01206    }
01207 
01209    state->fd_circ = open(circbufFileName, O_RDWR);
01210    if (state->fd_circ<0) { // check control OK
01211       D0(fprintf (debug_file,"Error opening %s\n", circbufFileName));
01212       return -2;
01213    }
01215    state->circ_buff_size=lseek(state->fd_circ,0,SEEK_END);
01216    ccam_dma_buf = (unsigned long *) mmap(0, state->circ_buff_size, PROT_READ, MAP_SHARED, state->fd_circ, 0);
01217    if((int)ccam_dma_buf == -1) {
01218      D0(fprintf (debug_file,"Error in mmap of %s\n",circbufFileName));
01219 //     close (fd_head);
01220      close(state->fd_circ);
01221      return -3;
01222    }
01223 
01225 
01227    state->fd_sens = open(SensParsFileName, O_RDWR);
01228    if (state->fd_sens<0) { // check control OK
01229       D0(fprintf (debug_file,"Error opening %s\n", SensParsFileName));
01230       return -2;
01231    }
01233    state->senspars_size=lseek(state->fd_sens,0,SEEK_END);
01234    imageParamsR = (unsigned long *) mmap(0, state->senspars_size, PROT_READ, MAP_SHARED, state->fd_sens, 0);
01235    if((int)imageParamsR == -1) {
01236      D0(fprintf (debug_file,"Error in mmap of %s\n",SensParsFileName));
01237      close(state->fd_sens);
01238      close(state->fd_circ);
01239      return -3;
01240    }
01241 
01242 
01243 
01246    i=unlink (argv[1]);
01247    if (i) {
01248        D1(fprintf (debug_file,"Unlink %s returned %d, errno=%d \n", argv[1], i, errno));
01249    }
01250    i=mkfifo(argv[1], 0777); //EEXIST
01252    if (i) {
01253     if (errno==EEXIST) {
01254        D1(fprintf (debug_file,"Named pipe %s already exists, will use it.\n", argv[1]));
01255     } else {
01256        D0(fprintf (debug_file,"Can not create a named pipe %s, errno=%d \n", argv[1], errno));
01257        return -4;
01258     }
01259    }
01260 
01263    if (!((cmd_file=fopen(argv[1],"r")))) {
01264      D0(fprintf (debug_file,"Can not open command file %s\n",argv[1]));
01265      return -5;
01266    }
01267    D1(fprintf (debug_file,"Pipe %s open for reading\n",argv[1]));
01268 
01270 #define COMMAND_LOOP_DELAY 500000 //0.5sec
01271  
01272         while(go) {
01273 //              D3(fprintf (debug_file,"%s:%d: format=%d, set_format=%d\n",__FILE__,__LINE__, state->format, state->set_format));
01275                 cmd = parse_cmd(cmd_file);
01276                 if(cmd) {
01277                         if(cmd < 0)
01278                                 D0(fprintf(debug_file,"Unrecognized command\n"));
01279                 } else {
01280                         if(state->running) {
01281                                 // process audio, if needed (really, check presence at this function)
01282                                 audio_process();
01283 
01284                                 // no commands in queue, started 
01285 //                              D3(fprintf (debug_file,"%s:%d: format=%d, set_format=%d\n",__FILE__,__LINE__, state->format, state->set_format));
01286                                 switch((rslt = -sendImageFrame())) {
01287                                 case 0:
01288 /*
01289                                         D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned %d\n" \
01290                                                 "state->cirbuf_rp= 0x%x\n",__FILE__,__LINE__,rslt,state->cirbuf_rp));
01291 */
01292                                         break; 
01293                                 case CAMOGM_FRAME_NOT_READY:        
01294 
01295 
01296 //     D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned -%d\n",__FILE__,__LINE__,rslt));
01297 /*
01298      D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned -%d\n" \
01299                                   "state->cirbuf_rp= 0x%x\n",__FILE__,__LINE__,rslt,state->cirbuf_rp));
01300 */
01301                                         lseek(state->fd_circ,LSEEK_CIRC_WAIT,SEEK_END);
01302                                         break;
01303                                 case CAMOGM_FRAME_CHANGED:   
01304                                 case CAMOGM_FRAME_NEXTFILE:  
01305                                 case CAMOGM_FRAME_INVALID:   
01306                                 case CAMOGM_FRAME_BROKEN:    
01307 
01308 //     D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned -%d\n",__FILE__,__LINE__,rslt));
01309                                         camogm_stop(0);
01310                                         camogm_start(0);
01311                                         break;
01312                                 case CAMOGM_FRAME_FILE_ERR:  
01313                                 case CAMOGM_FRAME_OTHER:     
01314                                         D0(fprintf (debug_file,"%s:line %d - error=%d\n",__FILE__,__LINE__,rslt));
01315                                         break;
01316                                 default:
01317                                         D0(fprintf (debug_file,"%s:line %d - should not get here (rslt=%d)\n",__FILE__,__LINE__,rslt));
01318                                         exit (-1);
01319                                 } //switch
01320                         } else {
01321                                 if(state->starting) { 
01322 //   D3(fprintf (debug_file,"%s:%d: format=%d, set_format=%d\n",__FILE__,__LINE__, state->format, state->set_format));
01323 
01325                                         switch ((rslt = -camogm_start(1))) {
01326                                         case 0:
01327                                                 break; 
01328                                         case CAMOGM_FRAME_NOT_READY:        
01329 
01330 
01331 //                lseek(state->fd_circ,LSEEK_CIRC_WAIT,SEEK_END);
01332                                         case CAMOGM_FRAME_CHANGED:   
01333                                         case CAMOGM_FRAME_NEXTFILE:
01334                                         case CAMOGM_FRAME_INVALID:   
01335                                         case CAMOGM_FRAME_BROKEN:    
01336 //     D3(fprintf (debug_file,"%s:line %d - camogm_start() returned -%d,  state->cirbuf_rp= 0x%x\n", __FILE__,__LINE__,rslt,state->cirbuf_rp));
01337                                                 usleep( COMMAND_LOOP_DELAY) ; 
01338                                                 break;
01339                                         case CAMOGM_FRAME_FILE_ERR:  
01340                                         case CAMOGM_FRAME_OTHER:     
01341                                                 D0(fprintf (debug_file,"%s:line %d - error=%d\n",__FILE__,__LINE__,rslt));
01342                                                 break;
01343                                         default:
01344                                                 D0(fprintf (debug_file,"%s:line %d - should not get here (rslt=%d)\n",__FILE__,__LINE__,rslt));
01345                                                 exit (-1);
01346                                         } //switch
01347                                 } else { 
01348                                         usleep( COMMAND_LOOP_DELAY) ; 
01349                                 }
01350                         }
01351                 }
01352         }
01353         return 0;
01354 }
01355 
01356 /*
01357  *
01358  * audio
01359  *
01360  */
01361 
01362 void camogm_set_audio_state(char *args) {
01363         if(strcmp(args, "on") == 0 || strcmp(args, "enable") == 0) {
01364                 state->audio_enable = 1;
01365         }
01366         if(strcmp(args, "off") == 0 || strcmp(args, "disable") == 0) {
01367                 state->audio_enable = 0;
01368         }
01369         fprintf(stderr, "request for audio state: %s\n", args);
01370 }
01371 
01372 void camogm_set_sync_state(char *args) {
01373         if(strcmp(args, "on") == 0 || strcmp(args, "enable") == 0) {
01374                 state->allow_sync = 1;
01375         }
01376         if(strcmp(args, "off") == 0 || strcmp(args, "disable") == 0) {
01377                 state->allow_sync = 0;
01378         }
01379 }
01380 
01381 void camogm_set_audio_format(char *args) {
01382         char buf[8];
01383         int i;
01384         int channels = -1;
01385         int rate = -1;
01386         char *right = strstr(args, "/");
01387         if(right != NULL) {
01388                 channels = atol(&right[1]);
01389                 if(channels < AUDIO_CHANNELS_MIN)
01390                         channels = AUDIO_CHANNELS_MIN;
01391                 if(channels > AUDIO_CHANNELS_MAX)
01392                         channels = AUDIO_CHANNELS_MAX;
01393                 state->audio_channels = channels;
01394         }
01395         for(i = 0; i < 7; i++) {
01396                 if(args[i] != '\0' && args[i] != '/')
01397                         buf[i] = args[i];
01398                 else
01399                         break;
01400         }
01401         buf[i] = '\0';
01402         if(buf[0] != '\0') {
01403                 rate = atol(buf);
01404                 if(rate < AUDIO_RATE_MIN)
01405                         rate = AUDIO_RATE_MIN;
01406                 if(rate > AUDIO_RATE_MAX)
01407                         rate = AUDIO_RATE_MAX;
01408                 state->audio_rate = rate;
01409         }
01410 
01411         fprintf(stderr, "request for audio format: %s; after apply: rate == %d; channels == %d\n", args, state->audio_rate, state->audio_channels);
01412 }
01413 
01414 #define SBUFFER_PREFIX  16
01415 int audio_set = 0;
01416 int audio_present = 0;
01417 snd_pcm_t *capture_handle = NULL;
01418 char *sbuffer = NULL;
01419 long sbuffer_len = 0;
01420 long sample_time = 100; // ms
01421 //long sample_time = 10; // ms
01422 
01423 void audio_process(void) {
01424         if(audio_present == 0)
01425                 return;
01426         if(state->format != CAMOGM_FORMAT_OGM) {
01427                 int slen;
01428                 int _len = 0;
01429                 while((slen = snd_pcm_readi(capture_handle, sbuffer, sbuffer_len)) > 0) {
01430                         wave_push((void *)sbuffer, slen * 2 * state->audio_channels);
01431                         _len += slen;
01432                 }
01433 fprintf(stderr, "process == %d bytes, request == %d bytes\n", _len, sbuffer_len);
01434         }
01435         if(state->format == CAMOGM_FORMAT_OGM) {
01436                 int slen;
01437                 int _len = 0;
01438                 snd_pcm_status_t *status;
01439                 snd_pcm_status_alloca(&status);
01440                 snd_timestamp_t ts;
01441                 for(;;) {
01442                         long avail = 0;
01443                         avail = snd_pcm_avail_update(capture_handle);
01444                         snd_pcm_status(capture_handle, status);
01445                         snd_pcm_status_get_tstamp(status, &ts);
01446 //                      avail = snd_pcm_status_get_avail_max(status);
01447 //                      int av = snd_pcm_status_get_avail(status);
01448                         if(avail >= sbuffer_len) {// || a == 0) {
01449                                 slen = snd_pcm_mmap_readi(capture_handle, (void *)(sbuffer + SBUFFER_PREFIX), sbuffer_len);
01450 //fprintf(stderr, "avail == %d, wait for == %d; slen == %d; time == %d:%06d\n", avail, sbuffer_len, slen, ts.tv_sec, (unsigned)ts.tv_usec);
01451                                 if(slen > 0)
01452                                         camogm_audio_ogm_push((void *)(sbuffer + SBUFFER_PREFIX), slen * 2 * state->audio_channels, slen, SBUFFER_PREFIX);
01453                         } else {
01454 //fprintf(stderr, "avail == %d, skip it; time == %d:%06d\n", avail, ts.tv_sec, (unsigned)ts.tv_usec);
01455                                 break;
01456                         }
01457                 }
01458         }
01459 }
01460 
01461 void audio_init(by_command) {
01462         int slen;
01463         if(state->audio_enable == 0) {
01464                 return;
01465         }
01466         // set up audio device
01467         if(by_command && !audio_set) {
01468                 snd_pcm_hw_params_t *hw_params;
01469                 audio_set = 1;
01470 //              sbuffer_len = state->audio_rate * 2 * state->audio_channels * sample_time;
01471                 sbuffer_len = state->audio_rate * state->audio_channels * sample_time;
01472                 sbuffer_len /= 1000;
01473                 sbuffer_len -= sbuffer_len % 2;
01474 
01475                 state->audio_format = SND_PCM_FORMAT_S16_LE;
01476 
01477                 int err;
01478                 sbuffer = (void *)malloc(sbuffer_len * 8 + SBUFFER_PREFIX);
01479                 if((err = snd_pcm_open(&capture_handle, "default", SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0)
01480                         return;
01481                 if((err = snd_pcm_hw_params_malloc(&hw_params)) < 0)
01482                         return;
01483                 if((err = snd_pcm_hw_params_any(capture_handle, hw_params)) < 0)
01484                         return;
01485                 snd_pcm_access_mask_t *mask = alloca(snd_pcm_access_mask_sizeof());
01486                 snd_pcm_access_mask_none(mask);
01487                 snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
01488                 if((err = snd_pcm_hw_params_set_access_mask(capture_handle, hw_params, mask)) < 0)
01489                         return;
01490                 if((err = snd_pcm_hw_params_set_format(capture_handle, hw_params, state->audio_format)) < 0)
01491                         return;
01492                 unsigned int t = state->audio_rate;
01493                 if((err = snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, &t, 0)) < 0)
01494                         return;
01495                 state->audio_rate = t;
01496                 if((err = snd_pcm_hw_params_set_channels(capture_handle, hw_params, state->audio_channels)) < 0)
01497                         return;
01498                 if((err = snd_pcm_hw_params(capture_handle, hw_params)) < 0)
01499                         return;
01500                 snd_pcm_uframes_t buffer_time = 2000000;
01501                 if((err = snd_pcm_hw_params_set_buffer_time_near(capture_handle, hw_params, &buffer_time, 0)) < 0)
01502                         return;
01503 fprintf(stderr, "buffer_time is == %d\n", buffer_time);
01504 
01505                 snd_pcm_sw_params_t *sw_params;
01506                 snd_pcm_sw_params_malloc(&sw_params);
01507                 err = snd_pcm_sw_params_current(capture_handle, sw_params);
01508                 if(err < 0)     return;
01509                 err = snd_pcm_sw_params_set_tstamp_mode(capture_handle, sw_params, SND_PCM_TSTAMP_MMAP);
01510                 if(err < 0)     return;
01511                 err = snd_pcm_sw_params(capture_handle, sw_params);
01512                 if(err < 0)     return;
01513 //              snd_pcm_sw_params_set_tstamp_mode(capture_handle, , SND_PCM_TSTAMP_MMAP)
01514                 snd_pcm_sw_params_free(sw_params);
01515                 
01516 //              snd_pcm_sw_params_set_tstamp_mode(capture_handle, , SND_PCM_TSTAMP_MMAP)
01517 
01518                 snd_pcm_access_mask_free(mask);
01519                 snd_pcm_hw_params_free(hw_params);
01520                 if((err = snd_pcm_prepare(capture_handle)) < 0)
01521                         return;
01522 
01523 //              snd_pcm_start(capture_handle);
01524 
01525                 audio_present = 1;
01526                 fprintf(stderr, "audio_init(%d)... OK\n", by_command);
01527 //              slen = snd_pcm_mmap_readi(capture_handle, (void *)(sbuffer + SBUFFER_PREFIX), sbuffer_len);
01528                 while((slen = snd_pcm_mmap_readi(capture_handle, (void *)(sbuffer), 2)) < 0)
01529                         snd_pcm_prepare(capture_handle);
01530 fprintf(stderr, "audio: device is open...   !!!!!!!!!!!!!!!!!!!; slen == %d\n", slen);
01531         }
01532 struct timeval tv;
01533 gettimeofday(&tv, NULL);
01534         fprintf(stderr, "audio_init(%d) - at %d:%06d\n", by_command, tv.tv_sec, (unsigned)tv.tv_usec);
01535 //      fprintf(stderr, "audio_init(%d)\n", by_command);
01536 }
01537 
01538 void audio_start(int by_command) {
01539         if(state->format != CAMOGM_FORMAT_OGM) {
01540                 if(audio_present) {
01541                         char fname[256];
01542                         sprintf(fname, "%s_01.wav", state->path_prefix);
01543                         // open WAV file...
01544                         fprintf(stderr, "open WAV file, name == \"%s\"\n", fname);
01545                         wave_begin(fname);
01546 //                      begin_wave(audio_fd, );
01547                 }
01548         }
01549 struct timeval tv;
01550 gettimeofday(&tv, NULL);
01551         fprintf(stderr, "audio_start(%d) - at %d:%06d\n", by_command, tv.tv_sec, (unsigned)tv.tv_usec);
01552 }
01553 
01554 void audio_end(int by_command) {
01555         if(audio_present) {
01556                 if(state->format != CAMOGM_FORMAT_OGM) {
01557                         // close WAV file...
01558                         fprintf(stderr, "close WAV file\n");
01559                         wave_end();
01560                 }
01561         }
01562         // set down audio device
01563         if(by_command && audio_set) {
01564                 audio_present = 0;
01565                 audio_set = 0;
01566                 snd_pcm_close(capture_handle);
01567 fprintf(stderr, "audio: device is closed... !!!!!!!!!!!!!!!!!!!\n");
01568                 free((void *)sbuffer);
01569                 sbuffer = NULL;
01570         }
01571 //      fprintf(stderr, "audio_end(%d)\n", by_command);
01572 struct timeval tv;
01573 gettimeofday(&tv, NULL);
01574         fprintf(stderr, "audio_end(%d) - at %d:%06d\n", by_command, tv.tv_sec, (unsigned)tv.tv_usec);
01575 }
01576 
01577 void audio_free(void) {
01578         fprintf(stderr, "audio_free()\n");
01579 }

Generated on Fri Nov 28 00:06:21 2008 for elphel by  doxygen 1.5.1