Skip to content

Commit b2b5312

Browse files
authored
split processWebStream/processWebFile
processWebstream is completely new and faster, better InBuff filling processWebFile is still the old routine
1 parent b3c87ef commit b2b5312

File tree

2 files changed

+124
-31
lines changed

2 files changed

+124
-31
lines changed

src/Audio.cpp

Lines changed: 120 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
*
44
* Created on: Oct 26.2018
55
*
6-
* Version 2.0.5g
7-
* Updated on: Aug 12.2022
6+
* Version 2.0.5h
7+
* Updated on: Aug 17.2022
88
* Author: Wolle (schreibfaul1)
99
*
1010
*/
@@ -316,7 +316,7 @@ void Audio::setDefaults() {
316316
m_f_firstmetabyte = false;
317317
m_f_playing = false;
318318
m_f_ssl = false;
319-
m_f_swm = true; // Assume no metaint (stream without metadata)
319+
m_f_metadata = false;
320320
m_f_tts = false;
321321
m_f_firstCall = true; // InitSequence for processWebstream and processLokalFile
322322
m_f_running = false;
@@ -2389,7 +2389,8 @@ void Audio::loop() {
23892389
if(m_playlistFormat == FORMAT_ASX) connecttohost(parsePlaylist_ASX());
23902390
break;
23912391
case AUDIO_DATA:
2392-
processWebStream();
2392+
if(m_streamType == ST_WEBSTREAM) processWebStream();
2393+
if(m_streamType == ST_WEBFILE) processWebFile();
23932394
break;
23942395
}
23952396
}
@@ -2444,12 +2445,20 @@ void Audio::loop() {
24442445
}
24452446
}
24462447
//---------------------------------------------------------------------------------------------------------------------
2447-
size_t Audio::chunkedDataTransfer(){
2448+
size_t Audio::chunkedDataTransfer(uint8_t* bytes){
24482449
size_t chunksize = 0;
24492450
int b = 0;
2451+
uint32_t ctime = millis();
2452+
uint32_t timeout = 2000; // ms
24502453
while(true){
2454+
if(ctime + timeout < millis()) {
2455+
log_e("timeout");
2456+
stopSong();
2457+
return 0;
2458+
}
24512459
b = _client->read();
2452-
if(b < 0) break;
2460+
*bytes++;
2461+
if(b < 0) continue; // -1 no data available
24532462
if(b == '\n') break;
24542463
if(b < '0') continue;
24552464
// We have received a hexadecimal character. Decode it and add to the result.
@@ -2466,8 +2475,8 @@ bool Audio::readPlayListData() {
24662475
if(getDatamode() != AUDIO_PLAYLISTINIT) return false;
24672476
if(_client->available() == 0) return false;
24682477

2469-
uint32_t chunksize = 0;
2470-
if(m_f_chunked) chunksize = chunkedDataTransfer();
2478+
uint32_t chunksize = 0; uint8_t readedBytes = 0;
2479+
if(m_f_chunked) chunksize = chunkedDataTransfer(&readedBytes);
24712480

24722481
// reads the content of the playlist and stores it in the vector m_contentlength
24732482
// m_contentlength is a table of pointers to the lines
@@ -2956,9 +2965,90 @@ void Audio::processLocalFile() {
29562965
if(afn) {free(afn); afn = NULL;}
29572966
}
29582967
}
2959-
//---------------------------------------------------------------------------------------------------------------------
2968+
//----------------------------------------------------------------------------------------------------------------------
29602969
void Audio::processWebStream() {
29612970

2971+
const uint16_t maxFrameSize = InBuff.getMaxBlockSize(); // every mp3/aac frame is not bigger
2972+
static bool f_tmr_1s;
2973+
static bool f_stream; // first audio data received
2974+
static uint8_t cnt_slow;
2975+
static uint32_t chunkSize; // chunkcount read from stream
2976+
static uint32_t tmr_1s; // timer 1 sec
2977+
static uint32_t loopCnt; // count loops if clientbuffer is empty
2978+
2979+
// first call, set some values to default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2980+
if(m_f_firstCall) { // runs only ont time per connection, prepare for start
2981+
m_f_firstCall = false;
2982+
f_stream = false;
2983+
cnt_slow = 0;
2984+
chunkSize = 0;
2985+
loopCnt = 0;
2986+
tmr_1s = millis();
2987+
m_metacount = m_metaint;
2988+
readMetadata(0, true); // reset all static vars
2989+
}
2990+
2991+
if(getDatamode() != AUDIO_DATA) return; // guard
2992+
uint32_t availableBytes = _client->available(); // available from stream
2993+
// chunked data tramsfer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2994+
if(m_f_chunked){
2995+
uint8_t readedBytes = 0;
2996+
if(!chunkSize) chunkSize = chunkedDataTransfer(&readedBytes);
2997+
availableBytes = min(availableBytes, chunkSize);
2998+
}
2999+
// we have metadata - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3000+
if(m_f_metadata){
3001+
if(availableBytes) if(m_metacount == 0) {chunkSize -= readMetadata(availableBytes); return;}
3002+
availableBytes = min(availableBytes, m_metacount);
3003+
}
3004+
// timer, triggers every second - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3005+
if((tmr_1s + 1000) < millis()) {
3006+
f_tmr_1s = true; // flag will be set every second for one loop only
3007+
tmr_1s = millis();
3008+
}
3009+
// if the buffer is often almost empty issue a warning - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3010+
if(InBuff.bufferFilled() > maxFrameSize) {f_tmr_1s = false; cnt_slow = 0; loopCnt = 0;}
3011+
if(f_tmr_1s){
3012+
cnt_slow ++;
3013+
if(cnt_slow > 25){cnt_slow = 0; AUDIO_INFO("slow stream, dropouts are possible");}
3014+
}
3015+
// if the buffer can't filled for several seconds try a new connection - - - - - - - - - - - - - - - - - - - - - - -
3016+
if(f_stream && !availableBytes){
3017+
loopCnt++;
3018+
if(loopCnt > 200000) { // wait several seconds
3019+
AUDIO_INFO("Stream lost -> try new connection");
3020+
connecttohost(m_lastHost);
3021+
return;
3022+
}
3023+
}
3024+
// buffer fill routine - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3025+
if(availableBytes) {
3026+
availableBytes = min(availableBytes, InBuff.writeSpace());
3027+
int16_t bytesAddedToBuffer = _client->read(InBuff.getWritePtr(), availableBytes);
3028+
3029+
if(bytesAddedToBuffer > 0) {
3030+
if(m_f_metadata) m_metacount -= bytesAddedToBuffer;
3031+
if(m_f_chunked) chunkSize -= bytesAddedToBuffer;
3032+
InBuff.bytesWritten(bytesAddedToBuffer);
3033+
}
3034+
3035+
if(InBuff.bufferFilled() > maxFrameSize && !f_stream) { // waiting for buffer filled
3036+
f_stream = true; // ready to play the audio data
3037+
AUDIO_INFO("stream ready");
3038+
}
3039+
if(!f_stream) return;
3040+
}
3041+
3042+
// play audio data - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3043+
if(f_stream){
3044+
static uint8_t cnt = 0;
3045+
cnt++;
3046+
if(cnt == 3){playAudioData(); cnt = 0;}
3047+
}
3048+
}
3049+
//---------------------------------------------------------------------------------------------------------------------
3050+
void Audio::processWebFile() {
3051+
29623052
const uint16_t maxFrameSize = InBuff.getMaxBlockSize(); // every mp3/aac frame is not bigger
29633053
uint32_t availableBytes; // available bytes in stream
29643054
static bool f_tmr_1s;
@@ -3044,15 +3134,15 @@ void Audio::processWebStream() {
30443134
}
30453135

30463136
// if we have metadata: get them - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3047-
if(!m_metacount && !m_f_swm){
3048-
int bytes = 0;
3049-
int res = 0;
3050-
if(m_f_chunked) bytes = min(m_chunkcount, availableBytes);
3051-
else bytes = availableBytes;
3052-
res = readMetadata(bytes);
3053-
if(m_f_chunked) m_chunkcount -= res;
3054-
if(!m_metacount) return;
3055-
}
3137+
// if(!m_metacount && !m_f_swm){
3138+
// int bytes = 0;
3139+
// int res = 0;
3140+
// if(m_f_chunked) bytes = min(m_chunkcount, availableBytes);
3141+
// else bytes = availableBytes;
3142+
// res = readMetadata(bytes);
3143+
// if(m_f_chunked) m_chunkcount -= res;
3144+
// if(!m_metacount) return;
3145+
// }
30563146

30573147
// if the buffer is often almost empty issue a warning - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
30583148
if(InBuff.bufferFilled() < maxFrameSize && f_stream && !f_webFileDataComplete){
@@ -3080,7 +3170,7 @@ void Audio::processWebStream() {
30803170
// buffer fill routine - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
30813171
if(true) { // statement has no effect
30823172
uint32_t bytesCanBeWritten = InBuff.writeSpace();
3083-
if(!m_f_swm) bytesCanBeWritten = min(m_metacount, bytesCanBeWritten);
3173+
// if(!m_f_swm) bytesCanBeWritten = min(m_metacount, bytesCanBeWritten);
30843174
if(m_f_chunked) bytesCanBeWritten = min(m_chunkcount, bytesCanBeWritten);
30853175

30863176
int16_t bytesAddedToBuffer = 0;
@@ -3109,7 +3199,7 @@ void Audio::processWebStream() {
31093199

31103200
if(bytesAddedToBuffer > 0) {
31113201
if(m_streamType == ST_WEBFILE) byteCounter += bytesAddedToBuffer; // Pull request #42
3112-
if(!m_f_swm) m_metacount -= bytesAddedToBuffer;
3202+
// if(!m_f_swm) m_metacount -= bytesAddedToBuffer;
31133203
if(m_f_chunked) m_chunkcount -= bytesAddedToBuffer;
31143204
InBuff.bytesWritten(bytesAddedToBuffer);
31153205
}
@@ -3279,7 +3369,8 @@ void Audio::processWebStreamTS() {
32793369

32803370
availableBytes = _client->available();
32813371
if(availableBytes){
3282-
if(m_f_chunked) chunkSize = chunkedDataTransfer();
3372+
uint8_t readedBytes = 0;
3373+
if(m_f_chunked) chunkSize = chunkedDataTransfer(&readedBytes);
32833374
int res = _client->read(ts_packet + ts_packetPtr, ts_packetsize - ts_packetPtr);
32843375
if(res > 0){
32853376
ts_packetPtr += res;
@@ -3401,7 +3492,8 @@ void Audio::processWebStreamHLS() {
34013492

34023493
availableBytes = _client->available();
34033494
if(availableBytes){
3404-
if(m_f_chunked) chunkSize = chunkedDataTransfer();
3495+
uint8_t readedBytes = 0;
3496+
if(m_f_chunked) chunkSize = chunkedDataTransfer(&readedBytes);
34053497
size_t bytesWasWritten = 0;
34063498
if(InBuff.writeSpace() >= availableBytes){
34073499
bytesWasWritten = _client->read(InBuff.getWritePtr(), availableBytes);
@@ -3623,7 +3715,7 @@ bool Audio::parseHttpResponseHeader() { // this is the response to a GET / reque
36233715
const char* c_metaint = (rhl + 12);
36243716
int32_t i_metaint = atoi(c_metaint);
36253717
m_metaint = i_metaint;
3626-
if(m_metaint) m_f_swm = false ; // Multimediastream
3718+
if(m_metaint) m_f_metadata = true; // Multimediastream
36273719
}
36283720

36293721
else if(startsWith(rhl, "icy-name:")) {
@@ -3768,20 +3860,18 @@ uint16_t Audio::readMetadata(uint16_t maxBytes, bool first) {
37683860
metalen = b * 16 ; // New count for metadata including length byte
37693861
if(metalen > 512){
37703862
AUDIO_INFO("Metadata block to long! Skipping all Metadata from now on.");
3771-
m_f_swm = true; // expect stream without metadata
3863+
m_f_metadata = false; // expect stream without metadata
3864+
return 1;
37723865
}
37733866
pos_ml = 0; chbuf[pos_ml] = 0; // Prepare for new line
37743867
res = 1;
37753868
}
3776-
if(!metalen) {m_metacount = m_metaint; return res;}
3777-
3869+
if(!metalen) {m_metacount = m_metaint; return res;} // metalen is 0
37783870
uint16_t a = _client->readBytes(&chbuf[pos_ml], min((uint16_t)(metalen - pos_ml), (uint16_t)(maxBytes -1)));
37793871
res += a;
37803872
pos_ml += a;
37813873
if(pos_ml == metalen) {
3782-
metalen = 0;
37833874
chbuf[pos_ml] = '\0';
3784-
m_metacount = m_metaint;
37853875
if(strlen(chbuf)) { // Any info present?
37863876
// metaline contains artist and song name. For example:
37873877
// "StreamTitle='Don McLean - American Pie';StreamUrl='';"
@@ -3796,6 +3886,8 @@ uint16_t Audio::readMetadata(uint16_t maxBytes, bool first) {
37963886
}
37973887
showstreamtitle(chbuf); // Show artist and title if present in metadata
37983888
}
3889+
m_metacount = m_metaint;
3890+
metalen = 0;
37993891
pos_ml = 0;
38003892
}
38013893
return res;

src/Audio.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Audio.h
33
*
44
* Created on: Oct 28,2018
5-
* Updated on: Aug 12,2022
5+
* Updated on: Aug 17,2022
66
* Author: Wolle (schreibfaul1)
77
*/
88

@@ -218,10 +218,11 @@ class Audio : private AudioBuffer{
218218
bool httpPrint(const char* host);
219219
void processLocalFile();
220220
void processWebStream();
221+
void processWebFile();
221222
void processWebStreamTS();
222223
void processWebStreamHLS();
223224
void playAudioData();
224-
size_t chunkedDataTransfer();
225+
size_t chunkedDataTransfer(uint8_t* bytes);
225226
bool readPlayListData();
226227
const char* parsePlaylist_M3U();
227228
const char* parsePlaylist_PLS();
@@ -509,7 +510,7 @@ class Audio : private AudioBuffer{
509510
uint32_t m_PlayingStartTime = 0; // Stores the milliseconds after the start of the audio
510511
uint32_t m_resumeFilePos = 0; // the return value from stopSong() can be entered here
511512
uint16_t m_m3u8_targetDuration = 10; //
512-
bool m_f_swm = true; // Stream without metadata
513+
bool m_f_metadata = false; // assume stream without metadata
513514
bool m_f_unsync = false; // set within ID3 tag but not used
514515
bool m_f_exthdr = false; // ID3 extended header
515516
bool m_f_ssl = false;

0 commit comments

Comments
 (0)