arduino-audio-tools
Loading...
Searching...
No Matches
RTSPMediaSourceMTS.h
Go to the documentation of this file.
1#pragma once
2
4#include "IMediaSource.h"
5#include "RTSPFormat.h"
6
7namespace audio_tools {
8
47class RTSPMediaSourceMTS : public IMediaSource, public Print {
48 public:
49 static constexpr int kPacketSize = 188;
50 static constexpr int kPacketsPerFragment = 7;
51
54 RTSPMediaSourceMTS(int bufferPackets = 128, float sendRate = 100)
55 : buffer(bufferPackets * kPacketSize) {
56 capacity = buffer.availableForWrite();
57 format.setFramerate(sendRate);
58 format.setFragmentSize(kPacketsPerFragment * kPacketSize);
59 }
60
61 RTSPFormat &getFormat() override { return format; }
62
66 void start() override {
67 uint8_t tmp[kPacketSize];
68 while (buffer.readArray(tmp, kPacketSize) > 0) {
69 }
70 is_active = true;
71 }
72
74 void stop() override { is_active = false; }
75
76 size_t write(uint8_t c) override { return write(&c, 1); }
77
79 size_t write(const uint8_t *data, size_t len) override {
80 size_t pos = 0;
81 while (pos < len) {
82 size_t n = kPacketSize - packet_len;
83 if (n > len - pos) n = len - pos;
84 memcpy(packet + packet_len, data + pos, n);
85 packet_len += n;
86 pos += n;
87 if (packet_len == kPacketSize) {
88 addPacket();
89 packet_len = 0;
90 }
91 }
92 return len;
93 }
94
96 int packetSize() override {
97 int packets = buffer.available() / kPacketSize;
98 if (packets > kPacketsPerFragment) packets = kPacketsPerFragment;
99 return packets * kPacketSize;
100 }
101
103 int readBytes(void *dest, int maxBytes) override {
104 int len = buffer.available() < maxBytes ? buffer.available() : maxBytes;
105 len = len / kPacketSize * kPacketSize;
106 return buffer.readArray((uint8_t *)dest, len);
107 }
108
110 uint32_t droppedPackets() { return dropped; }
111
113 uint32_t droppedVideoPackets() { return dropped_video; }
114
115 protected:
119 size_t packet_len = 0;
120 volatile bool is_active = false;
121 int capacity = 0;
122 uint32_t dropped = 0;
123 uint32_t dropped_video = 0;
124 int video_pid = -1; // learned from the PES stream ids
125 bool dropping_video = false;
126
127 void addPacket() {
128 if (!is_active) return; // no client is streaming
129 int pid = ((packet[1] & 0x1F) << 8) | packet[2];
130 bool pusi = packet[1] & 0x40;
131 if (pusi && isVideoPes()) video_pid = pid;
132 bool is_video = pid == video_pid;
133 int free = buffer.availableForWrite();
134
135 // too slow: drop video from the start of the next frame on, until the
136 // buffer has recovered and the next keyframe (preceded by the PAT)
137 if (dropping_video) {
138 if (pid == 0 && free >= capacity / 2) {
139 dropping_video = false;
140 LOGI("RTSPMediaSourceMTS: resuming video at the next keyframe");
141 }
142 } else if (is_video && pusi && free < capacity / 4) {
143 dropping_video = true;
144 LOGW("RTSPMediaSourceMTS: network too slow - dropping video");
145 }
146 if (dropping_video && is_video) {
148 return;
149 }
150
151 // only whole packets: the free space can only grow while we write
152 if (free < kPacketSize) {
153 if (dropped++ % 100 == 0) {
154 LOGW("RTSPMediaSourceMTS: buffer full, %u packets dropped",
155 (unsigned)dropped);
156 }
157 return;
158 }
159 buffer.writeArray(packet, kPacketSize);
160 }
161
164 bool isVideoPes() {
165 int afc = (packet[3] >> 4) & 3;
166 if (!(afc & 1)) return false; // no payload
167 int pos = (afc & 2) ? 5 + packet[4] : 4;
168 if (pos + 4 > kPacketSize) return false;
169 return packet[pos] == 0 && packet[pos + 1] == 0 && packet[pos + 2] == 1 &&
170 (packet[pos + 3] & 0xF0) == 0xE0;
171 }
172};
173
174} // namespace audio_tools
#define LOGW(...)
#define LOGI(...)
Media Source Interface - Contract for Media Data Providers.
Definition IMediaSource.h:19
Definition CodecOpusOgg.h:57
Audio Format Definition - Base class for RTSP audio formats.
Definition RTSPFormat.h:57
MPEG-2 Transport Stream (MP2T) format for RTSP streaming of a pre-muxed audio+video container,...
Definition RTSPFormat.h:1013
uint32_t droppedVideoPackets()
Number of video TS packets dropped to keep the audio going.
Definition RTSPMediaSourceMTS.h:113
RTSPFormat & getFormat() override
Get the media format configuration.
Definition RTSPMediaSourceMTS.h:61
uint32_t dropped_video
Definition RTSPMediaSourceMTS.h:123
size_t write(uint8_t c) override
Definition RTSPMediaSourceMTS.h:76
static constexpr int kPacketsPerFragment
Definition RTSPMediaSourceMTS.h:50
static constexpr int kPacketSize
Definition RTSPMediaSourceMTS.h:49
uint32_t droppedPackets()
Number of TS packets dropped because the buffer was full.
Definition RTSPMediaSourceMTS.h:110
uint32_t dropped
Definition RTSPMediaSourceMTS.h:122
RTSPFormatMTS format
Definition RTSPMediaSourceMTS.h:116
bool dropping_video
Definition RTSPMediaSourceMTS.h:125
uint8_t packet[kPacketSize]
Definition RTSPMediaSourceMTS.h:118
void start() override
Definition RTSPMediaSourceMTS.h:66
bool isVideoPes()
Definition RTSPMediaSourceMTS.h:164
int packetSize() override
Size of the next RTP payload: up to kPacketsPerFragment TS packets.
Definition RTSPMediaSourceMTS.h:96
void addPacket()
Definition RTSPMediaSourceMTS.h:127
size_t write(const uint8_t *data, size_t len) override
Accepts the transport stream, in any chunk sizes.
Definition RTSPMediaSourceMTS.h:79
RingBufferSPSC< uint8_t > buffer
Definition RTSPMediaSourceMTS.h:117
volatile bool is_active
Definition RTSPMediaSourceMTS.h:120
void stop() override
Called when the client stops streaming.
Definition RTSPMediaSourceMTS.h:74
RTSPMediaSourceMTS(int bufferPackets=128, float sendRate=100)
Definition RTSPMediaSourceMTS.h:54
int readBytes(void *dest, int maxBytes) override
Provides whole TS packets only.
Definition RTSPMediaSourceMTS.h:103
int capacity
Definition RTSPMediaSourceMTS.h:121
size_t packet_len
Definition RTSPMediaSourceMTS.h:119
int video_pid
Definition RTSPMediaSourceMTS.h:124
Lock-free Single-Producer Single-Consumer ring buffer.
Definition RingBufferSPSC.h:52
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6