Webcam Server.

Dependencies:   uvchost FatFileSystem mbed HTTPServer NetServicesMin

Committer:
va009039
Date:
Tue Aug 14 03:42:12 2012 +0000
Revision:
1:7a4f2c038803
Parent:
0:2b4ea8a138e5
supported LogitechC270 and Safari

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 0:2b4ea8a138e5 1
va009039 0:2b4ea8a138e5 2 /*
va009039 0:2b4ea8a138e5 3 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
va009039 0:2b4ea8a138e5 4
va009039 0:2b4ea8a138e5 5 Permission is hereby granted, free of charge, to any person obtaining a copy
va009039 0:2b4ea8a138e5 6 of this software and associated documentation files (the "Software"), to deal
va009039 0:2b4ea8a138e5 7 in the Software without restriction, including without limitation the rights
va009039 0:2b4ea8a138e5 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
va009039 0:2b4ea8a138e5 9 copies of the Software, and to permit persons to whom the Software is
va009039 0:2b4ea8a138e5 10 furnished to do so, subject to the following conditions:
va009039 0:2b4ea8a138e5 11
va009039 0:2b4ea8a138e5 12 The above copyright notice and this permission notice shall be included in
va009039 0:2b4ea8a138e5 13 all copies or substantial portions of the Software.
va009039 0:2b4ea8a138e5 14
va009039 0:2b4ea8a138e5 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
va009039 0:2b4ea8a138e5 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
va009039 0:2b4ea8a138e5 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
va009039 0:2b4ea8a138e5 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
va009039 0:2b4ea8a138e5 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
va009039 0:2b4ea8a138e5 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
va009039 0:2b4ea8a138e5 21 THE SOFTWARE.
va009039 0:2b4ea8a138e5 22 */
va009039 0:2b4ea8a138e5 23
va009039 1:7a4f2c038803 24 #include "WebcamServerConfig.h"
va009039 0:2b4ea8a138e5 25 #include "WebcamHandler.h"
va009039 0:2b4ea8a138e5 26
va009039 0:2b4ea8a138e5 27 //#define __DEBUG
va009039 0:2b4ea8a138e5 28 #include "mydbg.h"
va009039 0:2b4ea8a138e5 29 //#include "dbg/dbg.h"
va009039 0:2b4ea8a138e5 30
va009039 0:2b4ea8a138e5 31 #define _D(...) #__VA_ARGS__
va009039 0:2b4ea8a138e5 32
va009039 1:7a4f2c038803 33 #if CAM_COUNT == 1
va009039 1:7a4f2c038803 34 const char* html_index = _D(
va009039 1:7a4f2c038803 35 <html>
va009039 1:7a4f2c038803 36 <head>
va009039 1:7a4f2c038803 37 <meta http-equiv="refresh" content="10">
va009039 1:7a4f2c038803 38 </head>
va009039 1:7a4f2c038803 39 <body>
va009039 1:7a4f2c038803 40 <a href="/cam.jpg"><img src="/cam.jpg" width="320" height="240"></a>
va009039 1:7a4f2c038803 41 </body>
va009039 1:7a4f2c038803 42 </html>
va009039 1:7a4f2c038803 43 );
va009039 1:7a4f2c038803 44 #endif
va009039 1:7a4f2c038803 45
va009039 1:7a4f2c038803 46 #if CAM_COUNT == 2
va009039 0:2b4ea8a138e5 47 const char* html_index = _D(
va009039 0:2b4ea8a138e5 48 <html>
va009039 0:2b4ea8a138e5 49 <head>
va009039 0:2b4ea8a138e5 50 <meta http-equiv="refresh" content="10">
va009039 0:2b4ea8a138e5 51 </head>
va009039 0:2b4ea8a138e5 52 <body>
va009039 0:2b4ea8a138e5 53 <img src="/cam0.jpg">
va009039 0:2b4ea8a138e5 54 <img src="/cam1.jpg">
va009039 0:2b4ea8a138e5 55 </body>
va009039 0:2b4ea8a138e5 56 </html>
va009039 0:2b4ea8a138e5 57 );
va009039 1:7a4f2c038803 58 #endif
va009039 0:2b4ea8a138e5 59
va009039 0:2b4ea8a138e5 60 #define CHUNK_SIZE 128
va009039 0:2b4ea8a138e5 61
va009039 0:2b4ea8a138e5 62 WebcamHandler::WebcamHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket)
va009039 0:2b4ea8a138e5 63 : HTTPRequestHandler(rootPath, path, pTCPSocket)
va009039 0:2b4ea8a138e5 64 {}
va009039 0:2b4ea8a138e5 65
va009039 0:2b4ea8a138e5 66 void WebcamHandler::doGet()
va009039 0:2b4ea8a138e5 67 {
va009039 0:2b4ea8a138e5 68 DBG("\r\nIn WebcamHandler::doGet() - rootPath=%s, path=%s\r\n", rootPath().c_str(), path().c_str());
va009039 0:2b4ea8a138e5 69 if (path().find("/cam") == 0) {
va009039 0:2b4ea8a138e5 70 int cam = 0;
va009039 0:2b4ea8a138e5 71 if (path().find("/cam0") == 0) {
va009039 0:2b4ea8a138e5 72 cam = 1;
va009039 0:2b4ea8a138e5 73 }
va009039 0:2b4ea8a138e5 74 DBG_ASSERT(cam >= 0);
va009039 0:2b4ea8a138e5 75 DBG_ASSERT(cam <= 1);
va009039 1:7a4f2c038803 76 m_buf = (char*)m_image[cam].buf;
va009039 0:2b4ea8a138e5 77 m_buf_len = m_image[cam].len;
va009039 0:2b4ea8a138e5 78 respHeaders()["Content-Type"] = "image/jpeg";
va009039 0:2b4ea8a138e5 79 m_busy = true;
va009039 0:2b4ea8a138e5 80 } else if (path().length() == 0) {
va009039 0:2b4ea8a138e5 81 m_buf = const_cast<char*>(html_index);
va009039 0:2b4ea8a138e5 82 m_buf_len = strlen(html_index);
va009039 0:2b4ea8a138e5 83 respHeaders()["Content-Type"] = "text/html";
va009039 0:2b4ea8a138e5 84 } else {
va009039 0:2b4ea8a138e5 85 m_buf = NULL;
va009039 0:2b4ea8a138e5 86 }
va009039 0:2b4ea8a138e5 87 if(m_buf == NULL)
va009039 0:2b4ea8a138e5 88 {
va009039 0:2b4ea8a138e5 89 setErrCode(404);
va009039 0:2b4ea8a138e5 90 const char* msg = "iamge not found.";
va009039 0:2b4ea8a138e5 91 setContentLen(strlen(msg));
va009039 0:2b4ea8a138e5 92 respHeaders()["Content-Type"] = "text/html";
va009039 0:2b4ea8a138e5 93 respHeaders()["Connection"] = "close";
va009039 0:2b4ea8a138e5 94 writeData(msg,strlen(msg)); //Only send header
va009039 0:2b4ea8a138e5 95 DBG("\r\nExit WebcamHandler::doGet() w Error 404\r\n");
va009039 0:2b4ea8a138e5 96 return;
va009039 0:2b4ea8a138e5 97 }
va009039 0:2b4ea8a138e5 98 m_pos = 0;
va009039 0:2b4ea8a138e5 99 DBG("m_buf_len=%d\n", m_buf_len);
va009039 0:2b4ea8a138e5 100 setContentLen(m_buf_len);
va009039 0:2b4ea8a138e5 101 respHeaders()["Connection"] = "close";
va009039 0:2b4ea8a138e5 102 onWriteable();
va009039 0:2b4ea8a138e5 103 }
va009039 0:2b4ea8a138e5 104
va009039 0:2b4ea8a138e5 105 void WebcamHandler::onWriteable() //Data has been written & buf is free
va009039 0:2b4ea8a138e5 106 {
va009039 0:2b4ea8a138e5 107 DBG("\r\nImageHandler::onWriteable() event\r\n");
va009039 0:2b4ea8a138e5 108 if(m_buf == NULL)
va009039 0:2b4ea8a138e5 109 {
va009039 0:2b4ea8a138e5 110 //Error has been served, now exit
va009039 0:2b4ea8a138e5 111 close();
va009039 0:2b4ea8a138e5 112 return;
va009039 0:2b4ea8a138e5 113 }
va009039 0:2b4ea8a138e5 114
va009039 0:2b4ea8a138e5 115 while(true) {
va009039 0:2b4ea8a138e5 116 int len;
va009039 0:2b4ea8a138e5 117 if ((m_buf_len - m_pos) > CHUNK_SIZE) {
va009039 0:2b4ea8a138e5 118 len = CHUNK_SIZE;
va009039 0:2b4ea8a138e5 119 } else {
va009039 0:2b4ea8a138e5 120 len = m_buf_len - m_pos;
va009039 0:2b4ea8a138e5 121 }
va009039 0:2b4ea8a138e5 122 if(len > 0) {
va009039 0:2b4ea8a138e5 123 int writtenLen = writeData(m_buf + m_pos, len);
va009039 0:2b4ea8a138e5 124 DBG("writtenLen=%d m_buf=%p m_pos=%d len=%d\n", writtenLen, m_buf, m_pos, len);
va009039 0:2b4ea8a138e5 125 if(writtenLen < 0) //Socket error
va009039 0:2b4ea8a138e5 126 {
va009039 0:2b4ea8a138e5 127 DBG("WebcamHandler: Socket error %d\n", writtenLen);
va009039 0:2b4ea8a138e5 128 if(writtenLen == TCPSOCKET_MEM) {
va009039 0:2b4ea8a138e5 129 return; //Wait for the queued TCP segments to be transmitted
va009039 0:2b4ea8a138e5 130 } else {
va009039 0:2b4ea8a138e5 131 //This is a critical error
va009039 0:2b4ea8a138e5 132 close();
va009039 0:2b4ea8a138e5 133 return;
va009039 0:2b4ea8a138e5 134 }
va009039 0:2b4ea8a138e5 135 }
va009039 0:2b4ea8a138e5 136 else if(writtenLen < len) //Short write, socket's buffer is full
va009039 0:2b4ea8a138e5 137 {
va009039 0:2b4ea8a138e5 138 m_pos += writtenLen;
va009039 0:2b4ea8a138e5 139 return;
va009039 0:2b4ea8a138e5 140 }
va009039 0:2b4ea8a138e5 141 m_pos += writtenLen;
va009039 0:2b4ea8a138e5 142 } else {
va009039 0:2b4ea8a138e5 143 close(); //Data written, we can close the connection
va009039 0:2b4ea8a138e5 144 return;
va009039 0:2b4ea8a138e5 145 }
va009039 0:2b4ea8a138e5 146 }
va009039 0:2b4ea8a138e5 147 }
va009039 0:2b4ea8a138e5 148
va009039 0:2b4ea8a138e5 149 void WebcamHandler::onClose()
va009039 0:2b4ea8a138e5 150 {
va009039 0:2b4ea8a138e5 151 DBG("m_busy=%d\n", m_busy);
va009039 0:2b4ea8a138e5 152 m_busy = false;
va009039 0:2b4ea8a138e5 153 }
va009039 0:2b4ea8a138e5 154
va009039 0:2b4ea8a138e5 155 //static init
va009039 0:2b4ea8a138e5 156 struct stimage WebcamHandler::m_image[] = {{NULL,0},{NULL,0}};
va009039 0:2b4ea8a138e5 157 bool WebcamHandler::m_busy = false;
va009039 0:2b4ea8a138e5 158
va009039 1:7a4f2c038803 159 void WebcamHandler::setImage(uint8_t* buf, int len, int cam)
va009039 0:2b4ea8a138e5 160 {
va009039 0:2b4ea8a138e5 161 DBG_ASSERT(cam >= 0);
va009039 0:2b4ea8a138e5 162 DBG_ASSERT(cam <= 1);
va009039 0:2b4ea8a138e5 163 m_image[cam].buf = buf;
va009039 0:2b4ea8a138e5 164 m_image[cam].len = len;
va009039 0:2b4ea8a138e5 165 }