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

Fix formatting

Fix source code formatting with 'uncrustify' command-line utility
parent 045b76e0
This source diff could not be displayed because it is too large. You can view the blob instead.
#define CAMOGM_FRAME_NOT_READY 1 // frame pointer valid, but not yet acquired #define CAMOGM_FRAME_NOT_READY 1 // frame pointer valid, but not yet acquired
#define CAMOGM_FRAME_INVALID 2 // invalid frame pointer #define CAMOGM_FRAME_INVALID 2 // invalid frame pointer
#define CAMOGM_FRAME_CHANGED 3 // frame parameters have changed #define CAMOGM_FRAME_CHANGED 3 // frame parameters have changed
#define CAMOGM_FRAME_NEXTFILE 4 // need to switch to a new file segment #define CAMOGM_FRAME_NEXTFILE 4 // need to switch to a new file segment
#define CAMOGM_FRAME_BROKEN 5 // frame broken (buffer overrun) #define CAMOGM_FRAME_BROKEN 5 // frame broken (buffer overrun)
#define CAMOGM_FRAME_FILE_ERR 6 // error with file I/O #define CAMOGM_FRAME_FILE_ERR 6 // error with file I/O
#define CAMOGM_FRAME_MALLOC 7 // can not allocate memory #define CAMOGM_FRAME_MALLOC 7 // can not allocate memory
#define CAMOGM_TOO_EARLY 8 // too early to start, waiting for particular timestamp #define CAMOGM_TOO_EARLY 8 // too early to start, waiting for particular timestamp
#define CAMOGM_FRAME_OTHER 9 // other errors #define CAMOGM_FRAME_OTHER 9 // other errors
#define CAMOGM_FORMAT_NONE 0 // no video output #define CAMOGM_FORMAT_NONE 0 // no video output
#define CAMOGM_FORMAT_OGM 1 // output as Ogg Media file #define CAMOGM_FORMAT_OGM 1 // output as Ogg Media file
#define CAMOGM_FORMAT_JPEG 2 // output as individual JPEG files #define CAMOGM_FORMAT_JPEG 2 // output as individual JPEG files
#define CAMOGM_FORMAT_MOV 3 // output as Apple Quicktime #define CAMOGM_FORMAT_MOV 3 // output as Apple Quicktime
#define D(x) {if (debug_file && debug_level){x;fflush(debug_file);}} #define D(x) { if (debug_file && debug_level) { x; fflush(debug_file); } }
#define D0(x) {if (debug_file){x;fflush(debug_file);}} #define D0(x) { if (debug_file) { x; fflush(debug_file); } }
#define D1(x) {if (debug_file && (debug_level > 0)){x;fflush(debug_file);}} #define D1(x) { if (debug_file && (debug_level > 0)) { x; fflush(debug_file); } }
#define D2(x) {if (debug_file && (debug_level > 1)){x;fflush(debug_file);}} #define D2(x) { if (debug_file && (debug_level > 1)) { x; fflush(debug_file); } }
#define D3(x) {if (debug_file && (debug_level > 2)){x;fflush(debug_file);}} #define D3(x) { if (debug_file && (debug_level > 2)) { x; fflush(debug_file); } }
#define D4(x) {if (debug_file && (debug_level > 3)){x;fflush(debug_file);}} #define D4(x) { if (debug_file && (debug_level > 3)) { x; fflush(debug_file); } }
#define D5(x) {if (debug_file && (debug_level > 4)){x;fflush(debug_file);}} #define D5(x) { if (debug_file && (debug_level > 4)) { x; fflush(debug_file); } }
#define D6(x) {if (debug_file && (debug_level > 5)){x;fflush(debug_file);}} #define D6(x) { if (debug_file && (debug_level > 5)) { x; fflush(debug_file); } }
//#define DD(x) //#define DD(x)
#define DD(x) {if (debug_file){fprintf(debug_file,"%s:%d:",__FILE__,__LINE__);x;fflush(debug_file);}} #define DD(x) { if (debug_file) { fprintf(debug_file, "%s:%d:", __FILE__, __LINE__); x; fflush(debug_file); } }
// HEADER_SIZE is defined to be larger than actual header (later - with EXIF) to use compile-time buffer // HEADER_SIZE is defined to be larger than actual header (later - with EXIF) to use compile-time buffer
#define JPEG_HEADER_MAXSIZE 0x300 // will not change #define JPEG_HEADER_MAXSIZE 0x300 // will not change
...@@ -32,139 +32,139 @@ ...@@ -32,139 +32,139 @@
/* /*
#define Exif_Photo_DateTimeOriginal 0x19003 #define Exif_Photo_DateTimeOriginal 0x19003
#define Exif_GPSInfo_GPSLatitudeRef 0x20001 #define Exif_GPSInfo_GPSLatitudeRef 0x20001
#define Exif_GPSInfo_GPSLatitude 0x20002 #define Exif_GPSInfo_GPSLatitude 0x20002
#define Exif_GPSInfo_GPSLongitudeRef 0x20003 #define Exif_GPSInfo_GPSLongitudeRef 0x20003
#define Exif_GPSInfo_GPSLongitude 0x20004 #define Exif_GPSInfo_GPSLongitude 0x20004
#define Exif_GPSInfo_GPSAltitudeRef 0x20005 #define Exif_GPSInfo_GPSAltitudeRef 0x20005
#define Exif_GPSInfo_GPSAltitude 0x20006 #define Exif_GPSInfo_GPSAltitude 0x20006
#define Exif_GPSInfo_GPSTimeStamp 0x20007 #define Exif_GPSInfo_GPSTimeStamp 0x20007
#define Exif_GPSInfo_GPSDateStamp 0x2001D #define Exif_GPSInfo_GPSDateStamp 0x2001D
#define Exif_GPSInfo_CompassDirectionRef 0x20010 #define Exif_GPSInfo_CompassDirectionRef 0x20010
#define Exif_GPSInfo_CompassDirection 0x20011 #define Exif_GPSInfo_CompassDirection 0x20011
#define Exif_GPSInfo_CompassPitchRef 0x20013 #define Exif_GPSInfo_CompassPitchRef 0x20013
#define Exif_GPSInfo_CompassPitch 0x20014 #define Exif_GPSInfo_CompassPitch 0x20014
#define Exif_GPSInfo_CompassRollRef 0x20015 #define Exif_GPSInfo_CompassRollRef 0x20015
#define Exif_GPSInfo_CompassRoll 0x20016 #define Exif_GPSInfo_CompassRoll 0x20016
*/ */
/* /*
/// Exif data (variable, stored with each frame) used for KML (not only) /// Exif data (variable, stored with each frame) used for KML (not only)
#define Exif_Image_ImageDescription_Index 0x00 #define Exif_Image_ImageDescription_Index 0x00
#define Exif_Photo_DateTimeOriginal_Index 0x01 #define Exif_Photo_DateTimeOriginal_Index 0x01
#define Exif_Photo_SubSecTimeOriginal_Index 0x02 #define Exif_Photo_SubSecTimeOriginal_Index 0x02
#define Exif_GPSInfo_GPSLatitudeRef_Index 0x03 #define Exif_GPSInfo_GPSLatitudeRef_Index 0x03
#define Exif_GPSInfo_GPSLatitude_Index 0x04 #define Exif_GPSInfo_GPSLatitude_Index 0x04
#define Exif_GPSInfo_GPSLongitudeRef_Index 0x05 #define Exif_GPSInfo_GPSLongitudeRef_Index 0x05
#define Exif_GPSInfo_GPSLongitude_Index 0x06 #define Exif_GPSInfo_GPSLongitude_Index 0x06
#define Exif_GPSInfo_GPSAltitudeRef_Index 0x07 #define Exif_GPSInfo_GPSAltitudeRef_Index 0x07
#define Exif_GPSInfo_GPSAltitude_Index 0x08 #define Exif_GPSInfo_GPSAltitude_Index 0x08
#define Exif_GPSInfo_GPSTimeStamp_Index 0x09 #define Exif_GPSInfo_GPSTimeStamp_Index 0x09
#define Exif_GPSInfo_GPSDateStamp_Index 0x0a #define Exif_GPSInfo_GPSDateStamp_Index 0x0a
#define Exif_GPSInfo_CompassDirectionRef_Index 0x0b #define Exif_GPSInfo_CompassDirectionRef_Index 0x0b
#define Exif_GPSInfo_CompassDirection_Index 0x0c #define Exif_GPSInfo_CompassDirection_Index 0x0c
#define Exif_GPSInfo_CompassPitchRef_Index 0x0d #define Exif_GPSInfo_CompassPitchRef_Index 0x0d
#define Exif_GPSInfo_CompassPitch_Index 0x0e #define Exif_GPSInfo_CompassPitch_Index 0x0e
#define Exif_GPSInfo_CompassRollRef_Index 0x0f #define Exif_GPSInfo_CompassRollRef_Index 0x0f
#define Exif_GPSInfo_CompassRoll_Index 0x10 #define Exif_GPSInfo_CompassRoll_Index 0x10
#define ExifKmlNumber 0x11 #define ExifKmlNumber 0x11
*/ */
typedef struct { typedef struct {
int segment_duration; int segment_duration;
int segment_length; int segment_length;
int greedy; int greedy;
int ignore_fps; int ignore_fps;
int save_gp; //if non zero, current circbuf pointer will be saved to global pointer, so imgsrv can report /pointers int save_gp; //if non zero, current circbuf pointer will be saved to global pointer, so imgsrv can report /pointers
char path_prefix[256]; char path_prefix[256];
char path[300]; char path[300];
int cirbuf_rp; //!-1 - invalid int cirbuf_rp; //!-1 - invalid
int fd_circ; //! file descriptor for circbuf int fd_circ; //! file descriptor for circbuf
int fd_head; //! file descriptor for JPEG header int fd_head; //! file descriptor for JPEG header
// int fd_sens; //! file descriptor for sensor/compressor parameters // int fd_sens; //! file descriptor for sensor/compressor parameters
int fd_fparmsall; //! file descriptor for sensor/compressor parameters int fd_fparmsall; //! file descriptor for sensor/compressor parameters
int fd_exif; //! file descriptor for Exif data int fd_exif; //! file descriptor for Exif data
int head_size; //! JPEG header size int head_size; //! JPEG header size
char jpegHeader [JPEG_HEADER_MAXSIZE]; char jpegHeader [JPEG_HEADER_MAXSIZE];
int metadata_start; int metadata_start;
struct interframe_params_t frame_params; struct interframe_params_t frame_params;
struct interframe_params_t this_frame_params; struct interframe_params_t this_frame_params;
int jpeg_len; int jpeg_len;
int frame_period ; //!in microseconds (1/10 of what is needed for the Ogm header) int frame_period; //!in microseconds (1/10 of what is needed for the Ogm header)
int width; int width;
int height; int height;
int starting; int starting;
int running; int running;
int last_error_code; int last_error_code;
ogg_stream_state os; ogg_stream_state os;
ogg_page og; ogg_page og;
ogg_packet op; ogg_packet op;
elph_ogg_packet eop; elph_ogg_packet eop;
int serialno; int serialno;
ogg_int64_t packetno; ogg_int64_t packetno;
ogg_int64_t granulepos; ogg_int64_t granulepos;
FILE* vf; //! video file (ogm, fopen) FILE* vf; //! video file (ogm, fopen)
int ivf; //! video file (jpeg, mov - open) int ivf; //! video file (jpeg, mov - open)
int last; //last packet in a file int last; //last packet in a file
int exif; // 1 - calculate and include Exif headers in each frame int exif; // 1 - calculate and include Exif headers in each frame
// exif_pointers_t ep; // exif_pointers_t ep;
// int exifValid; // int exifValid;
int exifSize; //signed int exifSize; //signed
unsigned char ed[MAX_EXIF_SIZE]; unsigned char ed[MAX_EXIF_SIZE];
int circ_buff_size; int circ_buff_size;
int senspars_size; int senspars_size;
char debug_name[256]; char debug_name[256];
// FILE* debug_file; // FILE* debug_file;
int set_samples_per_unit; int set_samples_per_unit;
double timescale; //! current timescale, default 1.0 double timescale; //! current timescale, default 1.0
double set_timescale; double set_timescale;
double start_after_timestamp; /// delay recording start to after frame timestamp double start_after_timestamp; /// delay recording start to after frame timestamp
int max_frames; int max_frames;
int set_max_frames; int set_max_frames;
int frames_per_chunk; int frames_per_chunk;
int set_frames_per_chunk; // quicktime - index for fast forward? int set_frames_per_chunk; // quicktime - index for fast forward?
int frameno; int frameno;
int* frame_lengths; int* frame_lengths;
off_t frame_data_start; //! Quicktime (and else?) - frame data start (0xff 0xd8...) off_t frame_data_start; //! Quicktime (and else?) - frame data start (0xff 0xd8...)
ogg_int64_t time_unit; ogg_int64_t time_unit;
int formats; //! bitmask of used (initialized) formats int formats; //! bitmask of used (initialized) formats
int format; //! output file format int format; //! output file format
int set_format; //! output format to set (will be updated after stop) int set_format; //! output format to set (will be updated after stop)
elph_packet_chunk packetchunks[7]; elph_packet_chunk packetchunks[7];
int chunk_index; int chunk_index;
int buf_overruns; int buf_overruns;
int buf_min; int buf_min;
int set_frames_skip; //! will be copied to frames_skip if stopped or at start int set_frames_skip; //! will be copied to frames_skip if stopped or at start
int frames_skip; //! number of frames to skip after the one recorded (for time lapse) int frames_skip; //! number of frames to skip after the one recorded (for time lapse)
//! if negetive - -(interval between frames in seconds) //! if negetive - -(interval between frames in seconds)
int frames_skip_left; //! number of frames left to skip before the next one to be processed int frames_skip_left; //! number of frames left to skip before the next one to be processed
//! if (frames_skip <0) - next timestamp to save an image //! if (frames_skip <0) - next timestamp to save an image
//kml stuff //kml stuff
int kml_enable; //! enable KML file generation int kml_enable; //! enable KML file generation
int kml_used; //! KML file generation used (change only when stopped) int kml_used; //! KML file generation used (change only when stopped)
char kml_path[300]; //! full path for KML file (if any) char kml_path[300]; //! full path for KML file (if any)
FILE* kml_file; //! stream to write kml file FILE* kml_file; //! stream to write kml file
double kml_horHalfFov; //! half horizontal Fov (degrees) double kml_horHalfFov; //! half horizontal Fov (degrees)
double kml_vertHalfFov; //! half vertical Fov (degrees) double kml_vertHalfFov; //! half vertical Fov (degrees)
double kml_near; //! Use in KML "near" parameter (<=0 - don't use it) double kml_near; //! Use in KML "near" parameter (<=0 - don't use it)
int kml_height_mode; //! 1 - actual, 0 - ground int kml_height_mode; //! 1 - actual, 0 - ground
double kml_height; //! extra height to add double kml_height; //! extra height to add
int kml_period; //! generate PhotoOverlay for each kml_period seconds; int kml_period; //! generate PhotoOverlay for each kml_period seconds;
int kml_last_ts; //! last generated kml file timestamp int kml_last_ts; //! last generated kml file timestamp
int kml_last_uts; //! last generated kml file timestamp, microseconds int kml_last_uts; //! last generated kml file timestamp, microseconds
struct exif_dir_table_t kml_exif[ExifKmlNumber] ; //! store locations of the fields needed for KML generations in the Exif block struct exif_dir_table_t kml_exif[ExifKmlNumber]; //! store locations of the fields needed for KML generations in the Exif block
} camogm_state; } camogm_state;
extern int debug_level; extern int debug_level;
extern FILE* debug_file; extern FILE* debug_file;
extern camogm_state * state; extern camogm_state * state;
void put_uint16(void *buf, u_int16_t val); void put_uint16(void *buf, u_int16_t val);
void put_uint32(void *buf, u_int32_t val); void put_uint32(void *buf, u_int32_t val);
void put_uint64(void *buf, u_int64_t val); void put_uint64(void *buf, u_int64_t val);
unsigned long getGPValue(unsigned long GPNumber); unsigned long getGPValue(unsigned long GPNumber);
void setGValue(unsigned long GNumber, unsigned long value); void setGValue(unsigned long GNumber, unsigned long value);
int waitDaemonEnabled(int daemonBit); // <0 - use default int waitDaemonEnabled(int daemonBit); // <0 - use default
int isDaemonEnabled(int daemonBit); // <0 - use default int isDaemonEnabled(int daemonBit); // <0 - use default
/*!*************************************************************************** /*!***************************************************************************
*! FILE NAME : camogm_jpeg.c *! FILE NAME : camogm_jpeg.c
*! DESCRIPTION: Provides writing to series of individual JPEG files for camogm *! DESCRIPTION: Provides writing to series of individual JPEG files for camogm
*! Copyright (C) 2007 Elphel, Inc. *! Copyright (C) 2007 Elphel, Inc.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify *! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by *! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or *! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version. *! (at your option) any later version.
*! *!
*! This program is distributed in the hope that it will be useful, *! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of *! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details. *! GNU General Public License for more details.
*! *!
*! You should have received a copy of the GNU General Public License *! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>. *! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! *!
*! $Log: camogm_jpeg.c,v $ *! $Log: camogm_jpeg.c,v $
*! Revision 1.2 2009/02/25 17:50:51 spectr_rain *! Revision 1.2 2009/02/25 17:50:51 spectr_rain
*! removed deprecated dependency *! removed deprecated dependency
*! *!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel *! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*! *!
*! *!
*! Revision 1.3 2008/04/11 23:09:33 elphel *! Revision 1.3 2008/04/11 23:09:33 elphel
*! modified to handle kml generation *! modified to handle kml generation
*! *!
*! Revision 1.2 2007/11/19 03:23:21 elphel *! Revision 1.2 2007/11/19 03:23:21 elphel
*! 7.1.5.5 Added support for *.mov files in camogm. *! 7.1.5.5 Added support for *.mov files in camogm.
*! *!
*! Revision 1.1 2007/11/16 08:49:57 elphel *! Revision 1.1 2007/11/16 08:49:57 elphel
*! Initial release of camogm - program to record video/image to the camera hard drive (or other storage) *! Initial release of camogm - program to record video/image to the camera hard drive (or other storage)
*! *!
*/ */
//!Not all are needed, just copied from the camogm.c //!Not all are needed, just copied from the camogm.c
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
...@@ -51,77 +51,84 @@ ...@@ -51,77 +51,84 @@
#include <string.h> #include <string.h>
#include <netinet/in.h> /*little <-> big endian ?*/ #include <netinet/in.h> /*little <-> big endian ?*/
#include <sys/mman.h> /* mmap */ #include <sys/mman.h> /* mmap */
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <c313a.h> #include <c313a.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <ogg/ogg.h> // has to be before ogmstreams.h #include <ogg/ogg.h> // has to be before ogmstreams.h
#include "ogmstreams.h" // move it to <>? #include "ogmstreams.h" // move it to <>?
#include "camogm_jpeg.h" #include "camogm_jpeg.h"
#include "camogm.h" #include "camogm.h"
//! may add something - called first time format is changed to this one (only once) recording is stopped //! may add something - called first time format is changed to this one (only once) recording is stopped
int camogm_init_jpeg(void) { int camogm_init_jpeg(void)
return 0; {
return 0;
} }
void camogm_free_jpeg(void) { void camogm_free_jpeg(void)
{
} }
int camogm_start_jpeg(void) { int camogm_start_jpeg(void)
{
//!TODO: make directory if it does not exist (find the last "/" in the state->path //!TODO: make directory if it does not exist (find the last "/" in the state->path
char * slash; char * slash;
int rslt; int rslt;
strcpy (state->path,state->path_prefix); //!make state->path a directory name (will be replaced when the frames will be written)
slash=strrchr(state->path,'/'); strcpy(state->path, state->path_prefix); //!make state->path a directory name (will be replaced when the frames will be written)
D2(fprintf (debug_file, "camogm_start_jpeg\n")); slash = strrchr(state->path, '/');
if (slash) { D2(fprintf(debug_file, "camogm_start_jpeg\n"));
D3(fprintf (debug_file, "Full path %s\n", state->path)); if (slash) {
slash[0]='\0'; //! truncate path to the directory name D3(fprintf(debug_file, "Full path %s\n", state->path));
D3(fprintf (debug_file, "directory path %s\n", state->path)); slash[0] = '\0'; //! truncate path to the directory name
rslt=mkdir(state->path, 0777); D3(fprintf(debug_file, "directory path %s\n", state->path));
D3(fprintf (debug_file, "mkdir (%s, 0777) returned %d, errno=%d\n", state->path, rslt, errno)); rslt = mkdir(state->path, 0777);
if ((rslt<0) && (errno != EEXIST)) { // already exists is OK D3(fprintf(debug_file, "mkdir (%s, 0777) returned %d, errno=%d\n", state->path, rslt, errno));
D0(fprintf (debug_file, "Error creating directory %s, errno=%d\n", state->path, errno)); if ((rslt < 0) && (errno != EEXIST)) { // already exists is OK
return -CAMOGM_FRAME_FILE_ERR; D0(fprintf(debug_file, "Error creating directory %s, errno=%d\n", state->path, errno));
} return -CAMOGM_FRAME_FILE_ERR;
} }
return 0; }
return 0;
} }
int camogm_frame_jpeg(void){ int camogm_frame_jpeg(void)
int i,j; {
int i, j;
// int fd; // int fd;
ssize_t iovlen,l; ssize_t iovlen, l;
struct iovec chunks_iovec[7]; struct iovec chunks_iovec[7];
l=0;
for (i=0; i< (state->chunk_index)-1; i++) { l = 0;
chunks_iovec[i].iov_base=state->packetchunks[i+1].chunk; for (i = 0; i < (state->chunk_index) - 1; i++) {
chunks_iovec[i].iov_len= state->packetchunks[i+1].bytes; chunks_iovec[i].iov_base = state->packetchunks[i + 1].chunk;
l+=chunks_iovec[i].iov_len; chunks_iovec[i].iov_len = state->packetchunks[i + 1].bytes;
} l += chunks_iovec[i].iov_len;
}
sprintf(state->path,"%s%010ld_%06ld.jpeg",state->path_prefix,state->this_frame_params.timestamp_sec,state->this_frame_params.timestamp_usec); sprintf(state->path, "%s%010ld_%06ld.jpeg", state->path_prefix, state->this_frame_params.timestamp_sec, state->this_frame_params.timestamp_usec);
// if ((devfd = open("/dev/fpgaio", O_RDWR))<0) {printf("error opening /dev/fpgaio\r\n"); return -1;} // if ((devfd = open("/dev/fpgaio", O_RDWR))<0) {printf("error opening /dev/fpgaio\r\n"); return -1;}
//_1__12_Error opening /tmp/z/video1195147018_273452.jpeg for writing //_1__12_Error opening /tmp/z/video1195147018_273452.jpeg for writing
if (((state->ivf=open(state->path,O_RDWR | O_CREAT, 0777)))<0){ if (((state->ivf = open(state->path, O_RDWR | O_CREAT, 0777))) < 0) {
D0(fprintf (debug_file, "Error opening %s for writing, returned %d, errno=%d\n", state->path,state->ivf,errno)); D0(fprintf(debug_file, "Error opening %s for writing, returned %d, errno=%d\n", state->path, state->ivf, errno));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
iovlen=writev(state->ivf,chunks_iovec, (state->chunk_index)-1); iovlen = writev(state->ivf, chunks_iovec, (state->chunk_index) - 1);
if (iovlen < l) { if (iovlen < l) {
j=errno; j = errno;
D0(fprintf(debug_file,"writev error %d (returned %d, expected %d)\n",j,iovlen,l)); D0(fprintf(debug_file, "writev error %d (returned %d, expected %d)\n", j, iovlen, l));
close (state->ivf); close(state->ivf);
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
close (state->ivf); close(state->ivf);
return 0; return 0;
} }
int camogm_end_jpeg(void){ int camogm_end_jpeg(void)
return 0; {
return 0;
} }
/*!*************************************************************************** /*!***************************************************************************
*! FILE NAME : camogm_kml.c *! FILE NAME : camogm_kml.c
*! DESCRIPTION: Provides writing to series of individual JPEG files for camogm *! DESCRIPTION: Provides writing to series of individual JPEG files for camogm
*! Copyright (C) 2007 Elphel, Inc. *! Copyright (C) 2007 Elphel, Inc.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify *! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by *! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or *! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version. *! (at your option) any later version.
*! *!
*! This program is distributed in the hope that it will be useful, *! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of *! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details. *! GNU General Public License for more details.
*! *!
*! You should have received a copy of the GNU General Public License *! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>. *! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! *!
*! $Log: camogm_kml.c,v $ *! $Log: camogm_kml.c,v $
*! Revision 1.3 2011/01/03 22:00:29 elphel *! Revision 1.3 2011/01/03 22:00:29 elphel
*! fixed tilt generation *! fixed tilt generation
*! *!
*! Revision 1.2 2009/02/25 17:50:02 spectr_rain *! Revision 1.2 2009/02/25 17:50:02 spectr_rain
*! removed deprecated dependency *! removed deprecated dependency
*! *!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel *! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*! *!
*! *!
*! Revision 1.2 2008/04/13 21:05:20 elphel *! Revision 1.2 2008/04/13 21:05:20 elphel
*! Fixing KML generation *! Fixing KML generation
*! *!
*! Revision 1.1 2008/04/11 23:06:52 elphel *! Revision 1.1 2008/04/11 23:06:52 elphel
*! files to handle KML generation *! files to handle KML generation
*! *!
*! *!
*/ */
//!Not all are needed, just copied from the camogm.c //!Not all are needed, just copied from the camogm.c
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
...@@ -52,272 +52,279 @@ ...@@ -52,272 +52,279 @@
#include <string.h> #include <string.h>
#include <netinet/in.h> /*little <-> big endian ?*/ #include <netinet/in.h> /*little <-> big endian ?*/
#include <sys/mman.h> /* mmap */ #include <sys/mman.h> /* mmap */
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <c313a.h> #include <c313a.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <ogg/ogg.h> // has to be before ogmstreams.h #include <ogg/ogg.h> // has to be before ogmstreams.h
#include "ogmstreams.h" // move it to <>? #include "ogmstreams.h" // move it to <>?
#include "camogm_kml.h" #include "camogm_kml.h"
#include "camogm.h" #include "camogm.h"
const char ExifDirFileName[]="/dev/exif_metadir"; const char ExifDirFileName[] = "/dev/exif_metadir";
//! may add something - called first time format is changed to this one (only once) recording is stopped //! may add something - called first time format is changed to this one (only once) recording is stopped
int camogm_init_kml(void) { int camogm_init_kml(void)
return 0; {
return 0;
} }
void camogm_free_kml(void) { void camogm_free_kml(void)
{
} }
/* /*
int camogm_start_mov(void) { int camogm_start_mov(void) {
//! allocate memory for the frame index table //! allocate memory for the frame index table
if (!((state->frame_lengths=malloc(4*state->max_frames)))) return -CAMOGM_FRAME_MALLOC ; if (!((state->frame_lengths=malloc(4*state->max_frames)))) return -CAMOGM_FRAME_MALLOC ;
//! open file for writing //! open file for writing
sprintf(state->path,"%s%010ld_%06ld.mov",state->path_prefix,state->frame_params.timestamp_sec,state->frame_params.timestamp_usec); sprintf(state->path,"%s%010ld_%06ld.mov",state->path_prefix,state->frame_params.timestamp_sec,state->frame_params.timestamp_usec);
if (((state->ivf=open(state->path,O_RDWR | O_CREAT, 0777)))<0){ if (((state->ivf=open(state->path,O_RDWR | O_CREAT, 0777)))<0){
D0(fprintf (debug_file, "Error opening %s for writing, returned %d, errno=%d\n", state->path,state->ivf,errno)); D0(fprintf (debug_file, "Error opening %s for writing, returned %d, errno=%d\n", state->path,state->ivf,errno));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
//!skip header (plus extra) //!skip header (plus extra)
//! Quicktime (and else?) - frame data start (0xff 0xd8...) //! Quicktime (and else?) - frame data start (0xff 0xd8...)
state->frame_data_start=QUICKTIME_MIN_HEADER+16+ 4*(state->max_frames)+ ( 4*(state->max_frames))/(state->frames_per_chunk); // 8 bytes for "skip" tag state->frame_data_start=QUICKTIME_MIN_HEADER+16+ 4*(state->max_frames)+ ( 4*(state->max_frames))/(state->frames_per_chunk); // 8 bytes for "skip" tag
lseek(state->ivf, state->frame_data_start, SEEK_SET); lseek(state->ivf, state->frame_data_start, SEEK_SET);
return 0; return 0;
} }
*/ */
int camogm_start_kml(void) { int camogm_start_kml(void)
{
// struct exif_dir_table_t kml_exif[ExifKmlNumber] ; //! store locations of the fields needed for KML generations in the Exif block // struct exif_dir_table_t kml_exif[ExifKmlNumber] ; //! store locations of the fields needed for KML generations in the Exif block
///exif_metadir ///exif_metadir
/// state->kml_exif[i] /// state->kml_exif[i]
/// Re-read directory table and rebuild state->kml_exif when starting each file /// Re-read directory table and rebuild state->kml_exif when starting each file
struct exif_dir_table_t dir_table_entry; struct exif_dir_table_t dir_table_entry;
int fd_ExifDir; int fd_ExifDir;
int indx; int indx;
for (indx=0;indx<ExifKmlNumber;indx++) state->kml_exif[indx].ltag=0;
for (indx = 0; indx < ExifKmlNumber; indx++) state->kml_exif[indx].ltag = 0;
//! open Exif header directory file //! open Exif header directory file
fd_ExifDir=open(ExifDirFileName,O_RDONLY); fd_ExifDir = open(ExifDirFileName, O_RDONLY);
if (fd_ExifDir<0) { // check control OK if (fd_ExifDir < 0) { // check control OK
D0(fprintf (debug_file,"Error opening %s\n", ExifDirFileName)); D0(fprintf(debug_file, "Error opening %s\n", ExifDirFileName));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
while (read(fd_ExifDir, &dir_table_entry, sizeof(dir_table_entry))>0) { while (read(fd_ExifDir, &dir_table_entry, sizeof(dir_table_entry)) > 0) {
switch (dir_table_entry.ltag) { switch (dir_table_entry.ltag) {
case Exif_Photo_DateTimeOriginal: indx= Exif_Photo_DateTimeOriginal_Index; break; case Exif_Photo_DateTimeOriginal: indx = Exif_Photo_DateTimeOriginal_Index; break;
case Exif_GPSInfo_GPSLatitudeRef: indx= Exif_GPSInfo_GPSLatitudeRef_Index; break; case Exif_GPSInfo_GPSLatitudeRef: indx = Exif_GPSInfo_GPSLatitudeRef_Index; break;
case Exif_GPSInfo_GPSLatitude: indx= Exif_GPSInfo_GPSLatitude_Index ; break; case Exif_GPSInfo_GPSLatitude: indx = Exif_GPSInfo_GPSLatitude_Index; break;
case Exif_GPSInfo_GPSLongitudeRef: indx= Exif_GPSInfo_GPSLongitudeRef_Index ; break; case Exif_GPSInfo_GPSLongitudeRef: indx = Exif_GPSInfo_GPSLongitudeRef_Index; break;
case Exif_GPSInfo_GPSLongitude: indx= Exif_GPSInfo_GPSLongitude_Index; break; case Exif_GPSInfo_GPSLongitude: indx = Exif_GPSInfo_GPSLongitude_Index; break;
case Exif_GPSInfo_GPSAltitudeRef: indx= Exif_GPSInfo_GPSAltitudeRef_Index; break; case Exif_GPSInfo_GPSAltitudeRef: indx = Exif_GPSInfo_GPSAltitudeRef_Index; break;
case Exif_GPSInfo_GPSAltitude: indx= Exif_GPSInfo_GPSAltitude_Index; break; case Exif_GPSInfo_GPSAltitude: indx = Exif_GPSInfo_GPSAltitude_Index; break;
case Exif_GPSInfo_GPSTimeStamp: indx= Exif_GPSInfo_GPSTimeStamp_Index; break; case Exif_GPSInfo_GPSTimeStamp: indx = Exif_GPSInfo_GPSTimeStamp_Index; break;
case Exif_GPSInfo_GPSDateStamp: indx= Exif_GPSInfo_GPSDateStamp_Index; break; case Exif_GPSInfo_GPSDateStamp: indx = Exif_GPSInfo_GPSDateStamp_Index; break;
case Exif_GPSInfo_CompassDirectionRef: indx= Exif_GPSInfo_CompassDirectionRef_Index; break; case Exif_GPSInfo_CompassDirectionRef: indx = Exif_GPSInfo_CompassDirectionRef_Index; break;
case Exif_GPSInfo_CompassDirection: indx= Exif_GPSInfo_CompassDirection_Index; break; case Exif_GPSInfo_CompassDirection: indx = Exif_GPSInfo_CompassDirection_Index; break;
case Exif_GPSInfo_CompassPitchRef: indx= Exif_GPSInfo_CompassPitchRef_Index; break; case Exif_GPSInfo_CompassPitchRef: indx = Exif_GPSInfo_CompassPitchRef_Index; break;
case Exif_GPSInfo_CompassPitch: indx= Exif_GPSInfo_CompassPitch_Index; break; case Exif_GPSInfo_CompassPitch: indx = Exif_GPSInfo_CompassPitch_Index; break;
case Exif_GPSInfo_CompassRollRef: indx= Exif_GPSInfo_CompassRollRef_Index; break; case Exif_GPSInfo_CompassRollRef: indx = Exif_GPSInfo_CompassRollRef_Index; break;
case Exif_GPSInfo_CompassRoll: indx= Exif_GPSInfo_CompassRoll_Index; break; case Exif_GPSInfo_CompassRoll: indx = Exif_GPSInfo_CompassRoll_Index; break;
default: indx=-1; default: indx = -1;
} }
if (indx>=0) { if (indx >= 0) {
memcpy(&(state->kml_exif[indx]),&dir_table_entry,sizeof(dir_table_entry)); memcpy(&(state->kml_exif[indx]), &dir_table_entry, sizeof(dir_table_entry));
D2(fprintf(debug_file,"indx=%02d, ltag=0x%05x, len=0x%03x, src=0x%03x, dst=0x%03x\n",indx, \ D2(fprintf(debug_file, "indx=%02d, ltag=0x%05x, len=0x%03x, src=0x%03x, dst=0x%03x\n", indx, \
(int) dir_table_entry.ltag, \ (int)dir_table_entry.ltag, \
(int) dir_table_entry.len, \ (int)dir_table_entry.len, \
(int) dir_table_entry.src, \ (int)dir_table_entry.src, \
(int) dir_table_entry.dst)); (int)dir_table_entry.dst));
} }
} }
close (fd_ExifDir); close(fd_ExifDir);
sprintf(state->kml_path,"%s%010ld_%06ld.kml",state->path_prefix,state->this_frame_params.timestamp_sec,state->this_frame_params.timestamp_usec); sprintf(state->kml_path, "%s%010ld_%06ld.kml", state->path_prefix, state->this_frame_params.timestamp_sec, state->this_frame_params.timestamp_usec);
if (!((state->kml_file=fopen(state->kml_path,"w+"))) ){ if (!((state->kml_file = fopen(state->kml_path, "w+"))) ) {
D0(fprintf (debug_file, "Error opening %s for writing\n", state->kml_path)); D0(fprintf(debug_file, "Error opening %s for writing\n", state->kml_path));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
/// write start of the KML file /// write start of the KML file
fprintf (state->kml_file,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \ fprintf(state->kml_file, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
"<kml xmlns=\"http://earth.google.com/kml/2.2\">\n"); "<kml xmlns=\"http://earth.google.com/kml/2.2\">\n");
fprintf (state->kml_file,"<Document>\n"); fprintf(state->kml_file, "<Document>\n");
state->kml_used= 1; state->kml_used = 1;
return 0; return 0;
} }
int camogm_frame_kml(void){ int camogm_frame_kml(void)
char JPEGFileName[300]; {
char * filename; char JPEGFileName[300];
int fd_JPEG; char * filename;
int i,j; int fd_JPEG;
ssize_t iovlen,l; int i, j;
struct iovec chunks_iovec[7]; ssize_t iovlen, l;
char datestr[11]; struct iovec chunks_iovec[7];
double longitude=0.0, latitude=0.0, altitude=0.0, heading=0.0, tilt=0.0, roll=0.0, pitch=0.0; char datestr[11];
int hours=0, minutes=0; double longitude = 0.0, latitude = 0.0, altitude = 0.0, heading = 0.0, tilt = 0.0, roll = 0.0, pitch = 0.0;
double seconds=0.0; int hours = 0, minutes = 0;
int * ip; double seconds = 0.0;
if (state->kml_file) { // probably not needed int * ip;
i=state->this_frame_params.timestamp_sec - (state->kml_last_ts + state->kml_period);
if ((i>1) || ((i==0) && ( state->this_frame_params.timestamp_usec > state->kml_last_uts ))) { if (state->kml_file) { // probably not needed
i = state->this_frame_params.timestamp_sec - (state->kml_last_ts + state->kml_period);
if ((i > 1) || ((i == 0) && ( state->this_frame_params.timestamp_usec > state->kml_last_uts ))) {
// if (state->this_frame_params.timestamp_sec > (state->kml_last_ts + state->kml_period)) { // this way it is safe to put kml_period=1000, then kml_period=1 // if (state->this_frame_params.timestamp_sec > (state->kml_last_ts + state->kml_period)) { // this way it is safe to put kml_period=1000, then kml_period=1
state->kml_last_ts=state->this_frame_params.timestamp_sec; state->kml_last_ts = state->this_frame_params.timestamp_sec;
state->kml_last_uts=state->this_frame_params.timestamp_usec; state->kml_last_uts = state->this_frame_params.timestamp_usec;
if (state->format==CAMOGM_FORMAT_JPEG) { if (state->format == CAMOGM_FORMAT_JPEG) {
strcpy (JPEGFileName, state->path); strcpy(JPEGFileName, state->path);
} else { } else {
sprintf(JPEGFileName,"%s%010ld_%06ld.jpeg",state->path_prefix,state->this_frame_params.timestamp_sec,state->this_frame_params.timestamp_usec); sprintf(JPEGFileName, "%s%010ld_%06ld.jpeg", state->path_prefix, state->this_frame_params.timestamp_sec, state->this_frame_params.timestamp_usec);
if (((fd_JPEG=open(JPEGFileName,O_RDWR | O_CREAT, 0777)))>=0){ if (((fd_JPEG = open(JPEGFileName, O_RDWR | O_CREAT, 0777))) >= 0) {
l=0; l = 0;
for (i=0; i< (state->chunk_index)-1; i++) { for (i = 0; i < (state->chunk_index) - 1; i++) {
chunks_iovec[i].iov_base=state->packetchunks[i+1].chunk; chunks_iovec[i].iov_base = state->packetchunks[i + 1].chunk;
chunks_iovec[i].iov_len= state->packetchunks[i+1].bytes; chunks_iovec[i].iov_len = state->packetchunks[i + 1].bytes;
l+=chunks_iovec[i].iov_len; l += chunks_iovec[i].iov_len;
} }
iovlen=writev(fd_JPEG,chunks_iovec, (state->chunk_index)-1); iovlen = writev(fd_JPEG, chunks_iovec, (state->chunk_index) - 1);
if (iovlen < l) { if (iovlen < l) {
j=errno; j = errno;
D0(fprintf(debug_file,"writev error %d (returned %d, expected %d)\n",j,iovlen,l)); D0(fprintf(debug_file, "writev error %d (returned %d, expected %d)\n", j, iovlen, l));
close (fd_JPEG); close(fd_JPEG);
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
close (fd_JPEG); close(fd_JPEG);
} else { } else {
D0(fprintf (debug_file, "Error opening %s for writing, returned %d, errno=%d\n", JPEGFileName,fd_JPEG,errno)); D0(fprintf(debug_file, "Error opening %s for writing, returned %d, errno=%d\n", JPEGFileName, fd_JPEG, errno));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
} }
/// now we have JPEGFileName written. find realtive (to KML) location: /// now we have JPEGFileName written. find realtive (to KML) location:
filename=strrchr(JPEGFileName, '/'); filename = strrchr(JPEGFileName, '/');
filename[0]='\0'; filename[0] = '\0';
filename++; filename++;
///generating KML itself ///generating KML itself
/// Using GPS time - in the same structure /// Using GPS time - in the same structure
if (state->kml_exif[Exif_GPSInfo_GPSDateStamp_Index].ltag==Exif_GPSInfo_GPSDateStamp) { // Exif_GPSInfo_GPSDateStamp is present in template if (state->kml_exif[Exif_GPSInfo_GPSDateStamp_Index].ltag == Exif_GPSInfo_GPSDateStamp) { // Exif_GPSInfo_GPSDateStamp is present in template
memcpy(datestr, &(state->ed[state->kml_exif[Exif_GPSInfo_GPSDateStamp_Index].dst]) ,10); memcpy(datestr, &(state->ed[state->kml_exif[Exif_GPSInfo_GPSDateStamp_Index].dst]), 10);
datestr[4]='-';datestr[7]='-';datestr[10]='\0'; datestr[4] = '-'; datestr[7] = '-'; datestr[10] = '\0';
} }
if (state->kml_exif[Exif_GPSInfo_GPSTimeStamp_Index].ltag==Exif_GPSInfo_GPSTimeStamp) { // Exif_GPSInfo_GPSTimeStamp is present in template if (state->kml_exif[Exif_GPSInfo_GPSTimeStamp_Index].ltag == Exif_GPSInfo_GPSTimeStamp) { // Exif_GPSInfo_GPSTimeStamp is present in template
ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_GPSTimeStamp_Index].dst]); ip = (int*)&(state->ed[state->kml_exif[Exif_GPSInfo_GPSTimeStamp_Index].dst]);
hours= __cpu_to_be32( ip[0]); hours = __cpu_to_be32( ip[0]);
minutes= __cpu_to_be32( ip[2]); minutes = __cpu_to_be32( ip[2]);
seconds= (1.0*(__cpu_to_be32( ip[4])+1))/__cpu_to_be32( ip[5]); /// GPS likes ".999", let's inc by one - anyway will round that out seconds = (1.0 * (__cpu_to_be32( ip[4]) + 1)) / __cpu_to_be32( ip[5]); /// GPS likes ".999", let's inc by one - anyway will round that out
D2(fprintf (debug_file,"(when) 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",ip[0],ip[1],ip[2],ip[3],ip[4],ip[5])); D2(fprintf(debug_file, "(when) 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", ip[0], ip[1], ip[2], ip[3], ip[4], ip[5]));
D2(fprintf (debug_file,"(when) 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",__cpu_to_be32(ip[0]), \ D2(fprintf(debug_file, "(when) 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", __cpu_to_be32(ip[0]), \
__cpu_to_be32(ip[1]), \ __cpu_to_be32(ip[1]), \
__cpu_to_be32(ip[2]), \ __cpu_to_be32(ip[2]), \
__cpu_to_be32(ip[3]), \ __cpu_to_be32(ip[3]), \
__cpu_to_be32(ip[4]), \ __cpu_to_be32(ip[4]), \
__cpu_to_be32(ip[5]))); __cpu_to_be32(ip[5])));
} }
D1(fprintf (debug_file,"when=%sT%02d:%02d:%05.2fZ\n",datestr, hours, minutes, seconds)); D1(fprintf(debug_file, "when=%sT%02d:%02d:%05.2fZ\n", datestr, hours, minutes, seconds));
/// knowing format provided from GPS - degrees and minuts only, no seconds: /// knowing format provided from GPS - degrees and minuts only, no seconds:
if (state->kml_exif[Exif_GPSInfo_GPSLongitude_Index].ltag==Exif_GPSInfo_GPSLongitude) { // Exif_GPSInfo_GPSLongitude is present in template if (state->kml_exif[Exif_GPSInfo_GPSLongitude_Index].ltag == Exif_GPSInfo_GPSLongitude) { // Exif_GPSInfo_GPSLongitude is present in template
ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_GPSLongitude_Index].dst]); ip = (int*)&(state->ed[state->kml_exif[Exif_GPSInfo_GPSLongitude_Index].dst]);
longitude=__cpu_to_be32( ip[0])/(1.0*__cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2])/(60.0*__cpu_to_be32( ip[3])); longitude = __cpu_to_be32( ip[0]) / (1.0 * __cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2]) / (60.0 * __cpu_to_be32( ip[3]));
if ((state->kml_exif[Exif_GPSInfo_GPSLongitudeRef_Index].ltag==Exif_GPSInfo_GPSLongitudeRef) && if ((state->kml_exif[Exif_GPSInfo_GPSLongitudeRef_Index].ltag == Exif_GPSInfo_GPSLongitudeRef) &&
(state->ed[state->kml_exif[Exif_GPSInfo_GPSLongitudeRef_Index].dst] != 'E')) longitude=-longitude; (state->ed[state->kml_exif[Exif_GPSInfo_GPSLongitudeRef_Index].dst] != 'E')) longitude = -longitude;
D2(fprintf (debug_file,"(longitude) 0x%x 0x%x 0x%x 0x%x '%c'\n",ip[0],ip[1],ip[2],ip[3],state->ed[state->kml_exif[Exif_GPSInfo_GPSLongitudeRef_Index].dst])); D2(fprintf(debug_file, "(longitude) 0x%x 0x%x 0x%x 0x%x '%c'\n", ip[0], ip[1], ip[2], ip[3], state->ed[state->kml_exif[Exif_GPSInfo_GPSLongitudeRef_Index].dst]));
} }
if (state->kml_exif[Exif_GPSInfo_GPSLatitude_Index].ltag==Exif_GPSInfo_GPSLatitude) { // Exif_GPSInfo_GPSLatitude is present in template if (state->kml_exif[Exif_GPSInfo_GPSLatitude_Index].ltag == Exif_GPSInfo_GPSLatitude) { // Exif_GPSInfo_GPSLatitude is present in template
ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_GPSLatitude_Index].dst]); ip = (int*)&(state->ed[state->kml_exif[Exif_GPSInfo_GPSLatitude_Index].dst]);
latitude=__cpu_to_be32( ip[0])/(1.0*__cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2])/(60.0*__cpu_to_be32( ip[3])); latitude = __cpu_to_be32( ip[0]) / (1.0 * __cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2]) / (60.0 * __cpu_to_be32( ip[3]));
if ((state->kml_exif[Exif_GPSInfo_GPSLatitudeRef_Index].ltag==Exif_GPSInfo_GPSLatitudeRef) && if ((state->kml_exif[Exif_GPSInfo_GPSLatitudeRef_Index].ltag == Exif_GPSInfo_GPSLatitudeRef) &&
(state->ed[state->kml_exif[Exif_GPSInfo_GPSLatitudeRef_Index].dst] != 'N')) latitude=-latitude; (state->ed[state->kml_exif[Exif_GPSInfo_GPSLatitudeRef_Index].dst] != 'N')) latitude = -latitude;
D2(fprintf (debug_file,"(latitude) 0x%x 0x%x 0x%x 0x%x '%c'\n",ip[0],ip[1],ip[2],ip[3],state->ed[state->kml_exif[Exif_GPSInfo_GPSLatitudeRef_Index].dst]?'-':'+')); D2(fprintf(debug_file, "(latitude) 0x%x 0x%x 0x%x 0x%x '%c'\n", ip[0], ip[1], ip[2], ip[3], state->ed[state->kml_exif[Exif_GPSInfo_GPSLatitudeRef_Index].dst] ? '-' : '+'));
} }
/// altitude - will be modified/replaced later /// altitude - will be modified/replaced later
if (state->kml_exif[Exif_GPSInfo_GPSAltitude_Index].ltag==Exif_GPSInfo_GPSAltitude) { // Exif_GPSInfo_GPSAltitude is present in template if (state->kml_exif[Exif_GPSInfo_GPSAltitude_Index].ltag == Exif_GPSInfo_GPSAltitude) { // Exif_GPSInfo_GPSAltitude is present in template
ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_GPSAltitude_Index].dst]); ip = (int*)&(state->ed[state->kml_exif[Exif_GPSInfo_GPSAltitude_Index].dst]);
altitude=(1.0*__cpu_to_be32( ip[0]))/__cpu_to_be32( ip[1]); altitude = (1.0 * __cpu_to_be32( ip[0])) / __cpu_to_be32( ip[1]);
if ((state->kml_exif[Exif_GPSInfo_GPSAltitudeRef_Index].ltag==Exif_GPSInfo_GPSAltitudeRef) && if ((state->kml_exif[Exif_GPSInfo_GPSAltitudeRef_Index].ltag == Exif_GPSInfo_GPSAltitudeRef) &&
(state->ed[state->kml_exif[Exif_GPSInfo_GPSAltitudeRef_Index].dst] != '\0')) altitude=-altitude; (state->ed[state->kml_exif[Exif_GPSInfo_GPSAltitudeRef_Index].dst] != '\0')) altitude = -altitude;
D2(fprintf (debug_file,"(altitude) 0x%x 0x%x '%c'\n",ip[0],ip[1],state->ed[state->kml_exif[Exif_GPSInfo_GPSAltitudeRef_Index].dst])); D2(fprintf(debug_file, "(altitude) 0x%x 0x%x '%c'\n", ip[0], ip[1], state->ed[state->kml_exif[Exif_GPSInfo_GPSAltitudeRef_Index].dst]));
} }
D1(fprintf (debug_file,"longitude=%f, latitude=%f, altitude=%f\n",longitude, latitude, altitude)); D1(fprintf(debug_file, "longitude=%f, latitude=%f, altitude=%f\n", longitude, latitude, altitude));
/// Heading - no processing of "True/Magnetic" Exif_GPSInfo_CompassDirectionRef now (always M) /// Heading - no processing of "True/Magnetic" Exif_GPSInfo_CompassDirectionRef now (always M)
if (state->kml_exif[Exif_GPSInfo_CompassDirection_Index].ltag==Exif_GPSInfo_CompassDirection) { // Exif_GPSInfo_CompassDirection is present in template if (state->kml_exif[Exif_GPSInfo_CompassDirection_Index].ltag == Exif_GPSInfo_CompassDirection) { // Exif_GPSInfo_CompassDirection is present in template
ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_CompassDirection_Index].dst]); ip = (int*)&(state->ed[state->kml_exif[Exif_GPSInfo_CompassDirection_Index].dst]);
heading=(1.0*__cpu_to_be32( ip[0]))/__cpu_to_be32( ip[1]); heading = (1.0 * __cpu_to_be32( ip[0])) / __cpu_to_be32( ip[1]);
D2(fprintf (debug_file,"(heading) 0x%x 0x%x\n",ip[0],ip[1])); D2(fprintf(debug_file, "(heading) 0x%x 0x%x\n", ip[0], ip[1]));
} }
///Processing 'hacked' pitch and roll (made of Exif destination latitude/longitude) ///Processing 'hacked' pitch and roll (made of Exif destination latitude/longitude)
if (state->kml_exif[Exif_GPSInfo_CompassRoll_Index].ltag==Exif_GPSInfo_CompassRoll) { // Exif_GPSInfo_CompassRoll is present in template if (state->kml_exif[Exif_GPSInfo_CompassRoll_Index].ltag == Exif_GPSInfo_CompassRoll) { // Exif_GPSInfo_CompassRoll is present in template
ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_CompassRoll_Index].dst]); ip = (int*)&(state->ed[state->kml_exif[Exif_GPSInfo_CompassRoll_Index].dst]);
roll=__cpu_to_be32( ip[0])/(1.0*__cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2])/(60.0*__cpu_to_be32( ip[3])); roll = __cpu_to_be32( ip[0]) / (1.0 * __cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2]) / (60.0 * __cpu_to_be32( ip[3]));
if ((state->kml_exif[Exif_GPSInfo_CompassRollRef_Index].ltag==Exif_GPSInfo_CompassRollRef) && if ((state->kml_exif[Exif_GPSInfo_CompassRollRef_Index].ltag == Exif_GPSInfo_CompassRollRef) &&
(state->ed[state->kml_exif[Exif_GPSInfo_CompassRollRef_Index].dst] != EXIF_COMPASS_ROLL_ASCII[0])) roll=-roll; (state->ed[state->kml_exif[Exif_GPSInfo_CompassRollRef_Index].dst] != EXIF_COMPASS_ROLL_ASCII[0])) roll = -roll;
D2(fprintf (debug_file,"(roll) 0x%x 0x%x '%c'\n",ip[0],ip[1],state->ed[state->kml_exif[Exif_GPSInfo_CompassRollRef_Index].dst])); D2(fprintf(debug_file, "(roll) 0x%x 0x%x '%c'\n", ip[0], ip[1], state->ed[state->kml_exif[Exif_GPSInfo_CompassRollRef_Index].dst]));
} }
if (state->kml_exif[Exif_GPSInfo_CompassPitch_Index].ltag==Exif_GPSInfo_CompassPitch) { // Exif_GPSInfo_CompassPitch is present in template if (state->kml_exif[Exif_GPSInfo_CompassPitch_Index].ltag == Exif_GPSInfo_CompassPitch) { // Exif_GPSInfo_CompassPitch is present in template
ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_CompassPitch_Index].dst]); ip = (int*)&(state->ed[state->kml_exif[Exif_GPSInfo_CompassPitch_Index].dst]);
pitch=__cpu_to_be32( ip[0])/(1.0*__cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2])/(60.0*__cpu_to_be32( ip[3])); pitch = __cpu_to_be32( ip[0]) / (1.0 * __cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2]) / (60.0 * __cpu_to_be32( ip[3]));
if ((state->kml_exif[Exif_GPSInfo_CompassPitchRef_Index].ltag==Exif_GPSInfo_CompassPitchRef) && if ((state->kml_exif[Exif_GPSInfo_CompassPitchRef_Index].ltag == Exif_GPSInfo_CompassPitchRef) &&
(state->ed[state->kml_exif[Exif_GPSInfo_CompassPitchRef_Index].dst] != EXIF_COMPASS_PITCH_ASCII[0])) pitch=-pitch; (state->ed[state->kml_exif[Exif_GPSInfo_CompassPitchRef_Index].dst] != EXIF_COMPASS_PITCH_ASCII[0])) pitch = -pitch;
D2(fprintf (debug_file,"(pitch) 0x%x 0x%x '%c'\n",ip[0],ip[1],state->ed[state->kml_exif[Exif_GPSInfo_CompassPitchRef_Index].dst])); D2(fprintf(debug_file, "(pitch) 0x%x 0x%x '%c'\n", ip[0], ip[1], state->ed[state->kml_exif[Exif_GPSInfo_CompassPitchRef_Index].dst]));
} }
/// convert from GPS heading, pitch, roll to KML heading, tilt, roll /// convert from GPS heading, pitch, roll to KML heading, tilt, roll
tilt=pitch+90.0; tilt = pitch + 90.0;
if (tilt <0.0) tilt=0; if (tilt < 0.0) tilt = 0;
else if (tilt > 180.0) tilt=180.0; else if (tilt > 180.0) tilt = 180.0;
D2(fprintf (debug_file,"heading=%f, roll=%f, pitch=%f, tilt=%f\n",heading, roll, pitch, tilt)); D2(fprintf(debug_file, "heading=%f, roll=%f, pitch=%f, tilt=%f\n", heading, roll, pitch, tilt));
/// modify altitude /// modify altitude
altitude=(state->kml_height_mode?altitude:0.0)+state->kml_height; altitude = (state->kml_height_mode ? altitude : 0.0) + state->kml_height;
/// write to KML /// write to KML
fprintf(state->kml_file,"<PhotoOverlay>\n" \ fprintf(state->kml_file, "<PhotoOverlay>\n" \
" <shape>rectangle</shape>\n" \ " <shape>rectangle</shape>\n" \
" <TimeStamp>\n" \ " <TimeStamp>\n" \
" <when>%sT%02d:%02d:%05.2fZ</when>\n" \ " <when>%sT%02d:%02d:%05.2fZ</when>\n" \
" </TimeStamp>\n" \ " </TimeStamp>\n" \
" <Icon>\n" \ " <Icon>\n" \
" <href>%s</href>\n" \ " <href>%s</href>\n" \
" </Icon>\n" \ " </Icon>\n" \
" <Camera>\n" \ " <Camera>\n" \
" <longitude>%f</longitude>\n" \ " <longitude>%f</longitude>\n" \
" <latitude>%f</latitude>\n" \ " <latitude>%f</latitude>\n" \
" <altitude>%f</altitude>\n" \ " <altitude>%f</altitude>\n" \
" <heading>%f</heading>\n" \ " <heading>%f</heading>\n" \
" <tilt>%f</tilt>\n" \ " <tilt>%f</tilt>\n" \
" <roll>%f</roll>\n" \ " <roll>%f</roll>\n" \
" <altitudeMode>%s</altitudeMode>\n" \ " <altitudeMode>%s</altitudeMode>\n" \
" </Camera>\n" \ " </Camera>\n" \
" <ViewVolume>\n" \ " <ViewVolume>\n" \
" <leftFov>%f</leftFov>\n" \ " <leftFov>%f</leftFov>\n" \
" <rightFov>%f</rightFov>\n" \ " <rightFov>%f</rightFov>\n" \
" <bottomFov>%f</bottomFov>\n" \ " <bottomFov>%f</bottomFov>\n" \
" <topFov>%f</topFov>\n" \ " <topFov>%f</topFov>\n" \
" <near>%f</near>\n" \ " <near>%f</near>\n" \
" </ViewVolume>\n" \ " </ViewVolume>\n" \
"</PhotoOverlay>\n", \ "</PhotoOverlay>\n", \
datestr, hours, minutes, seconds, \ datestr, hours, minutes, seconds, \
filename, longitude,latitude,altitude,heading,tilt,roll,state->kml_height_mode?"absolute":"relativeToGround", \ filename, longitude, latitude, altitude, heading, tilt, roll, state->kml_height_mode ? "absolute" : "relativeToGround", \
-(state->kml_horHalfFov), state->kml_horHalfFov, -(state->kml_vertHalfFov), state->kml_vertHalfFov, state->kml_near); -(state->kml_horHalfFov), state->kml_horHalfFov, -(state->kml_vertHalfFov), state->kml_vertHalfFov, state->kml_near);
} }
} }
return 0; return 0;
} }
int camogm_end_kml(void){ int camogm_end_kml(void)
{
if (state->kml_file) { if (state->kml_file) {
fprintf (state->kml_file,"</Document>\n"); fprintf(state->kml_file, "</Document>\n");
fprintf (state->kml_file,"</kml>\n"); fprintf(state->kml_file, "</kml>\n");
fclose(state->kml_file); fclose(state->kml_file);
state->kml_file=NULL; state->kml_file = NULL;
} }
return 0; return 0;
} }
...@@ -15,74 +15,74 @@ void camogm_free_kml(void); ...@@ -15,74 +15,74 @@ void camogm_free_kml(void);
/* /*
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2"> <kml xmlns="http://earth.google.com/kml/2.2">
<Document> <Document>
<PhotoOverlay> <PhotoOverlay>
<TimeStamp> <TimeStamp>
<when>2007-01-14T21:05:02Z</when> <when>2007-01-14T21:05:02Z</when>
</TimeStamp> </TimeStamp>
<!-- inherited from Feature element --> <!-- inherited from Feature element -->
<name>...</name> <!-- string --> <name>...</name> <!-- string -->
<visibility>1</visibility> <!-- boolean --> <visibility>1</visibility> <!-- boolean -->
<open>0</open> <!-- boolean --> <open>0</open> <!-- boolean -->
<atom:author>...<atom:author> <!-- xmlns:atom --> <atom:author>...<atom:author> <!-- xmlns:atom -->
<atom:link>...</atom:link> <!-- xmlns:atom --> <atom:link>...</atom:link> <!-- xmlns:atom -->
<address>...</address> <!-- string --> <address>...</address> <!-- string -->
<AddressDetails xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">... <AddressDetails xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">...
</AddressDetails> <!-- string --> </AddressDetails> <!-- string -->
<phoneNumber>...</phoneNumber> <!-- string --> <phoneNumber>...</phoneNumber> <!-- string -->
<Snippet maxLines="2">...</Snippet> <!-- string --> <Snippet maxLines="2">...</Snippet> <!-- string -->
<description>...</description> <!-- string --> <description>...</description> <!-- string -->
<AbstractView>...</AbstractView> <!-- Camera or LookAt --> <AbstractView>...</AbstractView> <!-- Camera or LookAt -->
<TimePrimitive>...</TimePrimitive> <TimePrimitive>...</TimePrimitive>
<styleUrl>...</styleUrl> <!-- anyURI --> <styleUrl>...</styleUrl> <!-- anyURI -->
<StyleSelector>...</StyleSelector> <StyleSelector>...</StyleSelector>
<Region>...</Region> <Region>...</Region>
<ExtendedData>...</ExtendedData> <ExtendedData>...</ExtendedData>
<!-- inherited from Overlay element --> <!-- inherited from Overlay element -->
<color>ffffffff</color> <!-- kml:color --> <color>ffffffff</color> <!-- kml:color -->
<drawOrder>0</drawOrder> <!-- int --> <drawOrder>0</drawOrder> <!-- int -->
<Icon> <Icon>
<href>...</href> <!-- anyURI --> <href>...</href> <!-- anyURI -->
... ...
</Icon> </Icon>
<!-- specific to PhotoOverlay --> <!-- specific to PhotoOverlay -->
<rotation>0</rotation> <!-- kml:angle180 --> <rotation>0</rotation> <!-- kml:angle180 -->
<ViewVolume> <ViewVolume>
<leftFov>0</leftFov> <!-- kml:angle180 --> <leftFov>0</leftFov> <!-- kml:angle180 -->
<rightFov>0</rightFov> <!-- kml:angle180 --> <rightFov>0</rightFov> <!-- kml:angle180 -->
<bottomFov>0</bottomFov> <!-- kml:angle90 --> <bottomFov>0</bottomFov> <!-- kml:angle90 -->
<topFov>0</topFov> <!-- kml:angle90 --> <topFov>0</topFov> <!-- kml:angle90 -->
<near>0</near> <!-- double --> <near>0</near> <!-- double -->
</ViewVolume> </ViewVolume>
<ImagePyramid> <ImagePyramid>
<tileSize>256</tileSize> <!-- int --> <tileSize>256</tileSize> <!-- int -->
<maxWidth>...</maxWidth> <!-- int --> <maxWidth>...</maxWidth> <!-- int -->
<maxHeight>...</maxHeight> <!-- int --> <maxHeight>...</maxHeight> <!-- int -->
<gridOrigin>lowerLeft</gridOrigin> <!-- lowerLeft or upperLeft--> <gridOrigin>lowerLeft</gridOrigin> <!-- lowerLeft or upperLeft-->
</ImagePyramid> </ImagePyramid>
<Point> <Point>
<coordinates>...</coordinates> <!-- lon,lat[,alt] --> <coordinates>...</coordinates> <!-- lon,lat[,alt] -->
</Point> </Point>
<shape>rectangle</shape> <!-- kml:shape --> <shape>rectangle</shape> <!-- kml:shape -->
</PhotoOverlay> </PhotoOverlay>
<Camera id="ID"> <Camera id="ID">
<longitude>0</longitude> <!-- kml:angle180 --> <longitude>0</longitude> <!-- kml:angle180 -->
<latitude>0</latitude> <!-- kml:angle90 --> <latitude>0</latitude> <!-- kml:angle90 -->
<altitude>0</altitude> <!-- double --> <altitude>0</altitude> <!-- double -->
<heading>0</heading> <!-- kml:angle360 --> <heading>0</heading> <!-- kml:angle360 -->
<tilt>0</tilt> <!-- kml:anglepos180 --> <tilt>0</tilt> <!-- kml:anglepos180 -->
<roll>0</roll> <!-- kml:angle180 --> <roll>0</roll> <!-- kml:angle180 -->
<altitudeMode>clampToGround</altitudeMode> <altitudeMode>clampToGround</altitudeMode>
<!-- kml:altitudeModeEnum: relativeToGround, clampToGround, or absolute --> <!-- kml:altitudeModeEnum: relativeToGround, clampToGround, or absolute -->
</Camera> </Camera>
*/ */
/*!*************************************************************************** /*!***************************************************************************
*! FILE NAME : camogm_mov.c *! FILE NAME : camogm_mov.c
*! DESCRIPTION: Provides writing to file compatible with Apple Quicktime(R) for camogm *! DESCRIPTION: Provides writing to file compatible with Apple Quicktime(R) for camogm
*!TODO: Nothing yet here, will be added ASAP *!TODO: Nothing yet here, will be added ASAP
*! Copyright (C) 2007 Elphel, Inc. *! Copyright (C) 2007 Elphel, Inc.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify *! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by *! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or *! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version. *! (at your option) any later version.
*! *!
*! This program is distributed in the hope that it will be useful, *! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of *! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details. *! GNU General Public License for more details.
*! *!
*! You should have received a copy of the GNU General Public License *! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>. *! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! *!
*! $Log: camogm_mov.c,v $ *! $Log: camogm_mov.c,v $
*! Revision 1.2 2009/02/25 17:50:02 spectr_rain *! Revision 1.2 2009/02/25 17:50:02 spectr_rain
*! removed deprecated dependency *! removed deprecated dependency
*! *!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel *! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*! *!
*! *!
*! Revision 1.4 2008/04/11 23:09:33 elphel *! Revision 1.4 2008/04/11 23:09:33 elphel
*! modified to handle kml generation *! modified to handle kml generation
*! *!
*! Revision 1.3 2007/11/19 17:00:20 elphel *! Revision 1.3 2007/11/19 17:00:20 elphel
*! removed wrong dependency *! removed wrong dependency
*! *!
*! Revision 1.2 2007/11/19 03:23:21 elphel *! Revision 1.2 2007/11/19 03:23:21 elphel
*! 7.1.5.5 Added support for *.mov files in camogm. *! 7.1.5.5 Added support for *.mov files in camogm.
*! *!
*! Revision 1.1 2007/11/16 08:49:57 elphel *! Revision 1.1 2007/11/16 08:49:57 elphel
*! Initial release of camogm - program to record video/image to the camera hard drive (or other storage) *! Initial release of camogm - program to record video/image to the camera hard drive (or other storage)
*! *!
*/ */
//!Not all are needed, just copied from the camogm.c //!Not all are needed, just copied from the camogm.c
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
...@@ -55,415 +55,450 @@ ...@@ -55,415 +55,450 @@
#include <string.h> #include <string.h>
#include <netinet/in.h> /*little <-> big endian ?*/ #include <netinet/in.h> /*little <-> big endian ?*/
#include <sys/mman.h> /* mmap */ #include <sys/mman.h> /* mmap */
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <c313a.h> #include <c313a.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <ogg/ogg.h> // has to be before ogmstreams.h #include <ogg/ogg.h> // has to be before ogmstreams.h
#include "ogmstreams.h" // move it to <>? #include "ogmstreams.h" // move it to <>?
#include "camogm_mov.h" #include "camogm_mov.h"
#include "camogm.h" #include "camogm.h"
#define QUICKTIME_MIN_HEADER 0x300 // Quicktime header length (w/o index tables) enough to accomodate #define QUICKTIME_MIN_HEADER 0x300 // Quicktime header length (w/o index tables) enough to accomodate
// static data . // static data .
//! for the parser //! for the parser
const char hexStr[]="0123456789abcdef"; const char hexStr[] = "0123456789abcdef";
const char qtSourceFileName[]= "/etc/qt_source"; const char qtSourceFileName[] = "/etc/qt_source";
char comStr[1024]; char comStr[1024];
int width=1280; int width = 1280;
int height=1024; int height = 1024;
int nframes=100; int nframes = 100;
int sample_dur=80; int sample_dur = 80;
int samplesPerChunk=10; int samplesPerChunk = 10;
int framesize=80000; int framesize = 80000;
int timescale=600; int timescale = 600;
int * sizes; // array of frame sizes int * sizes; // array of frame sizes
int iPos; //!position in the string "iFile" int iPos; //!position in the string "iFile"
//int oPos; //!position in the string "oFile" //int oPos; //!position in the string "oFile"
int ofd; // output file descriptor (file opened by the caller) int ofd; // output file descriptor (file opened by the caller)
int iFileLen; int iFileLen;
char * q_template=NULL; char * q_template = NULL;
long headerSize=0; long headerSize = 0;
const char *iFile=NULL; const char *iFile = NULL;
int quicktime_template_parser (const char * i_iFile, //! now - string containing header template int quicktime_template_parser(const char * i_iFile, //! now - string containing header template
int i_ofd, //!output file descriptor (opened) int i_ofd, //!output file descriptor (opened)
int i_width, // width in pixels int i_width, // width in pixels
int i_height, int i_height,
int i_nframes, int i_nframes,
int i_sample_dur, int i_sample_dur,
int i_samplesPerChunk, int i_samplesPerChunk,
int i_framesize, int i_framesize,
int i_timescale, int i_timescale,
int * i_sizes, int * i_sizes,
int data_start // put zero if the header is written before data (no gap) int data_start // put zero if the header is written before data (no gap)
); );
void putBigEndian(unsigned long d, int l); void putBigEndian(unsigned long d, int l);
int parse_special(void); int parse_special(void);
int parse (int top); int parse(int top);
//! called first time format is changed to this one (only once) recording is stopped //! called first time format is changed to this one (only once) recording is stopped
//! read frame template from the file if it is not done yet //! read frame template from the file if it is not done yet
int camogm_init_mov(void) { int camogm_init_mov(void)
FILE* qt_header; {
int size; FILE* qt_header;
if ((qt_header= fopen (qtSourceFileName,"r"))==NULL) { int size;
D0(fprintf (debug_file,"Error opening Quicktime header template %s for reading\n", qtSourceFileName));
return -CAMOGM_FRAME_FILE_ERR; if ((qt_header = fopen(qtSourceFileName, "r")) == NULL) {
} D0(fprintf(debug_file, "Error opening Quicktime header template %s for reading\n", qtSourceFileName));
fseek(qt_header, 0, SEEK_END); return -CAMOGM_FRAME_FILE_ERR;
size=ftell(qt_header); }
//malloc(4*state->max_frames); fseek(qt_header, 0, SEEK_END);
if (!((q_template=malloc(size+1)))) { size = ftell(qt_header);
D0(fprintf (debug_file,"Could not allocate %d bytes of memory for Quicktime header template\n", (size+1))); //malloc(4*state->max_frames);
fclose(qt_header); if (!((q_template = malloc(size + 1)))) {
return -CAMOGM_FRAME_MALLOC ; D0(fprintf(debug_file, "Could not allocate %d bytes of memory for Quicktime header template\n", (size + 1)));
} fclose(qt_header);
fseek(qt_header, 0, SEEK_SET); //rewind return -CAMOGM_FRAME_MALLOC;
if (fread (q_template,size,1,qt_header)<1) { }
D0(fprintf (debug_file,"Could not read %d bytes of Quicktime header template from %s\n", (size+1),qtSourceFileName)); fseek(qt_header, 0, SEEK_SET); //rewind
free(q_template); if (fread(q_template, size, 1, qt_header) < 1) {
q_template=NULL; D0(fprintf(debug_file, "Could not read %d bytes of Quicktime header template from %s\n", (size + 1), qtSourceFileName));
fclose(qt_header); free(q_template);
return -CAMOGM_FRAME_FILE_ERR; q_template = NULL;
} fclose(qt_header);
q_template[size]=0; return -CAMOGM_FRAME_FILE_ERR;
return 0; }
q_template[size] = 0;
return 0;
} }
void camogm_free_mov(void) { void camogm_free_mov(void)
if (q_template) { {
free (q_template); if (q_template) {
q_template=NULL; free(q_template);
} q_template = NULL;
}
} }
int camogm_start_mov(void) { int camogm_start_mov(void)
{
//! allocate memory for the frame index table //! allocate memory for the frame index table
if (!((state->frame_lengths=malloc(4*state->max_frames)))) return -CAMOGM_FRAME_MALLOC ; if (!((state->frame_lengths = malloc(4 * state->max_frames)))) return -CAMOGM_FRAME_MALLOC;
//! open file for writing //! open file for writing
sprintf(state->path,"%s%010ld_%06ld.mov",state->path_prefix,state->frame_params.timestamp_sec,state->frame_params.timestamp_usec); sprintf(state->path, "%s%010ld_%06ld.mov", state->path_prefix, state->frame_params.timestamp_sec, state->frame_params.timestamp_usec);
if (((state->ivf=open(state->path,O_RDWR | O_CREAT, 0777)))<0){ if (((state->ivf = open(state->path, O_RDWR | O_CREAT, 0777))) < 0) {
D0(fprintf (debug_file, "Error opening %s for writing, returned %d, errno=%d\n", state->path,state->ivf,errno)); D0(fprintf(debug_file, "Error opening %s for writing, returned %d, errno=%d\n", state->path, state->ivf, errno));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
//!skip header (plus extra) //!skip header (plus extra)
//! Quicktime (and else?) - frame data start (0xff 0xd8...) //! Quicktime (and else?) - frame data start (0xff 0xd8...)
state->frame_data_start=QUICKTIME_MIN_HEADER+16+ 4*(state->max_frames)+ ( 4*(state->max_frames))/(state->frames_per_chunk); // 8 bytes for "skip" tag state->frame_data_start = QUICKTIME_MIN_HEADER + 16 + 4 * (state->max_frames) + ( 4 * (state->max_frames)) / (state->frames_per_chunk); // 8 bytes for "skip" tag
lseek(state->ivf, state->frame_data_start, SEEK_SET); lseek(state->ivf, state->frame_data_start, SEEK_SET);
return 0; return 0;
} }
int camogm_frame_mov(void){ int camogm_frame_mov(void)
int i,j; {
ssize_t iovlen,l; int i, j;
struct iovec chunks_iovec[7]; ssize_t iovlen, l;
l=0; struct iovec chunks_iovec[7];
for (i=0; i< (state->chunk_index)-1; i++) {
chunks_iovec[i].iov_base=state->packetchunks[i+1].chunk; l = 0;
chunks_iovec[i].iov_len= state->packetchunks[i+1].bytes; for (i = 0; i < (state->chunk_index) - 1; i++) {
l+=chunks_iovec[i].iov_len; chunks_iovec[i].iov_base = state->packetchunks[i + 1].chunk;
} chunks_iovec[i].iov_len = state->packetchunks[i + 1].bytes;
iovlen=writev(state->ivf,chunks_iovec, (state->chunk_index)-1); l += chunks_iovec[i].iov_len;
if (iovlen < l) { }
j=errno; iovlen = writev(state->ivf, chunks_iovec, (state->chunk_index) - 1);
D0(fprintf(debug_file,"writev error %d (returned %d, expected %d)\n",j,iovlen,l)); if (iovlen < l) {
close (state->ivf); j = errno;
state->ivf=-1; D0(fprintf(debug_file, "writev error %d (returned %d, expected %d)\n", j, iovlen, l));
return -CAMOGM_FRAME_FILE_ERR; close(state->ivf);
} state->ivf = -1;
state->frame_lengths[state->frameno]=l; return -CAMOGM_FRAME_FILE_ERR;
return 0; }
state->frame_lengths[state->frameno] = l;
return 0;
} }
//!move to the start of the file and insert generated header //!move to the start of the file and insert generated header
int camogm_end_mov(void){ int camogm_end_mov(void)
off_t l/*,he; {
unsigned char mdat_tag[8]; off_t l/*,he;
unsigned char skip_tag[]="\0\0\0\0skip"*/; unsigned char mdat_tag[8];
timescale=10000; //! frame period measured in 1/10000 of a second? unsigned char skip_tag[]="\0\0\0\0skip"*/;
//! that was in old code. If that works - try to switch to microseconds
l=lseek(state->ivf, 0, SEEK_CUR) - (state->frame_data_start)+8; //!4-byte length+"mdat" timescale = 10000; //! frame period measured in 1/10000 of a second?
//! that was in old code. If that works - try to switch to microseconds
l = lseek(state->ivf, 0, SEEK_CUR) - (state->frame_data_start) + 8; //!4-byte length+"mdat"
// lseek(state->ivf, state->frame_data_start, SEEK_SET); // lseek(state->ivf, state->frame_data_start, SEEK_SET);
// fill in the header in the beginning of the file // fill in the header in the beginning of the file
lseek(state->ivf, 0, SEEK_SET); lseek(state->ivf, 0, SEEK_SET);
quicktime_template_parser (q_template, //! now - string containing header template quicktime_template_parser(q_template, //! now - string containing header template
state->ivf, //!output file descriptor (opened) state->ivf, //!output file descriptor (opened)
state->width, //! width in pixels state->width, //! width in pixels
state->height, state->height,
state->frameno, state->frameno,
state->frame_period/ (1000000/timescale), state->frame_period / (1000000 / timescale),
state->frames_per_chunk, state->frames_per_chunk,
0, //!frame size - will look in the table 0, //!frame size - will look in the table
(int) ((float)timescale/(state->timescale)), (int)((float)timescale / (state->timescale)),
state->frame_lengths, //! array of frame lengths to build an index state->frame_lengths, //! array of frame lengths to build an index
state->frame_data_start state->frame_data_start
); );
#if 0 #if 0
//! now we need to overwrite last mdat tag in the header to the skip the gap, instead of the length 'mdat //! now we need to overwrite last mdat tag in the header to the skip the gap, instead of the length 'mdat
//! put length 'skip length 'mdat //! put length 'skip length 'mdat
he=lseek(state->ivf, 0, SEEK_CUR);// just after the original header end he = lseek(state->ivf, 0, SEEK_CUR); // just after the original header end
l=state->frame_data_start-he; //! should be >= l = state->frame_data_start - he; //! should be >=
D4(fprintf (debug_file,"Remaining gap between Quicktime header and the data is %d (it should be>=8) \n", (int) l)); D4(fprintf(debug_file, "Remaining gap between Quicktime header and the data is %d (it should be>=8) \n", (int)l));
lseek(state->ivf, he-8, SEEK_SET); lseek(state->ivf, he - 8, SEEK_SET);
read (state->ivf, mdat_tag,8); //!read calculated length+'mdat' tag read(state->ivf, mdat_tag, 8); //!read calculated length+'mdat' tag
lseek(state->ivf, state->frame_data_start-8, SEEK_SET); lseek(state->ivf, state->frame_data_start - 8, SEEK_SET);
write(state->ivf, mdat_tag,8); write(state->ivf, mdat_tag, 8);
skip_tag[0]=(l >> 24) & 0xff; skip_tag[0] = (l >> 24) & 0xff;
skip_tag[1]=(l >> 16) & 0xff; skip_tag[1] = (l >> 16) & 0xff;
skip_tag[2]=(l >> 8) & 0xff; skip_tag[2] = (l >> 8) & 0xff;
skip_tag[3]=(l ) & 0xff; skip_tag[3] = (l ) & 0xff;
lseek(state->ivf, he-8, SEEK_SET); lseek(state->ivf, he - 8, SEEK_SET);
write(state->ivf, skip_tag,8); write(state->ivf, skip_tag, 8);
#endif #endif
close (state->ivf); close(state->ivf);
state->ivf=-1; state->ivf = -1;
//! free memory used for index //! free memory used for index
if (state->frame_lengths) { if (state->frame_lengths) {
free(state->frame_lengths); free(state->frame_lengths);
state->frame_lengths=NULL; state->frame_lengths = NULL;
} }
return 0; return 0;
} }
/* /*
starts with the input file pointer just after the opening "{", starts with the input file pointer just after the opening "{",
and output file - at the beginning of it's output and output file - at the beginning of it's output
on exit - input pointer - after closing "}", output after it's output on exit - input pointer - after closing "}", output after it's output
*/ */
void putBigEndian(unsigned long d, int l) { void putBigEndian(unsigned long d, int l)
unsigned char od[4]; {
od[3]=d; unsigned char od[4];
od[2]=d >> 8;
od[1]=d >> 16; od[3] = d;
od[0]=d >> 24; od[2] = d >> 8;
if (l) write (ofd, &od[4-l], l); od[1] = d >> 16;
od[0] = d >> 24;
if (l) write(ofd, &od[4 - l], l);
// oPos+=l; // oPos+=l;
} }
//!temporary replacement for fgets to read from string //!temporary replacement for fgets to read from string
char * sfgets(char * str, int size, const char * stream, int * pos) { char * sfgets(char * str, int size, const char * stream, int * pos)
int l; {
const char * eol=strchr(&stream[*pos],'\n'); int l;
if (!eol) eol=stream+(strlen(stream)-1); //!pointer to last before \0 const char * eol = strchr(&stream[*pos], '\n');
l=(eol-stream)-(*pos);
if (!eol) eol = stream + (strlen(stream) - 1); //!pointer to last before \0
l = (eol - stream) - (*pos);
// if (l >= size) eol=stream+ (*pos+size-1); // if (l >= size) eol=stream+ (*pos+size-1);
if (l >= size) l=size-1; if (l >= size) l = size - 1;
memcpy(str, &stream[*pos],l); memcpy(str, &stream[*pos], l);
str[l]='\0'; str[l] = '\0';
*pos+=l; *pos += l;
return str; return str;
} }
int parse_special(void) { int parse_special(void)
{
time_t ltime;
int n,j,l; time_t ltime;
int n, j, l;
char str[256]; char str[256];
char c; char c;
int i=0; int i = 0;
int gap; int gap;
// while (((c=fgetc(infile))!=0x20) && (c!=0x09) && (c!=0x0a) && (c!=0x0d) && (c!=0x0) && (i<255) && ( feof(infile) == 0 )) str[i++]=c; // while (((c=fgetc(infile))!=0x20) && (c!=0x09) && (c!=0x0a) && (c!=0x0d) && (c!=0x0) && (i<255) && ( feof(infile) == 0 )) str[i++]=c;
while (((c=iFile[iPos++])!=0x20) && (c!=0x09) && (c!=0x0a) && (c!=0x0d) && (c!=0x0) && (i<255) && ( iPos<iFileLen )) str[i++]=c; while (((c = iFile[iPos++]) != 0x20) && (c != 0x09) && (c != 0x0a) && (c != 0x0d) && (c != 0x0) && (i < 255) && ( iPos < iFileLen )) str[i++] = c;
str[i]=0; str[i] = 0;
D4(fprintf (debug_file, "parse_special, str=!%s\n",str)); D4(fprintf(debug_file, "parse_special, str=!%s\n", str));
if (strcmp(str,"mdata")==0) {putBigEndian(headerSize, 4);return 0;} // will put zeroes on pass 1 if (strcmp(str, "mdata") == 0) {
if (strcmp(str,"height")==0) {putBigEndian(height,2);return 0;} putBigEndian(headerSize, 4); return 0;
if (strcmp(str,"width")==0) {putBigEndian(width,2);return 0;} } // will put zeroes on pass 1
if (strcmp(str,"width")==0) {putBigEndian(width,2);return 0;} if (strcmp(str, "height") == 0) {
if (strcmp(str,"nframes")==0) {putBigEndian(nframes,4);return 0;} putBigEndian(height, 2); return 0;
if (strcmp(str,"timescale")==0) {putBigEndian(timescale,4);return 0;} }
if (strcmp(str,"duration")==0) {putBigEndian(nframes*sample_dur,4);return 0;} if (strcmp(str, "width") == 0) {
if (strcmp(str,"frame_duration")==0) {putBigEndian(sample_dur,4);return 0;} putBigEndian(width, 2); return 0;
if (strcmp(str,"samples_chunk")==0) {putBigEndian(samplesPerChunk, 4);return 0;} // will put zeroes on pass 1 }
if (strcmp(str,"sample_sizes")==0) { if (strcmp(str, "width") == 0) {
if (sizes!=NULL) for (i=0;i<nframes;i++) putBigEndian(sizes[i],4); putBigEndian(width, 2); return 0;
else for (i=0;i<nframes;i++) putBigEndian(framesize,4); }
return 0; if (strcmp(str, "nframes") == 0) {
putBigEndian(nframes, 4); return 0;
}
if (strcmp(str, "timescale") == 0) {
putBigEndian(timescale, 4); return 0;
} }
if (strcmp(str,"chunk_offsets")==0) { if (strcmp(str, "duration") == 0) {
n= (nframes-1)/samplesPerChunk +1; putBigEndian(nframes * sample_dur, 4); return 0;
putBigEndian(n,4); }
if (sizes!=NULL) { if (strcmp(str, "frame_duration") == 0) {
l=0;j=0; putBigEndian(sample_dur, 4); return 0;
for (i=0; i<nframes;i++) { }
if (j==0) putBigEndian(headerSize+l,4); if (strcmp(str, "samples_chunk") == 0) {
j++; if (j>=samplesPerChunk) j=0; putBigEndian(samplesPerChunk, 4); return 0;
l+=sizes[i]; } // will put zeroes on pass 1
} if (strcmp(str, "sample_sizes") == 0) {
if (sizes != NULL) for (i = 0; i < nframes; i++) putBigEndian(sizes[i], 4);
} else for (i=0;i<n;i++) putBigEndian(headerSize+framesize*samplesPerChunk*i,4); else for (i = 0; i < nframes; i++) putBigEndian(framesize, 4);
return 0; return 0;
}
if (strcmp(str, "chunk_offsets") == 0) {
n = (nframes - 1) / samplesPerChunk + 1;
putBigEndian(n, 4);
if (sizes != NULL) {
l = 0; j = 0;
for (i = 0; i < nframes; i++) {
if (j == 0) putBigEndian(headerSize + l, 4);
j++; if (j >= samplesPerChunk) j = 0;
l += sizes[i];
}
} else for (i = 0; i < n; i++) putBigEndian(headerSize + framesize * samplesPerChunk * i, 4);
return 0;
} }
//! a hack - invlude length'skip if data position (header size is known and there is a gap) //! a hack - invlude length'skip if data position (header size is known and there is a gap)
if (strcmp(str,"data_size")==0) { if (strcmp(str, "data_size") == 0) {
gap=headerSize-lseek(ofd,0,SEEK_CUR)-8; gap = headerSize - lseek(ofd, 0, SEEK_CUR) - 8;
if (gap>0) { //!it should be exactly 0 if there is no gap or >8 if there is if (gap > 0) { //!it should be exactly 0 if there is no gap or >8 if there is
D4(fprintf (debug_file, "Inserting a skip tag to compensate for a gap (%d bytes) between the header and the frame data\n",gap)); D4(fprintf(debug_file, "Inserting a skip tag to compensate for a gap (%d bytes) between the header and the frame data\n", gap));
if (gap<8) { if (gap < 8) {
D0(fprintf (debug_file, "not enough room to insret 'skip' tag - %d (need 8)\n",gap)); D0(fprintf(debug_file, "not enough room to insret 'skip' tag - %d (need 8)\n", gap));
return -1; return -1;
} }
D4(fprintf (debug_file, "writing hex %x, %x bytes\n",gap,4)); D4(fprintf(debug_file, "writing hex %x, %x bytes\n", gap, 4));
putBigEndian(gap, 4); putBigEndian(gap, 4);
D4(fprintf (debug_file, "writing string <%s>\n","skip")); D4(fprintf(debug_file, "writing string <%s>\n", "skip"));
write (ofd, "skip", 4); write(ofd, "skip", 4);
lseek(ofd,gap-8,SEEK_CUR); //! lseek over the gap and proceed as before lseek(ofd, gap - 8, SEEK_CUR); //! lseek over the gap and proceed as before
} }
if (sizes!=NULL) { if (sizes != NULL) {
l=0; l = 0;
for (i=0; i<nframes;i++) l+=sizes[i]; for (i = 0; i < nframes; i++) l += sizes[i];
D4(fprintf (debug_file, "writing hex %x, %x bytes\n",l,4)); D4(fprintf(debug_file, "writing hex %x, %x bytes\n", l, 4));
putBigEndian(l,4); putBigEndian(l, 4);
} else putBigEndian(nframes * framesize,4); } else putBigEndian(nframes * framesize, 4);
return 0; return 0;
}
if (strcmp(str, "time") == 0) {
time(&ltime);
ltime += 2082801600; // 1970->1904// 31,557,600 seconds/year
putBigEndian(ltime, 4); return 0;
} }
if (strcmp(str,"time")==0) {
time (&ltime);
ltime+=2082801600; // 1970->1904// 31,557,600 seconds/year
putBigEndian(ltime,4);return 0;
}
return -1; return -1;
} }
int parse (int top) { // if top - will not include length int parse(int top) // if top - will not include length
{
long out_start, out_end; long out_start, out_end;
char c; char c;
unsigned long d,l; unsigned long d, l;
char * cp; char * cp;
D4(fprintf (debug_file,"parse(%x)\n",top));
D4(fprintf(debug_file, "parse(%x)\n", top));
// c=fgetc(infile); // c=fgetc(infile);
c=iFile[iPos++]; c = iFile[iPos++];
D5(fprintf (debug_file,"%c",c)); D5(fprintf(debug_file, "%c", c));
// out_start=ftell (outfile); // out_start=ftell (outfile);
// out_start=oPos; // out_start=oPos;
// out_start=oPos=lseek(ofd,0,SEEK_CUR); // out_start=oPos=lseek(ofd,0,SEEK_CUR);
out_start=lseek(ofd,0,SEEK_CUR); out_start = lseek(ofd, 0, SEEK_CUR);
if (!top) putBigEndian(0, 4); if (!top) putBigEndian(0, 4);
// while (( feof(infile) == 0 ) && (c!='}')) { // while (( feof(infile) == 0 ) && (c!='}')) {
while (( iPos<iFileLen ) && (c!='}')) { while (( iPos < iFileLen ) && (c != '}')) {
// skip white spaces strchr // skip white spaces strchr
if ((c!=' ') && (c!=0x9) && (c!=0xa) && (c!=0xd)) { if ((c != ' ') && (c != 0x9) && (c != 0xa) && (c != 0xd)) {
if (c=='!') { if (c == '!') {
if (parse_special()<0) return -1; if (parse_special() < 0) return -1;
} }
// children atoms // children atoms
else if (c=='{') { else if (c == '{') {
if (parse(0)<0) return -1; if (parse(0) < 0) return -1;
// skip comments // skip comments
// } else if (c=='#') fgets( comStr, sizeof(comStr), infile); // } else if (c=='#') fgets( comStr, sizeof(comStr), infile);
} else if (c=='#') sfgets( comStr, sizeof(comStr), iFile, &iPos); } else if (c == '#') sfgets( comStr, sizeof(comStr), iFile, &iPos);
else if (c=='\'') { else if (c == '\'') {
// fgets ( comStr, sizeof(comStr), infile); // fgets ( comStr, sizeof(comStr), infile);
sfgets( comStr, sizeof(comStr), iFile, &iPos); sfgets( comStr, sizeof(comStr), iFile, &iPos);
if ((cp=strchr(comStr,0x0a))!=NULL) cp[0]=0; if ((cp = strchr(comStr, 0x0a)) != NULL) cp[0] = 0;
if ((cp=strchr(comStr,0x0d))!=NULL) cp[0]=0; if ((cp = strchr(comStr, 0x0d)) != NULL) cp[0] = 0;
if ((cp=strchr(comStr,'#'))!=NULL) cp[0]=0; if ((cp = strchr(comStr, '#')) != NULL) cp[0] = 0;
cp=comStr+strlen(comStr)-1; cp = comStr + strlen(comStr) - 1;
while ((cp>comStr) && ((cp[0]==0x20) || (cp[0]==0x09))) cp--; while ((cp > comStr) && ((cp[0] == 0x20) || (cp[0] == 0x09))) cp--;
cp[1]=0; cp[1] = 0;
// fwrite (comStr,1, strlen(comStr),outfile); // fwrite (comStr,1, strlen(comStr),outfile);
// memcpy(&oFile[oPos],comStr,strlen(comStr)); // memcpy(&oFile[oPos],comStr,strlen(comStr));
write (ofd, comStr, strlen(comStr)); write(ofd, comStr, strlen(comStr));
D4(fprintf (debug_file, "writing string <%s>\n",comStr)); D4(fprintf(debug_file, "writing string <%s>\n", comStr));
} else if (strchr(hexStr,c)) { } else if (strchr(hexStr, c)) {
d=0; d = 0;
l=1; l = 1;
do { do {
d=(d<<4)+(strchr(hexStr,c)-hexStr); d = (d << 4) + (strchr(hexStr, c) - hexStr);
l++; l++;
} while (( iPos<iFileLen ) && (l<=8) && (strchr(hexStr,(c=iFile[iPos++]))) ); } while (( iPos < iFileLen ) && (l <= 8) && (strchr(hexStr, (c = iFile[iPos++]))) );
l=(l)>>1; l = (l) >> 1;
putBigEndian(d, l); putBigEndian(d, l);
D4(fprintf (debug_file, "writing hex %lx, %lx bytes\n",d,l)); D4(fprintf(debug_file, "writing hex %lx, %lx bytes\n", d, l));
} else if ((c=='}')){ } else if ((c == '}')) {
break; break;
} else { } else {
return -1; return -1;
} }
} }
// c=fgetc(infile); // c=fgetc(infile);
c=iFile[iPos++]; c = iFile[iPos++];
} }
// fread fseek ftell // fread fseek ftell
if (!top) { if (!top) {
// out_end=ftell (outfile); // out_end=ftell (outfile);
// out_end=oPos; // out_end=oPos;
out_end=lseek(ofd,0,SEEK_CUR); out_end = lseek(ofd, 0, SEEK_CUR);
// fseek (outfile,out_start,SEEK_SET); // fseek (outfile,out_start,SEEK_SET);
// oPos=out_start; // oPos=out_start;
lseek (ofd,out_start,SEEK_SET); lseek(ofd, out_start, SEEK_SET);
putBigEndian((out_end-out_start), 4); putBigEndian((out_end - out_start), 4);
// fseek (outfile,out_end,SEEK_SET); // fseek (outfile,out_end,SEEK_SET);
// oPos=out_end; // oPos=out_end;
lseek (state->ivf,out_end,SEEK_SET); lseek(state->ivf, out_end, SEEK_SET);
} }
return 0; return 0;
} }
int quicktime_template_parser (const char * i_iFile, //! now - string containing header template int quicktime_template_parser(const char * i_iFile, //! now - string containing header template
int i_ofd, //!output file descriptor (opened) int i_ofd, //!output file descriptor (opened)
int i_width, // width in pixels int i_width, // width in pixels
int i_height, int i_height,
int i_nframes, int i_nframes,
int i_sample_dur, int i_sample_dur,
int i_samplesPerChunk, int i_samplesPerChunk,
int i_framesize, int i_framesize,
int i_timescale, int i_timescale,
int * i_sizes, int * i_sizes,
int data_start // zero if dfata is not written yet (will be no gap) int data_start // zero if dfata is not written yet (will be no gap)
) { )
iFile= i_iFile; {
width= i_width; iFile = i_iFile;
height= i_height; width = i_width;
nframes= i_nframes; height = i_height;
sample_dur= i_sample_dur; nframes = i_nframes;
samplesPerChunk= i_samplesPerChunk; sample_dur = i_sample_dur;
framesize= i_framesize; samplesPerChunk = i_samplesPerChunk;
timescale= i_timescale; framesize = i_framesize;
sizes= i_sizes; timescale = i_timescale;
iPos=0; //!position in the string "iFile" sizes = i_sizes;
ofd= i_ofd; iPos = 0; //!position in the string "iFile"
iFileLen= strlen(iFile); ofd = i_ofd;
lseek (ofd,0,SEEK_SET); iFileLen = strlen(iFile);
if (data_start) headerSize=data_start; lseek(ofd, 0, SEEK_SET);
if (data_start) headerSize = data_start;
// int iFileLen=strlen(inFIle); // int iFileLen=strlen(inFIle);
D3(fprintf (debug_file, "PASS I\n")); D3(fprintf(debug_file, "PASS I\n"));
// while ( feof(infile) == 0 ) parse(1); // pass 1 // while ( feof(infile) == 0 ) parse(1); // pass 1
while ( iPos < iFileLen ) parse(1); // pass 1 while ( iPos < iFileLen ) parse(1); // pass 1
// headerSize=ftell (outfile); // headerSize=ftell (outfile);
// fseek (outfile,0,SEEK_SET); // rewind for pass 2 // fseek (outfile,0,SEEK_SET); // rewind for pass 2
// fseek (infile, 0,SEEK_SET); // // fseek (infile, 0,SEEK_SET); //
// headerSize=oPos; // headerSize=oPos;
if (!headerSize) headerSize=lseek(ofd,0,SEEK_CUR); if (!headerSize) headerSize = lseek(ofd, 0, SEEK_CUR);
iPos=0; iPos = 0;
// oPos=0; // oPos=0;
lseek (ofd,0,SEEK_SET); lseek(ofd, 0, SEEK_SET);
D3(fprintf (debug_file, "PASS II\n")); D3(fprintf(debug_file, "PASS II\n"));
// while ( feof(infile) == 0 ) parse(1); // pass 2 // while ( feof(infile) == 0 ) parse(1); // pass 2
while ( iPos < iFileLen ) parse(1); // pass 2 while ( iPos < iFileLen ) parse(1); // pass 2
//fclose (infile); //fclose (infile);
//fclose (outfile); //fclose (outfile);
......
/*!*************************************************************************** /*!***************************************************************************
*! FILE NAME : camogm_ogm.c *! FILE NAME : camogm_ogm.c
*! DESCRIPTION: Provides writing to ogm files for camogm *! DESCRIPTION: Provides writing to ogm files for camogm
*! Copyright (C) 2007 Elphel, Inc. *! Copyright (C) 2007 Elphel, Inc.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify *! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by *! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or *! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version. *! (at your option) any later version.
*! *!
*! This program is distributed in the hope that it will be useful, *! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of *! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details. *! GNU General Public License for more details.
*! *!
*! You should have received a copy of the GNU General Public License *! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>. *! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! *!
*! $Log: camogm_ogm.c,v $ *! $Log: camogm_ogm.c,v $
*! Revision 1.2 2009/02/25 17:50:02 spectr_rain *! Revision 1.2 2009/02/25 17:50:02 spectr_rain
*! removed deprecated dependency *! removed deprecated dependency
*! *!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel *! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*! *!
*! *!
*! Revision 1.2 2007/11/19 03:23:21 elphel *! Revision 1.2 2007/11/19 03:23:21 elphel
*! 7.1.5.5 Added support for *.mov files in camogm. *! 7.1.5.5 Added support for *.mov files in camogm.
*! *!
*! Revision 1.1 2007/11/16 08:49:58 elphel *! Revision 1.1 2007/11/16 08:49:58 elphel
*! Initial release of camogm - program to record video/image to the camera hard drive (or other storage) *! Initial release of camogm - program to record video/image to the camera hard drive (or other storage)
*! *!
*/ */
//!Not all are needed, just copied from the camogm.c //!Not all are needed, just copied from the camogm.c
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
...@@ -48,96 +48,100 @@ ...@@ -48,96 +48,100 @@
#include <string.h> #include <string.h>
#include <netinet/in.h> /*little <-> big endian ?*/ #include <netinet/in.h> /*little <-> big endian ?*/
#include <sys/mman.h> /* mmap */ #include <sys/mman.h> /* mmap */
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <c313a.h> #include <c313a.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <ogg/ogg.h> // has to be before ogmstreams.h #include <ogg/ogg.h> // has to be before ogmstreams.h
#include "ogmstreams.h" // move it to <>? #include "ogmstreams.h" // move it to <>?
#include "camogm_ogm.h" #include "camogm_ogm.h"
#include "camogm.h" #include "camogm.h"
//! may add something - called first time format is changed to this one (only once) recording is stopped //! may add something - called first time format is changed to this one (only once) recording is stopped
int camogm_init_ogm(void) { int camogm_init_ogm(void)
return 0; {
return 0;
} }
void camogm_free_ogm(void) { void camogm_free_ogm(void)
{
} }
int camogm_start_ogm(void) { int camogm_start_ogm(void)
char vendor[]= "ElphelOgm v 0.1"; {
int pos; char vendor[] = "ElphelOgm v 0.1";
stream_header sh; int pos;
char hdbuf[sizeof(sh)+1]; stream_header sh;
ogg_packet ogg_header; char hdbuf[sizeof(sh) + 1];
sprintf(state->path,"%s%010ld_%06ld.ogm",state->path_prefix,state->frame_params.timestamp_sec,state->frame_params.timestamp_usec); ogg_packet ogg_header;
if (!((state->vf=fopen(state->path,"w+"))) ){
D0(fprintf (debug_file, "Error opening %s for writing\n", state->path)); sprintf(state->path, "%s%010ld_%06ld.ogm", state->path_prefix, state->frame_params.timestamp_sec, state->frame_params.timestamp_usec);
return -CAMOGM_FRAME_FILE_ERR; if (!((state->vf = fopen(state->path, "w+"))) ) {
} D0(fprintf(debug_file, "Error opening %s for writing\n", state->path));
ogg_stream_init(&(state->os), state->serialno); return -CAMOGM_FRAME_FILE_ERR;
state->packetno = 0; }
memset(&sh, 0, sizeof(stream_header)); ogg_stream_init(&(state->os), state->serialno);
memcpy(sh.streamtype,"video",5); state->packetno = 0;
memcpy(sh.subtype, "MJPG", 4); memset(&sh, 0, sizeof(stream_header));
put_uint32(&sh.size, sizeof(sh)); memcpy(sh.streamtype, "video", 5);
memcpy(sh.subtype, "MJPG", 4);
put_uint32(&sh.size, sizeof(sh));
// put_uint64(&sh.time_unit, (ogg_int64_t) 10*state->frame_period); // put_uint64(&sh.time_unit, (ogg_int64_t) 10*state->frame_period);
put_uint64(&sh.time_unit, state->time_unit); put_uint64(&sh.time_unit, state->time_unit);
// put_uint64(&sh.samples_per_unit, 1); // put_uint64(&sh.samples_per_unit, 1);
put_uint64(&sh.samples_per_unit, (ogg_int64_t) state->timescale); put_uint64(&sh.samples_per_unit, (ogg_int64_t)state->timescale);
put_uint32(&sh.default_len, 1); put_uint32(&sh.default_len, 1);
put_uint32(&sh.buffersize, state->width*state->height); put_uint32(&sh.buffersize, state->width * state->height);
// put_uint16(&sh.bits_per_sample, 24); //? // put_uint16(&sh.bits_per_sample, 24); //?
put_uint16(&sh.bits_per_sample, 0); //? put_uint16(&sh.bits_per_sample, 0); //?
put_uint32(&sh.sh.video.width, state->width); put_uint32(&sh.sh.video.width, state->width);
put_uint32(&sh.sh.video.height, state->height); put_uint32(&sh.sh.video.height, state->height);
memcpy(&hdbuf[1], &sh, sizeof(sh)); memcpy(&hdbuf[1], &sh, sizeof(sh));
hdbuf[0]=1; hdbuf[0] = 1;
//! put it into Ogg stream //! put it into Ogg stream
ogg_header.packet = hdbuf; ogg_header.packet = hdbuf;
ogg_header.bytes = sizeof(sh)+1; ogg_header.bytes = sizeof(sh) + 1;
ogg_header.b_o_s = 1; ogg_header.b_o_s = 1;
ogg_header.e_o_s = 0; ogg_header.e_o_s = 0;
ogg_header.packetno = state->packetno++;; ogg_header.packetno = state->packetno++;;
ogg_header.granulepos =0; ogg_header.granulepos = 0;
ogg_stream_packetin(&(state->os), &ogg_header); ogg_stream_packetin(&(state->os), &ogg_header);
// while(ogg_stream_pageout(&(state->os), &(state->og))) { // while(ogg_stream_pageout(&(state->os), &(state->og))) {
while(ogg_stream_flush(&(state->os), &(state->og))) { while (ogg_stream_flush(&(state->os), &(state->og))) {
int i, j; int i, j;
if ((((i = fwrite(state->og.header, 1, state->og.header_len, state->vf))) != state->og.header_len) || if ((((i = fwrite(state->og.header, 1, state->og.header_len, state->vf))) != state->og.header_len) ||
(state->og.body_len && (((i = fwrite(state->og.body, 1, state->og.body_len, state->vf))) != state->og.body_len))) { (state->og.body_len && (((i = fwrite(state->og.body, 1, state->og.body_len, state->vf))) != state->og.body_len))) {
j=errno; j = errno;
D2(fprintf(debug_file,"\n%d %ld %ld\n",i,state->og.header_len,state->og.body_len)); D2(fprintf(debug_file, "\n%d %ld %ld\n", i, state->og.header_len, state->og.body_len));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
} }
//!create comment //!create comment
//!use fixed minimal one - hdbuf will be enough for that //!use fixed minimal one - hdbuf will be enough for that
memset(hdbuf, 0, sizeof(hdbuf)); memset(hdbuf, 0, sizeof(hdbuf));
hdbuf[0]=PACKET_TYPE_COMMENT; hdbuf[0] = PACKET_TYPE_COMMENT;
memcpy(&hdbuf[1], "vorbis",6); memcpy(&hdbuf[1], "vorbis", 6);
pos=7; pos = 7;
put_uint32(&hdbuf[pos], strlen(vendor)); put_uint32(&hdbuf[pos], strlen(vendor));
pos += 4; pos += 4;
strcpy(&hdbuf[pos], vendor); strcpy(&hdbuf[pos], vendor);
pos += strlen(vendor); pos += strlen(vendor);
put_uint32(&hdbuf[pos], 0); put_uint32(&hdbuf[pos], 0);
pos += 4; pos += 4;
hdbuf[pos++] = 1; hdbuf[pos++] = 1;
//! put it into Ogg stream //! put it into Ogg stream
ogg_header.packet = hdbuf; ogg_header.packet = hdbuf;
ogg_header.bytes = pos; ogg_header.bytes = pos;
ogg_header.b_o_s = 0; ogg_header.b_o_s = 0;
ogg_header.e_o_s = 0; ogg_header.e_o_s = 0;
ogg_header.packetno = state->packetno++;; ogg_header.packetno = state->packetno++;;
ogg_header.granulepos = 0; ogg_header.granulepos = 0;
ogg_stream_packetin(&(state->os), &ogg_header); ogg_stream_packetin(&(state->os), &ogg_header);
/* /*
while(ogg_stream_pageout(&(state->os), &(state->og))) { while(ogg_stream_pageout(&(state->os), &(state->og))) {
int i, j; int i, j;
...@@ -148,31 +152,33 @@ int camogm_start_ogm(void) { ...@@ -148,31 +152,33 @@ int camogm_start_ogm(void) {
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
} }
*/ */
//! calculate initial absolute granulepos (from 1970), then increment with each frame. Later try calculating granulepos of each frame //! calculate initial absolute granulepos (from 1970), then increment with each frame. Later try calculating granulepos of each frame
//! from the absolute time (actual timestamp) //! from the absolute time (actual timestamp)
state->granulepos= (ogg_int64_t) ( (((double) state->frame_params.timestamp_usec)+ state->granulepos = (ogg_int64_t)( (((double)state->frame_params.timestamp_usec) +
(((double) 1000000) * ((double)state->frame_params.timestamp_sec))) * (((double)1000000) * ((double)state->frame_params.timestamp_sec))) *
((double) 10) / ((double)10) /
((double) state->time_unit) * ((double)state->time_unit) *
((double) state->timescale)); ((double)state->timescale));
// state->frame_period=(state->this_frame_params.timestamp_usec - state->frame_params.timestamp_usec)+ // state->frame_period=(state->this_frame_params.timestamp_usec - state->frame_params.timestamp_usec)+
// 1000000*(state->this_frame_params.timestamp_sec - state->frame_params.timestamp_sec); // 1000000*(state->this_frame_params.timestamp_sec - state->frame_params.timestamp_sec);
// put_uint64(&sh.time_unit, (ogg_int64_t)((double)10000000.0 / (double)fps)); // put_uint64(&sh.time_unit, (ogg_int64_t)((double)10000000.0 / (double)fps));
//!Temporarily setting granulepos to 0 (suspect they do not process correctly 64 bits) //!Temporarily setting granulepos to 0 (suspect they do not process correctly 64 bits)
state->granulepos=0; state->granulepos = 0;
//! Here - Ogg stream started, both header and comment packets are sent out, next should be just data packets //! Here - Ogg stream started, both header and comment packets are sent out, next should be just data packets
return 0; return 0;
} }
int camogm_frame_ogm(void){ int camogm_frame_ogm(void)
int indx; {
elph_ogg_packet elp_packet; int indx;
elp_packet.bytes= 0; elph_ogg_packet elp_packet;
for (indx=0; indx<state->chunk_index; indx++) elp_packet.bytes+=state->packetchunks[indx].bytes;
elp_packet.packet=state->packetchunks; elp_packet.bytes = 0;
for (indx = 0; indx < state->chunk_index; indx++) elp_packet.bytes += state->packetchunks[indx].bytes;
elp_packet.packet = state->packetchunks;
//D(fprintf (debug_file,"elp_packet.bytes=0x%lx: elp_packet.packet=%p\n",elp_packet.bytes, elp_packet.packet)); //D(fprintf (debug_file,"elp_packet.bytes=0x%lx: elp_packet.packet=%p\n",elp_packet.bytes, elp_packet.packet));
/*D(fprintf (debug_file,"0:0x%lx: %p\n" \ /*D(fprintf (debug_file,"0:0x%lx: %p\n" \
"1:0x%lx: %p\n" \ "1:0x%lx: %p\n" \
...@@ -188,55 +194,56 @@ int camogm_frame_ogm(void){ ...@@ -188,55 +194,56 @@ int camogm_frame_ogm(void){
elp_packet.packet[4].bytes, elp_packet.packet[4].chunk, elp_packet.packet[4].bytes, elp_packet.packet[4].chunk,
elp_packet.packet[5].bytes, elp_packet.packet[5].chunk, elp_packet.packet[5].bytes, elp_packet.packet[5].chunk,
elp_packet.packet[6].bytes, elp_packet.packet[6].chunk)); elp_packet.packet[6].bytes, elp_packet.packet[6].chunk));
*/ */
elp_packet.b_o_s = 0; elp_packet.b_o_s = 0;
elp_packet.e_o_s = 0; elp_packet.e_o_s = 0;
elp_packet.packetno = state->packetno++;; elp_packet.packetno = state->packetno++;;
// tts[0]=state->frame_params.timestamp_usec; // tts[0]=state->frame_params.timestamp_usec;
// tts[1]=state->frame_params.timestamp_sec; // tts[1]=state->frame_params.timestamp_sec;
elp_packet.granulepos=state->granulepos; elp_packet.granulepos = state->granulepos;
//!TODO: If that works, calculate granulepos from timestamp for each frame //!TODO: If that works, calculate granulepos from timestamp for each frame
state->granulepos+= (ogg_int64_t) state->timescale; state->granulepos += (ogg_int64_t)state->timescale;
//D3(fprintf (debug_file,"_121_")); //D3(fprintf (debug_file,"_121_"));
ogg_stream_packetin_elph(&(state->os), &elp_packet); ogg_stream_packetin_elph(&(state->os), &elp_packet);
//D3(fprintf (debug_file,"_13_")); //D3(fprintf (debug_file,"_13_"));
while(ogg_stream_pageout(&(state->os), &(state->og))) { while (ogg_stream_pageout(&(state->os), &(state->og))) {
int i,j; int i, j;
if ((((i = fwrite(state->og.header, 1, state->og.header_len, state->vf))) != state->og.header_len) || if ((((i = fwrite(state->og.header, 1, state->og.header_len, state->vf))) != state->og.header_len) ||
(state->og.body_len && (((i = fwrite(state->og.body, 1, state->og.body_len, state->vf))) != state->og.body_len))) { (state->og.body_len && (((i = fwrite(state->og.body, 1, state->og.body_len, state->vf))) != state->og.body_len))) {
j=errno; j = errno;
D0(fprintf(debug_file,"\n%d %ld %ld\n",i,state->og.header_len,state->og.body_len)); D0(fprintf(debug_file, "\n%d %ld %ld\n", i, state->og.header_len, state->og.body_len));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
} }
return 0; return 0;
} }
//!Zero packets are OK, use them to end file with "last" turned on //!Zero packets are OK, use them to end file with "last" turned on
int camogm_end_ogm(void){ int camogm_end_ogm(void)
{
//! put zero-packet it into stream //! put zero-packet it into stream
ogg_packet ogg_header; ogg_packet ogg_header;
ogg_header.packet = NULL; ogg_header.packet = NULL;
ogg_header.bytes = 0; ogg_header.bytes = 0;
ogg_header.b_o_s = 0; ogg_header.b_o_s = 0;
ogg_header.e_o_s = 1; ogg_header.e_o_s = 1;
ogg_header.packetno = state->packetno++; ogg_header.packetno = state->packetno++;
ogg_header.granulepos = ++(state->granulepos); ogg_header.granulepos = ++(state->granulepos);
ogg_stream_packetin(&(state->os), &ogg_header); //!+++++++++++++++++++++++++++++++++++++++++++++++++++++ ogg_stream_packetin(&(state->os), &ogg_header); //!+++++++++++++++++++++++++++++++++++++++++++++++++++++
while(ogg_stream_flush(&(state->os), &(state->og))) { while (ogg_stream_flush(&(state->os), &(state->og))) {
int i, j; int i, j;
if ((((i = fwrite(state->og.header, 1, state->og.header_len, state->vf))) != state->og.header_len) || if ((((i = fwrite(state->og.header, 1, state->og.header_len, state->vf))) != state->og.header_len) ||
(state->og.body_len && (((i = fwrite(state->og.body, 1, state->og.body_len, state->vf))) != state->og.body_len))) { (state->og.body_len && (((i = fwrite(state->og.body, 1, state->og.body_len, state->vf))) != state->og.body_len))) {
j=errno; j = errno;
D0(fprintf(debug_file,"\n%d %ld %ld\n",i,state->og.header_len,state->og.body_len)); D0(fprintf(debug_file, "\n%d %ld %ld\n", i, state->og.header_len, state->og.body_len));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
} }
return 0; return 0;
} }
......
...@@ -4,33 +4,33 @@ ...@@ -4,33 +4,33 @@
/* /*
* Taken from http://tobias.everwicked.com/packfmt.htm * Taken from http://tobias.everwicked.com/packfmt.htm
* *
First packet (header) First packet (header)
--------------------- ---------------------
pos | content | description pos | content | description
-------+-------------------------+---------------------------------- -------+-------------------------+----------------------------------
0x0000 | 0x01 | indicates 'header packet' 0x0000 | 0x01 | indicates 'header packet'
-------+-------------------------+---------------------------------- -------+-------------------------+----------------------------------
0x0001 | stream_header | the size is indicated in the 0x0001 | stream_header | the size is indicated in the
| | size member | | size member
Second packet (comment) Second packet (comment)
----------------------- -----------------------
pos | content | description pos | content | description
-------+-------------------------+---------------------------------- -------+-------------------------+----------------------------------
0x0000 | 0x03 | indicates 'comment packet' 0x0000 | 0x03 | indicates 'comment packet'
-------+-------------------------+---------------------------------- -------+-------------------------+----------------------------------
0x0001 | data | see vorbis doc on www.xiph.org 0x0001 | data | see vorbis doc on www.xiph.org
Data packets Data packets
------------ ------------
pos | content | description pos | content | description
---------+-------------------------+---------------------------------- ---------+-------------------------+----------------------------------
0x0000 | Bit0 0 | indicates data packet 0x0000 | Bit0 0 | indicates data packet
| Bit1 Bit 2 of lenbytes | | Bit1 Bit 2 of lenbytes |
| Bit2 unused | | Bit2 unused |
| Bit3 keyframe | | Bit3 keyframe |
...@@ -38,14 +38,14 @@ ...@@ -38,14 +38,14 @@
| Bit5 unused | | Bit5 unused |
| Bit6 Bit 0 of lenbytes | | Bit6 Bit 0 of lenbytes |
| Bit7 Bit 1 of lenbytes | | Bit7 Bit 1 of lenbytes |
---------+-------------------------+---------------------------------- ---------+-------------------------+----------------------------------
0x0001 | LowByte | Length of this packet in samples 0x0001 | LowByte | Length of this packet in samples
| ... | (frames for video, samples for | ... | (frames for video, samples for
| HighByte | audio, 1ms units for text) | HighByte | audio, 1ms units for text)
---------+-------------------------+---------------------------------- ---------+-------------------------+----------------------------------
0x0001+ | data | packet contents 0x0001+ | data | packet contents
lenbytes | | lenbytes | |
* *
* *
*/ */
...@@ -53,29 +53,29 @@ ...@@ -53,29 +53,29 @@
//// OggDS headers //// OggDS headers
// Header for the new header format // Header for the new header format
typedef struct stream_header_video { typedef struct stream_header_video {
ogg_int32_t width; ogg_int32_t width;
ogg_int32_t height; ogg_int32_t height;
} stream_header_video; } stream_header_video;
typedef struct stream_header_audio { typedef struct stream_header_audio {
ogg_int16_t channels; ogg_int16_t channels;
ogg_int16_t blockalign; ogg_int16_t blockalign;
ogg_int32_t avgbytespersec; ogg_int32_t avgbytespersec;
} stream_header_audio; } stream_header_audio;
typedef struct stream_header { typedef struct stream_header {
char streamtype[8]; char streamtype[8];
char subtype[4]; char subtype[4];
ogg_int32_t size; // size of the structure ogg_int32_t size; // size of the structure
ogg_int64_t time_unit; // in reference time ogg_int64_t time_unit; // in reference time
ogg_int64_t samples_per_unit; ogg_int64_t samples_per_unit;
ogg_int32_t default_len; // in media time ogg_int32_t default_len; // in media time
ogg_int32_t buffersize; ogg_int32_t buffersize;
// ogg_int16_t bits_per_sample; // ogg_int16_t bits_per_sample;
ogg_int32_t bits_per_sample; ogg_int32_t bits_per_sample;
union { union {
// Video specific // Video specific
...@@ -85,24 +85,24 @@ typedef struct stream_header { ...@@ -85,24 +85,24 @@ typedef struct stream_header {
} sh; } sh;
// ogg_int16_t padding; // ogg_int16_t padding;
ogg_int32_t padding; ogg_int32_t padding;
} stream_header; } stream_header;
typedef struct old_stream_header { typedef struct old_stream_header {
char streamtype[8]; char streamtype[8];
char subtype[4]; char subtype[4];
ogg_int32_t size; // size of the structure ogg_int32_t size; // size of the structure
ogg_int64_t time_unit; // in reference time ogg_int64_t time_unit; // in reference time
ogg_int64_t samples_per_unit; ogg_int64_t samples_per_unit;
ogg_int32_t default_len; // in media time ogg_int32_t default_len; // in media time
ogg_int32_t buffersize; ogg_int32_t buffersize;
ogg_int16_t bits_per_sample; ogg_int16_t bits_per_sample;
ogg_int16_t padding; ogg_int16_t padding;
union { union {
// Video specific // Video specific
...@@ -121,4 +121,4 @@ typedef struct old_stream_header { ...@@ -121,4 +121,4 @@ typedef struct old_stream_header {
#define PACKET_LEN_BITS2 0x02 #define PACKET_LEN_BITS2 0x02
#define PACKET_IS_SYNCPOINT 0x08 #define PACKET_IS_SYNCPOINT 0x08
#endif /* __OGGSTREAMS_H */ #endif /* __OGGSTREAMS_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment