1
mirror of https://github.com/mpv-player/mpv synced 2024-08-04 14:59:58 +02:00

core: remove looping in update_video(), modify command handling a bit

Let higher-level code call update_video() again instead of looping
inside it until there's a frame ready to show. Change the conditions
for running user commands somewhat. Overall effect shouldn't be that
big. Now other commands can be executed after a seek before a video
frame is decoded; in this case the seek target time may be used as the
"current position".
This commit is contained in:
Uoti Urpala 2010-12-15 01:02:14 +02:00
parent de3be1d9ca
commit 00c2bafb0a
2 changed files with 47 additions and 27 deletions

View File

@ -152,6 +152,9 @@ typedef struct MPContext {
* (or at least queued to be flipped by VO) */
double video_pts;
// used to prevent hanging in some error cases
unsigned int start_timestamp;
// Timestamp from the last time some timing functions read the
// current time, in (occasionally wrapping) microseconds. Used
// to turn a new time value to a delta from last time.

View File

@ -2457,13 +2457,13 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx)
struct sh_video *sh_video = mpctx->sh_video;
double frame_time = 0;
struct vo *video_out = mpctx->video_out;
while (!video_out->frame_loaded) {
while (1) {
current_module = "filter_video";
// In nocorrect-pts mode there is no way to properly time these frames
if (vo_get_buffered_frame(video_out, 0) >= 0)
break;
if (vf_output_queued_frame(sh_video->vfilter))
continue;
break;
unsigned char *packet = NULL;
frame_time = sh_video->next_frame_time;
if (mpctx->restart_playback)
@ -2507,10 +2507,9 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx)
#endif
if (decoded_frame) {
current_module = "filter video";
if (filter_video(sh_video, decoded_frame, sh_video->pts))
if (!video_out->config_ok)
break;
filter_video(sh_video, decoded_frame, sh_video->pts);
}
break;
}
return frame_time;
}
@ -2557,21 +2556,19 @@ static double update_video(struct MPContext *mpctx)
double pts;
bool hit_eof = false;
while (!video_out->frame_loaded) {
while (1) {
current_module = "filter_video";
if (vo_get_buffered_frame(video_out, hit_eof) >= 0)
if (vo_get_buffered_frame(video_out, false) >= 0)
break;
// XXX Time used in this call is not counted in any performance
// timer now, OSD time is not updated correctly for filter-added frames
// timer now
if (vf_output_queued_frame(sh_video->vfilter))
continue;
if (hit_eof)
return -1;
break;
unsigned char *packet = NULL;
int in_size = ds_get_packet_pts(mpctx->d_video, &packet, &pts);
if (pts != MP_NOPTS_VALUE)
pts += mpctx->video_offset;
bool hit_eof = false;
if (in_size < 0) {
// try to extract last frames in case of decoder lag
in_size = 0;
@ -2587,12 +2584,17 @@ static double update_video(struct MPContext *mpctx)
if (decoded_frame) {
determine_frame_pts(mpctx);
current_module = "filter video";
if (filter_video(sh_video, decoded_frame, sh_video->pts))
if (!video_out->config_ok)
break; // We'd likely hang in this loop otherwise
filter_video(sh_video, decoded_frame, sh_video->pts);
} else if (hit_eof) {
if (vo_get_buffered_frame(video_out, true) < 0)
return -1;
}
break;
}
if (!video_out->frame_loaded)
return 0;
pts = video_out->next_pts;
if (pts == MP_NOPTS_VALUE) {
mp_msg(MSGT_CPLAYER, MSGL_ERR, "Video pts after filters MISSING\n");
@ -2880,9 +2882,10 @@ static int seek(MPContext *mpctx, double amount, int style)
* during initialization, so reinit must be done after the demux_seek()
* call that clears possible stream EOF. */
bool need_reset = false;
double demuxer_amount = amount;
if (mpctx->timeline) {
amount = timeline_set_from_time(mpctx, amount, &need_reset);
if (amount == -1) {
demuxer_amount = timeline_set_from_time(mpctx, amount, &need_reset);
if (demuxer_amount == -1) {
mpctx->stop_play = AT_END_OF_FILE;
// Clear audio from current position
if (mpctx->sh_audio) {
@ -2893,13 +2896,22 @@ static int seek(MPContext *mpctx, double amount, int style)
return -1;
}
}
int seekresult = demux_seek(mpctx->demuxer, amount, audio_delay, style);
int seekresult = demux_seek(mpctx->demuxer, demuxer_amount, audio_delay,
style);
if (need_reset)
reinit_decoders(mpctx);
if (seekresult == 0)
return -1;
seek_reset(mpctx);
/* Use the target time as "current position" for further relative
* seeks etc until a new video frame has been decoded */
if ((style & (SEEK_ABSOLUTE | SEEK_FACTOR)) == SEEK_ABSOLUTE)
mpctx->video_pts = amount;
mpctx->start_timestamp = GetTimerMS();
return 0;
}
@ -3051,6 +3063,7 @@ static void run_playloop(struct MPContext *mpctx)
if (!mpctx->sh_video) {
mpctx->restart_playback = false;
// handle audio-only case:
double a_pos = 0;
// sh_audio can be NULL due to video stream switching
@ -3253,21 +3266,25 @@ static void run_playloop(struct MPContext *mpctx)
while (1) {
mp_cmd_t *cmd;
while ((cmd = mp_input_get_cmd(mpctx->input, 0, 0)) != NULL) {
while ((cmd = mp_input_get_cmd(mpctx->input, 0, 1)) != NULL) {
/* Allow running consecutive seek commands to combine them,
* but execute the seek before running other commands.
* If the user seeks continuously (keeps arrow key down)
* try to finish showing a frame from one location before doing
* another seek (which could lead to unchanging display). */
if ((mpctx->rel_seek_secs || mpctx->abs_seek_pos)
&& cmd->id != MP_CMD_SEEK
|| mpctx->restart_playback && cmd->id == MP_CMD_SEEK
&& GetTimerMS() - mpctx->start_timestamp < 300)
break;
cmd = mp_input_get_cmd(mpctx->input, 0, 0);
run_command(mpctx, cmd);
mp_cmd_free(cmd);
if (mpctx->stop_play)
break;
if (mpctx->rel_seek_secs || mpctx->abs_seek_pos) {
cmd = mp_input_get_cmd(mpctx->input, 0, 1);
/* Allow seek commands to be combined, but execute the real seek
* before processing other commands */
if (!cmd || cmd->id != MP_CMD_SEEK)
break;
}
}
if (!mpctx->paused || mpctx->stop_play || mpctx->rel_seek_secs
|| mpctx->abs_seek_pos)
|| mpctx->abs_seek_pos || mpctx->restart_playback)
break;
if (mpctx->sh_video) {
update_osd_msg(mpctx);