diff options
Diffstat (limited to 'player')
-rw-r--r-- | player/audio.c | 1 | ||||
-rw-r--r-- | player/command.c | 41 | ||||
-rw-r--r-- | player/core.h | 14 | ||||
-rw-r--r-- | player/loadfile.c | 27 | ||||
-rw-r--r-- | player/main.c | 2 | ||||
-rw-r--r-- | player/osd.c | 7 | ||||
-rw-r--r-- | player/playloop.c | 37 | ||||
-rw-r--r-- | player/screenshot.c | 1 | ||||
-rw-r--r-- | player/sub.c | 1 | ||||
-rw-r--r-- | player/video.c | 228 |
10 files changed, 102 insertions, 257 deletions
diff --git a/player/audio.c b/player/audio.c index 014bde9ff1..ab53ab3b86 100644 --- a/player/audio.c +++ b/player/audio.c @@ -36,7 +36,6 @@ #include "audio/decode/dec_audio.h" #include "audio/out/ao.h" #include "demux/demux.h" -#include "video/decode/dec_video.h" #include "core.h" #include "command.h" diff --git a/player/command.c b/player/command.c index 809f859280..d1de5a86ff 100644 --- a/player/command.c +++ b/player/command.c @@ -36,6 +36,7 @@ #include "common/codecs.h" #include "common/msg.h" #include "common/msg_control.h" +#include "filters/f_decoder_wrapper.h" #include "command.h" #include "osdep/timer.h" #include "common/common.h" @@ -50,13 +51,12 @@ #include "options/m_option.h" #include "options/m_property.h" #include "options/m_config.h" -#include "video/decode/vd.h" #include "video/out/vo.h" #include "video/csputils.h" +#include "video/hwdec.h" #include "audio/aframe.h" #include "audio/format.h" #include "audio/out/ao.h" -#include "video/decode/dec_video.h" #include "audio/decode/dec_audio.h" #include "video/out/bitmap_packer.h" #include "options/path.h" @@ -675,10 +675,12 @@ static int mp_property_frame_drop_dec(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - if (!mpctx->vo_chain) + struct mp_decoder_wrapper *dec = mpctx->vo_chain && mpctx->vo_chain->track + ? mpctx->vo_chain->track->dec : NULL; + if (!dec) return M_PROPERTY_UNAVAILABLE; - return m_property_int_ro(action, arg, mpctx->vo_chain->video_src->dropped_frames); + return m_property_int_ro(action, arg, dec->dropped_frames); } static int mp_property_mistimed_frame_count(void *ctx, struct m_property *prop, @@ -2182,8 +2184,8 @@ static int get_track_entry(int item, int action, void *arg, void *ctx) track->stream ? *track->stream->codec : (struct mp_codec_params){0}; const char *decoder_desc = NULL; - if (track->d_video) - decoder_desc = track->d_video->decoder_desc; + if (track->dec) + decoder_desc = track->dec->decoder_desc; if (track->d_audio) decoder_desc = track->d_audio->decoder_desc; @@ -2367,7 +2369,7 @@ static int mp_property_hwdec(void *ctx, struct m_property *prop, { MPContext *mpctx = ctx; struct track *track = mpctx->current_track[0][STREAM_VIDEO]; - struct dec_video *vd = track ? track->d_video : NULL; + struct mp_decoder_wrapper *dec = track ? track->dec : NULL; struct MPOpts *opts = mpctx->opts; if (action == M_PROPERTY_SET) { @@ -2379,10 +2381,10 @@ static int mp_property_hwdec(void *ctx, struct m_property *prop, talloc_free(opts->hwdec_api); opts->hwdec_api = talloc_strdup(NULL, new); - if (!vd) + if (!dec) return M_PROPERTY_OK; - video_vd_control(vd, VDCTRL_REINIT, NULL); + 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); @@ -2397,13 +2399,13 @@ static int mp_property_hwdec_current(void *ctx, struct m_property *prop, { MPContext *mpctx = ctx; struct track *track = mpctx->current_track[0][STREAM_VIDEO]; - struct dec_video *vd = track ? track->d_video : NULL; + struct mp_decoder_wrapper *dec = track ? track->dec : NULL; - if (!vd) + if (!dec) return M_PROPERTY_UNAVAILABLE; char *current = NULL; - video_vd_control(vd, VDCTRL_GET_HWDEC, ¤t); + mp_decoder_wrapper_control(dec, VDCTRL_GET_HWDEC, ¤t); if (!current) current = "no"; return m_property_strdup_ro(action, arg, current); @@ -2547,7 +2549,7 @@ static int mp_property_video_codec(void *ctx, struct m_property *prop, { MPContext *mpctx = ctx; struct track *track = mpctx->current_track[0][STREAM_VIDEO]; - const char *c = track && track->d_video ? track->d_video->decoder_desc : NULL; + const char *c = track && track->dec ? track->dec->decoder_desc : NULL; return m_property_strdup_ro(action, arg, c); } @@ -2620,8 +2622,8 @@ static int mp_property_dec_imgparams(void *ctx, struct m_property *prop, MPContext *mpctx = ctx; struct mp_image_params p = {0}; struct vo_chain *vo_c = mpctx->vo_chain; - if (vo_c && vo_c->video_src) - video_get_dec_params(vo_c->video_src, &p); + if (vo_c && vo_c->track) + mp_decoder_wrapper_get_video_dec_params(vo_c->track->dec, &p); if (!p.imgfmt) return M_PROPERTY_UNAVAILABLE; return property_imgparams(p, action, arg); @@ -2984,9 +2986,8 @@ static int mp_property_aspect(void *ctx, struct m_property *prop, } } struct track *track = mpctx->current_track[0][STREAM_VIDEO]; - if (track && track->d_video && aspect <= 0) { - struct dec_video *d_video = track->d_video; - struct mp_codec_params *c = d_video->header->codec; + if (track && track->stream && aspect <= 0) { + struct mp_codec_params *c = track->stream->codec; if (c->disp_w && c->disp_h) aspect = (float)c->disp_w / c->disp_h; } @@ -5807,8 +5808,8 @@ void mp_option_change_callback(void *ctx, struct m_config_option *co, int flags) if (flags & UPDATE_IMGPAR) { struct track *track = mpctx->current_track[0][STREAM_VIDEO]; - if (track && track->d_video) { - video_reset_params(track->d_video); + if (track && track->dec) { + mp_decoder_wrapper_reset_params(track->dec); mp_force_video_refresh(mpctx); } } diff --git a/player/core.h b/player/core.h index 0560393bd3..f27c30b145 100644 --- a/player/core.h +++ b/player/core.h @@ -153,7 +153,7 @@ struct track { struct dec_sub *d_sub; // Current decoding state (NULL if selected==false) - struct dec_video *d_video; + struct mp_decoder_wrapper *dec; struct dec_audio *d_audio; // Where the decoded result goes to (one of them is not NULL if active) @@ -170,7 +170,6 @@ struct track { struct vo_chain { struct mp_log *log; - struct mp_hwdec_devices *hwdec_devs; double container_fps; struct mp_output_chain *filter; @@ -178,19 +177,13 @@ struct vo_chain { //struct vf_chain *vf; struct vo *vo; - // 1-element input frame queue. - struct mp_image *input_mpi; - struct track *track; struct mp_pin *filter_src; - bool filter_src_got_eof; // whether this returned EOF last time - struct dec_video *video_src; + struct mp_pin *dec_src; // - video consists of a single picture, which should be shown only once // - do not sync audio to video in any way bool is_coverart; - // Just to avoid decoding the coverart picture again after a seek. - struct mp_image *cached_coverart; }; // Like vo_chain, for audio. @@ -351,7 +344,6 @@ typedef struct MPContext { // Number of mistimed frames. int mistimed_frames_total; bool hrseek_active; // skip all data until hrseek_pts - bool hrseek_framedrop; // allow decoder to drop frames before hrseek_pts bool hrseek_lastframe; // drop everything until last frame reached bool hrseek_backstep; // go to frame before seek target double hrseek_pts; @@ -366,8 +358,6 @@ typedef struct MPContext { // How much video timing has been changed to make it match the audio // timeline. Used for status line information only. double total_avsync_change; - // Used to compute the number of frames dropped in a row. - int dropped_frames_start; // A-V sync difference when last frame was displayed. Kept to display // the same value if the status line is updated at a time where no new // video frame is shown. diff --git a/player/loadfile.c b/player/loadfile.c index ad1b20ac8e..d35ae6ad6b 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -45,13 +45,13 @@ #include "audio/decode/dec_audio.h" #include "audio/out/ao.h" +#include "filters/f_decoder_wrapper.h" #include "filters/f_lavfi.h" #include "filters/filter_internal.h" #include "demux/demux.h" #include "stream/stream.h" #include "sub/dec_sub.h" #include "external_files.h" -#include "video/decode/dec_video.h" #include "video/out/vo.h" #include "core.h" @@ -984,9 +984,9 @@ static void cleanup_deassociated_complex_filters(struct MPContext *mpctx) for (int n = 0; n < mpctx->num_tracks; n++) { struct track *track = mpctx->tracks[n]; if (!(track->sink || track->vo_c || track->ao_c)) { - if (track->d_video && !track->vo_c) { - video_uninit(track->d_video); - track->d_video = NULL; + if (track->dec && !track->vo_c) { + talloc_free(track->dec->f); + track->dec->f = NULL; } if (track->d_audio && !track->ao_c) { audio_uninit(track->d_audio); @@ -996,7 +996,7 @@ static void cleanup_deassociated_complex_filters(struct MPContext *mpctx) } } - if (mpctx->vo_chain && !mpctx->vo_chain->video_src && + if (mpctx->vo_chain && !mpctx->vo_chain->dec_src && !mpctx->vo_chain->filter_src) { uninit_video_chain(mpctx); @@ -1079,18 +1079,16 @@ static int reinit_complex_filters(struct MPContext *mpctx, bool force_uninit) struct mp_pin *pad = mp_filter_get_named_pin(mpctx->lavfi, "vo"); if (pad && mp_pin_get_dir(pad) == MP_PIN_OUT) { if (mpctx->vo_chain) { - if (mpctx->vo_chain->video_src) { - MP_ERR(mpctx, "Pad vo tries to connect to already used VO.\n"); - goto done; - } + MP_ERR(mpctx, "Pad vo tries to connect to already used VO.\n"); + goto done; } else { reinit_video_chain_src(mpctx, NULL); if (!mpctx->vo_chain) goto done; } - mp_pin_set_manual_connection(pad, true); struct vo_chain *vo_c = mpctx->vo_chain; vo_c->filter_src = pad; + mp_pin_connect(vo_c->filter->f->pins[0], vo_c->filter_src); } pad = mp_filter_get_named_pin(mpctx->lavfi, "ao"); @@ -1112,8 +1110,9 @@ static int reinit_complex_filters(struct MPContext *mpctx, bool force_uninit) for (int n = 0; n < mpctx->num_tracks; n++) { struct track *track = mpctx->tracks[n]; if (track->sink && track->type == STREAM_VIDEO) { - if (!track->d_video && !init_video_decoder(mpctx, track)) + if (!track->dec && !init_video_decoder(mpctx, track)) goto done; + mp_pin_connect(track->sink, track->dec->f->pins[0]); } if (track->sink && track->type == STREAM_AUDIO) { if (!track->d_audio && !init_audio_decoder(mpctx, track)) @@ -1587,8 +1586,8 @@ static void set_track_recorder_sink(struct track *track, { if (track->d_sub) sub_set_recorder_sink(track->d_sub, sink); - if (track->d_video) - track->d_video->recorder_sink = sink; + if (track->dec) + track->dec->recorder_sink = sink; if (track->d_audio) track->d_audio->recorder_sink = sink; track->remux_sink = sink; @@ -1633,7 +1632,7 @@ void open_recorder(struct MPContext *mpctx, bool on_init) for (int n = 0; n < mpctx->num_tracks; n++) { struct track *track = mpctx->tracks[n]; if (track->stream && track->selected && - (track->d_sub || track->d_video || track->d_audio)) + (track->d_sub || track->dec || track->d_audio)) { MP_TARRAY_APPEND(NULL, streams, num_streams, track->stream); } diff --git a/player/main.c b/player/main.c index 5f79e784ed..98abbc8e4f 100644 --- a/player/main.c +++ b/player/main.c @@ -42,6 +42,7 @@ #include "common/msg.h" #include "common/msg_control.h" #include "common/global.h" +#include "filters/f_decoder_wrapper.h" #include "options/parse_configfile.h" #include "options/parse_commandline.h" #include "common/playlist.h" @@ -54,7 +55,6 @@ #include "demux/demux.h" #include "stream/stream.h" #include "sub/osd.h" -#include "video/decode/dec_video.h" #include "video/out/vo.h" #include "core.h" diff --git a/player/osd.c b/player/osd.c index 875bc446db..fd6b421849 100644 --- a/player/osd.c +++ b/player/osd.c @@ -30,6 +30,7 @@ #include "options/options.h" #include "common/common.h" #include "options/m_property.h" +#include "filters/f_decoder_wrapper.h" #include "common/encode.h" #include "osdep/terminal.h" @@ -39,7 +40,6 @@ #include "stream/stream.h" #include "sub/osd.h" -#include "video/decode/dec_video.h" #include "video/out/vo.h" #include "core.h" @@ -221,8 +221,9 @@ static char *get_term_status_msg(struct MPContext *mpctx) talloc_free(r); } int64_t c = vo_get_drop_count(mpctx->video_out); - struct dec_video *d_video = mpctx->vo_chain->video_src; - int dropped_frames = d_video ? d_video->dropped_frames : 0; + struct mp_decoder_wrapper *dec = mpctx->vo_chain->track + ? mpctx->vo_chain->track->dec : NULL; + int dropped_frames = dec ? dec->dropped_frames : 0; 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 a75263cc5f..748469354d 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -29,6 +29,7 @@ #include "common/common.h" #include "common/encode.h" #include "common/recorder.h" +#include "filters/f_decoder_wrapper.h" #include "options/m_config.h" #include "options/m_property.h" #include "common/playlist.h" @@ -43,7 +44,6 @@ #include "demux/demux.h" #include "stream/stream.h" #include "sub/osd.h" -#include "video/decode/dec_video.h" #include "video/out/vo.h" #include "core.h" @@ -213,8 +213,6 @@ void add_step_frame(struct MPContext *mpctx, int dir) void reset_playback_state(struct MPContext *mpctx) { for (int n = 0; n < mpctx->num_tracks; n++) { - if (mpctx->tracks[n]->d_video) - video_reset(mpctx->tracks[n]->d_video); if (mpctx->tracks[n]->d_audio) audio_reset_decoding(mpctx->tracks[n]->d_audio); mpctx->tracks[n]->sink_eof = false; @@ -227,7 +225,6 @@ void reset_playback_state(struct MPContext *mpctx) reset_subtitle_state(mpctx); mpctx->hrseek_active = false; - mpctx->hrseek_framedrop = false; mpctx->hrseek_lastframe = false; mpctx->hrseek_backstep = false; mpctx->current_seek = (struct seek_params){0}; @@ -376,13 +373,22 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek) if (hr_seek) { mpctx->hrseek_active = true; - mpctx->hrseek_framedrop = !hr_seek_very_exact && opts->hr_seek_framedrop; mpctx->hrseek_backstep = seek.type == MPSEEK_BACKSTEP; mpctx->hrseek_pts = seek_pts; + // allow decoder to drop frames before hrseek_pts + bool hrseek_framedrop = !hr_seek_very_exact && opts->hr_seek_framedrop; + MP_VERBOSE(mpctx, "hr-seek, skipping to %f%s%s\n", mpctx->hrseek_pts, - mpctx->hrseek_framedrop ? "" : " (no framedrop)", + hrseek_framedrop ? "" : " (no framedrop)", mpctx->hrseek_backstep ? " (backstep)" : ""); + + for (int n = 0; n < mpctx->num_tracks; n++) { + struct track *track = mpctx->tracks[n]; + struct mp_decoder_wrapper *dec = track->dec; + if (dec && hrseek_framedrop) + mp_decoder_wrapper_set_start_pts(dec, mpctx->hrseek_pts); + } } if (mpctx->stop_play == AT_END_OF_FILE) @@ -1079,9 +1085,9 @@ static void handle_complex_filter_decoders(struct MPContext *mpctx) struct track *track = mpctx->tracks[n]; if (!track->selected) continue; - if (!track->sink || !mp_pin_in_needs_data(track->sink)) - continue; if (track->d_audio) { + if (!track->sink || !mp_pin_in_needs_data(track->sink)) + continue; audio_work(track->d_audio); struct mp_aframe *fr; int res = audio_get_frame(track->d_audio, &fr); @@ -1096,21 +1102,6 @@ static void handle_complex_filter_decoders(struct MPContext *mpctx) mp_wakeup_core(mpctx); } } - if (track->d_video) { - video_work(track->d_video); - struct mp_image *fr; - int res = video_get_frame(track->d_video, &fr); - if (res == DATA_OK) { - mp_pin_in_write(track->sink, MAKE_FRAME(MP_FRAME_VIDEO, fr)); - track->sink_eof = false; - } else if (res == DATA_EOF) { - if (!track->sink_eof) - mp_pin_in_write(track->sink, MP_EOF_FRAME); - track->sink_eof = true; - } else if (res == DATA_AGAIN) { - mp_wakeup_core(mpctx); - } - } } } diff --git a/player/screenshot.c b/player/screenshot.c index 5234b39d8e..16ff357dc8 100644 --- a/player/screenshot.c +++ b/player/screenshot.c @@ -34,7 +34,6 @@ #include "options/path.h" #include "video/mp_image.h" #include "video/mp_image_pool.h" -#include "video/decode/dec_video.h" #include "video/out/vo.h" #include "video/image_writer.h" #include "sub/osd.h" diff --git a/player/sub.c b/player/sub.c index 2d644e3e00..65b8ecc78f 100644 --- a/player/sub.c +++ b/player/sub.c @@ -33,7 +33,6 @@ #include "sub/dec_sub.h" #include "demux/demux.h" #include "video/mp_image.h" -#include "video/decode/dec_video.h" #include "core.h" diff --git a/player/video.c b/player/video.c index 483043f358..48b02ecec7 100644 --- a/player/video.c +++ b/player/video.c @@ -39,8 +39,7 @@ #include "stream/stream.h" #include "sub/osd.h" #include "video/hwdec.h" -#include "video/decode/dec_video.h" -#include "video/decode/vd.h" +#include "filters/f_decoder_wrapper.h" #include "video/out/vo.h" #include "audio/decode/dec_audio.h" @@ -55,7 +54,6 @@ enum { VD_PROGRESS = 1, // progress, but no output; repeat call with no waiting VD_NEW_FRAME = 2, // the call produced a new frame VD_WAIT = 3, // no EOF, but no output; wait until wakeup - VD_RECONFIG = 4, }; static const char av_desync_help_text[] = @@ -93,17 +91,7 @@ int reinit_video_filters(struct MPContext *mpctx) static void vo_chain_reset_state(struct vo_chain *vo_c) { - mp_image_unrefp(&vo_c->input_mpi); vo_seek_reset(vo_c->vo); - - if (vo_c->video_src) - video_reset(vo_c->video_src); - - // Prepare for continued playback after a seek. - if (!vo_c->input_mpi && vo_c->cached_coverart) - vo_c->input_mpi = mp_image_new_ref(vo_c->cached_coverart); - - vo_c->filter_src_got_eof = false; } void reset_video_state(struct MPContext *mpctx) @@ -123,7 +111,6 @@ void reset_video_state(struct MPContext *mpctx) mpctx->num_past_frames = 0; mpctx->total_avsync_change = 0; mpctx->last_av_difference = 0; - mpctx->dropped_frames_start = 0; mpctx->mistimed_frames_total = 0; mpctx->drop_message_shown = 0; mpctx->display_sync_drift_dir = 0; @@ -148,16 +135,15 @@ static void vo_chain_uninit(struct vo_chain *vo_c) if (track) { assert(track->vo_c == vo_c); track->vo_c = NULL; - assert(track->d_video == vo_c->video_src); - track->d_video = NULL; - video_uninit(vo_c->video_src); + if (vo_c->dec_src) + assert(track->dec->f->pins[0] == vo_c->dec_src); + talloc_free(track->dec->f); + track->dec = NULL; } if (vo_c->filter_src) mp_pin_disconnect(vo_c->filter_src); - mp_image_unrefp(&vo_c->input_mpi); - mp_image_unrefp(&vo_c->cached_coverart); talloc_free(vo_c->filter->f); talloc_free(vo_c); // this does not free the VO @@ -178,36 +164,25 @@ void uninit_video_chain(struct MPContext *mpctx) int init_video_decoder(struct MPContext *mpctx, struct track *track) { - assert(!track->d_video); + assert(!track->dec); if (!track->stream) goto err_out; - 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 = track->stream; - d_video->codec = track->stream->codec; - d_video->fps = d_video->header->codec->fps; + struct mp_filter *parent = mpctx->filter_root; + // If possible, set this as parent so the decoder gets the hwdec and DR + // interfaces. // Note: at least mpv_opengl_cb_uninit_gl() relies on being able to get // rid of all references to the VO by destroying the VO chain. Thus, // decoders not linked to vo_chain must not use the hwdec context. - if (mpctx->vo_chain) { - d_video->hwdec_devs = mpctx->vo_chain->hwdec_devs; - d_video->vo = mpctx->vo_chain->vo; - } - - MP_VERBOSE(d_video, "Container reported FPS: %f\n", d_video->fps); + if (track->vo_c) + parent = track->vo_c->filter->f; - if (d_video->opts->force_fps) { - d_video->fps = d_video->opts->force_fps; - MP_INFO(mpctx, "FPS forced to %5.3f.\n", d_video->fps); - MP_INFO(mpctx, "Use --no-correct-pts to force FPS based timing.\n"); - } + track->dec = mp_decoder_wrapper_create(parent, track->stream); + if (!track->dec) + goto err_out; - if (!video_init_best_codec(d_video)) + if (!mp_decoder_wrapper_reinit(track->dec)) goto err_out; return 1; @@ -216,8 +191,6 @@ err_out: if (track->sink) mp_pin_disconnect(track->sink); track->sink = NULL; - video_uninit(track->d_video); - track->d_video = NULL; error_on_track(mpctx, track); return 0; } @@ -232,6 +205,14 @@ void reinit_video_chain(struct MPContext *mpctx) reinit_video_chain_src(mpctx, track); } +static void filter_update_subtitles(void *ctx, double pts) +{ + struct MPContext *mpctx = ctx; + + if (osd_get_render_subs_in_filter(mpctx->osd)) + update_subtitles(mpctx, pts); +} + // (track=NULL creates a blank chain, used for lavfi-complex) void reinit_video_chain_src(struct MPContext *mpctx, struct track *track) { @@ -266,8 +247,8 @@ void reinit_video_chain_src(struct MPContext *mpctx, struct track *track) mp_output_chain_create(mpctx->filter_root, MP_OUTPUT_CHAIN_VIDEO); vo_c->filter->container_fps = vo_c->container_fps; mp_output_chain_set_vo(vo_c->filter, vo_c->vo); - - vo_c->hwdec_devs = vo_c->vo->hwdec_devs; + vo_c->filter->update_subtitles = filter_update_subtitles; + vo_c->filter->update_subtitles_ctx = mpctx; if (track) { vo_c->track = track; @@ -275,12 +256,14 @@ void reinit_video_chain_src(struct MPContext *mpctx, struct track *track) if (!init_video_decoder(mpctx, track)) goto err_out; - vo_c->video_src = track->d_video; - vo_c->container_fps = vo_c->video_src->fps; + vo_c->dec_src = track->dec->f->pins[0]; + vo_c->container_fps = track->dec->fps; vo_c->is_coverart = !!track->stream->attached_picture; track->vo_c = vo_c; vo_c->track = track; + + mp_pin_connect(vo_c->filter->f->pins[0], vo_c->dec_src); } #if HAVE_ENCODING @@ -328,129 +311,23 @@ void mp_force_video_refresh(struct MPContext *mpctx) } } -static bool check_framedrop(struct MPContext *mpctx, struct vo_chain *vo_c) +static void 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) && - vo_c->video_src) + vo_c->track && vo_c->track->dec && (opts->frame_dropping & 2)) { 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 = - 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); - } - return false; -} - -// Read a packet, store decoded image into d_video->waiting_decoded_mpi -// returns VD_* code -static int decode_image(struct MPContext *mpctx) -{ - struct vo_chain *vo_c = mpctx->vo_chain; - if (vo_c->input_mpi) - return VD_PROGRESS; - - int res = DATA_EOF; - if (vo_c->filter_src) { - struct mp_frame frame = mp_pin_out_read(vo_c->filter_src); - if (frame.type == MP_FRAME_EOF) { - res = DATA_EOF; - vo_c->filter_src_got_eof = true; - } else if (frame.type == MP_FRAME_VIDEO) { - res = DATA_OK; - vo_c->input_mpi = frame.data; - vo_c->filter_src_got_eof = false; - } else if (frame.type) { - MP_ERR(vo_c, "unexpected frame type\n"); - mp_frame_unref(&frame); - res = DATA_EOF; - } else { - res = vo_c->filter_src_got_eof ? DATA_EOF : DATA_WAIT; - } - } else if (vo_c->video_src) { - struct dec_video *d_video = vo_c->video_src; - bool hrseek = mpctx->hrseek_active && mpctx->hrseek_framedrop && - mpctx->video_status == STATUS_SYNCING; - video_set_start(d_video, hrseek ? mpctx->hrseek_pts : MP_NOPTS_VALUE); - - video_set_framedrop(d_video, check_framedrop(mpctx, vo_c)); - - video_work(d_video); - res = video_get_frame(d_video, &vo_c->input_mpi); - } - - switch (res) { - case DATA_WAIT: return VD_WAIT; - case DATA_OK: - case DATA_STARVE: - case DATA_AGAIN: return VD_PROGRESS; - case DATA_EOF: return VD_EOF; - default: abort(); - } -} - -static int video_filter(struct MPContext *mpctx, bool eof) -{ - struct vo_chain *vo_c = mpctx->vo_chain; - - if (vo_c->input_mpi || eof) { - struct mp_frame frame = {MP_FRAME_VIDEO, vo_c->input_mpi}; - if (!vo_c->input_mpi) { - frame = MP_EOF_FRAME; - if (vo_c->filter->got_input_eof) - return vo_c->filter->got_output_eof ? VD_EOF : VD_WAIT; - } - if (mp_pin_in_needs_data(vo_c->filter->f->pins[0])) { - if (osd_get_render_subs_in_filter(mpctx->osd)) - update_subtitles(mpctx, vo_c->input_mpi->pts); - mp_pin_in_write(vo_c->filter->f->pins[0], frame); - vo_c->input_mpi = NULL; - return VD_PROGRESS; - } - } - - return VD_WAIT; -} - -// Make sure at least 1 filtered image is available, decode new video if needed. -// returns VD_* code -// A return value of VD_PROGRESS doesn't necessarily output a frame, but makes -// the promise that calling this function again will eventually do something. -static int video_decode_and_filter(struct MPContext *mpctx) -{ - struct vo_chain *vo_c = mpctx->vo_chain; - - int r = video_filter(mpctx, false); - if (r < 0) - return r; - - if (!vo_c->input_mpi) { - if (vo_c->cached_coverart) { - // Don't ever decode it twice, not even after seek resets. - // (On seek resets, input_mpi is set to the cached image.) - r = VD_EOF; - } else { - // Decode a new image, or at least feed the decoder a packet. - r = decode_image(mpctx); - if (r == VD_WAIT) - return r; - } - } - - if (vo_c->input_mpi) { - if (vo_c->is_coverart && !vo_c->cached_coverart) - vo_c->cached_coverart = mp_image_new_ref(vo_c->input_mpi); - } else if (r == VD_EOF) { - r = video_filter(mpctx, true); + // it's a crappy heuristic; avoid getting upset by incorrect fps + if (fps <= 20 || fps >= 500) + return; + double frame_time = 1.0 / fps; + // try to drop as many frames as we appear to be behind + vo_c->track->dec->attempt_framedrops = + MPCLAMP((mpctx->last_av_difference - 0.010) / frame_time, 0, 100); } - - return r; } /* Modify video timing to match the audio timeline. There are two main @@ -511,9 +388,6 @@ static void handle_new_frame(struct MPContext *mpctx) mpctx->time_frame += frame_time / mpctx->video_speed; adjust_sync(mpctx, pts, frame_time); } - struct dec_video *d_video = mpctx->vo_chain->video_src; - if (d_video) - mpctx->dropped_frames_start = d_video->dropped_frames; MP_TRACE(mpctx, "frametime=%5.3f\n", frame_time); } @@ -586,18 +460,11 @@ static int video_output_image(struct MPContext *mpctx) int r = VD_PROGRESS; if (needs_new_frame(mpctx)) { // Filter a new frame. - if (!mp_pin_out_request_data(vo_c->filter->f->pins[1])) { - r = video_decode_and_filter(mpctx); - if (r < 0) - return r; // error - } struct mp_image *img = NULL; struct mp_frame frame = mp_pin_out_read(vo_c->filter->f->pins[1]); - if (frame.type == MP_FRAME_NONE && vo_c->filter->got_output_eof) - frame = MP_EOF_FRAME; - if (frame.type == MP_FRAME_NONE) - return video_decode_and_filter(mpctx); - if (frame.type == MP_FRAME_EOF) { + if (frame.type == MP_FRAME_NONE) { + r = vo_c->filter->got_output_eof ? VD_EOF : VD_WAIT; + } else if (frame.type == MP_FRAME_EOF) { r = VD_EOF; } else if (frame.type == MP_FRAME_VIDEO) { img = frame.data; @@ -657,11 +524,11 @@ static bool check_for_hwdec_fallback(struct MPContext *mpctx) { struct vo_chain *vo_c = mpctx->vo_chain; - if (!vo_c->filter->failed_output_conversion || !vo_c->video_src) + if (!vo_c->filter->failed_output_conversion || !vo_c->track) return false; - if (video_vd_control(vo_c->video_src, VDCTRL_FORCE_HWDEC_FALLBACK, NULL) - != CONTROL_OK) + if (mp_decoder_wrapper_control(vo_c->track->dec, + VDCTRL_FORCE_HWDEC_FALLBACK, NULL) != CONTROL_OK) return false; mp_output_chain_reset_harder(vo_c->filter); @@ -1213,11 +1080,8 @@ void write_video(struct MPContext *mpctx) // wait until VO wakes us up to get more frames // (NB: in theory, the 1st frame after display sync mode change uses the // wrong waiting mode) - if (!vo_is_ready_for_frame(vo, mpctx->display_sync_active ? -1 : pts)) { - if (video_decode_and_filter(mpctx) < 0) - goto error; + if (!vo_is_ready_for_frame(vo, mpctx->display_sync_active ? -1 : pts)) return; - } assert(mpctx->num_next_frames >= 1); @@ -1269,6 +1133,8 @@ void write_video(struct MPContext *mpctx) vo_queue_frame(vo, frame); + check_framedrop(mpctx, vo_c); + // The frames were shifted down; "initialize" the new first entry. if (mpctx->num_next_frames >= 1) handle_new_frame(mpctx); |