summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--filters/f_decoder_wrapper.c109
-rw-r--r--filters/f_decoder_wrapper.h39
-rw-r--r--player/audio.c10
-rw-r--r--player/command.c21
-rw-r--r--player/osd.c3
-rw-r--r--player/playloop.c2
-rw-r--r--player/video.c9
7 files changed, 125 insertions, 68 deletions
diff --git a/filters/f_decoder_wrapper.c b/filters/f_decoder_wrapper.c
index 6f90df04ad..23e796a6bc 100644
--- a/filters/f_decoder_wrapper.c
+++ b/filters/f_decoder_wrapper.c
@@ -57,6 +57,8 @@ struct priv {
struct mp_codec_params *codec;
struct mp_decoder *decoder;
+ char *decoder_desc;
+ bool try_spdif;
// Demuxer output.
struct mp_pin *demux;
@@ -86,6 +88,8 @@ struct priv {
struct mp_image_params dec_format, last_format, fixed_format;
+ double fps;
+
double start_pts;
double start, end;
struct demux_packet *new_segment;
@@ -100,6 +104,11 @@ struct priv {
struct mp_frame decoded_coverart;
int coverart_returned; // 0: no, 1: coverart frame itself, 2: EOF returned
+ int attempt_framedrops; // try dropping this many frames
+ int dropped_frames; // total frames _probably_ dropped
+ bool pts_reset;
+ int play_dir;
+
struct mp_decoder_wrapper public;
};
@@ -134,9 +143,9 @@ static void reset(struct mp_filter *f)
p->pts = MP_NOPTS_VALUE;
p->last_format = p->fixed_format = (struct mp_image_params){0};
- p->public.dropped_frames = 0;
- p->public.attempt_framedrops = 0;
- p->public.pts_reset = false;
+ p->dropped_frames = 0;
+ p->attempt_framedrops = 0;
+ p->pts_reset = false;
p->coverart_returned = 0;
@@ -196,6 +205,9 @@ bool mp_decoder_wrapper_reinit(struct mp_decoder_wrapper *d)
reset_decoder(p);
p->has_broken_packet_pts = -10; // needs 10 packets to reach decision
+ talloc_free(p->decoder_desc);
+ p->decoder_desc = NULL;
+
const struct mp_decoder_fns *driver = NULL;
struct mp_decoder_list *list = NULL;
char *user_list = NULL;
@@ -210,7 +222,7 @@ bool mp_decoder_wrapper_reinit(struct mp_decoder_wrapper *d)
user_list = opts->audio_decoders;
fallback = "aac";
- if (p->public.try_spdif && p->codec->codec) {
+ if (p->try_spdif && p->codec->codec) {
struct mp_decoder_list *spdif =
select_spdif_codec(p->codec->codec, opts->audio_spdif);
if (spdif->num_entries) {
@@ -241,9 +253,9 @@ bool mp_decoder_wrapper_reinit(struct mp_decoder_wrapper *d)
p->decoder = driver->create(p->f, p->codec, sel->decoder);
if (p->decoder) {
- p->public.decoder_desc =
+ p->decoder_desc =
talloc_asprintf(p, "%s (%s)", sel->decoder, sel->desc);
- MP_VERBOSE(p, "Selected codec: %s\n", p->public.decoder_desc);
+ MP_VERBOSE(p, "Selected codec: %s\n", p->decoder_desc);
break;
}
@@ -259,6 +271,49 @@ bool mp_decoder_wrapper_reinit(struct mp_decoder_wrapper *d)
return !!p->decoder;
}
+void mp_decoder_wrapper_get_desc(struct mp_decoder_wrapper *d,
+ char *buf, size_t buf_size)
+{
+ struct priv *p = d->f->priv;
+ snprintf(buf, buf_size, "%s", p->decoder_desc ? p->decoder_desc : "");
+}
+
+void mp_decoder_wrapper_set_frame_drops(struct mp_decoder_wrapper *d, int num)
+{
+ struct priv *p = d->f->priv;
+ p->attempt_framedrops = num;
+}
+
+int mp_decoder_wrapper_get_frames_dropped(struct mp_decoder_wrapper *d)
+{
+ struct priv *p = d->f->priv;
+ return p->dropped_frames;
+}
+
+double mp_decoder_wrapper_get_container_fps(struct mp_decoder_wrapper *d)
+{
+ struct priv *p = d->f->priv;
+ return p->fps;
+}
+
+void mp_decoder_wrapper_set_spdif_flag(struct mp_decoder_wrapper *d, bool spdif)
+{
+ struct priv *p = d->f->priv;
+ p->try_spdif = spdif;
+}
+
+bool mp_decoder_wrapper_get_pts_reset(struct mp_decoder_wrapper *d)
+{
+ struct priv *p = d->f->priv;
+ return p->pts_reset;
+}
+
+void mp_decoder_wrapper_set_play_dir(struct mp_decoder_wrapper *d, int dir)
+{
+ struct priv *p = d->f->priv;
+ p->play_dir = dir;
+}
+
static bool is_valid_peak(float sig_peak)
{
return !sig_peak || (sig_peak >= 1 && sig_peak <= 100);
@@ -371,11 +426,11 @@ static void crazy_video_pts_stuff(struct priv *p, struct mp_image *mpi)
// Compensate for incorrectly using mpeg-style DTS for avi timestamps.
if (p->decoder && p->decoder->control && p->codec->avi_dts &&
- mpi->pts != MP_NOPTS_VALUE && p->public.fps > 0)
+ mpi->pts != MP_NOPTS_VALUE && p->fps > 0)
{
int delay = -1;
p->decoder->control(p->decoder->f, VDCTRL_GET_BFRAMES, &delay);
- mpi->pts -= MPMAX(delay, 0) / p->public.fps;
+ mpi->pts -= MPMAX(delay, 0) / p->fps;
}
}
@@ -441,10 +496,10 @@ static void correct_video_pts(struct priv *p, struct mp_image *mpi)
{
struct MPOpts *opts = p->opt_cache->opts;
- mpi->pts *= p->public.play_dir;
+ mpi->pts *= p->play_dir;
if (!opts->correct_pts || mpi->pts == MP_NOPTS_VALUE) {
- double fps = p->public.fps > 0 ? p->public.fps : 25;
+ double fps = p->fps > 0 ? p->fps : 25;
if (opts->correct_pts) {
if (p->has_broken_decoded_pts <= 1) {
@@ -471,7 +526,7 @@ static void correct_video_pts(struct priv *p, struct mp_image *mpi)
static void correct_audio_pts(struct priv *p, struct mp_aframe *aframe)
{
- double dir = p->public.play_dir;
+ double dir = p->play_dir;
double frame_pts = mp_aframe_get_pts(aframe);
double frame_len = mp_aframe_duration(aframe);
@@ -491,7 +546,7 @@ static void correct_audio_pts(struct priv *p, struct mp_aframe *aframe)
if (p->pts != MP_NOPTS_VALUE && diff > 0.1) {
MP_WARN(p, "Invalid audio PTS: %f -> %f\n", p->pts, frame_pts);
if (diff >= 5)
- p->public.pts_reset = true;
+ p->pts_reset = true;
}
// Keep the interpolated timestamp if it doesn't deviate more
@@ -520,11 +575,11 @@ static void process_output_frame(struct priv *p, struct mp_frame frame)
fix_image_params(p, &mpi->params);
mpi->params = p->fixed_format;
- mpi->nominal_fps = p->public.fps;
+ mpi->nominal_fps = p->fps;
} else if (frame.type == MP_FRAME_AUDIO) {
struct mp_aframe *aframe = frame.data;
- if (p->public.play_dir < 0 && !mp_aframe_reverse(aframe))
+ if (p->play_dir < 0 && !mp_aframe_reverse(aframe))
MP_ERR(p, "Couldn't reverse audio frame.\n");
correct_audio_pts(p, aframe);
@@ -544,7 +599,7 @@ static bool is_new_segment(struct priv *p, struct mp_frame frame)
struct demux_packet *pkt = frame.data;
return (pkt->segmented && (pkt->start != p->start || pkt->end != p->end ||
pkt->codec != p->codec)) ||
- (p->public.play_dir < 0 && pkt->back_restart && p->packet_fed);
+ (p->play_dir < 0 && pkt->back_restart && p->packet_fed);
}
static void feed_packet(struct priv *p)
@@ -590,10 +645,10 @@ static void feed_packet(struct priv *p)
int framedrop_type = 0;
- if (p->public.attempt_framedrops)
+ if (p->attempt_framedrops)
framedrop_type = 1;
- if (start_pts != MP_NOPTS_VALUE && packet && p->public.play_dir > 0 &&
+ if (start_pts != MP_NOPTS_VALUE && packet && p->play_dir > 0 &&
packet->pts < start_pts - .005 && !p->has_broken_packet_pts)
framedrop_type = 2;
@@ -695,11 +750,10 @@ static void read_frame(struct priv *p)
return;
}
- if (p->public.attempt_framedrops) {
+ if (p->attempt_framedrops) {
int dropped = MPMAX(0, p->packets_without_output - 1);
- p->public.attempt_framedrops =
- MPMAX(0, p->public.attempt_framedrops - dropped);
- p->public.dropped_frames += dropped;
+ p->attempt_framedrops = MPMAX(0, p->attempt_framedrops - dropped);
+ p->dropped_frames += dropped;
}
p->packets_without_output = 0;
@@ -715,7 +769,7 @@ static void read_frame(struct priv *p)
bool segment_ended = process_decoded_frame(p, &frame);
- if (p->public.play_dir < 0 && frame.type) {
+ if (p->play_dir < 0 && frame.type) {
enqueue_backward_frame(p, frame);
frame = MP_NO_FRAME;
}
@@ -786,10 +840,9 @@ struct mp_decoder_wrapper *mp_decoder_wrapper_create(struct mp_filter *parent,
p->f = f;
p->header = src;
p->codec = p->header->codec;
+ p->play_dir = 1;
w->f = f;
- w->play_dir = 1;
-
struct MPOpts *opts = p->opt_cache->opts;
mp_filter_add_pin(f, MP_PIN_OUT, "out");
@@ -797,13 +850,13 @@ struct mp_decoder_wrapper *mp_decoder_wrapper_create(struct mp_filter *parent,
if (p->header->type == STREAM_VIDEO) {
p->log = f->log = mp_log_new(f, parent->log, "!vd");
- p->public.fps = src->codec->fps;
+ p->fps = src->codec->fps;
- MP_VERBOSE(p, "Container reported FPS: %f\n", p->public.fps);
+ MP_VERBOSE(p, "Container reported FPS: %f\n", p->fps);
if (opts->force_fps) {
- p->public.fps = opts->force_fps;
- MP_INFO(p, "FPS forced to %5.3f.\n", p->public.fps);
+ p->fps = opts->force_fps;
+ MP_INFO(p, "FPS forced to %5.3f.\n", p->fps);
MP_INFO(p, "Use --no-correct-pts to force FPS based timing.\n");
}
} else if (p->header->type == STREAM_AUDIO) {
diff --git a/filters/f_decoder_wrapper.h b/filters/f_decoder_wrapper.h
index 28d9b5cb7b..51badaaabd 100644
--- a/filters/f_decoder_wrapper.h
+++ b/filters/f_decoder_wrapper.h
@@ -32,29 +32,8 @@ struct mp_decoder_wrapper {
// Filter with no input and 1 output, which returns the decoded data.
struct mp_filter *f;
- // For informational purposes.
- char *decoder_desc;
-
// Can be set by user.
struct mp_recorder_sink *recorder_sink;
- int play_dir;
-
- // --- for STREAM_VIDEO
-
- // FPS from demuxer or from user override
- float fps;
-
- // Framedrop control for playback (not used for hr seek etc.)
- int attempt_framedrops; // try dropping this many frames
- int dropped_frames; // total frames _probably_ dropped
-
- // --- for STREAM_AUDIO
-
- // Prefer spdif wrapper over real decoders.
- bool try_spdif;
-
- // A pts reset was observed (audio only, heuristic).
- bool pts_reset;
};
// Create the decoder wrapper for the given stream, plus underlying decoder.
@@ -63,6 +42,24 @@ struct mp_decoder_wrapper {
struct mp_decoder_wrapper *mp_decoder_wrapper_create(struct mp_filter *parent,
struct sh_stream *src);
+// For informational purposes.
+void mp_decoder_wrapper_get_desc(struct mp_decoder_wrapper *d,
+ char *buf, size_t buf_size);
+
+// Legacy decoder framedrop control.
+void mp_decoder_wrapper_set_frame_drops(struct mp_decoder_wrapper *d, int num);
+int mp_decoder_wrapper_get_frames_dropped(struct mp_decoder_wrapper *d);
+
+double mp_decoder_wrapper_get_container_fps(struct mp_decoder_wrapper *d);
+
+// Whether to prefer spdif wrapper over real decoders on next reinit.
+void mp_decoder_wrapper_set_spdif_flag(struct mp_decoder_wrapper *d, bool spdif);
+
+// True if a pts reset was observed (audio only, heuristic).
+bool mp_decoder_wrapper_get_pts_reset(struct mp_decoder_wrapper *d);
+
+void mp_decoder_wrapper_set_play_dir(struct mp_decoder_wrapper *d, int dir);
+
struct mp_decoder_list *video_decoder_list(void);
struct mp_decoder_list *audio_decoder_list(void);
diff --git a/player/audio.c b/player/audio.c
index 8aba3d860b..cde444ffb4 100644
--- a/player/audio.c
+++ b/player/audio.c
@@ -190,7 +190,7 @@ void reset_audio_state(struct MPContext *mpctx)
ao_chain_reset_state(mpctx->ao_chain);
struct track *t = mpctx->ao_chain->track;
if (t && t->dec)
- t->dec->play_dir = mpctx->play_dir;
+ mp_decoder_wrapper_set_play_dir(t->dec, mpctx->play_dir);
}
mpctx->audio_status = mpctx->ao_chain ? STATUS_SYNCING : STATUS_EOF;
mpctx->delay = 0;
@@ -389,7 +389,7 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx)
MP_VERBOSE(mpctx, "Falling back to PCM output.\n");
ao_c->spdif_passthrough = false;
ao_c->spdif_failed = true;
- ao_c->track->dec->try_spdif = false;
+ mp_decoder_wrapper_set_spdif_flag(ao_c->track->dec, false);
if (!mp_decoder_wrapper_reinit(ao_c->track->dec))
goto init_error;
reset_audio_state(mpctx);
@@ -441,7 +441,7 @@ int init_audio_decoder(struct MPContext *mpctx, struct track *track)
goto init_error;
if (track->ao_c)
- track->dec->try_spdif = true;
+ mp_decoder_wrapper_set_spdif_flag(track->dec, true);
if (!mp_decoder_wrapper_reinit(track->dec))
goto init_error;
@@ -776,7 +776,7 @@ void reload_audio_output(struct MPContext *mpctx)
if (dec && ao_c->spdif_failed) {
ao_c->spdif_passthrough = true;
ao_c->spdif_failed = false;
- dec->try_spdif = true;
+ mp_decoder_wrapper_set_spdif_flag(ao_c->track->dec, true);
if (!mp_decoder_wrapper_reinit(dec)) {
MP_ERR(mpctx, "Error reinitializing audio.\n");
error_on_track(mpctx, ao_c->track);
@@ -836,7 +836,7 @@ void fill_audio_out_buffers(struct MPContext *mpctx)
}
if (mpctx->vo_chain && ao_c->track && ao_c->track->dec &&
- ao_c->track->dec->pts_reset)
+ mp_decoder_wrapper_get_pts_reset(ao_c->track->dec))
{
MP_WARN(mpctx, "Reset playback due to audio timestamp reset.\n");
reset_playback_state(mpctx);
diff --git a/player/command.c b/player/command.c
index 9e0f4f64e9..fb28b285e1 100644
--- a/player/command.c
+++ b/player/command.c
@@ -674,7 +674,8 @@ static int mp_property_frame_drop_dec(void *ctx, struct m_property *prop,
if (!dec)
return M_PROPERTY_UNAVAILABLE;
- return m_property_int_ro(action, arg, dec->dropped_frames);
+ return m_property_int_ro(action, arg,
+ mp_decoder_wrapper_get_frames_dropped(dec));
}
static int mp_property_mistimed_frame_count(void *ctx, struct m_property *prop,
@@ -1753,8 +1754,10 @@ static int mp_property_audio_codec(void *ctx, struct m_property *prop,
{
MPContext *mpctx = ctx;
struct track *track = mpctx->current_track[0][STREAM_AUDIO];
- const char *c = track && track->dec ? track->dec->decoder_desc : NULL;
- return m_property_strdup_ro(action, arg, c);
+ char desc[256] = "";
+ if (track && track->dec)
+ mp_decoder_wrapper_get_desc(track->dec, desc, sizeof(desc));
+ return m_property_strdup_ro(action, arg, desc[0] ? desc : NULL);
}
static int property_audiofmt(struct mp_aframe *fmt, int action, void *arg)
@@ -1904,9 +1907,9 @@ static int get_track_entry(int item, int action, void *arg, void *ctx)
struct mp_codec_params p =
track->stream ? *track->stream->codec : (struct mp_codec_params){0};
- const char *decoder_desc = NULL;
+ char decoder_desc[256];
if (track->dec)
- decoder_desc = track->dec->decoder_desc;
+ mp_decoder_wrapper_get_desc(track->dec, decoder_desc, sizeof(decoder_desc));
bool has_rg = track->stream && track->stream->codec->replaygain_data;
struct replaygain_data rg = has_rg ? *track->stream->codec->replaygain_data
@@ -1940,7 +1943,7 @@ static int get_track_entry(int item, int action, void *arg, void *ctx)
.unavailable = !track->external_filename},
{"ff-index", SUB_PROP_INT(track->ff_index)},
{"decoder-desc", SUB_PROP_STR(decoder_desc),
- .unavailable = !decoder_desc},
+ .unavailable = !decoder_desc[0]},
{"codec", SUB_PROP_STR(p.codec),
.unavailable = !p.codec},
{"demux-w", SUB_PROP_INT(p.disp_w), .unavailable = !p.disp_w},
@@ -2106,8 +2109,10 @@ 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->dec ? track->dec->decoder_desc : NULL;
- return m_property_strdup_ro(action, arg, c);
+ char desc[256] = "";
+ if (track && track->dec)
+ mp_decoder_wrapper_get_desc(track->dec, desc, sizeof(desc));
+ return m_property_strdup_ro(action, arg, desc[0] ? desc : NULL);
}
static int property_imgparams(struct mp_image_params p, int action, void *arg)
diff --git a/player/osd.c b/player/osd.c
index ff9bd9b429..0e8fd2a0e7 100644
--- a/player/osd.c
+++ b/player/osd.c
@@ -220,7 +220,8 @@ static char *get_term_status_msg(struct MPContext *mpctx)
int64_t c = vo_get_drop_count(mpctx->video_out);
struct mp_decoder_wrapper *dec = mpctx->vo_chain->track
? mpctx->vo_chain->track->dec : NULL;
- int dropped_frames = dec ? dec->dropped_frames : 0;
+ int dropped_frames =
+ dec ? mp_decoder_wrapper_get_frames_dropped(dec) : 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 c8c74edb64..9660a5b6ad 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -229,7 +229,7 @@ void reset_playback_state(struct MPContext *mpctx)
struct track *t = mpctx->tracks[n];
// (Often, but not always, this is redundant and also done elsewhere.)
if (t->dec)
- t->dec->play_dir = mpctx->play_dir;
+ mp_decoder_wrapper_set_play_dir(t->dec, mpctx->play_dir);
if (t->d_sub)
sub_set_play_dir(t->d_sub, mpctx->play_dir);
}
diff --git a/player/video.c b/player/video.c
index d1e1554ef0..2e0c8f6460 100644
--- a/player/video.c
+++ b/player/video.c
@@ -101,7 +101,7 @@ void reset_video_state(struct MPContext *mpctx)
vo_chain_reset_state(mpctx->vo_chain);
struct track *t = mpctx->vo_chain->track;
if (t && t->dec)
- t->dec->play_dir = mpctx->play_dir;
+ mp_decoder_wrapper_set_play_dir(t->dec, mpctx->play_dir);
}
for (int n = 0; n < mpctx->num_next_frames; n++)
@@ -259,7 +259,8 @@ void reinit_video_chain_src(struct MPContext *mpctx, struct track *track)
goto err_out;
vo_c->dec_src = track->dec->f->pins[0];
- vo_c->filter->container_fps = track->dec->fps;
+ vo_c->filter->container_fps =
+ mp_decoder_wrapper_get_container_fps(track->dec);
vo_c->is_coverart = !!track->stream->attached_picture;
vo_c->is_sparse = track->stream->still_image || vo_c->is_coverart;
@@ -323,8 +324,8 @@ static void check_framedrop(struct MPContext *mpctx, struct vo_chain *vo_c)
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);
+ mp_decoder_wrapper_set_frame_drops(vo_c->track->dec,
+ MPCLAMP((mpctx->last_av_difference - 0.010) / frame_time, 0, 100));
}
}