Sorry to add to this again, still trying to nut it out. What does “stream” mean in this context? I tried directly reading from spi to agent without storing an intermediate local variable:
local len = myCamera.read_fifo_length();
....
agent.send("img",spi.readblob(len));
But the agent.send line still causes the out-of-memory error when len is > 65528. Is there another way to “stream”?
Yes - essentially, you read the image out in chunks and send each chunk separately.
Here’s a snippet…
Device side:
// size of data chunks to send agent. Large multiple of 8.
static CHUNK_SIZE = 8192;
// next chunk to send
chunk_next = 0;
// number of chunks to send
chunk_count = 0;
function send_chunk() {
agent.send("jpeg_chunk", [chunk_next*CHUNK_SIZE, spi.readblob(CHUNK_SIZE)]);
// All done?
chunk_next++;
if (chunk_next < chunk_count) imp.wakeup(0, send_chunk.bindenv(this));
else {
cs_l.write(1);
agent.send("jpeg_end",1);
}
}
function send_buffer() {
local len = read_fifo_length();
chunk_count = math.ceil(len.tofloat()/CHUNK_SIZE).tointeger();
server.log(format("%d bytes: %d chunks",len,chunk_count));
cs_l.write(0);
set_fifo_burst();
spi.readblob(1); //dummy read
// Send header
agent.send("jpeg_start", len);
// As buffer can be big, we do the sending on imp.wakeup(0) to allow
// incoming messages to be processed
chunk_next = 0;
imp.wakeup(0, send_chunk.bindenv(this));
}
Agent side:
jpeg_buffer <- null
jpeg_startat <- 0;
image <- null
device.on("jpeg_start", function(size) {
jpeg_buffer = blob(size);
jpeg_startat = time();
});
device.on("jpeg_chunk", function(v) {
// check we've not got some barf from a previous boot
if (jpeg_buffer == null) return;
local offset = v[0];
local b = v[1];
for(local i = offset; i < (offset+b.len()); i++) {
if(i < jpeg_buffer.len()) {
jpeg_buffer[i] = b[i-offset];
}
}
});
device.on("jpeg_end", function(v) {
// check we've not got some barf from a previous boot
if (jpeg_buffer == null) return;
// copy last JPEG to web server blob
image = jpeg_buffer
server.log(format("Agent: JPEG Received (%d bytes) at rate of %.2fkB/s",image.len(), (image.len()/1024.0)/(time()-jpeg_startat)));
server.log(format("Agent memory remaining: %d bytes", imp.getmemoryfree()));
});
So, you call send_buffer() and it reads the length, rounds it up to CHUNK_SIZE (I had this as 8192 bytes), and sends a “jpeg_start” message to the agent with the length.
The agent then allocates a blob big enough to hold the entire image, and waits for “jpeg_chunk” messages, filling the blob in as it goes. When it gets a “jpeg_end” the whole image has been received (and in this case is served from the agent directly onto a webpage).
There will be some assembly required, but you should get the idea from this…