21
21
#include "private.h"
22
22
#include "reader.h"
25
int ipecamera_compute_buffer_size(ipecamera_t *ctx, size_t lines) {
26
const size_t header_size = 8 * sizeof(ipecamera_payload_t);
27
const size_t footer_size = 8 * sizeof(ipecamera_payload_t);
24
//#define CHECK_FRAME_MAGIC(buf) \
25
// memcmp(buf, ((void*)frame_magic) + 1, sizeof(frame_magic) - 1)
27
#define CHECK_FRAME_MAGIC(buf) \
28
memcmp(((ipecamera_payload_t*)(buf)) + 1, &frame_magic[1], sizeof(frame_magic) - sizeof(ipecamera_payload_t))
30
static ipecamera_payload_t frame_magic[3] = { 0x51111111, 0x52222222, 0x53333333 };
34
int ipecamera_compute_buffer_size(ipecamera_t *ctx, ipecamera_format_t format, size_t header_size, size_t lines) {
35
// const size_t header_size = 8 * sizeof(ipecamera_payload_t);
36
const size_t footer_size = CMOSIS_FRAME_TAIL_SIZE;
29
39
size_t line_size, raw_size, padded_blocks;
31
switch (ctx->firmware) {
42
case IPECAMERA_FORMAT_CMOSIS:
43
max_channels = CMOSIS_MAX_CHANNELS;
44
line_size = (1 + CMOSIS_PIXELS_PER_CHANNEL) * 32;
46
case IPECAMERA_FORMAT_CMOSIS20:
47
max_channels = CMOSIS20_MAX_CHANNELS;
48
line_size = (1 + CMOSIS20_PIXELS_PER_CHANNEL) * 32 / 2;
33
line_size = (1 + IPECAMERA_PIXELS_PER_CHANNEL) * 32;
34
raw_size = lines * line_size;
35
raw_size *= 16 / ctx->cmosis_outputs;
36
raw_size += header_size + footer_size;
51
pcilib_warning("Unsupported version (%u) of frame format...", format);
52
return PCILIB_ERROR_NOTSUPPORTED;
55
raw_size = lines * line_size;
56
raw_size *= max_channels / ctx->cmosis_outputs;
57
raw_size += header_size + footer_size;
38
59
#ifdef IPECAMERA_BUG_MISSING_PAYLOAD
39
// As I understand, the first 32-byte packet is missing, so we need to substract 32
60
// As I understand, the first 32-byte packet is missing, so we need to substract 32 (both CMOSIS and CMOSIS20)
41
62
#endif /* IPECAMERA_BUG_MISSING_PAYLOAD */
44
64
padded_blocks = raw_size / IPECAMERA_DMA_PACKET_LENGTH + ((raw_size % IPECAMERA_DMA_PACKET_LENGTH)?1:0);
46
66
ctx->roi_raw_size = raw_size;
47
67
ctx->roi_padded_size = padded_blocks * IPECAMERA_DMA_PACKET_LENGTH;
48
// printf("%lu %lu\n", ctx->roi_raw_size, ctx->roi_padded_size);
73
static int ipecamera_parse_header(ipecamera_t *ctx, ipecamera_payload_t *buf, size_t buf_size) {
74
int last = buf[0] & 1;
75
int version = (buf[0] >> 1) & 7;
76
size_t size = 0, n_lines;
77
ipecamera_format_t format = IPECAMERA_FORMAT_CMOSIS;
81
n_lines = ((uint32_t*)buf)[5] & 0x7FF;
82
ctx->frame[ctx->buffer_pos].event.info.seqnum = buf[6] & 0xFFFFFF;
83
ctx->frame[ctx->buffer_pos].event.info.offset = (buf[7] & 0xFFFFFF) * 80;
86
n_lines = ((uint32_t*)buf)[5] & 0xFFFF;
88
pcilib_error("The frame header claims 0 lines in the data");
92
ctx->frame[ctx->buffer_pos].event.info.seqnum = buf[6] & 0xFFFFFF;
93
ctx->frame[ctx->buffer_pos].event.info.offset = (buf[7] & 0xFFFFFF) * 80;
94
format = (buf[6] >> 24)&0x0F;
97
ipecamera_debug(HARDWARE, "Incorrect version of the frame header, ignoring broken data...");
100
gettimeofday(&ctx->frame[ctx->buffer_pos].event.info.timestamp, NULL);
102
ipecamera_debug(FRAME_HEADERS, "frame %lu: %x %x %x %x", ctx->frame[ctx->buffer_pos].event.info.seqnum, buf[0], buf[1], buf[2], buf[3]);
103
ipecamera_debug(FRAME_HEADERS, "frame %lu: %x %x %x %x", ctx->frame[ctx->buffer_pos].event.info.seqnum, buf[4], buf[5], buf[6], buf[7]);
105
while ((!last)&&((size + CMOSIS_FRAME_HEADER_SIZE) <= buf_size)) {
106
size += CMOSIS_FRAME_HEADER_SIZE;
107
last = buf[size] & 1;
110
size += CMOSIS_FRAME_HEADER_SIZE;
111
ipecamera_compute_buffer_size(ctx, format, size, n_lines);
113
// Returns total size of found headers or 0 on the error
53
118
static inline int ipecamera_new_frame(ipecamera_t *ctx) {
54
119
ctx->frame[ctx->buffer_pos].event.raw_size = ctx->cur_size;
102
165
if (!ctx->cur_size) {
103
166
#if defined(IPECAMERA_BUG_INCOMPLETE_PACKETS)||defined(IPECAMERA_BUG_MULTIFRAME_PACKETS)
105
for (startpos = 0; (startpos + sizeof(frame_magic)) <= bufsize; startpos += sizeof(uint32_t)) {
106
if (!memcmp(buf + startpos, frame_magic, sizeof(frame_magic))) break;
168
for (startpos = 0; (startpos + CMOSIS_FRAME_HEADER_SIZE) <= bufsize; startpos += sizeof(ipecamera_payload_t)) {
169
if (!CHECK_FRAME_MAGIC(buf + startpos)) break;
109
if ((startpos + sizeof(frame_magic)) > bufsize) {
172
if ((startpos + CMOSIS_FRAME_HEADER_SIZE) > bufsize) {
110
173
ipecamera_debug_buffer(RAW_PACKETS, bufsize, NULL, 0, "frame%4lu/frame%9lu.invalid", ctx->event_id, packet_id);
112
175
if (invalid_frame_id != ctx->event_id) {
134
197
#endif /* IPECAMERA_BUG_INCOMPLETE_PACKETS */
136
if ((bufsize >= 8)&&(!memcmp(buf, frame_magic, sizeof(frame_magic)))) {
137
// size_t first_line = ((uint32_t*)buf)[4] & 0x7FF;
138
size_t n_lines = ((uint32_t*)buf)[5] & 0x7FF;
139
ipecamera_compute_buffer_size(ctx, n_lines);
141
ctx->frame[ctx->buffer_pos].event.info.seqnum = ((uint32_t*)buf)[6] & 0xFFFFFF;
142
ctx->frame[ctx->buffer_pos].event.info.offset = (((uint32_t*)buf)[7] & 0xFFFFFF) * 80;
143
gettimeofday(&ctx->frame[ctx->buffer_pos].event.info.timestamp, NULL);
199
if ((bufsize >= CMOSIS_FRAME_HEADER_SIZE)&&(!CHECK_FRAME_MAGIC(buf))) {
200
// We should handle the case when multi-header is split between multiple DMA packets
201
if (!ipecamera_parse_header(ctx, buf, bufsize))
202
return PCILIB_STREAMING_CONTINUE;
145
204
ipecamera_debug(HARDWARE, "Frame magic is not found, ignoring broken data...");
146
205
return PCILIB_STREAMING_CONTINUE;