Parcourir la source

ST77xx memory corruption + mp3 sync using library + mutex for poll in stream() - release

Philippe G il y a 4 ans
Parent
commit
7e097a7ee9

BIN
components/codecs/lib/libmad.a


+ 2 - 2
components/display/ST77xx.c

@@ -90,7 +90,7 @@ static void Update16( struct GDS_Device* Device ) {
 			for (int i = FirstRow; i <= LastRow; i++) {
 				memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize);
 				optr += ChunkSize;
-				if (optr - Private->iRAM < PAGE_BLOCK && i < LastRow) continue;
+				if (optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue;
 				Device->WriteData(Device, Private->iRAM, optr - Private->iRAM);
 				optr = Private->iRAM;
 			}
@@ -157,7 +157,7 @@ static void Update24( struct GDS_Device* Device ) {
 			for (int i = FirstRow; i <= LastRow; i++) {
 				memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 3, ChunkSize);
 				optr += ChunkSize;
-				if (optr - Private->iRAM < PAGE_BLOCK && i < LastRow) continue;
+				if (optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue;
 				Device->WriteData(Device, Private->iRAM, optr - Private->iRAM);
 				optr = Private->iRAM;
 			}	

+ 13 - 7
components/squeezelite/display.c

@@ -628,8 +628,9 @@ static void grfe_handler( u8_t *data, int len) {
 	
 	scroller.active = false;
 	
-	// visu has priority when full screen on small screens
-	if ((visu.mode & VISU_ESP32) && !visu.col && visu.row < displayer.height) {
+	// full screen artwork or for small screen, full screen visu has priority
+	if (((visu.mode & VISU_ESP32) && !visu.col && visu.row < displayer.height) ||
+		(artwork.enable && artwork.x == 0 && artwork.y == 0)) {
 		xSemaphoreGive(displayer.mutex);
 		return;
 	}	
@@ -751,8 +752,11 @@ static void grfg_handler(u8_t *data, int len) {
 	
 	LOG_DEBUG("gfrg s:%hu w:%hu (len:%u)", htons(pkt->screen), htons(pkt->width), len);
 
-	// on small screen, visu has priority when full screen	
-	if ((visu.mode & VISU_ESP32) && !visu.col && visu.row < displayer.height) return;
+	// full screen artwork or for small screen, visu has priority when full screen	
+	if (((visu.mode & VISU_ESP32) && !visu.col && visu.row < displayer.height) || 
+		(artwork.enable && artwork.x == 0 && artwork.y == 0)) {
+		return;
+	}	
 	
 	xSemaphoreTake(displayer.mutex, portMAX_DELAY);
 		
@@ -795,7 +799,7 @@ static void grfa_handler(u8_t *data, int len) {
 
 	// when using full screen visualizer on small screen there is a brief overlay	
 	artwork.enable = (length != 0);
-
+	
 	// just a config or an actual artwork	
 	if (length < 32) {
 		if (artwork.enable) {
@@ -840,8 +844,10 @@ static void grfa_handler(u8_t *data, int len) {
  * Update visualization bars
  */
 static void visu_update(void) {
-	// no need to protect against no woning the display as we are playing	
-	if (pthread_mutex_trylock(&visu_export.mutex)) return;
+	// no update when artwork is full screen (but no need to protect against not owning the display as we are playing	
+	if ((artwork.enable && artwork.x == 0 && artwork.y == 0) || pthread_mutex_trylock(&visu_export.mutex)) {
+		return;
+	}	
 	
 	int mode = visu.mode & ~VISU_ESP32;
 				

+ 0 - 2
components/squeezelite/mad.c

@@ -243,8 +243,6 @@ static decode_state mad_decode(void) {
 		MAD(m, synth_frame, &m->synth, &m->frame);
 
 		if (decode.new_stream) {
-			// seems that mad can use some help in term of sync detection
-			if (m->stream.next_frame[0] != 0xff || (m->stream.next_frame[1] & 0xf0) != 0xf0) continue;
 			LOCK_O;
 			LOG_INFO("setting track_start");
 			output.next_sample_rate = decode_newstream(m->synth.pcm.samplerate, output.supported_rates);

+ 27 - 4
components/squeezelite/stream.c

@@ -40,13 +40,32 @@
 static log_level loglevel;
 
 static struct buffer buf;
-static mutex_type poll_mutex;
 struct buffer *streambuf = &buf;
 
 #define LOCK     mutex_lock(streambuf->mutex)
 #define UNLOCK   mutex_unlock(streambuf->mutex)
+
+/* 
+After a lot of hesitation, I've added that "poll mutex" to prevent
+socket from being allocated while we are still in poll(). The issue 
+happens is we have a close quickly followed by an open, we might still
+be in the poll() and simple OS fail as they re-allocate the same socket
+on which a thread is still waiting. 
+Ideally, you want to set the lock in the disconnect() but that would mean
+very often we'd have to always wait for the end of the poll(), i.e. up to
+100ms for nothing most of the time where if it is in the open(), it is 
+less elegant as closing a socket on which there is a poll() is not good 
+but it's more efficient as it is very rare that you'd have an open() less 
+then 100ms after a close()
+*/
+#if EMBEDDED
+static mutex_type poll_mutex;
 #define LOCK_L   mutex_lock(poll_mutex)
 #define UNLOCK_L mutex_unlock(poll_mutex)
+#else
+#define LOCK_L   
+#define UNLOCK_L 
+#endif
 
 static sockfd fd;
 
@@ -408,7 +427,9 @@ void stream_init(log_level level, unsigned stream_buf_size) {
 	*stream.header = '\0';
 
 	fd = -1;
+#if EMBEDDED	
 	mutex_create_p(poll_mutex);
+#endif	
 
 #if LINUX || FREEBSD
 	touch_memory(streambuf->buf, streambuf->size);
@@ -438,14 +459,16 @@ void stream_close(void) {
 #endif
 	free(stream.header);
 	buf_destroy(streambuf);
+#if EMBEDDED	
 	mutex_destroy(poll_mutex);
+#endif	
 }
 
 void stream_file(const char *header, size_t header_len, unsigned threshold) {
 	buf_flush(streambuf);
 
 	LOCK;
-
+	
 	stream.header_len = header_len;
 	memcpy(stream.header, header, header_len);
 	*(stream.header+header_len) = '\0';
@@ -480,7 +503,9 @@ void stream_file(const char *header, size_t header_len, unsigned threshold) {
 void stream_sock(u32_t ip, u16_t port, const char *header, size_t header_len, unsigned threshold, bool cont_wait) {
 	struct sockaddr_in addr;
 
+	LOCK_L;
 	int sock = socket(AF_INET, SOCK_STREAM, 0);
+	UNLOCK_L;
 
 	if (sock < 0) {
 		LOG_ERROR("failed to create socket");
@@ -588,13 +613,11 @@ bool stream_disconnect(void) {
 		ssl = NULL;
 	}
 #endif
-	LOCK_L;
 	if (fd != -1) {
 		closesocket(fd);
 		fd = -1;
 		disc = true;
 	}
-	UNLOCK_L,
 	stream.state = STOPPED;
 	UNLOCK;
 	return disc;