diff --git a/options/m_option.h b/options/m_option.h index 7be8ae4b7b..4289fa5a2e 100644 --- a/options/m_option.h +++ b/options/m_option.h @@ -412,7 +412,9 @@ char *format_file_size(int64_t size); #define UPDATE_VOL (1 << 17) // softvol related options #define UPDATE_LAVFI_COMPLEX (1 << 18) // --lavfi-complex #define UPDATE_VO_RESIZE (1 << 19) // --android-surface-size -#define UPDATE_OPT_LAST (1 << 19) +#define UPDATE_HWDEC (1 << 20) // --hwdec +#define UPDATE_DVB_PROG (1 << 21) // some --dvbin-... +#define UPDATE_OPT_LAST (1 << 21) // All bits between _FIRST and _LAST (inclusive) #define UPDATE_OPTS_MASK \ diff --git a/player/audio.c b/player/audio.c index e8e129dc49..4f4b1992ae 100644 --- a/player/audio.c +++ b/player/audio.c @@ -486,6 +486,7 @@ void reinit_audio_chain_src(struct MPContext *mpctx, struct track *track) ao_c->last_out_pts = MP_NOPTS_VALUE; ao_c->ao_buffer = mp_audio_buffer_create(NULL); ao_c->ao = mpctx->ao; + ao_c->delay = mpctx->opts->audio_delay; if (track) { ao_c->track = track; diff --git a/player/command.c b/player/command.c index e640ba933e..9cd7ef2fc6 100644 --- a/player/command.c +++ b/player/command.c @@ -460,34 +460,14 @@ static int mp_property_playback_speed(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - double speed = mpctx->opts->playback_speed; - switch (action) { - case M_PROPERTY_SET: { - int r = mp_property_generic_option(mpctx, prop, action, arg); - update_playback_speed(mpctx); - mp_wakeup_core(mpctx); - return r; - } - case M_PROPERTY_PRINT: + if (action == M_PROPERTY_PRINT) { + double speed = mpctx->opts->playback_speed; *(char **)arg = talloc_asprintf(NULL, "%.2f", speed); return M_PROPERTY_OK; } return mp_property_generic_option(mpctx, prop, action, arg); } -static int mp_property_play_direction(void *ctx, struct m_property *prop, - int action, void *arg) -{ - MPContext *mpctx = ctx; - if (action == M_PROPERTY_SET) { - if (mpctx->play_dir != *(int *)arg) { - queue_seek(mpctx, MPSEEK_ABSOLUTE, get_current_time(mpctx), - MPSEEK_EXACT, 0); - } - } - return mp_property_generic_option(mpctx, prop, action, arg); -} - static int mp_property_av_speed_correction(void *ctx, struct m_property *prop, int action, void *arg) { @@ -1124,22 +1104,10 @@ static int mp_property_edition(void *ctx, struct m_property *prop, if (!mpctx->playback_initialized || !demuxer || demuxer->num_editions <= 0) return mp_property_generic_option(mpctx, prop, action, arg); - int edition = demuxer->edition; - switch (action) { case M_PROPERTY_GET: - *(int *)arg = edition; + *(int *)arg = demuxer->edition; return M_PROPERTY_OK; - case M_PROPERTY_SET: { - edition = *(int *)arg; - if (edition != demuxer->edition) { - if (!mpctx->stop_play) - mpctx->stop_play = PT_CURRENT_ENTRY; - mp_wakeup_core(mpctx); - break; // write value, trigger option change notify - } - return M_PROPERTY_OK; - } case M_PROPERTY_GET_CONSTRICTED_TYPE: { int r = mp_property_generic_option(mpctx, prop, M_PROPERTY_GET_TYPE, arg); ((struct m_option *)arg)->max = demuxer->num_editions - 1; @@ -1393,18 +1361,6 @@ static int mp_property_filter_metadata(void *ctx, struct m_property *prop, return M_PROPERTY_NOT_IMPLEMENTED; } -static int mp_property_pause(void *ctx, struct m_property *prop, - int action, void *arg) -{ - MPContext *mpctx = ctx; - - if (mpctx->playback_initialized && action == M_PROPERTY_SET) { - set_pause_state(mpctx, *(int *)arg); - return M_PROPERTY_OK; - } - return mp_property_generic_option(mpctx, prop, action, arg); -} - static int mp_property_core_idle(void *ctx, struct m_property *prop, int action, void *arg) { @@ -1678,10 +1634,7 @@ static int mp_property_mute(void *ctx, struct m_property *prop, return M_PROPERTY_OK; } - int r = mp_property_generic_option(mpctx, prop, action, arg); - if (action == M_PROPERTY_SET) - audio_update_volume(mpctx); - return r; + return mp_property_generic_option(mpctx, prop, action, arg); } static int mp_property_ao_volume(void *ctx, struct m_property *prop, @@ -1831,18 +1784,9 @@ static int mp_property_audio_delay(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - float delay = mpctx->opts->audio_delay; - switch (action) { - case M_PROPERTY_PRINT: - *(char **)arg = format_delay(delay); + if (action == M_PROPERTY_PRINT) { + *(char **)arg = format_delay(mpctx->opts->audio_delay); return M_PROPERTY_OK; - case M_PROPERTY_SET: { - int r = mp_property_generic_option(mpctx, prop, action, arg); - if (mpctx->ao_chain && mpctx->vo_chain) - mpctx->delay += mpctx->opts->audio_delay - delay; - mp_wakeup_core(mpctx); - return r; - } } return mp_property_generic_option(mpctx, prop, action, arg); } @@ -2150,38 +2094,6 @@ static int mp_property_video(void *ctx, struct m_property *prop, return property_switch_track(prop, action, arg, ctx, 0, STREAM_VIDEO); } -static int mp_property_hwdec(void *ctx, struct m_property *prop, - int action, void *arg) -{ - MPContext *mpctx = ctx; - struct track *track = mpctx->current_track[0][STREAM_VIDEO]; - struct mp_decoder_wrapper *dec = track ? track->dec : NULL; - - if (action == M_PROPERTY_SET) { - char *new = *(char **)arg; - char *old = NULL; - if (mp_property_generic_option(mpctx, prop, M_PROPERTY_GET, &old) < 1) - old = NULL; - - bool same = bstr_equals(bstr0(old), bstr0(new)); - - mp_property_generic_option(mpctx, prop, M_PROPERTY_SET, &new); - - talloc_free(old); - - if (!dec || same) - return M_PROPERTY_OK; - - mp_decoder_wrapper_control(dec, VDCTRL_REINIT, NULL); - double last_pts = mpctx->last_vo_pts; - if (last_pts != MP_NOPTS_VALUE) - queue_seek(mpctx, MPSEEK_ABSOLUTE, last_pts, MPSEEK_EXACT, 0); - - return M_PROPERTY_OK; - } - return mp_property_generic_option(mpctx, prop, action, arg); -} - static int mp_property_hwdec_current(void *ctx, struct m_property *prop, int action, void *arg) { @@ -2480,13 +2392,6 @@ static int mp_property_window_scale(void *ctx, struct m_property *prop, goto generic; switch (action) { - case M_PROPERTY_SET: { - double scale = *(double *)arg; - int s[2] = {vid_w * scale, vid_h * scale}; - if (s[0] > 0 && s[1] > 0) - vo_control(vo, VOCTRL_SET_UNFS_WINDOW_SIZE, s); - goto generic; - } case M_PROPERTY_GET: { int s[2]; if (vo_control(vo, VOCTRL_GET_UNFS_WINDOW_SIZE, s) <= 0 || @@ -2502,6 +2407,24 @@ generic: return mp_property_generic_option(mpctx, prop, action, arg); } +static void update_window_scale(struct MPContext *mpctx) +{ + struct vo *vo = mpctx->video_out; + if (!vo) + return; + + struct mp_image_params params = get_video_out_params(mpctx); + int vid_w, vid_h; + mp_image_params_get_dsize(¶ms, &vid_w, &vid_h); + if (vid_w < 1 || vid_h < 1) + return; + + double scale = mpctx->opts->vo->window_scale; + int s[2] = {vid_w * scale, vid_h * scale}; + if (s[0] > 0 && s[1] > 0) + vo_control(vo, VOCTRL_SET_UNFS_WINDOW_SIZE, s); +} + static int mp_property_win_minimized(void *ctx, struct m_property *prop, int action, void *arg) { @@ -2902,31 +2825,6 @@ static int mp_property_sub_end(void *ctx, struct m_property *prop, return m_property_double_ro(action, arg, end); } -static int mp_property_cursor_autohide(void *ctx, struct m_property *prop, - int action, void *arg) -{ - MPContext *mpctx = ctx; - struct MPOpts *opts = mpctx->opts; - int old_value = opts->cursor_autohide_delay; - int r = mp_property_generic_option(mpctx, prop, action, arg); - if (opts->cursor_autohide_delay != old_value) - mpctx->mouse_timer = 0; - return r; -} - -static int mp_property_dvb_channel(void *ctx, struct m_property *prop, - int action, void *arg) -{ - MPContext *mpctx = ctx; - int r = mp_property_generic_option(mpctx, prop, action, arg); - if (r == M_PROPERTY_OK && is_property_set(action, arg)) { - if (!mpctx->stop_play) { - mpctx->stop_play = PT_CURRENT_ENTRY; - } - } - return r; -} - static int mp_property_playlist_pos_x(void *ctx, struct m_property *prop, int action, void *arg, int base) { @@ -3110,14 +3008,7 @@ static int mp_property_ab_loop(void *ctx, struct m_property *prop, return property_time(action, arg, val); } - int r = mp_property_generic_option(mpctx, prop, action, arg); - if (r > 0 && action == M_PROPERTY_SET) { - update_ab_loop_clip(mpctx); - // Update if visible - set_osd_bar_chapters(mpctx, OSD_BAR_SEEK); - mp_wakeup_core(mpctx); - } - return r; + return mp_property_generic_option(mpctx, prop, action, arg); } static int mp_property_packet_bitrate(void *ctx, struct m_property *prop, @@ -3177,26 +3068,6 @@ static int mp_property_cwd(void *ctx, struct m_property *prop, return M_PROPERTY_NOT_IMPLEMENTED; } -static int mp_property_record_file(void *ctx, struct m_property *prop, - int action, void *arg) -{ - struct MPContext *mpctx = ctx; - struct MPOpts *opts = mpctx->opts; - if (action == M_PROPERTY_SET) { - char *new = *(char **)arg; - if (!bstr_equals(bstr0(new), bstr0(opts->record_file))) { - talloc_free(opts->record_file); - opts->record_file = talloc_strdup(NULL, new); - open_recorder(mpctx, false); - // open_recorder() unsets it on failure. - if (new && !opts->record_file) - return M_PROPERTY_ERROR; - } - return M_PROPERTY_OK; - } - return mp_property_generic_option(mpctx, prop, action, arg); -} - static int mp_property_protocols(void *ctx, struct m_property *prop, int action, void *arg) { @@ -3569,7 +3440,6 @@ static const struct m_property mp_properties_base[] = { {"chapter-metadata", mp_property_chapter_metadata}, {"vf-metadata", mp_property_filter_metadata, .priv = "vf"}, {"af-metadata", mp_property_filter_metadata, .priv = "af"}, - {"pause", mp_property_pause}, {"core-idle", mp_property_core_idle}, {"eof-reached", mp_property_eof_reached}, {"seeking", mp_property_seeking}, @@ -3592,9 +3462,6 @@ static const struct m_property mp_properties_base[] = { {"track-list", property_list_tracks}, {"edition-list", property_list_editions}, - {"dvbin-prog", mp_property_dvb_channel}, - {"dvbin-channel-switch-offset", mp_property_dvb_channel}, - {"playlist", mp_property_playlist}, {"playlist-pos", mp_property_playlist_pos}, {"playlist-pos-1", mp_property_playlist_pos_1}, @@ -3640,7 +3507,6 @@ static const struct m_property mp_properties_base[] = { {"estimated-vf-fps", mp_property_vf_fps}, {"video-aspect", mp_property_aspect}, {"vid", mp_property_video}, - {"hwdec", mp_property_hwdec}, {"hwdec-current", mp_property_hwdec_current}, {"hwdec-interop", mp_property_hwdec_interop}, @@ -3680,8 +3546,6 @@ static const struct m_property mp_properties_base[] = { PROPERTY_BITRATE("audio-bitrate", false, STREAM_AUDIO), PROPERTY_BITRATE("sub-bitrate", false, STREAM_SUB), - {"cursor-autohide", mp_property_cursor_autohide}, - {"window-minimized", mp_property_win_minimized}, {"display-names", mp_property_display_names}, {"display-fps", mp_property_display_fps}, @@ -3690,8 +3554,6 @@ static const struct m_property mp_properties_base[] = { {"working-directory", mp_property_cwd}, - {"record-file", mp_property_record_file}, - {"protocol-list", mp_property_protocols}, {"decoder-list", mp_property_decoders}, {"encoder-list", mp_property_encoders}, @@ -3709,8 +3571,6 @@ static const struct m_property mp_properties_base[] = { {"command-list", mp_property_commands}, {"input-bindings", mp_property_bindings}, - {"play-dir", mp_property_play_direction}, - M_PROPERTY_ALIAS("video", "vid"), M_PROPERTY_ALIAS("audio", "aid"), M_PROPERTY_ALIAS("sub", "sid"), @@ -6302,7 +6162,9 @@ static void update_priority(struct MPContext *mpctx) void mp_option_change_callback(void *ctx, struct m_config_option *co, int flags) { struct MPContext *mpctx = ctx; + struct MPOpts *opts = mpctx->opts; struct command_ctx *cmd = mpctx->command_ctx; + void *opt_ptr = co ? co->data : NULL; // NULL on start if (flags & UPDATE_TERM) mp_update_logging(mpctx, false); @@ -6333,7 +6195,6 @@ void mp_option_change_callback(void *ctx, struct m_config_option *co, int flags) mp_input_update_opts(mpctx->input); // Rather coarse change-detection, but sufficient effort. - struct MPOpts *opts = mpctx->opts; if (!bstr_equals(bstr0(cmd->cur_ipc), bstr0(opts->ipc_path)) || !bstr_equals(bstr0(cmd->cur_ipc_input), bstr0(opts->input_file))) { @@ -6365,6 +6226,77 @@ void mp_option_change_callback(void *ctx, struct m_config_option *co, int flags) if (mpctx->video_out) vo_control(mpctx->video_out, VOCTRL_EXTERNAL_RESIZE, NULL); } + + if (opt_ptr == &opts->playback_speed) { + update_playback_speed(mpctx); + mp_wakeup_core(mpctx); + } + + if (opt_ptr == &opts->play_dir) { + if (mpctx->play_dir != opts->play_dir) { + queue_seek(mpctx, MPSEEK_ABSOLUTE, get_current_time(mpctx), + MPSEEK_EXACT, 0); + } + } + + if (opt_ptr == &opts->edition_id) { + struct demuxer *demuxer = mpctx->demuxer; + if (mpctx->playback_initialized && demuxer && demuxer->num_editions > 0) { + if (opts->edition_id != demuxer->edition) { + if (!mpctx->stop_play) + mpctx->stop_play = PT_CURRENT_ENTRY; + mp_wakeup_core(mpctx); + } + } + } + + if (opt_ptr == &opts->pause) { + if (mpctx->playback_initialized) { + int val = opts->pause; + opts->pause = !val; // temporary hack to force update + set_pause_state(mpctx, val); + } + } + + if (opt_ptr == &opts->audio_delay) { + if (mpctx->ao_chain) { + mpctx->delay += mpctx->opts->audio_delay - mpctx->ao_chain->delay; + mpctx->ao_chain->delay = mpctx->opts->audio_delay; + } + mp_wakeup_core(mpctx); + } + + if (flags & UPDATE_HWDEC) { + struct track *track = mpctx->current_track[0][STREAM_VIDEO]; + struct mp_decoder_wrapper *dec = track ? track->dec : NULL; + if (dec) { + mp_decoder_wrapper_control(dec, VDCTRL_REINIT, NULL); + double last_pts = mpctx->last_vo_pts; + if (last_pts != MP_NOPTS_VALUE) + queue_seek(mpctx, MPSEEK_ABSOLUTE, last_pts, MPSEEK_EXACT, 0); + } + } + + if (opt_ptr == &opts->vo->window_scale) + update_window_scale(mpctx); + + if (opt_ptr == &opts->cursor_autohide_delay) + mpctx->mouse_timer = 0; + + if (flags & UPDATE_DVB_PROG) { + if (!mpctx->stop_play) + mpctx->stop_play = PT_CURRENT_ENTRY; + } + + if (opt_ptr == &opts->ab_loop[0] || opt_ptr == &opts->ab_loop[1]) { + update_ab_loop_clip(mpctx); + // Update if visible + set_osd_bar_chapters(mpctx, OSD_BAR_SEEK); + mp_wakeup_core(mpctx); + } + + if (opt_ptr == &opts->record_file) + open_recorder(mpctx, false); } void mp_notify_property(struct MPContext *mpctx, const char *property) diff --git a/player/core.h b/player/core.h index ffe3905765..fb88c8d0f0 100644 --- a/player/core.h +++ b/player/core.h @@ -208,6 +208,8 @@ struct ao_chain { struct mp_pin *filter_src; struct mp_pin *dec_src; + double delay; + bool underrun; }; diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c index 3bb6f081ff..d6907cb792 100644 --- a/stream/stream_dvb.c +++ b/stream/stream_dvb.c @@ -73,12 +73,13 @@ static pthread_mutex_t global_dvb_state_lock = PTHREAD_MUTEX_INITIALIZER; const struct m_sub_options stream_dvb_conf = { .opts = (const m_option_t[]) { - OPT_STRING("prog", cfg_prog, 0), + OPT_STRING("prog", cfg_prog, UPDATE_DVB_PROG), OPT_INTRANGE("card", cfg_devno, 0, 0, MAX_ADAPTERS-1), OPT_INTRANGE("timeout", cfg_timeout, 0, 1, 30), OPT_STRING("file", cfg_file, M_OPT_FILE), OPT_FLAG("full-transponder", cfg_full_transponder, 0), - OPT_INT("channel-switch-offset", cfg_channel_switch_offset, 0), + OPT_INT("channel-switch-offset", cfg_channel_switch_offset, + UPDATE_DVB_PROG), {0} }, .size = sizeof(dvb_opts_t), diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index 92065fde0c..ef0f95e60e 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -118,7 +118,8 @@ const struct m_sub_options vd_lavc_conf = { 0, 1, INT_MAX, ({"no", INT_MAX}, {"yes", 1})), OPT_KEYVALUELIST("vd-lavc-o", avopts, 0), OPT_FLAG("vd-lavc-dr", dr, 0), - OPT_STRING_VALIDATE("hwdec", hwdec_api, M_OPT_OPTIONAL_PARAM, + OPT_STRING_VALIDATE("hwdec", hwdec_api, + M_OPT_OPTIONAL_PARAM | UPDATE_HWDEC, hwdec_validate_opt), OPT_STRING("hwdec-codecs", hwdec_codecs, 0), OPT_IMAGEFORMAT("hwdec-image-format", hwdec_image_format, 0, .min = -1),