Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ add_compile_definitions(BOARD_HAS_PSRAM)

set(
COMPONENTS
"main esptool_py esp_psram jpegdec task format monitor display_drivers wifi socket"
"main esptool_py esp_psram jpegdec task format monitor display_drivers wifi socket rtsp_client"
CACHE STRING
"List of components to include"
)
Expand Down
2 changes: 1 addition & 1 deletion components/espp
Submodule espp updated 320 files
3 changes: 3 additions & 0 deletions components/rtsp_client/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
idf_component_register(
INCLUDE_DIRS "include"
PRIV_REQUIRES logger socket task)
22 changes: 22 additions & 0 deletions components/rtsp_client/example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)

# add the component directories that we want to use
set(EXTRA_COMPONENT_DIRS
"../../../components/"
"../../../components/espp/components"
)

set(
COMPONENTS
"main esptool_py logger task socket wifi rtsp_client"
CACHE STRING
"List of components to include"
)

project(rtsp_client_example)

set(CMAKE_CXX_STANDARD 20)
67 changes: 67 additions & 0 deletions components/rtsp_client/example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
_Note that this is a template for an ESP-IDF example README.md file. When using this template, replace all these emphasised placeholders with example-specific content._

| Supported Targets | _Supported target, e.g. ESP32_ | _Another supported target, e.g. ESP32-S3_ |
| ----------------- | ------------------------------ | ----------------------------------------- |

_If the example supports all targets supported by ESP-IDF then the table can be omitted_
# _Example Title_

(See the README.md file in the upper level 'examples' directory for more information about examples.)

_What is this example? What does it do?_

_What features of ESP-IDF does it use?_

_What could someone create based on this example? ie applications/use cases/etc_

_If there are any acronyms or Espressif-only words used here, explain them or mention where in the datasheet/TRM this information can be found._

## How to use example

### Hardware Required

_If possible, example should be able to run on any commonly available ESP32 development board. Otherwise, describe what specific hardware should be used._

_If any other items (server, BLE device, app, second chip, whatever) are needed, mention them here. Include links if applicable. Explain how to set them up._

### Configure the project

```
idf.py menuconfig
```

* _If there is any project configuration that the user must set for this example, mention this here._

### Build and Flash

Build the project and flash it to the board, then run monitor tool to view serial output:

```
idf.py -p PORT flash monitor
```

(Replace PORT with the name of the serial port to use.)

(To exit the serial monitor, type ``Ctrl-]``.)

See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.

## Example Output

_Include an example of the console output from the running example, here:_

```
Use this style for pasting the log.
```

_If the user is supposed to interact with the example at this point (read/write GATT attribute, send HTTP request, press button, etc. then mention it here)_

_For examples where ESP32 is connected with some other hardware, include a table or schematics with connection details._

## Troubleshooting

_If there are any likely problems or errors which many users might encounter, mention them here. Remove this section for very simple examples where nothing is likely to go wrong._

## Example Breakdown

_If the example source code is lengthy, complex, or cannot be easily understood, use this section to break down and explain the source code. This can be done by breaking down the execution path step by step, or explaining what each major function/task/source file does. Add sub titles if necessary. Remove this section for very simple examples where the source code is self explanatory._
2 changes: 2 additions & 0 deletions components/rtsp_client/example/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRC_DIRS "."
INCLUDE_DIRS ".")
21 changes: 21 additions & 0 deletions components/rtsp_client/example/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
menu "WiFi Example Configuration"

config ESP_WIFI_SSID
string "WiFi SSID"
default "myssid"
help
SSID (network name) for the example to connect to.

config ESP_WIFI_PASSWORD
string "WiFi Password"
default "mypassword"
help
WiFi password (WPA or WPA2) for the example to use.

config ESP_MAXIMUM_RETRY
int "Maximum retry"
default 5
help
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.

endmenu
120 changes: 120 additions & 0 deletions components/rtsp_client/example/main/rtsp_client_example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include <algorithm>
#include <chrono>
#include <functional>
#include <iterator>
#include <thread>

#if CONFIG_ESP32_WIFI_NVS_ENABLED
#include "nvs_flash.h"
#endif

#include "logger.hpp"
#include "task.hpp"
#include "tcp_socket.hpp"
#include "udp_socket.hpp"
#include "wifi_sta.hpp"

