forked from len0rd/rockbox
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
This commit is contained in:
parent
fd01bf3e4c
commit
31af1a3ac2
5 changed files with 124 additions and 126 deletions
|
@ -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;
|
||||
|
||||
if (video_str.thread != 0 && disk_buf.in_file >= 0)
|
||||
stream_scan_init(&sk);
|
||||
|
||||
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;
|
||||
|
||||
case VIDEO_PRINT_FRAME:
|
||||
if (data)
|
||||
break;
|
||||
case VIDEO_PRINT_THUMBNAIL:
|
||||
if (disk_buf_status() != STREAM_STOPPED)
|
||||
break; /* Prepare image if not playing */
|
||||
|
||||
if (!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);
|
||||
DEBUGF("Image was ready\n");
|
||||
return true; /* Should already have the image */
|
||||
}
|
||||
|
||||
return retval;
|
||||
#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;
|
||||
}
|
||||
|
||||
/* 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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue