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
4567a7bf
Commit
4567a7bf
authored
May 14, 2016
by
Mikhail Karpenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move main loop to separate function, spawn processes
parent
38f6a374
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
170 additions
and
156 deletions
+170
-156
camogm.c
camogm.c
+167
-154
camogm.h
camogm.h
+3
-2
No files found.
camogm.c
View file @
4567a7bf
...
@@ -145,6 +145,7 @@
...
@@ -145,6 +145,7 @@
/* end of debug code */
/* end of debug code */
#define COMMAND_LOOP_DELAY 500000 //0.5sec
#define DEFAULT_DEBUG_LVL 6
#define DEFAULT_DEBUG_LVL 6
#define TRAILER_SIZE 0x02
#define TRAILER_SIZE 0x02
#define MAP_OPTIONS MAP_FILE | MAP_PRIVATE
#define MAP_OPTIONS MAP_FILE | MAP_PRIVATE
...
@@ -194,7 +195,7 @@ camogm_state sstate[SENSOR_PORTS];
...
@@ -194,7 +195,7 @@ camogm_state sstate[SENSOR_PORTS];
int
debug_level
;
int
debug_level
;
FILE
*
debug_file
;
FILE
*
debug_file
;
int
camogm_init
(
camogm_state
*
state
,
unsigned
int
port
);
void
camogm_init
(
camogm_state
*
state
,
unsigned
int
port
,
char
*
pipe_name
);
int
camogm_start
(
camogm_state
*
state
);
int
camogm_start
(
camogm_state
*
state
);
int
camogm_stop
(
camogm_state
*
state
);
int
camogm_stop
(
camogm_state
*
state
);
int
camogm_reset
(
camogm_state
*
state
);
//! reset circbuf read pointer
int
camogm_reset
(
camogm_state
*
state
);
//! reset circbuf read pointer
...
@@ -269,7 +270,14 @@ void put_uint64(void *buf, u_int64_t val)
...
@@ -269,7 +270,14 @@ void put_uint64(void *buf, u_int64_t val)
tmp
[
7
]
=
(
val
>>=
8
)
&
0xff
;
tmp
[
7
]
=
(
val
>>=
8
)
&
0xff
;
}
}
int
camogm_init
(
camogm_state
*
state
,
unsigned
int
port
)
/**
* @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
* @param[in] pipe_name pointer to command pipe name string
* @return none
*/
void
camogm_init
(
camogm_state
*
state
,
unsigned
int
port
,
char
*
pipe_name
)
{
{
const
char
sserial
[]
=
"elp0"
;
const
char
sserial
[]
=
"elp0"
;
int
*
ipser
=
(
int
*
)
sserial
;
int
*
ipser
=
(
int
*
)
sserial
;
...
@@ -283,17 +291,17 @@ int camogm_init(camogm_state *state, unsigned int port)
...
@@ -283,17 +291,17 @@ int camogm_init(camogm_state *state, unsigned int port)
camogm_set_ignore_fps
(
state
,
DEFAULT_IGNORE_FPS
);
camogm_set_ignore_fps
(
state
,
DEFAULT_IGNORE_FPS
);
camogm_set_max_frames
(
state
,
DEFAULT_FRAMES
);
camogm_set_max_frames
(
state
,
DEFAULT_FRAMES
);
camogm_set_frames_per_chunk
(
state
,
DEFAULT_FRAMES_PER_CHUNK
);
camogm_set_frames_per_chunk
(
state
,
DEFAULT_FRAMES_PER_CHUNK
);
camogm_set_start_after_timestamp
(
state
,
0
.
0
);
//
/
start any time
camogm_set_start_after_timestamp
(
state
,
0
.
0
);
// start any time
camogm_set_prefix
(
state
,
"
\0
"
);
camogm_set_prefix
(
state
,
"
\0
"
);
camogm_set_save_gp
(
state
,
0
);
camogm_set_save_gp
(
state
,
0
);
camogm_reset
(
state
);
//! sets state->buf_overruns=-1; //!first does not count
camogm_reset
(
state
);
// sets state->buf_overruns =- 1
state
->
serialno
=
ipser
[
0
];
state
->
serialno
=
ipser
[
0
];
state
->
last
=
0
;
state
->
last
=
0
;
debug_file
=
stderr
;
debug_file
=
stderr
;
camogm_debug_level
(
DEFAULT_DEBUG_LVL
);
camogm_debug_level
(
DEFAULT_DEBUG_LVL
);
strcpy
(
state
->
debug_name
,
"stderr"
);
strcpy
(
state
->
debug_name
,
"stderr"
);
camogm_set_timescale
(
state
,
1
.
0
);
camogm_set_timescale
(
state
,
1
.
0
);
camogm_set_frames_skip
(
state
,
0
);
//!
don't skip
camogm_set_frames_skip
(
state
,
0
);
//
don't skip
camogm_set_format
(
state
,
CAMOGM_FORMAT_OGM
);
camogm_set_format
(
state
,
CAMOGM_FORMAT_OGM
);
state
->
exifSize
=
0
;
state
->
exifSize
=
0
;
state
->
exif
=
DEFAULT_EXIF
;
state
->
exif
=
DEFAULT_EXIF
;
...
@@ -302,7 +310,7 @@ int camogm_init(camogm_state *state, unsigned int port)
...
@@ -302,7 +310,7 @@ int camogm_init(camogm_state *state, unsigned int port)
state
->
formats
=
0
;
state
->
formats
=
0
;
state
->
last_error_code
=
0
;
state
->
last_error_code
=
0
;
///
kml stuff
//
kml stuff
camogm_kml_set_enable
(
state
,
0
);
camogm_kml_set_enable
(
state
,
0
);
state
->
kml_file
=
NULL
;
state
->
kml_file
=
NULL
;
camogm_kml_set_horHalfFov
(
state
,
20
.
0
);
camogm_kml_set_horHalfFov
(
state
,
20
.
0
);
...
@@ -314,8 +322,7 @@ int camogm_init(camogm_state *state, unsigned int port)
...
@@ -314,8 +322,7 @@ int camogm_init(camogm_state *state, unsigned int port)
state
->
kml_path
[
0
]
=
'\0'
;
state
->
kml_path
[
0
]
=
'\0'
;
state
->
port_num
=
port
;
state
->
port_num
=
port
;
state
->
pipe_name
=
pipe_name
;
return
0
;
}
}
...
@@ -1280,16 +1287,22 @@ int create_pipe_names(const char *pipe_name, char **names)
...
@@ -1280,16 +1287,22 @@ int create_pipe_names(const char *pipe_name, char **names)
names
[
i
]
=
name
;
names
[
i
]
=
name
;
}
}
if
(
ret
<
0
)
{
for
(
int
i
=
0
;
i
<
SENSOR_PORTS
;
i
++
)
{
free
(
names
[
i
]);
names
[
i
]
=
NULL
;
}
}
return
ret
;
return
ret
;
}
}
/**
/**
* @brief This function closes open files and deletes allocated memory.
* @brief This function closes open files and deletes allocated memory.
* @param[in] state pointer to #camogm_state structure for a particular sensor channel
* @param[in] state pointer to #camogm_state structure for a particular sensor channel
* @param[in] names list of strings containing control pipe names
* return none
* return none
*/
*/
void
clean_up
(
camogm_state
*
state
,
char
**
names
)
void
clean_up
(
camogm_state
*
state
)
{
{
if
(
state
->
fd_exif
>
0
)
if
(
state
->
fd_exif
>
0
)
close
(
state
->
fd_exif
);
close
(
state
->
fd_exif
);
...
@@ -1299,177 +1312,130 @@ void clean_up(camogm_state *state, char **names)
...
@@ -1299,177 +1312,130 @@ void clean_up(camogm_state *state, char **names)
close
(
state
->
fd_circ
);
close
(
state
->
fd_circ
);
if
(
state
->
fd_fparmsall
)
if
(
state
->
fd_fparmsall
)
close
(
state
->
fd_fparmsall
);
close
(
state
->
fd_fparmsall
);
for
(
int
i
=
0
;
i
<
SENSOR_PORTS
;
i
++
)
{
free
(
state
->
pipe_name
);
free
(
names
[
i
]);
state
->
pipe_name
=
NULL
;
names
[
i
]
=
NULL
;
}
}
}
int
main
(
int
argc
,
char
*
argv
[])
/**
* @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_DELAYS 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.
*/
int
listener_loop
(
camogm_state
*
state
)
{
{
// int fd_circ;
FILE
*
cmd_file
;
FILE
*
cmd_file
;
int
rslt
,
ret
,
cmd
;
const
char
usage
[]
=
"This program allows recording of the video/images acquired by Elphel camera to the storage media.
\n
"
\
int
fp0
,
fp1
;
"It is designed to run in the background and accept commands through a named pipe.
\n\n
"
\
int
process
=
1
;
"Usage:
\n\n
"
\
unsigned
int
port
=
state
->
port_num
;
"%s <named_pipe_name>
\n\n
"
\
const
char
*
pipe_name
=
state
->
pipe_name
;
"i.e.:
\n\n
"
\
"%s /var/state/camogm_cmd
\n\n
"
\
// open Exif header file
"When the program is runninig you may send commands by writing strings to the command file
\n
"
\
"(/var/state/camogm_cmd in the example above). The complete list of available commands is available
\n
"
\
"on Elphel Wiki (http://wiki.elphel.com/index.php?title=Camogm), here is the example of usage
\n
"
\
"from the shell prompt in the camera:
\n\n
"
\
"echo
\"
status; exif=1; format=jpeg;status=/var/tmp/camogm.status
\"
> /var/state/camogm_cmd
\n\n
"
\
"That will print status information on the standard output (may not be visible if the program was not
\n
"
\
"started from the same session), set exif mode on (each frame will have the full Exif header including
\n
"
\
"a precise time stamp), set output format to a series of individual JPEG files, and then send status
\n
"
\
"information to a file /var/tmp/camogm.status in the camera file system.
\n\n
"
\
"This program does not control the process of acquisition of the video/images to the camera internal
\n
"
\
"buffer, it only retrieves that data from the buffer (waiting when needed), packages it to selected
\n
"
\
"format and stores the result files.
\n\n
"
;
int
go
=
1
;
int
cmd
;
int
i
,
rslt
;
int
fp0
,
fp1
;
// debugging
/* debug code follows */
unsigned
int
port
=
2
;
/*end of debug code */
camogm_state
*
state
=
&
sstate
[
port
];
char
*
pipe_names
[
SENSOR_PORTS
]
=
{
0
};
// state = &sstate; //extern
//! no command line options processing yet
if
((
argc
<
2
)
||
(
argv
[
1
][
1
]
==
'-'
))
{
printf
(
usage
,
argv
[
0
],
argv
[
0
]);
clean_up
(
state
,
pipe_names
);
return
0
;
}
camogm_init
(
state
,
port
);
create_pipe_names
(
argv
[
1
],
pipe_names
);
//! open Exif header file
#ifdef DISABLE_CODE
#ifdef DISABLE_CODE
state
->
fd_exif
=
open
(
exifFileNames
[
port
],
O_RDONLY
);
state
->
fd_exif
=
open
(
exifFileNames
[
port
],
O_RDONLY
);
if
(
state
->
fd_exif
<
0
)
{
// check control OK
if
(
state
->
fd_exif
<
0
)
{
// check control OK
D0
(
fprintf
(
debug_file
,
"Error opening %s
\n
"
,
exifFileNames
[
port
]));
D0
(
fprintf
(
debug_file
,
"Error opening %s
\n
"
,
exifFileNames
[
port
]));
clean_up
(
state
);
return
-
1
;
return
-
1
;
}
}
#endif
/* DESABLE_CODE */
#endif
/* DESABLE_CODE */
//!
open JPEG header file
//
open JPEG header file
state
->
fd_head
=
open
(
headFileNames
[
port
],
O_RDWR
);
state
->
fd_head
=
open
(
headFileNames
[
port
],
O_RDWR
);
if
(
state
->
fd_head
<
0
)
{
// check control OK
if
(
state
->
fd_head
<
0
)
{
// check control OK
D0
(
fprintf
(
debug_file
,
"Error opening %s
\n
"
,
headFileNames
[
port
]));
D0
(
fprintf
(
debug_file
,
"Error opening %s
\n
"
,
headFileNames
[
port
]));
clean_up
(
state
,
pipe_names
);
clean_up
(
state
);
return
-
1
;
return
-
1
;
}
}
state
->
head_size
=
lseek
(
state
->
fd_head
,
0
,
SEEK_END
);
state
->
head_size
=
lseek
(
state
->
fd_head
,
0
,
SEEK_END
);
if
(
state
->
head_size
>
JPEG_HEADER_MAXSIZE
)
{
if
(
state
->
head_size
>
JPEG_HEADER_MAXSIZE
)
{
D0
(
fprintf
(
debug_file
,
"%s:%d: Too big JPEG header (%d > %d)"
,
__FILE__
,
__LINE__
,
state
->
head_size
,
JPEG_HEADER_MAXSIZE
));
D0
(
fprintf
(
debug_file
,
"%s:%d: Too big JPEG header (%d > %d)"
,
__FILE__
,
__LINE__
,
state
->
head_size
,
JPEG_HEADER_MAXSIZE
));
clean_up
(
state
,
pipe_names
);
clean_up
(
state
);
return
-
2
;
return
-
2
;
}
}
//!
open circbuf and mmap it (once at startup)
//
open circbuf and mmap it (once at startup)
state
->
fd_circ
=
open
(
circbufFileNames
[
port
],
O_RDWR
);
state
->
fd_circ
=
open
(
circbufFileNames
[
port
],
O_RDWR
);
if
(
state
->
fd_circ
<
0
)
{
// check control OK
if
(
state
->
fd_circ
<
0
)
{
// check control OK
D0
(
fprintf
(
debug_file
,
"Error opening %s
\n
"
,
circbufFileNames
[
port
]));
D0
(
fprintf
(
debug_file
,
"Error opening %s
\n
"
,
circbufFileNames
[
port
]));
clean_up
(
state
,
pipe_names
);
clean_up
(
state
);
return
-
2
;
return
-
2
;
}
}
/*! find total buffer length (it is in defines, actually in c313a.h */
// find total buffer length (it is in defines, actually in c313a.h
state
->
circ_buff_size
=
lseek
(
state
->
fd_circ
,
0
,
SEEK_END
);
state
->
circ_buff_size
=
lseek
(
state
->
fd_circ
,
0
,
SEEK_END
);
ccam_dma_buf
[
port
]
=
(
unsigned
long
*
)
mmap
(
0
,
state
->
circ_buff_size
,
PROT_READ
,
MAP_SHARED
,
state
->
fd_circ
,
0
);
ccam_dma_buf
[
port
]
=
(
unsigned
long
*
)
mmap
(
0
,
state
->
circ_buff_size
,
PROT_READ
,
MAP_SHARED
,
state
->
fd_circ
,
0
);
if
((
int
)
ccam_dma_buf
[
port
]
==
-
1
)
{
if
((
int
)
ccam_dma_buf
[
port
]
==
-
1
)
{
D0
(
fprintf
(
debug_file
,
"Error in mmap of %s
\n
"
,
circbufFileNames
[
port
]));
D0
(
fprintf
(
debug_file
,
"Error in mmap of %s
\n
"
,
circbufFileNames
[
port
]));
clean_up
(
state
,
pipe_names
);
clean_up
(
state
);
return
-
3
;
return
-
3
;
}
}
//! Now open/mmap file to read sensor/compressor parameters (currently - just free memory in circbuf and compressor state)
// now open/mmap file to read sensor/compressor parameters (currently - just free memory in circbuf and compressor state)
//! open circbuf and mmap it (once at startup)
#ifdef DISABLE_CODE
#ifdef DISABLE_CODE
state
->
fd_fparmsall
=
open
(
ctlFileNames
[
port
],
O_RDWR
);
state
->
fd_fparmsall
=
open
(
ctlFileNames
[
port
],
O_RDWR
);
if
(
state
->
fd_fparmsall
<
0
)
{
// check control OK
if
(
state
->
fd_fparmsall
<
0
)
{
// check control OK
D0
(
fprintf
(
debug_file
,
"%s:%d:%s: Error opening %s
\n
"
,
__FILE__
,
__LINE__
,
__FUNCTION__
,
ctlFileNames
[
port
]));
D0
(
fprintf
(
debug_file
,
"%s:%d:%s: Error opening %s
\n
"
,
__FILE__
,
__LINE__
,
__FUNCTION__
,
ctlFileNames
[
port
]));
clean_up
(
state
,
pipe_names
);
clean_up
(
state
);
return
-
2
;
return
-
2
;
}
}
//! now try to mmap
// now try to mmap
/// frameParsAll = (struct framepars_all_t *) mmap(0, sizeof (struct framepars_all_t) , PROT_READ, MAP_SHARED, state->fd_fparmsall, 0);
// PROT_WRITE - only to write acknowledge
/// PROT_WRITE - only to write acknowledge
frameParsAll
[
port
]
=
(
struct
framepars_all_t
*
)
mmap
(
0
,
sizeof
(
struct
framepars_all_t
),
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
state
->
fd_fparmsall
,
0
);
frameParsAll
[
port
]
=
(
struct
framepars_all_t
*
)
mmap
(
0
,
sizeof
(
struct
framepars_all_t
),
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
state
->
fd_fparmsall
,
0
);
if
((
int
)
frameParsAll
[
port
]
==
-
1
)
{
if
((
int
)
frameParsAll
[
port
]
==
-
1
)
{
D0
(
fprintf
(
debug_file
,
"%s:%d:%s: Error in mmap in %s
\n
"
,
__FILE__
,
__LINE__
,
__FUNCTION__
,
ctlFileNames
[
port
]));
D0
(
fprintf
(
debug_file
,
"%s:%d:%s: Error in mmap in %s
\n
"
,
__FILE__
,
__LINE__
,
__FUNCTION__
,
ctlFileNames
[
port
]));
clean_up
(
state
,
pipe_names
);
clean_up
(
state
);
return
-
3
;
return
-
3
;
}
}
framePars
[
port
]
=
frameParsAll
[
port
]
->
framePars
;
framePars
[
port
]
=
frameParsAll
[
port
]
->
framePars
;
globalPars
[
port
]
=
frameParsAll
[
port
]
->
globalPars
;
globalPars
[
port
]
=
frameParsAll
[
port
]
->
globalPars
;
#endif
/* DESABLE_CODE */
#endif
/* DESABLE_CODE */
//!
create a named pipe
//
create a named pipe
//!
always delete the pipe if it existed, start a fresh one
//
always delete the pipe if it existed, start a fresh one
i
=
unlink
(
pipe_names
[
port
]
);
ret
=
unlink
(
pipe_name
);
if
(
i
)
{
if
(
ret
)
{
D1
(
fprintf
(
debug_file
,
"Unlink %s returned %d, errno=%d
\n
"
,
pipe_name
s
[
port
],
i
,
errno
));
D1
(
fprintf
(
debug_file
,
"Unlink %s returned %d, errno=%d
\n
"
,
pipe_name
,
ret
,
errno
));
}
}
i
=
mkfifo
(
pipe_names
[
port
]
,
0777
);
//EEXIST
ret
=
mkfifo
(
pipe_name
,
0777
);
//EEXIST
//!
now should not exist
//
now should not exist
if
(
i
)
{
if
(
ret
)
{
if
(
errno
==
EEXIST
)
{
if
(
errno
==
EEXIST
)
{
D1
(
fprintf
(
debug_file
,
"Named pipe %s already exists, will use it.
\n
"
,
pipe_name
s
[
port
]
));
D1
(
fprintf
(
debug_file
,
"Named pipe %s already exists, will use it.
\n
"
,
pipe_name
));
}
else
{
}
else
{
D0
(
fprintf
(
debug_file
,
"Can not create a named pipe %s, errno=%d
\n
"
,
pipe_name
s
[
port
]
,
errno
));
D0
(
fprintf
(
debug_file
,
"Can not create a named pipe %s, errno=%d
\n
"
,
pipe_name
,
errno
));
clean_up
(
state
,
pipe_names
);
clean_up
(
state
);
return
-
4
;
return
-
4
;
}
}
}
}
//!now open the pipe - will block until something will be written (or just open for writing
// now open the pipe - will block until something will be written (or just open for writing,
//!Reads themselves will not block
// reads themselves will not block)
if
(
!
((
cmd_file
=
fopen
(
pipe_name
s
[
port
]
,
"r"
))))
{
if
(
!
((
cmd_file
=
fopen
(
pipe_name
,
"r"
))))
{
D0
(
fprintf
(
debug_file
,
"Can not open command file %s
\n
"
,
pipe_name
s
[
port
]
));
D0
(
fprintf
(
debug_file
,
"Can not open command file %s
\n
"
,
pipe_name
));
clean_up
(
state
,
pipe_names
);
clean_up
(
state
);
return
-
5
;
return
-
5
;
}
}
// D1(fprintf (debug_file,"Pipe %s open for reading\n",argv[1]));
D0
(
fprintf
(
debug_file
,
"Pipe %s open for reading
\n
"
,
pipe_name
));
// to make sure something is sent out
D0
(
fprintf
(
debug_file
,
"Pipe %s open for reading
\n
"
,
pipe_names
[
port
]));
// to make sure something is sent out
//! Here is a main loop. If recording is on, it will check for commands after each frame, if it is off - poll with fixed usleep
#define COMMAND_LOOP_DELAY 500000 //0.5sec
while
(
go
)
{
// D3(fprintf (debug_file,"%s:%d: format=%d, set_format=%d\n",__FILE__,__LINE__, state->format, state->set_format));
//! look at command queue first
// enter main processing loop
while
(
process
)
{
// look at command queue first
cmd
=
parse_cmd
(
state
,
cmd_file
);
cmd
=
parse_cmd
(
state
,
cmd_file
);
if
(
cmd
)
{
if
(
cmd
)
{
if
(
cmd
<
0
)
D0
(
fprintf
(
debug_file
,
"Unrecognized command
\n
"
));
if
(
cmd
<
0
)
D0
(
fprintf
(
debug_file
,
"Unrecognized command
\n
"
));
/// Acknowledge received command by copying frame number to per-daemon parameter
}
else
if
(
state
->
running
)
{
// no commands in queue, started
// GLOBALPARS(G_DAEMON_ERR+lastDaemonBit)=GLOBALPARS(G_THIS_FRAME);
}
else
if
(
state
->
running
)
{
//!no commands in queue, started
// D3(fprintf (debug_file,"%s:%d: format=%d, set_format=%d\n",__FILE__,__LINE__, state->format, state->set_format));
switch
((
rslt
=
-
sendImageFrame
(
state
)))
{
switch
((
rslt
=
-
sendImageFrame
(
state
)))
{
case
0
:
case
0
:
/*
break
;
// frame sent OK, nothing to do (TODO: check file length/duration)
D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned %d\n" \
case
CAMOGM_FRAME_NOT_READY
:
// just wait for the frame to appear at the current pointer
"state->cirbuf_rp= 0x%x\n",__FILE__,__LINE__,rslt,state->cirbuf_rp));
// we'll wait for a frame, not to waste resources. But if the compressor is stopped this program will not respond to any commands
*/
// TODO - add another wait with (short) timeout?
break
;
//! frame sent OK, nothing to do (TODO: check file length/duration)
case
CAMOGM_FRAME_NOT_READY
:
//! just wait for the frame to appear at the current pointer
//! we'll wait for a frame, not to waste resources. But if the compressor is stopped this program will not respond to any commands
//! TODO - add another wait with (short) timeout?
// D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned -%d\n",__FILE__,__LINE__,rslt));
/*
D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned -%d\n" \
"state->cirbuf_rp= 0x%x\n",__FILE__,__LINE__,rslt,state->cirbuf_rp));
*/
// lseek(state->fd_circ,LSEEK_CIRC_WAIT,SEEK_END);
fp0
=
lseek
(
state
->
fd_circ
,
0
,
SEEK_CUR
);
fp0
=
lseek
(
state
->
fd_circ
,
0
,
SEEK_CUR
);
if
(
fp0
<
0
)
{
if
(
fp0
<
0
)
{
D0
(
fprintf
(
debug_file
,
"%s:line %d got broken frame (%d) before waiting for ready
\n
"
,
__FILE__
,
__LINE__
,
fp0
));
D0
(
fprintf
(
debug_file
,
"%s:line %d got broken frame (%d) before waiting for ready
\n
"
,
__FILE__
,
__LINE__
,
fp0
));
...
@@ -1483,64 +1449,111 @@ int main(int argc, char *argv[])
...
@@ -1483,64 +1449,111 @@ int main(int argc, char *argv[])
break
;
break
;
}
}
}
}
// break;
// no break
case
CAMOGM_FRAME_CHANGED
:
//
!
frame parameters have changed
case
CAMOGM_FRAME_CHANGED
:
// frame parameters have changed
case
CAMOGM_FRAME_NEXTFILE
:
//
!
next file needed (need to switch to a new file (time/size exceeded limit)
case
CAMOGM_FRAME_NEXTFILE
:
// next file needed (need to switch to a new file (time/size exceeded limit)
case
CAMOGM_FRAME_INVALID
:
//
!
invalid frame pointer
case
CAMOGM_FRAME_INVALID
:
// invalid frame pointer
case
CAMOGM_FRAME_BROKEN
:
//
!
frame broken (buffer overrun)
case
CAMOGM_FRAME_BROKEN
:
// frame broken (buffer overrun)
//!
restart the file
//
restart the file
// D3(fprintf (debug_file,"%s:line %d - sendImageFrame() returned -%d\n",__FILE__,__LINE__,
rslt));
D3
(
fprintf
(
debug_file
,
"%s:line %d - sendImageFrame() returned -%d
\n
"
,
__FILE__
,
__LINE__
,
rslt
));
camogm_stop
(
state
);
camogm_stop
(
state
);
camogm_start
(
state
);
camogm_start
(
state
);
break
;
break
;
case
CAMOGM_FRAME_FILE_ERR
:
//
!
error with file I/O
case
CAMOGM_FRAME_FILE_ERR
:
// error with file I/O
case
CAMOGM_FRAME_OTHER
:
//
!
other errors
case
CAMOGM_FRAME_OTHER
:
// other errors
D0
(
fprintf
(
debug_file
,
"%s:line %d - error=%d
\n
"
,
__FILE__
,
__LINE__
,
rslt
));
D0
(
fprintf
(
debug_file
,
"%s:line %d - error=%d
\n
"
,
__FILE__
,
__LINE__
,
rslt
));
break
;
break
;
default:
default:
D0
(
fprintf
(
debug_file
,
"%s:line %d - should not get here (rslt=%d)
\n
"
,
__FILE__
,
__LINE__
,
rslt
));
D0
(
fprintf
(
debug_file
,
"%s:line %d - should not get here (rslt=%d)
\n
"
,
__FILE__
,
__LINE__
,
rslt
));
clean_up
(
state
,
pipe_names
);
clean_up
(
state
);
exit
(
-
1
);
exit
(
-
1
);
}
//switch
}
// switch sendImageFrame()
if
((
rslt
!=
0
)
&&
(
rslt
!=
CAMOGM_FRAME_NOT_READY
)
&&
(
rslt
!=
CAMOGM_FRAME_CHANGED
))
state
->
last_error_code
=
rslt
;
if
((
rslt
!=
0
)
&&
(
rslt
!=
CAMOGM_FRAME_NOT_READY
)
&&
(
rslt
!=
CAMOGM_FRAME_CHANGED
))
state
->
last_error_code
=
rslt
;
}
else
if
(
state
->
starting
)
{
//!no commands in queue,starting (but not started yet)
}
else
if
(
state
->
starting
)
{
// no commands in queue,starting (but not started yet)
// D3(fprintf (debug_file,"%s:%d: format=%d, set_format=%d\n",__FILE__,__LINE__, state->format, state->set_format));
//!
retry starting
//
retry starting
switch
((
rslt
=
-
camogm_start
(
state
)))
{
switch
((
rslt
=
-
camogm_start
(
state
)))
{
case
0
:
break
;
//! file started OK, nothing to do
case
0
:
break
;
// file started OK, nothing to do
case
CAMOGM_TOO_EARLY
:
case
CAMOGM_TOO_EARLY
:
lseek
(
state
->
fd_circ
,
LSEEK_CIRC_TOWP
,
SEEK_END
);
/// set pointer to the frame to wait for
lseek
(
state
->
fd_circ
,
LSEEK_CIRC_TOWP
,
SEEK_END
);
// set pointer to the frame to wait for
lseek
(
state
->
fd_circ
,
LSEEK_CIRC_WAIT
,
SEEK_END
);
/// It already passed CAMOGM_FRAME_NOT_READY, so compressor may be running already
lseek
(
state
->
fd_circ
,
LSEEK_CIRC_WAIT
,
SEEK_END
);
// It already passed CAMOGM_FRAME_NOT_READY, so compressor may be running already
break
;
/// no need to wait extra
break
;
// no need to wait extra
case
CAMOGM_FRAME_NOT_READY
:
//! just wait for the frame to appear at the current pointer
case
CAMOGM_FRAME_NOT_READY
:
// just wait for the frame to appear at the current pointer
//! we'll wait for a frame, not to waste resources. But if the compressor is stopped this program will not respond to any commands
// we'll wait for a frame, not to waste resources. But if the compressor is stopped this program will not respond to any commands
//! TODO - add another wait with (short) timeout?
// TODO - add another wait with (short) timeout?
// lseek(state->fd_circ,LSEEK_CIRC_WAIT,SEEK_END);
case
CAMOGM_FRAME_CHANGED
:
// frame parameters have changed
case
CAMOGM_FRAME_CHANGED
:
//! frame parameters have changed
case
CAMOGM_FRAME_NEXTFILE
:
case
CAMOGM_FRAME_NEXTFILE
:
case
CAMOGM_FRAME_INVALID
:
//! invalid frame pointer
case
CAMOGM_FRAME_INVALID
:
// invalid frame pointer
case
CAMOGM_FRAME_BROKEN
:
//! frame broken (buffer overrun)
case
CAMOGM_FRAME_BROKEN
:
// frame broken (buffer overrun)
// D3(fprintf (debug_file,"%s:line %d - camogm_start() returned -%d, state->cirbuf_rp= 0x%x\n", __FILE__,__LINE__,rslt,state->cirbuf_rp));
usleep
(
COMMAND_LOOP_DELAY
);
// it should be not too long so empty buffer will not be overrun
usleep
(
COMMAND_LOOP_DELAY
);
//! it should be not too long so empty buffer will not be overrun
break
;
break
;
case
CAMOGM_FRAME_FILE_ERR
:
//!
error with file I/O
case
CAMOGM_FRAME_FILE_ERR
:
//
error with file I/O
case
CAMOGM_FRAME_OTHER
:
//!
other errors
case
CAMOGM_FRAME_OTHER
:
//
other errors
D0
(
fprintf
(
debug_file
,
"%s:line %d - error=%d
\n
"
,
__FILE__
,
__LINE__
,
rslt
));
D0
(
fprintf
(
debug_file
,
"%s:line %d - error=%d
\n
"
,
__FILE__
,
__LINE__
,
rslt
));
break
;
break
;
default:
default:
D0
(
fprintf
(
debug_file
,
"%s:line %d - should not get here (rslt=%d)
\n
"
,
__FILE__
,
__LINE__
,
rslt
));
D0
(
fprintf
(
debug_file
,
"%s:line %d - should not get here (rslt=%d)
\n
"
,
__FILE__
,
__LINE__
,
rslt
));
clean_up
(
state
,
pipe_names
);
clean_up
(
state
);
exit
(
-
1
);
exit
(
-
1
);
}
//
switch
}
//
switch camogm_start()
if
((
rslt
!=
0
)
&&
(
rslt
!=
CAMOGM_TOO_EARLY
)
&&
(
rslt
!=
CAMOGM_FRAME_NOT_READY
)
&&
(
rslt
!=
CAMOGM_FRAME_CHANGED
)
)
state
->
last_error_code
=
rslt
;
if
((
rslt
!=
0
)
&&
(
rslt
!=
CAMOGM_TOO_EARLY
)
&&
(
rslt
!=
CAMOGM_FRAME_NOT_READY
)
&&
(
rslt
!=
CAMOGM_FRAME_CHANGED
)
)
state
->
last_error_code
=
rslt
;
}
else
{
//! not running, not starting
}
else
{
// not running, not starting
usleep
(
COMMAND_LOOP_DELAY
);
//! make it longer but interruptible by signals?
usleep
(
COMMAND_LOOP_DELAY
);
// make it longer but interruptible by signals?
}
}
// while (process)
// normally, we should not be here
clean_up
(
state
);
return
EXIT_SUCCESS
;
}
int
main
(
int
argc
,
char
*
argv
[])
{
const
char
usage
[]
=
"This program allows recording of the video/images acquired by Elphel camera to the storage media.
\n
"
\
"It is designed to run in the background and accept commands through a named pipe.
\n\n
"
\
"Usage:
\n\n
"
\
"%s <named_pipe_name>
\n\n
"
\
"i.e.:
\n\n
"
\
"%s /var/state/camogm_cmd
\n\n
"
\
"When the program is runninig you may send commands by writing strings to the command file
\n
"
\
"(/var/state/camogm_cmd in the example above). The complete list of available commands is available
\n
"
\
"on Elphel Wiki (http://wiki.elphel.com/index.php?title=Camogm), here is the example of usage
\n
"
\
"from the shell prompt in the camera:
\n\n
"
\
"echo
\"
status; exif=1; format=jpeg;status=/var/tmp/camogm.status
\"
> /var/state/camogm_cmd
\n\n
"
\
"That will print status information on the standard output (may not be visible if the program was not
\n
"
\
"started from the same session), set exif mode on (each frame will have the full Exif header including
\n
"
\
"a precise time stamp), set output format to a series of individual JPEG files, and then send status
\n
"
\
"information to a file /var/tmp/camogm.status in the camera file system.
\n\n
"
\
"This program does not control the process of acquisition of the video/images to the camera internal
\n
"
\
"buffer, it only retrieves that data from the buffer (waiting when needed), packages it to selected
\n
"
\
"format and stores the result files.
\n\n
"
;
char
*
pipe_names
[
SENSOR_PORTS
]
=
{
0
};
int
ret
;
// no command line options processing yet
if
((
argc
<
2
)
||
(
argv
[
1
][
1
]
==
'-'
))
{
printf
(
usage
,
argv
[
0
],
argv
[
0
]);
return
EXIT_SUCCESS
;
}
}
if
(
create_pipe_names
(
argv
[
1
],
pipe_names
)
<
0
)
{
printf
(
"Error: unable to allocate memory for command pipe name
\n
"
);
return
EXIT_FAILURE
;
}
}
clean_up
(
state
,
pipe_names
);
return
0
;
// spawn a process for each sensor port
for
(
int
i
=
0
;
i
<
SENSOR_PORTS
;
i
++
)
{
camogm_init
(
&
sstate
[
i
],
i
,
pipe_names
[
i
]);
if
(
fork
()
==
0
)
{
ret
=
listener_loop
(
&
sstate
[
i
]);
exit
(
ret
);
}
}
return
EXIT_SUCCESS
;
}
}
/**
/**
...
...
camogm.h
View file @
4567a7bf
...
@@ -87,7 +87,7 @@ typedef struct {
...
@@ -87,7 +87,7 @@ typedef struct {
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
];
unsigned
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
;
...
@@ -158,7 +158,8 @@ typedef struct {
...
@@ -158,7 +158,8 @@ typedef struct {
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
unsigned
int
port_num
;
unsigned
int
port_num
;
// sensor port this state assigned to
char
*
pipe_name
;
// command pipe name for this sensor port
}
camogm_state
;
}
camogm_state
;
extern
int
debug_level
;
extern
int
debug_level
;
...
...
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