Webcam Server.
Dependencies: uvchost FatFileSystem mbed HTTPServer NetServicesMin
WebcamHandler.cpp@1:7a4f2c038803, 2012-08-14 (annotated)
- 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?
User | Revision | Line number | New 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 | } |