Webcam Server.

Dependencies:   uvchost FatFileSystem mbed HTTPServer NetServicesMin

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WebcamHandler.cpp Source File

WebcamHandler.cpp

00001 
00002 /*
00003 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
00004  
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to deal
00007 in the Software without restriction, including without limitation the rights
00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011  
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014  
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021 THE SOFTWARE.
00022 */
00023 
00024 #include "WebcamServerConfig.h"
00025 #include "WebcamHandler.h"
00026 
00027 //#define __DEBUG
00028 #include "mydbg.h"
00029 //#include "dbg/dbg.h"
00030 
00031 #define _D(...) #__VA_ARGS__
00032 
00033 #if CAM_COUNT == 1
00034 const char* html_index = _D(
00035 <html>
00036 <head>
00037 <meta http-equiv="refresh" content="10">
00038 </head>
00039 <body>
00040 <a href="/cam.jpg"><img src="/cam.jpg" width="320" height="240"></a>
00041 </body>
00042 </html>
00043 );
00044 #endif
00045 
00046 #if CAM_COUNT == 2
00047 const char* html_index = _D(
00048 <html>
00049 <head>
00050 <meta http-equiv="refresh" content="10">
00051 </head>
00052 <body>
00053 <img src="/cam0.jpg">
00054 <img src="/cam1.jpg">
00055 </body>
00056 </html>
00057 );
00058 #endif
00059 
00060 #define CHUNK_SIZE 128
00061 
00062 WebcamHandler::WebcamHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket) 
00063     : HTTPRequestHandler(rootPath, path, pTCPSocket)
00064 {}
00065 
00066 void WebcamHandler::doGet()
00067 {
00068   DBG("\r\nIn WebcamHandler::doGet() - rootPath=%s, path=%s\r\n", rootPath().c_str(), path().c_str());
00069   if (path().find("/cam") == 0) {
00070       int cam = 0;
00071       if (path().find("/cam0") == 0) {
00072           cam = 1;
00073       }
00074       DBG_ASSERT(cam >= 0);
00075       DBG_ASSERT(cam <= 1);
00076       m_buf = (char*)m_image[cam].buf;
00077       m_buf_len = m_image[cam].len;
00078       respHeaders()["Content-Type"] = "image/jpeg";
00079       m_busy = true;
00080   } else if (path().length() == 0) {
00081       m_buf = const_cast<char*>(html_index);
00082       m_buf_len = strlen(html_index);
00083       respHeaders()["Content-Type"] = "text/html";
00084   } else {
00085       m_buf = NULL;
00086   }
00087   if(m_buf == NULL)
00088   {
00089     setErrCode(404);
00090     const char* msg = "iamge not found.";
00091     setContentLen(strlen(msg));
00092     respHeaders()["Content-Type"] = "text/html";
00093     respHeaders()["Connection"] = "close";
00094     writeData(msg,strlen(msg)); //Only send header
00095     DBG("\r\nExit WebcamHandler::doGet() w Error 404\r\n");
00096     return;
00097   }
00098   m_pos = 0;
00099   DBG("m_buf_len=%d\n",  m_buf_len);
00100   setContentLen(m_buf_len);
00101   respHeaders()["Connection"] = "close";
00102   onWriteable();
00103 }
00104 
00105 void WebcamHandler::onWriteable() //Data has been written & buf is free
00106 {
00107   DBG("\r\nImageHandler::onWriteable() event\r\n");
00108   if(m_buf == NULL)
00109   {
00110     //Error has been served, now exit
00111     close();
00112     return;
00113   }
00114   
00115   while(true) {
00116     int len;
00117     if ((m_buf_len - m_pos) > CHUNK_SIZE) {
00118         len = CHUNK_SIZE;
00119     } else {
00120         len = m_buf_len - m_pos;
00121     }
00122     if(len > 0) {
00123       int writtenLen = writeData(m_buf + m_pos, len);
00124       DBG("writtenLen=%d m_buf=%p m_pos=%d len=%d\n", writtenLen, m_buf, m_pos, len);
00125       if(writtenLen < 0) //Socket error
00126       {
00127         DBG("WebcamHandler: Socket error %d\n", writtenLen);
00128         if(writtenLen == TCPSOCKET_MEM) {
00129           return; //Wait for the queued TCP segments to be transmitted
00130         } else {
00131           //This is a critical error
00132           close();
00133           return; 
00134         }
00135       } 
00136       else if(writtenLen < len) //Short write, socket's buffer is full
00137       {
00138         m_pos += writtenLen;
00139         return;
00140       }
00141       m_pos += writtenLen;
00142     } else {
00143       close(); //Data written, we can close the connection
00144       return;
00145     }
00146   }
00147 }
00148 
00149 void WebcamHandler::onClose()
00150 {
00151     DBG("m_busy=%d\n", m_busy);
00152     m_busy = false;
00153 }
00154 
00155 //static init
00156 struct stimage WebcamHandler::m_image[] = {{NULL,0},{NULL,0}};
00157 bool WebcamHandler::m_busy = false;
00158  
00159 void WebcamHandler::setImage(uint8_t* buf, int len, int cam)
00160 {
00161     DBG_ASSERT(cam >= 0);
00162     DBG_ASSERT(cam <= 1);
00163     m_image[cam].buf = buf;
00164     m_image[cam].len = len;
00165 }