diff --git a/.clang-format b/.clang-format index ba9095f..6223b69 100644 --- a/.clang-format +++ b/.clang-format @@ -50,7 +50,7 @@ BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeColon BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true -ColumnLimit: 80 +ColumnLimit: 120 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: true @@ -164,4 +164,4 @@ StatementMacros: TabWidth: 4 UseCRLF: false UseTab: Never -... +... \ No newline at end of file diff --git a/examples/capture/capture.ino b/examples/capture/capture.ino index 2e6a9a4..8e2247d 100644 --- a/examples/capture/capture.ino +++ b/examples/capture/capture.ino @@ -22,10 +22,11 @@ void setup() { } Serial.println("Camera Init Success"); - TimerCAM.Camera.sensor->set_pixformat(TimerCAM.Camera.sensor, - PIXFORMAT_JPEG); - TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, - FRAMESIZE_QVGA); + TimerCAM.Camera.sensor->set_pixformat(TimerCAM.Camera.sensor, PIXFORMAT_JPEG); + // 2MP Sensor + TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, FRAMESIZE_UXGA); + // 3MP Sensor + // TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, FRAMESIZE_QXGA); TimerCAM.Camera.sensor->set_vflip(TimerCAM.Camera.sensor, 1); TimerCAM.Camera.sensor->set_hmirror(TimerCAM.Camera.sensor, 0); diff --git a/examples/ext_wakeup/ext_wakeup.ino b/examples/ext_wakeup/ext_wakeup.ino index 9b03765..2121dce 100644 --- a/examples/ext_wakeup/ext_wakeup.ino +++ b/examples/ext_wakeup/ext_wakeup.ino @@ -38,10 +38,11 @@ void setup() { return; } Serial.println("Camera Init Success"); - TimerCAM.Camera.sensor->set_pixformat(TimerCAM.Camera.sensor, - PIXFORMAT_JPEG); - TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, - FRAMESIZE_QVGA); + TimerCAM.Camera.sensor->set_pixformat(TimerCAM.Camera.sensor, PIXFORMAT_JPEG); + // 2MP Sensor + TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, FRAMESIZE_UXGA); + // 3MP Sensor + // TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, FRAMESIZE_QXGA); TimerCAM.Camera.sensor->set_vflip(TimerCAM.Camera.sensor, 1); TimerCAM.Camera.sensor->set_hmirror(TimerCAM.Camera.sensor, 0); diff --git a/examples/http_post/http_post.ino b/examples/http_post/http_post.ino index 0786044..ca87670 100644 --- a/examples/http_post/http_post.ino +++ b/examples/http_post/http_post.ino @@ -34,10 +34,11 @@ void setup() { } Serial.println("Camera Init Success"); - TimerCAM.Camera.sensor->set_pixformat(TimerCAM.Camera.sensor, - PIXFORMAT_JPEG); - TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, - FRAMESIZE_QVGA); + TimerCAM.Camera.sensor->set_pixformat(TimerCAM.Camera.sensor, PIXFORMAT_JPEG); + // 2MP Sensor + TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, FRAMESIZE_UXGA); + // 3MP Sensor + // TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, FRAMESIZE_QXGA); TimerCAM.Camera.sensor->set_vflip(TimerCAM.Camera.sensor, 1); TimerCAM.Camera.sensor->set_hmirror(TimerCAM.Camera.sensor, 0); @@ -69,8 +70,7 @@ void loop() { String contentType = "image/jpeg"; // client.post("/post", contentType, postData); - client.post("/post", contentType.c_str(), TimerCAM.Camera.fb->len, - TimerCAM.Camera.fb->buf); + client.post("/post", contentType.c_str(), TimerCAM.Camera.fb->len, TimerCAM.Camera.fb->buf); // read the status code and body of the response int statusCode = client.responseStatusCode(); diff --git a/examples/rtsp_stream/CRtspSession.cpp b/examples/rtsp_stream/CRtspSession.cpp index 7d89b34..c1c6501 100644 --- a/examples/rtsp_stream/CRtspSession.cpp +++ b/examples/rtsp_stream/CRtspSession.cpp @@ -3,9 +3,7 @@ #include CRtspSession::CRtspSession(WiFiClient& aClient, CStreamer* aStreamer) - : LinkedListElement(aStreamer->getClientsListHead()), - m_Client(aClient), - m_Streamer(aStreamer) { + : LinkedListElement(aStreamer->getClientsListHead()), m_Client(aClient), m_Streamer(aStreamer) { printf("Creating RTSP session\n"); Init(); @@ -37,8 +35,7 @@ void CRtspSession::Init() { m_ContentLength = 0; }; -bool CRtspSession::ParseRtspRequest(char const* aRequest, - unsigned aRequestSize) { +bool CRtspSession::ParseRtspRequest(char const* aRequest, unsigned aRequestSize) { char CmdName[RTSP_PARAM_STRING_MAX]; static char CurRequest[RTSP_BUFFER_SIZE]; // Note: we assume single // threaded, this large buf we @@ -118,26 +115,20 @@ bool CRtspSession::ParseRtspRequest(char const* aRequest, // Skip over the prefix of any "rtsp://" or "rtsp:/" URL that follows: unsigned j = i + 1; - while (j < CurRequestSize && - (CurRequest[j] == ' ' || CurRequest[j] == '\t')) + while (j < CurRequestSize && (CurRequest[j] == ' ' || CurRequest[j] == '\t')) ++j; // skip over any additional white space for (; (int)j < (int)(CurRequestSize - 8); ++j) { - if ((CurRequest[j] == 'r' || CurRequest[j] == 'R') && - (CurRequest[j + 1] == 't' || CurRequest[j + 1] == 'T') && + if ((CurRequest[j] == 'r' || CurRequest[j] == 'R') && (CurRequest[j + 1] == 't' || CurRequest[j + 1] == 'T') && (CurRequest[j + 2] == 's' || CurRequest[j + 2] == 'S') && - (CurRequest[j + 3] == 'p' || CurRequest[j + 3] == 'P') && - CurRequest[j + 4] == ':' && CurRequest[j + 5] == '/') { + (CurRequest[j + 3] == 'p' || CurRequest[j + 3] == 'P') && CurRequest[j + 4] == ':' && + CurRequest[j + 5] == '/') { j += 6; if (CurRequest[j] == '/') { // This is a "rtsp://" URL; skip over // the host:port part that follows: ++j; unsigned uidx = 0; - while ( - j < CurRequestSize && CurRequest[j] != '/' && - CurRequest[j] != ' ' && - uidx < - sizeof(m_URLHostPort) - - 1) { // extract the host:port part of the URL here + while (j < CurRequestSize && CurRequest[j] != '/' && CurRequest[j] != ' ' && + uidx < sizeof(m_URLHostPort) - 1) { // extract the host:port part of the URL here m_URLHostPort[uidx] = CurRequest[j]; uidx++; ++j; @@ -152,8 +143,7 @@ bool CRtspSession::ParseRtspRequest(char const* aRequest, // Look for the URL suffix (before the following "RTSP/"): parseSucceeded = false; for (unsigned k = i + 1; (int)k < (int)(CurRequestSize - 5); ++k) { - if (CurRequest[k] == 'R' && CurRequest[k + 1] == 'T' && - CurRequest[k + 2] == 'S' && CurRequest[k + 3] == 'P' && + if (CurRequest[k] == 'R' && CurRequest[k + 1] == 'T' && CurRequest[k + 2] == 'S' && CurRequest[k + 3] == 'P' && CurRequest[k + 4] == '/') { while (--k >= i && CurRequest[k] == ' ') { } @@ -181,16 +171,12 @@ bool CRtspSession::ParseRtspRequest(char const* aRequest, // or \n as 'CSeq': parseSucceeded = false; for (j = i; (int)j < (int)(CurRequestSize - 5); ++j) { - if (CurRequest[j] == 'C' && CurRequest[j + 1] == 'S' && - CurRequest[j + 2] == 'e' && CurRequest[j + 3] == 'q' && + if (CurRequest[j] == 'C' && CurRequest[j + 1] == 'S' && CurRequest[j + 2] == 'e' && CurRequest[j + 3] == 'q' && CurRequest[j + 4] == ':') { j += 5; - while (j < CurRequestSize && - (CurRequest[j] == ' ' || CurRequest[j] == '\t')) - ++j; + while (j < CurRequestSize && (CurRequest[j] == ' ' || CurRequest[j] == '\t')) ++j; unsigned n; - for (n = 0; n < sizeof(m_CSeq) - 1 && j < CurRequestSize; - ++n, ++j) { + for (n = 0; n < sizeof(m_CSeq) - 1 && j < CurRequestSize; ++n, ++j) { char c = CurRequest[j]; if (c == '\r' || c == '\n') { parseSucceeded = true; @@ -206,18 +192,13 @@ bool CRtspSession::ParseRtspRequest(char const* aRequest, // Also: Look for "Content-Length:" (optional) for (j = i; (int)j < (int)(CurRequestSize - 15); ++j) { - if (CurRequest[j] == 'C' && CurRequest[j + 1] == 'o' && - CurRequest[j + 2] == 'n' && CurRequest[j + 3] == 't' && - CurRequest[j + 4] == 'e' && CurRequest[j + 5] == 'n' && - CurRequest[j + 6] == 't' && CurRequest[j + 7] == '-' && - (CurRequest[j + 8] == 'L' || CurRequest[j + 8] == 'l') && - CurRequest[j + 9] == 'e' && CurRequest[j + 10] == 'n' && - CurRequest[j + 11] == 'g' && CurRequest[j + 12] == 't' && - CurRequest[j + 13] == 'h' && CurRequest[j + 14] == ':') { + if (CurRequest[j] == 'C' && CurRequest[j + 1] == 'o' && CurRequest[j + 2] == 'n' && CurRequest[j + 3] == 't' && + CurRequest[j + 4] == 'e' && CurRequest[j + 5] == 'n' && CurRequest[j + 6] == 't' && + CurRequest[j + 7] == '-' && (CurRequest[j + 8] == 'L' || CurRequest[j + 8] == 'l') && + CurRequest[j + 9] == 'e' && CurRequest[j + 10] == 'n' && CurRequest[j + 11] == 'g' && + CurRequest[j + 12] == 't' && CurRequest[j + 13] == 'h' && CurRequest[j + 14] == ':') { j += 15; - while (j < CurRequestSize && - (CurRequest[j] == ' ' || CurRequest[j] == '\t')) - ++j; + while (j < CurRequestSize && (CurRequest[j] == ' ' || CurRequest[j] == '\t')) ++j; unsigned num; if (sscanf(&CurRequest[j], "%u", &num) == 1) m_ContentLength = num; } @@ -225,8 +206,7 @@ bool CRtspSession::ParseRtspRequest(char const* aRequest, return true; }; -RTSP_CMD_TYPES CRtspSession::Handle_RtspRequest(char const* aRequest, - unsigned aRequestSize) { +RTSP_CMD_TYPES CRtspSession::Handle_RtspRequest(char const* aRequest, unsigned aRequestSize) { if (ParseRtspRequest(aRequest, aRequestSize)) { switch (m_RtspCmdType) { case RTSP_OPTIONS: { @@ -272,15 +252,12 @@ void CRtspSession::Handle_RtspDESCRIBE() { // check whether we know a stream with the URL which is requested m_StreamID = -1; // invalid URL - if ((strcmp(m_URLPreSuffix, "mjpeg") == 0) && - (strcmp(m_URLSuffix, "1") == 0)) + if ((strcmp(m_URLPreSuffix, "mjpeg") == 0) && (strcmp(m_URLSuffix, "1") == 0)) m_StreamID = 0; - else if ((strcmp(m_URLPreSuffix, "mjpeg") == 0) && - (strcmp(m_URLSuffix, "2") == 0)) + else if ((strcmp(m_URLPreSuffix, "mjpeg") == 0) && (strcmp(m_URLSuffix, "2") == 0)) m_StreamID = 1; if (m_StreamID == -1) { // Stream not available - snprintf(Response, sizeof(Response), - "RTSP/1.0 404 Stream Not Found\r\nCSeq: %s\r\n%s\r\n", m_CSeq, + snprintf(Response, sizeof(Response), "RTSP/1.0 404 Stream Not Found\r\nCSeq: %s\r\n%s\r\n", m_CSeq, DateHeader()); socketsend(m_RtspClient, Response, strlen(Response)); @@ -294,16 +271,15 @@ void CRtspSession::Handle_RtspDESCRIBE() { ColonPtr = strstr(OBuf, ":"); if (ColonPtr != nullptr) ColonPtr[0] = 0x00; - snprintf( - SDPBuf, sizeof(SDPBuf), - "v=0\r\n" - "o=- %d 1 IN IP4 %s\r\n" - "s=\r\n" - "t=0 0\r\n" // start / stop - 0 -> unbounded and permanent session - "m=video 0 RTP/AVP 26\r\n" // currently we just handle UDP sessions - // "a=x-dimensions: 640,480\r\n" - "c=IN IP4 0.0.0.0\r\n", - rand(), OBuf); + snprintf(SDPBuf, sizeof(SDPBuf), + "v=0\r\n" + "o=- %d 1 IN IP4 %s\r\n" + "s=\r\n" + "t=0 0\r\n" // start / stop - 0 -> unbounded and permanent session + "m=video 0 RTP/AVP 26\r\n" // currently we just handle UDP sessions + // "a=x-dimensions: 640,480\r\n" + "c=IN IP4 0.0.0.0\r\n", + rand(), OBuf); char StreamName[64]; switch (m_StreamID) { case 0: @@ -345,16 +321,13 @@ void CRtspSession::Handle_RtspSETUP() { // simulate SETUP server response if (m_TcpTransport) - snprintf(Transport, sizeof(Transport), - "RTP/AVP/TCP;unicast;interleaved=0-1"); + snprintf(Transport, sizeof(Transport), "RTP/AVP/TCP;unicast;interleaved=0-1"); else snprintf(Transport, sizeof(Transport), "RTP/" "AVP;unicast;destination=127.0.0.1;source=127.0.0.1;client_" "port=%i-%i;server_port=%i-%i", - m_ClientRTPPort, m_ClientRTCPPort, - m_Streamer->GetRtpServerPort(), - m_Streamer->GetRtcpServerPort()); + m_ClientRTPPort, m_ClientRTCPPort, m_Streamer->GetRtpServerPort(), m_Streamer->GetRtcpServerPort()); snprintf(Response, sizeof(Response), "RTSP/1.0 200 OK\r\nCSeq: %s\r\n" "%s\r\n" @@ -397,17 +370,16 @@ int CRtspSession::GetStreamID() { bool CRtspSession::handleRequests(uint32_t readTimeoutMs) { if (m_stopped) return false; // Already closed down - static char - RecvBuf[RTSP_BUFFER_SIZE]; // Note: we assume single threaded, this - // large buf we keep off of the tiny stack + static char RecvBuf[RTSP_BUFFER_SIZE]; // Note: we assume single threaded, this + // large buf we keep off of the tiny stack memset(RecvBuf, 0x00, sizeof(RecvBuf)); int res = socketread(m_RtspClient, RecvBuf, sizeof(RecvBuf), readTimeoutMs); if (res > 0) { // we filter away everything which seems not to be an RTSP command: // O-ption, D-escribe, S-etup, P-lay, T-eardown - if ((RecvBuf[0] == 'O') || (RecvBuf[0] == 'D') || (RecvBuf[0] == 'S') || - (RecvBuf[0] == 'P') || (RecvBuf[0] == 'T')) { + if ((RecvBuf[0] == 'O') || (RecvBuf[0] == 'D') || (RecvBuf[0] == 'S') || (RecvBuf[0] == 'P') || + (RecvBuf[0] == 'T')) { RTSP_CMD_TYPES C = Handle_RtspRequest(RecvBuf, res); if (C == RTSP_PLAY) m_streaming = true; diff --git a/examples/rtsp_stream/CRtspSession.h b/examples/rtsp_stream/CRtspSession.h index 115169d..d3dc9d9 100644 --- a/examples/rtsp_stream/CRtspSession.h +++ b/examples/rtsp_stream/CRtspSession.h @@ -5,14 +5,7 @@ #include "platglue-esp32.h" // supported command types -enum RTSP_CMD_TYPES { - RTSP_OPTIONS, - RTSP_DESCRIBE, - RTSP_SETUP, - RTSP_PLAY, - RTSP_TEARDOWN, - RTSP_UNKNOWN -}; +enum RTSP_CMD_TYPES { RTSP_OPTIONS, RTSP_DESCRIBE, RTSP_SETUP, RTSP_PLAY, RTSP_TEARDOWN, RTSP_UNKNOWN }; #define RTSP_BUFFER_SIZE 10000 // for incoming requests, and outgoing responses #define RTSP_PARAM_STRING_MAX 200 @@ -23,8 +16,7 @@ class CRtspSession : public LinkedListElement { CRtspSession(WiFiClient& aRtspClient, CStreamer* aStreamer); ~CRtspSession(); - RTSP_CMD_TYPES Handle_RtspRequest(char const* aRequest, - unsigned aRequestSize); + RTSP_CMD_TYPES Handle_RtspRequest(char const* aRequest, unsigned aRequestSize); int GetStreamID(); /** @@ -74,15 +66,13 @@ class CRtspSession : public LinkedListElement { // parameters of the last received RTSP request RTSP_CMD_TYPES - m_RtspCmdType; // command type (if any) of the current request + m_RtspCmdType; // command type (if any) of the current request char m_URLPreSuffix[RTSP_PARAM_STRING_MAX]; // stream name pre suffix char m_URLSuffix[RTSP_PARAM_STRING_MAX]; // stream name suffix char m_CSeq[RTSP_PARAM_STRING_MAX]; // RTSP command sequence number char m_URLHostPort[MAX_HOSTNAME_LEN]; // host:port part of the URL unsigned m_ContentLength; // SDP string size - uint16_t - m_RtpClientPort; // RTP receiver port on client (in host byte order!) - uint16_t - m_RtcpClientPort; // RTCP receiver port on client (in host byte order!) + uint16_t m_RtpClientPort; // RTP receiver port on client (in host byte order!) + uint16_t m_RtcpClientPort; // RTCP receiver port on client (in host byte order!) }; diff --git a/examples/rtsp_stream/CStreamer.cpp b/examples/rtsp_stream/CStreamer.cpp index 3d4d232..53f11fc 100644 --- a/examples/rtsp_stream/CStreamer.cpp +++ b/examples/rtsp_stream/CStreamer.cpp @@ -38,8 +38,7 @@ void CStreamer::addSession(WiFiClient &aClient) { // we have it stored in m_Clients } -int CStreamer::SendRtpPacket(unsigned const char *jpeg, int jpegLen, - int fragmentOffset, BufPtr quant0tbl, +int CStreamer::SendRtpPacket(unsigned const char *jpeg, int jpegLen, int fragmentOffset, BufPtr quant0tbl, BufPtr quant1tbl) { // printf("CStreamer::SendRtpPacket offset:%d - begin\n", fragmentOffset); #define KRtpHeaderSize 12 // size of the RTP header @@ -47,8 +46,7 @@ int CStreamer::SendRtpPacket(unsigned const char *jpeg, int jpegLen, #define MAX_FRAGMENT_SIZE 1100 // FIXME, pick more carefully int fragmentLen = MAX_FRAGMENT_SIZE; - if (fragmentLen + fragmentOffset > - jpegLen) // Shrink last fragment if needed + if (fragmentLen + fragmentOffset > jpegLen) // Shrink last fragment if needed fragmentLen = jpegLen - fragmentOffset; bool isLastFragment = (fragmentOffset + fragmentLen) == jpegLen; @@ -64,8 +62,7 @@ int CStreamer::SendRtpPacket(unsigned const char *jpeg, int jpegLen, static char RtpBuf[2048]; // Note: we assume single threaded, this large // buf we keep off of the tiny stack - int RtpPacketSize = fragmentLen + KRtpHeaderSize + KJpegHeaderSize + - (includeQuantTbl ? (4 + 64 * 2) : 0); + int RtpPacketSize = fragmentLen + KRtpHeaderSize + KJpegHeaderSize + (includeQuantTbl ? (4 + 64 * 2) : 0); memset(RtpBuf, 0x00, sizeof(RtpBuf)); // Prepare the first 4 byte of the packet. This is the Rtp over Rtsp header @@ -76,15 +73,11 @@ int CStreamer::SendRtpPacket(unsigned const char *jpeg, int jpegLen, RtpBuf[2] = (RtpPacketSize & 0x0000FF00) >> 8; RtpBuf[3] = (RtpPacketSize & 0x000000FF); // Prepare the 12 byte RTP header - RtpBuf[4] = 0x80; // RTP version - RtpBuf[5] = - 0x1a | - (isLastFragment ? 0x80 : 0x00); // JPEG payload (26) and marker bit - RtpBuf[7] = m_SequenceNumber & - 0x0FF; // each packet is counted with a sequence counter - RtpBuf[6] = m_SequenceNumber >> 8; - RtpBuf[8] = - (m_Timestamp & 0xFF000000) >> 24; // each image gets a timestamp + RtpBuf[4] = 0x80; // RTP version + RtpBuf[5] = 0x1a | (isLastFragment ? 0x80 : 0x00); // JPEG payload (26) and marker bit + RtpBuf[7] = m_SequenceNumber & 0x0FF; // each packet is counted with a sequence counter + RtpBuf[6] = m_SequenceNumber >> 8; + RtpBuf[8] = (m_Timestamp & 0xFF000000) >> 24; // each image gets a timestamp RtpBuf[9] = (m_Timestamp & 0x00FF0000) >> 16; RtpBuf[10] = (m_Timestamp & 0x0000FF00) >> 8; RtpBuf[11] = (m_Timestamp & 0x000000FF); @@ -94,9 +87,8 @@ int CStreamer::SendRtpPacket(unsigned const char *jpeg, int jpegLen, RtpBuf[15] = 0x67; // Prepare the 8 byte payload JPEG header - RtpBuf[16] = 0x00; // type specific - RtpBuf[17] = (fragmentOffset & 0x00FF0000) >> - 16; // 3 byte fragmentation offset for fragmented images + RtpBuf[16] = 0x00; // type specific + RtpBuf[17] = (fragmentOffset & 0x00FF0000) >> 16; // 3 byte fragmentation offset for fragmented images RtpBuf[18] = (fragmentOffset & 0x0000FF00) >> 8; RtpBuf[19] = (fragmentOffset & 0x000000FF); @@ -155,8 +147,7 @@ int CStreamer::SendRtpPacket(unsigned const char *jpeg, int jpegLen, // over RTSP header { socketpeeraddr(session->getClient(), &otherip, &otherport); - udpsocketsend(m_RtpSocket, &RtpBuf[4], RtpPacketSize, otherip, - session->getRtpClientPort()); + udpsocketsend(m_RtpSocket, &RtpBuf[4], RtpPacketSize, otherip, session->getRtpClientPort()); } } element = element->m_Next; @@ -232,8 +223,7 @@ bool CStreamer::handleRequests(uint32_t readTimeoutMs) { return retVal; } -void CStreamer::streamFrame(unsigned const char *data, uint32_t dataLen, - uint32_t curMsec) { +void CStreamer::streamFrame(unsigned const char *data, uint32_t dataLen, uint32_t curMsec) { if (m_prevMsec == 0) // first frame init our timestamp m_prevMsec = curMsec; @@ -255,10 +245,8 @@ void CStreamer::streamFrame(unsigned const char *data, uint32_t dataLen, } while (offset != 0); // Increment ONLY after a full frame - uint32_t units = 90000; // Hz per RFC 2435 - m_Timestamp += - (units * deltams / - 1000); // fixed timestamp increment for a frame rate of 25fps + uint32_t units = 90000; // Hz per RFC 2435 + m_Timestamp += (units * deltams / 1000); // fixed timestamp increment for a frame rate of 25fps m_SendIdx++; if (m_SendIdx > 1) m_SendIdx = 0; @@ -361,8 +349,7 @@ void nextJpegBlock(BufPtr *bytes) { // When JPEG is stored as a file it is wrapped in a container // This function fixes up the provided start ptr to point to the // actual JPEG stream data and returns the number of bytes skipped -bool decodeJPEGfile(BufPtr *start, uint32_t *len, BufPtr *qtable0, - BufPtr *qtable1) { +bool decodeJPEGfile(BufPtr *start, uint32_t *len, BufPtr *qtable0, BufPtr *qtable1) { // per https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format unsigned const char *bytes = *start; diff --git a/examples/rtsp_stream/CStreamer.h b/examples/rtsp_stream/CStreamer.h index b398eff..51a04ed 100644 --- a/examples/rtsp_stream/CStreamer.h +++ b/examples/rtsp_stream/CStreamer.h @@ -27,18 +27,15 @@ class CStreamer { u_short GetRtpServerPort(); u_short GetRtcpServerPort(); - virtual void streamImage( - uint32_t curMsec) = 0; // send a new image to the client + virtual void streamImage(uint32_t curMsec) = 0; // send a new image to the client bool InitUdpTransport(void); void ReleaseUdpTransport(void); protected: - void streamFrame(unsigned const char *data, uint32_t dataLen, - uint32_t curMsec); + void streamFrame(unsigned const char *data, uint32_t dataLen, uint32_t curMsec); private: - int SendRtpPacket(unsigned const char *jpeg, int jpegLen, - int fragmentOffset, BufPtr quant0tbl = NULL, + int SendRtpPacket(unsigned const char *jpeg, int jpegLen, int fragmentOffset, BufPtr quant0tbl = NULL, BufPtr quant1tbl = NULL); // returns new fragmentOffset // or 0 if finished with frame @@ -66,8 +63,7 @@ class CStreamer { // actual JPEG stream data and returns the number of bytes skipped // returns true if the file seems to be valid jpeg // If quant tables can be found they will be stored in qtable0/1 -bool decodeJPEGfile(BufPtr *start, uint32_t *len, BufPtr *qtable0, - BufPtr *qtable1); +bool decodeJPEGfile(BufPtr *start, uint32_t *len, BufPtr *qtable0, BufPtr *qtable1); bool findJPEGheader(BufPtr *start, uint32_t *len, uint8_t marker); // Given a jpeg ptr pointing to a pair of length bytes, advance the pointer to diff --git a/examples/rtsp_stream/platglue-esp32.h b/examples/rtsp_stream/platglue-esp32.h index f7e31e1..69a87a0 100644 --- a/examples/rtsp_stream/platglue-esp32.h +++ b/examples/rtsp_stream/platglue-esp32.h @@ -15,9 +15,8 @@ typedef WiFiClient *SOCKET; typedef WiFiUDP *UDPSOCKET; -typedef IPAddress - IPADDRESS; // On linux use uint32_t in network byte order (per getpeername) -typedef uint16_t IPPORT; // on linux use network byte order +typedef IPAddress IPADDRESS; // On linux use uint32_t in network byte order (per getpeername) +typedef uint16_t IPPORT; // on linux use network byte order #define NULLSOCKET NULL @@ -62,8 +61,7 @@ inline ssize_t socketsend(SOCKET sockfd, const void *buf, size_t len) { return sockfd->write((uint8_t *)buf, len); } -inline ssize_t udpsocketsend(UDPSOCKET sockfd, const void *buf, size_t len, - IPADDRESS destaddr, IPPORT destport) { +inline ssize_t udpsocketsend(UDPSOCKET sockfd, const void *buf, size_t len, IPADDRESS destaddr, IPPORT destport) { sockfd->beginPacket(destaddr, destport); sockfd->write((const uint8_t *)buf, len); if (!sockfd->endPacket()) printf("error sending udp packet\n"); diff --git a/examples/rtsp_stream/rtsp_stream.ino b/examples/rtsp_stream/rtsp_stream.ino index 38ea31e..90bbad8 100644 --- a/examples/rtsp_stream/rtsp_stream.ino +++ b/examples/rtsp_stream/rtsp_stream.ino @@ -24,8 +24,7 @@ class TimerCamRTSP : public CStreamer { Camera_Class &_camera; public: - TimerCamRTSP(Camera_Class &camera, int width, int height) - : CStreamer(width, height), _camera(camera){}; + TimerCamRTSP(Camera_Class &camera, int width, int height) : CStreamer(width, height), _camera(camera){}; virtual void streamImage(uint32_t curMsec) { if (_camera.get()) { streamFrame(_camera.fb->buf, _camera.fb->len, millis()); @@ -46,10 +45,13 @@ void setup() { } Serial.println("Camera Init Success"); - TimerCAM.Camera.sensor->set_pixformat(TimerCAM.Camera.sensor, - PIXFORMAT_JPEG); - TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, - FRAMESIZE_QVGA); + TimerCAM.Camera.sensor->set_pixformat(TimerCAM.Camera.sensor, PIXFORMAT_JPEG); + TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, FRAMESIZE_QVGA); + + // 2MP Sensor + // TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, FRAMESIZE_UXGA); + // 3MP Sensor + // TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, FRAMESIZE_QXGA); TimerCAM.Camera.sensor->set_vflip(TimerCAM.Camera.sensor, 1); TimerCAM.Camera.sensor->set_hmirror(TimerCAM.Camera.sensor, 0); @@ -96,16 +98,14 @@ void loop() { // instead we send only if we have new enough frames uint32_t now = millis(); if (streamer->anySessions()) { - if (now > lastimage + msecPerFrame || - now < lastimage) { // handle clock rollover + if (now > lastimage + msecPerFrame || now < lastimage) { // handle clock rollover streamer->streamImage(now); lastimage = now; // check if we are overrunning our max frame rate now = millis(); if (now > lastimage + msecPerFrame) { - Serial.printf("warning exceeding max frame rate of %d ms\n", - now - lastimage); + Serial.printf("warning exceeding max frame rate of %d ms\n", now - lastimage); } } } diff --git a/examples/web_cam/ap/ap.ino b/examples/web_cam/ap/ap.ino index e605a1c..2ee81a8 100644 --- a/examples/web_cam/ap/ap.ino +++ b/examples/web_cam/ap/ap.ino @@ -29,10 +29,12 @@ void setup() { } Serial.println("Camera Init Success"); - TimerCAM.Camera.sensor->set_pixformat(TimerCAM.Camera.sensor, - PIXFORMAT_JPEG); - TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, - FRAMESIZE_SVGA); + TimerCAM.Camera.sensor->set_pixformat(TimerCAM.Camera.sensor, PIXFORMAT_JPEG); + // 2MP Sensor + TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, FRAMESIZE_UXGA); + // 3MP Sensor + // TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, FRAMESIZE_QXGA); + TimerCAM.Camera.sensor->set_vflip(TimerCAM.Camera.sensor, 1); TimerCAM.Camera.sensor->set_hmirror(TimerCAM.Camera.sensor, 0); @@ -72,11 +74,9 @@ void loop() { // used to image stream #define PART_BOUNDARY "123456789000000000000987654321" -static const char* _STREAM_CONTENT_TYPE = - "multipart/x-mixed-replace;boundary=" PART_BOUNDARY; -static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n"; -static const char* _STREAM_PART = - "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n"; +static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY; +static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n"; +static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n"; static void jpegStream(WiFiClient* client) { Serial.println("Image stream satrt"); @@ -114,10 +114,8 @@ static void jpegStream(WiFiClient* client) { int64_t frame_time = fr_end - last_frame; last_frame = fr_end; frame_time /= 1000; - Serial.printf("MJPG: %luKB %lums (%.1ffps)\r\n", - (long unsigned int)(TimerCAM.Camera.fb->len / 1024), - (long unsigned int)frame_time, - 1000.0 / (long unsigned int)frame_time); + Serial.printf("MJPG: %luKB %lums (%.1ffps)\r\n", (long unsigned int)(TimerCAM.Camera.fb->len / 1024), + (long unsigned int)frame_time, 1000.0 / (long unsigned int)frame_time); TimerCAM.Camera.free(); TimerCAM.Power.setLed(0); diff --git a/examples/web_cam/sta/sta.ino b/examples/web_cam/sta/sta.ino index 4749e8c..e58639c 100644 --- a/examples/web_cam/sta/sta.ino +++ b/examples/web_cam/sta/sta.ino @@ -29,10 +29,12 @@ void setup() { } Serial.println("Camera Init Success"); - TimerCAM.Camera.sensor->set_pixformat(TimerCAM.Camera.sensor, - PIXFORMAT_JPEG); - TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, - FRAMESIZE_SVGA); + TimerCAM.Camera.sensor->set_pixformat(TimerCAM.Camera.sensor, PIXFORMAT_JPEG); + // 2MP Sensor + TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, FRAMESIZE_UXGA); + // 3MP Sensor + // TimerCAM.Camera.sensor->set_framesize(TimerCAM.Camera.sensor, FRAMESIZE_QXGA); + TimerCAM.Camera.sensor->set_vflip(TimerCAM.Camera.sensor, 1); TimerCAM.Camera.sensor->set_hmirror(TimerCAM.Camera.sensor, 0); @@ -59,8 +61,8 @@ void setup() { void loop() { WiFiClient client = server.available(); // listen for incoming clients if (client) { // if you get a client, - while (client.connected()) { // loop while the client's connected - if (client.available()) { // if there's bytes to read from the + while (client.connected()) { // loop while the client's connected + if (client.available()) { // if there's bytes to read from the jpegStream(&client); } } @@ -72,11 +74,9 @@ void loop() { // used to image stream #define PART_BOUNDARY "123456789000000000000987654321" -static const char* _STREAM_CONTENT_TYPE = - "multipart/x-mixed-replace;boundary=" PART_BOUNDARY; -static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n"; -static const char* _STREAM_PART = - "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n"; +static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY; +static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n"; +static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n"; static void jpegStream(WiFiClient* client) { Serial.println("Image stream satrt"); @@ -114,10 +114,8 @@ static void jpegStream(WiFiClient* client) { int64_t frame_time = fr_end - last_frame; last_frame = fr_end; frame_time /= 1000; - Serial.printf("MJPG: %luKB %lums (%.1ffps)\r\n", - (long unsigned int)(TimerCAM.Camera.fb->len / 1024), - (long unsigned int)frame_time, - 1000.0 / (long unsigned int)frame_time); + Serial.printf("MJPG: %luKB %lums (%.1ffps)\r\n", (long unsigned int)(TimerCAM.Camera.fb->len / 1024), + (long unsigned int)frame_time, 1000.0 / (long unsigned int)frame_time); TimerCAM.Camera.free(); TimerCAM.Power.setLed(0); diff --git a/library.json b/library.json index 85cdaf9..d40da26 100644 --- a/library.json +++ b/library.json @@ -10,7 +10,7 @@ "type": "git", "url": "https://github.com/m5stack/TimerCam-arduino.git" }, - "version": "1.0.0", + "version": "1.0.1", "frameworks": "arduino", "platforms": "espressif32", "dependencies": { diff --git a/library.properties b/library.properties index 2618839..a516de1 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Timer-CAM -version=1.0.0 +version=1.0.1 author=M5Stack maintainer=M5Stack sentence=Library for M5Stack Timer-CAM development kit diff --git a/src/utility/Camera_Class.cpp b/src/utility/Camera_Class.cpp index 162963c..b598f2b 100644 --- a/src/utility/Camera_Class.cpp +++ b/src/utility/Camera_Class.cpp @@ -24,12 +24,12 @@ static camera_config_t camera_config = { .ledc_channel = LEDC_CHANNEL_0, .pixel_format = PIXFORMAT_JPEG, - .frame_size = FRAMESIZE_QVGA, + .frame_size = FRAMESIZE_UXGA, .jpeg_quality = 16, .fb_count = 2, .fb_location = CAMERA_FB_IN_PSRAM, - .grab_mode = CAMERA_GRAB_WHEN_EMPTY, - .sccb_i2c_port = 1, + .grab_mode = CAMERA_GRAB_LATEST, + .sccb_i2c_port = 0, }; bool Camera_Class::begin() { diff --git a/src/utility/I2C_Class.cpp b/src/utility/I2C_Class.cpp index 78d1f7f..14ebc1e 100644 --- a/src/utility/I2C_Class.cpp +++ b/src/utility/I2C_Class.cpp @@ -8,8 +8,7 @@ void I2C_Class::begin(TwoWire *wire, uint8_t sda, uint8_t scl, long freq) { _wire->begin(sda, scl, freq); } -bool I2C_Class::writeBytes(uint8_t addr, uint8_t reg, uint8_t *buffer, - uint8_t length) { +bool I2C_Class::writeBytes(uint8_t addr, uint8_t reg, uint8_t *buffer, uint8_t length) { _wire->beginTransmission(addr); _wire->write(reg); _wire->write(buffer, length); @@ -17,8 +16,7 @@ bool I2C_Class::writeBytes(uint8_t addr, uint8_t reg, uint8_t *buffer, return false; } -bool I2C_Class::readBytes(uint8_t addr, uint8_t reg, uint8_t *buffer, - uint8_t length) { +bool I2C_Class::readBytes(uint8_t addr, uint8_t reg, uint8_t *buffer, uint8_t length) { uint8_t index = 0; _wire->beginTransmission(addr); _wire->write(reg); diff --git a/src/utility/Power_Class.cpp b/src/utility/Power_Class.cpp index 06b734e..726fff3 100644 --- a/src/utility/Power_Class.cpp +++ b/src/utility/Power_Class.cpp @@ -9,10 +9,8 @@ void Power_Class::begin() { adc1_config_width(ADC_WIDTH_BIT_12); adc1_config_channel_atten(BAT_ADC_CHANNEL, ADC_ATTEN_DB_11); - adc_chars = (esp_adc_cal_characteristics_t*)calloc( - 1, sizeof(esp_adc_cal_characteristics_t)); - esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, - BASE_VOLATAGE, adc_chars); + adc_chars = (esp_adc_cal_characteristics_t*)calloc(1, sizeof(esp_adc_cal_characteristics_t)); + esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, BASE_VOLATAGE, adc_chars); ledc_timer_config_t ledc_timer = { .speed_mode = LEDC_HIGH_SPEED_MODE, // timer mode @@ -46,10 +44,8 @@ int16_t Power_Class::getBatteryVoltage() { adc_raw_value += adc1_get_raw(BAT_ADC_CHANNEL); } - adc_raw_value = adc_raw_value / ADC_FILTER_SAMPLE; - uint32_t voltage = - (uint32_t)(esp_adc_cal_raw_to_voltage(adc_raw_value, adc_chars) / - SCALE); + adc_raw_value = adc_raw_value / ADC_FILTER_SAMPLE; + uint32_t voltage = (uint32_t)(esp_adc_cal_raw_to_voltage(adc_raw_value, adc_chars) / SCALE); return voltage; } diff --git a/src/utility/RTC8563_Class.cpp b/src/utility/RTC8563_Class.cpp index 6986592..5a4fccb 100644 --- a/src/utility/RTC8563_Class.cpp +++ b/src/utility/RTC8563_Class.cpp @@ -8,8 +8,7 @@ tm rtc_datetime_t::get_tm(void) { tm t_st = { - time.seconds, time.minutes, time.hours, date.date, date.month - 1, - date.year - 1900, date.weekDay, 0, 0, + time.seconds, time.minutes, time.hours, date.date, date.month - 1, date.year - 1900, date.weekDay, 0, 0, }; return t_st; } @@ -53,8 +52,7 @@ bool RTC8563_Class::getDateTime(rtc_datetime_t* datetime) { datetime->date.date = bcd2ToByte(buf[3] & 0x3f); datetime->date.weekDay = bcd2ToByte(buf[4] & 0x07); datetime->date.month = bcd2ToByte(buf[5] & 0x1f); - datetime->date.year = - bcd2ToByte(buf[6] & 0xff) + ((0x80 & buf[5]) ? 1900 : 2000); + datetime->date.year = bcd2ToByte(buf[6] & 0xff) + ((0x80 & buf[5]) ? 1900 : 2000); return true; } @@ -72,8 +70,7 @@ bool RTC8563_Class::getTime(rtc_time_t* time) { } void RTC8563_Class::setTime(const rtc_time_t& time) { - std::uint8_t buf[] = {byteToBcd2(time.seconds), byteToBcd2(time.minutes), - byteToBcd2(time.hours)}; + std::uint8_t buf[] = {byteToBcd2(time.seconds), byteToBcd2(time.minutes), byteToBcd2(time.hours)}; _i2c.writeBytes(BM8563_I2C_ADDR, 0x02, buf, sizeof(buf)); } @@ -93,8 +90,7 @@ bool RTC8563_Class::getDate(rtc_date_t* date) { void RTC8563_Class::setDate(const rtc_date_t& date) { std::uint8_t w = date.weekDay; - if (w > 6 && date.year >= 1900 && - ((std::size_t)(date.month - 1)) < 12) { /// weekDay auto adjust + if (w > 6 && date.year >= 1900 && ((std::size_t)(date.month - 1)) < 12) { /// weekDay auto adjust int32_t year = date.year; int32_t month = date.month; int32_t day = date.date; @@ -103,15 +99,12 @@ void RTC8563_Class::setDate(const rtc_date_t& date) { month += 12; } int32_t ydiv100 = year / 100; - w = (year + (year >> 2) - ydiv100 + (ydiv100 >> 2) + - (13 * month + 8) / 5 + day) % - 7; + w = (year + (year >> 2) - ydiv100 + (ydiv100 >> 2) + (13 * month + 8) / 5 + day) % 7; } - std::uint8_t buf[] = { - byteToBcd2(date.date), w, - (std::uint8_t)(byteToBcd2(date.month) + (date.year < 2000 ? 0x80 : 0)), - byteToBcd2(date.year % 100)}; + std::uint8_t buf[] = {byteToBcd2(date.date), w, + (std::uint8_t)(byteToBcd2(date.month) + (date.year < 2000 ? 0x80 : 0)), + byteToBcd2(date.year % 100)}; _i2c.writeBytes(BM8563_I2C_ADDR, 0x05, buf, sizeof(buf)); } diff --git a/src/utility/RTC8563_Class.h b/src/utility/RTC8563_Class.h index ba9bfb6..426fe19 100644 --- a/src/utility/RTC8563_Class.h +++ b/src/utility/RTC8563_Class.h @@ -21,15 +21,11 @@ struct __attribute__((packed)) rtc_time_t { std::int8_t minutes; std::int8_t seconds; - rtc_time_t(std::int8_t hours_ = -1, std::int8_t minutes_ = -1, - std::int8_t seconds_ = -1) + rtc_time_t(std::int8_t hours_ = -1, std::int8_t minutes_ = -1, std::int8_t seconds_ = -1) : hours{hours_}, minutes{minutes_}, seconds{seconds_} { } - rtc_time_t(const tm& t) - : hours{(int8_t)t.tm_hour}, - minutes{(int8_t)t.tm_min}, - seconds{(int8_t)t.tm_sec} { + rtc_time_t(const tm& t) : hours{(int8_t)t.tm_hour}, minutes{(int8_t)t.tm_min}, seconds{(int8_t)t.tm_sec} { } }; @@ -46,8 +42,7 @@ struct __attribute__((packed)) rtc_date_t { /// weekDay 0:sun / 1:mon / 2:tue / 3:wed / 4:thu / 5:fri / 6:sat std::int8_t weekDay; - rtc_date_t(std::int16_t year_ = 2000, std::int8_t month_ = 1, - std::int8_t date_ = -1, std::int8_t weekDay_ = -1) + rtc_date_t(std::int16_t year_ = 2000, std::int8_t month_ = 1, std::int8_t date_ = -1, std::int8_t weekDay_ = -1) : year{year_}, month{month_}, date{date_}, weekDay{weekDay_} { } @@ -63,8 +58,7 @@ struct __attribute__((packed)) rtc_datetime_t { rtc_date_t date; rtc_time_t time; rtc_datetime_t() = default; - rtc_datetime_t(const rtc_date_t& d, const rtc_time_t& t) - : date{d}, time{t} {}; + rtc_datetime_t(const rtc_date_t& d, const rtc_time_t& t) : date{d}, time{t} {}; rtc_datetime_t(const tm& t) : date{t}, time{t} { } tm get_tm(void);