Skip to content

Commit 6dafb2e

Browse files
committed
DRAFT HLSStreamESP32
1 parent 4d6f5e1 commit 6dafb2e

File tree

5 files changed

+97
-37
lines changed

5 files changed

+97
-37
lines changed

src/AudioTools/AudioLibs/HLSStream.h

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#pragma once
2-
#include "AudioToolsConfig.h"
32
#include "AudioTools/AudioCodecs/AudioEncoded.h"
43
#include "AudioTools/CoreAudio/AudioBasic/Str.h"
54
#include "AudioTools/CoreAudio/AudioHttp/URLStream.h"
65
#include "AudioTools/CoreAudio/StreamCopy.h"
6+
#include "AudioToolsConfig.h"
77

88
#define MAX_HLS_LINE 512
99
#define START_URLS_LIMIT 4
@@ -24,6 +24,7 @@ namespace audio_tools_hls {
2424
* @copyright GPLv3
2525
*/
2626

27+
template <typename URLStream>
2728
class URLLoaderHLS {
2829
public:
2930
URLLoaderHLS() = default;
@@ -81,15 +82,13 @@ class URLLoaderHLS {
8182
return url_stream.httpRequest().reply().get(CONTENT_TYPE);
8283
}
8384

84-
int contentLength() {
85-
return url_stream.contentLength();
86-
}
85+
int contentLength() { return url_stream.contentLength(); }
8786

8887
void setBufferSize(int size, int count) {
8988
buffer_size = size;
9089
buffer_count = count;
9190
// support call after begin()!
92-
if (buffer.size()!=0){
91+
if (buffer.size() != 0) {
9392
buffer.resize(buffer_size * buffer_count);
9493
}
9594
}
@@ -176,7 +175,7 @@ class URLLoaderHLS {
176175
class URLHistory {
177176
public:
178177
bool add(const char *url) {
179-
if (url==nullptr) return true;
178+
if (url == nullptr) return true;
180179
bool found = false;
181180
StrView url_str(url);
182181
for (int j = 0; j < history.size(); j++) {
@@ -206,10 +205,11 @@ class URLHistory {
206205
};
207206

208207
/**
209-
* @brief Simple Parser for HLS data.
208+
* @brief Simple Parser for HLS data.
210209
* @author Phil Schatzmann
211210
* @copyright GPLv3
212211
*/
212+
template <typename URLStream>
213213
class HLSParser {
214214
public:
215215
// loads the index url
@@ -222,6 +222,7 @@ class HLSParser {
222222
TRACEI();
223223
segments_url_str = "";
224224
bandwidth = 0;
225+
total_read = 0;
225226

226227
if (!parseIndex()) {
227228
TRACEE();
@@ -262,14 +263,13 @@ class HLSParser {
262263
reloadSegments();
263264

264265
if (active) result = url_loader.readBytes(data, len);
266+
total_read += result;
265267
return result;
266268
}
267269

268270
const char *indexUrl() { return index_url_str; }
269271

270-
const char *segmentsUrl() {
271-
return segments_url_str.c_str();
272-
}
272+
const char *segmentsUrl() { return segments_url_str.c_str(); }
273273

274274
/// Provides the codec
275275
const char *getCodec() { return codec.c_str(); }
@@ -310,20 +310,26 @@ class HLSParser {
310310
const char *reqURL)) {
311311
resolve_url = cb;
312312
}
313+
/// Provides the hls url as string
314+
const char *urlStr() { return url_str.c_str(); }
313315

314-
protected:
316+
/// Povides the number of bytes read
317+
size_t totalRead() { return total_read; };
318+
319+
protected:
315320
enum class URLType { Undefined, Index, Segment };
316321
URLType next_url_type = URLType::Undefined;
317322
int bandwidth = 0;
318323
int url_count = 5;
324+
size_t total_read = 0;
319325
bool url_active = false;
320326
bool is_extm3u = false;
321327
Str codec;
322328
Str segments_url_str;
323329
Str url_str;
324330
const char *index_url_str = nullptr;
325331
URLStream url_stream;
326-
URLLoaderHLS url_loader;
332+
URLLoaderHLS<URLStream> url_loader;
327333
URLHistory url_history;
328334
bool active = false;
329335
bool parse_segments_active = false;
@@ -531,7 +537,8 @@ class HLSParser {
531537
memset(tmp, 0, MAX_HLS_LINE);
532538
while (true) {
533539
memset(tmp, 0, MAX_HLS_LINE);
534-
size_t len = url_stream.httpRequest().readBytesUntil('\n', tmp, MAX_HLS_LINE);
540+
size_t len =
541+
url_stream.httpRequest().readBytesUntil('\n', tmp, MAX_HLS_LINE);
535542
if (len == 0 && url_stream.available() == 0) break;
536543
StrView str(tmp);
537544

@@ -633,13 +640,14 @@ namespace audio_tools {
633640
* @ingroup http *@copyright GPLv3
634641
*/
635642

636-
class HLSStream : public AbstractURLStream {
643+
template <typename URLStream>
644+
class HLSStreamT : public AbstractURLStream {
637645
public:
638646
/// Empty constructor
639-
HLSStream() = default;
647+
HLSStreamT() = default;
640648

641649
/// Convenience constructor which logs in to the WiFi
642-
HLSStream(const char *ssid, const char *password) {
650+
HLSStreamT(const char *ssid, const char *password) {
643651
setSSID(ssid);
644652
setPassword(password);
645653
}
@@ -719,8 +727,16 @@ class HLSStream : public AbstractURLStream {
719727
parser.setURLResolver(cb);
720728
}
721729

730+
const char *urlStr() override { return parser.urlStr(); }
731+
732+
size_t totalRead() override { return parser.totalRead(); };
733+
/// not implemented
734+
void setConnectionClose(bool flag) override {};
735+
/// not implemented
736+
bool waitForData(int timeout) override { return false; }
737+
722738
protected:
723-
audio_tools_hls::HLSParser parser;
739+
audio_tools_hls::HLSParser<URLStream> parser;
724740
const char *ssid = nullptr;
725741
const char *password = nullptr;
726742

@@ -759,4 +775,6 @@ class HLSStream : public AbstractURLStream {
759775
void addRequestHeader(const char *header, const char *value) {}
760776
};
761777

778+
using HLSStream = HLSStreamT<URLStream>;
779+
762780
} // namespace audio_tools
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
#include "AudioTools/CoreAudio/AudioHttp/URLStreamESP32.h"
3+
#include "HLSStream.h"
4+
5+
namespace audio_tools {
6+
7+
using HLSStreamESP32 = HLSStreamT<URLStreamESP32>;
8+
9+
} // namespace audio_tools

src/AudioTools/CoreAudio/AudioHttp/AbstractURLStream.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,26 @@ class AbstractURLStream : public AudioStream {
5252

5353
/// provides access to the HttpRequest
5454
virtual HttpRequest& httpRequest() = 0;
55+
5556
/// (Re-)defines the client
5657
virtual void setClient(Client& clientPar) = 0;
5758

59+
/// Add Connection: close to request header
60+
virtual void setConnectionClose(bool flag) = 0;
61+
62+
/// Provides the url as string
63+
virtual const char* urlStr() = 0;
64+
65+
/// Total amout of data that was consumed so far
66+
virtual size_t totalRead() = 0;
67+
68+
/// Provides the reported data size from the http reply
69+
virtual int contentLength() = 0;
70+
71+
/// Waits the indicated time for the data to be available
72+
/// waits for some data - returns false if the request has failed
73+
virtual bool waitForData(int timeout) = 0;
74+
5875
};
5976

6077

src/AudioTools/CoreAudio/AudioHttp/URLStream.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -230,12 +230,11 @@ class URLStream : public AbstractURLStream {
230230

231231
void setWaitForData(bool flag) { wait_for_data = flag; }
232232

233-
int contentLength() { return size; }
234-
235-
size_t totalRead() { return total_read; }
233+
int contentLength() override { return size; }
236234

235+
size_t totalRead() override { return total_read; }
237236
/// waits for some data - returns false if the request has failed
238-
virtual bool waitForData(int timeout) {
237+
bool waitForData (int timeout) override{
239238
TRACED();
240239
uint32_t end = millis() + timeout;
241240
if (request.available() == 0) {
@@ -254,10 +253,11 @@ class URLStream : public AbstractURLStream {
254253
return request.available() > 0;
255254
}
256255

257-
const char* urlStr() { return url_str.c_str(); }
256+
257+
const char* urlStr() override { return url_str.c_str(); }
258258

259259
/// Define the Root PEM Certificate for SSL
260-
void setCACert(const char* cert){
260+
void setCACert(const char* cert) override{
261261
#ifdef USE_WIFI_CLIENT_SECURE
262262
if (clientSecure!=nullptr) clientSecure->setCACert(cert);
263263
#endif

src/AudioTools/CoreAudio/AudioHttp/URLStreamESP32.h

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include "AudioTools/CoreAudio/AudioHttp/HttpRequest.h"
55
#include "AudioTools/CoreAudio/AudioHttp/ICYStreamT.h"
66
#include "AudioTools/CoreAudio/AudioHttp/URLStreamBufferedT.h"
7-
87
#include "esp_http_client.h"
98
#include "esp_idf_version.h"
109
#include "esp_system.h"
@@ -175,6 +174,9 @@ class URLStreamESP32 : public AbstractURLStream {
175174
MethodID action = GET, const char* reqMime = "",
176175
const char* reqData = "") {
177176
TRACED();
177+
total_read = 0;
178+
url_str = urlStr;
179+
content_length = 0;
178180
// start wifi if necessary and possible
179181
if (ssid != nullptr) {
180182
if (!IDF_WIFI.begin(ssid, password)) {
@@ -263,7 +265,7 @@ class URLStreamESP32 : public AbstractURLStream {
263265
}
264266

265267
// Determine the result
266-
int content_length = esp_http_client_fetch_headers(client_handle);
268+
content_length = esp_http_client_fetch_headers(client_handle);
267269
int status_code = esp_http_client_get_status_code(client_handle);
268270
LOGI("status_code: %d / content_length: %d", status_code, content_length);
269271

@@ -302,7 +304,9 @@ class URLStreamESP32 : public AbstractURLStream {
302304

303305
size_t readBytes(uint8_t* data, size_t len) override {
304306
TRACED();
305-
return esp_http_client_read(client_handle, (char*)data, len);
307+
size_t read = esp_http_client_read(client_handle, (char*)data, len);
308+
total_read += read;
309+
return read;
306310
}
307311

308312
/// Adds/Updates a request header
@@ -324,21 +328,31 @@ class URLStreamESP32 : public AbstractURLStream {
324328

325329
/// Attach and enable use of a bundle for certificate verification e.g.
326330
/// esp_crt_bundle_attach or arduino_esp_crt_bundle_attach
327-
void setCACert(esp_err_t (*cb)(void *conf)){
328-
crt_bundle_attach = cb;
329-
}
331+
void setCACert(esp_err_t (*cb)(void* conf)) { crt_bundle_attach = cb; }
330332

331333
/// Defines the read buffer size
332-
void setReadBufferSize(int size) {
333-
buffer_size = size; }
334+
void setReadBufferSize(int size) { buffer_size = size; }
334335

335336
/// Used for request and reply header parameters
336-
HttpRequest& httpRequest() override {
337-
return request; }
337+
HttpRequest& httpRequest() override { return request; }
338338

339339
/// Does nothing
340340
void setClient(Client& client) override {}
341341

342+
/// Provides the url as string
343+
const char* urlStr() override { return (char*)url_str; }
344+
345+
/// Total amout of data that was consumed so far
346+
size_t totalRead() override { return total_read; }
347+
348+
/// Provides the reported data size from the http reply
349+
int contentLength() override { return content_length; }
350+
351+
/// Not used
352+
virtual bool waitForData(int timeout) override{ return false; }
353+
/// Not used
354+
void setConnectionClose(bool flag) override {}
355+
342356
protected:
343357
int id = 0;
344358
HttpRequest request;
@@ -349,11 +363,13 @@ class URLStreamESP32 : public AbstractURLStream {
349363
int buffer_size = DEFAULT_BUFFER_SIZE;
350364
const uint8_t* pem_cert = nullptr;
351365
int pem_cert_len = 0;
352-
esp_err_t (*crt_bundle_attach)(void *conf) = nullptr;
353-
366+
esp_err_t (*crt_bundle_attach)(void* conf) = nullptr;
367+
size_t total_read = 0;
368+
const char* url_str = nullptr;
369+
int content_length = 0;
354370

355-
/// Define the Root PEM Certificate for SSL: the last byte must be null, the
356-
/// len is including the ending null
371+
/// Define the Root PEM Certificate for SSL: the last byte must be null,
372+
/// the len is including the ending null
357373
void setCACert(const uint8_t* cert, int len) {
358374
pem_cert_len = len;
359375
pem_cert = cert;

0 commit comments

Comments
 (0)