mirror of
https://github.com/mpv-player/mpv
synced 2024-12-25 16:33:02 +00:00
core: audio: improve audio-only seeks and position reporting
Seeking while paused could result in the current audio pts being reported incorrectly due to relevant variables not being reinitialized after the seek until more audio was played. When playing audio-only files, this meant that current overall playback position could be reported incorrectly which in turn could break further seeks. Improve things on two levels: First, store the seek target position and use that as the current playback position for audio-only files until things can be reinitialized. Second, try to reinitialize audio decoding enough to know its current pts even while paused. Also avoid printing the actual huge negative value of MP_NOPTS_VALUE on the status line when pts could not be determined.
This commit is contained in:
parent
f1bb6fde32
commit
ec72cb7a73
@ -159,6 +159,7 @@ typedef struct MPContext {
|
||||
/* timestamp of video frame currently visible on screen
|
||||
* (or at least queued to be flipped by VO) */
|
||||
double video_pts;
|
||||
double last_seek_pts;
|
||||
|
||||
// used to prevent hanging in some error cases
|
||||
unsigned int start_timestamp;
|
||||
|
40
mplayer.c
40
mplayer.c
@ -1223,7 +1223,7 @@ static void sadd_hhmmssf(char *buf, unsigned *pos, int len, float time) {
|
||||
int ss = (tenths / 10) % 60;
|
||||
int mm = (tenths / 600) % 60;
|
||||
int hh = tenths / 36000;
|
||||
if (time <= 0) {
|
||||
if (time < 0) {
|
||||
saddf(buf, pos, len, "unknown");
|
||||
return;
|
||||
}
|
||||
@ -1254,6 +1254,8 @@ static void print_status(struct MPContext *mpctx, double a_pos, bool at_frame)
|
||||
if (opts->quiet)
|
||||
return;
|
||||
|
||||
if (a_pos == MP_NOPTS_VALUE)
|
||||
a_pos = -9; // don't print a huge negative number
|
||||
|
||||
int width;
|
||||
char *line;
|
||||
@ -2375,6 +2377,13 @@ static void adjust_sync(struct MPContext *mpctx, double frame_time)
|
||||
mpctx->total_avsync_change += change;
|
||||
}
|
||||
|
||||
static int write_to_ao(struct MPContext *mpctx, void *data, int len, int flags)
|
||||
{
|
||||
if (mpctx->paused)
|
||||
return 0;
|
||||
return ao_play(mpctx->ao, data, len, flags);
|
||||
}
|
||||
|
||||
#define ASYNC_PLAY_DONE -3
|
||||
static int audio_start_sync(struct MPContext *mpctx, int playsize)
|
||||
{
|
||||
@ -2442,7 +2451,7 @@ static int audio_start_sync(struct MPContext *mpctx, int playsize)
|
||||
* in playsize. */
|
||||
char *p = malloc(playsize);
|
||||
memset(p, fillbyte, playsize);
|
||||
playsize = ao_play(ao, p, playsize, 0);
|
||||
playsize = write_to_ao(mpctx, p, playsize, 0);
|
||||
free(p);
|
||||
mpctx->delay += opts->playback_speed*playsize/(double)ao->bps;
|
||||
return ASYNC_PLAY_DONE;
|
||||
@ -2475,6 +2484,9 @@ static int fill_audio_out_buffers(struct MPContext *mpctx)
|
||||
// sync completely wrong; there should be no need to use ao->pts
|
||||
// in get_space()
|
||||
ao->pts = ((mpctx->sh_video?mpctx->sh_video->timer:0)+mpctx->delay)*90000.0;
|
||||
if (mpctx->paused)
|
||||
playsize = 1; // just initialize things (audio pts at least)
|
||||
else
|
||||
playsize = ao_get_space(ao);
|
||||
|
||||
// Fill buffer if needed:
|
||||
@ -2535,7 +2547,7 @@ static int fill_audio_out_buffers(struct MPContext *mpctx)
|
||||
// They're obviously badly broken in the way they handle av sync;
|
||||
// would not having access to this make them more broken?
|
||||
ao->pts = ((mpctx->sh_video?mpctx->sh_video->timer:0)+mpctx->delay)*90000.0;
|
||||
int played = ao_play(ao, ao->buffer.start, playsize, playflags);
|
||||
int played = write_to_ao(mpctx, ao->buffer.start, playsize, playflags);
|
||||
assert(played % unitsize == 0);
|
||||
ao->buffer_playable_size = playsize - played;
|
||||
|
||||
@ -2543,7 +2555,7 @@ static int fill_audio_out_buffers(struct MPContext *mpctx)
|
||||
ao->buffer.len -= played;
|
||||
memmove(ao->buffer.start, ao->buffer.start + played, ao->buffer.len);
|
||||
mpctx->delay += opts->playback_speed * played / ao->bps;
|
||||
} else if (audio_eof && ao_get_delay(ao) < .04) {
|
||||
} else if (!mpctx->paused && audio_eof && ao_get_delay(ao) < .04) {
|
||||
// Sanity check to avoid hanging in case current ao doesn't output
|
||||
// partial chunks and doesn't check for AOPLAY_FINAL_CHUNK
|
||||
return -2;
|
||||
@ -3230,8 +3242,11 @@ static int seek(MPContext *mpctx, struct seek_params seek,
|
||||
|
||||
/* Use the target time as "current position" for further relative
|
||||
* seeks etc until a new video frame has been decoded */
|
||||
if (seek.type == MPSEEK_ABSOLUTE)
|
||||
if (seek.type == MPSEEK_ABSOLUTE) {
|
||||
mpctx->video_pts = seek.amount;
|
||||
mpctx->last_seek_pts = seek.amount;
|
||||
} else
|
||||
mpctx->last_seek_pts = MP_NOPTS_VALUE;
|
||||
|
||||
if (hr_seek) {
|
||||
mpctx->hrseek_active = true;
|
||||
@ -3317,7 +3332,10 @@ double get_current_time(struct MPContext *mpctx)
|
||||
struct sh_video *sh_video = demuxer->video->sh;
|
||||
if (sh_video)
|
||||
return mpctx->video_pts;
|
||||
return playing_audio_pts(mpctx);
|
||||
double apts = playing_audio_pts(mpctx);
|
||||
if (apts != MP_NOPTS_VALUE)
|
||||
return apts;
|
||||
return mpctx->last_seek_pts;
|
||||
}
|
||||
|
||||
int get_percent_pos(struct MPContext *mpctx)
|
||||
@ -3419,8 +3437,10 @@ static void run_playloop(struct MPContext *mpctx)
|
||||
|
||||
/*========================== PLAY AUDIO ============================*/
|
||||
|
||||
if (mpctx->sh_audio && !mpctx->paused
|
||||
&& (!mpctx->restart_playback || !mpctx->sh_video)) {
|
||||
if (!mpctx->sh_video)
|
||||
mpctx->restart_playback = false;
|
||||
|
||||
if (mpctx->sh_audio && !mpctx->restart_playback) {
|
||||
int status = fill_audio_out_buffers(mpctx);
|
||||
full_audio_buffers = status >= 0 && !mpctx->ao->untimed;
|
||||
if (status == -2)
|
||||
@ -3431,7 +3451,6 @@ static void run_playloop(struct MPContext *mpctx)
|
||||
|
||||
|
||||
if (!mpctx->sh_video) {
|
||||
mpctx->restart_playback = false;
|
||||
if (mpctx->step_frames) {
|
||||
mpctx->step_frames = 0;
|
||||
pause_player(mpctx);
|
||||
@ -3597,7 +3616,7 @@ static void run_playloop(struct MPContext *mpctx)
|
||||
}
|
||||
if (mpctx->restart_playback) {
|
||||
mpctx->syncing_audio = true;
|
||||
if (mpctx->sh_audio && !mpctx->paused)
|
||||
if (mpctx->sh_audio)
|
||||
fill_audio_out_buffers(mpctx);
|
||||
mpctx->restart_playback = false;
|
||||
mpctx->time_frame = 0;
|
||||
@ -4790,6 +4809,7 @@ if(play_n_frames==0){
|
||||
mpctx->drop_message_shown = 0;
|
||||
mpctx->restart_playback = true;
|
||||
mpctx->video_pts = 0;
|
||||
mpctx->last_seek_pts = 0;
|
||||
mpctx->hrseek_active = false;
|
||||
mpctx->hrseek_framedrop = false;
|
||||
mpctx->step_frames = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user