arduino-audio-tools
Loading...
Searching...
No Matches
RTSPAudioStreamerUsingTask.h
1/*
2 * Author: Phil Schatzmann
3 *
4 * Based on Micro-RTSP library:
5 * https://github.com/geeksville/Micro-RTSP
6 * https://github.com/Tomp0801/Micro-RTSP-Audio
7 */
8#pragma once
9#include "RTSPAudioStreamer.h"
10
11namespace audio_tools {
12
37template <typename Platform>
39 public:
40 RTSPAudioStreamerUsingTask(bool throttled = true)
42 LOGD("Creating RTSP Audio streamer with task");
43 m_taskRunning = false;
44 m_throttled = throttled;
45 }
46
47 RTSPAudioStreamerUsingTask(IAudioSource &source, bool throttled = true)
48 : RTSPAudioStreamerUsingTask(throttled) {
49 this->setAudioSource(&source);
50 }
51
52 virtual ~RTSPAudioStreamerUsingTask() { stop(); }
53
54 void setTaskParameters(uint32_t stackSize, uint8_t priority, int core = -1) {
55 if (!m_taskRunning) {
56 m_taskStackSize = stackSize;
57 m_taskPriority = priority;
58 m_taskCore = core;
59 LOGI("Task parameters set: stack=%d bytes, priority=%d, core=%d",
60 stackSize, priority, core);
61 } else {
62 LOGW("Cannot change task parameters while streaming is active");
63 }
64 }
65
66 void start() override {
67 LOGI("Starting RTP Stream with task");
69 if (this->m_audioSource != nullptr && !m_taskRunning) {
70 m_taskRunning = true;
71 if (!m_streamingTask.create("RTSPStreaming", m_taskStackSize,
72 m_taskPriority, m_taskCore)) {
73 LOGE("Failed to create streaming task");
74 m_taskRunning = false;
75 return;
76 }
77 m_streamingTask.setReference(this);
78 m_send_counter = 0;
79 m_last_throttle_us = micros();
80 if (m_streamingTask.begin([this]() { this->streamingTaskLoop(); })) {
81 LOGI("Streaming task started successfully");
82 LOGI("Task: stack=%d bytes, priority=%d, core=%d, period=%d us",
83 m_taskStackSize, m_taskPriority, m_taskCore,
84 this->m_timer_period_us);
85#ifdef ESP32
86 LOGI("Free heap size: %i KB", esp_get_free_heap_size() / 1000);
87#endif
88 } else {
89 LOGE("Failed to start streaming task");
90 m_taskRunning = false;
91 }
92 }
93 }
94
95 void stop() override {
96 LOGI("Stopping RTP Stream with task");
97 if (m_taskRunning) {
98 m_taskRunning = false;
99 m_streamingTask.end();
100 delay(50);
101 }
103 LOGI("RTP Stream with task stopped - ready for restart");
104 }
105
106 bool isTaskRunning() const { return m_taskRunning; }
107 void setThrottled(bool isThrottled) { m_throttled = isThrottled; }
108 void setFixedDelayMs(uint32_t delayUs) { this->m_fixed_delay_ms = delayUs; m_throttled = false; }
109 void setThrottleInterval(uint32_t interval) { m_throttle_interval = interval; }
110
111 protected:
112 audio_tools::Task m_streamingTask;
113 volatile bool m_taskRunning;
114 uint32_t m_taskStackSize = 8192;
115 uint8_t m_taskPriority = 5;
116 int m_taskCore = -1;
117 bool m_throttled = true;
118 uint16_t m_fixed_delay_ms = 1;
119 uint32_t m_throttle_interval = 50;
120 uint32_t m_send_counter = 0;
121 unsigned long m_last_throttle_us = 0;
122
123 void streamingTaskLoop() {
124 LOGD("Streaming task loop iteration");
125 auto iterationStartUs = micros();
127 applyThrottling(iterationStartUs);
128 }
129
130 inline void applyThrottling(unsigned long iterationStartUs) {
131 ++m_send_counter;
132 delay(m_fixed_delay_ms);
133 if (m_throttled && m_throttle_interval > 0) {
134 if (this->checkTimerPeriodChange()) {
135 LOGI("Timer period updated; resetting throttle window to %u us",
136 (unsigned)this->m_timer_period_us);
137 m_send_counter = 0;
138 m_last_throttle_us = iterationStartUs;
139 return;
140 }
141 if (m_send_counter >= m_throttle_interval) {
142 uint64_t expectedUs = (uint64_t)m_throttle_interval * (uint64_t)this->getTimerPeriodUs();
143 unsigned long nowUs = micros();
144 uint64_t actualUs = (uint64_t)(nowUs - m_last_throttle_us);
145 if (actualUs < expectedUs) {
146 uint32_t remainingUs = (uint32_t)(expectedUs - actualUs);
147 if (remainingUs >= 1000) delay(remainingUs / 1000);
148 uint32_t remUs = remainingUs % 1000;
149 if (remUs > 0) delayMicroseconds(remUs);
150 }
151 m_send_counter = 0;
152 m_last_throttle_us = micros();
153 }
154 }
155 }
156};
157
158} // namespace audio_tools
Audio Source Interface - Contract for Audio Data Providers.
Definition IAudioSource.h:19
RTSPAudioStreamerBase - Core RTP Audio Streaming Engine.
Definition RTSPAudioStreamer.h:50
virtual void start()
Start audio source (base implementation)
Definition RTSPAudioStreamer.h:344
virtual void setAudioSource(IAudioSource *source)
Configure the audio source for streaming.
Definition RTSPAudioStreamer.h:130
static void timerCallback(void *audioStreamerObj)
Static timer callback function for periodic RTP streaming.
Definition RTSPAudioStreamer.h:477
uint32_t getTimerPeriodUs() const
Get the timer period in microseconds.
Definition RTSPAudioStreamer.h:408
virtual void stop()
Stop audio source (base implementation)
Definition RTSPAudioStreamer.h:372
bool checkTimerPeriodChange()
Check if timer period has changed and update if necessary.
Definition RTSPAudioStreamer.h:445
RTSPAudioStreamerUsingTask - Task-driven RTP Audio Streaming Engine.
Definition RTSPAudioStreamerUsingTask.h:38
void start() override
Start audio source (base implementation)
Definition RTSPAudioStreamerUsingTask.h:66
void stop() override
Stop audio source (base implementation)
Definition RTSPAudioStreamerUsingTask.h:95
FreeRTOS task.
Definition Task.h:21
bool create(const char *name, int stackSize, int priority=1, int core=-1)
If you used the empty constructor, you need to call create!
Definition Task.h:32
void end()
suspends the task
Definition Task.h:65
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10