summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Herkt <lachs0r@srsfckn.biz>2016-08-26 19:15:57 +0200
committerMartin Herkt <lachs0r@srsfckn.biz>2016-08-26 19:15:57 +0200
commite60a36bd4e27162ddc26212ab67afdd69b4164ed (patch)
tree08e9ca345558bc57500a0a1cdf018a9bf837d972
parentef2d6ed12537fbd6d5cd98f8759a5d00fe3e8610 (diff)
parentbc97d60542b353141bedeee985f9e5bd68b9f076 (diff)
downloadmpv-e60a36bd4e27162ddc26212ab67afdd69b4164ed.tar.bz2
mpv-e60a36bd4e27162ddc26212ab67afdd69b4164ed.tar.xz
Merge branch 'master' into release/current
-rw-r--r--.github/ISSUE_TEMPLATE4
-rw-r--r--DOCS/interface-changes.rst4
-rw-r--r--DOCS/man/input.rst4
-rw-r--r--DOCS/man/options.rst29
-rw-r--r--DOCS/man/vo.rst10
-rw-r--r--audio/decode/ad_lavc.c3
-rw-r--r--audio/filter/af.c6
-rw-r--r--audio/filter/af.h1
-rw-r--r--audio/filter/af_lavrresample.c30
-rw-r--r--audio/out/ao_alsa.c4
-rw-r--r--common/av_common.c31
-rw-r--r--common/av_common.h1
-rw-r--r--demux/demux.c32
-rw-r--r--demux/demux.h3
-rw-r--r--demux/demux_lavf.c23
-rw-r--r--demux/demux_mf.c1
-rw-r--r--demux/demux_raw.c4
-rw-r--r--demux/stheader.h6
-rw-r--r--options/m_option.c27
-rw-r--r--options/options.c7
-rw-r--r--options/options.h1
-rw-r--r--player/audio.c81
-rw-r--r--player/command.c100
-rw-r--r--player/command.h2
-rw-r--r--player/core.h10
-rw-r--r--player/loadfile.c6
-rw-r--r--player/misc.c10
-rw-r--r--player/playloop.c41
-rw-r--r--player/video.c53
-rw-r--r--stream/cache.c24
-rw-r--r--stream/stream_memory.c1
-rw-r--r--ta/ta.h4
-rw-r--r--video/decode/vd_lavc.c10
-rw-r--r--video/filter/vf.c7
-rw-r--r--video/filter/vf.h1
-rw-r--r--video/filter/vf_rotate.c11
-rw-r--r--video/out/aspect.c10
-rw-r--r--video/out/opengl/context.h1
-rw-r--r--video/out/opengl/context_angle.c9
-rw-r--r--video/out/vo.c51
-rw-r--r--video/out/vo.h3
-rw-r--r--video/out/vo_opengl.c5
-rw-r--r--video/out/w32_common.c152
-rw-r--r--video/out/x11_common.c14
-rw-r--r--wscript2
45 files changed, 583 insertions, 256 deletions
diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE
index 9edfac412d..8576f3d072 100644
--- a/.github/ISSUE_TEMPLATE
+++ b/.github/ISSUE_TEMPLATE
@@ -13,7 +13,9 @@ If you're not using git master or the latest release, update.
Make a log file made with -v or --log-file=output.txt, paste it to
http://sprunge.us or a similar site, and replace this text with a link to it.
-Do not bother reporting a bug if you do not provide the required information.
+Providing a log file is strongly encouraged. It is very helpful for reproducing
+bugs or getting important technical context. Without log it might not be
+possible to analyze and fix certain bugs.
### Sample files
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst
index d7db0106b4..f02f6588ff 100644
--- a/DOCS/interface-changes.rst
+++ b/DOCS/interface-changes.rst
@@ -19,6 +19,10 @@ Interface changes
::
+ --- mpv 0.20.0 ---
+ - add --image-display-duration option - this also means that image duration
+ is not influenced by --mf-fps anymore in the general case (this is an
+ incompatible change)
--- mpv 0.19.0 ---
- deprecate "balance" option/property (no replacement)
--- mpv 0.18.1 ---
diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst
index 2cc41bf5d5..8cdba41a3d 100644
--- a/DOCS/man/input.rst
+++ b/DOCS/man/input.rst
@@ -526,7 +526,7 @@ Input Commands that are Possibly Subject to Change
``disable-section "<section>"``
Disable the named input section. Undoes ``enable-section``.
-``define-section "<section>" "<contents>" [default|forced]``
+``define-section "<section>" "<contents>" [default|force]``
Create a named input section, or replace the contents of an already existing
input section. The ``contents`` parameter uses the same syntax as the
``input.conf`` file (except that using the section syntax in it is not
@@ -544,7 +544,7 @@ Input Commands that are Possibly Subject to Change
<default> (also used if parameter omitted)
Use a key binding defined by this section only if the user hasn't
already bound this key to a command.
- <forced>
+ <force>
Always bind a key. (The input section that was made active most recently
wins if there are ambiguities.)
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 39416d2a64..ec8f82349d 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -701,6 +701,8 @@ Video
controls how much of the image is cropped. May not work with all video
output drivers.
+ This option has no effect if ``--video-unscaled`` option is used.
+
``--video-aspect=<ratio>``
Override video aspect ratio, in case aspect information is incorrect or
missing in the file being played. See also ``--no-video-aspect``.
@@ -738,10 +740,12 @@ Video
choices if you encounter video that has the wrong aspect ratio in mpv,
but seems to be correct in other players.
-``--video-unscaled``
+``--video-unscaled=<no|yes|downscale-big>``
Disable scaling of the video. If the window is larger than the video,
- black bars are added. Otherwise, the video is cropped. The video still
- can be influenced by the other ``--video-...`` options.
+ black bars are added. Otherwise, the video is cropped, unless the option
+ is set to ``downscale-big``, in which case the video is fit to window. The
+ video still can be influenced by the other ``--video-...`` options. This
+ option disables the effect of ``--panscan``.
Note that the scaler algorithm may still be used, even if the video isn't
scaled. For example, this can influence chroma conversion. The video will
@@ -1873,6 +1877,23 @@ Window
file.mkv normally, then fail to open ``/dev/null``, then exit). (In
mpv 0.8.0, ``always`` was introduced, which restores the old behavior.)
+``--image-display-duration=<seconds|inf>``
+ If the current file is an image, play the image for the given amount of
+ seconds (default: 1). ``inf`` means the file is kept open forever (until
+ the user stops playback manually).
+
+ Unlike ``--keep-open``, the player is not paused, but simply continues
+ playback until the time has elapsed. (It should not use any resources
+ during "playback".)
+
+ This affects image files, which are defined as having only 1 video frame
+ and no audio. The player may recognize certain non-images as images, for
+ example if ``--length`` is used to reduce the length to 1 frame, or if
+ you seek to the last frame.
+
+ This option does not affect the framerate used for ``mf://`` or
+ ``--merge-files``. For that, use ``--mf-fps`` instead.
+
``--force-window=<yes|no|immediate>``
Create a video output window even if there is no video. This can be useful
when pretending that mpv is a GUI application. Currently, the window
@@ -3650,7 +3671,7 @@ Miscellaneous
``--video-sync-max-audio-change=<value>``
Maximum *additional* speed difference in percent that is applied to audio
with ``--video-sync=display-...`` (default: 0.125). Normally, the player
- play the audio at the speed of the video. But if the difference between
+ plays the audio at the speed of the video. But if the difference between
audio and video position is too high, e.g. due to drift or other timing
errors, it will attempt to speed up or slow down audio by this additional
factor. Too low values could lead to video frame dropping or repeating if
diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst
index 0beaee59a5..c775f6dde7 100644
--- a/DOCS/man/vo.rst
+++ b/DOCS/man/vo.rst
@@ -881,6 +881,16 @@ Available video output drivers are:
Windows only.
+ ``dcomposition=<yes|no>``
+ Allows DirectComposition when using the ANGLE backend (default: yes).
+ DirectComposition implies flip-model presentation, which can improve
+ rendering efficiency on Windows 8+ by avoiding a copy of the video frame.
+ mpv uses it by default where possible, but it can cause poor behaviour
+ with some drivers, such as a black screen or graphical corruption when
+ leaving full-screen mode. Use "no" to disable it.
+
+ Windows with ANGLE only.
+
``sw``
Continue even if a software renderer is detected.
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c
index c785c62c90..78d0cec807 100644
--- a/audio/decode/ad_lavc.c
+++ b/audio/decode/ad_lavc.c
@@ -86,7 +86,7 @@ static int init(struct dec_audio *da, const char *decoder)
struct priv *ctx = talloc_zero(NULL, struct priv);
da->priv = ctx;
- ctx->codec_timebase = (AVRational){0};
+ ctx->codec_timebase = mp_get_codec_timebase(da->codec);
ctx->force_channel_map = c->force_channels;
@@ -103,6 +103,7 @@ static int init(struct dec_audio *da, const char *decoder)
lavc_context->refcounted_frames = 1;
lavc_context->codec_type = AVMEDIA_TYPE_AUDIO;
lavc_context->codec_id = lavc_codec->id;
+ lavc_context->time_base = ctx->codec_timebase;
if (opts->downmix && mpopts->audio_output_channels.num_chmaps == 1) {
lavc_context->request_channel_layout =
diff --git a/audio/filter/af.c b/audio/filter/af.c
index a132965295..f380459747 100644
--- a/audio/filter/af.c
+++ b/audio/filter/af.c
@@ -779,6 +779,12 @@ struct mp_audio *af_read_output_frame(struct af_stream *s)
return af_dequeue_output_frame(s->last);
}
+void af_unread_output_frame(struct af_stream *s, struct mp_audio *frame)
+{
+ struct af_instance *af = s->last;
+ MP_TARRAY_INSERT_AT(af, af->out_queued, af->num_out_queued, 0, frame);
+}
+
// Make sure the caller can change data referenced by the frame.
// Return negative error code on failure (i.e. you can't write).
int af_make_writeable(struct af_instance *af, struct mp_audio *frame)
diff --git a/audio/filter/af.h b/audio/filter/af.h
index 697024b781..a773f561b3 100644
--- a/audio/filter/af.h
+++ b/audio/filter/af.h
@@ -148,6 +148,7 @@ void af_add_output_frame(struct af_instance *af, struct mp_audio *frame);
int af_filter_frame(struct af_stream *s, struct mp_audio *frame);
int af_output_frame(struct af_stream *s, bool eof);
struct mp_audio *af_read_output_frame(struct af_stream *s);
+void af_unread_output_frame(struct af_stream *s, struct mp_audio *frame);
int af_make_writeable(struct af_instance *af, struct mp_audio *frame);
double af_calc_delay(struct af_stream *s);
diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c
index fdef69a16b..dc5d1a0d23 100644
--- a/audio/filter/af_lavrresample.c
+++ b/audio/filter/af_lavrresample.c
@@ -99,10 +99,6 @@ static double get_delay(struct af_resample *s)
return avresample_get_delay(s->avrctx) / (double)s->in_rate +
avresample_available(s->avrctx) / (double)s->out_rate;
}
-static void drop_all_output(struct af_resample *s)
-{
- while (avresample_read(s->avrctx, NULL, 1000) > 0) {}
-}
static int get_out_samples(struct af_resample *s, int in_samples)
{
return avresample_get_out_samples(s->avrctx, in_samples);
@@ -113,10 +109,6 @@ static double get_delay(struct af_resample *s)
int64_t base = s->in_rate * (int64_t)s->out_rate;
return swr_get_delay(s->avrctx, base) / (double)base;
}
-static void drop_all_output(struct af_resample *s)
-{
- while (swr_drop_output(s->avrctx, 1000) > 0) {}
-}
static int get_out_samples(struct af_resample *s, int in_samples)
{
#if LIBSWRESAMPLE_VERSION_MAJOR > 1 || LIBSWRESAMPLE_VERSION_MINOR >= 2
@@ -406,8 +398,17 @@ static int control(struct af_instance *af, int cmd, void *arg)
return AF_OK;
}
case AF_CONTROL_RESET:
- if (s->avrctx)
- drop_all_output(s);
+ if (s->avrctx) {
+#if HAVE_LIBSWRESAMPLE
+ swr_close(s->avrctx);
+ if (swr_init(s->avrctx) < 0) {
+ close_lavrr(af);
+ return AF_ERROR;
+ }
+#else
+ while (avresample_read(s->avrctx, NULL, 1000) > 0) {}
+#endif
+ }
return AF_OK;
}
return AF_UNKNOWN;
@@ -479,19 +480,20 @@ static void reorder_planes(struct mp_audio *mpa, int *reorder,
static int filter_resample(struct af_instance *af, struct mp_audio *in)
{
struct af_resample *s = af->priv;
+ struct mp_audio *out = NULL;
+
+ if (!s->avrctx)
+ goto error;
int samples = get_out_samples(s, in ? in->samples : 0);
struct mp_audio out_format = s->pool_fmt;
- struct mp_audio *out = mp_audio_pool_get(af->out_pool, &out_format, samples);
+ out = mp_audio_pool_get(af->out_pool, &out_format, samples);
if (!out)
goto error;
if (in)
mp_audio_copy_attributes(out, in);
- if (!s->avrctx)
- goto error;
-
if (out->samples) {
out->samples = resample_frame(s->avrctx, out, in);
if (out->samples < 0)
diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c
index bbe15b4b61..c6248d302b 100644
--- a/audio/out/ao_alsa.c
+++ b/audio/out/ao_alsa.c
@@ -337,8 +337,10 @@ static bool query_chmaps(struct ao *ao, struct mp_chmap *chmap)
struct mp_chmap_sel chmap_sel = {.tmp = p};
snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps(p->alsa);
- if (!maps)
+ if (!maps) {
+ MP_VERBOSE(ao, "snd_pcm_query_chmaps() returned NULL\n");
return false;
+ }
for (int i = 0; maps[i] != NULL; i++) {
char aname[128];
diff --git a/common/av_common.c b/common/av_common.c
index e40c751e9f..3a424b0c62 100644
--- a/common/av_common.c
+++ b/common/av_common.c
@@ -16,6 +16,7 @@
*/
#include <assert.h>
+#include <math.h>
#include <libavutil/common.h>
#include <libavutil/log.h>
@@ -84,6 +85,30 @@ void mp_set_lav_codec_headers(AVCodecContext *avctx, struct mp_codec_params *c)
#endif
}
+// Pick a "good" timebase, which will be used to convert double timestamps
+// back to fractions for passing them through libavcodec.
+AVRational mp_get_codec_timebase(struct mp_codec_params *c)
+{
+ AVRational tb = {c->native_tb_num, c->native_tb_den};
+ if (tb.num < 1 || tb.den < 1) {
+ if (c->reliable_fps)
+ tb = av_inv_q(av_d2q(c->fps, 1000000));
+ if (tb.num < 1 || tb.den < 1)
+ tb = AV_TIME_BASE_Q;
+ }
+
+ // If the timebase is too coarse, raise its precision, or small adjustments
+ // to timestamps done between decoder and demuxer could be lost.
+ if (av_q2d(tb) > 0.001) {
+ AVRational r = av_div_q(tb, (AVRational){1, 1000});
+ tb.den *= (r.num + r.den - 1) / r.den;
+ }
+
+ av_reduce(&tb.num, &tb.den, tb.num, tb.den, 1000000);
+
+ return tb;
+}
+
// We merely pass-through our PTS/DTS as an int64_t; libavcodec won't use it.
union pts { int64_t i; double d; };
@@ -97,8 +122,10 @@ union pts { int64_t i; double d; };
int64_t mp_pts_to_av(double mp_pts, AVRational *tb)
{
assert(sizeof(int64_t) >= sizeof(double));
- if (tb && tb->num > 0 && tb->den > 0)
- return mp_pts == MP_NOPTS_VALUE ? AV_NOPTS_VALUE : mp_pts / av_q2d(*tb);
+ if (tb && tb->num > 0 && tb->den > 0) {
+ return mp_pts == MP_NOPTS_VALUE ?
+ AV_NOPTS_VALUE : llrint(mp_pts / av_q2d(*tb));
+ }
// The + 0.0 is to squash possible negative zero mp_pts, which would
// happen to end up as AV_NOPTS_VALUE.
return (union pts){.d = mp_pts + 0.0}.i;
diff --git a/common/av_common.h b/common/av_common.h
index e2b86bfe40..4b13dcdd0c 100644
--- a/common/av_common.h
+++ b/common/av_common.h
@@ -33,6 +33,7 @@ struct mp_log;
int mp_lavc_set_extradata(AVCodecContext *avctx, void *ptr, int size);
void mp_copy_lav_codec_headers(AVCodecContext *avctx, AVCodecContext *st);
void mp_set_lav_codec_headers(AVCodecContext *avctx, struct mp_codec_params *c);
+AVRational mp_get_codec_timebase(struct mp_codec_params *c);
void mp_set_av_packet(AVPacket *dst, struct demux_packet *mpkt, AVRational *tb);
int64_t mp_pts_to_av(double mp_pts, AVRational *tb);
double mp_pts_from_av(int64_t av_pts, AVRational *tb);
diff --git a/demux/demux.c b/demux/demux.c
index 648e629f77..29e13f3344 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -580,12 +580,12 @@ static bool read_packet(struct demux_internal *in)
if (packs >= in->max_packs || bytes >= in->max_bytes) {
if (!in->warned_queue_overflow) {
in->warned_queue_overflow = true;
- MP_ERR(in, "Too many packets in the demuxer packet queues:\n");
+ MP_WARN(in, "Too many packets in the demuxer packet queues:\n");
for (int n = 0; n < in->num_streams; n++) {
struct demux_stream *ds = in->streams[n]->ds;
if (ds->selected) {
- MP_ERR(in, " %s/%d: %zd packets, %zd bytes\n",
- stream_type_name(ds->type), n, ds->packs, ds->bytes);
+ MP_WARN(in, " %s/%d: %zd packets, %zd bytes\n",
+ stream_type_name(ds->type), n, ds->packs, ds->bytes);
}
}
}
@@ -1031,6 +1031,7 @@ static void demux_copy(struct demuxer *dst, struct demuxer *src)
dst->ts_resets_possible = src->ts_resets_possible;
dst->fully_read = src->fully_read;
dst->start_time = src->start_time;
+ dst->is_network = src->is_network;
dst->priv = src->priv;
}
@@ -1039,10 +1040,10 @@ static void demux_copy(struct demuxer *dst, struct demuxer *src)
dst->metadata = mp_tags_dup(dst, src->metadata);
if (dst->num_update_stream_tags != src->num_update_stream_tags) {
+ dst->num_update_stream_tags = src->num_update_stream_tags;
talloc_free(dst->update_stream_tags);
dst->update_stream_tags =
talloc_zero_array(dst, struct mp_tags *, dst->num_update_stream_tags);
- dst->num_update_stream_tags = src->num_update_stream_tags;
}
for (int n = 0; n < dst->num_update_stream_tags; n++) {
talloc_free(dst->update_stream_tags[n]);
@@ -1151,6 +1152,23 @@ static void demux_init_cuesheet(struct demuxer *demuxer)
}
}
+static void demux_maybe_replace_stream(struct demuxer *demuxer)
+{
+ struct demux_internal *in = demuxer->in;
+ assert(!in->threading && demuxer == in->d_user);
+
+ if (demuxer->fully_read) {
+ MP_VERBOSE(demuxer, "assuming demuxer read all data; closing stream\n");
+ free_stream(demuxer->stream);
+ demuxer->stream = open_memory_stream(NULL, 0); // dummy
+ in->d_thread->stream = demuxer->stream;
+ in->d_buffer->stream = demuxer->stream;
+
+ if (demuxer->desc->control)
+ demuxer->desc->control(in->d_thread, DEMUXER_CTRL_REPLACE_STREAM, NULL);
+ }
+}
+
static struct demuxer *open_given_type(struct mpv_global *global,
struct mp_log *log,
const struct demuxer_desc *desc,
@@ -1172,6 +1190,7 @@ static struct demuxer *open_given_type(struct mpv_global *global,
.log = mp_log_new(demuxer, log, desc->name),
.glog = log,
.filename = talloc_strdup(demuxer, stream->url),
+ .is_network = stream->is_network,
.events = DEMUX_EVENT_ALL,
};
demuxer->seekable = stream->seekable;
@@ -1311,6 +1330,7 @@ done:
// Convenience function: open the stream, enable the cache (according to params
// and global opts.), open the demuxer.
// (use free_demuxer_and_stream() to free the underlying stream too)
+// Also for some reason may close the opened stream if it's not needed.
struct demuxer *demux_open_url(const char *url,
struct demuxer_params *params,
struct mp_cancel *cancel,
@@ -1329,7 +1349,9 @@ struct demuxer *demux_open_url(const char *url,
if (!params->disable_cache)
stream_enable_cache(&s, &opts->stream_cache);
struct demuxer *d = demux_open(s, params, global);
- if (!d) {
+ if (d) {
+ demux_maybe_replace_stream(d);
+ } else {
params->demuxer_failed = true;
free_stream(s);
}
diff --git a/demux/demux.h b/demux/demux.h
index 07803d2838..9978335cfd 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -43,6 +43,7 @@ enum demux_ctrl {
DEMUXER_CTRL_STREAM_CTRL,
DEMUXER_CTRL_GET_READER_STATE,
DEMUXER_CTRL_GET_BITRATE_STATS, // double[STREAM_TYPE_COUNT]
+ DEMUXER_CTRL_REPLACE_STREAM,
};
struct demux_ctrl_reader_state {
@@ -183,6 +184,7 @@ typedef struct demuxer {
// packets is not slow either (unlike e.g. libavdevice pseudo-demuxers).
// Typical examples: text subtitles, playlists
bool fully_read;
+ bool is_network; // opened directly from a network stream
// Bitmask of DEMUX_EVENT_*
int events;
@@ -219,6 +221,7 @@ typedef struct demuxer {
// thread-safe, only the demuxer is allowed to access the stream directly.
// You can freely use demux_stream_control() to send STREAM_CTRLs, or use
// demux_pause() to get exclusive access to the stream.
+ // Also note that the stream can get replaced if fully_read is set.
struct stream *stream;
} demuxer_t;
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index e28ebd0c23..d7dbfe3ff1 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -114,6 +114,7 @@ struct format_hack {
// Do not confuse player's position estimation (position is into external
// segment, with e.g. HLS, player knows about the playlist main file only).
bool clear_filepos : 1;
+ bool ignore_start : 1;
};
#define BLACKLIST(fmt) {fmt, .ignore = true}
@@ -137,6 +138,9 @@ static const struct format_hack format_hacks[] = {
{"h264", .if_flags = AVFMT_NOTIMESTAMPS },
{"hevc", .if_flags = AVFMT_NOTIMESTAMPS },
+ // Rebasing start time to 0 is very weird with ogg shoutcast streams.
+ {"ogg", .ignore_start = true},
+
TEXTSUB("aqtitle"), TEXTSUB("jacosub"), TEXTSUB("microdvd"),
TEXTSUB("mpl2"), TEXTSUB("mpsub"), TEXTSUB("pjs"), TEXTSUB("realtext"),
TEXTSUB("sami"), TEXTSUB("srt"), TEXTSUB("stl"), TEXTSUB("subviewer"),
@@ -158,6 +162,7 @@ static const struct format_hack format_hacks[] = {
typedef struct lavf_priv {
struct stream *stream;
+ bool own_stream;
char *filename;
struct format_hack format_hack;
AVInputFormat *avif;
@@ -286,8 +291,10 @@ static void convert_charset(struct demuxer *demuxer)
if (conv.start)
data = conv;
}
- if (data.start)
+ if (data.start) {
priv->stream = open_memory_stream(data.start, data.len);
+ priv->own_stream = true;
+ }
talloc_free(alloc);
}
@@ -666,6 +673,8 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
if (sh->codec->lav_headers)
mp_copy_lav_codec_headers(sh->codec->lav_headers, codec);
#endif
+ sh->codec->native_tb_num = st->time_base.num;
+ sh->codec->native_tb_den = st->time_base.den;
if (st->disposition & AV_DISPOSITION_DEFAULT)
sh->default_track = true;
@@ -855,8 +864,8 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
demuxer->ts_resets_possible =
priv->avif_flags & (AVFMT_TS_DISCONT | AVFMT_NOTIMESTAMPS);
- demuxer->start_time = priv->avfc->start_time == AV_NOPTS_VALUE ?
- 0 : (double)priv->avfc->start_time / AV_TIME_BASE;
+ if (avfc->start_time != AV_NOPTS_VALUE && !priv->format_hack.ignore_start)
+ demuxer->start_time = avfc->start_time / (double)AV_TIME_BASE;
demuxer->fully_read = priv->format_hack.fully_read;
@@ -1062,6 +1071,12 @@ redo:
av_seek_frame(priv->avfc, 0, stream_tell(priv->stream),
AVSEEK_FLAG_BYTE);
return DEMUXER_CTRL_OK;
+ case DEMUXER_CTRL_REPLACE_STREAM:
+ if (priv->own_stream)
+ free_stream(priv->stream);
+ priv->own_stream = false;
+ priv->stream = demuxer->stream;
+ return DEMUXER_CTRL_OK;
default:
return DEMUXER_CTRL_NOTIMPL;
}
@@ -1086,7 +1101,7 @@ static void demux_close_lavf(demuxer_t *demuxer)
#endif
}
}
- if (priv->stream != demuxer->stream)
+ if (priv->own_stream)
free_stream(priv->stream);
talloc_free(priv);
demuxer->priv = NULL;
diff --git a/demux/demux_mf.c b/demux/demux_mf.c
index c0b159e4ea..20b948630c 100644
--- a/demux/demux_mf.c
+++ b/demux/demux_mf.c
@@ -321,6 +321,7 @@ static int demux_open_mf(demuxer_t *demuxer, enum demux_check check)
c->disp_w = 0;
c->disp_h = 0;
c->fps = demuxer->opts->mf_fps;
+ c->reliable_fps = true;
demux_add_sh_stream(demuxer, sh);
diff --git a/demux/demux_raw.c b/demux/demux_raw.c
index bd8e11306d..51378e7031 100644
--- a/demux/demux_raw.c
+++ b/demux/demux_raw.c
@@ -145,6 +145,9 @@ static int demux_rawaudio_open(demuxer_t *demuxer, enum demux_check check)
c->force_channels = true;
c->samplerate = opts->samplerate;
+ c->native_tb_num = 1;
+ c->native_tb_den = c->samplerate;
+
int f = opts->aformat;
// See PCM(): sign float bits endian
mp_set_pcm_codec(sh->codec, f & 1, f & 2, f >> 3, f & 4);
@@ -233,6 +236,7 @@ static int demux_rawvideo_open(demuxer_t *demuxer, enum demux_check check)