summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
Diffstat (limited to 'player')
-rw-r--r--player/audio.c1
-rw-r--r--player/command.c41
-rw-r--r--player/core.h14
-rw-r--r--player/loadfile.c27
-rw-r--r--player/main.c2
-rw-r--r--player/osd.c7
-rw-r--r--player/playloop.c37
-rw-r--r--player/screenshot.c1
-rw-r--r--player/sub.c1
-rw-r--r--player/video.c228
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, &current);
+ mp_decoder_wrapper_control(dec, VDCTRL_GET_HWDEC, &current);
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);