mpegplayer: Get it in better shape for dual core targets. Utilize the newly added cache stuff. Add a mutex to core shared buffer variables. I'd prefer to have a true spinlock there but this will do for the moment and protect the data. Nonetheless I can't seem to crash it on an e200 any longer and the display garbage is gone.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13153 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/plugin.c b/apps/plugin.c
index 1db0253..a059a8d 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -486,6 +486,12 @@
detect_flashed_ramimage,
detect_flashed_romimage,
#endif
+
+#if NUM_CORES > 1
+ spinlock_init,
+ spinlock_lock,
+ spinlock_unlock,
+#endif
};
int plugin_load(const char* plugin, void* parameter)
diff --git a/apps/plugin.h b/apps/plugin.h
index 51421ff..0c2d050 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -110,7 +110,7 @@
#define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */
-#define PLUGIN_API_VERSION 52
+#define PLUGIN_API_VERSION 53
/* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any
@@ -600,6 +600,12 @@
bool (*detect_flashed_ramimage)(void);
bool (*detect_flashed_romimage)(void);
#endif
+
+#if NUM_CORES > 1
+ void (*spinlock_init)(struct mutex *m);
+ void (*spinlock_lock)(struct mutex *m);
+ void (*spinlock_unlock)(struct mutex *m);
+#endif
};
/* plugin header */
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c
index b61e76c..7d97766 100644
--- a/apps/plugins/mpegplayer/mpegplayer.c
+++ b/apps/plugins/mpegplayer/mpegplayer.c
@@ -224,9 +224,28 @@
/* NOTE: Putting the following variables in IRAM cause audio corruption
on the ipod (reason unknown)
*/
-static uint8_t *disk_buf, *disk_buf_end;
+static uint8_t *disk_buf IBSS_ATTR;
+static uint8_t *disk_buf_end IBSS_ATTR;
static uint8_t *disk_buf_tail IBSS_ATTR;
-static size_t buffer_size IBSS_ATTR;
+static size_t buffer_size IBSS_ATTR;
+#if NUM_CORES > 1
+/* Some stream variables are shared between cores */
+struct mutex stream_lock IBSS_ATTR;
+static inline void init_stream_lock(void)
+ { rb->spinlock_init(&stream_lock); }
+static inline void lock_stream(void)
+ { rb->spinlock_lock(&stream_lock); }
+static inline void unlock_stream(void)
+ { rb->spinlock_unlock(&stream_lock); }
+#else
+/* No RMW issue here */
+static inline void init_stream_lock(void)
+ { }
+static inline void lock_stream(void)
+ { }
+static inline void unlock_stream(void)
+ { }
+#endif
/* Events */
static struct event_queue msg_queue IBSS_ATTR;
@@ -558,7 +577,7 @@
/* Problem */
//rb->splash( HZ*3, "missing packet start code prefix : %X%X at %X", *p, *(p+2), p-disk_buf );
str->curr_packet_end = str->curr_packet = NULL;
- return;
+ break;
//++p;
//break;
}
@@ -574,7 +593,7 @@
if (stream == 0xB9)
{
str->curr_packet_end = str->curr_packet = NULL;
- return;
+ break;
}
/* It's not the packet we're looking for, skip it */
@@ -667,6 +686,8 @@
if (str->curr_packet != NULL)
{
+ lock_stream();
+
if (str->curr_packet < str->prev_packet)
{
str->buffer_remaining -= (disk_buf_end - str->prev_packet) +
@@ -679,6 +700,8 @@
str->buffer_remaining -= (str->curr_packet - str->prev_packet);
}
+ unlock_stream();
+
str->prev_packet = str->curr_packet;
}
@@ -689,8 +712,6 @@
str->guard_bytes = str->curr_packet_end - disk_buf_end;
rb->memcpy(disk_buf_end, disk_buf, str->guard_bytes);
}
-
- return;
}
break;
@@ -1250,9 +1271,9 @@
mpeg2dec = mpeg2_init();
if (mpeg2dec == NULL)
{
- videostatus = STREAM_ERROR;
rb->splash(0, "mpeg2_init failed");
/* Commit suicide */
+ videostatus = THREAD_TERMINATED;
rb->remove_thread(NULL);
}
@@ -1282,6 +1303,8 @@
else if (videostatus == PLEASE_PAUSE)
{
videostatus = STREAM_PAUSING;
+ flush_icache();
+
while (videostatus == STREAM_PAUSING)
rb->sleep(HZ/10);
}
@@ -1533,6 +1556,8 @@
}
done:
+ flush_icache();
+
videostatus = STREAM_DONE;
while (videostatus != PLEASE_STOP)
@@ -1550,10 +1575,7 @@
int audiosize;
int in_file;
uint8_t* buffer;
- size_t audio_remaining, video_remaining;
- size_t bytes_to_read;
size_t file_remaining;
- size_t n;
size_t disk_buf_len;
#ifndef HAVE_LCD_COLOR
long graysize;
@@ -1692,6 +1714,8 @@
gray_show(true);
#endif
+ init_stream_lock();
+
/* We put the video thread on the second processor for multi-core targets. */
if ((videothread_id = rb->create_thread(video_thread,
(uint8_t*)video_stack,VIDEO_STACKSIZE,"mpgvideo" IF_PRIO(,PRIORITY_PLAYBACK)
@@ -1711,32 +1735,39 @@
rb->lcd_setfont(FONT_SYSFIXED);
/* Wait until both threads have finished their work */
- while ((audiostatus != STREAM_DONE) || (videostatus != STREAM_DONE)) {
- audio_remaining = audio_str.buffer_remaining;
- video_remaining = video_str.buffer_remaining;
+ while ((audiostatus != STREAM_DONE) || (videostatus != STREAM_DONE))
+ {
+ size_t audio_remaining = audio_str.buffer_remaining;
+ size_t video_remaining = video_str.buffer_remaining;
+
if (MIN(audio_remaining,video_remaining) < MPEG_LOW_WATERMARK) {
- // TODO: Add mutex when updating the A/V buffer_remaining variables.
- bytes_to_read = buffer_size - MPEG_GUARDBUF_SIZE - MAX(audio_remaining,video_remaining);
+ size_t bytes_to_read = buffer_size - MPEG_GUARDBUF_SIZE -
+ MAX(audio_remaining,video_remaining);
bytes_to_read = MIN(bytes_to_read,(size_t)(disk_buf_end-disk_buf_tail));
while (( bytes_to_read > 0) && (file_remaining > 0) &&
((audiostatus != STREAM_DONE) || (videostatus != STREAM_DONE))) {
- n = rb->read(in_file, disk_buf_tail, MIN(32*1024,bytes_to_read));
+ size_t n = rb->read(in_file, disk_buf_tail, MIN(32*1024,bytes_to_read));
bytes_to_read -= n;
file_remaining -= n;
+
+ lock_stream();
audio_str.buffer_remaining += n;
video_str.buffer_remaining += n;
+ unlock_stream();
+
disk_buf_tail += n;
+
rb->yield();
}
if (disk_buf_tail == disk_buf_end)
disk_buf_tail = buffer;
-
}
+
rb->sleep(HZ/10);
}