video streaming using websocket. but,streaming is very slower than 0.1fps.

Dependencies:   BaseUsbHost EthernetInterface WebSocketClient mbed-rtos mbed

Fork of BaseUsbHost_example by Norimasa Okamoto

viewer

Committer:
va009039
Date:
Tue Feb 19 15:50:06 2013 +0000
Revision:
7:5dc595bbff58
Parent:
6:420a86583681
video streaming using websocket

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 6:420a86583681 1 // VideoStreaming/main.cpp 2013/2/20
va009039 6:420a86583681 2 #include "EthernetInterface.h"
va009039 6:420a86583681 3 #include "Websocket.h"
va009039 3:6ae9a03a6145 4 #include "BaseUsbHost.h"
va009039 3:6ae9a03a6145 5 #include "UvcCam.h"
va009039 3:6ae9a03a6145 6 #include "decodeMJPEG.h"
va009039 3:6ae9a03a6145 7 #include "MyThread.h"
va009039 3:6ae9a03a6145 8
va009039 6:420a86583681 9 #define CHANNEL "public-ch"
va009039 6:420a86583681 10 #define URL "ws://sockets.mbed.org/ws/"CHANNEL"/rw"
va009039 6:420a86583681 11 #define VIEWER "http://va009039-mbed.appspot.com/VideoStreaming/"CHANNEL"/viewer"
va009039 6:420a86583681 12 #define FRAME_LIMIT 4
va009039 6:420a86583681 13 #define IMAGE_BUFFER_SIZE (1024*3)
va009039 3:6ae9a03a6145 14
va009039 6:420a86583681 15 Serial term(USBTX, USBRX);
va009039 3:6ae9a03a6145 16 DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
va009039 3:6ae9a03a6145 17
va009039 5:495f7536897b 18 struct ImageBuffer {
va009039 6:420a86583681 19 uint16_t pos;
va009039 6:420a86583681 20 uint8_t buf[IMAGE_BUFFER_SIZE];
va009039 5:495f7536897b 21 void clear() { pos = 0; }
va009039 5:495f7536897b 22 int size() { return pos; }
va009039 5:495f7536897b 23 void put(uint8_t c) {
va009039 5:495f7536897b 24 if (pos < sizeof(buf)) {
va009039 5:495f7536897b 25 buf[pos++] = c;
va009039 5:495f7536897b 26 }
va009039 5:495f7536897b 27 }
va009039 5:495f7536897b 28 };
va009039 5:495f7536897b 29
va009039 5:495f7536897b 30 Mail<ImageBuffer, 1> mail_box;
va009039 5:495f7536897b 31
va009039 6:420a86583681 32 class Capture : public MyThread, public decodeMJPEG {
va009039 3:6ae9a03a6145 33 public:
va009039 6:420a86583681 34 Capture(BaseUvc* cam) : m_cam(cam) {
va009039 6:420a86583681 35 m_cam->setOnResult(this, &Capture::callback_motion_jpeg);
va009039 5:495f7536897b 36 m_buf = NULL;
va009039 3:6ae9a03a6145 37 }
va009039 6:420a86583681 38 private:
va009039 6:420a86583681 39 ImageBuffer* m_buf;
va009039 6:420a86583681 40 BaseUvc* m_cam;
va009039 6:420a86583681 41
va009039 6:420a86583681 42 // from decodeMJPEG
va009039 3:6ae9a03a6145 43 virtual void outputJPEG(uint8_t c, int status) {
va009039 5:495f7536897b 44 if (m_buf == NULL && status == JPEG_START) {
va009039 5:495f7536897b 45 m_buf = mail_box.alloc();
va009039 5:495f7536897b 46 if (m_buf) {
va009039 5:495f7536897b 47 m_buf->clear();
va009039 5:495f7536897b 48 }
va009039 3:6ae9a03a6145 49 }
va009039 5:495f7536897b 50 if (m_buf) {
va009039 5:495f7536897b 51 m_buf->put(c);
va009039 5:495f7536897b 52 if (status == JPEG_END) {
va009039 5:495f7536897b 53 mail_box.put(m_buf);
va009039 5:495f7536897b 54 m_buf = NULL;
va009039 3:6ae9a03a6145 55 }
va009039 3:6ae9a03a6145 56 }
va009039 3:6ae9a03a6145 57 }
va009039 3:6ae9a03a6145 58
va009039 3:6ae9a03a6145 59 void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) {
va009039 6:420a86583681 60 inputPacket(buf, len); // to decodeMJPEG
va009039 3:6ae9a03a6145 61 }
va009039 3:6ae9a03a6145 62
va009039 3:6ae9a03a6145 63 virtual void run() {
va009039 6:420a86583681 64 while(1) {
va009039 6:420a86583681 65 m_cam->poll();
va009039 3:6ae9a03a6145 66 }
va009039 3:6ae9a03a6145 67 }
va009039 3:6ae9a03a6145 68 };
va009039 3:6ae9a03a6145 69
va009039 6:420a86583681 70 // Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
va009039 6:420a86583681 71 int base64enc(const char *input, unsigned int length, char *output, int outputlen) {
va009039 6:420a86583681 72 static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
va009039 6:420a86583681 73 unsigned int c, c1, c2, c3;
va009039 6:420a86583681 74
va009039 6:420a86583681 75 if (outputlen < (((length-1)/3)+1)<<2) return -1;
va009039 6:420a86583681 76
va009039 6:420a86583681 77 for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
va009039 6:420a86583681 78 c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
va009039 6:420a86583681 79 c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
va009039 6:420a86583681 80 c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;
va009039 6:420a86583681 81
va009039 6:420a86583681 82 c = ((c1 & 0xFC) >> 2);
va009039 6:420a86583681 83 output[j+0] = base64[c];
va009039 6:420a86583681 84 c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
va009039 6:420a86583681 85 output[j+1] = base64[c];
va009039 6:420a86583681 86 c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
va009039 6:420a86583681 87 output[j+2] = (length>i+1)?base64[c]:'=';
va009039 6:420a86583681 88 c = (c3 & 0x3F);
va009039 6:420a86583681 89 output[j+3] = (length>i+2)?base64[c]:'=';
va009039 6:420a86583681 90 }
va009039 6:420a86583681 91 output[(((length-1)/3)+1)<<2] = '\0';
va009039 6:420a86583681 92 return 0;
va009039 6:420a86583681 93 }
va009039 6:420a86583681 94
va009039 6:420a86583681 95 #define CHUNK (3*20)
va009039 6:420a86583681 96
va009039 6:420a86583681 97 void buf_to_websocket(Websocket*ws, ImageBuffer* buf) {
va009039 6:420a86583681 98 Timer t;
va009039 6:420a86583681 99 int send_bytes = 0;
va009039 6:420a86583681 100 t.reset();
va009039 6:420a86583681 101 t.start();
va009039 6:420a86583681 102 char output[CHUNK/3*4+1];
va009039 6:420a86583681 103 for(int i = 0; i < buf->size(); i += CHUNK) {
va009039 6:420a86583681 104 int len = buf->size() - i;
va009039 6:420a86583681 105 if (len > CHUNK) {
va009039 6:420a86583681 106 len = CHUNK;
va009039 6:420a86583681 107 }
va009039 6:420a86583681 108 base64enc(reinterpret_cast<const char*>(buf->buf+i), len, output, sizeof(output));
va009039 6:420a86583681 109 term.printf("%s\n", output);
va009039 6:420a86583681 110 send_bytes += ws->send(output);
va009039 6:420a86583681 111 }
va009039 6:420a86583681 112 strcpy(output, ".");
va009039 6:420a86583681 113 term.printf("%s\n", output);
va009039 6:420a86583681 114 send_bytes += ws->send(output);
va009039 6:420a86583681 115 term.printf("websocket: send %d bytes %d ms\n", send_bytes, t.read_ms());
va009039 6:420a86583681 116 }
va009039 6:420a86583681 117
va009039 3:6ae9a03a6145 118 void no_memory () {
va009039 3:6ae9a03a6145 119 error("Failed to allocate memory!\n");
va009039 3:6ae9a03a6145 120 }
va009039 3:6ae9a03a6145 121
va009039 3:6ae9a03a6145 122 int main() {
va009039 6:420a86583681 123 term.baud(921600);
va009039 6:420a86583681 124 term.printf("%s\n", __FILE__);
va009039 3:6ae9a03a6145 125 set_new_handler(no_memory);
va009039 3:6ae9a03a6145 126
va009039 6:420a86583681 127 EthernetInterface eth;
va009039 6:420a86583681 128 eth.init(); //Use DHCP
va009039 6:420a86583681 129 int r = eth.connect();
va009039 6:420a86583681 130 if (r != 0) {
va009039 6:420a86583681 131 error("mbed is not connected to the Internet. %d\n", r);
va009039 6:420a86583681 132 }
va009039 6:420a86583681 133 term.printf("IP Address is %s\n\r", eth.getIPAddress());
va009039 6:420a86583681 134 Websocket* ws = new Websocket(URL);
va009039 6:420a86583681 135 if (!ws->connect()) {
va009039 6:420a86583681 136 error("mbed is not connected to websocket "URL);
va009039 6:420a86583681 137 }
va009039 6:420a86583681 138
va009039 3:6ae9a03a6145 139 BaseUsbHost* usbHost = new BaseUsbHost();
va009039 3:6ae9a03a6145 140 ControlEp* ctlEp = new ControlEp; // root hub
va009039 6:420a86583681 141 if (UsbHub::check(ctlEp)) {
va009039 6:420a86583681 142 UsbHub* hub = new UsbHub(ctlEp);
va009039 6:420a86583681 143 ctlEp = hub->search<UvcCam>(0);
va009039 6:420a86583681 144 if (ctlEp == NULL) {
va009039 6:420a86583681 145 error("UVC Camera is not connected in USB hub.\n");
va009039 5:495f7536897b 146 }
va009039 6:420a86583681 147 } else if (!UvcCam::check(ctlEp)) {
va009039 3:6ae9a03a6145 148 error("UVC Camera is not connected.\n");
va009039 3:6ae9a03a6145 149 }
va009039 6:420a86583681 150 UvcCam* cam = new UvcCam(UVC_MJPEG, UVC_160x120, _5FPS, ctlEp);
va009039 6:420a86583681 151
va009039 6:420a86583681 152 Capture* capture_th = new Capture(cam);
va009039 6:420a86583681 153 capture_th->set_stack(512);
va009039 6:420a86583681 154 capture_th->start();
va009039 6:420a86583681 155
va009039 6:420a86583681 156 term.printf("\n\n"VIEWER"\n\n");
va009039 3:6ae9a03a6145 157
va009039 6:420a86583681 158 int frame = 0;
va009039 6:420a86583681 159 for(int n = 0;; n++) {
va009039 6:420a86583681 160 osEvent evt = mail_box.get(200);
va009039 5:495f7536897b 161 if (evt.status == osEventMail) {
va009039 5:495f7536897b 162 ImageBuffer *buf = reinterpret_cast<ImageBuffer*>(evt.value.p);
va009039 6:420a86583681 163 if (frame < 10) {
va009039 6:420a86583681 164 term.printf("Capture stack used: %d/%d bytes\n", capture_th->stack_used(), capture_th->stack_size());
va009039 6:420a86583681 165 term.printf("image size: %d bytes\n", buf->size());
va009039 6:420a86583681 166 }
va009039 6:420a86583681 167 if (frame++ < FRAME_LIMIT || FRAME_LIMIT==(-1)) {
va009039 6:420a86583681 168 led2 = 1;
va009039 6:420a86583681 169 buf_to_websocket(ws, buf);
va009039 6:420a86583681 170 led2 = 0;
va009039 5:495f7536897b 171 }
va009039 5:495f7536897b 172 mail_box.free(buf);
va009039 5:495f7536897b 173 led4 = !led4;
va009039 5:495f7536897b 174 }
va009039 6:420a86583681 175 led1 = ws->is_connected();
va009039 3:6ae9a03a6145 176 }
va009039 3:6ae9a03a6145 177 }