From dc54794546c90f56a7399406c6a7baf9603ae07c Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Wed, 12 Aug 2015 17:37:04 +0200 Subject: Handle frame headers split between 2 packets --- base.c | 4 ++++ private.h | 16 +++++++++++++--- reader.c | 34 +++++++++++++++++++++++++++++----- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/base.c b/base.c index 1355486..1adc185 100644 --- a/base.c +++ b/base.c @@ -351,6 +351,10 @@ int ipecamera_start(pcilib_context_t *vctx, pcilib_event_t event_mask, pcilib_ev ctx->parse_data = (flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY)?0:1; ctx->cur_size = 0; +#ifdef IPECAMERA_BUG_MULTIFRAME_HEADERS + ctx->saved_header_size = 0; +#endif /* IPECAMERA_BUG_MULTIFRAME_HEADERS */ + switch (ctx->firmware) { case IPECAMERA_FIRMWARE_UFO5: ctx->dim.width = CMOSIS_WIDTH; diff --git a/private.h b/private.h index a0034c8..18138e7 100644 --- a/private.h +++ b/private.h @@ -20,6 +20,7 @@ #define IPECAMERA_BUG_MISSING_PAYLOAD //**< CMOSIS fails to provide a first payload for each frame, therefore the frame is 32 bit shorter */ #define IPECAMERA_BUG_MULTIFRAME_PACKETS //**< This is by design, start of packet comes directly after the end of last one in streaming mode */ +#define IPECAMERA_BUG_MULTIFRAME_HEADERS //**< UFO Camera operates with 32-byte entities, but some times there is 16-byte padding before the data which may result in spliting the header between 2 DMA packets. We still need to define a minimal number of bytes which are always in the same DMA packet (CMOSIS_ENTITY_SIZE) */ #define IPECAMERA_BUG_REPEATING_DATA //**< 16 bytes repeated at frame offset 4096, the problem start/stop happenning on board restart */ //#define IPECAMERA_BUG_INCOMPLETE_PACKETS //**< Support incomplete packets, i.e. check for frame magic even if full frame size is not reached yet (slow) */ //#define IPECAMERA_ANNOUNCE_READY //**< Announce new event only after the reconstruction is done */ @@ -46,8 +47,13 @@ #define IPECAMERA_END_OF_SEQUENCE 0x1F001001 -#define CMOSIS_FRAME_HEADER_SIZE 8 * sizeof(ipecamera_payload_t) -#define CMOSIS_FRAME_TAIL_SIZE 8 * sizeof(ipecamera_payload_t) +#define CMOSIS_FRAME_HEADER_SIZE (8 * sizeof(ipecamera_payload_t)) +#define CMOSIS_FRAME_TAIL_SIZE (8 * sizeof(ipecamera_payload_t)) +#ifdef IPECAMERA_BUG_MULTIFRAME_HEADERS +# define CMOSIS_ENTITY_SIZE (4 * sizeof(ipecamera_payload_t)) //**< This normaly should be equal to 32 bytes like header and tail, but in fact is only 16 bytes */ +#else /* IPECAMERA_BUG_MULTIFRAME_HEADERS */ +# define CMOSIS_ENTITY_SIZE (8 * sizeof(ipecamera_payload_t)) //**< This normaly should be equal to 32 bytes like header and tail, but in fact is only 16 bytes */ +#endif /* IPECAMERA_BUG_MULTIFRAME_HEADERS */ #define CMOSIS_MAX_CHANNELS 16 #define CMOSIS_PIXELS_PER_CHANNEL 128 @@ -228,7 +234,11 @@ struct ipecamera_s { void *buffer; ipecamera_change_mask_t *cmask; ipecamera_frame_t *frame; - + +#ifdef IPECAMERA_BUG_MULTIFRAME_HEADERS + size_t saved_header_size; /**< If it happened that the frame header is split between 2 DMA packets, this variable holds the size of the part containing in the first packet */ + char saved_header[CMOSIS_FRAME_HEADER_SIZE]; /**< If it happened that the frame header is split between 2 DMA packets, this variable holds the part containing in the first packet */ +#endif /* IPECAMERA_BUG_MULTIFRAME_HEADERS */ ipecamera_image_dimensions_t dim; diff --git a/reader.c b/reader.c index e293005..b603e47 100644 --- a/reader.c +++ b/reader.c @@ -163,13 +163,30 @@ static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t ipecamera_debug_buffer(RAW_PACKETS, bufsize, buf, PCILIB_DEBUG_BUFFER_MKDIR, "frame%4lu/frame%9lu", ctx->event_id, packet_id); if (!ctx->cur_size) { +#ifdef IPECAMERA_BUG_MULTIFRAME_HEADERS + if (ctx->saved_header_size) { + void *buf2 = alloca(ctx->saved_header_size + bufsize); + if (!buf2) { + pcilib_error("Error allocating %zu bytes of memory in stack", ctx->saved_header_size + bufsize); + return -PCILIB_ERROR_MEMORY; + } + memcpy(buf2, ctx->saved_header, ctx->saved_header_size); + memcpy(buf2 + ctx->saved_header_size, buf, bufsize); + + buf = buf2; + bufsize += ctx->saved_header_size; + + ctx->saved_header_size = 0; + } +#endif /* IPECAMERA_BUG_MULTIFRAME_HEADERS */ + #if defined(IPECAMERA_BUG_INCOMPLETE_PACKETS)||defined(IPECAMERA_BUG_MULTIFRAME_PACKETS) size_t startpos; - for (startpos = 0; (startpos + CMOSIS_FRAME_HEADER_SIZE) <= bufsize; startpos += sizeof(ipecamera_payload_t)) { + for (startpos = 0; (startpos + CMOSIS_ENTITY_SIZE) <= bufsize; startpos += sizeof(ipecamera_payload_t)) { if (!CHECK_FRAME_MAGIC(buf + startpos)) break; } - if ((startpos + CMOSIS_FRAME_HEADER_SIZE) > bufsize) { + if ((startpos + CMOSIS_ENTITY_SIZE) > bufsize) { ipecamera_debug_buffer(RAW_PACKETS, bufsize, NULL, 0, "frame%4lu/frame%9lu.invalid", ctx->event_id, packet_id); if (invalid_frame_id != ctx->event_id) { @@ -200,8 +217,15 @@ static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t // We should handle the case when multi-header is split between multiple DMA packets if (!ipecamera_parse_header(ctx, buf, bufsize)) return PCILIB_STREAMING_CONTINUE; + +#ifdef IPECAMERA_BUG_MULTIFRAME_HEADERS + } else if ((bufsize >= CMOSIS_ENTITY_SIZE)&&(!CHECK_FRAME_MAGIC(buf))) { + memcpy(ctx->saved_header, buf, bufsize); + ctx->saved_header_size = bufsize; + return PCILIB_STREAMING_REQ_FRAGMENT; +#endif /* IPECAMERA_BUG_MULTIFRAME_HEADERS */ } else { - ipecamera_debug(HARDWARE, "Frame magic is not found, ignoring broken data..."); + ipecamera_debug(HARDWARE, "Frame magic is not found in the remaining DMA packet consisting of %u bytes, ignoring broken data...", bufsize); return PCILIB_STREAMING_CONTINUE; } } @@ -213,11 +237,11 @@ static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t if (ctx->cur_size + bufsize > ctx->roi_raw_size) { size_t need; - for (need = ctx->roi_raw_size - ctx->cur_size; (need + CMOSIS_FRAME_HEADER_SIZE) <= bufsize; need += sizeof(uint32_t)) { + for (need = ctx->roi_raw_size - ctx->cur_size; (need + CMOSIS_ENTITY_SIZE) <= bufsize; need += sizeof(uint32_t)) { if (!CHECK_FRAME_MAGIC(buf + need)) break; } - if ((need + CMOSIS_FRAME_HEADER_SIZE) <= bufsize) { + if ((need + CMOSIS_ENTITY_SIZE) <= bufsize) { extra_data = bufsize - need; eof = 1; } -- cgit v1.2.1