Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
E
elphel-apps-camogm
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Elphel
elphel-apps-camogm
Commits
28233c9b
Commit
28233c9b
authored
Jun 23, 2016
by
Mikhail Karpenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update doxygen documentation
parent
974633b6
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
256 additions
and
295 deletions
+256
-295
camogm.c
camogm.c
+160
-177
camogm.h
camogm.h
+96
-118
No files found.
camogm.c
View file @
28233c9b
/*!***************************************************************************
*! FILE NAME : camogm.c
*! DESCRIPTION: Program to write captured video (and audio) to camera file system
*! using Ogg container.
*! Original implementation will copy package data to a buffer to use library calls?
*! 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.c,v $
*! Revision 1.13 2011/04/22 22:38:30 elphel
*! added "greedy" and "ignore_fps" options
*!
*! Revision 1.12 2010/08/16 17:10:59 elphel
*! typo
*!
*! Revision 1.11 2010/08/08 21:14:04 elphel
*! 8.0.8.38
*!
*! Revision 1.10 2010/08/07 23:38:01 elphel
*! fixed skipping (sometimes) frames at start recording
*!
*! Revision 1.9 2010/08/03 06:19:57 elphel
*! more debug for debug-level>=3
*!
*! Revision 1.8 2010/08/02 01:26:42 elphel
*! error tracking
*!
*! Revision 1.7 2010/08/01 19:30:24 elphel
*! new readonly parameter FRAME_SIZE and it support in the applications
*!
*! Revision 1.6 2010/07/18 16:59:09 elphel
*! 8.0.8.31 - added parameters to camogm (one is to start at certain absolute time, helps to synchronize multiple cameras)
*!
*! Revision 1.5 2010/07/04 19:06:02 elphel
*! moved acknowledge earlier
*!
*! Revision 1.4 2010/06/22 18:27:26 elphel
*! bug fix
*!
*! Revision 1.3 2010/06/22 16:53:30 elphel
*! camogm acknowledges received command by copying G_THIS_FRAME value to G_DAEMON_ERR+3 (default number for camogm)
*!
*! 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.6 2008/11/21 01:52:53 elphel
*! updated for 8.0
*!
*! Revision 1.5 2008/11/20 23:21:32 elphel
*! Put FIXME notes and removed parameters that are not used anymore
*!
*! Revision 1.4 2008/10/29 04:18:28 elphel
*! v.8.0.alpha10 made a separate structure for global parameters (not related to particular frames in a frame queue)
*!
*! Revision 1.3 2008/10/13 16:55:53 elphel
*! removed (some) obsolete P_* parameters, renamed CIRCLSEEK to LSEEK_CIRC constants (same as other similar)
*!
*! Revision 1.2 2008/09/07 19:48:08 elphel
*! snapshot
*!
*! Revision 1.9 2008/04/13 21:05:19 elphel
*! Fixing KML generation
*!
*! Revision 1.8 2008/04/11 23:09:33 elphel
*! modified to handle kml generation
*!
*! Revision 1.7 2008/04/07 09:13:34 elphel
*! Changes related to new Exif generation/processing
*!
*! Revision 1.6 2008/01/14 22:59:00 elphel
*! 7.1.7.4 - added timelapse mode to camogm
*!
*! Revision 1.5 2007/12/03 08:28:45 elphel
*! Multiple changes, mostly cleanup
*!
*! Revision 1.4 2007/11/29 00:38:57 elphel
*! fixed timescale bug
*!
*! Revision 1.3 2007/11/19 05:07:19 elphel
*! fixed 2 typos
*!
*! 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:56 elphel
*! Initial release of camogm - program to record video/image to the camera hard drive (or other storage)
*!
/** @file camogm.c
* @brief Program to write captured video (and audio) to camera file system
* using Ogg container.
* @copyright Copyright (C) 2016 Elphel, Inc.
*
* @par <b>License</b>
* 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/>.
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
...
...
@@ -110,18 +24,40 @@
#include <linux/fs.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <string.h>
#include "camogm_ogm.h"
#include "camogm_jpeg.h"
#include "camogm_mov.h"
#include "camogm_kml.h"
#include "camogm_read.h"
#include "camogm.h"
/** @brief Time interval (in microseconds) for processing commands */
#define COMMAND_LOOP_DELAY 500000 //0.5sec
/** @brief Default debug level */
#define DEFAULT_DEBUG_LVL 6
/** @brief JPEG trailer syze in bytes */
#define TRAILER_SIZE 0x02
#define MAP_OPTIONS MAP_FILE | MAP_PRIVATE
/** @brief Default segment duration in seconds */
#define DEFAULT_DURATION 600
/** @brief Default segment length in bytes */
#define DEFAULT_LENGTH 1073741824
/** @brief Behavior for the files: 0 clean buffer, 1 - save as much as possible */
#define DEFAULT_GREEDY 0
/** @brief 0 - restartf file if fps changed, 1 - ignore variable fps (and skip less frames) */
#define DEFAULT_IGNORE_FPS 0
/** @brief Maximal number of frames in file segment (each need 4* (1 + 1/frames_per_chunk) bytes for the frame index.
* This parameter is mostrly for Quicktime */
#define DEFAULT_FRAMES 16384
/** @brief Second sparse index - for Quicktime fast forward */
#define DEFAULT_FRAMES_PER_CHUNK 10
/** @brief Use Exif */
#define DEFAULT_EXIF 1
/** @brief Bit mask indicating all 4 sensor port channels are active */
#define ALL_CHN_ACTIVE 0x0f
/** @brief Bit mask indicating all 4 sensor port channels are inactive */
#define ALL_CHN_INACTIVE 0x00
/** @brief This is a basic helper macro for processing all sensor ports at a time */
#define FOR_EACH_PORT(indtype, indvar) for (indtype indvar = 0; indvar < SENSOR_PORTS; indvar++)
char
trailer
[
TRAILER_SIZE
]
=
{
0xff
,
0xd9
};
...
...
@@ -139,33 +75,25 @@ const char *ctlFileNames[] = { "/dev/frameparsall0", "/dev/frameparsall1",
const
char
*
circbufFileNames
[]
=
{
"/dev/circbuf0"
,
"/dev/circbuf1"
,
"/dev/circbuf2"
,
"/dev/circbuf3"
};
unsigned
long
*
ccam_dma_buf
[
SENSOR_PORTS
];
/* mmapped arrays */
int
lastDaemonBit
[
SENSOR_PORTS
]
=
{
DAEMON_BIT_CAMOGM
};
struct
framepars_all_t
*
frameParsAll
[
SENSOR_PORTS
];
struct
framepars_t
*
framePars
[
SENSOR_PORTS
];
unsigned
long
*
aglobalPars
[
SENSOR_PORTS
];
/// parameters that are not frame-related, their changes do not initiate any actions
#define DEFAULT_DURATION 600
/*!default segment duration (seconds) */
#define DEFAULT_LENGTH 1073741824
/*!default segment length (B) */
#define DEFAULT_GREEDY 0
/*!behavior for the files: 0 clean buffer, 1 - save as much as possible */
#define DEFAULT_IGNORE_FPS 0
/*!0 restartf file if fps changed, 1 - ignore variable fps (and skip less frames) */
/** @brief Bit mask indicating all 4 sensor port channels are active */
#define ALL_CHN_ACTIVE 0x0f
/** @brief Bit mask indicating all 4 sensor port channels are inactive */
#define ALL_CHN_INACTIVE 0x00
//!Next 2 for Quicktime (mostly)
#define DEFAULT_FRAMES 16384
/* Maximal number of frames in file segment (each need 4* (1 + 1/frames_per_chunk) bytes for the frame index */
#define DEFAULT_FRAMES_PER_CHUNK 10
/*second sparse index - for Quicktime fast forward */
#define DEFAULT_EXIF 1
/* use Exif */
/** @brief Parameters that are not frame-related, their changes do not initiate any actions */
unsigned
long
*
aglobalPars
[
SENSOR_PORTS
];
/** @brief Global structure containing current state of the running program */
camogm_state
sstate
;
//camogm_state * state;
/** @brief Memory mapped circular buffer arrays */
unsigned
long
*
ccam_dma_buf
[
SENSOR_PORTS
];
/**
* @enum path_type
* @brief Define the path type passed to a function
* @var path_type::RAW_PATH
* The path specified is a path to raw device buffer and it starts with /dev
* @var path_type::FILE_PATH
* The path specified is a regular path
*/
typedef
enum
{
RAW_PATH
,
FILE_PATH
...
...
@@ -174,10 +102,10 @@ typedef enum {
int
debug_level
;
FILE
*
debug_file
;
void
camogm_init
(
camogm_state
*
state
,
unsigned
int
port
,
char
*
pipe_name
);
void
camogm_init
(
camogm_state
*
state
,
char
*
pipe_name
);
int
camogm_start
(
camogm_state
*
state
);
int
camogm_stop
(
camogm_state
*
state
);
int
camogm_reset
(
camogm_state
*
state
);
//! reset circbuf read pointer
void
camogm_reset
(
camogm_state
*
state
);
int
camogm_debug
(
camogm_state
*
state
,
const
char
*
fname
);
int
camogm_debug_level
(
int
d
);
void
camogm_set_segment_duration
(
camogm_state
*
state
,
int
sd
);
...
...
@@ -217,7 +145,6 @@ unsigned int select_port(camogm_state *states);
inline
void
set_chn_state
(
camogm_state
*
s
,
unsigned
int
port
,
unsigned
int
new_state
);
inline
int
is_chn_active
(
camogm_state
*
s
,
unsigned
int
port
);
//!======================================================================================================
void
put_uint16
(
void
*
buf
,
u_int16_t
val
)
{
unsigned
char
*
tmp
;
...
...
@@ -257,68 +184,55 @@ void put_uint64(void *buf, u_int64_t val)
}
/**
* @brief Initialize state for a particular sensor port.
* @param[in] state pointer to #camogm_state structure for a particular sensor channel
* @param[in] port sensor port number
* @brief Initialize the state of the program
* @param[in] state pointer to #camogm_state structure containing program state
* @param[in] pipe_name pointer to command pipe name string
* @return none
*/
void
camogm_init
(
camogm_state
*
state
,
unsigned
int
port
,
char
*
pipe_name
)
void
camogm_init
(
camogm_state
*
state
,
char
*
pipe_name
)
{
const
char
sserial
[]
=
"elp0"
;
int
*
ipser
=
(
int
*
)
sserial
;
memset
(
state
,
0
,
sizeof
(
camogm_state
));
// state->running = 0; // mo
// state->starting = 0; // mo
// state->vf = NULL;
camogm_set_segment_duration
(
state
,
DEFAULT_DURATION
);
camogm_set_segment_length
(
state
,
DEFAULT_LENGTH
);
camogm_set_greedy
(
state
,
DEFAULT_GREEDY
);
camogm_set_ignore_fps
(
state
,
DEFAULT_IGNORE_FPS
);
camogm_set_max_frames
(
state
,
DEFAULT_FRAMES
);
camogm_set_frames_per_chunk
(
state
,
DEFAULT_FRAMES_PER_CHUNK
);
// camogm_set_start_after_timestamp(state, 0.0); // start any time
// camogm_set_prefix(state, "\0", FILE_PATH);
// camogm_set_save_gp(state, 0);
camogm_reset
(
state
);
// sets state->buf_overruns =- 1
state
->
serialno
=
ipser
[
0
];
// state->last = 0;
debug_file
=
stderr
;
camogm_debug_level
(
DEFAULT_DEBUG_LVL
);
strcpy
(
state
->
debug_name
,
"stderr"
);
camogm_set_timescale
(
state
,
1
.
0
);
camogm_set_frames_skip
(
state
,
0
);
// don't skip
camogm_set_format
(
state
,
CAMOGM_FORMAT_MOV
);
// FOR_EACH_PORT(int, chn) {state->exifSize[chn] = 0;}
state
->
exif
=
DEFAULT_EXIF
;
state
->
frame_lengths
=
NULL
;
// state->frameno = 0;
// state->formats = 0;
// state->last_error_code = 0;
// kml stuff
// camogm_kml_set_enable(state, 0);
// state->kml_file = NULL;
camogm_kml_set_horHalfFov
(
state
,
20
.
0
);
camogm_kml_set_vertHalfFov
(
state
,
15
.
0
);
camogm_kml_set_height_mode
(
state
,
0
);
camogm_kml_set_height
(
state
,
10
.
0
);
camogm_kml_set_period
(
state
,
2
);
// 2 sec
camogm_kml_set_near
(
state
,
40
.
0
);
// 40 m (distance to PhotoOverlay)
// state->kml_path[0] = '\0';
state
->
port_num
=
port
;
state
->
pipe_name
=
pipe_name
;
state
->
rawdev
.
start_pos
=
RAWDEV_START_OFFSET
;
state
->
rawdev
.
end_pos
=
state
->
rawdev
.
start_pos
;
state
->
rawdev
.
curr_pos
=
state
->
rawdev
.
start_pos
;
// state->rawdev.overrun = 0;
// state->rawdev_op = 0;
state
->
active_chn
=
ALL_CHN_ACTIVE
;
}
/**
* @brief Set debug output file
* @param[in] state a pointer to a structure containing current state
* @param[in] fname file used for debug output
* @return 0 if the file was opened successfully and negative error code otherwise
*/
int
camogm_debug
(
camogm_state
*
state
,
const
char
*
fname
)
{
int
none
=
1
;
...
...
@@ -341,12 +255,18 @@ int camogm_debug(camogm_state *state, const char * fname)
return
0
;
}
/** @brief Set current debug level */
int
camogm_debug_level
(
int
d
)
{
debug_level
=
d
;
return
0
;
}
/**
* @brief Start recording for each active sensor port
* @param[in] state a pointer to a structure containing current state
* @return 0 if the recording finished successfully and negative error code otherwise
*/
int
camogm_start
(
camogm_state
*
state
)
{
int
timestamp_start
;
...
...
@@ -533,6 +453,11 @@ int camogm_start(camogm_state *state)
return
0
;
}
/**
* @brief Save a single image from circular buffer to a file.
* @param[in] state a pointer to a structure containing current state
* @return 0 if the image was successfully saved and negative error code otherwise
*/
int
sendImageFrame
(
camogm_state
*
state
)
{
int
rslt
;
...
...
@@ -712,6 +637,12 @@ int sendImageFrame(camogm_state *state)
return
0
;
}
/**
* @brief Stop current recording. If recording was not started, this function has no effect. This function
* calls @e camogm_end_* for the current file format.
* @param[in] state a pointer to a structure containing current state
* @return 0 if the operation was stopped successfully and negative error code otherwise
*/
int
camogm_stop
(
camogm_state
*
state
)
{
int
rslt
=
0
;
...
...
@@ -745,13 +676,15 @@ int camogm_stop(camogm_state *state)
return
0
;
}
/**
* @brief Free all file format handlers that were used. @e camogm_free_* for
* each format used will be called.
* @param[in] state a pointer to a structure containing current state
* @return None
*/
void
camogm_free
(
camogm_state
*
state
)
{
int
f
;
//! free all file format handlers that were used
//add kml when needed
for
(
f
=
0
;
f
<
31
;
f
++
)
{
for
(
int
f
=
0
;
f
<
31
;
f
++
)
{
if
(
state
->
formats
&
(
1
<<
(
state
->
format
)))
{
switch
(
f
)
{
case
CAMOGM_FORMAT_NONE
:
break
;
...
...
@@ -764,43 +697,52 @@ void camogm_free(camogm_state *state)
state
->
formats
=
0
;
}
int
camogm_reset
(
camogm_state
*
state
)
//! reset circbuf read pointer
/**
* @brief Reset read pointer and overruns counter for each sensor port
* @param[in] state a pointer to a structure containing current state
* @return None
*/
void
camogm_reset
(
camogm_state
*
state
)
{
FOR_EACH_PORT
(
int
,
chn
)
{
state
->
port_num
=
chn
;
state
->
cirbuf_rp
[
state
->
port_num
]
=
-
1
;
state
->
buf_overruns
[
state
->
port_num
]
=
-
1
;
//!first will not count
state
->
cirbuf_rp
[
chn
]
=
-
1
;
state
->
buf_overruns
[
chn
]
=
-
1
;
// first overrun will not count
}
return
0
;
}
/
//kml stuff
/
** @brief kml parameter setter */
void
camogm_kml_set_enable
(
camogm_state
*
state
,
int
d
)
{
state
->
kml_enable
=
d
;
}
/** @brief kml parameter setter */
void
camogm_kml_set_horHalfFov
(
camogm_state
*
state
,
double
dd
)
{
state
->
kml_horHalfFov
=
dd
;
}
/** @brief kml parameter setter */
void
camogm_kml_set_vertHalfFov
(
camogm_state
*
state
,
double
dd
)
{
state
->
kml_vertHalfFov
=
dd
;
}
/** @brief kml parameter setter */
void
camogm_kml_set_height_mode
(
camogm_state
*
state
,
int
d
)
{
state
->
kml_height_mode
=
d
;
}
/** @brief kml parameter setter */
void
camogm_kml_set_height
(
camogm_state
*
state
,
double
dd
)
{
state
->
kml_height
=
dd
;
}
/** @brief kml parameter setter */
void
camogm_kml_set_period
(
camogm_state
*
state
,
int
d
)
{
state
->
kml_period
=
d
;
state
->
kml_last_ts
=
0
;
state
->
kml_last_uts
=
0
;
}
/** @brief kml parameter setter */
void
camogm_kml_set_near
(
camogm_state
*
state
,
double
dd
)
// distance to PhotoOverlay
{
state
->
kml_near
=
dd
;
...
...
@@ -824,7 +766,6 @@ void camogm_set_exif(camogm_state *state, int d)
state
->
exif
=
d
;
}
void
camogm_set_greedy
(
camogm_state
*
state
,
int
d
)
{
state
->
greedy
=
d
?
1
:
0
;
...
...
@@ -834,6 +775,13 @@ void camogm_set_ignore_fps(camogm_state *state, int d)
state
->
ignore_fps
=
d
?
1
:
0
;
}
/**
* @brief Set file name prefix or raw device file name.
* @param[in] state a pointer to a structure containing current state
* @param[in] p a pointer to the prefix string. The string is prepended to
* the file name as is.
* @param[in] type the type of prefix, can be one of #path_type
*/
void
camogm_set_prefix
(
camogm_state
*
state
,
const
char
*
p
,
path_type
type
)
{
if
(
type
==
FILE_PATH
)
{
...
...
@@ -858,6 +806,7 @@ void camogm_set_prefix(camogm_state *state, const char * p, path_type type)
}
}
/** @brief Set timescale @e d */
void
camogm_set_timescale
(
camogm_state
*
state
,
double
d
)
//! set timescale, default=1,000,000
{
state
->
set_timescale
=
d
;
...
...
@@ -866,6 +815,7 @@ void camogm_set_timescale(camogm_state *state, double d) //! set timescale, d
}
}
/** @brief Set the number of frames @e d to be skipped during recording. This values is common for each sensor port */
void
camogm_set_frames_skip
(
camogm_state
*
state
,
int
d
)
//! set frames to skip (for time lapse)
{
state
->
set_frames_skip
=
d
;
...
...
@@ -875,7 +825,8 @@ void camogm_set_frames_skip(camogm_state *state, int d) //! set frames to ski
}
}
/** @brief Set file format @e d the images will be recorded to. This function calls corresponding @e camogm_init_*
* function for the format selected.*/
void
camogm_set_format
(
camogm_state
*
state
,
int
d
)
{
int
rslt
=
0
;
...
...
@@ -895,22 +846,35 @@ void camogm_set_format(camogm_state *state, int d)
state
->
formats
|=
1
<<
(
state
->
format
);
}
}
//! needed for Quicktime - maybe something else?
/** @brief Set max number of frames @e d */
void
camogm_set_max_frames
(
camogm_state
*
state
,
int
d
)
{
state
->
set_max_frames
=
d
;
if
((
state
->
running
==
0
)
&&
(
state
->
starting
==
0
))
state
->
max_frames
=
d
;
}
/** @brief Set the number of frames @e d recorded per chunk */
void
camogm_set_frames_per_chunk
(
camogm_state
*
state
,
int
d
)
{
state
->
set_frames_per_chunk
=
d
;
if
((
state
->
running
==
0
)
&&
(
state
->
starting
==
0
))
state
->
frames_per_chunk
=
d
;
}
/** @brief Set the time stamp @e d when recording should be started */
void
camogm_set_start_after_timestamp
(
camogm_state
*
state
,
double
d
)
{
state
->
start_after_timestamp
=
d
;
}
/**
* @brief Print current status either as plain text or in xml format
* @param[in] state to a structure containing current state
* @param[in] fn a pointer to a file name which will be used for output. Can be NULL or 'stdout' for
* output to stdout, 'stderr' for output to stderr and a file name for output to a file
* @param[in] xml flag indicating that the output should be in xml format
* @return None
*/
void
camogm_status
(
camogm_state
*
state
,
char
*
fn
,
int
xml
)
{
int
_len
=
0
;
...
...
@@ -1126,7 +1090,11 @@ void camogm_status(camogm_state *state, char * fn, int xml)
FOR_EACH_PORT
(
int
,
chn
)
{
state
->
buf_min
[
chn
]
=
_b_free
[
chn
];}
}
//! will read from pipe, return pointer to null terminated string if available, NULL otherwise
/**
* @brief Read from a single command from pipe
* @param[in] npipe pointer to command pipe
* @return Pointer to null terminated string if a command is available or NULL otherwise
*/
char
*
getLineFromPipe
(
FILE
*
npipe
)
{
int
fl
;
...
...
@@ -1162,6 +1130,13 @@ char * getLineFromPipe(FILE* npipe)
}
}
/**
* @brief Read and execute commands sent over command pipe
* @param state pointer to a structure containing current state
* @param npipe pointer to command pipe
* @return 0 if pipe was empty, positive value corresponding to a command processed or
* -1 in case of an error
*/
int
parse_cmd
(
camogm_state
*
state
,
FILE
*
npipe
)
{
char
*
cmd
;
...
...
@@ -1170,7 +1145,6 @@ int parse_cmd(camogm_state *state, FILE* npipe)
int
d
;
double
dd
;
// if (!((cmd=getLineFromPipe(npipe)))) return 0; //! nothing in the pipe
//!skip empty commands
while
(((
cmd
=
getLineFromPipe
(
npipe
)))
&&
!
cmd
[
0
])
;
if
(
!
cmd
)
return
0
;
//! nothing in the pipe
...
...
@@ -1338,7 +1312,7 @@ int parse_cmd(camogm_state *state, FILE* npipe)
/**
* @brief This function closes open files and deletes allocated memory.
* @param[in] state pointer to #camogm_state structure for a particular sensor channel
* return
n
one
* return
N
one
*/
void
clean_up
(
camogm_state
*
state
)
{
...
...
@@ -1358,10 +1332,10 @@ void clean_up(camogm_state *state)
* @brief Main processing loop
*
* If recording is on, this function will check for new commands in command pipe after each frame. If recording is
* turn off, it will poll command pipe each #COMMAND_LOOP_DELAY
S
microseconds and then sleep.
* turn off, it will poll command pipe each #COMMAND_LOOP_DELAY microseconds and then sleep.
* @param[in] state #camogm_state structure associated with a single port
* @return normally this function loops indefinitely processing commands but will return negative exit code in case
* of error and
\
e EXIT_SUCCESS it eventually terminates in normal way.
* of error and
@
e EXIT_SUCCESS it eventually terminates in normal way.
*/
int
listener_loop
(
camogm_state
*
state
)
{
...
...
@@ -1490,7 +1464,7 @@ int listener_loop(camogm_state *state)
}
/**
* @brief Return disk size in bytes
* @brief Return
total
disk size in bytes
*
* This function reads disk size using ioctl call and returns it in bytes.
* @param name pointer to disk name string
...
...
@@ -1544,6 +1518,12 @@ unsigned int select_port(camogm_state *state)
return
chn
;
}
/**
* @brief Check if channel is enabled or disabled
* @param[in] s a pointer to a structure containing current state
* @param[in] port a port which should be checked
* @return 0 if the channel is disabled and 1 otherwise
*/
inline
int
is_chn_active
(
camogm_state
*
s
,
unsigned
int
port
)
{
return
(
s
->
active_chn
>>
port
)
&
0x1
;
...
...
@@ -1667,7 +1647,7 @@ int main(int argc, char *argv[])
return
EXIT_SUCCESS
;
}
camogm_init
(
&
sstate
,
0
,
argv
[
1
]);
camogm_init
(
&
sstate
,
argv
[
1
]);
ret
=
open_files
(
&
sstate
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -1696,9 +1676,10 @@ unsigned long getGPValue(unsigned int port, unsigned long GPNumber)
/**
* @brief Set value of the specified global (G_*) parameter
* @param[in] port sensor port number
* @param[in] GNumber parameter number (as defined in c313a.h)
* @param[in] value value to set
* @return
n
one
* @return
N
one
*/
void
setGValue
(
unsigned
int
port
,
unsigned
long
GNumber
,
unsigned
long
value
)
{
...
...
@@ -1708,6 +1689,7 @@ void setGValue(unsigned int port, unsigned long GNumber, unsigned long value)
/**
* @brief Check if this application is enabled (by appropriate bit in P_DAEMON_EN), if not -
* and wait until enabled (return false when enabled)
* @param[in] port sensor port number
* @param[in] daemonBit bit number to accept control in P_DAEMON_EN parameter
* @return (after possible waiting) true if there was no waiting, false if there was waiting
*/
...
...
@@ -1725,6 +1707,7 @@ int waitDaemonEnabled(unsigned int port, int daemonBit) // <0 - use default
/**
* @brief Check if this application is enabled (by appropriate bit in P_DAEMON_EN)
* @param[in] port sensor port number
* @param[in] daemonBit bit number to accept control in P_DAEMON_EN parameter
* @return (after possible waiting) true if there was no waiting, false if there was waiting
*/
...
...
camogm.h
View file @
28233c9b
/** @file camogm.h
* @brief Program to write captured video (and audio) to camera file system
* using Ogg container.
* @copyright Copyright (C) 2016 Elphel, Inc.
*
* @par <b>License</b>
* 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/>.
*/
#ifndef _CAMOGM_H
#define _CAMOGM_H
#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
#include <exifa.h>
#include <c313a.h>
#include <ogg/ogg.h>
#include "ogmstreams.h"
#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 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); } }
...
...
@@ -27,55 +50,9 @@
//#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 <exifa.h>
#include <c313a.h>
#include <ogg/ogg.h> // has to be before ogmstreams.h
#include "ogmstreams.h" // move it to <>?
/*
#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
*/
/** @brief HEADER_SIZE is defined to be larger than actual header (with EXIF) to use compile-time buffer */
#define JPEG_HEADER_MAXSIZE 0x300
/** @brief Offset from the beginning of raw device buffer. Must be aligned to physical sector size */
#define RAWDEV_START_OFFSET 1024
/** @brief Maximum length of file or raw device path */
...
...
@@ -110,30 +87,34 @@ typedef struct {
uint64_t
file_start
;
}
rawdev_buffer
;
/**
* @struct camogm_state
* @brief Holds current state of the running program
*/
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
[
ELPHEL_PATH_MAX
];
int
cirbuf_rp
[
SENSOR_PORTS
];
//!-1 -
invalid
int
fd_circ
[
SENSOR_PORTS
];
//!
file descriptor for circbuf
int
fd_head
[
SENSOR_PORTS
];
//!
file descriptor for JPEG header
int
fd_fparmsall
[
SENSOR_PORTS
];
//!
file descriptor for sensor/compressor parameters
int
fd_exif
[
SENSOR_PORTS
];
//!
file descriptor for Exif data
int
head_size
[
SENSOR_PORTS
];
//!
JPEG header size
int
save_gp
;
///<
if non zero, current circbuf pointer will be saved to global pointer, so imgsrv can report /pointers
char
path_prefix
[
256
];
///< file name prefix
char
path
[
ELPHEL_PATH_MAX
];
///< full file name
int
cirbuf_rp
[
SENSOR_PORTS
];
///< -1 means the pointer is
invalid
int
fd_circ
[
SENSOR_PORTS
];
///<
file descriptor for circbuf
int
fd_head
[
SENSOR_PORTS
];
///<
file descriptor for JPEG header
int
fd_fparmsall
[
SENSOR_PORTS
];
///<
file descriptor for sensor/compressor parameters
int
fd_exif
[
SENSOR_PORTS
];
///<
file descriptor for Exif data
int
head_size
[
SENSOR_PORTS
];
///<
JPEG header size
unsigned
char
jpegHeader
[
SENSOR_PORTS
][
JPEG_HEADER_MAXSIZE
];
int
metadata_start
;
struct
interframe_params_t
frame_params
[
SENSOR_PORTS
];
struct
interframe_params_t
this_frame_params
[
SENSOR_PORTS
];
int
jpeg_len
;
int
frame_period
[
SENSOR_PORTS
];
//!
in microseconds (1/10 of what is needed for the Ogm header)
int
width
;
int
height
;
int
starting
;
int
running
;
int
frame_period
[
SENSOR_PORTS
];
///<
in microseconds (1/10 of what is needed for the Ogm header)
int
width
;
///< image width
int
height
;
///< image height
int
starting
;
///< the program is starting
int
running
;
///< the program is running
int
last_error_code
;
ogg_stream_state
os
;
ogg_page
og
;
...
...
@@ -142,73 +123,70 @@ typedef struct {
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
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
int
exifSize
[
SENSOR_PORTS
];
//
signed
int
exif
;
///< flag indicating that Exif headers should be calculated and included
in each frame
int
exifSize
[
SENSOR_PORTS
];
///<
signed
unsigned
char
ed
[
SENSOR_PORTS
][
MAX_EXIF_SIZE
];
int
circ_buff_size
[
SENSOR_PORTS
];
// int senspars_size;
char
debug_name
[
256
];
// FILE* debug_file;
// int set_samples_per_unit;
double
timescale
;
//! current timescale, default 1.0
double
timescale
;
///< current timescale, default 1.0
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
set_max_frames
;
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
*
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
;
int
formats
;
//!
bitmask of used (initialized) formats
int
format
;
//!
output file format
int
set_format
;
//!
output format to set (will be updated after stop)
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
[
SENSOR_PORTS
];
int
buf_min
[
SENSOR_PORTS
];
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 nege
tive - -(interval between frames in seconds)
int
frames_skip_left
[
SENSOR_PORTS
];
//
!
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
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 nega
tive - -(interval between frames in seconds)
int
frames_skip_left
[
SENSOR_PORTS
];
//
/<
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
unsigned
int
port_num
;
// sensor port we are currently working with
char
*
pipe_name
;
// command pipe name
int
rawdev_op
;
// flag indicating writing to raw device
rawdev_buffer
rawdev
;
// contains pointers to raw device buffer
unsigned
int
active_chn
;
// bitmask of active sensor ports
unsigned
int
port_num
;
//
/<
sensor port we are currently working with
char
*
pipe_name
;
//
/<
command pipe name
int
rawdev_op
;
//
/<
flag indicating writing to raw device
rawdev_buffer
rawdev
;
//
/<
contains pointers to raw device buffer
unsigned
int
active_chn
;
//
/<
bitmask of active sensor ports
}
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
int
port
,
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
void
setGValue
(
unsigned
int
port
,
unsigned
long
GNumber
,
unsigned
long
value
);
int
waitDaemonEnabled
(
unsigned
int
port
,
int
daemonBit
);
int
isDaemonEnabled
(
unsigned
int
port
,
int
daemonBit
);
#endif
/* _CAMOGM_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment