summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-01-17 18:07:50 +0100
committerwm4 <wm4@nowhere>2016-01-17 18:38:07 +0100
commit4195a345a51e52337bc972aacbce0fd6e88ebb5d (patch)
tree267a57310fffe943845d7ce2058447ccd7f7458d /player
parent004bc9526308c6bc3f51591423e88bb1adaff167 (diff)
downloadmpv-4195a345a51e52337bc972aacbce0fd6e88ebb5d.tar.bz2
mpv-4195a345a51e52337bc972aacbce0fd6e88ebb5d.tar.xz
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.
Diffstat (limited to 'player')
-rw-r--r--player/audio.c4
-rw-r--r--player/command.c86
-rw-r--r--player/core.h9
-rw-r--r--player/loadfile.c3
-rw-r--r--player/osd.c8
-rw-r--r--player/playloop.c12
-rw-r--r--player/screenshot.c4
-rw-r--r--player/sub.c3
-rw-r--r--player/video.c80
9 files changed, 109 insertions, 100 deletions
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)