diff options
author | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-12-08 04:45:59 +0100 |
---|---|---|
committer | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-12-08 04:45:59 +0100 |
commit | c3812d3569aa98e23953eea323d980912580e659 (patch) | |
tree | 3b9d3bbf8bdcc554bb9cb1827f19dad457debf41 /ipecamera/image.c | |
parent | 869ed99dbc3a645fee6de36e97e1e12127068f10 (diff) | |
download | ipecamera-c3812d3569aa98e23953eea323d980912580e659.tar.gz ipecamera-c3812d3569aa98e23953eea323d980912580e659.tar.bz2 ipecamera-c3812d3569aa98e23953eea323d980912580e659.tar.xz ipecamera-c3812d3569aa98e23953eea323d980912580e659.zip |
Support multiple frames sharing a single DMA packet
Diffstat (limited to 'ipecamera/image.c')
-rw-r--r-- | ipecamera/image.c | 53 |
1 files changed, 44 insertions, 9 deletions
diff --git a/ipecamera/image.c b/ipecamera/image.c index 4b060b6..ad99246 100644 --- a/ipecamera/image.c +++ b/ipecamera/image.c @@ -372,18 +372,37 @@ static int ipecamera_resolve_event_id(ipecamera_t *ctx, pcilib_event_id_t evid) return (evid - 1) % ctx->buffer_size; } -static inline void ipecamera_new_frame(ipecamera_t *ctx) { +static inline int ipecamera_new_frame(ipecamera_t *ctx) { ctx->buffer_pos = (++ctx->event_id) % ctx->buffer_size; ctx->cur_size = 0; ctx->frame_info[ctx->buffer_pos].info.type = PCILIB_EVENT0; // memset(ctx->cmask + ctx->buffer_pos * ctx->dim.height, 0, ctx->dim.height * sizeof(ipecamera_change_mask_t)); + + if ((ctx->event_id == ctx->autostop.evid)&&(ctx->event_id)) { + ctx->run_reader = 0; + return 1; + } + + if (check_deadline(&ctx->autostop.timestamp, PCILIB_DMA_TIMEOUT)) { + ctx->run_reader = 0; + return 1; + } + + return 0; } static uint32_t frame_magic[6] = { 0x51111111, 0x52222222, 0x53333333, 0x54444444, 0x55555555, 0x56666666 }; +#define IPECAMERA_BUG_MULTIFRAME_PACKETS + static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t bufsize, void *buf) { int eof = 0; + +#ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS + size_t extra_data = 0; +#endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */ + ipecamera_t *ctx = (ipecamera_t*)user; @@ -394,6 +413,22 @@ static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t gettimeofday(&ctx->frame_info[ctx->buffer_pos].info.timestamp, NULL); } +#ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS + if (ctx->cur_size + bufsize > ctx->raw_size) { + size_t need; + + for (need = ctx->raw_size - ctx->cur_size; need < bufsize; need += sizeof(uint32_t)) { + if (*(uint32_t*)(buf + need) == frame_magic[0]) break; + } + + if (need < bufsize) { + extra_data = bufsize - need; + bufsize = need; + eof = 1; + } + } +#endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */ + if (ctx->parse_data) { if (ctx->cur_size + bufsize > ctx->full_size) { pcilib_error("Unexpected event data, we are expecting at maximum (%zu) bytes, but (%zu) already read", ctx->full_size, ctx->cur_size + bufsize); @@ -413,17 +448,15 @@ static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t } if (eof) { - ipecamera_new_frame(ctx); - - if ((ctx->event_id == ctx->autostop.evid)&&(ctx->event_id)) { - ctx->run_reader = 0; + if (ipecamera_new_frame(ctx)) { return PCILIB_STREAMING_STOP; } - if (check_deadline(&ctx->autostop.timestamp, PCILIB_DMA_TIMEOUT)) { - ctx->run_reader = 0; - return PCILIB_STREAMING_STOP; +#ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS + if (extra_data) { + return ipecamera_data_callback(user, flags, extra_data, buf + bufsize); } +#endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */ } return PCILIB_STREAMING_REQ_FRAGMENT; @@ -437,6 +470,7 @@ static void *ipecamera_reader_thread(void *user) { err = pcilib_stream_dma(ctx->event.pcilib, ctx->rdma, 0, 0, PCILIB_DMA_FLAG_MULTIPACKET, PCILIB_DMA_TIMEOUT, &ipecamera_data_callback, user); if (err) { if (err == PCILIB_ERROR_TIMEOUT) { + if (ctx->cur_size > ctx->raw_size) ipecamera_new_frame(ctx); if (check_deadline(&ctx->autostop.timestamp, PCILIB_DMA_TIMEOUT)) { ctx->run_reader = 0; break; @@ -450,7 +484,8 @@ static void *ipecamera_reader_thread(void *user) { ctx->run_streamer = 0; - if (ctx->cur_size) pcilib_error("partialy read frame after stop signal, %zu bytes in the buffer", ctx->cur_size); + if (ctx->cur_size) + pcilib_error("partialy read frame after stop signal, %zu bytes in the buffer", ctx->cur_size); return NULL; } |