diff --git a/README.md b/README.md index dff03fd..f2be9cb 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ There are a lot of boards available that are all called ESP32-CAM. However, there are differences in CPU (type/speed/cores), how the camera is connected, presence of PSRAM or not... To select the right board use the table below and use the configuration that is listed below for your board: -| Board | Image | CPU | SRAM | Flash | PSRAM | Camera | | Site | +| Board | Image | CPU | SRAM | Flash | PSRAM | Camera | Extras | Manufacturer site | |--- |--- |--- |--- |--- | --- |--- |--- |--- | | Espressif ESP32-Wrover CAM | ![img](assets/boards/esp32-wrover-cam.jpg) | ESP32 | 520KB | 4Mb | 4MB | OV2640 | | | | AI-Thinker ESP32-CAM | ![img](assets/boards/ai-thinker-esp32-cam-ipex.jpg) ![img](assets/boards/ai-thinker-esp32-cam.jpg) | ESP32-S | 520KB | 4Mb | 4MB | OV2640 | | [https://docs.ai-thinker.com/esp32-cam](https://docs.ai-thinker.com/esp32-cam) | diff --git a/dotnet_riscv b/dotnet_riscv new file mode 160000 index 0000000..70e3cb6 --- /dev/null +++ b/dotnet_riscv @@ -0,0 +1 @@ +Subproject commit 70e3cb657b88224d7d98e0aa8d0d8f7f9ed5c288 diff --git a/lib/micro-rtsp-server/include/micro_rtsp_camera.h b/lib/micro-rtsp-server/include/micro_rtsp_camera.h index 6b4481f..534eab2 100644 --- a/lib/micro-rtsp-server/include/micro_rtsp_camera.h +++ b/lib/micro-rtsp-server/include/micro_rtsp_camera.h @@ -1,8 +1,9 @@ #pragma once +#include #include -class micro_rtsp_camera +class micro_rtsp_camera : public micro_rtsp_source { public: micro_rtsp_camera(); @@ -11,12 +12,12 @@ class micro_rtsp_camera esp_err_t initialize(camera_config_t *camera_config); esp_err_t deinitialize(); - void update_frame(); + virtual void update_frame(); - uint8_t *data() const { return fb_->buf; } - size_t width() const { return fb_->width; } - size_t height() const { return fb_->height; } - size_t size() const { return fb_->len; } + virtual uint8_t *data() const { return fb_->buf; } + virtual size_t width() const { return fb_->width; } + virtual size_t height() const { return fb_->height; } + virtual size_t size() const { return fb_->len; } private: esp_err_t init_result_; diff --git a/lib/micro-rtsp-server/include/micro_rtsp_requests.h b/lib/micro-rtsp-server/include/micro_rtsp_requests.h index e15202b..c48c99b 100644 --- a/lib/micro-rtsp-server/include/micro_rtsp_requests.h +++ b/lib/micro-rtsp-server/include/micro_rtsp_requests.h @@ -1,5 +1,6 @@ #pragma once +#include #include class micro_rtsp_requests @@ -8,40 +9,41 @@ class micro_rtsp_requests std::string process_request(const std::string& request); private: - enum rtsp_command - { - rtsp_command_unknown, - rtsp_command_option, // OPTIONS - rtsp_command_describe, // DESCRIBE - rtsp_command_setup, // SETUP - rtsp_command_play, // PLAY - rtsp_command_teardown // TEARDOWN - }; - - const char* available_stream_name_ = "mjpeg/1"; - - rtsp_command parse_command(const std::string &request); + // enum rtsp_command + // { + // rtsp_command_unknown, + // rtsp_command_options, // OPTIONS + // rtsp_command_describe, // DESCRIBE + // rtsp_command_setup, // SETUP + // rtsp_command_play, // PLAY + // rtsp_command_teardown // TEARDOWN + // }; + + static const std::string available_stream_name_; + + //rtsp_command parse_command(const std::string &request); + //static bool parse_cseq(const std::string &line, unsigned long &cseq); bool parse_client_port(const std::string &request); - bool parse_cseq(const std::string &request); - bool parse_stream_url(const std::string &request); + //bool parse_stream_url(const std::string &request); - std::string date_header(); - std::string rtsp_error(unsigned short code, const std::string& message); + //static std::string date_header(); + static std::string handle_rtsp_error(unsigned long cseq, unsigned short code, const std::string &message); - std::string handle_option(const std::string &request); - std::string handle_describe(const std::string &request); - std::string handle_setup(const std::string &request); - std::string handle_play(const std::string &request); - std::string handle_teardown(const std::string &request); + static std::string handle_options(unsigned long cseq); + static std::string handle_describe(unsigned long cseq, const std::string &request); + std::string handle_setup(unsigned long cseq, const std::map &request); + std::string handle_play(unsigned long cseq); + std::string handle_teardown(unsigned long cseq); - unsigned long cseq_; + //unsigned long cseq_; - std::string host_url_; - unsigned short host_port_; - std::string stream_name_; + // std::string host_url_; + // unsigned short host_port_; + // std::string stream_name_; bool tcp_transport_; - unsigned short client_port_; + unsigned short start_client_port_; + unsigned short end_client_port_; unsigned short rtp_streamer_port_; unsigned short rtcp_streamer_port_; diff --git a/lib/micro-rtsp-server/include/micro_rtsp_server.h b/lib/micro-rtsp-server/include/micro_rtsp_server.h index f2d8d34..09bdff4 100644 --- a/lib/micro-rtsp-server/include/micro_rtsp_server.h +++ b/lib/micro-rtsp-server/include/micro_rtsp_server.h @@ -13,18 +13,18 @@ class micro_rtsp_server : WiFiServer { public: - micro_rtsp_server(micro_rtsp_camera &source, unsigned frame_interval = 100); + micro_rtsp_server(micro_rtsp_source &source); ~micro_rtsp_server(); void begin(unsigned short port = 554); void end(); - unsigned get_frame_interval() { return frame_interval_; } + unsigned get_frame_interval() const { return frame_interval_; } unsigned set_frame_interval(unsigned value) { return frame_interval_ = value; } void loop(); - size_t clients() { return clients_.size(); } + size_t clients() const { return clients_.size(); } class rtsp_client : public WiFiClient, public micro_rtsp_requests { @@ -36,7 +36,7 @@ class micro_rtsp_server : WiFiServer }; private: - micro_rtsp_camera &source_; + micro_rtsp_source &source_; unsigned frame_interval_; unsigned long next_frame_update_; unsigned long next_check_client_; diff --git a/lib/micro-rtsp-server/include/micro_rtsp_source.h b/lib/micro-rtsp-server/include/micro_rtsp_source.h new file mode 100644 index 0000000..1079a25 --- /dev/null +++ b/lib/micro-rtsp-server/include/micro_rtsp_source.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +// Interface for a video source +class micro_rtsp_source +{ +public: + virtual void update_frame() = 0; + + virtual uint8_t *data() const = 0; + virtual size_t width() const = 0; + virtual size_t height() const = 0; + virtual size_t size() const = 0; +}; \ No newline at end of file diff --git a/lib/micro-rtsp-server/include/micro_rtsp_streamer.h b/lib/micro-rtsp-server/include/micro_rtsp_streamer.h index 328f489..edbbd96 100644 --- a/lib/micro-rtsp-server/include/micro_rtsp_streamer.h +++ b/lib/micro-rtsp-server/include/micro_rtsp_streamer.h @@ -1,7 +1,8 @@ #pragma once #include -#include +#include // Add this line to include the definition of micro_rtsp_camera +#include // https://en.wikipedia.org/wiki/Maximum_transmission_unit constexpr size_t max_wifi_mtu = 2304; @@ -32,11 +33,11 @@ typedef struct __attribute__((packed)) class micro_rtsp_streamer { public: - micro_rtsp_streamer(const uint16_t width, const uint16_t height); + micro_rtsp_streamer(const micro_rtsp_source& source); rtp_over_tcp_hdr_t *create_jpg_packet(const uint8_t *jpg_scan, const uint8_t *jpg_scan_end, uint8_t **jpg_offset, const uint32_t timestamp, const uint8_t *quantization_table_luminance, const uint8_t *quantization_table_chrominance); private: - uint16_t width_, height_; + const micro_rtsp_source& source_; uint32_t ssrc_; uint16_t sequence_number_; }; \ No newline at end of file diff --git a/lib/micro-rtsp-server/include/micro_rtp_structs.h b/lib/micro-rtsp-server/include/micro_rtsp_structs.h similarity index 89% rename from lib/micro-rtsp-server/include/micro_rtp_structs.h rename to lib/micro-rtsp-server/include/micro_rtsp_structs.h index 2d90b8d..671efac 100644 --- a/lib/micro-rtsp-server/include/micro_rtp_structs.h +++ b/lib/micro-rtsp-server/include/micro_rtsp_structs.h @@ -5,9 +5,9 @@ // https://www.ietf.org/rfc/rfc2326#section-10.12 typedef struct __attribute__((packed)) { - char magic='$'; // Magic encapsulation ASCII dollar sign (24 hexadecimal) - uint8_t channel; // Channel identifier - uint16_t length; // Network order + char magic = '$'; // Magic encapsulation ASCII dollar sign (24 hexadecimal) + uint8_t channel; // Channel identifier + uint16_t length; // Network order } rtp_over_tcp_hdr_t; // RTP data header - http://www.ietf.org/rfc/rfc3550.txt diff --git a/lib/micro-rtsp-server/src/micro_rtsp_requests.cpp b/lib/micro-rtsp-server/src/micro_rtsp_requests.cpp index 11f0595..a95252d 100644 --- a/lib/micro-rtsp-server/src/micro_rtsp_requests.cpp +++ b/lib/micro-rtsp-server/src/micro_rtsp_requests.cpp @@ -1,33 +1,13 @@ #include +#include +#include #include #include "micro_rtsp_requests.h" // https://datatracker.ietf.org/doc/html/rfc2326 -micro_rtsp_requests::rtsp_command micro_rtsp_requests::parse_command(const std::string &request) -{ - log_v("request: %s", request.c_str()); - // Check for RTSP commands: Option, Describe, Setup, Play, Teardown - - if (std::regex_match(request, std::regex("^OPTION ", std::regex_constants::icase))) - return rtsp_command::rtsp_command_option; - - if (std::regex_match(request, std::regex("^DESCRIBE ", std::regex_constants::icase))) - return rtsp_command::rtsp_command_describe; - - if (std::regex_match(request, std::regex("^SETUP ", std::regex_constants::icase))) - return rtsp_command::rtsp_command_setup; - - if (std::regex_match(request, std::regex("^PLAY ", std::regex_constants::icase))) - return rtsp_command::rtsp_command_play; - - if (std::regex_match(request, std::regex("^TEARDOWN ", std::regex_constants::icase))) - return rtsp_command::rtsp_command_teardown; - - log_e("Invalid rtsp command: %s", request.c_str()); - return rtsp_command::rtsp_command_unknown; -} +const std::string micro_rtsp_requests::available_stream_name_ = "/mjpeg/1"; bool micro_rtsp_requests::parse_client_port(const std::string &request) { @@ -41,189 +21,195 @@ bool micro_rtsp_requests::parse_client_port(const std::string &request) return false; } - client_port_ = std::stoi(match[1].str()); - return true; -} - -bool micro_rtsp_requests::parse_cseq(const std::string &request) -{ - log_v("request: %s", request.c_str()); - - // CSeq: 2 - std::regex regex("CSeq: (\\d+)", std::regex_constants::icase); - std::smatch match; - if (!std::regex_match(request, match, regex)) - { - log_e("CSeq not found"); - return false; - } - - cseq_ = std::stoul(match[1].str()); - return true; -} - -bool micro_rtsp_requests::parse_stream_url(const std::string &request) -{ - log_v("request: %s", request.c_str()); - - // SETUP rtsp://192.168.10.93:1234/mjpeg/1 RTSP/1.0 - std::regex regex("rtsp:\\/\\/([\\w.]+):(\\d+)\\/([\\/\\w]+)\\s+RTSP/1.0", std::regex_constants::icase); - std::smatch match; - if (!std::regex_match(request, match, regex)) - { - log_e("Unable to parse url"); - return false; - } - - host_url_ = match[1].str(); - host_port_ = std::stoi(match[2].str()); - stream_name_ = match[3].str(); + start_client_port_ = std::stoi(match[1].str()); return true; } -std::string micro_rtsp_requests::date_header() +std::string micro_rtsp_requests::handle_rtsp_error(unsigned long cseq, unsigned short code, const std::string &message) { - char buffer[50]; - auto now = std::time(nullptr); - std::strftime(buffer, sizeof(buffer), "Date: %a, %b %d %Y %H:%M:%S GMT", std::gmtime(&now)); - return buffer; -} - -std::string micro_rtsp_requests::rtsp_error(unsigned short code, const std::string &message) -{ - log_v("code: %d, message: %s", code, message.c_str()); - + log_e("code: %d, message: %s", code, message.c_str()); + auto now = time(nullptr); std::ostringstream oss; oss << "RTSP/1.0 " << code << " " << message << "\r\n" - << "CSeq: " << cseq_ << "\r\n" - << date_header() << "\r\n" - << "\r\n"; + << "CSeq: " << cseq << "\r\n" + << std::put_time(std::gmtime(&now), "Date: %a, %b %d %Y %H:%M:%S GMT") << "\r\n"; return oss.str(); } -std::string micro_rtsp_requests::handle_option(const std::string &request) +// OPTIONS rtsp://192.168.178.247:554/mjpeg/1 RTSP/1.0 +// CSeq: 2 +// User-Agent: LibVLC/3.0.20 (LIVE555 Streaming Media v2016.11.28) +std::string micro_rtsp_requests::handle_options(unsigned long cseq) { - log_v("request: %s", request.c_str()); - + auto now = time(nullptr); std::ostringstream oss; oss << "RTSP/1.0 200 OK\r\n" - << "CSeq: " << cseq_ << "\r\n" - << date_header() << "\r\n" + << "CSeq: " << cseq << "\r\n" + << std::put_time(std::gmtime(&now), "Date: %a, %b %d %Y %H:%M:%S GMT") << "\r\n" << "Content-Length: 0\r\n" - << "Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE\r\n" - << "\r\n"; + << "Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE"; return oss.str(); } -std::string micro_rtsp_requests::handle_describe(const std::string &request) +// DESCRIBE rtsp://192.168.178.247:554/mjpeg/1 RTSP/1.0 +// CSeq: 3 +// User-Agent: LibVLC/3.0.20 (LIVE555 Streaming Media v2016.11.28) +// Accept: application/sdp +std::string micro_rtsp_requests::handle_describe(unsigned long cseq, const std::string &request) { - log_v("request: %s", request.c_str()); - - if (!parse_stream_url(request)) - return rtsp_error(400, "Invalid Stream Name"); - - if (stream_name_ != available_stream_name_) - return rtsp_error(404, "Stream Not Found"); - - std::ostringstream sdpos; - sdpos << "v=0\r\n" - << "o=- " << host_port_ << " 1 IN IP4 " << std::rand() << "\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 - << "c=IN IP4 0.0.0.0\r\n"; - auto sdp = sdpos.str(); - + // Parse the url + static const std::regex regex_url("rtsp:\\/\\/([^\\/:]+)(?::(\\d+))?(\\/.*)?\\s+RTSP\\/1\\.0", std::regex_constants::icase); + std::smatch match; + if (!std::regex_search(request, match, regex_url)) + return handle_rtsp_error(cseq, 400, "Invalid URL"); + + auto host = match[1].str(); + auto port = match[2].str().length() > 0 ? std::stoi(match[2].str()) : 554; + auto path = match[3].str(); + log_i("host: %s, port: %d, path: %s", host.c_str(), port, path.c_str()); + + if (path != available_stream_name_) + return handle_rtsp_error(cseq, 404, "Stream Not Found"); + + std::ostringstream osbody; + osbody << "v=0\r\n" + << "o=- " << std::rand() << " 1 IN IP4 " << host << "\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 + << "c=IN IP4 0.0.0.0\r\n"; + auto body = osbody.str(); + + auto now = time(nullptr); std::ostringstream oss; oss << "RTSP/1.0 200 OK\r\n" - << "CSeq: " << cseq_ << "\r\n" - << date_header() << "\r\n" - << "Content-Base: " << stream_name_ << "/\r\n" + << "CSeq: " << cseq << "\r\n" + << std::put_time(std::gmtime(&now), "Date: %a, %b %d %Y %H:%M:%S GMT") << "\r\n" + << "Content-Base: rtsp://" << host << ":" << port << path << "\r\n" << "Content-Type: application/sdp\r\n" - << "Content-Length: " << sdp.size() << "\r\n" + << "Content-Length: " << body.size() << "\r\n" << "\r\n" - << sdp; + << body; return oss.str(); } -std::string micro_rtsp_requests::handle_setup(const std::string &request) +// SETUP rtsp://192.168.178.247:554/mjpeg/1 RTSP/1.0 +// CSeq: 0 +// Transport: RTP/AVP;unicast;client_port=9058-9059 +std::string micro_rtsp_requests::handle_setup(unsigned long cseq, const std::map &lines) { log_v("request: %s", request.c_str()); - tcp_transport_ = request.find("rtp/avp/tcp") != std::string::npos; + auto it = lines.find("Transport"); + if (it == lines.end()) + return handle_rtsp_error(cseq, 400, "No Transport Header Found"); - if (!parse_client_port(request)) - return rtsp_error(400, "Could Not Find Client Port"); + static const std::regex regex_transport("\\s+RTP\\/AVP(\\/TCP)?;unicast;client_port=(\\d+)-(\\d+)", std::regex_constants::icase); + std::smatch match; + if (!std::regex_search(it->second, match, regex_transport)) + return handle_rtsp_error(cseq, 400, "Could Not Parse Transport"); + + tcp_transport_ = match[1].str().length() > 0; + start_client_port_ = std::stoi(match[2].str()); + end_client_port_ = std::stoi(match[3].str()); + log_i("tcp_transport: %d, start_client_port: %d, end_client_port: %d", tcp_transport_, start_client_port_, end_client_port_); std::ostringstream ostransport; if (tcp_transport_) ostransport << "RTP/AVP/TCP;unicast;interleaved=0-1"; else - ostransport << "RTP/AVP;unicast;destination=127.0.0.1;source=127.0.0.1;client_port=" << client_port_ << "-" << client_port_ + 1 << ";server_port=" << rtp_streamer_port_ << "-" << rtcp_streamer_port_; + ostransport << "RTP/AVP;unicast;destination=127.0.0.1;source=127.0.0.1;client_port=" << start_client_port_ << "-" << end_client_port_ + 1 << ";server_port=" << rtp_streamer_port_ << "-" << rtcp_streamer_port_; + auto now = time(nullptr); std::ostringstream oss; oss << "RTSP/1.0 200 OK\r\n" - << "CSeq: " << cseq_ << "\r\n" - << date_header() << "\r\n" + << "CSeq: " << cseq << "\r\n" + << std::put_time(std::gmtime(&now), "Date: %a, %b %d %Y %H:%M:%S GMT") << "\r\n" << "Transport: " << ostransport.str() << "\r\n" - << "Session: " << rtsp_session_id_ << "\r\n" - << "\r\n"; + << "Session: " << rtsp_session_id_; return oss.str(); } -std::string micro_rtsp_requests::handle_play(const std::string &request) +std::string micro_rtsp_requests::handle_play(unsigned long cseq) { log_v("request: %s", request.c_str()); stream_active_ = true; + + auto now = time(nullptr); std::ostringstream oss; oss << "RTSP/1.0 200 OK\r\n" - << "CSeq: " << cseq_ << "\r\n" - << date_header() << "\r\n" + << "CSeq: " << cseq << "\r\n" + << std::put_time(std::gmtime(&now), "Date: %a, %b %d %Y %H:%M:%S GMT") << "\r\n" << "Range: npt=0.000-\r\n" << "Session: " << rtsp_session_id_ << "\r\n" - << "RTP-Info: url=rtsp://127.0.0.1:8554/" << available_stream_name_ << "/track1\r\n" - << "\r\n"; + << "RTP-Info: url=rtsp://127.0.0.1:8554" << available_stream_name_ << "/track1" << "\r\n" + << "\r\n"; return oss.str(); } -std::string micro_rtsp_requests::handle_teardown(const std::string &request) +std::string micro_rtsp_requests::handle_teardown(unsigned long cseq) { log_v("request: %s", request.c_str()); stream_stopped_ = true; + + auto now = time(nullptr); std::ostringstream oss; oss << "RTSP/1.0 200 OK\r\n" - << "CSeq: " << cseq_ << "\r\n" - << date_header() << "\r\n" - << "\r\n"; + << "CSeq: " << cseq << "\r\n" + << std::put_time(std::gmtime(&now), "Date: %a, %b %d %Y %H:%M:%S GMT") << "\r\n"; return oss.str(); } +// Parse a request e.g. +// Request: OPTIONS rtsp://192.168.178.247:554/mjpeg/1 RTSP/1.0 +// CSeq: 2 +// User-Agent: LibVLC/3.0.20 (LIVE555 Streaming Media v2016.11.28) + std::string micro_rtsp_requests::process_request(const std::string &request) { log_v("request: %s", request.c_str()); - - auto command = parse_command(request); - if (command != rtsp_command_unknown) + + std::stringstream ss(request); + // Get the request line + std::string request_line; + if (!std::getline(ss, request_line)) + return handle_rtsp_error(0, 400, "No Request Found"); + + // Create a map with headers + std::string line; + std::map headers; + std::size_t pos; + while (std::getline(ss, line)) { - if (!parse_cseq(request)) - return rtsp_error(400, "No Sequence Found"); - - switch (command) - { - case rtsp_command_option: - return handle_option(request); - case rtsp_command_describe: - return handle_describe(request); - case rtsp_command_setup: - return handle_setup(request); - case rtsp_command_play: - return handle_play(request); - case rtsp_command_teardown: - return handle_teardown(request); - } + if ((pos = line.find(':')) != std::string::npos) + headers[line.substr(0, pos)] = line.substr(pos + 1); + else + log_e("No : found for header: %s", line.c_str()); } - return rtsp_error(400, "Unknown Command"); + log_i("request_line: %s", request_line.c_str()); + for (const auto &header : headers) + log_i("header: %s: %s", header.first.c_str(), header.second.c_str()); + + // Check for CSeq + const auto cseq_it = headers.find("CSeq"); + if (cseq_it == headers.end()) + return handle_rtsp_error(0, 400, "No Sequence Found"); + + auto cseq = std::stoul(cseq_it->second); + + if (request_line.find("OPTIONS") == 0) + return handle_options(cseq); + if (request_line.find("DESCRIBE") == 0) + return handle_describe(cseq, request_line); + if (request_line.find("SETUP") == 0) + return handle_setup(cseq, headers); + if (request_line.find("PLAY") == 0) + return handle_play(cseq); + if (request_line.find("TEARDOWN") == 0) + return handle_teardown(cseq); + + return handle_rtsp_error(cseq, 400, "Unknown Command or malformed request"); } diff --git a/lib/micro-rtsp-server/src/micro_rtsp_server.cpp b/lib/micro-rtsp-server/src/micro_rtsp_server.cpp index 0b5ef5e..4e6569f 100644 --- a/lib/micro-rtsp-server/src/micro_rtsp_server.cpp +++ b/lib/micro-rtsp-server/src/micro_rtsp_server.cpp @@ -6,11 +6,9 @@ // Check client connections every 100 milliseconds #define CHECK_CLIENT_INTERVAL 10 -micro_rtsp_server::micro_rtsp_server(micro_rtsp_camera &source, unsigned frame_interval /*= 100*/) - : source_(source), streamer_(source.width(), source.height()) +micro_rtsp_server::micro_rtsp_server(micro_rtsp_source &source) + : source_(source), streamer_(source) { - log_v("frame_interval:%d", frame_interval); - frame_interval_ = frame_interval; } micro_rtsp_server::~micro_rtsp_server() @@ -52,7 +50,7 @@ void micro_rtsp_server::loop() if (next_frame_update_ < now) { - log_v("Stream frame"); + log_v("Stream frame t=%d", next_frame_update_); next_frame_update_ = now + frame_interval_; auto ts = time(nullptr); @@ -96,14 +94,15 @@ void micro_rtsp_server::rtsp_client::handle_request() auto bytes_available = available(); if (bytes_available > 0) { - std::string request; - request.reserve(bytes_available); - if (read((uint8_t *)request.data(), bytes_available) == bytes_available) + std::string request(bytes_available, '\0'); + if (read((uint8_t*)&request[0], bytes_available) == bytes_available) { - log_i("Request: %s", request); + request.resize(bytes_available); + log_i("Request: %s", request.c_str()); auto response = process_request(request); - log_i("Response: %s", response); - write(response.data(), response.size()); + log_i("Response: %s", response.c_str()); + println(response.c_str()); + println(); } } } diff --git a/lib/micro-rtsp-server/src/micro_rtsp_streamer.cpp b/lib/micro-rtsp-server/src/micro_rtsp_streamer.cpp index 5272f9a..cf49658 100644 --- a/lib/micro-rtsp-server/src/micro_rtsp_streamer.cpp +++ b/lib/micro-rtsp-server/src/micro_rtsp_streamer.cpp @@ -5,11 +5,9 @@ #include "micro_rtsp_streamer.h" #include "esp_random.h" -micro_rtsp_streamer::micro_rtsp_streamer(const uint16_t width, const uint16_t height) +micro_rtsp_streamer::micro_rtsp_streamer(const micro_rtsp_source &source) + : source_(source) { - log_v("width:%d, height:%d", width, height); - width_ = width; - height_ = height; // Random number ssrc_ = esp_random(); sequence_number_ = 0; @@ -52,8 +50,8 @@ rtp_over_tcp_hdr_t *micro_rtsp_streamer::create_jpg_packet(const uint8_t *jpg_sc packet->jpeg_hdr.off = (uint32_t)(*jpg_offset - jpg_scan); // fragment byte offset (24 bits in jpg) packet->jpeg_hdr.type = 0; // id of jpeg decoder params packet->jpeg_hdr.q = (uint8_t)(include_quantization_tables ? 0x80 : 0x5e); // quantization factor (or table id) 5eh=94d - packet->jpeg_hdr.width = (uint8_t)(width_ >> 3); // frame width in 8 pixel blocks - packet->jpeg_hdr.height = (uint8_t)(height_ >> 3); // frame height in 8 pixel blocks + packet->jpeg_hdr.width = (uint8_t)(source_.width() >> 3); // frame width in 8 pixel blocks + packet->jpeg_hdr.height = (uint8_t)(source_.height() >> 3); // frame height in 8 pixel blocks log_v("jpeg_hdr={.tspec:%u,.off:0x%6x,.type:0x2%x,.q:%u,.width:%u.height:%u}", packet->jpeg_hdr.tspec, packet->jpeg_hdr.off, packet->jpeg_hdr.type, packet->jpeg_hdr.q, packet->jpeg_hdr.width, packet->jpeg_hdr.height); // Only in first packet of the frame diff --git a/platformio.ini b/platformio.ini index 7a4992b..52cd65e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -49,7 +49,7 @@ monitor_filters = esp32_exception_decoder build_flags = -Ofast -D 'BOARD_NAME="${this.board}"' - -D 'CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE' + -D 'CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO' -D 'IOTWEBCONF_PASSWORD_LEN=64' board_build.embed_txtfiles =