Compare commits

...
618 Commits
Author SHA1 Message Date
Martin Herkt c226bc7616 Release 0.20.0 2016-08-26 19:40:58 +02:00
Martin Herkt e60a36bd4e Merge branch 'master' into release/current 2016-08-26 19:15:57 +02:00
wm4 bc97d60542 demux: close underlying stream if it's fully read anyway
This is for text subtitles. libavformat currently always reads text
subtitles completely on init. This means the underlying stream is
useless and will consume resources for various reasons (network
connection, file handles, cache memory).

Take care of this by closing the underlying stream if we think the
demuxer has read everything. Since libavformat doesn't export whether it
did (or whether it may access the stream again in the future), we rely
on a whitelist. Also, instead of setting the stream to NULL or so, set
it to an empty dummy stream. This way we don't have to litter the code
with NULL checks.

demux_lavf.c needs extra changes, because it tries to do clever things
for the sake of subtitle charset conversion.

The main reason we keep the demuxer etc. open is because we fell for
libavformat being so generic, and we tried to remove corresponding
special-cases in the higher-level player code. Some of this is forced
due to ass/srt mkv/mp4 demuxing being very similar to external text
files. In the future it might be better to do this in a more
straight-forward way, such as reading text subtitles into libass and
then discarding the demuxer entirely, but for aforementioned reasons
this could be more of a mess than the solution introduced by this
commit.

Probably fixes #3456.
2016-08-26 13:34:52 +02:00
wm4 4121016689 player: don't directly access demuxer->stream
Cleaner and makes it easier to change the underlying stream.

mp_property_stream_capture() still directly accesses it directly via
demux_run_on_thread(). This is evil, but still somewhat sane and is not
getting into the way here.

Not sure if I got all field accesses.
2016-08-26 13:33:38 +02:00
wm4 b636b19058 cache: don't use a backbuffer if the cache is as large as the file
It's just wasted memory.

One corner case is when a file grows during playback, but this is rare
and usually happens on-disk only. The cache size was generally limited
before this change already, so no reason to care.

As an unrelated change, move the cache size info to the resize_cache()
function. There's really no reason not to do this, and it's slightly
more informative if the user changes the cache size at runtime.
2016-08-26 13:33:38 +02:00
wm4 cb9b60ef19 stream_memory: disable stream cache
Obviously makes no sense and just wastes resources.
2016-08-26 13:33:38 +02:00
James Ross-Gowan 31f28da0f3 w32_common: use hooks to detect parent window resize
Because VOCTRL_CHECK_EVENTS is processed asynchronously (as of 088a007,)
the GUI thread no longer gets regular wakeups, so the old check that
made sure the video window matched the parent window's size in --wid
embedding mode did not run very often. This made --wid embedding not
very usable.

Instead of polling for window size changes, use Windows hooks to react
to them when they happen. When the parent window is owned by the same
process as the video window, use a WH_CALLWNDPROC hook. When the parent
window is not owned by the same process, WinEvents must be used, which
are not as smooth, but still work for this purpose.

Since neither SetWindowsHookEx nor SetWinEventHook take a context
parameter to send data to the hook function, the hook functions must
find the child window by its class instead, so there are a few changes
to ensure this is fast and the class is unique.

This also fixes up the logic to handle window destruction. When a parent
window is destroyed, its children are also destroyed, so this gives us a
way to react to parent window destruction without polling.
2016-08-26 20:02:58 +10:00
Avi Halachmi (:avih) ef0b2e33b1 vo_opengl: angle: new opengl flag to control DirectComposition
On some systems DirectComposition might behave poorly. Add an opengl
suboption flag 'dcomposition' (default=yes) which can disable it.
2016-08-25 23:47:37 +10:00
wm4 2a5b61244f x11: work around mutter fullscreen issue
If the video has the same size as the screen, starting with --fs and
then leaving fullscreen doesn't actually leave fullscreen.

The reason is that mpv tries to restore the previous window size if
necessary (otherwise, you'd end up with a Window of nearly the same size
as the screen with some WMs). It will typically restore with the
rectangle set exactly to the screen if no other position or size is
forced. This triggers pre-EWMH fullscreen mode, which WMs detect using
various heuristics.

Apparently we triggered this with mutter (but strangely no other WMs).
It's possible that pre-EWMH fullscreen mode actually requires removing
decorations, and mutter either ignores this. But this is speculation and
I haven't checked.

Work this around by reducing the requested size by 1 pixel if it
happens.

This was observed with mutter 3.18.2.

Fixes #2072.
2016-08-25 14:16:10 +02:00
wm4 c4ba600832 audio: avoid missed wakeups with ab-loops
Could get "stuck".
2016-08-24 12:14:48 +02:00
wm4 c218d9e960 vd_lavc: minor simplification
The timebase is now always valid.
2016-08-23 12:07:46 +02:00
wm4 a47d849df7 ad_lavc: actually tell decoder about the timebase
Essentially forgotten in commit 05e4df3f.
2016-08-23 12:06:47 +02:00
wm4 6980575e15 ao_alsa: log if retrieving supported channel maps fails
It's a sign that the driver doesn't implement the channel map API.
2016-08-22 20:05:34 +02:00
wm4 724f60bf9a audio: do not apply --audio-channels if spdif passthrough is in use
If spdif is enabled, the channel layout has no meaning other than
setting the number of channels. The number of channels must be fixed to
achieve the exact bitrate required.

Fixes #3445.
2016-08-22 12:12:10 +02:00
wm4 74d4073771 demux: demote packet queue overflow to a warning
It doesn't necessarily have to mean anything bad.

We're still too lazy to provide any more detailed information (e.g.
whether this happened to likely bad interleaving, excessive amount of
packets like with some ASS subs, or that the readahead user option is
limitted by the packet queue size).
2016-08-22 12:10:55 +02:00
wm4 93104142f4 player: log if video is considered an image
It's a heristic that can fail, so better log it.
2016-08-21 12:27:48 +02:00
wm4 9a5e062a04 manpage: fix typo 2016-08-20 18:15:24 +02:00
wm4 6b676d82fd vo: be more trusting to estimated display FPS
This should actually be rather safe - we already check whether the
estimated value jitters less than the (possibly untrustworthy) nominal
one. Remove a "safety" check that disabled this code for small
deviations, and make it trigger sooner into playback. Also lower the log
level of messages about using the estimated display FPS down to verbose.

Normally there's another mechanism for smoothing out minor estimation
differences, but that is not good enough here.

This possibly improves behavior as reported in #3433, which can be
reproduced with --vo=null:fps=48.426 --display-fps=48 (though it doesn't
consider the jitter introduced by a real VO).
2016-08-20 18:15:17 +02:00
wm4 af103aebd7 player: update Windows playback state asynchronously
Doing this required synchronizing with the VO thread, which could lead
to audio dropouts if the VO was frozen (which can happen in practice if
e.g. an opengl_cb user is not doing what the API demands).

Add a way to send asynchronous VOCTRLs, and use that for the playback
state. In theory, it would be better to make this status update a
several function and to "merge" several queued update, but that would be
slightly more effort/code, and the update is so infrequent that the
merging would never happen anyway.

The change to vo_destroy() is to make sure all queued asynchronous
reuqests are finished before making the vo_thread exit.

Even though it's only used on MS Windows, it's run on any platform with
any VO, which makes this worse.
2016-08-20 14:46:38 +02:00
wm4 969c011522 ta: add a helper macro 2016-08-20 14:41:12 +02:00
wm4 1a8af89b7d vo: fix mismatching types in pointer operation
run_control() dereferences an uint32_t as int. Whether this is allowed
depends on what uint32_t is typedefed to (dereferencing an unsigned int
as int should be fine). Fix it by always using int. The uint32_t type
never really made sense.
2016-08-20 14:11:35 +02:00
Paul B Mahol e057629493 af_lavrresample: better swr reinitialization 2016-08-20 11:37:06 +02:00
rr- cb31e72589 manpage: info about --panscan vs. --video-unscaled 2016-08-19 22:53:17 +02:00
rr- ed644b0d33 aspect: add --video-unscaled=downscale-big 2016-08-19 22:51:46 +02:00
wm4 23993e91f3 af_lavrresample: fix error if resampler could not be recreated
There are situations where the resampler is destroyed and recreated
during playback. If recreating the resampler unexpectedly fails, the
filter function is supposed to return an error. This wasn't done
correctly, because get_out_samples() accessed the resampler before the
check. Move the check up to fix this.
2016-08-19 22:27:15 +02:00
James Ross-Gowan 68dc869d6a command: prevent O(n^2) behaviour for playlist property
When fetching the playlist property, playlist_entry_from_index would be
called for each playlist entry, which traversed a linked list to get the
entry corresponding to the specified index. This was very slow for large
playlists. Since get_playlist_entry is called for each index in order,
it can avoid a full traversal of the linked list by using the next
pointer on the previously requested entry.
2016-08-20 00:07:32 +10:00
wm4 e5f61c2bd5 vd_lavc: remove unnecessary initialization
This is already the default value.
2016-08-19 15:00:58 +02:00
wm4 2fbd1d3610 demux: change fps field to double
Because why not.
2016-08-19 15:00:58 +02:00
wm4 05e4df3f0c video/audio: always provide "proper" timestamps to libavcodec
Instead of passing through double float timestamps opaquely, pass real
timestamps. Do so by always setting a valid timebase on the
AVCodecContext for audio and video decoding.

Specifically try not to round timestamps to a too coarse timebase, which
could round off small adjustments to timestamps (such as for start time
rebasing or demux_timeline). If the timebase is considered too coarse,
make it finer.

This gets rid of the need to do this specifically for some hardware
decoding wrapper. The old method of passing through double timestamps
was also a bit questionable. While libavcodec is not supposed to
interpret timestamps at all if no timebase is provided, it was
needlessly tricky. Also, it actually does compare them with
AV_NOPTS_VALUE. This change will probably also reduce confusion in the
future.
2016-08-19 14:59:30 +02:00
wm4 4aaa83339c av_common: improve rounding for float->int timestamp conversions 2016-08-19 14:11:32 +02:00
wm4 5d2dfbdfca player: refresh very low framerate video on filter changes
Limit the max. time the refresh is delayed. Make it refresh at all if
image mode is enabled.

Fixes #3435.
2016-08-19 09:38:45 +02:00
wm4 4e3663a2da vf_rotate: allow arbitrary rotation
vf_rotate selects the correct filter for 90° rotation, but it can be
extended to use lavfi's vf_rotate as fallback.

See #3434.
2016-08-19 09:37:52 +02:00
wm4 e6952c7053 github: fix typo 2016-08-18 21:17:25 +02:00
wm4 0f83caf96a github: encourage bug reports
Word this sentence slightly more positively because we are a positive
project.
2016-08-18 21:05:20 +02:00
wm4 1e53fc3a15 demux_lavf: don't report start time for ogg
Better with ogg shoutcast streams. These have PTS resets on each
playlist item, so the PTS would usually reset to some negative value.
2016-08-18 21:03:01 +02:00
wm4 a1dec6f54a player: make looping slightly more seamless
This affects A-B loops and --loop-file, and audio. Instead of dropping
audio by resetting the AO, try to make it seamless by not sending data
after the loop point, and after the seek send new data without a reset.
2016-08-18 20:40:23 +02:00
wm4 bbcd0b6a03 audio: improve aspects of EOF handling
The code actually kept going out of EOF mode into resync mode back into
EOF mode when the playloop had to wait after an audio EOF caused by the
endpts. This would break seamless looping (as added by the next commit).

Apply endpts earlier, to ensure the filter_audio() function always
returns AD_EOF in this case.

The idiotic ao_buffer makes this an amazing pain in the ass.
2016-08-18 20:38:09 +02:00
wm4 7bba97b301 video: don't discard video frames after endpts
Instead of letting it keep decoding by trying to find a new frame,
"plug" the frame queue by not removing it. (Or actually, by putting
it back instead of discarding it.)

Matters for seamless looping (following commits), and possibly some
other corner cases.

The added function vf_unread_output_frame() is a bit of a sin, but still
reasonable, since its implementation is trivial.
2016-08-18 20:37:25 +02:00
wm4 0a0967f48b build: make avutil-mastering-metadata check slightly more robust
Fixes the specific scenario of compiling against a local Libav build,
while the system has FFmpeg installed.
2016-08-18 14:55:43 +02:00
jaseg e02cb674ce manpage: input: fix define-section syntax
Source says "force", manpage said "forced". Now both say "force".
2016-08-17 23:33:20 +02:00
wm4 f5bbb5aed2 player: add option to control duration of image display
The --image-display-duration option controls how long an image is
displayed. It's also possible to display the image forever (until manual
user interaction stops playback).

With this, the core drops the old method to "drain" video (i.e. waiting
for the last frame duration on end of playback). Instead, we reuse
MPContext.time_frame. The old mechanism was disabled for non-images
anyway.

Fixes #3425.
2016-08-17 22:46:48 +02:00
wm4 07f8b64754 m_option: add mechanism to allow inf/-inf float options
Used by the next commit.
2016-08-17 21:48:56 +02:00
wm4 3a7e86ff6e m_option: simplify float value range handling
Use clamp_double() to handle all value restriction/verification. The
error messages become a bit less nice, but they were kind of incomplete
before.
2016-08-17 21:44:05 +02:00
wm4 12e251c29e demux: fix undefined behavior with ogg metadata update
When an ogg track upodates metadata, we have to perform a complicated
runtime update due to the demux.c architecture. A detail was broken and
an array was allocated with the previous number of streams, which
usually led to invalid memory write accesses at least on the first
update.

See github commit comment on commit b9ba9a89.
2016-08-16 10:48:54 +02:00
wm4 814dacdd7d af_lavrresample: work around libswresample misbehavior
The touched code is for seek resets and such - we simply want to reset
the entire resample state. But I noticed after a seek a tiny bit of
audio is missing (mpv's audio sync code inserted silence to compensate).

It turns out swr_drop_output() either does not reset some internal state
as we expect, or it's designed to drop not only buffered samples, but
also future samples.

On the other hand, libavresample's avresample_read(), does not have this
problem. (It is also pretty explicit in what it does - return/skip
buffered data, nothing else.)

Is the libswresample behavior a bug? Or a feature? Does nobody even
know? Who cares - use the hammer to unfuck the situation. Destroy and
deallocate the libswresample context and recreate it. On every seek.
2016-08-16 00:05:34 +02:00
wm4 86fa1e6129 player: allow passing flags to queue_seek()
Change the last parameter from a bool to an int, which is supposed to
take bit-flags. The at this point only flag is MPSEEK_FLAG_DELAY, which
replaces the previous bool parameter. The old false parameter becomes 0,
the old true parameter becomes MPSEEK_FLAG_DELAY.

Since the old "immediate" parameter is now essentially inverted, two
coalesced immediate and delayed seeks end up as delayed instead of
immediate. This change doesn't matter, since there are no relative
immediate seeks anyway.
2016-08-15 21:07:32 +02:00
Martin Herkt 795b65b2ff DOCS: Update version 2016-08-15 16:16:17 +02:00
Martin Herkt ef2d6ed125 Release 0.19.0 2016-08-15 16:10:59 +02:00
Martin Herkt fd1bc95b48 Merge branch 'master' into release/current 2016-08-15 15:19:29 +02:00
Paul B Mahol d7a7e9a8c8 vo_direct3d: add missing header
Fixes build under cygwin.

Signed-off-by: wm4 <wm4@nowhere>
2016-08-14 21:51:59 +02:00
wm4 4a8647b6b8 sub: don't potentially discard too many subtitles on seek
The accepts_packet packet callback is supposed to deal with subtitle
decoders which have only a small queue of current subtitle events (i.e.
sd_lavc.c), in case feeding it too many packets would discard events
that are still needed.

Normally, the number of subtitles that need to be preserved is estimated
by the rendering pts (get_bitmaps() argument). Rendering lags behind
decoding, so normally the rendering pts is smaller than the next video
frame pts, and we simply discard all subtitle events until the rendering
pts.

This breaks down in some annoying corner cases. One of them is seeking
backwards: the VO will still try to render the old PTS during seeks,
which passes a high PTS to the subtitle renderer, which in turn would
discard more subtitles than it should. There is a similar issue with
forward seeks. Add hacks to deal with those issues.

There should be a better way to deal with the essentially unknown
"rendering position", which is made worse by screenshots or rendering
with vf_sub. At the very least, we could handle seeks better, and e.g.
either force the VO not to re-render subs after seeks (ugly), or
introduce seek sequence numbers to distinguish attempts to render
earlier subtitles when a seek is done.
2016-08-14 20:27:37 +02:00
wm4 4b5de33e89 command: add replaygain information properties to track-list 2016-08-13 15:21:09 +02:00
wm4 9d2bcd2ef9 demux: minor cleanup to replaygain error handling
If the PEAK tag is invalid, return an error.

Make the error signalling conventions more uniform by strictly returning
a negative value on error, and treating >=0 as success.
2016-08-13 15:09:03 +02:00
wm4 e392d6610d demux: make ALBUM replaygain tags optional
IF they're missing, use the TRACK ones instead. See #3405.
2016-08-13 15:06:45 +02:00
wm4 78d808c5bd audio: log replaygain values in af_volume instead demuxer
The demuxer layer usually doesn't log per-stream information, and even
the replaygain information was logged only if it came from tags.

So log it in af_volume instead.
2016-08-13 15:06:07 +02:00
wm4 b9ba9a898a demux: add per-track metadata
...and ignore it. The main purpose is for retrieving per-track
replaygain tags. Other than that per-track tags are not used or accessed
by the playback core yet.

The demuxer infrastructure is still not really good with that whole
synchronization thing (at least in part due to being inherited from
mplayer's single-threaded architecture). A convoluted mechanism is
needed to transport the tags from demuxer thread to user thread. Two
factors contribute to the complexity: tags can change during playback,
and tracks (i.e. struct sh_stream) are not duplicated per thread.

In particular, we update the way replaygain tags are retrieved. We first
try to use per-track tags (common in Matroska) and global tags
(effectively formats like mp3). This part fixes #3405.
2016-08-12 21:39:32 +02:00
Paul B Mahol e2a54bb1ca audio/filter: remove delay audio filter
Similar filter is available in libavfilter.
2016-08-12 19:45:39 +02:00
wm4 ec4a8bdb3d github: encourage providing sample files
Also, try to save users from trying to use the github file upload
function. While we're at it, also make the sprunge.us hint a link.
2016-08-11 22:55:36 +02:00
wm4 dc6f8d4a0a command: add a property that returns filename without extension
Requested. Fixes #3404.
2016-08-11 22:40:00 +02:00
wm4 9024cb1685 manpage: remove the word "slave"
It's discriminatory or something.
2016-08-11 22:29:18 +02:00
Ricardo Constantino 5d74ba98ce stream/stream_bluray: display list of available titles on verbose
Based on similar code on FFmpeg and libbluray's list_titles example.
2016-08-11 10:02:46 +02:00
wm4 87190969a7 player: add --no-autoload-files option
Allt his auto-loading is getting annoying especially for testing.
2016-08-10 22:22:50 +02:00
wm4 367e9fb7f1 ao_alsa: make pause state more robust, reduce minor code duplication
With the previous commit, ao_alsa.c now has 3 possible ways to pause
playback. Actually all 3 of them need get_delay() to fake its return
value, so don't duplicate that code.

Also much of the code looks a bit questionable when considering
inconsistent pause/resume calls from outside, so ignore redundant calls.
2016-08-09 17:09:29 +02:00
wm4 2ded41d2be ao_alsa: handle --audio-stream-silence
push.c does not handle this automatically, and AOs using push.c have to
handle it themselves. Also, ALSA is low-level enough that it needs
explicit support in user code. At least I haven't found any option that
does this.

We still can get away relatively cheaply by abusing underflow-handling
for this. ao_alsa.c already configures ALSA to handle underflows by
playing silence. So we purposely induce an underflow when opening the
device, as well as when pausing or resetting the device.

This introduces minor misbehavior: it doesn't account for the additional
delay the initial silence adds, unless the device has fully played the
fragment of silence when the player starts sending data to it. But
nobody cares.
2016-08-09 17:09:29 +02:00
wm4 062349ff5b player: add --audio-wait-open options
Complements the option added in the previous commit.
2016-08-09 17:09:29 +02:00
wm4 eab92cec60 player: add --audio-stream-silence
Completely insane that this has to be done. Crap for compensating HDMI
crap.
2016-08-09 17:09:29 +02:00
wm4 3759a3f40b ao_coreaudio: actually use stop callback
The .pause callback is never used for pull.c-based AOs.

This means this always streamed silence instead of deactivating audio.
2016-08-09 17:09:29 +02:00
wm4 d81b5690df af_lavcac3enc: allow passing options to libavcodec 2016-08-09 17:09:29 +02:00
Thomas Petazzoni 8c2e299b84 wscript: improve stdatomic check
The current stdatomic check verifies the availability of the function by
calling atomic_load(). It also uses this test to check if linking
against libatomic is needed or not.

Unfortunately, on specific architectures (namely SPARC), using
atomic_load() does *not* require linking against libatomic, while other
atomic operations do. Due to this, mpv's wscript concludes that
stdatomic is available, and that linking against libatomic is not
needed, causing the following link failure:

[190/190] Linking build/mpv
audio/out/ao.c.13.o: In function `ao_query_and_reset_events':
/home/peko/autobuild/instance-0/output/build/mpv-0.18.1/build/../audio/out/ao.c:399: undefined reference to `__atomic_fetch_and_4'

In order to fix this, the stdatomic check is adjusted to call
atomic_fetch_add() instead, which does require libatomic. Thanks to
this, the wscript realizes that linking against libatomic is needed, and
the build works fine.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
2016-08-09 17:09:29 +02:00
wm4 469666b75b stream: fix double-free if cache init fails
If the normal stream cache init fails, and a file cache was initialized
before, we free the file cache as well. But since the file cache is
chained to the real stream, the real stream will also be freed. This has
to be prevented by clearing the pointer to the original stream in the
uncached_stream field.

This could in particular be triggered by using --cache-initial=1000 and
aborting playback during loading. (Without that option, stream cache
init failure is far less likely.)
2016-08-08 11:32:55 +02:00
wm4 896a97c2e2 demux: do not add packets between refresh seek requested and done
Could cause strange issues on seeks or track switches, was only visible
as race condition.
2016-08-08 11:13:43 +02:00
wm4 56c52bd2e1 stream_cb: fix stale comment
Oops.
2016-08-08 10:34:12 +02:00
wm4 355a145a48 DOCS/release-policy.md: reminder to update certain version numbers 2016-08-07 19:43:57 +02:00
wm4 3a21d71ad0 client API: bump API for stream_cb
Forgotten in previous commit.

Also minor semi-related change: remove the extra "," from the
mpv_sub_api enum, which I accidentally added in the previous commit.
(C99 is fine with trailing ",", C89 strictly speaking not. So do
this for maximum compatibility.)
2016-08-07 19:42:20 +02:00
Aman Gupta 7ca4a453e0 client API: add stream_cb API for user-defined stream implementations
Based on #2630. Some heavy changes by committer.

Signed-off-by: wm4 <wm4@nowhere>
2016-08-07 19:33:20 +02:00
wm4 52a0cbe456 client API: fix indentation 2016-08-07 19:33:20 +02:00
wm4 5640ceb838 client API: add MPV_ERROR_GENERIC
Because why not.
2016-08-07 19:33:20 +02:00
wm4 cfed84af2b w32_common: update window size on resize events
Fixes a regression introduced by commit 088a0075.

Fixes #3400.
2016-08-07 19:33:20 +02:00
wm4 259f219438 player: gross hack to improve non-hr seeking with external audio tracks
Relative seeks backwards with external audio tracks does not always work
well: it tends to happen that video seek back further than audio, so
audio will remain silent until the audio's after-seek position is
reached. This happens because we strictly seek both video and audio
demuxer to the approximate desirted target PTS, and then start decoding
from that.

Commit 81358380 removes an older method that was supposed to deal with
this. It was sort of bad, because it could lead to the playback core
freezing by waiting on network.

Ideally, the demuxer layer would probably somehow deal with such seeks,
and do them in a way the audio is seeked after video. Currently this is
infeasible, because the demuxer layer assumes a single demuxer, and
external tracks simply use separate demuxer layers. (MPlayer actually
had a pseudo-demuxer that joined external tracks into a single demuxer,
but this is not flexible enough - and also, the demuxer layer as it
currently exists can't deal with dynamically removing external tracks
either. Maybe some time in the future.)

Instead, add a gross hack, that essentially reseeks the audio if it
detects that it's too far off. The result is actually not too bad,
because we can reuse the mechanism that is used for instant track
switching. This way we can make sure of the right position, without
having to care about certain other issues.

It should be noted that if the audio demuxer is used for other tracks
too, and the demuxer does not support refresh seeking, audio will
probably be off by even a higher amount. But this should be rare.
2016-08-07 16:29:13 +02:00
wm4 c7b73edc65 player: fix mid-stream audio sync condition
This code is for resyncing audio-only streams (e.g. switching between
audio tracks if no video track is active). This must not be run if the
video PTS just isn't known yet. (Although the case in which this changes
anything is probably very obscure, if it can even happen. Still, it's a
bit more correct.)

This is a correction to commit 91a3bda6.
2016-08-07 16:00:14 +02:00
wm4 32cc190a55 player: fix display-sync timing if audio take long on resume
In display-sync mode, the very first video frame is idiotically fully
timed, even though audio has not been synced yet at this point, and the
video frame is more like a "preview" frame. But since it's fully timed,
an underflow is detected if audio takes longer than the display time of
the frame (we send the second frame only after audio is done).

The timing code will try to compensate for the determined desync, but it
really shouldn't. So explicitly discard the timing info in this specific
case. On the other hand, if the first frame still hasn't finished
display, we can pretend everything is ok.

This is a hack - ideally, we either would send a frame without timing
info (and then send it again or so when playback starts properly), or we
would add real pause support to the VO, and pause it during syncing.
2016-08-07 14:14:32 +02:00
wm4 39ae261cc5 demux_timeline: enable refresh seeks in some situations
Play a trick to make the packet pos field monotonically increasing over
segment boundaries if the source demuxers return monotonically
increasing pos values. This allows the demuxer to uniquely identify
packets with the pos field, and can do refresh seeks using that.

Normally, the packet pos field is used as a fallback for determining the
playback position if the demuxer returns no proper duration. But
demux_timeline.c always will, and the packet pos fields usually make no
sense in relation to the returned file size anyway if the timeline
source demuxers originate from separate streams.
2016-08-07 13:53:34 +02:00
wm4 78bcbe289e demux: make refresh seek handling more generic
Remove the explicit whitelisting of formats for refresh seeks. Instead,
check whether the packet position is somewhat reliable during demuxing.
If there are packets without position, or the packet position is not
monotonically increasing, then do not use them for refresh seeks.

This does not make sure of some requirements, such as deterministic
seeks. If that happens, mpv will mess up a bit on stream switching.

Also, add another method that uses DTS to identify packets, and prefer
it to the packet position method. Even if there's a demuxer which
randomizes packet positions, it hardly can do that with DTS. The DTS
method is not always available either, though. Some formats do not have
a DTS, and others are not always strictly monotonic (possibly due to
libavformat codec parsing and timestamp determination issues).
2016-08-06 19:28:41 +02:00
wm4 91a3bda6f5 player: sync audio as well when enabling it mid-stream
If an audio track is enabled during playback, then make it resume at the
exact "current position", instead of playing audio before that position.
This was already done for video.
2016-08-06 17:48:45 +02:00
wm4 7fd3dbcd52 demux: fix a minor race condition
If the packet read function returns, and EOF was detected, and a seek
was issued in the meantime, then don't use the EOF result. The seek will
be processed later, and reset the EOF state anyway.

The main effect is probably that we don't return EOF to the decoders
(which the playback core resets before issuing the seek), and that we
won't log an EOF message.

Not important, but slightly more correct.
2016-08-06 17:48:45 +02:00
wm4 d41f0a54b0 player: improve instant track switching
When switching tracks, we normally have the problem that data gets lost
due to readahead buffering. (Which in turn is because we're stubborn and
instruct the demuxers to discard data on unselected streams.) The
demuxer layer has a hack that re-reads discarded buffered data if a
stream is enabled mid-stream, so track switching will seem instant.

A somewhat similar problem is when all tracks of an external files were
disabled - when enabling the first track, we have to seek to the target
position.

Handle these with the same mechanism. Pass the "current time" to the
demuxer's stream switch function, and let the demuxer figure out what to
do. The demuxer will issue a refresh seek (if possible) to update the
new stream, or will issue a "normal" seek if there was no active stream
yet.

One case that changes is when a video/audio stream is enabled on an
external file with only a subtitle stream active, and the demuxer does
not support rrefresh seeks. This is a fuzzy case, because subtitles are
sparse, and the demuxer might have skipped large amounts of data. We
used to seek (and send the subtitle decoder some subtitle packets
twice). This case is sort of obscure and insane, and the fix would be
questionable, so we simply don't care.

Should mostly fix #3392.
2016-08-06 15:47:04 +02:00
wm4 d4ee5e5a8a build: always require atomics
Always require them, instead of just for some components which have hard
requirements on correct atomic semantics. They should be widely
available, and are supported by all recent gcc and clang compiler
versions. We even have the fallbacks builtins, which should keep this
working on very old gcc releases.

In particular, w32_common.c recently added a hard requirement on
atomics, but checking this properly in the build system would have been
messy. This commit makes sure it always works.

The fallback where weak atomic semantics are always fine is in theory
rather questionable as well.
2016-08-05 17:10:22 +02:00
wm4 b2e5eb13bc ao_wasapi: in exclusive mode do not output multichannel by default
Exactly the same situation as with ao_alsa in commit 0b144eac (except
that we can detect the situation better under wasapi).

Essentially, wasapi will allow us to output any sample format, and not
just the one configured by the user in the audio system settings.
2016-08-05 16:11:42 +02:00
wm4 088a0075c5 w32_common: don't wait for GUI thread when polling for events
VOCTRL_CHECK_EVENTS is called on every frame. This is by design, and is
supposed to check the event queue of the windowing API.

With the decoupled GUI thread in w32_common.c this doesn't make too much
sense, and the purpose of VOCTRL_CHECK_EVENTS is really reduced to
checking event flags. Even worse, waiting on the GUI thread can
interfere with playback, since win32 sometimes blocks the event loop
(e.g. clicking the window title bar).

Change the code such that we really only query the event flags. Use
atomics to avoid having to add a new mutex. (We assume we always have
real atomics available. The build system doesn't check this properly,
and it could fall back to dummy atomics, which are not atomic.)

Should help with #3393. Doesn't help if the core happens to send a
synchronous request, most commonly via VOCTRL_SET_CURSOR_VISIBILITY or
VOCTRL_UPDATE_PLAYBACK_STATE.
2016-08-05 16:04:57 +02:00
wm4 9f70117233 ao_null: use channel list option type for channel-layouts suboption 2016-08-05 12:23:42 +02:00
wm4 eccabeb81c options: fix channels options copy/free operations
For some fucked up reason the arguments can be NULL. Makes no sense to
me, but ok.
2016-08-05 12:23:15 +02:00
Ben Boeckel 0c4a73fa21 tvi_v4l2: fix style in the uninit function 2016-08-05 10:08:57 +02:00
Ben Boeckel fa7beaad1f tvi_v4l2: explicitly brace the code
It's fine either way, but this code is weirdly formatted. Make it more
explicit.
2016-08-05 10:08:52 +02:00
wm4 00091411ec github: discourage bug reports 2016-08-05 00:41:08 +02:00
wm4 0b144eac39 audio: use --audio-channels=auto behavior, except on ALSA
This commit adds an --audio-channel=auto-safe mode, and makes it the
default. This mode behaves like "auto" with most AOs, except with
ao_alsa. The intention is to allow multichannel output by default on
sane APIs. ALSA is not sane as in it's so low level that it will e.g.
configure any layout over HDMI, even if the connected A/V receiver does
not support it. The HDMI fuckup is of course not ALSA's fault, but other
audio APIs normally isolate applications from dealing with this and
require the user to globally configure the correct output layout.

This will help with other AOs too. ao_lavc (encoding) is changed to the
new semantics as well, because it used to force stereo (perhaps because
encoding mode is supposed to produce safe files for crap devices?).
Exclusive mode output on Windows might need to be adjusted accordingly,
as it grants the same kind of low level access as ALSA (requires more
research).

In addition to the things mentioned above, the --audio-channels option
is extended to accept a set of channel layouts. This is supposed to be
the correct way to configure mpv ALSA multichannel output. You need to
put a list of channel layouts that your A/V receiver supports.
2016-08-04 20:49:20 +02:00
wm4 c30aa23401 player: remove special-case for DL/DR speakers
Pointless anyway. With superficial checking I couldn't find any decoder
which actually outputs this, and AO chmap negotiation would properly
ignore them anyway in most cases.
2016-08-04 19:14:35 +02:00
wm4 efa9fe8edf options: un-restrict --audio-delay
Not a real reason to restrict its value range.
2016-08-04 11:27:15 +02:00
wm4 3c3361217c player: offset demuxer on start/seek properly with audio/sub delay
Assume you use a large value like --audio-delay=20. Then until now the
player would just have seeked normally to a "too late" position, and
played silence for about 20 seconds until audio in the correct time
range is coming again.

Change this by offsetting seeks by the right amount. This works for both
external and muxed files. If a seek isn't precise, then it works only
for external files.

This might cause issues with very large delay options. Hr-seek skipping
could take a lot of time (especially because it affects video too), the
demuxer queue could overflow, and other weird corner cases could appear.
But we just try this on best-effort basis, and if the user uses extreme
values we don't guarantee good behavior.
2016-08-04 11:26:57 +02:00
wm4 356e703510 vo_opengl_cb: log better error message if OpenGL not initialized by user
Otherwise opengl/video.c would confusingly complain about a wrong
version, which in this case makes no sense.
2016-08-03 19:18:00 +02:00
wm4 f3c35d8108 af_lavcac3enc: skip output if there was no input frame
Unrealistic corner case: drainning was initiated right after a seek.
2016-08-02 22:06:22 +02:00
Rostislav Pehlivanov dea738a245 wayland_common: check for NULL current_output on fs switching
Prevents segfaults when a fullscreen switch is issued before fully
initializing the VO.
Doesn't change anything since the schedule_resize is only there to
resize in case the image size switches, which happens long after init.
2016-08-01 22:16:40 +02:00
wm4 251299da4f af_lavcac3enc: fix buffering timestamps calculations
In theory, an encoder could buffer some data.
2016-08-01 19:59:59 +02:00
wm4 2e3db648b5 af_lavcac3enc: fix memory leak
A major one. Oops.
2016-08-01 17:59:37 +02:00
Rostislav Pehlivanov 08a4af5e6e wayland_common: provide the real scaled window resolution
It makes more sense to completely abstract this scaling inside the
backend so that internally the player only works with real actual
drawn pixels.
2016-08-01 00:31:34 +02:00
wm4 0432ab8f09 af_lavcac3enc: fix a debug message 2016-07-31 18:51:10 +02:00
wm4 0a1c87464b af_lavcac3enc: error out properly if encoding fails 2016-07-31 18:51:08 +02:00
wm4 48f60e182a af_lavcac3enc: fix aspects of AVFrame handling
We send a refcounted frame to the encoder, but then disrespect
refcounting rules and write to the frame data without making sure the
buffer is really writeable.

In theory this can lead to reallocation on every frame is the encoder
really keeps a reference. If we really cared, we could fix this by
providing a buffer pool. But then again, we don't care.
2016-07-31 18:51:05 +02:00
wm4 98af572484 audio: make mp_audio_realloc[_min] ensure frame is writeable
This is logical: the function makes sense only in situations where you
are going to write to the audio data. To make it worse,
av_buffer_realloc() also handles this situation, but only if the buffer
size changes (simply because it can't realloc memory in use), so we have
to explicitly force reallocation by unreffing the buffers first.
2016-07-31 18:51:02 +02:00
Ricardo Constantino 5bcb22beea ytdl: Error out with http_dash_segments
Unsupported for now.
2016-07-30 19:02:39 +02:00
wm4 546f7472fb options: add vp9 to --hwdec-codecs 2016-07-30 15:47:51 +02:00
Rostislav Pehlivanov 45687c17f7 wayland_common: fix fullscreen image switching bug
The problem was that when in fullscreen, switching between images did
not issue a resize event, causing none of the images to be rendered
correctly.
This fixes the problem by issuing a resize event with the screen width
and height.
This commit also moves the zeroing of the events field to when it gets
retrieved by mpv rather than randomly after a resize in the vo/backend
code.
2016-07-30 15:33:00 +02:00
Rostislav Pehlivanov 2f986a5980 wayland_common: prevent black bars on most non-native aspect ratios
ssurface_handle_configure()'s width and height are just hints given by
the compositor, the application's free to not respect those strictly and
to compensate for e.g. aspect ratio.
This prevents crazy scenarios in which pictures with portrait aspect
ratios have a huge black area to make them 16:9 or whatever the
compositor feels like.
2016-07-30 15:32:57 +02:00
Eric Toombs 27b59e1940 demux_raw: s16be support was missing due to small typo
Signed-off-by: wm4 <wm4@nowhere>
2016-07-30 00:05:40 +02:00
Jan Ekström aaf6e3b58d wscript: add proper non-version'd SONAME for Android
This seems to have become a requirement since API target 23+, and
matches what FFmpeg does.
2016-07-30 00:02:40 +02:00
Chris Mayo f95cde60ff build: add --htmldir option
Defaults to docdir but makes it possible to install html documentation
separately.
2016-07-30 00:02:40 +02:00
Rostislav Pehlivanov 3fe5ff99c6 wayland_common: clip window size to the display output size
With X11 it was usually left up to the window manager to prevent huge
windows from being out of range, but no Wayland compositor will do
this right now.

Hugely improves usability when using mpv as an image viewer.
2016-07-30 00:02:40 +02:00
Rostislav Pehlivanov f918ec4b2b wayland_common: flush wakeup_pipe on a wakeup
Missed during the recent changes.
Also simplify error checking code and check for POLLNVAL
as well (the display fd was never actually checked to be valid).
2016-07-30 00:02:39 +02:00
Rostislav Pehlivanov c3e11f7b7c osdep/io: introduce mp_flush_wakeup_pipe()
Makes a fairly common occurence with wakeup_pipes easier to handle.
2016-07-30 00:02:39 +02:00
Rostislav Pehlivanov f3f4e048d8 wayland_common: remove untested/unusable wayland dnd code
Not worth keeping 200 lines of untestable as of today code which might
be broken, if it hasn't been already.
2016-07-30 00:02:39 +02:00
Niklas Haas 46b60a3e72 vo_opengl: remove the 3dlut-size npot2 restriction
This requires changing the pixel upload alignment because the odd sizes
might not be aligned to multiples of 4.

Anyway, the restriction has no real benefit and the sizes in between 32
and 64 might be worth using, so just drop it.
2016-07-25 12:50:11 +02:00
Niklas Haas f127869037 vo_opengl: reduce default 3dlut-size to 64x64x64
Following testing after ebe798a, this is a more than sufficient size to
cover our use case.

The old default was a drop of about 58 dB PSNR using the old code, and
this new default is about 65 dB PSNR, so it's actually an improvement
despite resulting in a smaller size.

There was no outlier whatsoever when comparing sizes around the 64
neighbourhood (with every step corresponding to a PSNR drop of about
0.07 dB), so I picked this since it's a power of two and requires no
change to the current 3dlut-size parsing logic.

I also tested smaller sizes such as 32x32x32 which performed almost as
well on colorful samples, but this results in noticeable black boost in
the dark regions, which is pretty undesirable. Therefore, we should
avoid going much further below 64x64x64.

Either way, this new size is so fast to compute that the 3dlut cache is
almost useless on my end. In fact, it might even be slower to load the
profile from the cache than to recompute it from scratch. (For caches on
a disk. For cache on a tmpfs, it makes no difference)
2016-07-25 12:50:04 +02:00
wm4 cb4342dda4 x11: do not accidentally discard event flags
It seems vo_x11_check_events() was supposed to return the currently
flagged events and reset them. But there are many places where
vo_x11_check_events() is called without checking its return value. This
could lead to forgotten events.

Change the code such that they can't get lost.
2016-07-25 11:28:06 +02:00
Niklas Haas ebe798a333 vo_opengl: increase 3DLUT accuracy at lower LUT sizes
This code had the exact same texture indexing bug that the original
scaler code had before the introduction of the LUT_POS macro to fix it.

We can re-use this same macro here, and the performance drop is
virtually entirely negligible. The benefit is greatly improved LUT
accuracy as the 3DLUT size decreases - in particular, the old LUT
started introducing more and more black crush the lower your LUT size is
(because the error was essentially an over-contrast bias, with a
magnitude linearly related to the lut size).

The new code improves black stability as the LUT size decreases, and
only at very low values (16 and below) do black levels start noticeably
getting affected (due to crude linearization of the nonlinear response
curve).

The default value of 3dlut-size is definitely generous enough for this
to make no difference out of the box, but it also causes no performance
drop at all on my machine so I see no harm in improving the logic.
Furthermore, this means we could easily decrease the default 3dlut size
in a future commit, perhaps even down to 64x64x64 as a default. (But
more testing is warranted here)
2016-07-25 10:26:45 +02:00
wm4 dcfde2934d audio: use idiotic FFmpeg ABI rules for public-except-not-public fields
The FFmpeg API is incredibly weird and inconsistent about this. This is
also a FFmpeg-only issue and nothing like this is in Libav - which
doesn't really show FFmpeg in a very positive light.

(To make it even worse: this is a full-blown Libav API incompatibility,
even though this crap was added for Libav ABI-compatibility. It's
absurd.)

Quoting the FFmpeg header for the AVFrame.channels field:

    /**
     * number of audio channels, only used for audio.
     * Code outside libavutil should access this field using:
     * av_frame_get_channels(frame)
     * - encoding: unused
     * - decoding: Read by user.
     */
    int channels;

It says "should" not must, and it doesn't even mention
av_frame_set_channels(). It's also in the section for public fields (not
below a marker that indicates private fields in a public struct, like
it's done e.g. in AVCodecContext).

But not using the accessor will cause silent failures on ABI changes.
The failure that happened due to this code didn't even make it apparent
what was wrong. So just use the idiotic accessor.

Also harmonize the FFmpeg-cursing in the code. (It's fully justified.)

Fixes #3295.

Note that mpv will still check the exact library version numbers, and
reject mismatches - to protect itself from such issues in the future.
2016-07-24 19:33:20 +02:00
wm4 6bb48a10db player: disable DS with spdif transcoding too
Otherwise it behaves dumb. (Although you could argue it shouldn't try to
guess whether speed changes work, but instead simply disable DS if they
don't work.)
2016-07-24 19:19:24 +02:00
wm4 3623cec7d2 af_lavcac3enc: use common code for AVFrame setup 2016-07-24 19:06:00 +02:00
wm4 d60db967bd demux_lavf: remove subtitle seeking special-case
It used not to work - but now it apparently does. Not sure when that got
fixed in FFmpeg, but there's no longer a reason to keep this hack.

This also gets rid of the check for the read_seek2 field, which is not
part of the public API.
2016-07-24 18:41:55 +02:00
wm4 99d9921f39 vo_opengl: glctx can be NULL during init
This fixes a crash that can happen with the Cocoa backend: it calls
vo_wakeup() during init, which calls vo_opengl.c/wakeup().

Fixes #3360.
2016-07-21 16:07:15 +02:00
wm4 16d276308a x11, wayland: do not accidentally close FD 0
Both backends have code to close each FD of their wakeup_pipe array.
This array is default-initialized with 0, which means if the backends
exit before the wakeup pipe is created (e.g. when probing), they would
close FD 0.

Initialize the FDs with -1. Then we call close(-1) in these situations,
which is perfectly allowed and has no bad consequences.
2016-07-21 15:18:32 +02:00
wm4 b4acfcc8aa vo: remove now unused event_fd handling 2016-07-21 14:48:30 +02:00
Rostislav Pehlivanov c6b83fec7d wayland_common: make function declaration consistent
Half the code had a space before the arguments and half didn't.
2016-07-21 14:45:40 +02:00
Rostislav Pehlivanov c0ef3cf9c2 wayland: port to the new wakeup/wait_events framework
This fits natively into the vo/backend and allows to simplify the
polling code.
One new change is the fact that surface_handle_enter flags VO_EVENT_WIN_STATE
and VO_EVENT_RESIZE instead of only VO_EVENT_WIN_STATE. Before this, the code
hackily relied on the timeout and the loop in the wait_frame function to track
and set the scaling factor. Instead, this triggers mpv to run a schedule_resize
and adjust the new VO output dimensions immediately. This is also more accurate
since surface_handle_enter() gets called when a surface is created, moved and
resized, which is exactly what the rest of the player might be interested in.
2016-07-21 14:45:38 +02:00
wm4 8f51418ca4 manpage: not-document tscale=linear 2016-07-21 12:26:05 +02:00
Niklas Haas 7d01a16f64 vo_opengl: add a tscale=linear direct implementation
This uses GLSL mix() instead of going through an indirect texture
access. Easy to implement and might require less resources on some
devices, since the oversample code was already essentially just a
special case of this.

Could be made the new default (as per issue #2685), but that should be
done in a separate commit.
2016-07-21 11:26:19 +02:00
Akemi f53c7f1a78 cocoa: remove unused icc profile variables 2016-07-21 08:48:45 +02:00
Akemi 7531275f62 cocoa: update screen fps only if necessary
we don't need to update the display refresh rate
when going fullscreen or updating the colour profile
2016-07-21 08:48:37 +02:00
wm4 fde784129f x11: stop using vo.event_fd
Instead let it do its own event loop wakeup handling.
2016-07-20 20:52:08 +02:00
wm4 bd9c0a10e5 vo_opengl: allow backends to provide callbacks for custom event loops
Until now, this has been either handled over vo.event_fd (which should
go away), or by putting event handling on a separate thread. The
backends which do the latter do it for a reason and won't need this, but
X11 and Wayland will, in order to get rid of event_fd.
2016-07-20 20:42:30 +02:00
Rostislav Pehlivanov e11a20a812 vo_wayland: fix high CPU usage due to busy polling
There's no need to call wl_display_flush() since all the client-side
buffered data has already been flushed prior to polling the fd.
Instead only check for POLLIN and the usual ERR+HUP.
2016-07-19 10:01:51 +02:00
wm4 64cd0f4292 x11: skip ICC update on every window move
Don't just cause vo_opengl to update the ICC profile every time the
window is moved. Instead, explicitly check if the screen was changed.

Mostly untested.
2016-07-18 13:06:38 +02:00
wm4 510c6a1be4 libarchive: sanitize non-UTF8 archive entries
Some client API users simply don't like such filenames. For their sake,
don't return them, but return a dummy filename instead. (Returning a
latin1-ized version would work too, but is slightly more work.)

Also remove the "\n" from the replacement dummy filename. This was
accidental.
2016-07-18 12:52:59 +02:00
wm4 fb8deb69a6 libarchive: unify entry iteration between stream/demux layers
No really good reason to duplicate this.
2016-07-18 12:44:56 +02:00
wm4 77e1e8e38e audio: refactor mixer code and delete mixer.c
mixer.c didn't really deserve to be separate anymore, as half of its
contents were unnecessary glue code after recent changes. It also
created a weird split between audio.c and af.c due to the fact that
mixer.c could insert audio filters. With the code being in audio.c
directly, together with other code that unserts filters during runtime,
it will be possible to cleanup this code a bit and make it work like the
video filter code.

As part of this change, make the balance code work like the volume code,
and add an option to back the current balance value. Also, since the
balance semantics are unexpected for most users (panning between the
audio channels, instead of just changing the relative volume), and there
are some other volumes, formally deprecate both the old property and the
new option.
2016-07-17 19:21:28 +02:00
wm4 79974e7ad9 audio: fix crashes due to broken uninit check
Since mixer->ao is always NULL now (it was really just forgotten to be
removed), the uninit call never actually cleared the af field, leaving
a dangling pointer that could be accessed by volume control.
2016-07-15 23:11:25 +02:00
wm4 ea18cb99ba vf_vavpp: get rid of mp_refqueue_is_interlaced()
This makes the difference between passing VA_FRAME_PICTURE or
VA_BOTTOM_FIELD for progressive frames (that should be force-
deinterlaced) to VAProcPipelineParameterBuffer.flags. VA-VPP doesn't
really seem to care, and we can get rid of mp_refqueue_is_interlaced()
entirely. It could be argued it's better to pass field flags instead of
the progressive flag.
2016-07-15 20:37:46 +02:00
wm4 c5361d12d8 vf_d3d11vpp: fix interlaced-only=no mode
"Real" frame flag vs. what we pretend it to be. It always used the real
flag, and thus never deinterlaced unflagged frames, even if the
suboption was set to "no".
2016-07-15 20:21:03 +02:00
wm4 358932a109 vf_d3d11vpp: add video processor selection
Unfortunately completely useless. I still don't know how to force a
video processor to use a specific algorithm, if it's even possible.
2016-07-15 19:48:58 +02:00
wm4 831fc4f012 player: do not cut off terminal status line if it contains newlines
Just a heuristic to preserve the status line in odd corner cases.
Probably a crap idea.

Fixes #3340.
2016-07-15 18:58:36 +02:00
wm4 f29bba1123 af: avoid rebuilding filter chain in another minor case
No need to create additional noise of we can trivially see that
rebuiding the chain won't change anything.
2016-07-15 13:04:17 +02:00
wm4 48f9ea7104 videotoolbox: add yuv420p to --videotoolbox-format 2016-07-15 13:04:17 +02:00
wm4 ae94f329a9 vo_opengl: hwdec: reset hw_subfmt field
In theory, mp_image_params with hw_subfmt set to non-0 if imgfmt is not
a hwaccel format is invalid. (It worked fine because nothing checks this
yet.)
2016-07-15 13:04:17 +02:00
wm4 85488f6892 video: change hw_subfmt meaning
The hw_subfmt field roughly corresponds to the field
AVHWFramesContext.sw_format in ffmpeg. The ffmpeg one is of the type
AVPixelFormat (instead of the underlying hardware format), so it's a
good idea to switch to this too for preparation.

Now the hw_subfmt field is an mp_imgfmt instead of an opaque/API-
specific number. VDPAU and Direct3D11 already used mp_imgfmt, but
Videotoolbox and VAAPI had to be switched.

One somewhat user-visible change is that the verbose log will now always
show the hw_subfmt as image format, instead of as nonsensical number.

(In the end it would be good if we could switch to AVHWFramesContext
completely, but the upstream API is incomplete and doesn't cover
Direct3D11 and Videotoolbox.)
2016-07-15 13:04:17 +02:00
Martin Herkt 4a4a9f3302 man: fix PDF build error
ReportLab really doesn’t like breaking inline literals, so insert an
explicit line break.

Fixes #3338
2016-07-15 12:59:26 +02:00
Aman Gupta 588b2f48e5 videotoolbox: add --hwdec=videotoolbox-copy for h/w accelerated decoding with video filters 2016-07-15 01:01:17 +02:00
wm4 e656889624 DOCS/compile-windows.md: MSVC DLL usage instructions 2016-07-14 22:40:10 +02:00
Timotej Lazar 91a1b17104 Use - as command-name separator everywhere
Old-style commands using _ as separator (e.g. show_progress) were still
used in some places, including documentation and configuration files.
This commit updates all such instances to the new style (show-progress)
so that commands are easier to find in the manual.
2016-07-14 22:37:42 +02:00
wm4 6e45e1de77 demux_timeline: restore mkv edition switching 2016-07-14 18:26:58 +02:00
wm4 d191d76e52 ao_pulse: fix some volume control rounding issues
Volume could get easily "stuck" or making too huge steps when doing
things like "add ao-volume 1".
2016-07-14 18:11:14 +02:00
wm4 f53d73b9dc ao_creoaudio: print OSStatus as decimal signed integer too
OSStatus is quite inconsistent. Sometimes it's a FourCC, sometimes it
reads as decimal signed number.
2016-07-13 17:07:06 +02:00
wm4 79f48500e2 ao_coreaudio: use correct free function on errors 2016-07-13 16:34:00 +02:00
wm4 b5bc93d009 manpage: add some missing color management related sub-properties 2016-07-13 11:05:27 +02:00
Niklas Haas a14f9249c4 command: add properties for HDR metadata
Since it turns out that knowing what exactly a file was tagged with can
be useful for debugging purposes, expose this as a property so I can
check it more easily.

This is mostly useful for sig-peak (since nom-peak is currently entirely
calculated by us), but I added both for consistency.
2016-07-13 11:03:42 +02:00
wm4 8b47e5daa4 video: respect --deinterlace=auto
--deinterlace=auto is the default, and has the obscure semantics that
deinterlacing is disabled, unless the user has manually inserted a
deinterlacing filter.

While in software decoding this doesn't matter, and we will happily
insert 2 yadif filters (if the user has already added one), or not
remove the yadif filter (if deinterlacing is disabled, but the user has
added the filter manually), this is different with hardware deinterlacer
filters. These support VFCTRL_SET_DEINTERLACE for toggling deinterlacing
filtering at runtime. It exists mainly for legacy reasons, and possibly
because it makes switching deinterlacing modes more efficient. It might
also gives us an entry-point for VO deinterlacing, maybe. For whatever
reasons this mechanism exists, we still support and use it.

This commit fixes that video.c always used VFCTRL_SET_DEINTERLACE to
disable deinterlacing, even if --deinterlace=auto was set. Fix this by
checking the value of the option directly.
2016-07-12 19:37:09 +02:00
James Ross-Gowan bf2e2bf3e8 win32: mpv.rc: re-add version info
For some reason, the lack of version info was preventing mpv from
appearing in the Default Programs dialog. Re-add it, but don't set the
string version numbers from version.h, because that's what was causing
trouble when the version info was removed. Like the binary version
numbers, these are now hardcoded to 2.0.0.0, which probably doesn't
matter.

The new version info block is also slightly different to the old one. It
fills out all the binary VERSIONINFO fields and makes better use of
macros. It also removes the \000 line terminators from the string
version info, since as far as I can tell, this was just cargo-culting
for an old broken version of the Microsoft resource compiler, and
binutils' windres terminates the strings properly without them.
2016-07-12 21:05:33 +10:00
James Ross-Gowan 43e811cb4b vo_opengl: angle: use WARP if there are no hw adapters
This should get mpv working on Windows 7 machines without hardware
accelerated graphics adapters. It already worked on Windows 8 and up
because those systems would silently fall back to WARP if there was no
graphics hardware installed.

The normal MPGL_CAP_SW flag is not set, so unlike other opengl backends,
this will choose a software adapter even if opengl:sw is not specified.
The reason for this is, unlike on Linux, where vo_xv and vo_x11 can be
used, mpv on Windows does not have any VO to fall back on when hardware
acceleration isn't available, so if software adapters are rejected, the
user won't see any video output when using the default settings. WARP
seems to perform quite well, so it should be used in this case.
2016-07-12 20:26:41 +10:00
wm4 2d44dfaba9 cache: minor simplification
Every cache_wakeup_and_wait() caller has to deal with asynchronous
stream abort, so why not make it somehow part of the function.
2016-07-11 22:20:23 +02:00
wm4 f4d62dc4a0 cache: fix previous commit
The cache reader thread actually unlocks the mutex protecting the
underlying stream while reading from it. That's why other code goes out
of its way to run certain stream operations on the cache thread. Do the
same.

We could have this simpler by creating a mechanism that would "park" the
cache thread and make it wait for the lock (while we have it) in order
to gain exclusive access. This could be done in the future.
2016-07-11 22:16:06 +02:00
wm4 374600cec0 cache: propagate seek failures
Eagerly execute seeks to the underlying stream in the cache seek
entrypoint itself. While asynchronous execution is a goal of the cache,
it doesn't matter too much for seeks. They always were executed within
the lock, so the reader was blocked anyway. It's not necessary to ensure
async. execution here either, because seeks are relatively rare, and the
demuxer can just stay blocked for a while.

Fixes: mpv http://samples.mplayerhq.hu/V-codecs/DIV5/ayaneshk-test.avi
2016-07-11 20:52:30 +02:00
James Ross-Gowan 5a6ba2a4fd vo_opengl: angle: try D3D9 when D3D11 fails eglInitialize
This will happen when D3D11 is present on the machine but the supported
feature level is too low.
2016-07-11 22:07:13 +10:00
wm4 e246c3f060 audio: fix code for adjusting conversion filters
This code was supposed to adjust existing conversion filters (to make
them output a different format). But the code was just broken,
apparently a refactoring accident. It accessed af instead of af->prev.

The bug tended to add new conversion filters, even if an existing one
could have been used. (Can be tested by inserting a dummy lavrresample
filter followed by a format filter which forces conversion.)

In addition, it's probably better to return the actual error code if
reinitializing the filter fails. It would then respect an AF_FALSE
return value, which means format negotiation failed, instead of a
generic error.
2016-07-11 12:23:32 +02:00
wm4 61afe3820a af_volume: don't let softvol overwrite af_volume volumedb sub-option
af_volume has a volumedb sub-option, which allows the user to set an
explicit volume. Until recently, the player read back this value and
used it as initial softvol volume. But now it just overwrites it.

Instead of overwriting it, multiply the different gain values. Above
all, this will do the right thing if only softvol is used, or if the
user only adds the af_volume filter manually.
2016-07-11 11:03:36 +02:00
wm4 60048b7eb9 audio: add heuristic to move auto-downmixing before other filters
Normally, you want downmixing to happen first thing in the filter chain.
This is reflected in codec downmixing, which feeds the filter chain
downmixed audio in the first place. Doing this has the advantage of
needing less data to process. But the main motivation is that if there
is a drc filter in the chain, you want to process it the downmixed
audio.

Add an idiotic heuristic to achieve this. It tries to detect whether the
audio was indeed automatically downmixed (or upmixed). To detect what
the output format is going to be, it builds the filter chain normally,
and then retries with the heuristic applied (and for extra paranoia,
retries without the heuristic again if it fails to successfully rebuild
the filter chain for unknown reasons). This is simple and will work in
almost all cases.

Doing it in a more complete way is rather hard, because filters are so
generic. For example, we know absolutely nothing about the behavior of
af_lavfi, which creates an opaque filter graph with libavfilter. We
don't know why a filter would e.g. change the channel layout on its
output. (Our heuristic bails out in this case.) We're also slave to the
lowest common denominator of how our format negotiation works, and how
libavfilter's works.

In theory, we could make this mechanism explicit by introducing a
special dummy filter. The filter chain would then try to convert between
input and output formats at the dummy filter, which would give the user
more control over how downmix happens. On the other hand, the user could
just insert explicit conversion filters instead, so this would probably
have questionable value.
2016-07-10 19:53:53 +02:00
wm4 7be98ef1b2 audio: add auto-inserted flag to filter list logging
Like the video filter chain.
2016-07-10 19:51:09 +02:00
wm4 2eac58eaa9 audio: cleanup audio filter format negotiation
The algorithm and functionality is the same, but the code becomes much
simpler and easier to follow.

The assumption that there is only 1 conversion filter (lavrresample)
helps with the simplification, but the main change is to use the same
code for format/channels/rate. Get rid of the different AF_CONTROL_SET_*
controls, and change the af->data parameters directly. (af->data is
badly named, but essentially is a placeholder for the output format.)

Also, instead of trying to use the af_reinit() loop to init inserted
conversion filters or filters with changed output formats, do it inline,
and move the common code to a filter_reinit() function. This gets rid of
the awful retry variable.

In general, this should not change any runtime behavior.
2016-07-10 19:51:09 +02:00
wm4 065bb635d9 manpage: minor fix
Also fix some other type in interface-changes.rst.
2016-07-10 19:51:09 +02:00
Uros Vampl c5827387fd audio: show an osd bar when changing ao-volume
also, make the osd msg prettier
2016-07-10 19:49:28 +02:00
Martin Herkt 1e00bcc14c Release 0.18.1 2016-07-10 02:20:08 +02:00
Martin Herkt 7635438592 Merge branch 'master' into release/current 2016-07-10 01:06:17 +02:00
wm4 e518bf2c72 audio: insert audio-inserted filters at end of chain
This happens to be better for the af_volume filter (for softvol), and
saves some code too. It's "better" because you want to affect the
final filtered audio, such as after a manually inserted drc filter.
2016-07-09 20:23:15 +02:00
wm4 d47b708f00 audio: don't crash when changing volume if no audio is initialized
Oversight.
2016-07-09 19:34:45 +02:00
wm4 2fb2f9b93a man: fix typo 2016-07-09 18:55:14 +02:00
wm4 995c47da9a audio: drop --softvol=no and --softvol=auto
Drop the code for switching the volume options and properties between
af_volume and AO volume controls. interface-changes.rst mentions the
changes in detail.

Do this because this was exceedingly complex and had other problems as
well. It was also very hard to test. It's just not worth the trouble.

Some leftovers like AOCONTROL_HAS_PER_APP_VOLUME will be removed at a
later point.

Fixes #3322.
2016-07-09 18:31:18 +02:00
Jakub Wilk da9590d368 man: fix typos 2016-07-09 16:27:42 +02:00
Jakub Wilk 34a33ebd4d vo_xv, vo_x11: fix typos in warnings 2016-07-09 14:35:41 +02:00
wm4 e58ecc3630 man: fix botched sentence
Fixes #3323.
2016-07-08 19:34:52 +02:00
wm4 6d83455a95 vd_d3d11vpp: remove nonsensical flush call
I made this call up because I sort of thought this makes senssssse. I'm
now convinced that it does not, and even is actively harmful. I'm still
quite in the dark how the DirectD 11 video API is supposed to work with
synchronization, but at least for normal graphics this call would not
make much sense.
2016-07-08 19:34:24 +02:00
wm4 35be389031 x11: add missing FocusChangeMask
So we actually get FocusOut events. Disables key repeat when losing
focus while a key is down.
2016-07-08 16:36:53 +02:00
wm4 885e991312 ao_coreaudio: error out when selecting invalid device
When selecting a device that simply doesn't exist with --audio-device,
AudioUnit will still initialize and start playback without complaining.
But it will never call the audio render callback, which leads to audio
playback simply not progressing.

I couldn't find a way to get AudioUnit to report an error at all, so
here's a crappy hack that takes care of this in most cases. We assume
that all devices have a kAudioDevicePropertyDeviceIsAlive property.
Invalid devices will error when querying the property (with 'obj!' as
status code).

This is not the correct fix, because we try to double-guess AudioUnit's
behavior by accessing a lower label API. Suggestions welcome.
2016-07-08 16:11:03 +02:00
wm4 26b6873ffd client API: remove "status" log level from mpv_request_event docs
Although it appears to be accepted by the function, MSGL_STATUS messages
are never passed to the client API. Consequently "status" has the same
meaning as "v" and is useless.
2016-07-08 16:10:57 +02:00
wm4 71a8aa2e9a command: don't delay progress updates to next video frame 2016-07-08 13:46:15 +02:00
wm4 16b48a429d video: fix midstream video configuration changes
Commit 771a8bf5 added code to avoid unnecessary vf_reconfig() calls for
unrelated reasons, but forget to consider that it has to be called at
least once if the input format changes. As a consequence it got "stuck"
due to not being able to decode more frames.
2016-07-08 08:22:51 +02:00
wm4 f2110f582d vo_vdpau: minor simplification
Remove some indirections that aren't needed anymore.
2016-07-07 16:10:53 +02:00
wm4 8660b4c9f0 video: limit number of frames sent to VO to the VO requested amount
vo_frame can have more than 1 frame - the extra frames are future
references, which are sometimes useful for filtering (vo_opengl
interpolation). There's no harm in reducing the number of frames sent to
the VO requested amount of future frames, so do that.

Doesn't actually reduce the number of concurrently in use frames in
practice.
2016-07-07 16:10:13 +02:00
wm4 ab6fac43b4 player: cut off status line on terminal width
If the status line is wider than the reported terminal size, then cut it
off instead of causing the terminal to scroll down for the next line.

This is done in the most primitive way possible, assuming ASCII.

This was actually done in the past as far as I'm aware; do it again.
(Probably differently.)
2016-07-06 19:52:09 +02:00
wm4 5d2f1da7c5 vf, af: print filter labels in verbose mode 2016-07-06 14:13:03 +02:00
wm4 771a8bf5c6 video: fix deinterlace filter handling for VFCTRL_SET_DEINTERLACE filters
Some filters support VFCTRL_SET_DEINTERLACE. This affects most hardware
deinterlace filters. They can be inserted by the user manually, or auto-
inserted by vf.c itself as conversion filter (vf_d3d11vpp). In these
cases, we shouldn't insert or remove filters outselves, and instead
VFCTRL_SET_DEINTERLACE should be invoked to switch the mode.

This wasn't done correctly in the recently refactored code and could
have broken with --deinterlace. (The refactor only considered switching
via property in this case.) Fix it by making it a proper part of the
filter_reconfig() function, and making set_deinterlacing() (which is
called by the property handler) merely call filter_reconfig() in all
cases to do the real work.

We can even avoid rebuilding the filter chain - though only if no other
auto-filters are inserted. It probably also provides a slightly cleaner
way to implement functionality in the VO while still inserting video
filter fallbacks correctly if required.
2016-07-06 14:08:47 +02:00
wm4 08cd50b84b vf: mark filter chain as uninitialized when mutating it
Sounds fair. Can be used to determine if the filter chain was mutated at
all, and avoiding unconditional reinit if it wasn't.
2016-07-06 13:47:58 +02:00
wm4 0b1ef81498 video: fix deinterlace filter handling on pixel format changes
The test scenario at hand was hardware decoding a file with d3d11 and
with deinterlacing enabled. The file switches to a non-hardware
dedocdeable format mid-stream. This failed, because it tried to call
vf_reconfig() with the old filters inserted, with was fatal due to
vf_d3d11vpp accepting only hardware input formats.

Fix this by always strictly removing all auto-inserted filters
(including the deinterlacing one), and reconfiguring only after that.

Note that this change is good for other situations too, because we
generally don't want to use a hardware deinterlacer for software
decoding by default. They're not necessarily optimal, and VAAPI VPP even
has incomprehensible deinterlacer bugs specifically with software frames
not coming from a hardware decoder.
2016-07-06 13:38:43 +02:00
wm4 fc76966d9e vf: don't clobber input params on reconfigure failure
I think this is more robust, and future commits will rely on it.
2016-07-06 13:27:20 +02:00
wm4 0fe62bc1d2 player: it's not --force-seeking but --force-seekable
Oops. Fuck.
2016-07-06 00:11:57 +02:00
wm4 d72bcc8041 player: rewrite deinterlace filter auto-insertion
Instead of using the "vf" command code (which changes filters at runtime
on user input), use the general filter-insertion code. The latter was
added later, and is more suitable for automatically inserted filters.

The old code failed in particular when using watch-later saving, which
stored the filter list in the resume config file. If a user changed the
hardware decoding mode via command line, the stored filter chain was out
of date and could cause failure due to not working with hardware or
software decoding mode. Storing the deinterlace filter in the filter
list was unavoidable, because it was part of the user state. (The new
code only edits the actually instantiated filters.)
2016-07-05 21:10:26 +02:00
Niklas Haas 329a7147d0 csp: document deviations from the references where they occur
These mostly happen in situations where the correct behavior is
relatively new and not found in the wild (therefore not worth
implementing) and/or extremely complicated (and thus not worth worrying
about the potential edge cases and UI changes).

Still, it's best to document these where they happen to guide the poor
souls maintaining these files in the future.
2016-07-05 19:16:49 +02:00
Ben Boeckel 4f4eea6b44 x11_common: silence xdg-screensaver
Some screen lockers have a habit of dumping output to the terminal when
their output is reset. Ignore its output to keep the TTY output clean.
2016-07-05 19:16:01 +02:00
Ben Boeckel 33e72ed451 subprocess: add a callback to ignore output
This callback is equivalent to shoving data into /dev/null.
2016-07-05 19:15:59 +02:00
James Ross-Gowan 6a3da439cd vo_opengl: angle: update the swapchain on resize
This uses eglPostSubBufferNV to trigger ANGLE to check the window size
and update the size of the swapchain to match, which is recommended
here: https://groups.google.com/d/msg/angleproject/RvyVkjRCQGU/gfKfT64IAgAJ

With the D3D11 backend, using eglPostSubBufferNV with a 0-sized update
region will even skip the Present() call, meaning it won't block for a
vsync period. Hopefully ANGLE will have a less hacky way of doing this
in future. See the relevant ANGLE issue: http://anglebug.com/1438

Fixes #3301
2016-07-04 22:04:37 +10:00
wm4 f98e1b0b96 vo_opengl: error out gracefully when trying to use FBOs without FBO API
This can for example happen with vo_opengl_cb, if it is used with a GL
implementation that does not supports FBOs. (mpv itself should never
attempt to use FBOs if they're not available.)

Without this check it would trigger an assert() in our dummy
glBindFramebuffer wrapper.

Suspected cause of #3308, although it's still unlikely.
2016-07-04 13:34:31 +02:00
wm4 7cd1a3c766 vf_d3d11vpp: fix output image format if not doing any filtering
For example it should be set to IMGFMT_D3D11NV12 if it isn't already.
Otherwise, an assertion in vf.c could trigger.

This probably couldn't be provoked yet.
2016-07-04 11:54:02 +02:00
wm4 46f1ce1e2f input: remove redundant log message 2016-07-04 10:50:00 +02:00
Niklas Haas be230d16e5 vo_opengl: move eval_szexpr to user_shaders.c
This moves some of the bulky user-shader specific logic into the file
dedicated to it. Rather than expose video.c state, variable lookup is
now done via a simulated closure.
2016-07-03 19:42:52 +02:00
Niklas Haas 5b6cce2b73 vd_lavc: expose mastering display side data reference peak
This greatly improves the result when decoding typical (ST.2084) HDR
content, since the job of tone mapping gets significantly easier when
you're only mapping from 1000 to 250, rather than 10000 to 250.

The difference is so drastic that we can now even reasonably use
`hdr-tone-mapping=linear` and get a very perceptually uniform result
that is only slightly darker than normal. (To compensate for the extra
dynamic range)

Due to weird implementation details, this only seems to be present on
keyframes (or something like that), so we have to cache the last seen
value for the frames in between.

Also, in some files the metadata is just completely broken /
nonsensical, so I decided to apply a simple heuristic to detect
completely broken metadata.
2016-07-03 19:42:52 +02:00
Niklas Haas 923e3c7b20 vo_opengl: generalize HDR tone mapping mechanism
This involves multiple changes:

1. Brightness metadata is split into nominal peak and signal peak.

For a quick and dirty explanation: nominal peak is the brightest value
that your color space can represent (i.e. the brightness of an encoded
1.0), and signal peak is the brightest value that actually occurs in
the video (i.e. the brightest thing that's displayed).

2. vo_opengl uses a new decision logic to figure out the right nom_peak
and sig_peak for all situations. It also does a better job of picking
the right target gamut/colorspace to use for the OSD. (Which still is
and still should be treated as sRGB). This change in logic also
fixes #3293 en passant.

3. Since it was growing rapidly, the logic for auto-guessing / inferring
the right colorimetry configuration (in pass_colormanage) was split from
the logic for actually performing the adaptation (now pass_color_map).

Right now, the new logic doesn't do a whole lot since HDR metadata is
still ignored (but not for long).
2016-07-03 19:42:52 +02:00
Niklas Haas d81fb97f45 mp_image: split colorimetry metadata into its own struct
This has two reasons:

1. I tend to add new fields to this metadata, and every time I've done
so I've consistently forgotten to update all of the dozens of places in
which this colorimetry metadata might end up getting used. While most
usages don't really care about most of the metadata, sometimes the
intend was simply to “copy” the colorimetry metadata from one struct to
another. With this being inside a substruct, those lines of code can now
simply read a.color = b.color without having to care about added or
removed fields.

2. It makes the type definitions nicer for upcoming refactors.

In going through all of the usages, I also expanded a few where I felt
that omitting the “young” fields was a bug.
2016-07-03 19:42:52 +02:00
Niklas Haas 3abf9c9204 vo_opengl: don't constantly resize the output FBO
Commit 883d3114 seems to have (accidentally?) dropped the FBOTEX_FUZZY
from the output_fbo resize, which means that current master will keep
resizing and resizing the FBO as you change the window size, introducing
severe memory leaking after a while. (Not sure why that would cause
memory leaks, but I blame nvidia)

Either way, it's bad for performance too, so it's worth fixing.
2016-07-03 19:42:52 +02:00
wm4 ea23a86f49 sub: remove unused sub_bitmaps.scaled field 2016-07-03 19:32:43 +02:00
wm4 8ed32e90c9 sub: move RGBA scaling to vo_vaapi
vo_vaapi is the only thing which can't scale RGBA on the GPU. (Other
cases of RGBA scaling are handled in draw_bmp.c for some reason.)

Move this code and get rid of the osd_conv_cache thing.

Functionally, nothing changes.
2016-07-03 19:32:43 +02:00
wm4 37cf92c07a sub: change how libass output is converted to RGBA in some cases
This affects VOs (or other code which render OSD) which does not support
the LIBASS format, but only RGBA. Instead of having a converter stage in
osd.c, make mp_ass_packer_pack() output directly in RGBA.

In general, this is work towards refcounted subtitle images.

Although we could keep the "converter" design, doing it this way seems
simpler, at least considering the current situation with only 2 OSD
formats. It also prevents copying & packing the data twice, which will
lead to better performance. (Although I guess this case is not important
at all.)

It also fixes --force-rgba-osd-rendering when used with vo_opengl,
vo_vdpau, and vo_direct3d.
2016-07-03 19:32:31 +02:00
wm4 59972fbfe1 sub: move around some code
Put the packing code into separate functions. Preparation for the
following commit.
2016-07-03 19:32:00 +02:00
wm4 f110552898 sub: pass preferred OSD format to subtitle renderers
The intention is to let mp_ass_packer_pack() produce different output
for the RGBA and LIBASS formats. VOs (or whatever generates the OSD)
currently do not signal a preferred format, and this mechanism just
exists to switch between RGBA and LIBASS formats correctly, preferring
LIBASS if the VO supports it.
2016-07-03 19:31:56 +02:00
wm4 315e2e3da8 vo_opengl: remove caching GL_MAX_TEXTURE_SIZE value
No real need to cache this, and we need fewer fields in the OSD part
struct.

Also add logging for when the OSD texture is reallocated.
2016-07-03 17:33:59 +02:00
wm4 b57debe5b3 vo_opengl: use ringbuffer of PBOs
This is how PBOs are normally supposed to be used.

Unfortunately I can't see an any absolute improvement on nVidia binary
drivers and playing 4K material. Compared to the "old" PBO path with 1
buffer, the measured GL time decreases significantly, though.
2016-07-03 16:34:32 +02:00
wm4 8c7f9dc1a8 vo_opengl: support inconsistent negative strides per plane
GL generally does not support flipping the image on upload, meaning
negative strides are not supported. vo_opengl handles this by flipping
rendering if the stride is inverted, and gl_pbo_upload() "ignores"
negative strides by uploading without flipping the image.

If individual planes had strides with different signs, this broke. The
flipping affected the entire image, and only the sign of the first plane
was respected.

This is just a crazy corner case that will never happen, but it turns
out this is quite simple to support, and actually improves the code
somewhat.
2016-07-03 16:34:32 +02:00
wm4 823c353faa vo_opengl: move PBO upload handling to shared code
This introduces a gl_pbo_upload_tex() function, which works almost like
our gl_upload_tex() glTexSubImage2D() wrapper, except it takes a struct
which caches the PBO handles. It also takes the full texture size (to
make allocating an ideal buffer size easier), and a parameter to disable
PBOs (so that the caller doesn't have to duplicate the gl_upload_tex()
call if PBOs are disabled or unavailable).

This also removes warnings and fallbacks on PBO failure. We just
silently try using PBOs on every frame, and if that fails at some point,
revert to normal texture uploads. Probably doesn't matter.
2016-07-03 16:34:32 +02:00
James Ross-Gowan 06219c7f88 w32_common: make WM_NCHITTEST simpler and more accurate
This makes the geometry of the sizing borders more like the ones in
Windows 10. It also fixes an off-by-one error that made the right and
bottom borders thinner than the left and top borders, which made it
difficult to resize the window when using the Windows 7 classic theme
(because it has pretty thin sizing borders to begin with.)
2016-07-03 21:58:29 +10:00
wm4 5d47f9a565 manpage: document confusing "vf clr" command usage 2016-07-03 13:45:18 +02:00
wm4 1298c29dc7 player: add missing space to error message 2016-07-02 18:26:55 +02:00
Ben Boeckel 76a73a0a5d vd_lavc: hide structs behind platform flags
Otherwise, warnings about them being unused appear.
2016-07-01 19:12:34 -04:00
Ben Boeckel b2ce00ed56 readme: fix typo 2016-07-01 19:12:26 -04:00
wm4 d057e7a142 player: fatal error if linked and compiled FFmpeg versions mismatch
We don't support this anymore.

This tries to exit in a controlled way after command line options are
applied in order to honor logging options and, in case of libmpv, not to
kill the host. Not sure if it would be better to just vomit text to
stderr and call abort().
2016-07-01 20:56:59 +02:00
wm4 3738bfb451 bitmap_packer: remove some unused functions 2016-07-01 20:29:45 +02:00
wm4 8523e1fd95 sub: set ASS sub bitmap data to correct pointer
Point it to the copied data. Doesn't really matter at this point, but
later it might have left dangling pointers.
2016-07-01 20:28:49 +02:00
wm4 fd5098a409 vo_direct3d: remove bitmap packer
See previous comments.
2016-07-01 20:28:49 +02:00
wm4 c0f272fcd1 vo_vdpau: remove bitmap packer use
See previous commit.
2016-07-01 20:28:49 +02:00
wm4 1b71cfccba vo_opengl: remove OSD bitmap packing
It's packed in the OSD common layer already.
2016-07-01 20:28:49 +02:00
wm4 549a9ea6fa command: pack sub image data in overlay-add command
Working towards refcounted sub images, and also for removing bitmap
packers from VOs.

I'm not sure why we even have this overlay-add command. It was sort of
"needed" before opengl-cb was introduced, and before Lua scripts could
put ASS drawings on OSD without conflicting with the OSC. But now trying
to use it doesn't make too much sense anymore.

Still keep it because we're trying to be nice, but throw performance out
of the window. Now image data is copied 2 more times before displaying
it. This also makes using the command a bit simpler.
2016-07-01 20:22:09 +02:00
wm4 614efea3e6 ad_lavc: work around braindead ffmpeg behavior
The libavcodec wmapro decoder will skip some bytes at the start of the
first packet and return each time. It will not return any audio data in
this state.

Our own code as well as libavcodec's new API handling
(avcodec_send_packet() etc.) discard the PTS on the first return, which
means the PTS is never known for the first packet. This results in a
"Failed audio resync." message.

Fixy it by remember the PTS in next_pts. This field is used only if the
decoder outputs no PTS, and is updated after each frame - and thus
should be safe to set.

(Possibly this should be fixed in libavcodec new API handling by not
setting the PTS to NOPTS as long as no real data has been output. It
could even interpolate the PTS if the timebase is known.)

Fixes the failure message seen in #3297.
2016-07-01 15:51:34 +02:00
wm4 c57304a591 sub: pack libass bitmaps directly in sd_ass.c and osd_libass.c
Change all producer of libass images to packing the bitmaps into a
single larger bitmap directly when they're output. This is supposed to
help working towards refcounted sub bitmaps.

This will reduce performance for VOs like vo_xv, but not for vo_opengl.
vo_opengl simply will pick up the pre-packed sub bitmaps, and skip
packing them again. vo_xv will copy and pack the sub bitmaps
unnecessarily - but if we want sub bitmap refcounting, they'd have to be
copied anyway.

The packing code cannot be removed yet from vo_opengl, because there are
certain corner cases that still produce unpackad other sub bitmaps.
Actual refcounting will also require more work.
2016-06-30 21:38:50 +02:00
wm4 2d6da37b6b README: declare that we do not respect FFmpeg ABI rules 2016-06-29 21:16:42 +02:00
wm4 e40851ea22 options: deprecate --heartbeat-cmd
It's useless. --heartbeat-interval is also considered deprecated, but
this is not made explicit.
2016-06-29 18:10:15 +02:00
wm4 9ed5dae480 options: add a deprecation warning printing mechanism
We have a warning mechanism for removed and for replaced options, but
none yet for options which have been simply deprecated.

For the following commit.

(Fun fact: just adding the m_option field increases binary size by
14KB.)
2016-06-29 18:09:30 +02:00
wm4 c6953bfa8c ao_oss: do not add an entry to audio-device-list if device file missing
This effectively makes it go away on Linux (unless you have OSS
emulation loaded).
2016-06-29 17:40:04 +02:00
wm4 deb1c3c7a8 audio: don't add default entry to audio-device-list if AO support listing
In such cases there isn't really a reason to do so, and using such an
entry would probably fail anyway.

Also convenient for the following commit.
2016-06-29 17:38:57 +02:00
wm4 9ca1592f3f d3d: implement screenshots for --hwdec=d3d11va
No method of taking a screenshot was implemented at all. vo_opengl
lacked window screenshotting, because ANGLE doesn't allow reading the
frontbuffer. There was no way to read back from a D3D11 texture either.

Implement reading image data from D3D11 textures. This is a low-quality
effort to get basic screenshots done. Eventually there will be a better
implementation: once we use AVHWFramesContext natively, the readback
implementation will be in libavcodec, and will be able to cache the
staging texture correctly. Hopefully. (For now it doesn't even have a
AVHWFramesContext for D3D11 yet. But the abstraction is more appropriate
for this purpose.)
2016-06-28 20:38:53 +02:00
wm4 17c5738cb4 d3d: merge angle_common.h into d3d.h
OK, this was dumb. The file didn't have much to do with ANGLE, and the
functionality can simply be moved to d3d.c. That file contains helpers
for decoding, but can always be present (on Windows) since it doesn't
access any D3D specific libavcodec APIs. Thus it doesn't need to be
conditionally built like the actual hwaccel wrappers.
2016-06-28 20:07:56 +02:00
Muhammad Faiz d5615102d5 vo_opengl: add output_size uniform to custom shader
logically, scaler should know its input and output size

Signed-off-by: wm4 <wm4@nowhere>
2016-06-28 19:52:55 +02:00
wm4 40c9b38023 vo_opengl: minor typo and coding style fixes 2016-06-28 19:48:29 +02:00
Niklas Haas dc9a5cbfd7 vo_opengl: revise the transfer curve logic
Instead of hard-coding a big list, move some of the functionality
to csputils. Affects both the auto-guess blacklist and the peak
estimation.

Also update the comments.
2016-06-28 19:48:29 +02:00
Niklas Haas 65499d863a csputils: adjust whitespace
All these blank lines felt sort of weird, especially since the functions
were semantically related.
2016-06-28 19:48:29 +02:00
Niklas Haas 6e6c32ed6c vo_opengl: revise the logic for picking the default color space
Too many "exceptions" these days, it's easier to just hard-code a
whitelist instead of a blacklist. And besides, it only really makes
sense to avoid adaptation for BT.601 specifically, since that's the one
we auto-guess based on the resolution.
2016-06-28 19:48:29 +02:00
Niklas Haas f9fe5d06ad vo_opengl: use image_params instead of *_src for autoconfig
I'm not even sure why we ever consulted *_src to begin with, since that
just describes the current image format - and not the original metadata.
(And in fact, we specifically had logic to work around the impliciations
this had on linear scaling)

image_params is *the* authoritative source on the intended (i.e.
reference) image metadata, whereas *_src may be changed by previous
passes already. So only consult image_params for picking auto-generated
values.

Also, add some more missing "wide gamut" and "non-gamma" curves to the
autoconfig blacklist. (Maybe it would make sense to move this list to
csputils in the future? Or perhaps even auto-detect it based on the
associated primaries)
2016-06-28 19:48:29 +02:00
Niklas Haas f3b6966d14 vo_opengl: implement the Panasonic V-Log function
User request and not that hard. Closes #3157.

Note that FFmpeg doesn't support this and there's no signalling in HEVC
etc., so the only way users can access it is by using vf_format
manually.

Mind: This encoding uses full range values, not TV range.
2016-06-28 19:48:29 +02:00
Niklas Haas 740fdc139f manpage: add missing documentation for vf_format:gamma=dci-p3 2016-06-28 19:48:29 +02:00
Niklas Haas 247ec0cb84 csputils: add Panasonic V-Gamut primaries
This is actually not entirely trivial since it involves negative Yxy
coordinates, so the CMM has to be capable of full floating point
operation. Fortunately, LittleCMS is, so we can just blindly implement
it.
2016-06-28 19:48:29 +02:00
Niklas Haas 13a63331b6 manpage: warn about the use of HDR functions for target-trc
Most devices seems to require special signalling (e.g. via HDMI
metadata) to actually decode HDR signals and treat them as such, so it's
probably worth warning the potential user about the fact that mpv pretty
definitely does *not* set any of this metadata signalling.
2016-06-28 19:48:29 +02:00
Niklas Haas 9278ce98f7 vo_opengl: implement ARIB STD-B68 (HLG) HDR TRC
This HDR function is unique in that it's still display-referred, it just
allows for values above the reference peak (super-highlights). The
official standard doesn't actually document this very well, but the
nominal peak turns out to be exactly 12.0 - so we normalize to this
value internally in mpv. (This lets us preserve the property that the
textures are encoded in the range [0,1], preventing clipping and making
the best use of an integer texture's range)

This was grouped together with SMPTE ST2084 when checking libavutil
compatibility since they were added in the same release window, in a
similar timeframe.
2016-06-28 19:48:29 +02:00
wm4 4ce53025cb audio: add a helper for getting frame end PTS
Although I don't see any use for it yet, why not.
2016-06-27 15:12:21 +02:00
wm4 3e58ce96ac dec_audio: fix segment boudnary switching
Some bugs in this code are exposed by e.g. playing lossless audio files
with --ad-lavc-threads=16. (libavcodec doesn't really support threaded
audio decoding, except for lossless files.) In these cases, a major
amount of audio can be buffered, which makes incorrect handling of this
buffering obvious.

For one, draining the decoder can take a while, so if there's a new
segment, we shouldn't read audio.

The segment end check was completely wrong, and used the start value.
2016-06-27 15:12:21 +02:00
Rudolf Polzer acb74236ac ao_lavc, vo_lavc: Migrate to new encoding API.
Also marked some places for possible later refactoring, as they became
quite similar in this commit.
2016-06-27 08:33:12 -04:00
stepshal c5094206ce Fix misspellings 2016-06-26 13:47:21 +02:00
quilloss 24478a8a72 vo_opengl utils: use gl->main_fb when reading window content
The main framebuffer is not the default framebuffer for the dxinterop
backend. Bind the main framebuffer and use the appropriate attachment
when reading the window content.

Fix #3284
2016-06-26 13:17:39 +02:00
wm4 e081e46950 manpage: fix typo 2016-06-26 12:33:16 +02:00
wm4 22c76e85db vo_xv: fix behavior with odd sizes
The size check introduced in commit d941a57b did not consider that Xv
can round up the image size to the next chroma boundary. Doing that
makes sense, so it can't certainly be considered server misbehavior.

Do 2 things against this: allow if the server returns a larger image (we
just crop it then), and also allocate a properly aligned image in the
first place.
2016-06-25 12:44:42 +02:00
wm4 d1d864546c DOCS: change version references from 0.17.1 to 0.18.0
0.17.1 was never released, so the actual 0.18.0 release takes its place.
2016-06-25 12:39:08 +02:00
Martin Herkt 69e7b0d3ea Release 0.18.0 2016-06-25 03:23:40 +02:00
Martin Herkt ad56f2c46a Merge branch 'master' into release/current 2016-06-25 02:25:44 +02:00
wm4 393bb2a565 image_writer: port to new encode API 2016-06-24 18:20:36 +02:00
wm4 ea098d3462 ass_mp.h: remove conditional inclusion guards
This file is only used when libass is enabled. (It used to be different,
when code was more entangled.)
2016-06-24 18:05:34 +02:00
wm4 1c3bbd9318 af_lavcac3enc: use av_err2str() call (fixes Libav build)
I added this call because I thought it'd be nice, but Libav doesn't have
this function (macro, actually).
2016-06-23 12:41:41 +02:00
wm4 e911e208b8 af_lavcac3enc: make encoder configurable 2016-06-23 12:14:45 +02:00
wm4 5c74da4503 af_lavcac3enc: implement flushing on seek
There's a lot of data that could have been buffered, and which has to be
discarded.
2016-06-23 12:07:05 +02:00
wm4 c071c30bcd af_lavcac3enc: port to new encode API 2016-06-23 12:04:04 +02:00
wm4 b01855714b af_lavcac3enc: automatically configure most encoder parameters
Instead of hardcoding what the libavcodec ac3 encoder expects, configure
it based on the AVCodec fields.

Unfortunately, it doesn't export the list of sample rates, so that is
done manually. This commit actually fixes the rate always to 48Khz. I
don't even know whether the other rates worked. (Possibly did, but
they'd still change the spdif parameters, and would work differently
from ad_spdif.c.)
2016-06-23 12:02:36 +02:00
wm4 5a60f594e5 af_lavcac3enc: drop log message prefixes
MPlayer leftover. They're already added by the logging code.
2016-06-23 10:45:56 +02:00
wm4 31b73d5ca0 af_lavcac3enc: fix custom bitrates
Probably has been broken for ages.

(Not sure why anyone would use this feature, though.)
2016-06-23 10:43:54 +02:00
wm4 b753c229f7 vo_opengl: improve missing function warning
Mostly a cosmetic change. Handling bultin and extension functions
separaterly makes more sense here too.
2016-06-22 21:55:00 +02:00
wm4 7ea22fe889 ad_lavc: resume from mid-stream EOF conditions with new decode API
Workaround for an awful corner-case. The new decode API "locks" the
decoder into the EOF state once a drain packet has been sent. The
problem starts with a file containing a 0-sized packet, which is
interpreted as drain packet.

This should probably be changed in libavcodec (not treating 0-sized
packets as drain packets with the new API) or in libavformat (discard
0-sized packets as invalid), but efforts to do so have been fruitless.

Note that vd_lavc.c already does something similar, but originally for
other reasons.

Fixes #3106.
2016-06-22 21:37:36 +02:00
dirb 9d0af06811 vo_opengl: add scaler name to the 'Disabling scaler' message
Print to the user the name of the scaler that gets disabled rather than
just printing its number.
2016-06-22 18:16:43 +02:00
wm4 6f9973618c vf_vdpaurb: use new common nv12 download code
See previous commit. (The mixing case was never supported, so this has
equivalent functionality.)

This also implicitly fixes a bug: the old code allocated image data for
the cropped surface size only, which means the
video_surface_get_bits_y_cb_cr call could write beyond the allocated
image memory.
2016-06-21 21:44:13 +02:00
wm4 b40d8fdfa3 vdpau: get surface data as nv12 if possible
For now, this affects taking screenshots only.

If the video mixer is actually needed, we want to go through the video
mixer for screenshots too - which is why this function simply always
used the video mixer, and then copied the surface to RAM as RGBA.

Add reading the surface as nv12 if possible. If the format is correct,
and no special video processing (like deinterlacing) is used, then it's
read directly without going through the video mixer.

There's no particular reason for doing this, other than avoiding the
video mixer (like vo_opengl can do it now). Also, the next commit will
make use of this in vf_vdpaurb.c.
2016-06-21 21:31:58 +02:00
wm4 22291a2587 command: improve playlist* properties change notifications
Until now, only the "playlist" property itself had proper change
notification. Extend it to all other properties as well.

Fixes #3267 (hopefully).
2016-06-20 21:35:59 +02:00
wm4 fc50f3772c github: move "reproduction steps" before behavior sections 2016-06-20 20:06:54 +02:00
Floens 65280e47cd vo_opengl: manually add the GL_BACK_LEFT constant for GLES
GLES doesn't have this constant. It's not used on GLES.
I'm starting to think we need some better way to do this.
2016-06-20 19:24:42 +02:00
Floens 30adf280fd vo_opengl: GL_ARB_timer_query compile fix for GLES
The GL_ARB_timer_query extension and thus the GL_TIME_ELAPSED constant
don't exist for GLES.
For ES the EXT_disjoint_timer_query is used so take the constant from
that else provide the constant manually.
See pr #3216 which introduced this error.
2016-06-20 19:24:42 +02:00
wm4 9bac0ea421 vf_vdpaurb: fix operation
The hw_subfmt field remained set, while it has to be unset for non-hwdec
formats.
2016-06-20 19:10:58 +02:00
wm4 761eeacf54 vo_opengl: unmap hwdec images once rendering is done
Instead of keeping them for a while. While keeping the mapping was
perfectly ok, nothing speaks against reducing the time they're mapped.
2016-06-20 13:57:46 +02:00
wm4 7be37337f4 vo_opengl: vdpau interop without RGB conversion
Until now, we've always converted vdpau video surfaces to RGB, and then
mapped the resulting RGB texture. Change this so that the surface is
mapped as NV12 plane textures.

The reason this wasn't done until now is because vdpau surfaces are
mapped in an "interlaced" way as separate fields, even for progressive
video. This requires messy reinterleraving. It turns out that even
though it's an extra processing step, the result can be faster than
going through the video mixer for RGB conversion.

Other than some potential speed-gain, doing this has multiple other
advantages. We can apply our own color conversion, which is important in
more complex cases. We can correctly apply debanding and potentially
other processing that requires chroma-specific or in-YUV handling.

If deinterlacing is enabled, this switches back to the old RGB
conversion method. Until we have at least a primitive deinterlacer in
vo_opengl, this will stay this way. The d3d11 and vaapi code paths are
similar. (Of course these don't require any crazy field reinterleaving.)
2016-06-19 19:58:40 +02:00
wm4 754ad1d730 refqueue: free referenced images on free
Otherwise stale references will survive forever. Could leak hardware
video surfaces.

In particular, the mpv vdpau code crashed with an assertion when exiting
after toggling deinterlacing, because not all references were released.
2016-06-19 19:52:49 +02:00
wm4 0cf187caca bitmap_packet: let max=0 mean unlimited
And remove the strange PACKER_MAX_WH define. This is more convenient for
users which don't care about limits, such as sd_lavc.c.
2016-06-18 19:31:23 +02:00
wm4 07c11656e3 sd_lavc: fix sub-bitmap alignment
Ooops.
2016-06-18 19:30:38 +02:00
Bin Jin 67a6203ce0 vo_opengl: remove prescaling framework with superxbr prescaler
Signed-off-by: wm4 <wm4@nowhere>
2016-06-18 19:17:28 +02:00
Bin Jin 3df95ee57a vo_opengl: remove uniform buffer object routines 2016-06-18 19:16:31 +02:00
Bin Jin 61bc96518a vo_opengl: remove nnedi3 prescaler 2016-06-18 19:16:27 +02:00
Akemi 47d9fbd133 cocoa: fix display refresh rate retrieval on multi monitor setups
1. this basically reverts commit de4c74e5a4.
even with CVDisplayLinkCreateWithActiveCGDisplays and
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext we still have to
explicitly set the current display ID, otherwise it will just always
choose the display with the lowest refresh rate. another weird thing is,
we still have to set the display ID another time with
CVDisplayLinkSetCurrentCGDisplay after the link was started. otherwise
the display period is 0 and the fallback will be used.
if we ever use the callback method for something useful it's probably
better to use CVDisplayLinkCreateWithActiveCGDisplays since we will need
to keep the display link around instead of releasing it at the end.
in that case we have to call CVDisplayLinkSetCurrentCGDisplay two times,
once before and once after LinkStart.
2. add windowDidChangeScreen delegate to update the display refresh rate
when mpv is moved to a different screen.
2016-06-18 19:15:36 +02:00
Akemi fb7c5804bb cocoa: fix actual display refresh rate retrieval
We have two problems here.
1. CVDisplayLinkGetActualOutputVideoRefreshPeriod, like the name suggests,
returns a frame period and not a refresh rate. using this as screen_fps
just leads to a slideshow. why didn't this break video playback on OS X
completely? the answer to this leads us to the second problem.
2. it seems that CVDisplayLinkGetActualOutputVideoRefreshPeriod always
returns 0 if used without CVDisplayLinkSetOutputCallback and hence always
fell back to CVDisplayLinkGetNominalOutputVideoRefreshPeriod. adding a
callback to CVDisplayLink solves this problem. the callback function at
this moment doesn't do anything but could possibly used in the future.
2016-06-18 19:15:34 +02:00
James Ross-Gowan 0fd5a24ecb vo_opengl: dxinterop: render to gl->main_fb
This can also remove all the stuff for lazily attaching the texture. It
doesn't matter if the dxinterop backend changes the bound framebuffer
during a VOCTRL, since the renderer does not rely on the GL state being
preserved.
2016-06-18 23:51:57 +10:00
wm4 4a15bc6d73 vo_opengl: add ability to render to an arbitrary backing framebuffer
Most of the functionality already exists for the sake of vo_opengl_cb.
We only have to use it.

This will be used by dxinterop in the following commit.
2016-06-18 15:16:29 +02:00
wm4 9215a9e598 sd_lavc: align sub-bitmaps for the sake of libswscale
Since there are not many sub-rectangles, this doesn't cost too much. On
the other hand, it avoids frequent warnings with vo_xv.

Also, the second copy in mp_blur_rgba_sub_bitmap() can be dropped.
2016-06-18 12:08:17 +02:00
wm4 689cf04571 sd_lavc: fix typo 2016-06-18 10:49:41 +02:00
wm4 8e6704acdb sub, vo_opengl: use packed sub-bitmaps directly if available
The previous few commits changed sd_lavc.c's output to packed RGB sub-
images. In particular, this means all sub-bitmaps are part of a larger,
single bitmap. Change the vo_opengl OSD code such that it can make use
of this, and upload the pre-packed image, instead of packing and copying
them again.

This complicates the upload code a bit (4 code paths due to messy PBO
handling). The plan is to make sub-bitmaps always packed, but some more
work is required to reach this point. The plan is to pack libass images
as well. Since this implies a copy, this will make it easy to refcount
the result.

(This is all targeted towards vo_opengl. Other VOs, vo_xv, vo_x11, and
vo_wayland in particular, will become less efficient. Although at least
vo_vdpau and vo_direct3d could be switched to the new method as well.)
2016-06-17 23:15:50 +02:00
wm4 28c7dec157 sd_lavc: change hack against vobsubs with wrong resolution
The sub-bitmaps get extended by --sub-gauss, so we have to compute the
bounding box on the original subs. Not sure if this is really
eqauivalent to what the code did before, and I don't have the sample
anymore. (But this approach sure is a _shitty_ hack.)
2016-06-17 23:15:39 +02:00
wm4 56058a95e5 sub: fix --sub-gauss
Implement it directly in sd_lavc.c as well. Blurring requires extending
the size of the sub-images by the blur radius. Since we now want
sub_bitmaps to be packed into a single image, and we don't want to
repack for blurring, we add some extra padding to each sub-bitmap in the
initial packing, and then extend their size later. This relies on the
previous bitmap_packer commit, which always adds the padding in all
cases.

Since blurring is now done on parts of a large bitmap, the data pointers
can become unaligned, depending on their position. To avoid shitty
libswscale printing a dumb warning, allocate an extra image, so that the
blurring pass is done on two newly allocated images. (I don't find this
feature important enough to waste more time on it.)

The previous refactor accidentally broke this feature due to a logic bug
in osd.c. It didn't matter before it happened to break, and doesn't
matter now since the code paths are different.
2016-06-17 23:14:26 +02:00
wm4 f72eb5b394 sub: move paletted image handling completely to sd_lavc.c
Until now, subtitle renderers could export SUBBITMAP_INDEXED, which is a
8 bit per pixel with palette format. sd_lavc.c was the only renderer
doing this, and the result was converted to RGBA in every use-case
(except maybe when the subtitles were hidden.)

Change it so that sd_lavc.c converts to RGBA on its own. This simplifies
everything a bit, and the palette handling can be removed from the
common code.

This is also preparation for making subtitle images refcounted. The
"caching" in img_convert.c is a PITA in this respect, and needs to be
redone. So getting rid of some img_convert.c code is a positive side-
effect. Also related to refcounted subtitles is packing them into a
single mp_image. Fewer objects to refcount is easier, and for the libass
format the same will be done. The plan is to remove manual packing from
the VOs which need single images entirely.
2016-06-17 23:13:14 +02:00
wm4 454fff39ad bitmap_packer: make manual use slightly more convenient
Apply the padding internally to each input bitmap, instead of requiring
this for the semi-public API.

Right now, everything still uses packer_pack_from_subbitmaps() to fill
the input bitmap sizes, but that's going to change with the following
commit. Since bitmap_packer.in is mutated during packing anyway, it's
more convenient to add the padding automatically.

Also, guarantee that every sub-bitmap has a padding border around it.
Don't let the padding overlap. Add padding even on the containing
borders.

This is simpler, doesn't cost much in memory usage, and is convenient
for one of the following commits.
2016-06-17 23:12:43 +02:00
wm4 8986b37fe7 sd_lavc: move AVSubtitle bitmap setup code into its own function
No functional changes.
2016-06-17 23:12:34 +02:00
wm4 d0bd39eb90 Add github issue and pull request templates
I do not understand why github requires adding this crap to source code
repositories themselves, instead of making them part of the repository
configuration. Remove CONTRIBUTING.md to compensate for github crap
accumulating.
2016-06-17 16:16:03 +02:00
wm4 7ecac3ae6f d3d11va: remove unused d3d11va_surface.subindex field
This is now stored within the AVFrame/mp_image.
2016-06-16 18:13:46 +02:00
wm4 a6074a3375 vf_d3d11vpp: flush device context only when using shared textures
Reduces interference with pass-through case, where this is not needed.
2016-06-16 17:29:53 +02:00
wm4 36f8d41702 vf_d3d11vpp: make missing deinterlacing caps non-fatal
Instead, warn.
2016-06-16 17:17:54 +02:00
wm4 1878a4655d vf_d3d11vpp: log some video processor creation parameters 2016-06-16 16:34:51 +02:00
James Ross-Gowan 5700da4a8f vo_opengl: use EXT_disjoint_timer_query for timers
This is the ES equivalent to ARB_timer_query. It enables the performance
timers on ANGLE. All the added functions should be identical in
semantics to their desktop GL equivalents.
2016-06-15 20:32:47 +10:00
wm4 43e964e2d6 vo_opengl: fix framebuffer object name
The OpenGL 3.0+ and ES specs are quite clear on what values are
accepted for the attachment object name parameter. And there's no
overlap for the default framebuffer. Sigh.

Probably fixes Mesa raising an error in this case and might fix #3251.
Regression by the previous vo_opengl change.
2016-06-15 00:55:27 +02:00
wm4 a30e727266 demux_mkv: support Matroska webvtt
They're different from the Google/WebM subtitle types, and use a new
codec ID.

Fixes #3247.
2016-06-14 16:43:07 +02:00
wm4 788929e4e0 vo_opengl: use standard functions to retrieve display depth
Until now, we've used system-specific API (GLX, EGL, etc.) to retrieve
the depth of the default framebuffer. (We equal this to display depth
and use the determined depth for dithering.)

We can actually retrieve this value through standard GL API, and it
works everywhere (except GLES 2 of course). This simplifies everything a
great deal.

egl_helpers.c is empty now. But I expect that some EGL boilerplate will
be moved to it, so don't remove it yet.
2016-06-14 10:35:43 +02:00
wm4 3682df2dd5 vo_opengl: hwdec_d3d11egl: remove ES2 swizzle special-case
This was somehow done under the assumption that ANGLE would somehow
always use RG in ES2 mode. But there's no basis for this. Even if ANGLE
supports NV12 textures with drivers that do not allow for texture_rg,
this cas eis too obscure to worry about. So do the robust and correct
thing instead, and disable this code if texture_rg is not available.
2016-06-13 16:15:57 +02:00
Gusar321 81ec9cf596 vo_rpi: fix destroying overlays
Commit 74e3d11 resulted in the background overlay not getting destroyed
when mpv quits. Add back a piece of code that was removed in that commit
to restore correct functionality.

Fixes issue #3100
2016-06-13 14:48:11 +02:00
wm4 b00eab525a audio: apply an upper bound timeout when draining
This helps with shitty APIs and even shittier drivers (I'm looking at
you, ALSA). Sometimes they won't send proper wakeups. This can be fine
during playback, when for example playing video, because mpv still will
wakeup the AO outside of its own wakeup mechanisms when sending new data
to it. But when draining, it entirely relies on the driver's wakeup
mechanism. So when the driver wakeup mechanism didn't work, it could
hard freeze while waiting for the audio thread to play the rest of the
data.

Avoid this by waiting for an upper bound. We set this upper bound at the
total mpv audio buffer size plus 1 second. We don't use the get_delay
value, because the audio API could return crap for it, and we're being
paranoid here. I couldn't confirm whether this works correctly, because
my driver issue fixed itself.

(In the case that happened to me, the driver somehow stopped getting
interrupts. aplay froze instead of playing audio, and playing audio-only
files resulted in a chop party. Video worked, for reasons mentioned
above, but drainign froze hard. The driver problem was solved when
closing all audio output streams in the system. Might have been a dmix
related problem too.)
2016-06-12 21:05:10 +02:00
wm4 972ea9ca59 audio: do not wake up core during EOF
When we're draining, don't wakeup the core on every buffer fill, since
unlike during normal playback, we won't actually get more data. The
wakeup here conceptually works like wakeups with condition variables, so
redundant wakeups do not hurt, so this is just a minor change and
nothing of consequence.

(Final EOF also requires waking up the core, but there is separate code
to send this notification.)

Also dump the p->still_playing field in trace logging.
2016-06-12 20:59:11 +02:00
Bin Jin 3d844cddf8 vo_opengl: make size of OUTPUT available to user shaders 2016-06-12 17:51:50 +02:00
wm4 0b082b2086 player: fix previous commit
Of course we can't just skip updating the OSD if the playloop was woken
up for the purpose of removing OSD after an OSD timer expired.

Fixes e.g. OSD bars sometimes sticking along when seeking while paused.
2016-06-12 12:52:35 +02:00
wm4 bb9aad097a player: do not update OSD all the time when paused
Normally, OSD is updated every time the playloop is run. This has to be
done, because the OSD may implicitly reference various properties,
without knowing whether they really need to be updated or not. (There's
a property update mechanism, but it's mostly unavailable, because OSD is
special-cased and can not use the client API mechanism properly.)

Normally, these updates are no problem, because the OSD is only actually
printed when the OSD text actually changes.

But commit d23ffd24 added a rate-limiting mechanism, which tries to
limit OSD updates at most every 50ms (or the next video frame). Since it
can't know in advance whether the OSD is going to change or not, this
simply waked up the player every 50ms.

Change this so that the player is updated only as part of general
updates determined through mp_notify(). (This function also notifies the
client API of changed properties.) The desired result is that the player
will not wake up at all in normal idle mode, but still update properties
that can change when paused, such as the cache.

This is mostly a cosmetic change (in the sense of making runtime
behavior just slightly better). It has the slightly more negative
consequence that properties which update implicitly (such as "clock")
will not update periodically anymore.
2016-06-11 18:40:08 +02:00
James Ross-Gowan 9fcc517cee win32: use HINST_THISCOMPONENT
This is a common idiom used in MSDN docs and Raymond Chen's example
programs to get a HINSTANCE for the current module, regardless of
whether it's an .exe or a .dll. Using GetModuleHandle(NULL) for this is
technically incorrect, since it always gets a handle to the .exe, even
when the executing code (in libmpv) is running in a .dll. In this case,
using the wrong HINSTANCE could cause namespace issues with window
classes, since CreateWindowEx uses the HINSTANCE to search for the
matching window class name.

See:
https://blogs.msdn.microsoft.com/oldnewthing/20050418-59/?p=35873
https://blogs.msdn.microsoft.com/oldnewthing/20041025-00/?p=37483
2016-06-11 15:35:17 +02:00
Stefano Pigozzi de4c74e5a4 cocoa: use displaylink without manually tracking the display id
Maybe it partially helps with #2392 (on dual display setups). Either way, it
makes the code simpler.
2016-06-11 11:58:07 +02:00
Rudolf Polzer 9cc5507079 vo_sdl: fix pixel formats.
There were two mistakes:

- SDL's RGB565 is always equivalent to ffmpeg's RGB565 (both are packed 16bit
  native-endian integers in RGB=565 form) - this was wrongly reversed on
  big endian platforms.
- SDL's RGB888 doesn't actually mean RGB24, but XRGB8888 (i.e. 32bit
  packed integer, top 8 bits unused).
- Use RGB0 not RGBA when there is no alpha.
2016-06-10 16:30:12 -04:00
wm4 bea2e39721 vo_opengl: request core profile on X11/EGL too
Avoids that some OpenGL implementation will pin it to 3.0.
2016-06-10 20:31:28 +02:00
Bin Jin 2b1656b1ac vo_opengl: increase the size limit for cached file
This is mainly for the nnedi3 user shader. With all whose NN weights
hardcoded into the shader source code, the shader file could be as
large as 300 kB.
2016-06-10 17:08:54 +02:00
wm4 1c5fd2d901 Revert "wscript: Require recent FFmpeg by default"
This reverts commit b51957fab5.

Breaks big time. It appears to ignore explicitly configured paths within
the libav* .pc files, which for example breaks mpv-build.
2016-06-09 21:05:33 +02:00
wm4 d38d26057a vo_opengl: hwdec_d3d11eglrgb: remove some more unused fields
Not sure what/if I was thinking there.
2016-06-09 18:43:40 +02:00
wm4 262ceca731 vo_opengl: fix d3d11 hardware decoding probing on Windows 7
Although D3D11 video decoding is unuspported on Windows 7, the
associated APIs almost work. Where they fail is texture creation, where
we try to create D3D11_BIND_DECODER surfaces. So specifically try to
detect this situation.

One issue is that once the hwdec interop is created, the damage is done,
and it can't use another backend (because currently only 1 hwdec backend
is supported). So that's where we prevent attempts to use it.

It still can fail when trying to use d3d11va-copy (since that doesn't
require an interop backend), but at that point we don't care anymore -
dxva2(-copy) is tried before that anyway.
2016-06-09 11:18:36 +02:00
wm4 6fd7f5a111 vo_opengl: hwdec_d3d11eglrgb: remove unused fields
Leftovers.
2016-06-09 10:51:04 +02:00
Martin Herkt b51957fab5 wscript: Require recent FFmpeg by default
Distros and users alike should be made aware of the fact that old
FFmpeg versions are bad. When users come to us with FFmpeg-related
trouble, the answer is “update FFmpeg” more often than not
(and no further support will be provided until they have done so),
so instead we just nag them about it here.
2016-06-09 01:41:53 +02:00
wm4 4123c9642d vo_opengl: hwdec_vdpau: remove minor code duplication
Move unmap() to the top of the function, and replace some duplicated
code with a call to it.
2016-06-08 22:16:32 +02:00
Niklas Haas ff37d7efec vo_opengl: refactor performance data properties
Instead of having 9 different properties, requiring 18 different
VOCTRLs to read them all, they are now exposed as a single property.
This is not only cleaner (since they're all together) but also allows
querying all 9 of them with only a single VOCTRL (by using
mp.get_property_native).

(The extra factor of 2 was due to an extra query being needed to get the
type, which is now also unnecessary)

This makes it much easier to access performance metrics from within a
lua script, and also makes it easier to just show a readable, formatted
version via show-text.
2016-06-08 22:11:38 +02:00
Niklas Haas 54c48bd801 vo_opengl: make user hook passes optional
User hooks can now use an extra WHEN expression to specify when the
shader should be run. For example, this can be used to only run a chroma
scaling shader `WHEN CHROMA.w LUMA.w <`.

There's a slight semantics change to user shaders: When trying to bind a
texture that does not exist, a shader will now be silently skipped
(similar to when the condition is false) instead of generating an error.

This allows shader stages to depend on an optional earlier stage without
having to copy/paste the same condition everywhere.

(In other words: there's an implicit condition on all of the bound
textures existing)
2016-06-08 20:50:19 +02:00
wm4 a15181e5df vo_opengl: do not leak previous FBO when reallocating it
WTF of the day.
2016-06-08 17:49:23 +02:00
James Ross-Gowan b906eb37ed hwdec_d3d11eglrgb: reduce log level when probing
When using --hwdec=auto, systems that don't provide
D3D11_CREATE_DEVICE_VIDEO_SUPPORT, which probably includes all Windows
Vista and 7 systems, will print an error message. Reduce the log level
to verbose when probing and skip the error message entirely if d3d11.dll
is not present.

This commit is in a similar spirit to 991af7d.
2016-06-09 00:24:49 +10:00
wm4 7373158703 vo_opengl: hwdec_d3d11egl: remove broken code on error path
If ID3D11Device_QueryInterface fails, "multithread" will be set to NULL.
The _Release would just make it crash with a null pointer deref.
2016-06-08 12:57:14 +02:00
wm4 69d5be1ee9 player: remove unused return value 2016-06-08 12:04:56 +02:00
wm4 bd9bba40ee player: tell user about --force-seeking if demuxer is not seekable
This comes up often, see e.g. #3220. The issue is that if the stream
input is not seekable, the demuxer is marked as not seekable. But if the
stream cache is enabled, the file still _might_ be seekable to a degree.
We recently disabled seeking in this mode because it can cause very
weird issues, mostly because if stream-layer seeking fails, the demuxers
will arbitrarily misbehave. On the other hand, it can work if the seek
is within the cached range, which is why the user can still enable it
with --force-seeking. There is a weird trade-off between allowing this
and not crapping up too easily, so just informing the user about the
possibility seems best.
2016-06-08 12:02:06 +02:00
wm4 aeb3df0e2c demux_lavf: assume fully read files (subtitles) are always seekable
Since the libavformat API is crap, we have to apply tons of heuristics
to check whether seeking will work. (No, checking it at seek time isn't
going to work either, because if a seek fails, the demuxer will be in an
undefined state. Because the libavformat API is crap.)
2016-06-08 12:02:06 +02:00
stepshal 9c286d7472 waftools: remove trailing newline 2016-06-08 12:01:57 +02:00
wm4 68796fbdf5 demux: fix memory leak when loading of ordered chapter file is aborted 2016-06-07 21:56:09 +02:00
Niklas Haas 5b5db336e9 build: silence -Wunused-result
For clang, it's enough to just put (void) around usages we are
intentionally ignoring the result of.

Since GCC does not seem to want to respect this decision, we are forced
to disable the warning globally.
2016-06-07 14:12:33 +02:00
Niklas Haas 38ac5d5e7b vo_opengl: avoid outputting ultra-wide-gamut by default
The default behavior of vo_opengl has pretty much always been 'show the
source colors as-is, without caring to adapt it to the target device'.
This decision is mostly based on the fact that if we do anything else,
lots of people will complain.

With the rise of content like BT.2020, however, it turns out more people
complain about this content being very desaturated than people complain
about this content not matching VLC - so let's just map ultra-wide gamut
content back down to standard gamut by default.
2016-06-07 12:18:39 +02:00
Niklas Haas 9bd886f449 vo_opengl: also collect upload perfdata for hwdec
Instead of measuring the actual upload time, this instead measures the
time needed to render + map the texture via vdpau. These numbers are
still useful, since they're part of the critical path.
2016-06-07 12:18:05 +02:00
Niklas Haas 393a069112 vo_opengl: expose performance timers as properties
This is plumbed through a new VOCTRL, VOCTRL_PERFORMANCE_DATA, and
exposed as properties render-time-last, render-time-avg etc.

All of these numbers are in microseconds, which gives a good precision
range when just outputting them via show-text. (Lua scripts can
obviously still do their own formatting etc.)

Signed-off-by: wm4 <wm4@nowhere>
2016-06-07 12:17:25 +02:00
Niklas Haas 8ceb935bd8 vo_opengl: add time queries
To avoid blocking the CPU, we use 8 time objects and rotate through
them, only blocking until the last possible moment (before we need
access to them on the next iteration through the ring buffer). I tested
it out on my machine and 4 query objects were enough to guarantee
block-free querying, but the extra margin shouldn't hurt.

Frame render times are just output at the end of each frame, via MP_DBG.
This might be improved in the future. (In particular, I want to expose
these numbers as properties so that users get some more visible feedback
about render times)

Currently, we measure pass_render_frame and pass_draw_to_screen
separately because the former might be called multiple times due to
interpolation. Doing it this way gives more faithful numbers. Same goes
for frame upload times.
2016-06-07 12:16:15 +02:00
James Ross-Gowan 88b584656d dxva2: remove dead code in failure case
This was made unnecessary by a02d77b, since the only way the function
could fail was by failing to add a reference to the DirectX DLLs.
2016-06-07 18:53:05 +10:00
James Ross-Gowan a9150a49d7 vo_opengl: angle: prevent DXGI hooking Alt+Enter
When ANGLE is using D3D11 and not running in DirectComposition mode,
DXGI will hook the video window's message loop and override Alt+Enter to
trigger a transition to exclusive fullscreen mode (which doesn't even
work with mpv's renderer for some reason.) This behaviour can be
disabled by getting a pointer to the IDXGIFactory associated with the
D3D11 device and calling MakeWindowAssociation with the appropriate
flags.
2016-06-07 18:41:47 +10:00
Kevin Mitchell b3e74f652b ao_wasapi: initialize COM in main thread with MTA
Since the main thread is shared by other things in the player, using STA (single
threaded aparement) may have caused problems. Instead initialize in MTA
(multithreaded apartment).
2016-06-05 16:31:03 -07:00
wm4 c1cb04b6a3 vo_opengl: apply vo-cmdline command incrementally
Instead of implicitly resetting the options to defaults and then
applying the options, they're always applied on top of the current
options (in the same way adding new options to the CLI command line
will).

This does not apply to vo_opengl_cb, because that has an even worse mess
which I refuse to deal with.
2016-06-05 16:56:34 +02:00
wm4 ee337b47be vo_opengl_cb: icc-profile-auto does not and will not work
In theory we could probably make icc-profile-auto a vo_opengl-specific
option, but I won't bother with this. Logging an error is simpler.
2016-06-05 15:00:07 +02:00
wm4 b3a3ed00f0 vo_opengl: possibly update icc profile after changing options
Changing the options can enable icc-profile-auto, and in this case the
profile has to be reteieved again from the system.
2016-06-05 12:21:47 +02:00
wm4 65f5fbc5d4 vo_opengl: somewhat simplify suboption handling mess
Enable m_sub_options_copy() to copy nested sub-options, and also enable
it to create an option struct from defaults. We can get rid of most of
the crap in assign_options() now.

Calling handle_scaler_opt() to get a static allocation for scaler name
is still needed. It's moved to reinit_scaler(), which seems to be a
better place for it. Without it, dangling pointers could be created when
options are changed. (And in fact, this fixes possible dangling pointers
for window.name.) In theory we could create a dynamic copy, but that
seemed even more messy.

Chance of regressions.
2016-06-04 20:48:56 +02:00
wm4 352904fd03 vo_opengl: cleanup icc + runtime option changing behavior
Commit 026b75e7 actually enabled changing icc options at runtime (via
vo_cmdline), but it didn't quite work. In particular, changing the icc-
profile option just kept the old profile, because it was cached
accordingly.

As part of this, change gl_lcms.opts from a struct to a pointer to a
struct. We properly copy it, instead of allowing possibly dangling
strings, like it was done in a working but unclean way before.

Also, reinit the whole rendering chain when the auto icc profile
changes, just like it's done when icc options are changed.
2016-06-04 17:52:10 +02:00
wm4 2dfea67f3b vo_opengl: minor simplification to gl_lcms_set_memory_profile()
Passing the bstr thing as pointer makes no sense. Everywhere else bstr
structs are passed by value because they're so small. Only when it's
supposed to receive a return value they're not.
2016-06-04 14:50:32 +02:00
wm4 a9ffe38aa1 vo_opengl: remove pointless NULL-check
It's never NULL.
2016-06-04 13:44:46 +02:00
wm4 026b75e7f5 vo_opengl: move all icc handling from vo_opengl.c to video.c
Originally, video.c did not access any CMS things (other than lut3d
being set on it), but this has changed. In practice, almost all accesses
to it have moved to video.c. vo_opengl only created it, and set the auto
icc profile path.

Complete the move.

Some things wrt. option handling are a bit fishy. (But when is this not
the case.)

icc-profile-auto was not tested, but the distributed human CI will take
care of it.
2016-06-03 20:35:22 +02:00
wm4 2179879172 vo_opengl: move struct lut3d definition
This was dumb. Also, lcms.h has actually no need to include video.h
besides this and csputils.h (makes it slightly less entangled).
2016-06-03 20:06:29 +02:00
wm4 2d76c145c3 vo_opengl: fix giant memory leaks with icc profiles
Well this was dumb.
2016-06-03 20:03:49 +02:00
wm4 645a0d7791 client API: fully document opengl-cb hardware decoding interop
Document it exhaustively. Most of these issues were basically burried in
the code.
2016-06-01 22:33:36 +02:00
wm4 62acbd795f manpage: update --hwdec=d3d11va remarks 2016-05-31 18:32:06 +02:00
Rostislav Pehlivanov e44882d792 wayland: mark existing dnd entry print as debug rather than an error
It gets printed on every alt+tab or desktop switch under mutter and
weston, and offers no useful information since it's handled by
destroying the previous entry.

Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com>
2016-05-31 11:22:57 +02:00
Rostislav Pehlivanov 29ea6e5e4a wayland: correctly report display refresh rate
This commit will cause the wayland backend and vo to correctly report
the display frame rate. This didn't work as VOCTRL_GET_DISPLAY_FPS was
received way too early, before the window was created (and thus
current_output set).

The VO will now signal VO_EVENT_WIN_STATE after window initialization
and upon a resize.

Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com>
2016-05-31 11:22:55 +02:00
Niklas Haas 68c77d955f vo_opengl: default hdr-tone-mapping to hable
This algorithm works really well. Setting it is a much better
"out-of-the-box" experience than just clipping, which will always look
ugly.

In other words, with this default, users of mpv will just be able to
play HDR content without even realizing it's HDR (pretty much).
2016-05-30 20:17:35 +02:00
Niklas Haas 45c3e0f0d0 vo_opengl: refactor HDR mechanism
Instead of doing HDR tone mapping on an ad-hoc basis inside
pass_colormanage, the reference peak of an image is now part of the
image params (alongside colorspace, gamma, etc.) and tone mapping is
done whenever peak_src != peak_dst.

To get sensible behavior when mixing HDR and SDR content and displays,
target-brightness is a generic filler for "the assumed brightness of SDR
content".

This gets rid of the weird display_scaled hack, sets the framework
for multiple HDR functions with difference reference peaks, and allows
us to (in a future commit) autodetect the right source peak from
the HDR metadata.

(Apart from metadata, the source peak can also be controlled via
vf_format. For HDR content this adjusts the overall image brightness,
for SDR content it's like simulating a different exposure)
2016-05-30 20:17:33 +02:00
Rostislav Pehlivanov 098ff4174c wayland: implement HIDPI support
The wayland protocol exposes scaling done by the compositor to
compensate for small window sizes on small high DPI displays. If the
program ignores the scaling done, what'll happen is the compositor is
going to ask the program to be scaled down by N times the window size and
then it'll upscale the program's surface by N times. The scaling
algorithm seems to be bilinear so the scaling is quite obvious.

This commit sets up callbacks to listen for the scaling factor of each
output and, on rescale events, notifies the compositor that the
surface's scale is what the compositor asked for and changes the
player's surface to the appropriate size, causing no scaling to be done
by the compositor.

Compositors not supporting this interface will ignore the callbacks and do
nothing, keeping program behaviour the same. For compositors supporting
and using this interface (mutter), this will fix the rendering to be pixel
precise as it should be.

Both the opengl wayland backend and the wayland vo have been fixed to support
this. Verified to not break either on weston and mutter.

Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com>
2016-05-30 20:17:26 +02:00
wm4 9009601c2d vf: fix filter auto-insertion
Commit 0348cd08 was too naive/simple, and always inserted the d3d11vpp
filter if any d3d11 output image formats were supported, even if it
makes no sense. For example --vf=format=rgb8 already breaks it.

It needs to take the set of supported input formats into account. the
weird format negotiation makes this hard. As a simple and cheap
solution, make some assumptions about the supported formats of a filter.

I hope to simplify this one day by using another format negotiation
algorithm, but this can probably wait.
2016-05-30 20:03:01 +02:00
wm4 4853eca8c6 mp_image: properly communicate aspect ratio through AVFrame
No idea why this wasn't done before. In particular, this fixes playing
anamorphic video through --lavfi-complex.
2016-05-30 19:12:41 +02:00
wm4 079f67268f mp_image: don't reset pixel aspect with mp_image_set_size()
No reason to do so. See also commit 240ba92b.

Since now many mp_images will never have a pixel aspect ratio set,
redefine a 0/0 aspect ratio to "undefined" instead invalid. This also
brings it more in line with how decoder vs. container aspect ratios are
handled.

Most callers seem to be fine with the new behavior.

mp_image_params_valid() in particular has to be adjusted, or some things
stop working due to mp_images not becoming valid after setting size and
format.
2016-05-30 19:07:22 +02:00
Niklas Haas 15bb05d2fe vo_opengl: add hable tone-mapping algorithm
Developed by John Hable for use in Uncharted 2. Also used by Frictional
Games in SOMA. Originally inspired by a filmic tone mapping algorithm
created by Kodak.

From http://frictionalgames.blogspot.de/2012/09/tech-feature-hdr-lightning.html
2016-05-30 16:58:25 +02:00
Niklas Haas 48015009b7 vo_opengl: rename tone-mapping=simple to reinhard
This is the canonical name for the algorithm. I simply didn't know it
before.
2016-05-30 16:58:22 +02:00
maniak1349 899d3e55b3 w32_common: center window on original window center on video resize
Position the window around the original window center on video size change
(when switching to the next file with different resolution, for example)
instead of keeping the position of its top-left corner fixed.
2016-05-30 16:58:07 +02:00
Ricardo Constantino 256d9d2b89 ytdl: fix brightcove urls 2016-05-30 16:57:43 +02:00
Ilya Tumaykin b1dd3beda9 build: don't install tests, only build them
Considering tests are usually executed right after a successful build,
there's no reason to keep them around for later.
2016-05-29 20:02:47 +02:00
wm4 240ba92bed mp_image: don't lose pixel aspect ratio when setting format
This is quite unexpected. It's caused by mp_image_set_size(), which is
used to update certain fields which can be format-dependent, but which
is actually also supposed to reset the pixel aspect ratio.
2016-05-29 19:00:55 +02:00
wm4 0348cd080f video: remove d3d11 video processor use from OpenGL interop
We now have a video filter that uses the d3d11 video processor, so it
makes no sense to have one in the VO interop code. The VO uses it for
formats not directly supported by ANGLE (so the video data is converted
to a RGB texture, which ANGLE can take in).

Change this so that the video filter is automatically inserted if
needed. Move the code that maps RGB surfaces to its own inteorp backend.
Add a bunch of new image formats, which are used to enforce the new
constraints, and to automatically insert the filter only when needed.

The added vf mechanism to auto-insert the d3d11vpp filter is very dumb
and primitive, and will work only for this specific purpose. The format
negotiation mechanism in the filter chain is generally not very pretty,
and mostly broken as well. (libavfilter has a different mechanism, and
these mechanisms don't match well, so vf_lavfi uses some sort of hack.
It only works because hwaccel and non-hwaccel formats are strictly
separated.)

The RGB interop is now only used with older ANGLE versions. The only
reason I'm keeping it is because it's relatively isolated (uses only
existing mechanisms and adds no new concepts), and because I want to be
able to compare the behavior of the old code with the new one for
testing. It will be removed eventually.

If ANGLE has NV12 interop, P010 is now handled by converting to NV12
with the video processor, instead of converting it to RGB and using the
old mechanism to import that as a texture.
2016-05-29 19:00:55 +02:00
wm4 49f73eaf7b vf_d3d11vpp: add a D3D11 video processor filter
Main use: deinterlacing.

I'm not sure how to select the deinterlacing mode at all. You can
enumate the available video processors, but at least on Intel, all of
them either signal support for all deinterlacers, or none (the latter is
apparently used for IVTC). I haven't found anything that actually tells
the processor _which_ algorithm to use.

Another strange detail is how to select top/bottom fields and field
dominance. At least I'm getting quite similar results to vavpp on Linux,
so I'm content with it for now.

Future plans include removing the D3D11 video processor use from the
ANGLE interop code.
2016-05-28 19:28:08 +02:00
James Ross-Gowan 9eccedf447 vo_opengl: angle: enable DirectComposition
This avoids a copy of the video image and lowers vsync jitter. Since
there are now two options to add to the window_attribs list, it has been
made dynamic.
2016-05-29 01:55:10 +10:00
wm4 9f42760538 vf_vdpaupp: use refqueue helper
This makes vf_vdpaupp use the deinterlacer helper code already used by
vf_vavpp. I nice side-effect is that this also removes some traces of
code originating from vo_vdpau.c, so we can switch it to LGPL.

Extend the refqueue helper with a deint setting. If not set,
mp_refqueue_should_deint() always returns false, which slightly
simplifies vf_vdpaupp. It's of no consequence to vf_vavpp (other than it
has to set it to get expected behavior).
2016-05-27 17:03:00 +02:00
Niklas Haas f8df0528b5 vo_opengl: skip junk before first user shader pass
A lot of real-world shaders start off with comments explaining the usage
or license, generating lots of "empty" passes. This simply change allows
us to skip them, which silences the warning spam and prevents us from
having to store and copy around these empty passes.

It also adds a more useful failure check: Attempting to use a user
shader that doesn't define any passes at all.
2016-05-27 17:03:00 +02:00
Yen Chi Hsuan 72e94941c9 TOOLS/zsh.pl: add .f4v extension in zsh completions 2016-05-27 17:03:00 +02:00
James Ross-Gowan 84fba1df21 vo_opengl: enable color management on GLES
This requires the GL_EXT_texture_norm16 extension and works in ANGLE.
A default precision had to be set for sampler3Ds, otherwise the shaders
would fail to compile.
2016-05-27 23:02:26 +10:00
wm4 ca87e623b5 command: add playlist-pos-1 property
This has often been requested for use on OSD. I don't really like having
such "special" properties, but whatever. Hopefully this will be the only
case.

Untested because I'm too damn lazy.

Fixes #2828.
2016-05-26 18:44:01 +02:00
wm4 306c554376 vo_opengl: fix superxbr shader compilation on ES
ES shaders do not allow implicit conversion from int to float, which
is the most annoying ES anti-feature ever.
2016-05-26 08:21:10 +02:00
wm4 e5f49d9685 vo_opengl: always autoselect ANGLE as backend if available
Remove the opengl-hq option default that caused it not to autoselect
ANGLE (unlike --vo=opengl). Details see commit d5df90a2.

Back then the intention was to use ANGLE by default, since it integrates
much nicer with the Windows compositor (instead of native OpenGL, which
tends to cause crazy glitches). On the other hand, many opengl-hq
capabilities are not available with older ANGLE builds, so it didn't
make any sense to autoselect ANGLE for it.

With the GL_EXT_texture_norm16 extension recently added to ANGLE, it has
essentially reached feature parity to desktop GL for the subset we are
using. (Even the integer texture hack for high bit depth input could be
dropped now.)

It (probably) still does not support nnedi3, due to the weird way the NN
coefficients are imported. Also, it uses half-floats instead of 16 bit
fixed-point textures for technical reasons, which implies about 5 bits
of precision loss. If anyone actually manages to distinguish the two
dithering texture formats in a double-blind test, I will fix it.
2016-05-26 00:07:10 +02:00
wm4 5c9f164caf vf_vavpp: make refqueue logic field-based
Abstracts the annoying framerate-doubling behavior.

Same deal as with refqueue introduction: the code size blows up, but at
least it can be reused for other filters.
2016-05-25 23:51:24 +02:00
wm4 fc18e1df62 vf_vavpp: minor simplification 2016-05-25 23:51:24 +02:00
wm4 68191fdca7 vf_vavpp: simplify update_pipeline() usage
Calling this right at start of filter_ext() also fixes a small
regression from previous commit. The change in reference surfaces due to
the first update_pipeline() with deinterlacing enabled changed behavior
of mp_refqueue_next() and mp_refqueue_has_output(). Since
update_pipeline() was called between those, the frame output logic got
inconsistent, and the first deinterlaced frame was duplicated from the
previous non-deinterlaced frame.

Also reset the number of ref-frames when switching back to non-deint
mode.
2016-05-25 23:51:24 +02:00
wm4 5353571de0 vf_vavpp: use future instead of past PTS to determine field duration
If the deinterlacer separates fields, the framerate must be doubled.
Since we have no stable and reliably framerate anywhere, we've been
calculating it by taking the time halfway to the next frame.

vf_vavpp actually used the past frame to calculate the frame duration,
which is sort of ok, but will skip the 2nd field in a stream (since the
first frame has no past PTS). This is annoying for testing, so use the
future frame PTS instead, which means the last field of the stream will
be dropped instead.
2016-05-25 23:51:24 +02:00
wm4 15a5d33b79 vf_vavpp: move frame handling to separate file
Move the handling of the future/past frames and the associated dataflow
rules to a separate source file.

While this on its own seems rather questionable and just inflates the
code, I intend to reuse it for other filters. The logic is annoying
enough that it shouldn't be duplicated a bunch of times.

(I considered other ways of sharing this logic, such as an uber-
deinterlace filter, which would access the hardware deinterlacer via a
different API. Although that sounds like kind of the right approach,
this would have other problems, so let's not, at least for now.)
2016-05-25 23:51:24 +02:00
wm4 b9cc33de58 win32: pthread: use SRW locks by default
SRW locks are available since Windows Vista. They work essentially like
Linux futexes. In particular, they can be statically initialized, and do
not require deinitialization. This makes them ideal for implementing
PTHREAD_MUTEX_INITIALIZER.

We still need CRITICAL_SECTION for recursive mutexes.
2016-05-24 19:02:22 +02:00
wm4 8ff96f0216 hwdec_d3d11egl: call ID3D11DeviceContext::Flush
This must be called if a texture shared between D3D devices is updated.

Often enough, the shared devices will be the same device, but ANGLE
forces using shared surfaces. I suppose there is no guarantee the driver
will do the expected thing. Internally, the driver could for example not
insert the required barriers before the shared texture is used.
2016-05-24 14:30:15 +02:00
dequis d941a57bd3 vo_xv: Handle incorrect size returned by Xv(Shm)CreateImage
Fixes #320 (which is closed as 'not our problem' but eh)

Relevant xorg bug: https://bugs.freedesktop.org/show_bug.cgi?id=70931

For me this happened when (accidentally) trying to play a 8460x2812 jpg
file with mpv. Like the referenced bug, xvinfo reports "maximum XvImage
size: 8192 x 8192". So the returned XvImage is 8192x2812 and memory
corruption happens.

Only after handling this BadShmSeg X11 errors are shown.
2016-05-24 10:25:39 +02:00
wm4 6bd021e4ee manpage: adjust dxva2 description 2016-05-23 23:46:58 +02:00
wm4 e293e411b5 etc/mpv.conf: add missing comment
The config file is an example, and is not supposed to actually define
anything by default.
2016-05-23 23:41:58 +02:00
wm4 335278b86e manpage: document how hardware decoding might cause quality loss 2016-05-23 22:55:30 +02:00
wm4 c4707cdee6 vo_opengl: fix other minor namespace issues
See previous commit.
2016-05-23 21:27:18 +02:00
wm4 e76aa7e8db vo_opengl: rename glUploadTex, drop unused parameter
Rename it to get out of OpenGL's namespace. The gl_ prefix is used by
other mpv functions, but no OpenGL ones.

The "slice" parameter was never actually used, and all callers passed 0
for it.
2016-05-23 21:27:18 +02:00
wm4 66079048ea vo_opengl: unify PBO and normal OSD texture upload path
The main change is actually that e first copy to a "staging" memory
frame, and then upload this at once. The old non-PBO code called
glTexsubImage2D for each OSD sub-bitmap.

The new non-PBO code path is a bit faster now if there are many small
sub-bitmaps (on Linux/nVidia). It's also a bit simpler, so this is a
win.

(Although I don't particularly appreciate the mixed normal/PBO texture
code.)
2016-05-23 21:27:18 +02:00
wm4 049e3ccb65 vo_opengl: make ES float texture format checks stricter
Some of these checks became pointless after dropping ES 2.0 support for
extended filtering.

GL_EXT_texture_rg is part of core in ES 3.0, and we already check for
this version, so testing for the extension is redundant.

GL_OES_texture_half_float_linear is also always available, at least as
far as our needs go.

The functionality we need from GL_EXT_color_buffer_half_float is always
available in ES 3.2, and we explicitly check for ES 3.2, so reject this
extension if the ES version is new enough.
2016-05-23 21:27:18 +02:00
wm4 80d702dce8 vo_opengl: make PBOs work on GLES 3.x
For some reason, GLES has no glMapBuffer, only glMapBufferRange.

GLES 2 has no buffer mapping at all, and GL 2.1 does not always have
glMapBufferRange. On those PBOs remain unsupported (there's no reason to
care about GL 2.1 without the extension).

This doesn't actually work on ANGLE, and I have no idea why. (There are
artifacts on OSD, as if parts of the OSD data weren't copied.) It works
on desktop OpenGL and at least 1 other ES 3 implementation. Don't enable
it on ANGLE, I guess.
2016-05-23 21:27:18 +02:00
Ben Boeckel afcef4c25b docs: fix some typos 2016-05-23 21:27:18 +02:00
wm4 75f373cc46 vo_opengl: remove unused glDrawBuffer 2016-05-23 21:27:18 +02:00
wm4 cc72a4e8c3 vo_opengl: support framebuffer invalidation
Not sure how much can be gained with this, as we can't use it properly
yet. For now, this is used only before rendering, which probably does
overwhelmingly nothing.

In the future, this should be used after temporary passes, which could
possibly reduce memory usage and even memory bandwidth usage, depending
on the drivers.
2016-05-23 21:27:18 +02:00
wm4 cc4a0571fa vo_opengl: slightly improve logging of loaded extensions
Only log when actual extensions are loaded, never log anything about
builtins.
2016-05-23 21:27:18 +02:00
wm4 c06a92e09e demux_edl: adjust warnings and variable names
Don't warn against unknown sourve length if the segment length is
explicitly provided.

Rename "len" to "end_time", because that's what it actually is.
2016-05-23 15:23:27 +02:00
Ricardo Constantino 4ff2a60632 ytdl_hook: support multi-arc subtitles
While at it, pass durations of segments from ytdl if available.
2016-05-23 15:14:14 +02:00
Josh de Kock 4aa017e301 ao_opensles: remove 32bit audio
It's unsupported by android, and can cause problems when trying to play 32bit audio. Removing 32bit fixes it by forcing 16 bit or 8 bit audio.
2016-05-22 14:31:37 +02:00
maniak1349 c4e8c36071 options: --geometry: center window position after applying size
Center window position after applying W and H parameters of the --geometry
option. Passing valid X and Y values will still override the position.

Fixes #2397.
2016-05-22 14:31:37 +02:00
maniak1349 5a3c299ca1 w32_common: make VOCTRL_SET_UNFS_WINDOW_SIZE resize the window around its center
Before that position of the window top-left corner was remaining the same
when the window was scaled.

Right now VOCTRL_SET_UNFS_WINDOW_SIZE is called only by window-scale. This
change will not affect resizes made by the user (dragging window edge).

Fixes #3164.
2016-05-22 14:31:37 +02:00
maniak1349 364af7c630 w32_common: center window on original window center on resize to fit screen
Center the window on the original window center instead of the screen center
when the window has been resized due to requested window size exceeding the
size of the screen.

If user moved the window, he probably did it for the reason and he probably
don't want it to get back to the center of the screen when he is resizing it
(with window-scale for example).
2016-05-22 14:31:37 +02:00
maniak1349 981048e041 w32_common: update stored client area size on window resize
Properly update stored client area size when the window is resized in
reinit_window_state due to window size exceeding the size of the screen.

This was causing wrong behavior with window-scale - when window size was
becoming too big the window was resized but the video was not.
2016-05-22 14:31:37 +02:00
wm4 035297212a demux_mkv: better resync behavior for broken google-created webms
I've got a broken webm that fails to seek correctly with "--start=0".
The problem is that every index entry points to 1 byte before cluster
start (!!!). demux_mkv tries to resync to the next cluster, but since it
already has read 2 bytes with ebml_read_id(), it doesn't get the first
cluster, but the following one. Actually, it can be any amount of bytes
from 1-4, whatever happens to look valid at this essentially random byte
position.

Improve this by resyncing from the original position, instead of the one
after the EBML element ID has been attempted to be read.

The file shows the following headers:

| + Muxing application: google at 177
| + Writing application: google at 186

Indeed, the file was downloaded with youtube-dl. I can only guess that
Google got it completely wrong.
2016-05-21 16:39:44 +02:00
wm4 79afa347cc vo_opengl: remove non-working rgb/rgba FBO formats
Following commit 84ccebd9, the internal helpers don't allow GL_RGB and
GL_RGBA as internal formats for FBO attachments anymore.

While OpenGL itself is perfectly fine with it, I don't see much of a
reason to bother, and mixing sized and unsized internal formats is
confusing anyway.

Just remove these formats.
2016-05-20 23:21:43 +02:00
wm4 3deedef195 stream: separate posix/win32 cancellation code
This code evolved into an ifdef mess as support for cancellation on
Windows was added. Make the Windows-specific code completely separate.
It looks cleaner, and it also means that some of the posix code is not
uselessly enabled on Windows. The latter made msvcrt.dll output warnings
because it does not like -1 passed as FD to read/write. (The same would
be harmless on POSIX.)
2016-05-20 15:51:50 +02:00
Quentin Glidic f0d7437412 build: Do not link to libGL for egl-drm
Signed-off-by: Quentin Glidic <sardemff7+git@sardemff7.net>
2016-05-20 14:15:44 +02:00
wm4 e431a7bbfd vf_crop: support opaque hardware decoding formats
Cropping usually happens by adjusting the plane start pointers and the
image size. The former is obviously not possible for opaque hwaccel
formats, but the latter must work.

Since the code already takes care of aligning the top/left crop origin
to chroma alignment, simply set the crop origin to 0/0 in the hwaccel
case. Also add a message if such an adjustment happens.

Supporting this isn't worth much; the main usefulness is with debugging.
2016-05-19 22:56:11 +02:00
wm4 05b3a8cd14 vo_opengl: require at least ES 3.0 for float textures
ES 2.0 has this weird rule that not the internalformat parameter
determines the internal format, but the combination of all texture
parameters. GL_OES_texture_half_float thus does not specify e.g. a
GL_RGBA16F format, but requires passing GL_RGBA as format and
GL_HALF_FLOAT_OES as type. We won't bother with this, since ES 2.0 is a
lost cause anyway.

This also removes the OpenGL error when the code is trying to create a
f16 FBO for testing whether FBOs work.
2016-05-19 17:52:09 +02:00
wm4 561630cb01 vo_opengl: change error state handling and fix hwdec crashes on errors
gl_video_upload_image() can fail in the hardware decoding case. In this
case rendering continued "normally", which meant that pass_get_img_tex()
would kill the process with an assertion failure.

Fix this by allowing gl_video_upload_image() to fail, and exit rendering
early enough to skip code which requires an image to be present. (Maybe
this is still a bit too subtle, but better than before.)

Set an error flag, and render the blue screen we introduced for shader
errors. (For this purpose also move the rendering of it to final output,
to ensure it's visible at all.) The error flag is temporary, because the
associated failure might also be temporary, unlike shader compilation
errors.
2016-05-19 12:18:48 +02:00
wm4 4e5f1ec00e vo_opengl: d3d11egl: enable "required" GLSL extensions
ANGLE doesn't handle this very strictly. But if they change this in the
future, it shouldn't brick us.

Not quite happy with this glsl_extensions fields, but it is quite
unintrusive after all.
2016-05-19 12:02:08 +02:00
wm4 b0d3c2ede7 vo_opengl: make gl_sc_enable_extension() permanent/idempotent
No reason not to, and makes the following commit slightly simpler.

In fact, this makes the shaders more correct too. Normally, "#extension"
must come before any normal shader text, including the "precision"
directive. Not sure why this worked before. (Probably didn't.)
2016-05-19 12:01:59 +02:00
wm4 b46eaa3b43 vo_opengl: d3d11egl: enable direct nv12 sampling on ES 3.x
ANGLE was missing texture() overloads in the shader compiler for
GL_TEXTURE_EXTERNAL_OES textures. Support has been added upstream,
so we can use it now.
2016-05-19 10:43:57 +02:00
wm4 5f7bd411fb vo_opengl: remove unused field 2016-05-18 18:22:27 +02:00
wm4 0b911792ca vo_opengl: fix/simplify reinitialization on dynamic reconfiguration
With the new hooks mechanism, user shaders and such are actually loaded
before rendering starts, instead of being loaded during rendering. This
is used to cache them (instead of e.g. reparsing them every frame).

The cached state wasn't cleared correctly in some situations. Namely,
resizing didn't correctly enable/disable prescale hooks.

Reorganize how these reinitializations are handled. Get rid of
reinit_rendering(), whose meaning was pretty unclear. Call the required
functions to reset or recreate state directly wherever they are needed.
2016-05-18 17:47:10 +02:00
wm4 26b6d74484 demux_playlist: recognize m3u8 as playlist extension
Whatever. As mentioned in #3154.
2016-05-17 18:18:00 +02:00
wm4 a02d77ba0d d3d: simplify DLL loading
For some reason, the d3d9/dxva2/d3d11 DLLs are still optional. But we
don't need to try so hard to keep exact references. In fact, there's no
reason to unload them at all.

So load them once in a central place. For simplicity, the d3d9/d3d11
backends both load all DLLs. (They will error out only if the required
DLLs could not be loaded.)

In theory, we could just call LoadLibrary multiple times (without
calling FreeLibrary), but I'm slightly worried that this could be
detected as a "bug", or that the reference count could even have a low
static limit that could be hit soon.
2016-05-17 11:59:54 +02:00
wm4 39b64fb176 video: merge dxva2 source files
video/dxva2.c exported only 2 functions, both used only by
video/decode/dxva2.c.

The same was already done for d3d11.
2016-05-17 11:05:51 +02:00
wm4 9b56bbecdf vo_opengl: hwdec: remove build-dependency on dxva2
wscript builds hwdec_dxva2gldx.c if gl-dxinterop is enabled, while
video/dxva2.c depends on d3d-hwaccel. If d3d-hwaccel is disabled, then
hwdec_dxva2gldx.c will fail to link, because it uses
d3d9_surface_in_mp_image(), defined in dxva2.c.

Fix this by removing the use of this function. It has barely any value
at this point anyway. Just use the libavcodec documented way to get the
surface directly.

Fixes #3150.
2016-05-17 10:59:11 +02:00
wm4 b18a598444 ta: remove old and redundant macro 2016-05-17 10:53:14 +02:00
wm4 a2d58d9986 vo_opengl: move UT_buffer to switch handling
No reason to make it a special case.
2016-05-17 10:48:05 +02:00
wm4 f00040b9fc vo_opengl: make number of cached shaders/uniform dynamic
Use dynamic memory allocation, as the static allocation is starting to
get annoying.

Currently, SC_MAX_ENTRIES is essentially still a static upper limit on
the number of shaders. But in future we could try a more clever cache
replacement strategy, which does not keep stale entries forever if the
maximum happens not to be reached.
2016-05-17 10:45:01 +02:00
wm4 09763bef83 vo_opengl: move cached uniforms to a separate struct 2016-05-17 10:33:45 +02:00
Niklas Haas 8262a4dd52 vo_opengl: increase shader limits
The new uniforms introduced by 362015c have exceeded the uniform limit
when using high-radius tscale. In addition, the SC limit of 32 entries
might be pushing it with user shaders.

Just make these value a bigger to delay the onset of this same failure
mode. Maybe in the future it should be reworked to grow dynamically?
Either way, we *can* always predict a static upper bound on the number
of uniforms and shader cache entries, it's just that we forgot to do so.

Fixes #3151
2016-05-17 10:09:01 +02:00
Niklas Haas ca09cd68c8 DOCS/mplayer-changes: document HDR support
Marketing told me to do so.
2016-05-16 19:29:15 +02:00
Niklas Haas e73c83d3df vo_opengl: skip tonemapping if the output trc is HDR
This makes it so that users with actual HDR displays can just set their
config to target-trc=st2084 and get native HDR output. This will look a
bit silly for SDR content (everything will be really bright), but for
lack of a better tone mapping situation (including reverse tone mapping)
this is the easiest thing to do for now.

Ideally the brightness metadata should be part of the colorspace struct
or something (with mpv always adapting where necessary), but it depends
on the TRC and not the primaries so it's a bit more complicated than
that.
2016-05-16 14:42:45 +02:00
Niklas Haas e6f6ae94f3 vo_opengl: copy over HDR parameters to dumb_mode
Since dumb mode is affected by tone mapping (which I'll call a feature,
not a bug), we need to copy over the configuration - in particular, the
defaults. (To prevent a render failure)
2016-05-16 14:20:48 +02:00
Niklas Haas 3bdbf6274c vo_opengl: fall back to gamma2.2 by default for HDR content
Since HDR content is now auto-detected as such, we should probably do
something smarter in the "no configuration" case, such as outputting
gamma 2.2 instead.

This decision will affect the majority of users of stock configurations
who just play back appropriately tagged HDR files, so having a good
default behavior is important. "Output the HDR content as-is" is
definitely not likely to give the user a good result.
2016-05-16 14:07:39 +02:00
Niklas Haas b6c40953cb csputils: add AVCOL_TRC_SMPTEST2084 support
This now lets us auto-detect appropriately tagged HDR content using
FFmpeg's new TRC entries (when available).

Hidden behind an #if because Libav stable doesn't have it yet.
2016-05-16 13:59:57 +02:00
wm4 887b2cc30f vo_opengl: remove unnecessary casts 2016-05-16 12:58:09 +02:00
wm4 1bc902336a vo_opengl: remove another unneeded allocation 2016-05-16 12:54:45 +02:00
wm4 51307e9f18 vo_opengl: remove possibly undefined behavior 2016-05-16 12:53:45 +02:00
wm4 70df6aa375 vo_opengl: free to-be-added hook on hook array overflow
Seems sensible.

Untested.
2016-05-16 12:51:36 +02:00
wm4 155857dbe6 vo_opengl: never clear file cache
Make it dynamic and never remove entries from it.

For now, this is better than possibly creating dangling pointers all
over the place in the gl_user_shader struct.

Untested.
2016-05-16 12:51:26 +02:00
wm4 0c40eee479 vo_opengl: use proper include statement 2016-05-16 12:44:12 +02:00
wm4 dd99c1e3b4 vo_opengl: remove unnecessary allocation 2016-05-16 12:42:08 +02:00
wm4 56ed5bf1c7 vo_opengl: remove unused global variable
?
2016-05-16 12:41:55 +02:00
wm4 320627d600 manpage: declare user-shader syntax for not stable 2016-05-16 12:41:08 +02:00
wm4 51603e472d vo_opengl: fix bicubic_fast in ES mode
GLES shaders disallow implicit conversion from int to float.

This has been broken for quite a while.
2016-05-16 12:10:47 +02:00
Niklas Haas e047cc0931 vo_opengl: implement more HDR tonemapping algorithms
This is now a configurable option, with tunable parameters.

I got inspiration for these algorithms off wikipedia. "simple" seems to
work pretty well, but not well enough to make it a reasonable default.

Some other notable candidates:

- Local functions (e.g. based on local contrast or gradient)
- Clamp with soft knee (linear up to a point)
- Mapping in CIE L*Ch. Map L smoothly, clamp C and h.
- Color appearance models

These will have to be implemented some other time.

Note that the parameter "peak_src" to pass_tone_map should, in
principle, be auto-detected from the SEI information of the source file
where available. This will also have to be implemented in a later
commit.
2016-05-16 02:49:49 +02:00
Niklas Haas 3cfe98c684 vo_opengl: avoid redundant double-gamma conversion
Due to the way color management in mpv worked historically, the subtitle
blending function was written to preserve the linearity of the input.
(In the past, the 3DLUT function required linear inputs)

Since the 3DLUT was refactored to accept the video color directly, the
re-linearization after blending is now virtually always redundant.
(Notably, it's also redundant when CMS is turned off, so this way of
writing the code stopped making sense a long time ago. It is a remnant
from before the pass_colormanage function was as flexible as it is now)
2016-05-16 02:45:39 +02:00
Niklas Haas f81f486c68 vo_opengl: implement HDR (SMPTE ST2084)
Currently, this relies on the user manually entering their display
brightness (since we have no way to detect this at runtime or from ICC
metadata). The default value of 250 was picked by looking at ~10 reviews
on tftcentral.co.uk and realizing they all come with around 250 cd/m^2
out of the box. (In addition, ITU-R Rec. BT.2022 supports this)

Since there is no metadata in FFmpeg to indicate usage of this TRC, the
only way to actually play HDR content currently is to set
``--vf=format=gamma=st2084``. (It could be guessed based on SEI, but
this is not implemented yet)

Incidentally, since SEI is ignored, it's currently assumed that all
content is scaled to 10,000 cd/m^2 (and hard-clipped where out of
range). I don't see this assumption changing much, though.

As an unfortunate consequence of the fact that we don't know the display
brightness, mixed with the fact that LittleCMS' parametric tone curves
are not flexible enough to support PQ, we have to build the 3DLUT
against gamma 2.2 if it's used. This might be a good thing, though,
consdering the PQ source space is probably not fantastic for
interpolation either way.

Partially addresses #2572.
2016-05-16 02:45:39 +02:00
Niklas Haas 965031ccd5 vo_opengl: use enums for choice options internally
This is much more readable than hard-coding magic IDs all over the file,
and removes the need for all the explanatory comments that were a direct
result of this.
2016-05-16 02:45:39 +02:00
Niklas Haas 362015cd77 vo_opengl: abstract hook texture access behind macro
This macro takes care of rotation, swizzling, integer conversion and
normalization automatically. I found the performance impact to be
nonexistant for superxbr and debanding, although rotation *did* have an
impact due to the extra matrix multiplication. (So it gets skipped where
possible)

All of the internal hooks have been rewritten to use this new mechanism,
and the prescaler hooks have finally been separated from each other.
This also means the prescale FBO kludge is no longer required.

This fixes image corruption for image formats like 0bgr, and also fixes
prescaling under rotation. (As well as other user hooks that have
orientation-dependent access)

The "raw" attributes (tex, tex_pos, pixel_size) are still un-rotated, in
case something needs them, but ideally the hooks should be rewritten to
use the new API as much as possible. The hooked texture has been renamed
from just NAME to NAME_raw to make script authors notice the change (and
also deemphasize direct texture access).

This is also a step towards getting rid of the use_integer pass.
2016-05-15 20:42:08 +02:00
Niklas Haas dfc7b59909 vo_opengl: make the screen blue on shader errors
This helps visually signify that somthing went wrong, and prevents
confusing shader compilation errors with other types of bugs.
2016-05-15 20:42:02 +02:00
Niklas Haas 034faaa9d8 vo_opengl: use RPN expressions for user hook sizes
This replaces the previous TRANSFORM by WIDTH, HEIGHT and OFFSET where
WIDTH and HEIGHT are RPN expressions. This allows for more fine-grained
control over the output size, and also makes sure that overwriting
existing textures works more cleanly.

(Also add some more useful bstr functions)
2016-05-15 20:42:02 +02:00
Niklas Haas 7c3d78fd82 vo_opengl: support external user hooks
This allows users to add their own near-arbitrary hooks to the vo_opengl
processing pipeline, greatly enhancing the flexibility of user shaders.
This enables, among other things, user shaders such as CrossBilateral,
SuperRes, LumaSharpen and many more.

To make parsing the user shaders easier, shaders are now loaded as
bstrs, and the hooks are set up during video reconfig instead of on
every single frame.
2016-05-15 20:42:02 +02:00
Niklas Haas d53142f9ba vo_opengl: add optional hook points
These are "sequence points" where the image could be rendered out to an
FBO, hooked, and re-loaded if any such hook exists. This is perfect for
things like the current user shaders system, as well as optional effects
like unsharp masking.

Note that since we have to pick *some* FBO to store the optionally
hooked texture, we just store it in an array indexed by an increasing
counter. Since we only ever store as many as MAX_TEXTURE_HOOKS + all
internal hook points entries, this is guaranteed to be enough space.

This commit also removes some of the now unused FBOs.
2016-05-15 20:42:02 +02:00
Niklas Haas 070edd7300 vo_opengl: add hooks and rework pass_read_video
The hook mechanism allows arbitrary processing stages to get dispatched
whenever certain named textures have been "finalized" by the code.

This is mostly meant to serve as a change that opens up the internal
processing in pass_read_video to user scripts, but as a side benefit all
of the code dealing with offsets and plane alignment and other such
confusing things has been rewritten.

This hook mechanism is powerful enough to cover the needs of both
debanding and prescaling (and more), so as a result they can be removed
from pass_read_video entirely and implemented through hooks.

Some avenues for optimization:

- The prescale hook is currently somewhat distributed code-wise. It might be
  cleaner to split it into superxbr and NNEDI3 hooks which can each be
  self-contained.

- It might be possible to move a large part of the hook code out to an
  external file (including the hook definitions for debanding and
  prescaling), which would be very much desired.

- Currently, some stages (chroma merging, integer conversion) will
  *always* run even if unnecessary. I'm planning another series of
  refactors (deferred img_tex) to allow dropping unnecessary shader
  stages like these, but that's probably some ways away. In the meantime
  it would be doable to re-add some of the logic to skip these stages if
  we know we don't need them.

- More hook locations could be added (?)
2016-05-15 20:42:02 +02:00
Niklas Haas 3d4889e91e vo_opengl: minor change to scaler_resizes_only
Instead of rounding down, we round to the nearest float. This reduces
the maximum possible error introduced by this rounding operation. Also
clarify the comment.
2016-05-15 20:42:02 +02:00
wm4 32c10956e0 vaapi: avoid forward declaration of variable
Why is everything so horrible.
2016-05-15 18:37:51 +02:00
Julian 6ae7a555bf lua: add timer:is_enabled() function
Allows to query if some timer is currently running or was
stopped/killed.
2016-05-14 20:49:28 +02:00
wm4 449b948ee8 vo_opengl: remove some pointless compatibility
Remove non-texture_rg compatibility from LUT sampling. OpenGL without
texture_rg support will always trigger dumb-mode, and dumb-mode does not
use LUTs. It used not to, and that was when this made sense.
2016-05-14 12:02:02 +02:00
Ricardo Constantino 77d50cb3cf ytdl_hook: Just check if protocol is rtmp
Partial fix to #3090
2016-05-14 11:22:25 +02:00
wm4 3858d37b61 vo_opengl: partially fix 0bgr format support
Fixes broken colors with --vf=format=0bgr (but only if deband is
disabled).

0bgr means the first byte is padding, while the following three bytes
are bgr. From the vo_opengl perspective, it has 4 physical components
with 3 logical components. copy_img_tex() simply copied 3 components
from the physical representation, which means the last component (r) was
sliced off.

Fix this by not using p->color_swizzle for packed formats, and instead
let packed formats set the per-plane swizzle in texplane.swizzle. The
latter applies the swizzle as part of operation in copy_img_tex(), which
essentially moves physical to logical representations.

Unfortunately, debanding (and thus with opengl-hq defaults) is still
broken.
2016-05-13 22:35:42 +02:00
wm4 09e07e92c5 vo_opengl: drop duplicate LUMINANCE_ALPHA handling
This was supposed to handle the absence of GL_ARB_texture_rg. But it's
already handled elsewhere. (init_format() sets texplane.swizzle
accordingly.)
2016-05-13 22:07:25 +02:00
wm4 7d2c6d60da vo_opengl: minor simplification
Make the find_plane_format function take a bit count.

This also makes the function's comment true for the first time the
function and its comment exist. (It was commented as taking bits, but
always took bytes.)
2016-05-13 21:46:08 +02:00
wm4 c9d8bc088c vo_opengl: restrict ES2 FBO formats
Only a few very low bit depth internal formats can be rendered to in
pure ES2 (GL_RGB565 is the "best" one).

Seems like the only potentially reasonable renderable formats in ES2
could be provided via GL_OES_rgb8_rgba8, or half-floats, so don't
bother with this at all.
2016-05-13 18:50:38 +02:00
wm4 f7c81c03b2 vo_opengl: angle: log extension string 2016-05-13 15:39:11 +02:00
wm4 5bd6b76f5c cache: simplify speed calculations
Remove the attempted cleverness; keep it dumb.

This strictly calculates the average speed over an at least 1 second
window (longer if I/O blocks it).

Since this doesn't reset the speed anymore when reading stops by going
idle, the results might actually be more accurate now.
2016-05-12 22:37:45 +02:00
wm4 ee85473d4a travis: move travis-deps script to TOOLS
Don't let it clutter the top level directory.
2016-05-12 21:24:32 +02:00
wm4 a228bf54c8 vo_opengl: slightly better FBO format check
Now that we know in advance whether an implementation should support a
specific format, we have more flexibility when determining which format
to use.

In particular, we can drop the roundabout ES logic.

I'm not sure if actually trying to create the FBO for probing still has
any value. But it might, so leave it for now.
2016-05-12 21:22:28 +02:00
wm4 0cd217b039 vo_opengl: disable scalers on ES2
Even if everything else is available, the need for first class arrays
breaks it. In theory we could fix this since we don't strictly need
them, but I guess it's not worth bothering.

Also give the misnamed have_mix variable a slightly better name.
2016-05-12 21:22:28 +02:00
wm4 bd41a3ab62 vo_opengl: add detection for the ES texture_rg extension 2016-05-12 21:22:28 +02:00
wm4 84ccebd9b9 vo_opengl: reorganize texture format handling
This merges all knowledge about texture format into a central table.

Most of the work done here is actually identifying which formats exactly
are supported by OpenGL(ES) under which circumstances, and keeping this
information in the format table in a somewhat declarative way. (Although
only to the extend needed by mpv.) In particular, ES and float formats
are a horrible mess.

Again this is a big refactor that might cause regression on "obscure"
configurations.
2016-05-12 21:22:28 +02:00
wm4 e68b510a94 vo_opengl: correctly disable interpolation if tscale can't be used
It'll fail with an assertion in the interpolation code otherwise.
2016-05-12 21:22:28 +02:00
James Ross-Gowan c160e5f31d Add Appveyor CI integration for Windows builds 2016-05-12 23:34:06 +10:00
wm4 d4712af5af vo_opengl: angle: dump translated shaders
Helpful for debugging and such.
2016-05-12 11:17:49 +02:00
wm4 809d235208 manpage: document missing sub-properties
This is the client-API part; the normal descriptions are present in the
text above.
2016-05-11 19:14:31 +02:00
wm4 01d04b100f vo_opengl: don't use dumb-mode with 10 bit integer texture hack
Recent regression. Caused it to use dumb-mode with integer textures,
which on ANGLE leads to nearest scaling.
2016-05-11 17:41:00 +02:00
wm4 fe540f4477 vo_opengl: fix NULL deref on certain init failures 2016-05-11 17:12:59 +02:00
wm4 70b3561270 video: add --hwdec=auto-copy mode
This uses the normal autoprobing rules like "auto", but rejects anything
that isn't flagged as copying data back to system memory.

The chunk in command.c was dead code, so remove it instead of updating
it.
2016-05-11 16:20:13 +02:00
wm4 2ec26b8396 manpage: unmark d3d11va as "experimental"
Also add missing mediacodec entry.
2016-05-11 16:18:05 +02:00
wm4 cb694ffd8e vo_opengl: d3d11egl: support full range YUV
MSDN documents this as "Introduced in Windows 8.1.". I assume on Windows
7 this field will simply be ignored. Too bad for Windows 7 users.

Also, I'm not using D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_16_235 and
D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_0_255, because these are apparently
completely missing from the MinGW headers. (Such a damn pain.)
2016-05-11 15:40:31 +02:00
wm4 7983cda5bf vo_opengl: d3d11egl: don't require EGL_EXT_device_query
Older ANGLE builds don't export this.

This change is really only for convenience, and I might revert it at
some later point.
2016-05-11 15:40:31 +02:00
wm4 fd82e14888 build: merge d3d11va and dxva2 hwaccel checks
We don't have any reason to disable either. Both are loaded dynamically
at runtime anyway. There is also no reason why dxva2 would disappear
from libavcodec any time soon.
2016-05-11 15:40:31 +02:00
wm4 fde20d10bc vo_opengl: angle: dynamically load ANGLE
ANGLE is _really_ annoying to build. (Requires special toolchain and a
recent MSVC version.) This results in various issues with people
having trouble to build mpv against ANGLE (apparently linking it
against a prebuilt binary doesn't count, or using binaries from
potentially untrusted sources is not wanted).

Dynamically loading ANGLE is going to be a huge convenience. This commit
implements this, with special focus on keeping it source compatible to
a normal build with ANGLE linked at build-time.
2016-05-11 15:39:29 +02:00
q66 bea7675307 build: also use the iconv check on freebsd
This is necessary to make mpv build out of box on FreeBSD.
2016-05-10 23:03:53 +02:00
wm4 1f6e71c7fa vo_opengl: fix passing along swizzle from hwdec interop
In theory this was needed for the previous commit (but wasn't in
practice, since for hwdec the LUMINANCE_ALPHA mangling is not applied
anymore, and ANGLE uses RG textures in absence of GL_ARB_texture_rg for
whatever crazy reasons).

In practice this caused funky colors on OSX with the uyvy422 format,
which is also fixed in this commit.
2016-05-10 21:12:57 +02:00
wm4 a3d416c3d3 vo_opengl: d3d11egl: native NV12 sampling support
This uses EGL_ANGLE_stream_producer_d3d_texture_nv12 and related
extensions to map the D3D textures coming from the hardware decoder
directly in GL.

In theory this would be trivial to achieve, but unfortunately ANGLE does
not have a mechanism to "import" D3D textures as GL textures. Instead,
an awkward mechanism via EGL_KHR_stream was implemented, which involves
at least 5 extensions and a lot of glue code. (Even worse than VAAPI EGL
interop, and very far from the simplicity you get on OSX.)

The ANGLE mechanism so far supports only the NV12 texture format, which
means 10 bit won't work. It also does not work in ES3 mode yet. For
these reasons, the "old" ID3D11VideoProcessor code is kept and used as a
fallback.
2016-05-10 21:06:34 +02:00
wm4 4b3faf9dc1 vo_opengl: add an angle-es2 backend
It forces es2 mode on ANGLE. Only useful for testing. Since the normal
"angle" backend already falls back to es2 if es3 does not work, this new
backend always exit when autoprobing it.
2016-05-10 20:19:25 +02:00
wm4 12ae19c449 vo_opengl: cosmetics: rename variables
"p" is used for the private context everywhere in the source file, but
renaming it also requires renaming some local variables.
2016-05-10 18:49:49 +02:00
wm4 b0b01aa250 vo_opengl: refactor how hwdec interop exports textures
Rename gl_hwdec_driver.map_image to map_frame, and let it fill out a
struct gl_hwdec_frame describing the exact texture layout. This gives
more flexibility to what the hwdec interop can export. In particular, it
can export strange component orders/permutations and textures with
padded size. (The latter originating from cropped video.)

The way gl_hwdec_frame works is in the spirit of the rest of the
vo_opengl video processing code, which tends to put as much information
in immediate state (as part of the dataflow), instead of declaring it
globally. To some degree this duplicates the texplane and img_tex
structs, but until we somehow unify those, it's better to give the hwdec
state its own struct. The fact that changing the hwdec struct would
require changes and testing on at least 4 platform/GPU combinations
makes duplicating it almost a requirement to avoid pain later.

Make gl_hwdec_driver.reinit set the new image format and remove the
gl_hwdec.converted_imgfmt field.

Likewise, gl_hwdec.gl_texture_target is replaced with
gl_hwdec_plane.gl_target.

Split out a init_image_desc function from init_format. The latter is not
called in the hwdec case at all anymore. Setting up most of struct
texplane is also completely separate in the hwdec and normal cases.

video.c does not check whether the hwdec "mapped" image format is
supported. This should not really happen anyway, and if it does, the
hwdec interop backend must fail at creation time, so this is not an
issue.
2016-05-10 18:42:42 +02:00
wm4 7e6e47b8c4 sd_lavc: work around bug in older ffmpeg releases
Older ffmpeg releases don't have ffmpeg git commit
50401f5fb7d778583b03a13bc4440f71063d319d, which fixes ffmpeg's
pkt_timebase check to reject its default "unset" timebase as invalid.
The consequence was that all non-PGS bitmap subtitle timestamps were
forced to 0.

Of course this hit _only_ shitty distros using outdated/badly maintained
ffmpeg releases, so this is not worth working around. I've already
wasted a lot of time on analyzing this dumb issue, and it could be
useful for bisecting, so don't drop pre-3.0 ffmpeg just yet.

Fixes #3109.
2016-05-10 11:48:43 +02:00
wm4 013d63b081 stream_cdda: enable cache by default
Requested.
2016-05-10 11:17:52 +02:00
wm4 5d8d8618c4 manpage: document -- and some issues passing filenames 2016-05-10 11:15:45 +02:00
Richard H Lee da0bf27930 ass_process_chunk: Use llrint, not lrint
libass's ass_process_chunk expects long long int for the timecode and
durations arguments, thus should use llrint instead of lrint.

This does not cause any problems on most platforms, but on cygwin, it
causes strange subtitle behaviour, like subtitles not showing, getting
stuck or old subtitles showing at the same time as new subtitles.
2016-05-10 00:41:57 +02:00
wm4 af0a8d7478 player: restore usual seeking behavior
Commit 786f37ae accidentally changed seeking behavior such that
continuous seeking (holding the seek button down) would use the previous
seek target timestamp, instead of the new video timestamp. (This is for
the default mode, seeking to keyframes.)

The result is that the movement on the seekbar is smooth, but the way
the video updates is awkward. Some might actually prefer the new
behavior (and some players effectively show similar bahavior), but I
don't. So restore the old behavior.

This is done in two steps:

First: strictly wait for the entire seek process to finish, which will
effectively make the seeking code pick up the new video timestamp
correctly.

This would play audio immediately, which would result in noise during
continuous seeking, which leads to second: explicitly abort the playback
restarting process if this case is detected, and never play audio.
2016-05-09 22:54:49 +02:00
Mantas Mikulėnas 00c9bdf3f7 x11: tell GNOME to use dark window decorations 2016-05-09 20:39:59 +02:00
wm4 73aa7484f2 manpage: fix some script_message references to preferred name 2016-05-09 20:39:33 +02:00
wm4 46fff8d31a video: refactor how VO exports hwdec device handles
The main change is with video/hwdec.h. mp_hwdec_info is made opaque (and
renamed to mp_hwdec_devices). Its accessors are mainly thread-safe (or
documented where not), which makes the whole thing saner and cleaner. In
particular, thread-safety rules become less subtle and more obvious.

The new internal API makes it easier to support multiple OpenGL interop
backends. (Although this is not done yet, and it's not clear whether it
ever will.)

This also removes all the API-specific fields from mp_hwdec_ctx and
replaces them with a "ctx" field. For d3d in particular, we drop the
mp_d3d_ctx struct completely, and pass the interfaces directly.

Remove the emulation checks from vaapi.c and vdpau.c; they are
pointless, and the checks that matter are done on the VO layer.

The d3d hardware decoders might slightly change behavior: dxva2-copy
will not use the VO device anymore if the VO supports proper interop.
This pretty much assumes that any in such cases the VO will not use any
form of exclusive mode, which makes using the VO device in copy mode
unnecessary.

This is a big refactor. Some things may be untested and could be broken.
2016-05-09 20:03:22 +02:00
wm4 ee4c00698f vo_direct3d: remove passing device to decoder
This was never really used anyway. Removing it for the sake of the
following commit.
2016-05-09 18:59:10 +02:00
Emmanuel Gil Peyrot f99e48ae6a wayland: use the advertised size in fullscreen
When we receive the wl_shell_surface::configure event, it makes sense
to respect the aspect ratio of the video in windowed mode, but in
fullscreen it forces compositing and wastes resources (until atomic
modesetting is available everywhere and we can stop having
desynchronised planes).

Weston mitigates a resolution mismatch by creating black surfaces and
compositing them around the fullscreen surface, placed at the middle,
while GNOME puts it at the top-left and leaves the rest of the desktop
composited below, both of them producing a subpar experience.

Fixes #3021, #2657.
2016-05-08 19:47:08 +02:00
maniak1349 7d9eab15f0 win32: make taskbar progress indication optional
Add --taskbar-progress command line option and property which controls taskbar
progress indication rendering in Windows 7+. This option is on by default and
can be toggled during playback.

This option does not affect the creation process of ITaskbarList3. When the
option is turned off the progress bar is just hidden with TBPF_NOPROGRESS.

Closes #2535
2016-05-08 17:05:20 +02:00
wm4 2f8b4dd480 demux_lavf: fix a minor memory leak 2016-05-08 13:24:22 +02:00
wm4 ababfcbfe3 manpage: document --x11-bypass-compositor=no
Requested.
2016-05-08 11:05:01 +02:00
wm4 8fe33a11e2 x11: slightly safer X11 error handler behavior
The X11 error handler is global, and not per-display. If another Xlib
user exists in the process, they can conflict. In theory, it might
happen that e.g. another library sets an error handler (overwriting the
mpv one), and some time after mpv closes its display, restores the error
handler to mpv's one. To mitigate this, check if the error log instance
is actually set, instead of possibly crashing.

The change in vo_x11_uninit() is mostly cosmetic.
2016-05-08 11:04:44 +02:00
Rahul Kalkani 11406b9215 manpage: change gnome-screensaver-command example
Correct options to deactivate is -d or --deactivate.

Signed-off-by: wm4 <wm4@nowhere>
2016-05-07 12:17:28 +02:00
wm4 062493fa7e x11: rename inappropriate --x11-bypass-compositor=never option
This obviously made no sense.
2016-05-07 12:14:56 +02:00
wm4 55846641ea x11: add --x11-bypass-compositor=always
Also add missing documentation for fs-only, and correct the default.
2016-05-06 19:57:17 +02:00
Niklas Haas 7c5188c27e DOCS: update documentation related to color management
Some of this documentation was left woefully inaccurate as color
management in mpv evolved. This commit updates all of the wording and
adds notes and comments where appropriate.
2016-05-06 18:09:17 +02:00
wm4 a93fb460cd ao_alsa: add more shitty workarounds
This reportedly makes it work on ODROID-C2. The idea for this hack is
taken from kodi; they unconditionally set some or all of those flags.
I don't trust ALSA enough to hope that setting these flags couldn't
break something else, so we try without them first.

It's not clear whether this is a driver bug or a bug in the ALSA libs.
There is no ALSA bug tracker (the ALSA website has had a dead link to
a deleted bug tracker fo years). There's not much we can do other than
piling up ridiculous hacks. At least I think that at this point invalid
API usage by mpv can be excluded as a cause.

ALSA might be the worst audio API ever.
2016-05-06 17:20:02 +02:00
wm4 eef271c8f4 manpage: minor fixes to --lavfi-complex 2016-05-06 10:15:33 +02:00
wm4 7a75e7c002 vo_opengl: angle: avoid fullscreen FBO copy for flipping
In order to honor the differences between OpenGL and Direct3D coordinate
systems, ANGLE uses a full FBO copy merely to flip the final frame
vertically. This can be avoided with the EGL_ANGLE_surface_orientation
extension.
2016-05-05 18:44:41 +02:00
wm4 605dd928d3 vo_opengl: angle: call eglTerminate()
I hope that this does what we expect it does: destroy the EGLDisplay
specific to our HDC. (Some implementations will terminate all EGL
contexts in the whole process.)

eglReleaseThread() merely calls eglMakeCurrent(0, 0, 0, 0), which is
not enough.

This commit also fixes the problem fixed with the previous commit,
but I think both changes are needed to make our API usage clean.
2016-05-05 13:46:18 +02:00
wm4 f56555b514 vo_opengl: EGL: fix hwdec probing
If ANGLE was probed before (but rejected), the ANGLE API can remain
"initialized", and eglGetCurrentDisplay() will return a non-NULL
EGLDisplay. Then if a native GL context is used, the ANGLE/EGL API will
then (apparently) keep working alongside native OpenGL API. Since GL
objects are just numbers, they'll simply fail to interact, and OpenGL
will get invalid textures. For some reason this will result in black
textures.

With VAAPI-EGL, something similar could happen in theory, but didn't in
practice.
2016-05-05 13:38:08 +02:00
wm4 e5e1088c92 command: use NBSP for spacing after current marker for OSD lists
Requested. Will prevent odd layout for playlists with URLs longer than
the screen.
2016-05-04 21:51:35 +02:00
wm4 b2646911a9 client API: access choices as flags if appropriate
Options/properties that are choices, and which include "yes" or "no"
values (or both) can now be read and written as MPV_FORMAT_FLAG.

For write access, rejecting flags in these cases was obnoxiously
unintuitive and inconvenient.

For read access, the value of this is less convincing, and actually it's
a major API change. At this point I probably have to admit that the
finer details of the client API are very unstable.
2016-05-04 17:37:54 +02:00
wm4 833375f88d command: change some hwdec properties
Introduce hwdec-current and hwdec-interop properties.

Deprecate hwdec-detected, which never made a lot of sense, and which is
replaced by the new properties. hwdec-active also becomes useless, as
hwdec-current is a superset, so it's deprecated too (for now).
2016-05-04 16:55:26 +02:00
Niklas Haas 86b5f1463c lcms: don't warn/error on 3dlut cache misses
Cache misses are a normal and expected part of the operation of a cache.
It doesn't really make sense to show a user-visible warning for them.

To work-around this, just skip trying to open the cache if it doesn't
exist yet.
2016-05-04 12:10:55 +02:00
Niklas Haas 9054460bba lcms: improve black point handling (especially BT.1886)
First of all, black point compensation is now on by default. This is
really rather harmless and only improves the result (where "improvement"
means "less black clipping").

Second, this adds an option to limit the ICC profile's contrast, which
helps for untagged matrix profiles that are implicitly black scaled even
in colorimetric intent. (Note that this relies on BPC being enabled to
work properly, which is why the two changes are tied together)

Third, this uses the LittleCMS built in black point estimator instead of
relying on the presence of accurate A2B tables. This also checks tags
and does some amounts of noise elimination.

If the option is unspecified and the profile is missing black point
information, print a warning instructing the user to set the option, and
fall back to 1000 otherwise.
2016-05-04 12:10:45 +02:00
wm4 05c398fb6c command: slightly nicer OSD list formatting
For "current" markers on OSD properties like chapter-list. The marker is
now an actual arrow instead of "> ", and non-current entries will have
the same indentation as the current entry.

While I'm not entirely sure about the new look of those lists, it's a
bit better than the visual mess that was before.
2016-05-03 22:41:53 +02:00
wm4 485ae095f7 osd: make osd_ass_0/1 defines
So we can concatenate them with strings at compile time.
2016-05-03 22:29:12 +02:00
wm4 5be40f035b d3d: DXVA2_ModeMPEG2_VLD supports all profiles
Fixes hardware decoding of most mpeg2 things.
2016-05-03 15:46:16 +02:00
wm4 eefe7ad28b vo_opengl: vdpau: fix certain cases of preemption recovery failures
The vdpau_mixer could fail to be recreated properly if preemption
occured at some point before playback initialization (like when using
--hwdec-preload and the opengl-cb API).

Normally, the vdpau_mixer was supposed to be marked invalid when the
components using it detect a preemption, e.g. in hwdec_vdpau.c. This one
didn't mark the vdpau_mixer as invalid if preemption was detected in
reinit(), only in map_image().

It's cleaner to detect preemption directly in the vdpau_mixer, which
ensures it's always recreated correctly.
2016-05-03 13:56:11 +02:00
wm4 51e4c065ff ao_alsa: log final hwparams too
snd_pcm_hw_params() updates them.
2016-05-03 11:24:47 +02:00
wm4 8a26e139af x11: extend --x11-bypass-compositor with fs-only option
The "fs-only" choice sets the _NET_WM_BYPASS_COMPOSITOR to 1 if the
window is fullscreened, and 0 otherwise. (0 is specified to be the
implicit default - i.e. no change is requested in windowed mode.)

In particular, change the default to "fs-only".

Fixes #2582.
2016-05-02 21:21:53 +02:00
wm4 f54e555d27 wscript: make at least 1 OpenGL output mandatory
You have to explicitly disable it if you really want to compile without
it (like with libass).
2016-05-01 20:15:53 +02:00
wm4 3ff3749b7d av_log: readd ffmpeg library runtime version mismatch warning
It just happens far too often.
2016-05-01 20:11:15 +02:00
James Ross-Gowan 622bcb0e37 win32: replace libuuid.a usage with initguid.h
Including initguid.h at the top of a file that uses references to GUIDs
causes the GUIDs to be declared globally with __declspec(selectany). The
'selectany' attribute tells the linker to consolidate multiple
definitions of each GUID, which would be great except that, in Cygwin
and MinGW GCC 6.1, this method of linking makes the GUIDs conflict with
the ones declared in libuuid.a.

Since initguid.h obsoletes libuuid.a in modern compilers that support
__declspec(selectany), add initguid.h to all files that use GUIDs and
remove libuuid.a from the build.

Fixes #3097
2016-05-01 21:10:24 +10:00
Vaidas Kascėnas 9fda504d18 manpage: fix typo
Signed-off-by: wm4 <wm4@nowhere>
2016-04-30 18:58:34 +02:00
Nyx0uf ed695ce689 os x: handle multiple dropped files on the window
Should fix #3076 (partially).

Signed-off-by: wm4 <wm4@nowhere>
2016-04-30 18:58:06 +02:00
maniak1349 949247d6e6 w32_common: respect --fit-border on size check
Fit whole window or just a client area in accord with value of --fit-border option.

Fixes #2935.
2016-04-30 18:55:09 +02:00
maniak1349 70f64f3ca9 options: add --fit-border video option
Flag that is set by default. Reseting it will result in mpv trying to fit
client area with video instead of the whole window with border and
decorations on the screen.
Marked as (Windows only) for now until it's implemented on other platforms.
2016-04-30 18:55:09 +02:00
maniak1349 5c90352ae6 w32_common: fix size calculations for window resize
Substraction of 1 is not necessary due to .right and .bottom values of RECT
struct describing a point one pixel outside of the rectangle.

Fixes #2935. (2.b)
2016-04-30 18:55:09 +02:00
wm4 0826b78bc5 sd_ass: minor consistency adjustment 2016-04-30 14:26:08 +02:00
wm4 3a8058658d sd_add: replace --sub-ass=no with --ass-style-override=strip
--sub-ass=no / --ass=no still work, but --ass-style-override=strip is
preferred now. With this change, --ass-style-override can control all
the types of style overriding.
2016-04-30 14:25:23 +02:00
Kevin Mitchell 8d51f08010 d3d11va: fix invalid deref on decoder init failure
fixes #3092
2016-04-29 23:36:01 -07:00
wm4 64f9e48bf1 d3d11va, dxva2: return the format struct directly
Slight simplification, IMHO.
2016-04-29 23:30:01 +02:00
wm4 016eab2209 d3d11va, dxva2: simplify decoder selection
In particular, this moves the depth test to common code.

Should be functionally equivalent, except that for DXVA2, the
IDirectXVideoDecoderService_GetDecoderRenderTargets API is called
more often potentially.
2016-04-29 23:24:28 +02:00
wm4 bda111018c video: add IMGFMT_P010 alias
Gets rid of some silliness, and might be useful in the future.
2016-04-29 22:38:54 +02:00
wm4 0ed206abd9 command: don't seek immediately when setting a-b loop when paused
Because it's annoying and feels unnatural.

If the B point is set while paused, don't seek. If not paused, it should
properly loop immediately.

In theory there's a chance that it will show at least 1 frame after the
loop point when setting the B point. But let's not care about that.
2016-04-28 22:46:49 +02:00
wm4 d30634b104 ao_alsa: log hwparams while restricting them
They can sometimes fail, so I want logging to determine what's going on.

Most of them are at debug log-level, except the final hwparams.
2016-04-28 13:31:13 +02:00
wm4 304d9d58dd vo_opengl: fix build with GLES3 headers
Legacy desktop GL only symbols. Broken by the previous commit.
2016-04-27 20:26:08 +02:00
wm4 9d16837c99 vo_opengl: support GL_EXT_texture_norm16 on GLES
This gives us 16 bit fixed-point integer texture formats, including
ability to sample from them with linear filtering, and using them as FBO
attachments.

The integer texture format path is still there for the sake of ANGLE,
which does not support GL_EXT_texture_norm16 yet.

The change to pass_dither() is needed, because the code path using
GL_R16 for the dither texture relies on glTexImage2D being able to
convert from GL_FLOAT to GL_R16. GLES does not allow this. This could be
trivially fixed by doing the conversion ourselves, but I'm too lazy to
do this now.
2016-04-27 19:19:56 +02:00
wm4 757c8baf8c vo_opengl: always use sized internal formats
This shouldn't make much of a difference, but should make the following
commit simpler.
2016-04-27 19:02:04 +02:00
wm4 5df4ee55f1 player: strictly wait until done when backstepping
This fixes backstepping getting "stuck" when e.g. holding down a key
bound to the backstep command. The reason is that even if the backstep
itself is finished, the next backstep might not take the new video PTS
as reference if the hr-seek itself isn't finished yet.

The intention of not waiting for the hr-seek to finish was faster
backstepping by possibly skipping audio decoding. But it probably
doesn't matter enough to make the rest of the code more complex.
2016-04-27 17:02:00 +02:00
wm4 9cb036f297 vo_opengl: d3d11egl: minor simplification
This should be ok. eglBindTexImage() just associates the texture, and
does not make a copy (not even a conceptual one).
2016-04-27 14:35:24 +02:00
wm4 0b1ba577b1 vo_opengl: d3d11egl: print warning on unsupported colorspaces
Not much we can do about. If there are many complaints, a mechanism to
automatically disable interop in such cases could be added.
2016-04-27 14:34:46 +02:00
wm4 dff33893f2 d3d11va: store texture/subindex in IMGFMT_D3D11VA plane pointers
Basically this gets rid of the need for the accessors in d3d11va.h, and
the code can be cleaned up a little bit.

Note that libavcodec only defines a ID3D11VideoDecoderOutputView pointer
in the last plane pointers, but it tolerates/passes through the other
plane pointers we set.
2016-04-27 14:06:50 +02:00
wm4 9896994688 vd_lavc: adjust D3D11VA autoprobe order
We want to prefer d3d11va over dxva2 anything. But since dxva2 copyback
is more efficient than d3d11va's currently, d3d11va-copy should come
last.
2016-04-27 13:54:20 +02:00
wm4 3706918311 vo_opengl: D3D11VA + ANGLE interop
This uses ID3D11VideoProcessor to convert the video to a RGBA surface,
which is then bound to ANGLE. Currently ANGLE does not provide any way
to bind nv12 surfaces directly, so this will have to do.

ID3D11VideoContext1 would give us slightly more control about the
colorspace conversion, though it's still not good, and not available
in MinGW headers yet.

The video processor is created lazily, because we need to have the coded
frame size, of which AVFrame and mp_image have no concept of. Doing the
creation lazily is less of a pain than somehow hacking the coded frame
size into mp_image.

I'm not really sure how ID3D11VideoProcessorInputView is supposed to
work. We recreate it on every frame, which is simple and hopefully
doesn't affect performance.
2016-04-27 13:49:47 +02:00
wm4 cf9b415173 hwdec: remove numbers from enum
They don't actually mean anything.

Just HWDEC_NONE should remain 0, because it's the default init value for
structs etc.
2016-04-27 13:37:55 +02:00
wm4 d3a26272cd vo_opengl: print error if opengl hwdec interop fails 2016-04-27 13:32:49 +02:00
wm4 0c6c62cb17 lavfi: shut up false positive compiler warnings
As a positive side-effect, this also errors out gracefully for the
extremely unlikely but possible case certain builtin filters are not
available. (This could happen only with crippled libavfilter builds that
can't be used by anything using its public API.)
2016-04-26 19:38:51 +02:00
wm4 da59726776 vd_lavc: hack against videotoolbox crash on failure
I guess this won't ever be fixed properly in FFmpeg. Too hairy, and the
alternative (using VideoToolbox as "full decoder") is too attractive.
2016-04-26 18:53:58 +02:00
wm4 66a958bb4f ao_coreaudio: remove detected_device
Setting this here is a race condition. It's called from a CoreAudio
callbacks, and there are no locks. It's a string, so this can be
potentially severe.

It's hard to fix and only CoreAudio supported it, so remove it.

This causes the "audio-out-detected-device" property to return nothing
on all platforms.
2016-04-26 18:35:37 +02:00
wm4 dfe40f770d vo_rpi: rename mutex/cond variables
They're now used for the TV callback too, not just vsync.
2016-04-26 17:12:01 +02:00
wm4 6798525251 vo_rpi: wait for vsync with a timeout
Sucks, but better than freezing forever given the (to me) unpredictable
RPI behavior. This will be good enough to drop out of vsync timing mode,
or to abort playback.
2016-04-26 17:11:16 +02:00
wm4 74e3d11f21 vo_rpi: attempt to survive display mode changes
Recreate all dispmanx objects after mode changes signalled by the TV
callback. This is needed since dispmanx objects are marked as invalid
and cease working.

One important point is that the vsync callbacks will stop coming when
this happens, so restoring the callback is important.

Note that the MMAL renderer itself does not get trashed by the firmware
on such events, but we completely reconfigure it anyway when it happens.
2016-04-26 16:47:53 +02:00
wm4 dfa88271a2 vp_rpi: fix indentation
This also moves the p->background check into the top if (the code
effectively didn't do anything when this false).
2016-04-26 13:59:06 +02:00
wm4 8ffd2f1dd4 vd_lavc: simplify some unneeded ifdeffery
These were for ancient libavcodec versions.
2016-04-25 19:11:16 +02:00
wm4 6a1814dfb8 vd_lavc: make image_format hwdec field optional
For Mediacodec in particular we don't care about the format. It can just
decode to whatever it wants. The only case we would care about is it not
returning an opaque format if we don't have proper interop, but
libavcodec always returns non-opaque formats by default.
2016-04-25 12:23:38 +02:00
wm4 7e3d8e7134 vd_lavc: simplify RPI and Mediacodec wrappers
Use the recently added lavc_suffix mechanism to select the wrapper
decoder.

With all hwdec callbacks being optional, and RPI/Mediacodec having only
dummy callbacks, all the callbacks can be removed as well.

The result is that the vd_lavc_hwdec struct for both of them is tiny.
It's better to move them to vd_lavc.c directly, because they are so
trivial and small.
2016-04-25 12:23:38 +02:00
wm4 46e49a37be vd_lavc: make all hwdec callbacks optional 2016-04-25 12:23:37 +02:00
wm4 bb17df1f07 vd_lavc: set AVCodecContext.time_base to forced time base
This is a bit sketchy, as there isn't a truly standard way to
communicate the timebase.
2016-04-25 12:23:37 +02:00
wm4 4f5509e1dd vd_lavc: better hwdec wrapper decoder selection
This is intended for cases when --hwdec needs to override the decoder
implementation in use, like for example on the RPI.

It does two things:
1. Allow the hwdec to indicate a decoder suffix. libavcodec by
   convention adds a suffix to all wrapper decoders, and here we start
   relying on it. While not necessarily the best idea, it's the only
   thing we got. libavcodec's hwaccel list is useless, because it only
   has the codec ID, not the associated decoder's name.
2. Make --hwdec=auto work properly. It shouldn't fail anymore, and hwdec
   probing should reliably work, even if a different decoder is selected
   with --vd. The semantics of --hwdec should dictate that it overrides
   the default decoder.
2016-04-25 12:13:12 +02:00
wm4 85416bc36a vd_lavc: allow process_image() to return NULL
In case of errors or whatever.
2016-04-25 11:30:07 +02:00
wm4 021cb2c387 mp_image: allow passing NULL to mp_image_new_custom_ref()
A minor simplification. Most callers don't need this, and there's no
good reason why the caller should provide an "initializer" like this.
(This function calls mp_image_new_dummy_ref(), which has no reason
for an initializer either.)
2016-04-25 11:28:49 +02:00
trUSTssc e232f1a731 player: fix memleak when using video-frame-info 2016-04-24 20:44:01 +02:00
wm4 5800d1845f player: always show the first frame in DS mode
Fixes bogus frame drop counter in cover art mode.
2016-04-24 20:14:51 +02:00
wm4 5f97bd4223 player: assume video forwards timestamps jumps only with some formats
Another crappy fix for timestamp reset issues. This time, we try to fix
files which have very weird but legitimate frame durations, such as
cdgraphics. It can have many short frames, but once in a while there are
potentially very long frames.

Fixes #3027.
2016-04-24 18:24:46 +02:00
wm4 649e155938 manpage: fix --autofit example
Fixes #3069.
2016-04-24 17:58:39 +02:00
wm4 47e7676e7e player: force VO reconfig when unselecting video track
Switches to a black window if --force-window is used while coverart
"video" is playing.
2016-04-23 18:55:24 +02:00
wm4 786f37ae1c player: cleaner determination of current playback PTS
In particular, this won't overwrite the playback PTS in coverart mode,
which actually fixes relative seeks.
2016-04-23 18:55:24 +02:00
wm4 abb3f80998 player: eagerly redraw OSD when seeking with coverart 2016-04-23 16:39:46 +02:00
wm4 b1a8e8dba6 vd_lavc: fix hwdec fallback if hwdec pre-initialization fails
Damn.
2016-04-22 15:52:16 +02:00
wm4 244eff9201 vo_opengl: always reset some GL state when leaving renderer
The active texture and some pixelstore parameters are now always reset
to defaults when entering and leaving the renderer. Could be important
for libmpv.
2016-04-22 12:08:21 +02:00
wm4 2b4123f078 player: fix OSD bar chapter marks
Truly dumb bug introduced with the previous commit.
2016-04-22 09:31:21 +02:00
wm4 1944a34c23 command: if only ab-loop-b is set, loop from start of file
Commit 382bafcb changed the behavior for ab-loop-a. This commit changes
ab-loop-b so that the behavior is symmetric.

Adjust the OSD rendering accordingly to the two changes.

Also fix mentions of the "ab_loop" command to the now preferred
"ab-loop".
2016-04-21 22:15:36 +02:00
wm4 78346e9c9a ad_spdif: take care of deprecated libavcodec API usage 2016-04-20 19:37:45 +02:00
wm4 60664bc00b stream_memory: add hex:// protocol
Completely useless, expect for some special purposes.
2016-04-20 18:00:20 +02:00
wm4 834a236514 player: force wakeup on playback restart
Just a theoretical issue, most likely.
2016-04-20 13:11:11 +02:00
wm4 cd9ee1a853 player: really start audio only once video is ready
The check whether video is ready yet was done only in STATUS_FILLING.
But it also switched to STATUS_READY, which means the next time
fill_audio_out_buffers() was called, audio would actually be started
before video.

In most situations, this bug didn't show up, because it was only
triggered if the demuxer didn't provide video packets quickly enough,
but did for audio packets.

Also log when audio is started.

(I hate fill_audio_out_buffers(), why did I write it?)
2016-04-20 13:08:06 +02:00
wm4 61ac156d47 player: reduce some timer calls 2016-04-20 10:50:22 +02:00
wm4 8dbc93a94c player: minor simplification to buffering property updates
Strictly schedule an update in regular intervals as long as either
stream cache or demuxer are prefetching. Don't update just always
because the stream cache is enabled ("idle != -1") or cache-related
properties are observed (mp_client_event_is_registered()).

Also, the "idle" variable was awkard; get rid of it with equivalent
code.
2016-04-20 10:41:09 +02:00
wm4 8db9206c54 player: simplify an aspect of buffering determination
Calculate the buffering percentage in the same code which determines
whether the player is or should be buffering. In particular it can't
happen that percentage and buffering state are slightly out of sync due
to calling DEMUXER_CTRL_GET_READER_STATE and reusing it with the
previously determined buffering state.

Now it's also easier to guarantee that the buffering state is updated
properly.

Add some more verbose output as well.

(Damn I hate this code, why did I write it?)
2016-04-19 22:01:30 +02:00
wm4 503dada42f demux_playlist: read directories recursive
demux_playlist.c recognizes if the source stream points to a directory,
and adds its directory entries. Until now, only 1 level was added.
During playback, further directory entries could be resolved as
directory paths were "played".

While this worked fine, it lead to frequent user confusion, because
playlist resuming and other things didn't work as expected. So just
recursively scan everything.

I'm unsure whether it's a good fix, but at least it gets rid of the
complaints. (And probably will add others.)
2016-04-18 22:08:44 +02:00
wm4 382bafcb13 player: loop on end of file if ab-loop-b is unset
Possibly slightly more useful/intuitive.
2016-04-18 21:33:19 +02:00
Kevin Mitchell ce153bdb42 d3dva: move Intel_H264_NoFGT_ClearVideo to lower priority
This seems to cause problems, so only use it if H264_E is not available.

fixes #3059
2016-04-18 02:00:50 -07:00
Kevin Mitchell 2f5c7af914 dxva2: fix missing newline in error message 2016-04-18 01:58:18 -07:00
Kevin Mitchell 611594e7e8 d3dva: include selected decoder and format in verbose output 2016-04-17 18:28:14 -07:00
Philip Sequeira 1f1117d0dd input: fix parsing multiple input command prefixes 2016-04-17 12:53:30 +02:00
Philip Sequeira d797f7def9 TOOLS/zsh.pl: complete --audio-device 2016-04-16 18:47:15 +02:00
wm4 44644e69f0 vo_opengl: fix an outdated comment
This wasn't updated over multiple iterations.
2016-04-16 16:16:50 +02:00
wm4 8e96e04999 command: fix cycling certain properties
Commit a9bd4535 generally changed properties are set to string values.
This actually broke the fallback for non-string properties, because the
set string action was redirected directly to the property, instead of
the generic handler and its fallback code.
2016-04-15 22:10:19 +02:00
wm4 9db1b7a001 vo_lavc: fix build on Libav
OF COURSE Libav doesn't have AV_PICTURE_TYPE_NONE. Why the fuck would
it?
2016-04-15 19:35:29 +02:00
wm4 050b17ca9c mp_image: make mp_image_copy_fields_* private
Future code should always use mp_image_{to,from}_av_frame(). Everything
else is way too messy and fragile.
2016-04-15 15:48:02 +02:00
wm4 a77cbc504a vo_lavc: unsupport deprecated AVFMT_RAWPICTURE
As of ffmpeg git master, only the libavdevice decklink wrapper supports
this. Everything else has dropped support.

You're now supposed to use AV_CODEC_ID_WRAPPED_AVFRAME, which works a
bit differently. Normal AVFrames should still work for these encoders.
2016-04-15 15:45:38 +02:00
wm4 798188cb33 vo_lavc: send refcounted AVFrame to encoder
This potentially makes it more efficient, and actually makes it simpler.

Yes, AV_PICTURE_TYPE_NONE is the default for pict_type.
2016-04-15 15:43:46 +02:00
wm4 d04aa5ef4e mp_image: add mp_image_to_av_frame()
What mp_image_to_av_frame_and_unref() should have been. (The _unref
variant is still useful though.)
2016-04-15 15:33:53 +02:00
wm4 e6cdfdfa74 mp_image: simplify mp_image_steal_data()
Why was this so complex.
2016-04-15 15:31:23 +02:00
wm4 bbaedfd0c5 mp_image: pass through AVHWFramesContext
In both directions.
2016-04-15 15:07:02 +02:00
wm4 607ba5f235 ao_coreaudio_exclusive: list formats when searching substream
Should help debug problems with AC3 passthrough not working.
2016-04-15 14:19:22 +02:00
wm4 1aa943d8ab ao_coreaudio: remove unused function 2016-04-15 14:14:42 +02:00
wm4 b735c0e207 lcms: include math.h
Fixes #3053.
2016-04-15 13:58:41 +02:00
wm4 fbb5da0010 command: log property set calls
And remove the same thing from the client API code.

The command.c code has to deal with many specialized M_PROPERTY_SET_*
actions, and we bother with a subset only.
2016-04-15 13:20:05 +02:00
wm4 177f5d9e9c command: allow setting panscan etc. properties if no video is active
In that case, it merely changes the underlying option value.
2016-04-15 11:32:40 +02:00
wm4 a9bd4535d2 client API: improve mpv_set_property() handling of MPV_FORMAT_NODE
If a mpv_node wrapped a string, the behavior was different from calling
mpv_set_property() with MPV_FORMAT_STRING directly. Change this.

The original intention was to be strict about types if MPV_FORMAT_NODE
is used. But I think the result was less than ideal, and the same change
towards less strict behavior was made to mpv_set_option() ages ago.
2016-04-15 11:32:40 +02:00
wm4 8c02c92ab9 vo_opengl: rpi: don't include x11 header file
Copy & paste bug.
2016-04-15 09:45:15 +02:00
wm4 4ebac1e936 player: fix use-after-free with --screenshot-directory
Probably fixes #3049.
2016-04-14 22:48:12 +02:00
wm4 e13cc25a2c build: add check for AVHWFramesContext API
It's not used yet anywhere. Pushing this now so switching between
branches is less bothersome.
2016-04-14 18:20:13 +02:00
wm4 0467f5287d m_option: slightly improve --msg-level=help output
In particular get rid of the semi-deprecated ":" separator.
2016-04-13 22:25:51 +02:00
wm4 9a4120f21f m_option: add string conversion for --audio-channels
Requested in #3040.
2016-04-13 22:22:53 +02:00
Niklas Haas e3e03d0f34 vo_opengl: simplify and improve up scale=oversample
Since what we're doing is a linear blend of the four colors, we can just
do it for free by using GPU sampling.

This requires significantly fewer texture fetches and calculations to
compute the final color, making it much more efficient. The code is also
much shorter and simpler.
2016-04-12 16:26:53 +02:00
wm4 f4142ab9ad demux_mkv: fix seeking with files that miss the first index entry
Now it will always be able to seek back to the start, even if the index
is sparse or misses the first entry.

This can be achieved by reusing the logic for incremental index
generation (for files with no index), and start time probing (for making
sure the first block is always indexed).
2016-04-12 15:41:44 +02:00
wm4 837b865c7f vf_vavpp: reindent 2016-04-11 22:03:26 +02:00
wm4 f5ff2656e0 vaapi: determine surface format in decoder, not in renderer
Until now, we have made the assumption that a driver will use only 1
hardware surface format. the format is dictated by the driver (you
don't create surfaces with a specific format - you just pass a
rt_format and get a surface that will be in a specific driver-chosen
format).

In particular, the renderer created a dummy surface to probe the format,
and hoped the decoder would produce the same format. Due to a driver
bug this required a workaround to actually get the same format as the
driver did.

Change this so that the format is determined in the decoder. The format
is then passed down as hw_subfmt, which allows the renderer to configure
itself with the correct format. If the hardware surface changes its
format midstream, the renderer can be reconfigured using the normal
mechanisms.

This calls va_surface_init_subformat() each time after the decoder
returns a surface. Since libavcodec/AVFrame has no concept of sub-
formats, this is unavoidable. It creates and destroys a derived
VAImage, but this shouldn't have any bad performance effects (at
least I didn't notice any measurable effects).

Note that vaDeriveImage() failures are silently ignored as some
drivers (the vdpau wrapper) support neither vaDeriveImage, nor EGL
interop. In addition, we still probe whether we can map an image
in the EGL interop code. This is important as it's the only way
to determine whether EGL interop is supported at all. With respect
to the driver bug mentioned above, it doesn't matter which format
the test surface has.

In vf_vavpp, also remove the rt_format guessing business. I think the
existing logic was a bit meaningless anyway. It's not even a given
that vavpp produces the same rt_format for output.
2016-04-11 22:03:26 +02:00
Rudolf Polzer 49431626cb Revert "build: disable encoding mode by default"
Reverting because the use of deprecated API has been fixed.

This reverts commit d0238711dc.
2016-04-11 14:59:33 -04:00
Rudolf Polzer 160497b8ff encode_lavc: Migrate to codecpar API. 2016-04-11 14:57:20 -04:00
290 changed files with 13472 additions and 7912 deletions

No files matched your search

+23
View File
@@ -0,0 +1,23 @@
### mpv version and platform
If you're not using git master or the latest release, update.
### Reproduction steps
### Expected behavior
### Actual behavior
### Log files
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.
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
Sample files needed to reproduce this issue can be uploaded to https://0x0.st/
or similar sites. (Only needed if the issue cannot be reproduced without it.)
+7
View File
@@ -0,0 +1,7 @@
Ideally, you shouldn't need enter any text here, and your commit messages should
explain your changes sufficiently (especially why they are needed). Read
https://github.com/mpv-player/mpv/blob/master/DOCS/contribute.md for coding
style and development conventions. Remove this text block, but if you haven't
agreed to it before, leave the following sentence in place:
I agree that my changes can be relicensed to LGPL 2.1 or later.
-1
View File
@@ -15,7 +15,6 @@
/tags
/TAGS
/video/out/x11_icon.inc
/video/out/opengl/nnedi3_weights.inc
/demux/ebml_defs.c
/demux/ebml_types.h
/sub/osd_font.h
+1 -1
View File
@@ -37,7 +37,7 @@ matrix:
- os: linux
compiler: clang
before_install: ./travis-deps libass-stable $LIBAV
before_install: TOOLS/travis-deps libass-stable $LIBAV
script:
- ./bootstrap.py
- ./waf configure
-32
View File
@@ -1,32 +0,0 @@
Reporting bugs
==============
- State your platform and mpv version.
- Make sure you're actually using the latest mpv release. Linux distributions
in particular love redistributing ancient and unmaintained mpv releases.
- Attach a log file made with ``-v`` or ``--log-file=output.txt``.
- Avoid attaching text files packed in archive files (zip/rar/...), unless
explicitly asked so. There are better means, such as using http://sprunge.us
- If you think this is file specific, upload a sample file and link it.
- Don't report multiple unrelated/barely related bugs in one issue.
- If you don't get a reply after days, be sure to post a new message to the
issue - it could have been overlooked or forgotten.
- Read: https://mpv.io/bug-reports/
Asking questions
================
Preferably, asking questions should be done via IRC (#mpv on irc.freenode.net),
but asking questions by opening a github issue is also barely tolerated.
When asking on IRC (#mpv on irc.freenode.net), don't ask to ask, just state
your problem. Stay long enough until someone gets a chance to reply. Sometimes
it can take hours.
Sending patches
===============
See: https://github.com/mpv-player/mpv/blob/master/DOCS/contribute.md
In particular, be aware that all changes to GPL code must come with the
implicit agreement that they might be LGPLv2.1+ relicensed at a later point.
-3
View File
@@ -12,9 +12,6 @@ the code to LGPLv2.1+ at a later point without asking the contributor. (This
is a safeguard for making potential relicensing of the project to LGPLv2.1+
easier.) Using a more liberal license compatible to LGPLv2.1+ is also ok.
Some GPLv3 or LGPLv3 code in mpv can be enabled by building with --enable-gpl3,
and in this case, the resulting binaries must be distributed under GPLv3.
For information about authors and contributors, consult the git log, which
contains the complete SVN and CVS history as well.
+26
View File
@@ -32,6 +32,32 @@ API changes
::
--- mpv 0.20.0
--- mpv 0.19.0
1.22 - add stream_cb API for custom protocols
--- mpv 0.18.1 ---
---- - remove "status" log level from mpv_request_log_messages() docs. This
is 100% equivalent to "v". The behavior is still the same, thus no
actual API change.
--- mpv 0.18.0 ---
1.21 - mpv_set_property() changes behavior with MPV_FORMAT_NODE. Before this
change it rejected mpv_nodes with format==MPV_FORMAT_STRING if the
property was not a string or did not have special mechanisms in place
the function failed. Now it always invokes the option string parser,
and mpv_node with a basic data type works exactly as if the function
is invoked with that type directly. This new behavior is equivalent
to mpv_set_option().
This also affects the mp.set_property_native() Lua function.
- generally, setting choice options/properties with "yes"/"no" options
can now be set as MPV_FORMAT_FLAG
- reading a choice property as MPV_FORMAT_NODE will now return a
MPV_FORMAT_FLAG value if the choice is "yes" (true) or "no" (false)
This implicitly affects Lua and JSON IPC interfaces as well.
- big changes to vo-cmdline on vo_opengl and vo_opengl_hq (but not
vo_opengl_cb): options are now normally not reset, but applied on top
of the current options. The special undocumented value "-" still
works, but now resets all options to before any vo-cmdline command
has been called.
--- mpv 0.12.0 ---
1.20 - deprecate "GL_MP_D3D_interfaces"/"glMPGetD3DInterface", and introduce
"GL_MP_MPGetNativeDisplay"/"glMPGetNativeDisplay" (this is a
+18
View File
@@ -173,6 +173,24 @@ sed -i 's_/mingw64/bin_/mingw64/lib_' /mingw64/lib/pkgconfig/mpv.pc
rmdir /mingw64/bin/pkgconfig
```
Linking libmpv with MSVC programs
---------------------------------
You can build C++ programs in Visual Studio and link them with libmpv. To do
this, you need a Visual Studio which supports ``stdint.h`` (recent ones do),
and you need to create a import library for the mpv DLL:
```bash
lib /def:mpv.def /name:mpv-1.dll /out:mpv.lib /MACHINE:X64
```
The string in the ``/name:`` parameter must match the filename of the DLL (this
is simply the filename the MSVC linker will use). The ``mpv.def`` can be
retrieved from the mpv build directory, or can be produced by MingGW's
gendef.exe helper from the mpv DLL.
Static linking is not possible.
Running mpv
-----------
+41
View File
@@ -19,6 +19,47 @@ 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 ---
- deprecate --heartbeat-cmd
- remove --softvol=no capability:
- deprecate --softvol, it now does nothing
- --volume, --mute, and the corresponding properties now always control
softvol, and behave as expected without surprises (e.g. you can set
them normally while no audio is initialized)
- rename --softvol-max to --volume-max (deprecated alias is added)
- the --volume-restore-data option and property are removed without
replacement. They were _always_ internal, and used for watch-later
resume/restore. Now --volume/--mute are saved directly instead.
- the previous point means resuming files with older watch-later configs
will print an error about missing --volume-restore-data (which you can
ignore), and will not restore the previous value
- as a consequence, volume controls will no longer control PulseAudio
per-application value, or use the system mixer's per-application
volume processing
- system or per-application volume can still be controlled with the
ao-volume and ao-mute properties (there are no command line options)
--- mpv 0.18.0 ---
- now ab-loops are active even if one of the "ab-loop-a"/"-b" properties is
unset ("no"), in which case the start of the file is used if the A loop
point is unset, and the end of the file for an unset B loop point
- deprecate --sub-ass=no option by --ass-style-override=strip
(also needs --embeddedfonts=no)
- add "hwdec-interop" and "hwdec-current" properties
- deprecated "hwdec-active" and "hwdec-detected" properties (to be removed
in mpv 0.20.0)
- choice option/property values that are "yes" or "no" will now be returned
as booleans when using the mpv_node functions in the client API, the
"native" property accessors in Lua, and the JSON API. They can be set as
such as well.
- the VO opengl fbo-format sub-option does not accept "rgb" or "rgba"
anymore
- all VO opengl prescalers have been removed (replaced by user scripts)
--- mpv 0.17.0 ---
- deprecate "track-list/N/audio-channels" property (use
"track-list/N/demux-channel-count" instead)
+5 -29
View File
@@ -70,7 +70,7 @@ Available filters are:
Set AVOptions on the SwrContext or AVAudioResampleContext. These should
be documented by FFmpeg or Libav.
``lavcac3enc[=tospdif[:bitrate[:minch]]]``
``lavcac3enc[=options]``
Encode multi-channel audio to AC-3 at runtime using libavcodec. Supports
16-bit native-endian input format, maximum 6 channels. The output is
big-endian when outputting a raw AC-3 stream, native-endian when
@@ -103,6 +103,10 @@ Available filters are:
If the input channel number is less than ``<minch>``, the filter will
detach itself (default: 3).
``encoder=<name>``
Select the libavcodec encoder used. Currently, this should be an AC-3
encoder, and using another codec will fail horribly.
``equalizer=g1:g2:g3:...:g10``
10 octave band graphic equalizer, implemented using 10 IIR band-pass
filters. This means that it works regardless of what type of audio is
@@ -308,34 +312,6 @@ Available filters are:
``mpv '--af=format=channels=5.1' '--audio-channels=5.1'`` would always force
remixing audio to 5.1 and output it like this.
``delay[=[ch1,ch2,...]]``
Delays the sound to the loudspeakers such that the sound from the
different channels arrives at the listening position simultaneously. It is
only useful if you have more than 2 loudspeakers.
``[ch1,ch2,...]``
The delay in ms that should be imposed on each channel (floating point
number between 0 and 1000).
To calculate the required delay for the different channels, do as follows:
1. Measure the distance to the loudspeakers in meters in relation to your
listening position, giving you the distances s1 to s5 (for a 5.1
system). There is no point in compensating for the subwoofer (you will
not hear the difference anyway).
2. Subtract the distances s1 to s5 from the maximum distance, i.e.
``s[i] = max(s) - s[i]; i = 1...5``.
3. Calculate the required delays in ms as ``d[i] = 1000*s[i]/342; i =
1...5``.
.. admonition:: Example
``mpv --af=delay=[10.5,10.5,0,0,7,0] media.avi``
Would delay front left and right by 10.5 ms, the two rear channels
and the subwoofer by 0 ms and the center channel by 7 ms.
``drc[=method:target]``
Applies dynamic range compression. This maximizes the volume by compressing
the audio signal's dynamic range. (Formerly called ``volnorm``.)
+148 -52
View File
@@ -459,6 +459,8 @@ Input Commands that are Possibly Subject to Change
Remove all filters. Note that like the other sub-commands, this does
not control automatically inserted filters.
The argument is always needed. E.g. in case of ``clr`` use ``vf clr ""``.
You can assign labels to filter by prefixing them with ``@name:`` (where
``name`` is a user-chosen arbitrary identifier). Labels can be used to
refer to filters by name in all of the filter chain modification commands.
@@ -524,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
@@ -542,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.)
@@ -561,29 +563,20 @@ Input Commands that are Possibly Subject to Change
the resolution is reduced to that of the video's. You can read the
``osd-width`` and ``osd-height`` properties. At least with ``--vo-xv`` and
anamorphic video (such as DVD), ``osd-par`` should be read as well, and the
overlay should be aspect-compensated. (Future directions: maybe mpv should
take care of some of these things automatically, but it's hard to tell
where to draw the line.)
overlay should be aspect-compensated.
``id`` is an integer between 0 and 63 identifying the overlay element. The
ID can be used to add multiple overlay parts, update a part by using this
command with an already existing ID, or to remove a part with
``overlay-remove``. Using a previously unused ID will add a new overlay,
while reusing an ID will update it. (Future directions: there should be
something to ensure different programs wanting to create overlays don't
conflict with each others, should that ever be needed.)
while reusing an ID will update it.
``x`` and ``y`` specify the position where the OSD should be displayed.
``file`` specifies the file the raw image data is read from. It can be
either a numeric UNIX file descriptor prefixed with ``@`` (e.g. ``@4``),
or a filename. The file will be mapped into memory with ``mmap()``. Some VOs
will pass the mapped pointer directly to display APIs (e.g. opengl or
vdpau), so no actual copying is involved. Truncating the source file while
the overlay is active will crash the player. You shouldn't change the data
while the overlay is active, because the data is essentially accessed at
random points. Instead, call ``overlay-add`` again (preferably with a
different memory region to prevent tearing).
or a filename. The file will be mapped into memory with ``mmap()``,
copied, and unmapped before the command returns (changed in mpv 0.18.1).
It is also possible to pass a raw memory address for use as bitmap memory
by passing a memory address as integer prefixed with an ``&`` character.
@@ -616,15 +609,14 @@ Input Commands that are Possibly Subject to Change
(Technically, the minimum size would be ``stride * (h - 1) + w * 4``, but
for simplicity, the player will access all ``stride * h`` bytes.)
.. admonition:: Warning
.. note::
When updating the overlay, you should prepare a second shared memory
region (e.g. make use of the offset parameter) and add this as overlay,
instead of reusing the same memory every time. Otherwise, you might
get the equivalent of tearing, when your application and mpv write/read
the buffer at the same time. Also, keep in mind that mpv might access
an overlay's memory at random times whenever it feels the need to do
so, for example when redrawing the screen.
Before mpv 0.18.1, you had to do manual "double buffering" when updating
an overlay by replacing it with a different memory buffer. Since mpv
0.18.1, the memory is simply copied and doesn't reference any of the
memory indicated by the command's arguments after the commend returns.
If you want to use this command before mpv 0.18.1, reads the old docs
to see how to handle this correctly.
``overlay-remove <id>``
Remove an overlay added with ``overlay-add`` and the same ID. Does nothing
@@ -634,10 +626,10 @@ Input Commands that are Possibly Subject to Change
Send a message to all clients, and pass it the following list of arguments.
What this message means, how many arguments it takes, and what the arguments
mean is fully up to the receiver and the sender. Every client receives the
message, so be careful about name clashes (or use ``script_message_to``).
message, so be careful about name clashes (or use ``script-message-to``).
``script-message-to "<target>" "<arg1>" "<arg2>" ...``
Same as ``script_message``, but send it only to the client named
Same as ``script-message``, but send it only to the client named
``<target>``. Each client (scripts etc.) has a unique name. For example,
Lua scripts can get their name via ``mp.get_script_name()``.
@@ -648,11 +640,11 @@ Input Commands that are Possibly Subject to Change
The argument is the name of the binding.
It can optionally be prefixed with the name of the script, using ``/`` as
separator, e.g. ``script_binding scriptname/bindingname``.
separator, e.g. ``script-binding scriptname/bindingname``.
For completeness, here is how this command works internally. The details
could change any time. On any matching key event, ``script_message_to``
or ``script_message`` is called (depending on whether the script name is
could change any time. On any matching key event, ``script-message-to``
or ``script-message`` is called (depending on whether the script name is
included), with the following arguments:
1. The string ``key-binding``.
@@ -817,7 +809,7 @@ Input sections group a set of bindings, and enable or disable them at once.
In ``input.conf``, each key binding is assigned to an input section, rather
than actually having explicit text sections.
See also: ``enable_section`` and ``disable_section`` commands.
See also: ``enable-section`` and ``disable-section`` commands.
Predefined bindings:
@@ -877,6 +869,12 @@ Property list
looks better for display purposes. Use the ``path`` property to get an
unmodified filename.)
This has a sub-property:
``filename/no-ext``
Like the ``filename`` property, but if the text contains a ``.``, strip
all text after the last ``.``. Usually this removes the file extension.
``file-size``
Length in bytes of the source file/stream. (This is the same as
``${stream-end}``. For ordered chapters and such, the
@@ -1081,8 +1079,8 @@ Property list
"default" MPV_FORMAT_FLAG
``ab-loop-a``, ``ab-loop-b`` (RW)
Set/get A-B loop points. See corresponding options and ``ab_loop`` command.
The special value ``no`` on either of these properties disables looping.
Set/get A-B loop points. See corresponding options and ``ab-loop`` command
for details.
``angle`` (RW)
Current DVD angle.
@@ -1242,29 +1240,31 @@ Property list
See ``--hr-seek``.
``mixer-active``
Return ``yes`` if the audio mixer is active, ``no`` otherwise. This has
implications for ``--softvol=no`` mode: if the mixer is inactive, changing
``volume`` doesn't actually change anything on the system mixer. If the
``--volume`` or ``--mute`` option are used, these might not be applied
properly until the mixer becomes active either. (The options, if set, will
just overwrite the mixer state at audio initialization.)
Return ``yes`` if the audio mixer is active, ``no`` otherwise.
While the behavior with ``mixer-active==yes`` is relatively well-defined,
the ``no`` case will provide possibly wrong or insignificant values.
Note that an active mixer does not necessarily imply active audio output,
although this is implied in the current implementation.
This option is relatively useless. Before mpv 0.18.1, it could be used to
infer behavior of the ``volume`` property.
``volume`` (RW)
Current volume (see ``--volume`` for details). Also see ``mixer-active``
property.
Current volume (see ``--volume`` for details).
``volume-max``
Current maximum value the volume property can be set to. (This may depend
on the ``--softvol-max`` option.)
``volume-max`` (RW)
Current maximum value the volume property can be set to. (Equivalent to the
``--volume-max`` option.)
``mute`` (RW)
Current mute status (``yes``/``no``). Also see ``mixer-active`` property.
Current mute status (``yes``/``no``).
``ao-volume`` (RW)
System volume. This property is available only if mpv audio output is
currently active, and only if the underlying implementation supports volume
control. What this option does depends on the API. For example, on ALSA
this usually changes system-wide audio, while with PulseAudio this controls
per-application volume.
``ao-mute`` (RW)
Similar to ``ao-volume``, but controls the mute state. May be unimplemented
even if ``ao-volume`` works.
``audio-delay`` (RW)
See ``--audio-delay``.
@@ -1327,6 +1327,8 @@ Property list
It doesn't change the volumes of each channel, but instead sets up a pan
matrix to mix the left and right channels.)
Deprecated.
``fullscreen`` (RW)
See ``--fullscreen``.
@@ -1349,6 +1351,9 @@ Property list
``colormatrix-primaries`` (R)
See ``colormatrix``.
``taskbar-progress`` (RW)
See ``--taskbar-progress``.
``ontop`` (RW)
See ``--ontop``.
@@ -1385,14 +1390,39 @@ Property list
properties to see whether this was successful.
Unlike in mpv 0.9.x and before, this does not return the currently active
hardware decoder.
hardware decoder. Since mpv 0.18.0, ``hwdec-current`` is available for
this purpose.
``hwdec-current``
Return the current hardware decoding in use. If decoding is active, return
one of the values used by the ``hwdec`` option/property. ``no`` indicates
software decoding. If no decoder is loaded, the property is unavailable.
``hwdec-interop``
This returns the currently loaded hardware decoding/output interop driver.
This is known only once the VO has opened (and possibly later). With some
VOs (like ``opengl``), this might be never known in advance, but only when
the decoder attempted to create the hw decoder successfully. (Using
``--hwdec-preload`` can load it eagerly.) If there are multiple drivers
loaded, they will be separated by ``,``.
If no VO is active or no interop driver is known, this property is
unavailable.
This does not necessarily use the same values as ``hwdec``. There can be
multiple interop drivers for the same hardware decoder, depending on
platform and VO.
``hwdec-active``
Deprecated. To be removed in mpv 0.20.0. Use ``hwdec-current`` instead.
Return ``yes`` or ``no``, depending on whether any type of hardware decoding
is actually in use.
``hwdec-detected``
If software decoding is active, this returns the hardware decoder in use.
Deprecated. To be removed in mpv 0.20.0.
If hardware decoding is active, this returns the hardware decoder in use.
Otherwise, it returns either ``no``, or if applicable, the currently loaded
hardware decoding API. This is known only once the VO has opened (and
possibly later). With some VOs (like ``opengl``), this is never known in
@@ -1457,6 +1487,12 @@ Property list
``video-params/gamma``
The gamma function in use as string. (Exact values subject to change.)
``video-params/nom-peak``
The video encoding's nominal peak brightness as float.
``video-params/sig-peak``
The video file's tagged signal peak as float.
``video-params/chroma-location``
Chroma location as string. (Exact values subject to change.)
@@ -1483,6 +1519,9 @@ Property list
"colormatrix" MPV_FORMAT_STRING
"colorlevels" MPV_FORMAT_STRING
"primaries" MPV_FORMAT_STRING
"gamma" MPV_FORMAT_STRING
"nom-peak" MPV_FORMAT_DOUBLE
"sig-peak" MPV_FORMAT_DOUBLE
"chroma-location" MPV_FORMAT_STRING
"rotate" MPV_FORMAT_INT64
"stereo-in" MPV_FORMAT_STRING
@@ -1563,7 +1602,7 @@ Property list
``osd-width``, ``osd-height``
Last known OSD width (can be 0). This is needed if you want to use the
``overlay_add`` command. It gives you the actual OSD size, which can be
``overlay-add`` command. It gives you the actual OSD size, which can be
different from the window size in some cases.
``osd-par``
@@ -1646,6 +1685,9 @@ Property list
Current position on playlist. The first entry is on position 0. Writing
to the property will restart playback at the written entry.
``playlist-pos-1`` (RW)
Same as ``playlist-pos``, but 1-based.
``playlist-count``
Number of total playlist entries.
@@ -1771,6 +1813,16 @@ Property list
``track-list/N/audio-channels`` (deprecated)
Deprecated alias for ``track-list/N/demux-channel-count``.
``track-list/N/replaygain-track-peak``, ``track-list/N/replaygain-track-gain``
Per-track replaygain values. Only available for audio tracks with
corresponding information stored in the source file.
``track-list/N/replaygain-album-peak``, ``track-list/N/replaygain-album-gain``
Per-album replaygain values. If the file has per-track but no per-album
information, the per-album values will be copied from the per-track
values currently. It's possible that future mpv versions will make
these properties unavailable instead in this case.
When querying the property with the client API using ``MPV_FORMAT_NODE``,
or with Lua ``mp.get_property_native``, this will return a mpv_node with
the following contents:
@@ -1787,9 +1839,11 @@ Property list
"albumart" MPV_FORMAT_FLAG
"default" MPV_FORMAT_FLAG
"forced" MPV_FORMAT_FLAG
"selected" MPV_FORMAT_FLAG
"external" MPV_FORMAT_FLAG
"external-filename" MPV_FORMAT_STRING
"codec" MPV_FORMAT_STRING
"ff-index" MPV_FORMAT_INT64
"decoder-desc" MPV_FORMAT_STRING
"demux-w" MPV_FORMAT_INT64
"demux-h" MPV_FORMAT_INT64
@@ -1798,6 +1852,10 @@ Property list
"demux-samplerate" MPV_FORMAT_INT64
"demux-fps" MPV_FORMAT_DOUBLE
"audio-channels" MPV_FORMAT_INT64
"replaygain-track-peak" MPV_FORMAT_DOUBLE
"replaygain-track-gain" MPV_FORMAT_DOUBLE
"replaygain-album-peak" MPV_FORMAT_DOUBLE
"replaygain-album-gain" MPV_FORMAT_DOUBLE
``chapter-list``
List of chapters, current entry marked. Currently, the raw property value
@@ -1904,6 +1962,44 @@ Property list
whether the video window is visible. If the ``--force-window`` option is
used, this is usually always returns ``yes``.
``vo-performance``
Some video output performance metrics. Not implemented by all VOs. This has
a number of sup-properties, of the form ``vo-performance/<metric>-<value>``,
all of them in milliseconds.
``<metric>`` refers to one of:
``upload``
Time needed to make the frame available to the GPU (if necessary).
``render``
Time needed to perform all necessary video postprocessing and rendering
passes (if necessary).
``present``
Time needed to present a rendered frame on-screen.
When a step is unnecessary or skipped, it will have the value 0.
``<value>`` refers to one of:
``last``
Last measured value.
``avg``
Average over a fixed number of past samples. (The exact timeframe
varies, but it should generally be a handful of seconds)
``peak``
The peak (highest value) within this averaging range.
When querying the property with the client API using ``MPV_FORMAT_NODE``,
or with Lua ``mp.get_property_native``, this will return a mpv_node with
the following contents:
::
MPV_FORMAT_NODE_MAP
"<metric>-<value>" MPV_FORMAT_INT64
(One entry for each ``<metric>`` and ``<value>`` combination)
``video-bitrate``, ``audio-bitrate``, ``sub-bitrate``
Bitrate values calculated on the packet level. This works by dividing the
bit size of all packets between two keyframes by their presentation
@@ -2063,7 +2159,7 @@ Property list
(Note that if an option is marked as file-local, even ``options/`` will
access the local value, and the ``old`` value, which will be restored on
end of playback, can not be read or written until end of playback.)
end of playback, cannot be read or written until end of playback.)
``option-info/<name>``
Additional per-option information.
+2 -2
View File
@@ -41,7 +41,7 @@ It's also possible to send input.conf style text-only commands:
::
> echo 'show_text ${playback-time}' | socat - /tmp/mpvsocket
> echo 'show-text ${playback-time}' | socat - /tmp/mpvsocket
But you won't get a reply over the socket. (This particular command shows the
playback time on the player's OSD.)
@@ -65,7 +65,7 @@ You can send commands from a command prompt:
::
echo show_text ${playback-time} >\\.\pipe\mpvsocket
echo show-text ${playback-time} >\\.\pipe\mpvsocket
To be able to simultaneously read and write from the IPC pipe, like on Linux,
it's necessary to write an external program that uses overlapped file I/O (or
+10 -6
View File
@@ -175,7 +175,7 @@ The ``mp`` module is preloaded, although it can be loaded manually with
Similar to ``mp.set_property``, but set the given property using its native
type.
Since there are several data types which can not represented natively in
Since there are several data types which cannot represented natively in
Lua, this might not always work as expected. For example, while the Lua
wrapper can do some guesswork to decide whether a Lua table is an array
or a map, this would fail with empty tables. Also, there are not many
@@ -350,6 +350,10 @@ The ``mp`` module is preloaded, although it can be loaded manually with
with ``add_timeout()``), this starts the timer from the beginning,
using the initially configured timeout.
``is_enabled()``
Whether the timer is currently enabled or was previously disabled
(e.g. by ``stop()`` or ``kill()``).
``timeout`` (RW)
This field contains the current timeout period. This value is not
updated as time progresses. It's only used to calculate when the
@@ -454,9 +458,9 @@ are useful only in special situations.
The level is a string, see ``msg.log`` for allowed log levels.
``mp.register_script_message(name, fn)``
This is a helper to dispatch ``script_message`` or ``script_message_to``
invocations to Lua functions. ``fn`` is called if ``script_message`` or
``script_message_to`` (with this script as destination) is run
This is a helper to dispatch ``script-message`` or ``script-message-to``
invocations to Lua functions. ``fn`` is called if ``script-message`` or
``script-message-to`` (with this script as destination) is run
with ``name`` as first parameter. The other parameters are passed to ``fn``.
If a message with the given name is already registered, it's overwritten.
@@ -537,8 +541,8 @@ Example command-line::
--script-opts=myscript-optionA=TEST,myscript-optionB=0,myscript-optionC=yes
mp.utils options
----------------
mp.utils functions
------------------
This built-in module provides generic helper functions for Lua, and have
strictly speaking nothing to do with mpv or video/audio playback. They are
+16 -2
View File
@@ -320,11 +320,22 @@ example, paths starting with ``-`` will be interpreted as options. Likewise,
if a path contains the sequence ``://``, the string before that might be
interpreted as protocol prefix, even though ``://`` can be part of a legal
UNIX path. To avoid problems with arbitrary paths, you should be sure that
absolute paths passed to mpv start with ``/``, and relative paths with ``./``.
absolute paths passed to mpv start with ``/``, and prefix relative paths with
``./``.
Using the ``file://`` pseudo-protocol is discouraged, because it involves
strange URL unescaping rules.
The name ``-`` itself is interpreted as stdin, and will cause mpv to disable
console controls. (Which makes it suitable for playing data piped to stdin.)
The special argument ``--`` can be used to stop mpv from interpreting the
following arguments as options.
When using the client API, you should strictly avoid using ``mpv_command_string``
for invoking the ``loadfile`` command, and instead prefer e.g. ``mpv_command``
to avoid the need for filename escaping.
For paths passed to suboptions, the situation is further complicated by the
need to escape special characters. To work this around, the path can be
additionally wrapped in the fixed-length syntax, e.g. ``%n%string_of_length_n``
@@ -715,6 +726,9 @@ PROTOCOLS
``memory://data``
Use the ``data`` part as source data.
``hex://data``
Like ``memory://``, but the string is interpreted as hexdump.
PSEUDO GUI MODE
===============
@@ -932,7 +946,7 @@ For Windows-specifics, see `FILES ON WINDOWS`_ section.
``~/.config/mpv/watch_later/``
Contains temporary config files needed for resuming playback of files with
the watch later feature. See for example the ``Q`` key binding, or the
``quit_watch_later`` input command.
``quit-watch-later`` input command.
Each file is a small config file which is loaded if the corresponding media
file is loaded. It contains the playback position and some (not necessarily
+243 -77
View File
@@ -196,7 +196,7 @@ Playback Control
position and so can take some time depending on decoding performance. For
some video formats, precise seeks are disabled. This option selects the
default choice to use for seeks; it is possible to explicitly override that
default in the definition of key bindings and in slave mode commands.
default in the definition of key bindings and in input commands.
:no: Never use precise seeks.
:absolute: Use precise seeks if the seek is to an absolute position in the
@@ -261,8 +261,13 @@ Playback Control
``--ab-loop-a=<time>``, ``--ab-loop-b=<time>``
Set loop points. If playback passes the ``b`` timestamp, it will seek to
the ``a`` timestamp. Seeking past the ``b`` point doesn't loop (this is
intentional). The loop-points can be adjusted at runtime with the
corresponding properties. See also ``ab_loop`` command.
intentional).
If both options are set to ``no``, looping is disabled. Otherwise, the
start/end of the file is used if one of the options is set to ``no``.
The loop-points can be adjusted at runtime with the corresponding
properties. See also ``ab-loop`` command.
``--ordered-chapters``, ``--no-ordered-chapters``
Enabled by default.
@@ -369,7 +374,7 @@ Program Behavior
``--idle=<no|yes|once>``
Makes mpv wait idly instead of quitting when there is no file to play.
Mostly useful in slave mode, where mpv can be controlled through input
Mostly useful in input mode, where mpv can be controlled through input
commands.
``once`` will only idle at start and let the player close once the
@@ -399,7 +404,7 @@ Program Behavior
``--no-resume-playback``
Do not restore playback position from the ``watch_later`` configuration
subdirectory (usually ``~/.config/mpv/watch_later/``).
See ``quit_watch_later`` input command.
See ``quit-watch-later`` input command.
``--profile=<profile1,profile2,...>``
Use the given profile(s), ``--profile=help`` displays a list of the
@@ -576,14 +581,19 @@ Video
:no: always use software decoding (default)
:auto: see below
:auto-copy: see below
:vdpau: requires ``--vo=vdpau`` or ``--vo=opengl`` (Linux only)
:vaapi: requires ``--vo=opengl`` or ``--vo=vaapi`` (Linux only)
:vaapi-copy: copies video back into system RAM (Linux with Intel GPUs only)
:videotoolbox: requires ``--vo=opengl`` (OS X 10.8 and up only)
:videotoolbox-copy: copies video back into system RAM (OS X 10.8 and up only)
:dxva2: requires ``--vo=opengl:backend=angle`` or
``--vo=opengl:backend=dxinterop`` (Windows only)
:dxva2-copy: copies video back to system RAM (Windows only)
:d3d11va-copy: experimental (Windows only)
:d3d11va: requires ``--vo=opengl:backend=angle`` (Windows only)
:d3d11va-copy: copies video back to system RAM (Windows only)
:mediacodec: copies video back to system RAM (Android only)
:rpi: requires ``--vo=rpi`` (Raspberry Pi only - default if available)
``auto`` tries to automatically enable hardware decoding using the first
@@ -593,6 +603,13 @@ Video
work, it will always fall back to software decoding, instead of trying the
next method (might matter on some Linux systems).
``auto-copy`` selects only modes that copy the video data back to system
memory after decoding. Currently, this selects only one of the following
modes: ``vaapi-copy``, ``dxva2-copy``, ``d3d11va-copy``, ``mediacodec``.
If none of these work, hardware decoding is disabled. This mode is always
guaranteed to incur no additional loss compared to software decoding, and
will allow CPU processing with video filters.
The ``vaapi`` mode, if used with ``--vo=opengl``, requires Mesa 11 and most
likely works with Intel GPUs only. It also requires the opengl EGL backend
(automatically used if available). You can also try the old GLX backend by
@@ -614,6 +631,46 @@ Video
codecs. See ``--hwdec-codecs`` to enable hardware decoding for more
codecs.
.. admonition:: Quality reduction with hardware decoding
Normally, hardware decoding does not reduce video quality (at least for
the codecs h264 and HEVC). However, due to restrictions in video output
APIs, there can be some loss, or blatantly incorrect results.
In some cases, RGB conversion is forced, which means the RGB conversion
is performed by the hardware decoding API, instead of the OpenGL code
used by ``--vo=opengl``. This means certain obscure colorspaces may
not display correctly, not certain filtering (such as debanding)
cannot be applied in an ideal way.
``vdpau`` is usually safe. If deinterlacing enabled (or the ``vdpaupp``
video filter is active in general), it forces RGB conversion. The latter
currently does not treat certain colorspaces like BT.2020 correctly
(which is mostly a mpv-specific restriction). The ``vdpauprb`` video
filter retrieves image data without RGB conversion and is safe (but
precludes use of vdpau postprocessing).
``vaapi`` is safe if the ``vaapi-egl`` backend is indicated in the logs.
If ``vaapi-glx`` is indicated, and the video colorspace is either BT.601
or BT.709, a forced but correct RGB conversion is performed. Otherwise,
the result will be incorrect.
``d3d11va`` is usually safe (if used with ANGLE builds that support
``EGL_KHR_stream path`` - otherwise, it converts to RGB), except that
10 bit input (HEVC main 10 profiles) will be rounded down to 8 bits.
``dxva2`` is not safe. It appears to always use BT.601 for forced RGB
conversion, but actual behavior depends on the GPU drivers. Some drivers
appear to convert to limited range RGB, which gives a faded appearance.
In addition to driver-specific behavior, global system settings might
affect this additionally. This can give incorrect results even with
completely ordinary video sources.
All other methods, in particular the copy-back methods (like
``dxva2-copy`` etc.) are either fully safe, or not worse than software
decoding. In particular, ``auto-copy`` will only select safe modes
(although potentially slower than other methods).
``--hwdec-preload=<api>``
This is useful for the ``opengl`` and ``opengl-cb`` VOs for creating the
hardware decoding OpenGL interop context, but without actually enabling
@@ -635,8 +692,8 @@ Video
choice of the format can influence performance considerably. On the other
hand, there doesn't appear to be a good way to detect the best format for
the given hardware. ``nv12``, the default, works better on modern hardware,
while ``uyvy422`` appears to be better for old hardware. ``rgb0`` also
works.
while ``uyvy422`` appears to be better for old hardware. ``rgb0`` and
``yuv420p`` also work.
``--panscan=<0.0-1.0>``
Enables pan-and-scan functionality (cropping the sides of e.g. a 16:9
@@ -644,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``.
@@ -681,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
@@ -828,9 +889,9 @@ Video
You can get the list of allowed codecs with ``mpv --vd=help``. Remove the
prefix, e.g. instead of ``lavc:h264`` use ``h264``.
By default, this is set to ``h264,vc1,wmv3,hevc,mpeg2video``. Note that the
hardware acceleration special codecs like ``h264_vdpau`` are not relevant
anymore, and in fact have been removed from Libav in this form.
By default, this is set to ``h264,vc1,wmv3,hevc,mpeg2video,vp9``. Note that
the hardware acceleration special codecs like ``h264_vdpau`` are not
relevant anymore, and in fact have been removed from Libav in this form.
This is usually only needed with broken GPUs, where a codec is reported
as supported, but decoding causes more problems than it solves.
@@ -1017,14 +1078,15 @@ Audio
``--volume=<value>``
Set the startup volume. 0 means silence, 100 means no volume reduction or
amplification. A value of -1 (the default) will not change the volume. See
also ``--softvol``.
amplification. Negative values can be passed for compatibility, but are
treated as 0.
.. note::
Since mpv 0.18.1, this always controls the internal mixer (aka "softvol").
This was changed after the mpv 0.9 release. Before that, 100 actually
meant maximum volume. At the same time, the volume scale was made cubic,
so the old values won't match up with the new ones anyway.
``--balance=<value>``
How much left/right channels contribute to the audio.
Deprecated.
``--audio-delay=<sec>``
Audio delay in seconds (positive or negative float value). Positive values
@@ -1039,20 +1101,17 @@ Audio
See also: ``--volume``.
``--softvol=<mode>``
Control whether to use the volume controls of the audio output driver or
the internal mpv volume filter.
``--softvol=<no|yes|auto>``
Deprecated/unfunctional. Before mpv 0.18.1, this used to control whether
to use the volume controls of the audio output driver or the internal mpv
volume filter.
:no: prefer audio driver controls, use the volume filter only if
absolutely needed
:yes: always use the volume filter
:auto: prefer the volume filter if the audio driver uses the system mixer
(default)
The current behavior is as if this option was set to ``yes``. The other
behaviors are not available anymore, although ``auto`` almost matches
current behavior in most cases.
The intention of ``auto`` is to avoid changing system mixer settings from
within mpv with default settings. mpv is a video player, not a mixer panel.
On the other hand, mixer controls are enabled for sound servers like
PulseAudio, which provide per-application volume.
The ``no`` behavior is still partially available through the ``ao-volume``
and ``ao-mute`` properties. But there are no options to reset these.
``--audio-demuxer=<[+]name>``
Use this audio demuxer type when using ``--audio-file``. Use a '+' before
@@ -1095,30 +1154,51 @@ Audio
This and enabling passthrough via ``--ad`` are deprecated in favor of
using ``--audio-spdif=dts-hd``.
``--audio-channels=<auto|number|layout>``
Request a channel layout for audio output (default: stereo). This will ask
the AO to open a device with the given channel layout. It's up to the AO
to accept this layout, or to pick a fallback or to error out if the
requested layout is not supported.
``--audio-channels=<auto-safe|auto|layouts>``
Control which audio channels are output (e.g. surround vs. stereo). There
are the following possibilities:
The ``--audio-channels`` option either takes a channel number or an explicit
channel layout. Channel numbers refer to default layouts, e.g. 2 channels
refer to stereo, 6 refers to 5.1.
- ``--audio-channels=auto-safe``
Use the system's preferred channel layout. If there is none (such
as when accessing a hardware device instead of the system mixer),
force stereo. Some audio outputs might simply accept any layout and
do downmixing on their own.
This is the default.
- ``--audio-channels=auto``
Send the audio device whatever it accepts, preferring the audio's
original channel layout. Can cause issues with HDMI (see the warning
below).
- ``--audio-channels=layout1,layout2,...``
List of ``,``-separated channel layouts which should be allowed.
Technically, this only adjusts the filter chain output to the best
matching layout in the list, and passes the result to the audio API.
It's possible that the audio API will select a different channel
layout.
Using this mode is recommended for direct hardware output, especially
over HDMI (see HDMI warning below).
- ``--audio-channels=stereo``
Force a plain stereo downmix. This is a special-case of the previous
item. (See paragraphs below for implications.)
If a list of layouts is given, each item can be either an explicit channel
layout name (like ``5.1``), or a channel number. Channel numbers refer to
default layouts, e.g. 2 channels refer to stereo, 6 refers to 5.1.
See ``--audio-channels=help`` output for defined default layouts. This also
lists speaker names, which can be used to express arbitrary channel
layouts (e.g. ``fl-fr-lfe`` is 2.1).
``--audio-channels=auto`` tries to play audio using the input file's
channel layout. There is no guarantee that the audio API handles this
correctly. See the HDMI warning below.
(``empty`` is an accepted obsolete alias for ``auto``.)
This will also request the channel layout from the decoder. If the decoder
does not support the layout, it will fall back to its native channel layout.
(You can use ``--ad-lavc-downmix=no`` to make the decoder always output
its native layout.) Note that only some decoders support remixing audio.
Some that do include AC-3, AAC or DTS audio.
If the list of channel layouts has only 1 item, the decoder is asked to
produce according output. This sometimes triggers decoder-downmix, which
might be different from the normal mpv downmix. (Only some decoders support
remixing audio, like AC-3, AAC or DTS. You can use ``--ad-lavc-downmix=no``
to make the decoder always output its native layout.) One consequence is
that ``--audio-channels=stereo`` triggers decoder downmix, while ``auto``
or ``auto-safe`` never will, even if they end up selecting stereo. This
happens because the decision whether to use decoder downmix happens long
before the audio device is opened.
If the channel layout of the media file (i.e. the decoder) and the AO's
channel layout don't match, mpv will attempt to insert a conversion filter.
@@ -1131,6 +1211,10 @@ Audio
channel layout, random things can happen, such as dropping the
additional channels, or adding noise.
You are recommended to set an explicit whitelist of the layouts you
want. For example, most A/V receivers connected via HDMI and that can
do 7.1 would be served by: ``--audio-channels=7.1,5.1,stereo``
``--audio-normalize-downmix=<yes|no>``
Enable/disable normalization if surround audio is downmixed to stereo
(default: no). If this is disabled, downmix can cause clipping. If it's
@@ -1209,10 +1293,12 @@ Audio
their start timestamps differ, and then video timing is gradually adjusted
if necessary to reach correct synchronization later.
``--softvol-max=<100.0-1000.0>``
``--volume-max=<100.0-1000.0>``, ``--softvol-max=<...>``
Set the maximum amplification level in percent (default: 130). A value of
130 will allow you to adjust the volume up to about double the normal level.
``--softvol-max`` is a deprecated alias and should not be used.
``--audio-file-auto=<no|exact|fuzzy|all>``, ``--no-audio-file-auto``
Load additional audio files matching the video filename. The parameter
specifies how external audio files are matched. ``exact`` is enabled by
@@ -1221,7 +1307,7 @@ Audio
:no: Don't automatically load external audio files.
:exact: Load the media filename with audio file extension (default).
:fuzzy: Load all audio files containing media filename.
:all: Load all aufio files in the current and ``--audio-file-paths``
:all: Load all audio files in the current and ``--audio-file-paths``
directories.
``--audio-file-paths=<path1:path2:...>``
@@ -1233,7 +1319,7 @@ Audio
or to set your own application name when using libmpv.
``--volume-restore-data=<string>``
Used internally for use by playback resume (e.g. with ``quit_watch_later``).
Used internally for use by playback resume (e.g. with ``quit-watch-later``).
Restoring value has to be done carefully, because different AOs as well as
softvol can have different value ranges, and we don't want to restore
volume if setting the volume changes it system wide. The normal options
@@ -1259,13 +1345,32 @@ Audio
Default: 0.2 (200 ms).
``--audio-stream-silence=<yes|no>``
Cash-grab consumer audio hardware (such as A/V receivers) often ignore
initial audio sent over HDMI. This can happen every time audio over HDMI
is stopped and resumed. In order to compensate for this, you can enable
this option to not to stop and restart audio on seeks, and fill the gaps
with silence. Likewise, when pausing playback, audio is not stopped, and
silence is played while paused. Note that if no audio track is selected,
the audio device will still be closed immediately.
Not all AOs support this.
``--audio-wait-open=<secs>``
This makes sense for use with ``--audio-stream-silence=yes``. If this option
is given, the player will wait for the given amount of seconds after opening
the audio device before sending actual audio data to it. Useful if your
expensive hardware discards the first 1 or 2 seconds of audio data sent to
it. If ``--audio-stream-silence=yes`` is not set, this option will likely
just waste time.
Subtitles
---------
.. note::
Changing styling and position does not work with all subtitles. Image-based
subtitles (DVD, Bluray/PGS, DVB) can not changed for fundamental reasons.
subtitles (DVD, Bluray/PGS, DVB) cannot changed for fundamental reasons.
Subtitles in ASS format are normally not changed intentionally, but
overriding them can be controlled with ``--ass-style-override``.
@@ -1423,7 +1528,7 @@ Subtitles
Using this option may lead to incorrect subtitle rendering.
``--ass-style-override=<yes|no|force>``
``--ass-style-override=<yes|no|force|signfs|strip>``
Control whether user style overrides should be applied.
:yes: Apply all the ``--ass-*`` style override options. Changing the default
@@ -1433,6 +1538,8 @@ Subtitles
:no: Render subtitles as forced by subtitle scripts.
:force: Try to force the font style as defined by the ``--sub-text-*``
options. Can break rendering easily.
:strip: Radically strip all ASS tags and styles from the subtitle. This
is equivalent to the old ``--no-ass`` / ``--no-sub-ass`` options.
``--ass-force-margins``
Enables placing toptitles and subtitles in black borders when they are
@@ -1529,6 +1636,13 @@ Subtitles
``--sub-ass``, ``--no-sub-ass``
Render ASS subtitles natively (enabled by default).
.. note::
This has been deprecated by ``--ass-style-override=strip``. You also
may need ``--embeddedfonts=no`` to get the same behavior. Also,
using ``--ass-style-override=force`` should give better results
without breaking subtitles too much.
If ``--no-sub-ass`` is specified, all tags and style declarations are
stripped and ignored on display. The subtitle renderer uses the font style
as specified by the ``--sub-text-`` options instead.
@@ -1539,10 +1653,6 @@ Subtitles
rendering of ASS/SSA subtitles. It can sometimes be useful to forcibly
override the styling of ASS subtitles, but should be avoided in general.
.. note::
Try using ``--ass-style-override=force`` instead.
``--sub-auto=<no|exact|fuzzy|all>``, ``--no-sub-auto``
Load additional subtitle files matching the video filename. The parameter
specifies how external subtitle files are matched. ``exact`` is enabled by
@@ -1767,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
@@ -1783,6 +1910,12 @@ Window
mode can be used to create the window always on program start, but this
may cause other issues.
``--taskbar-progress``, ``--no-taskbar-progress``
(Windows only)
Enable/disable playback progress rendering in taskbar (Windows 7 and above).
Enabled by default.
``--ontop``
Makes the player window stay on top of other windows.
@@ -1794,6 +1927,12 @@ Window
Play video with window border and decorations. Since this is on by
default, use ``--no-border`` to disable the standard window decorations.
``--fit-border``, ``--no-fit-border``
(Windows only) Fit the whole window with border and decorations on the
screen. Since this is on by default, use ``--no-fit-border`` to make mpv
try to only fit client area with video on the screen. This behavior only
applied to window/video with size exceeding size of the screen.
``--on-all-workspaces``
(X11 only)
Show the video window on all virtual desktops.
@@ -1885,7 +2024,7 @@ Window
Make the window width 70% of the screen size, keeping aspect ratio.
``1000``
Set the window width to 1000 pixels, keeping aspect ratio.
``70%:60%``
``70%x60%``
Make the window as large as possible, without being wider than 70%
of the screen width, or higher than 60% of the screen height.
@@ -1947,6 +2086,14 @@ Window
be the default behavior. Currently only affects X11 VOs.
``--heartbeat-cmd=<command>``
.. warning::
This option is redundant with Lua scripting. Further, it shouldn't be
needed for disabling screensaver anyway, since mpv will call
``xdg-screensaver`` when using X11 backend. As a consequence this
option has been deprecated with no direct replacement.
Command that is executed every 30 seconds during playback via *system()* -
i.e. using the shell. The time between the commands can be customized with
the ``--heartbeat-interval`` option. The command is not run while playback
@@ -1972,7 +2119,7 @@ Window
.. admonition:: Example for GNOME screensaver
``mpv --heartbeat-cmd="gnome-screensaver-command -p" file``
``mpv --heartbeat-cmd="gnome-screensaver-command --deactivate" file``
``--heartbeat-interval=<sec>``
@@ -2068,9 +2215,17 @@ Window
This option might be removed in the future.
``--x11-bypass-compositor=<yes|no>``
``--x11-bypass-compositor=<yes|no|fs-only|never>``
If set to ``yes``, then ask the compositor to unredirect the mpv window
(default: no). This uses the ``_NET_WM_BYPASS_COMPOSITOR`` hint.
(default: ``fs-only``). This uses the ``_NET_WM_BYPASS_COMPOSITOR`` hint.
``fs-only`` asks the window manager to disable the compositor only in
fullscreen mode.
``no`` sets ``_NET_WM_BYPASS_COMPOSITOR`` to 0, which is the default value
as declared by the EWMH specification, i.e. no change is done.
``never`` asks the window manager to never disable the compositor.
Disc Devices
@@ -2358,7 +2513,7 @@ Demuxer
stop reading additional packets as soon as one of the limits is reached.
(The limits still can be slightly overstepped due to technical reasons.)
Set these limits highher if you get a packet queue overflow warning, and
Set these limits higher if you get a packet queue overflow warning, and
you think normal playback would be possible with a larger packet queue.
See ``--list-options`` for defaults and value range.
@@ -2383,7 +2538,7 @@ Demuxer
``--force-seekable=<yes|no>``
If the player thinks that the media is not seekable (e.g. playing from a
pipe, or it's a http stream with a server that doesn't support range
pipe, or it's an http stream with a server that doesn't support range
requests), seeking will be disabled. This option can forcibly enable it.
For seeks within the cache, there's a good chance of success.
@@ -2453,7 +2608,7 @@ Input
automatically enabled when ``-`` is found on the command line. There are
situations where you have to set it manually, e.g. if you open
``/dev/stdin`` (or the equivalent on your system), use stdin in a playlist
or intend to read from stdin later on via the loadfile or loadlist slave
or intend to read from stdin later on via the loadfile or loadlist input
commands.
``--input-ipc-server=<filename>``
@@ -2575,7 +2730,7 @@ OSD
(default), then the playback time, duration, and some more information is
shown.
This is also used for the ``show_progress`` command (by default mapped to
This is also used for the ``show-progress`` command (by default mapped to
``P``), or in some non-default cases when seeking.
``--osd-status-msg`` is a legacy equivalent (but with a minor difference).
@@ -2583,7 +2738,7 @@ OSD
``--osd-status-msg=<string>``
Show a custom string during playback instead of the standard status text.
This overrides the status text used for ``--osd-level=3``, when using the
``show_progress`` command (by default mapped to ``P``), or in some
``show-progress`` command (by default mapped to ``P``), or in some
non-default cases when seeking. Expands properties. See
`Property Expansion`_.
@@ -2844,7 +2999,7 @@ Screenshot
insert the number of the current month as number. You have to use
multiple ``%tX`` specifiers to build a full date/time string.
``%{prop[:fallback text]}``
Insert the value of the slave property 'prop'. E.g. ``%{filename}`` is
Insert the value of the input property 'prop'. E.g. ``%{filename}`` is
the same as ``%f``. If the property does not exist or is not available,
an error text is inserted, unless a fallback is specified.
``%%``
@@ -3093,7 +3248,7 @@ TV
If <chan> is an integer greater than 1000, it will be treated as
frequency (in kHz) rather than channel name from frequency table.
Use _ for spaces in names (or play with quoting ;-) ). The channel
names will then be written using OSD, and the slave commands
names will then be written using OSD, and the input commands
``tv_step_channel``, ``tv_set_channel`` and ``tv_last_channel``
will be usable for a remote control. Not compatible with
the ``frequency`` parameter.
@@ -3210,7 +3365,7 @@ Cache
With ``auto``, the cache will usually be enabled for network streams,
using the size set by ``--cache-default``. With ``yes``, the cache will
always be enabled with the size set by ``--cache-default`` (unless the
stream can not be cached, or ``--cache-default`` disables caching).
stream cannot be cached, or ``--cache-default`` disables caching).
May be useful when playing files from slow media, but can also have
negative effects, especially with file formats that require a lot of
@@ -3516,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
@@ -3524,7 +3679,7 @@ Miscellaneous
frame dropping due to the audio "overshooting" and skipping multiple video
frames before the sync logic can react.
``--video-sync-adrop-size=<value``
``--video-sync-adrop-size=<value>``
For the ``--video-sync=display-adrop`` mode. This mode duplicates/drops
audio data to keep audio in sync with video. To avoid audio artifacts on
jitter (which would add/remove samples all the time), this is done in
@@ -3542,7 +3697,7 @@ Miscellaneous
``--stream-capture=<filename>``
Allows capturing the primary stream (not additional audio tracks or other
kind of streams) into the given file. Capturing can also be started and
stopped by changing the filename with the ``stream-capture`` slave property.
stopped by changing the filename with the ``stream-capture`` property.
Generally this will not produce usable results for anything else than MPEG
or raw streams, unless capturing includes the file headers and is not
interrupted. Note that, due to cache latencies, captured data may begin and
@@ -3586,6 +3741,16 @@ Miscellaneous
``--audio-file``, this includes all tracks, and does not cause default
stream selection over the "proper" file.
``--autoload-files=<yes|no>``
Automatically load/select external files (default: yes).
If set to ``no``, then do not automatically load external files as specified
by ``--sub-auto`` and ``--audio-file-auto``. If external files are forcibly
added (like with ``--sub-file``), they will not be auto-selected.
This does not affect playlist expansion, redirection, or other loading of
referenced files like with ordered chapters.
``--lavfi-complex=<string>``
Set a "complex" libavfilter filter, which means a single filter graph can
take input from multiple source audio and video tracks. The graph can result
@@ -3597,7 +3762,7 @@ Miscellaneous
- A label of the form ``aidN`` selects audio track N as input (e.g.
``aid1``).
- A label of the form ``vidN`` selects video track N as input.
- A label named ``ao`` will be connected to the audio input.
- A label named ``ao`` will be connected to the audio output.
- A label named ``vo`` will be connected to the video output.
Each label can be used only once. If you want to use e.g. an audio stream
@@ -3605,7 +3770,7 @@ Miscellaneous
video or audio outputs are not possible, but you can use filters to merge
them into one.
The complex filter can not be changed yet during playback. It's also not
The complex filter cannot be changed yet during playback. It's also not
possible to change the tracks connected to the filter at runtime. Other
tracks, as long as they're not connected to the filter, and the
corresponding output is not connected to the filter, can still be freely
@@ -3634,4 +3799,5 @@ Miscellaneous
- ``null:// --lavfi-complex='life [vo]'``
Conways' Life Game.
See the FFmpeg libavfilter documentation for details on the filter.
See the FFmpeg libavfilter documentation for details on the available
filters.
+2 -2
View File
@@ -266,6 +266,6 @@ Example
You could put this into ``input.conf`` to hide the OSC with the ``a`` key and
to set auto mode (the default) with ``b``::
a script_message osc-visibility never
b script_message osc-visibility auto
a script-message osc-visibility never
b script-message osc-visibility auto
+30 -2
View File
@@ -214,7 +214,7 @@ Available filters are:
Format name, e.g. rgb15, bgr24, 420p, etc. (default: don't change).
``<outfmt>``
Format name that should be substituted for the output. If they do not
have the same bytes per pixel and chroma subsamplimg, it will fail.
have the same bytes per pixel and chroma subsampling, it will fail.
``<colormatrix>``
Controls the YUV to RGB color space conversion when playing video. There
are various standards. Normally, BT.601 should be used for SD video, and
@@ -288,6 +288,8 @@ Available filters are:
:adobe: Adobe RGB (1998)
:prophoto: ProPhoto RGB (ROMM)
:cie1931: CIE 1931 RGB
:dci-p3: DCI-P3 (Digital Cinema)
:v-gamut: Panasonic V-Gamut primaries
``<gamma>``
Gamma function the source file was encoded with. Normally this should be set
@@ -303,13 +305,24 @@ Available filters are:
Available gamma functions are:
:auto: automatic selection (default)
:bt.1886: ITU-R BT.1886 (approximation of BT.601/BT.709/BT.2020 curve)
:bt.1886: ITU-R BT.1886 (EOTF corresponding to BT.601/BT.709/BT.2020)
:srgb: IEC 61966-2-4 (sRGB)
:linear: Linear light
:gamma1.8: Pure power curve (gamma 1.8)
:gamma2.2: Pure power curve (gamma 2.2)
:gamma2.8: Pure power curve (gamma 2.8)
:prophoto: ProPhoto RGB (ROMM) curve
:st2084: SMPTE ST2084 (HDR) curve
:std-b67: ARIB STD-B67 (Hybrid Log-gamma) curve
:v-log: Panasonic V-Log transfer curve
``<peak>``
Reference peak illumination for the video file. This is mostly
interesting for HDR, but it can also be used tone map SDR content
to a darker or brighter exposure.
The default of 0.0 will default to the display's reference brightness
for SDR and the source's reference brightness for HDR.
``<stereo-in>``
Set the stereo mode the video is assumed to be encoded in. Takes the
@@ -800,6 +813,21 @@ Available filters are:
This filter must be specified before ``vdpaupp`` in the filter chain if
``vdpaupp`` is used.
``d3d11vpp``
Direct3D 11 video post processing. Currently requires D3D11 hardware
decoding for use.
``deint=<yes|no>``
Whether deinterlacing is enabled (default: no).
``interlaced-only=<yes|no>``
If ``yes`` (default), only deinterlace frames marked as interlaced.
``mode=<blend|bob|adaptive|mocomp|ivctc|none>``
Tries to select a video processor with the given processing capability.
If a video processor supports multiple capabilities, it is not clear
which algorithm is actually selected. ``none`` always falls back. On
most if not all hardware, this option will probably do nothing, because
a video processor usually supports all modes or none.
``buffer=<num>``
Buffer ``<num>`` frames in the filter chain. This filter is probably pretty
useless, except for debugging. (Note that this won't help to smooth out
+242 -75
View File
@@ -362,6 +362,9 @@ Available video output drivers are:
exchange for adding some blur. This filter is good at temporal
interpolation, and also known as "smoothmotion" (see ``tscale``).
``linear``
A ``tscale`` filter.
``custom``
A user-defined custom shader (see ``scale-shader``).
@@ -465,7 +468,7 @@ Available video output drivers are:
8
Dither to 8 bit output.
Note that the depth of the connected video display device can not be
Note that the depth of the connected video display device cannot be
detected. Often, LCD panels will do dithering on their own, which
conflicts with ``opengl``'s dithering and leads to ugly output.
@@ -582,68 +585,6 @@ Available video output drivers are:
better than without it) since it will extend the size to match only the
milder of the scale factors between the axes.
``prescale-luma=<filter>``
Apply additional pre-scaling (image doubling) on the luma plane
(if present). As the name implies, these will run before the main
upscaling pass.
``none``
Disable all prescalers. This is the default.
``superxbr``
A relatively fast prescaler originally developed for pixel art.
Some parameters can be tuned with ``superxbr-sharpness`` and
``superxbr-edge-strength`` options.
``nnedi3``
An artificial neural network based deinterlacer, which can be used
to upscale images.
Extremely slow and requires a recent mid or high end graphics card
to work smoothly (as of 2015).
``prescale-passes=<1..5>``
The number of passes to apply the prescaler (defaults to be 1). Setting
it to 2 will perform a 4x upscaling.
``prescale-downscaling-threshold=<0..32>``
This option prevents "overkill" use of prescalers, which can be caused
by misconfiguration, or user trying to play a video with much larger
size. With this option, user can specify the maximal allowed downscaling
ratio in both dimension. To satisfy it, the number of passes for
prescaler will be reduced, and if necessary prescaler could also be
disabled.
The default value is 2.0, and should be able to prevent most seemingly
unreasonable use of prescalers. Most user would probably want to set it
to a smaller value between 1.0 and 1.5 for better performance.
A value less than 1.0 will disable the check.
``nnedi3-neurons=<16|32|64|128>``
Specify the neurons for nnedi3 prescaling (defaults to be 32). The
rendering time is expected to be linear to the number of neurons.
``nnedi3-window=<8x4|8x6>``
Specify the size of local window for sampling in nnedi3 prescaling
(defaults to be ``8x4``). The ``8x6`` window produces sharper images,
but is also slower.
``nnedi3-upload=<ubo|shader>``
Specify how to upload the NN weights to GPU. Depending on the graphics
card, driver, shader compiler and nnedi3 settings, both method can be
faster or slower.
``ubo``
Upload these weights via uniform buffer objects. This is the
default. (requires OpenGL 3.1 / GLES 3.0)
``shader``
Hard code all the weights into the shader source code. (requires
OpenGL 3.3 / GLES 3.0)
``pre-shaders=<files>``, ``post-shaders=<files>``, ``scale-shader=<file>``
Custom GLSL fragment shaders.
@@ -691,6 +632,9 @@ Available video output drivers are:
never resets (regardless of seeks).
vec2 image_size
The size in pixels of the input image.
vec2 target_size
The size in pixels of the visible part of the scaled (and possibly
cropped) image.
For example, a shader that inverts the colors could look like this::
@@ -700,6 +644,152 @@ Available video output drivers are:
return vec4(1.0 - color.rgb, color.a);
}
``user-shaders=<files>``
Custom GLSL hooks. These are similar to ``post-shaders`` etc., but more
flexible: They can be injected at almost arbitrary points in the
rendering pipeline, and access all previous intermediate textures.
.. admonition:: Warning
The syntax is not stable yet and may change any time.
The general syntax of a user shader looks like this::
//!METADATA ARGS...
//!METADATA ARGS...
vec4 hook() {
...
return something;
}
//!METADATA ARGS...
//!METADATA ARGS...
...
Each block of metadata, along with the non-metadata lines after it,
defines a single pass. Each pass can set the following metadata:
HOOK <name> (required)
The texture which to hook into. May occur multiple times within a
metadata block, up to a predetermined limit. See below for a list
of hookable textures.
BIND <name>
Loads a texture and makes it available to the pass, and sets up
macros to enable accessing it. See below for a list of set macros.
By default, no textures are bound. The special name HOOKED can be
used to refer to the texture that triggered this pass.
SAVE <name>
Gives the name of the texture to save the result of this pass
into. By default, this is set to the special name HOOKED which has
the effect of overwriting the hooked texture.
WIDTH <szexpr>, HEIGHT <szexpr>
Specifies the size of the resulting texture for this pass.
``szexpr`` refers to an expression in RPN (reverse polish
notation), using the operators + - * / > < !, floating point
literals, and references to sizes of existing texture and OUTPUT
(such as MAIN.width or CHROMA.height). By default, these are set to
HOOKED.w and HOOKED.h, respectively.
WHEN <szexpr>
Specifies a condition that needs to be true (non-zero) for the
shader stage to be evaluated. If it fails, it will silently be
omitted. (Note that a shader stage like this which has a dependency
on an optional hook point can still cause that hook point to be
saved, which has some minor overhead)
OFFSET ox oy
Indicates a pixel shift (offset) introduced by this pass. These
pixel offsets will be accumulated and corrected during the
next scaling pass (``cscale`` or ``scale``). The default values
are 0 0 which correspond to no shift. Note that offsets are ignored
when not overwriting the hooked texture.
COMPONENTS n
Specifies how many components of this pass's output are relevant
and should be stored in the texture, up to 4 (rgba). By default,
this value is equal to the number of components in HOOKED.
Each bound texture (via ``BIND``) will make available the following
definitions to that shader pass, where NAME is the name of the bound
texture:
vec4 NAME_tex(vec2 pos)
The sampling function to use to access the texture at a certain
spot (in texture coordinate space, range [0,1]). This takes care
of any necessary normalization conversions.
vec4 NAME_texOff(vec2 offset)
Sample the texture at a certain offset in pixels. This works like
NAME_tex but additionally takes care of necessary rotations, so
that sampling at e.g. vec2(-1,0) is always one pixel to the left.
vec2 NAME_pos
The local texture coordinate of that texture, range [0,1].
vec2 NAME_size
The (rotated) size in pixels of the texture.
mat2 NAME_rot
The rotation matrix associated with this texture. (Rotates
pixel space to texture coordinates)
vec2 NAME_pt
The (unrotated) size of a single pixel, range [0,1].
sampler NAME_raw
The raw bound texture itself. The use of this should be
avoided unless absolutely necessary.
In addition, the global uniforms described in ``post-shaders`` are
also available.
Internally, vo_opengl may generate any number of the following
textures. Whenever a texture is rendered and saved by vo_opengl, all of
the passes that have hooked into it will run, in the order they were
added by the user. This is a list of the legal hook points:
RGB, LUMA, CHROMA, ALPHA, XYZ (resizable)
Source planes (raw). Which of these fire depends on the image
format of the source.
CHROMA_SCALED, ALPHA_SCALED (fixed)
Source planes (upscaled). These only fire on subsampled content.
NATIVE (resizable)
The combined image, in the source colorspace, before conversion
to RGB.
MAINPRESUB (resizable)
The image, after conversion to RGB, but before
``blend-subtitles=video`` is applied.
MAIN (resizable)
The main image, after conversion to RGB but before upscaling.
LINEAR (fixed)
Linear light image, before scaling. This only fires when
``linear-scaling`` is in effect.
SIGMOID (fixed)
Sigmoidized light, before scaling. This only fires when
``sigmoid-upscaling`` is in effect.
PREKERNEL (fixed)
The image immediately before the scaler kernel runs.
POSTKERNEL (fixed)
The image immediately after the scaler kernel runs.
SCALED (fixed)
The final upscaled image, before color management.
OUTPUT (fixed)
The final output image, after color management but before
dithering and drawing to screen.
Only the textures labelled with ``resizable`` may be transformed by the
pass. When overwriting a texture marked ``fixed``, the WIDTH, HEIGHT
and OFFSET must be left at their default values.
``deband``
Enable the debanding algorithm. This greatly reduces the amount of
visible banding, blocking and other quantization artifacts, at the
@@ -791,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.
@@ -807,8 +907,8 @@ Available video output drivers are:
Win32/WGL
angle
Direct3D11 through the OpenGL ES translation layer ANGLE. This
supports almost everything the ``win`` backend does, except ICC
profiles, and the ``nnedi3`` prescaler.
supports almost everything the ``win`` backend does (if the ANGLE
build is new enough).
dxinterop (experimental)
Win32, using WGL for rendering and Direct3D 9Ex for presentation.
Works on Nvidia and AMD. Newer Intel chips with the latest drivers
@@ -835,10 +935,11 @@ Available video output drivers are:
``fbo-format=<fmt>``
Selects the internal format of textures used for FBOs. The format can
influence performance and quality of the video output.
``fmt`` can be one of: rgb, rgba, rgb8, rgb10, rgb10_a2, rgb16, rgb16f,
``fmt`` can be one of: rgb8, rgb10, rgb10_a2, rgb16, rgb16f,
rgb32f, rgba12, rgba16, rgba16f, rgba32f.
Default: ``auto``, which maps to rgba16 on desktop GL, and rgba16f or
rgb10_a2 on GLES (e.g. ANGLE).
rgb10_a2 on GLES (e.g. ANGLE), unless GL_EXT_texture_norm16 is
available.
``gamma=<0.1..2.0>``
Set a gamma value (default: 1.0). If gamma is adjusted in other ways
@@ -854,6 +955,10 @@ Available video output drivers are:
0.8
Pitch black room
NOTE: Typical movie content (Blu-ray etc.) already contains a gamma
drop of about 0.8, so specifying it here as well will result in even
even darker image than intended!
``gamma-auto``
Automatically corrects the gamma value depending on ambient lighting
conditions (adding a gamma boost for dark rooms).
@@ -864,8 +969,9 @@ Available video output drivers are:
NOTE: Only implemented on OS X.
``target-prim=<value>``
Specifies the primaries of the display. Video colors will be adapted
to this colorspace if necessary. Valid values are:
Specifies the primaries of the display. Video colors will be adapted to
this colorspace when ICC color management is not being used. Valid
values are:
auto
Disable any adaptation (default)
@@ -889,15 +995,18 @@ Available video output drivers are:
CIE 1931 RGB (not to be confused with CIE XYZ)
dci-p3
DCI-P3 (Digital Cinema Colorspace), SMPTE RP431-2
v-gamut
Panasonic V-Gamut (VARICAM) primaries
``target-trc=<value>``
Specifies the transfer characteristics (gamma) of the display. Video
colors will be adjusted to this curve. Valid values are:
colors will be adjusted to this curve when ICC color management is
not being used. Valid values are:
auto
Disable any adaptation (default)
bt.1886
ITU-R BT.1886 curve, without the brightness drop (approx. 1.961)
ITU-R BT.1886 curve (assuming infinite contrast)
srgb
IEC 61966-2-4 (sRGB)
linear
@@ -910,9 +1019,61 @@ Available video output drivers are:
Pure power curve (gamma 2.8), also used for BT.470-BG
prophoto
ProPhoto RGB (ROMM)
st2084
SMPTE ST2084 (HDR) curve, PQ OETF
std-b67
ARIB STD-B67 (Hybrid Log-gamma) curve, also known as BBC/NHK HDR
v-log
Panasonic V-Log (VARICAM) curve
NOTE: When using HDR output formats, mpv will encode to the specified
curve but it will not set any HDMI flags or other signalling that
might be required for the target device to correctly display the
HDR signal. The user should independently guarantee this before
using these signal formats for display.
``target-brightness=<1..100000>``
Specifies the display's approximate brightness in cd/m^2. When playing
HDR content on a SDR display (or SDR content on an HDR display), video
colors will be tone mapped to this target brightness using the
algorithm specified by ``hdr-tone-mapping``. The default of 250 cd/m^2
corresponds to a typical consumer display.
``hdr-tone-mapping=<value>``
Specifies the algorithm used for tone-mapping HDR images onto the
target display. Valid values are:
clip
Hard-clip any out-of-range values.
reinhard
Reinhard tone mapping algorithm. Very simple continuous curve.
Preserves dynamic range and peak but uses nonlinear contrast.
hable
Similar to ``reinhard`` but preserves dark contrast better
(slightly sigmoidal). Developed by John Hable for use in video
games. (default)
gamma
Fits a logarithmic transfer between the tone curves.
linear
Linearly stretches the entire reference gamut to (a linear multiple
of) the display.
``tone-mapping-param=<value>``
Set tone mapping parameters. Ignored if the tone mapping algorithm is
not tunable. This affects the following tone mapping algorithms:
reinhard
Specifies the local contrast coefficient at the display peak.
Defaults to 0.5, which means that in-gamut values will be about
half as bright as when clipping.
gamma
Specifies the exponent of the function. Defaults to 1.8.
linear
Specifies the scale factor to use while stretching. Defaults to
1.0.
``icc-profile=<file>``
Load an ICC profile and use it to transform linear RGB to screen output.
Load an ICC profile and use it to transform video RGB to screen output.
Needs LittleCMS 2 support compiled in. This option overrides the
``target-prim``, ``target-trc`` and ``icc-profile-auto`` options.
@@ -947,8 +1108,14 @@ Available video output drivers are:
``3dlut-size=<r>x<g>x<b>``
Size of the 3D LUT generated from the ICC profile in each dimension.
Default is 128x256x64.
Sizes must be a power of two, and 512 at most.
Default is 64x64x64. Sizes may range from 2 to 512.
``icc-contrast=<0-100000>``
Specifies an upper limit on the target device's contrast ratio.
This is detected automatically from the profile if possible, but for
some profiles it might be missing, causing the contrast to be assumed
as infinite. As a result, video may appear darker than intended. This
only affects BT.1886 content. The default of 0 means no limit.
``blend-subtitles=<yes|video|no>``
Blend subtitles directly onto upscaled video frames, before
@@ -1145,7 +1312,7 @@ Available video output drivers are:
This also supports many of the suboptions the ``opengl`` VO has. Run
``mpv --vo=opengl-cb:help`` for a list.
This also supports the ``vo_cmdline`` command.
This also supports the ``vo-cmdline`` command.
``rpi`` (Raspberry Pi)
Native video output on the Raspberry Pi using the MMAL API.
+8 -7
View File
@@ -30,7 +30,7 @@ Player
* Slave mode compatibility broken (see below).
* Re-enable screensaver while the player is paused.
* Allow resuming playback at a later point with ``Shift+q``, also see the
``quit_watch_later`` input command.
``quit-watch-later`` input command.
* ``--keep-open`` option to stop the player from closing the window and
exiting after playback ends.
* A client API, that allows embedding **mpv** into applications
@@ -79,7 +79,8 @@ Video
using most of FFmpeg's filters, which improve greatly on the old MPlayer
filters in features, performance, and correctness.
* More correct color reproduction (color matrix generation), including support
for BT.2020 (Ultra HD) and linear XYZ (Digital Cinema) inputs.
for BT.2020 (Ultra HD). linear XYZ (Digital Cinema) and SMPTE ST2084 (HDR)
inputs.
* Support for color managed displays, via ICC profiles.
* High-quality image resamplers (see the ``opengl`` ``scale`` suboption).
* Support for scaling in (sigmoidized) linear light.
@@ -311,11 +312,11 @@ input.conf and Slave Commands
+--------------------------------+----------------------------------------+
| Old | New |
+================================+========================================+
| ``pt_step 1 [0|1]`` | ``playlist_next [weak|force]`` |
| ``pt_step 1 [0|1]`` | ``playlist-next [weak|force]`` |
| | (translation layer cannot deal with |
| | whitespace) |
+--------------------------------+----------------------------------------+
| ``pt_step -1 [0|1]`` | ``playlist_prev [weak|force] (same)`` |
| ``pt_step -1 [0|1]`` | ``playlist-prev [weak|force] (same)`` |
+--------------------------------+----------------------------------------+
| ``switch_ratio [<ratio>]`` | ``set video-aspect <ratio>`` |
| | |
@@ -330,7 +331,7 @@ input.conf and Slave Commands
| ``<step> <dir>`` | ``no-osd``: ``no-osd cycle <prop>`` |
| | ``<step>`` |
+--------------------------------+----------------------------------------+
| ``osd_show_property_text`` | ``show_text <text>`` |
| ``osd_show_property_text`` | ``show-text <text>`` |
| ``<text>`` | The property expansion format string |
| | syntax slightly changed. |
+--------------------------------+----------------------------------------+
@@ -339,9 +340,9 @@ input.conf and Slave Commands
| | ``raw`` prefix to disable property |
| | expansion. |
+--------------------------------+----------------------------------------+
| ``show_tracks`` | ``show_text ${track-list}`` |
| ``show_tracks`` | ``show-text ${track-list}`` |
+--------------------------------+----------------------------------------+
| ``show_chapters`` | ``show_text ${chapter-list}`` |
| ``show_chapters`` | ``show-text ${chapter-list}`` |
+--------------------------------+----------------------------------------+
| ``af_switch``, ``af_add``, ... | ``af set|add|...`` |
+--------------------------------+----------------------------------------+
+2 -1
View File
@@ -25,7 +25,8 @@ Release procedure
- Create and/or update the `VERSION` file.
- Update `DOCS/client-api-changes.rst` (on major releases).
- Update `DOCS/client-api-changes.rst` and `DOCS/interface-changes.rst`
(in particular, update the last version numbers if necessary)
- Create tag v0.X.Y.
+1 -1
View File
@@ -123,7 +123,7 @@ options/options.h, options/options.c
parser-mpcmd.c, and uses the option table in options.c.
input/input.c:
This translates keyboard input comming from VOs and other sources (such
This translates keyboard input coming from VOs and other sources (such
as remote control devices like Apple IR or client API commands) to the
key bindings listed in the user's (or the builtin) input.conf and turns
them into items of type struct mp_cmd. These commands are queued, and read
+14
View File
@@ -137,6 +137,20 @@ most likely the best maintenance out of all stable releases. Older releases
are for distros, and at best receive basic changes like fixing critical security
issues or build fixes, and at worst are completely abandoned.
## FFmpeg ABI compatibility
mpv does not support linking against FFmpeg versions it was not built with, even
if the linked version is supposedly ABI-compatible with the version it was
compiled against. Expect malfunctions, crashes, and security issues if you
do it anyway.
The reason for not supporting this is because it creates far too much complexity
with little to no benefit, coupled with absurd and unusable FFmpeg API
artifacts.
Newer mpv versions will refuse to start if runtime and compile time FFmpeg
library versions mismatch.
## Release cycle
Every other month, an arbitrary git snapshot is made, and is assigned
+388
View File
@@ -1,3 +1,391 @@
Release 0.20.0
==============
Options and Commands
--------------------
Added
~~~~~
- aspect: add --video-unscaled=downscale-big
- player: add --image-display-duration option to control duration of image display (#3425)
- vo_opengl: angle: new flag (dcomposition) to control DirectComposition
Fixes and Minor Enhancements
----------------------------
- af_lavrresample: fix error if resampler could not be recreated
- audio: avoid missed wakeups with ab-loops
- audio: do not apply --audio-channels if spdif passthrough is in use (#3445)
- cache: don't use a backbuffer if the cache is as large as the file
- command: prevent O(n^2) behaviour for playlist property
- demux: close underlying stream if it's fully read anyway (#3456)
- demux: fix undefined behavior with ogg metadata update (#3451)
- player: make looping slightly more seamless
- player: refresh very low framerate video on filter changes (#3435)
- stream_memory: disable stream cache
- vf_rotate: allow arbitrary rotation (#3434)
- vo: be more trusting to estimated display FPS (#3433)
- w32_common: use hooks to detect parent window resize
- x11: work around mutter fullscreen issue (#2072)
This listing is not complete. Check DOCS/client-api-changes.rst for a history
of changes to the client API, and DOCS/interface-changes.rst for a history
of changes to other user-visible interfaces.
A complete changelog can be seen by running `git log v0.19.0..v0.20.0`
in the git repository or by visiting either
https://github.com/mpv-player/mpv/compare/v0.19.0...v0.20.0 or
http://git.srsfckn.biz/mpv/log/?qt=range&q=v0.20.0..v0.20.0
Release 0.19.0
==============
Build System Changes
--------------------
- build: add --htmldir option
- build: always require atomics
- wscript: add proper unversioned SONAME for Android
Features
--------
New
~~~
- client API: add stream_cb API for user-defined stream implementations (bumps client API version to 1.22)
- vf_d3d11vpp: add video processor selection
- videotoolbox: add --hwdec=videotoolbox-copy for h/w accelerated decoding with video filters
- vo_opengl: add a tscale=linear direct implementation
Removed
~~~~~~~
- audio/filter: remove delay audio filter
Options and Commands
--------------------
Added
~~~~~
- command: add filename/no-ext sub-property that returns filename without extension (#3404)
- command: add properties for HDR metadata
- command: add replaygain information properties to track-list
- options: add vp9 to --hwdec-codecs
- player: add --audio-stream-silence
- player: add --audio-wait-open
- player: add --no-autoload-files
- videotoolbox: add yuv420p to --videotoolbox-format
Changed
~~~~~~~
- options: un-restrict --audio-delay
- use - as command-name separator everywhere
- vo_opengl: reduce default 3dlut-size to 64x64x64 (since accuracy is improved)
Deprecated
~~~~~~~~~~
- deprecate "balance" option/property (no replacement)
Fixes and Minor Enhancements
----------------------------
- Windows: don't wait for GUI thread when polling for events (#3393)
- af_lavcac3enc: error out properly if encoding fails
- af_volume: don't let softvol overwrite af_volume volumedb sub-option
- ao_pulse: fix some volume control rounding issues
- ao_wasapi: in exclusive mode, do not output multichannel by default
- audio: add heuristic to move auto-downmixing before other filters
- audio: show an osd bar when changing ao-volume
- demux: make ALBUM replaygain tags optional (#3405)
- demux_raw: fix small typo to add s16be support
- demux_timeline: restore mkv edition switching
- libarchive: sanitize non-UTF8 archive entries
- macOS/vo_opengl: fix crash when glctx is NULL during init (#3360)
- player: disable display-sync with spdif transcoding
- player: do not cut off terminal status line if it contains newlines (#3340)
- player: fix display-sync timing if audio resumes slowly
- player: improve instant track switching (#3392)
- player: improve non-hr seeking with external audio tracks
- player: offset demuxer on start/seek properly with audio/sub delay
- player: sync audio as well when enabling it mid-stream
- stream/stream_bluray: display list of available titles in verbose mode
- sub: don't potentially discard too many subtitles on seek
- video: respect --deinterlace=auto
- vo_direct3d: add missing header (fixes Cygwin build)
- vo_opengl: angle: try D3D9 when D3D11 fails eglInitialize
- vo_opengl: angle: use WARP if there are no hw adapters (makes it work on Windows 7 without hardware-accelerated graphics)
- vo_opengl: increase 3DLUT accuracy at smaller LUT sizes
- vo_opengl: remove the 3dlut-size npot2 restriction
- vo_wayland: fix high CPU usage due to busy polling
- wayland_common: clip window size to the display output size
- wayland_common: fix crashes when switching to fullscreen before the video output is fully initialized
- wayland_common: fix fullscreen image switching bug
- wayland_common: prevent black bars on most non-native aspect ratios
- wayland_common: remove untested/unusable wayland dnd code
- win32: mpv.rc: re-add version info
- x11: skip ICC update on every window move
- ytdl: Error out with http_dash_segments (unsupported for now)
This listing is not complete. Check DOCS/client-api-changes.rst for a history
of changes to the client API, and DOCS/interface-changes.rst for a history
of changes to other user-visible interfaces.
A complete changelog can be seen by running `git log v0.18.1..v0.19.0`
in the git repository or by visiting either
https://github.com/mpv-player/mpv/compare/v0.18.1...v0.19.0 or
http://git.srsfckn.biz/mpv/log/?qt=range&q=v0.18.1..v0.19.0
Release 0.18.1
==============
Note: Running mpv with different versions of the FFmpeg/Libav libraries than
it was compiled with is no longer supported. Even supposedly ABI-compatible
versions have been a source of trouble, and it creates far too much
complexity with little to no benefit, coupled with absurd and unusable FFmpeg
API artifacts.
Instead, mpv will exit with an error when such a situation is detected.
This simply means that mpv needs to be rebuilt whenever FFmpeg libraries change.
Features
--------
New
~~~
- d3d: implement screenshots for --hwdec=d3d11va
- vo_opengl: add output_size uniform to custom shader
- vo_opengl: implement the Panasonic V-Log function (#3157)
- vo_opengl: implement ARIB STD-B68 (HLG) HDR TRC
Options and Commands
--------------------
Changed
~~~~~~~
- command: pack sub image data in overlay-add command
Deprecated
~~~~~~~~~~
- options: deprecate --heartbeat-cmd
- audio: deprecate --softvol
Removed
~~~~~~~
- audio: drop --softvol=no and --softvol=auto (#3322)
Fixes and Minor Enhancements
----------------------------
- video: fix deinterlace filter handling on pixel format changes
- x11: silence xdg-screensaver
- vo_opengl: angle: update the swapchain on resize (#3301)
- vo_opengl: error out gracefully when trying to use FBOs without FBO API
- vd_lavc: expose mastering display side data reference peak (improves results with HDR content)
- vo_opengl: generalize HDR tone mapping mechanism (#3293)
- vo_opengl: don't constantly resize the output FBO
- vo_opengl: use ringbuffer of PBOs
- Windows: make WM_NCHITTEST simpler and more accurate
- ao_oss: do not add an entry to audio-device-list if device file missing
- dec_audio: fix segment boudnary switching
- ao_lavc, vo_lavc: Migrate to new FFmpeg encoding API
- vo_opengl: explicitly use main framebuffer when reading window content (#3284)
- vo_xv: fix behavior with odd sizes
- audio: insert auto-inserted filters at end of chain
- x11: add missing FocusChangeMask (disables key repeat when losing focus while a key is down)
- ao_coreaudio: error out when selecting invalid device
- ad_lavc: work around misbehavior of some FFmpeg decoders like wmapro (#3297)
- player: cut off status line on terminal width
This listing is not complete. Check DOCS/client-api-changes.rst for a history
of changes to the client API, and DOCS/interface-changes.rst for a history
of changes to other user-visible interfaces.
A complete changelog can be seen by running `git log v0.18.0..v0.18.1`
in the git repository or by visiting either
https://github.com/mpv-player/mpv/compare/v0.18.0...v0.18.1 or
http://git.srsfckn.biz/mpv/log/?qt=range&q=v0.18.0..v0.18.1
Release 0.18.0
==============
Build System Changes
--------------------
- build: Do not link to libGL for egl-drm
- build: also use the iconv check on FreeBSD
- build: don't install tests, only build them
- build: re-enable encoding mode by default
- vo_opengl: hwdec: remove build-dependency on dxva2 (#3150)
- wscript: make at least 1 OpenGL output mandatory
Features
--------
New
~~~
- csputils: add SMPTE ST2084 support
- demux_mkv: support Matroska webvtt (#3247)
- demux_playlist: read directories recursively
- stream_memory: add hex:// protocol
- vf_crop: support opaque hardware decoding formats
- vf_d3d11vpp: add a D3D11 video processor filter
- vo_opengl: D3D11VA + ANGLE interop
- vo_opengl: add an angle-es2 backend
- vo_opengl: angle: dynamically load ANGLE
- vo_opengl: d3d11egl: native NV12 sampling support
- vo_opengl: enable color management on GLES
- vo_opengl: implement HDR (SMPTE ST2084)
- vo_opengl: implement tone mapping algorithms
- vo_opengl: make PBOs work on GLES 3.x
- vo_opengl: support external user hooks, enhancing the flexibility of user shaders
- vo_opengl: vdpau interop without RGB conversion
- wayland: implement HIDPI support
Removed
~~~~~~~
- vo_opengl: remove nnedi3 prescaler (replaced by user shaders)
- vo_opengl: remove prescaling framework with superxbr prescaler (replaced by user shaders)
Options and Commands
--------------------
Added
~~~~~
- Windows: make taskbar progress indication optional (#2535)
- af_lavcac3enc: make encoder configurable
- command: add playlist-pos-1 property (#2828)
- command: introduce hwdec-current and hwdec-interop properties.
- options: add --fit-border video option (currently Windows only)
- video: add --hwdec=auto-copy mode
- vo_opengl: always autoselect ANGLE as backend if available
- vo_opengl: expose performance timers as properties
- x11: add --x11-bypass-compositor=never
- x11: extend --x11-bypass-compositor with fs-only option (#2582)
Changed
~~~~~~~
- command: allow setting panscan etc. properties if no video is active
- command: don't seek immediately when setting a-b loop while paused
- command: if only ab-loop-b is set, loop from start of file
- options: --geometry: center window position after applying size (#2397)
- player: loop on end of file if ab-loop-b is unset
- sd_add: replace --sub-ass=no with --ass-style-override=strip
Removed
~~~~~~~
- vo_opengl: remove non-working rgb/rgba FBO formats
Fixes and Minor Enhancements
----------------------------
- TOOLS/zsh.pl: add .f4v extension in zsh completions
- TOOLS/zsh.pl: complete --audio-device
- Windows: center window on original window center on resize to fit screen
- Windows: fix size calculations for window resize (#2935)
- Windows: fix wrong behavior with window-scale when window size exceeds screen size
- Windows: make VOCTRL_SET_UNFS_WINDOW_SIZE resize the window around its center (#3164)
- af_lavcac3enc: fix custom bitrates
- ao_alsa: add more workarounds for hardware with broken drivers (e.g. ODROID-C2)
- ao_opensles: remove 32-bit audio formats (not supported by Android)
- cocoa: fix actual display refresh rate retrieval
- cocoa: use displaylink without manually tracking the display id (#2392)
- command: improve playlist* properties change notifications (#3267)
- command: slightly nicer OSD list formatting
- compatibility with recent FFmpeg APIs
- d3d: fix hardware decoding of most MPEG2 things
- d3dva: move Intel_H264_NoFGT_ClearVideo to lower priority (#3059)
- demux_mkv: better resync behavior for broken google-created webms
- demux_mkv: fix seeking with files that miss the first index entry
- demux_playlist: recognize m3u8 as playlist extension (#3154)
- input: fix parsing multiple input command prefixes
- lcms: don't warn/error on 3dlut cache misses
- lcms: improve black point handling (especially BT.1886)
- macOS: handle multiple dropped files on the window (#3076)
- player: always show the first frame in DS mode
- player: assume video forwards timestamps jumps only with some formats (#3027)
- player: do not update OSD all the time when paused
- player: eagerly redraw OSD when seeking with coverart
- player: fix use-after-free with --screenshot-directory (#3049)
- player: force VO reconfig when unselecting video track
- player: really start audio only once video is ready
- sd_lavc: work around bug in older FFmpeg releases (#3109)
- stream_cdda: enable cache by default
- sub: fix --sub-gauss
- vd_lavc: better hwdec wrapper decoder selection
- vo_opengl: EGL: fix hwdec probing
- vo_opengl: angle: avoid fullscreen FBO copy for flipping
- vo_opengl: angle: enable DirectComposition (lowers vsync jitter)
- vo_opengl: angle: prevent DXGI hooking Alt+Enter
- vo_opengl: avoid outputting ultra-wide-gamut by default
- vo_opengl: correctly disable interpolation if tscale can't be used
- vo_opengl: fix bicubic_fast in ES mode
- vo_opengl: fix d3d11 hardware decoding probing on Windows 7
- vo_opengl: improve scale=oversample performance
- vo_opengl: make the screen blue on shader errors
- vo_opengl: partially fix 0bgr format support
- vo_opengl: possibly update icc profile after changing options
- vo_opengl: request core profile on X11/EGL too
- vo_opengl: require at least ES 3.0 for float textures
- vo_opengl: vdpau: fix certain cases of preemption recovery failures
- vo_rpi: attempt to survive display mode changes
- vo_rpi: fix destroying overlays (#3100)
- vo_rpi: wait for vsync with a timeout
- vo_sdl: fix pixel formats.
- vo_xv: Handle incorrect size returned by Xv(Shm)CreateImage (#320)
- wayland: correctly report display refresh rate
- wayland: use the advertised size in fullscreen (#3021, #2657)
- x11: tell GNOME to use dark window decorations
- ytdl_hook: fix brightcove urls
- ytdl_hook: just check if protocol is rtmp (#3090)
- ytdl_hook: support multi-arc subtitles
This listing is not complete. Check DOCS/client-api-changes.rst for a history
of changes to the client API, and DOCS/interface-changes.rst for a history
of changes to other user-visible interfaces.
A complete changelog can be seen by running `git log v0.17.0..v0.18.0`
in the git repository or by visiting either
https://github.com/mpv-player/mpv/compare/v0.17.0...v0.18.0 or
http://git.srsfckn.biz/mpv/log/?qt=range&q=v0.17.0..v0.18.0
Release 0.17.0
==============
+22
View File
@@ -0,0 +1,22 @@
#!/usr/bin/bash
set -e
export DEST_OS=win32
export CC=gcc
export PKG_CONFIG=/usr/bin/pkg-config
export PERL=/usr/bin/perl
export PYTHON=/usr/bin/python3
"$PYTHON" bootstrap.py
"$PYTHON" waf configure \
--check-c-compiler=gcc \
--disable-cdda \
--enable-egl-angle \
--enable-jpeg \
--enable-lcms2 \
--enable-libarchive \
--enable-libass \
--enable-lua \
--enable-rubberband \
--enable-uchardet
"$PYTHON" waf build
+35
View File
@@ -0,0 +1,35 @@
#!/usr/bin/bash
set -e
case $MSYSTEM in
MINGW32)
export MINGW_PACKAGE_PREFIX=mingw-w64-i686
;;
MINGW64)
export MINGW_PACKAGE_PREFIX=mingw-w64-x86_64
;;
esac
# Write an empty fonts.conf to speed up fc-cache
export FONTCONFIG_FILE=/dummy-fonts.conf
cat >"$FONTCONFIG_FILE" <<EOF
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig></fontconfig>
EOF
# Install build dependencies for mpv
pacman -S --noconfirm --needed \
$MINGW_PACKAGE_PREFIX-gcc \
$MINGW_PACKAGE_PREFIX-angleproject-git \
$MINGW_PACKAGE_PREFIX-ffmpeg \
$MINGW_PACKAGE_PREFIX-lcms2 \
$MINGW_PACKAGE_PREFIX-libarchive \
$MINGW_PACKAGE_PREFIX-libass \
$MINGW_PACKAGE_PREFIX-libjpeg-turbo \
$MINGW_PACKAGE_PREFIX-lua51 \
$MINGW_PACKAGE_PREFIX-rubberband \
$MINGW_PACKAGE_PREFIX-uchardet-git
# Delete unused packages to reduce space used in the Appveyor cache
pacman -Sc --noconfirm
+1 -1
View File
@@ -25,7 +25,7 @@ function add_files_at(index, files)
local oldcount = mp.get_property_number("playlist-count", 1)
for i = 1, #files do
mp.commandv("loadfile", files[i], "append")
mp.commandv("playlist_move", oldcount + i - 1, index + i - 1)
mp.commandv("playlist-move", oldcount + i - 1, index + i - 1)
end
end
View File
File renamed without changes.
+23 -7
View File
@@ -36,7 +36,8 @@ chomp $vf_str;
$protos_str = join(' ', @protos);
my $profile_comp = <<'EOS';
my $runtime_completions = <<'EOS';
profile|show-profile)
local -a profiles
local current
for current in "${(@f)$($words[1] --profile=help)}"; do
@@ -63,8 +64,25 @@ my $profile_comp = <<'EOS';
profiles=($profiles 'help[list profiles]')
_values -s , 'profile(s)' $profiles && rc=0
fi
;;
audio-device)
local -a audio_devices
local current
for current in "${(@f)$($words[1] --audio-device=help)}"; do
current=${current//\*/\\\*}
current=${current//\:/\\\:}
current=${current//\[/\\\[}
current=${current//\]/\\\]}
if [[ $current =~ ' '\'([^\']*)\'' \('(.*)'\)' ]]; then
audio_devices=($audio_devices "$match[1][$match[2]]")
fi
done
audio_devices=($audio_devices 'help[list audio devices]')
_values 'audio device' $audio_devices && rc=0
;;
EOS
chomp $profile_comp;
chomp $runtime_completions;
my $tmpl = <<"EOS";
#compdef mpv
@@ -111,9 +129,7 @@ $vf_str
&& rc=0
;;
profile|show-profile)
$profile_comp
;;
$runtime_completions
files)
compset -P '*,'
@@ -126,7 +142,7 @@ $profile_comp
_tags files urls
while _tags; do
_requested files expl 'media file' _files -g \\
"*.(#i)(asf|asx|avi|flac|flv|m1v|m2p|m2v|m4v|mjpg|mka|mkv|mov|mp3|mp4|mpe|mpeg|mpg|ogg|ogm|ogv|opus|qt|rm|ts|vob|wav|webm|wma|wmv|wv)(-.)" && rc=0
"*.(#i)(asf|asx|avi|f4v|flac|flv|m1v|m2p|m2v|m4v|mjpg|mka|mkv|mov|mp3|mp4|mpe|mpeg|mpg|ogg|ogm|ogv|opus|qt|rm|ts|vob|wav|webm|wma|wmv|wv)(-.)" && rc=0
if _requested urls; then
while _next_label urls expl URL; do
_urls "\$expl[@]" && rc=0
@@ -189,7 +205,7 @@ sub parse_main_opts {
}
} elsif ($line =~ /\[file\]/) {
$entry .= '->files';
} elsif ($name =~ /^--(ao|vo|af|vf|profile|show-profile)$/) {
} elsif ($name =~ /^--(ao|vo|af|vf|profile|show-profile|audio-device)$/) {
$entry .= "->$1";
}
push @list, $entry;
+1 -1
View File
@@ -1 +1 @@
0.17.0
0.20.0
+29
View File
@@ -0,0 +1,29 @@
branches:
only:
- master
- appveyor
environment:
matrix:
- MSYSTEM: MINGW64
- MSYSTEM: MINGW32
shallow_clone: true
test: off
install:
# Update core packages
- C:\msys64\usr\bin\pacman -Syyuu --noconfirm
# Update non-core packages
- C:\msys64\usr\bin\pacman -Suu --noconfirm
# Install required MSYS2 packages
- C:\msys64\usr\bin\pacman -S --noconfirm --needed perl python pkg-config
# Now MSYS2 is up to date, do the rest of the install from a bash script
- C:\msys64\usr\bin\bash -lc "cd \"$APPVEYOR_BUILD_FOLDER\" && exec ./TOOLS/appveyor-install.sh"
build_script:
- C:\msys64\usr\bin\bash -lc "cd \"$APPVEYOR_BUILD_FOLDER\" && exec ./TOOLS/appveyor-build.sh"
on_failure:
- type "%APPVEYOR_BUILD_FOLDER%\build\config.log"
cache:
- C:\msys64\var\cache\pacman\pkg
+44 -13
View File
@@ -138,6 +138,9 @@ static void mp_audio_destructor(void *ptr)
* available on every plane. The previous data is kept (for the smallest
* common number of samples before/after resize).
*
* This also makes sure the resulting buffer is writable (even in the case
* the buffer has the correct size).
*
* mpa->samples is not set or used.
*
* This function is flexible enough to handle format and channel layout
@@ -153,6 +156,12 @@ void mp_audio_realloc(struct mp_audio *mpa, int samples)
int size = get_plane_size(mpa, samples);
if (size < 0)
abort(); // oom or invalid parameters
if (!mp_audio_is_writeable(mpa)) {
for (int n = 0; n < MP_NUM_CHANNELS; n++) {
av_buffer_unref(&mpa->allocated[n]);
mpa->planes[n] = NULL;
}
}
for (int n = 0; n < mpa->num_planes; n++) {
if (!mpa->allocated[n] || size != mpa->allocated[n]->size) {
if (av_buffer_realloc(&mpa->allocated[n], size) < 0)
@@ -171,7 +180,7 @@ void mp_audio_realloc(struct mp_audio *mpa, int samples)
// If the buffer is reallocated, also preallocate.
void mp_audio_realloc_min(struct mp_audio *mpa, int samples)
{
if (samples > mp_audio_get_allocated_size(mpa)) {
if (samples > mp_audio_get_allocated_size(mpa) || !mp_audio_is_writeable(mpa)) {
size_t alloc = ta_calc_prealloc_elems(samples);
if (alloc > INT_MAX)
abort(); // oom
@@ -257,13 +266,21 @@ void mp_audio_skip_samples(struct mp_audio *data, int samples)
data->pts += samples / (double)data->rate;
}
// Return the timestamp of the sample just after the end of this frame.
double mp_audio_end_pts(struct mp_audio *f)
{
if (f->pts == MP_NOPTS_VALUE || f->rate < 1)
return MP_NOPTS_VALUE;
return f->pts + f->samples / (double)f->rate;
}
// Clip the given frame to the given timestamp range. Adjusts the frame size
// and timestamp.
void mp_audio_clip_timestamps(struct mp_audio *f, double start, double end)
{
if (f->pts == MP_NOPTS_VALUE || f->rate < 1)
double f_end = mp_audio_end_pts(f);
if (f_end == MP_NOPTS_VALUE)
return;
double f_end = f->pts + f->samples / (double)f->rate;
if (end != MP_NOPTS_VALUE) {
if (f_end >= end) {
if (f->pts >= end) {
@@ -339,9 +356,9 @@ struct mp_audio *mp_audio_from_avframe(struct AVFrame *avframe)
mp_chmap_from_lavc(&lavc_chmap, avframe->channel_layout);
#if LIBAVUTIL_VERSION_MICRO >= 100
// FFmpeg being special again
if (lavc_chmap.num != avframe->channels)
mp_chmap_from_channels(&lavc_chmap, avframe->channels);
// FFmpeg being stupid POS again
if (lavc_chmap.num != av_frame_get_channels(avframe))
mp_chmap_from_channels(&lavc_chmap, av_frame_get_channels(avframe));
#endif
new->rate = avframe->sample_rate;
@@ -386,12 +403,9 @@ fail:
return NULL;
}
// Returns NULL on failure. The input is always unreffed.
struct AVFrame *mp_audio_to_avframe_and_unref(struct mp_audio *frame)
int mp_audio_to_avframe(struct mp_audio *frame, struct AVFrame *avframe)
{
struct AVFrame *avframe = av_frame_alloc();
if (!avframe)
goto fail;
av_frame_unref(avframe);
avframe->nb_samples = frame->samples;
avframe->format = af_to_avformat(frame->format);
@@ -402,8 +416,8 @@ struct AVFrame *mp_audio_to_avframe_and_unref(struct mp_audio *frame)
if (!avframe->channel_layout)
goto fail;
#if LIBAVUTIL_VERSION_MICRO >= 100
// FFmpeg being a stupid POS (but I respect it)
avframe->channels = frame->channels.num;
// FFmpeg being a stupid POS again
av_frame_set_channels(avframe, frame->channels.num);
#endif
avframe->sample_rate = frame->rate;
@@ -449,6 +463,23 @@ struct AVFrame *mp_audio_to_avframe_and_unref(struct mp_audio *frame)
avframe = tmp;
}
return 0;
fail:
av_frame_unref(avframe);
return -1;
}
// Returns NULL on failure. The input is always unreffed.
struct AVFrame *mp_audio_to_avframe_and_unref(struct mp_audio *frame)
{
struct AVFrame *avframe = av_frame_alloc();
if (!avframe)
goto fail;
if (mp_audio_to_avframe(frame, avframe) < 0)
goto fail;
talloc_free(frame);
return avframe;
+2
View File
@@ -73,6 +73,7 @@ void mp_audio_copy(struct mp_audio *dst, int dst_offset,
void mp_audio_copy_attributes(struct mp_audio *dst, struct mp_audio *src);
void mp_audio_skip_samples(struct mp_audio *data, int samples);
void mp_audio_clip_timestamps(struct mp_audio *f, double start, double end);
double mp_audio_end_pts(struct mp_audio *data);
bool mp_audio_is_writeable(struct mp_audio *data);
int mp_audio_make_writeable(struct mp_audio *data);
@@ -80,6 +81,7 @@ int mp_audio_make_writeable(struct mp_audio *data);
struct AVFrame;
struct mp_audio *mp_audio_from_avframe(struct AVFrame *avframe);
struct AVFrame *mp_audio_to_avframe_and_unref(struct mp_audio *frame);
int mp_audio_to_avframe(struct mp_audio *frame, struct AVFrame *avframe);
struct mp_audio_pool;
struct mp_audio_pool *mp_audio_pool_create(void *ta_parent);
-38
View File
@@ -230,44 +230,6 @@ void mp_chmap_set_unknown(struct mp_chmap *dst, int num_channels)
}
}
// Return channel index of the given speaker, or -1.
static int mp_chmap_find_speaker(const struct mp_chmap *map, int speaker)
{
for (int n = 0; n < map->num; n++) {
if (map->speaker[n] == speaker)
return n;
}
return -1;
}
static void mp_chmap_remove_speaker(struct mp_chmap *map, int speaker)
{
int index = mp_chmap_find_speaker(map, speaker);
if (index >= 0) {
for (int n = index; n < map->num - 1; n++)
map->speaker[n] = map->speaker[n + 1];
map->num--;
}
}
// Some decoders output additional, redundant channels, which are usually
// useless and will mess up proper audio output channel handling.
// map: channel map from which the channels should be removed
// requested: if not NULL, and if it contains any of the "useless" channels,
// don't remove them (this is for convenience)
void mp_chmap_remove_useless_channels(struct mp_chmap *map,
const struct mp_chmap *requested)
{
if (requested &&
mp_chmap_find_speaker(requested, MP_SPEAKER_ID_DL) >= 0)
return;
if (map->num > 2) {
mp_chmap_remove_speaker(map, MP_SPEAKER_ID_DL);
mp_chmap_remove_speaker(map, MP_SPEAKER_ID_DR);
}
}
// Return the ffmpeg/libav channel layout as in <libavutil/channel_layout.h>.
// Speakers not representable by ffmpeg/libav are dropped.
// Warning: this ignores the order of the channels, and will return a channel
-3
View File
@@ -109,9 +109,6 @@ void mp_chmap_fill_na(struct mp_chmap *map, int num);
void mp_chmap_from_channels(struct mp_chmap *dst, int num_channels);
void mp_chmap_set_unknown(struct mp_chmap *dst, int num_channels);
void mp_chmap_remove_useless_channels(struct mp_chmap *map,
const struct mp_chmap *requested);
uint64_t mp_chmap_to_lavc(const struct mp_chmap *src);
uint64_t mp_chmap_to_lavc_unchecked(const struct mp_chmap *src);
void mp_chmap_from_lavc(struct mp_chmap *dst, uint64_t src);
+13
View File
@@ -374,3 +374,16 @@ void mp_chmal_sel_log(const struct mp_chmap_sel *s, struct mp_log *log, int lev)
if (s->allow_any)
mp_msg(log, lev, " - anything\n");
}
// Select a channel map from the given list that fits best to c. Don't change
// *c if there's no match, or the list is empty.
void mp_chmap_sel_list(struct mp_chmap *c, struct mp_chmap *maps, int num_maps)
{
// This is a separate function to keep messing with mp_chmap_sel internals
// within this source file.
struct mp_chmap_sel sel = {
.chmaps = maps,
.num_chmaps = num_maps,
};
mp_chmap_sel_fallback(&sel, c);
}
+2
View File
@@ -47,4 +47,6 @@ bool mp_chmap_sel_get_def(const struct mp_chmap_sel *s, struct mp_chmap *map,
struct mp_log;
void mp_chmal_sel_log(const struct mp_chmap_sel *s, struct mp_log *log, int lev);
void mp_chmap_sel_list(struct mp_chmap *c, struct mp_chmap *maps, int num_maps);
#endif
+17 -3
View File
@@ -45,6 +45,7 @@ struct priv {
uint32_t skip_samples, trim_samples;
bool preroll_done;
double next_pts;
bool needs_reset;
AVRational codec_timebase;
};
@@ -85,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;
@@ -102,10 +103,11 @@ 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) {
if (opts->downmix && mpopts->audio_output_channels.num_chmaps == 1) {
lavc_context->request_channel_layout =
mp_chmap_to_lavc(&mpopts->audio_output_channels);
mp_chmap_to_lavc(&mpopts->audio_output_channels.chmaps[0]);
}
// Always try to set - option only exists for AC3 at the moment
@@ -173,6 +175,7 @@ static int control(struct dec_audio *da, int cmd, void *arg)
ctx->trim_samples = 0;
ctx->preroll_done = false;
ctx->next_pts = MP_NOPTS_VALUE;
ctx->needs_reset = false;
return CONTROL_TRUE;
}
return CONTROL_UNKNOWN;
@@ -184,6 +187,12 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt,
struct priv *priv = da->priv;
AVCodecContext *avctx = priv->avctx;
// If the decoder discards the timestamp for some reason, we use the
// interpolated PTS. Initialize it so that it works for the initial
// packet as well.
if (mpkt && priv->next_pts == MP_NOPTS_VALUE)
priv->next_pts = mpkt->pts;
int in_len = mpkt ? mpkt->len : 0;
AVPacket pkt;
@@ -192,6 +201,9 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt,
int got_frame = 0;
av_frame_unref(priv->avframe);
if (priv->needs_reset)
control(da, ADCTRL_RESET, NULL);
#if HAVE_AVCODEC_NEW_CODEC_API
int ret = avcodec_send_packet(avctx, &pkt);
if (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
@@ -200,6 +212,8 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt,
ret = avcodec_receive_frame(avctx, priv->avframe);
if (ret >= 0)
got_frame = 1;
if (ret == AVERROR_EOF)
priv->needs_reset = true;
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
ret = 0;
}
+7
View File
@@ -116,9 +116,16 @@ static int determine_codec_profile(struct dec_audio *da, AVPacket *pkt)
goto done;
}
#if HAVE_AVCODEC_NEW_CODEC_API
if (avcodec_send_packet(ctx, pkt) < 0)
goto done;
if (avcodec_receive_frame(ctx, frame) < 0)
goto done;
#else
int got_frame = 0;
if (avcodec_decode_audio4(ctx, frame, &got_frame, pkt) < 1 || !got_frame)
goto done;
#endif
profile = ctx->profile;
+6 -3
View File
@@ -200,7 +200,9 @@ void audio_work(struct dec_audio *da)
if (da->current_frame)
return;
if (!da->packet && demux_read_packet_async(da->header, &da->packet) == 0) {
if (!da->packet && !da->new_segment &&
demux_read_packet_async(da->header, &da->packet) == 0)
{
da->current_state = DATA_WAIT;
return;
}
@@ -211,6 +213,7 @@ void audio_work(struct dec_audio *da)
da->packet = NULL;
}
bool had_input_packet = !!da->packet;
bool had_packet = da->packet || da->new_segment;
int ret = da->ad_driver->decode_packet(da, da->packet, &da->current_frame);
@@ -233,12 +236,12 @@ void audio_work(struct dec_audio *da)
fix_audio_pts(da);
bool segment_end = true;
bool segment_end = !da->current_frame && !had_input_packet;
if (da->current_frame) {
mp_audio_clip_timestamps(da->current_frame, da->start, da->end);
if (da->current_frame->pts != MP_NOPTS_VALUE && da->start != MP_NOPTS_VALUE)
segment_end = da->current_frame->pts >= da->start;
segment_end = da->current_frame->pts >= da->end;
if (da->current_frame->samples == 0) {
talloc_free(da->current_frame);
da->current_frame = NULL;
+151 -174
View File
@@ -31,7 +31,6 @@
#include "af.h"
// Static list of filters
extern const struct af_info af_info_delay;
extern const struct af_info af_info_channels;
extern const struct af_info af_info_format;
extern const struct af_info af_info_volume;
@@ -46,7 +45,6 @@ extern const struct af_info af_info_lavfi;
extern const struct af_info af_info_rubberband;
static const struct af_info *const filter_list[] = {
&af_info_delay,
&af_info_channels,
&af_info_format,
&af_info_volume,
@@ -210,29 +208,6 @@ static struct af_instance *af_prepend(struct af_stream *s,
return new;
}
/* Create and insert a new filter of type name after the filter in the
argument. This function can be called during runtime, the return
value is the new filter */
static struct af_instance *af_append(struct af_stream *s,
struct af_instance *af,
char *name, char **args)
{
if (!af)
af = s->first;
if (af == s->last)
af = s->last->prev;
// Create the new filter and make sure it is OK
struct af_instance *new = af_create(s, name, args);
if (!new)
return NULL;
// Update pointers
new->prev = af;
new->next = af->next;
af->next = new;
new->next->prev = new;
return new;
}
// Uninit and remove the filter "af"
static void af_remove(struct af_stream *s, struct af_instance *af)
{
@@ -275,8 +250,12 @@ static void af_print_filter_chain(struct af_stream *s, struct af_instance *at,
while (af) {
char b[128] = {0};
mp_snprintf_cat(b, sizeof(b), " [%s] ", af->info->name);
if (af->label)
mp_snprintf_cat(b, sizeof(b), "\"%s\" ", af->label);
if (af->data)
mp_snprintf_cat(b, sizeof(b), "%s", mp_audio_config_to_str(af->data));
if (af->auto_inserted)
mp_snprintf_cat(b, sizeof(b), " [a]");
if (af == at)
mp_snprintf_cat(b, sizeof(b), " <-");
MP_MSG(s, msg_level, "%s\n", b);
@@ -287,169 +266,156 @@ static void af_print_filter_chain(struct af_stream *s, struct af_instance *at,
MP_MSG(s, msg_level, " [ao] %s\n", mp_audio_config_to_str(&s->output));
}
static bool af_is_conversion_filter(struct af_instance *af)
{
return af && strcmp(af->info->name, "lavrresample") == 0;
}
// in is what af can take as input - insert a conversion filter if the actual
// input format doesn't match what af expects.
// Returns:
// AF_OK: must call af_reinit() or equivalent, format matches (or is closer)
// AF_FALSE: nothing was changed, format matches
// else: error
static int af_fix_format_conversion(struct af_stream *s,
struct af_instance **p_af,
struct mp_audio in)
{
int rv;
struct af_instance *af = *p_af;
struct af_instance *prev = af->prev;
struct mp_audio actual = *prev->data;
if (actual.format == in.format)
return AF_FALSE;
int dstfmt = in.format;
char *filter = "lavrresample";
if (!af_lavrresample_test_conversion(actual.format, dstfmt))
return AF_ERROR;
if (strcmp(filter, prev->info->name) == 0) {
if (prev->control(prev, AF_CONTROL_SET_FORMAT, &dstfmt) == AF_OK) {
*p_af = prev;
return AF_OK;
}
return AF_ERROR;
}
struct af_instance *new = af_prepend(s, af, filter, NULL);
if (new == NULL)
return AF_ERROR;
new->auto_inserted = true;
if (AF_OK != (rv = new->control(new, AF_CONTROL_SET_FORMAT, &dstfmt))) {
af_remove(s, new);
return rv;
}
*p_af = new;
return AF_OK;
}
// same as af_fix_format_conversion - only wrt. channels
static int af_fix_channels(struct af_stream *s, struct af_instance **p_af,
struct mp_audio in)
{
int rv;
struct af_instance *af = *p_af;
struct af_instance *prev = af->prev;
struct mp_audio actual = *prev->data;
if (mp_chmap_equals(&actual.channels, &in.channels))
return AF_FALSE;
if (prev->control(prev, AF_CONTROL_SET_CHANNELS, &in.channels) == AF_OK) {
*p_af = prev;
return AF_OK;
}
char *filter = "lavrresample";
struct af_instance *new = af_prepend(s, af, filter, NULL);
if (new == NULL)
return AF_ERROR;
new->auto_inserted = true;
if (AF_OK != (rv = new->control(new, AF_CONTROL_SET_CHANNELS, &in.channels)))
return rv;
*p_af = new;
return AF_OK;
}
static int af_fix_rate(struct af_stream *s, struct af_instance **p_af,
struct mp_audio in)
{
int rv;
struct af_instance *af = *p_af;
struct af_instance *prev = af->prev;
struct mp_audio actual = *prev->data;
if (actual.rate == in.rate)
return AF_FALSE;
if (prev->control(prev, AF_CONTROL_SET_RESAMPLE_RATE, &in.rate) == AF_OK) {
*p_af = prev;
return AF_OK;
}
char *filter = "lavrresample";
struct af_instance *new = af_prepend(s, af, filter, NULL);
if (new == NULL)
return AF_ERROR;
new->auto_inserted = true;
if (AF_OK != (rv = new->control(new, AF_CONTROL_SET_RESAMPLE_RATE, &in.rate)))
return rv;
*p_af = new;
return AF_OK;
}
static void reset_formats(struct af_stream *s)
{
struct mp_audio none = {0};
for (struct af_instance *af = s->first; af; af = af->next) {
af->control(af, AF_CONTROL_SET_RESAMPLE_RATE, &(int){0});
af->control(af, AF_CONTROL_SET_CHANNELS, &(struct mp_chmap){0});
af->control(af, AF_CONTROL_SET_FORMAT, &(int){0});
if (af != s->first && af != s->last)
mp_audio_copy_config(af->data, &none);
}
}
static int filter_reinit(struct af_instance *af)
{
struct af_instance *prev = af->prev;
assert(prev);
// Check if this is the first filter
struct mp_audio in = *prev->data;
// Reset just in case...
mp_audio_set_null_data(&in);
if (!mp_audio_config_valid(&in))
return AF_ERROR;
af->fmt_in = in;
int rv = af->control(af, AF_CONTROL_REINIT, &in);
if (rv == AF_OK && !mp_audio_config_equals(&in, prev->data))
rv = AF_FALSE; // conversion filter needed
if (rv == AF_FALSE)
af->fmt_in = in;
if (rv == AF_OK) {
if (!mp_audio_config_valid(af->data))
return AF_ERROR;
af->fmt_out = *af->data;
}
return rv;
}
static int filter_reinit_with_conversion(struct af_stream *s, struct af_instance *af)
{
int rv = filter_reinit(af);
// Conversion filter is needed
if (rv == AF_FALSE) {
// First try if we can change the output format of the previous
// filter to the input format the current filter is expecting.
struct mp_audio in = af->fmt_in;
if (af->prev != s->first && !mp_audio_config_equals(af->prev->data, &in)) {
// This should have been successful (because it succeeded
// before), even if just reverting to the old output format.
mp_audio_copy_config(af->prev->data, &in);
rv = filter_reinit(af->prev);
if (rv != AF_OK)
return rv;
}
if (!mp_audio_config_equals(af->prev->data, &in)) {
// Retry with conversion filter added.
struct af_instance *new =
af_prepend(s, af, "lavrresample", NULL);
if (!new)
return AF_ERROR;
new->auto_inserted = true;
mp_audio_copy_config(new->data, &in);
rv = filter_reinit(new);
if (rv != AF_OK)
af_remove(s, new);
}
if (rv == AF_OK)
rv = filter_reinit(af);
}
return rv;
}
static int af_find_output_conversion(struct af_stream *s, struct mp_audio *cfg)
{
assert(mp_audio_config_valid(&s->output));
assert(s->initialized > 0);
if (mp_chmap_equals_reordered(&s->input.channels, &s->output.channels))
return AF_ERROR;
// Heuristic to detect point of conversion. If it looks like something
// more complicated is going on, better bail out.
// We expect that the last filter converts channels.
struct af_instance *conv = s->last->prev;
if (!conv->auto_inserted)
return AF_ERROR;
if (!(mp_chmap_equals_reordered(&conv->fmt_in.channels, &s->input.channels) &&
mp_chmap_equals_reordered(&conv->fmt_out.channels, &s->output.channels)))
return AF_ERROR;
// Also, should be the only one which does auto conversion.
for (struct af_instance *af = s->first->next; af != s->last; af = af->next)
{
if (af != conv && af->auto_inserted &&
!mp_chmap_equals_reordered(&af->fmt_in.channels, &af->fmt_out.channels))
return AF_ERROR;
}
// And not if it's the only filter.
if (conv->prev == s->first && conv->next == s->last)
return AF_ERROR;
*cfg = s->output;
return AF_OK;
}
// Return AF_OK on success or AF_ERROR on failure.
// Warning:
// A failed af_reinit() leaves the audio chain behind in a useless, broken
// state (for example, format filters that were tentatively inserted stay
// inserted).
// In that case, you should always rebuild the filter chain, or abort.
static int af_reinit(struct af_stream *s)
static int af_do_reinit(struct af_stream *s, bool second_pass)
{
struct mp_audio convert_early = {0};
if (second_pass) {
// If a channel conversion happens, and it is done by an auto-inserted
// filter, then insert a filter to convert it early. Otherwise, do
// nothing and return immediately.
if (af_find_output_conversion(s, &convert_early) != AF_OK)
return AF_OK;
}
remove_auto_inserted_filters(s);
af_chain_forget_frames(s);
reset_formats(s);
s->first->fmt_in = s->first->fmt_out = s->input;
if (mp_audio_config_valid(&convert_early)) {
struct af_instance *new = af_prepend(s, s->first, "lavrresample", NULL);
if (!new)
return AF_ERROR;
new->auto_inserted = true;
mp_audio_copy_config(new->data, &convert_early);
int rv = filter_reinit(new);
if (rv != AF_DETACH && rv != AF_OK)
return AF_ERROR;
MP_VERBOSE(s, "Moving up output conversion.\n");
}
// Start with the second filter, as the first filter is the special input
// filter which needs no initialization.
struct af_instance *af = s->first->next;
// Up to 4 retries per filter (channel, rate, format conversions)
int max_retry = 4;
int retry = 0;
while (af) {
if (retry >= max_retry)
goto negotiate_error;
int rv = filter_reinit_with_conversion(s, af);
// Check if this is the first filter
struct mp_audio in = *af->prev->data;
// Reset just in case...
mp_audio_set_null_data(&in);
if (!mp_audio_config_valid(&in))
goto error;
af->fmt_in = in;
int rv = af->control(af, AF_CONTROL_REINIT, &in);
if (rv == AF_OK && !mp_audio_config_equals(&in, af->prev->data))
rv = AF_FALSE; // conversion filter needed
switch (rv) {
case AF_OK:
if (!mp_audio_config_valid(af->data))
goto error;
af->fmt_out = *af->data;
af = af->next;
break;
case AF_FALSE: { // Configuration filter is needed
if (af_fix_channels(s, &af, in) == AF_OK) {
retry++;
continue;
}
if (af_fix_rate(s, &af, in) == AF_OK) {
retry++;
continue;
}
// Do this last, to prevent "format->lavrresample" being added to
// the filter chain when output formats not supported by
// af_lavrresample are in use.
if (af_fix_format_conversion(s, &af, in) == AF_OK) {
retry++;
continue;
}
case AF_FALSE: {
// If the format conversion is (probably) caused by spdif, then
// (as a feature) drop the filter, instead of failing hard.
int fmt_in1 = af->prev->data->format;
int fmt_in2 = in.format;
int fmt_in2 = af->fmt_in.format;
if (af_fmt_is_valid(fmt_in1) && af_fmt_is_valid(fmt_in2)) {
bool spd1 = af_fmt_is_spdif(fmt_in1);
bool spd2 = af_fmt_is_spdif(fmt_in2);
@@ -460,7 +426,6 @@ static int af_reinit(struct af_stream *s)
struct af_instance *aft = af->prev;
af_remove(s, af);
af = aft->next;
retry++;
continue;
}
}
@@ -478,8 +443,6 @@ static int af_reinit(struct af_stream *s)
af->info->name, rv);
goto error;
}
if (af && !af->auto_inserted)
retry = 0;
}
/* Set previously unset fields in s->output to those of the filter chain
@@ -503,6 +466,19 @@ error:
return AF_ERROR;
}
static int af_reinit(struct af_stream *s)
{
int r = af_do_reinit(s, false);
if (r == AF_OK && mp_audio_config_valid(&s->output)) {
r = af_do_reinit(s, true);
if (r != AF_OK) {
MP_ERR(s, "Failed second pass filter negotiation.\n");
r = af_do_reinit(s, false);
}
}
return r;
}
// Uninit and remove all filters
void af_uninit(struct af_stream *s)
{
@@ -557,7 +533,7 @@ void af_destroy(struct af_stream *s)
format of the preferred output respectively. The function is
reentrant i.e. if called with an already initialized stream the
stream will be reinitialized.
If one of the prefered output parameters is 0 the one that needs
If one of the preferred output parameters is 0 the one that needs
no conversion is used (i.e. the output format in the last filter).
The return value is 0 if success and -1 if failure */
int af_init(struct af_stream *s)
@@ -602,12 +578,7 @@ struct af_instance *af_add(struct af_stream *s, char *name, char *label,
if (af_find_by_label(s, label))
return NULL;
struct af_instance *new;
// Insert the filter somewhere nice
if (af_is_conversion_filter(s->first->next))
new = af_append(s, s->first->next, name, args);
else
new = af_prepend(s, s->first->next, name, args);
struct af_instance *new = af_prepend(s, s->last, name, args);
if (!new)
return NULL;
new->label = talloc_strdup(new, label);
@@ -808,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)
+1 -5
View File
@@ -112,9 +112,6 @@ struct af_stream {
enum af_control {
AF_CONTROL_REINIT = 1,
AF_CONTROL_RESET,
AF_CONTROL_SET_RESAMPLE_RATE,
AF_CONTROL_SET_FORMAT,
AF_CONTROL_SET_CHANNELS,
AF_CONTROL_SET_VOLUME,
AF_CONTROL_GET_VOLUME,
AF_CONTROL_SET_PAN_LEVEL,
@@ -151,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);
@@ -160,6 +158,4 @@ int af_test_output(struct af_instance *af, struct mp_audio *out);
int af_from_ms(int n, float *in, int *out, int rate, float mi, float ma);
float af_softclip(float a);
bool af_lavrresample_test_conversion(int src_format, int dst_format);
#endif /* MPLAYER_AF_H */
-194
View File
@@ -1,194 +0,0 @@
/*
* This audio filter delays the output signal for the different
* channels and can be used for simple position panning.
* An extension for this filter would be a reverb.
*
* Original author: Anders
*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "common/common.h"
#include "af.h"
#define L 65536
#define UPDATEQI(qi) qi=(qi+1)&(L-1)
// Data for specific instances of this filter
typedef struct af_delay_s
{
void* q[AF_NCH]; // Circular queues used for delaying audio signal
int wi[AF_NCH]; // Write index
int ri; // Read index
float d[AF_NCH]; // Delay [ms]
char *delaystr;
}af_delay_t;
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
af_delay_t* s = af->priv;
switch(cmd){
case AF_CONTROL_REINIT:{
int i;
struct mp_audio *in = arg;
if (in->bps != 1 && in->bps != 2 && in->bps != 4) {
MP_FATAL(af, "Sample format not supported\n");
return AF_ERROR;
}
// Free prevous delay queues
for(i=0;i<af->data->nch;i++)
free(s->q[i]);
mp_audio_force_interleaved_format(in);
mp_audio_copy_config(af->data, in);
// Allocate new delay queues
for(i=0;i<af->data->nch;i++){
s->q[i] = calloc(L,af->data->bps);
if(NULL == s->q[i])
MP_FATAL(af, "Out of memory\n");
}
if(AF_OK != af_from_ms(AF_NCH, s->d, s->wi, af->data->rate, 0.0, 1000.0))
return AF_ERROR;
s->ri = 0;
for(i=0;i<AF_NCH;i++){
MP_DBG(af, "Channel %i delayed by %0.3fms\n",
i,MPCLAMP(s->d[i],0.0,1000.0));
MP_TRACE(af, "Channel %i delayed by %i samples\n",
i,s->wi[i]);
}
return AF_OK;
}
}
return AF_UNKNOWN;
}
// Deallocate memory
static void uninit(struct af_instance* af)
{
int i;
for(i=0;i<AF_NCH;i++)
free(((af_delay_t*)(af->priv))->q[i]);
}
static int filter_frame(struct af_instance *af, struct mp_audio *c)
{
if (!c)
return 0;
af_delay_t* s = af->priv; // Setup for this instance
int nch = c->nch; // Number of channels
int len = mp_audio_psize(c)/c->bps; // Number of sample in data chunk
int ri = 0;
int ch,i;
if (af_make_writeable(af, c) < 0) {
talloc_free(c);
return -1;
}
for(ch=0;ch<nch;ch++){
switch(c->bps){
case 1:{
int8_t* a = c->planes[0];
int8_t* q = s->q[ch];
int wi = s->wi[ch];
ri = s->ri;
for(i=ch;i<len;i+=nch){
q[wi] = a[i];
a[i] = q[ri];
UPDATEQI(wi);
UPDATEQI(ri);
}
s->wi[ch] = wi;
break;
}
case 2:{
int16_t* a = c->planes[0];
int16_t* q = s->q[ch];
int wi = s->wi[ch];
ri = s->ri;
for(i=ch;i<len;i+=nch){
q[wi] = a[i];
a[i] = q[ri];
UPDATEQI(wi);
UPDATEQI(ri);
}
s->wi[ch] = wi;
break;
}
case 4:{
int32_t* a = c->planes[0];
int32_t* q = s->q[ch];
int wi = s->wi[ch];
ri = s->ri;
for(i=ch;i<len;i+=nch){
q[wi] = a[i];
a[i] = q[ri];
UPDATEQI(wi);
UPDATEQI(ri);
}
s->wi[ch] = wi;
break;
}
}
}
s->ri = ri;
af_add_output_frame(af, c);
return 0;
}
// Allocate memory and set function pointers
static int af_open(struct af_instance* af){
af->control=control;
af->uninit=uninit;
af->filter_frame = filter_frame;
af_delay_t *s = af->priv;
int n = 1;
int i = 0;
char* cl = s->delaystr;
while(cl && n && i < AF_NCH ){
sscanf(cl,"%f%n",&s->d[i],&n);
if(n==0 || cl[n-1] == '\0')
break;
cl=&cl[n];
if (*cl != ',')
break;
cl++;
i++;
}
return AF_OK;
}
#define OPT_BASE_STRUCT af_delay_t
const struct af_info af_info_delay = {
.info = "Delay audio filter",
.name = "delay",
.open = af_open,
.priv_size = sizeof(af_delay_t),
.options = (const struct m_option[]) {
OPT_STRING("delays", delaystr, 0),
{0}
},
};
+8 -8
View File
@@ -29,10 +29,10 @@ struct priv {
int in_format;
int in_srate;
struct mp_chmap in_channels;
struct m_channels in_channels;
int out_format;
int out_srate;
struct mp_chmap out_channels;
struct m_channels out_channels;
int fail;
};
@@ -44,8 +44,8 @@ static void force_in_params(struct af_instance *af, struct mp_audio *in)
if (priv->in_format != AF_FORMAT_UNKNOWN)
mp_audio_set_format(in, priv->in_format);
if (priv->in_channels.num)
mp_audio_set_channels(in, &priv->in_channels);
if (priv->in_channels.num_chmaps > 0)
mp_audio_set_channels(in, &priv->in_channels.chmaps[0]);
if (priv->in_srate)
in->rate = priv->in_srate;
@@ -58,8 +58,8 @@ static void force_out_params(struct af_instance *af, struct mp_audio *out)
if (priv->out_format != AF_FORMAT_UNKNOWN)
mp_audio_set_format(out, priv->out_format);
if (priv->out_channels.num)
mp_audio_set_channels(out, &priv->out_channels);
if (priv->out_channels.num_chmaps > 0)
mp_audio_set_channels(out, &priv->out_channels.chmaps[0]);
if (priv->out_srate)
out->rate = priv->out_srate;
@@ -124,10 +124,10 @@ const struct af_info af_info_format = {
.options = (const struct m_option[]) {
OPT_AUDIOFORMAT("format", in_format, 0),
OPT_INTRANGE("srate", in_srate, 0, 1000, 8*48000),
OPT_CHMAP("channels", in_channels, CONF_MIN, .min = 0),
OPT_CHANNELS("channels", in_channels, 0, .min = 1),
OPT_AUDIOFORMAT("out-format", out_format, 0),
OPT_INTRANGE("out-srate", out_srate, 0, 1000, 8*48000),
OPT_CHMAP("out-channels", out_channels, CONF_MIN, .min = 0),
OPT_CHANNELS("out-channels", out_channels, 0, .min = 1),
OPT_FLAG("fail", fail, 0),
{0}
},
+152 -54
View File
@@ -31,9 +31,13 @@
#include <libavutil/bswap.h>
#include <libavutil/mem.h>
#include "config.h"
#include "common/av_common.h"
#include "common/common.h"
#include "af.h"
#include "audio/audio_buffer.h"
#include "audio/chmap_sel.h"
#include "audio/fmt-conversion.h"
@@ -54,13 +58,52 @@ typedef struct af_ac3enc_s {
struct mp_audio *pending; // unconsumed input data
int in_samples; // samples of input per AC3 frame
int out_samples; // upper bound on encoded output per AC3 frame
int in_sampleformat;
int64_t encoder_buffered;
int cfg_add_iec61937_header;
int cfg_bit_rate;
int cfg_min_channel_num;
char *cfg_encoder;
char **cfg_avopts;
} af_ac3enc_t;
// fmt carries the input format. Change it to the best next-possible format
// the encoder likely accepts.
static void select_encode_format(AVCodecContext *c, struct mp_audio *fmt)
{
int formats[AF_FORMAT_COUNT];
af_get_best_sample_formats(fmt->format, formats);
for (int n = 0; formats[n]; n++) {
const enum AVSampleFormat *lf = c->codec->sample_fmts;
for (int i = 0; lf && lf[i] != AV_SAMPLE_FMT_NONE; i++) {
int mpfmt = af_from_avformat(lf[i]);
if (mpfmt && mpfmt == formats[n]) {
mp_audio_set_format(fmt, mpfmt);
goto done_fmt;
}
}
}
done_fmt: ;
int rate =
af_select_best_samplerate(fmt->rate, c->codec->supported_samplerates);
if (rate > 0)
fmt->rate = rate;
struct mp_chmap_sel sel = {0};
const uint64_t *lch = c->codec->channel_layouts;
for (int n = 0; lch && lch[n]; n++) {
struct mp_chmap chmap = {0};
mp_chmap_from_lavc(&chmap, lch[n]);
mp_chmap_sel_add_map(&sel, &chmap);
}
struct mp_chmap res = fmt->channels;
mp_chmap_sel_adjust(&sel, &res);
if (!mp_chmap_is_empty(&res))
mp_audio_set_channels(fmt, &res);
}
// Initialization and runtime control
static int control(struct af_instance *af, int cmd, void *arg)
{
@@ -76,23 +119,17 @@ static int control(struct af_instance *af, int cmd, void *arg)
if (!af_fmt_is_pcm(in->format) || in->nch < s->cfg_min_channel_num)
return AF_DETACH;
mp_audio_set_format(in, s->in_sampleformat);
// At least currently, the AC3 encoder doesn't export sample rates.
in->rate = 48000;
select_encode_format(s->lavc_actx, in);
if (in->rate != 48000 && in->rate != 44100 && in->rate != 32000)
in->rate = 48000;
af->data->rate = in->rate;
mp_chmap_reorder_to_lavc(&in->channels);
if (in->nch > AC3_MAX_CHANNELS)
mp_audio_set_num_channels(in, AC3_MAX_CHANNELS);
mp_audio_set_format(af->data, AF_FORMAT_S_AC3);
mp_audio_set_num_channels(af->data, 2);
if (!mp_audio_config_equals(in, &orig_in))
return AF_FALSE;
s->in_samples = AC3_FRAME_SIZE;
if (s->cfg_add_iec61937_header) {
s->out_samples = AC3_FRAME_SIZE;
} else {
@@ -100,14 +137,11 @@ static int control(struct af_instance *af, int cmd, void *arg)
}
mp_audio_copy_config(s->input, in);
mp_audio_realloc(s->input, s->in_samples);
s->input->samples = 0;
talloc_free(s->pending);
s->pending = NULL;
MP_DBG(af, "af_lavcac3enc reinit: %d, %d, %d.\n",
in->nch, in->rate, s->in_samples);
MP_DBG(af, "reinit: %d, %d, %d.\n", in->nch, in->rate, s->in_samples);
int bit_rate = s->bit_rate ? s->bit_rate : default_bit_rate[in->nch];
@@ -118,6 +152,7 @@ static int control(struct af_instance *af, int cmd, void *arg)
avcodec_close(s->lavc_actx);
// Put sample parameters
s->lavc_actx->sample_fmt = af_to_avformat(in->format);
s->lavc_actx->channels = in->nch;
s->lavc_actx->channel_layout = mp_chmap_to_lavc(&in->channels);
s->lavc_actx->sample_rate = in->rate;
@@ -127,14 +162,26 @@ static int control(struct af_instance *af, int cmd, void *arg)
MP_ERR(af, "Couldn't open codec %s, br=%d.\n", "ac3", bit_rate);
return AF_ERROR;
}
if (s->lavc_actx->frame_size < 1) {
MP_ERR(af, "encoder didn't specify input frame size\n");
return AF_ERROR;
}
}
if (s->lavc_actx->frame_size != AC3_FRAME_SIZE) {
MP_ERR(af, "lavcac3enc: unexpected ac3 "
"encoder frame size %d\n", s->lavc_actx->frame_size);
return AF_ERROR;
}
s->in_samples = s->lavc_actx->frame_size;
mp_audio_realloc(s->input, s->in_samples);
s->input->samples = 0;
s->encoder_buffered = 0;
return AF_OK;
}
case AF_CONTROL_RESET:
if (avcodec_is_open(s->lavc_actx))
avcodec_flush_buffers(s->lavc_actx);
talloc_free(s->pending);
s->pending = NULL;
s->input->samples = 0;
s->encoder_buffered = 0;
return AF_OK;
}
return AF_UNKNOWN;
}
@@ -156,8 +203,8 @@ static void uninit(struct af_instance* af)
static void update_delay(struct af_instance *af)
{
af_ac3enc_t *s = af->priv;
af->delay = ((s->pending ? s->pending->samples : 0) + s->input->samples) /
(double)s->input->rate;
af->delay = ((s->pending ? s->pending->samples : 0) + s->input->samples +
s->encoder_buffered) / (double)s->input->rate;
}
static int filter_frame(struct af_instance *af, struct mp_audio *audio)
@@ -190,6 +237,9 @@ static bool fill_buffer(struct af_instance *af)
af->delay = 0;
if (s->pending) {
if (!mp_audio_is_writeable(s->input))
assert(s->input->samples == 0); // we can't have sent a partial frame
mp_audio_realloc_min(s->input, s->in_samples);
int copy = MPMIN(s->in_samples - s->input->samples, s->pending->samples);
s->input->samples += copy;
mp_audio_copy(s->input, s->input->samples - copy, s->pending, 0, copy);
@@ -199,12 +249,27 @@ static bool fill_buffer(struct af_instance *af)
return s->input->samples >= s->in_samples;
}
static int filter_out(struct af_instance *af)
// Return <0 on error, 0 on need more input, 1 on success (and *frame set).
// To actually advance the read pointer, set s->input->samples=0 afterwards.
static int read_input_frame(struct af_instance *af, AVFrame *frame)
{
af_ac3enc_t *s = af->priv;
if (!fill_buffer(af))
return 0; // need more input
if (mp_audio_to_avframe(s->input, frame) < 0)
return -1;
return 1;
}
static int filter_out(struct af_instance *af)
{
af_ac3enc_t *s = af->priv;
if (!s->pending)
return 0;
AVFrame *frame = av_frame_alloc();
if (!frame) {
MP_FATAL(af, "Could not allocate memory \n");
@@ -212,29 +277,59 @@ static int filter_out(struct af_instance *af)
}
int err = -1;
frame->nb_samples = s->in_samples;
frame->format = s->lavc_actx->sample_fmt;
frame->channel_layout = s->lavc_actx->channel_layout;
assert(s->input->num_planes <= AV_NUM_DATA_POINTERS);
frame->extended_data = frame->data;
for (int n = 0; n < s->input->num_planes; n++)
frame->data[n] = s->input->planes[n];
frame->linesize[0] = s->input->samples * s->input->sstride;
AVPacket pkt = {0};
av_init_packet(&pkt);
#if HAVE_AVCODEC_NEW_CODEC_API
// Send input as long as it wants.
while (1) {
err = read_input_frame(af, frame);
if (err < 0)
goto done;
if (err == 0)
break;
err = -1;
int lavc_ret = avcodec_send_frame(s->lavc_actx, frame);
// On EAGAIN, we're supposed to read remaining output.
if (lavc_ret == AVERROR(EAGAIN))
break;
if (lavc_ret < 0) {
MP_FATAL(af, "Encode failed.\n");
goto done;
}
s->encoder_buffered += s->input->samples;
s->input->samples = 0;
}
int lavc_ret = avcodec_receive_packet(s->lavc_actx, &pkt);
if (lavc_ret == AVERROR(EAGAIN)) {
// Need to buffer more input.
err = 0;
goto done;
}
if (lavc_ret < 0) {
MP_FATAL(af, "Encode failed.\n");
goto done;
}
#else
err = read_input_frame(af, frame);
if (err < 0)
goto done;
if (err == 0)
goto done;
err = -1;
int ok;
int lavc_ret = avcodec_encode_audio2(s->lavc_actx, &pkt, frame, &ok);
av_frame_free(&frame);
s->input->samples = 0;
if (lavc_ret < 0 || !ok) {
MP_FATAL(af, "Encode failed.\n");
goto done;
}
#endif
MP_DBG(af, "avcodec_encode_audio got %d, pending %d.\n",
pkt.size, s->pending->samples);
pkt.size, s->pending->samples + s->input->samples);
s->encoder_buffered -= AC3_FRAME_SIZE;
struct mp_audio *out =
mp_audio_pool_get(af->out_pool, af->data, s->out_samples);
@@ -271,11 +366,12 @@ static int filter_out(struct af_instance *af)
swap_16((uint16_t *)(buf + header_len), pkt.size / 2);
out->samples = frame_size / out->sstride;
af_add_output_frame(af, out);
update_delay(af);
err = 0;
done:
av_packet_unref(&pkt);
av_frame_free(&frame);
update_delay(af);
return err;
}
@@ -287,9 +383,9 @@ static int af_open(struct af_instance* af){
af->filter_frame = filter_frame;
af->filter_out = filter_out;
s->lavc_acodec = avcodec_find_encoder_by_name("ac3");
s->lavc_acodec = avcodec_find_encoder_by_name(s->cfg_encoder);
if (!s->lavc_acodec) {
MP_ERR(af, "Audio LAVC, couldn't find encoder for codec %s.\n", "ac3");
MP_ERR(af, "Couldn't find encoder %s.\n", s->cfg_encoder);
return AF_ERROR;
}
@@ -298,35 +394,34 @@ static int af_open(struct af_instance* af){
MP_ERR(af, "Audio LAVC, couldn't allocate context!\n");
return AF_ERROR;
}
const enum AVSampleFormat *fmts = s->lavc_acodec->sample_fmts;
for (int i = 0; fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
s->in_sampleformat = af_from_avformat(fmts[i]);
if (s->in_sampleformat) {
s->lavc_actx->sample_fmt = fmts[i];
break;
}
}
if (!s->in_sampleformat) {
MP_ERR(af, "Audio LAVC, encoder doesn't "
"support expected sample formats!\n");
if (mp_set_avopts(af->log, s->lavc_actx, s->cfg_avopts) < 0)
return AF_ERROR;
// For this one, we require the decoder to expert lists of all supported
// parameters. (Not all decoders do that, but the ones we're interested
// in do.)
if (!s->lavc_acodec->sample_fmts ||
!s->lavc_acodec->channel_layouts)
{
MP_ERR(af, "Audio encoder doesn't list supported parameters.\n");
return AF_ERROR;
}
MP_VERBOSE(af, "[af_lavcac3enc]: in sample format: %s\n",
af_fmt_to_str(s->in_sampleformat));
s->input = talloc_zero(s, struct mp_audio);
if (s->cfg_bit_rate) {
int i;
for (i = 0; i < 19; i++) {
if (ac3_bitrate_tab[i] == s->cfg_bit_rate)
if (ac3_bitrate_tab[i] == s->cfg_bit_rate) {
s->bit_rate = ac3_bitrate_tab[i] * 1000;
break;
}
}
if (i >= 19) {
MP_WARN(af, "af_lavcac3enc unable set unsupported "
"bitrate %d, use default bitrate (check manpage to see "
"supported bitrates).\n", s->cfg_bit_rate);
s->cfg_bit_rate = 0;
MP_WARN(af, "unable set unsupported bitrate %d, use default "
"bitrate (check manpage to see supported bitrates).\n",
s->cfg_bit_rate);
}
}
@@ -344,12 +439,15 @@ const struct af_info af_info_lavcac3enc = {
.cfg_add_iec61937_header = 1,
.cfg_bit_rate = 640,
.cfg_min_channel_num = 3,
.cfg_encoder = "ac3",
},
.options = (const struct m_option[]) {
OPT_FLAG("tospdif", cfg_add_iec61937_header, 0),
OPT_CHOICE_OR_INT("bitrate", cfg_bit_rate, 0, 32, 640,
({"auto", 0}, {"default", 0})),
OPT_INTRANGE("minch", cfg_min_channel_num, 0, 2, 6),
OPT_STRING("encoder", cfg_encoder, 0),
OPT_KEYVALUELIST("o", cfg_avopts, 0),
{0}
},
};
+16 -35
View File
@@ -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
@@ -173,12 +165,6 @@ static int check_output_conversion(int mp_format)
return af_to_avformat(mp_format);
}
bool af_lavrresample_test_conversion(int src_format, int dst_format)
{
return af_to_avformat(src_format) != AV_SAMPLE_FMT_NONE &&
check_output_conversion(dst_format) != AV_SAMPLE_FMT_NONE;
}
static struct mp_chmap fudge_pairs[][2] = {
{MP_CHMAP2(BL, BR), MP_CHMAP2(SL, SR)},
{MP_CHMAP2(SL, SR), MP_CHMAP2(BL, BR)},
@@ -407,28 +393,22 @@ static int control(struct af_instance *af, int cmd, void *arg)
r = configure_lavrr(af, in, out, true);
return r;
}
case AF_CONTROL_SET_FORMAT: {
int format = *(int *)arg;
if (format && check_output_conversion(format) == AV_SAMPLE_FMT_NONE)
return AF_FALSE;
mp_audio_set_format(af->data, format);
return AF_OK;
}
case AF_CONTROL_SET_CHANNELS: {
mp_audio_set_channels(af->data, (struct mp_chmap *)arg);
return AF_OK;
}
case AF_CONTROL_SET_RESAMPLE_RATE:
af->data->rate = *(int *)arg;
return AF_OK;
case AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE: {
s->playback_speed = *(double *)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;
@@ -500,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)
+12 -8
View File
@@ -71,15 +71,19 @@ static int control(struct af_instance *af, int cmd, void *arg)
if (af_fmt_is_planar(in->format))
mp_audio_set_format(af->data, af_fmt_to_planar(af->data->format));
s->rgain = 1.0;
if ((s->rgain_track || s->rgain_album) && af->replaygain_data) {
float gain, peak;
struct replaygain_data *rg = af->replaygain_data;
if ((s->rgain_track || s->rgain_album) && rg) {
MP_VERBOSE(af, "Replaygain: Track=%f/%f Album=%f/%f\n",
rg->track_gain, rg->track_peak,
rg->album_gain, rg->album_peak);
float gain, peak;
if (s->rgain_track) {
gain = af->replaygain_data->track_gain;
peak = af->replaygain_data->track_peak;
gain = rg->track_gain;
peak = rg->track_peak;
} else {
gain = af->replaygain_data->album_gain;
peak = af->replaygain_data->album_peak;
gain = rg->album_gain;
peak = rg->album_peak;
}
gain += s->rgain_preamp;
@@ -115,7 +119,7 @@ static void filter_plane(struct af_instance *af, struct mp_audio *data, int p)
{
struct priv *s = af->priv;
float level = s->level * s->rgain;
float level = s->level * s->rgain * from_dB(s->cfg_volume, 20.0, -200.0, 60.0);
int num_samples = data->samples * data->spf;
if (af_fmt_from_planar(af->data->format) == AF_FORMAT_S16) {
@@ -158,7 +162,7 @@ static int af_open(struct af_instance *af)
struct priv *s = af->priv;
af->control = control;
af->filter_frame = filter;
s->level = from_dB(s->cfg_volume, 20.0, -200.0, 60.0);
s->level = 1.0;
return AF_OK;
}
-403
View File
@@ -1,403 +0,0 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <libavutil/common.h>
#include "config.h"
#include "audio/out/ao.h"
#include "audio/filter/af.h"
#include "common/global.h"
#include "common/msg.h"
#include "mpv_talloc.h"
#include "mixer.h"
struct mixer {
struct mp_log *log;
struct MPOpts *opts;
struct ao *ao;
struct af_stream *af;
// Static, dependent on ao/softvol settings
bool softvol; // use AO (false) or af_volume (true)
bool persistent_volume; // volume does not need to be restored
bool emulate_mute; // if true, emulate mute with volume=0
// Last known values (possibly out of sync with reality)
float vol_l, vol_r;
bool muted;
// Used to decide whether we should unmute on uninit
bool muted_by_us;
/* Contains ao driver name or "softvol" if volume is not persistent
* and needs to be restored after the driver is reinitialized. */
const char *driver;
// Other stuff
float balance;
};
struct mixer *mixer_init(void *talloc_ctx, struct mpv_global *global)
{
struct mixer *mixer = talloc_ptrtype(talloc_ctx, mixer);
*mixer = (struct mixer) {
.log = mp_log_new(mixer, global->log, "mixer"),
.opts = global->opts,
.vol_l = 100,
.vol_r = 100,
.driver = "",
};
return mixer;
}
bool mixer_audio_initialized(struct mixer *mixer)
{
return !!mixer->ao;
}
float mixer_getmaxvolume(struct mixer *mixer)
{
// gain == 1
return mixer->softvol ? mixer->opts->softvol_max : 100;
}
static void checkvolume(struct mixer *mixer)
{
if (!mixer->ao)
return;
ao_control_vol_t vol = {mixer->vol_l, mixer->vol_r};
if (mixer->softvol) {
float gain;
if (!af_control_any_rev(mixer->af, AF_CONTROL_GET_VOLUME, &gain))
gain = 1.0;
vol.left = gain * 100.0;
vol.right = gain * 100.0;
} else {
MP_DBG(mixer, "Reading volume from AO.\n");
// Rely on the values not changing if the query is not supported
ao_control(mixer->ao, AOCONTROL_GET_VOLUME, &vol);
ao_control(mixer->ao, AOCONTROL_GET_MUTE, &mixer->muted);
}
float l = mixer->vol_l;
float r = mixer->vol_r;
if (mixer->emulate_mute && mixer->muted)
l = r = 0;
/* Try to detect cases where the volume has been changed by some external
* action (such as something else changing a shared system-wide volume).
* We don't test for exact equality, as some AOs may round the value
* we last set to some nearby supported value. 3 has been the default
* volume step for increase/decrease keys, and is apparently big enough
* to step to the next possible value in most setups.
*/
if (FFABS(vol.left - l) >= 3 || FFABS(vol.right - r) >= 3) {
mixer->vol_l = vol.left;
mixer->vol_r = vol.right;
if (mixer->emulate_mute)
mixer->muted = false;
}
mixer->muted_by_us &= mixer->muted;
}
void mixer_getvolume(struct mixer *mixer, float *l, float *r)
{
checkvolume(mixer);
*l = mixer->vol_l;
*r = mixer->vol_r;
}
static void setvolume_internal(struct mixer *mixer)
{
float l = mixer->vol_l, r = mixer->vol_r;
if (mixer->emulate_mute && mixer->muted)
l = r = 0;
if (!mixer->softvol) {
MP_DBG(mixer, "Setting volume on AO.\n");
struct ao_control_vol vol = {.left = l, .right = r};
if (ao_control(mixer->ao, AOCONTROL_SET_VOLUME, &vol) != CONTROL_OK)
MP_ERR(mixer, "Failed to change audio output volume.\n");
return;
}
float gain = (l + r) / 2.0 / 100.0;
if (!af_control_any_rev(mixer->af, AF_CONTROL_SET_VOLUME, &gain)) {
if (gain == 1.0)
return;
MP_VERBOSE(mixer, "Inserting volume filter.\n");
if (!(af_add(mixer->af, "volume", "softvol", NULL)
&& af_control_any_rev(mixer->af, AF_CONTROL_SET_VOLUME, &gain)))
MP_ERR(mixer, "No volume control available.\n");
}
}
void mixer_setvolume(struct mixer *mixer, float l, float r)
{
checkvolume(mixer); // to check mute status
float max = mixer_getmaxvolume(mixer);
mixer->vol_l = MPCLAMP(l, 0, max);
mixer->vol_r = MPCLAMP(r, 0, max);
if (mixer->ao)
setvolume_internal(mixer);
}
void mixer_getbothvolume(struct mixer *mixer, float *b)
{
float mixer_l, mixer_r;
mixer_getvolume(mixer, &mixer_l, &mixer_r);
*b = (mixer_l + mixer_r) / 2;
}
void mixer_setmute(struct mixer *mixer, bool mute)
{
checkvolume(mixer);
if (mute == mixer->muted)
return;
if (mixer->ao) {
mixer->muted = mute;
mixer->muted_by_us = mute;
if (mixer->emulate_mute) {
setvolume_internal(mixer);
} else {
ao_control(mixer->ao, AOCONTROL_SET_MUTE, &mute);
}
checkvolume(mixer);
} else {
mixer->muted = mute;
mixer->muted_by_us = mute;
}
}
bool mixer_getmute(struct mixer *mixer)
{
checkvolume(mixer);
return mixer->muted;
}
void mixer_addvolume(struct mixer *mixer, float step)
{
float vol_l, vol_r;
mixer_getvolume(mixer, &vol_l, &vol_r);
mixer_setvolume(mixer, vol_l + step, vol_r + step);
}
void mixer_getbalance(struct mixer *mixer, float *val)
{
if (mixer->af)
af_control_any_rev(mixer->af, AF_CONTROL_GET_PAN_BALANCE, &mixer->balance);
*val = mixer->balance;
}
/* NOTE: Currently the balance code is seriously buggy: it always changes
* the af_pan mapping between the first two input channels and first two
* output channels to particular values. These values make sense for an
* af_pan instance that was automatically inserted for balance control
* only and is otherwise an identity transform, but if the filter was
* there for another reason, then ignoring and overriding the original
* values is completely wrong.
*/
void mixer_setbalance(struct mixer *mixer, float val)
{
struct af_instance *af_pan_balance;
mixer->balance = val;
if (!mixer->af)
return;
if (af_control_any_rev(mixer->af, AF_CONTROL_SET_PAN_BALANCE, &val))
return;
if (val == 0)
return;
if (!(af_pan_balance = af_add(mixer->af, "pan", "autopan", NULL))) {
MP_ERR(mixer, "No balance control available.\n");
return;
}
/* make all other channels pass through since by default pan blocks all */
for (int i = 2; i < AF_NCH; i++) {
float level[AF_NCH] = {0};
level[i] = 1.f;
af_control_ext_t arg_ext = { .ch = i, .arg = level };
af_pan_balance->control(af_pan_balance, AF_CONTROL_SET_PAN_LEVEL,
&arg_ext);
}
af_pan_balance->control(af_pan_balance, AF_CONTROL_SET_PAN_BALANCE, &val);
}
char *mixer_get_volume_restore_data(struct mixer *mixer)
{
if (!mixer->driver[0])
return NULL;
return talloc_asprintf(NULL, "%s:%f:%f:%d", mixer->driver, mixer->vol_l,
mixer->vol_r, mixer->muted_by_us);
}
static void probe_softvol(struct mixer *mixer)
{
bool ao_perapp = ao_control(mixer->ao, AOCONTROL_HAS_PER_APP_VOLUME, 0) == 1;
bool ao_softvol = ao_control(mixer->ao, AOCONTROL_HAS_SOFT_VOLUME, 0) == 1;
assert(!(ao_perapp && ao_softvol));
mixer->persistent_volume = !ao_softvol;
if (mixer->opts->softvol == SOFTVOL_AUTO) {
// No system-wide volume => fine with AO volume control.
mixer->softvol = !ao_softvol && !ao_perapp;
} else {
mixer->softvol = mixer->opts->softvol == SOFTVOL_YES;
}
if (mixer->softvol)
mixer->persistent_volume = false;
MP_DBG(mixer, "Will use af_volume: %s\n", mixer->softvol ? "yes" : "no");
// If we can't use real volume control => force softvol.
if (!mixer->softvol) {
ao_control_vol_t vol;
if (ao_control(mixer->ao, AOCONTROL_GET_VOLUME, &vol) != CONTROL_OK) {
mixer->softvol = true;
MP_WARN(mixer, "Hardware volume control unavailable.\n");
}
}
// Probe native mute support.
mixer->emulate_mute = true;
if (!mixer->softvol) {
if (ao_control(mixer->ao, AOCONTROL_GET_MUTE, &(bool){0}) == CONTROL_OK)
mixer->emulate_mute = false;
}
}
static void restore_volume(struct mixer *mixer)
{
struct MPOpts *opts = mixer->opts;
struct ao *ao = mixer->ao;
float force_vol_l = -1, force_vol_r = -1;
int force_mute = -1;
const char *prev_driver = mixer->driver;
mixer->driver = mixer->softvol ? "softvol" : ao_get_name(ao);
if (!prev_driver[0])
prev_driver = mixer->driver;
// Restore old parameters if volume won't survive reinitialization.
// But not if volume scale is possibly different.
if (!mixer->persistent_volume && strcmp(mixer->driver, prev_driver) == 0) {
force_vol_l = mixer->vol_l;
force_vol_r = mixer->vol_r;
}
// Set mute if we disabled it on uninit last time.
if (mixer->muted_by_us)
force_mute = 1;
// Set parameters from command line.
if (opts->mixer_init_volume >= 0)
force_vol_l = force_vol_r = opts->mixer_init_volume;
if (opts->mixer_init_mute >= 0)
force_mute = opts->mixer_init_mute;
// Set parameters from playback resume.
char *data = mixer->opts->mixer_restore_volume_data;
if (!mixer->persistent_volume && data && data[0]) {
char drv[40];
float v_l, v_r;
int m;
if (sscanf(data, "%39[^:]:%f:%f:%d", drv, &v_l, &v_r, &m) == 4) {
if (strcmp(mixer->driver, drv) == 0) {
force_vol_l = v_l;
force_vol_r = v_r;
force_mute = !!m;
MP_DBG(mixer, "Restoring volume from resume config.\n");
}
}
talloc_free(mixer->opts->mixer_restore_volume_data);
mixer->opts->mixer_restore_volume_data = NULL;
}
// Using --volume should not reset the volume on every file (i.e. reinit),
// OTOH mpv --{ --volume 10 f1.mkv --} --{ --volume 20 f2.mkv --} must work.
// Resetting the option volumes to "auto" (-1) is easiest. If file local
// options (as shown above) are used, the option handler code will reset
// them to other values, and force the volume to be reset as well.
opts->mixer_init_volume = -1;
opts->mixer_init_mute = -1;
checkvolume(mixer);
if (force_vol_l >= 0 && force_vol_r >= 0) {
MP_DBG(mixer, "Restoring previous volume.\n");
mixer_setvolume(mixer, force_vol_l, force_vol_r);
}
if (force_mute >= 0) {
MP_DBG(mixer, "Restoring previous mute toggle.\n");
mixer_setmute(mixer, force_mute);
}
}
// Called after the audio filter chain is built or rebuilt.
// (Can be called multiple times, even without mixer_uninit() in-between.)
void mixer_reinit_audio(struct mixer *mixer, struct ao *ao, struct af_stream *af)
{
if (!ao || !af)
return;
mixer->ao = ao;
mixer->af = af;
MP_DBG(mixer, "Reinit...\n");
probe_softvol(mixer);
restore_volume(mixer);
if (mixer->balance != 0)
mixer_setbalance(mixer, mixer->balance);
}
/* Called before uninitializing the audio filter chain. The main purpose is to
* turn off mute, in case it's a global/persistent setting which might
* otherwise be left enabled even after this player instance exits.
*/
void mixer_uninit_audio(struct mixer *mixer)
{
if (!mixer->ao)
return;
MP_DBG(mixer, "Uninit...\n");
checkvolume(mixer);
if (mixer->muted_by_us && mixer->persistent_volume) {
MP_DBG(mixer, "Draining.\n");
/* Current audio output API combines playing the remaining buffered
* audio and uninitializing the AO into one operation, even though
* ideally unmute would happen between those two steps. We can't do
* volume changes after uninitialization, but we don't want the
* remaining audio to play at full volume either. Thus this
* workaround to drop remaining audio first. */
ao_reset(mixer->ao);
mixer_setmute(mixer, false);
/* We remember mute status and re-enable it if we play more audio
* in the same process. */
mixer->muted_by_us = true;
}
mixer->ao = NULL;
mixer->af = NULL;
mixer->softvol = false;
}
-50
View File
@@ -1,50 +0,0 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MPLAYER_MIXER_H
#define MPLAYER_MIXER_H
#include <stdbool.h>
// Values of MPOpts.softvol
enum {
SOFTVOL_NO = 0,
SOFTVOL_YES = 1,
SOFTVOL_AUTO = 2,
};
struct mpv_global;
struct ao;
struct af_stream;
struct mixer;
struct mixer *mixer_init(void *talloc_ctx, struct mpv_global *global);
void mixer_reinit_audio(struct mixer *mixer, struct ao *ao, struct af_stream *af);
void mixer_uninit_audio(struct mixer *mixer);
bool mixer_audio_initialized(struct mixer *mixer);
void mixer_getvolume(struct mixer *mixer, float *l, float *r);
void mixer_setvolume(struct mixer *mixer, float l, float r);
void mixer_addvolume(struct mixer *mixer, float step);
void mixer_getbothvolume(struct mixer *mixer, float *b);
void mixer_setmute(struct mixer *mixer, bool mute);
bool mixer_getmute(struct mixer *mixer);
void mixer_getbalance(struct mixer *mixer, float *bal);
void mixer_setbalance(struct mixer *mixer, float bal);
float mixer_getmaxvolume(struct mixer *mixer);
char *mixer_get_volume_restore_data(struct mixer *mixer);
#endif /* MPLAYER_MIXER_H */
+33 -8
View File
@@ -158,7 +158,7 @@ error:
static struct ao *ao_init(bool probing, struct mpv_global *global,
struct input_ctx *input_ctx,
struct encode_lavc_context *encode_lavc_ctx,
struct encode_lavc_context *encode_lavc_ctx, int flags,
int samplerate, int format, struct mp_chmap channels,
char *dev, char *name, char **args)
{
@@ -169,6 +169,7 @@ static struct ao *ao_init(bool probing, struct mpv_global *global,
ao->channels = channels;
ao->format = format;
ao->encode_lavc_ctx = encode_lavc_ctx;
ao->init_flags = flags;
if (ao->driver->encode != !!ao->encode_lavc_ctx)
goto fail;
@@ -182,6 +183,8 @@ static struct ao *ao_init(bool probing, struct mpv_global *global,
ao->api_priv = talloc_zero_size(ao, ao->api->priv_size);
assert(!ao->api->priv_defaults && !ao->api->options);
ao->stream_silence = flags & AO_INIT_STREAM_SILENCE;
int r = ao->driver->init(ao);
if (r < 0) {
// Silly exception for coreaudio spdif redirection
@@ -190,7 +193,7 @@ static struct ao *ao_init(bool probing, struct mpv_global *global,
snprintf(redirect, sizeof(redirect), "%s", ao->redirect);
snprintf(rdevice, sizeof(rdevice), "%s", ao->device ? ao->device : "");
talloc_free(ao);
return ao_init(probing, global, input_ctx, encode_lavc_ctx,
return ao_init(probing, global, input_ctx, encode_lavc_ctx, flags,
samplerate, format, channels, rdevice, redirect, NULL);
}
goto fail;
@@ -240,7 +243,7 @@ static void split_ao_device(void *tmp, char *opt, char **out_ao, char **out_dev)
}
struct ao *ao_init_best(struct mpv_global *global,
bool ao_null_fallback,
int init_flags,
struct input_ctx *input_ctx,
struct encode_lavc_context *encode_lavc_ctx,
int samplerate, int format, struct mp_chmap channels)
@@ -283,7 +286,7 @@ struct ao *ao_init_best(struct mpv_global *global,
}
}
if (ao_null_fallback) {
if (init_flags & AO_INIT_NULL_FALLBACK) {
MP_TARRAY_APPEND(tmp, ao_list, ao_num,
(struct m_obj_settings){.name = "null"});
}
@@ -297,7 +300,7 @@ struct ao *ao_init_best(struct mpv_global *global,
dev = pref_dev;
mp_verbose(log, "Using preferred device '%s'\n", dev);
}
ao = ao_init(probing, global, input_ctx, encode_lavc_ctx,
ao = ao_init(probing, global, input_ctx, encode_lavc_ctx, init_flags,
samplerate, format, channels, dev,
entry->name, entry->attribs);
if (ao)
@@ -429,6 +432,29 @@ bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s,
return r;
}
// safe_multichannel=true behaves like ao_chmap_sel_adjust.
// safe_multichannel=false is a helper for callers which do not support safe
// handling of arbitrary channel layouts. If the multichannel layouts are not
// considered "always safe" (e.g. HDMI), then allow only stereo or mono, if
// they are part of the list in *s.
bool ao_chmap_sel_adjust2(struct ao *ao, const struct mp_chmap_sel *s,
struct mp_chmap *map, bool safe_multichannel)
{
if (!safe_multichannel && (ao->init_flags & AO_INIT_SAFE_MULTICHANNEL_ONLY)) {
struct mp_chmap res = *map;
if (mp_chmap_sel_adjust(s, &res)) {
if (!mp_chmap_equals(&res, &(struct mp_chmap)MP_CHMAP_INIT_MONO) &&
!mp_chmap_equals(&res, &(struct mp_chmap)MP_CHMAP_INIT_STEREO))
{
MP_WARN(ao, "Disabling multichannel output.\n");
*map = (struct mp_chmap)MP_CHMAP_INIT_STEREO;
}
}
}
return ao_chmap_sel_adjust(ao, s, map);
}
bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s,
struct mp_chmap *map, int num)
{
@@ -490,10 +516,9 @@ struct ao_hotplug *ao_hotplug_create(struct mpv_global *global,
static void get_devices(struct ao *ao, struct ao_device_list *list)
{
int num = list->num_devices;
if (ao->driver->list_devs)
if (ao->driver->list_devs) {
ao->driver->list_devs(ao, list);
// Add at least a default entry
if (list->num_devices == num) {
} else {
char name[80] = "Default";
if (num > 1)
mp_snprintf_cat(name, sizeof(name), " (%s)", ao->driver->name);
+11 -1
View File
@@ -50,6 +50,16 @@ enum {
AO_EVENT_HOTPLUG = 2,
};
enum {
// Allow falling back to ao_null if nothing else works.
AO_INIT_NULL_FALLBACK = 1 << 0,
// Only accept multichannel configurations that are guaranteed to work
// (i.e. not sending arbitrary layouts over HDMI).
AO_INIT_SAFE_MULTICHANNEL_ONLY = 1 << 1,
// Stream silence as long as no audio is playing.
AO_INIT_STREAM_SILENCE = 1 << 2,
};
typedef struct ao_control_vol {
float left;
float right;
@@ -72,7 +82,7 @@ struct encode_lavc_context;
struct mp_audio;
struct ao *ao_init_best(struct mpv_global *global,
bool ao_null_fallback,
int init_flags,
struct input_ctx *input_ctx,
struct encode_lavc_context *encode_lavc_ctx,
int samplerate, int format, struct mp_chmap channels);
+133 -26
View File
@@ -53,11 +53,14 @@ struct priv {
bool device_lost;
snd_pcm_format_t alsa_fmt;
bool can_pause;
bool paused;
snd_pcm_sframes_t prepause_frames;
double delay_before_pause;
snd_pcm_uframes_t buffersize;
snd_pcm_uframes_t outburst;
snd_output_t *output;
char *cfg_device;
char *cfg_mixer_device;
char *cfg_mixer_name;
@@ -334,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];
@@ -358,7 +363,7 @@ static bool query_chmaps(struct ao *ao, struct mp_chmap *chmap)
snd_pcm_free_chmaps(maps);
return ao_chmap_sel_adjust(ao, &chmap_sel, chmap);
return ao_chmap_sel_adjust2(ao, &chmap_sel, chmap, false);
}
// Map back our selected channel layout to an ALSA one. This is done this way so
@@ -477,6 +482,22 @@ static int set_chmap(struct ao *ao, struct mp_chmap *dev_chmap, int num_channels
#endif /* else HAVE_CHMAP_API */
static void dump_hw_params(struct ao *ao, int msglevel, const char *msg,
snd_pcm_hw_params_t *hw_params)
{
struct priv *p = ao->priv;
int err;
err = snd_pcm_hw_params_dump(hw_params, p->output);
CHECK_ALSA_WARN("Dump hwparams error");
char *tmp = NULL;
size_t tmp_s = snd_output_buffer_string(p->output, &tmp);
if (tmp)
mp_msg(ao->log, msglevel, "%s---\n%.*s---\n", msg, (int)tmp_s, tmp);
snd_output_flush(p->output);
}
static int map_iec958_srate(int srate)
{
switch (srate) {
@@ -520,7 +541,7 @@ static char *append_params(void *ta_parent, const char *device, const char *p)
abort();
}
static int try_open_device(struct ao *ao, const char *device)
static int try_open_device(struct ao *ao, const char *device, int mode)
{
struct priv *p = ao->priv;
int err;
@@ -534,7 +555,7 @@ static int try_open_device(struct ao *ao, const char *device)
map_iec958_srate(ao->samplerate));
const char *ac3_device = append_params(tmp, device, params);
MP_VERBOSE(ao, "opening device '%s' => '%s'\n", device, ac3_device);
err = snd_pcm_open(&p->alsa, ac3_device, SND_PCM_STREAM_PLAYBACK, 0);
err = snd_pcm_open(&p->alsa, ac3_device, SND_PCM_STREAM_PLAYBACK, mode);
if (err < 0) {
// Some spdif-capable devices do not accept the AES0 parameter,
// and instead require the iec958 pseudo-device (they will play
@@ -547,13 +568,13 @@ static int try_open_device(struct ao *ao, const char *device)
MP_VERBOSE(ao, "got error %d; opening iec fallback device '%s'\n",
err, ac3_device);
err = snd_pcm_open
(&p->alsa, ac3_device, SND_PCM_STREAM_PLAYBACK, 0);
(&p->alsa, ac3_device, SND_PCM_STREAM_PLAYBACK, mode);
}
}
talloc_free(tmp);
} else {
MP_VERBOSE(ao, "opening device '%s'\n", device);
err = snd_pcm_open(&p->alsa, device, SND_PCM_STREAM_PLAYBACK, 0);
err = snd_pcm_open(&p->alsa, device, SND_PCM_STREAM_PLAYBACK, mode);
}
return err;
@@ -563,6 +584,10 @@ static void uninit(struct ao *ao)
{
struct priv *p = ao->priv;
if (p->output)
snd_output_close(p->output);
p->output = NULL;
if (p->alsa) {
int err;
@@ -574,20 +599,35 @@ static void uninit(struct ao *ao)
alsa_error: ;
}
static int init_device(struct ao *ao)
#define INIT_DEVICE_ERR_GENERIC -1
#define INIT_DEVICE_ERR_HWPARAMS -2
static int init_device(struct ao *ao, int mode)
{
struct priv *p = ao->priv;
int ret = INIT_DEVICE_ERR_GENERIC;
char *tmp;
size_t tmp_s;
int err;
err = snd_output_buffer_open(&p->output);
CHECK_ALSA_ERROR("Unable to create output buffer");
const char *device = "default";
if (ao->device)
device = ao->device;
if (p->cfg_device && p->cfg_device[0])
device = p->cfg_device;
err = try_open_device(ao, device);
err = try_open_device(ao, device, mode);
CHECK_ALSA_ERROR("Playback open error");
err = snd_pcm_dump(p->alsa, p->output);
CHECK_ALSA_WARN("Dump PCM error");
tmp_s = snd_output_buffer_string(p->output, &tmp);
if (tmp)
MP_DBG(ao, "PCM setup:\n---\n%.*s---\n", (int)tmp_s, tmp);
snd_output_flush(p->output);
err = snd_pcm_nonblock(p->alsa, 0);
CHECK_ALSA_WARN("Unable to set blocking mode");
@@ -597,12 +637,15 @@ static int init_device(struct ao *ao)
err = snd_pcm_hw_params_any(p->alsa, alsa_hwparams);
CHECK_ALSA_ERROR("Unable to get initial parameters");
dump_hw_params(ao, MSGL_DEBUG, "Start HW params:\n", alsa_hwparams);
// Some ALSA drivers have broken delay reporting, so disable the ALSA
// resampling plugin by default.
if (!p->cfg_resample) {
err = snd_pcm_hw_params_set_rate_resample(p->alsa, alsa_hwparams, 0);
CHECK_ALSA_ERROR("Unable to disable resampling");
}
dump_hw_params(ao, MSGL_DEBUG, "HW params after rate:\n", alsa_hwparams);
snd_pcm_access_t access = af_fmt_is_planar(ao->format)
? SND_PCM_ACCESS_RW_NONINTERLEAVED
@@ -614,6 +657,7 @@ static int init_device(struct ao *ao)
err = snd_pcm_hw_params_set_access(p->alsa, alsa_hwparams, access);
}
CHECK_ALSA_ERROR("Unable to set access type");
dump_hw_params(ao, MSGL_DEBUG, "HW params after access:\n", alsa_hwparams);
bool found_format = false;
int try_formats[AF_FORMAT_COUNT];
@@ -637,6 +681,7 @@ static int init_device(struct ao *ao)
err = snd_pcm_hw_params_set_format(p->alsa, alsa_hwparams, p->alsa_fmt);
CHECK_ALSA_ERROR("Unable to set format");
dump_hw_params(ao, MSGL_DEBUG, "HW params after format:\n", alsa_hwparams);
struct mp_chmap dev_chmap = ao->channels;
if (af_fmt_is_spdif(ao->format) || p->cfg_ignore_chmap) {
@@ -656,6 +701,7 @@ static int init_device(struct ao *ao)
err = snd_pcm_hw_params_set_channels_near
(p->alsa, alsa_hwparams, &num_channels);
CHECK_ALSA_ERROR("Unable to set channels");
dump_hw_params(ao, MSGL_DEBUG, "HW params after channels:\n", alsa_hwparams);
if (num_channels > MP_NUM_CHANNELS) {
MP_FATAL(ao, "Too many audio channels (%d).\n", num_channels);
@@ -665,6 +711,7 @@ static int init_device(struct ao *ao)
err = snd_pcm_hw_params_set_rate_near
(p->alsa, alsa_hwparams, &ao->samplerate, NULL);
CHECK_ALSA_ERROR("Unable to set samplerate-2");
dump_hw_params(ao, MSGL_DEBUG, "HW params after rate-2:\n", alsa_hwparams);
snd_pcm_hw_params_t *hwparams_backup;
snd_pcm_hw_params_alloca(&hwparams_backup);
@@ -682,9 +729,14 @@ static int init_device(struct ao *ao)
if (err < 0)
snd_pcm_hw_params_copy(alsa_hwparams, hwparams_backup);
dump_hw_params(ao, MSGL_V, "Going to set final HW params:\n", alsa_hwparams);
/* finally install hardware parameters */
err = snd_pcm_hw_params(p->alsa, alsa_hwparams);
ret = INIT_DEVICE_ERR_HWPARAMS;
CHECK_ALSA_ERROR("Unable to set hw-parameters");
ret = INIT_DEVICE_ERR_GENERIC;
dump_hw_params(ao, MSGL_DEBUG, "Final HW params:\n", alsa_hwparams);
if (set_chmap(ao, &dev_chmap, num_channels) < 0)
goto alsa_error;
@@ -736,11 +788,19 @@ static int init_device(struct ao *ao)
MP_VERBOSE(ao, "buffersize: %d samples\n", (int)p->buffersize);
MP_VERBOSE(ao, "period size: %d samples\n", (int)p->outburst);
ao->device_buffer = p->buffersize;
// ao_alsa implements this by relying on underrun behavior (no data means
// underrun, during which silence is played). Trigger by playing some
// initial silence.
if (ao->stream_silence)
ao_play_silence(ao, p->outburst);
return 0;
alsa_error:
uninit(ao);
return -1;
return ret;
}
static int init(struct ao *ao)
@@ -751,7 +811,18 @@ static int init(struct ao *ao)
MP_VERBOSE(ao, "using ALSA version: %s\n", snd_asoundlib_version());
int r = init_device(ao);
int mode = 0;
int r = init_device(ao, mode);
if (r == INIT_DEVICE_ERR_HWPARAMS) {
// With some drivers, ALSA appears to be unable to set valid hwparams,
// but they work if at least SND_PCM_NO_AUTO_FORMAT is set. Also, it
// appears you can set this flag only on opening a device, thus there
// is the need to retry opening the device.
MP_WARN(ao, "Attempting to work around even more ALSA bugs...\n");
mode |= SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT |
SND_PCM_NO_AUTO_RESAMPLE;
r = init_device(ao, mode);
}
// Sometimes, ALSA will advertise certain chmaps, but it's not possible to
// set them. This can happen with dmix: as of alsa 1.0.29, dmix can do
@@ -773,7 +844,7 @@ static int init(struct ao *ao)
MP_VERBOSE(ao, "Working around braindead dmix multichannel behavior.\n");
uninit(ao);
ao->channels = without_na;
r = init_device(ao);
r = init_device(ao, mode);
}
}
@@ -814,7 +885,7 @@ static double get_delay(struct ao *ao)
struct priv *p = ao->priv;
snd_pcm_sframes_t delay;
if (snd_pcm_state(p->alsa) == SND_PCM_STATE_PAUSED)
if (p->paused)
return p->delay_before_pause;
if (snd_pcm_delay(p->alsa, &delay) < 0)
@@ -828,27 +899,47 @@ static double get_delay(struct ao *ao)
return delay / (double)ao->samplerate;
}
// For stream-silence mode: replace remaining buffer with silence.
// Tries to cause an instant buffer underrun.
static void soft_reset(struct ao *ao)
{
struct priv *p = ao->priv;
snd_pcm_sframes_t frames = snd_pcm_rewindable(p->alsa);
if (frames > 0 && snd_pcm_state(p->alsa) == SND_PCM_STATE_RUNNING) {
frames = snd_pcm_rewind(p->alsa, frames);
if (frames < 0) {
int err = frames;
CHECK_ALSA_WARN("pcm rewind error");
}
}
}
static void audio_pause(struct ao *ao)
{
struct priv *p = ao->priv;
int err;
if (p->can_pause) {
if (p->paused)
return;
p->delay_before_pause = get_delay(ao);
p->prepause_frames = p->delay_before_pause * ao->samplerate;
if (ao->stream_silence) {
soft_reset(ao);
} else if (p->can_pause) {
if (snd_pcm_state(p->alsa) == SND_PCM_STATE_RUNNING) {
p->delay_before_pause = get_delay(ao);
err = snd_pcm_pause(p->alsa, 1);
CHECK_ALSA_ERROR("pcm pause error");
p->prepause_frames = 0;
}
} else {
if (snd_pcm_delay(p->alsa, &p->prepause_frames) < 0
|| p->prepause_frames < 0)
p->prepause_frames = 0;
p->delay_before_pause = p->prepause_frames / (double)ao->samplerate;
err = snd_pcm_drop(p->alsa);
CHECK_ALSA_ERROR("pcm drop error");
}
p->paused = true;
alsa_error: ;
}
@@ -870,9 +961,15 @@ static void audio_resume(struct ao *ao)
struct priv *p = ao->priv;
int err;
if (!p->paused)
return;
resume_device(ao);
if (p->can_pause) {
if (ao->stream_silence) {
p->paused = false;
get_delay(ao); // recovers from underrun (as a side-effect)
} else if (p->can_pause) {
if (snd_pcm_state(p->alsa) == SND_PCM_STATE_PAUSED) {
err = snd_pcm_pause(p->alsa, 0);
CHECK_ALSA_ERROR("pcm resume error");
@@ -881,11 +978,13 @@ static void audio_resume(struct ao *ao)
MP_VERBOSE(ao, "resume not supported by hardware\n");
err = snd_pcm_prepare(p->alsa);
CHECK_ALSA_ERROR("pcm prepare error");
if (p->prepause_frames)
ao_play_silence(ao, p->prepause_frames);
}
if (p->prepause_frames)
ao_play_silence(ao, p->prepause_frames);
alsa_error: ;
p->paused = false;
}
static void reset(struct ao *ao)
@@ -893,12 +992,18 @@ static void reset(struct ao *ao)
struct priv *p = ao->priv;
int err;
p->paused = false;
p->prepause_frames = 0;
p->delay_before_pause = 0;
err = snd_pcm_drop(p->alsa);
CHECK_ALSA_ERROR("pcm prepare error");
err = snd_pcm_prepare(p->alsa);
CHECK_ALSA_ERROR("pcm prepare error");
if (ao->stream_silence) {
soft_reset(ao);
} else {
err = snd_pcm_drop(p->alsa);
CHECK_ALSA_ERROR("pcm prepare error");
err = snd_pcm_prepare(p->alsa);
CHECK_ALSA_ERROR("pcm prepare error");
}
alsa_error: ;
}
@@ -937,6 +1042,8 @@ static int play(struct ao *ao, void **data, int samples, int flags)
}
} while (res == 0);
p->paused = false;
return res < 0 ? -1 : res;
alsa_error:
+1 -6
View File
@@ -133,11 +133,6 @@ static bool reinit_device(struct ao *ao) {
OSStatus err = ca_select_device(ao, ao->device, &p->device);
CHECK_CA_ERROR("failed to select device");
char *uid;
err = CA_GET_STR(p->device, kAudioDevicePropertyDeviceUID, &uid);
CHECK_CA_ERROR("failed to get device UID");
ao->detected_device = talloc_steal(ao, uid);
return true;
coreaudio_error:
@@ -424,7 +419,7 @@ const struct ao_driver audio_out_coreaudio = {
.uninit = uninit,
.init = init,
.control = control,
.pause = stop,
.reset = stop,
.resume = start,
.hotplug_init = hotplug_init,
.hotplug_uninit = hotplug_uninit,
+1 -1
View File
@@ -399,7 +399,7 @@ const struct ao_driver audio_out_coreaudio_exclusive = {
.name = "coreaudio_exclusive",
.uninit = uninit,
.init = init,
.pause = audio_pause,
.reset = audio_pause,
.resume = audio_resume,
.list_devs = ca_get_device_list,
.priv_size = sizeof(struct priv),
+1 -1
View File
@@ -70,7 +70,7 @@ OSStatus ca_get_ary(AudioObjectID id, ca_scope scope, ca_sel selector,
return err;
coreaudio_error_free:
free(*data);
talloc_free(*data);
coreaudio_error:
return err;
}
+11 -25
View File
@@ -114,6 +114,13 @@ OSStatus ca_select_device(struct ao *ao, char* name, AudioDeviceID *device)
kAudioObjectSystemObject, &p_addr, 0, 0, &size, &v);
CFRelease(uid);
CHECK_CA_ERROR("unable to query for device UID");
uint32_t is_alive = 1;
err = CA_GET(*device, kAudioDevicePropertyDeviceIsAlive, &is_alive);
CHECK_CA_ERROR("could not check whether device is alive (invalid device?)");
if (!is_alive)
MP_WARN(ao, "device is not alive!\n");
} else {
// device not set by user, get the default one
err = CA_GET(kAudioObjectSystemObject,
@@ -140,7 +147,7 @@ bool check_ca_st(struct ao *ao, int level, OSStatus code, const char *message)
{
if (code == noErr) return true;
mp_msg(ao->log, level, "%s (%s)\n", message, mp_tag_str(code));
mp_msg(ao->log, level, "%s (%s/%d)\n", message, mp_tag_str(code), (int)code);
return false;
}
@@ -323,6 +330,9 @@ bool ca_stream_supports_compressed(struct ao *ao, AudioStreamID stream)
for (int i = 0; i < n_formats; i++) {
AudioStreamBasicDescription asbd = formats[i].mFormat;
ca_print_asbd(ao, "- ", &asbd);
if (ca_formatid_is_compressed(asbd.mFormatID)) {
talloc_free(formats);
return true;
@@ -334,30 +344,6 @@ coreaudio_error:
return false;
}
bool ca_device_supports_compressed(struct ao *ao, AudioDeviceID device)
{
AudioStreamID *streams = NULL;
size_t n_streams;
/* Retrieve all the output streams. */
OSStatus err =
CA_GET_ARY_O(device, kAudioDevicePropertyStreams, &streams, &n_streams);
CHECK_CA_ERROR("could not get number of streams.");
for (int i = 0; i < n_streams; i++) {
if (ca_stream_supports_compressed(ao, streams[i])) {
talloc_free(streams);
return true;
}
}
talloc_free(streams);
coreaudio_error:
return false;
}
OSStatus ca_lock_device(AudioDeviceID device, pid_t *pid)
{
*pid = getpid();
-1
View File
@@ -65,7 +65,6 @@ bool ca_asbd_is_better(AudioStreamBasicDescription *req,
int64_t ca_frames_to_us(struct ao *ao, uint32_t frames);
int64_t ca_get_latency(const AudioTimeStamp *ts);
bool ca_device_supports_compressed(struct ao *ao, AudioDeviceID device);
bool ca_stream_supports_compressed(struct ao *ao, AudioStreamID stream);
OSStatus ca_lock_device(AudioDeviceID device, pid_t *pid);
OSStatus ca_unlock_device(AudioDeviceID device, pid_t *pid);
+156 -111
View File
@@ -39,9 +39,8 @@
#include "common/encode_lavc.h"
struct priv {
uint8_t *buffer;
size_t buffer_size;
AVStream *stream;
AVCodecContext *codec;
int pcmhack;
int aframesize;
int aframecount;
@@ -98,15 +97,14 @@ static int init(struct ao *ao)
pthread_mutex_lock(&ao->encode_lavc_ctx->lock);
ac->stream = encode_lavc_alloc_stream(ao->encode_lavc_ctx,
AVMEDIA_TYPE_AUDIO);
if (!ac->stream) {
MP_ERR(ao, "could not get a new audio stream\n");
goto fail;
if (encode_lavc_alloc_stream(ao->encode_lavc_ctx,
AVMEDIA_TYPE_AUDIO,
&ac->stream, &ac->codec) < 0) {
MP_ERR(ao, "could not get a new audio stream\n");
goto fail;
}
codec = encode_lavc_get_codec(ao->encode_lavc_ctx, ac->stream);
codec = ao->encode_lavc_ctx->ac;
int samplerate = af_select_best_samplerate(ao->samplerate,
codec->supported_samplerates);
@@ -118,46 +116,38 @@ static int init(struct ao *ao)
// Using codec->time_bvase is deprecated, but needed for older lavf.
ac->stream->time_base.num = 1;
ac->stream->time_base.den = ao->samplerate;
ac->stream->codec->time_base.num = 1;
ac->stream->codec->time_base.den = ao->samplerate;
ac->codec->time_base.num = 1;
ac->codec->time_base.den = ao->samplerate;
ac->stream->codec->sample_rate = ao->samplerate;
ac->codec->sample_rate = ao->samplerate;
struct mp_chmap_sel sel = {0};
mp_chmap_sel_add_any(&sel);
if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels))
if (!ao_chmap_sel_adjust2(ao, &sel, &ao->channels, false))
goto fail;
mp_chmap_reorder_to_lavc(&ao->channels);
ac->stream->codec->channels = ao->channels.num;
ac->stream->codec->channel_layout = mp_chmap_to_lavc(&ao->channels);
ac->codec->channels = ao->channels.num;
ac->codec->channel_layout = mp_chmap_to_lavc(&ao->channels);
ac->stream->codec->sample_fmt = AV_SAMPLE_FMT_NONE;
ac->codec->sample_fmt = AV_SAMPLE_FMT_NONE;
select_format(ao, codec);
ac->sample_size = af_fmt_to_bytes(ao->format);
ac->stream->codec->sample_fmt = af_to_avformat(ao->format);
ac->stream->codec->bits_per_raw_sample = ac->sample_size * 8;
ac->codec->sample_fmt = af_to_avformat(ao->format);
ac->codec->bits_per_raw_sample = ac->sample_size * 8;
if (encode_lavc_open_codec(ao->encode_lavc_ctx, ac->stream) < 0)
if (encode_lavc_open_codec(ao->encode_lavc_ctx, ac->codec) < 0)
goto fail;
ac->pcmhack = 0;
if (ac->stream->codec->frame_size <= 1)
ac->pcmhack = av_get_bits_per_sample(ac->stream->codec->codec_id) / 8;
if (ac->codec->frame_size <= 1)
ac->pcmhack = av_get_bits_per_sample(ac->codec->codec_id) / 8;
if (ac->pcmhack) {
if (ac->pcmhack)
ac->aframesize = 16384; // "enough"
ac->buffer_size =
ac->aframesize * ac->pcmhack * ao->channels.num * 2 + 200;
} else {
ac->aframesize = ac->stream->codec->frame_size;
ac->buffer_size =
ac->aframesize * ac->sample_size * ao->channels.num * 2 + 200;
}
if (ac->buffer_size < FF_MIN_BUFFER_SIZE)
ac->buffer_size = FF_MIN_BUFFER_SIZE;
ac->buffer = talloc_size(ac, ac->buffer_size);
else
ac->aframesize = ac->codec->frame_size;
// enough frames for at least 0.25 seconds
ac->framecount = ceil(ao->samplerate * 0.25 / ac->aframesize);
@@ -182,7 +172,7 @@ fail:
}
// close audio device
static int encode(struct ao *ao, double apts, void **data);
static void encode(struct ao *ao, double apts, void **data);
static void uninit(struct ao *ao)
{
struct priv *ac = ao->priv;
@@ -199,12 +189,12 @@ static void uninit(struct ao *ao)
return;
}
if (ac->buffer) {
if (ac->stream) {
double outpts = ac->expected_next_pts;
if (!ectx->options->rawts && ectx->options->copyts)
outpts += ectx->discontinuity_pts_offset;
outpts += encode_lavc_getoffset(ectx, ac->stream);
while (encode(ao, outpts, NULL) > 0) ;
outpts += encode_lavc_getoffset(ectx, ac->codec);
encode(ao, outpts, NULL);
}
pthread_mutex_unlock(&ectx->lock);
@@ -220,24 +210,130 @@ static int get_space(struct ao *ao)
return ac->aframesize * ac->framecount;
}
static void write_packet(struct ao *ao, AVPacket *packet)
{
// TODO: Can we unify this with the equivalent video code path?
struct priv *ac = ao->priv;
packet->stream_index = ac->stream->index;
if (packet->pts != AV_NOPTS_VALUE) {
packet->pts = av_rescale_q(packet->pts,
ac->codec->time_base,
ac->stream->time_base);
} else {
// Do we need this at all? Better be safe than sorry...
MP_WARN(ao, "encoder lost pts, why?\n");
if (ac->savepts != MP_NOPTS_VALUE) {
packet->pts = av_rescale_q(ac->savepts,
ac->codec->time_base,
ac->stream->time_base);
}
}
if (packet->dts != AV_NOPTS_VALUE) {
packet->dts = av_rescale_q(packet->dts,
ac->codec->time_base,
ac->stream->time_base);
}
if (packet->duration > 0) {
packet->duration = av_rescale_q(packet->duration,
ac->codec->time_base,
ac->stream->time_base);
}
ac->savepts = AV_NOPTS_VALUE;
if (encode_lavc_write_frame(ao->encode_lavc_ctx,
ac->stream, packet) < 0) {
MP_ERR(ao, "error writing at %d %d/%d\n",
(int) packet->pts,
ac->stream->time_base.num,
ac->stream->time_base.den);
return;
}
}
static void encode_audio_and_write(struct ao *ao, AVFrame *frame)
{
// TODO: Can we unify this with the equivalent video code path?
struct priv *ac = ao->priv;
AVPacket packet = {0};
#if HAVE_AVCODEC_NEW_CODEC_API
int status = avcodec_send_frame(ac->codec, frame);
if (status < 0) {
MP_ERR(ao, "error encoding at %d %d/%d\n",
frame ? (int) frame->pts : -1,
ac->codec->time_base.num,
ac->codec->time_base.den);
return;
}
for (;;) {
av_init_packet(&packet);
status = avcodec_receive_packet(ac->codec, &packet);
if (status == AVERROR(EAGAIN)) { // No more packets for now.
if (frame == NULL) {
MP_ERR(ao, "sent flush frame, got EAGAIN");
}
break;
}
if (status == AVERROR_EOF) { // No more packets, ever.
if (frame != NULL) {
MP_ERR(ao, "sent audio frame, got EOF");
}
break;
}
if (status < 0) {
MP_ERR(ao, "error encoding at %d %d/%d\n",
frame ? (int) frame->pts : -1,
ac->codec->time_base.num,
ac->codec->time_base.den);
break;
}
if (frame) {
if (ac->savepts == AV_NOPTS_VALUE)
ac->savepts = frame->pts;
}
encode_lavc_write_stats(ao->encode_lavc_ctx, ac->codec);
write_packet(ao, &packet);
av_packet_unref(&packet);
}
#else
av_init_packet(&packet);
int got_packet = 0;
int status = avcodec_encode_audio2(ac->codec, &packet, frame, &got_packet);
if (status < 0) {
MP_ERR(ao, "error encoding at %d %d/%d\n",
frame ? (int) frame->pts : -1,
ac->codec->time_base.num,
ac->codec->time_base.den);
return;
}
if (!got_packet) {
return;
}
if (frame) {
if (ac->savepts == AV_NOPTS_VALUE)
ac->savepts = frame->pts;
}
encode_lavc_write_stats(ao->encode_lavc_ctx, ac->codec);
write_packet(ao, &packet);
av_packet_unref(&packet);
#endif
}
// must get exactly ac->aframesize amount of data
static int encode(struct ao *ao, double apts, void **data)
static void encode(struct ao *ao, double apts, void **data)
{
AVPacket packet;
struct priv *ac = ao->priv;
struct encode_lavc_context *ectx = ao->encode_lavc_ctx;
double realapts = ac->aframecount * (double) ac->aframesize /
ao->samplerate;
int status, gotpacket;
ac->aframecount++;
if (data)
ectx->audio_pts_offset = realapts - apts;
av_init_packet(&packet);
packet.data = ac->buffer;
packet.size = ac->buffer_size;
if(data) {
AVFrame *frame = av_frame_alloc();
frame->format = af_to_avformat(ao->format);
@@ -252,82 +348,29 @@ static int encode(struct ao *ao, double apts, void **data)
if (ectx->options->rawts || ectx->options->copyts) {
// real audio pts
frame->pts = floor(apts * ac->stream->codec->time_base.den / ac->stream->codec->time_base.num + 0.5);
frame->pts = floor(apts * ac->codec->time_base.den / ac->codec->time_base.num + 0.5);
} else {
// audio playback time
frame->pts = floor(realapts * ac->stream->codec->time_base.den / ac->stream->codec->time_base.num + 0.5);
frame->pts = floor(realapts * ac->codec->time_base.den / ac->codec->time_base.num + 0.5);
}
int64_t frame_pts = av_rescale_q(frame->pts, ac->stream->codec->time_base, ac->worst_time_base);
int64_t frame_pts = av_rescale_q(frame->pts, ac->codec->time_base, ac->worst_time_base);
if (ac->lastpts != AV_NOPTS_VALUE && frame_pts <= ac->lastpts) {
// this indicates broken video
// (video pts failing to increase fast enough to match audio)
MP_WARN(ao, "audio frame pts went backwards (%d <- %d), autofixed\n",
(int)frame->pts, (int)ac->lastpts);
frame_pts = ac->lastpts + 1;
frame->pts = av_rescale_q(frame_pts, ac->worst_time_base, ac->stream->codec->time_base);
frame->pts = av_rescale_q(frame_pts, ac->worst_time_base, ac->codec->time_base);
}
ac->lastpts = frame_pts;
frame->quality = ac->stream->codec->global_quality;
status = avcodec_encode_audio2(ac->stream->codec, &packet, frame, &gotpacket);
if (!status) {
if (ac->savepts == AV_NOPTS_VALUE)
ac->savepts = frame->pts;
}
frame->quality = ac->codec->global_quality;
encode_audio_and_write(ao, frame);
av_frame_free(&frame);
}
else
{
status = avcodec_encode_audio2(ac->stream->codec, &packet, NULL, &gotpacket);
}
if(status) {
MP_ERR(ao, "error encoding\n");
return -1;
}
if(!gotpacket)
return 0;
MP_DBG(ao, "got pts %f (playback time: %f); out size: %d\n",
apts, realapts, packet.size);
encode_lavc_write_stats(ao->encode_lavc_ctx, ac->stream);
packet.stream_index = ac->stream->index;
// Do we need this at all? Better be safe than sorry...
if (packet.pts == AV_NOPTS_VALUE) {
MP_WARN(ao, "encoder lost pts, why?\n");
if (ac->savepts != MP_NOPTS_VALUE)
packet.pts = ac->savepts;
}
if (packet.pts != AV_NOPTS_VALUE)
packet.pts = av_rescale_q(packet.pts, ac->stream->codec->time_base,
ac->stream->time_base);
if (packet.dts != AV_NOPTS_VALUE)
packet.dts = av_rescale_q(packet.dts, ac->stream->codec->time_base,
ac->stream->time_base);
if(packet.duration > 0)
packet.duration = av_rescale_q(packet.duration, ac->stream->codec->time_base,
ac->stream->time_base);
ac->savepts = AV_NOPTS_VALUE;
if (encode_lavc_write_frame(ao->encode_lavc_ctx, &packet) < 0) {
MP_ERR(ao, "error writing at %f %f/%f\n",
realapts, (double) ac->stream->time_base.num,
(double) ac->stream->time_base.den);
return -1;
}
return packet.size;
encode_audio_and_write(ao, NULL);
}
// this should round samples down to frame sizes
@@ -377,22 +420,22 @@ static int play(struct ao *ao, void **data, int samples, int flags)
}
if (ac->worst_time_base.den == 0) {
//if (ac->stream->codec->time_base.num / ac->stream->codec->time_base.den >= ac->stream->time_base.num / ac->stream->time_base.den)
if (ac->stream->codec->time_base.num * (double) ac->stream->time_base.den >=
ac->stream->time_base.num * (double) ac->stream->codec->time_base.den) {
//if (ac->codec->time_base.num / ac->codec->time_base.den >= ac->stream->time_base.num / ac->stream->time_base.den)
if (ac->codec->time_base.num * (double) ac->stream->time_base.den >=
ac->stream->time_base.num * (double) ac->codec->time_base.den) {
MP_VERBOSE(ao, "NOTE: using codec time base (%d/%d) for pts "
"adjustment; the stream base (%d/%d) is not worse.\n",
(int)ac->stream->codec->time_base.num,
(int)ac->stream->codec->time_base.den,
(int)ac->codec->time_base.num,
(int)ac->codec->time_base.den,
(int)ac->stream->time_base.num,
(int)ac->stream->time_base.den);
ac->worst_time_base = ac->stream->codec->time_base;
ac->worst_time_base = ac->codec->time_base;
ac->worst_time_base_is_stream = 0;
} else {
MP_WARN(ao, "NOTE: not using codec time base (%d/%d) for pts "
"adjustment; the stream base (%d/%d) is worse.\n",
(int)ac->stream->codec->time_base.num,
(int)ac->stream->codec->time_base.den,
(int)ac->codec->time_base.num,
(int)ac->codec->time_base.den,
(int)ac->stream->time_base.num,
(int)ac->stream->time_base.den);
ac->worst_time_base = ac->stream->time_base;
@@ -437,7 +480,7 @@ static int play(struct ao *ao, void **data, int samples, int flags)
}
// Shift pts by the pts offset first.
outpts += encode_lavc_getoffset(ectx, ac->stream);
outpts += encode_lavc_getoffset(ectx, ac->codec);
while (samples - bufpos >= ac->aframesize) {
void *start[MP_NUM_CHANNELS] = {0};
@@ -492,3 +535,5 @@ const struct ao_driver audio_out_lavc = {
.play = play,
.drain = drain,
};
// vim: sw=4 ts=4 et tw=80
+5 -11
View File
@@ -57,7 +57,7 @@ struct priv {
// (This is not needed by the AO API, but many AOs behave this way.)
int outburst; // samples
char **channel_layouts;
struct m_channels channel_layouts;
};
static void drain(struct ao *ao)
@@ -91,15 +91,9 @@ static int init(struct ao *ao)
ao->untimed = priv->untimed;
struct mp_chmap_sel sel = {.tmp = ao};
if (priv->channel_layouts) {
for (int n = 0; priv->channel_layouts[n]; n++) {
struct mp_chmap map = {0};
if (!mp_chmap_from_str(&map, bstr0(priv->channel_layouts[n]))) {
MP_FATAL(ao, "Invalid channel map in option.\n");
return -1;
}
mp_chmap_sel_add_map(&sel, &map);
}
if (priv->channel_layouts.num_chmaps) {
for (int n = 0; n < priv->channel_layouts.num_chmaps; n++)
mp_chmap_sel_add_map(&sel, &priv->channel_layouts.chmaps[n]);
} else {
mp_chmap_sel_add_any(&sel);
}
@@ -244,7 +238,7 @@ const struct ao_driver audio_out_null = {
OPT_FLOATRANGE("latency", latency_sec, 0, 0, 100),
OPT_FLAG("broken-eof", broken_eof, 0),
OPT_FLAG("broken-delay", broken_delay, 0),
OPT_STRINGLIST("channel-layouts", channel_layouts, 0),
OPT_CHANNELS("channel-layouts", channel_layouts, 0),
{0}
},
};
-1
View File
@@ -46,7 +46,6 @@ struct priv {
static const int fmtmap[][2] = {
{ AF_FORMAT_U8, SL_PCMSAMPLEFORMAT_FIXED_8 },
{ AF_FORMAT_S16, SL_PCMSAMPLEFORMAT_FIXED_16 },
{ AF_FORMAT_S32, SL_PCMSAMPLEFORMAT_FIXED_32 },
{ 0 }
};
+8 -1
View File
@@ -462,7 +462,7 @@ static int init(struct ao *ao)
p->buffersize = 0;
memset(data, 0, p->outburst);
while (p->buffersize < 0x40000 && device_writable(ao) > 0) {
write(p->audio_fd, data, p->outburst);
(void)write(p->audio_fd, data, p->outburst);
p->buffersize += p->outburst;
}
free(data);
@@ -612,6 +612,12 @@ static int audio_wait(struct ao *ao, pthread_mutex_t *lock)
return r;
}
static void list_devs(struct ao *ao, struct ao_device_list *list)
{
if (stat(PATH_DEV_DSP, &(struct stat){0}) == 0)
ao_device_list_add(list, ao, &(struct ao_device_desc){"", "Default"});
}
#define OPT_BASE_STRUCT struct priv
const struct ao_driver audio_out_oss = {
@@ -629,6 +635,7 @@ const struct ao_driver audio_out_oss = {
.drain = drain,
.wait = audio_wait,
.wakeup = ao_wakeup_poll,
.list_devs = list_devs,
.priv_size = sizeof(struct priv),
.priv_defaults = &(const struct priv) {
.audio_fd = -1,
+3 -2
View File
@@ -23,6 +23,7 @@
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include <pthread.h>
#include <pulse/pulseaudio.h>
@@ -34,8 +35,8 @@
#include "ao.h"
#include "internal.h"
#define VOL_PA2MP(v) ((v) * 100 / PA_VOLUME_NORM)
#define VOL_MP2PA(v) ((v) * PA_VOLUME_NORM / 100)
#define VOL_PA2MP(v) ((v) * 100.0 / PA_VOLUME_NORM)
#define VOL_MP2PA(v) lrint((v) * PA_VOLUME_NORM / 100)
struct priv {
// PulseAudio playback stream object
+3 -3
View File
@@ -132,7 +132,7 @@ static bool thread_feed(struct ao *ao)
mp_time_us() + (int64_t)llrint(delay_us));
// note, we can't use ao_read_data return value here since we already
// commited to frame_count above in the GetBuffer call
// committed to frame_count above in the GetBuffer call
hr = IAudioRenderClient_ReleaseBuffer(state->pRenderClient,
frame_count, 0);
EXIT_ON_ERROR(hr);
@@ -270,7 +270,7 @@ static void uninit(struct ao *ao)
static int init(struct ao *ao)
{
MP_DBG(ao, "Init wasapi\n");
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
CoInitializeEx(NULL, COINIT_MULTITHREADED);
struct wasapi_state *state = ao->priv;
state->log = ao->log;
@@ -469,7 +469,7 @@ static int hotplug_init(struct ao *ao)
MP_DBG(ao, "Hotplug init\n");
struct wasapi_state *state = ao->priv;
state->log = ao->log;
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
CoInitializeEx(NULL, COINIT_MULTITHREADED);
HRESULT hr = wasapi_change_init(ao, true);
EXIT_ON_ERROR(hr);
+2 -1
View File
@@ -17,6 +17,7 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <initguid.h>
#include <wchar.h>
#include "ao_wasapi.h"
@@ -94,7 +95,7 @@ static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDeviceAdded(
return S_OK;
}
// maybe MPV can go over to the prefered device once it is plugged in?
// maybe MPV can go over to the preferred device once it is plugged in?
static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDeviceRemoved(
IMMNotificationClient *This,
LPCWSTR pwstrDeviceId)
+1 -1
View File
@@ -407,7 +407,7 @@ static bool search_channels(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat)
}
entry = ao->channels;
if (ao_chmap_sel_adjust(ao, &chmap_sel, &entry)){
if (ao_chmap_sel_adjust2(ao, &chmap_sel, &entry, !state->opt_exclusive)){
change_waveformat_channels(wformat, &entry);
return true;
}
+4
View File
@@ -43,6 +43,8 @@ struct ao {
struct encode_lavc_context *encode_lavc_ctx;
struct input_ctx *input_ctx;
struct mp_log *log; // Using e.g. "[ao/coreaudio]" as prefix
int init_flags; // AO_INIT_* flags
bool stream_silence; // if audio inactive, just play silence
// The device as selected by the user, usually using ao_device_desc.name
// from an entry from the list returned by driver->list_devices. If the
@@ -191,6 +193,8 @@ void ao_wakeup_poll(struct ao *ao);
bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s,
struct mp_chmap *map);
bool ao_chmap_sel_adjust2(struct ao *ao, const struct mp_chmap_sel *s,
struct mp_chmap *map, bool safe_multichannel);
bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s,
struct mp_chmap *map, int num);
+6 -2
View File
@@ -185,7 +185,7 @@ static double get_delay(struct ao *ao)
static void reset(struct ao *ao)
{
struct ao_pull_state *p = ao->api_priv;
if (ao->driver->reset)
if (!ao->stream_silence && ao->driver->reset)
ao->driver->reset(ao); // assumes the audio callback thread is stopped
set_state(ao, AO_STATE_NONE);
for (int n = 0; n < ao->num_planes; n++)
@@ -195,7 +195,7 @@ static void reset(struct ao *ao)
static void pause(struct ao *ao)
{
if (ao->driver->reset)
if (!ao->stream_silence && ao->driver->reset)
ao->driver->reset(ao);
set_state(ao, AO_STATE_NONE);
}
@@ -244,6 +244,10 @@ static int init(struct ao *ao)
p->buffers[n] = mp_ring_new(ao, ao->buffer * ao->sstride);
atomic_store(&p->state, AO_STATE_NONE);
assert(ao->driver->resume);
if (ao->stream_silence)
ao->driver->resume(ao);
return 0;
}
+20 -11
View File
@@ -142,6 +142,7 @@ static void resume(struct ao *ao)
static void drain(struct ao *ao)
{
struct ao_push_state *p = ao->api_priv;
double maxbuffer = ao->buffer / (double)ao->samplerate + 1;
MP_VERBOSE(ao, "draining...\n");
@@ -151,14 +152,23 @@ static void drain(struct ao *ao)
p->final_chunk = true;
wakeup_playthread(ao);
while (p->still_playing && mp_audio_buffer_samples(p->buffer) > 0)
pthread_cond_wait(&p->wakeup, &p->lock);
// Wait until everything is done. Since the audio API (especially ALSA)
// can't be trusted to do this right, and we're hard-blocking here, apply
// an upper bound timeout.
struct timespec until = mp_rel_time_to_timespec(maxbuffer);
while (p->still_playing && mp_audio_buffer_samples(p->buffer) > 0) {
if (pthread_cond_timedwait(&p->wakeup, &p->lock, &until)) {
MP_WARN(ao, "Draining is taking too long, aborting.\n");
goto done;
}
}
if (ao->driver->drain) {
ao->driver->drain(ao);
} else {
double time = unlocked_get_delay(ao);
mp_sleep_us(MPMIN(time, ao->buffer / (double)ao->samplerate + 1) * 1e6);
mp_sleep_us(MPMIN(time, maxbuffer) * 1e6);
}
done:
@@ -292,11 +302,12 @@ static void ao_play_data(struct ao *ao)
// If we just filled the AO completely (r == space), don't refill for a
// while. Prevents wakeup feedback with byte-granular AOs.
int needed = unlocked_get_space(ao);
bool more = needed >= (r == space ? ao->device_buffer / 4 : 1) && !stuck;
bool more = needed >= (r == space ? ao->device_buffer / 4 : 1) && !stuck &&
!(flags & AOPLAY_FINAL_CHUNK);
if (more)
mp_input_wakeup(ao->input_ctx); // request more data
MP_TRACE(ao, "in=%d flags=%d space=%d r=%d wa=%d needed=%d more=%d\n",
max, flags, space, r, p->wait_on_ao, needed, more);
MP_TRACE(ao, "in=%d flags=%d space=%d r=%d wa/pl=%d/%d needed=%d more=%d\n",
max, flags, space, r, p->wait_on_ao, p->still_playing, needed, more);
}
static void *playthread(void *arg)
@@ -486,10 +497,8 @@ int ao_wait_poll(struct ao *ao, struct pollfd *fds, int num_fds,
bool wakeup = false;
if (p_fds[num_fds].revents & POLLIN) {
wakeup = true;
// flush the wakeup pipe contents - might "drown" some wakeups, but
// that's ok for our use-case
char buf[100];
read(p->wakeup_pipe[0], buf, sizeof(buf));
// might "drown" some wakeups, but that's ok for our use-case
mp_flush_wakeup_pipe(p->wakeup_pipe[0]);
}
return (r >= 0 || r == -EINTR) ? wakeup : -1;
}
@@ -499,7 +508,7 @@ void ao_wakeup_poll(struct ao *ao)
assert(ao->api == &ao_api_push);
struct ao_push_state *p = ao->api_priv;
write(p->wakeup_pipe[1], &(char){0}, 1);
(void)write(p->wakeup_pipe[1], &(char){0}, 1);
}
#endif
+29 -2
View File
@@ -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;
+1
View File
@@ -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);
+7 -2
View File
@@ -189,7 +189,7 @@ struct lib {
unsigned runv;
};
void print_libav_versions(struct mp_log *log, int v)
bool print_libav_versions(struct mp_log *log, int v)
{
const struct lib libs[] = {
{"libavutil", LIBAVUTIL_VERSION_INT, avutil_version()},
@@ -207,17 +207,22 @@ void print_libav_versions(struct mp_log *log, int v)
mp_msg(log, v, "%s library versions:\n", LIB_PREFIX);
bool mismatch = false;
for (int n = 0; n < MP_ARRAY_SIZE(libs); n++) {
const struct lib *l = &libs[n];
mp_msg(log, v, " %-15s %d.%d.%d", l->name, V(l->buildv));
if (l->buildv != l->runv)
if (l->buildv != l->runv) {
mp_msg(log, v, " (runtime %d.%d.%d)", V(l->runv));
mismatch = true;
}
mp_msg(log, v, "\n");
}
#if HAVE_AV_VERSION_INFO
mp_msg(log, v, "%s version: %s\n", LIB_PREFIX, av_version_info());
#endif
return !mismatch;
}
#undef V
+4 -1
View File
@@ -1,8 +1,11 @@
#ifndef MP_AV_LOG_H
#define MP_AV_LOG_H
#include <stdbool.h>
struct mpv_global;
struct mp_log;
void init_libav(struct mpv_global *global);
void uninit_libav(struct mpv_global *global);
void print_libav_versions(struct mp_log *log, int v);
bool print_libav_versions(struct mp_log *log, int v);
#endif
+176 -148
View File
@@ -21,6 +21,7 @@
#include <libavutil/avutil.h>
#include "config.h"
#include "encode_lavc.h"
#include "common/global.h"
#include "common/msg.h"
@@ -291,32 +292,20 @@ int encode_lavc_start(struct encode_lavc_context *ctx)
CHECK_FAIL(ctx, 0);
if (ctx->expect_video) {
unsigned i;
for (i = 0; i < ctx->avc->nb_streams; ++i)
if (ctx->avc->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
break;
if (i >= ctx->avc->nb_streams) {
if (ctx->avc->oformat->video_codec != AV_CODEC_ID_NONE ||
ctx->options->vcodec) {
encode_lavc_fail(ctx,
"no video stream succeeded - invalid codec?\n");
return 0;
}
if (ctx->expect_video && ctx->vcc == NULL) {
if (ctx->avc->oformat->video_codec != AV_CODEC_ID_NONE ||
ctx->options->vcodec) {
encode_lavc_fail(ctx,
"no video stream succeeded - invalid codec?\n");
return 0;
}
}
if (ctx->expect_audio) {
unsigned i;
for (i = 0; i < ctx->avc->nb_streams; ++i)
if (ctx->avc->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
break;
if (i >= ctx->avc->nb_streams) {
if (ctx->avc->oformat->audio_codec != AV_CODEC_ID_NONE ||
ctx->options->acodec) {
encode_lavc_fail(ctx,
"no audio stream succeeded - invalid codec?\n");
return 0;
}
if (ctx->expect_audio && ctx->acc == NULL) {
if (ctx->avc->oformat->audio_codec != AV_CODEC_ID_NONE ||
ctx->options->acodec) {
encode_lavc_fail(ctx,
"no audio stream succeeded - invalid codec?\n");
return 0;
}
}
@@ -387,33 +376,38 @@ void encode_lavc_finish(struct encode_lavc_context *ctx)
if (ctx->header_written > 0)
av_write_trailer(ctx->avc); // this is allowed to fail
for (i = 0; i < ctx->avc->nb_streams; i++) {
switch (ctx->avc->streams[i]->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
if (ctx->twopass_bytebuffer_v) {
char *stats = ctx->avc->streams[i]->codec->stats_out;
if (stats)
stream_write_buffer(ctx->twopass_bytebuffer_v,
stats, strlen(stats));
}
break;
case AVMEDIA_TYPE_AUDIO:
if (ctx->twopass_bytebuffer_a) {
char *stats = ctx->avc->streams[i]->codec->stats_out;
if (stats)
stream_write_buffer(ctx->twopass_bytebuffer_a,
stats, strlen(stats));
}
break;
default:
break;
if (ctx->vcc) {
if (ctx->twopass_bytebuffer_v) {
char *stats = ctx->vcc->stats_out;
if (stats)
stream_write_buffer(ctx->twopass_bytebuffer_v,
stats, strlen(stats));
}
avcodec_close(ctx->avc->streams[i]->codec);
talloc_free(ctx->avc->streams[i]->codec->stats_in);
av_free(ctx->avc->streams[i]->codec);
avcodec_close(ctx->vcc);
talloc_free(ctx->vcc->stats_in);
av_free(ctx->vcc);
ctx->vcc = NULL;
}
if (ctx->acc) {
if (ctx->twopass_bytebuffer_a) {
char *stats = ctx->acc->stats_out;
if (stats)
stream_write_buffer(ctx->twopass_bytebuffer_a,
stats, strlen(stats));
}
avcodec_close(ctx->acc);
talloc_free(ctx->acc->stats_in);
av_free(ctx->acc);
ctx->acc = NULL;
}
for (i = 0; i < ctx->avc->nb_streams; i++) {
av_free(ctx->avc->streams[i]->info);
av_free(ctx->avc->streams[i]);
}
ctx->vst = NULL;
ctx->ast = NULL;
if (ctx->twopass_bytebuffer_v) {
free_stream(ctx->twopass_bytebuffer_v);
@@ -437,6 +431,7 @@ void encode_lavc_finish(struct encode_lavc_context *ctx)
}
av_free(ctx->avc);
ctx->avc = NULL;
}
ctx->finished = true;
@@ -461,7 +456,9 @@ void encode_lavc_set_audio_pts(struct encode_lavc_context *ctx, double pts)
static void encode_2pass_prepare(struct encode_lavc_context *ctx,
AVDictionary **dictp,
AVStream *stream, struct stream **bytebuf,
AVStream *stream,
AVCodecContext *codec,
struct stream **bytebuf,
const char *prefix)
{
if (!*bytebuf) {
@@ -476,7 +473,7 @@ static void encode_2pass_prepare(struct encode_lavc_context *ctx,
if (!(*bytebuf = stream_open(buf, ctx->global))) {
MP_WARN(ctx, "%s: could not open '%s', "
"disabling 2-pass encoding at pass 2\n", prefix, buf);
stream->codec->flags &= ~CODEC_FLAG_PASS2;
codec->flags &= ~CODEC_FLAG_PASS2;
set_to_avdictionary(ctx, dictp, "flags", "-pass2");
} else {
struct bstr content = stream_read_complete(*bytebuf, NULL,
@@ -487,7 +484,7 @@ static void encode_2pass_prepare(struct encode_lavc_context *ctx,
prefix, ctx->avc->filename);
} else {
content.start[content.len] = 0;
stream->codec->stats_in = content.start;
codec->stats_in = content.start;
}
free_stream(*bytebuf);
*bytebuf = NULL;
@@ -506,43 +503,55 @@ static void encode_2pass_prepare(struct encode_lavc_context *ctx,
}
}
AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx,
enum AVMediaType mt)
int encode_lavc_alloc_stream(struct encode_lavc_context *ctx,
enum AVMediaType mt,
AVStream **stream_out,
AVCodecContext **codec_out)
{
AVDictionaryEntry *de;
AVStream *stream = NULL;
char **p;
int i;
CHECK_FAIL(ctx, NULL);
*stream_out = NULL;
*codec_out = NULL;
CHECK_FAIL(ctx, -1);
if (ctx->header_written)
return NULL;
for (i = 0; i < ctx->avc->nb_streams; ++i)
if (ctx->avc->streams[i]->codec->codec_type == mt)
// already have a stream of that type, this cannot really happen
return NULL;
return -1;
if (ctx->avc->nb_streams == 0) {
// if this stream isn't stream #0, allocate a dummy stream first for
// the next loop to use
// the next call to use
if (mt == AVMEDIA_TYPE_VIDEO && ctx->audio_first) {
MP_INFO(ctx, "vo-lavc: preallocated audio stream for later use\n");
avformat_new_stream(ctx->avc, NULL); // this one is AVMEDIA_TYPE_UNKNOWN for now
ctx->ast = avformat_new_stream(
ctx->avc, NULL); // this one is AVMEDIA_TYPE_UNKNOWN for now
}
if (mt == AVMEDIA_TYPE_AUDIO && ctx->video_first) {
MP_INFO(ctx, "ao-lavc: preallocated video stream for later use\n");
avformat_new_stream(ctx->avc, NULL); // this one is AVMEDIA_TYPE_UNKNOWN for now
ctx->vst = avformat_new_stream(
ctx->avc, NULL); // this one is AVMEDIA_TYPE_UNKNOWN for now
}
} else {
// find possibly preallocated stream
for (i = 0; i < ctx->avc->nb_streams; ++i)
if (ctx->avc->streams[i]->codec->codec_type == AVMEDIA_TYPE_UNKNOWN) // preallocated stream
stream = ctx->avc->streams[i];
}
if (!stream)
stream = avformat_new_stream(ctx->avc, NULL);
// already have a stream of that type (this cannot really happen)?
switch (mt) {
case AVMEDIA_TYPE_VIDEO:
if (ctx->vcc != NULL)
return -1;
if (ctx->vst == NULL)
ctx->vst = avformat_new_stream(ctx->avc, NULL);
break;
case AVMEDIA_TYPE_AUDIO:
if (ctx->acc != NULL)
return -1;
if (ctx->ast == NULL)
ctx->ast = avformat_new_stream(ctx->avc, NULL);
break;
default:
encode_lavc_fail(ctx, "requested invalid stream type\n");
return -1;
}
if (ctx->timebase.den == 0) {
AVRational r;
@@ -584,13 +593,18 @@ AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx,
ctx->options->vcodec) {
encode_lavc_fail(ctx, "vo-lavc: encoder not found\n");
}
return NULL;
return -1;
}
avcodec_get_context_defaults3(stream->codec, ctx->vc);
#if HAVE_AVCODEC_HAS_CODECPAR
ctx->vcc = avcodec_alloc_context3(ctx->vc);
#else
avcodec_get_context_defaults3(ctx->vst->codec, ctx->vc);
ctx->vcc = ctx->vst->codec;
#endif
// Using codec->time_base is deprecated, but needed for older lavf.
stream->time_base = ctx->timebase;
stream->codec->time_base = ctx->timebase;
ctx->vst->time_base = ctx->timebase;
ctx->vcc->time_base = ctx->timebase;
ctx->voptions = NULL;
@@ -606,10 +620,12 @@ AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx,
if (ctx->avc->oformat->flags & AVFMT_GLOBALHEADER)
set_to_avdictionary(ctx, &ctx->voptions, "flags", "+global_header");
encode_2pass_prepare(ctx, &ctx->voptions, stream,
encode_2pass_prepare(ctx, &ctx->voptions, ctx->vst, ctx->vcc,
&ctx->twopass_bytebuffer_v,
"vo-lavc");
break;
*stream_out = ctx->vst;
*codec_out = ctx->vcc;
return 0;
case AVMEDIA_TYPE_AUDIO:
if (!ctx->ac) {
@@ -617,15 +633,20 @@ AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx,
ctx->options->acodec) {
encode_lavc_fail(ctx, "ao-lavc: encoder not found\n");
}
return NULL;
return -1;
}
avcodec_get_context_defaults3(stream->codec, ctx->ac);
#if HAVE_AVCODEC_HAS_CODECPAR
ctx->acc = avcodec_alloc_context3(ctx->ac);
#else
avcodec_get_context_defaults3(ctx->ast->codec, ctx->ac);
ctx->acc = ctx->ast->codec;
#endif
// Using codec->time_base is deprecated, but needed for older lavf.
stream->time_base = ctx->timebase;
stream->codec->time_base = ctx->timebase;
ctx->ast->time_base = ctx->timebase;
ctx->acc->time_base = ctx->timebase;
ctx->aoptions = NULL;
ctx->aoptions = 0;
if (ctx->options->aopts)
for (p = ctx->options->aopts; *p; ++p)
@@ -639,49 +660,34 @@ AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx,
if (ctx->avc->oformat->flags & AVFMT_GLOBALHEADER)
set_to_avdictionary(ctx, &ctx->aoptions, "flags", "+global_header");
encode_2pass_prepare(ctx, &ctx->aoptions, stream,
encode_2pass_prepare(ctx, &ctx->aoptions, ctx->ast, ctx->acc,
&ctx->twopass_bytebuffer_a,
"ao-lavc");
break;
default:
encode_lavc_fail(ctx, "requested invalid stream type\n");
return NULL;
*stream_out = ctx->ast;
*codec_out = ctx->acc;
return 0;
}
return stream;
// Unreachable.
return -1;
}
AVCodec *encode_lavc_get_codec(struct encode_lavc_context *ctx,
AVStream *stream)
{
CHECK_FAIL(ctx, NULL);
switch (stream->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
return ctx->vc;
case AVMEDIA_TYPE_AUDIO:
return ctx->ac;
default:
break;
}
return NULL;
}
int encode_lavc_open_codec(struct encode_lavc_context *ctx, AVStream *stream)
int encode_lavc_open_codec(struct encode_lavc_context *ctx,
AVCodecContext *codec)
{
AVDictionaryEntry *de;
int ret;
CHECK_FAIL(ctx, -1);
switch (stream->codec->codec_type) {
switch (codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
MP_INFO(ctx, "Opening video encoder: %s [%s]\n",
ctx->vc->long_name, ctx->vc->name);
if (ctx->vc->capabilities & CODEC_CAP_EXPERIMENTAL) {
stream->codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
MP_WARN(ctx, "\n\n"
" ********************************************\n"
" **** Experimental VIDEO codec selected! ****\n"
@@ -701,7 +707,11 @@ int encode_lavc_open_codec(struct encode_lavc_context *ctx, AVStream *stream)
ctx->vc->name);
}
ret = avcodec_open2(stream->codec, ctx->vc, &ctx->voptions);
ret = avcodec_open2(codec, ctx->vc, &ctx->voptions);
#if HAVE_AVCODEC_HAS_CODECPAR
if (ret >= 0)
ret = avcodec_parameters_from_context(ctx->vst->codecpar, codec);
#endif
// complain about all remaining options, then free the dict
for (de = NULL; (de = av_dict_get(ctx->voptions, "", de,
@@ -716,7 +726,7 @@ int encode_lavc_open_codec(struct encode_lavc_context *ctx, AVStream *stream)
ctx->ac->long_name, ctx->ac->name);
if (ctx->ac->capabilities & CODEC_CAP_EXPERIMENTAL) {
stream->codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
MP_WARN(ctx, "\n\n"
" ********************************************\n"
" **** Experimental AUDIO codec selected! ****\n"
@@ -735,7 +745,12 @@ int encode_lavc_open_codec(struct encode_lavc_context *ctx, AVStream *stream)
"If none of this helps you, try another codec in place of %s.\n\n",
ctx->ac->name);
}
ret = avcodec_open2(stream->codec, ctx->ac, &ctx->aoptions);
ret = avcodec_open2(codec, ctx->ac, &ctx->aoptions);
#if HAVE_AVCODEC_HAS_CODECPAR
if (ret >= 0)
ret = avcodec_parameters_from_context(ctx->ast->codecpar, codec);
#endif
// complain about all remaining options, then free the dict
for (de = NULL; (de = av_dict_get(ctx->aoptions, "", de,
@@ -757,36 +772,43 @@ int encode_lavc_open_codec(struct encode_lavc_context *ctx, AVStream *stream)
return ret;
}
void encode_lavc_write_stats(struct encode_lavc_context *ctx, AVStream *stream)
void encode_lavc_write_stats(struct encode_lavc_context *ctx,
AVCodecContext *codec)
{
CHECK_FAIL(ctx, );
switch (stream->codec->codec_type) {
switch (codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
if (ctx->twopass_bytebuffer_v)
if (stream->codec->stats_out)
if (codec->stats_out)
stream_write_buffer(ctx->twopass_bytebuffer_v,
stream->codec->stats_out,
strlen(stream->codec->stats_out));
codec->stats_out,
strlen(codec->stats_out));
break;
case AVMEDIA_TYPE_AUDIO:
if (ctx->twopass_bytebuffer_a)
if (stream->codec->stats_out)
if (codec->stats_out)
stream_write_buffer(ctx->twopass_bytebuffer_a,
stream->codec->stats_out,
strlen(stream->codec->stats_out));
codec->stats_out,
strlen(codec->stats_out));
break;
default:
break;
}
}
int encode_lavc_write_frame(struct encode_lavc_context *ctx, AVPacket *packet)
int encode_lavc_write_frame(struct encode_lavc_context *ctx, AVStream *stream,
AVPacket *packet)
{
int r;
CHECK_FAIL(ctx, -1);
if (stream->index != packet->stream_index) {
MP_ERR(ctx, "Called encode_lavc_write_frame on the wrong stream\n");
return -1;
}
if (ctx->header_written <= 0)
return -1;
@@ -795,27 +817,32 @@ int encode_lavc_write_frame(struct encode_lavc_context *ctx, AVPacket *packet)
(int)packet->stream_index,
(int)packet->pts,
packet->pts
* (double)ctx->avc->streams[packet->stream_index]->time_base.num
/ (double)ctx->avc->streams[packet->stream_index]->time_base.den,
* (double)stream->time_base.num
/ (double)stream->time_base.den,
(int)packet->dts,
packet->dts
* (double)ctx->avc->streams[packet->stream_index]->time_base.num
/ (double)ctx->avc->streams[packet->stream_index]->time_base.den,
* (double)stream->time_base.num
/ (double)stream->time_base.den,
(int)packet->size);
switch (ctx->avc->streams[packet->stream_index]->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
ctx->vbytes += packet->size;
++ctx->frames;
break;
case AVMEDIA_TYPE_AUDIO:
ctx->abytes += packet->size;
ctx->audioseconds += packet->duration
* (double)ctx->avc->streams[packet->stream_index]->time_base.num
/ (double)ctx->avc->streams[packet->stream_index]->time_base.den;
break;
default:
break;
#if HAVE_AVCODEC_HAS_CODECPAR
switch (stream->codecpar->codec_type) {
#else
switch (stream->codec->codec_type) {
#endif
case AVMEDIA_TYPE_VIDEO:
ctx->vbytes += packet->size;
++ctx->frames;
break;
case AVMEDIA_TYPE_AUDIO:
ctx->abytes += packet->size;
ctx->audioseconds += packet->duration
* (double)stream->time_base.num
/ (double)stream->time_base.den;
break;
default:
break;
}
r = av_interleaved_write_frame(ctx->avc, packet);
@@ -1062,11 +1089,12 @@ bool encode_lavc_showhelp(struct mp_log *log, struct encode_opts *opts)
return help_output;
}
double encode_lavc_getoffset(struct encode_lavc_context *ctx, AVStream *stream)
double encode_lavc_getoffset(struct encode_lavc_context *ctx,
AVCodecContext *codec)
{
CHECK_FAIL(ctx, 0);
switch (stream->codec->codec_type) {
switch (codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
return ctx->options->voffset;
case AVMEDIA_TYPE_AUDIO:
@@ -1151,49 +1179,49 @@ void encode_lavc_fail(struct encode_lavc_context *ctx, const char *format, ...)
}
bool encode_lavc_set_csp(struct encode_lavc_context *ctx,
AVStream *stream, enum mp_csp csp)
AVCodecContext *codec, enum mp_csp csp)
{
CHECK_FAIL(ctx, NULL);
if (ctx->header_written) {
if (stream->codec->colorspace != mp_csp_to_avcol_spc(csp))
if (codec->colorspace != mp_csp_to_avcol_spc(csp))
MP_WARN(ctx, "can not change color space during encoding\n");
return false;
}
stream->codec->colorspace = mp_csp_to_avcol_spc(csp);
codec->colorspace = mp_csp_to_avcol_spc(csp);
return true;
}
bool encode_lavc_set_csp_levels(struct encode_lavc_context *ctx,
AVStream *stream, enum mp_csp_levels lev)
AVCodecContext *codec, enum mp_csp_levels lev)
{
CHECK_FAIL(ctx, NULL);
if (ctx->header_written) {
if (stream->codec->color_range != mp_csp_levels_to_avcol_range(lev))
if (codec->color_range != mp_csp_levels_to_avcol_range(lev))
MP_WARN(ctx, "can not change color space during encoding\n");
return false;
}
stream->codec->color_range = mp_csp_levels_to_avcol_range(lev);
codec->color_range = mp_csp_levels_to_avcol_range(lev);
return true;
}
enum mp_csp encode_lavc_get_csp(struct encode_lavc_context *ctx,
AVStream *stream)
AVCodecContext *codec)
{
CHECK_FAIL(ctx, 0);
return avcol_spc_to_mp_csp(stream->codec->colorspace);
return avcol_spc_to_mp_csp(codec->colorspace);
}
enum mp_csp_levels encode_lavc_get_csp_levels(struct encode_lavc_context *ctx,
AVStream *stream)
AVCodecContext *codec)
{
CHECK_FAIL(ctx, 0);
return avcol_range_to_mp_csp_levels(stream->codec->color_range);
return avcol_range_to_mp_csp_levels(codec->color_range);
}
// vim: ts=4 sw=4 et
+22 -11
View File
@@ -46,8 +46,14 @@ struct encode_lavc_context {
float vo_fps;
// these are processed from the options
// FFmpeg contexts.
AVFormatContext *avc;
AVStream *vst;
AVStream *ast;
AVCodecContext *vcc;
AVCodecContext *acc;
// these are processed from the options
AVRational timebase;
AVCodec *vc;
AVCodec *ac;
@@ -88,26 +94,31 @@ struct encode_lavc_context {
};
// interface for vo/ao drivers
AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx, enum AVMediaType mt);
void encode_lavc_write_stats(struct encode_lavc_context *ctx, AVStream *stream);
int encode_lavc_write_frame(struct encode_lavc_context *ctx, AVPacket *packet);
int encode_lavc_alloc_stream(struct encode_lavc_context *ctx,
enum AVMediaType mt, AVStream **stream_out,
AVCodecContext **codec_out);
void encode_lavc_write_stats(struct encode_lavc_context *ctx,
AVCodecContext *stream);
int encode_lavc_write_frame(struct encode_lavc_context *ctx, AVStream *stream,
AVPacket *packet);
int encode_lavc_supports_pixfmt(struct encode_lavc_context *ctx, enum AVPixelFormat format);
AVCodec *encode_lavc_get_codec(struct encode_lavc_context *ctx, AVStream *stream);
int encode_lavc_open_codec(struct encode_lavc_context *ctx, AVStream *stream);
int encode_lavc_open_codec(struct encode_lavc_context *ctx,
AVCodecContext *codec);
int encode_lavc_available(struct encode_lavc_context *ctx);
int encode_lavc_timesyncfailed(struct encode_lavc_context *ctx);
int encode_lavc_start(struct encode_lavc_context *ctx); // returns 1 on success
int encode_lavc_oformat_flags(struct encode_lavc_context *ctx);
double encode_lavc_getoffset(struct encode_lavc_context *ctx, AVStream *stream);
double encode_lavc_getoffset(struct encode_lavc_context *ctx,
AVCodecContext *codec);
void encode_lavc_fail(struct encode_lavc_context *ctx, const char *format, ...); // report failure of encoding
bool encode_lavc_set_csp(struct encode_lavc_context *ctx,
AVStream *stream, enum mp_csp csp);
AVCodecContext *codec, enum mp_csp csp);
bool encode_lavc_set_csp_levels(struct encode_lavc_context *ctx,
AVStream *stream, enum mp_csp_levels lev);
AVCodecContext *codec, enum mp_csp_levels lev);
enum mp_csp encode_lavc_get_csp(struct encode_lavc_context *ctx,
AVStream *stream);
AVCodecContext *codec);
enum mp_csp_levels encode_lavc_get_csp_levels(struct encode_lavc_context *ctx,
AVStream *stream);
AVCodecContext *codec);
#endif
+250 -121
View File
@@ -119,16 +119,20 @@ struct demux_internal {
int max_packs;
int max_bytes;
// Set if we know that we are at the start of the file. This is used to
// avoid a redundant initial seek after enabling streams. We could just
// allow it, but to avoid buggy seeking affecting normal playback, we don't.
bool initial_state;
bool tracks_switched; // thread needs to inform demuxer of this
bool seeking; // there's a seek queued
int seek_flags; // flags for next seek (if seeking==true)
double seek_pts;
bool refresh_seeks_enabled;
bool start_refresh_seek;
double ref_pts; // assumed player position (only for track switches)
double ts_offset; // timestamp offset to apply everything
double ts_offset; // timestamp offset to apply to everything
void (*run_fn)(void *); // if non-NULL, function queued to be run on
void *run_fn_arg; // the thread as run_fn(run_fn_arg)
@@ -152,7 +156,10 @@ struct demux_stream {
// if false, this stream is disabled, or passively
// read (like subtitles)
bool eof; // end of demuxed stream? (true if all buffer empty)
bool need_refresh; // enabled mid-stream
bool refreshing;
bool correct_dts; // packet DTS is strictly monotonically increasing
bool correct_pos; // packet pos is strictly monotonically increasing
size_t packs; // number of packets in buffer
size_t bytes; // total bytes of packets in buffer
double base_ts; // timestamp of the last packet returned to decoder
@@ -161,12 +168,12 @@ struct demux_stream {
size_t last_br_bytes; // summed packet sizes since last bitrate calculation
double bitrate;
int64_t last_pos;
double last_dts;
struct demux_packet *head;
struct demux_packet *tail;
// for closed captions (demuxer_feed_caption)
struct sh_stream *cc;
};
// Return "a", or if that is NOPTS, return "def".
@@ -199,7 +206,10 @@ static void ds_flush(struct demux_stream *ds)
ds->eof = false;
ds->active = false;
ds->refreshing = false;
ds->need_refresh = false;
ds->last_pos = -1;
ds->last_dts = MP_NOPTS_VALUE;
ds->correct_dts = ds->correct_pos = true;
}
void demux_set_ts_offset(struct demuxer *demuxer, double offset)
@@ -222,6 +232,7 @@ struct sh_stream *demux_alloc_sh_stream(enum stream_type type)
.ff_index = -1, // may be overwritten by demuxer
.demuxer_id = -1, // ... same
.codec = talloc_zero(sh, struct mp_codec_params),
.tags = talloc_zero(sh, struct mp_tags),
};
sh->codec->type = type;
return sh;
@@ -266,6 +277,33 @@ void demux_add_sh_stream(struct demuxer *demuxer, struct sh_stream *sh)
pthread_mutex_unlock(&in->lock);
}
// Update sh->tags (lazily). This must be called by demuxers which update
// stream tags after init. (sh->tags can be accessed by the playback thread,
// which means the demuxer thread cannot write or read it directly.)
// Before init is finished, sh->tags can still be accessed freely.
// Ownership of tags goes to the function.
void demux_set_stream_tags(struct demuxer *demuxer, struct sh_stream *sh,
struct mp_tags *tags)
{
struct demux_internal *in = demuxer->in;
assert(demuxer == in->d_thread);
if (sh->ds) {
while (demuxer->num_update_stream_tags <= sh->index) {
MP_TARRAY_APPEND(demuxer, demuxer->update_stream_tags,
demuxer->num_update_stream_tags, NULL);
}
talloc_free(demuxer->update_stream_tags[sh->index]);
demuxer->update_stream_tags[sh->index] = talloc_steal(demuxer, tags);
demux_changed(demuxer, DEMUX_EVENT_METADATA);
} else {
// not added yet
talloc_free(sh->tags);
sh->tags = talloc_steal(sh, tags);
}
}
// Return a stream with the given index. Since streams can only be added during
// the lifetime of the demuxer, it is guaranteed that an index within the valid
// range [0, demux_get_num_stream()) always returns a valid sh_stream pointer,
@@ -389,6 +427,59 @@ void demuxer_feed_caption(struct sh_stream *stream, demux_packet_t *dp)
demux_add_packet(sh, dp);
}
// An obscure mechanism to get stream switching to be executed faster.
// On a switch, it seeks back, and then grabs all packets that were
// "missing" from the packet queue of the newly selected stream.
// Returns MP_NOPTS_VALUE if no seek should happen.
static double get_refresh_seek_pts(struct demux_internal *in)
{
struct demuxer *demux = in->d_thread;
double start_ts = in->ref_pts;
bool needed = false;
bool normal_seek = true;
bool refresh_possible = true;
for (int n = 0; n < in->num_streams; n++) {
struct demux_stream *ds = in->streams[n]->ds;
if (!ds->selected)
continue;
if (ds->type == STREAM_VIDEO || ds->type == STREAM_AUDIO)
start_ts = MP_PTS_MIN(start_ts, ds->base_ts);
needed |= ds->need_refresh;
// If there were no other streams selected, we can use a normal seek.
normal_seek &= ds->need_refresh;
ds->need_refresh = false;
refresh_possible &= ds->correct_dts || ds->correct_pos;
}
if (!needed || start_ts == MP_NOPTS_VALUE || !demux->desc->seek ||
!demux->seekable || demux->partially_seekable)
return MP_NOPTS_VALUE;
if (normal_seek)
return start_ts;
if (!refresh_possible) {
MP_VERBOSE(in, "can't issue refresh seek\n");
return MP_NOPTS_VALUE;
}
for (int n = 0; n < in->num_streams; n++) {
struct demux_stream *ds = in->streams[n]->ds;
// Streams which didn't have any packets yet will return all packets,
// other streams return packets only starting from the last position.
if (ds->last_pos != -1 || ds->last_dts != MP_NOPTS_VALUE)
ds->refreshing = true;
}
// Seek back to player's current position, with a small offset added.
return start_ts - 1.0;
}
void demux_add_packet(struct sh_stream *stream, demux_packet_t *dp)
{
struct demux_stream *ds = stream ? stream->ds : NULL;
@@ -399,25 +490,34 @@ void demux_add_packet(struct sh_stream *stream, demux_packet_t *dp)
struct demux_internal *in = ds->in;
pthread_mutex_lock(&in->lock);
bool drop = false;
bool drop = ds->refreshing;
if (ds->refreshing) {
// Resume reading once the old position was reached (i.e. we start
// returning packets where we left off before the refresh).
drop = dp->pos <= ds->last_pos;
if (dp->pos >= ds->last_pos)
ds->refreshing = false;
// If it's the same position, drop, but continue normally next time.
if (ds->correct_dts) {
ds->refreshing = dp->dts < ds->last_dts;
} else if (ds->correct_pos) {
ds->refreshing = dp->pos < ds->last_pos;
} else {
ds->refreshing = false; // should not happen
}
}
if (!ds->selected || in->seeking || drop) {
if (!ds->selected || ds->need_refresh || in->seeking || drop) {
pthread_mutex_unlock(&in->lock);
talloc_free(dp);
return;
}
ds->correct_pos &= dp->pos >= 0 && dp->pos > ds->last_pos;
ds->correct_dts &= dp->dts != MP_NOPTS_VALUE && dp->dts > ds->last_dts;
ds->last_pos = dp->pos;
ds->last_dts = dp->dts;
dp->stream = stream->index;
dp->next = NULL;
ds->last_pos = dp->pos;
ds->packs++;
ds->bytes += dp->len;
if (ds->tail) {
@@ -480,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);
}
}
}
@@ -505,27 +605,40 @@ static bool read_packet(struct demux_internal *in)
if (!read_more)
return false;
double seek_pts = get_refresh_seek_pts(in);
// Actually read a packet. Drop the lock while doing so, because waiting
// for disk or network I/O can take time.
in->idle = false;
in->initial_state = false;
pthread_mutex_unlock(&in->lock);
struct demuxer *demux = in->d_thread;
if (seek_pts != MP_NOPTS_VALUE) {
MP_VERBOSE(in, "refresh seek to %f\n", seek_pts);
demux->desc->seek(demux, seek_pts, SEEK_BACKWARD | SEEK_HR);
}
bool eof = !demux->desc->fill_buffer || demux->desc->fill_buffer(demux) <= 0;
update_cache(in);
pthread_mutex_lock(&in->lock);
if (eof) {
for (int n = 0; n < in->num_streams; n++)
in->streams[n]->ds->eof = true;
// If we had EOF previously, then don't wakeup (avoids wakeup loop)
if (!in->last_eof) {
if (in->wakeup_cb)
in->wakeup_cb(in->wakeup_cb_ctx);
pthread_cond_signal(&in->wakeup);
MP_VERBOSE(in, "EOF reached.\n");
if (!in->seeking) {
if (eof) {
for (int n = 0; n < in->num_streams; n++)
in->streams[n]->ds->eof = true;
// If we had EOF previously, then don't wakeup (avoids wakeup loop)
if (!in->last_eof) {
if (in->wakeup_cb)
in->wakeup_cb(in->wakeup_cb_ctx);
pthread_cond_signal(&in->wakeup);
MP_VERBOSE(in, "EOF reached.\n");
}
}
in->eof = in->last_eof = eof;
}
in->eof = in->last_eof = eof;
return true;
}
@@ -550,42 +663,6 @@ static void ds_get_packets(struct demux_stream *ds)
}
}
// An obscure mechanism to get stream switching to be executed faster.
// On a switch, it seeks back, and then grabs all packets that were
// "missing" from the packet queue of the newly selected stream.
static void start_refreshing(struct demux_internal *in)
{
struct demuxer *demux = in->d_thread;
in->start_refresh_seek = false;
double start_ts = MP_NOPTS_VALUE;
for (int n = 0; n < in->num_streams; n++) {
struct demux_stream *ds = in->streams[n]->ds;
if (ds->type == STREAM_VIDEO || ds->type == STREAM_AUDIO)
start_ts = MP_PTS_MIN(start_ts, ds->base_ts);
}
if (start_ts == MP_NOPTS_VALUE || !demux->desc->seek || !demux->seekable ||
demux->partially_seekable || !demux->allow_refresh_seeks)
return;
for (int n = 0; n < in->num_streams; n++) {
struct demux_stream *ds = in->streams[n]->ds;
// Streams which didn't read any packets yet can return all packets,
// or they'd be stuck forever; affects newly selected streams too.
if (ds->last_pos != -1)
ds->refreshing = true;
}
pthread_mutex_unlock(&in->lock);
// Seek back to player's current position, with a small offset added.
in->d_thread->desc->seek(in->d_thread, start_ts - 1.0, SEEK_BACKWARD | SEEK_HR);
pthread_mutex_lock(&in->lock);
}
static void execute_trackswitch(struct demux_internal *in)
{
in->tracks_switched = false;
@@ -603,9 +680,6 @@ static void execute_trackswitch(struct demux_internal *in)
&(int){any_selected});
pthread_mutex_lock(&in->lock);
if (in->start_refresh_seek)
start_refreshing(in);
}
static void execute_seek(struct demux_internal *in)
@@ -613,6 +687,7 @@ static void execute_seek(struct demux_internal *in)
int flags = in->seek_flags;
double pts = in->seek_pts;
in->seeking = false;
in->initial_state = false;
pthread_mutex_unlock(&in->lock);
@@ -853,17 +928,18 @@ static int decode_float(char *str, float *out)
return 0;
}
static int decode_gain(demuxer_t *demuxer, const char *tag, float *out)
static int decode_gain(struct mp_log *log, struct mp_tags *tags,
const char *tag, float *out)
{
char *tag_val = NULL;
float dec_val;
tag_val = mp_tags_get_str(demuxer->metadata, tag);
tag_val = mp_tags_get_str(tags, tag);
if (!tag_val)
return -1;
if (decode_float(tag_val, &dec_val)) {
mp_msg(demuxer->log, MSGL_ERR, "Invalid replaygain value\n");
if (decode_float(tag_val, &dec_val) < 0) {
mp_msg(log, MSGL_ERR, "Invalid replaygain value\n");
return -1;
}
@@ -871,62 +947,68 @@ static int decode_gain(demuxer_t *demuxer, const char *tag, float *out)
return 0;
}
static int decode_peak(demuxer_t *demuxer, const char *tag, float *out)
static int decode_peak(struct mp_log *log, struct mp_tags *tags,
const char *tag, float *out)
{
char *tag_val = NULL;
float dec_val;
*out = 1.0;
tag_val = mp_tags_get_str(demuxer->metadata, tag);
tag_val = mp_tags_get_str(tags, tag);
if (!tag_val)
return 0;
if (decode_float(tag_val, &dec_val))
return 0;
if (dec_val == 0.0)
return 0;
if (decode_float(tag_val, &dec_val) < 0 || dec_val <= 0.0)
return -1;
*out = dec_val;
return 0;
}
static void apply_replaygain(demuxer_t *demuxer, struct replaygain_data *rg)
static struct replaygain_data *decode_rgain(struct mp_log *log,
struct mp_tags *tags)
{
struct replaygain_data rg = {0};
if (decode_gain(log, tags, "REPLAYGAIN_TRACK_GAIN", &rg.track_gain) >= 0 &&
decode_peak(log, tags, "REPLAYGAIN_TRACK_PEAK", &rg.track_peak) >= 0)
{
if (decode_gain(log, tags, "REPLAYGAIN_ALBUM_GAIN", &rg.album_gain) < 0 ||
decode_peak(log, tags, "REPLAYGAIN_ALBUM_PEAK", &rg.album_peak) < 0)
{
rg.album_gain = rg.track_gain;
rg.album_peak = rg.track_peak;
}
return talloc_memdup(NULL, &rg, sizeof(rg));
}
if (decode_gain(log, tags, "REPLAYGAIN_GAIN", &rg.track_gain) >= 0 &&
decode_peak(log, tags, "REPLAYGAIN_PEAK", &rg.track_peak) >= 0)
{
rg.album_gain = rg.track_gain;
rg.album_peak = rg.track_peak;
return talloc_memdup(NULL, &rg, sizeof(rg));
}
return NULL;
}
static void demux_update_replaygain(demuxer_t *demuxer)
{
struct demux_internal *in = demuxer->in;
for (int n = 0; n < in->num_streams; n++) {
struct sh_stream *sh = in->streams[n];
if (sh->type == STREAM_AUDIO && !sh->codec->replaygain_data) {
MP_VERBOSE(demuxer, "Replaygain: Track=%f/%f Album=%f/%f\n",
rg->track_gain, rg->track_peak,
rg->album_gain, rg->album_peak);
sh->codec->replaygain_data = talloc_memdup(in, rg, sizeof(*rg));
struct replaygain_data *rg = decode_rgain(demuxer->log, sh->tags);
if (!rg)
rg = decode_rgain(demuxer->log, demuxer->metadata);
if (rg)
sh->codec->replaygain_data = talloc_steal(in, rg);
}
}
}
static void demux_export_replaygain(demuxer_t *demuxer)
{
struct replaygain_data rg = {0};
if (!decode_gain(demuxer, "REPLAYGAIN_TRACK_GAIN", &rg.track_gain) &&
!decode_peak(demuxer, "REPLAYGAIN_TRACK_PEAK", &rg.track_peak) &&
!decode_gain(demuxer, "REPLAYGAIN_ALBUM_GAIN", &rg.album_gain) &&
!decode_peak(demuxer, "REPLAYGAIN_ALBUM_PEAK", &rg.album_peak))
{
apply_replaygain(demuxer, &rg);
}
if (!decode_gain(demuxer, "REPLAYGAIN_GAIN", &rg.track_gain) &&
!decode_peak(demuxer, "REPLAYGAIN_PEAK", &rg.track_peak))
{
rg.album_gain = rg.track_gain;
rg.album_peak = rg.track_peak;
apply_replaygain(demuxer, &rg);
}
}
// Copy all fields from src to dst, depending on event flags.
static void demux_copy(struct demuxer *dst, struct demuxer *src)
{
@@ -947,15 +1029,30 @@ static void demux_copy(struct demuxer *dst, struct demuxer *src)
dst->partially_seekable = src->partially_seekable;
dst->filetype = src->filetype;
dst->ts_resets_possible = src->ts_resets_possible;
dst->allow_refresh_seeks = src->allow_refresh_seeks;
dst->fully_read = src->fully_read;
dst->start_time = src->start_time;
dst->is_network = src->is_network;
dst->priv = src->priv;
}
if (src->events & DEMUX_EVENT_METADATA) {
talloc_free(dst->metadata);
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);
}
for (int n = 0; n < dst->num_update_stream_tags; n++) {
talloc_free(dst->update_stream_tags[n]);
dst->update_stream_tags[n] =
talloc_steal(dst->update_stream_tags, src->update_stream_tags[n]);
src->update_stream_tags[n] = NULL;
}
}
dst->events |= src->events;
src->events = 0;
}
@@ -977,8 +1074,6 @@ void demux_changed(demuxer_t *demuxer, int events)
if (demuxer->events & DEMUX_EVENT_INIT)
demuxer_sort_chapters(demuxer);
if (demuxer->events & (DEMUX_EVENT_METADATA | DEMUX_EVENT_STREAMS))
demux_export_replaygain(demuxer);
demux_copy(in->d_buffer, demuxer);
@@ -1001,8 +1096,28 @@ void demux_update(demuxer_t *demuxer)
demux_copy(demuxer, in->d_buffer);
demuxer->events |= in->events;
in->events = 0;
if (in->stream_metadata && (demuxer->events & DEMUX_EVENT_METADATA))
mp_tags_merge(demuxer->metadata, in->stream_metadata);
if (demuxer->events & DEMUX_EVENT_METADATA) {
int num_streams = MPMIN(in->num_streams, demuxer->num_update_stream_tags);
for (int n = 0; n < num_streams; n++) {
struct mp_tags *tags = demuxer->update_stream_tags[n];
demuxer->update_stream_tags[n] = NULL;
if (tags) {
struct sh_stream *sh = in->streams[n];
talloc_free(sh->tags);
sh->tags = talloc_steal(sh, tags);
}
}
// Often useful audio-only files, which have metadata in the audio track
// metadata instead of the main metadata (especially OGG).
if (in->num_streams == 1)
mp_tags_merge(demuxer->metadata, in->streams[0]->tags);
if (in->stream_metadata)
mp_tags_merge(demuxer->metadata, in->stream_metadata);
}
if (demuxer->events & (DEMUX_EVENT_METADATA | DEMUX_EVENT_STREAMS))
demux_update_replaygain(demuxer);
pthread_mutex_unlock(&in->lock);
}
@@ -1037,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,
@@ -1058,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;
@@ -1074,6 +1207,7 @@ static struct demuxer *open_given_type(struct mpv_global *global,
.min_secs = demuxer->opts->demuxer_min_secs,
.max_packs = demuxer->opts->demuxer_max_packs,
.max_bytes = demuxer->opts->demuxer_max_bytes,
.initial_state = true,
};
pthread_mutex_init(&in->lock, NULL);
pthread_cond_init(&in->wakeup, NULL);
@@ -1129,6 +1263,7 @@ static struct demuxer *open_given_type(struct mpv_global *global,
&params2, DEMUX_CHECK_FORCE);
if (sub)
return sub;
timeline_destroy(tl);
}
return demuxer;
}
@@ -1195,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,
@@ -1213,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);
}
@@ -1276,18 +1414,6 @@ int demux_seek(demuxer_t *demuxer, double seek_pts, int flags)
return 1;
}
// Enable doing a "refresh seek" on the next stream switch.
// Note that this by design does not disable ongoing refresh seeks, and
// does not affect previous stream switch commands (even if they were
// asynchronous).
void demux_set_enable_refresh_seeks(struct demuxer *demuxer, bool enabled)
{
struct demux_internal *in = demuxer->in;
pthread_mutex_lock(&in->lock);
in->refresh_seeks_enabled = enabled;
pthread_mutex_unlock(&in->lock);
}
struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d,
enum stream_type t, int id)
{
@@ -1300,19 +1426,22 @@ struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d,
return NULL;
}
// Set whether the given stream should return packets.
// ref_pts is used only if the stream is enabled. Then it serves as approximate
// start pts for this stream (in the worst case it is ignored).
void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream,
bool selected)
double ref_pts, bool selected)
{
struct demux_internal *in = demuxer->in;
pthread_mutex_lock(&in->lock);
// don't flush buffers if stream is already selected / unselected
if (stream->ds->selected != selected) {
stream->ds->selected = selected;
stream->ds->active = false;
ds_flush(stream->ds);
in->tracks_switched = true;
if (selected && in->refresh_seeks_enabled)
in->start_refresh_seek = true;
stream->ds->need_refresh = selected && !in->initial_state;
if (stream->ds->need_refresh)
in->ref_pts = MP_ADD_PTS(ref_pts, -in->ts_offset);
if (in->threading) {
pthread_cond_signal(&in->wakeup);
} else {
+10 -9
View File
@@ -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 {
@@ -178,17 +179,12 @@ typedef struct demuxer {
double start_time;
// File format allows PTS resets (even if the current file is without)
bool ts_resets_possible;
// Enable fast track switching hacks. This requires from the demuxer:
// - seeking is somewhat reliable; packet contents must not change
// - packet position (demux_packet.pos) is set, not negative, unique, and
// monotonically increasing
// - seeking leaves packet positions invariant
bool allow_refresh_seeks;
// The file data was fully read, and there is no need to keep the stream
// open, keep the cache active, or to run the demuxer thread. Generating
// 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;
@@ -216,12 +212,16 @@ typedef struct demuxer {
struct mp_log *log, *glog;
struct demuxer_params *params;
struct demux_internal *in; // internal to demux.c
// internal to demux.c
struct demux_internal *in;
struct mp_tags **update_stream_tags;
int num_update_stream_tags;
// Since the demuxer can run in its own thread, and the stream is not
// 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;
@@ -265,13 +265,12 @@ bool demux_cancel_test(struct demuxer *demuxer);
void demux_flush(struct demuxer *demuxer);
int demux_seek(struct demuxer *demuxer, double rel_seek_secs, int flags);
void demux_set_enable_refresh_seeks(struct demuxer *demuxer, bool enabled);
void demux_set_ts_offset(struct demuxer *demuxer, double offset);
int demux_control(struct demuxer *demuxer, int cmd, void *arg);
void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream,
bool selected);
double ref_pts, bool selected);
void demux_set_stream_autoselect(struct demuxer *demuxer, bool autoselect);
void demuxer_help(struct mp_log *log);
@@ -280,6 +279,8 @@ int demuxer_add_attachment(struct demuxer *demuxer, char *name,
char *type, void *data, size_t data_size);
int demuxer_add_chapter(demuxer_t *demuxer, char *name,
double pts, uint64_t demuxer_id);
void demux_set_stream_tags(struct demuxer *demuxer, struct sh_stream *sh,
struct mp_tags *tags);
double demuxer_get_time_length(struct demuxer *demuxer);
+1 -1
View File
@@ -57,7 +57,7 @@ static void reselect_streams(demuxer_t *demuxer)
for (int n = 0; n < MPMIN(num_slave, p->num_streams); n++) {
if (p->streams[n]) {
demuxer_select_track(p->slave, demux_get_stream(p->slave, n),
demux_stream_is_selected(p->streams[n]));
MP_NOPTS_VALUE, demux_stream_is_selected(p->streams[n]));
}
}
}
+14 -14
View File
@@ -213,25 +213,25 @@ static void build_timeline(struct timeline *tl, struct tl_parts *parts)
resolve_timestamps(part, source);
double len = source_get_length(source);
if (len > 0) {
len += source->start_time;
} else {
MP_WARN(tl, "EDL: source file '%s' has unknown duration.\n",
part->filename);
}
double end_time = source_get_length(source);
if (end_time >= 0)
end_time += source->start_time;
// Unknown length => use rest of the file. If duration is unknown, make
// something up.
if (part->length < 0)
part->length = (len < 0 ? 1 : len) - part->offset;
if (len > 0) {
double partlen = part->offset + part->length;
if (partlen > len) {
if (part->length < 0) {
if (end_time < 0) {
MP_WARN(tl, "EDL: source file '%s' has unknown duration.\n",
part->filename);
end_time = 1;
}
part->length = end_time - part->offset;
} else if (end_time >= 0) {
double end_part = part->offset + part->length;
if (end_part > end_time) {
MP_WARN(tl, "EDL: entry %d uses %f "
"seconds, but file has only %f seconds.\n",
n, partlen, len);
n, end_part, end_time);
}
}
+47 -50
View File
@@ -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;
@@ -168,7 +173,6 @@ typedef struct lavf_priv {
int num_streams;
int cur_program;
char *mime_type;
bool merge_track_metadata;
double seek_delay;
} lavf_priv_t;
@@ -287,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);
}
@@ -502,7 +508,7 @@ static void select_tracks(struct demuxer *demuxer, int start)
}
}
static void export_replaygain(demuxer_t *demuxer, struct mp_codec_params *c,
static void export_replaygain(demuxer_t *demuxer, struct sh_stream *sh,
AVStream *st)
{
for (int i = 0; i < st->nb_side_data; i++) {
@@ -528,7 +534,10 @@ static void export_replaygain(demuxer_t *demuxer, struct mp_codec_params *c,
rgain->album_peak = (av_rgain->album_peak != 0.0) ?
av_rgain->album_peak / 100000.0f : 1.0;
c->replaygain_data = rgain;
// This must be run only before the stream was added, otherwise there
// will be race conditions with accesses from the user thread.
assert(!sh->ds);
sh->codec->replaygain_data = rgain;
}
}
@@ -575,7 +584,7 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
delay = lavc_delay / (double)codec->sample_rate;
priv->seek_delay = MPMAX(priv->seek_delay, delay);
export_replaygain(demuxer, sh->codec, st);
export_replaygain(demuxer, sh, st);
break;
}
@@ -664,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;
@@ -681,6 +692,7 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
if (!sh->title && sh->hls_bitrate > 0)
sh->title = talloc_asprintf(sh, "bitrate %d", sh->hls_bitrate);
sh->missing_timestamps = !!(priv->avif_flags & AVFMT_NOTIMESTAMPS);
mp_tags_copy_from_av_dictionary(sh->tags, st->metadata);
demux_add_sh_stream(demuxer, sh);
}
@@ -703,14 +715,14 @@ static void update_metadata(demuxer_t *demuxer, AVPacket *pkt)
priv->avfc->event_flags = 0;
demux_changed(demuxer, DEMUX_EVENT_METADATA);
}
if (priv->merge_track_metadata) {
for (int n = 0; n < priv->num_streams; n++) {
AVStream *st = priv->streams[n] ? priv->avfc->streams[n] : NULL;
if (st && st->event_flags & AVSTREAM_EVENT_FLAG_METADATA_UPDATED) {
mp_tags_copy_from_av_dictionary(demuxer->metadata, st->metadata);
st->event_flags = 0;
demux_changed(demuxer, DEMUX_EVENT_METADATA);
}
for (int n = 0; n < priv->num_streams; n++) {
AVStream *st = priv->streams[n] ? priv->avfc->streams[n] : NULL;
if (st && st->event_flags & AVSTREAM_EVENT_FLAG_METADATA_UPDATED) {
st->event_flags = 0;
struct mp_tags *tags = talloc_zero(NULL, struct mp_tags);
mp_tags_copy_from_av_dictionary(tags, st->metadata);
demux_set_stream_tags(demuxer, priv->streams[n], tags);
}
}
}
@@ -795,6 +807,7 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
avfc->pb = priv->pb;
if (stream_control(priv->stream, STREAM_CTRL_HAS_AVSEEK, NULL) > 0)
demuxer->seekable = true;
demuxer->seekable |= priv->format_hack.fully_read;
}
if (matches_avinputformat_name(priv, "rtsp")) {
@@ -845,26 +858,15 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
add_new_streams(demuxer);
// Often useful with OGG audio-only files, which have metadata in the audio
// track metadata instead of the main metadata.
if (demux_get_num_stream(demuxer) == 1) {
priv->merge_track_metadata = true;
for (int n = 0; n < priv->num_streams; n++) {
if (priv->streams[n])
mp_tags_copy_from_av_dictionary(demuxer->metadata, avfc->streams[n]->metadata);
}
}
mp_tags_copy_from_av_dictionary(demuxer->metadata, avfc->metadata);
update_metadata(demuxer, NULL);
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->allow_refresh_seeks = matches_avinputformat_name(priv, "mp4");
demuxer->fully_read = priv->format_hack.fully_read;
return 0;
@@ -952,30 +954,15 @@ static void demux_seek_lavf(demuxer_t *demuxer, double seek_pts, int flags)
seek_pts_av = seek_pts * AV_TIME_BASE;
}
int r;
if (!priv->avfc->iformat->read_seek2) {
// Normal seeking.
int r = av_seek_frame(priv->avfc, -1, seek_pts_av, avsflags);
if (r < 0 && (avsflags & AVSEEK_FLAG_BACKWARD)) {
// When seeking before the beginning of the file, and seeking fails,
// try again without the backwards flag to make it seek to the
// beginning.
avsflags &= ~AVSEEK_FLAG_BACKWARD;
r = av_seek_frame(priv->avfc, -1, seek_pts_av, avsflags);
if (r < 0 && (avsflags & AVSEEK_FLAG_BACKWARD)) {
// When seeking before the beginning of the file, and seeking fails,
// try again without the backwards flag to make it seek to the
// beginning.
avsflags &= ~AVSEEK_FLAG_BACKWARD;
r = av_seek_frame(priv->avfc, -1, seek_pts_av, avsflags);
}
} else {
// av_seek_frame() won't work. Use "new" seeking API. We don't use this
// API by default, because there are some major issues.
// Set max_ts==ts, so that demuxing starts from an earlier position in
// the worst case.
r = avformat_seek_file(priv->avfc, -1, INT64_MIN,
seek_pts_av, seek_pts_av, avsflags);
// Similar issue as in the normal seeking codepath.
if (r < 0) {
r = avformat_seek_file(priv->avfc, -1, INT64_MIN,
seek_pts_av, INT64_MAX, avsflags);
}
}
if (r < 0) {
char buf[180];
av_strerror(r, buf, sizeof(buf));
@@ -1084,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;
}
@@ -1101,10 +1094,14 @@ static void demux_close_lavf(demuxer_t *demuxer)
av_freep(&priv->pb->buffer);
av_freep(&priv->pb);
for (int n = 0; n < priv->num_streams; n++) {
if (priv->streams[n])
if (priv->streams[n]) {
avcodec_free_context(&priv->streams[n]->codec->lav_headers);
#if HAVE_AVCODEC_HAS_CODECPAR
avcodec_parameters_free(&priv->streams[n]->codec->lav_codecpar);
#endif
}
}
if (priv->stream != demuxer->stream)
if (priv->own_stream)
free_stream(priv->stream);
talloc_free(priv);
demuxer->priv = NULL;
+3 -16
View File
@@ -65,23 +65,10 @@ static int open_file(struct demuxer *demuxer, enum demux_check check)
char **files = NULL;
int num_files = 0;
for (;;) {
struct archive_entry *entry;
int r = archive_read_next_header(mpa->arch, &entry);
if (r == ARCHIVE_EOF)
break;
if (r < ARCHIVE_OK)
MP_ERR(demuxer, "%s\n", archive_error_string(mpa->arch));
if (r < ARCHIVE_WARN)
break;
if (archive_entry_filetype(entry) != AE_IFREG)
continue;
const char *fn = archive_entry_pathname(entry);
// Some archives may have no filenames.
if (!fn)
fn = talloc_asprintf(mpa, "mpv_unknown#%d\n", num_files);
while (mp_archive_next_entry(mpa)) {
// stream_libarchive.c does the real work
char *f = talloc_asprintf(mpa, "archive://%s|%s", prefix, fn);
char *f = talloc_asprintf(mpa, "archive://%s|%s", prefix,
mpa->entry_filename);
MP_TARRAY_APPEND(mpa, files, num_files, f);
}
+1
View File
@@ -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);
+25 -8
View File
@@ -93,6 +93,7 @@ typedef struct mkv_content_encoding {
typedef struct mkv_track {
int tnum;
uint64_t uid;
char *name;
struct sh_stream *stream;
@@ -595,6 +596,7 @@ static void parse_trackentry(struct demuxer *demuxer,
} else {
MP_ERR(demuxer, "Missing track number!\n");
}
track->uid = entry->track_uid;
if (entry->name) {
track->name = talloc_strdup(track, entry->name);
@@ -773,8 +775,9 @@ static int demux_mkv_read_cues(demuxer_t *demuxer)
if (cues.n_cue_point <= 3) // probably too sparse and will just break seeking
goto done;
// Discard incremental index.
mkv_d->num_indexes = 0;
// Discard incremental index. (Keep the first entry, which must be the
// start of the file - helps with files that miss the first index entry.)
mkv_d->num_indexes = MPMIN(1, mkv_d->num_indexes);
mkv_d->index_has_durations = false;
for (int i = 0; i < cues.n_cue_point; i++) {
@@ -985,9 +988,6 @@ static void process_tags(demuxer_t *demuxer)
for (int i = 0; i < tags->n_tag; i++) {
struct ebml_tag tag = tags->tag[i];
if (tag.targets.target_track_uid || tag.targets.target_attachment_uid)
continue;
struct mp_tags *dst = NULL;
if (tag.targets.target_chapter_uid) {
@@ -1008,6 +1008,19 @@ static void process_tags(demuxer_t *demuxer)
break;
}
}
} else if (tag.targets.target_track_uid) {
for (int n = 0; n < mkv_d->num_tracks; n++) {
if (mkv_d->tracks[n]->uid ==
tag.targets.target_track_uid)
{
struct sh_stream *sh = mkv_d->tracks[n]->stream;
if (sh)
dst = sh->tags;
break;
}
}
} else if (tag.targets.target_attachment_uid) {
/* ignore */
} else {
dst = demuxer->metadata;
}
@@ -1719,6 +1732,7 @@ static const char *const mkv_sub_tag[][2] = {
{ "S_HDMV/PGS", "hdmv_pgs_subtitle"},
{ "D_WEBVTT/SUBTITLES", "webvtt-webm"},
{ "D_WEBVTT/CAPTIONS", "webvtt-webm"},
{ "S_TEXT/WEBVTT", "webvtt"},
{ "S_DVBSUB", "dvb_subtitle"},
{0}
};
@@ -1922,10 +1936,9 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check)
MP_VERBOSE(demuxer, "All headers are parsed!\n");
process_tags(demuxer);
display_create_tracks(demuxer);
add_coverart(demuxer);
demuxer->allow_refresh_seeks = true;
process_tags(demuxer);
probe_first_timestamp(demuxer);
if (opts->demux_mkv->probe_duration)
@@ -2609,6 +2622,7 @@ static int read_next_block(demuxer_t *demuxer, struct block_info *block)
find_next_cluster:
mkv_d->cluster_end = 0;
for (;;) {
stream_peek(s, 4); // guarantee we can undo ebml_read_id() below
mkv_d->cluster_start = stream_tell(s);
uint32_t id = ebml_read_id(s);
if (id == MATROSKA_ID_CLUSTER)
@@ -2627,6 +2641,7 @@ static int read_next_block(demuxer_t *demuxer, struct block_info *block)
if ((!ebml_is_mkv_level1_id(id) && id != EBML_ID_VOID) ||
ebml_read_skip(demuxer->log, -1, s) != 0)
{
stream_seek(s, mkv_d->cluster_start);
ebml_resync_cluster(demuxer->log, s);
}
}
@@ -2963,8 +2978,10 @@ static void probe_first_timestamp(struct demuxer *demuxer)
return;
struct block_info block;
if (read_next_block(demuxer, &block) > 0)
if (read_next_block(demuxer, &block) > 0) {
index_block(demuxer, &block);
mkv_d->tmp_block = block;
}
demuxer->start_time = mkv_d->cluster_tc / 1e9;
+66 -19
View File
@@ -20,6 +20,7 @@
#include <strings.h>
#include <dirent.h>
#include "config.h"
#include "common/common.h"
#include "options/options.h"
#include "common/msg.h"
@@ -105,14 +106,21 @@ static int parse_m3u(struct pl_parser *p)
if (p->check_level == DEMUX_CHECK_UNSAFE) {
char *ext = mp_splitext(p->real_stream->url, NULL);
bstr data = stream_peek(p->real_stream, PROBE_SIZE);
if (ext && !strcmp(ext, "m3u") && data.len > 10 && maybe_text(data))
goto ok;
if (ext && data.len > 10 && maybe_text(data)) {
const char *exts[] = {"m3u", "m3u8", NULL};
for (int n = 0; exts[n]; n++) {
if (strcasecmp(ext, exts[n]) == 0)
goto ok;
}
}
}
return -1;
}
ok:
if (p->probing)
return 0;
char *title = NULL;
while (line.len || !pl_eof(p)) {
if (bstr_eatstart0(&line, "#EXTINF:")) {
@@ -209,6 +217,59 @@ static int parse_txt(struct pl_parser *p)
return 0;
}
#define MAX_DIR_STACK 20
static bool same_st(struct stat *st1, struct stat *st2)
{
return HAVE_POSIX && st1->st_dev == st2->st_dev && st1->st_ino == st2->st_ino;
}
// Return true if this was a readable directory.
static bool scan_dir(struct pl_parser *p, char *path,
struct stat *dir_stack, int num_dir_stack,
char ***files, int *num_files)
{
if (strlen(path) >= 8192 || num_dir_stack == MAX_DIR_STACK)
return false; // things like mount bind loops
DIR *dp = opendir(path);
if (!dp) {
MP_ERR(p, "Could not read directory.\n");
return false;
}
struct dirent *ep;
while ((ep = readdir(dp))) {
if (ep->d_name[0] == '.')
continue;
if (mp_cancel_test(p->s->cancel))
break;
char *file = mp_path_join(p, path, ep->d_name);
struct stat st;
if (stat(file, &st) == 0 && S_ISDIR(st.st_mode)) {
for (int n = 0; n < num_dir_stack; n++) {
if (same_st(&dir_stack[n], &st)) {
MP_VERBOSE(p, "Skip recursive entry: %s\n", file);
goto skip;
}
}
dir_stack[num_dir_stack] = st;
scan_dir(p, file, dir_stack, num_dir_stack + 1, files, num_files);
} else {
MP_TARRAY_APPEND(p, *files, *num_files, file);
}
skip: ;
}
closedir(dp);
return true;
}
static int cmp_filename(const void *a, const void *b)
{
return strcmp(*(char **)a, *(char **)b);
@@ -222,32 +283,18 @@ static int parse_dir(struct pl_parser *p)
return 0;
char *path = mp_file_get_path(p, bstr0(p->real_stream->url));
if (strlen(path) >= 8192)
return -1; // things like mount bind loops
DIR *dp = opendir(path);
if (!dp) {
MP_ERR(p, "Could not read directory.\n");
return -1;
}
char **files = NULL;
int num_files = 0;
struct stat dir_stack[MAX_DIR_STACK];
struct dirent *ep;
while ((ep = readdir(dp))) {
if (ep->d_name[0] == '.')
continue;
MP_TARRAY_APPEND(p, files, num_files, talloc_strdup(p, ep->d_name));
}
scan_dir(p, path, dir_stack, 0, &files, &num_files);
if (files)
qsort(files, num_files, sizeof(files[0]), cmp_filename);
for (int n = 0; n < num_files; n++)
playlist_add_file(p->pl, mp_path_join(p, path, files[n]));
closedir(dp);
playlist_add_file(p->pl, files[n]);
p->add_base = false;
+18 -5
View File
@@ -36,7 +36,7 @@
#include "osdep/endian.h"
struct demux_rawaudio_opts {
struct mp_chmap channels;
struct m_channels channels;
int samplerate;
int aformat;
};
@@ -49,13 +49,13 @@ struct demux_rawaudio_opts {
#define OPT_BASE_STRUCT struct demux_rawaudio_opts
const struct m_sub_options demux_rawaudio_conf = {
.opts = (const m_option_t[]) {
OPT_CHMAP("channels", channels, CONF_MIN, .min = 1),
OPT_CHANNELS("channels", channels, 0, .min = 1),
OPT_INTRANGE("rate", samplerate, 0, 1000, 8 * 48000),
OPT_CHOICE("format", aformat, 0,
({"u8", PCM(0, 0, 8, 0)},
{"s8", PCM(1, 0, 8, 0)},
{"u16le", PCM(0, 0, 16, 0)}, {"u16be", PCM(0, 0, 16, 1)},
{"s16le", PCM(1, 0, 16, 0)}, {"u16be", PCM(1, 0, 16, 1)},
{"s16le", PCM(1, 0, 16, 0)}, {"s16be", PCM(1, 0, 16, 1)},
{"u24le", PCM(0, 0, 24, 0)}, {"u24be", PCM(0, 0, 24, 1)},
{"s24le", PCM(1, 0, 24, 0)}, {"s24be", PCM(1, 0, 24, 1)},
{"u32le", PCM(0, 0, 32, 0)}, {"u32be", PCM(0, 0, 32, 1)},
@@ -75,7 +75,11 @@ const struct m_sub_options demux_rawaudio_conf = {
.size = sizeof(struct demux_rawaudio_opts),
.defaults = &(const struct demux_rawaudio_opts){
// Note that currently, stream_cdda expects exactly these parameters!
.channels = MP_CHMAP_INIT_STEREO,
.channels = {
.set = 1,
.chmaps = (struct mp_chmap[]){ MP_CHMAP_INIT_STEREO, },
.num_chmaps = 1,
},
.samplerate = 44100,
.aformat = PCM(1, 0, 16, 0), // s16le
},
@@ -130,12 +134,20 @@ static int demux_rawaudio_open(demuxer_t *demuxer, enum demux_check check)
if (check != DEMUX_CHECK_REQUEST && check != DEMUX_CHECK_FORCE)
return -1;
if (opts->channels.num_chmaps != 1) {
MP_ERR(demuxer, "Invalid channels option given.\n");
return -1;
}
struct sh_stream *sh = demux_alloc_sh_stream(STREAM_AUDIO);
struct mp_codec_params *c = sh->codec;
c->channels = opts->channels;
c->channels = opts->channels.chmaps[0];
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);
@@ -224,6 +236,7 @@ static int demux_rawvideo_open(demuxer_t *demuxer, enum demux_check check)
c->codec = decoder;
c->codec_tag = imgfmt;
c->fps = opts->fps;
c->reliable_fps = true;
c->disp_w = width;
c->disp_h = height;
demux_add_sh_stream(demuxer, sh);
+9 -1
View File
@@ -84,7 +84,7 @@ static void reselect_streams(struct demuxer *demuxer)
// This stops demuxer readahead for inactive segments.
if (!p->current || seg->d != p->current->d)
selected = false;
demuxer_select_track(seg->d, sh, selected);
demuxer_select_track(seg->d, sh, MP_NOPTS_VALUE, selected);
}
}
}
@@ -197,6 +197,11 @@ static int d_fill_buffer(struct demuxer *demuxer)
if (pkt->stream < 0)
goto drop;
// for refresh seeks, demux.c prefers monotonically increasing packet pos
// since the packet pos is meaningless anyway for timeline, use it
if (pkt->pos >= 0)
pkt->pos |= (seg->index & 0x7FFFULL) << 48;
struct virtual_stream *vs = &p->streams[pkt->stream];
if (pkt->pts != MP_NOPTS_VALUE && pkt->pts >= seg->end) {
@@ -301,6 +306,9 @@ static int d_open(struct demuxer *demuxer, enum demux_check check)
demuxer->metadata = meta->metadata;
demuxer->attachments = meta->attachments;
demuxer->num_attachments = meta->num_attachments;
demuxer->editions = meta->editions;
demuxer->num_editions = meta->num_editions;
demuxer->edition = meta->edition;
int num_streams = demux_get_num_stream(meta);
for (int n = 0; n < num_streams; n++) {
+7 -1
View File
@@ -46,6 +46,8 @@ struct sh_stream {
bool forced_track; // container forced track flag
int hls_bitrate;
struct mp_tags *tags;
bool missing_timestamps;
// stream is a picture (such as album art)
@@ -72,6 +74,9 @@ struct mp_codec_params {
struct AVCodecContext *lav_headers;
struct AVCodecParameters *lav_codecpar;
// Timestamp granularity for converting double<->rational timestamps.
int native_tb_num, native_tb_den;
// STREAM_AUDIO
int samplerate;
struct mp_chmap channels;
@@ -82,7 +87,8 @@ struct mp_codec_params {
// STREAM_VIDEO
bool avi_dts; // use DTS timing; first frame and DTS is 0
float fps; // frames per second (set only if constant fps)
double fps; // frames per second (set only if constant fps)
bool reliable_fps; // the fps field is definitely not broken
int par_w, par_h; // pixel aspect ratio (0 if unknown/square)
int disp_w, disp_h; // display size
int rotate; // intended display rotation, in degrees, [0, 359]
+2 -2
View File
@@ -79,7 +79,7 @@
#> playlist-next # skip to next file
#ENTER playlist-next # skip to next file
#< playlist-prev # skip to previous file
#O no-osd cycle_values osd-level 3 1 # cycle through OSD mode
#O no-osd cycle-values osd-level 3 1 # cycle through OSD mode
#o show-progress
#P show-progress
#I show-text "${filename}" # display filename in osd
@@ -142,7 +142,7 @@
#CLOSE_WIN quit
#CLOSE_WIN {encode} quit 4
#E cycle edition # next edition
#l ab_loop # Set/clear A-B loop points
#l ab-loop # Set/clear A-B loop points
#L cycle-values loop "inf" "no" # toggle infinite looping
#ctrl+c quit 4
+8 -8
View File
@@ -24,19 +24,19 @@ SHARP cycle audio # switch audio streams
BS set speed 1.0 # reset speed to normal
q quit
ESC quit
ENTER playlist_next force # skip to next file
ENTER playlist-next force # skip to next file
p cycle pause
. frame_step # advance one frame and pause
. frame-step # advance one frame and pause
SPACE cycle pause
HOME set playlist-pos 0 # not the same as MPlayer
#END pt_up_step -1
> playlist_next # skip to next file
< playlist_prev # previous
> playlist-next # skip to next file
< playlist-prev # previous
#INS alt_src_step 1
#DEL alt_src_step -1
o osd
I show_text "${filename}" # display filename in osd
P show_progress
I show-text "${filename}" # display filename in osd
P show-progress
z add sub-delay -0.1 # subtract 100 ms delay from subs
x add sub-delay +0.1 # add
9 add volume -1
@@ -57,8 +57,8 @@ d cycle framedrop
D cycle deinterlace # toggle deinterlacer (auto-inserted filter)
r add sub-pos -1 # move subtitles up
t add sub-pos +1 # down
#? sub_step +1 # immediately display next subtitle
#? sub_step -1 # previous
#? sub-step +1 # immediately display next subtitle
#? sub-step -1 # previous
#? add sub-scale +0.1 # increase subtitle font size
#? add sub-scale -0.1 # decrease subtitle font size
f cycle fullscreen
+1 -1
View File
@@ -79,7 +79,7 @@
#softvol=no
# Do not filter audio to keep pitch when changing playback speed.
audio-pitch-correction=no
#audio-pitch-correction=no
# Output 5.1 audio natively, and upmix/downmix audio with a different format.
#audio-channels=5.1
+2 -2
View File
@@ -17,7 +17,7 @@ d cycle framedrop
# changed in mpv 0.7.0
ENTER playlist_next force
ENTER playlist-next force
# changed in mpv 0.6.0
@@ -38,4 +38,4 @@ TAB cycle program
A cycle angle
U stop
o osd
I show_text "${filename}"
I show-text "${filename}"
+1 -1
View File
@@ -257,7 +257,7 @@ static const struct legacy_cmd legacy_cmds[] = {
{"saturation", "add saturation"},
{"hue", "add hue"},
{"switch_vsync", "cycle vsync"},
{"sub_load", "sub_add"},
{"sub_load", "sub-add"},
{"sub_select", "cycle sub"},
{"sub_pos", "add sub-pos"},
{"sub_delay", "add sub-delay"},
-1
View File
@@ -273,7 +273,6 @@ static struct mp_cmd *parse_cmd_str(struct mp_log *log, void *tmp,
break;
if (pctx_read_token(ctx, &cur_token) < 0)
goto error;
break;
}
if (!find_cmd(ctx->log, cmd, cur_token))
+1 -1
View File
@@ -31,7 +31,7 @@ void mp_event_drop_files(struct input_ctx *ictx, int num_files, char **files,
for (int i = 0; i < num_files; i++) {
const char *cmd[] = {
"osd-auto",
"sub_add",
"sub-add",
files[i],
NULL
};
+1 -4
View File
@@ -1247,12 +1247,9 @@ void mp_input_load(struct input_ctx *ictx)
void *tmp = talloc_new(NULL);
char **files = mp_find_all_config_files(tmp, ictx->global, "input.conf");
for (int n = 0; files && files[n]; n++)
config_ok = config_ok | parse_config_file(ictx, files[n], false);
parse_config_file(ictx, files[n], false);
talloc_free(tmp);
}
if (!config_ok) {
MP_VERBOSE(ictx, "Falling back on default (hardcoded) input config\n");
}
if (input_conf->use_alt_gr) {
ictx->using_alt_gr = true;
+2 -3
View File
@@ -133,8 +133,7 @@ static void *client_thread(void *p)
}
if (fds[0].revents & POLLIN) {
char discard[100];
read(pipe_fd, discard, sizeof(discard));
mp_flush_wakeup_pipe(pipe_fd);
while (1) {
mpv_event *event = mpv_wait_event(arg->client, 0);
@@ -413,7 +412,7 @@ void mp_uninit_ipc(struct mp_ipc_ctx *arg)
if (!arg)
return;
write(arg->death_pipe[1], &(char){0}, 1);
(void)write(arg->death_pipe[1], &(char){0}, 1);
pthread_join(arg->thread, NULL);
close(arg->death_pipe[0]);
+23 -9
View File
@@ -215,7 +215,7 @@ extern "C" {
* relational operators (<, >, <=, >=).
*/
#define MPV_MAKE_VERSION(major, minor) (((major) << 16) | (minor) | 0UL)
#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 20)
#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 22)
/**
* Return the MPV_CLIENT_API_VERSION the mpv source has been compiled with.
@@ -248,7 +248,7 @@ typedef enum mpv_error {
* making asynchronous requests. (Bugs in the client API implementation
* could also trigger this, e.g. if events become "lost".)
*/
MPV_ERROR_EVENT_QUEUE_FULL = -1,
MPV_ERROR_EVENT_QUEUE_FULL = -1,
/**
* Memory allocation failed.
*/
@@ -299,7 +299,7 @@ typedef enum mpv_error {
*/
MPV_ERROR_COMMAND = -12,
/**
* Generic error on loading (used with mpv_event_end_file.error).
* Generic error on loading (usually used with mpv_event_end_file.error).
*/
MPV_ERROR_LOADING_FAILED = -13,
/**
@@ -329,7 +329,11 @@ typedef enum mpv_error {
/**
* The API function which was called is a stub only.
*/
MPV_ERROR_NOT_IMPLEMENTED = -19
MPV_ERROR_NOT_IMPLEMENTED = -19,
/**
* Unspecified error.
*/
MPV_ERROR_GENERIC = -20
} mpv_error;
/**
@@ -660,7 +664,7 @@ typedef enum mpv_format {
MPV_FORMAT_NODE_MAP = 8,
/**
* A raw, untyped byte array. Only used only with mpv_node, and only in
* some very special situations. (Currently, only for the screenshot_raw
* some very special situations. (Currently, only for the screenshot-raw
* command.)
*/
MPV_FORMAT_BYTE_ARRAY = 9
@@ -780,6 +784,10 @@ void mpv_free_node_contents(mpv_node *node);
* mpv_set_property() to change settings during playback, because the property
* mechanism guarantees that changes take effect immediately.
*
* Using a format other than MPV_FORMAT_NODE is equivalent to constructing a
* mpv_node with the given format and data, and passing the mpv_node to this
* function.
*
* @param name Option name. This is the same as on the mpv command line, but
* without the leading "--".
* @param format see enum mpv_format.
@@ -877,7 +885,13 @@ int mpv_command_node_async(mpv_handle *ctx, uint64_t reply_userdata,
* usually will fail with MPV_ERROR_PROPERTY_FORMAT. In some cases, the data
* is automatically converted and access succeeds. For example, MPV_FORMAT_INT64
* is always converted to MPV_FORMAT_DOUBLE, and access using MPV_FORMAT_STRING
* usually invokes a string parser.
* usually invokes a string parser. The same happens when calling this function
* with MPV_FORMAT_NODE: the underlying format may be converted to another
* type if possible.
*
* Using a format other than MPV_FORMAT_NODE is equivalent to constructing a
* mpv_node with the given format and data, and passing the mpv_node to this
* function. (Before API version 1.21, this was different.)
*
* @param name The property name. See input.rst for a list of properties.
* @param format see enum mpv_format.
@@ -1138,13 +1152,13 @@ typedef enum mpv_event_id {
* @deprecated This was used internally with the internal "script_dispatch"
* command to dispatch keyboard and mouse input for the OSC.
* It was never useful in general and has been completely
* replaced with "script_binding".
* replaced with "script-binding".
* This event never happens anymore, and is included in this
* header only for compatibility.
*/
MPV_EVENT_SCRIPT_INPUT_DISPATCH = 15,
/**
* Triggered by the script_message input command. The command uses the
* Triggered by the script-message input command. The command uses the
* first argument of the command as client name (see mpv_client_name()) to
* dispatch the message, and passes along all arguments starting from the
* second argument as strings.
@@ -1436,7 +1450,7 @@ int mpv_request_event(mpv_handle *ctx, mpv_event_id event, int enable);
* required log level for a message to be received with MPV_EVENT_LOG_MESSAGE.
*
* @param min_level Minimal log level as string. Valid log levels:
* no fatal error warn info status v debug trace
* no fatal error warn info v debug trace
* The value "no" disables all messages. This is the default.
* An exception is the value "terminal-default", which uses the
* log level as set by the "--msg-level" option. This works
+1
View File
@@ -37,6 +37,7 @@ mpv_set_property
mpv_set_property_async
mpv_set_property_string
mpv_set_wakeup_callback
mpv_stream_cb_add_ro
mpv_suspend
mpv_terminate_destroy
mpv_unobserve_property
+40 -3
View File
@@ -108,6 +108,28 @@ extern "C" {
* context must have been uninitialized. If this doesn't happen, undefined
* behavior will result.
*
* Hardware decoding
* -----------------
*
* Hardware decoding via opengl_cb is fully supported, but requires some
* additional setup. (At least if direct hardware decoding modes are wanted,
* instead of copying back surface data from GPU to CPU RAM.)
*
* While "normal" mpv loads the OpenGL hardware decoding interop on demand,
* this can't be done with opengl_cb for internal technical reasons. Instead,
* make it load the interop at load time by setting the "hwdec-preload"="auto"
* option before calling mpv_opengl_cb_init_gl().
*
* There may be certain requirements on the OpenGL implementation:
* - Windows: ANGLE is required (although in theory GL/DX interop could be used)
* - Intel/Linux: EGL is required, and also a glMPGetNativeDisplay() callback
* must be provided (see sections below)
* - nVidia/Linux: GLX is required
* - OSX: CGL is required (CGLGetCurrentContext() returning non-NULL)
*
* Once these things are setup, hardware decoding can be enabled/disabled at
* any time by setting the "hwdec" property.
*
* Special windowing system interop considerations
* ------------------------------------------------
*
@@ -126,19 +148,34 @@ extern "C" {
* up until mpv_opengl_cb_uninit_gl() is called. If the name is not anything
* you know/expected, return NULL from the function.
*
* Windowing system interop on Linux
* ---------------------------------
* Windowing system interop on Intel/Linux with VAAPI
* --------------------------------------------------
*
* The new VAAPI OpenGL interop requires an EGL context. EGL provides no way
* to query the X11 Display associated to a specific EGL context, so this API
* is used to pass it through.
*
* glMPGetNativeDisplay("x11") should return a X11 "Display*", which then will
* be used to create the hardware decoder state. (On GLX, this is not needed.)
* be used to create the hardware decoder state.
*
* glMPGetNativeDisplay("wl") should return a Wayland "struct wl_display *".
*
* glMPGetNativeDisplay("drm") should return a DRM FD casted to intptr_t (note
* that a 0 FD is not supported - if this can happen in your case, you must
* dup2() it to a non-0 FD).
*
* nVidia/Linux via VDPAU requires GLX, which does not have this problem (the
* GLX API can return the current X11 Display).
*
* Windowing system interop on MS win32
* ------------------------------------
*
* Warning: the following is only required if native OpenGL instead of ANGLE
* is used. ANGLE is recommended, because it also allows direct
* hardware decoding interop without further setup by the libmpv
* API user, while the same with native OpenGL is either very hard
* to do (via GL/DX interop with D3D9), or not implemented.
*
* If OpenGL switches to fullscreen, most players give it access GPU access,
* which means DXVA2 hardware decoding in mpv won't work. This can be worked
* around by giving mpv access to Direct3D device, which it will then use to
+230
View File
@@ -0,0 +1,230 @@
/* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Note: the client API is licensed under ISC (see above) to ease
* interoperability with other licenses. But keep in mind that the
* mpv core is still mostly GPLv2+. It's up to lawyers to decide
* whether applications using this API are affected by the GPL.
* One argument against this is that proprietary applications
* using mplayer in slave mode is apparently tolerated, and this
* API is basically equivalent to slave mode.
*/
#ifndef MPV_CLIENT_API_STREAM_CB_H_
#define MPV_CLIENT_API_STREAM_CB_H_
#include "client.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Warning: this API is not stable yet.
*
* Overview
* --------
*
* This API can be used to make mpv read from a stream with a custom
* implementation. This interface is inspired by funopen on BSD and
* fopencookie on linux. The stream is backed by user-defined callbacks
* which can implement customized open, read, seek, size and close behaviors.
*
* Usage
* -----
*
* Register your stream callbacks with the mpv_stream_cb_add_ro() function. You
* have to provide a mpv_stream_cb_open_ro_fn callback to it (open_fn argument).
*
* Once registered, you can `loadfile myprotocol://myfile`. Your open_fn will be
* invoked with the URI and you must fill out the provided mpv_stream_cb_info
* struct. This includes your stream callbacks (like read_fn), and an opaque
* cookie, which will be passed as the first argument to all the remaining
* stream callbacks.
*
* Note that your custom callbacks must not invoke libmpv APIs as that would
* cause a deadlock.
*
* Stream lifetime
* ---------------
*
* A stream remains valid until its close callback has been called. It's up to
* libmpv to call the close callback, and the libmpv user cannot close it
* directly with the stream_cb API.
*
* For example, if you consider your custom stream to become suddenly invalid
* (maybe because the underlying stream died), libmpv will continue using your
* stream. All you can do is returning errors from each callback, until libmpv
* gives up and closes it.
*
* Protocol registration and lifetime
* ----------------------------------
*
* Protocols remain registered until the mpv instance is terminated. This means
* in particular that it can outlive the mpv_handle that was used to register
* it, but once mpv_terminate_destroy() is called, your registered callbacks
* will not be called again.
*
* Protocol unregistration is finished after the mpv core has been destroyed
* (e.g. after mpv_terminate_destroy() has returned).
*
* If you do not call mpv_terminate_destroy() yourself (e.g. plugin-style code),
* you will have to deal with the registration or even streams outliving your
* code. Here are some possible ways to do this:
* - call mpv_terminate_destroy(), which destroys the core, and will make sure
* all streams are closed once this function returns
* - you refcount all resources your stream "cookies" reference, so that it
* doesn't matter if streams live longer than expected
* - create "cancellation" semantics: after your protocol has been unregistered,
* notify all your streams that are still opened, and make them drop all
* referenced resources - then return errors from the stream callbacks as
* long as the stream is still opened
*
*/
/**
* Read callback used to implement a custom stream. The semantics of the
* callback match read(2) in blocking mode. Short reads are allowed (you can
* return less bytes than requested, and libmpv will retry reading the rest
* with a nother call). If no data can be immediately read, the callback must
* block until there is new data. A return of 0 will be interpreted as final
* EOF, although libmpv might retry the read, or seek to a different position.
*
* @param cookie opaque cookie identifying the stream,
* returned from mpv_stream_cb_open_fn
* @param buf buffer to read data into
* @param size of the buffer
* @return number of bytes read into the buffer
* @return 0 on EOF
* @return -1 on error
*/
typedef int64_t (*mpv_stream_cb_read_fn)(void *cookie, char *buf, uint64_t nbytes);
/**
* Seek callback used to implement a custom stream.
*
* Note that mpv will issue a seek to position 0 immediately after opening. This
* is used to test whether the stream is seekable (since seekability might
* depend on the URI contents, not just the protocol). Return
* MPV_ERROR_UNSUPPORTED if seeking is not implemented for this stream. This
* seek also servies to establish the fact that streams start at position 0.
*
* This callback can be NULL, in which it behaves as if always returning
* MPV_ERROR_UNSUPPORTED.
*
* @param cookie opaque cookie identifying the stream,
* returned from mpv_stream_cb_open_fn
* @param offset target absolut stream position
* @return the resulting offset of the stream
* MPV_ERROR_UNSUPPORTED or MPV_ERROR_GENERIC if the seek failed
*/
typedef int64_t (*mpv_stream_cb_seek_fn)(void *cookie, int64_t offset);
/**
* Size callback used to implement a custom stream.
*
* Return MPV_ERROR_UNSUPPORTED if no size is known.
*
* This callback can be NULL, in which it behaves as if always returning
* MPV_ERROR_UNSUPPORTED.
*
* @param cookie opaque cookie identifying the stream,
* returned from mpv_stream_cb_open_fn
* @return the total size in bytes of the stream
*/
typedef int64_t (*mpv_stream_cb_size_fn)(void *cookie);
/**
* Close callback used to implement a custom stream.
*
* @param cookie opaque cookie identifying the stream,
* returned from mpv_stream_cb_open_fn
*/
typedef void (*mpv_stream_cb_close_fn)(void *cookie);
/**
* See mpv_stream_cb_open_ro_fn callback.
*/
typedef struct mpv_stream_cb_info {
/**
* Opaque user-provided value, which will be passed to the other callbacks.
* The close callback will be called to release the cookie. It is not
* interpreted by mpv. It doesn't even need to be a valid pointer.
*
* The user sets this in the mpv_stream_cb_open_ro_fn callback.
*/
void *cookie;
/**
* Callbacks set by the user in the mpv_stream_cb_open_ro_fn callback. Some
* of them are optional, and can be left unset.
*
* The following callbacks are mandatory: read_fn, close_fn
*/
mpv_stream_cb_read_fn read_fn;
mpv_stream_cb_seek_fn seek_fn;
mpv_stream_cb_size_fn size_fn;
mpv_stream_cb_close_fn close_fn;
} mpv_stream_cb_info;
/**
* Open callback used to implement a custom read-only (ro) stream. The user
* must set the callback fields in the passed info struct. The cookie field
* also can be set to store state associated to the stream instance.
*
* Note that the info struct is valid only for the duration of this callback.
* You can't change the callbacks or the pointer to the cookie at a later point.
*
* Each stream instance created by the open callback can have different
* callbacks.
*
* The close_fn callback will terminate the stream instance. The pointers to
* your callbacks and cookie will be discarded, and the callbacks will not be
* called again.
*
* @param user_data opaque user data provided via mpv_stream_cb_add()
* @param uri name of the stream to be opened (with protocol prefix)
* @param info fields which the user should fill
* @return opaque cookie identifing the newly opened stream
* @return 0 on success, MPV_ERROR_LOADING_FAILED if the URI cannot be opened.
*/
typedef int (*mpv_stream_cb_open_ro_fn)(void *user_data, char *uri,
mpv_stream_cb_info *info);
/**
* Add a custom stream protocol. This will register a protocol handler under
* the given protocol prefix, and invoke the given callbacks if an URI with the
* matching protocol prefix is opened.
*
* The "ro" is for read-only - only read-only streams can be registered with
* this function.
*
* The callback remains registered until the mpv core is registered.
*
* If a custom stream with the same name is already registered, then the
* MPV_ERROR_INVALID_PARAMETER error is returned.
*
* @param protocol protocol prefix, for example "foo" for "foo://" URIs
* @param user_data opaque pointer passed into the mpv_stream_cb_open_fn
* callback.
* @return error code
*/
int mpv_stream_cb_add_ro(mpv_handle *ctx, const char *protocol, void *user_data,
mpv_stream_cb_open_ro_fn open_fn);
#ifdef __cplusplus
}
#endif
#endif
+10 -2
View File
@@ -215,9 +215,9 @@ struct bstr *bstr_splitlines(void *talloc_ctx, struct bstr str)
return r;
}
struct bstr bstr_getline(struct bstr str, struct bstr *rest)
struct bstr bstr_splitchar(struct bstr str, struct bstr *rest, const char c)
{
int pos = bstrchr(str, '\n');
int pos = bstrchr(str, c);
if (pos < 0)
pos = str.len;
if (rest)
@@ -243,6 +243,14 @@ bool bstr_eatstart(struct bstr *s, struct bstr prefix)
return true;
}
bool bstr_eatend(struct bstr *s, struct bstr prefix)
{
if (!bstr_endswith(*s, prefix))
return false;
s->len -= prefix.len;
return true;
}
void bstr_lower(struct bstr str)
{
for (int i = 0; i < str.len; i++)
+18 -6
View File
@@ -116,10 +116,15 @@ int bstr_validate_utf8(struct bstr s);
// talloc, with talloc_ctx as parent.
struct bstr bstr_sanitize_utf8_latin1(void *talloc_ctx, struct bstr s);
// Return the text before the next line break, and return it. Change *rest to
// point to the text following this line break. (rest can be NULL.)
// Line break characters are not stripped.
struct bstr bstr_getline(struct bstr str, struct bstr *rest);
// Return the text before the occurrence of a character, and return it. Change
// *rest to point to the text following this character. (rest can be NULL.)
struct bstr bstr_splitchar(struct bstr str, struct bstr *rest, const char c);
// Like bstr_splitchar. Trailing newlines are not stripped.
static inline struct bstr bstr_getline(struct bstr str, struct bstr *rest)
{
return bstr_splitchar(str, rest, '\n');
}
// Strip one trailing line break. This is intended for use with bstr_getline,
// and will remove the trailing \n or \r\n sequence.
@@ -131,8 +136,10 @@ void bstr_xappend_asprintf(void *talloc_ctx, bstr *s, const char *fmt, ...)
void bstr_xappend_vasprintf(void *talloc_ctx, bstr *s, const char *fmt, va_list va)
PRINTF_ATTRIBUTE(3, 0);
// If s starts with prefix, return true and return the rest of the string in s.
// If s starts/ends with prefix, return true and return the rest of the string
// in s.
bool bstr_eatstart(struct bstr *s, struct bstr prefix);
bool bstr_eatend(struct bstr *s, struct bstr prefix);
bool bstr_case_startswith(struct bstr s, struct bstr prefix);
bool bstr_case_endswith(struct bstr s, struct bstr suffix);
@@ -200,11 +207,16 @@ static inline int bstr_find0(struct bstr haystack, const char *needle)
return bstr_find(haystack, bstr0(needle));
}
static inline int bstr_eatstart0(struct bstr *s, const char *prefix)
static inline bool bstr_eatstart0(struct bstr *s, const char *prefix)
{
return bstr_eatstart(s, bstr0(prefix));
}
static inline bool bstr_eatend0(struct bstr *s, const char *prefix)
{
return bstr_eatend(s, bstr0(prefix));
}
// create a pair (not single value!) for "%.*s" printf syntax
#define BSTR_P(bstr) (int)((bstr).len), ((bstr).start ? (char*)(bstr).start : "")
Loaded 100 of 290 files, more files were not shown because too many files have changed in this diff. Show more