Compare commits

...
39 Commits
Author SHA1 Message Date
Alessandro Ghedini 777295ce28 Release 0.4.2 2014-07-26 12:12:40 +02:00
Alessandro Ghedini d50be0a2a6 command: append entries to the end of the playlist with loadlist append
Currently entries are added after the current playlist element. This is kinda
confusing, more so given that "loadfile append" appends at the end of the
playlist.
2014-07-26 11:55:02 +02:00
wm4 2d8e26bb72 command: add append-play loadfile mode
"loadfile filename append-play" will now always append the file to the
playlist, and if nothing is playing yet, start playback. I don't want to
change the semantics of "append" mode, so a new mode is needed.

Probably fixes issue #950.
2014-07-24 21:15:55 +02:00
wm4 7ee275095f manpage: correct the --mf options
The MPlayer style syntax ("-mf fps=10:type=png") was removed a while
ago, and now only the flat variants ("--mf-fps=10" etc.) work.

CC: @mpv-player/stable
2014-07-23 12:39:38 +02:00
wm4 5a5b219853 demux: fix opening pipes with demux_lavf
We told the demuxer that a pipe (if stream cache is enabled) is
seekable. This is because the stream cache is technically seekable, it's
just that seeking may fail at runtime if a non-cached byte range is
requested.

This caused libavformat to issue seeks on initialization (at least when
piping mp4 youtube videos). Initialization failed completely after
spamming tons of error messages.

So, if an unseekable stream is cached, tell the demuxer that the file is
not seekable. This gets reversed later (when printing a message about
caching an unseekable stream), so the user can still try his luck by
issuing a seek command. The important part is that libavformat
initialization will not take code paths that will unnecessarily seek for
whatever reasons.

CC: @mpv-player/stable: regression from 0.3.x

Conflicts:
	demux/demux.c
2014-07-20 21:56:46 +02:00
wm4 608bed1aed demux_lavf: reverse rotation direction with new API
The old FFmpeg API and the new Libav API disagree about mp4 display
rotation direction. Well, whatever, fix it trial-and-error-style.

CC: @mpv-player/stable: add
2014-07-18 10:31:58 +02:00
wm4 636b62fc1a audio: drop buffered audio when switching tracks or filters
No reason to wait until the audio has been played. This isn't a problem
with gapless audio disabled, and since gapless is now default, this
behavior might be perceived as regression.

CC: @mpv-player/stable
2014-07-14 13:48:36 +02:00
wm4 78195cd742 audio: don't wait for draining if paused
Logic for this was missing from pull.c. For push.c it was missing if the
driver didn't support it. But even if the driver supported it (such as
with ao_alsa), strange behavior was observed by users. See issue #933.

Always check explicitly whether the AO is in paused mode, and if so,
don't drain.

Possibly fixes #933.

CC: @mpv-player/stable
2014-07-14 13:48:31 +02:00
Alessandro Ghedini e7fc048eca stream_dvdnav: suspend read on vts change even if the requested title is not found 2014-07-14 13:48:24 +02:00
wm4 0ab7d01425 stream: don't sleep for reconnecting network if playback is stopped
Also silences the bogus message if that happens.

CC: @mpv-player/stable
2014-07-13 15:06:52 +02:00
wm4 bd0b661183 cache_file: fix operation if stream size is unknown
Happens when playing from a pipe.

Note that seeking forward doesn't work. It would be possible to create a
workaround for that by reading and skipping data until the target
position is reached (and writing the skipped data into the cache file),
but I'm not sure about that.

Fixes #928.

CC: @mpv-player/stable
2014-07-13 15:06:46 +02:00
Alessandro Ghedini 0989d8358c RELEASE_NOTES: include changes in point releases too 2014-07-13 15:05:57 +02:00
Alessandro Ghedini c979ee34e1 RELEASE_NOTES: add some more changes that I missed 2014-07-13 15:05:46 +02:00
Alessandro Ghedini bb00774514 RELEASE_NOTES: use the release version as title 2014-07-12 13:20:43 +02:00
Alessandro Ghedini ef41a98a79 Release 0.4.0 2014-07-11 17:22:35 +02:00
wm4 b18c2d9fe2 input: restore ability to combine mouse buttons
Key bindings are decided on the "down" event, so if the prefix is not
unique, the first/shortest will be used (e.g. when both "a" and "a-b"
are mapped, "a" will always be chosen).

This also breaks combining multiple mouse buttons. But it seems users
expect it to work, and it's indeed a bit strange that it shouldn't work,
as mouse bindings are emitted on the key "up" event, not "down" (if the
shorter binding didn't emit a command yet, why shouldn't it be
combinable).

Deal with this by clearing the key history when a command is actually
emitted, instead of when a command is decided. This means if both
MOUSE_BTN0 and MOUSE_BTN0-MOUSE_BTN1 are mapped, the sequence of holding
down BTN0 and then BTN1 will redecide the current command. On the other
hand, if BTN0 is released before BTN1 is pressed, the command is
emitted, and the key history is deleted. So the BTN1 press will not
trigger BTN0-BTN1.

For normal keys, nothing should change, because commands are emitted on
the "down" event already, so the key history is always cleared.

Might fix #902.

CC: @mpv-player/stable (if this fix is successful)
2014-07-08 10:11:07 +02:00
wm4 8f5ebdbe59 ao_null: disable latency emulation
Doesn't work quite right, and will pause for the latency duration after
seeking. Some users use --ao=null to disable audio (even though they
should probably use --no-audio), and this use-case is broken by this
issue too.

CC: @mpv-player/stable
2014-07-08 10:10:59 +02:00
wm4 e8616fea50 vf_vapoursynth: reset error state on seeking
When seeking, we violently destroy the filter, because vapoursynth has
no proper API for terminating a video with unknown frame count. This
looks like an error to vapoursynth, and the error is returned via the
frame callbacks. The bug is that we remember this error state across
reinitialization, so on the first filter call after reinitialization, we
thought filtering the current frame failed. This caused a shift by 1
frame on each seek.

CC: @mpv-player/stable
2014-07-05 19:04:05 +02:00
wm4 00997484f1 build: allow compilation without any atomics
Not all compilers on all platforms have atomics available (even if they
could, technically speaking).

We don't use atomics that much, only the following things rely on it:
1. the audio pull code, and all audio outputs using it
2. updating global msg levels
3. reading log messages through the client API

Just disable 1. and 3. if atomics are not available. For 2., using fake-
atomics isn't too bad; at worst, message levels won't properly update
under certain situations (but most likely, it will work just fine).

This means if atomics are not available, the client API function
mpv_request_log_messages() will do nothing.

CC: @mpv-player/stable
2014-07-05 19:04:00 +02:00
wm4 ea556e5398 options: remove bogus replacement message for --fstype
CC: @mpv-player/stable
2014-07-05 19:03:49 +02:00
wm4 a3fc0b2015 options: add --autosub-match to option replacement list
CC: @mpv-player/stable
2014-07-05 19:03:39 +02:00
wm4 2db094203d dvd: flush buffers properly on seek
Suggested by tholin on github issue #882.

This is not entirely clean, but the fields we're accessing might be
considered internal to libavformat. On the other hand, existence of the
fields is guaranteed by the ABI, and nothing in the libavformat doxygen
suggestes they're not allowed to be accessed.

CC: @mpv-player/stable
2014-07-05 19:03:32 +02:00
wm4 958858f920 demux_lavf: for now, ignore the new libavformat image demuxers
Recently, libavformat added demuxers to open image files like normal
demuxers. This is a good thing, but for now they interfere with the
operation of demux_mf. Add them to the blacklist until there is a proper
solution.

(The list doesn't contain _all_ recognized image formats, just those
that might interfere with demux_mf.)

CC: @mpv-player/stable
2014-07-05 19:03:28 +02:00
tholin bd271ae1cc stream_dvdnav: check the length of all titles with dvdnav://longest
The last title was ignored before.

CC: @mpv-player/stable

Signed-off-by: wm4 <wm4@nowhere>
2014-07-05 00:29:17 +02:00
tholin c71644b595 stream_dvdnav: free pointer to priv->filename on close
CC: @mpv-player/stable

Signed-off-by: wm4 <wm4@nowhere>
2014-07-05 00:29:06 +02:00
tholin 9b18ed8d8b stream_dvdnav: make sure seeking bounds are within range
libdvdnav returns an error is the seek position is out of range.

CC: @mpv-player/stable

Signed-off-by: wm4 <wm4@nowhere>
2014-07-05 00:29:01 +02:00
wm4 5dce714dfe client API: allow calling mpv_terminate_destroy(NULL)
This is an oversight and a bug.

CC: @mpv-player/stable
2014-07-05 00:28:54 +02:00
Alessandro Ghedini 25a0709972 TOOLS/zsh.pl: sort options in reverse order by length
This stops options that are prefixes of other options from blocking
completion of values for the longer ones.

Conflicts:
	TOOLS/zsh.pl
2014-07-05 00:28:05 +02:00
Philip Sequeira 6cf2f634b3 TOOLS/zsh.pl: don't consume extra arguments
Completion now uses "--opt=value" instead of "--opt value". Once the
user presses space and starts a new argument, the option just
completed is out of the picture, whether or not it was given an
argument. This handles options with no arguments or optional arguments
much better; previously, completing such an option would effectively
disable completion for the next argument.

Custom completed options such as "--ao" and friends will no longer
claim to consume an extra argument.
2014-07-05 00:26:55 +02:00
Philip Sequeira e165ccbf3b TOOLS/zsh.pl: escape all colons in option descriptions 2014-07-05 00:26:00 +02:00
wm4 f78c0692e2 cache: clear DVD timestamps
When resizing the cache, the buffer for the DVD timestamps is
initialized with 0. This causes the player to always return playback
position 0 with any file format (not just DVD), and also makes all
relative seeks relative to position 0. Fix this by clearing the
timestamps explicitly.

Closes #899.

CC: @mpv-player/stable
2014-07-05 00:25:49 +02:00
wm4 59f456cdd3 x11: clear window only on initial map
Apparently clearing on every map can cause problems with vdpau when
switching virtual desktops and such. This was observed with at least
XMonad and nvidia-340.17. It's not observed on some other setups without
XMonad.

It's not clear why this happens. Normally, the window background is not
saved, so clearing should have no additional affect. It's a complete
mystery. Possible, the use of legacy X drawing commands (used to clear
the window) interferes with vdpau operation in non-trivial ways.

Work this around by clearing on initial map only. This probably only
hides the underlying issue, but good enough.

Closes #897.

CC: @mpv-player/stable
2014-07-05 00:25:42 +02:00
wm4 0e35c230f4 demux_mkv: minor improvement to overflow check
CC: @mpv-player/stable
2014-07-05 00:25:38 +02:00
Alessandro Ghedini 9ae80929ea README: fix link to release policy document 2014-07-05 00:25:30 +02:00
wm4 98d1358e6e options: fix --gapless-audio default value
It was intended to be set to "weak" (and that was even documented), but
the actual setting was "no".

Closes #890.

CC: @mpv-player/stable
2014-07-05 00:25:26 +02:00
wm4 e71d68cdae demux_mkv: add some overflow checks etc.
Some of these might be security relevant.

The RealAudio code was especially bad. I'm not sure if all RealAudio
stuff still plays correctly; I didn't have that many samples for
testing. Some checks might be unnecessary or overcomplicated compared
to the (obfuscated) nature of the code.

CC: @mpv-player/stable
2014-07-05 00:25:19 +02:00
Mohammad Alsaleh 950ef5b75b af_volume: fix calculations including replay-gain
rgain is not an additive value. It's a multiplier/gain.

Previous behaviour produced negative level values in some cases
(when rgain < 1.0) which caused volume to be louder when its value
was lowered.

CC: @mpv-player/stable

Signed-off-by: Mohammad Alsaleh <CE.Mohammad.AlSaleh@gmail.com>
Signed-off-by: wm4 <wm4@nowhere>
2014-07-05 00:25:04 +02:00
wm4 0075f8e0cf sub: fix undefined behavior with dvd://
The string could get reallocated.

CC: @mpv-player/stable
2014-07-05 00:24:59 +02:00
Alessandro Ghedini 49275b2879 Release 0.4.0 2014-06-25 20:50:02 +02:00
35 changed files with 435 additions and 125 deletions

No files matched your search

