From 4195a345a51e52337bc972aacbce0fd6e88ebb5d Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 17 Jan 2016 18:07:50 +0100 Subject: player: refactor: eliminate MPContext.d_video Eventually we want the VO be driven by a A->V filter, so a decoder doesn't even have to exist. Some features definitely require a decoder though (like reporting the decoder in use, hardware decoding, etc.), so for each thing which accessed d_video, it has to be redecided if and how it can access decoder state. At least the "framedrop" property slightly changes semantics: you can now always set this property, even if no video is active. Some untested changes in this commit, but our bio-based distributed test suite has to take care of this. --- player/audio.c | 4 +-- player/command.c | 86 ++++++++++++++++++++++++++--------------------------- player/core.h | 9 +++++- player/loadfile.c | 3 -- player/osd.c | 8 ++--- player/playloop.c | 12 ++++---- player/screenshot.c | 4 +-- player/sub.c | 3 +- player/video.c | 80 ++++++++++++++++++++++++++----------------------- 9 files changed, 109 insertions(+), 100 deletions(-) (limited to 'player') diff --git a/player/audio.c b/player/audio.c index 0655dda51e..a7a5f727c7 100644 --- a/player/audio.c +++ b/player/audio.c @@ -468,7 +468,7 @@ static bool get_sync_samples(struct MPContext *mpctx, int *skip) if (written_pts == MP_NOPTS_VALUE && !mp_audio_buffer_samples(mpctx->ao_buffer)) return false; // no audio read yet - bool sync_to_video = mpctx->d_video && mpctx->sync_audio_to_video && + bool sync_to_video = mpctx->vo_chain && mpctx->sync_audio_to_video && mpctx->video_status != STATUS_EOF; double sync_pts = MP_NOPTS_VALUE; @@ -545,7 +545,7 @@ void fill_audio_out_buffers(struct MPContext *mpctx, double endpts) return; // try again next iteration } - if (mpctx->d_video && d_audio->pts_reset) { + if (mpctx->vo_chain && d_audio->pts_reset) { MP_VERBOSE(mpctx, "Reset playback due to audio timestamp reset.\n"); reset_playback_state(mpctx); mpctx->sleeptime = 0; diff --git a/player/command.c b/player/command.c index 4c40be2bf1..3c7cfb282d 100644 --- a/player/command.c +++ b/player/command.c @@ -536,7 +536,7 @@ static int mp_property_avsync(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - if (!mpctx->d_audio || !mpctx->d_video) + if (!mpctx->d_audio || !mpctx->vo_chain) return M_PROPERTY_UNAVAILABLE; if (action == M_PROPERTY_PRINT) { *(char **)arg = talloc_asprintf(NULL, "%7.3f", mpctx->last_av_difference); @@ -549,7 +549,7 @@ static int mp_property_total_avsync_change(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - if (!mpctx->d_audio || !mpctx->d_video) + if (!mpctx->d_audio || !mpctx->vo_chain) return M_PROPERTY_UNAVAILABLE; if (mpctx->total_avsync_change == MP_NOPTS_VALUE) return M_PROPERTY_UNAVAILABLE; @@ -560,17 +560,17 @@ static int mp_property_drop_frame_cnt(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - if (!mpctx->d_video) + if (!mpctx->vo_chain) return M_PROPERTY_UNAVAILABLE; - return m_property_int_ro(action, arg, mpctx->d_video->dropped_frames); + return m_property_int_ro(action, arg, mpctx->vo_chain->video_src->dropped_frames); } static int mp_property_mistimed_frame_count(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - if (!mpctx->d_video || !mpctx->display_sync_active) + if (!mpctx->vo_chain || !mpctx->display_sync_active) return M_PROPERTY_UNAVAILABLE; return m_property_int_ro(action, arg, mpctx->mistimed_frames_total); @@ -580,7 +580,7 @@ static int mp_property_vsync_ratio(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - if (!mpctx->d_video || !mpctx->display_sync_active) + if (!mpctx->vo_chain || !mpctx->display_sync_active) return M_PROPERTY_UNAVAILABLE; int vsyncs = 0, frames = 0; @@ -602,7 +602,7 @@ static int mp_property_vo_drop_frame_count(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - if (!mpctx->d_video) + if (!mpctx->vo_chain) return M_PROPERTY_UNAVAILABLE; return m_property_int_ro(action, arg, vo_get_drop_count(mpctx->video_out)); @@ -612,7 +612,7 @@ static int mp_property_vo_delayed_frame_count(void *ctx, struct m_property *prop int action, void *arg) { MPContext *mpctx = ctx; - if (!mpctx->d_video) + if (!mpctx->vo_chain) return M_PROPERTY_UNAVAILABLE; return m_property_int_ro(action, arg, vo_get_delayed_count(mpctx->video_out)); @@ -1696,7 +1696,7 @@ static int mp_property_audio_delay(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - if (!(mpctx->d_audio && mpctx->d_video)) + if (!(mpctx->d_audio && mpctx->vo_chain)) return M_PROPERTY_UNAVAILABLE; float delay = mpctx->opts->audio_delay; switch (action) { @@ -2101,8 +2101,9 @@ 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 dec_video *vd = track ? track->d_video : NULL; struct MPOpts *opts = mpctx->opts; - struct dec_video *vd = mpctx->d_video; if (action == M_PROPERTY_SET) { int new = *(int *)arg; @@ -2133,7 +2134,8 @@ static int mp_property_hwdec_active(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - struct dec_video *vd = mpctx->d_video; + struct track *track = mpctx->current_track[0][STREAM_VIDEO]; + struct dec_video *vd = track ? track->d_video : NULL; bool active = false; if (vd) { int current = 0; @@ -2147,7 +2149,8 @@ static int mp_property_detected_hwdec(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - struct dec_video *vd = mpctx->d_video; + struct track *track = mpctx->current_track[0][STREAM_VIDEO]; + struct dec_video *vd = track ? track->d_video : NULL; switch (action) { case M_PROPERTY_GET_TYPE: { @@ -2358,11 +2361,11 @@ static int get_frame_count(struct MPContext *mpctx) { struct demuxer *demuxer = mpctx->demuxer; if (!demuxer) - return 0; - if (!mpctx->d_video) - return 0; + return -1; + if (!mpctx->vo_chain) + return -1; double len = get_time_length(mpctx); - double fps = mpctx->d_video->fps; + double fps = mpctx->vo_chain->container_fps; if (len < 0 || fps <= 0) return 0; @@ -2373,32 +2376,23 @@ static int mp_property_frame_number(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - if (!mpctx->d_video) + int frames = get_frame_count(mpctx); + if (frames < 0) return M_PROPERTY_UNAVAILABLE; return m_property_int_ro(action, arg, - lrint(get_current_pos_ratio(mpctx, false) * get_frame_count(mpctx))); + lrint(get_current_pos_ratio(mpctx, false) * frames)); } static int mp_property_frame_count(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - - if (!mpctx->d_video) + int frames = get_frame_count(mpctx); + if (frames < 0) return M_PROPERTY_UNAVAILABLE; - return m_property_int_ro(action, arg, get_frame_count(mpctx)); -} - -static int mp_property_framedrop(void *ctx, struct m_property *prop, - int action, void *arg) -{ - MPContext *mpctx = ctx; - if (!mpctx->d_video) - return M_PROPERTY_UNAVAILABLE; - - return mp_property_generic_option(mpctx, prop, action, arg); + return m_property_int_ro(action, arg, frames); } static int mp_property_video_color(void *ctx, struct m_property *prop, @@ -2433,7 +2427,8 @@ static int mp_property_video_format(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - const char *c = mpctx->d_video ? mpctx->d_video->header->codec->codec : NULL; + struct track *track = mpctx->current_track[0][STREAM_VIDEO]; + const char *c = track && track->stream ? track->stream->codec->codec : NULL; return m_property_strdup_ro(action, arg, c); } @@ -2442,7 +2437,8 @@ static int mp_property_video_codec(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - const char *c = mpctx->d_video ? mpctx->d_video->decoder_desc : NULL; + struct track *track = mpctx->current_track[0][STREAM_VIDEO]; + const char *c = track->d_video ? track->d_video->decoder_desc : NULL; return m_property_strdup_ro(action, arg, c); } @@ -2511,12 +2507,14 @@ static int mp_property_vd_imgparams(void *ctx, struct m_property *prop, { MPContext *mpctx = ctx; struct vo_chain *vo_c = mpctx->vo_chain; - if (!vo_c && !mpctx->d_video) + struct track *track = mpctx->current_track[0][STREAM_VIDEO]; + if (!vo_c || !track) return M_PROPERTY_UNAVAILABLE; - struct mp_codec_params *c = mpctx->d_video->header->codec; + struct mp_codec_params *c = + track && track->stream ? track->stream->codec : NULL; if (vo_c->vf->input_params.imgfmt) { return property_imgparams(vo_c->vf->input_params, action, arg); - } else if (c->disp_w && c->disp_h) { + } else if (c && c->disp_w && c->disp_h) { // Simplistic fallback for stupid scripts querying "width"/"height" // before the first frame is decoded. struct m_sub_property props[] = { @@ -2744,7 +2742,7 @@ static int mp_property_fps(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - float fps = mpctx->d_video ? mpctx->d_video->fps : 0; + float fps = mpctx->vo_chain ? mpctx->vo_chain->container_fps : 0; if (fps < 0.1 || !isfinite(fps)) return M_PROPERTY_UNAVAILABLE;; return m_property_float_ro(action, arg, fps); @@ -2754,7 +2752,7 @@ static int mp_property_vf_fps(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - if (!mpctx->d_video) + if (!mpctx->vo_chain) return M_PROPERTY_UNAVAILABLE; double avg = calc_average_frame_duration(mpctx); if (avg <= 0) @@ -2770,8 +2768,9 @@ static int mp_property_aspect(void *ctx, struct m_property *prop, switch (action) { case M_PROPERTY_SET: { mpctx->opts->movie_aspect = *(float *)arg; - if (mpctx->d_video) { - video_reset_aspect(mpctx->d_video); + struct track *track = mpctx->current_track[0][STREAM_VIDEO]; + if (track && track->d_video) { + video_reset_aspect(track->d_video); mp_force_video_refresh(mpctx); } return M_PROPERTY_OK; @@ -2785,8 +2784,9 @@ static int mp_property_aspect(void *ctx, struct m_property *prop, } case M_PROPERTY_GET: { float aspect = mpctx->opts->movie_aspect; - if (mpctx->d_video && mpctx->vo_chain && aspect <= 0) { - struct dec_video *d_video = mpctx->d_video; + struct track *track = mpctx->current_track[0][STREAM_VIDEO]; + if (track && track->d_video && mpctx->vo_chain && aspect <= 0) { + struct dec_video *d_video = track->d_video; struct mp_codec_params *c = d_video->header->codec; struct mp_image_params *params = &mpctx->vo_chain->vf->input_params; if (params && params->p_w > 0 && params->p_h > 0) { @@ -3575,7 +3575,7 @@ static const struct m_property mp_properties[] = { {"ontop", mp_property_ontop}, {"border", mp_property_border}, {"on-all-workspaces", mp_property_all_workspaces}, - {"framedrop", mp_property_framedrop}, + {"framedrop", mp_property_generic_option}, {"gamma", mp_property_video_color}, {"brightness", mp_property_video_color}, {"contrast", mp_property_video_color}, diff --git a/player/core.h b/player/core.h index 715ce74ef3..e3397d234a 100644 --- a/player/core.h +++ b/player/core.h @@ -144,6 +144,9 @@ struct track { // Current subtitle state (or cached state if selected==false). struct dec_sub *d_sub; + // Current video decoding state (NULL if selected==false) + struct dec_video *d_video; + // For external subtitles, which are read fully on init. Do not attempt // to read packets from them. bool preloaded; @@ -153,6 +156,9 @@ struct track { struct vo_chain { struct mp_log *log; + struct mp_hwdec_info *hwdec_info; + double container_fps; + struct vf_chain *vf; struct vo *vo; @@ -161,6 +167,8 @@ struct vo_chain { // Last known input_mpi format (so vf can be reinitialized any time). struct mp_image_params input_format; + + struct dec_video *video_src; }; /* Note that playback can be paused, stopped, etc. at any time. While paused, @@ -259,7 +267,6 @@ typedef struct MPContext { // Currently, this is used for the secondary subtitle track only. struct track *current_track[NUM_PTRACKS][STREAM_TYPE_COUNT]; - struct dec_video *d_video; struct dec_audio *d_audio; // Uses: accessing metadata (consider ordered chapters case, where the main diff --git a/player/loadfile.c b/player/loadfile.c index 88004a0ec1..aecdbf46de 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -60,7 +60,6 @@ static void uninit_demuxer(struct MPContext *mpctx) { - assert(!mpctx->d_video && !mpctx->d_audio); for (int r = 0; r < NUM_PTRACKS; r++) { for (int t = 0; t < STREAM_TYPE_COUNT; t++) mpctx->current_track[r][t] = NULL; @@ -1088,8 +1087,6 @@ reopen_file: assert(mpctx->stream == NULL); assert(mpctx->demuxer == NULL); - assert(mpctx->d_audio == NULL); - assert(mpctx->d_video == NULL); if (process_open_hooks(mpctx) < 0) goto terminate_playback; diff --git a/player/osd.c b/player/osd.c index 3b5ecf98fd..8912873368 100644 --- a/player/osd.c +++ b/player/osd.c @@ -197,7 +197,7 @@ static void print_status(struct MPContext *mpctx) if (mpctx->d_audio) saddf(&line, "A"); - if (mpctx->d_video) + if (mpctx->vo_chain) saddf(&line, "V"); saddf(&line, ": "); @@ -217,7 +217,7 @@ static void print_status(struct MPContext *mpctx) saddf(&line, " x%4.2f", opts->playback_speed); // A-V sync - if (mpctx->d_audio && mpctx->d_video && mpctx->sync_audio_to_video) { + if (mpctx->d_audio && mpctx->vo_chain && mpctx->sync_audio_to_video) { saddf(&line, " A-V:%7.3f", mpctx->last_av_difference); if (fabs(mpctx->total_avsync_change) > 0.05) saddf(&line, " ct:%7.3f", mpctx->total_avsync_change); @@ -235,7 +235,7 @@ static void print_status(struct MPContext *mpctx) #endif { // VO stats - if (mpctx->d_video) { + if (mpctx->vo_chain) { if (mpctx->display_sync_active) { char *r = mp_property_expand_string(mpctx, "${vsync-ratio}"); saddf(&line, " DS: %s/%"PRId64, r, @@ -243,7 +243,7 @@ static void print_status(struct MPContext *mpctx) talloc_free(r); } int64_t c = vo_get_drop_count(mpctx->video_out); - int dropped_frames = mpctx->d_video->dropped_frames; + int dropped_frames = mpctx->vo_chain->video_src->dropped_frames; if (c > 0 || dropped_frames > 0) { saddf(&line, " Dropped: %"PRId64, c); if (dropped_frames) diff --git a/player/playloop.c b/player/playloop.c index 174318e70e..120712899b 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -127,7 +127,7 @@ end: void add_step_frame(struct MPContext *mpctx, int dir) { - if (!mpctx->d_video) + if (!mpctx->vo_chain) return; if (dir > 0) { mpctx->step_frames += 1; @@ -525,7 +525,7 @@ static void handle_osd_redraw(struct MPContext *mpctx) return; } // Don't redraw immediately during a seek (makes it significantly slower). - if (mpctx->d_video && mp_time_sec() - mpctx->start_timestamp < 0.1) { + if (mpctx->vo_chain && mp_time_sec() - mpctx->start_timestamp < 0.1) { mpctx->sleeptime = MPMIN(mpctx->sleeptime, 0.1); return; } @@ -707,7 +707,7 @@ static void handle_loop_file(struct MPContext *mpctx) void seek_to_last_frame(struct MPContext *mpctx) { - if (!mpctx->d_video) + if (!mpctx->vo_chain) return; if (mpctx->hrseek_lastframe) // exit if we already tried this return; @@ -737,7 +737,7 @@ static void handle_keep_open(struct MPContext *mpctx) opts->loop_times == 1) { mpctx->stop_play = KEEP_PLAYING; - if (mpctx->d_video) { + if (mpctx->vo_chain) { if (!vo_has_frame(mpctx->video_out)) // EOF not reached normally seek_to_last_frame(mpctx); mpctx->playback_pts = mpctx->last_vo_pts; @@ -765,7 +765,7 @@ static void handle_chapter_change(struct MPContext *mpctx) int handle_force_window(struct MPContext *mpctx, bool force) { // Don't interfere with real video playback - if (mpctx->d_video) + if (mpctx->vo_chain) return 0; // True if we're either in idle mode, or loading of the file has finished. @@ -897,7 +897,7 @@ static void handle_segment_switch(struct MPContext *mpctx, bool end_is_new_segme * and video streams to "disabled" at runtime. Handle this by waiting * rather than immediately stopping playback due to EOF. */ - if ((mpctx->d_audio || mpctx->d_video) && !prevent_eof && + if ((mpctx->d_audio || mpctx->vo_chain) && !prevent_eof && mpctx->audio_status == STATUS_EOF && mpctx->video_status == STATUS_EOF) { diff --git a/player/screenshot.c b/player/screenshot.c index 3fc0b90c98..4ab0653fd4 100644 --- a/player/screenshot.c +++ b/player/screenshot.c @@ -345,8 +345,8 @@ static struct mp_image *screenshot_get(struct MPContext *mpctx, int mode) } } - if (image && mpctx->d_video && mpctx->d_video->hwdec_info) { - struct mp_hwdec_ctx *ctx = mpctx->d_video->hwdec_info->hwctx; + if (image && mpctx->vo_chain && mpctx->vo_chain->hwdec_info) { + struct mp_hwdec_ctx *ctx = mpctx->vo_chain->hwdec_info->hwctx; struct mp_image *nimage = NULL; if (ctx && ctx->download_image && (image->fmt.flags & MP_IMGFLAG_HWACCEL)) nimage = ctx->download_image(ctx, image, NULL); diff --git a/player/sub.c b/player/sub.c index 6635ef98fb..6e707b3d95 100644 --- a/player/sub.c +++ b/player/sub.c @@ -135,8 +135,9 @@ static bool init_subdec(struct MPContext *mpctx, struct track *track) if (!track->d_sub) return false; + struct track *vtrack = mpctx->current_track[0][STREAM_VIDEO]; struct mp_codec_params *v_c = - mpctx->d_video ? mpctx->d_video->header->codec : NULL; + vtrack && vtrack->stream ? vtrack->stream->codec : NULL; double fps = v_c ? v_c->fps : 25; sub_control(track->d_sub, SD_CTRL_SET_VIDEO_DEF_FPS, &fps); diff --git a/player/video.c b/player/video.c index dc46140859..faa8a652bb 100644 --- a/player/video.c +++ b/player/video.c @@ -193,16 +193,15 @@ static void filter_reconfig(struct vo_chain *vo_c) static void recreate_video_filters(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; - struct dec_video *d_video = mpctx->d_video; struct vo_chain *vo_c = mpctx->vo_chain; - assert(d_video && vo_c); + assert(vo_c); vf_destroy(vo_c->vf); vo_c->vf = vf_new(mpctx->global); - vo_c->vf->hwdec = d_video->hwdec_info; + vo_c->vf->hwdec = vo_c->hwdec_info; vo_c->vf->wakeup_callback = wakeup_playloop; vo_c->vf->wakeup_callback_ctx = mpctx; - vo_c->vf->container_fps = d_video->fps; + vo_c->vf->container_fps = vo_c->container_fps; vo_control(vo_c->vo, VOCTRL_GET_DISPLAY_FPS, &vo_c->vf->display_fps); vf_append_filter_list(vo_c->vf, opts->vf_settings); @@ -216,10 +215,9 @@ static void recreate_video_filters(struct MPContext *mpctx) int reinit_video_filters(struct MPContext *mpctx) { - struct dec_video *d_video = mpctx->d_video; struct vo_chain *vo_c = mpctx->vo_chain; - if (!d_video) + if (!vo_c) return 0; bool need_reconfig = vo_c->vf->initialized != 0; @@ -243,10 +241,10 @@ static void vo_chain_reset_state(struct vo_chain *vo_c) void reset_video_state(struct MPContext *mpctx) { - if (mpctx->d_video) - video_reset(mpctx->d_video); - if (mpctx->vo_chain) + if (mpctx->vo_chain) { + video_reset(mpctx->vo_chain->video_src); vo_chain_reset_state(mpctx->vo_chain); + } for (int n = 0; n < mpctx->num_next_frames; n++) mp_image_unrefp(&mpctx->next_frames[n]); @@ -266,7 +264,7 @@ void reset_video_state(struct MPContext *mpctx) mpctx->display_sync_drift_dir = 0; mpctx->display_sync_broken = false; - mpctx->video_status = mpctx->d_video ? STATUS_SYNCING : STATUS_EOF; + mpctx->video_status = mpctx->vo_chain ? STATUS_SYNCING : STATUS_EOF; } void uninit_video_out(struct MPContext *mpctx) @@ -282,20 +280,21 @@ void uninit_video_out(struct MPContext *mpctx) static void vo_chain_uninit(struct vo_chain *vo_c) { mp_image_unrefp(&vo_c->input_mpi); - if (vo_c) + if (vo_c) { vf_destroy(vo_c->vf); + if (vo_c->video_src) + video_uninit(vo_c->video_src); + } talloc_free(vo_c); // this does not free the VO } void uninit_video_chain(struct MPContext *mpctx) { - if (mpctx->d_video) { + if (mpctx->vo_chain) { reset_video_state(mpctx); vo_chain_uninit(mpctx->vo_chain); mpctx->vo_chain = NULL; - video_uninit(mpctx->d_video); - mpctx->d_video = NULL; mpctx->video_status = STATUS_EOF; mpctx->sync_audio_to_video = false; reselect_demux_streams(mpctx); @@ -307,7 +306,6 @@ void uninit_video_chain(struct MPContext *mpctx) int reinit_video_chain(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; - assert(!mpctx->d_video); assert(!mpctx->vo_chain); struct track *track = mpctx->current_track[0][STREAM_VIDEO]; struct sh_stream *sh = track ? track->stream : NULL; @@ -333,17 +331,21 @@ int reinit_video_chain(struct MPContext *mpctx) update_window_title(mpctx, true); - struct dec_video *d_video = talloc_zero(NULL, struct dec_video); - mpctx->d_video = d_video; + struct vo_chain *vo_c = talloc_zero(NULL, struct vo_chain); + mpctx->vo_chain = vo_c; + vo_c->log = mpctx->log; + vo_c->vo = mpctx->video_out; + + vo_control(vo_c->vo, VOCTRL_GET_HWDEC_INFO, &vo_c->hwdec_info); + + track->d_video = talloc_zero(NULL, struct dec_video); + struct dec_video *d_video = track->d_video; d_video->global = mpctx->global; d_video->log = mp_log_new(d_video, mpctx->log, "!vd"); d_video->opts = mpctx->opts; d_video->header = sh; d_video->fps = sh->codec->fps; - - mpctx->vo_chain = talloc_zero(NULL, struct vo_chain); - mpctx->vo_chain->log = d_video->log; - mpctx->vo_chain->vo = mpctx->video_out; + d_video->hwdec_info = vo_c->hwdec_info; MP_VERBOSE(d_video, "Container reported FPS: %f\n", sh->codec->fps); @@ -353,23 +355,24 @@ int reinit_video_chain(struct MPContext *mpctx) MP_INFO(mpctx, "Use --no-correct-pts to force FPS based timing.\n"); } + vo_c->container_fps = d_video->fps; + vo_c->video_src = d_video; + #if HAVE_ENCODING if (mpctx->encode_lavc_ctx) encode_lavc_set_video_fps(mpctx->encode_lavc_ctx, d_video->fps); #endif - vo_control(mpctx->video_out, VOCTRL_GET_HWDEC_INFO, &d_video->hwdec_info); - recreate_video_filters(mpctx); if (!video_init_best_codec(d_video, opts->video_decoders)) goto err_out; bool saver_state = opts->pause || !opts->stop_screensaver; - vo_control(mpctx->video_out, saver_state ? VOCTRL_RESTORE_SCREENSAVER - : VOCTRL_KILL_SCREENSAVER, NULL); + vo_control(vo_c->vo, saver_state ? VOCTRL_RESTORE_SCREENSAVER + : VOCTRL_KILL_SCREENSAVER, NULL); - vo_set_paused(mpctx->video_out, mpctx->paused); + vo_set_paused(vo_c->vo, mpctx->paused); mpctx->sync_audio_to_video = !sh->attached_picture; @@ -410,19 +413,19 @@ void mp_force_video_refresh(struct MPContext *mpctx) } } -static bool check_framedrop(struct MPContext *mpctx) +static bool check_framedrop(struct MPContext *mpctx, struct vo_chain *vo_c) { struct MPOpts *opts = mpctx->opts; // check for frame-drop: if (mpctx->video_status == STATUS_PLAYING && !mpctx->paused && mpctx->audio_status == STATUS_PLAYING && !ao_untimed(mpctx->ao)) { - float fps = mpctx->d_video->fps; + float fps = vo_c->container_fps; double frame_time = fps > 0 ? 1.0 / fps : 0; // we should avoid dropping too many frames in sequence unless we // are too late. and we allow 100ms A-V delay here: int dropped_frames = - mpctx->d_video->dropped_frames - mpctx->dropped_frames_start; + vo_c->video_src->dropped_frames - mpctx->dropped_frames_start; if (mpctx->last_av_difference - 0.100 > dropped_frames * frame_time) return !!(opts->frame_dropping & 2); } @@ -433,14 +436,14 @@ static bool check_framedrop(struct MPContext *mpctx) // returns VD_* code static int decode_image(struct MPContext *mpctx) { - struct dec_video *d_video = mpctx->d_video; struct vo_chain *vo_c = mpctx->vo_chain; + struct dec_video *d_video = vo_c->video_src; bool hrseek = mpctx->hrseek_active && mpctx->video_status == STATUS_SYNCING && mpctx->hrseek_framedrop; video_set_start(d_video, hrseek ? mpctx->hrseek_pts : MP_NOPTS_VALUE); - video_set_framedrop(d_video, check_framedrop(mpctx)); + video_set_framedrop(d_video, check_framedrop(mpctx, vo_c)); video_work(d_video); @@ -504,7 +507,7 @@ static int video_filter(struct MPContext *mpctx, bool eof) // Most video filters don't work with hardware decoding, so this // might be the reason why filter reconfig failed. if (vf->initialized < 0 && - video_vd_control(mpctx->d_video, VDCTRL_FORCE_HWDEC_FALLBACK, NULL) + video_vd_control(vo_c->video_src, VDCTRL_FORCE_HWDEC_FALLBACK, NULL) == CONTROL_OK) { // Fallback active; decoder will return software format next @@ -630,7 +633,7 @@ static void handle_new_frame(struct MPContext *mpctx) mpctx->time_frame += frame_time / mpctx->video_speed; adjust_sync(mpctx, pts, frame_time); } - mpctx->dropped_frames_start = mpctx->d_video->dropped_frames; + mpctx->dropped_frames_start = mpctx->vo_chain->video_src->dropped_frames; MP_TRACE(mpctx, "frametime=%5.3f\n", frame_time); } @@ -689,7 +692,8 @@ static int video_output_image(struct MPContext *mpctx, double endpts) { bool hrseek = mpctx->hrseek_active && mpctx->video_status == STATUS_SYNCING; - if (mpctx->d_video->header->attached_picture) { + struct track *track = mpctx->current_track[0][STREAM_VIDEO]; + if (track && track->stream && track->stream->attached_picture) { if (vo_has_frame(mpctx->video_out)) return VD_EOF; hrseek = false; @@ -1123,8 +1127,8 @@ static void calculate_frame_duration(struct MPContext *mpctx) { assert(mpctx->num_past_frames >= 1 && mpctx->num_next_frames >= 1); - double demux_duration = - mpctx->d_video->fps > 0 ? 1.0 / mpctx->d_video->fps : -1; + double demux_duration = mpctx->vo_chain->container_fps > 0 + ? 1.0 / mpctx->vo_chain->container_fps : -1; double duration = -1; if (mpctx->num_next_frames >= 2) { @@ -1175,10 +1179,10 @@ static void calculate_frame_duration(struct MPContext *mpctx) void write_video(struct MPContext *mpctx, double endpts) { struct MPOpts *opts = mpctx->opts; - struct vo *vo = mpctx->video_out; - if (!mpctx->d_video) + if (!mpctx->vo_chain) return; + struct vo *vo = mpctx->vo_chain->vo; // Actual playback starts when both audio and video are ready. if (mpctx->video_status == STATUS_READY) -- cgit v1.2.3