Unverified Commit 70c0a15c authored by Wolle's avatar Wolle Committed by GitHub

Format .m3u8 not working #601

parent 301935fa
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
* *
* Created on: Oct 26.2018 * Created on: Oct 26.2018
* *
* Version 3.0.7f * Version 3.0.7h
* Updated on: Oct 14.2023 * Updated on: Oct 16.2023
* Author: Wolle (schreibfaul1) * Author: Wolle (schreibfaul1)
* *
*/ */
...@@ -313,8 +313,6 @@ void Audio::setDefaults() { ...@@ -313,8 +313,6 @@ void Audio::setDefaults() {
} // free if stream is not m3u8 } // free if stream is not m3u8
vector_clear_and_shrink(m_playlistURL); vector_clear_and_shrink(m_playlistURL);
vector_clear_and_shrink(m_playlistContent); vector_clear_and_shrink(m_playlistContent);
m_hashQueue.clear();
m_hashQueue.shrink_to_fit(); // uint32_t vector
client.stop(); client.stop();
clientsecure.stop(); clientsecure.stop();
_client = static_cast<WiFiClient*>(&client); /* default to *something* so that no NULL deref can happen */ _client = static_cast<WiFiClient*>(&client); /* default to *something* so that no NULL deref can happen */
...@@ -2209,76 +2207,57 @@ void Audio::loop() { ...@@ -2209,76 +2207,57 @@ void Audio::loop() {
xSemaphoreTake(mutex_audio, portMAX_DELAY); xSemaphoreTake(mutex_audio, portMAX_DELAY);
if(m_playlistFormat != FORMAT_M3U8) { // normal process if(m_playlistFormat != FORMAT_M3U8) { // normal process
switch(getDatamode()) { switch(getDatamode()) {
case AUDIO_LOCALFILE: case AUDIO_LOCALFILE: processLocalFile(); break;
processLocalFile(); case HTTP_RESPONSE_HEADER: parseHttpResponseHeader(); break;
break; case AUDIO_PLAYLISTINIT: readPlayListData(); break;
case HTTP_RESPONSE_HEADER: case AUDIO_PLAYLISTDATA:
parseHttpResponseHeader(); if(m_playlistFormat == FORMAT_M3U) connecttohost(parsePlaylist_M3U());
break; if(m_playlistFormat == FORMAT_PLS) connecttohost(parsePlaylist_PLS());
case AUDIO_PLAYLISTINIT: if(m_playlistFormat == FORMAT_ASX) connecttohost(parsePlaylist_ASX());
readPlayListData(); break;
break; case AUDIO_DATA:
case AUDIO_PLAYLISTDATA: if(m_streamType == ST_WEBSTREAM) processWebStream();
if(m_playlistFormat == FORMAT_M3U) connecttohost(parsePlaylist_M3U()); if(m_streamType == ST_WEBFILE) processWebFile();
if(m_playlistFormat == FORMAT_PLS) connecttohost(parsePlaylist_PLS()); break;
if(m_playlistFormat == FORMAT_ASX) connecttohost(parsePlaylist_ASX());
break;
case AUDIO_DATA:
if(m_streamType == ST_WEBSTREAM) processWebStream();
if(m_streamType == ST_WEBFILE) processWebFile();
break;
} }
} }
else { // m3u8 datastream only else { // m3u8 datastream only
static bool f_noNewHost = false; const char* host;
static int32_t remaintime, timestamp1, timestamp2; // m3u8 time management
const char* host;
switch(getDatamode()) { switch(getDatamode()) {
case HTTP_RESPONSE_HEADER: case HTTP_RESPONSE_HEADER:
playAudioData(); // fill I2S DMA buffer playAudioData(); // fill I2S DMA buffer
parseHttpResponseHeader(); parseHttpResponseHeader();
m_codec = CODEC_AAC; m_codec = CODEC_AAC;
break; break;
case AUDIO_PLAYLISTINIT: case AUDIO_PLAYLISTINIT:
readPlayListData(); playAudioData(); // fill I2S DMA buffer
break; readPlayListData();
case AUDIO_PLAYLISTDATA: break;
host = parsePlaylist_M3U8(); case AUDIO_PLAYLISTDATA:
m_f_m3u8data = true; playAudioData(); // fill I2S DMA buffer
if(host) { host = parsePlaylist_M3U8();
f_noNewHost = false; playAudioData(); // fill I2S DMA buffer
timestamp1 = millis(); if(host) { // host contains the next playlist URL
httpPrint(host); httpPrint(host);
} }
else { else { // host == NULL means connect to m3u8 URL
f_noNewHost = true; httpPrint(m_lastHost);
timestamp2 = millis() + remaintime; setDatamode(HTTP_RESPONSE_HEADER); // we have a new playlist now
setDatamode(AUDIO_DATA); // fake datamode, we have no new audiosequence yet, so let audio run }
}
break; break;
case AUDIO_DATA: case AUDIO_DATA:
if(m_f_ts) processWebStreamTS(); // aac or aacp with ts packets if(m_f_ts) { processWebStreamTS(); } // aac or aacp with ts packets
else else { processWebStreamHLS(); } // aac or aacp normal stream
processWebStreamHLS(); // aac or aacp normal stream
if(f_noNewHost) { if(m_f_continue) { // at this point m_f_continue is true, means processWebStream() needs more data
m_f_continue = false; setDatamode(AUDIO_PLAYLISTDATA);
if(timestamp2 < millis()) { m_f_continue = false;
httpPrint(m_lastHost); }
remaintime = 1000; break;
}
}
else {
if(m_f_continue) { // processWebStream() needs more data
remaintime = (int32_t)(m_m3u8_targetDuration * 1000) - (millis() - timestamp1);
// if(m_m3u8_targetDuration < 10) remaintime += 1000;
m_f_continue = false;
setDatamode(AUDIO_PLAYLISTDATA);
}
}
break;
} }
} }
xSemaphoreGive(mutex_audio); xSemaphoreGive(mutex_audio);
...@@ -2351,10 +2330,13 @@ bool Audio::readPlayListData() { ...@@ -2351,10 +2330,13 @@ bool Audio::readPlayListData() {
if(startsWith(pl, "<!DOCTYPE")) {AUDIO_INFO("url is a webpage!"); goto exit;} if(startsWith(pl, "<!DOCTYPE")) {AUDIO_INFO("url is a webpage!"); goto exit;}
if(startsWith(pl, "<html")) {AUDIO_INFO("url is a webpage!"); goto exit;} if(startsWith(pl, "<html")) {AUDIO_INFO("url is a webpage!"); goto exit;}
if(strlen(pl) > 0) m_playlistContent.push_back(x_strdup(pl)); if(strlen(pl) > 0) m_playlistContent.push_back(x_strdup(pl));
if(m_playlistContent.size() == 100) { if(!m_f_psramFound && m_playlistContent.size() == 101){
if(m_f_Log) log_i("the maximum number of lines in the playlist has been reached"); AUDIO_INFO("the number of lines in playlist > 100, for bigger playlist use PSRAM!");
break; break;
} }
if(m_playlistContent.size() && m_playlistContent.size() % 1000 == 0) {
AUDIO_INFO("current playlist line: %lu", (long unsigned)m_playlistContent.size());
}
// termination conditions // termination conditions
// 1. The http response header returns a value for contentLength -> read chars until contentLength is reached // 1. The http response header returns a value for contentLength -> read chars until contentLength is reached
// 2. no contentLength, but Transfer-Encoding:chunked -> compute chunksize and read until chunksize is reached // 2. no contentLength, but Transfer-Encoding:chunked -> compute chunksize and read until chunksize is reached
...@@ -2517,12 +2499,11 @@ const char* Audio::parsePlaylist_M3U8() { ...@@ -2517,12 +2499,11 @@ const char* Audio::parsePlaylist_M3U8() {
// #EXTINF:10,title="text=\"Spot Block End\" amgTrackId=\"9876543\"",artist=" ",url="length=\"00:00:00\"" // #EXTINF:10,title="text=\"Spot Block End\" amgTrackId=\"9876543\"",artist=" ",url="length=\"00:00:00\""
// http://n3fa-e2.revma.ihrhls.com/zc7729/63_sdtszizjcjbz02/main/163374039.aac // http://n3fa-e2.revma.ihrhls.com/zc7729/63_sdtszizjcjbz02/main/163374039.aac
static int16_t xMedPos = 0;
static uint64_t xMedSeq = 0; static uint64_t xMedSeq = 0;
static boolean f_medSeq_found = false; static boolean f_medSeq_found = false;
char llasc[21]; // uint64_t max = 18,446,744,073,709,551,615 thats 20 chars + \0
if(m_f_firstM3U8call){ if(m_f_firstM3U8call){
m_f_firstM3U8call = false; m_f_firstM3U8call = false;
xMedPos = 0;
xMedSeq = 0; xMedSeq = 0;
f_medSeq_found = false; f_medSeq_found = false;
} }
...@@ -2531,7 +2512,7 @@ const char* Audio::parsePlaylist_M3U8() { ...@@ -2531,7 +2512,7 @@ const char* Audio::parsePlaylist_M3U8() {
bool f_begin = false; bool f_begin = false;
const char* ret; const char* ret;
if(lines) { if(lines) {
for(int i = 0; i < lines; i++) { for(uint16_t i = 0; i < lines; i++) {
if(strlen(m_playlistContent[i]) == 0) continue; // empty line if(strlen(m_playlistContent[i]) == 0) continue; // empty line
if(startsWith(m_playlistContent[i], "#EXTM3U")) {f_begin = true; continue;} // what we expected if(startsWith(m_playlistContent[i], "#EXTM3U")) {f_begin = true; continue;} // what we expected
if(!f_begin) continue; if(!f_begin) continue;
...@@ -2541,40 +2522,30 @@ const char* Audio::parsePlaylist_M3U8() { ...@@ -2541,40 +2522,30 @@ const char* Audio::parsePlaylist_M3U8() {
if(ret) return ret; if(ret) return ret;
} }
//if(startsWith(m_playlistContent[i], "#EXT-X-DISCONTINUITY-SEQUENCE:0")) { // not used // "#EXT-X-DISCONTINUITY-SEQUENCE: // not used, 0: seek for continuity numbers, is sometimes not set
// seek for continuity numbers, is sometimes not set // "#EXT-X-MEDIA-SEQUENCE:" // not used, is unreliable
// log_i("EXT-X-DISCONTINUITY-SEQUENCE:0"); if (startsWith(m_playlistContent[i], "#EXT-X-VERSION:")) continue;
//} if (startsWith(m_playlistContent[i], "#EXT-X-ALLOW-CACHE:")) continue;
if (startsWith(m_playlistContent[i], "##")) continue;
if(!f_medSeq_found && startsWith(m_playlistContent[i], "#EXT-X-MEDIA-SEQUENCE:")) { // if xMedSeq exists, convert xMedSeq to an uint64 if (startsWith(m_playlistContent[i], "#EXT-X-INDEPENDENT-SEGMENTS")) continue;
char* pEnd; // and look for the position in m_playlistContent
char llasc[21]; // uint64_t max = 18,446,744,073,709,551,615 if(!f_medSeq_found){
xMedSeq = strtoull(m_playlistContent[i] + 22, &pEnd, 10); xMedSeq = m3u8_findMediaSeqInURL();
if(xMedSeq > 0){ if(xMedSeq > 0) f_medSeq_found = true;
lltoa(xMedSeq, llasc, 10); if(xMedSeq == 0){
for(uint8_t j = i + 1; j < lines; j++){ log_e("MEDIA SEQUENCE not found");
if(startsWith(m_playlistContent[j], "#EXTINF:")) { stopSong();
xMedPos = (indexOf(m_playlistContent[j + 1], llasc, 0)); return 0;
if(xMedPos > 0){
log_e("found at pos %u, %s", xMedPos, m_playlistContent[j + 1]);
f_medSeq_found = true;
break;
}
}
}
} }
} }
// if(startsWith(m_playlistContent[i], "#EXT-X-TARGETDURATION:")) {
static uint16_t targetDuration = 0; // m_m3u8_targetDuration = atoi(m_playlistContent[i] + 22);
if(startsWith(m_playlistContent[i], "#EXT-X-TARGETDURATION:")) { // if(m_f_Log) log_i("m_m3u8_targetDuration %d", m_m3u8_targetDuration);
targetDuration = atoi(m_playlistContent[i] + 22); // }
}
if(targetDuration) m_m3u8_targetDuration = targetDuration;
if(m_f_Log) log_i("m_m3u8_targetDuration %d", m_m3u8_targetDuration);
if(startsWith(m_playlistContent[i], "#EXTINF")) { if(startsWith(m_playlistContent[i], "#EXTINF")) {
if(STfromEXTINF(m_playlistContent[i])) showstreamtitle(m_chbuf); if(STfromEXTINF(m_playlistContent[i])) {showstreamtitle(m_chbuf);}
i++; i++;
if(i == lines) continue; // and exit for() if(i == lines) continue; // and exit for()
...@@ -2589,36 +2560,21 @@ const char* Audio::parsePlaylist_M3U8() { ...@@ -2589,36 +2560,21 @@ const char* Audio::parsePlaylist_M3U8() {
} }
else { tmp = strdup(m_playlistContent[i]); } else { tmp = strdup(m_playlistContent[i]); }
uint32_t hash = simpleHash(tmp); lltoa(xMedSeq, llasc, 10);
if(m_hashQueue.size() == 0) { if(indexOf(tmp, llasc) > 0){
m_hashQueue.insert(m_hashQueue.begin(), hash);
m_playlistURL.insert(m_playlistURL.begin(), strdup(tmp)); m_playlistURL.insert(m_playlistURL.begin(), strdup(tmp));
} xMedSeq++;
else {
bool known = false;
for(int i = 0; i < m_hashQueue.size(); i++) {
if(hash == m_hashQueue[i]) {
if(m_f_Log) log_i("file already known %s", tmp);
known = true;
}
}
if(!known) {
m_hashQueue.insert(m_hashQueue.begin(), hash);
m_playlistURL.insert(m_playlistURL.begin(), strdup(tmp));
}
} }
if(m_hashQueue.size() > 20) m_hashQueue.pop_back();
if(tmp) { if(tmp) {
free(tmp); free(tmp);
tmp = NULL; tmp = NULL;
} }
if(m_playlistURL.size() == 20) { // if(m_playlistURL.size() == 20) {
ESP_LOGD("", "can't stuff anymore"); // ESP_LOGD("", "can't stuff anymore");
break; // break;
} // }
continue; continue;
} }
} }
...@@ -2663,21 +2619,19 @@ const char* Audio::m3u8redirection(){ ...@@ -2663,21 +2619,19 @@ const char* Audio::m3u8redirection(){
uint16_t choosenLine = 0; uint16_t choosenLine = 0;
uint16_t plcSize = m_playlistContent.size(); uint16_t plcSize = m_playlistContent.size();
if(plcSize > 20) plcSize = 20; if(plcSize > 20) plcSize = 20;
uint8_t posBW = 0, posC = 0; int16_t posBW = 0;
// looking for best (highest) bandwidth
for(uint16_t i = 0; i < plcSize; i++){ for(uint16_t i = 0; i < plcSize; i++){ // looking for best (highest) bandwidth
posBW = indexOf(m_playlistContent[i], "BANDWIDTH="); posBW = indexOf(m_playlistContent[i], "BANDWIDTH=");
if(posBW > 0){ if(posBW > 0){
posC = indexOf(m_playlistContent[i], ","); char* endP;
if(posC > posBW && posC - posBW < 18){ // valid BW bw[i] = strtol(m_playlistContent[i] + posBW + 10, &endP, 10); // read until comma
bw[i] = atoi(m_playlistContent[i] + posBW + 10); // read until comma
}
} }
} }
for(uint16_t i = 0; i < plcSize; i++){ for(uint16_t i = 0; i < plcSize; i++){
if(bw[i] > finalBW) {finalBW = bw[i], choosenLine = i + 1;} if(bw[i] > finalBW) {finalBW = bw[i], choosenLine = i + 1;}
} }
if(m_f_Log) log_i("choosenBW: %i at line: %i", finalBW, choosenLine); AUDIO_INFO("bandwidth: %lu bit/s", (long unsigned)finalBW);
char* tmp = nullptr; char* tmp = nullptr;
if((!endsWith(m_playlistContent[choosenLine], "m3u8") && indexOf(m_playlistContent[choosenLine], "m3u8?") == -1)) { if((!endsWith(m_playlistContent[choosenLine], "m3u8") && indexOf(m_playlistContent[choosenLine], "m3u8?") == -1)) {
...@@ -2726,6 +2680,62 @@ exit: ...@@ -2726,6 +2680,62 @@ exit:
stopSong(); stopSong();
return NULL; return NULL;
} }
//---------------------------------------------------------------------------------------------------------------------
uint64_t Audio::m3u8_findMediaSeqInURL(){ // We have no clue what the media sequence is
char* pEnd;
uint64_t MediaSeq = 0;
uint8_t idx = 0;
uint16_t linesWithURL[3] = {0};
char llasc[21]; // uint64_t max = 18,446,744,073,709,551,615 thats 20 chars + \0
for(uint16_t i = 0; i < m_playlistContent.size(); i++){
if(startsWith(m_playlistContent[i], "#EXTINF:")) {
linesWithURL[idx] = i + 1;
idx++;
if(idx == 3) break;
}
}
if(idx < 3){
log_e("not enough lines with \"#EXTINF:\" found");
return 0;
}
// Look for differences from right: ∨
// http://lampsifmlive.mdc.akamaized.net/strmLampsi/userLampsi/l_50551_3318804060_229668.aac
// http://lampsifmlive.mdc.akamaized.net/strmLampsi/userLampsi/l_50551_3318810050_229669.aac
// go back to first digit: ∧
// log_i("m_playlistContent[linesWithURL[0]] %s", m_playlistContent[linesWithURL[0]]);
// log_i("m_playlistContent[linesWithURL[1]] %s", m_playlistContent[linesWithURL[1]]);
// log_i("m_playlistContent[linesWithURL[2]] %s", m_playlistContent[linesWithURL[2]]);
int16_t len = strlen(m_playlistContent[linesWithURL[0]]) - 1;
int16_t qm = indexOf(m_playlistContent[linesWithURL[0]], "?", 0);
if(qm > 0) len = qm; // If we find a question mark, look to the left of it
for(int16_t pos = len; pos >= 0 ; pos--){
if(isdigit(m_playlistContent[linesWithURL[0]][pos])){
while(isdigit(m_playlistContent[linesWithURL[0]][pos])) pos--;
pos++;
uint64_t a, b, c;
a = strtoull(m_playlistContent[linesWithURL[0]] + pos, &pEnd, 10);
b = a + 1;
c = b + 1;
lltoa(b, llasc, 10);
int16_t idx_b = indexOf(m_playlistContent[linesWithURL[1]], llasc);
lltoa(c, llasc, 10);
int16_t idx_c = indexOf(m_playlistContent[linesWithURL[2]], llasc);
if(idx_b > 0 && idx_c > 0){
MediaSeq = a;
AUDIO_INFO("media sequence number: %llu", MediaSeq);
break;
}
}
}
return MediaSeq;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool Audio::STfromEXTINF(char* str) { bool Audio::STfromEXTINF(char* str) {
// the result is copied in chbuf!! // the result is copied in chbuf!!
...@@ -3177,6 +3187,7 @@ void Audio::processWebStreamTS() { ...@@ -3177,6 +3187,7 @@ void Audio::processWebStreamTS() {
uint32_t availableBytes; // available bytes in stream uint32_t availableBytes; // available bytes in stream
static bool f_stream; // first audio data received static bool f_stream; // first audio data received
static bool f_firstPacket; static bool f_firstPacket;
static bool f_chunkFinished;
static uint32_t byteCounter; // count received data static uint32_t byteCounter; // count received data
static uint8_t ts_packet[188]; // m3u8 transport stream is 188 bytes long static uint8_t ts_packet[188]; // m3u8 transport stream is 188 bytes long
uint8_t ts_packetStart = 0; uint8_t ts_packetStart = 0;
...@@ -3189,6 +3200,7 @@ void Audio::processWebStreamTS() { ...@@ -3189,6 +3200,7 @@ void Audio::processWebStreamTS() {
if(m_f_firstCall) { // runs only ont time per connection, prepare for start if(m_f_firstCall) { // runs only ont time per connection, prepare for start
f_stream = false; f_stream = false;
f_firstPacket = true; f_firstPacket = true;
f_chunkFinished = false;
byteCounter = 0; byteCounter = 0;
chunkSize = 0; chunkSize = 0;
m_t0 = millis(); m_t0 = millis();
...@@ -3244,12 +3256,21 @@ void Audio::processWebStreamTS() { ...@@ -3244,12 +3256,21 @@ void Audio::processWebStreamTS() {
} }
} }
if(byteCounter == m_contentlength || byteCounter == chunkSize) { if(byteCounter == m_contentlength || byteCounter == chunkSize) {
f_chunkFinished = true;
byteCounter = 0; byteCounter = 0;
m_f_continue = true;
} }
if(byteCounter > m_contentlength) log_e("byteCounter overflow"); if(byteCounter > m_contentlength) log_e("byteCounter overflow");
} }
} }
if(f_chunkFinished) {
if(m_f_psramFound) {
if(InBuff.bufferFilled() < 50000) { f_chunkFinished = false; m_f_continue = true;}
}
else {
f_chunkFinished = false;
m_f_continue = true;
}
}
// if the buffer is often almost empty issue a warning - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // if the buffer is often almost empty issue a warning - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if(f_stream) { if(f_stream) {
...@@ -3285,6 +3306,7 @@ void Audio::processWebStreamHLS() { ...@@ -3285,6 +3306,7 @@ void Audio::processWebStreamHLS() {
uint32_t availableBytes; // available bytes in stream uint32_t availableBytes; // available bytes in stream
static bool f_stream; // first audio data received static bool f_stream; // first audio data received
static bool firstBytes; static bool firstBytes;
static bool f_chunkFinished;
static uint32_t byteCounter; // count received data static uint32_t byteCounter; // count received data
static size_t chunkSize = 0; static size_t chunkSize = 0;
static uint16_t ID3WritePtr; static uint16_t ID3WritePtr;
...@@ -3294,6 +3316,7 @@ void Audio::processWebStreamHLS() { ...@@ -3294,6 +3316,7 @@ void Audio::processWebStreamHLS() {
// first call, set some values to default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // first call, set some values to default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if(m_f_firstCall) { // runs only ont time per connection, prepare for start if(m_f_firstCall) { // runs only ont time per connection, prepare for start
f_stream = false; f_stream = false;
f_chunkFinished = false;
byteCounter = 0; byteCounter = 0;
chunkSize = 0; chunkSize = 0;
ID3WritePtr = 0; ID3WritePtr = 0;
...@@ -3352,14 +3375,26 @@ void Audio::processWebStreamHLS() { ...@@ -3352,14 +3375,26 @@ void Audio::processWebStreamHLS() {
size_t bytesWasWritten = 0; size_t bytesWasWritten = 0;
if(InBuff.writeSpace() >= availableBytes) { if(InBuff.writeSpace() >= availableBytes) {
if(availableBytes > 1024) availableBytes = 1024; // 1K throttle
bytesWasWritten = _client->read(InBuff.getWritePtr(), availableBytes); bytesWasWritten = _client->read(InBuff.getWritePtr(), availableBytes);
} }
else { bytesWasWritten = _client->read(InBuff.getWritePtr(), InBuff.writeSpace()); } else { bytesWasWritten = _client->read(InBuff.getWritePtr(), InBuff.writeSpace()); }
InBuff.bytesWritten(bytesWasWritten); InBuff.bytesWritten(bytesWasWritten);
byteCounter += bytesWasWritten; byteCounter += bytesWasWritten;
if(byteCounter == m_contentlength || byteCounter == chunkSize) { if(byteCounter == m_contentlength || byteCounter == chunkSize) {
f_chunkFinished = true;
byteCounter = 0; byteCounter = 0;
}
}
if(f_chunkFinished) {
if(m_f_psramFound) {
if(InBuff.bufferFilled() < 50000) {f_chunkFinished = false; m_f_continue = true;}
}
else {
f_chunkFinished = false;
m_f_continue = true; m_f_continue = true;
} }
} }
...@@ -3380,7 +3415,7 @@ void Audio::processWebStreamHLS() { ...@@ -3380,7 +3415,7 @@ void Audio::processWebStreamHLS() {
if(f_stream) { if(f_stream) {
static uint8_t cnt = 0; static uint8_t cnt = 0;
cnt++; cnt++;
if(cnt == 3) { if(cnt == 2) {
playAudioData(); playAudioData();
cnt = 0; cnt = 0;
} // aac only } // aac only
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
* *
* Created on: Oct 28,2018 * Created on: Oct 28,2018
* *
* Version 3.0.7f * Version 3.0.7h
* Updated on: Oct 14.2023 * Updated on: Oct 16.2023
* Author: Wolle (schreibfaul1) * Author: Wolle (schreibfaul1)
*/ */
...@@ -198,6 +198,7 @@ private: ...@@ -198,6 +198,7 @@ private:
const char* parsePlaylist_ASX(); const char* parsePlaylist_ASX();
const char* parsePlaylist_M3U8(); const char* parsePlaylist_M3U8();
const char* m3u8redirection(); const char* m3u8redirection();
uint64_t m3u8_findMediaSeqInURL();
bool STfromEXTINF(char* str); bool STfromEXTINF(char* str);
void showCodecParams(); void showCodecParams();
int findNextSync(uint8_t* data, size_t len); int findNextSync(uint8_t* data, size_t len);
...@@ -462,7 +463,6 @@ private: ...@@ -462,7 +463,6 @@ private:
#endif #endif
std::vector<char*> m_playlistContent; // m3u8 playlist buffer std::vector<char*> m_playlistContent; // m3u8 playlist buffer
std::vector<char*> m_playlistURL; // m3u8 streamURLs buffer std::vector<char*> m_playlistURL; // m3u8 streamURLs buffer
std::vector<uint32_t> m_hashQueue;
const size_t m_frameSizeWav = 1024; const size_t m_frameSizeWav = 1024;
const size_t m_frameSizeMP3 = 1600; const size_t m_frameSizeMP3 = 1600;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment