#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_system.h"
#include "esp_log.h"
static const char *TAG = "WebRTC_Streaming";
// Queue handles
QueueHandle_t frameQueue;
QueueHandle_t encodedQueue;
SemaphoreHandle_t networkSemaphore;
// Frame structure
typedef struct {
int frameNumber;
uint32_t timestamp;
int frameSize;
} Frame;
/**
* Task 1: Camera Capture Simulation
* Priority: 5 (Highest)
*/
void cameraTask(void *pvParameter) {
Frame frame;
int frameCount = 0;
ESP_LOGI(TAG, "✅ Camera Task Started");
while(1) {
frame.frameNumber = frameCount++;
frame.timestamp = xTaskGetTickCount();
frame.frameSize = 65536; // 64KB frame
if(xQueueSend(frameQueue, &frame, pdMS_TO_TICKS(10)) == pdPASS) {
ESP_LOGI(TAG, "📷 Captured Frame #%d (Size: %d bytes)",
frame.frameNumber, frame.frameSize);
} else {
ESP_LOGW(TAG, "⚠️ Frame queue full! Dropping frame #%d",
frame.frameNumber);
}
vTaskDelay(pdMS_TO_TICKS(33)); // 30 FPS
}
}
/**
* Task 2: Video Encoding Simulation
* Priority: 4
*/
void encodingTask(void *pvParameter) {
Frame frame;
ESP_LOGI(TAG, "✅ Encoding Task Started");
while(1) {
if(xQueueReceive(frameQueue, &frame, portMAX_DELAY) == pdPASS) {
ESP_LOGI(TAG, "🎬 Encoding Frame #%d using H.264...",
frame.frameNumber);
vTaskDelay(pdMS_TO_TICKS(10)); // Encoding time
frame.frameSize = frame.frameSize / 2; // 50% compression
xQueueSend(encodedQueue, &frame, portMAX_DELAY);
}
}
}
/**
* Task 3: WebRTC Streaming Simulation
* Priority: 3
*/
void webrtcTask(void *pvParameter) {
Frame frame;
int packetsTransmitted = 0;
ESP_LOGI(TAG, "✅ WebRTC Streaming Task Started");
while(1) {
if(xQueueReceive(encodedQueue, &frame, portMAX_DELAY) == pdPASS) {
if(xSemaphoreTake(networkSemaphore, pdMS_TO_TICKS(100)) == pdPASS) {
int packetsInFrame = frame.frameSize / 1200; // MTU size
ESP_LOGI(TAG, "📡 Streaming Frame #%d (%d RTP packets)",
frame.frameNumber, packetsInFrame);
vTaskDelay(pdMS_TO_TICKS(5));
packetsTransmitted += packetsInFrame;
xSemaphoreGive(networkSemaphore);
if(packetsTransmitted % 100 == 0) {
ESP_LOGI(TAG, "📊 Total RTP packets sent: %d",
packetsTransmitted);
}
}
}
}
}
/**
* Task 4: WiFi Management Simulation
* Priority: 2
*/
void wifiTask(void *pvParameter) {
ESP_LOGI(TAG, "✅ WiFi Management Task Started");
while(1) {
ESP_LOGI(TAG, "📶 WiFi Status: Connected | RSSI: -45 dBm");
vTaskDelay(pdMS_TO_TICKS(5000)); // Check every 5 seconds
}
}
/**
* Task 5: Performance Monitor
* Priority: 1
*/
void monitorTask(void *pvParameter) {
ESP_LOGI(TAG, "✅ Performance Monitor Task Started");
while(1) {
uint32_t freeHeap = esp_get_free_heap_size();
ESP_LOGI(TAG, "💾 Free Heap: %lu bytes | Min Free: %lu bytes",
freeHeap, esp_get_minimum_free_heap_size());
ESP_LOGI(TAG, "⚙️ FreeRTOS Tasks Running: 6");
ESP_LOGI(TAG, "----------------------------------------");
vTaskDelay(pdMS_TO_TICKS(10000)); // Every 10 seconds
}
}
/**
* Main Application Entry Point
*/
void app_main(void)
{
printf("\n========================================\n");
printf(" FreeRTOS WebRTC Live Streaming Demo\n");
printf(" ESP32-WROVER Simulation on Wokwi\n");
printf("========================================\n\n");
// Create queues
frameQueue = xQueueCreate(10, sizeof(Frame));
encodedQueue = xQueueCreate(10, sizeof(Frame));
networkSemaphore = xSemaphoreCreateBinary();
xSemaphoreGive(networkSemaphore);
if(frameQueue == NULL || encodedQueue == NULL || networkSemaphore == NULL) {
ESP_LOGE(TAG, "❌ Failed to create queues/semaphores!");
return;
}
ESP_LOGI(TAG, "✅ Queues and Semaphores created successfully");
// Create FreeRTOS tasks with priorities
xTaskCreate(&cameraTask, "Camera", 4096, NULL, 5, NULL);
xTaskCreate(&encodingTask, "Encoder", 4096, NULL, 4, NULL);
xTaskCreate(&webrtcTask, "WebRTC", 4096, NULL, 3, NULL);
xTaskCreate(&wifiTask, "WiFi", 2048, NULL, 2, NULL);
xTaskCreate(&monitorTask, "Monitor", 2048, NULL, 1, NULL);
ESP_LOGI(TAG, "✅ All FreeRTOS tasks created successfully");
ESP_LOGI(TAG, "🚀 Starting live video streaming...");
}