Commit 38d28dd5 authored by Mikhail Karpenko's avatar Mikhail Karpenko

Initial commit of unmodified application

parents
This diff is collapsed.
AXIS_USABLE_LIBS = UCLIBC GLIBC
AXIS_AUTO_DEPEND = yes
include $(AXIS_TOP_DIR)/tools/build/Rules.axis
INSTDIR = $(prefix)/usr/local/sbin/
OTHERDIR = $(prefix)/usr/html/
PHPDIR = $(prefix)/usr/html/
INSTMODE = 0755
INSTOTHER = 0644
INSTPHP = 0644
INSTOWNER = root
INSTGROUP = root
INCDIR = $(prefix)/include
PROGS = camogm
PHPFILES = camogmstate.php
SRCS = camogm.c camogm_ogm.c camogm_jpeg.c camogm_mov.c camogm_kml.c
OBJS = camogm.o camogm_ogm.o camogm_jpeg.o camogm_mov.o camogm_kml.o
CFLAGS += -Wall -I$(INCDIR) -I$(AXIS_KERNEL_DIR)/include
all: $(PROGS)
$(PROGS): $(OBJS)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -logg -o $@
cris-strip -s $@
install: $(PROGS)
$(INSTALL) -d $(INSTDIR)
$(INSTALL) -m $(INSTMODE) -o $(INSTOWNER) -g $(INSTGROUP) $(PROGS) $(INSTDIR)
#already installed with ccam.cgi
$(INSTALL) -m $(INSTMODE) -o $(INSTOWNER) -g $(INSTGROUP) qt_source $(prefix)/etc
$(INSTALL) -m $(INSTPHP) -o $(INSTOWNER) -g $(INSTGROUP) $(PHPFILES) $(PHPDIR)
clean:
rm -rf $(PROGS) *.o *~
configsubs:
#### elphel-apps-camogm
*camogm* is a program from Elphel user space applications set. It is used to write captured video/images/audio from camera memory buffer to file system using Ogg container.
This diff is collapsed.
#define CAMOGM_FRAME_NOT_READY 1 // frame pointer valid, but not yet acquired
#define CAMOGM_FRAME_INVALID 2 // invalid frame pointer
#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_BROKEN 5 // frame broken (buffer overrun)
#define CAMOGM_FRAME_FILE_ERR 6 // error with file I/O
#define CAMOGM_FRAME_MALLOC 7 // can not allocate memory
#define CAMOGM_TOO_EARLY 8 // too early to start, waiting for particular timestamp
#define CAMOGM_FRAME_OTHER 9 // other errors
#define CAMOGM_FORMAT_NONE 0 // no video output
#define CAMOGM_FORMAT_OGM 1 // output as Ogg Media file
#define CAMOGM_FORMAT_JPEG 2 // output as individual JPEG files
#define CAMOGM_FORMAT_MOV 3 // output as Apple Quicktime
#define D(x) {if (debug_file && debug_level){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 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 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 D6(x) {if (debug_file && (debug_level > 5)){x;fflush(debug_file);}}
//#define DD(x)
#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
#define JPEG_HEADER_MAXSIZE 0x300 // will not change
//#include "camogm_exif.h"
#include <asm/elphel/exifa.h>
/*
#define Exif_Photo_DateTimeOriginal 0x19003
#define Exif_GPSInfo_GPSLatitudeRef 0x20001
#define Exif_GPSInfo_GPSLatitude 0x20002
#define Exif_GPSInfo_GPSLongitudeRef 0x20003
#define Exif_GPSInfo_GPSLongitude 0x20004
#define Exif_GPSInfo_GPSAltitudeRef 0x20005
#define Exif_GPSInfo_GPSAltitude 0x20006
#define Exif_GPSInfo_GPSTimeStamp 0x20007
#define Exif_GPSInfo_GPSDateStamp 0x2001D
#define Exif_GPSInfo_CompassDirectionRef 0x20010
#define Exif_GPSInfo_CompassDirection 0x20011
#define Exif_GPSInfo_CompassPitchRef 0x20013
#define Exif_GPSInfo_CompassPitch 0x20014
#define Exif_GPSInfo_CompassRollRef 0x20015
#define Exif_GPSInfo_CompassRoll 0x20016
*/
/*
/// Exif data (variable, stored with each frame) used for KML (not only)
#define Exif_Image_ImageDescription_Index 0x00
#define Exif_Photo_DateTimeOriginal_Index 0x01
#define Exif_Photo_SubSecTimeOriginal_Index 0x02
#define Exif_GPSInfo_GPSLatitudeRef_Index 0x03
#define Exif_GPSInfo_GPSLatitude_Index 0x04
#define Exif_GPSInfo_GPSLongitudeRef_Index 0x05
#define Exif_GPSInfo_GPSLongitude_Index 0x06
#define Exif_GPSInfo_GPSAltitudeRef_Index 0x07
#define Exif_GPSInfo_GPSAltitude_Index 0x08
#define Exif_GPSInfo_GPSTimeStamp_Index 0x09
#define Exif_GPSInfo_GPSDateStamp_Index 0x0a
#define Exif_GPSInfo_CompassDirectionRef_Index 0x0b
#define Exif_GPSInfo_CompassDirection_Index 0x0c
#define Exif_GPSInfo_CompassPitchRef_Index 0x0d
#define Exif_GPSInfo_CompassPitch_Index 0x0e
#define Exif_GPSInfo_CompassRollRef_Index 0x0f
#define Exif_GPSInfo_CompassRoll_Index 0x10
#define ExifKmlNumber 0x11
*/
typedef struct {
int segment_duration;
int segment_length;
int greedy;
int ignore_fps;
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[300];
int cirbuf_rp; //!-1 - invalid
int fd_circ; //! file descriptor for circbuf
int fd_head; //! file descriptor for JPEG header
// int fd_sens; //! file descriptor for sensor/compressor parameters
int fd_fparmsall; //! file descriptor for sensor/compressor parameters
int fd_exif; //! file descriptor for Exif data
int head_size; //! JPEG header size
char jpegHeader [JPEG_HEADER_MAXSIZE];
int metadata_start;
struct interframe_params_t frame_params;
struct interframe_params_t this_frame_params;
int jpeg_len;
int frame_period ; //!in microseconds (1/10 of what is needed for the Ogm header)
int width;
int height;
int starting;
int running;
int last_error_code;
ogg_stream_state os;
ogg_page og;
ogg_packet op;
elph_ogg_packet eop;
int serialno;
ogg_int64_t packetno;
ogg_int64_t granulepos;
FILE* vf; //! video file (ogm, fopen)
int ivf; //! video file (jpeg, mov - open)
int last; //last packet in a file
int exif; // 1 - calculate and include Exif headers in each frame
// exif_pointers_t ep;
// int exifValid;
int exifSize; //signed
unsigned char ed[MAX_EXIF_SIZE];
int circ_buff_size;
int senspars_size;
char debug_name[256];
// FILE* debug_file;
int set_samples_per_unit;
double timescale; //! current timescale, default 1.0
double set_timescale;
double start_after_timestamp; /// delay recording start to after frame timestamp
int max_frames;
int set_max_frames;
int frames_per_chunk;
int set_frames_per_chunk; // quicktime - index for fast forward?
int frameno;
int* frame_lengths;
off_t frame_data_start; //! Quicktime (and else?) - frame data start (0xff 0xd8...)
ogg_int64_t time_unit;
int formats; //! bitmask of used (initialized) formats
int format; //! output file format
int set_format; //! output format to set (will be updated after stop)
elph_packet_chunk packetchunks[7];
int chunk_index;
int buf_overruns;
int buf_min;
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)
//! if negetive - -(interval between frames in seconds)
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
//kml stuff
int kml_enable; //! enable KML file generation
int kml_used; //! KML file generation used (change only when stopped)
char kml_path[300]; //! full path for KML file (if any)
FILE* kml_file; //! stream to write kml file
double kml_horHalfFov; //! half horizontal Fov (degrees)
double kml_vertHalfFov; //! half vertical Fov (degrees)
double kml_near; //! Use in KML "near" parameter (<=0 - don't use it)
int kml_height_mode; //! 1 - actual, 0 - ground
double kml_height; //! extra height to add
int kml_period; //! generate PhotoOverlay for each kml_period seconds;
int kml_last_ts; //! last generated kml file timestamp
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
} camogm_state;
extern int debug_level;
extern FILE* debug_file;
extern camogm_state * state;
void put_uint16(void *buf, u_int16_t val);
void put_uint32(void *buf, u_int32_t val);
void put_uint64(void *buf, u_int64_t val);
unsigned long getGPValue(unsigned long GPNumber);
void setGValue(unsigned long GNumber, unsigned long value);
int waitDaemonEnabled(int daemonBit); // <0 - use default
int isDaemonEnabled(int daemonBit); // <0 - use default
/*!***************************************************************************
*! FILE NAME : camogm_jpeg.c
*! DESCRIPTION: Provides writing to series of individual JPEG files for camogm
*! Copyright (C) 2007 Elphel, Inc.
*! -----------------------------------------------------------------------------**
*! 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
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*!
*! $Log: camogm_jpeg.c,v $
*! Revision 1.2 2009/02/25 17:50:51 spectr_rain
*! removed deprecated dependency
*!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*!
*!
*! Revision 1.3 2008/04/11 23:09:33 elphel
*! modified to handle kml generation
*!
*! Revision 1.2 2007/11/19 03:23:21 elphel
*! 7.1.5.5 Added support for *.mov files in camogm.
*!
*! 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)
*!
*/
//!Not all are needed, just copied from the camogm.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
//#include <ctype.h>
//#include <getopt.h>
#include <time.h>
#include <string.h>
#include <netinet/in.h> /*little <-> big endian ?*/
#include <sys/mman.h> /* mmap */
#include <sys/ioctl.h>
#include <asm/elphel/c313a.h>
#include <asm/byteorder.h>
#include <ogg/ogg.h> // has to be before ogmstreams.h
#include "ogmstreams.h" // move it to <>?
#include "camogm_jpeg.h"
#include "camogm.h"
//! may add something - called first time format is changed to this one (only once) recording is stopped
int camogm_init_jpeg(void) {
return 0;
}
void camogm_free_jpeg(void) {
}
int camogm_start_jpeg(void) {
//!TODO: make directory if it does not exist (find the last "/" in the state->path
char * slash;
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,'/');
D2(fprintf (debug_file, "camogm_start_jpeg\n"));
if (slash) {
D3(fprintf (debug_file, "Full path %s\n", state->path));
slash[0]='\0'; //! truncate path to the directory name
D3(fprintf (debug_file, "directory path %s\n", state->path));
rslt=mkdir(state->path, 0777);
D3(fprintf (debug_file, "mkdir (%s, 0777) returned %d, errno=%d\n", state->path, rslt, errno));
if ((rslt<0) && (errno != EEXIST)) { // already exists is OK
D0(fprintf (debug_file, "Error creating directory %s, errno=%d\n", state->path, errno));
return -CAMOGM_FRAME_FILE_ERR;
}
}
return 0;
}
int camogm_frame_jpeg(void){
int i,j;
// int fd;
ssize_t iovlen,l;
struct iovec chunks_iovec[7];
l=0;
for (i=0; i< (state->chunk_index)-1; i++) {
chunks_iovec[i].iov_base=state->packetchunks[i+1].chunk;
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);
// 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
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));
return -CAMOGM_FRAME_FILE_ERR;
}
iovlen=writev(state->ivf,chunks_iovec, (state->chunk_index)-1);
if (iovlen < l) {
j=errno;
D0(fprintf(debug_file,"writev error %d (returned %d, expected %d)\n",j,iovlen,l));
close (state->ivf);
return -CAMOGM_FRAME_FILE_ERR;
}
close (state->ivf);
return 0;
}
int camogm_end_jpeg(void){
return 0;
}
int camogm_init_jpeg(void);
int camogm_start_jpeg(void);
int camogm_frame_jpeg(void);
int camogm_end_jpeg(void);
void camogm_free_jpeg(void);
This diff is collapsed.
int camogm_init_kml(void);
int camogm_start_kml(void);
int camogm_frame_kml(void);
int camogm_end_kml(void);
void camogm_free_kml(void);
/*
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
<Document>
<PhotoOverlay>
<TimeStamp>
<when>2007-01-14T21:05:02Z</when>
</TimeStamp>
<!-- inherited from Feature element -->
<name>...</name> <!-- string -->
<visibility>1</visibility> <!-- boolean -->
<open>0</open> <!-- boolean -->
<atom:author>...<atom:author> <!-- xmlns:atom -->
<atom:link>...</atom:link> <!-- xmlns:atom -->
<address>...</address> <!-- string -->
<AddressDetails xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">...
</AddressDetails> <!-- string -->
<phoneNumber>...</phoneNumber> <!-- string -->
<Snippet maxLines="2">...</Snippet> <!-- string -->
<description>...</description> <!-- string -->
<AbstractView>...</AbstractView> <!-- Camera or LookAt -->
<TimePrimitive>...</TimePrimitive>
<styleUrl>...</styleUrl> <!-- anyURI -->
<StyleSelector>...</StyleSelector>
<Region>...</Region>
<ExtendedData>...</ExtendedData>
<!-- inherited from Overlay element -->
<color>ffffffff</color> <!-- kml:color -->
<drawOrder>0</drawOrder> <!-- int -->
<Icon>
<href>...</href> <!-- anyURI -->
...
</Icon>
<!-- specific to PhotoOverlay -->
<rotation>0</rotation> <!-- kml:angle180 -->
<ViewVolume>
<leftFov>0</leftFov> <!-- kml:angle180 -->
<rightFov>0</rightFov> <!-- kml:angle180 -->
<bottomFov>0</bottomFov> <!-- kml:angle90 -->
<topFov>0</topFov> <!-- kml:angle90 -->
<near>0</near> <!-- double -->
</ViewVolume>
<ImagePyramid>
<tileSize>256</tileSize> <!-- int -->
<maxWidth>...</maxWidth> <!-- int -->
<maxHeight>...</maxHeight> <!-- int -->
<gridOrigin>lowerLeft</gridOrigin> <!-- lowerLeft or upperLeft-->
</ImagePyramid>
<Point>
<coordinates>...</coordinates> <!-- lon,lat[,alt] -->
</Point>
<shape>rectangle</shape> <!-- kml:shape -->
</PhotoOverlay>
<Camera id="ID">
<longitude>0</longitude> <!-- kml:angle180 -->
<latitude>0</latitude> <!-- kml:angle90 -->
<altitude>0</altitude> <!-- double -->
<heading>0</heading> <!-- kml:angle360 -->
<tilt>0</tilt> <!-- kml:anglepos180 -->
<roll>0</roll> <!-- kml:angle180 -->
<altitudeMode>clampToGround</altitudeMode>
<!-- kml:altitudeModeEnum: relativeToGround, clampToGround, or absolute -->
</Camera>
*/
This diff is collapsed.
int camogm_init_mov(void);
int camogm_start_mov(void);
int camogm_frame_mov(void);
int camogm_end_mov(void);
void camogm_free_mov(void);
/*!***************************************************************************
*! FILE NAME : camogm_ogm.c
*! DESCRIPTION: Provides writing to ogm files for camogm
*! Copyright (C) 2007 Elphel, Inc.
*! -----------------------------------------------------------------------------**
*! 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
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*!
*! $Log: camogm_ogm.c,v $
*! Revision 1.2 2009/02/25 17:50:02 spectr_rain
*! removed deprecated dependency
*!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*!
*!
*! Revision 1.2 2007/11/19 03:23:21 elphel
*! 7.1.5.5 Added support for *.mov files in camogm.
*!
*! 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)
*!
*/
//!Not all are needed, just copied from the camogm.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
//#include <ctype.h>
//#include <getopt.h>
#include <time.h>
#include <string.h>
#include <netinet/in.h> /*little <-> big endian ?*/
#include <sys/mman.h> /* mmap */
#include <sys/ioctl.h>
#include <asm/elphel/c313a.h>
#include <asm/byteorder.h>
#include <ogg/ogg.h> // has to be before ogmstreams.h
#include "ogmstreams.h" // move it to <>?
#include "camogm_ogm.h"
#include "camogm.h"
//! may add something - called first time format is changed to this one (only once) recording is stopped
int camogm_init_ogm(void) {
return 0;
}
void camogm_free_ogm(void) {
}
int camogm_start_ogm(void) {
char vendor[]= "ElphelOgm v 0.1";
int pos;
stream_header sh;
char hdbuf[sizeof(sh)+1];
ogg_packet ogg_header;
sprintf(state->path,"%s%010ld_%06ld.ogm",state->path_prefix,state->frame_params.timestamp_sec,state->frame_params.timestamp_usec);
if (!((state->vf=fopen(state->path,"w+"))) ){
D0(fprintf (debug_file, "Error opening %s for writing\n", state->path));
return -CAMOGM_FRAME_FILE_ERR;
}
ogg_stream_init(&(state->os), state->serialno);
state->packetno = 0;
memset(&sh, 0, sizeof(stream_header));
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, state->time_unit);
// put_uint64(&sh.samples_per_unit, 1);
put_uint64(&sh.samples_per_unit, (ogg_int64_t) state->timescale);
put_uint32(&sh.default_len, 1);
put_uint32(&sh.buffersize, state->width*state->height);
// put_uint16(&sh.bits_per_sample, 24); //?
put_uint16(&sh.bits_per_sample, 0); //?
put_uint32(&sh.sh.video.width, state->width);
put_uint32(&sh.sh.video.height, state->height);
memcpy(&hdbuf[1], &sh, sizeof(sh));
hdbuf[0]=1;
//! put it into Ogg stream
ogg_header.packet = hdbuf;
ogg_header.bytes = sizeof(sh)+1;
ogg_header.b_o_s = 1;
ogg_header.e_o_s = 0;
ogg_header.packetno = state->packetno++;;
ogg_header.granulepos =0;
ogg_stream_packetin(&(state->os), &ogg_header);
// while(ogg_stream_pageout(&(state->os), &(state->og))) {
while(ogg_stream_flush(&(state->os), &(state->og))) {
int i, j;
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))) {
j=errno;
D2(fprintf(debug_file,"\n%d %ld %ld\n",i,state->og.header_len,state->og.body_len));
return -CAMOGM_FRAME_FILE_ERR;
}
}
//!create comment
//!use fixed minimal one - hdbuf will be enough for that
memset(hdbuf, 0, sizeof(hdbuf));
hdbuf[0]=PACKET_TYPE_COMMENT;
memcpy(&hdbuf[1], "vorbis",6);
pos=7;
put_uint32(&hdbuf[pos], strlen(vendor));
pos += 4;
strcpy(&hdbuf[pos], vendor);
pos += strlen(vendor);
put_uint32(&hdbuf[pos], 0);
pos += 4;
hdbuf[pos++] = 1;
//! put it into Ogg stream
ogg_header.packet = hdbuf;
ogg_header.bytes = pos;
ogg_header.b_o_s = 0;
ogg_header.e_o_s = 0;
ogg_header.packetno = state->packetno++;;
ogg_header.granulepos = 0;
ogg_stream_packetin(&(state->os), &ogg_header);
/*
while(ogg_stream_pageout(&(state->os), &(state->og))) {
int i, j;
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))) {
j=errno;
D(fprintf(debug_file,"\n%d %ld %ld\n",i,state->og.header_len,state->og.body_len));
return -CAMOGM_FRAME_FILE_ERR;
}
}
*/
//! calculate initial absolute granulepos (from 1970), then increment with each frame. Later try calculating granulepos of each frame
//! from the absolute time (actual timestamp)
state->granulepos= (ogg_int64_t) ( (((double) state->frame_params.timestamp_usec)+
(((double) 1000000) * ((double)state->frame_params.timestamp_sec))) *
((double) 10) /
((double) state->time_unit) *
((double) state->timescale));
// 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);
// 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)
state->granulepos=0;
//! Here - Ogg stream started, both header and comment packets are sent out, next should be just data packets
return 0;
}
int camogm_frame_ogm(void){
int indx;
elph_ogg_packet elp_packet;
elp_packet.bytes= 0;
for (indx=0; indx<state->chunk_index; indx++) elp_packet.bytes+=state->packetchunks[indx].bytes;
elp_packet.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,"0:0x%lx: %p\n" \
"1:0x%lx: %p\n" \
"2:0x%lx: %p\n" \
"3:0x%lx: %p\n" \
"4:0x%lx: %p\n" \
"5:0x%lx: %p\n" \
"6:0x%lx: %p\n", \
elp_packet.packet[0].bytes, elp_packet.packet[0].chunk,
elp_packet.packet[1].bytes, elp_packet.packet[1].chunk,
elp_packet.packet[2].bytes, elp_packet.packet[2].chunk,
elp_packet.packet[3].bytes, elp_packet.packet[3].chunk,
elp_packet.packet[4].bytes, elp_packet.packet[4].chunk,
elp_packet.packet[5].bytes, elp_packet.packet[5].chunk,
elp_packet.packet[6].bytes, elp_packet.packet[6].chunk));
*/
elp_packet.b_o_s = 0;
elp_packet.e_o_s = 0;
elp_packet.packetno = state->packetno++;;
// tts[0]=state->frame_params.timestamp_usec;
// tts[1]=state->frame_params.timestamp_sec;
elp_packet.granulepos=state->granulepos;
//!TODO: If that works, calculate granulepos from timestamp for each frame
state->granulepos+= (ogg_int64_t) state->timescale;
//D3(fprintf (debug_file,"_121_"));
ogg_stream_packetin_elph(&(state->os), &elp_packet);
//D3(fprintf (debug_file,"_13_"));
while(ogg_stream_pageout(&(state->os), &(state->og))) {
int i,j;
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))) {
j=errno;
D0(fprintf(debug_file,"\n%d %ld %ld\n",i,state->og.header_len,state->og.body_len));
return -CAMOGM_FRAME_FILE_ERR;
}
}
return 0;
}
//!Zero packets are OK, use them to end file with "last" turned on
int camogm_end_ogm(void){
//! put zero-packet it into stream
ogg_packet ogg_header;
ogg_header.packet = NULL;
ogg_header.bytes = 0;
ogg_header.b_o_s = 0;
ogg_header.e_o_s = 1;
ogg_header.packetno = state->packetno++;
ogg_header.granulepos = ++(state->granulepos);
ogg_stream_packetin(&(state->os), &ogg_header); //!+++++++++++++++++++++++++++++++++++++++++++++++++++++
while(ogg_stream_flush(&(state->os), &(state->og))) {
int i, j;
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))) {
j=errno;
D0(fprintf(debug_file,"\n%d %ld %ld\n",i,state->og.header_len,state->og.body_len));
return -CAMOGM_FRAME_FILE_ERR;
}
}
return 0;
}
int camogm_init_ogm(void);
int camogm_start_ogm(void);
int camogm_frame_ogm(void);
int camogm_end_ogm(void);
void camogm_free_ogm(void);
<?php
/*!***************************************************************************
*! FILE NAME : camogmstate.php
*! DESCRIPTION: Just a sample program that interacts with camogm recorder
*! Copyright (C) 2007 Elphel, Inc
*! -----------------------------------------------------------------------------**
*!
*! 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
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: camogmstate.php,v $
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*!
*!
*! Revision 1.2 2007/11/28 07:15:38 elphel
*! added sending arbitrary commands to camogm
*!
*! Revision 1.1 2007/11/19 03:23:21 elphel
*! 7.1.5.5 Added support for *.mov files in camogm.
*!
*!
*/
//! just for testing, asuming camogm is running and listening to /var/state/camogm_cmd
//! create a named pipe - "/var/state/camogm.state"
$pipe="/var/state/camogm.state";
$cmd_pipe="/var/state/camogm_cmd";
$mode=0777;
if(!file_exists($pipe)) {
// create the pipe
umask(0);
posix_mkfifo($pipe,$mode);
} else {
//! make sure $pipe is empty (how?) or just unlink($pipe) if it existed?
}
//! open command pipe to camogm
$fcmd=fopen($cmd_pipe,"w");
//! did the caller supply any command to be send to camogm?
$cmd=$_GET['cmd'];
if ($cmd) $cmd=urldecode($cmd).";";
//! ask it to send status to the pipe $pipe (so this program will wait for the data to appear)
fprintf($fcmd,$cmd."xstatus=%s\n",$pipe);
fclose($fcmd);
//! it seems that everything worked - caller (this script) waits for the file to appear
$status=file_get_contents($pipe);
header("Content-Type: text/xml");
header("Content-Length: ".strlen($status)."\n");
header("Pragma: no-cache\n");
printf($status);
?>
#ifndef __OGGSTREAMS_H
#define __OGGSTREAMS_H
/*
* Taken from http://tobias.everwicked.com/packfmt.htm
*
First packet (header)
---------------------
pos | content | description
-------+-------------------------+----------------------------------
0x0000 | 0x01 | indicates 'header packet'
-------+-------------------------+----------------------------------
0x0001 | stream_header | the size is indicated in the
| | size member
Second packet (comment)
-----------------------
pos | content | description
-------+-------------------------+----------------------------------
0x0000 | 0x03 | indicates 'comment packet'
-------+-------------------------+----------------------------------
0x0001 | data | see vorbis doc on www.xiph.org
Data packets
------------
pos | content | description
---------+-------------------------+----------------------------------
0x0000 | Bit0 0 | indicates data packet
| Bit1 Bit 2 of lenbytes |
| Bit2 unused |
| Bit3 keyframe |
| Bit4 unused |
| Bit5 unused |
| Bit6 Bit 0 of lenbytes |
| Bit7 Bit 1 of lenbytes |
---------+-------------------------+----------------------------------
0x0001 | LowByte | Length of this packet in samples
| ... | (frames for video, samples for
| HighByte | audio, 1ms units for text)
---------+-------------------------+----------------------------------
0x0001+ | data | packet contents
lenbytes | |
*
*
*/
//// OggDS headers
// Header for the new header format
typedef struct stream_header_video {
ogg_int32_t width;
ogg_int32_t height;
} stream_header_video;
typedef struct stream_header_audio {
ogg_int16_t channels;
ogg_int16_t blockalign;
ogg_int32_t avgbytespersec;
} stream_header_audio;
typedef struct stream_header {
char streamtype[8];
char subtype[4];
ogg_int32_t size; // size of the structure
ogg_int64_t time_unit; // in reference time
ogg_int64_t samples_per_unit;
ogg_int32_t default_len; // in media time
ogg_int32_t buffersize;
// ogg_int16_t bits_per_sample;
ogg_int32_t bits_per_sample;
union {
// Video specific
stream_header_video video;
// Audio specific
stream_header_audio audio;
} sh;
// ogg_int16_t padding;
ogg_int32_t padding;
} stream_header;
typedef struct old_stream_header {
char streamtype[8];
char subtype[4];
ogg_int32_t size; // size of the structure
ogg_int64_t time_unit; // in reference time
ogg_int64_t samples_per_unit;
ogg_int32_t default_len; // in media time
ogg_int32_t buffersize;
ogg_int16_t bits_per_sample;
ogg_int16_t padding;
union {
// Video specific
stream_header_video video;
// Audio specific
stream_header_audio audio;
} sh;
} old_stream_header;
/// Some defines from OggDS
#define PACKET_TYPE_HEADER 0x01
#define PACKET_TYPE_COMMENT 0x03
#define PACKET_TYPE_BITS 0x07
#define PACKET_LEN_BITS01 0xc0
#define PACKET_LEN_BITS2 0x02
#define PACKET_IS_SYNCPOINT 0x08
#endif /* __OGGSTREAMS_H */
{'moov
{'mvhd
00 # version
000000 # Flags
!time # Creation time
!time # Modification time
!timescale # Time Scale - time unints per second
!duration # Duration - in time units
00010000 # Preferred rate
00ff # Preferred volume
00000000 00000000 0000 # (reserved)
00010000 00000000 00000000 # Matrix [a b u]
00000000 00010000 00000000 # Matrix [c d v]
00000000 00000000 40000000 # Matrix [x y w]
00000000 # Preview Time
00000000 # Preview Duration
00000000 # Poster Time
00000000 # Selection Time
00000000 # Selection Duration
00000000 # Current Time
00000002 # Next Track ID
}
{'trak
{'tkhd
00 # version
00000f # Flags
!time # Creation time
!time # Modification time
00000001 # Track ID
00000000 # (reserved)
!duration # Duration
00000000 00000000 # (reserved)
0000 # Layer
0000 # Alternate group
0000 # Volume
0000 # (reserved)
00010000 00000000 00000000 # Matrix [a b u]
00000000 00010000 00000000 # Matrix [c d v]
00000000 00000000 40000000 # Matrix [x y w]
!width 0000 # Track width
!height 0000 # Track height
}
{'mdia
{'mdhd
00 # version
000000 # Flags
!time # Creation time
!time # Modification time
!timescale # Time Scale
!duration # Duration
0000 # Language
0000 # Quality
}
{'hdlr
00 # version
000000 # Flags
'mhlr # Component type
'vide # Component subtype
'appl # Component manufacturer
00000000 # Component Flags
0001001f # Component Flags Mask
19 'Apple Video Media Handler # Component Name
}
{'minf
{'vmhd
00 # version
000001 # Flags
0040 # Graphics Mode
8000 8000 8000 # Opcolor
}
{'hdlr
00 # version
000000 # Flags
'dhlr # Component type
'alis # Component subtype
'appl # Cmponent manufacturer
00000001 # Component Flags
00010026 # Component Flags Mask
18 'Apple Alias Data Handler # Component Name
}
{'dinf
{'dref
00 # version
000000 # Flags (1 - the same file???)
00000001 # Number of entries
0000000c 616c6973 00000001 # Data references
}
}
{'stbl
{'stsd
00 # version
000000 # Flags
00000001 # Number of entries
00000056 # Sample description size
'jpeg # Data format
00000000 0000 # (reserved)
0001 # Data reference index
0000 # Version
0000 # Revision Level
'appl # Vendor
00000000 # Temporal quality
00000200 # Spatial quality
!width # Width
!height # Height
00480000 # Horizontal resolution
00480000 # Vertical resolution
00000000 # Data size
0001 # Frame count
0c 'Photo - JPEG # Compressor Name
00000000 00000000 00000000 00000000 000000 # padding
0018 # Color depth (24)
ffff # Color table ID
}
{'stts
00 # version
000000 # Flags
00000001 # Number of entries
!nframes !frame_duration # TIME-TO-SAMPLE table (was 0x0a 0x28) - time units/sample
}
{'stsc
00 # version
000000 # Flags
00000001 # Number of entries
# 00000001 !nframes 00000001 # SAMPLE-TO-CHUNK table - all in one chunk
00000001 !samples_chunk 00000001 # SAMPLE-TO-CHUNK table - each sample it new chunk
}
{'stsz
00 # version
000000 # Flags
00000000 # Sample Size ** Did not work with non-zero!
!nframes # Number of entries
!sample_sizes # nframes of 4-byte words
}
{'stco
00 # version
000000 # Flags
# 00000001 # Number of entries
# !mdata #
# !nframes # Number of entries
!chunk_offsets #
}
}
}
}
{'udta
00000000
}
}
{'udta
{'WLOC
0017
0020
}
00000000 # ???
}
}
!data_size
'mdat
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