apps/camogm2/camogm_mov.c

Go to the documentation of this file.
00001 /*!***************************************************************************
00002 *! FILE NAME  : camogm_mov.c
00003 *! DESCRIPTION: Provides writing to file compatible with Apple Quicktime(R) for camogm
00004 *!TODO: Nothing yet here, will be added ASAP
00005 *! Copyright (C) 2007 Elphel, Inc.
00006 *! -----------------------------------------------------------------------------**
00007 *!  This program is free software: you can redistribute it and/or modify
00008 *!  it under the terms of the GNU General Public License as published by
00009 *!  the Free Software Foundation, either version 3 of the License, or
00010 *!  (at your option) any later version.
00011 *!
00012 *!  This program is distributed in the hope that it will be useful,
00013 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 *!  GNU General Public License for more details.
00016 *!
00017 *!  You should have received a copy of the GNU General Public License
00018 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 *! -----------------------------------------------------------------------------**
00020 *!
00021 *!  $Log: camogm_mov.c,v $
00022 *!  Revision 1.5  2008/06/06 10:53:32  spectr_rain
00023 *!  clean
00024 *!
00025 *!  Revision 1.4  2008/06/02 19:49:41  spectr_rain
00026 *!  fixed QuickTime compatibility - need to cleanup
00027 *!
00028 *!  Revision 1.2  2008/05/23 13:09:49  spectr_rain
00029 *!  QuickTime support
00030 *!
00031 *!  Revision 1.1  2008/05/02 12:45:58  spectr_rain
00032 *!  initial revision with the sound support
00033 *!
00034 *!  Revision 1.4  2008/04/11 23:09:33  elphel
00035 *!  modified to handle kml generation
00036 *!
00037 *!  Revision 1.3  2007/11/19 17:00:20  elphel
00038 *!  removed wrong dependency
00039 *!
00040 *!  Revision 1.2  2007/11/19 03:23:21  elphel
00041 *!  7.1.5.5 Added support for *.mov files in camogm.
00042 *!
00043 *!  Revision 1.1  2007/11/16 08:49:57  elphel
00044 *!  Initial release of camogm - program to record video/image to the camera hard drive (or other storage)
00045 *!
00046 */
00048 #include <unistd.h>
00049 #include <stdio.h>
00050 #include <stdlib.h>
00051 #include <signal.h>
00052 #include <fcntl.h>
00053 #include <sys/uio.h>
00054 #include <errno.h>
00055 #include <sys/types.h>
00056 #include <sys/socket.h>
00057 #include <sys/stat.h>
00058 //#include <ctype.h>
00059 //#include <getopt.h>
00060 #include <time.h>
00061 #include <string.h>
00062 
00063 #include <netinet/in.h> /*little <-> big endian ?*/
00064 #include <sys/mman.h>           /* mmap */
00065 #include <sys/ioctl.h>
00066 
00067 #include <asm/elphel/c313a.h>
00068 #include <asm/elphel/ext353.h>
00069 #include <asm/byteorder.h>
00070 
00071 
00072 #include <ogg/ogg.h> // has to be before ogmstreams.h
00073 #include "ogmstreams.h" // move it to <>?
00074 
00075 #include "camogm_mov.h"
00076 #include "camogm.h"
00077 
00078 #define QUICKTIME_MIN_HEADER 0x300 // Quicktime header length (w/o index tables) enough to accomodate 
00079                                    // static data .
00080 
00081 //#define D4(x) {x; fflush(debug_file);}
00082 //FILE *debug_file;
00083 
00085 const char hexStr[] = "0123456789abcdef";
00087 char qtSourceFileName_video[] = "/etc/qt_video";
00088 char qtSourceFileName_audio[] = "/etc/qt_audio";
00089 //*/
00090 char *qtSourceFileName = NULL;
00091 char comStr[1024];
00092 int     width = 1280;
00093 int height = 1024;
00094 int nframes = 100;
00095 int sample_dur = 80;
00096 int samplesPerChunk = 10;
00097 int     framesize = 80000;
00098 int     timescale = 600;
00099 int * sizes;    // array of frame sizes
00100 int iPos; 
00101 //int oPos; //!position in the string "oFile"
00102 int ofd; // output file descriptor (file opened by the caller)
00103 int iFileLen;
00104 char * q_template = NULL;
00105 long headerSize = 0;
00106 const char *iFile = NULL;
00107 
00108 unsigned long audio_rate = 0;
00109 unsigned short audio_channels = 0;
00110 int audio_timescale;
00111 long audio_duration;
00112 
00113 int quicktime_template_parser (const char * i_iFile, 
00114            int i_ofd,   
00115            int i_width, // width in pixels
00116            int i_height,
00117            int i_nframes,
00118            int i_sample_dur,
00119            int i_samplesPerChunk,
00120            int i_framesize,
00121            int i_timescale,
00122            int * i_sizes,
00123            int   data_start // put zero if the header is written before data (no gap)
00124          );
00125 void putBigEndian(unsigned long d, int l);
00126 int parse_special(void);
00127 int parse (int top);
00128 
00131 int camogm_init_mov(void) {
00132         FILE* qt_header;
00133         int size;
00134         qtSourceFileName = qtSourceFileName_video;
00135         if(ctx_a.audio_present) {
00136                 qtSourceFileName = qtSourceFileName_audio;
00137         }
00138         if((qt_header = fopen(qtSourceFileName, "r")) == NULL) {
00139                 D0(fprintf (debug_file,"Error opening Quicktime header template %s for reading\n", qtSourceFileName));
00140                 return -CAMOGM_FRAME_FILE_ERR;
00141         }
00142         fseek(qt_header, 0, SEEK_END);
00143         size = ftell(qt_header);
00144         if(!((q_template = malloc(size + 1)))) {
00145                 D0(fprintf (debug_file,"Could not allocate %d bytes of memory for Quicktime header template\n", (size+1)));
00146                 fclose(qt_header);
00147                 return -CAMOGM_FRAME_MALLOC ;
00148         }
00149         fseek(qt_header, 0, SEEK_SET); //rewind
00150         if(fread(q_template, size, 1, qt_header) < 1) {
00151                 D0(fprintf(debug_file, "Could not read %d bytes of Quicktime header template from %s\n", (size + 1), qtSourceFileName));
00152                 free(q_template);
00153                 q_template = NULL;
00154                 fclose(qt_header);
00155                 return -CAMOGM_FRAME_FILE_ERR;
00156         }
00157         q_template[size] = 0;
00158         return 0;
00159 }
00160 
00161 void camogm_free_mov(void) {
00162         if(q_template) {
00163                 free(q_template);
00164                 q_template = NULL;
00165         }
00166 }
00167 
00168 int camogm_start_mov(void) {
00169         state->frames_pos = 0;
00170 
00171         // allocate memory for the frame index table
00172 DA(fprintf(stderr, "max_frames == %d\n", state->max_frames););
00173         if(!((state->audio_samples_to_chunk = malloc(12 * 3))))
00174                 return -CAMOGM_FRAME_MALLOC;
00175         state->audio_samples_to_chunk[0] = -1;
00176         state->audio_samples_to_chunk[1] = -1;
00177         state->audio_samples_to_chunk[2] = -1;
00178 
00179         if(!((state->frames_len = (unsigned long *)malloc(4 * state->max_frames))))
00180                 return -CAMOGM_FRAME_MALLOC;
00181         state->offset_current = 0;
00182         // open file for writing
00183         sprintf(state->path, "%s%010ld_%06ld.mov", state->path_prefix, state->frame_params.timestamp_sec, state->frame_params.timestamp_usec);
00184         if(((state->ivf = open(state->path, O_RDWR | O_CREAT, 0777))) < 0){
00185                 D0(fprintf(debug_file, "Error opening %s for writing, returned %d, errno=%d\n", state->path, state->ivf, errno));
00186                 return -CAMOGM_FRAME_FILE_ERR;
00187         }
00188         // skip header (plus extra)
00189         // Quicktime (and else?) - frame data start (0xff 0xd8...) 
00190         int data_offset = QUICKTIME_MIN_HEADER + 16;
00191         data_offset += 4 * (state->max_frames); // space for sample size atom - video
00192         data_offset += 4 * (state->max_frames); // space for chunk offsets atom - video
00193         if(ctx_a.audio_present) {
00194                 data_offset += 4 * (state->max_frames); // space for chunk offsets atom - audio
00195                 data_offset += 12 * 3; // space for samples size atom - audio
00196         }
00197         // add audio tables space
00198 //      state->frame_data_start = QUICKTIME_MIN_HEADER + 16 + 4 * (state->max_frames) + (4 * (state->max_frames)) / (state->frames_per_chunk); // 8 bytes for "skip" tag
00199         state->frame_data_start = data_offset;
00200         lseek(state->ivf, state->frame_data_start, SEEK_SET);
00201         return 0;
00202 }
00203 
00204 int camogm_frame_mov(void) {
00205         int i, j;
00206         ssize_t iovlen, l;
00207         struct iovec chunks_iovec[7];
00208         l = 0;
00209         for(i = 0; i < state->chunk_index - 1; i++) {
00210                 chunks_iovec[i].iov_base = state->packetchunks[i + 1].chunk;
00211                 chunks_iovec[i].iov_len = state->packetchunks[i + 1].bytes;
00212                 l += chunks_iovec[i].iov_len;
00213         }
00214         iovlen = writev(state->ivf, chunks_iovec, state->chunk_index - 1);
00215         if(iovlen < l) {
00216                 fprintf(stderr, "MOV: fail to save frame...\n");
00217                 j = errno;
00218                 D0(fprintf(debug_file, "writev error %d (returned %d, expected %d)\n", j, iovlen, l));
00219                 close(state->ivf);
00220                 state->ivf = -1;
00221                 return -CAMOGM_FRAME_FILE_ERR;
00222         }
00223         state->frames_len[state->frames_pos] = l; // 0x00 mask for video
00224         state->frames_pos++;
00225 
00226         state->offset_current += l;
00227 
00228         if(state->frames_pos >= state->max_frames - 16)
00229                 return -CAMOGM_FRAME_FILE_ERR;
00230         // check here space ???
00231         return 0;
00232 }
00233 
00234 int camogm_audio_mov(void *buf, int len, int slen) {
00235 //return;
00236         int i, j;
00237         ssize_t wrlen;
00238         wrlen = write(state->ivf, buf, len);
00239         if(wrlen < len) {
00240                 j = errno;
00241                 D0(fprintf(debug_file, "writev error %d (returned %d, expected %d)\n", j, wrlen, len));
00242                 close(state->ivf);
00243                 state->ivf = -1;
00244                 return -CAMOGM_FRAME_FILE_ERR;
00245         }
00246         unsigned long k;
00247         k = len;
00248         k |= 0x80000000;
00249         state->frames_len[state->frames_pos] = k;
00250         state->frames_pos++;
00251 
00252         if(state->audio_samples_to_chunk[0] == -1) {
00253                 state->audio_samples_to_chunk[0] = slen;
00254         } else {
00255                 state->audio_samples_to_chunk[1]= state->audio_samples_to_chunk[2];
00256                 state->audio_samples_to_chunk[2]= slen;
00257         }
00258         state->offset_current += wrlen;
00259         state->audio_frameno++;
00260         state->audio_samples += slen;
00261 //fprintf(stderr, "push_audio...\n");
00262         // check here space ???
00263         return 0;
00264 }
00265 
00267 int camogm_end_mov(void){
00268         off_t l/*,he;
00269         unsigned char mdat_tag[8];
00270         unsigned char skip_tag[]="\0\0\0\0skip"*/;
00271         timescale = 10000; 
00272 
00273         l = lseek(state->ivf, 0, SEEK_CUR) - (state->frame_data_start) + 8; 
00274 //      lseek(state->ivf, state->frame_data_start, SEEK_SET);
00275         // fill in the header in the beginning of the file
00276         lseek(state->ivf, 0, SEEK_SET);
00277 fprintf(stderr, "frameno == %d, frames_per_chunk == %d\n", state->frameno, state->frames_per_chunk);
00278         quicktime_template_parser(q_template, 
00279                 state->ivf,   
00280                 state->width, 
00281                 state->height,
00282                 state->frameno, // frames count...
00283                 state->frame_period / (1000000 / timescale),
00284                 state->frames_per_chunk,
00285                 0, 
00286                 (int) ((float)timescale/(state->timescale)),
00287 //              state->frame_lengths, //! array of frame lengths to build an index
00288                 NULL, 
00289                 state->frame_data_start
00290                 );
00291         close(state->ivf);
00292         state->ivf = -1;
00294         if(state->frames_len) {
00295                 free(state->frames_len);
00296                 state->frames_len = NULL;
00297         }
00298         if(state->audio_samples_to_chunk) {
00299                 free(state->audio_samples_to_chunk);
00300                 state->audio_samples_to_chunk = NULL;
00301         }
00302         return 0;
00303 }
00304 
00305 /*
00306  starts with the input file pointer just after the opening "{",
00307  and output file - at the beginning of it's output
00308  on exit - input pointer - after closing "}", output after it's output
00309 */
00310 
00311 void putBigEndian(unsigned long d, int l) {
00312         unsigned char od[4];
00313         od[3] = d;
00314         od[2] = d >> 8;
00315         od[1] = d >> 16;
00316         od[0] = d >> 24;
00317         if(l)
00318                 write(ofd, &od[4 - l], l);
00319 //    oPos+=l;
00320 }
00321 
00323 char * sfgets(char * str, int size, const char * stream, int * pos) {
00324         int l;
00325         const char *eol = strchr(&stream[*pos], '\n');
00326         if(!eol)
00327                 eol = stream + (strlen(stream) - 1); 
00328         l = (eol - stream) - (*pos);
00329 //      if(l >= size) eol = stream + (*pos + size - 1);
00330         if(l >= size)
00331                 l = size - 1;
00332         memcpy(str, &stream[*pos], l);
00333         str[l] = '\0';
00334         *pos += l;
00335         return str;
00336 }
00337 
00338 int parse_special(void) {
00339         time_t ltime;
00340         int n,j,l;
00341         unsigned long k;
00342         char str[256];
00343         char c;
00344         int i = 0;
00345         int gap;
00346 //      while(((c = iFile[iPos++]) != 0x20) && (c != 0x09) && (c != 0x0a) && (c != 0x0d) && (c != 0x0) && (i < 255) && (iPos < iFileLen))
00347         while(((c = iFile[iPos++]) != ' ') && (c != '\t') && (c != '\n') && (c != '\r') && (c != '\0') && (i < 255) && (iPos < iFileLen))
00348                 str[i++] = c;
00349         str[i] = 0;
00350         
00351         D4(fprintf (debug_file, "parse_special, str=!%s\n",str));
00352 
00353         if(strcmp(str, "mdata") == 0)  { putBigEndian(headerSize, 4);return 0;} // will put zeroes on pass 1
00354         if(strcmp(str, "height") == 0) { putBigEndian(height,2);return 0;}
00355         if(strcmp(str, "width") == 0)  { putBigEndian(width,2);return 0;}
00356         if(strcmp(str, "nframes") == 0)  { putBigEndian(nframes,4);return 0;}
00357         if(strcmp(str, "timescale") == 0)  { putBigEndian(timescale,4);return 0;}
00358         if(strcmp(str, "duration") == 0)  { putBigEndian(nframes*sample_dur,4);return 0;}
00359 
00360         if(strcmp(str, "audio_channels") == 0)  { putBigEndian(audio_channels, 2); return 0;}
00361         if(strcmp(str, "audio_rate") == 0)  { putBigEndian(audio_rate, 4); return 0;}
00362         if(strcmp(str, "audio_timescale") == 0)  { putBigEndian(audio_timescale, 4); return 0;}
00363         if(strcmp(str, "audio_duration") == 0)  { putBigEndian(audio_duration, 4); return 0;}
00364         if(strcmp(str, "audio_frames") == 0)  { putBigEndian(state->audio_frameno, 4); return 0;}
00365         if(strcmp(str, "audio_samples") == 0)  { putBigEndian(state->audio_samples, 4); return 0;}
00366         if(strcmp(str, "audio_bytes_per_frame") == 0)  { putBigEndian(state->audio_channels * 2, 4); return 0;}
00367 
00368         if(strcmp(str, "audio_stsz") == 0)  {
00369                 putBigEndian(state->audio_channels * 2, 4);
00370                 putBigEndian(state->audio_samples, 4);
00371                 return 0;
00372         }
00373         if(strcmp(str, "audio_stco") == 0)  {   // (4 + 4 * chunk_count) bytes
00374                 long offset = 0;
00375                 n = state->audio_frameno;
00376 //fprintf(stderr, "chunk_offsets; n == %d; nframes == %d; samplesPerChunk == %d\n", n, nframes, samplesPerChunk);
00377                 putBigEndian(n, 4);
00378                 j = 0;
00379                 for(i = 0; i < state->frames_pos; i++) {
00380                         k = state->frames_len[i];
00381                         if(k & 0x80000000) {
00382                                 l = offset;
00383                                 putBigEndian(headerSize + l, 4);
00384                                 j++;
00385                         }
00386                         offset += k & 0x7FFFFFFF;
00387                 }
00388                 if(j != n)
00389                         fprintf(stderr, "MOV: wrong records for \"audio_stco\": have write: %d, need to write: %d\n", j, n);
00390                 return 0;
00391         }
00392         // TODO!!!
00393         if(strcmp(str, "audio_stsc") == 0)  {
00394                 n = 0;
00395                 for(i = 0; i < 3; i++) {
00396                         if(state->audio_samples_to_chunk[i] != -1) {
00397                                 n++;
00398                         }
00399                 }
00400                 putBigEndian(n, 4);
00401                 putBigEndian(1, 4);
00402                 putBigEndian(state->audio_samples_to_chunk[0], 4);
00403                 putBigEndian(01, 4); // TODO: 02 ???
00404                 n = 2;
00405                 if(state->audio_samples_to_chunk[1] != -1) {
00406                         putBigEndian(n, 4);
00407                         putBigEndian(state->audio_samples_to_chunk[1], 4);
00408                         putBigEndian(01, 4);
00409                         n = state->audio_frameno;
00410                 }
00411                 if(state->audio_samples_to_chunk[2] != -1) {
00412                         putBigEndian(n, 4);
00413                         putBigEndian(state->audio_samples_to_chunk[2], 4);
00414                         putBigEndian(01, 4);
00415                 }
00416                 return 0;
00417         }
00418         if(strcmp(str, "audio_samples_chunk") == 0)  { putBigEndian(1, 4);return 0;} // will put zeroes on pass 1
00419 
00420         if(strcmp(str, "frame_duration") == 0)  { putBigEndian(sample_dur,4);return 0;}
00421         if(strcmp(str, "samples_chunk") == 0)  { putBigEndian(samplesPerChunk, 4);return 0;} // will put zeroes on pass 1
00422 
00423         if(strcmp(str, "sample_sizes") == 0)  {
00424                 j = 0;
00425                 n = nframes;
00426                 for(i = 0; i < state->frames_pos; i++) {
00427                         k = state->frames_len[i];
00428                         if((k & 0x80000000) == 0x0) {
00429                                 l = k;
00430                                 putBigEndian(l, 4);
00431                                 j++;
00432                         }
00433                 }
00434                 if(j != n)
00435                         fprintf(stderr, "MOV: wrong records for \"samples_sizes\": have write: %d, need to write: %d\n", j, n);
00436                 return 0;
00437         }
00438         if(strcmp(str, "chunk_offsets") == 0)  {
00439                 long offset = 0;
00440                 n = nframes;
00441                 j = 0;
00442                 putBigEndian(n, 4);
00443                 for(i = 0; i < state->frames_pos; i++) {
00444                         k = state->frames_len[i];
00445                         if((k & 0x80000000) == 0x0) {
00446                                 l = offset;
00447                                 putBigEndian(headerSize + l, 4);
00448                                 j++;
00449                         }
00450                         offset += k & 0x7FFFFFFF;
00451                 }
00452                 if(j != n)
00453                         fprintf(stderr, "MOV: wrong records for \"samples_sizes\": have write: %d, need to write: %d\n", j, n);
00454                 return 0;
00455         }
00456 
00457         // a hack - include length'skip if data position (header size is known and there is a gap)
00458         if(strcmp(str, "data_size") == 0)  {
00459                 gap = headerSize - lseek(ofd, 0, SEEK_CUR) - 8;
00460                 if(gap > 0) { 
00461                         D4(fprintf (debug_file, "Inserting a skip tag to compensate for a gap (%d bytes) between the header and the frame data\n", gap));
00462                         if(gap < 8) {
00463                                 D0(fprintf(debug_file, "not enough room to insret 'skip' tag - %d (need 8)\n", gap));
00464                                 return -1; 
00465                         }
00466                         D4(fprintf(debug_file, "writing hex %x, %x bytes\n", gap, 4));
00467                         putBigEndian(gap, 4);
00468                         D4(fprintf(debug_file, "writing string <%s>\n","skip"));
00469                         write(ofd, "skip", 4);
00470                         lseek(ofd, gap - 8, SEEK_CUR); 
00471                 }
00472                 if(sizes != NULL) {
00473                         l = 0;
00474                         for(i = 0; i < nframes; i++)
00475                                 l += sizes[i];
00476                         D4(fprintf(debug_file, "writing hex %x, %x bytes\n", l, 4));
00477                         putBigEndian(l, 4);
00478                 } else
00479                         putBigEndian(nframes * framesize, 4);
00480                 return 0;
00481         }
00482         if(strcmp(str, "time") == 0)  {
00483                 time(&ltime);
00484                 ltime += 2082801600;    // 1970->1904// 31,557,600 seconds/year
00485                 putBigEndian(ltime, 4);
00486 //fprintf(stderr, "put !time...\n");
00487                 return 0;
00488         }
00489         return -1;
00490 }
00491 
00492 int parse(int top) {    // if top - will not include length
00493         long out_start, out_end;
00494         char c;
00495         unsigned long d, l;
00496         char *cp;
00497         D4(fprintf(debug_file, "parse(%x)\n", top));
00498         c = iFile[iPos++];
00499         D5(fprintf(debug_file, "%c", c));
00500         out_start = lseek(ofd, 0, SEEK_CUR);
00501 
00502         if(!top)
00503                 putBigEndian(0, 4);
00504         while((iPos < iFileLen ) && (c != '}')) {
00505                 if((c != ' ') && (c != '\t') && (c != '\r') && (c != '\n')) {
00506                         if(c == '!') {
00507                                 if(parse_special() < 0)
00508                                         return -1;
00509                         }
00510                         // children atoms
00511                         else {
00512                                 if(c == '{') {
00513                                         if(parse(0) < 0)
00514                                                 return -1;
00515                                         // skip comments
00516                                 } else {
00517                                         if(c == '#') {
00518                                                 sfgets(comStr, sizeof(comStr), iFile, &iPos);
00519                                         } else {
00520                                                 if(c == '\'') {
00521                                                         sfgets(comStr, sizeof(comStr), iFile, &iPos);
00522                                                         if((cp = strchr(comStr, 0x0a)) != NULL) cp[0] = 0;
00523                                                         if((cp = strchr(comStr, 0x0d)) != NULL) cp[0] = 0;
00524                                                         if((cp = strchr(comStr, '#')) != NULL) cp[0] = 0;
00525                                                         cp = comStr + strlen(comStr) - 1;
00526                                                         while((cp > comStr) && ((cp[0] == 0x20) || (cp[0] == 0x09)))
00527                                                                 cp--;
00528                                                         cp[1] = 0;
00529                                                         write(ofd, comStr, strlen(comStr));
00530                                                         D4(fprintf(debug_file, "writing string <%s>\n", comStr));
00531                                                 } else {
00532                                                         if(strchr(hexStr, c)) {
00533                                                                 d = 0;
00534                                                                 l = 1;
00535                                                                 do {
00536                                                                         d = (d << 4) + (strchr(hexStr, c) - hexStr);
00537                                                                         l++;
00538                                                                 } while((iPos < iFileLen) && (l <= 8) && (strchr(hexStr, (c = iFile[iPos++]))));
00539                                                                 l = (l) >> 1;
00540                                                                 putBigEndian(d, l);
00541                                                                 D4(fprintf(debug_file, "writing hex %lx, %lx bytes\n", d, l));
00542                                                         } else {
00543                                                                 if(c == '}') {
00544                                                                         break;
00545                                                                 } else {
00546                                                                         return -1;
00547                                                                 }
00548                                                         }
00549                                                 }
00550                                         }
00551                                 }
00552                         }
00553                 }
00554                 c = iFile[iPos++];
00555         }       
00556         // fread fseek ftell
00557         if(!top) {
00558                 out_end = lseek(ofd, 0, SEEK_CUR);
00559                 lseek(ofd, out_start, SEEK_SET);
00560                 putBigEndian((out_end - out_start), 4);
00561                 lseek(state->ivf, out_end, SEEK_SET);
00562         }
00563         return 0;
00564 }
00565 
00566 
00567 int quicktime_template_parser (const char * i_iFile, 
00568            int i_ofd,   
00569            int i_width, // width in pixels
00570            int i_height,
00571            int i_nframes,
00572            int i_sample_dur,
00573            int i_samplesPerChunk,
00574            int i_framesize,
00575            int i_timescale,
00576            int * i_sizes,
00577            int   data_start // zero if dfata is not written yet (will be no gap)
00578          ) {
00579         iFile=           i_iFile;
00580         width=           i_width;
00581         height=          i_height;
00582         nframes=         i_nframes;
00583         sample_dur=      i_sample_dur;
00584         samplesPerChunk= i_samplesPerChunk;
00585         framesize=       i_framesize;
00586         timescale=       i_timescale;
00587         sizes=           i_sizes;
00588         iPos=0; 
00589         ofd=             i_ofd;
00590         iFileLen=        strlen(iFile);
00591         lseek(ofd, 0, SEEK_SET);
00592 
00593         audio_timescale = state->audio_rate;
00594         audio_rate = audio_timescale;
00595         audio_rate <<= 16;
00596         audio_duration = state->audio_samples;//ctx_a.audio_count;
00597         audio_channels = state->audio_channels;
00598 
00599         if(data_start)
00600                 headerSize = data_start;
00601         D3(fprintf(debug_file, "PASS I\n"));
00602         while(iPos < iFileLen)
00603                 parse(1); // pass 1
00604         if(!headerSize)
00605                 headerSize = lseek(ofd, 0, SEEK_CUR);
00606         iPos = 0;
00607         lseek(ofd, 0, SEEK_SET);
00608         D3(fprintf(debug_file, "PASS II\n"));
00609         while(iPos < iFileLen)
00610                 parse(1); // pass 2
00611         return 0;
00612 }

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