video streaming using websocket. but,streaming is very slower than 0.1fps.
Dependencies: BaseUsbHost EthernetInterface WebSocketClient mbed-rtos mbed
Fork of BaseUsbHost_example by
Diff: main.cpp
- Revision:
- 6:420a86583681
- Parent:
- 5:495f7536897b
--- a/main.cpp Fri Jan 25 14:55:08 2013 +0000 +++ b/main.cpp Tue Feb 19 15:49:33 2013 +0000 @@ -1,27 +1,25 @@ -// BaseUsbHost_example/main.cpp 2013/1/25 -#include "mbed.h" -#include "rtos.h" +// VideoStreaming/main.cpp 2013/2/20 +#include "EthernetInterface.h" +#include "Websocket.h" #include "BaseUsbHost.h" -#include "LogitechC270.h" -#include "LifeCamVX700.h" #include "UvcCam.h" -#include "UsbFlashDrive.h" #include "decodeMJPEG.h" #include "MyThread.h" -#include <string> -#define IMAGE_BUF_SIZE (1024*7) -#define INTERVAL_S 30 +#define CHANNEL "public-ch" +#define URL "ws://sockets.mbed.org/ws/"CHANNEL"/rw" +#define VIEWER "http://va009039-mbed.appspot.com/VideoStreaming/"CHANNEL"/viewer" +#define FRAME_LIMIT 4 +#define IMAGE_BUFFER_SIZE (1024*3) -Serial pc(USBTX, USBRX); +Serial term(USBTX, USBRX); DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); struct ImageBuffer { - int pos; - uint8_t buf[IMAGE_BUF_SIZE]; + uint16_t pos; + uint8_t buf[IMAGE_BUFFER_SIZE]; void clear() { pos = 0; } int size() { return pos; } - uint8_t get(int pos) { return buf[pos]; } void put(uint8_t c) { if (pos < sizeof(buf)) { buf[pos++] = c; @@ -31,13 +29,17 @@ Mail<ImageBuffer, 1> mail_box; -class captureJPEG : public MyThread, public decodeMJPEG { +class Capture : public MyThread, public decodeMJPEG { public: - captureJPEG(BaseUvc* cam) : m_cam(cam) { + Capture(BaseUvc* cam) : m_cam(cam) { + m_cam->setOnResult(this, &Capture::callback_motion_jpeg); m_buf = NULL; - m_cam->setOnResult(this, &captureJPEG::callback_motion_jpeg); } -private: +private: + ImageBuffer* m_buf; + BaseUvc* m_cam; + + // from decodeMJPEG virtual void outputJPEG(uint8_t c, int status) { if (m_buf == NULL && status == JPEG_START) { m_buf = mail_box.alloc(); @@ -50,112 +52,126 @@ if (status == JPEG_END) { mail_box.put(m_buf); m_buf = NULL; - led3 = !led3; } } } void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) { - inputPacket(buf, len); - led1 = buf[1]&1; // FID - if (buf[1]&2) { // EOF - led2 = !led2; - } + inputPacket(buf, len); // to decodeMJPEG } virtual void run() { - while(true) { - if (m_cam) { - m_cam->poll(); - } + while(1) { + m_cam->poll(); } } - ImageBuffer* m_buf; - BaseUvc* m_cam; }; +// Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) +int base64enc(const char *input, unsigned int length, char *output, int outputlen) { + static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + unsigned int c, c1, c2, c3; + + if (outputlen < (((length-1)/3)+1)<<2) return -1; + + for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) { + c1 = ((((unsigned char)*((unsigned char *)&input[i])))); + c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0; + c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0; + + c = ((c1 & 0xFC) >> 2); + output[j+0] = base64[c]; + c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4); + output[j+1] = base64[c]; + c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6); + output[j+2] = (length>i+1)?base64[c]:'='; + c = (c3 & 0x3F); + output[j+3] = (length>i+2)?base64[c]:'='; + } + output[(((length-1)/3)+1)<<2] = '\0'; + return 0; +} + +#define CHUNK (3*20) + +void buf_to_websocket(Websocket*ws, ImageBuffer* buf) { + Timer t; + int send_bytes = 0; + t.reset(); + t.start(); + char output[CHUNK/3*4+1]; + for(int i = 0; i < buf->size(); i += CHUNK) { + int len = buf->size() - i; + if (len > CHUNK) { + len = CHUNK; + } + base64enc(reinterpret_cast<const char*>(buf->buf+i), len, output, sizeof(output)); + term.printf("%s\n", output); + send_bytes += ws->send(output); + } + strcpy(output, "."); + term.printf("%s\n", output); + send_bytes += ws->send(output); + term.printf("websocket: send %d bytes %d ms\n", send_bytes, t.read_ms()); +} + void no_memory () { error("Failed to allocate memory!\n"); } int main() { - pc.baud(921600); - printf("%s\n", __FILE__); + term.baud(921600); + term.printf("%s\n", __FILE__); set_new_handler(no_memory); - BaseUvc* cam = NULL; - UsbFlashDrive* drive = NULL; + EthernetInterface eth; + eth.init(); //Use DHCP + int r = eth.connect(); + if (r != 0) { + error("mbed is not connected to the Internet. %d\n", r); + } + term.printf("IP Address is %s\n\r", eth.getIPAddress()); + Websocket* ws = new Websocket(URL); + if (!ws->connect()) { + error("mbed is not connected to websocket "URL); + } + BaseUsbHost* usbHost = new BaseUsbHost(); ControlEp* ctlEp = new ControlEp; // root hub - if (!UsbHub::check(ctlEp)) { - error("USB Hub is not connected.\n"); - } - UsbHub* hub = new UsbHub(ctlEp); - ctlEp = hub->search<UsbFlashDrive>(); - if (ctlEp) { - drive = new UsbFlashDrive("usb", ctlEp); - } - ctlEp = hub->search<LogitechC270>(); - if (ctlEp) { - //cam = new LogitechC270(C270_MJPEG, C270_160x120, _5FPS, ctlEp); - cam = new LogitechC270(C270_MJPEG, C270_320x176, _5FPS, ctlEp); - } - if (cam == NULL) { - ctlEp = hub->search<LifeCamVX700>(); - if (ctlEp) { - cam = new LifeCamVX700(VX700_160x120, _5FPS, ctlEp); + if (UsbHub::check(ctlEp)) { + UsbHub* hub = new UsbHub(ctlEp); + ctlEp = hub->search<UvcCam>(0); + if (ctlEp == NULL) { + error("UVC Camera is not connected in USB hub.\n"); } - } - if (cam == NULL) { - ctlEp = hub->search<UvcCam>(); - if (ctlEp) { - cam = new UvcCam(UVC_MJPEG, UVC_160x120, _5FPS, ctlEp); - } - } - if (cam == NULL) { + } else if (!UvcCam::check(ctlEp)) { error("UVC Camera is not connected.\n"); } - if (drive == NULL) { - error("USB flash drive is not connected.\n"); - } + UvcCam* cam = new UvcCam(UVC_MJPEG, UVC_160x120, _5FPS, ctlEp); + + Capture* capture_th = new Capture(cam); + capture_th->set_stack(512); + capture_th->start(); + + term.printf("\n\n"VIEWER"\n\n"); - captureJPEG* capture = new captureJPEG(cam); - capture->set_stack(DEFAULT_STACK_SIZE-128*8); - capture->start(); - - for(int n = 0; ; n++) { - printf("%d captureJPEG stack used: %d/%d bytes\n", n, capture->stack_used(), capture->stack_size()); - osEvent evt = mail_box.get(); + int frame = 0; + for(int n = 0;; n++) { + osEvent evt = mail_box.get(200); if (evt.status == osEventMail) { ImageBuffer *buf = reinterpret_cast<ImageBuffer*>(evt.value.p); - time_t timestamp = time(NULL); - struct tm* tminfo = localtime(×tamp); - char tmbuf[32]; - strftime(tmbuf, sizeof(tmbuf), "/usb/img%M%S.jpg", tminfo); - string path = tmbuf; - printf("%s %d bytes\n", path.c_str(), buf->size()); - FILE* fp = fopen(path.c_str(), "wb"); - if (fp) { - for(int i = 0; i < buf->size(); i++) { - fputc(buf->get(i), fp); - //Thread::yield(); - } - fclose(fp); + if (frame < 10) { + term.printf("Capture stack used: %d/%d bytes\n", capture_th->stack_used(), capture_th->stack_size()); + term.printf("image size: %d bytes\n", buf->size()); + } + if (frame++ < FRAME_LIMIT || FRAME_LIMIT==(-1)) { + led2 = 1; + buf_to_websocket(ws, buf); + led2 = 0; } mail_box.free(buf); led4 = !led4; } - - printf("CC:"); - for(int i = 0; i < 16; i++) { - printf(" %u", cam->report_cc_count[i]); - } - printf("\nPS:"); - for(int i = 0; i < 16; i++) { - printf(" %u", cam->report_ps_cc_count[i]); - } - printf("\n"); - - Thread::wait(INTERVAL_S*1000); + led1 = ws->is_connected(); } }