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
86dd9391
Commit
86dd9391
authored
Mar 29, 2017
by
Mikhail Karpenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WIP: Write aligned frames to block device
parent
d9fcca99
Changes
6
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
708 additions
and
53 deletions
+708
-53
Makefile
src/Makefile
+1
-1
camogm.c
src/camogm.c
+16
-12
camogm.h
src/camogm.h
+10
-1
camogm_align.c
src/camogm_align.c
+516
-0
camogm_align.h
src/camogm_align.h
+82
-0
camogm_jpeg.c
src/camogm_jpeg.c
+83
-39
No files found.
src/Makefile
View file @
86dd9391
...
@@ -11,7 +11,7 @@ IMAGES = $(GUIDIR)/images/filebrowser-01.gif $(GUIDIR)/images/filebrowser-bo
...
@@ -11,7 +11,7 @@ IMAGES = $(GUIDIR)/images/filebrowser-01.gif $(GUIDIR)/images/filebrowser-bo
$(GUIDIR)
/images/rec_folder.png
$(GUIDIR)
/images/up_folder.gif
$(GUIDIR)
/images/play_audio.png
$(GUIDIR)
/images/hdd.png
$(GUIDIR)
/images/rec_folder.png
$(GUIDIR)
/images/up_folder.gif
$(GUIDIR)
/images/play_audio.png
$(GUIDIR)
/images/hdd.png
SRCS
=
camogm.c camogm_ogm.c camogm_jpeg.c camogm_mov.c camogm_kml.c camogm_read.c index_list.c
SRCS
=
camogm.c camogm_ogm.c camogm_jpeg.c camogm_mov.c camogm_kml.c camogm_read.c index_list.c
camogm_align.c
TEST_SRC
=
camogm_test.c
TEST_SRC
=
camogm_test.c
OBJS
=
$
(
SRCS:.c
=
.o
)
OBJS
=
$
(
SRCS:.c
=
.o
)
...
...
src/camogm.c
View file @
86dd9391
...
@@ -514,8 +514,7 @@ int sendImageFrame(camogm_state *state)
...
@@ -514,8 +514,7 @@ int sendImageFrame(camogm_state *state)
int
port
=
state
->
port_num
;
int
port
=
state
->
port_num
;
struct
timeval
start_time
,
end_time
;
struct
timeval
start_time
,
end_time
;
D6
(
fprintf
(
debug_file
,
"last_error_code = %d
\n
"
,
state
->
last_error_code
));
// start_time = get_fpga_time(state->fd_fparmsall[port], port);
start_time
=
get_fpga_time
(
state
->
fd_fparmsall
[
port
],
port
);
// This is probably needed only for Quicktime (not to exceed already allocated frame index)
// This is probably needed only for Quicktime (not to exceed already allocated frame index)
if
(
!
state
->
rawdev_op
&&
(
state
->
frameno
>=
(
state
->
max_frames
)))
{
if
(
!
state
->
rawdev_op
&&
(
state
->
frameno
>=
(
state
->
max_frames
)))
{
...
@@ -646,12 +645,14 @@ int sendImageFrame(camogm_state *state)
...
@@ -646,12 +645,14 @@ int sendImageFrame(camogm_state *state)
/* copy from the beginning of the buffer to the end of the frame */
/* copy from the beginning of the buffer to the end of the frame */
state
->
packetchunks
[
state
->
chunk_index
].
bytes
=
state
->
jpeg_len
-
(
state
->
circ_buff_size
[
port
]
-
state
->
cirbuf_rp
[
port
]);
state
->
packetchunks
[
state
->
chunk_index
].
bytes
=
state
->
jpeg_len
-
(
state
->
circ_buff_size
[
port
]
-
state
->
cirbuf_rp
[
port
]);
state
->
packetchunks
[
state
->
chunk_index
++
].
chunk
=
(
unsigned
char
*
)
&
ccam_dma_buf
[
state
->
port_num
][
0
];
state
->
packetchunks
[
state
->
chunk_index
++
].
chunk
=
(
unsigned
char
*
)
&
ccam_dma_buf
[
state
->
port_num
][
0
];
state
->
writer_params
.
segments
=
2
;
}
else
{
// single segment
}
else
{
// single segment
D3
(
fprintf
(
debug_file
,
"_11_"
));
D3
(
fprintf
(
debug_file
,
"_11_"
));
/* copy from the beginning of the frame to the end of the frame (no buffer rollovers) */
/* copy from the beginning of the frame to the end of the frame (no buffer rollovers) */
state
->
packetchunks
[
state
->
chunk_index
].
bytes
=
state
->
jpeg_len
;
state
->
packetchunks
[
state
->
chunk_index
].
bytes
=
state
->
jpeg_len
;
state
->
packetchunks
[
state
->
chunk_index
++
].
chunk
=
(
unsigned
char
*
)
&
ccam_dma_buf
[
state
->
port_num
][
state
->
cirbuf_rp
[
port
]
>>
2
];
state
->
packetchunks
[
state
->
chunk_index
++
].
chunk
=
(
unsigned
char
*
)
&
ccam_dma_buf
[
state
->
port_num
][
state
->
cirbuf_rp
[
port
]
>>
2
];
state
->
writer_params
.
segments
=
1
;
}
}
D3
(
fprintf
(
debug_file
,
"
\t
cirbuf_rp = 0x%x
\t
"
,
state
->
cirbuf_rp
[
port
]));
D3
(
fprintf
(
debug_file
,
"
\t
cirbuf_rp = 0x%x
\t
"
,
state
->
cirbuf_rp
[
port
]));
D3
(
fprintf
(
debug_file
,
"_12_"
));
D3
(
fprintf
(
debug_file
,
"_12_"
));
...
@@ -687,16 +688,16 @@ int sendImageFrame(camogm_state *state)
...
@@ -687,16 +688,16 @@ int sendImageFrame(camogm_state *state)
}
}
D3
(
fprintf
(
debug_file
,
"cirbuf_rp to next frame = 0x%x
\n
"
,
state
->
cirbuf_rp
[
port
]));
D3
(
fprintf
(
debug_file
,
"cirbuf_rp to next frame = 0x%x
\n
"
,
state
->
cirbuf_rp
[
port
]));
end_time
=
get_fpga_time
(
state
->
fd_fparmsall
[
port
],
port
);
//
end_time = get_fpga_time(state->fd_fparmsall[port], port);
unsigned
int
mbps
;
// write speed, MB/s
//
unsigned int mbps; // write speed, MB/s
unsigned
long
long
time_diff
;
// time elapsed, in microseconds
//
unsigned long long time_diff; // time elapsed, in microseconds
time_diff
=
((
end_time
.
tv_sec
*
1000000
+
end_time
.
tv_usec
)
-
(
start_time
.
tv_sec
*
1000000
+
start_time
.
tv_usec
));
//
time_diff = ((end_time.tv_sec * 1000000 + end_time.tv_usec) - (start_time.tv_sec * 1000000 + start_time.tv_usec));
mbps
=
((
double
)
state
->
rawdev
.
last_jpeg_size
/
(
double
)
1048576
)
/
((
double
)
time_diff
/
(
double
)
1000000
);
//
mbps = ((double)state->rawdev.last_jpeg_size / (double)1048576) / ((double)time_diff / (double)1000000);
D6
(
fprintf
(
debug_file
,
"Frame start time: %ld:%ld; frame end time: %ld:%ld; last frame size: %lu
\n
"
,
//
D6(fprintf(debug_file, "Frame start time: %ld:%ld; frame end time: %ld:%ld; last frame size: %lu\n",
start_time
.
tv_sec
,
start_time
.
tv_usec
,
//
start_time.tv_sec, start_time.tv_usec,
end_time
.
tv_sec
,
end_time
.
tv_usec
,
//
end_time.tv_sec, end_time.tv_usec,
state
->
rawdev
.
last_jpeg_size
));
//
state->rawdev.last_jpeg_size));
D6
(
fprintf
(
debug_file
,
"Write speed: %d MB/s
\n
"
,
mbps
));
//
D6(fprintf(debug_file, "Write speed: %d MB/s\n", mbps));
return
0
;
return
0
;
}
}
...
@@ -880,6 +881,9 @@ void get_disk_info(camogm_state *state)
...
@@ -880,6 +881,9 @@ void get_disk_info(camogm_state *state)
}
}
if
(
get_disk_range
(
state
->
rawdev
.
rawdev_path
,
&
rng
)
==
0
)
{
if
(
get_disk_range
(
state
->
rawdev
.
rawdev_path
,
&
rng
)
==
0
)
{
state
->
writer_params
.
lba_start
=
rng
.
from
;
state
->
writer_params
.
lba_end
=
rng
.
to
;
state
->
writer_params
.
lba_current
=
state
->
writer_params
.
lba_start
;
set_disk_range
(
&
rng
);
set_disk_range
(
&
rng
);
}
else
{
}
else
{
D0
(
fprintf
(
debug_file
,
"ERROR: unable to get disk size and starting sector
\n
"
));
D0
(
fprintf
(
debug_file
,
"ERROR: unable to get disk size and starting sector
\n
"
));
...
...
src/camogm.h
View file @
86dd9391
...
@@ -27,7 +27,6 @@
...
@@ -27,7 +27,6 @@
#include <elphel/c313a.h>
#include <elphel/c313a.h>
#include <elphel/x393_devices.h>
#include <elphel/x393_devices.h>
#define CAMOGM_FRAME_NOT_READY 1 ///< frame pointer valid, but not yet acquired
#define CAMOGM_FRAME_NOT_READY 1 ///< frame pointer valid, but not yet acquired
#define CAMOGM_FRAME_INVALID 2 ///< invalid frame pointer
#define CAMOGM_FRAME_INVALID 2 ///< invalid frame pointer
#define CAMOGM_FRAME_CHANGED 3 ///< frame parameters have changed
#define CAMOGM_FRAME_CHANGED 3 ///< frame parameters have changed
...
@@ -150,6 +149,16 @@ struct writer_params {
...
@@ -150,6 +149,16 @@ struct writer_params {
int
last_ret_val
;
///< error value return during last frame recording (if any occurred)
int
last_ret_val
;
///< error value return during last frame recording (if any occurred)
bool
exit_thread
;
///< flag indicating that the writing thread should terminate
bool
exit_thread
;
///< flag indicating that the writing thread should terminate
int
state
;
///< the state of disk writing thread
int
state
;
///< the state of disk writing thread
int
segments
;
///< the number of segments in frame
struct
iovec
*
data_chunks
;
///< a set of vectors pointing to aligned frame data buffers
struct
iovec
prev_rem_vect
;
///< vector pointing to the remainder of the previous frame
unsigned
char
*
rem_buff
;
///< buffer containing the unaligned remainder of the current frame
unsigned
char
*
prev_rem_buff
;
///< buffer containing the unaligned remainder of the previous frame
unsigned
char
*
common_buff
;
///< buffer for aligned JPEG header
uint64_t
lba_start
;
///< disk starting LBA
uint64_t
lba_current
;
///< current write position in LBAs
uint64_t
lba_end
;
///< disk last LBA
};
};
/**
/**
* @struct camogm_state
* @struct camogm_state
...
...
src/camogm_align.c
0 → 100644
View file @
86dd9391
This diff is collapsed.
Click to expand it.
src/camogm_align.h
0 → 100644
View file @
86dd9391
/** @file camogm_align.h
* @brief Provides frame alignment functions use for recording to block device.
* @copyright Copyright (C) 2017 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_ALIGN_H
#define _CAMOGM_ALIGN_H
#include <unistd.h>
#include <sys/types.h>
#include "camogm.h"
#define PHY_BLOCK_SIZE 512 ///< Physical disk block size
#define JPEG_MARKER_LEN 2 ///< The size in bytes of JPEG marker
#define JPEG_SIZE_LEN 2 ///< The size in bytes of JPEG marker length field
#define INCLUDE_REM 1 ///< Include REM buffer to total size calculation
#define EXCLUDE_REM 0 ///< Exclude REM buffer from total size calculation
#define MAX_DATA_CHUNKS 9 ///< An array or JPEG frame chunks contains pointers to JPEG leading marker,
///< JPEG header, Exif data if present, stuffing bytes chunk which aligns
///< the frame size to disk sector boundary, JPEG data which
///< can be split into two chunks, align buffers, JPEG
///< trailing marker, and pointer to a buffer containing the remainder of a
///< frame. Nine chunks of data in total.
#define ALIGNMENT_SIZE 32 ///< Align buffers length to this amount of bytes
/** Common buffer should be large enough to contain JPEG header, Exif, some alignment bytes and remainder from previous frame */
#define COMMON_BUFF_SZ MAX_EXIF_SIZE + JPEG_HEADER_MAXSIZE + ALIGNMENT_SIZE + 2 * PHY_BLOCK_SIZE
#define REM_BUFF_SZ 2 * PHY_BLOCK_SIZE
///** This structure holds raw device buffer pointers */
//struct drv_pointers {
// uint64_t lba_start; ///< raw buffer starting LBA
// uint64_t lba_end; ///< raw buffer ending LBA
// uint64_t lba_write; ///< current write pointer inside raw buffer
// uint16_t wr_count; ///< the number of LBA to write next time
//};
/** Container structure for frame buffers */
//struct frame_buffers {
// struct fvec exif_buff; ///< Exif buffer
// struct fvec jpheader_buff; ///< JPEG header buffer
// struct fvec trailer_buff; ///< buffer for trailing marker
// struct fvec common_buff; ///< common buffer where other parts are combined
// struct fvec rem_buff; ///< remainder from previous frame
//};
/** Symbolic names for slots in buffer pointers. Buffer alignment function relies on the order of these names, so
* new names can be added but the overall order should not be changed */
enum
{
CHUNK_LEADER
,
///< pointer to JPEG leading marker
CHUNK_EXIF
,
///< pointer to Exif buffer
CHUNK_HEADER
,
///< pointer to JPEG header data excluding leading marker
CHUNK_COMMON
,
///< pointer to common buffer
CHUNK_DATA_0
,
///< pointer to JPEG data
CHUNK_DATA_1
,
///< pointer to the second half of JPEG data if a frame crosses circbuf boundary
CHUNK_TRAILER
,
///< pointer to JPEG trailing marker
CHUNK_ALIGN
,
///< pointer to buffer where the second part of JPEG data should be aligned
CHUNK_REM
///< pointer to buffer containing the remainder of current frame. It will be recorded during next transaction
};
int
init_align_buffers
(
camogm_state
*
state
);
void
deinit_align_buffers
(
camogm_state
*
state
);
void
align_frame
(
camogm_state
*
state
);
void
reset_chunks
(
struct
iovec
*
vects
,
int
all
);
int
update_lba
(
camogm_state
*
state
);
int
get_data_buffers
(
camogm_state
*
state
,
struct
iovec
*
mapped
,
size_t
all_sz
);
int
prep_last_block
(
camogm_state
*
state
);
off64_t
lba_to_offset
(
uint64_t
lba
);
#endif
/* _CAMOGM_ALIGN_H */
src/camogm_jpeg.c
View file @
86dd9391
...
@@ -32,12 +32,15 @@
...
@@ -32,12 +32,15 @@
#include "camogm_jpeg.h"
#include "camogm_jpeg.h"
#include "camogm_read.h"
#include "camogm_read.h"
#include "camogm_align.h"
/** State file record format. It includes device path in /dev, starting, current and ending LBAs */
/** State file record format. It includes device path in /dev, starting, current and ending LBAs */
#define STATE_FILE_FORMAT "%s\t%llu\t%llu\t%llu\n"
#define STATE_FILE_FORMAT "%s\t%llu\t%llu\t%llu\n"
/* forward declarations */
/* forward declarations */
static
void
*
jpeg_writer
(
void
*
thread_args
);
static
void
*
jpeg_writer
(
void
*
thread_args
);
static
int
save_state_file
(
const
rawdev_buffer
*
rawdev
,
uint64_t
current_pos
);
static
int
open_state_file
(
const
rawdev_buffer
*
rawdev
,
uint64_t
*
current_pos
);
/** Get starting and endign LBAs of the partition specified as raw device buffer */
/** Get starting and endign LBAs of the partition specified as raw device buffer */
static
int
get_disk_range
(
struct
range
*
range
)
static
int
get_disk_range
(
struct
range
*
range
)
...
@@ -96,12 +99,12 @@ static int find_state(FILE *f, uint64_t *pos, const rawdev_buffer *rawdev)
...
@@ -96,12 +99,12 @@ static int find_state(FILE *f, uint64_t *pos, const rawdev_buffer *rawdev)
}
}
/** Read state from file and restore disk write pointer */
/** Read state from file and restore disk write pointer */
static
int
open_state_file
(
const
rawdev_buffer
*
rawdev
)
static
int
open_state_file
(
const
rawdev_buffer
*
rawdev
,
uint64_t
*
current_pos
)
{
{
int
fd
,
len
;
int
fd
,
len
;
FILE
*
f
;
FILE
*
f
;
int
ret
=
0
;
int
ret
=
0
;
uint64_t
curr
_pos
;
uint64_t
lba
_pos
;
char
buff
[
SMALL_BUFF_LEN
]
=
{
0
};
char
buff
[
SMALL_BUFF_LEN
]
=
{
0
};
if
(
strlen
(
rawdev
->
state_path
)
==
0
)
{
if
(
strlen
(
rawdev
->
state_path
)
==
0
)
{
...
@@ -110,15 +113,9 @@ static int open_state_file(const rawdev_buffer *rawdev)
...
@@ -110,15 +113,9 @@ static int open_state_file(const rawdev_buffer *rawdev)
f
=
fopen
(
rawdev
->
state_path
,
"r"
);
f
=
fopen
(
rawdev
->
state_path
,
"r"
);
if
(
f
!=
NULL
)
{
if
(
f
!=
NULL
)
{
if
(
find_state
(
f
,
&
curr_pos
,
rawdev
)
!=
-
1
)
{
if
(
find_state
(
f
,
&
lba_pos
,
rawdev
)
!=
-
1
)
{
fd
=
open
(
SYSFS_AHCI_LBA_CURRENT
,
O_WRONLY
);
*
current_pos
=
lba_pos
;
if
(
fd
>=
0
)
{
D0
(
fprintf
(
debug_file
,
"Got starting LBA from state file: %llu
\n
"
,
lba_pos
));
len
=
snprintf
(
buff
,
SMALL_BUFF_LEN
,
"%llu"
,
curr_pos
);
write
(
fd
,
buff
,
len
+
1
);
close
(
fd
);
}
else
{
ret
=
-
1
;
}
}
}
fclose
(
f
);
fclose
(
f
);
}
else
{
}
else
{
...
@@ -129,12 +126,11 @@ static int open_state_file(const rawdev_buffer *rawdev)
...
@@ -129,12 +126,11 @@ static int open_state_file(const rawdev_buffer *rawdev)
}
}
/** Save current position of the disk write pointer */
/** Save current position of the disk write pointer */
static
int
save_state_file
(
const
rawdev_buffer
*
rawdev
)
static
int
save_state_file
(
const
rawdev_buffer
*
rawdev
,
uint64_t
current_pos
)
{
{
int
ret
=
0
;
int
ret
=
0
;
FILE
*
f
;
FILE
*
f
;
struct
range
range
;
struct
range
range
;
uint64_t
curr_pos
;
if
(
strlen
(
rawdev
->
state_path
)
==
0
)
{
if
(
strlen
(
rawdev
->
state_path
)
==
0
)
{
return
ret
;
return
ret
;
...
@@ -143,21 +139,13 @@ static int save_state_file(const rawdev_buffer *rawdev)
...
@@ -143,21 +139,13 @@ static int save_state_file(const rawdev_buffer *rawdev)
return
-
1
;
return
-
1
;
}
}
// get raw device buffer current postion on disk, this position indicates where recording has stopped
f
=
fopen
(
SYSFS_AHCI_LBA_CURRENT
,
"r"
);
if
(
f
==
NULL
)
{
return
-
1
;
}
fscanf
(
f
,
"%llu
\n
"
,
&
curr_pos
);
fclose
(
f
);
// save pointers to a regular file
// save pointers to a regular file
f
=
fopen
(
rawdev
->
state_path
,
"w"
);
f
=
fopen
(
rawdev
->
state_path
,
"w"
);
if
(
f
==
NULL
)
{
if
(
f
==
NULL
)
{
return
-
1
;
return
-
1
;
}
}
fprintf
(
f
,
"Device
\t\t
Start LBA
\t
Current LBA
\t
End LBA
\n
"
);
fprintf
(
f
,
"Device
\t\t
Start LBA
\t
Current LBA
\t
End LBA
\n
"
);
fprintf
(
f
,
STATE_FILE_FORMAT
,
rawdev
->
rawdev_path
,
range
.
from
,
curr_pos
,
range
.
to
);
fprintf
(
f
,
STATE_FILE_FORMAT
,
rawdev
->
rawdev_path
,
range
.
from
,
curr
ent
_pos
,
range
.
to
);
fflush
(
f
);
fflush
(
f
);
fsync
(
fileno
(
f
));
fsync
(
fileno
(
f
));
fclose
(
f
);
fclose
(
f
);
...
@@ -198,6 +186,12 @@ int camogm_init_jpeg(camogm_state *state)
...
@@ -198,6 +186,12 @@ int camogm_init_jpeg(camogm_state *state)
D0
(
fprintf
(
debug_file
,
"Can not start writer thread: %s
\n
"
,
strerror
(
ret_val
)));
D0
(
fprintf
(
debug_file
,
"Can not start writer thread: %s
\n
"
,
strerror
(
ret_val
)));
ret
=
-
1
;
ret
=
-
1
;
}
}
ret_val
=
init_align_buffers
(
state
);
if
(
ret_val
!=
0
)
{
D0
(
fprintf
(
debug_file
,
"Can not initialize alignment buffers
\n
"
));
ret
=
-
1
;
}
}
}
return
ret
;
return
ret
;
...
@@ -221,6 +215,8 @@ void camogm_free_jpeg(camogm_state *state)
...
@@ -221,6 +215,8 @@ void camogm_free_jpeg(camogm_state *state)
pthread_mutex_unlock
(
&
state
->
writer_params
.
writer_mutex
);
pthread_mutex_unlock
(
&
state
->
writer_params
.
writer_mutex
);
pthread_join
(
state
->
writer_params
.
writer_thread
,
NULL
);
pthread_join
(
state
->
writer_params
.
writer_thread
,
NULL
);
state
->
writer_params
.
exit_thread
=
false
;
state
->
writer_params
.
exit_thread
=
false
;
deinit_align_buffers
(
state
);
}
}
/** Calculate the total length of current frame */
/** Calculate the total length of current frame */
...
@@ -247,6 +243,7 @@ int camogm_start_jpeg(camogm_state *state)
...
@@ -247,6 +243,7 @@ int camogm_start_jpeg(camogm_state *state)
{
{
char
*
slash
;
char
*
slash
;
int
rslt
;
int
rslt
;
off64_t
offset
;
if
(
!
state
->
rawdev_op
)
{
if
(
!
state
->
rawdev_op
)
{
strcpy
(
state
->
path
,
state
->
path_prefix
);
// make state->path a directory name (will be replaced when the frames will be written)
strcpy
(
state
->
path
,
state
->
path_prefix
);
// make state->path a directory name (will be replaced when the frames will be written)
...
@@ -264,16 +261,18 @@ int camogm_start_jpeg(camogm_state *state)
...
@@ -264,16 +261,18 @@ int camogm_start_jpeg(camogm_state *state)
}
}
}
}
}
else
{
}
else
{
// if (open_state_file(&state->rawdev
) != 0) {
if
(
open_state_file
(
&
state
->
rawdev
,
&
state
->
writer_params
.
lba_current
)
!=
0
)
{
// D0(fprintf(debug_file, "Could not set write pointer via sysfs
, recording will start from the beginning of partition: "
D0
(
fprintf
(
debug_file
,
"Could not get write pointer from state file
, recording will start from the beginning of partition: "
//
"%s\n", state->rawdev.rawdev_path));
"%s
\n
"
,
state
->
rawdev
.
rawdev_path
));
//
}
}
state
->
writer_params
.
blockdev_fd
=
open
(
state
->
rawdev
.
rawdev_path
,
O_WRONLY
);
state
->
writer_params
.
blockdev_fd
=
open
(
state
->
rawdev
.
rawdev_path
,
O_WRONLY
);
if
(
state
->
writer_params
.
blockdev_fd
<
0
)
{
if
(
state
->
writer_params
.
blockdev_fd
<
0
)
{
D0
(
fprintf
(
debug_file
,
"Error opening block device: %s
\n
"
,
state
->
rawdev
.
rawdev_path
));
D0
(
fprintf
(
debug_file
,
"Error opening block device: %s
\n
"
,
state
->
rawdev
.
rawdev_path
));
return
-
CAMOGM_FRAME_FILE_ERR
;
return
-
CAMOGM_FRAME_FILE_ERR
;
}
}
D6
(
fprintf
(
debug_file
,
"Open block device: %s
\n
"
,
state
->
rawdev
.
rawdev_path
));
offset
=
lba_to_offset
(
state
->
writer_params
.
lba_current
-
state
->
writer_params
.
lba_start
);
lseek64
(
state
->
writer_params
.
blockdev_fd
,
offset
,
SEEK_SET
);
D6
(
fprintf
(
debug_file
,
"Open block device: %s, offset in bytes: %llu
\n
"
,
state
->
rawdev
.
rawdev_path
,
offset
));
}
}
return
0
;
return
0
;
...
@@ -325,6 +324,15 @@ int camogm_frame_jpeg(camogm_state *state)
...
@@ -325,6 +324,15 @@ int camogm_frame_jpeg(camogm_state *state)
while
(
state
->
writer_params
.
data_ready
)
while
(
state
->
writer_params
.
data_ready
)
pthread_cond_wait
(
&
state
->
writer_params
.
main_cond
,
&
state
->
writer_params
.
writer_mutex
);
pthread_cond_wait
(
&
state
->
writer_params
.
main_cond
,
&
state
->
writer_params
.
writer_mutex
);
D6
(
fprintf
(
debug_file
,
"_13a_"
));
D6
(
fprintf
(
debug_file
,
"_13a_"
));
D6
(
fprintf
(
debug_file
,
"
\n
"
));
align_frame
(
state
);
if
(
update_lba
(
state
)
==
1
)
{
D0
(
fprintf
(
debug_file
,
"The end of block device reached, continue recording from start
\n
"
));
}
D6
(
fprintf
(
debug_file
,
"Block device positions: start = %llu, current = %llu, end = %llu
\n
"
,
state
->
writer_params
.
lba_start
,
state
->
writer_params
.
lba_current
,
state
->
writer_params
.
lba_end
));
// proceed if last frame was recorded without errors
// proceed if last frame was recorded without errors
if
(
state
->
writer_params
.
last_ret_val
==
0
)
{
if
(
state
->
writer_params
.
last_ret_val
==
0
)
{
state
->
writer_params
.
data_ready
=
true
;
state
->
writer_params
.
data_ready
=
true
;
...
@@ -336,8 +344,8 @@ int camogm_frame_jpeg(camogm_state *state)
...
@@ -336,8 +344,8 @@ int camogm_frame_jpeg(camogm_state *state)
}
}
// update statistics
// update statistics
state
->
rawdev
.
last_jpeg_size
=
camogm_get_jpeg_size
(
state
);
//
state->rawdev.last_jpeg_size = camogm_get_jpeg_size(state);
state
->
rawdev
.
total_rec_len
+=
state
->
rawdev
.
last_jpeg_size
;
//
state->rawdev.total_rec_len += state->rawdev.last_jpeg_size;
}
}
return
0
;
return
0
;
...
@@ -353,15 +361,36 @@ int camogm_frame_jpeg(camogm_state *state)
...
@@ -353,15 +361,36 @@ int camogm_frame_jpeg(camogm_state *state)
int
camogm_end_jpeg
(
camogm_state
*
state
)
int
camogm_end_jpeg
(
camogm_state
*
state
)
{
{
int
ret
=
0
;
int
ret
=
0
;
int
bytes
;
ssize_t
iovlen
;
struct
frame_data
fdata
=
{
0
};
struct
frame_data
fdata
=
{
0
};
if
(
state
->
rawdev_op
)
{
if
(
state
->
rawdev_op
)
{
// write any remaining data, do not use writer thread as there can be only one block left CHUNK_REM buffer
pthread_mutex_lock
(
&
state
->
writer_params
.
writer_mutex
);
bytes
=
prep_last_block
(
state
);
if
(
bytes
>
0
)
{
D6
(
fprintf
(
debug_file
,
"Write last block of data, size = %d
\n
"
,
bytes
));
// the remaining data block is placed in CHUNK_COMMON buffer, write just this buffer
iovlen
=
writev
(
state
->
writer_params
.
blockdev_fd
,
&
state
->
writer_params
.
data_chunks
[
CHUNK_COMMON
],
1
);
if
(
iovlen
<
bytes
)
{
D0
(
fprintf
(
debug_file
,
"writev error: %s (returned %i, expected %i)
\n
"
,
strerror
(
errno
),
iovlen
,
bytes
));
state
->
writer_params
.
last_ret_val
=
-
CAMOGM_FRAME_FILE_ERR
;
}
else
{
// update statistic, just one block written
state
->
writer_params
.
lba_current
+=
1
;
state
->
rawdev
.
total_rec_len
+=
bytes
;
}
reset_chunks
(
state
->
writer_params
.
data_chunks
,
1
);
}
pthread_mutex_unlock
(
&
state
->
writer_params
.
writer_mutex
);
D6
(
fprintf
(
debug_file
,
"Closing block device %s
\n
"
,
state
->
rawdev
.
rawdev_path
));
D6
(
fprintf
(
debug_file
,
"Closing block device %s
\n
"
,
state
->
rawdev
.
rawdev_path
));
ret
=
close
(
state
->
writer_params
.
blockdev_fd
);
ret
=
close
(
state
->
writer_params
.
blockdev_fd
);
if
(
ret
==
-
1
)
if
(
ret
==
-
1
)
D0
(
fprintf
(
debug_file
,
"Error: %s
\n
"
,
strerror
(
errno
)));
D0
(
fprintf
(
debug_file
,
"Error: %s
\n
"
,
strerror
(
errno
)));
// save_state_file(&state->rawdev
);
save_state_file
(
&
state
->
rawdev
,
state
->
writer_params
.
lba_current
);
}
}
return
ret
;
return
ret
;
}
}
...
@@ -395,25 +424,40 @@ void *jpeg_writer(void *thread_args)
...
@@ -395,25 +424,40 @@ void *jpeg_writer(void *thread_args)
if
(
params
->
data_ready
)
{
if
(
params
->
data_ready
)
{
l
=
0
;
l
=
0
;
state
->
writer_params
.
last_ret_val
=
0
;
state
->
writer_params
.
last_ret_val
=
0
;
for
(
int
i
=
0
;
i
<
(
state
->
chunk_index
)
-
1
;
i
++
)
{
// for (int i = 0; i < (state->chunk_index) - 1; i++) {
chunks_iovec
[
i
].
iov_base
=
state
->
packetchunks
[
i
+
1
].
chunk
;
// chunks_iovec[i].iov_base = state->packetchunks[i + 1].chunk;
chunks_iovec
[
i
].
iov_len
=
state
->
packetchunks
[
i
+
1
].
bytes
;
// chunks_iovec[i].iov_len = state->packetchunks[i + 1].bytes;
// l += chunks_iovec[i].iov_len;
// }
// chunk_index = state->chunk_index;
chunk_index
=
get_data_buffers
(
state
,
&
chunks_iovec
,
FILE_CHUNKS_NUM
);
if
(
chunk_index
>
0
)
{
for
(
int
i
=
0
;
i
<
chunk_index
;
i
++
)
l
+=
chunks_iovec
[
i
].
iov_len
;
l
+=
chunks_iovec
[
i
].
iov_len
;
}
iovlen
=
writev
(
state
->
writer_params
.
blockdev_fd
,
chunks_iovec
,
chunk_index
);
chunk_index
=
state
->
chunk_index
;
iovlen
=
writev
(
state
->
writer_params
.
blockdev_fd
,
chunks_iovec
,
chunk_index
-
1
);
if
(
iovlen
<
l
)
{
if
(
iovlen
<
l
)
{
D0
(
fprintf
(
debug_file
,
"writev error: %s (returned %li, expected %li)
\n
"
,
strerror
(
errno
),
iovlen
,
l
));
D0
(
fprintf
(
debug_file
,
"writev error: %s (returned %i, expected %i)
\n
"
,
strerror
(
errno
),
iovlen
,
l
));
state
->
writer_params
.
last_ret_val
=
-
CAMOGM_FRAME_FILE_ERR
;
}
else
{
// update statistic
state
->
rawdev
.
last_jpeg_size
=
l
;
state
->
rawdev
.
total_rec_len
+=
state
->
rawdev
.
last_jpeg_size
;
D6
(
fprintf
(
debug_file
,
"Current position in block device: %lld
\n
"
,
lseek64
(
state
->
writer_params
.
blockdev_fd
,
0
,
SEEK_CUR
)));
}
}
else
{
D0
(
fprintf
(
debug_file
,
"data vector mapping error: %d)
\n
"
,
chunk_index
));
state
->
writer_params
.
last_ret_val
=
-
CAMOGM_FRAME_FILE_ERR
;
state
->
writer_params
.
last_ret_val
=
-
CAMOGM_FRAME_FILE_ERR
;
}
}
// release main thread
// release main thread
reset_chunks
(
state
->
writer_params
.
data_chunks
,
0
);
params
->
data_ready
=
false
;
params
->
data_ready
=
false
;
pthread_cond_signal
(
&
params
->
main_cond
);
pthread_cond_signal
(
&
params
->
main_cond
);
}
}
}
}
params
->
state
=
STATE_STOPPED
;
params
->
state
=
STATE_STOPPED
;
pthread_mutex_unlock
(
&
state
->
writer_params
.
writer_mutex
);
pthread_mutex_unlock
(
&
state
->
writer_params
.
writer_mutex
);
D5
(
fprintf
(
debug_file
,
"Exit from recording thread
\n
"
));
return
NULL
;
return
NULL
;
}
}
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