/alps/ipecamera

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/ipecamera

« back to all changes in this revision

Viewing changes to reader.c

  • Committer: Suren A. Chilingaryan
  • Date: 2015-07-23 16:36:04 UTC
  • Revision ID: csa@suren.me-20150723163604-5ot6xjmom62zbosy
Support for new CMOSIS 20MPix camera

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
#include "private.h"
22
22
#include "reader.h"
23
23
 
24
 
 
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);
28
 
 
 
24
//#define CHECK_FRAME_MAGIC(buf) \
 
25
//      memcmp(buf, ((void*)frame_magic) + 1, sizeof(frame_magic) - 1)
 
26
 
 
27
#define CHECK_FRAME_MAGIC(buf) \
 
28
        memcmp(((ipecamera_payload_t*)(buf)) + 1, &frame_magic[1], sizeof(frame_magic) - sizeof(ipecamera_payload_t))
 
29
 
 
30
static ipecamera_payload_t frame_magic[3] = { 0x51111111, 0x52222222, 0x53333333 };
 
31
 
 
32
 
 
33
 
 
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;
 
37
 
 
38
    size_t max_channels;
29
39
    size_t line_size, raw_size, padded_blocks;
30
40
 
31
 
    switch (ctx->firmware) {
 
41
    switch (format) {
 
42
     case IPECAMERA_FORMAT_CMOSIS:
 
43
        max_channels = CMOSIS_MAX_CHANNELS;
 
44
        line_size = (1 + CMOSIS_PIXELS_PER_CHANNEL) * 32; 
 
45
        break;
 
46
     case IPECAMERA_FORMAT_CMOSIS20:
 
47
        max_channels = CMOSIS20_MAX_CHANNELS;
 
48
        line_size = (1 + CMOSIS20_PIXELS_PER_CHANNEL) * 32 / 2;
 
49
        break;
32
50
     default:
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;
 
53
    }
 
54
 
 
55
    raw_size = lines * line_size;
 
56
    raw_size *= max_channels / ctx->cmosis_outputs;
 
57
    raw_size += header_size + footer_size;
37
58
 
38
59
#ifdef IPECAMERA_BUG_MISSING_PAYLOAD
39
 
            // As I understand, the first 32-byte packet is missing, so we need to substract 32
40
 
        raw_size -= 32;
 
60
        // As I understand, the first 32-byte packet is missing, so we need to substract 32 (both CMOSIS and CMOSIS20)
 
61
    raw_size -= 32;
41
62
#endif /* IPECAMERA_BUG_MISSING_PAYLOAD */
42
 
    }
43
63
 
44
64
    padded_blocks = raw_size / IPECAMERA_DMA_PACKET_LENGTH + ((raw_size % IPECAMERA_DMA_PACKET_LENGTH)?1:0);
45
 
    
 
65
 
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);
49
68
 
50
69
    return 0;
51
70
}
52
71
 
 
72
 
 
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;
 
78
 
 
79
    switch (version) {
 
80
     case 0:
 
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;
 
84
        break;
 
85
     case 1:
 
86
        n_lines = ((uint32_t*)buf)[5] & 0xFFFF;
 
87
        if (!n_lines) {
 
88
            pcilib_error("The frame header claims 0 lines in the data");
 
89
            return 0;
 
90
        }
 
91
 
 
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;
 
95
        break;
 
96
     default:
 
97
        ipecamera_debug(HARDWARE, "Incorrect version of the frame header, ignoring broken data...");
 
98
        return 0;
 
99
    }
 
100
    gettimeofday(&ctx->frame[ctx->buffer_pos].event.info.timestamp, NULL);
 
101
 
 
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]);
 
104
 
 
105
    while ((!last)&&((size + CMOSIS_FRAME_HEADER_SIZE) <= buf_size)) {
 
106
        size += CMOSIS_FRAME_HEADER_SIZE;
 
107
        last = buf[size] & 1;
 
108
    }
 
109
 
 
110
    size += CMOSIS_FRAME_HEADER_SIZE;
 
111
    ipecamera_compute_buffer_size(ctx, format, size, n_lines);
 
112
 
 
113
        // Returns total size of found headers or 0 on the error
 
114
    return size;
 
115
}
 
116
 
 
117
 
53
118
static inline int ipecamera_new_frame(ipecamera_t *ctx) {
54
119
    ctx->frame[ctx->buffer_pos].event.raw_size = ctx->cur_size;
55
120
 
77
142
    return 0;
78
143
}
79
144
 
80
 
static uint32_t frame_magic[4] = { 0x51111111, 0x52222222, 0x53333333, 0x54444444 };
81
 
 
82
145
static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t bufsize, void *buf) {
83
146
    int res;
84
147
    int eof = 0;
102
165
    if (!ctx->cur_size) {
103
166
#if defined(IPECAMERA_BUG_INCOMPLETE_PACKETS)||defined(IPECAMERA_BUG_MULTIFRAME_PACKETS)
104
167
        size_t startpos;
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;
107
170
        }
108
171
        
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);
111
174
            
112
175
            if (invalid_frame_id != ctx->event_id) {
133
196
        }
134
197
#endif /* IPECAMERA_BUG_INCOMPLETE_PACKETS */
135
198
 
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);
140
 
 
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;
144
203
        } else {
145
204
            ipecamera_debug(HARDWARE, "Frame magic is not found, ignoring broken data...");
146
205
            return PCILIB_STREAMING_CONTINUE;
154
213
    if (ctx->cur_size + bufsize > ctx->roi_raw_size) {
155
214
        size_t need;
156
215
        
157
 
        for (need = ctx->roi_raw_size - ctx->cur_size; (need + sizeof(frame_magic)) < bufsize; need += sizeof(uint32_t)) {
158
 
            if (!memcmp(buf + need, frame_magic, sizeof(frame_magic))) break;
 
216
        for (need = ctx->roi_raw_size - ctx->cur_size; (need + CMOSIS_FRAME_HEADER_SIZE) <= bufsize; need += sizeof(uint32_t)) {
 
217
            if (!CHECK_FRAME_MAGIC(buf + need)) break;
159
218
        }
160
219
        
161
 
        if ((need + sizeof(frame_magic)) < bufsize) {
 
220
        if ((need + CMOSIS_FRAME_HEADER_SIZE) <= bufsize) {
162
221
            extra_data = bufsize - need;
163
222
            eof = 1;
164
223
        }