summaryrefslogtreecommitdiffstats
path: root/player/playloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'player/playloop.c')
-rw-r--r--player/playloop.c102
1 files changed, 71 insertions, 31 deletions
diff --git a/player/playloop.c b/player/playloop.c
index 6cff3c9108..12239d69ab 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -23,7 +23,6 @@
#include "client.h"
#include "command.h"
-#include "config.h"
#include "core.h"
#include "mpv_talloc.h"
#include "screenshot.h"
@@ -33,7 +32,6 @@
#include "common/encode.h"
#include "common/msg.h"
#include "common/playlist.h"
-#include "common/recorder.h"
#include "common/stats.h"
#include "demux/demux.h"
#include "filters/f_decoder_wrapper.h"
@@ -77,7 +75,7 @@ void mp_set_timeout(struct MPContext *mpctx, double sleeptime)
{
if (mpctx->sleeptime > sleeptime) {
mpctx->sleeptime = sleeptime;
- int64_t abstime = mp_add_timeout(mp_time_us(), sleeptime);
+ int64_t abstime = mp_time_ns_add(mp_time_ns(), sleeptime);
mp_dispatch_adjust_timeout(mpctx->dispatch, abstime);
}
}
@@ -110,21 +108,25 @@ void mp_core_unlock(struct MPContext *mpctx)
// Process any queued user input.
static void mp_process_input(struct MPContext *mpctx)
{
+ int processed = 0;
for (;;) {
mp_cmd_t *cmd = mp_input_read_cmd(mpctx->input);
if (!cmd)
break;
run_command(mpctx, cmd, NULL, NULL, NULL);
+ processed = 1;
}
mp_set_timeout(mpctx, mp_input_get_delay(mpctx->input));
+ if (processed)
+ mp_notify(mpctx, MP_EVENT_INPUT_PROCESSED, NULL);
}
double get_relative_time(struct MPContext *mpctx)
{
- int64_t new_time = mp_time_us();
+ int64_t new_time = mp_time_ns();
int64_t delta = new_time - mpctx->last_time;
mpctx->last_time = new_time;
- return delta * 0.000001;
+ return delta * 1e-9;
}
void update_core_idle_state(struct MPContext *mpctx)
@@ -159,8 +161,10 @@ void set_pause_state(struct MPContext *mpctx, bool user_pause)
if (internal_paused != mpctx->paused) {
mpctx->paused = internal_paused;
- if (mpctx->ao)
- ao_set_paused(mpctx->ao, internal_paused);
+ if (mpctx->ao) {
+ bool eof = mpctx->audio_status == STATUS_EOF;
+ ao_set_paused(mpctx->ao, internal_paused, eof);
+ }
if (mpctx->video_out)
vo_set_paused(mpctx->video_out, internal_paused);
@@ -176,10 +180,6 @@ void set_pause_state(struct MPContext *mpctx, bool user_pause)
} else {
(void)get_relative_time(mpctx); // ignore time that passed during pause
}
-
- // For some reason, these events are supposed to be sent even if only
- // the internal pause state changed (and "pause" property didn't)... OK.
- mp_notify(mpctx, opts->pause ? MPV_EVENT_PAUSE : MPV_EVENT_UNPAUSE, 0);
}
update_core_idle_state(mpctx);
@@ -197,7 +197,8 @@ void update_screensaver_state(struct MPContext *mpctx)
if (!mpctx->video_out)
return;
- bool saver_state = !mpctx->playback_active || !mpctx->opts->stop_screensaver;
+ bool saver_state = (!mpctx->playback_active || !mpctx->opts->stop_screensaver) &&
+ mpctx->opts->stop_screensaver != 2;
vo_control_async(mpctx->video_out, saver_state ? VOCTRL_RESTORE_SCREENSAVER
: VOCTRL_KILL_SCREENSAVER, NULL);
}
@@ -235,6 +236,10 @@ void reset_playback_state(struct MPContext *mpctx)
sub_set_play_dir(t->d_sub, mpctx->play_dir);
}
+ // May need unpause first
+ if (mpctx->paused_for_cache)
+ update_internal_pause_state(mpctx);
+
mpctx->hrseek_active = false;
mpctx->hrseek_lastframe = false;
mpctx->hrseek_backstep = false;
@@ -260,6 +265,13 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek)
if (!mpctx->demuxer || !seek.type || seek.amount == MP_NOPTS_VALUE)
return;
+ if (seek.type == MPSEEK_CHAPTER) {
+ mpctx->last_chapter_flag = false;
+ seek.type = MPSEEK_ABSOLUTE;
+ } else {
+ mpctx->last_chapter_seek = -2;
+ }
+
bool hr_seek_very_exact = seek.exact == MPSEEK_VERY_EXACT;
double current_time = get_playback_time(mpctx);
if (current_time == MP_NOPTS_VALUE && seek.type == MPSEEK_RELATIVE)
@@ -286,7 +298,7 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek)
if (len >= 0)
seek_pts = seek.amount * len;
break;
- default: abort();
+ default: MP_ASSERT_UNREACHABLE();
}
double demux_pts = seek_pts;
@@ -296,10 +308,6 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek)
(opts->hr_seek >= 0 && seek.type == MPSEEK_ABSOLUTE) ||
(opts->hr_seek == 2 && (!mpctx->vo_chain || mpctx->vo_chain->is_sparse)));
- if (seek.type == MPSEEK_FACTOR || seek.amount < 0 ||
- (seek.type == MPSEEK_ABSOLUTE && seek.amount < mpctx->last_chapter_pts))
- mpctx->last_chapter_seek = -2;
-
// Under certain circumstances, prefer SEEK_FACTOR.
if (seek.type == MPSEEK_FACTOR && !hr_seek &&
(mpctx->demuxer->ts_resets_possible || seek_pts == MP_NOPTS_VALUE))
@@ -367,8 +375,6 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek)
clear_audio_output_buffers(mpctx);
reset_playback_state(mpctx);
- if (mpctx->recorder)
- mp_recorder_mark_discontinuity(mpctx->recorder);
demux_block_reading(mpctx->demuxer, false);
for (int t = 0; t < mpctx->num_tracks; t++) {
@@ -413,6 +419,7 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek)
update_ab_loop_clip(mpctx);
mpctx->current_seek = seek;
+ redraw_subs(mpctx);
}
// This combines consecutive seek requests.
@@ -442,6 +449,7 @@ void queue_seek(struct MPContext *mpctx, enum seek_type type, double amount,
case MPSEEK_ABSOLUTE:
case MPSEEK_FACTOR:
case MPSEEK_BACKSTEP:
+ case MPSEEK_CHAPTER:
*seek = (struct seek_params) {
.type = type,
.amount = amount,
@@ -453,7 +461,7 @@ void queue_seek(struct MPContext *mpctx, enum seek_type type, double amount,
*seek = (struct seek_params){ 0 };
return;
}
- abort();
+ MP_ASSERT_UNREACHABLE();
}
void execute_queued_seek(struct MPContext *mpctx)
@@ -579,7 +587,8 @@ int get_current_chapter(struct MPContext *mpctx)
for (i = 0; i < mpctx->num_chapters; i++)
if (current_pts < mpctx->chapters[i].pts)
break;
- return MPMAX(mpctx->last_chapter_seek, i - 1);
+ return mpctx->last_chapter_flag ?
+ mpctx->last_chapter_seek : MPMAX(mpctx->last_chapter_seek, i - 1);
}
char *chapter_display_name(struct MPContext *mpctx, int chapter)
@@ -657,6 +666,9 @@ static void handle_osd_redraw(struct MPContext *mpctx)
if (!want_redraw)
return;
vo_redraw(mpctx->video_out);
+ // Even though we just redrew, it may need to be done again for certain
+ // cases of subtitles on an image.
+ redraw_subs(mpctx);
}
static void clear_underruns(struct MPContext *mpctx)
@@ -791,6 +803,22 @@ int get_cache_buffering_percentage(struct MPContext *mpctx)
return mpctx->demuxer ? mpctx->cache_buffer : -1;
}
+static void handle_update_subtitles(struct MPContext *mpctx)
+{
+ if (mpctx->video_status == STATUS_EOF) {
+ update_subtitles(mpctx, mpctx->playback_pts);
+ return;
+ }
+
+ for (int n = 0; n < mpctx->num_tracks; n++) {
+ struct track *track = mpctx->tracks[n];
+ if (track->type == STREAM_SUB && !track->demuxer_ready) {
+ update_subtitles(mpctx, mpctx->playback_pts);
+ break;
+ }
+ }
+}
+
static void handle_cursor_autohide(struct MPContext *mpctx)
{
struct MPOpts *opts = mpctx->opts;
@@ -937,13 +965,16 @@ static void handle_keep_open(struct MPContext *mpctx)
{
struct MPOpts *opts = mpctx->opts;
if (opts->keep_open && mpctx->stop_play == AT_END_OF_FILE &&
- (opts->keep_open == 2 || !playlist_get_next(mpctx->playlist, 1)) &&
- opts->loop_times == 1)
+ (opts->keep_open == 2 ||
+ (!playlist_get_next(mpctx->playlist, 1) && opts->loop_times == 1)))
{
mpctx->stop_play = KEEP_PLAYING;
if (mpctx->vo_chain) {
- if (!vo_has_frame(mpctx->video_out)) // EOF not reached normally
+ if (!vo_has_frame(mpctx->video_out)) { // EOF not reached normally
seek_to_last_frame(mpctx);
+ mpctx->audio_status = STATUS_EOF;
+ mpctx->video_status = STATUS_EOF;
+ }
}
if (opts->keep_open_pause) {
if (mpctx->ao && ao_is_playing(mpctx->ao))
@@ -958,7 +989,7 @@ static void handle_chapter_change(struct MPContext *mpctx)
int chapter = get_current_chapter(mpctx);
if (chapter != mpctx->last_chapter) {
mpctx->last_chapter = chapter;
- mp_notify(mpctx, MPV_EVENT_CHAPTER_CHANGE, NULL);
+ mp_notify(mpctx, MP_EVENT_CHAPTER_CHANGE, NULL);
}
}
@@ -1019,15 +1050,22 @@ int handle_force_window(struct MPContext *mpctx, bool force)
break;
}
}
+
+ // Use a 16:9 aspect ratio so that fullscreen on a 16:9 screen will not
+ // have vertical margins, which can lead to a different size or position
+ // of subtitles than with 16:9 videos.
int w = 960;
- int h = 480;
+ int h = 540;
struct mp_image_params p = {
.imgfmt = config_format,
.w = w, .h = h,
.p_w = 1, .p_h = 1,
+ .force_window = true,
};
if (vo_reconfig(vo, &p) < 0)
goto err;
+ struct track *track = mpctx->current_track[0][STREAM_VIDEO];
+ update_content_type(mpctx, track);
update_screensaver_state(mpctx);
vo_set_paused(vo, true);
vo_redraw(vo);
@@ -1074,8 +1112,7 @@ static void handle_playback_time(struct MPContext *mpctx)
} else if (mpctx->video_status == STATUS_EOF &&
mpctx->audio_status == STATUS_EOF)
{
- double apts =
- mpctx->ao_chain ? mpctx->ao_chain->last_out_pts : MP_NOPTS_VALUE;
+ double apts = playing_audio_pts(mpctx);
double vpts = mpctx->video_pts;
double mpts = MP_PTS_MAX(apts, vpts);
if (mpts != MP_NOPTS_VALUE)
@@ -1119,6 +1156,7 @@ static void handle_playback_restart(struct MPContext *mpctx)
mpctx->hrseek_active = false;
mpctx->restart_complete = true;
mpctx->current_seek = (struct seek_params){0};
+ run_command_opts(mpctx);
handle_playback_time(mpctx);
mp_notify(mpctx, MPV_EVENT_PLAYBACK_RESTART, NULL);
update_core_idle_state(mpctx);
@@ -1134,7 +1172,9 @@ static void handle_playback_restart(struct MPContext *mpctx)
if (opts->osd_playing_msg && opts->osd_playing_msg[0]) {
char *msg =
mp_property_expand_escaped_string(mpctx, opts->osd_playing_msg);
- set_osd_msg(mpctx, 1, opts->osd_duration, "%s", msg);
+ set_osd_msg(mpctx, 1, opts->osd_playing_msg_duration ?
+ opts->osd_playing_msg_duration : opts->osd_duration,
+ "%s", msg);
talloc_free(msg);
}
}
@@ -1209,8 +1249,8 @@ void run_playloop(struct MPContext *mpctx)
handle_dummy_ticks(mpctx);
update_osd_msg(mpctx);
- if (mpctx->video_status == STATUS_EOF)
- update_subtitles(mpctx, mpctx->playback_pts);
+
+ handle_update_subtitles(mpctx);
handle_each_frame_screenshot(mpctx);