#include "jpeg_frame.hpp"
#include "rtsp_client.hpp"

using namespace std::chrono_literals;
using namespace std::placeholders;

extern "C" void app_main(void) {
espp::Logger logger({.tag = "RtspClient example", .level = espp::Logger::Verbosity::INFO});
logger.info("Starting RtspClient example");

#if CONFIG_ESP32_WIFI_NVS_ENABLED
// Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
#endif

// create a wifi station here so that LwIP will be init for this example
espp::WifiSta wifi_sta({
.ssid = CONFIG_ESP_WIFI_SSID,
.password = CONFIG_ESP_WIFI_PASSWORD,
.num_connect_retries = CONFIG_ESP_MAXIMUM_RETRY,
.on_connected = nullptr,
.on_disconnected = nullptr,
.on_got_ip = [](ip_event_got_ip_t* eventdata) {
fmt::print("got IP: {}.{}.{}.{}\n", IP2STR(&eventdata->ip_info.ip));
}
});

// wait until wifi is connected
while (!wifi_sta.is_connected()) {
std::this_thread::sleep_for(1s);
}

std::unique_ptr<espp::JpegFrame> most_recent_jpeg_frame;
std::error_code ec;
espp::RtspClient rtsp_client({
.server_address = "192.168.86.181",
.rtsp_port = 8554,
.path = "/mjpeg/1",
.on_jpeg_frame = [&most_recent_jpeg_frame](std::unique_ptr<espp::JpegFrame> jpeg_frame) {
auto jpeg_data = jpeg_frame->get_data();
auto jpeg_size = jpeg_data.size();
fmt::print("Got JPEG frame: {} bytes\n", jpeg_size);
most_recent_jpeg_frame = std::move(jpeg_frame);
},
.log_level = espp::Logger::Verbosity::INFO,
});

do {
// clear the error code
ec.clear();
rtsp_client.connect(ec);
if (ec) {
logger.error("Error connecting to server: {}", ec.message());
logger.info("Retrying in 1s...");
std::this_thread::sleep_for(1s);
}
} while (ec);

rtsp_client.describe(ec);
if (ec) {
logger.error("Failed to describe stream: {}", ec.message());
return;
}

rtsp_client.setup(ec);
if (ec) {
logger.error("Failed to setup stream: {}", ec.message());
return;
}

rtsp_client.play(ec);
if (ec) {
logger.error("Failed to play stream: {}", ec.message());
return;
}

// sleep for 5 seconds
std::this_thread::sleep_for(5s);

// NOTE: the current server doesn't properly respond to the teardown request, so we'll just
// ignore the error here
rtsp_client.teardown(ec);

// NOTE: the current server doesn't properly respond to the teardown request, so we'll just
// ignore the error here
rtsp_client.disconnect(ec);

auto jpeg_data = most_recent_jpeg_frame->get_data();
logger.info("Most recent JPEG frame: {} bytes", jpeg_data.size());
std::vector<uint8_t> jpeg_vector(jpeg_data.begin(), jpeg_data.end());
logger.info("Most recent JPEG:\n{::#04x}", jpeg_vector);

logger.info("RtspClient example finished");

// wait forever
while (true) {
std::this_thread::sleep_for(1s);
}
}
5 changes: 5 additions & 0 deletions components/rtsp_client/example/partitions.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Name, Type, SubType, Offset, Size
nvs, data, nvs, 0x9000, 0x6000
phy_init, data, phy, 0xf000, 0x1000
factory, app, factory, 0x10000, 4M
images, 0x40, 0x01, , 8M
32 changes: 32 additions & 0 deletions components/rtsp_client/example/sdkconfig.defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
CONFIG_IDF_TARGET="esp32s3"

CONFIG_COMPILER_OPTIMIZATION_PERF=y
# CONFIG_COMPILER_OPTIMIZATION_SIZE=y

CONFIG_FREERTOS_HZ=1000

CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_ESPTOOLPY_FLASHSIZE="16MB"

#
# Partition Table
#
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"

#
# Common ESP-related
#
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192

# SPIRAM Configuration
CONFIG_SPIRAM=y
CONFIG_SPIRAM_USE=y
CONFIG_SPIRAM_MODE_OCT=y
CONFIG_SPIRAM_SPEED_80M=y

# ESP32-specific
#
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240
Loading