summaryrefslogtreecommitdiff
path: root/apps/plugins/mpegplayer/video_thread.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-01-03 16:41:19 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-01-03 16:41:19 +0000
commitb664f62e36b5f0ac296567e423816dab3811075d (patch)
tree7ca49c59d7332d7c1e51139efa12466b6730e511 /apps/plugins/mpegplayer/video_thread.c
parentf8fde296a63dd06efef5cf71c9fdb2c26c5a3fd6 (diff)
downloadrockbox-b664f62e36b5f0ac296567e423816dab3811075d.zip
rockbox-b664f62e36b5f0ac296567e423816dab3811075d.tar.gz
rockbox-b664f62e36b5f0ac296567e423816dab3811075d.tar.bz2
rockbox-b664f62e36b5f0ac296567e423816dab3811075d.tar.xz
MPEGPlayer graphics mutation: Implement a more visible FPS display and remove the debugging info from it. Tweak thumbnailing and printing of unavailable frames.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28960 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/mpegplayer/video_thread.c')
-rw-r--r--apps/plugins/mpegplayer/video_thread.c129
1 files changed, 65 insertions, 64 deletions
diff --git a/apps/plugins/mpegplayer/video_thread.c b/apps/plugins/mpegplayer/video_thread.c
index 69d94f8..aa88590 100644
--- a/apps/plugins/mpegplayer/video_thread.c
+++ b/apps/plugins/mpegplayer/video_thread.c
@@ -37,21 +37,23 @@ struct video_thread_data
int state; /* Thread state */
int status; /* Media status */
struct queue_event ev; /* Our event queue to receive commands */
- int num_drawn; /* Number of frames drawn since reset */
- int num_skipped; /* Number of frames skipped since reset */
uint32_t eta_stream; /* Current time of stream */
uint32_t eta_video; /* Time that frame has been scheduled for */
int32_t eta_early; /* How early has the frame been decoded? */
int32_t eta_late; /* How late has the frame been decoded? */
int frame_drop_level; /* Drop severity */
int skip_level; /* Skip severity */
- long last_showfps; /* Last time the FPS display was updated */
long last_render; /* Last time a frame was drawn */
uint32_t curr_time; /* Current due time of frame */
uint32_t period; /* Frame period in clock ticks */
int syncf_perfect; /* Last sync fit result */
};
+/* Number drawn since reset */
+static int video_num_drawn SHAREDBSS_ATTR;
+/* Number skipped since reset */
+static int video_num_skipped SHAREDBSS_ATTR;
+
/* TODO: Check if 4KB is appropriate - it works for my test streams,
so maybe we can reduce it. */
#define VIDEO_STACKSIZE (4*1024)
@@ -60,35 +62,6 @@ static struct event_queue video_str_queue SHAREDBSS_ATTR;
static struct queue_sender_list video_str_queue_send SHAREDBSS_ATTR;
struct stream video_str IBSS_ATTR;
-static void draw_fps(struct video_thread_data *td)
-{
- uint32_t start;
- uint32_t clock_ticks = stream_get_ticks(&start);
- int fps = 0;
- int buf_pct;
- char str[80];
-
- clock_ticks -= start;
- if (clock_ticks != 0)
- fps = muldiv_uint32(CLOCK_RATE*100, td->num_drawn, clock_ticks);
-
- buf_pct = muldiv_uint32(100, pcm_output_used(), PCMOUT_BUFSIZE);
-
- rb->snprintf(str, sizeof(str), "v:%d.%02d %d %d a:%02d%% %d %d ",
- /* Video information */
- fps / 100, fps % 100, td->num_skipped,
- td->info->display_picture->temporal_reference,
- /* Audio information */
- buf_pct, pcm_underruns, pcm_skipped);
- mylcd_putsxy(0, 0, str);
-
- vo_lock();
- mylcd_update_rect(0, 0, LCD_WIDTH, 8);
- vo_unlock();
-
- td->last_showfps = *rb->current_tick;
-}
-
#if defined(DEBUG) || defined(SIMULATOR)
static unsigned char pic_coding_type_char(unsigned type)
{
@@ -452,6 +425,31 @@ sync_finished:
return retval;
}
+static bool frame_print_handler(struct video_thread_data *td)
+{
+ bool retval;
+ uint8_t * const * buf = NULL;
+
+ if (td->info != NULL && td->info->display_fbuf != NULL &&
+ td->syncf_perfect > 0)
+ buf = td->info->display_fbuf->buf;
+
+ if (td->ev.id == VIDEO_PRINT_THUMBNAIL)
+ {
+ /* Print a thumbnail of whatever was last decoded - scale and
+ * position to fill the specified rectangle */
+ retval = vo_draw_frame_thumb(buf, (struct vo_rect *)td->ev.data);
+ }
+ else
+ {
+ /* Print the last frame decoded */
+ vo_draw_frame(buf);
+ retval = buf != NULL;
+ }
+
+ return retval;
+}
+
/* This only returns to play or quit */
static void video_thread_msg(struct video_thread_data *td)
{
@@ -520,8 +518,7 @@ static void video_thread_msg(struct video_thread_data *td)
if (td->ev.data)
{
- if (td->info != NULL && td->info->display_fbuf != NULL)
- vo_draw_frame(td->info->display_fbuf->buf);
+ frame_print_handler(td);
}
else
{
@@ -547,10 +544,9 @@ static void video_thread_msg(struct video_thread_data *td)
td->eta_late = 0;
td->frame_drop_level = 0;
td->skip_level = 0;
- td->num_drawn = 0;
- td->num_skipped = 0;
- td->last_showfps = *rb->current_tick - HZ;
- td->last_render = td->last_showfps;
+ td->last_render = *rb->current_tick - HZ;
+ video_num_drawn = 0;
+ video_num_skipped = 0;
reply = true;
break;
@@ -573,28 +569,17 @@ static void video_thread_msg(struct video_thread_data *td)
str_data_notify_received(&video_str);
break;
+ case VIDEO_PRINT_FRAME:
case VIDEO_PRINT_THUMBNAIL:
- /* Print a thumbnail of whatever was last decoded - scale and
- * position to fill the specified rectangle */
- if (td->info != NULL && td->info->display_fbuf != NULL)
- {
- vo_draw_frame_thumb(td->info->display_fbuf->buf,
- (struct vo_rect *)td->ev.data);
- reply = true;
- }
+ reply = frame_print_handler(td);
break;
case VIDEO_SET_CLIP_RECT:
vo_set_clip_rect((const struct vo_rect *)td->ev.data);
break;
- case VIDEO_PRINT_FRAME:
- /* Print the last frame decoded */
- if (td->info != NULL && td->info->display_fbuf != NULL)
- {
- vo_draw_frame(td->info->display_fbuf->buf);
- reply = true;
- }
+ case VIDEO_GET_CLIP_RECT:
+ reply = vo_get_clip_rect((struct vo_rect *)td->ev.data);
break;
case VIDEO_GET_SIZE:
@@ -621,6 +606,11 @@ static void video_thread_msg(struct video_thread_data *td)
reply = video_str_scan(td, (struct str_sync_data *)td->ev.data);
break;
+ case VIDEO_SET_POST_FRAME_CALLBACK:
+ vo_set_post_draw_callback((void (*)(void))td->ev.data);
+ reply = true;
+ break;
+
case STREAM_QUIT:
/* Time to go - make thread exit */
td->state = TSTATE_EOS;
@@ -802,6 +792,8 @@ static void video_thread(void)
if (td.info->display_fbuf == NULL)
break; /* No picture */
+ td.syncf_perfect = 1; /* yes, a frame exists */
+
/* Get presentation times in audio samples - quite accurate
enough - add previous frame duration if not stamped */
td.curr_time = (td.info->display_picture->flags & PIC_FLAG_TAGS) ?
@@ -902,8 +894,8 @@ static void video_thread(void)
{
/* This frame was set to skip so skip it after having updated
timing information */
- td.num_skipped++;
td.eta_early = INT32_MIN;
+ video_num_skipped++;
goto picture_skip;
}
@@ -913,8 +905,8 @@ static void video_thread(void)
/* Render drop was set previously but nothing was dropped in the
decoder or it's been to long since drawing the last frame. */
td.skip_level = 0;
- td.num_skipped++;
td.eta_early = INT32_MIN;
+ video_num_skipped++;
goto picture_skip;
}
@@ -970,18 +962,11 @@ static void video_thread(void)
picture_draw:
/* Record last frame time */
td.last_render = *rb->current_tick;
+
vo_draw_frame(td.info->display_fbuf->buf);
- td.num_drawn++;
+ video_num_drawn++;
picture_skip:
- if (!settings.showfps)
- break;
-
- if (TIME_BEFORE(*rb->current_tick, td.last_showfps + HZ))
- break;
-
- /* Calculate and display fps */
- draw_fps(&td);
break;
}
@@ -1032,3 +1017,19 @@ void video_thread_exit(void)
video_str.thread = 0;
}
}
+
+
+/** Misc **/
+void video_thread_get_stats(struct video_output_stats *s)
+{
+ uint32_t start;
+ uint32_t now = stream_get_ticks(&start);
+ s->num_drawn = video_num_drawn;
+ s->num_skipped = video_num_skipped;
+
+ s->fps = 0;
+
+ if (now > start)
+ s->fps = muldiv_uint32(CLOCK_RATE*100, s->num_drawn, now - start);
+}
+