From 2fbc1e71caacbe2588c278803f7e93af7e8264f3 Mon Sep 17 00:00:00 2001 From: jethead71 Date: Sun, 19 Dec 2010 08:28:03 +0000 Subject: [PATCH] MPEGPlayer: Move some code that's probably better situated in the stream manager rather than the parser. Fix visibility checking in video out. Extra message sending for new stream isn't needed; just do full decoder sequence reset when requesting dimensions. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28855 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/mpegplayer/mpeg_parser.c | 172 +++++++++++----------------- apps/plugins/mpegplayer/parser.h | 2 +- apps/plugins/mpegplayer/stream_mgr.c | 48 +++++++- apps/plugins/mpegplayer/video_out_rockbox.c | 6 +- apps/plugins/mpegplayer/video_thread.c | 12 +- 5 files changed, 119 insertions(+), 121 deletions(-) diff --git a/apps/plugins/mpegplayer/mpeg_parser.c b/apps/plugins/mpegplayer/mpeg_parser.c index 1be11a467..b683efe1c 100644 --- a/apps/plugins/mpegplayer/mpeg_parser.c +++ b/apps/plugins/mpegplayer/mpeg_parser.c @@ -564,84 +564,6 @@ static off_t mpeg_parser_seek_PTS(uint32_t time, unsigned id) return pos; } -static bool prepare_image(uint32_t time) -{ - struct stream_scan sk; - int tries; - int result; - - stream_scan_init(&sk); - - if (!str_send_msg(&video_str, STREAM_NEEDS_SYNC, time)) - { - DEBUGF("Image was ready\n"); - return true; /* Should already have the image */ - } - -#ifdef HAVE_ADJUSTABLE_CPU_FREQ - rb->cpu_boost(true); /* No interference with trigger_cpu_boost */ -#endif - - str_send_msg(&video_str, STREAM_RESET, 0); - - sk.pos = parser_can_seek() ? - mpeg_parser_seek_PTS(time, video_str.id) : 0; - sk.len = sk.pos; - sk.dir = SSCAN_REVERSE; - - tries = 1; -try_again: - - if (mpeg_parser_scan_start_code(&sk, MPEG_START_GOP)) - { - DEBUGF("GOP found at: %ld\n", sk.pos); - - unsigned id = mpeg_parser_scan_pes(&sk); - - if (id != video_str.id && sk.pos > 0) - { - /* Not part of our stream */ - DEBUGF(" wrong stream: 0x%02x\n", id); - goto try_again; - } - - /* This will hit the PES header since it's known to be there */ - uint32_t pts = mpeg_parser_scan_pts(&sk, id); - - if (pts == INVALID_TIMESTAMP || pts > time) - { - DEBUGF(" wrong timestamp: %u\n", (unsigned)pts); - goto try_again; - } - } - - str_parser.parms.sd.time = time; - str_parser.parms.sd.sk.pos = MAX(sk.pos, 0); - str_parser.parms.sd.sk.len = 1024*1024; - str_parser.parms.sd.sk.dir = SSCAN_FORWARD; - - DEBUGF("thumb pos:%ld len:%ld\n", str_parser.parms.sd.sk.pos, - (long)str_parser.parms.sd.sk.len); - - result = str_send_msg(&video_str, STREAM_SYNC, - (intptr_t)&str_parser.parms.sd); - - if (result != STREAM_PERFECT_MATCH) - { - /* Two tries should be all that is nescessary to find the exact frame - * if the first GOP actually started later than the timestamp - the - * GOP just prior must then start on or earlier. */ - if (++tries <= 2) - goto try_again; - } - -#ifdef HAVE_ADJUSTABLE_CPU_FREQ - rb->cpu_boost(false); -#endif - - return result > STREAM_OK; -} - static void prepare_audio(uint32_t time) { off_t pos; @@ -1037,41 +959,82 @@ static int parse_elementary(struct stream *str, enum stream_parse_mode type) return STREAM_OK; } -intptr_t parser_send_video_msg(long id, intptr_t data) +bool parser_prepare_image(uint32_t time) { - intptr_t retval = 0; + struct stream_scan sk; + int tries; + int result; + + stream_scan_init(&sk); - if (video_str.thread != 0 && disk_buf.in_file >= 0) + if (!str_send_msg(&video_str, STREAM_NEEDS_SYNC, time)) { - /* Hook certain messages since they involve multiple operations - * behind the scenes */ - switch (id) - { - case VIDEO_DISPLAY_SHOW: - if (data != 0 && disk_buf_status() == STREAM_STOPPED) - { /* Only prepare image if showing and not playing */ - prepare_image(str_parser.last_seek_time); - } - break; + DEBUGF("Image was ready\n"); + return true; /* Should already have the image */ + } - case VIDEO_PRINT_FRAME: - if (data) - break; - case VIDEO_PRINT_THUMBNAIL: - if (disk_buf_status() != STREAM_STOPPED) - break; /* Prepare image if not playing */ +#ifdef HAVE_ADJUSTABLE_CPU_FREQ + rb->cpu_boost(true); /* No interference with trigger_cpu_boost */ +#endif - if (!prepare_image(str_parser.last_seek_time)) - return false; /* Preparation failed */ + str_send_msg(&video_str, STREAM_RESET, 0); - /* Image ready - pass message to video thread */ - break; + sk.pos = parser_can_seek() ? + mpeg_parser_seek_PTS(time, video_str.id) : 0; + sk.len = sk.pos; + sk.dir = SSCAN_REVERSE; + + tries = 1; +try_again: + + if (mpeg_parser_scan_start_code(&sk, MPEG_START_GOP)) + { + DEBUGF("GOP found at: %ld\n", sk.pos); + + unsigned id = mpeg_parser_scan_pes(&sk); + + if (id != video_str.id && sk.pos > 0) + { + /* Not part of our stream */ + DEBUGF(" wrong stream: 0x%02x\n", id); + goto try_again; + } + + /* This will hit the PES header since it's known to be there */ + uint32_t pts = mpeg_parser_scan_pts(&sk, id); + + if (pts == INVALID_TIMESTAMP || pts > time) + { + DEBUGF(" wrong timestamp: %u\n", (unsigned)pts); + goto try_again; } + } + + str_parser.parms.sd.time = time; + str_parser.parms.sd.sk.pos = MAX(sk.pos, 0); + str_parser.parms.sd.sk.len = 1024*1024; + str_parser.parms.sd.sk.dir = SSCAN_FORWARD; - retval = str_send_msg(&video_str, id, data); + DEBUGF("thumb pos:%ld len:%ld\n", str_parser.parms.sd.sk.pos, + (long)str_parser.parms.sd.sk.len); + + result = str_send_msg(&video_str, STREAM_SYNC, + (intptr_t)&str_parser.parms.sd); + + if (result != STREAM_PERFECT_MATCH) + { + /* Two tries should be all that is nescessary to find the exact frame + * if the first GOP actually started later than the timestamp - the + * GOP just prior must then start on or earlier. */ + if (++tries <= 2) + goto try_again; } - return retval; +#ifdef HAVE_ADJUSTABLE_CPU_FREQ + rb->cpu_boost(false); +#endif + + return result > STREAM_OK; } /* Seek parser to the specified time and return absolute time. @@ -1095,7 +1058,7 @@ void parser_prepare_streaming(void) DEBUGF("parser_prepare_streaming\n"); /* Prepare initial video frame */ - prepare_image(str_parser.last_seek_time); + parser_prepare_image(str_parser.last_seek_time); /* Sync audio stream */ if (audio_str.start_pts != INVALID_TIMESTAMP) @@ -1215,7 +1178,6 @@ int parser_init_stream(void) void parser_close_stream(void) { - str_send_msg(&video_str, STREAM_CLOSE, 0); stream_remove_streams(); parser_init_state(); } diff --git a/apps/plugins/mpegplayer/parser.h b/apps/plugins/mpegplayer/parser.h index 4c58d2b6e..ba2181e98 100644 --- a/apps/plugins/mpegplayer/parser.h +++ b/apps/plugins/mpegplayer/parser.h @@ -86,7 +86,7 @@ off_t mpeg_stream_stream_seek_PTS(uint32_t time, int id); /* General parsing */ bool parser_init(void); void str_initialize(struct stream *str, off_t pos); -intptr_t parser_send_video_msg(long id, intptr_t data); +bool parser_prepare_image(uint32_t time); bool parser_get_video_size(struct vo_ext *sz); int parser_init_stream(void); void parser_close_stream(void); diff --git a/apps/plugins/mpegplayer/stream_mgr.c b/apps/plugins/mpegplayer/stream_mgr.c index b88c6d70c..67ec16cbb 100644 --- a/apps/plugins/mpegplayer/stream_mgr.c +++ b/apps/plugins/mpegplayer/stream_mgr.c @@ -668,13 +668,51 @@ void stream_clear_notify(struct stream *str, int for_msg) } } +/* Special handling for certain messages since they involve multiple + * operations behind the scenes */ +static intptr_t send_video_msg(long id, intptr_t data) +{ + intptr_t retval = 0; + + if (video_str.thread != 0 && disk_buf.in_file >= 0) + { + + switch (id) + { + case VIDEO_DISPLAY_SHOW: + if (data != 0 && disk_buf_status() == STREAM_STOPPED) + { /* Only prepare image if showing and not playing */ + parser_prepare_image(str_parser.last_seek_time); + } + break; + + case VIDEO_PRINT_FRAME: + if (data) + break; + case VIDEO_PRINT_THUMBNAIL: + if (disk_buf_status() != STREAM_STOPPED) + break; /* Prepare image if not playing */ + + if (!parser_prepare_image(str_parser.last_seek_time)) + return false; /* Preparation failed */ + + /* Image ready - pass message to video thread */ + break; + } + + retval = str_send_msg(&video_str, id, data); + } + + return retval; +} + /* Show/hide the video output */ bool stream_show_vo(bool show) { bool vis; stream_mgr_lock(); - vis = parser_send_video_msg(VIDEO_DISPLAY_SHOW, show); + vis = send_video_msg(VIDEO_DISPLAY_SHOW, show); #ifndef HAVE_LCD_COLOR grey_show(show); #endif @@ -688,7 +726,7 @@ bool stream_vo_is_visible(void) { bool vis; stream_mgr_lock(); - vis = parser_send_video_msg(VIDEO_DISPLAY_IS_VISIBLE, 0); + vis = send_video_msg(VIDEO_DISPLAY_IS_VISIBLE, 0); stream_mgr_unlock(); return vis; } @@ -721,7 +759,7 @@ void stream_vo_set_clip(const struct vo_rect *rc) rc = &stream_mgr.parms.rc; } - parser_send_video_msg(VIDEO_SET_CLIP_RECT, (intptr_t)rc); + send_video_msg(VIDEO_SET_CLIP_RECT, (intptr_t)rc); stream_mgr_unlock(); } @@ -750,7 +788,7 @@ bool stream_display_thumb(const struct vo_rect *rc) stream_mgr_lock(); stream_mgr.parms.rc = *rc; - retval = parser_send_video_msg(VIDEO_PRINT_THUMBNAIL, + retval = send_video_msg(VIDEO_PRINT_THUMBNAIL, (intptr_t)&stream_mgr.parms.rc); stream_mgr_unlock(); @@ -763,7 +801,7 @@ bool stream_draw_frame(bool no_prepare) bool retval; stream_mgr_lock(); - retval = parser_send_video_msg(VIDEO_PRINT_FRAME, no_prepare); + retval = send_video_msg(VIDEO_PRINT_FRAME, no_prepare); stream_mgr_unlock(); diff --git a/apps/plugins/mpegplayer/video_out_rockbox.c b/apps/plugins/mpegplayer/video_out_rockbox.c index cf47982ab..fe3deafd0 100644 --- a/apps/plugins/mpegplayer/video_out_rockbox.c +++ b/apps/plugins/mpegplayer/video_out_rockbox.c @@ -116,9 +116,11 @@ static inline void yuv_blit(uint8_t * const * buf, int src_x, int src_y, void vo_draw_frame(uint8_t * const * buf) { - if (vo.flags == 0) + if ((vo.flags & (VO_NON_NULL_RECT | VO_VISIBLE)) != + (VO_NON_NULL_RECT | VO_VISIBLE)) { - /* Frame is hidden - copout */ + /* Frame is hidden - either by being set invisible or is clipped + * away - copout */ DEBUGF("vo hidden\n"); return; } diff --git a/apps/plugins/mpegplayer/video_thread.c b/apps/plugins/mpegplayer/video_thread.c index 4ccdc8b84..69d94f8ba 100644 --- a/apps/plugins/mpegplayer/video_thread.c +++ b/apps/plugins/mpegplayer/video_thread.c @@ -124,7 +124,8 @@ static int video_str_scan(struct video_thread_data *td, tmp_str.hdr.pos = sd->sk.pos; tmp_str.hdr.limit = sd->sk.pos + sd->sk.len; - mpeg2_reset(td->mpeg2dec, false); + /* Fully reset if obtaining size for a new stream */ + mpeg2_reset(td->mpeg2dec, td->ev.id == VIDEO_GET_SIZE); mpeg2_skip(td->mpeg2dec, 1); while (1) @@ -503,12 +504,6 @@ static void video_thread_msg(struct video_thread_data *td) reply = true; break; - case STREAM_CLOSE: - vo_cleanup(); - mpeg2_close(td->mpeg2dec); - reply = true; - break; - case VIDEO_DISPLAY_IS_VISIBLE: reply = vo_is_visible(); break; @@ -605,8 +600,9 @@ static void video_thread_msg(struct video_thread_data *td) case VIDEO_GET_SIZE: { if (td->state != TSTATE_INIT) - break; + break; /* Can only use after a reset was issued */ + /* This will reset the decoder in full for this particular event */ if (init_sequence(td)) { reply = true; -- 2.11.4.GIT