+2
View File
@@ -193,6 +193,8 @@ List of Input Commands
Stop playback of the current file, and play the new file immediately.
<append>
Append the file to the playlist.
<append-play>
Append the file, and if nothing is currently playing, start playback.
The third argument is a list of options and values which should be set
while the file is playing. It is of the form ``opt1=value1,opt2=value2,..``.
+6 -6
View File
@@ -1366,13 +1366,13 @@ OPTIONS
example files or playlists loaded with the ``loadfile`` or ``loadlist``
commands.
``--mf=<option1:option2:...>``
Used when decoding from multiple PNG or JPEG files with ``mf://``.
``--mf-fps=<value>``
Framerate used when decoding from multiple PNG or JPEG files with ``mf://``
(default: 1).
Available options are:
:fps=<value>: output fps (default: 1)
:type=<value>: input file type (available: jpeg, png, tga, sgi)
``--mf-type=<value>``
Input file type for ``mf://`` (available: jpeg, png, tga, sgi). By default,
this is guessed from the file extension.
``--monitoraspect=<ratio>``
Set the aspect ratio of your monitor or TV screen. A value of 0 disables a
+1 -1
View File
@@ -136,4 +136,4 @@ To contact the `mpv` team in private write to `mpv-team@googlegroups.com`.
[mpv-users]: https://groups.google.com/forum/?hl=en#!forum/mpv-users
[mpv-devel]: https://groups.google.com/forum/?hl=en#!forum/mpv-devel
[ffmpeg_vs_libav]: https://github.com/mpv-player/mpv/wiki/FFmpeg-versus-Libav
[release-policy]: https://github.com/mpv-player/mpv/blob/master/release-policy.md
[release-policy]: https://github.com/mpv-player/mpv/blob/master/DOCS/release-policy.md
+182
View File
@@ -0,0 +1,182 @@
Release 0.4.2
=============
Bug fixes
---------
- Include changes from point releases in the release notes.
- Fix --cache-file operation when file size is unknown (e.g. when playing from
a pipe).
- Don't sleep if playback is stopped when reconnecting for remote stream.
- Suspend read on vts change even if the requested title is not found when
using dvdnav (dvd://) (this fixes a bug where the DVD menu was not shown
properly after a DVD track ended).
- Avoid draining if the audio output is paused (this fixes a bug where mpv would
hang when switching tracks when paused).
- Drop buffered audio when switching tracks or filters (this fixes a possible
regression when using gapless audio).
- Reverse video rotation direction.
- Fix initialization of the input when playing from a pipe.
- Fix description of the --mf option in the manpage (the --mf syntax changed a
while ago, but was not documented).
- Actually append entries to the end of the playlist instead of after the
current entry with the "loadlist append" command.
New features
------------
- Add "append-play" mode for the loadfile command.
This listing is not complete. There are many more bug fixes and changes. The
complete change log can be viewed by running ``git log bb00774..d50be0a`` in
the git repository.
Release 0.4.1
=============
Bug fixes
---------
- Fix af_volume bug that caused negative ReplayGain values to increase volume
instead of decreasing it in some situations.
- Actually use "weak" as --gapless-audio default value (as documented in the
0.4.0 release notes).
- Fix cache resizing bug that caused seeking to not work anymore.
- Escape all colons in the options descriptions in the zsh completion script.
- Don't consume an extra argument with --ao/af and --vo/vf options in the zsh
completion script (as side effect, the completion now uses --opt=val instead
of --opt val).
- Allow client applications to call mpv_terminate_destroy(NULL).
- Make sure seeking bounds are within range with dvdnav://.
- Check the length of the last title too with dvdnav://longest.
- Properly flush buffers on DVD seek (this fixes some seeking problems when
playing DVDs).
- Allow compilation without atomics (for compilers that don't support atomic
operations).
- Disable ao_null latency emulation.
- Restore ability to combine mouse buttons.
This listing is not complete. There are many more bug fixes and changes. The
complete change log can be viewed by running ``git log 0075f8e..b18c2d9`` in
the git repository.
Release 0.4.0
=============
Changes
-------
- Drop support for Libav 9 and earlier FFmpeg releases. At least FFmpeg 2.1.4 or
Libav 10 are now required.
- Change cache options to take kilobytes instead of percentages, and raise the
default values.
- Lower --auto-pause/resume defaults values to improve web streams playback.
- Use dvdnav support instead of the internal dvd implementation for dvd:// URLs
(the old implementation is available under dvdread://).
- DVD (dvd://) tracks IDs now start from 0 instead of 1.
- Play the longest track by default with dvd://.
- Rename some options to make them more consistent. Here's a partial list of
renamed options:
+ Audio-related:
* --audiofile → --audio-file
* --audiofile-cache → --audio-file-cache
* --channels → --audio-channels
* --format → --audio-format
* --srate → --audio-samplerate
+ Input-related:
* --ar → --input-appleremote
* --consolecontrols → --input-terminal
* --media-keys → --input-media-keys
* --joystick → --input-joystick
* --lirc → --input-lirc
* --lircconf → --input-lirc-conf
* --mouse-movements → --input-cursor
* --right-alt-gr → --input-right-alt-gr
+ Terminal-related:
* --msgcolor → --msg-color
* --msglevel → --msg-level
* --msgmodule → --msg-module
* --msgtime → --msg-time
* --playing-msg → --term-playing-msg
* --status-msg → --term-status-msg
+ Subtitle-related:
* --ass → --sub-ass
* --autosub → --sub-auto
* --autosub-match → --sub-auto-match
* --sub → --sub-file
* --subcp → --sub-codepage
* --subfps → --sub-fps
+ Video-related:
* --aspect → --video-aspect
* --fstype → --x11-fstype
* --native-fs → --fs-missioncontrol
* --name → --x11-name
- Remove global options variables for --tv, --pvr, --dvb and --cdda.
- Move post-processing support to a separate filter (vdpaupp) for the vdpau vo,
and deprecate the old vdpau post-processing options.
- Remove radio:// support.
- Remove support for ASX, SMIL and NSC playlist formats.
- Re-introduce pretty-printing for module names with --msg-module.
- Load Lua scripts under `$MPV_HOME/lua/` (default `~/.mpv/lua/`) automatically
(this can be disabled by using `--load-scripts=no`).
- Corrupt/broken frames are not shown by default anymore (this can be re-enabled
by using --vd-lavc-show-all=yes).
- Automatically copy metadata from the input file to the output when encoding
(this can be disabled by using --no-ometadata).
- Change --sub-file semantics: if multiple --sub-file are used, the subtitle
tracks can be cycled at runtime and used with --sid and --secondary-sid.
- Make the subtitle font size relative to the window, instead of the video, when
--sub-scale-with-window=yes is used.
- Change default ao from wasapi to dsound on Windows.
Bug fixes
---------
- Fix tv:// playback with missing timestamps.
- Fix display of cover art inside audio files with the vdpau vo.
New features
------------
- Add client API in the form of the libmpv library, which is intended to be a
stable API to get some rough control over the player (this is not supported on
Mac OS X).
- Add option for approximating BT.709 gamma for the opengl vo (similarly to many
programs in the Apple ecosystem).
- Add support for non-BT.709 primaries.
- Add support for BT.2020 colorspace.
- Generate and install zsh completion script (disabled by default since it may
interfere with cross-compilation).
- Add support for looping a single file (instead of the whole playlist) with the
--loop-file option.
- Add VapourSynth video filter (this has various restrictions, which are listed
in the manpage).
- Add support for ReplayGain in the volume audio filter.
- Add a --config-dir option to force config directory.
- Add support for GPU switching on Mac OS X.
- Add support for automatic selection of color profiles on Mac OS X.
- Add support for binding commands to sequences of keys.
- Add support for passing options to Lua scripts with --lua-opts.
- Add some filesystem utility functions to the Lua API.
- Add functions for observing property changes to the Lua API .
- Add support for creating a cache file on the filesystem with --cache-file.
- Add support for window dragging by grabbing with the x11 vo.
- Add option to write file name to watch later file.
- Add support for a "weak" gapless mode, and make it default (the old mode can
be enabled with --gapless-audio or --gapless-audio=yes).
- Automatically detect network filesystems on Linux and Windows.
This listing is not complete. There are many more bug fixes and changes. The
complete change log can be viewed by running ``git log 56ce2a3..8bb7d42`` in
the git repository.
+28 -11
View File
@@ -7,7 +7,7 @@ use warnings;
my $mpv = $ARGV[0] || 'mpv';
my @opts = parse_opts("$mpv --list-options", '^ (\-\-[^\s\*]*)\*?\s*(.*)');
my @opts = parse_opts("$mpv --list-options", '^ (\-\-[^\s\*]*)\*?\s*(.*)', 1);
my @ao = parse_opts("$mpv --ao=help", '^ ([^\s\:]*)\s*: (.*)');
my @vo = parse_opts("$mpv --vo=help", '^ ([^\s\:]*)\s*: (.*)');
@@ -17,7 +17,7 @@ my @vf = parse_opts("$mpv --vf=help", '^ ([^\s\:]*)\s*: (.*)');
my ($opts_str, $ao_str, $vo_str, $af_str, $vf_str);
$opts_str .= qq{ '$_': \\\n} foreach (@opts);
$opts_str .= qq{ '$_' \\\n} foreach (@opts);
chomp $opts_str;
$ao_str .= qq{ '$_' \\\n} foreach (@ao);
@@ -98,7 +98,7 @@ EOS
print $tmpl;
sub parse_opts {
my ($cmd, $regex) = @_;
my ($cmd, $regex, $parsing_main_options) = @_;
my @list;
my @lines = split /\n/, `$cmd`;
@@ -108,21 +108,38 @@ sub parse_opts {
next;
}
my $entry = "$1:";
my $entry = $1;
if ($parsing_main_options) {
$entry .= '=-';
}
if (defined $2) {
my $desc = $2;
$desc =~ s/\:/\\:/;
$desc =~ s/\:/\\:/g;
$entry .= $desc;
$entry .= ':' . $desc;
}
$entry .= ':->ao' if ($1 eq '--ao');
$entry .= ':->vo' if ($1 eq '--vo');
$entry .= ':->af' if ($1 eq '--af');
$entry .= ':->vf' if ($1 eq '--vf');
if ($parsing_main_options) {
$entry .= ':';
push @list, $entry if ($line =~ /^$regex/)
$entry .= '->ao' if ($1 eq '--ao');
$entry .= '->vo' if ($1 eq '--vo');
$entry .= '->af' if ($1 eq '--af');
$entry .= '->vf' if ($1 eq '--vf');
}
push @list, $entry
}
if ($parsing_main_options) {
@list = sort {
$a =~ /(.*?)\:/; my $ma = $1;
$b =~ /(.*?)\:/; my $mb = $1;
length($mb) <=> length($ma)
} @list;
}
return @list;
+1
View File
@@ -0,0 +1 @@
0.4.2
+2 -2
View File
@@ -79,7 +79,7 @@ static int control(struct af_instance *af, int cmd, void *arg)
if (!s->rgain_clip) // clipping prevention
s->rgain = MPMIN(s->rgain, 1.0 / peak);
}
if (s->detach && fabs(s->level + s->rgain - 2.0) < 0.00001)
if (s->detach && fabs(s->level * s->rgain - 1.0) < 0.00001)
return AF_DETACH;
return af_test_output(af, in);
}
@@ -97,7 +97,7 @@ static void filter_plane(struct af_instance *af, void *ptr, int num_samples)
{
struct priv *s = af->priv;
float level = s->level + s->rgain - 1.0;
float level = s->level * s->rgain;
if (af_fmt_from_planar(af->data->format) == AF_FORMAT_S16) {
int16_t *a = ptr;
+1 -13
View File
@@ -31,7 +31,6 @@
#include "options/options.h"
#include "options/m_config.h"
#include "osdep/timer.h"
#include "common/msg.h"
#include "common/common.h"
#include "common/global.h"
@@ -309,22 +308,11 @@ void ao_resume(struct ao *ao)
ao->api->resume(ao);
}
// Be careful with locking
void ao_wait_drain(struct ao *ao)
{
// This is probably not entirely accurate, but good enough.
mp_sleep_us(ao_get_delay(ao) * 1000000);
ao_reset(ao);
}
// Block until the current audio buffer has played completely.
void ao_drain(struct ao *ao)
{
if (ao->api->drain) {
if (ao->api->drain)
ao->api->drain(ao);
} else {
ao_wait_drain(ao);
}
}
bool ao_eof_reached(struct ao *ao)
-1
View File
@@ -210,7 +210,6 @@ const struct ao_driver audio_out_null = {
.priv_size = sizeof(struct priv),
.priv_defaults = &(const struct priv) {
.bufferlen = 0.2,
.latency_sec = 0.5,
.outburst = 256,
.speed = 1,
},
-1
View File
@@ -158,7 +158,6 @@ struct ao_driver {
// These functions can be called by AOs.
int ao_play_silence(struct ao *ao, int samples);
void ao_wait_drain(struct ao *ao);
int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_us);
struct pollfd;
int ao_wait_poll(struct ao *ao, struct pollfd *fds, int num_fds,
+9
View File
@@ -193,6 +193,14 @@ static void resume(struct ao *ao)
ao->driver->resume(ao);
}
static void drain(struct ao *ao)
{
struct ao_pull_state *p = ao->api_priv;
if (atomic_load(&p->state) == AO_STATE_PLAY)
mp_sleep_us(get_delay(ao) * 1000000);
reset(ao);
}
static void uninit(struct ao *ao)
{
ao->driver->uninit(ao);
@@ -212,6 +220,7 @@ const struct ao_driver ao_api_pull = {
.init = init,
.control = control,
.uninit = uninit,
.drain = drain,
.reset = reset,
.get_space = get_space,
.play = play,
+6 -1
View File
@@ -146,6 +146,10 @@ static void drain(struct ao *ao)
struct ao_push_state *p = ao->api_priv;
pthread_mutex_lock(&p->lock);
if (p->paused) {
pthread_mutex_unlock(&p->lock);
return;
}
p->final_chunk = true;
p->drain = true;
wakeup_playthread(ao);
@@ -154,7 +158,8 @@ static void drain(struct ao *ao)
pthread_mutex_unlock(&p->lock);
if (!ao->driver->drain)
ao_wait_drain(ao);
mp_sleep_us(get_delay(ao) * 1000000);
reset(ao);
}
static int unlocked_get_space(struct ao *ao)
+4
View File
@@ -469,6 +469,10 @@ struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global,
{
struct mp_log_root *root = global->log->root;
#if !HAVE_ATOMICS
return NULL;
#endif
pthread_mutex_lock(&mp_msg_lock);
struct mp_log_buffer *buffer = talloc_ptrtype(NULL, buffer);
+9
View File
@@ -215,6 +215,15 @@ void playlist_transfer_entries(struct playlist *pl, struct playlist *source_pl)
}
}
void playlist_append_entries(struct playlist *pl, struct playlist *source_pl)
{
while (source_pl->first) {
struct playlist_entry *e = source_pl->first;
playlist_unlink(source_pl, e);
playlist_add(pl, e);
}
}
// Return number of entries between list start and e.
// Return -1 if e is not on the list, or if e is NULL.
int playlist_entry_to_index(struct playlist *pl, struct playlist_entry *e)
+1
View File
@@ -74,6 +74,7 @@ void playlist_shuffle(struct playlist *pl);
struct playlist_entry *playlist_get_next(struct playlist *pl, int direction);
void playlist_add_base_path(struct playlist *pl, bstr base_path);
void playlist_transfer_entries(struct playlist *pl, struct playlist *source_pl);
void playlist_append_entries(struct playlist *pl, struct playlist *source_pl);
int playlist_entry_to_index(struct playlist *pl, struct playlist_entry *e);
int playlist_entry_count(struct playlist *pl);
+13 -2
View File
@@ -22,6 +22,8 @@
#include <inttypes.h>
#include "config.h"
#define HAVE_ATOMICS 1
#if HAVE_STDATOMIC
#include <stdatomic.h>
#else
@@ -58,8 +60,17 @@ typedef struct { volatile unsigned long long v; } atomic_ullong;
__sync_fetch_and_add(&(a)->v, b)
#else
# error "this should have been a configuration error, report a bug please"
#endif
// This is extremely wrong. The build system actually disables code that has
// a serious dependency on working atomics, so this is barely ok.
#define atomic_load(p) ((p)->v)
#define atomic_store(p, val) ((p)->v = (val))
#define atomic_fetch_add(a, b) (((a)->v += (b)) - (b))
#undef HAVE_ATOMICS
#define HAVE_ATOMICS 0
#endif /* no atomics */
#endif /* else HAVE_STDATOMIC */
+5
View File
@@ -583,6 +583,11 @@ static struct demuxer *open_given_type(struct mpv_global *global,
.filename = talloc_strdup(demuxer, stream->url),
.metadata = talloc_zero(demuxer, struct mp_tags),
};
demuxer->seekable = stream->seekable;
if (demuxer->stream->uncached_stream &&
!demuxer->stream->uncached_stream->seekable)
demuxer->seekable = false;
demuxer->params = params; // temporary during open()
int64_t start_pos = stream_tell(stream);
+8 -4
View File
@@ -129,6 +129,9 @@ static const struct format_hack format_hacks[] = {
static const char *const format_blacklist[] = {
"tty", // Useless non-sense, sometimes breaks MLP2 subreader.c fallback
// Image demuxers, disabled in favor of demux_mf:
"image2", "image2pipe",
"bmp_pipe", "dpx_pipe", "exr_pipe", "j2k_pipe", "png_pipe", "tiff_pipe",
0
};
@@ -504,7 +507,7 @@ static void handle_stream(demuxer_t *demuxer, int i)
#if HAVE_AV_DISPLAYMATRIX
uint8_t *sd = av_stream_get_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, NULL);
if (sd)
sh_video->rotate = av_display_rotation_get((uint32_t *)sd);
sh_video->rotate = -av_display_rotation_get((uint32_t *)sd);
#else
AVDictionaryEntry *rot = av_dict_get(st->metadata, "rotate", NULL, 0);
if (rot && rot->value) {
@@ -1006,11 +1009,12 @@ redo:
* call the new API instead of relying on av_seek_frame() to do this
* for us.
*/
stream_drop_buffers(demuxer->stream);
avio_flush(priv->avfc->pb);
av_seek_frame(priv->avfc, 0, stream_tell(demuxer->stream),
AVSEEK_FLAG_BYTE);
avio_flush(priv->avfc->pb);
// avio_flush() is designed for write-only streams, and does the wrong
// thing when reading. Flush it manually instead.
priv->avfc->pb->buf_ptr = priv->avfc->pb->buf_end;
stream_drop_buffers(demuxer->stream);
return DEMUXER_CTRL_OK;
default:
return DEMUXER_CTRL_NOTIMPL;
+103 -58
View File
@@ -128,13 +128,13 @@ typedef struct mkv_track {
double ra_pts; /* previous audio timestamp */
/** realaudio descrambling */
int sub_packet_size; ///< sub packet size, per stream
int sub_packet_h; ///< number of coded frames per block
int coded_framesize; ///< coded frame size, per stream
int audiopk_size; ///< audio packet size
uint16_t sub_packet_size; ///< sub packet size, per stream
uint16_t sub_packet_h; ///< number of coded frames per block
uint32_t coded_framesize; ///< coded frame size, per stream
uint16_t audiopk_size; ///< audio packet size
unsigned char *audio_buf; ///< place to store reordered audio data
double *audio_timestamp; ///< timestamp for each audio packet
int sub_packet_cnt; ///< number of subpacket already received
uint16_t sub_packet_cnt; ///< number of subpacket already received
int audio_filepos; ///< file position of first audio packet in block
/* generic content encoding support */
@@ -142,7 +142,7 @@ typedef struct mkv_track {
int num_encodings;
/* latest added index entry for this track */
int last_index_entry;
size_t last_index_entry;
} mkv_track_t;
typedef struct mkv_index {
@@ -167,7 +167,7 @@ typedef struct mkv_demuxer {
uint64_t cluster_end;
mkv_index_t *indexes;
int num_indexes;
size_t num_indexes;
bool index_complete;
uint64_t deferred_cues;
@@ -192,19 +192,6 @@ typedef struct mkv_demuxer {
// (Subtitle packets added before first A/V keyframe packet is found with seek.)
#define NUM_SUB_PREROLL_PACKETS 500
/**
* \brief ensures there is space for at least one additional element
* \param array array to grow
* \param nelem current number of elements in array
* \param elsize size of one array element
*/
static void *grow_array(void *array, int nelem, size_t elsize)
{
if (!(nelem & 31))
array = realloc(array, (nelem + 32) * elsize);
return array;
}
#define AAC_SYNC_EXTENSION_TYPE 0x02b7
static int aac_get_sample_rate_index(uint32_t sample_rate)
{
@@ -258,6 +245,12 @@ static bstr demux_mkv_decode(struct mp_log *log, mkv_track_t *track,
zstream.avail_out = size;
int result;
do {
if (size >= INT_MAX - 4000) {
talloc_free(dest);
dest = NULL;
inflateEnd(&zstream);
goto error;
}
size += 4000;
dest = talloc_realloc_size(track->parser_tmp, dest, size);
zstream.next_out = (Bytef *) (dest + zstream.total_out);
@@ -279,6 +272,9 @@ static bstr demux_mkv_decode(struct mp_log *log, mkv_track_t *track,
} else if (enc->comp_algo == 2) {
/* lzo encoded track */
int out_avail;
int maxlen = INT_MAX - AV_LZO_OUTPUT_PADDING;
if (size >= maxlen / 3)
goto error;
int dstlen = size * 3;
dest = NULL;
@@ -297,6 +293,11 @@ static bstr demux_mkv_decode(struct mp_log *log, mkv_track_t *track,
goto error;
}
mp_dbg(log, "lzo decompression buffer too small.\n");
if (dstlen >= maxlen / 2) {
talloc_free(dest);
dest = NULL;
goto error;
}
dstlen *= 2;
}
size = dstlen - out_avail;
@@ -311,6 +312,8 @@ static bstr demux_mkv_decode(struct mp_log *log, mkv_track_t *track,
error:
if (src != dest && src != orig_src)
talloc_free(src);
if (!size)
dest = NULL;
return (bstr){dest, size};
}
@@ -433,7 +436,7 @@ static void parse_trackencodings(struct demuxer *demuxer,
if (e.order >= ce[i].order)
break;
}
ce = talloc_realloc_size(track, ce, (n_enc + 1) * sizeof(*ce));
ce = talloc_realloc(track, ce, mkv_content_encoding_t, n_enc + 1);
memmove(ce + i + 1, ce + i, (n_enc - i) * sizeof(*ce));
memcpy(ce + i, &e, sizeof(e));
}
@@ -525,8 +528,8 @@ static void parse_trackentry(struct demuxer *demuxer,
struct ebml_track_entry *entry)
{
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
struct mkv_track *track = talloc_zero_size(NULL, sizeof(*track));
track->last_index_entry = -1;
struct mkv_track *track = talloc_zero(NULL, struct mkv_track);
track->last_index_entry = (size_t)-1;
track->parser_tmp = talloc_new(track);
track->tnum = entry->track_number;
@@ -584,7 +587,7 @@ static void parse_trackentry(struct demuxer *demuxer,
track->codec_id = "";
}
if (entry->n_codec_private) {
if (entry->n_codec_private && entry->codec_private.len <= 0x1000000) {
int len = entry->codec_private.len;
track->private_data = talloc_size(track, len + AV_LZO_INPUT_PADDING);
memcpy(track->private_data, entry->codec_private.start, len);
@@ -640,8 +643,8 @@ static int demux_mkv_read_tracks(demuxer_t *demuxer)
if (ebml_read_element(s, &parse_ctx, &tracks, &ebml_tracks_desc) < 0)
return -1;
mkv_d->tracks = talloc_size(mkv_d,
tracks.n_track_entry * sizeof(*mkv_d->tracks));
mkv_d->tracks = talloc_zero_array(mkv_d, struct mkv_track*,
tracks.n_track_entry);
for (int i = 0; i < tracks.n_track_entry; i++) {
MP_VERBOSE(demuxer, "| + a track...\n");
parse_trackentry(demuxer, &tracks.track_entry[i]);
@@ -655,8 +658,8 @@ static void cue_index_add(demuxer_t *demuxer, int track_id, uint64_t filepos,
{
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
mkv_d->indexes = grow_array(mkv_d->indexes, mkv_d->num_indexes,
sizeof(mkv_index_t));
MP_TARRAY_GROW(mkv_d, mkv_d->indexes, mkv_d->num_indexes);
mkv_d->indexes[mkv_d->num_indexes].tnum = track_id;
mkv_d->indexes[mkv_d->num_indexes].timecode = timecode;
mkv_d->indexes[mkv_d->num_indexes].filepos = filepos;
@@ -670,7 +673,7 @@ static void add_block_position(demuxer_t *demuxer, struct mkv_track *track,
if (mkv_d->index_complete || !track)
return;
if (track->last_index_entry >= 0) {
if (track->last_index_entry != (size_t)-1) {
mkv_index_t *index = &mkv_d->indexes[track->last_index_entry];
// filepos is always the cluster position, which can contain multiple
// blocks with different timecodes - one is enough.
@@ -1241,6 +1244,11 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
}
}
if (extradata_size > 0x1000000) {
MP_WARN(demuxer, "Invalid CodecPrivate\n");
return 1;
}
sh = new_sh_stream(demuxer, STREAM_VIDEO);
if (!sh)
return 1;
@@ -1465,6 +1473,8 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track)
if (track->private_size == 0 || track->ms_compat && !sh_a->wf->cbSize)
goto error;
if (!track->ms_compat) {
if (track->private_size > 0x1000000)
goto error;
sh_a->wf->cbSize = track->private_size;
sh_a->wf = talloc_realloc_size(sh_a, sh_a->wf,
sizeof(*sh_a->wf) + sh_a->wf->cbSize);
@@ -1499,10 +1509,18 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track)
src += RAPROPERTIES5_SIZE;
}
if (track->audiopk_size == 0 || track->sub_packet_size == 0 ||
track->sub_packet_h == 0 || track->coded_framesize == 0)
goto error;
if (track->coded_framesize > 0x40000000)
goto error;
src += 3;
if (version == 5)
src++;
codecdata_length = AV_RB32(src);
if (codecdata_length < 0 || codecdata_length > 0x1000000)
goto error;
src += 4;
sh_a->wf->cbSize = codecdata_length;
sh_a->wf = talloc_realloc_size(sh_a, sh_a->wf,
@@ -1527,9 +1545,9 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track)
sh_a->wf->nBlockAlign = track->coded_framesize;
audiobuf:
track->audio_buf =
talloc_size(demuxer, track->sub_packet_h * track->audiopk_size);
talloc_array_size(track, track->sub_packet_h, track->audiopk_size);
track->audio_timestamp =
talloc_size(demuxer, track->sub_packet_h * sizeof(double));
talloc_array(track, double, track->sub_packet_h);
break;
}
@@ -1631,6 +1649,9 @@ static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track)
}
}
if (track->private_size > 0x10000000)
return 1;
bstr in = (bstr){track->private_data, track->private_size};
struct sh_stream *sh = new_sh_stream(demuxer, STREAM_SUB);
if (!sh)
@@ -1989,46 +2010,63 @@ static void handle_realaudio(demuxer_t *demuxer, mkv_track_t *track,
bstr data, bool keyframe)
{
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
int sps = track->sub_packet_size;
int sph = track->sub_packet_h;
int cfs = track->coded_framesize;
int w = track->audiopk_size;
int spc = track->sub_packet_cnt;
uint16_t sps = track->sub_packet_size;
uint16_t sph = track->sub_packet_h;
uint32_t cfs = track->coded_framesize; // restricted to [1,0x40000000]
uint16_t w = track->audiopk_size;
uint16_t spc = track->sub_packet_cnt;
uint8_t *buffer = data.start;
uint32_t size = data.len;
demux_packet_t *dp;
// track->audio_buf allocation size
size_t audiobuf_size = sph * w;
if ((track->a_formattag == MP_FOURCC('2', '8', '_', '8'))
|| (track->a_formattag == MP_FOURCC('c', 'o', 'o', 'k'))
|| (track->a_formattag == MP_FOURCC('a', 't', 'r', 'c'))
|| (track->a_formattag == MP_FOURCC('s', 'i', 'p', 'r'))) {
// if(!block_bref)
// spc = track->sub_packet_cnt = 0;
|| (track->a_formattag == MP_FOURCC('s', 'i', 'p', 'r')))
{
switch (track->a_formattag) {
case MP_FOURCC('2', '8', '_', '8'):
for (int x = 0; x < sph / 2; x++)
memcpy(track->audio_buf + x * 2 * w + spc * cfs,
buffer + cfs * x, cfs);
for (int x = 0; x < sph / 2; x++) {
uint64_t dst_offset = x * 2 * w + spc * (uint64_t)cfs;
if (dst_offset + cfs > audiobuf_size)
goto error;
uint64_t src_offset = x * (uint64_t)cfs;
if (src_offset + cfs > size)
goto error;
memcpy(track->audio_buf + dst_offset, buffer + src_offset, cfs);
}
break;
case MP_FOURCC('c', 'o', 'o', 'k'):
case MP_FOURCC('a', 't', 'r', 'c'):
for (int x = 0; x < w / sps; x++)
memcpy(track->audio_buf +
sps * (sph * x + ((sph + 1) / 2) * (spc & 1) +
(spc >> 1)), buffer + sps * x, sps);
for (int x = 0; x < w / sps; x++) {
uint32_t dst_offset = sps * (sph * x + ((sph + 1) / 2) * (spc & 1)
+ (spc >> 1));
if (dst_offset + sps > audiobuf_size)
goto error;
uint32_t src_offset = sps * x;
if (src_offset + sps > size)
goto error;
memcpy(track->audio_buf + dst_offset, buffer + src_offset, sps);
}
break;
case MP_FOURCC('s', 'i', 'p', 'r'):
if (spc * w + w > audiobuf_size || w > size)
goto error;
memcpy(track->audio_buf + spc * w, buffer, w);
if (spc == sph - 1) {
int n;
int bs = sph * w * 2 / 96; // nibbles per subpacket
// Perform reordering
for (n = 0; n < 38; n++) {
int j;
int i = bs * sipr_swaps[n][0];
int o = bs * sipr_swaps[n][1];
// swap nibbles of block 'i' with 'o' TODO: optimize
for (j = 0; j < bs; j++) {
int i = bs * sipr_swaps[n][0]; // 77 max
int o = bs * sipr_swaps[n][1]; // 95 max
// swap nibbles of block 'i' with 'o'
for (int j = 0; j < bs; j++) {
if (i / 2 >= audiobuf_size || o / 2 >= audiobuf_size)
goto error;
int x = (i & 1) ?
(track->audio_buf[i >> 1] >> 4) :
(track->audio_buf[i >> 1] & 0x0F);
@@ -2060,8 +2098,11 @@ static void handle_realaudio(demuxer_t *demuxer, mkv_track_t *track,
if (track->sub_packet_cnt == 0)
track->audio_filepos = mkv_d->last_filepos;
if (++(track->sub_packet_cnt) == sph) {
int apk_usize = track->stream->audio->wf->nBlockAlign;
track->sub_packet_cnt = 0;
// apk_usize has same range as coded_framesize in worst case
uint32_t apk_usize = track->stream->audio->wf->nBlockAlign;
if (apk_usize > audiobuf_size)
goto error;
// Release all the audio packets
for (int x = 0; x < sph * w / apk_usize; x++) {
dp = new_demux_packet_from(track->audio_buf + x * apk_usize,
@@ -2087,6 +2128,9 @@ static void handle_realaudio(demuxer_t *demuxer, mkv_track_t *track,
dp->keyframe = keyframe;
demuxer_add_packet(demuxer, track->stream, dp);
}
return;
error:
MP_ERR(demuxer, "RealAudio decrypting error.\n");
}
static void mkv_seek_reset(demuxer_t *demuxer)
@@ -2154,6 +2198,9 @@ static int libav_parse_wavpack(mkv_track_t *track, uint8_t *src,
if (blocksize > srclen)
goto fail;
if (dstlen > 0x10000000 || blocksize > 0x10000000)
goto fail;
tmp = talloc_realloc(track->parser_tmp, dst, uint8_t,
dstlen + blocksize + 32);
if (!tmp)
@@ -2223,7 +2270,7 @@ static bool mkv_parse_packet(mkv_track_t *track, bstr *raw, bstr *out)
int len = av_parser_parse2(track->av_parser, track->av_parser_codec,
&data, &size, raw->start, raw->len,
AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
if (len < 0)
if (len < 0 || len > 0x10000000)
return false;
*raw = bstr_cut(*raw, len);
if (size) {
@@ -2640,7 +2687,7 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id,
min_diff = -min_diff;
min_diff = FFMAX(min_diff, 1);
for (int i = 0; i < mkv_d->num_indexes; i++) {
for (size_t i = 0; i < mkv_d->num_indexes; i++) {
if (seek_id < 0 || mkv_d->indexes[i].tnum == seek_id) {
int64_t diff =
target_timecode -
@@ -2661,7 +2708,7 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id,
uint64_t seek_pos = index->filepos;
if (flags & SEEK_SUBPREROLL) {
uint64_t prev_target = 0;
for (int i = 0; i < mkv_d->num_indexes; i++) {
for (size_t i = 0; i < mkv_d->num_indexes; i++) {
if (seek_id < 0 || mkv_d->indexes[i].tnum == seek_id) {
uint64_t index_pos = mkv_d->indexes[i].filepos;
if (index_pos > prev_target && index_pos < seek_pos)
@@ -2745,7 +2792,6 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs, int flags)
stream_t *s = demuxer->stream;
uint64_t target_filepos;
mkv_index_t *index = NULL;
int i;
read_deferred_cues(demuxer);
@@ -2759,7 +2805,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs, int flags)
stream_control(s, STREAM_CTRL_GET_SIZE, &size);
target_filepos = (uint64_t) (size * rel_seek_secs);
for (i = 0; i < mkv_d->num_indexes; i++)
for (size_t i = 0; i < mkv_d->num_indexes; i++)
if (mkv_d->indexes[i].tnum == v_tnum)
if ((index == NULL)
|| ((mkv_d->indexes[i].filepos >= target_filepos)
@@ -2807,7 +2853,6 @@ static void mkv_free(struct demuxer *demuxer)
mkv_seek_reset(demuxer);
for (int i = 0; i < mkv_d->num_tracks; i++)
demux_mkv_free_trackentry(mkv_d->tracks[i]);
free(mkv_d->indexes);
}
const demuxer_desc_t demuxer_desc_matroska = {
+9 -1
View File
@@ -364,7 +364,7 @@ static void ebml_parse_element(struct ebml_parse_ctx *ctx, void *target,
char *s = target;
uint8_t *end = data + size;
uint8_t *p = data;
int num_elems[MAX_EBML_SUBELEMENTS] = {};
int num_elems[MAX_EBML_SUBELEMENTS] = {0};
while (p < end) {
uint8_t *startp = p;
int len;
@@ -390,6 +390,10 @@ static void ebml_parse_element(struct ebml_parse_ctx *ctx, void *target,
if (type->fields[i].id == id) {
field_idx = i;
num_elems[i]++;
if (num_elems[i] >= 0x70000000) {
MP_ERR(ctx, "Too many EBML subelements.\n");
goto other_error;
}
break;
}
@@ -566,6 +570,10 @@ static void ebml_parse_element(struct ebml_parse_ctx *ctx, void *target,
case EBML_TYPE_STR:
case EBML_TYPE_BINARY:;
if (length > 0x80000000) {
MP_ERR(ctx, "Not reading overly long EBML element.\n");
break;
}
struct bstr *strptr;
GETPTR(strptr, struct bstr);
strptr->start = data;
+2 -1
View File
@@ -111,7 +111,8 @@ const struct mp_cmd_def mp_cmds[] = {
{ MP_CMD_LOADFILE, "loadfile", {
ARG_STRING,
OARG_CHOICE(0, ({"replace", 0}, {"0", 0},
{"append", 1}, {"1", 1})),
{"append", 1}, {"1", 1},
{"append-play", 2})),
OPT_KEYVALUELIST(ARG(str_list), MP_CMD_OPT_ARG),
}},
{ MP_CMD_LOADLIST, "loadlist", {
+6 -8
View File
@@ -557,6 +557,7 @@ static void release_down_cmd(struct input_ctx *ictx, bool drop_current)
if (!drop_current && ictx->current_down_cmd &&
ictx->current_down_cmd->key_up_follows)
{
memset(ictx->key_history, 0, sizeof(ictx->key_history));
ictx->current_down_cmd->key_up_follows = false;
queue_add_tail(&ictx->cmd_queue, ictx->current_down_cmd);
ictx->got_new_events = true;
@@ -596,15 +597,10 @@ static struct mp_cmd *resolve_key(struct input_ctx *ictx, int code)
{
update_mouse_section(ictx);
struct mp_cmd *cmd = get_cmd_from_keys(ictx, NULL, code);
if (cmd && cmd->id != MP_CMD_IGNORE) {
memset(ictx->key_history, 0, sizeof(ictx->key_history));
if (!should_drop_cmd(ictx, cmd))
return cmd;
talloc_free(cmd);
return NULL;
}
talloc_free(cmd);
key_buf_add(ictx->key_history, code);
if (cmd && cmd->id != MP_CMD_IGNORE && !should_drop_cmd(ictx, cmd))
return cmd;
talloc_free(cmd);
return NULL;
}
@@ -673,6 +669,8 @@ static void interpret_key(struct input_ctx *ictx, int code, double scale)
return;
}
memset(ictx->key_history, 0, sizeof(ictx->key_history));
cmd->scale = scale;
if (cmd->key_up_follows)
+1 -1
View File
@@ -920,7 +920,6 @@ static const char *const replaced_opts =
"|font#--osd-font"
"|forcedsubsonly#--sub-forced-only"
"|format#--audio-format"
"|fstype#--x11-fstype"
"|hardframedrop#--framedrop=hard"
"|identify#removed; use TOOLS/mpv_identify.sh"
"|lavdopts#--vd-lavc-..."
@@ -969,6 +968,7 @@ static const char *const replaced_opts =
"|lirc#--input-lirc"
"|right-alt-gr#--input-right-alt-gr"
"|autosub#--sub-auto"
"|autosub-match#--sub-auto"
"|native-fs#--fs-missioncontrol"
"|status-msg#--term-status-msg"
"|idx#--index"
+1
View File
@@ -540,6 +540,7 @@ const struct MPOpts mp_default_opts = {
.mixer_init_volume = -1,
.mixer_init_mute = -1,
.volstep = 3,
.gapless_audio = -1,
.vo = {
.video_driver_list = NULL,
.monitor_pixel_aspect = 1.0,
+3
View File
@@ -330,6 +330,9 @@ static void get_thread(void *ptr)
void mpv_terminate_destroy(mpv_handle *ctx)
{
if (!ctx)
return;
mpv_command(ctx, (const char*[]){"quit", NULL});
if (!ctx->owner) {
+4 -3
View File
@@ -2995,6 +2995,7 @@ static bool reinit_filters(MPContext *mpctx, enum stream_type mediatype)
case STREAM_VIDEO:
return reinit_video_filters(mpctx) >= 0;
case STREAM_AUDIO:
clear_audio_output_buffers(mpctx);
return reinit_audio_filters(mpctx) >= 0;
}
return false;
@@ -3549,7 +3550,7 @@ int run_command(MPContext *mpctx, mp_cmd_t *cmd)
case MP_CMD_LOADFILE: {
char *filename = cmd->args[0].v.s;
bool append = cmd->args[1].v.i;
int append = cmd->args[1].v.i;
if (!append)
playlist_clear(mpctx->playlist);
@@ -3564,7 +3565,7 @@ int run_command(MPContext *mpctx, mp_cmd_t *cmd)
}
playlist_add(mpctx->playlist, entry);
if (!append)
if (!append || (append == 2 && !mpctx->playlist->current))
mp_set_playlist_entry(mpctx, mpctx->playlist->first);
break;
}
@@ -3576,7 +3577,7 @@ int run_command(MPContext *mpctx, mp_cmd_t *cmd)
if (pl) {
if (!append)
playlist_clear(mpctx->playlist);
playlist_transfer_entries(mpctx->playlist, pl);
playlist_append_entries(mpctx->playlist, pl);
talloc_free(pl);
if (!append && mpctx->playlist->first) {
+1
View File
@@ -598,6 +598,7 @@ void mp_switch_track_n(struct MPContext *mpctx, int order, enum stream_type type
uninit |= mpctx->opts->fixed_vo && track ? 0 : INITIALIZED_VO;
uninit_player(mpctx, uninit);
} else if (type == STREAM_AUDIO) {
clear_audio_output_buffers(mpctx);
uninit_player(mpctx, INITIALIZED_AO | INITIALIZED_ACODEC);
} else if (type == STREAM_SUB) {
uninit_player(mpctx, INITIALIZED_SUB);
+1 -1
View File
@@ -189,7 +189,7 @@ static void set_dvdsub_fake_extradata(struct dec_sub *dec_sub, struct stream *st
color = (c[2] << 16) | (c[1] << 8) | c[0];
if (i != 0)
talloc_asprintf_append(s, ", ");
s = talloc_asprintf_append(s, ", ");
s = talloc_asprintf_append(s, "%06x", color);
}
s = talloc_asprintf_append(s, "\n");
+3
View File
@@ -361,6 +361,9 @@ static int resize_cache(struct priv *s, int64_t size)
if (s->seek_limit > s->buffer_size - FILL_LIMIT)
s->seek_limit = s->buffer_size - FILL_LIMIT;
for (size_t n = 0; n < s->buffer_size / BYTE_META_CHUNK_SIZE + 2; n++)
s->bm[n] = (struct byte_meta){.stream_pts = MP_NOPTS_VALUE};
return STREAM_OK;
}
+3 -2
View File
@@ -66,7 +66,7 @@ static int fill_buffer(stream_t *s, char *buffer, int max_len)
if (s->pos >= p->size - BLOCK_SIZE) {
int64_t new_size = -1;
stream_control(s, STREAM_CTRL_GET_SIZE, &new_size);
if (new_size != p->size)
if (p->size >= 0 && new_size != p->size)
set_bit(p, BLOCK_ALIGN(p->size), 0);
p->size = MPMIN(p->max_size, new_size);
}
@@ -94,7 +94,8 @@ static int fill_buffer(stream_t *s, char *buffer, int max_len)
// align/limit to blocks
max_len = MPMIN(max_len, BLOCK_SIZE - (s->pos % BLOCK_SIZE));
// Limit to max. known file size
max_len = MPMIN(max_len, p->size - s->pos);
if (p->size >= 0)
max_len = MPMIN(max_len, p->size - s->pos);
return fread(buffer, 1, max_len, p->cache_file);
}
+2
View File
@@ -388,6 +388,8 @@ static int stream_reconnect(stream_t *s)
return 0;
if (!s->seekable)
return 0;
if (stream_check_interrupt(s))
return 0;
int64_t pos = s->pos;
int sleep_ms = 5;
for (int retry = 0; retry < MAX_RECONNECT_RETRIES; retry++) {
+8 -3
View File
@@ -443,7 +443,6 @@ static int fill_buffer(stream_t *s, char *buf, int max_len)
if (priv->title > 0 && tit != priv->title) {
priv->next_event |= 1 << MP_NAV_EVENT_EOF;;
MP_WARN(s, "Requested title not found\n");
return 0;
}
}
if (priv->nav_enabled)
@@ -546,7 +545,11 @@ static int control(stream_t *stream, int cmd, void *arg)
return STREAM_OK;
}
case STREAM_CTRL_SEEK_TO_TIME: {
uint64_t tm = (uint64_t) (*((double *)arg) * 90000);
int64_t tm = (int64_t) (*((double *)arg) * 90000);
if (tm < 0)
tm = 0;
if (priv->duration && tm >= (priv->duration * 90))
tm = priv->duration * 90 - 1;
MP_VERBOSE(stream, "seek to PTS %"PRId64"\n", tm);
if (dvdnav_time_search(dvdnav, tm) != DVDNAV_STATUS_OK)
break;
@@ -634,6 +637,8 @@ static void stream_dvdnav_close(stream_t *s)
priv->dvdnav = NULL;
if (priv->dvd_speed)
dvd_set_speed(s, priv->filename, -1);
if (priv->filename)
free(priv->filename);
}
static struct priv *new_dvdnav_stream(stream_t *stream, char *filename)
@@ -692,7 +697,7 @@ static int open_s(stream_t *stream)
int best_title = -1;
int32_t num_titles;
if (dvdnav_get_number_of_titles(dvdnav, &num_titles) == DVDNAV_STATUS_OK) {
for (int n = 1; n < num_titles; n++) {
for (int n = 1; n <= num_titles; n++) {
uint64_t *parts = NULL, duration = 0;
dvdnav_describe_title_chapters(dvdnav, n, &parts, &duration);
if (parts) {
+1
View File
@@ -434,6 +434,7 @@ static void destroy_vs(struct vf_instance *vf)
p->next_image = NULL;
p->out_pts = MP_NOPTS_VALUE;
p->out_frameno = p->in_frameno = 0;
p->failed = false;
MP_DBG(vf, "uninitialized.\n");
}
+2 -1
View File
@@ -858,8 +858,9 @@ int vo_x11_check_events(struct vo *vo)
get_mods(Event.xbutton.state) | MP_KEY_STATE_UP);
break;
case MapNotify:
if (x11->window_hidden)
vo_x11_clearwindow(vo, x11->window);
x11->window_hidden = false;
vo_x11_clearwindow(vo, x11->window);
vo_x11_update_geometry(vo);
break;
case DestroyNotify:
+7 -4
View File
@@ -138,12 +138,10 @@ main_dependencies = [
'test = __sync_add_and_fetch(&test, 1)'),
'deps_neg': [ 'stdatomic', 'atomic-builtins' ],
}, {
'name': 'thread-synchronization-builtins',
'name': 'atomics',
'desc': 'compiler support for usable thread synchronization built-ins',
'func': check_true,
'deps_any': ['stdatomic', 'atomic-builtins', 'sync-builtins'],
'req': True,
'fmsg': 'your compiler must support either __atomic or __sync built-ins',
}, {
'name': 'librt',
'desc': 'linking with -lrt',
@@ -419,11 +417,13 @@ audio_output_features = [
{
'name': '--sdl2',
'desc': 'SDL2',
'deps': ['atomics'],
'func': check_pkg_config('sdl2'),
'default': 'disable'
}, {
'name': '--sdl1',
'desc': 'SDL (1.x)',
'deps': ['atomics'],
'deps_neg': [ 'sdl2' ],
'func': check_pkg_config('sdl'),
'default': 'disable'
@@ -478,12 +478,13 @@ audio_output_features = [
}, {
'name': '--portaudio',
'desc': 'PortAudio audio output',
'deps': [ 'pthreads' ],
'deps': [ 'atomics' ],
'func': check_pkg_config('portaudio-2.0', '>= 19'),
'default': 'disable',
}, {
'name': '--jack',
'desc': 'JACK audio output',
'deps': ['atomics'],
'func': check_pkg_config('jack'),
}, {
'name': '--openal',
@@ -497,6 +498,7 @@ audio_output_features = [
}, {
'name': '--coreaudio',
'desc': 'CoreAudio audio output',
'deps': ['atomics'],
'func': check_cc(
fragment=load_fragment('coreaudio.c'),
framework_name=['CoreFoundation', 'CoreAudio', 'AudioUnit', 'AudioToolbox'])
@@ -507,6 +509,7 @@ audio_output_features = [
}, {
'name': '--wasapi',
'desc': 'WASAPI audio output',
'deps': ['atomics'],
'func': check_cc(fragment=load_fragment('wasapi.c'), lib='ole32'),
}
]