Unverified Commit fe1f37c9 authored by Wolle's avatar Wolle Committed by GitHub

fix ESP crashes during playing local MP3 file with ID3 Tag v2.2

parent be305923
/*7d /*
* Audio.cpp * Audio.cpp
* *
* Created on: Oct 26.2018 * Created on: Oct 26.2018
* *
* Version 2.0.8b * Version 2.0.8c
* Updated on: Jan 10.2023 * Updated on: Jan 11.2023
* Author: Wolle (schreibfaul1) * Author: Wolle (schreibfaul1)
* *
*/ */
...@@ -959,7 +959,7 @@ void Audio::showID3Tag(const char* tag, const char* value){ ...@@ -959,7 +959,7 @@ void Audio::showID3Tag(const char* tag, const char* value){
if(!strcmp(tag, "IPL")) sprintf(m_chbuf, "Involved people list: %s", value); if(!strcmp(tag, "IPL")) sprintf(m_chbuf, "Involved people list: %s", value);
if(!strcmp(tag, "PIC")) sprintf(m_chbuf, "Attached picture: %s", value); if(!strcmp(tag, "PIC")) sprintf(m_chbuf, "Attached picture: %s", value);
if(!strcmp(tag, "SLT")) sprintf(m_chbuf, "Synchronized lyric/text: %s", value); if(!strcmp(tag, "SLT")) sprintf(m_chbuf, "Synchronized lyric/text: %s", value);
// if(!strcmp(tag, "TAL")) sprintf(m_chbuf, "Album/Movie/Show title: %s", value); if(!strcmp(tag, "TAL")) sprintf(m_chbuf, "Album/Movie/Show title: %s", value);
if(!strcmp(tag, "TBP")) sprintf(m_chbuf, "BPM (Beats Per Minute): %s", value); if(!strcmp(tag, "TBP")) sprintf(m_chbuf, "BPM (Beats Per Minute): %s", value);
if(!strcmp(tag, "TCM")) sprintf(m_chbuf, "Composer: %s", value); if(!strcmp(tag, "TCM")) sprintf(m_chbuf, "Composer: %s", value);
if(!strcmp(tag, "TCO")) sprintf(m_chbuf, "Content type: %s", value); if(!strcmp(tag, "TCO")) sprintf(m_chbuf, "Content type: %s", value);
...@@ -1524,7 +1524,8 @@ int Audio::read_FLAC_Header(uint8_t *data, size_t len) { ...@@ -1524,7 +1524,8 @@ int Audio::read_FLAC_Header(uint8_t *data, size_t len) {
int Audio::read_ID3_Header(uint8_t *data, size_t len) { int Audio::read_ID3_Header(uint8_t *data, size_t len) {
static size_t id3Size; static size_t id3Size;
static size_t headerSize; static size_t remainingHeaderBytes;
static size_t universal_tmp = 0;
static uint8_t ID3version; static uint8_t ID3version;
static int ehsz = 0; static int ehsz = 0;
static char tag[5]; static char tag[5];
...@@ -1543,7 +1544,7 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) { ...@@ -1543,7 +1544,7 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) {
} }
m_controlCounter ++; m_controlCounter ++;
APIC_seen = false; APIC_seen = false;
headerSize = 0; remainingHeaderBytes = 0;
ehsz = 0; ehsz = 0;
if(specialIndexOf(data, "ID3", 4) != 0) { // ID3 not found if(specialIndexOf(data, "ID3", 4) != 0) { // ID3 not found
if(!m_f_m3u8data) AUDIO_INFO("file has no mp3 tag, skip metadata"); if(!m_f_m3u8data) AUDIO_INFO("file has no mp3 tag, skip metadata");
...@@ -1573,9 +1574,9 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) { ...@@ -1573,9 +1574,9 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) {
if(ID3version == 2){ if(ID3version == 2){
m_controlCounter = 10; m_controlCounter = 10;
} }
headerSize = id3Size; remainingHeaderBytes = id3Size;
m_ID3Size = id3Size; m_ID3Size = id3Size;
headerSize -= 10; remainingHeaderBytes -= 10;
return 10; return 10;
} }
...@@ -1585,7 +1586,7 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) { ...@@ -1585,7 +1586,7 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) {
if(m_f_exthdr) { if(m_f_exthdr) {
AUDIO_INFO("ID3 extended header"); AUDIO_INFO("ID3 extended header");
ehsz = bigEndian(data, 4); ehsz = bigEndian(data, 4);
headerSize -= 4; remainingHeaderBytes -= 4;
ehsz -= 4; ehsz -= 4;
return 4; return 4;
} }
...@@ -1598,16 +1599,16 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) { ...@@ -1598,16 +1599,16 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) {
if(m_controlCounter == 2){ // skip extended header if exists if(m_controlCounter == 2){ // skip extended header if exists
if(ehsz > 256) { if(ehsz > 256) {
ehsz -=256; ehsz -=256;
headerSize -= 256; remainingHeaderBytes -= 256;
return 256;} // Throw it away return 256;} // Throw it away
else { else {
m_controlCounter ++; m_controlCounter ++;
headerSize -= ehsz; remainingHeaderBytes -= ehsz;
return ehsz;} // Throw it away return ehsz;} // Throw it away
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if(m_controlCounter == 3){ // read a ID3 frame, get the tag if(m_controlCounter == 3){ // read a ID3 frame, get the tag
if(headerSize == 0){ if(remainingHeaderBytes == 0){
m_controlCounter = 99; m_controlCounter = 99;
return 0; return 0;
} }
...@@ -1619,7 +1620,7 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) { ...@@ -1619,7 +1620,7 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) {
frameid[4] = 0; frameid[4] = 0;
for(uint8_t i = 0; i < 4; i++) tag[i] = frameid[i]; // tag = frameid for(uint8_t i = 0; i < 4; i++) tag[i] = frameid[i]; // tag = frameid
headerSize -= 4; remainingHeaderBytes -= 4;
if(frameid[0] == 0 && frameid[1] == 0 && frameid[2] == 0 && frameid[3] == 0) { if(frameid[0] == 0 && frameid[1] == 0 && frameid[2] == 0 && frameid[3] == 0) {
// We're in padding // We're in padding
m_controlCounter = 98; // all ID3 metadata processed m_controlCounter = 98; // all ID3 metadata processed
...@@ -1636,18 +1637,18 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) { ...@@ -1636,18 +1637,18 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) {
else { else {
framesize = bigEndian(data, 4); // << 8 framesize = bigEndian(data, 4); // << 8
} }
headerSize -= 4; remainingHeaderBytes -= 4;
uint8_t flag = *(data + 4); // skip 1st flag uint8_t flag = *(data + 4); // skip 1st flag
(void) flag; (void) flag;
headerSize--; remainingHeaderBytes--;
compressed = (*(data + 5)) & 0x80; // Frame is compressed using [#ZLIB zlib] with 4 bytes for 'decompressed compressed = (*(data + 5)) & 0x80; // Frame is compressed using [#ZLIB zlib] with 4 bytes for 'decompressed
// size' appended to the frame header. // size' appended to the frame header.
headerSize--; remainingHeaderBytes--;
uint32_t decompsize = 0; uint32_t decompsize = 0;
if(compressed){ if(compressed){
if(m_f_Log) log_i("iscompressed"); if(m_f_Log) log_i("iscompressed");
decompsize = bigEndian(data + 6, 4); decompsize = bigEndian(data + 6, 4);
headerSize -= 4; remainingHeaderBytes -= 4;
(void) decompsize; (void) decompsize;
if(m_f_Log) log_i("decompsize=%u", decompsize); if(m_f_Log) log_i("decompsize=%u", decompsize);
return 6 + 4; return 6 + 4;
...@@ -1658,12 +1659,12 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) { ...@@ -1658,12 +1659,12 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) {
if(m_controlCounter == 5){ // If the frame is larger than 256 bytes, skip the rest if(m_controlCounter == 5){ // If the frame is larger than 256 bytes, skip the rest
if(framesize > 256){ if(framesize > 256){
framesize -= 256; framesize -= 256;
headerSize -= 256; remainingHeaderBytes -= 256;
return 256; return 256;
} }
else { else {
m_controlCounter = 3; // check next frame m_controlCounter = 3; // check next frame
headerSize -= framesize; remainingHeaderBytes -= framesize;
return framesize; return framesize;
} }
} }
...@@ -1682,7 +1683,7 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) { ...@@ -1682,7 +1683,7 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) {
isUnicode = false; isUnicode = false;
if(getDatamode() == AUDIO_LOCALFILE){ if(getDatamode() == AUDIO_LOCALFILE){
APIC_seen = true; APIC_seen = true;
APIC_pos = id3Size - headerSize; APIC_pos = id3Size - remainingHeaderBytes;
APIC_size = framesize; APIC_size = framesize;
} }
return 0; return 0;
...@@ -1694,7 +1695,7 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) { ...@@ -1694,7 +1695,7 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) {
value[i] = *(data + i); value[i] = *(data + i);
} }
framesize -= fs; framesize -= fs;
headerSize -= fs; remainingHeaderBytes -= fs;
value[fs] = 0; value[fs] = 0;
if(isUnicode && fs > 1) { if(isUnicode && fs > 1) {
unicode2utf8(value, fs); // convert unicode to utf-8 U+0020...U+07FF unicode2utf8(value, fs); // convert unicode to utf-8 U+0020...U+07FF
...@@ -1718,26 +1719,45 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) { ...@@ -1718,26 +1719,45 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) {
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// -- section V2.2 only , greater Vers above ---- // --- section V2.2 only , greater Vers above ----
// see https://mutagen-specs.readthedocs.io/en/latest/id3/id3v2.2.html
if(m_controlCounter == 10){ // frames in V2.2, 3bytes identifier, 3bytes size descriptor if(m_controlCounter == 10){ // frames in V2.2, 3bytes identifier, 3bytes size descriptor
if(universal_tmp > 0){
if( universal_tmp > 256) { universal_tmp -= 256; return 256;}
else{ uint8_t t = universal_tmp; universal_tmp = 0; return t;}
}
frameid[0] = *(data + 0); frameid[0] = *(data + 0);
frameid[1] = *(data + 1); frameid[1] = *(data + 1);
frameid[2] = *(data + 2); frameid[2] = *(data + 2);
frameid[3] = 0; frameid[3] = 0;
for(uint8_t i = 0; i < 4; i++) tag[i] = frameid[i]; // tag = frameid for(uint8_t i = 0; i < 4; i++) tag[i] = frameid[i]; // tag = frameid
headerSize -= 3; remainingHeaderBytes -= 3;
size_t len = bigEndian(data + 3, 3); size_t len = bigEndian(data + 3, 3);
headerSize -= 3; universal_tmp = len;
headerSize -= len; remainingHeaderBytes -= 3;
char value[256]; char value[256];
size_t tmp = len; if(len > 249) {len = 249; }
if(tmp > 254) tmp = 254; memcpy(value, (data + 7), len);
memcpy(value, (data + 7), tmp); value[len + 1] = 0;
value[tmp+1] = 0;
m_chbuf[0] = 0; m_chbuf[0] = 0;
if(startsWith(tag, "PIC")) { // image embedded in header
if(getDatamode() == AUDIO_LOCALFILE){
APIC_seen = true; // #460
APIC_pos = id3Size - remainingHeaderBytes;
APIC_size = universal_tmp;
if(m_f_Log) log_i("Attached picture seen at pos %d length %d", APIC_pos, APIC_size);
}
}
else{
showID3Tag(tag, value);
}
remainingHeaderBytes -= universal_tmp;
universal_tmp -= len;
showID3Tag(tag, value);
if(len == 0) m_controlCounter = 98; if(len == 0) m_controlCounter = 98;
if(remainingHeaderBytes == 0) m_controlCounter = 98;
return 3 + 3 + len; return 3 + 3 + len;
} }
...@@ -1745,13 +1765,13 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) { ...@@ -1745,13 +1765,13 @@ int Audio::read_ID3_Header(uint8_t *data, size_t len) {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if(m_controlCounter == 98){ // skip all ID3 metadata (mostly spaces) if(m_controlCounter == 98){ // skip all ID3 metadata (mostly spaces)
if(headerSize > 256) { if(remainingHeaderBytes > 256) {
headerSize -=256; remainingHeaderBytes -=256;
return 256; return 256;
} // Throw it away } // Throw it away
else { else {
m_controlCounter = 99; m_controlCounter = 99;
return headerSize; return remainingHeaderBytes;
} // Throw it away } // Throw it away
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
......
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
* Audio.h * Audio.h
* *
* Created on: Oct 28,2018 * Created on: Oct 28,2018
* Updated on: Jan 10,2023 *
* Version 2.0.8c
* Updated on: Jan 11,2023
* Author: Wolle (schreibfaul1) * Author: Wolle (schreibfaul1)
*/ */
......
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