Skip to content

Commit

Permalink
Merge pull request #170 from sepfy/aiortc
Browse files Browse the repository at this point in the history
Aiortc
  • Loading branch information
sepfy authored Dec 16, 2024
2 parents 9f55c47 + c52c9e2 commit b875f3c
Show file tree
Hide file tree
Showing 18 changed files with 452 additions and 321 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ if (DEFINED ENV{IDF_PATH})
INCLUDE_DIRS "./src" ${HTTP_INCLUDE_PUBLIC_DIRS} ${MQTT_INCLUDE_PUBLIC_DIRS}
REQUIRES mbedtls srtp json esp_netif
)
add_definitions("-DCONFIG_USE_LWIP=1" "-DCONFIG_USE_USRSCTP=0" "-DCONFIG_AUDIO_BUFFER_SIZE=8096" "-DCONFIG_DATA_BUFFER_SIZE=102400" "-DHTTP_DO_NOT_USE_CUSTOM_CONFIG" "-DMQTT_DO_NOT_USE_CUSTOM_CONFIG")
add_definitions("-DCONFIG_USE_LWIP=1" "-DCONFIG_USE_USRSCTP=0" "-DCONFIG_AUDIO_BUFFER_SIZE=8096" "-DCONFIG_DATA_BUFFER_SIZE=102400" "-D__BYTE_ORDER=__LITTLE_ENDIAN" "-DHTTP_DO_NOT_USE_CUSTOM_CONFIG" "-DMQTT_DO_NOT_USE_CUSTOM_CONFIG")
return()
endif()

Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# libpeer - Portable WebRTC Library for IoT/Embedded Device

![build](https://github.com/sepfy/pear/actions/workflows/build.yml/badge.svg)
[![Discord](https://img.shields.io/discord/1265486725967253667?logo=discord)](https://discord.gg/AsPgabeS67)

libpeer is a WebRTC implementation written in C, developed with BSD socket. The library aims to integrate IoT/Embedded device video/audio streaming with WebRTC, such as ESP32 and Raspberry Pi

Expand Down Expand Up @@ -29,15 +28,18 @@ libpeer is a WebRTC implementation written in C, developed with BSD socket. The
* [coreMQTT](https://github.com/FreeRTOS/coreMQTT)

### Getting Started with Generic Example
- Copy URL from the test [website](https://sepfy.github.io/libpeer)
- Build and run the example
```bash
$ sudo apt -y install git cmake
$ git clone --recursive https://github.com/sepfy/libpeer
$ cd libpeer
$ cmake -S . -B build && cmake --build build
$ wget http://www.live555.com/liveMedia/public/264/test.264 # Download test video file
$ wget https://mauvecloud.net/sounds/alaw08m.wav # Download test audio file
$ ./generic/sample/sample
$ ./examples/generic/sample -u <URL>
```
- Click Connect button on the website

### Examples for Platforms
- [ESP32](https://github.com/sepfy/libpeer/tree/main/examples/esp32): MJPEG over datachannel
Expand Down
12 changes: 11 additions & 1 deletion examples/esp32/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
menu "ESP32 Hardware Configuration"
menu "Peer Example Configuration"

choice ESP32_CAMERA_MODEL
prompt "Camera model"
Expand All @@ -15,4 +15,14 @@ menu "ESP32 Hardware Configuration"
bool "ESP32S3-XIAO-SENSE"
endchoice

config SIGNALING_URL
string "Signaling URL"
default "https://libpeer.com/public/test"
help
Enter the URL of the Peer library to use.
config SIGNALING_TOKEN
string "Signaling Token"
default ""
help
Enter the token of the Peer library to use.
endmenu
21 changes: 5 additions & 16 deletions examples/esp32/main/app_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,6 @@ void peer_connection_task(void* arg) {
}

void app_main(void) {
static char deviceid[32] = {0};
uint8_t mac[8] = {0};

PeerConfiguration config = {
.ice_servers = {
{.urls = "stun:stun.l.google.com:19302"}},
Expand All @@ -104,11 +101,6 @@ void app_main(void) {
ESP_ERROR_CHECK(esp_event_loop_create_default());
ESP_ERROR_CHECK(example_connect());

if (esp_read_mac(mac, ESP_MAC_WIFI_STA) == ESP_OK) {
sprintf(deviceid, "esp32-%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
ESP_LOGI(TAG, "Device ID: %s", deviceid);
}

xSemaphore = xSemaphoreCreateMutex();

peer_init();
Expand All @@ -122,13 +114,7 @@ void app_main(void) {
g_pc = peer_connection_create(&config);
peer_connection_oniceconnectionstatechange(g_pc, oniceconnectionstatechange);
peer_connection_ondatachannel(g_pc, onmessage, onopen, onclose);

ServiceConfiguration service_config = SERVICE_CONFIG_DEFAULT();
service_config.client_id = deviceid;
service_config.pc = g_pc;
service_config.mqtt_url = "broker.emqx.io";
peer_signaling_set_config(&service_config);
peer_signaling_join_channel();
peer_signaling_connect(CONFIG_SIGNALING_URL, CONFIG_SIGNALING_TOKEN, g_pc);

#if defined(CONFIG_ESP32S3_XIAO_SENSE)
StackType_t* stack_memory = (StackType_t*)heap_caps_malloc(8192 * sizeof(StackType_t), MALLOC_CAP_SPIRAM);
Expand All @@ -143,7 +129,10 @@ void app_main(void) {
xTaskCreatePinnedToCore(peer_connection_task, "peer_connection", 8192, NULL, 5, &xPcTaskHandle, 1);

ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "open https://sepfy.github.io/webrtc?deviceId=%s", deviceid);
printf("============= Configuration =============\n");
printf(" %-5s : %s\n", "URL", CONFIG_SIGNALING_URL);
printf(" %-5s : %s\n", "Token", CONFIG_SIGNALING_TOKEN);
printf("=========================================\n");

while (1) {
peer_signaling_loop();
Expand Down
46 changes: 34 additions & 12 deletions examples/generic/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,42 @@ static uint64_t get_timestamp() {
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

void print_usage(const char* prog_name) {
printf("Usage: %s -u <url> [-t <token>]\n", prog_name);
}

void parse_arguments(int argc, char* argv[], const char** url, const char** token) {
*token = NULL;
*url = NULL;

for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-u") == 0 && (i + 1) < argc) {
*url = argv[++i];
} else if (strcmp(argv[i], "-t") == 0 && (i + 1) < argc) {
*token = argv[++i];
} else {
print_usage(argv[0]);
exit(1);
}
}

if (*url == NULL) {
print_usage(argv[0]);
exit(1);
}
}

int main(int argc, char* argv[]) {
uint64_t curr_time, video_time, audio_time;
uint8_t buf[102400];
const char* url = NULL;
const char* token = NULL;
int size;

pthread_t peer_singaling_thread;
pthread_t peer_connection_thread;

if (argc < 2) {
printf("Usage: %s <device_id>\n", argv[0]);
return -1;
}
parse_arguments(argc, argv, &url, &token);

signal(SIGINT, signal_handler);

Expand All @@ -83,19 +107,17 @@ int main(int argc, char* argv[]) {
.video_codec = CODEC_H264,
.audio_codec = CODEC_PCMA};

ServiceConfiguration service_config = SERVICE_CONFIG_DEFAULT();

printf("open https://sepfy.github.io/webrtc?deviceId=%s\n", argv[1]);
printf("=========== Parsed Arguments ===========\n");
printf(" %-5s : %s\n", "URL", url);
printf(" %-5s : %s\n", "Token", token ? token : "");
printf("========================================\n");

peer_init();
g_pc = peer_connection_create(&config);
peer_connection_oniceconnectionstatechange(g_pc, onconnectionstatechange);
peer_connection_ondatachannel(g_pc, onmessage, onopen, onclose);

service_config.client_id = argv[1];
service_config.pc = g_pc;
peer_signaling_set_config(&service_config);
peer_signaling_join_channel();
peer_signaling_connect(url, token, g_pc);

pthread_create(&peer_connection_thread, NULL, peer_connection_task, NULL);
pthread_create(&peer_singaling_thread, NULL, peer_singaling_task, NULL);
Expand Down Expand Up @@ -130,7 +152,7 @@ int main(int argc, char* argv[]) {

reader_deinit();

peer_signaling_leave_channel();
peer_signaling_disconnect();
peer_connection_destroy(g_pc);
peer_deinit();

Expand Down
5 changes: 5 additions & 0 deletions examples/pico/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ target_compile_definitions(peer PRIVATE
CONFIG_MBEDTLS_2_X=1
CONFIG_DATA_BUFFER_SIZE=512
CONFIG_AUDIO_BUFFER_SIZE=2048
CONFIG_HTTP_BUFFER_SIZE=1024
CONFIG_SDP_BUFFER_SIZE=4096
HTTP_DO_NOT_USE_CUSTOM_CONFIG
MQTT_DO_NOT_USE_CUSTOM_CONFIG
Expand All @@ -107,9 +108,13 @@ target_link_libraries(peer
cjson
)

pico_generate_pio_header(pico_peer ${CMAKE_CURRENT_LIST_DIR}/rp2040_i2s_example/i2s.pio)

# Build pico_peer
add_executable(pico_peer
main.c
rp2040_i2s_example/i2s.c
pcm-g711/pcm-g711/g711.c
)

target_compile_definitions(pico_peer PRIVATE
Expand Down
50 changes: 49 additions & 1 deletion examples/pico/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@
#include "pico/stdlib.h"
#include "task.h"

#include "hardware/dma.h"

#include "pcm-g711/pcm-g711/g711.h"
#include "peer.h"
#include "rp2040_i2s_example/i2s.h"

static __attribute__((aligned(8))) pio_i2s i2s;

#define TEST_TASK_PRIORITY (tskIDLE_PRIORITY + 1UL)

Expand All @@ -38,6 +44,45 @@ void onopen(void* userdata) {

static void onclose(void* userdata) {
}
#if 1
uint32_t get_epoch_time() {
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint32_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
#endif
static void dma_i2s_in_handler(void) {
int8_t alaw[AUDIO_BUFFER_FRAMES];
int16_t pcm[AUDIO_BUFFER_FRAMES];
int32_t* input_buffer;
if (*(int32_t**)dma_hw->ch[i2s.dma_ch_in_ctrl].read_addr == i2s.input_buffer) {
input_buffer = i2s.input_buffer;
} else {
input_buffer = i2s.input_buffer + STEREO_BUFFER_SIZE;
}
for (int i = 0; i < AUDIO_BUFFER_FRAMES; i++) {
pcm[i] = (int16_t)(input_buffer[2 * i + 1] >> 16);
alaw[i] = ALaw_Encode(pcm[i]);
}

#if 1
static uint32_t total_bytes = 0;
static uint32_t last_time = 0;
total_bytes += AUDIO_BUFFER_FRAMES;
uint32_t current_time = get_epoch_time();
if (current_time - last_time > 1000) {
printf("AUDIO_BUFFER_FRAMES: %d, bps: %d\n", AUDIO_BUFFER_FRAMES, 1000 * total_bytes * 8 / (current_time - last_time));
total_bytes = 0;
last_time = current_time;
}
#endif

if (eState == PEER_CONNECTION_COMPLETED) {
peer_connection_send_audio(g_pc, alaw, AUDIO_BUFFER_FRAMES);
}

dma_hw->ints0 = 1u << i2s.dma_ch_in_data; // clear the IRQ
}

void peer_connection_task() {
printf("Run peer connection task on the core: %d\n", portGET_CORE_ID());
Expand Down Expand Up @@ -68,6 +113,7 @@ void main_task(__unused void* params) {
PeerConfiguration config = {
.ice_servers = {
{.urls = "stun:stun.l.google.com:19302"}},
.audio_codec = CODEC_PCMA,
.datachannel = DATA_CHANNEL_STRING,
};

Expand All @@ -84,6 +130,8 @@ void main_task(__unused void* params) {

xTaskCreate(peer_connection_task, "PeerConnectionTask", 4096, NULL, TEST_TASK_PRIORITY, &xPcTaskHandle);

i2s_program_start_synched(pio0, &i2s_config_default, dma_i2s_in_handler, &i2s);

printf("Run main task on the core: %d\n", portGET_CORE_ID());
printf("open https://sepfy.github.io/webrtc?deviceId=mypico\n");
while (true) {
Expand All @@ -103,7 +151,7 @@ void vLaunch(void) {

int main(void) {
stdio_init_all();
// set_sys_clock_khz(200000, true);
// set_sys_clock_khz(132000, true);
vLaunch();
return 0;
}
9 changes: 8 additions & 1 deletion src/agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,14 @@ void agent_set_remote_description(Agent* agent, char* description) {

} else if (strncmp(line_start, "a=candidate:", strlen("a=candidate:")) == 0) {
if (ice_candidate_from_description(&agent->remote_candidates[agent->remote_candidates_count], line_start, line_end) == 0) {
agent->remote_candidates_count++;
for (i = 0; i < agent->remote_candidates_count; i++) {
if (strcmp(agent->remote_candidates[i].foundation, agent->remote_candidates[agent->remote_candidates_count].foundation) == 0) {
break;
}
}
if (i == agent->remote_candidates_count) {
agent->remote_candidates_count++;
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#ifndef CONFIG_H_
#define CONFIG_H_

// uncomment this if you want to handshake with a aiortc
#define CONFIG_DTLS_USE_ECDSA 1

#define SCTP_MTU (1200)
#define CONFIG_MTU (1300)

Expand All @@ -22,6 +25,10 @@
#define RSA_KEY_LENGTH 1024
#endif

#ifndef CONFIG_DTLS_USE_ECDSA
#define CONFIG_DTLS_USE_ECDSA 0
#endif

#ifndef CONFIG_USE_USRSCTP
#define CONFIG_USE_USRSCTP 1
#endif
Expand Down
6 changes: 5 additions & 1 deletion src/dtls_srtp.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,13 @@ static int dtls_srtp_selfsign_cert(DtlsSrtp* dtls_srtp) {

mbedtls_ctr_drbg_seed(&dtls_srtp->ctr_drbg, mbedtls_entropy_func, &dtls_srtp->entropy, (const unsigned char*)pers, strlen(pers));

#if CONFIG_DTLS_USE_ECDSA
mbedtls_pk_setup(&dtls_srtp->pkey, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, mbedtls_pk_ec(dtls_srtp->pkey), mbedtls_ctr_drbg_random, &dtls_srtp->ctr_drbg);
#else
mbedtls_pk_setup(&dtls_srtp->pkey, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));

mbedtls_rsa_gen_key(mbedtls_pk_rsa(dtls_srtp->pkey), mbedtls_ctr_drbg_random, &dtls_srtp->ctr_drbg, RSA_KEY_LENGTH, 65537);
#endif

mbedtls_x509write_crt_init(&crt);

Expand Down
Loading

0 comments on commit b875f3c

Please sign in to comment.