Compare commits

..
827 Commits
Author SHA1 Message Date
Martin Herkt dfac83a81d Release 0.28.0 2017-12-25 00:18:05 +01:00
Ricardo Constantino b1b03da137 ytdl_hook: use table concat for playlist building
Faster and more efficient than string concat with large playlists.
2017-12-24 14:13:57 -07:00
Ricardo Constantino 1623430b20 ytdl_hook: don't preappend ytdl:// to non-youtube links in playlists
Close #5003
2017-12-24 14:13:57 -07:00
wm4 29af787217 player: update duration based on highest timestamp demuxed
This will help with things like livestreams.

As a minor detail, subtitles are excluded, because they sometimes have
"unused" events after video and audio ends. To avoid this annoying
corner case, just ignore them.
2017-12-24 21:49:12 +01:00
wm4 c12d897a3a player: allow seeking in cached parts of unseekable streams
Before this change and before the seekable stream cache became a thing,
we could possibly seek using the stream cache. But we couldn't know
whether the seek would succeed. We knew the available byte range, but
could in general not tell whether a demuxer would stay within the range
when trying to seek to a specific time position. We preferred to have
safe defaults, so seeking in streams that were detected as unseekable
were not honored. We allowed overriding this via --force-seekable=yes,
in which case it depended on your luck whether the seek would work, or
the player crapped its pants.

With the demuxer packet cache, we can tell exactly whether a seek will
work (at least if there's only 1 seek range). We can just let seeks go
through. Everything to allow this is already in place, and this commit
just moves around some minor things.

Note that the demux_seek() return value was not used before, because low
level (i.e. network level) seeks are usually asynchronous, and if they
fail, the state is pretty much undefined. We simply repurpose the return
value to signal whether cache seeking worked. If it didn't, we can just
resume playback normally, because demuxing continues unaffected, and no
decoder are reset.

This should be particularly helpful to people who for some reason stream
data into stdin via streamlink and such.
2017-12-24 21:45:12 +01:00
wm4 bf111f9c3c stream_libarchive: fix seeking fallback
In commit 1199c1e3, we added checks to every libarchive API call to make
sure the archive was closed on ARCHIVE_FATAL - otherwise, libarchive
could endow us with free CVEs (such as it apparently happens when you
continue reading a rar archive that uses features not yet supported by
libarchive).

This broke the fallback for seeking in unseekable archive formats. Of
course libarchive won't tell us directly whether a format implementation
has seek support or not - and OF COURSE it returns ARCHIVE_FATAL if it
has no seek support. (The error string, which you can retrieve via API,
is actually more detailed, and also claims it's an "internal error". I
don't think so, libarchive.) Returning ARCHIVE_FATAL means we have to
assume free CVEs are ahead, and we have to close the archive. Which
breaks the fallback in a dumb way (we have no way of telling which of
those cases happened anyway).

Fix this by assuming that all seek errors are potentially due to lack of
seek support. If the seek call fails, reopen the archive, and set a flag
so the seek API is never tried again. (This means we can still skip
ahead for forward seeks, which is more efficient than skipping from the
start of the archive entry.)

Also fix an old typo in an error message.
2017-12-24 21:33:16 +01:00
wm4 2a43060560 cache: propagate underlying stream seek errors in some cases
This just put the cache into an endless loop. This can happen simply if
any seek call of the underlying stream returns an error.
2017-12-24 21:33:16 +01:00
Martin Herkt 5ffbe2ba8a command: use IEC symbols for file size formatting 2017-12-24 21:27:41 +01:00
Martin Herkt 79b9f48353 wscript: support static linking of shaderc
These idiots have no idea how to design a library, so we’ll have
to work around their bullshit for now.
2017-12-24 20:45:45 +01:00
wm4 a721dac601 player: make track language matching case insensitive
There is no reason not to do this, and probably saves the user some
trouble.

Mostly untested.

Closes #5272.
2017-12-23 15:14:13 -07:00
wm4 30686dcec3 demux_mkv: fix off by one error
Caused by the relatively recent change to packet parsing. This time it
was probably triggered by lace type 0, which reduces the byte length of
a 0 sized packet to 3 (timestamp + flag) instead of 4 (lace count for
other lace types). The thing about laces is just my guess why it worked
for other 0 sized packets, though.

Also remove the redundant and now incorrect check below.

Fixes #5271.
2017-12-23 14:07:21 -07:00
wm4 2c3a172ef1 demux: note refresh state separately in debug output
This log line tells us why the demuxer is trying to read more, which us
useful when debugging queue overflows. Probably barely useful, but I
think keeping that flag separately also makes the code slightly easier
to understand.
2017-12-23 00:32:59 +01:00
wm4 62cf960ef0 osc: show demuxer cache buffered amount in bytes
Same as previous commit, but for the OSC.

(A bit of a waste to request demuxer-cache-state at least twice per
frame, but the OSC queries so many properties it probably doesn't matter
anymore.)
2017-12-23 00:32:59 +01:00
wm4 822b247d10 player: show demuxer cache buffered amount in bytes in the status line
I don't want to add another field to display stream and demuxer cache
separately, so just add them up. This strangely makes sense, since the
forward buffered stream cache amount consists of data not read by the
demuxer yet. (If the demuxer cache has buffered the full stream, the
forward buffered stream cache amount is 0.)
2017-12-23 00:32:59 +01:00
wm4 a23a98f648 cache: lower default size to 2*10MB
Reduce it from 75MB in both directions (forward/backwards) to 10MB each.

The stream cache is kind of becoming useless in favor of the demuxer
cache. Using both doesn't make much sense, because they will contain
duplicated data for no reason.

Still leave it at 10MB, which may help with mp4 a bit. libavformat's mp4
demuxer tends to seek too much, so we try to avoid triggering network
level seeks by having some caching in the stream layer.
2017-12-23 00:32:59 +01:00
wm4 382a8ac0b0 demux: bump the demuxer cache readahead duration
Set it to 10 hours, which is practically unlimited. (Avoiding use of
"inf", since that might interact strangely with the option parser and
such.)
2017-12-23 00:32:59 +01:00
wm4 cc8759a855 demux: always discard cached packets on track switches
This fixes weird behavior in the following case:

- open a file
- make sure the max. demuxer forward cache is smaller than the
  file's video track
- make sure the max. readahead duration is larger than the file's
  duration
- disable the audio track
- seek to the beginning of the file
- once the cache has filled enable the audio track
- a queue overflow warning should appear
(- looking at the seek ranges is also interesting)

The queue overflow warning happens because the packed queue for the
video track will use up the full quota set by --demuxer-max-bytes. When
the audio track is enabled, reading an audio packet would technically
overflow the packet cache by the size of whatever packet is read next.

This means the demuxer signals EOF to the decoder, and once playback has
consumed enough video packets so that audio packets can be read again,
the decoder resumes from EOF. This interacts badly with A/V
synchronization and the whole thing can randomly crap itself until audio
has fully recovered.

We didn't care about this so far, but we want to raise the readahead
duration to something very high, so that the demuxer cache is fully
used. This means this case can be hit quite quickly by switching audio
or subtitle tracks, and is not really an obscure corner case anymore.

Fix this by always losing all cache. Since the cache can't be used
anyway until the newly selected track has been read, this is not much of
a disadvantage. The only thing that could be brought up is that
unselecting the track again could resume operation normally. (Maybe this
would be useful if network died completely without chance of recovery.
Then you could watch the already buffered video anyway by deselecting
the audio track again.) But given the headaches, this seems like the
better solution.

Unfortunately this requires adding new new strange fields and strangely
fragmenting state management functions again. I'm sure whoever works on
this in the future will hate me. Currently it seems like the lesser
evil, and much simpler and robust than the other potential solutions.

In case this needs to be revisited, here is a reminder for readers from
the future what alternative solutions were considered, without those
disadvantages:

A first attempted solution allowed the demuxer to buffer some additional
packets on track switching. This would allow it to read enough data to
feed the decoder at least. But it was still awkward, as it didn't allow
the demuxer to continue prefetching the newly selected track. It also
barely worked, because you could make the forward buffer "over full" by
seeking back with seekable cache enabled, and then it couldn't read
packets anyway.

As alternative solution, we could always demux and cache all tracks,
even if they're deselected. This would also not require a network-level
seek for the "refresh" logic (it's the thing that lets the video decoder
continue as if nothing happened, while actually seeking back in the
stream to get the missing audio packets, in the case of enabling a
previously disabled audio track). But it would also possibly waste
network and memory resources, depending on what the user actually wants.

A second solution would just account the queue sizes for each stream
separately. We could freely fill up the audio packet queue, even if the
video queue is full. Since the demuxer API returns interleaved packets
and doesn't let you predict which packet type comes next, this is not as
simple as it sounds, but it'd probably tie in nicely with the "refresh"
logic.

A third solution would be removing buffered video packets from the end
of the packet queue. Since the "refresh" logic gets these anyway, there
is no reason to keep them if they prevent the audio packet queue from
catching up with the video one. But this would require additional logic,
would interact badly with a bunch of other corner cases. And as far as
the code goes, it's rather complex, because all the logic is written
with FIFO behavior in mind (including the fact that the packet queue is
a singly linked list with no backwards links, making removal from the
end harder).
2017-12-23 00:32:59 +01:00
Ricardo Constantino 08dbc8f43e travis: stop excluding ffmpeg-git
Signed-off-by: Stefano Pigozzi <stefano.pigozzi@gmail.com>
2017-12-22 21:49:21 +01:00
wm4 2964788055 options: deprecate --ff- options and properties
Some old crap which nobody needs and which probably nobody uses.

This relies on a GCC extension: using "## __VA_ARGS__" to remove the
comma from the argument list if the va args are empty. It's supported
by clang, and there's some chance newer standards will introduce a
proper way to do this. (Even if it breaks somewhere, it will be a
problem only for 1 release, since I want to drop the deprecated
properties immediately.)
2017-12-21 19:51:30 +01:00
Scott Zeid 688768b9bd build: use a list instead of a string for rpi cflags
Using a string caused all 4 flags to be passed as one argument, causing
the build to fail when trying to include bcm_host.h.
2017-12-21 19:47:54 +01:00
wm4 3412c1a1aa Restore Libav support
Libav has been broken due to the hwdec changes. This was always a
temporary situation (depended on pending patches to be merged), although
it took a bit longer. This also restores the travis config.

One code change is needed in vd_lavc.c, because it checks the AV_PIX_FMT
for videotoolbox (as opposed to the mpv format identifier), which is not
available in Libav. Add an ifdef; the affected code is for a deprecated
option anyway.
2017-12-21 19:45:32 +01:00
wm4 2ce7face96 hwdec: remove unused fields
These were replaced by a different mechanism, but the old fields weren't
removed.
2017-12-21 19:31:36 +01:00
Aman Gupta 7e2252688b vo_mediacodec_embed: implement hwcontext
Fixes vo_mediacodec_embed, which was broken in 80359c6615
2017-12-20 15:45:55 +11:00
wm4 eb619d0f57 command: make video-frame-info property observable
Pointed out as missing by someone. Not terribly useful, but here we go.
2017-12-20 15:28:23 +11:00
James Ross-Gowan 3d8ca93d23 vo_gpu: win: remove exclusive-fullscreen detection hack
This hack was part of a solution to VSync judder in desktop OpenGL on
Windows. Rather than using blocking-SwapBuffers(), mpv could use
DwmFlush() to wait for the image to be presented by the compositor.
Since this would only work while the compositor was running, and the
compositor was silently disabled when OpenGL entered exclusive
fullscreen mode, mpv needed a way to detect exclusive fullscreen mode.

The code that is being removed could detect exclusive fullscreen mode by
checking the state of an undocumented mutex using undocumented native
API functions, but because of how fragile it was, it was always meant to
be removed when a better solution for accurate VSync in OpenGL was
found. Since then, mpv got the dxinterop backend, which uses desktop
OpenGL but has accurate VSync. It also got a native Direct3D 11 backend,
which is a viable alternative to OpenGL on Windows.

For people who are still using desktop OpenGL with WGL, there shouldn't
be much of a difference, since mpv can use other API functions to detect
exclusive fullscreen.
2017-12-20 14:53:41 +11:00
pavelxdd d13f9d0886 w32_common: refactor and improve window state handling
Refactored and split the `reinit_window_state` code into four
separate functions:
- `update_window_style` used to update window styles without
modifying the window rect.
- `fit_window_on_screen` used to adjust the window size when it is
larger than the screen size. Added a helper function `fit_rect` to
fit one rect on another without using any data from w32 struct.
- `update_fullscreen_state` used to calculate the new fullscreen
state and adjust the window rect accordingly.
- `update_window_state` used to display the window on screen with
new size, position and ontop state.

This commit fixes three issues:
- fixed #4753 by skipping `fit_window_on_screen` for a maximized
window, since maximized window should already fit on the screen.
It should be noted that this bug was only reproducible with
`--fit-border` option which is enabled by default. The cause of the
bug is that after calling the `add_window_borders` for a maximized
window, the rect in result is slightly larger than the screen rect,
which is okay, `SetWindowPos` will interpret it as a maximized state
later, so no auto-fitting to screen size is needed here.
- fixed #5215 by skipping `fit_window_on_screen` when leaving fullscreen.
On a multi-monitor system if the mpv window was stretched to cover
multiple monitors, its size was reset after switching back from
fullscreen to fit the size of the active monitor. Also, when changing
`--ontop` and `--border` options, now only the
`update_window_style` and `update_window_state` functions are used,
so `fit_window_on_screen` is not used for them too.
- fixed #2451 by moving the `ITaskbarList2_MarkFullscreenWindow`
below the `SetWindowPos`. If the taskbar is notified about fullscreen
state before the window is shown on screen, the taskbar button could
be missing until Alt-TAB is pressed, usually it was reproducible on
Windows 8.

Other changes:
- In `update_fullscreen_state` the `reset window bounds` debug
message now reports client area size and position, instead of window area
size and position. This is done for consistency with debug messages
in handling fullscreen state above in this function, since they also print
window bounds of the client area.
- Refactored `gui_thread_reconfig`. Added a new window flag `fit_on_screen`
to fit the window on screen even when leaving fullscreen. This is needed
for the case when the new video opened while the window is still in the
fullscreen state.
- Moved parent and fullscreen state checks out from the WM_MOVING to
`snap_to_screen_edges` function for consistency with other functions.
There's no point in keeping these checks out of the function body.
2017-12-19 23:22:52 +11:00
pavelxdd ebd5ae3721 w32_common: use RECT for storing screen and window size & position
When window and screen size and position are stored in RECT, it's
much easier to modify them using WinAPI functions.
Added two macros to get width and height of the rect.
2017-12-19 23:22:52 +11:00
wm4 d690ee0959 client API: change --stop-playback-on-init-failure default
This was off for mpv CLI, but on for libmpv. The motivation behind this
was that it would be confusing for applications if libmpv continued
playback in a severely "degraded" way (without either audio or video),
and that it would be better to fail early.

In reality the behavior was just a confusing difference to mpv CLI, and
has confused actual users as well. Get rid of it.

Not bothering with a version bump, since this is so minor, and it's easy
to ensure compatibility in affected applications by just setting the
option explicitly.

(Also adding the missing next-release-marker in client-api-changes.rst.)
2017-12-17 15:45:24 -08:00
wm4 9ed8ca2529 vo_gpu: hwdec_drmprime_drm: don't crash for non-GL contexts
Using vulkan with --hwdec crashed because of this.
2017-12-17 11:00:51 -08:00
rim b0d0bc5700 dvb: Fix long channel switching: next/prev channel 2017-12-16 23:24:55 -08:00
rim 04d04033e6 dvb: Add multiple frontends support: MAX_FRONTENDS now 8. 2017-12-16 23:24:55 -08:00
TheAMM 3c4667c862 js: implement mp.msg.trace()
To match the new Lua helper introduced in
1afdeee1ad

Add documentation for both.
2017-12-16 02:25:24 -08:00
Niklas Haas 1afdeee1ad lua: implement mp.msg.trace 2017-12-15 22:28:47 -08:00
Niklas Haas d64c33c518 msg: bump up log level of --log-file
This now logs -v -v by default, instead of -v.
2017-12-15 22:28:47 -08:00
Niklas Haas ba1943ac00 msg: reinterpret a bunch of message levels
I've decided that MP_TRACE means “noisy spam per frame”, whereas
MP_DBG just means “more verbose debugging messages than MSGL_V”.
Basically, MSGL_DBG shouldn't create spam per frame like it currently
does, and MSGL_V should make sense to the end-user and provide mostly
additional informational output.

MP_DBG is basically what I want to make the new default for --log-file,
so the cut-off point for MP_DBG is if we probably want to know if for
debugging purposes but the user most likely doesn't care about on the
terminal.

Also, the debug callbacks for libass and ffmpeg got bumped in their
verbosity levels slightly, because being external components they're a
bit less relevant to mpv debugging, and a bit too over-eager in what
they consider to be relevant information.

I exclusively used the "try it on my machine and remove messages from
MSGL_* until it does what I want it to" approach of refactoring, so
YMMV.
2017-12-15 22:28:47 -08:00
Larivact d744dca537 README: some rewording and markdown improvements 2017-12-15 22:16:59 -08:00
Larivact 732c33e884 README: reorganize table of contents
Add missing sections, make order consistent, create a new section for external
links and rename "Manual" link.
2017-12-15 22:16:55 -08:00
pavelxdd e1ac0c1eb6 options: rename 'error' labels to 'exit' where appropriate 2017-12-16 02:20:44 +03:00
pavelxdd 7fc9ff54d3 options: don't report errors on help value for OPT_SIZE_BOX
The same idea as in 3723e61 but for OPT_SIZE_BOX now.

Affects options `autofit`, `autofit-larger` and `autofit-smaller`.
2017-12-16 01:29:05 +03:00
Martin Shirokov 0e311fc0e8 ipc: avoid dereferencing NULL
This can happen when ctr->client_api->shutting_down is set to true,
or when there are over 1000 clients with the same name passed to mp_new_client().
2017-12-15 12:51:16 +02:00
wm4 cedcdc1f3c vd_lavc: rename --hwdec=rpi to --hwdec=mmal
Annoying exception that makes no sense to keep. Normally, users or
client applications will either use --hwdec=auto, or not set the option
at all, which both leads to the expected result.
2017-12-15 12:32:25 +02:00
wm4 9824a30eb1 vd_lavc: use libavcodec metadata for hardware decoder wrappers
This removes the need to keep an explicit list and to attempt to parse
codec names. Needs latest FFmpeg git.
2017-12-15 12:32:25 +02:00
Vittorio Giovara d7d670fcbf csputils: Add support for Display P3 primaries 2017-12-14 23:31:09 +02:00
Vittorio Giovara 3b0ed13e39 csputils: Fix DCI P3 primaries white point 2017-12-14 23:31:09 +02:00
pavelxdd 74c6e7ba1d subprocess-win: don't change the mouse cursor in CreateProcess
By default the CreateProcess changes the mouse cursor to
IDC_APPSTARTING. The new flag added to STARTUPINFOEXW prevents
changing the cursor from default arrow on creating a new process.
2017-12-14 21:35:55 +11:00
TSaaristo 522bfe5be1 lua+js: implement utils.file_info()
This commit introduces mp.utils.file_info() for querying information
on file paths, implemented for both Lua and Javascript.

The function takes a file path as an argument and returns a Lua table /
JS object upon success. The table/object will contain the values:
mode, size, atime, mtime, ctime and the convenience booleans is_file, is_dir.

On error, the Lua side will return `nil, error` and the Javascript side
will return `undefined` (and mark the last error).

This feature utilizes the already existing cross-platform `mp_stat()`
function.
2017-12-13 21:55:28 +02:00
Leo Izen 47131365a3 sd_ass: accept otc as fallback OpenType collection file extension
The OpenType Font File specification recommends that "Collection fonts
that use CFF or CFF2 outlines should have an .OTC extension." mpv
should accept .otc as a fallback extension for font detection should
the mimetype detection fail.
2017-12-13 21:00:22 +02:00
Leo Izen f3d2f4c6c2 sd_ass: accept RFC8081 font media types
IETF RFC8081 added the "font" top-level media type,
including font/ttf, font/otf, font/sfnt, and also
font/collection. These font formats are all supported
by mpv/libass but they are not accepted as valid
Matroska mime types. mpv can load them via file extension
and they work as expected, so files using the new types
should not trigger a warning from mpv.
2017-12-13 21:00:22 +02:00
wm4 26cdd52801 vf_buffer: remove this filter
It has been deprecated for a while and is 100% useless. It was forgotten
in the recent filter purge. Get rid of it.
2017-12-12 22:02:56 +02:00
pavelxdd 6c8e7daebb options: don't report errors on help value for OPT_GEOMETRY
The same idea as in 3723e61 but for OPT_GEOMETRY now.
2017-12-11 21:56:20 +02:00
pavelxdd cdb6cb55e0 options: don't report errors on help value for OPT_COLOR
The same idea as in 3723e61 but for OPT_COLOR now.
Added missing closing bracket in the help message.
2017-12-11 21:56:20 +02:00
pavelxdd 3f127448e8 options: don't report errors on help value for OPT_FLAG
The same idea as in 3723e61 but for OPT_FLAG now.
2017-12-11 21:56:20 +02:00
pavelxdd 6a85f9bf74 w32_common: update outdated comment about wakeup events
mpv doesn't use WM_USER for wakeup events since 91079c0
Updated the comment.
2017-12-11 11:51:41 -08:00
wm4 308b3cd71b vf_convert: default to limited range when converting RGB to YUV
Full range YUV causes problems everywhere. For example it's usually the
wrong choice when using encoding mode, and libswscale sometimes messes
up when converting to full range too. (In this partricular case, we
found that converting rgba->yuv420p16 full range actually seems to
output limited range.)

This actually restores a similar heueristic from the late vf_scale.c.
2017-12-11 21:27:11 +02:00
wm4 5e38e03980 vo_gpu: hwdec_drmprime_drm: silence error on failed autoprobing
When autoprobing the hwdec interops (which now happens to all compiled
interops if hardware decoding is used), failure to load an interop
should not print an error in the normal case. So hide it.

(We could make the log level conditional on whether autoprobing is used,
but directly loading it without autoprobing is obscure, and most other
interops don't do this either.)
2017-12-11 20:50:50 +02:00
wm4 92c4be4b6e hwdec: document a forgotten parameter
Add the "all" value to the --gpu-hwdec-interop help output.
2017-12-11 20:44:59 +02:00
wm4 6047333f0b video: remove code duplication by calling a hwdec loader helper
Make gl_video_load_hwdecs() call gl_video_load_hwdecs_all() when
all HW decoders should be loaded.
2017-12-11 20:44:59 +02:00
wm4 5196c34aec video: properly initialize and set hwdec_interop
Don't reset --gpu-hwdec-interop if vo_gpu uses dumb mode.
2017-12-11 20:44:59 +02:00
wm4 a4705e8b59 vd_lavc: always load VO interops with non-copy hw decoders
For METHOD_INTERNAL hwdecs (non-copy cases), make sure the VO interops
are always loaded, because those decoders will output hardware pixel
formats, which will need special support in vo_gpu. Otherwise,
initialization will fail, complaining that it can't convert the output
format to something the VO supports.
2017-12-11 20:44:59 +02:00
pavelxdd fd4e756e9c osd: fix a compiler warning by adding parentheses in if condition 2017-12-10 17:20:58 -08:00
Jan Ekström affcccb007 vo: fix a compiler warning by properly printing a 64bit integer 2017-12-11 00:16:01 +02:00
LongChair b60ac5b5ba vd_lavc: add rkmpp to the hwdec_wrappers array.
Allows to get the hwdec picked up properly by mpv on rockchip devices
2017-12-10 18:24:50 +02:00
wm4 b782c90180 demux_timeline: disable pointless packet cache for sub-demuxers
It seems like there's nothing stopping from sub-demuxers from keeping
packets in the cache, even if it's completely pointless. The top-most
demuxer (demux_timeline) already takes care of caching, so sub-demuxers
only waste space and time with this.

Add a function that can disable the packet cache even at runtime and
after packets are read. (It's not clear whether it really can happen
that packets are read before demux_timeline gets the sub-demuxers, but
there's no reason to make it too fragile.) Call it on all sub-demuxers.

For this to work, it seems we have to move the code for setting the
seekable_cache flag to before demux_timeline is potentially initialized,
because otherwise the cache would be reenabled if the demuxer triggering
timeline support is a timeline segment itself (e.g. ordered chapters).
2017-12-10 06:37:49 +02:00
wm4 451a502c1d demux: fix accounting for seekable ranges on track switches
This fixes missing audio when cycling through audio tracks with anything
that uses nested demuxers, such as demux_timeline, which us used for
EDL, --merge-files, ordered chapters, and youtube-dl pseudo DASH
support. When this bug happened, reenabling an audio track would lead to
silence for the duration of the readahead amount.

The underlying reason is the incorrectly updated buffered range on track
switch. It accidentally included the amount covered by the deselected
stream. But the cause of the observed effect was that demux_timeline
issued a refresh seek to the underlying slave demuxer, which in turn
thought it could do a cache seek, because the seek range still included
everything.

update_stream_selection_state() calls update_seek_ranges() to update the
seek ranges after a track switch. When reenabling the track, ds->eager
was set to false during update_seek_ranges(), which made it think the
stream was sparse, and thus it didn't restrict the current seek range
(making later code think everything was buffered). Fix this by moving
some code, so we first update the ds->eager flag, then the seek ranges.

Also verbose log the low level stream selection calls.
2017-12-10 06:37:49 +02:00
Anna-Maria Meriniemi 39bc954488 manpage: Fix typo (reomve -> remove)
This commit fixes the "reomve" typo in the Javascript docs.
2017-12-10 00:10:02 +02:00
Drew DeVault f60bfd1ad5 terminal-unix: fix race condition with tty reset
Calling do_deactivate_getch2 before joining the terminal thread could
lead to breakage if the terminal thread got another interation in before
it was signaled to stop.

This also addresses a minor error with the order in which things are
initialized - getch2_poll would previously call tcgetpgrp(tty_in) before
tty_in was initialized, which did not lead to broken behavior, but was
not correct either.

Fixes #5195
2017-12-09 21:37:44 +02:00
Drew DeVault a0fc195112 terminal-unix: switch back to poll(3)
This leverages the new polldev shim which lets us "poll" device files on
macOS with select and use the genuine article on other platforms.
2017-12-09 21:11:46 +02:00
Drew DeVault ba418132cd osdep: add poll shim for macOS
This implements a poll-compatible interface, backed by select on macOS,
suitable for polling on device files - which are not supported by
macOS's implementation of poll. This is a (long-standing) bug in macOS,
so hopefully we can eventually remove this shim.
2017-12-09 21:11:46 +02:00
James Ross-Gowan 1d7a746505 appveyor: fix FFmpeg download
Broken in f19797dea6. It seems like the Git server on git.ffmpeg.org
doesn't like clone --depth=1, so use the GitHub mirror instead.
2017-12-09 20:01:54 +11:00
James Ross-Gowan 6ab7e0d465 vo_gpu: d3d11: check for timestamp query support
Apparently timestamp queries are optional for 10level9 devices. Check
for support when creating the device rather than spamming error messages
during rendering. CreateQuery can be used to check for support by
passing NULL as the final parameter.

See:
https://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx#ID3D11Device_CreateQuery
2017-12-09 19:53:53 +11:00
pavelxdd 3723e611fc options: don't report errors on help value for OPT_CHOICE
'help' is a valid value for a lot of mpv options, such as `hwdec`
or `vo` for printing available values, so this change makes the
output of OPT_CHOICE options like `--video-sync=help` more
consistent by not reporting an error about invalid value 'help'.
2017-12-08 20:47:14 +02:00
wm4 0a749a38f7 video: add a shitty hack to avoid missing subtitles with vf_sub
update_subtitles() makes sure all subtitle packets at/before the given
PTS have been read and processed. Normally, this function is only called
before sending a frame to the VO. This is too late for vf_sub, which
expects the subtitles to be updated before feeding a frame to the
filters.

Apparently this was specifically a problem for the first frame.
Subsequent frames might have been ok due to general prefetching.

(This will fail anyway, should a filter dare to add an offset to the
timestamps of the filered frames before they pass to vf_sub.)

Fixes #5194.
2017-12-08 20:33:23 +02:00
Drew DeVault 0f9a690eba terminal-unix: fix busy looping on Linux
POSIX permits select() to modify the timeout, which can happen on the
Linux implementation. This can reset the timeout, which spins this into
a tight loop. A timeout isn't necessary in the first place, so just use
NULL instead.
2017-12-08 19:58:36 +02:00
wm4 3c62a20f48 manpage: clarify --sub-file(s) options
This was a bit confused, and I bet nobody understood whether to use
--sub-file or --sub-files, and what the difference is. Explicitly
mention that both variants exist, and how they are related.
2017-12-07 23:48:16 -08:00
wm4 80d43ee4e6 player: when loading external file, always add all track types
Until now, using --sub-file would add only subtitle tracks from the
given file. (E.g. if you passed a video file, only the subtitle tracks
from it were added, not the video or audio tracks.)

This is slightly messy (because streams are hidden), and users don't
even want it, as shown by #5132. Change it to always add all streams.
But if there's no stream of the wanted type, we still report an error
and do not add any streams. It's also made sure none of the other track
types are autoselected.

Also adjust the error messages on load failure slightly.

Fixes #5132.
2017-12-07 23:48:16 -08:00
wm4 520fc74036 player: rebase start time even for subtitle streams
It appears libavformat never sets the file start time for subtitles, so
this special check is not needed. The original idea was probably that
_if_ the demuxer set the start time to the first subtitle packet, the
subtitles would be shifted incorrectly.
2017-12-07 23:48:16 -08:00
Drew DeVault 8977fe5ed9 Use /dev/tty instead of stdin for terminal input
Fixes #4190

This allows you to use terminal input even if you've piped something
into mpv.
2017-12-08 01:30:42 +02:00
pavelxdd 665173d8b2 w32_common: improve the window message state machine
* Distinguish between the window being moved or not.
* Skip trying to snap if currently in full screen or an embedded
  window.
* Exit snapped state if the size changed when the window was being
  moved.
2017-12-07 23:32:56 +02:00
pavelxdd 483437ba91 w32_common: skip window snapping if Windows handled it
Check the expected width and height against up-to-date
window placement. If they do not match, we will consider snapping
to have happened on Windows' side.
2017-12-07 23:32:56 +02:00
Kevin Mitchell 985e83e217 Revert "ytdl: handle HLS with FFmpeg"
Apparently, this breaks youtube live and possibly other things.

This reverts commit 06519aae58.
2017-12-07 00:46:27 -08:00
wm4 06519aae58 ytdl: handle HLS with FFmpeg
Using youtube-dl's metadata ends up with stupid things like missing
variant streams, or missing audio streams entirely.
2017-12-06 23:59:59 -08:00
Aman Gupta 0c6a488ef9 options: add --start=none to reset previously set start time
Previously when using a libmpv instance to play multiple videos,
once --start was set there was no clear way to unset it. You could
use --start=0, but 0 does not always mean the beginning of the file
(especially when using --rebase-start-time=no). Looking up the start
timestamp and passing that in also does not always work, particularly
when the first timestamp is negative (since negative values to --start
have a special meaning).

This commit adds a new "none" value which maps to the internal
REL_TIME_NONE, matching the default value of the play_start option.
2017-12-06 20:50:31 +02:00
Leo Izen a2e34b6f41 manpage: minor fixes to documenation 2017-12-06 00:11:37 -08:00
Kevin Mitchell f23c21ef17 manpage: add note about properties not immediately showing up
fixes #5134
2017-12-06 09:05:57 +02:00
Leo Izen 0433162f7f player/osd.c: fix putting --start time on OSD
I missed an ab-loop check in ff7e294. It should now work as expected.
2017-12-05 17:15:08 -05:00
Leo Izen 9513165c99 player/playloop.c: fix --loop-file without --start
I missed a check for MP_NOPTS_VALUE in 4efe330. Now
it should work as expected.
2017-12-05 14:36:47 -05:00
Rostislav Pehlivanov f19797dea6 Remove support for ffmpeg-mpv 2017-12-05 08:27:55 +00:00
Rostislav Pehlivanov a743fef837 vo: add support for externally driven renderloop and make wayland use it
Fixes display-sync (though if you change virtual desktops you'll need to seek
to re-enable display-sync) partially under wayland.

As an advantage, rendering is completely disabled if you change desktops or
alt+tab so you lose no performance if you leave mpv running elsewhere as long
as it isn't visible.

This could also be ported to other VOs which supports it.
2017-12-05 08:26:24 +00:00
Leo Izen 713668b99a manpage: add some minor documenation fixes
- replace the incorrect reference to --opengl-shader
- document a caveat when using --image-display-duration
- add some documentation on --vf=lavfi=
2017-12-04 20:57:16 -05:00
wm4 7a3df7d6a4 Copyright: remove removed file from GPL list 2017-12-05 01:19:53 +01:00
Leo Izen fdc311625e player/misc.c: allow both --length and --end to control play endpoint
Most options that change the playback endpoint coexist and playback
stops when it reaches any of them. (e.g. --ab-loop-b, --end, or
--chapter). This patch extends that behavior to --length so it isn't
automatically trumped by --end if both are present. These two will
interact now as the other options do.

This change is also documented in DOCS/man/options.rst.
2017-12-04 12:34:02 -05:00
James Ross-Gowan 9abb710afb vo_gpu: d3d11_helpers: use better formatting for PCI IDs
The old format was definitely misleading, since it used an 0x prefix and
formatted the device IDs with %d.
2017-12-04 20:11:20 +11:00
Leo Izen 4efe330efb player/playloop.c: respect playback start time when using --loop-file
Using --loop-file should now seek to the position denoted by --start
or equivalent option, rather than always seeking to the beginning as
it had done before. --loop-playlist already behaves this way, so
this brings --loop-file in line for added consistency.
2017-12-03 22:32:36 -05:00
Leo Izen ff7e294610 player: use start timestamp for ab-looping if --ab-loop-a is absent
If --ab-loop-b is present, then ab-looping will be enabled and will
attempt to seek to the beginning of the file. This patch changes it
so it will instead seek to the start of playback, either via --start
or some equivalent, rather than always to the beginning of the file.
2017-12-03 22:23:24 -05:00
Leo Izen a6ca167794 player: add get_play_start_pts
Added a get_play_start_pts function to coincide with the
already-existing get_play_end_pts. This prevents code duplication
and also serves to make it so code that probes the start time
(such as get_current_pos_ratio) will work correctly with chapters.

Included is a bug fix for misc.c/rel_time_to_abs that makes it work
correctly with chapters when --rebase-start-time=no is set.
2017-12-03 21:57:34 -05:00
Ckat e92d1b72a7 TOOLS/autoload.lua: update extensions
* duplicated 'ogv' renamed to 'ogm'
* 'ogg' and 'opus' added as common audio file extensions
2017-12-03 22:12:53 +01:00
sfan5 3ac8a7f694 stream_libarchive: Fix locale includes on macOS
Fixes #5108
2017-12-03 21:54:12 +01:00
Nicolas F 744b67d9e5 Fix various typos in log messages 2017-12-03 21:24:18 +01:00
Mariusz Skoneczko 1a9fb7937a manpage: vaapi-copy is not limited to Intel GPUs
vaapi-copy works with some AMD cards
2017-12-03 21:19:39 +01:00
Anton Kindestam cc16cd5aa4 video: probe format of primary plane in drm/egl context
We need to support hardware/drivers which do not support ARGB8888 in
their primary plane.

We also use p->primary_plane_format when creating the gbm surface, to
make sure it always matches (in actuality there should be little
difference).
2017-12-03 17:30:17 +02:00
Anton Kindestam 04e5fbde43 hwdec: whitespace cleanup in hwdec_drmprime_drm.c 2017-12-03 17:30:17 +02:00
Anton Kindestam eb46d46e73 video: fix use of possibly-NULL pointer in drm_egl_init 2017-12-03 17:30:17 +02:00
Anton Kindestam 5129d777a6 video: fix double free in drm_atomic_create_context
Passing in an invalid DRM overlay id with the --drm-overlay option would
cause drmplane to be freed twice: once in the for-loop and once at the
error-handler label fail.

Solve by setting drmpanel to NULL after freeing it.

Also the 'return false' statement after the error handler label should
probably be 'return NULL', given that the return type of
drm_atomic_create_context returns a pointer.
2017-12-03 17:30:17 +02:00
wm4 9bbf8a6dfa travis: remove Libav check for now
I sure hope they merge the patches for the required hwdec info API,
which is already in FFmpeg.
2017-12-02 23:30:11 +01:00
wm4 7bc48f7843 build: remove nanosleep() check
Also guaranteed by POSIX.
2017-12-02 23:29:40 +01:00
wm4 0601e48ef4 build: remove termios check
Also should be fully covered by POSIX.
2017-12-02 23:27:23 +01:00
wm4 d7a02bcb3b build: remove POSIX/sysv shared memory test
vo_x11 and vo_xv need this. According to the Linux manpage, all involved
functions are POSIX-2001 anyway. (I just assumed they were not, because
they're mostly System V UNIX legacy garbage.)
2017-12-02 23:19:13 +01:00
wm4 ca29a5aa9b vd_lavc: don't request native pixfmt with -copy and METHOD_INTERNAL
If the codec uses AV_CODEC_HW_CONFIG_METHOD_INTERNAL, and we're using
the -copy method, then don't request the native pix_fmt. It might not
have a AVFrame.hw_frames_ctx set, and we couldn't read back at all. On
top of that, most of those decoders probably don't provide read-back
when using such opaque formats anyway, while providing separate decoding
modes to decode to RAM.
2017-12-02 21:08:38 +01:00
Martin Herkt 1d92a804d2 man: remove incorrect note about default opengl backend 2017-12-02 06:49:12 +01:00
wm4 292724538c video: remove some more hwdec legacy stuff
Finally get rid of all the HWDEC_* things, and instead rely on the
libavutil equivalents. vdpau still uses a shitty hack, but fuck the
vdpau code.

Remove all the now unneeded remains. The vdpau preemption thing was not
unused anymore; if someone cares this could probably be restored.
2017-12-02 04:53:55 +01:00
wm4 23a9efd124 vd_lavc, vdpau, vaapi: restore emulated API avoidance
This code is for trying to avoid using an emulation layer when using
auto probing, so that we end up using the actual API the drivers
provide. It was destroyed in the recent refactor.
2017-12-02 04:53:51 +01:00
wm4 0780d38329 hwdec: don't require setting legacy hwdec fields
With the recent changes, mpv's internal mechanisms got synced to
libavcodec's once more. Some things are still needed for filters (until
the mechanism gets replaced), but there's no need to require other hwdec
methods to use these fields. So remove them where they are unnecessary.

Also fix some minor leaks in the dxva2 backends, and set the driver_name
field in the Apple ones. Untested on Apple crap.
2017-12-02 04:53:51 +01:00
wm4 8b3dbab19e vd_lavc: simpler way to check for opque hw frame
The ->fmt shit is something I'd like to phase out.
2017-12-02 02:45:49 +01:00
wm4 3c07db0345 vd_lavc: sort -copy hwdec modes to end of list
Otherwise, if e.g. "nvdec" didn't work, but "nvdec-copy" did, it would
never try "vdpau", which is actually the next non-copy mode on the
autprobe list. It's really expected that it selects "vdpau". Fix this by
sorting the -copy modes to the end of the final hwdec list.

But we still don't want preferred -copy modes like "nvdec-copy" to be
sorted after fragile non-preferred modes like "cuda", and --hwdec=auto
should prefer "nvdec-copy" over it, so make sure the copying mode does
not get precedence over preferred vs. non-preferred mode.

Also simplify the existing auto_pos sorting condition, and fix the
fallback sort order (although that doesn't matter too much).
2017-12-02 02:32:41 +01:00
wm4 b279cfb1dd vd_lavc: allow forcing single implementations with --hwdec 2017-12-02 00:57:25 +01:00
wm4 5990f640f4 vd_lavc: slightly simplify
Factor the somewhat-duplicated code into an append function. Also fix
setting the copying flag in one of the cases. This also ensures some
uniformity.
2017-12-02 00:54:42 +01:00
wm4 47f7920006 vd_lavc: coding style 2017-12-02 00:45:03 +01:00
wm4 627fa5aae0 hwdec: remove unused HWDEC_* constants
Removing the rest requires replacing some other mechanisms, later.
2017-12-01 22:09:38 +01:00
wm4 55c7e96878 vd_lavc: fix dumb nonsense 2017-12-01 22:08:59 +01:00
wm4 9d367cb0f9 vd_lavc, mp_image: remove weird mpv specific palette constant
Was for times when we were trying to be less dependent on libav* I
guess.
2017-12-01 22:03:38 +01:00
wm4 d891239d72 vd_lavc: merge redundant header
This is not needed anymore.
2017-12-01 22:01:54 +01:00
wm4 076b1d266e audio: fix missing volume update on init and reinit
This is never updated after the AO inits, so there are several cases
where the volume would stay at 100%, even if it shouldn't. This affects
initial volume as well as track switching or switching between files.
2017-12-01 21:18:06 +01:00
Nicolas F 2e24f5f1b5 scripting: report dlerror() output
dlopen() and dlsym() can fail in various ways, and we can find out
how it failed by calling dlerror(). This is particularly useful if
you typo the filename of a script when explicitly passing it with
--script, and dlopen actually tells you that the file doesn't exist
instead of leading you down a rabbit hole of disassembling your
shared object file to figure out why the thing won't load.
2017-12-01 21:13:48 +01:00
wm4 eb8957cea1 vd_lavc: rewrite how --hwdec is handled
Change it from explicit metadata about every hwaccel method to trying to
get it from libavcodec. As shown by add_all_hwdec_methods(), this is a
quite bumpy road, and a bit worse than expected.

This will probably cause a bunch of regressions. In particular I didn't
check all the strange decoder wrappers, which all cause some sort of
special cases each. You're volunteering for beta testing by using this
commit.

One interesting thing is that we completely get rid of mp_hwdec_ctx in
vd_lavc.c, and that HWDEC_* mostly goes away (some filters still use it,
and the VO hwdec interops still have a lot of code to set it up, so it's
not going away completely for now).
2017-12-01 21:11:43 +01:00
wm4 43af055a70 options: rename empty string special case for option values
"--bla" behaved differently from "--bla=". Change this, in line with how
options have been changed in general over the last few years.
2017-12-01 21:01:40 +01:00
wm4 8b141ab9ac av_common: drop old hack against ancient lavc vdpau wrapper
Seems like they finally got rid of this. It was the first lavc vdpau
API, and mpv stopped supporting it in favor of newer APIs a long time
ago, causing confusion to users who tried to enable vdpau decoding by
forcing the decoders (MPlayer style).
2017-12-01 18:15:52 +01:00
wm4 80359c6615 vd_lavc: drop mediacodec direct rendering support temporarily
The libavcodec mediacodec support does not conform to the new hwaccel
APIs yet. It has been agreed uppon that this glue code can be deleted
for now, and support for it will be restored at a later point.

Readding would require that it supports the AVCodecContext.hw_device_ctx
API. The hw_device_ctx would then contain the surface ID.
vo_mediacodec_embed would actually perform the task of creating
vo.hwdec_devs and adding a mp_hwdec_ctx, whose av_device_ref is a
AVHWDeviceContext containing the android surface.
2017-12-01 18:01:15 +01:00
wm4 9f52a92899 video: move d3d.c out of decode sub directory
It makes more sense to have it in the general video directory (along
with vdpau.c and vaapi.c), since the decoder source files don't even
access it anymore.
2017-12-01 17:58:56 +01:00
wm4 1e44540906 vd_lavc: delete hw_d3d11va.c/hw_dxva2.c and merge leftovers
Like with all hwaccels, there's little that is actually specific to
decoding (which has been moved away anyway), and what is left are
declarations (which will also go away soon).
2017-12-01 17:58:56 +01:00
wm4 b89f5084cc hw_dxva2: move dxva2 code to d3d.c
This source file will disappear, so just collect the leftovers in d3d.c.
2017-12-01 08:10:31 +01:00
wm4 a0d9e15342 video: refactor hw device creation for hwdec copy modes
Lots of shit code for nothing. We probably could just use libavutil's
code for all of this. But for now go with this, since it tends to
prevent stupid terminal messages during probing (libavutil has no
mechanism to selectively suppress errors specifically during probing).

Ignores the "emulated" API flag (for avoiding vaapi/vdpau wrappers), but
it doesn't matter that much for -copy anyway.
2017-12-01 08:05:16 +01:00
wm4 afd5f3227e video: fix memory leaks with hwdec copy modes
This leaked 2 unreffed AVFrame structs (roughly 1KB) per decoded frame.

Can I blame the FFmpeg API and the weird difference between freeing and
unreffing an AVFrame?
2017-12-01 08:01:41 +01:00
wm4 c5fac0c2b0 vd_lavc: move entrypoint for hwframes_refine
The idea is to get rid of vd_lavc_hwdec, so special functionality like
this has to go somewhere else. At this point, hwframes_refine is only
needed for d3d11, and it doesn't do much, so for now the new callback
has no context. In can be made more fancy if really needed.
2017-12-01 08:01:41 +01:00
wm4 643a1fc7de vd_lavc: remove process_image callback
Now unused.
2017-12-01 05:57:41 +01:00
wm4 9345964bad d3d11: move code for d3d11eglrgb hack 2017-12-01 05:57:41 +01:00
wm4 7e87feaf15 vo_gpu: hwdec: remove redundant fields
The testing_only field is not referenced anymore with vaglx removed and
the previous commit dropping all uses.

The ra_hwdec_driver.api field became unused with the previous commit,
but all hwdec interop drivers still initialized it.

Since this touches highly OS-specific code, build regressions are
possible (plus the previous commit might break hw decoding at runtime).
At least hwdec_cuda.c still used the .api field, other than initializing
it.
2017-12-01 05:57:41 +01:00
wm4 91586c3592 vo_gpu: make it possible to load multiple hwdec interop drivers
Make the VO<->decoder interface capable of supporting multiple hwdec
APIs at once. The main gain is that this simplifies autoprobing a lot.
Before this change, it could happen that the VO loaded the "wrong" hwdec
API, and the decoder was stuck with the choice (breaking hw decoding).
With the change applied, the VO simply loads all available APIs, so
autoprobing trickery is left entirely to the decoder.

In the past, we were quite careful about not accidentally loading the
wrong interop drivers. This was in part to make sure autoprobing works,
but also because libva had this obnoxious bug of dumping garbage to
stderr when using the API. libva was fixed, so this is not a problem
anymore.

The --opengl-hwdec-interop option is changed in various ways (again...),
and renamed to --gpu-hwdec-interop. It does not have much use anymore,
other than debugging. It's notable that the order in the hwdec interop
array ra_hwdec_drivers[] still matters if multiple drivers support the
same image formats, so the option can explicitly force one, if that
should ever be necessary, or more likely, for debugging. One example are
the ra_hwdec_d3d11egl and ra_hwdec_d3d11eglrgb drivers, which both
support d3d11 input.

vo_gpu now always loads the interop lazily by default, but when it does,
it loads them all. vo_opengl_cb now always loads them when the GL
context handle is initialized. I don't expect that this causes any
problems.

It's now possible to do things like changing between vdpau and nvdec
decoding at runtime.

This is also preparation for cleaning up vd_lavc.c hwdec autoprobing.
It's another reason why hwdec_devices_request_all() does not take a
hwdec type anymore.
2017-12-01 05:57:01 +01:00
Mark Thompson 2cf5836293 vo_opengl: hwdec_vaegl: Reenable vaExportSurfaceHandle()
It will be present from libva 2.1 (VAAPI 1.1.0 or higher).
2017-11-30 23:35:28 +00:00
wm4 c7596d3c8b vd_lavc: prefer nvdec over vdpau with --hwdec=auto
nvdec aka cuvid aka cuda should work much better than vdpau, and support
newer codecs (such as vp9), and more advanced surface formats (like 10
bit).

This requires moving the d3d hwaccels in the autoprobe order, since on
Windows, d3d decoding should be preferred over nvidia proprietary stuff.

Users of older drivers will need to force --hwdec=vdpau, since it could
happen that the vo_gpu cuda hwdec interop loads (so the vdpau interop is
not loaded), but the hwdec itself doesn't work.

I expect this does not break AMD (which still needs vdpau for vo_gpu
interop, until libva is fixed so it can fully support AMD).
2017-11-30 21:54:13 +01:00
wm4 ce3af51e58 DOCS/contribute.md: fix a typo 2017-11-30 20:36:09 +01:00
Leo Izen 60f5260f94 DOCS/mpv.rst: document bluray:// alias for bd://
bluray:// is an alias for bd://, but this
isn't actually documented anywhere.
This should fix that.
2017-11-30 20:17:03 +01:00
sfan5 244cc1f018 client: Allow "C.UTF-8" as LC_NUMERIC locale
This is required on newer Android NDKs, as setting LC_NUMERIC
to "C" will still return "C.UTF-8" if you query it.
2017-11-30 21:06:37 +02:00
Kevin Mitchell bc7ac29966 DOCS/interface-changes.rst: fix typo 2017-11-29 22:19:30 -08:00
wm4 c437267518 vo_gpu: remove hwdec_vaglx interop
This has stopped being useful a long time ago, and it's the only GPL
source file in the vo_gpu source directories. Recently it wasn't even
loaded at all, unless you forced loading it.
2017-11-30 04:19:12 +01:00
wm4 1c463d13e1 vf: remove a stray HAVE_GPL
These were determined to be LGPL a few commits ago.
2017-11-30 04:07:34 +01:00
wm4 b56f109219 ao: minor simplification to gain processing code
Cosmetic move of a variable, and consider an adjustment below 1/256 or
so not worth applying (even in the float case).
2017-11-30 01:31:37 +01:00
wm4 6f8cf73f54 ao: simplify hack for float atomics
stdatomic.h defines no atomic_float typedef. We can't just use _Atomic
unconditionally, because we support compilers without C11 atomics. So
just create a custom atomic_float typedef in the wrapper, which uses
_Atomic in the C11 code path.
2017-11-30 01:20:03 +01:00
wm4 963eb15006 build: bump required ffmpeg version
For the vp9 fix (at least if upstream ffmpeg is used).
2017-11-30 01:09:31 +01:00
wm4 7f8f134730 DOCS/interface-changes.rst: update according to recent commits 2017-11-29 21:34:08 +01:00
wm4 d725630b5f audio: add audio softvol processing to AO
This does what af_volume used to do. Since we couldn't relicense it,
just rewrite it. Since we don't have a new filter mechanism yet, and the
libavfilter is too inconvenient, do applying the volume gain in ao.c
directly. This is done before handling the audio data to the driver.

Since push.c runs a separate thread, and pull.c is called asynchronously
from the audio driver's thread, the volume value needs to be
synchronized. There's no existing central mutex, so do some shit with
atomics. Since there's no atomic_float type predefined (which is at
least needed when using the legacy wrapper), do some nonsense about
reinterpret casting the float value to an int for the purpose of atomic
access. Not sure if using memcpy() is undefined behavior, but for now I
don't care.

The advantage of not using a filter is lower complexity (no filter auto
insertion), and lower latency (gain processing is done after our
internal audio buffer of at least 200ms).

Disavdantages include inability to use native volume control _before_
other filters with custom filter chains, and the need to add new
processing for each new sample type.

Since this doesn't reuse any of the old GPL code, nor does indirectly
rely on it, volume and replaygain handling now works in LGPL mode.

How to process the gain is inspired by libavfilter's af_volume (LGPL).
In particular, we use exactly the same rounding, and we quantize
processing for integer sample types by 256 steps. Some of libavfilter's
copyright may or may not apply, but I think not, and it's the same
license anyway.
2017-11-29 21:30:51 +01:00
wm4 9c909fbb4d build: fix LGPL build with ALSA enabled
Oops. This is part of the TV code, for which we didn't make any effort
to relicense. But files were always built, because they didn't depend on
the common TV code. (The HAVE_GPL in the source file exposed this by
making the build fail.)
2017-11-29 21:30:51 +01:00
wm4 3d27a0792b af: remove deprecated audio filters
These couldn't be relicensed, and won't survive the LGPL transition. The
other existing filters are mostly LGPL (except libaf glue code).

This remove the deprecated pan option. I guess it could be restored by
inserting a libavfilter filter (if there's one), but for now let it be
gone.

This temporarily breaks volume control (and things related to it, like
replaygain).
2017-11-29 21:30:51 +01:00
wm4 23d9dc5457 video: remove automatic stereo3d filter insertion
The internal stereo3d filter was removed due to being GPL only, and due
to being a mess that somehow used libavfilter's filter. Without this
filter, it's hard to remove our internal stereo3d image attribute, so
even using libavfilter's stereo3d filter would not work too well (unless
someone fixes it and makes it able to use AVFrame metadata, which we
then could mirror in mp_image).

This was never well thought-through anyway, so just drop it. I think
some "downsampling" support would still make sense, maybe that can be
readded later.
2017-11-29 21:30:51 +01:00
wm4 03518c1a83 video: fix rotation and deinterlace auto filters
Now using libavfilter filters directly.

The rotation case is a bit lazy, because it uses the slow vf_rotate
filter in all cases, instead of using special filters for 90° step
rotations.
2017-11-29 21:30:51 +01:00
wm4 9d6bc77a59 input: remove a stray HAVE_GPL
This was marked GPL, because the implementation in command.c (which is
shared with the subtitle code) was marked as GPL. This has been changed,
so this is unnecessary. The original commands for external audio tracks
have been added to mpv by someone who agreed with the relicensing.
2017-11-29 18:28:27 +01:00
wm4 f082db8f67 vf_lavfi: remove old internal wrapper API stuff
This was for filters "redirecting" to vf_lavfi. All filters using it
have been removed.
2017-11-29 18:26:25 +01:00
wm4 194ec2b47b vf_sub, vf_format: change license to LGPL
They were added to the "to deleted" list and never relicensed, because I
thought I'd delete them early. But it's possible that they'll stay in
mpv for a longer time, so relicense them. Still leaving them as
deprecated and scheduled for removal, so they can still be dropped once
there is a better way to deal with them, if they get annoying, or if a
better mechanism is found that makes them unnecessary.

All contributors agreed. There are some minor changes by people who did
not agree, but these are all not relevant or have been removed.
2017-11-29 18:22:23 +01:00
wm4 12cac1d111 vf: remove most GPL video filters
Almost all of them had their guts removed and replaced by libavfilter
long ago, but remove them anyway. They're pointless and have been
scheduled for deprecation.

Still leave vf_format (because we need it in some form) and vf_sub (not
sure).

This will break some builtin functionality: lavfi yadif defaults are
different, auto rotation and stereo3d downconversion are broken. These
might be fixed later.
2017-11-29 18:15:19 +01:00
wm4 d752f743ff vf: add vf_convert as interim replacement for vf_scale
We want to drop vf_scale, but we still need a way to auto convert
between imgfmts. In particular, vf.c will auto insert the "scale" filter
if the VO doesn't support a pixfmt.

To avoid chaos, create a new vf_convert.c filter, based on vf_scale.c,
but without the unrelicensed code parts. In particular, this filter does
not do scaling and has no options. It merely converts from one imgfmt to
another, if needed.
2017-11-29 18:04:56 +01:00
wm4 4dff0a8094 Copyright: fix some typos 2017-11-29 17:29:41 +01:00
wm4 20894016cc build: accept ffmpeg git by default
VP9 is still broken due to a difference with Libav, though.
2017-11-29 03:11:41 +01:00
wm4 d5dae869c6 player: match subtitles with language tags with --sub-auto=exact
Apparently a relatively widespread convention, and almost as strict as
the old "exact" semantics. (So it's not going to auto load radically
unrelated files.)
2017-11-27 19:45:13 +01:00
Vijay Marupudi e7c12bead4 README: fix markdown formatting of ffmpeg link
Pretty self-explanatory, square brackets instead of curly ones.
2017-11-26 13:36:29 -08:00
wm4 386e8cd16d player: change 3 remaining GPL-only code pieces to LGPL
There has been no new developments or agreements, but I was uncertain
about the copyright status of them. Thus this part of code was marked as
being potentially GPL, and was not built in LGPL mode. Now I've taken a
close look again, and decided that these can be relicensed using the
existing relicensing agreements.

OSD level 3 was introduced in commit 8d190244, with the author being
unreachable. As I decided in commit 6ddd95fd, OSD level 3 itself can
be kept, but the "osd" command had to go, and the "rendering" of OSD
level 3 (the HAVE_GPL code in osd.c) was uncertain. But the code for
this was rewritten: instead of duplicating the time/percent formatting
code, it was changed to use common code, and some weird extra logic was
removed. The code inside of the "if" is exactly the same as the code
that formats the OSD status line (covered by LGPL relicensing).

The current commands for adding/removing sub/audio tracks more or less
originated from commit 2f376d1b39, with the author being unreachable.
But the original code was very different, mostly due to MPlayer's
incredibly messy handling of subtitles in general. Nothing of this
remains in the current code. Even the command declarations were
rewritten. The commands (as seen from the user side) are rather similar
in naming and semantics, but we don't consider this copyrightable. So it
doesn't look like anything copyrightable is left.

The add/cycle commands were more or less based on step_property,
introduced in commit 7a71da01d6, with the patch author disagreeing with
the LGPL relicensing. But all code original to the patch has been
replaced in later mpv changes, and the original code was mostly copied
from MP_CMD_SET_PROPERTY anyway. The underlying property interface was
completely changed, the error handling was redone, and all of this is
very similar to the changes that were done on SET_PROPERTY. The command
declarations are completely different in the first place, because the
semantic change from step to add/cycle. The commit also seems to have
been co-authored by reimar to some degree. He also had the idea to
change the original patch from making the command modify a specific
property to making it generic.

(The error message line, especially with its %g formatting, might
contain some level of originality, so change that just to be sure.
This commit Copies and adapts the error message for SET_PROPERTY.)

Although I'm a bit on the fence with all the above things, it really
doesn't look like there's anything substantial that would cause issues.
I thus claim that there is no problem with changing the license to LGPL
for the above things. It's probably still slightly below the standard
that was usually applied in the code relicensing in mpv, but probably
still far above to the usual in open source relicensing (and above
commercial standards as well, if you look what certain tech giants do).
2017-11-24 14:12:10 +01:00
wm4 efbb919997 player: minor fix/simplification of OSD time/duration handling
Always display the duration as "unknown" if the duration is known. Also
fix that at least demux_lavf reported unknown duration as 0 (fix by
setting the default to unknown in demux.c).

Remove the dumb _u formatter function, and use a different approach to
avoiding displaying "unknown" as playback time on playback start (set
last_seek_pts for that).
2017-11-24 13:58:57 +01:00
wm4 274cc06aaf ao_alsa: change license to LGPL
Looks like this is covered by LGPL relicensing agreements now.

Notes about contributors who could not be reached or who didn't agree:

Commit 7fccb6486e has tons of mp_msg changes look like they are not
copyrightable (even if they were, all mp_msg calls were rewritten in
mpv times again). The additional play() change looks suspicious, but
the function was rewritten several times anyway (first time after that
commit in 4f40ec312).

Commit 89ed1748ae was rewritten in commit 325311af3 and then again
several times after that. Basically all this code is unnecessary in
modern mpv and has been removed.

No code survived from the following commits: 4d31c3c53, 61ecf838f2,
d38968bd, 4deb67c3f. At least two cosmetic typo fixes are not
considered as well.

Commit 22bb046ad is reverted (this wasn't a valid warning anyway, just
a C++-ism icc applied to C). Using the constants is nicer, but at least
I don't have to decide whether that change was copyrightable.
2017-11-23 16:43:59 +01:00
wm4 b2a08db71a ao_alsa: don't convert twice on retry
Obscure corner case.
2017-11-23 16:43:59 +01:00
Oswald Pan ae05d1f62c manpage: clarify bitstreaming options
Changes:
List other (commonly used) bitstreamed formats.
Clarify that WASAPI can only output multichannel PCM in exclusive mode.
2017-11-19 11:34:10 -08:00
James Ross-Gowan 4569f39da5 vo_gpu: d3d11: don't use runtime version for UAV slot count
FL 11_1 is only supported with the Direct3D 11.1 runtime anyway, so
there is no need to check both the runtime version and the feature
level.
2017-11-19 21:49:27 +11:00
James Ross-Gowan b9c742df10 vo_gpu: d3d11_helpers: don't try BGRA_SUPPORT
The D3D11_CREATE_DEVICE_BGRA_SUPPORT flag doesn't enable support for
BGRA textures. BGRA textures will be supported whether or not the flag
is passed. The flag just fails device creation if they are not supported
as an API convenience for programs that need BGRA textures, such as
programs that use D2D or D3D9 interop. We can handle devices without
BGRA support fine, so don't bother with the flag.
2017-11-19 21:37:57 +11:00
James Ross-Gowan 021fe791e1 vo_gpu: d3d11: mark the bgra8 format as unordered
Whoops. I was confused by the double-negative here.
2017-11-19 21:17:31 +11:00
James Ross-Gowan 0bdbe2bc53 win32: fix semantics of POSIX 2008 locale stubs
This sliences some warnings about unused values and statements with no
effect, but it also fixes a logic error with freelocale(), since
previously it would not work as expected when used in the body of an if
statement without braces.

Uses real functions, because with macros, I don't think there is a way
to silence the "statement with no effect" warnings in the case where the
return value of uselocale() is ignored.

As for replacing the these functions with working implementations, I
don't think this is possible for mpv's use-case, since MSVCRT does not
support UTF-8 locales, or any locale with multibyte characters that are
three or more bytes long. See:
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale
2017-11-19 21:10:56 +11:00
wm4 cd6f964b56 demux_mkv: remove unnecessary parsing for vp9
We can finally get rid of this crap.

Depends on a ffmpeg-mpv change. Always worked with Libav (ever since
they fixed it properly).
2017-11-17 14:18:57 +01:00
pavelxdd 35d74e1612 w32_common: move imm32.dll function to w32->api struct
For consistency with already implemented shcore.dll
function loading in w32->api:

Moved loading of imm32.dll to w32_api_load, and declare
pImmDisableIME function pointer in the w32->api struct.
Removed unloading of imm32.dll.
2017-11-15 22:54:54 +11:00
sfan5 3471e27efb vo_gpu/context_android: Process surface resizes correctly 2017-11-14 20:46:18 +02:00
James Ross-Gowan ff1ee66231 appveyor: use git submodule update --init
Thanks @jeeb.
2017-11-13 23:19:03 +11:00
wm4 41243e7c4f demux_lavf: always give libavformat the filename when probing
This gives the filename or URL to the libavformat probing logic, which
might use the file extension as a "help" to decide which format the file
is. This helps with mp3 files that have large id3v2 tags and prevents
the idiotic ffmpeg probing logic to think that a mp3 file is amr.

(What we really want is knowing whether we _really_ need to feed more
data to libavformat to detect the format. And without having to pre-read
excessive amounts of data for relatively normal streams.)
2017-11-12 19:38:45 +01:00
wm4 41cefe3e1f stream_libarchive, osdep: use stubs for POSIX 2008 locale on MinGW 2017-11-12 16:43:34 +01:00
wm4 987291d042 demux_playlist: support .url files
Requested. Not tested due to lack of real samples. Fixes #5107.
2017-11-12 15:51:48 +01:00
wm4 e2d0e0c6cb build: enable libarchive by default
Or libcve, as the vlc developers call it.
2017-11-12 13:51:30 +01:00
wm4 9922b6ff43 vo_gpu: ra_gl: remove stride hack
Same reasoning as in commit 9b5d062d36.
2017-11-12 13:49:00 +01:00
wm4 1e70e82baa stream_libarchive: workaround various types of locale braindeath
Fix that libarchive fails to return filenames for UTF-8/UTF-16 entries.
The reason is that it uses locales and all that garbage, and mpv does
not set a locale.

Both C locales and wchar_t are shitfucked retarded legacy braindeath. If
the C/POSIX standard committee had actually competent members, these
would have been deprecated or removed long ago. (I mean, they managed to
remove gets().) To justify this emotional outbreak potentially insulting
to unknown persons, I will write a lot of text. Those not comfortable
with toxic language should pretend this is a religious text.

C locales are supposed to be a way to support certain languages and
cultures easier. One example are character codepages. Back when UTF-8
was not invented yet, there were only 255 possible characters, which is
not enough for anything but English and some european languages. So they
decided to make the meaning of a character dependent on the current
codepage. The locale (LC_CTYPE specifically) determines what character
encoding is currently used.

Of course nowadays, this is legacy nonsense. Everything uses UTF-8 for
"char", and what doesn't is broken and terrible anyway. But the old ways
stayed with us, and the stupidity of it as well.

C locales were utterly moronic even when they were invented. The locale
(via setlocale()) is global state, and global state is not a reasonable
way to do anything. It will break libraries, or well modularized code.
(The latter would be forced to strictly guard all entrypoints set
set/restore locales, assuming a single threaded world.)

On top of that, setting a locale randomly changes the semantics of a
bunch of standard functions. If a function respects locale, you suddenly
can't rely on it to behave the same on all systems. Some behavior can
come as a surprise, and of course it will be dependent on the region of
the user (it doesn't help that most software is US-centric, and the US
locale is almost like the C locale, i.e. almost what you expect).

Idiotically, locales were not just used to define the current character
encoding, but the concept was used for a whole lot of things, like e. g.
whether numbers should use "," or "." as decimal separaror. The latter
issue is actually much worse, because it breaks basic string conversion
or parsing of numbers for the purpose of interacting with file formats
and such.

Much can be said about how retarded locales are, even beyond what I just
wrote, or will wrote below. They are so hilariously misdesigned and
insufficient, I can't even fathom how this shit was _standardized_. (In
any case, that meant everyone was forced to implement it.) Many C
functions can't even do it correctly. For example, the character set
encoding can be a multibyte encoding (not just UTF-8, but awful garbage
like Shift JIS (sometimes called SHIT JIZZ), yet functions like
toupper() can return only 1 byte. Or just take the fact that the locale
API tries to define standard paper sizes (LC_PAPER) or telephone number
formatting (LC_TELEPHONE). Who the fuck uses this, or would ever use
this?

But the badness doesn't stop here. At some point, they invented threads.
And they put absolutely no thought into how threads should interact with
locales. So they kept locales as global state. Because obviously, you
want to be able to change the semantics of basic string processing
functions _while_ they're running, right? (Any thread can call
setlocale() at any time, and it's supposed to change the locale of all
other threads.)

At this point, how the fuck are you supposed to do anything correctly?
You can't even temporarily switch the locale with setlocale(), because
it would asynchronously fuckup the other threads. All you can do is to
enforce a convention not to set anything but the C local (this is what
mpv does), or to duplicate standard functions using code that doesn't
query locale (this is what e.g. libass does, a close dependency of mpv).

Imagine they had done this for certain other things. Like errno, with
all the brokenness of the locale API. This simply wouldn't have worked,
shit would just have been too broken. So they didn't. But locales give a
delicious sweet spot of brokenness, where things are broken enough to
cause neverending pain, but not broken enough that enough effort would
have spent to fix it completely.

On that note, standard C11 actually can't stringify an error value. It
does define strerror(), but it's not thread safe, even though C11
supports threads. The idiots could just have defined it to be thread
safe. Even if your libc is horrible enough that it can't return string
literals, it could just just some thread local buffer. Because C11 does
define thread local variables. But hey, why care about details, if you
can just create a shitty standard?

(POSIX defines strerror_r(), which "solves" this problem, while still
not making strerror() thread safe.)

Anyway, back to threads. The interaction of locales and threads makes no
sense. Why would you make locales process global? Who even wanted it to
work this way? Who decided that it should keep working this way, despite
being so broken (and certainly causing implementation difficulties in
libc)? Was it just a fucked up psychopath?

Several decades later, the moronic standard committees noticed that this
was (still is) kind of a bad situation. Instead of fixing the situation,
they added more garbage on top of it. (Probably for the sake of
"compatibility"). Now there is a set of new functions, which allow you
to override the locale for the current thread. This means you can
temporarily override and restore the local on all entrypoints of your
code (like you could with setlocale(), before threads were invented).

And of course not all operating systems or libcs implement this. For
example, I'm pretty sure Microsoft doesn't. (Microsoft got to fuck it up
as usual, and only provides _configthreadlocale(). This is shitfucked on
its own, because it's GLOBAL STATE to configure that GLOBAL STATE should
not be GLOBAL STATE, i.e. completely broken garbage, because it requires
agreement over all modules/libraries what behavior should be used. I
mean, sure, makign setlocale() affect only the current thread would have
been the reasonable behavior. Making this behavior configurable isn't,
because you can't rely on what behavior is active.)

POSIX showed some minor decency by at least introducing some variations
of standard functions, which have a locale argument (e.g. toupper_l()).
You just pass the locale which you want to be used, and don't have to do
the set locale/call function/restore locale nonense. But OF COURSE they
fucked this up too. In no less than 2 ways:

- There is no statically available handle for the C locale, so you have
  to initialize and store it somewhere, which makes it harder to make
  utility functions safe, that call locale-affected standard functions
  and expect C semantics. The easy solution, using pthread_once() and a
  global variable with the created locale, will not be easily accepted
  by pedantic assholes, because they'll worry about allocation failure,
  or leaking the locale when using this in library code (and then
  unloading the library). Or you could have complicated library
  init/uninit functions, which bring a big load of their own mess.
  Same for automagic DLL constructors/destructors.
- Not all functions have a variant that takes a locale argument, and
  they missed even some important ones, like snprintf() or strtod() WHAT
  THE FUCK WHAT THE FUCK WHAT THE FUCK WHAT THE FUCK WHAT THE FUCK WHAT
  THE FUCK WHAT THE FUCK WHAT THE FUCK WHAT THE FUCK

I would like to know why it took so long to standardize a half-assed
solution, that, apart from being conceptually half-assed, is even
incomplete and insufficient. The obvious way to fix this would have
been:

- deprecate the entire locale API and their use, and make it a NOP
- make UTF-8 the standard character type
- make the C locale behavior the default
- add new APIs that explicitly take locale objects
- provide an emulation layer, that can be used to transparently build
  legacy code without breaking them

But this wouldn't have been "compatible", and the apparently incompetent
standard committees would have never accepted this. As if anyone
actually used this legacy garbage, except other legacy garbage. Oh yeah,
and let's care a lot about legacy compatibility, and let's not care  at
all about modern code that either has to suffer from this, or subtly
breaks when the wrong locales are active.

Last but not least, the UTF-8 locale name is apparently not even
standardized. At the moment I'm trying to use "C.UTF-8", which is
apparently glibc _and_ Debian specific. Got to use every opportunity to
make correct usage of UTF-8 harder. What luck that this commit is only
for some optional relatively obscure mpv feature.

Why is the C locale not UTF-8? Why did POSIX not standardize an UTF-8
locale? Well, according to something I heard a few years ago, they're
considering disallowing UTF-8 as locale, because UTF-8 would violate
certain ivnariants expected by C or POSIX. (But I'm not sure if I
remember this correctly - probably better not to rage about it.)

Now, on to libarchive.

libarchive intentionally uses the locale API and all the broken crap
around it to "convert" UTF-8 or UTF-16 (as contained in reasonably sane
archive formats) to "char*". This is a good start!

Since glibc does not think that the C locale uses UTF-8, this fails for
mpv. So trying to use archive_entry_pathname() to get the archive entry
name fails if the name contains non-ASCII characters.

Maybe use archive_entry_pathname_utf8()? Surely that should return
UTF-8, since its name seems to indicate that it returns UTF-8. But of
fucking course it doesn't! libarchive's horribly convoluted code (that
is full of locale API usage and other legacy shit, as well as ifdefs and
OS specific code, including Windows and fucking Cygwin) somehow fucks up
and fails if the locale is not set to UTF-8. I made a PR fixing this in
libarchive almost 2 years ago, but it was ignored.

So, would archive_entry_pathname_w() as fallback work? No, why would it?
Of course this _also_ involves shitfucked code that calls shitfucked
standard functions (or OS specific ifdeffed shitfuck). The truth is that
at least glibc changes the meaning of wchar_t depending on the locale.
Unlike most people think, wchar_t is not standardized to be an UTF
variant (or even unicode) - it's an encoding that uses basic units that
can be larger than 8 bit. It's an implementation defined thing. Windows
defines it to 2 bytes and UTF-16, and glibc defines it to 4 bytes and
UTF-32, but only if an UTF-8 locale is set (apparently).

Yes. Every libarchive function dealing with strings has 3 variants:
plain, _utf8, and _w. And none of these work if the locale is not set.
I cannot fathom why they even have a wchar_t variant, because it's
redundant and fucking useless for any modern code.

Writing a UTF-16 to UTF-8 conversion routine is maybe 3 pages of code,
or a few lines if you use iconv. But libarchive uses all this glorious
bullshit, and ends up with 3 not working API functions, and with over
4000 lines of its own string abstraction code with gratuitous amounts of
ifdefs and OS dependent code that breaks in a fairly common use case.

So what we do is:

- Use the idiotic POSIX 2008 API (uselocale() etc.) (Too bad for users
  who try to build this on a system that doesn't have these - hopefully
  none are left in 2017. But if there are, torturing them with obscure
  build errors is probably justified. Might be bad for Windows though,
  which is a very popular platform except on phones.)
- Use the "C.UTF-8" locale, which is probably not 100% standards
  compliant, but works on my system, so it's fine.
- Guard every libarchive call with uselocale() + restoring the locale.
- Be lazy and skip some libarchive calls. Look forward to the unlikely
  and astonishingly stupid bugs this could produce.

We could also just set a C UTF-8 local in main (since that would have no
known negative effects on the rest of the code), but this won't work for
libmpv.

We assume that uselocale() never fails. In an unexplainable stroke of
luck, POSIX made the semantics of uselocale() nice enough that user code
can fail failures without introducing crash or security bugs, even if
there should be an implementation fucked up enough where it's actually
possible that uselocale() fails even with valid input.

With all this shitty ugliness added, it finally works, without fucking
up other parts of the player. This is still less bad than that time when
libquivi fucked up OpenGL rendering, because calling a libquvi function
would load some proxy abstraction library, which in turn loaded a KDE
plugin (even if KDE was not used), which in turn called setlocale()
because Qt does this, and consequently made the mpv GLSL shader
generation code emit "," instead of "." for numbers, and of course only
for users who had that KDE plugin installed, and lived in a part of the
world where "." is not used as decimal separator.

All in all, I believe this proves that software developers as a whole
and as a culture produce worse results than drug addicted butt fucked
monkeys randomly hacking on typewriters while inhaling the fumes of a
radioactive dumpster fire fueled by chinese platsic toys for children
and Elton John/Justin Bieber crossover CDs for all eternity.
2017-11-12 13:36:56 +01:00
James Ross-Gowan 9b5d062d36 vo_gpu: d3d11: remove flipped texture upload hack
Made unnecessary by 4a6b04bdb9.
2017-11-12 17:10:22 +11:00
Akemi 007cd24c2b osx: fix the bundle $PATH yet again
we have 5 parameters for the string but only 4 were being used.
2017-11-11 19:21:21 +01:00
Akemi fb1d3caa9e cocoa: always return the target NSRect when in fullscreen
there is no need to calculate a new rectangle when in fullscreen since
we always want to cover the whole screen. so just return the target
rectangle.
2017-11-11 19:19:28 +01:00
wm4 871a8a316a demux: avoid queue overflow warning when joining two ranges
If the backbuffer is much larger than the forward buffer, and if you
join a small range with a large range (larger than the forward buffer),
then the seek issues to the end of the range after joining will overflow
the queue.

Normally, read_more will be false when the forward buffer is full, but
the resume seek after joining will set need_refresh to true, which
forces more reading and thus triggers the overfloe warning.

Attempt to fix this by not setting read_more to true on refresh seeks.
Set prefetch_more instead. read_more will still be set if an A/V stream
has no data.

This doesn't help with the following problems related to using refresh
seeks for track switching:

- If the forward buffer is full, then enabling another track will
  obviously immediately overflow the queue, and immediately lead to
  marking the new track as having no more data (i.e. EOF). We could cut
  down the forward buffer or so, but there's no simple way to implement
  it. Another possibility would be dropping all buffers and trying to
  resume again, but this would likely be complex as well.
- Subtitle tracks will not even show a warning (because they are sparse,
  and we have no way of telling whether a packet is missing, or there's
  just no packet near the current position). Before this commit,
  enabling an empty subtitle track would probably have overflown the
  queue, because ds->refreshing was never set to true. Possibly this
  could be solved by determining a demuxer read position, which would
  reflect until which PTS all subtitle packets should have been demuxed.

The forward buffer limit was intended as a last safeguard to avoid
excessive memory usage against badly interleaved files or decoders going
crazy (up to reading the whole into memory and OOM'ing the user's
system). It's not good at all to limit prefetch. Possibly solutions
include having another smaller limit for prefetch, or maybe having only
a total buffer limit, and discarding back buffer if more data has to be
read. The current solution is making the forward buffer larger than the
forward duration (--cache-secs) would require, but of course this
depends on the stream's bitrate.
2017-11-11 06:23:50 +01:00
wm4 8e50dc1b4d demux: export demuxer cache sizes in bytes
Plus sort of document them, together with the already existing
undocumented fields. (This is mostly for debugging, so use is
discouraged.)
2017-11-10 16:43:18 +01:00
wm4 1b0dc7d169 demux: use seekable cache for network by default, bump prefetch limit
The option for enabling it has now an "auto" choice, which is the
default, and which will enable it if the media is thought to be via
network or if the stream cache is enabled (same logic as --cache-secs).

Also bump the --cache-secs default from 10 to 120.
2017-11-10 16:30:43 +01:00
wm4 618b8a33e5 demux_mkv: fix potential uninitialized variable read 2017-11-10 12:49:53 +01:00
wm4 6bcdcaeeea demux: set default back buffer to some high value
Some back buffer is required to make the immediate forward range
seekable. This is because the back buffer limit is strictly enforced.
Just set a rather high back buffer by default. It's not use if
--demuxer-seekable-cache is disabled, so this is without risk.
2017-11-10 12:37:19 +01:00
wm4 b0de1ac36c demux: limit number of seek ranges to a static maximum
Limit the number of cached ranges to MAX_SEEK_RANGES, which is the same
number of maximally exported seek ranges. It makes no sense to keep
them, as the user won't see them anyway. Remove the smallest ones to
enforce the limit if the number grows too high.
2017-11-10 12:32:40 +01:00
wm4 c8bb78bad8 demux: speed up cache seeking with a coarse index
Helps a little bit, I guess. But in general, t(h)rashing the cache kills
us anyway.

This has a fixed number of index entries. Entries are added/removed as
packets go through the packet queue. Only keyframes after index_distance
seconds are added. If there are too many keyframe packets, the existing
index is reduced by half, and index_distance is doubled. This should
provide somewhat even spacing between the entries.
2017-11-10 12:17:34 +01:00
wm4 2485b899c3 demux: avoid wasting time by stopping packet search as early as possible
The packet queue is sorted, so we can stop the search if we have found a
packet, and the next packet in the queue has a higher PTS than the seek
PTS (for the sake of SEEK_FORWARD, we still consider the first packet
with a higher PTS).

Also, as a mostly cosmetic change, but which might be "faster", check
target for NULL, instead of target_diff for a magic float value.
2017-11-10 12:11:33 +01:00
wm4 968a24772e demux: simplify remove_packet() function
Turns out this is only ever used to remove the head element anyway.
2017-11-10 11:35:19 +01:00
wm4 65d36013dd demux: fix failure to join ranges with subtitles in some cases
Subtitle streams are sparse, and no overlap is required to correctly
join two cached ranges. This was not correctly handled iff the two
ranges had different subtitle packets close to the join point.
2017-11-10 11:06:07 +01:00
wm4 4681b4b28b demux: reverse which range is reused when joining them
Which one to use doesn't really matter, but reusing the first one will
probably be slightly more convenient later on.
2017-11-10 10:46:54 +01:00
wm4 f123cc4c9b demux: fix a race condition with async seeking
demux_add_packet() must completely ignore any packets that are added
while a queued seek is not initiated yet.

The main issue is that after setting in->seeking==true, the central lock
is released, and it can take "a while" until it's reacquired on the
demux thread and the seek is actually initiated. During that time,
packets could be read and added, that have nothing to do with the new
state.
2017-11-10 10:23:49 +01:00
wm4 d3bc93cf2e demux: get rid of an unnecessary field 2017-11-10 10:15:37 +01:00
wm4 4a6b04bdb9 vo_gpu: never pass flipped images to ra or ra backends
Seems like the last refactor to this code broke playing flipped images,
at least with --opengl-pbo --gpu-api=opengl.

Flipping is rather a shitmess. The main problem is that OpenGL does not
support flipped uploading. The original vo_gl implementation considered
it important to handle the flipped case efficiently, so instead of
uploading the image line by line backwards, it uploaded it flipped, and
then flipped it in the renderer (basically the upload path ignored the
flipping). The ra code and backends probably have an insane and
inconsistent mix of semantics, so fix this by never passing it flipped
images in the first place.

In the future, the backends should probably support flipped images
directly.

Fixes #5097.
2017-11-10 10:06:33 +01:00
wm4 ed1af99727 demux: attempt to accurately reflect seek range with muxed subtitles
If subtitles are part of the stream, determining the seekable range
becomes harder. Subtitles are sparse, and can have packets in irregular
intervals, or even completely lack packets. The usual logic of computing
the seek range by the min/max packet timestamps fails.

Solve this by making the only assumption we can make: subtitle packets
are implicitly demuxed along with other packets. We also assume perfect
interleaving for this, but you really can't do anything with sparse
packets that makes sense without this assumption.

One special case is if we prune sparse packets within the current
seekable range. Obviously this should limit the seekable range to after
the pruned packet.
2017-11-10 08:57:37 +01:00
wm4 7c1e7468e6 demux: reduce indentation for two functions
Remove the single-exit, that added a huge if statement containing
everything, just for some corner case.
2017-11-10 04:41:56 +01:00
wm4 6493ef2e34 demux: some minor mostly cosmetics
None of these change functionality in any way (although the log level
changes obviously change the terminal output).
2017-11-10 04:36:50 +01:00
wm4 a0b6f805f9 demux: simplify a function
update_stream_selection_state() doesn't need all these arguments. Not
sure what I was thinking here.
2017-11-10 04:08:15 +01:00
wm4 8c5ef33044 demux: change how refreshes on track switching are handled
Instead of weirdly deciding this on every packet read and having the
code far away from where it's actually needed, just run it where it's
actually needed.
2017-11-10 03:56:24 +01:00
wm4 25ed7ff0c8 demux: get rid of weird backwards loop
A typical idiom for calling functions that remove something from the
array being iterated, but it's not needed here. I have no idea why this
was ever done.
2017-11-10 03:26:40 +01:00
wm4 9c330b53e3 demux: avoid broken readahead when joining ranges
Setting ds->refreshing for unselected streams could lead to a
nonsensical queue overflow warning, because read_packet() took it as a
reason to continue reading.

Also add some more information to the queue overflow warning (even if
that one doesn't have anything to do with this bug - it was for
unselected streams only).
2017-11-10 03:19:25 +01:00
wm4 c494049e76 demux: reduce difference between threaded and non-threaded mode
This fixes an endless loop with threading disabled, such as for example
when playing a file with an external subtitle file, and seeking to the
beginning. Something will set in->seeking, but the seek is never
executed, which made demux_read_packet() loop endlessly. (External
subtitles will use non-threaded mode for whatever reasons.)

Fix this by by making the unthreaded code to execute the worker thread
body, which reduces the difference in logic.
2017-11-10 02:55:02 +01:00
wm4 935e406d63 demux: support multiple seekable cached ranges
Until now, the demuxer cache was limited to a single range. Extend this
to multiple range. Should be useful for slow network streams.

This commit changes a lot in the internal demuxer cache logic, so
there's a lot of room for bugs and regressions. The logic without
demuxer cache is mostly untouched, but also involved with the code
changes. Or in other words, this commit probably fucks up shit.

There are two things which makes multiple cached ranges rather hard:

1. the need to resume the demuxer at the end of a cached range when
   seeking to it
2. joining two adjacent ranges when the lowe range "grows" into it (and
   resuming the demuxer at the end of the new joined range)

"Resuming" the demuxer means that we perform a low level seek to the end
of a cached range, and properly append new packets to it, without adding
packets multiple times or creating holes due to missing packets.

Since audio and video never line up exactly, there is no clean "cut"
possible, at which you could resume the demuxer cleanly (for 1.) or
which you could use to detect that two ranges are perfectly adjacent
(for 2.). The way how the demuxer interleaves multiple streams is also
unpredictable. Typically you will have to expect that it randomly allows
one of the streams to be ahead by a bit, and so on.

To deal with this, we have heuristics in place to detect when one packet
equals or is "behind" a packet that was demuxed earlier. We reuse the
refresh seek logic (used to "reread" packets into the demuxer cache when
enabling a track), which checks for certain packet invariants.
Currently, it observes whether either the raw packet position, or the
packet DTS is strictly monotonically increasing. If none of them are
true, we discard old ranges when creating a new one.

This heavily depends on the file format and the demuxer behavior. For
example, not all file formats have DTS, and the packet position can be
unset due to libavformat not always setting it (e.g. when parsers are
used).

At the same time, we must deal with all the complicated state used to
track prefetching and seek ranges. In some complicated corner cases, we
just give up and discard other seek ranges, even if the previously
mentioned packet invariants are fulfilled.

To handle joining, we're being particularly dumb, and require a small
overlap to be confident that two ranges join perfectly. (This could be
done incrementally with as little overlap as 1 packet, but corner cases
would eat us: each stream needs to be joined separately, and the cache
pruning logic could remove overlapping packets for other streams again.)

Another restriction is that switching the cached range will always
trigger an asynchronous low level seek to resume demuxing at the new
range. Some users might find this annoying.

Dealing with interleaved subtitles is not fully handled yet. It will
clamp the seekable range to where subtitle packets are.
2017-11-09 10:23:57 +01:00
James Ross-Gowan bd4ec8e4e1 appveyor: update ffmpeg and test d3d11/vulkan
Build ffmpeg-mpv, shaderc and crossc from source, since they are not
packaged in MSYS2. Also, add some more explicit --enable flags to the
mpv build to make sure things like D3D11, D3D11VA hwaccels and Vulkan
are auto-detected.
2017-11-08 07:22:54 +11:00
James Ross-Gowan e7bf5576e5 vo_gpu: hwdec_d3d11va: allow zero-copy video decoding
Like the manual says, this is technically undefined behaviour. See:
https://msdn.microsoft.com/en-us/library/windows/desktop/ff476085.aspx

In particular, MSDN says texture arrays created with the BIND_DECODER
flag cannot be used with CreateShaderResourceView, which means they
can't be sampled through SRVs like normal Direct3D textures. However,
some programs (Google Chrome included) do this anyway for performance
and power-usage reasons, and it appears to work with most drivers.

Older AMD drivers had a "bug" with zero-copy decoding, but this appears
to have been fixed. See #3255, #3464 and http://crbug.com/623029.
2017-11-07 20:27:13 +11:00
James Ross-Gowan b258d82d6e vo_gpu: d3d11: enhance cache invalidation
The shader cache in ra_d3d11 caches the result of shaderc, crossc and
the D3DCompiler DLL, so it should be invalidated when any of those
components are updated. This should make the cache more reliable, which
makes it safer to enable gpu-shader-cache-dir. Shader compilation is
slow with D3D11, so gpu-shader-cache-dir is highly necessary
2017-11-07 20:27:13 +11:00
James Ross-Gowan b9c1286893 vo_gpu: d3d11: log shader compilation times
Some shaders take a _long_ time to compile with the Direct3D compiler.
The ANGLE backend had this problem too, to a certain extent. Logging
should help identify which shaders cause long stalls and could also help
with benchmarking ways of reducing compile times.
2017-11-07 20:27:13 +11:00
James Ross-Gowan 4b014b3a81 vo_gpu: move d3d11_screenshot to shared code
This can be used by the ANGLE backend and ra_d3d11.
2017-11-07 20:27:13 +11:00
James Ross-Gowan 9b2dae79b1 vo_gpu: d3d11: add RA caps for ra_d3d11
ra_d3d11 uses the SPIR-V compiler to translate GLSL to SPIR-V, which is
then translated to HLSL. This means it always exposes the same GLSL
version that the SPIR-V compiler supports (4.50 for shaderc/glslang.)

Despite claiming to support GLSL 4.50, some features that are tied to
the GLSL version in OpenGL are not supported by ra_d3d11 when targeting
legacy Direct3D feature levels.

This includes two features that mpv relies on:
- Reading from gl_FragCoord in the fragment shader (requires FL 10_0)
- textureGather from any texture component (requires FL 11_0)

These features have been exposed as new RA caps.
2017-11-07 20:27:13 +11:00
James Ross-Gowan 68eac1a1e7 vo_gpu: d3d11: initial implementation
This is a new RA/vo_gpu backend that uses Direct3D 11. The GLSL
generated by vo_gpu is cross-compiled to HLSL with SPIRV-Cross.

What works:

- All of mpv's internal shaders should work, including compute shaders.

- Some external shaders have been tested and work, including RAVU and
  adaptive-sharpen.

- Non-dumb mode works, even on very old hardware. Most features work at
  feature level 9_3 and all features work at feature level 10_0. Some
  features also work at feature level 9_1 and 9_2, but without high-bit-
  depth FBOs, it's not very useful. (Hardware this old is probably not
  fast enough for advanced features anyway.)

  Note: This is more compatible than ANGLE, which requires 9_3 to work
  at all (GLES 2.0,) and 10_1 for non-dumb-mode (GLES 3.0.)

- Hardware decoding with D3D11VA, including decoding of 10-bit formats
  without truncation to 8-bit.

What doesn't work / can be improved:

- PBO upload and direct rendering does not work yet. Direct rendering
  requires persistent-mapped PBOs because the decoder needs to be able
  to read data from images that have already been decoded and uploaded.
  Unfortunately, it seems like persistent-mapped PBOs are fundamentally
  incompatible with D3D11, which requires all resources to use driver-
  managed memory and requires memory to be unmapped (and hence pointers
  to be invalidated) when a resource is used in a draw or copy
  operation.

  However it might be possible to use D3D11's limited multithreading
  capabilities to emulate some features of PBOs, like asynchronous
  texture uploading.

- The blit() and clear() operations don't have equivalents in the D3D11
  API that handle all cases, so in most cases, they have to be emulated
  with a shader. This is currently done inside ra_d3d11, but ideally it
  would be done in generic code, so it can take advantage of mpv's
  shader generation utilities.

- SPIRV-Cross is used through a NIH C-compatible wrapper library, since
  it does not expose a C interface itself.

  The library is available here: https://github.com/rossy/crossc

- The D3D11 context could be made to support more modern DXGI features
  in future. For example, it should be possible to add support for
  high-bit-depth and HDR output with DXGI 1.5/1.6.
2017-11-07 20:27:13 +11:00
James Ross-Gowan 8020a62953 vo_gpu: export the GLSL format qualifier for ra_format
Backported from @haasn's change to libplacebo, except in the current RA,
there's nothing to indicate an ra_format can be bound as a storage
image, so there's no way to force all of these formats to have a
glsl_format. Instead, the layout qualifier will be removed if
glsl_format is NULL.

This is needed for the upcoming ra_d3d11 backend. In Direct3D 11, while
loading float values from unorm images often works as expected, it's
technically undefined behaviour, and in Windows 10, it will cause the
debug layer to spam the log with error messages. Also, apparently in
GLSL, the format name must match the image's format exactly (but in
Direct3D, it just has to have the same component type.)
2017-11-07 20:27:13 +11:00
James Ross-Gowan 41dff03f8d vo_gpu: add namespace query mechanism
Backported from @haasn's change to libplacebo. More flexible than the
previous "shared || non-shared" distinction. The extra flexibility is
needed for Direct3D 11, but it also doesn't hurt code-wise.
2017-11-07 20:27:13 +11:00
wm4 793b43020c vo_lavc: remove messy delayed subtitle rendering logic
For some reason vo_lavc's draw_image can buffer the frame and encode it
only later. Also, there is logic for rendering the OSD (i.e. subtitles)
only when needed.

In theory this can lead to subtitles being pruned before it tries to
render them (as the subtitle logic doesn't know that the VO still needs
them later), although this probably never happens in reality.

The worse issue, that actually happened, is that if the last frame gets
buffered, it attempts to render subtitles in the uninit callback. At
this point, the subtitle decoder is already torn down and all subtitles
removed, thus it will draw nothing. This didn't always happen. I'm not
sure why - potentially in the working cases, the frame wasn't buffered.

Since this logic doesn't have much worth, except a minor performance
advantage if frames with subtitles are dropped, just remove it.

Hopefully fixes #4689.
2017-11-07 05:29:26 +01:00
wm4 a2a623ebb9 player: change license of some code surrounding --frames to LGPL
The original author of the patch has agreed now.
2017-11-06 20:53:27 +01:00
wm4 921073bf86 img_format: remove some guards against old ffmpeg API
These are always present in ffmpeg-mpv, and never in Libav.
2017-11-06 17:14:01 +01:00
wm4 4ef0887f7b demux: explicitly discard 0 sized packets
libavcodec can't deal with them, because its API doesn't distinguish
between 0 sized packets and sending EOF. As such, keeping them doesn't
do any good, ever. This actually fixes some obscure mkv sample (see
previous commit).
2017-11-06 17:13:42 +01:00
wm4 e598b19dad demux_mkv: allow 0 sized packets
Fixes some obscure sample that uses fixed size laces with 0-sized lace
size. Some broken shit. (Maybe the decoder wouldn't care about these
packets, but the demuxer attempted to resync after these packet reading
errors, even though they were perfectly recoverable. But I don't care
enough about this.)

Sample link: https://samples.ffmpeg.org/Matroska/switzler084d_dl.mkv
2017-11-06 17:12:58 +01:00
wm4 7334d93b30 demux: slightly simplify pruning
We can compute the overhead size easily now - no need for awkward
incremental updates to cached values on top of it.
2017-11-06 17:11:31 +01:00
wm4 9e1fbffc37 demux_mkv: rewrite packet reading to avoid 1 memcpy()
This directly reads individual mkv sub-packets (block laces) into a
dedicated AVBufferRefs, which can be directly used for creating packets
without a additional copy of the packet data. This also means we switch
parsing of block header fields and lacing metadata to read directly from
the stream, instead of a memory buffer.

This could have been much easier if libavcodec didn't require padding
the packet data with zero bytes. We could just have each packet
reference a slice of the block data. But as it is, the only way to get
padding without a copy is to read the laces into individually allocated
(and padded) memory block, which required a larger rewrite.

This probably makes recovering from broken mkv files slightly worse if
the transport is unseekable. We just read, and then check if we've
overread. But I think that shouldn't be a real concern.

No actual measureable performance change. Potential for some
regressions, as this is quite intrusive, and touches weird obscure shit
like mkv lacing. Still keeping it because I like how it removes some
redundant EBML parsing functions.
2017-11-05 18:13:34 +01:00
wm4 8aa1db3b17 demux: refactoring in preparation for multiple seek range support
This adds a bunch of stuff (mostly unused or redundant) as preparation
for supporting multiple seek ranges. Actual support is probably still
far away.

One change that messes deeper with the actual code is that we account
for total buffered bytes instead of just the backwards bytes now. This
way, prune_old_packets() doesn't have to iterate over all seek ranges to
determine whether something needs pruning.
2017-11-04 23:45:21 +01:00
wm4 10d0963d85 demux: improve and optimize cache pruning and seek range determination
The main purpose of this commit is avoiding any hidden O(n^2) algorithms
in the code for pruning the demuxer cache, and for determining the
seekable boundaries of the cache. The old code could loop over the whole
packet queue on every packet pruned in certain corner cases.

There are two ways how to reach the goal:
 1) commit a cardinal sin
 2) do everything incrementally

The cardinal sin is adding an extra field to demux_packet, which caches
the determined seekable range for a keyframe range. demux_packet is a
rather general data structure and thus shouldn't have any fields that
are not inherent to its use, and are only needed as an implementation
detail of code using it. But what are you gonna do, sue me?

In the future, demux.c might have its own packet struct though. Then the
other existing cardinal sin (the "next" field, from MPlayer times) could
be removed as well.

This commit also changes slightly how the seek end is determined. There
is a note on the manpage in case anyone finds the new behavior
confusing. It's somewhat cleaner and  might be needed for supporting
multiple ranges (although that's unclear).
2017-11-04 23:18:42 +01:00
wm4 6e998be7be demux: reduce overhead when searching over keyframe ranges
The demuxer cache seeking mechanism looks at keyframe ranges to
determine the earlierst PTS of a packet. Instead of looping over all
packets twice (once to find the next keyframe, a second time to find the
seek PTS), do it in one go.

For that basically turn recompute_keyframe_target_pts() into an
iteration functionn. Functionality should be unchanged with this commit.
2017-11-04 18:18:42 +01:00
wm4 75cdd13e29 player: log if NDEBUG is defined
I sure want to know whether assert()s were unexpectedly not compiled in.
2017-11-04 17:48:30 +01:00
wm4 104e18214c demux: avoid excessive readahead after cache seek
The base_ts field is used to guess the decoder position, and when set to
NOPTS, it just read ahead arbitrarily. Also demux_add_packet() sets
base_ts to the new timestamp when appending a packet, which would also
make it readahead by a too large amount.

Fix this by setting base_ts after a seek. This assumes that normally, a
cached seek target will always have the timestamp set. This is actually
not quite clear (as it calls recompute_keyframe_target_pts(), which
looks at multiple packets), but maybe it works well enough.
2017-11-04 17:43:22 +01:00
wm4 c1f981f863 demux: make pruning more efficient for unseekable demuxer cache
Don't do any of the extra work related to pruning the backbuffer if
demuxer cache seeking is disabled.

As a small extra, always prune packets with no timestamps immediately,
or queue heads that are not keyframes. (Both of them would be pruned
from the backbuffer by the normal logic anyway.)
2017-11-04 17:32:34 +01:00
wm4 d46c9c2e62 demux: on queue overflow wake up reader thread on EOF only
This seems to make more sense.
2017-11-03 16:36:59 +01:00
wm4 49ae599883 demux: don't show queue overflow warning when merely prefetching
If fulfilling --demuxer-readahead-secs requires more memory than allowed
by --demuxer-max-bytes, the queue obviously overflows. But the warning
is normally only for the case when trying to find the next video or
audio packet fails, and decoding can't continue.

Use a separate variable for determining whether to prefetch, and if the
queue has overflown, skip the message. In fact, skip the EOF setting and
waking up the decoder thread as well, because the EOF flag should not be
(have been) set in this situation, and waking up the reader thread helps
only if the EOF state changed.
2017-11-03 16:36:21 +01:00
wm4 5261d1b099 vo_gpu: don't re-render hwdec frames when repeating frames
Repeating frames (for display-sync) is not supposed to render the entire
frame again. When using hardware decoding, it unfortunately did: the
renderer uses the frame ID to check whether the frame data changed, and
unmapping the hwdec frame clears it.

Essentially reverts commit 761eeacf54. Back then I probably
thought it would be a good idea to release the hwdec image quickly in
order to return it to the decoder, but they're referenced anyway.

This should increase the performance and reduce GPU work.
2017-11-03 15:11:56 +01:00
wm4 4fca1856e1 demux: don't allow subtitles to mess up buffered time display
In a shit show of subtle corner case interactions, making the demuxer
cache buffer the entire file can display a small buffered time if
subtitles are enabled. The reason is that some subtitle decoders may
read in advance infinitely, i.e. they read the entire subtitle stream.
Then, since the other streams (audio/video) have logically reached EOF,
and the subtitle stream is set to ds->active==true. This will have to be
fixed properly later to account buffering for subtitle-only files
(another corner case) correctly, but for now this is less annoying.
2017-11-03 14:58:13 +01:00
wm4 36630585f6 osc: make cycling visibility an input.conf key binding
As builtin script, it should not register global key bindings, and add
them to input.conf instead. This is similar to what stats.lua does.
2017-11-03 14:41:18 +01:00
wm4 57248915fa demux: add option to create CC tracks eagerly
We don't hope to auto-detect them at load time, as that would be too
much of a pain - even FFmpeg requires fetching and parsing of video
packets, and exposes the information only via deprecated API.

But there still needs to be a way to select them by default. This is
also needed to get the first CC packet at all (without seeking back).

This commit also attempts to clean up locking a bit, which is a PITA,
but it's better be careful & clean.
2017-11-03 13:55:32 +01:00
wm4 99dd2f57f0 vo_gpu: ra_gl: fix minimum GLSL version to 120
Not sure why there was 110, or why there is even a default.
2017-11-03 11:53:31 +01:00
wm4 2abf20b2b2 vo_gpu: fix mobius tone mapping compatibility to GLSL 120
Normally such code is didsabled by have_mglsl==false in
check_gl_features(), but apparently not this one.

Just fix it. Seems also more readable.

Fixes #5069.
2017-11-03 11:53:17 +01:00
wm4 aac74b7c36 vo_gpu: ra_gl: fix crash trying to use glBindBufferBase on GL 2.1
Apparently this is required, but it doesn't check for it. To be fair,
this was tested by creating a compatibility context and pretending it's
GL 2.1. GL_ARB_shader_storage_buffer_object actually requires GL 4.0 or
up, but GL_ARB_uniform_buffer_object requires only GL 2.0.
2017-11-03 11:39:15 +01:00
Martin Herkt b86fb0f3e9 wscript: use pkg-config for vulkan check 2017-11-03 09:26:32 +01:00
Nicolas F e6a68e2330 demux_mkv: add V_SNOW tag to mkv_video_tags
Apparently, and to nobody's surprise, mkv can contain snow. It does
so with the V_SNOW tag. We can now play back snow-inside-mkv in mpv.
2017-11-03 01:03:39 +01:00
ChrisK2 89513d26a2 osc: render seek ranges a bit less ugly 2017-11-02 22:00:12 +01:00
wm4 1d9057cb9a osc: render seek ranges
Pretty fucking ugly, but I'm not a UI designer.

Of course only does something with --demuxer-seekable-cache.
2017-11-02 20:03:53 +01:00
wm4 1199c1e38a stream_libarchive: stop reading on ARCHIVE_FATAL
According to

https://github.com/libarchive/libarchive/pull/773#issuecomment-334892291

we're not allowed to "continue reading" (post above) or performing "more
operations" (comments in archive.h header), whatever that means. Assume
closing and freeing the archive is still ok.

Since the codec already includes logic for closing and reopening the
archive for seeking in unseekable archives, this probably isn't too bad.

Untested due to lack of crashing sample (I lost my original test case,
and as recently user-provided one didn't crash).
2017-11-02 18:47:05 +01:00
Nicolas F 49e925f830 screenshot: create directories from template
screenshot-template could be set to e.g. "%F/%04n", so we want to
make sure that the path generated from the template actually exists.
2017-11-02 17:07:35 +01:00
wm4 f099f504af osd: don't skip leading whitespace on the first line either
Stupid libass.
2017-11-02 16:46:09 +01:00
wm4 ff17760c00 vd_lavc: restore --hwdec-image-format and d3d11 opaque mode
When the ifdeffery for the frame_params API was added, the new code
accidentally didn't include this.
2017-11-02 15:58:36 +01:00
wm4 09c61347a8 build: fix cuda test 2017-11-02 00:51:54 +01:00
wm4 27ab99dc3e build: garbage => upstream
"garbage" is considered offensive. The result will still be pretty bad
though (currently build failures).
2017-11-01 18:19:06 +01:00
wm4 a7a1ae0b3d build: make it easier to force FFmpeg upstream
Apparently some people want this. Actually making it compile is still
their problem, though, and I expect that build with FFmpeg upstream will
occasionally be broken (as it is right now). This is because mpv also
relies on API provided by Libav, and if FFmpeg hasn't merged that yet,
it's not our problem - we provide a version of FFmpeg upstream with
those changes merged, and it's called ffmpeg-mpv.

Also adjust the README which still talked about FFmpeg releases.
2017-11-01 16:50:18 +01:00
wm4 501230f2a0 vo_gpu: potentially fix icc-profile-auto updating
vo_gpu.c will call gl_video_icc_auto_enabled() to check whether it
should retrieve the ICC profile. But the value returned by this function
will be outdated, because gl_video_update_options() is not called yet.
Change the order of function calls so that this is done after updating
the options.

(This is fairly chaotic, but I guess this code will be refactored a
dozen of times anyway in the future.)
2017-11-01 01:58:16 +01:00
wm4 95c6a482eb vd_lavc: clean out more hwdec legacy code
All this code used to be required by the old variants of the libavcodec
hw decoding APIs. Almost all of that is gone, although the mediacodec
API unfortunately still pulls in some old stuff (but not all of it).

(mediacodec build/functionality is untested, but should work.)
2017-10-31 17:11:52 +01:00
wm4 f27a9aaa17 vd_lavc: remove more dead legacy code
All of this was dead code and completely unused.

get_buffer2_hwdec() is the biggest chunk. One unfortunate thing about it
is that, while it was active, it could perform a software fallback much
faster, because it didn't have to wait until a full frame is decoded (it
actually decoded a full frame, but the current code has to decode many
more frames due to the codec delay, because the current code waits until
the API returns a decoded frame.) We should probably restore the latter,
although since it's an optional optimization, and the current behavior
doesn't change with the removal of this code, don't actually do anything
about it.
2017-10-31 15:29:13 +01:00
wm4 7fd1359fcf videotoolbox: use generic code for dummy hwdevice init
And move the remaining code (just 2 struct constant definitions) to
vd_lavc.c.
2017-10-31 15:20:09 +01:00
wm4 e0f42bdc5d vd_lavc: remove dead legacy code 2017-10-31 14:18:35 +01:00
wm4 078a3ed996 d3d: remove some legacy code
See #5062.
2017-10-31 14:14:45 +01:00
wm4 ff093e5b78 vd_lavc: makre sure required headers are included early enough
Should fix #5062.
2017-10-31 14:12:11 +01:00
wm4 0b8b64fba3 osd: don't strip leading whitespace in messages
Do this by replacing the first space after a line break with "\h".
2017-10-30 21:15:09 +01:00
wm4 a18a7cd4f5 vd_lavc: move display mastering data stuff to mp_image
This is where it should be. It only wasn't because of an old libavcodec
bug, that returned the side data only on every IDR. This required some
sort of caching, which is now dropped. (mp_image wouldn't have been able
to do this kind of caching, because this code is stateless.) We don't
support these old libavcodec versions anymore, which is why this is not
needed anymore.

Also move initialization of rotation/stereo stuff to dec_video.c.
2017-10-30 21:07:48 +01:00
wm4 a7f4ecb012 Bump libav* API use
(Not tested on Windows and OSX.)
2017-10-30 20:55:42 +01:00
wm4 1c46bd5e50 vo_gpu: remove a redundant ifdef 2017-10-30 18:35:33 +01:00
wm4 58d83a9309 vd_lavc: make --hwdec=nvdec-copy actually work
This simply didn't work. Unlike cuda-copy, this is a true hwaccel, and
obviously we need to provide it a device.

Implement this in a relatively generic way, which can probably reused
directly by videotoolbox (not doing this yet because it would require
testing on OSX).

Like with cuda-copy, --cuda-decode-device is ignored. We might be able
to provide a more general way to select devices at some later point.
2017-10-30 18:34:49 +01:00
wm4 b7ce3ac445 vd_lavc: remove need for duplicated cuda GL interop backend
This is just a dumb consequence of HWDEC_ types somehow being part of
both decoder and VO. Obviously, the VO should only care about supporting
specific hardware surface types or providing specific device types, but
until they are separated, stupid unintuitive mismatches will occur.
2017-10-30 18:31:20 +01:00
wm4 694157e024 m_option: pretty print mpv_node for OSD
Somewhat useful for debugging. Unfortunately libass (or something else)
strips leading whitespace, making it look slightly more ugly than
necessary. Still an improvement.
2017-10-30 15:32:24 +01:00
wm4 2d958dbf2b demux: refactor to export seek ranges
Even though only 1 seek range is supported at the time.

Other than preparation for possibly future features, the main gain is
actually that we finally separate the reporting for the buffering, and
the seek ranges. These can be subtly different, so it's good to have a
clear separation.

This commit also fixes that the ts_reader wasn't rebased to the start
time, which could make the player show "???" for buffered cache amount
in some .ts files and others (especially at the end, when ts_reader
could become higher than ts_max). It also fixes writing the cache-end
field in the demuxer-cache-state property: it checked ts_start against
NOPTS, which makes no sense.

ts_start was never used (except for the bug mentioned above), so get rid
of it completely. This also makes it convenient to move the segment
check for last_ts to the demux_add_packet() function.
2017-10-30 15:28:59 +01:00
wm4 d6ebb2df47 Get rid of deprecated AVFrame accessors
Fist we were required to use them for ABI compat. reasons (and other
BS), now they're deprecated and we're supposed to access them directly
again.
2017-10-30 13:36:44 +01:00
wm4 4f51326c28 manpage: fix/improve --msg-level description
Fixes #5055.
2017-10-30 12:58:55 +01:00
Ryo Munakata 046fe45950 hwdec_drmprime_drm: fix segv with --hwdec 2017-10-30 12:46:49 +01:00
Oleg Oshmyan 98986948e8 lavc_conv: make disable_styles faster
The current invocation of bstr_cut is as good as no cutting at all.
Almost the entire header is reread in every iteration of the loop.
I don't know how many styles libavcodec tends to generate, but if
(now or in the future) it generates many, then this loop is slow
for no good reason. If anything, the code would be more clear and
have the same performance if it didn't call bstr_cut at all.

The intention here (and the sensible thing regardless) seems to be
to skip the part of the string that bstr_find has already looked
through and found nothing. This commit additionally skips the whole
substring, because overlapping matches are impossible.
2017-10-30 12:44:11 +01:00
Daniel Kucera e9dc4ac86f demux_lavf: return AVERROR_EOF on file end
Signed-off-by: Daniel Kucera <daniel.kucera@gmail.com>
Signed-off-by: wm4 <wm4@nowhere>

Uses different style and different logic from original PR.
2017-10-30 12:42:00 +01:00
wm4 6b745769b1 vd_lavc: add support for nvdec hwaccel
See manpage additions.

(In ffmpeg-mpv and Libav, this is still called "cuvid". Libav won't work
yet, because it has no frame params support yet, but this could get
fixed soon.)
2017-10-28 19:59:08 +02:00
wm4 3413fe4dfd demux_mkv: don't probe start time by default
It isn't all that reliable, and improving it would make startup slower
and require more complexity. There isn't even a good reason to do this
(other than semi-broken mkv files), so don't do it. Also see previous
commit.
2017-10-27 18:41:47 +02:00
wm4 c23c9e22ae lavc_conv: clamp timestamps to positive, fixes idiotic ffmpeg issue
In some cases, demux_mkv will detect a start time slightly above 0, but
there might still be a subtitle starting at exactly 0. When the player
rebases the timestamps to assumed start time, the subtitle will have a
slightly negative timestamp in the end. libavcodec's subtitle converter
turns this into a larger number due to underflow. Fix by clamping
subtitles always to 0, which may or may not be what you want.

At least it fixes #5047.
2017-10-27 18:40:33 +02:00
wm4 3c21694ff0 travis: correctly remove ffmpeg-stable from build matrix 2017-10-27 18:23:39 +02:00
wm4 47dca74f03 travis: adjust ffmpeg URL
No idea if this is correct.
2017-10-27 18:13:02 +02:00
wm4 4d47805a76 lavfi: fix warnings with newer libavfilter versions
Most likely will cause new warnings with avfilter_graph_alloc_filter()
on old libavfilter versions. Ingore that part.
2017-10-27 18:09:08 +02:00
wm4 83d44aca7d build: require our own ffmpeg repo
This is required now. Can't have FFmpeg upstream randomly break us and
then not fix it (like this recent EOF issue).

Upstream FFmpeg is of course still supported, but you will need to edit
the build scripts. Official support is only with the master branch of
our own repo.
2017-10-27 18:08:40 +02:00
wm4 f36d152eb7 vd_lavc: use avcodec_fill_hw_frames_parameters() API
This removes the need for codec- and API-specific knowledge in the
libavcodec hardware acceleration API user. For mpv, this removes the
need for vd_lavc_hwdec.pixfmt_map and a few other things. (For now, we
still keep the "old" parts for the sake of supporting older Libav, and
FFgarbage.)
2017-10-27 18:08:20 +02:00
Niklas Haas 4701c5ba4f vo_gpu: fix ra_tex_upload_pbo for 2D textures
params->rc was ignored in the calculation for the buffer size. I fucking
hate this stupid ra_tex_upload signature where *rc is randomly relevant
or not.
2017-10-27 16:56:23 +02:00
wm4 d6f33e0b0d vo_gpu: osd: simplify some code
Coverity complains about this, but it's probably a false positive.
Anyway, rewrite it in a slightly more readable way. Now it's more
obvious that it is correct.
2017-10-27 14:19:57 +02:00
wm4 6a9f457102 audio/out: initialize an array to avoid confusing static analyzer
I _think_ this confuses Coverity and it thinks there is uninitialized
data to be read. Initialize the array to change/remove the warning, or
if there's a real problem, to make it easier to detect. (Basically apply
defensive coding.)
2017-10-27 14:11:33 +02:00
wm4 c54673b86f af_lavfi: fix small memory leak
Plus restructure the error path to make this simpler.
2017-10-27 13:54:40 +02:00
wm4 41beaa653a audio: fix small memory leak
Most commonly happened with --end, in which case that field tends to be
set.
2017-10-27 13:54:08 +02:00
wm4 f08ec22567 command: change demuxer-cache-state property to return multiple ranges
Even if the demuxer cache does not multiple ranges yet. This is to
reduce the pain should caching of multiple ranges ever be implemented.

Also change it from the sub properties stuff to return a mpv_node
directly, which is less roundabout. Sub-property access won't work
anymore, though.

Remove the seekable-start/-end fields as well, as they're redundant with
the ranges.

All this would normally be considered an API change, but since it's been
only a few days with no known users, change it immediately.

This adds some node.c helpers as well, as the code would be too damn
fugly otherwise.
2017-10-26 22:31:04 +02:00
wm4 22fa498bf9 vd_lavc: more aggressive frame dropping for intra only codecs
Should speed up seeks.

(Unfortunately it's useless for backstepping. Backstepping is like
precise seeking, except we're unable to drop frames, as we can't know
the previous frame if we drop it.)
2017-10-26 19:44:26 +02:00
wm4 ae8b531207 demux_timeline: don't use segments for DASH
Recent regression. Crashes because it sets the segmented flag, without
actually setting the fields required for segmentation.
2017-10-26 00:38:20 +02:00
Niklas Haas c2d4fd0ef4 vo_gpu: change --tone-mapping-desaturate algorithm
Comparing mpv's implementation against the ACES ODR reference samples
and algorithms, it seems like they're happy desaturating highlights
_way_ more aggressively than mpv currently does. And indeed, looking at
some example clips like The Redwoods (which is actually well-mastered),
the current desaturation produces unnatural-looking brightness fringes
where the sky meets the treeline.

Adjust the algorithm to make it apply to a much larger, more gradual
brightness region; and change the interpretation of the parameter. As a
bonus, the new parameter is actually sanely scaled (higher values = more
desaturation). Also, make it scale based on the signal level instead of
the luminance, to avoid under-desaturating bright blues.
2017-10-25 17:24:27 +02:00
wm4 ec8cad40f2 demux: better computation of seek start target
Avoids that cache seeking is not possible with files that have audio
frames with no timestamps (such as avi, sometimes mkv sub-packets from
lacing). These would set back_pts (first seekable PTS) to NOPTS, and
thus disable cache seeking completely. Instead, prune such packets until
we find one with timestamps.

One corner case is that the new next good packet might be in the forward
cache. In this case we defer dropping until the next time this code is
run, and the reader position has possibly moved past the drop point.
2017-10-25 16:39:33 +02:00
wm4 d235380cd3 demux: reject cache seeks if parts of the range are unset
In theory, start/ts_min could be set to NOPTS, in which case
"pts < start" for a valid pts would always evaluate to false.

Also remove the redundant "in-cache seek is possible.." message, as
there's always another message when cache seeks are done.
2017-10-25 16:39:33 +02:00
wm4 03a0e8336a demux: fall back to DTS when determining seek target
Fixes AVI in particular, which abuses DTS for reordered PTS. (It's not
really DTS...)
2017-10-25 16:39:33 +02:00
wm4 e6348504b3 demux: disallow seeking if there are streams with no timestamps
The seek range computation ignored streams with no timestamps. For
things like buffer estimation this is OK and wanted, but the seek range
needs to be conservative.
2017-10-25 16:39:33 +02:00
wm4 3d71651523 demux: fix tracking of forward/backward cache size
Which parts of the queue are considered forward or backward cache
depends on ds->reader_header. The packet at ds->reader_head, as well as
all packets following it (via the ->next field) are considered forward.
The fw_packs/fw_bytes/bw_bytes must be updated accordingly.

This broke in demux_add_packet(), when ds->reader_head was _not_ set on
the first packet (or before). This could happen since commit
05ae571241, which can require skipping packets (so they immediately end
up in the backbuffer).
2017-10-25 16:39:33 +02:00
wm4 56d9dafbbb demux: respect timeline boundaries for cache seeks
With the timeline code, a packet at the start or end of a segment can
refer to an invisible frame. So it doesn't extend the seek range, and
the timestamp should be clipped to the actual segment range.

Also restructure recompute_keyframe_target_pts() to be hopefully less
confusing.
2017-10-25 16:39:33 +02:00
wm4 8bf399e02e demux: don't report unknown queue state if no packets were added
Restores some behavior from before the demuxer cache changes, though
affects mostly just OSD display. The unknown queue state is reserved for
streams with missing or messed up timestamps.
2017-10-25 16:39:33 +02:00
wm4 374e3bd83c demux_timeline: trust attached picture flag
Fully fixes behavior of the files mentioned in the previous commit. Will
probably lead to worse behavior if someone tries to fix real video and
cover art tracks, but that's a broken fringe case anyway.
2017-10-25 16:39:33 +02:00
wm4 3d32cb1649 demux: set correct stream index for attached pictures
This fixes .cue files with audio files that contain attached pictures to
some degree. demux_timeline.c just discarded packets with unset index,
so the picture was never fed to the decoder.
2017-10-25 16:39:33 +02:00
James Ross-Gowan 257a2b9646 win32: add more-POSIXy versions of open() and fstat()
Directory-opening never worked on Windows because MSVCRT's open()
doesn't open directories and its fstat() doesn't recognise directory
handles. These are just MSVCRT restrictions, and the Windows API itself
has no problem with opening directories as file objects, so reimplement
mpv's mp_open and mp_stat to use the Windows API directly. This should
fix directory playback.

This also populates the st_dev and st_ino fields of struct stat, so
filesystem loop checking in demux_playlist.c should now work on Windows.

Fixes #4711
2017-10-25 22:37:20 +11:00
wm4 a5b51f75dc demux: get rid of demux_packet.new_segment field
The new_segment field was used to track the decoder data flow handler of
timeline boundaries, which are used for ordered chapters etc. (anything
that sets demuxer_desc.load_timeline). This broke seeking with the
demuxer cache enabled. The demuxer is expected to set the new_segment
field after every seek or segment boundary switch, so the cached packets
basically contained incorrect values for this, and the decoders were not
initialized correctly.

Fix this by getting rid of the flag completely. Let the decoders instead
compare the segment information by content, which is hopefully enough.
(In theory, two segments with same information could perhaps appear in
broken-ish corner cases, or in an attempt to simulate looping, and such.
I preferred the simple solution over others, such as generating unique
and stable segment IDs.)

We still add a "segmented" field to make it explicit whether segments
are used, instead of doing something silly like testing arbitrary other
segment fields for validity.

Cached seeking with timeline stuff is still slightly broken even with
this commit: the seek logic is not aware of the overlap that segments
can have, and the timestamp clamping that needs to be performed in
theory to account for the fact that a packet might contain a frame that
is always clipped off by segment handling. This can be fixed later.
2017-10-24 19:35:55 +02:00
wm4 bb9679d9a3 demux_timeline: change virtual_stream array to array of pointers
Needed for a failed thing, leaving it anyway because it causes no harm
and might be less awkward if struct virtual_stream is possibly extended
anyway in the future.
2017-10-24 19:24:20 +02:00
wm4 4593002222 manpage: add --hwdec=rkmpp entry 2017-10-23 21:12:45 +02:00
wm4 2c00687641 client API: minor bump + change entry for DRM related opengl-cb changes
Commit cfcee4cfe7 forgot those.
2017-10-23 21:11:44 +02:00
Lionel CHAZALLON 1992bb5151 video : Move drm options to substruct.
This allows to group them and most of all query the group config when
needed and when we don't have the access to vo.
2017-10-23 21:08:20 +02:00
Lionel CHAZALLON cfcee4cfe7 Add DRM_PRIME Format Handling and Display for RockChip MPP decoders
This commit allows to use the AV_PIX_FMT_DRM_PRIME newly introduced
format in ffmpeg that allows decoders to provide an AVDRMFrameDescriptor
struct.

That struct holds dmabuf fds and information allowing zerocopy rendering
using KMS / DRM Atomic.

This has been tested on RockChip ROCK64 device.
2017-10-23 21:07:24 +02:00
Lionel CHAZALLON 762b8cc300 video : allow drm primary plane to be transparent for egl context
We want primary plane to be one top of overlay (video), so we need it to
be 32 bits.
2017-10-23 21:06:53 +02:00
wm4 05ae571241 demux: fix cached SEEK_FORWARD seeks into end of cached regions/EOF
Although seeking past the cached range will trigger a low level seek, a
seek into the region between cache end and last video key frame would
simply seek to the video key frame. This meant that you could get
"stuck" at the end of the file instead of terminating playback when
trying to seek past the end.

One change is that we fix this by _actually_ allowing SEEK_FORWARD to
seek past the last video keyframe in find_seek_target().

In that case, or otherwise seeking to cache buffer end, it could happen
that we set ds->reader_head=NULL if the seek target is after the current
packet. We allow this, because the end of the cached region is defined
by the existence of "any" packet, not necessarily a key frame. Seeking
there still makes sense, because we know that there is going to be more
packets (or EOF) that satisfy the seek target.

The problem is that just resuming demuxing with reader_head==NULL will
simply return any packets that come its way, even non-keyframe ones.
Some decoders will produce ugly soup in this case. (In practice, this
was not a problem, because seeking at the end of the cached region was
rare before this commit, and also some decoders like h264 will skip
broken frames by default anyway.)

So the other change of this commit is to enable key frame skipping.

As a nasty implementation detail, we use a separate flag, instead of
setting reader_head to the first key frame encounted (reader_head being
NULL can happen after a normal seek or on playback start, and then we
want to mirror the underlying demuxer behavior, for better or worse).

This change is relatively untested, so you get to keep the pieces for
yourself.
2017-10-23 20:55:11 +02:00
wm4 512509705e demux: report buffered duration of 0 during seeking instead of unknown
Looks ugly on the status line and could upset the buffering logic.
2017-10-23 19:36:20 +02:00
wm4 dbd22f43be demux: drop redundant SEEK_BACKWARD flag
Seems like most code dealing with this was for setting it in redundant
cases. Now SEEK_BACKWARD is redundant, and SEEK_FORWARD is the odd one
out.

Also fix that SEEK_FORWARD was not correctly unset in try_seek_cache().

In demux_mkv_seek(), make the arbitrary decision that a video stream is
not required for the subtitle prefetch logic to be active. We might want
subtitles with long duration even with audio only playback, or if the
file is used as external subtitle.
2017-10-23 19:05:39 +02:00
Mark Thompson 26b46950a1 vo_opengl: hwdec_vaegl: Disable vaExportSurfaceHandle()
libva 2.0 (VAAPI 1.0.0) was released without it, but it is scheduled to
be included in libva 2.1.
2017-10-23 11:58:13 +02:00
wm4 34676fc94d demux: fix crash with cue/ordered chapter files
If a packet uses segmentation, the codec field must be set. Copying the
codec field was forgotten as an oversight, which is why this just
crashes. This showed up only now, because demux_copy_packet() was not
used before in the main demux path until recently.

Fixes #5027.
2017-10-23 11:31:45 +02:00
Nicolas F 0358cca39e video: fix typo in log message 2017-10-22 16:51:09 +11:00
Rostislav Pehlivanov f8aeda0da9 wayland_common: check monitor scale
Since we divide by it in a couple of places and compositors can be crazy,
its better to be safe than sorry.
Also checks cursor spawn durinig init (pointless since it does again on
cursor entry but its more correct).
2017-10-22 06:49:35 +01:00
Rostislav Pehlivanov 78ef7fb766 wayland_common: improve cursor code and scale cursor properly
It seems the cursor hadn't had its position properly adjusted when scaled.
Hence, bring back correct buffer scaling to make the cursor look fine.
Also the cursor surface now gets created sooner so that's better.
2017-10-22 05:53:20 +01:00
wm4 60df01512c command: read the diff if you want to know 2017-10-21 21:13:53 +02:00
wm4 633077814e *** empty log message *** 2017-10-21 20:42:40 +02:00
wm4 0004af3e71 demux: replace redundant field with a better redundant field 2017-10-21 20:36:06 +02:00
wm4 719a435d36 demux: add a back buffer and the ability to seek into it
This improves upon the previous commit, and partially rewrites it (and
other code). It does:

- disable the seeking within cache by default, and add an option to
  control it
- mess with the buffer estimation reporting code, which will most likely
  lead to funny regressions even if the new features are not enabled
- add a back buffer to the packet cache
- enhance the seek code so you can seek into the back buffer
- unnecessarily change a bunch of other stuff for no reason
- fuck up everything and vomit ponies and rainbows

This should actually be pretty usable. One thing we should add are some
properties to report the proper buffer state. Then the OSC could show a
nice buffer range. Also configuration of the buffers could be made
simpler. Once this has been tested enough, it can be enabled by default,
and might replace the stream cache's byte ringbuffer.

In addition it may or may not be possible to keep other buffer ranges
when seeking outside of the current range, but that would be much more
complex.
2017-10-21 19:26:33 +02:00
Aman Gupta 83c9f169c4 demux: optimize seeks within readahead cache
If a suitable keyframe cannot be found in each stream's
readahead cache, fallback to a regular seek.
2017-10-21 13:29:37 +02:00
wm4 044af63d98 demux: improvements to previous commits
More the ignore_eof field to the internal demux_stream struct. This is
relatively messy, because the internal struct exists only once the
stream is created, and after that setting the ignore_eof flag is a race
condition. We could bother with adding demux_add_sh_stream() parameters
for this, but let's not. So in theory a tiny race condition is
introduced, which can never be triggered since all demux API functions
are called by the playback thread only anyway.

Fix that ts_offset is accessed without log (this was introduced much
earlier by myself).

Introduce an alternative way of avoiding the annoying EOF reached
messages by not resetting the EOF flags for CC streams when a CC packet
is added. This makes the second commit in the PR which added the
original fix unnecessary.

As another cosmetic change merge the check in cached_demux_control()
into a single if().

In the future, the CC pseudo-stream should probably be replaced with an
entire pseudo-demuxer or such, which would avoid some of the messiness
(or maybe not, we don't know yet).
2017-10-20 22:30:59 +02:00
Aman Gupta f57ff79867 demux: ignore false underrun reporting from eia_608 captions decoder 2017-10-20 22:14:54 +02:00
wm4 7163c95cfd cache: throttle wakeups
In the extreme case, reading 1 byte would wake up the cache to make the
cache thread read 1 byte. This would be extremely inefficient. This will
not normally happen in our cache implementation, but it's still present
to some lesser degree. Normally you'd set a predefined "cache too low"
boundary, after which you would restart reading. For some reason
something like this is already present using a hardcoded value
(FILL_LIMIT - I don't even know the deeper reason why this exists). So
use that to reduce wakeups.

This doesn't fix redundant wakeups on EOFs, which is especially visible
should something keep retrying reading on EOF (like in an endless loop).
2017-10-20 22:13:22 +02:00
Rostislav Pehlivanov 13fb166d87 wayland_common: don't scale the cursor wl_buffer
Only gnome does something as stupid as always applying scaling to
the cursor rather than just using a larger sized one with HIDPI.
2017-10-19 21:35:20 +01:00
wm4 d3c022779a video: fix alpha handling
Regression since ec6e8a31e0. Removal of the explicit else case
always applies the conversion to premultiplied alpha in the else branch.
We want to scale with multiplied alpha, but we don't want to multiply
with alpha again on top of it.

Fixes #4983, hopefully.
2017-10-19 19:01:33 +02:00
wm4 f37c9b36aa github: Google Drive sucks
Is there even anything that fucking sucks more than it?
2017-10-19 18:45:05 +02:00
James Ross-Gowan d9e3bad500 vo_gpu: add rgba16hf to the list of FBO formats
This should be functionally identical to rgba16f, since the formats only
differ in their representation on the CPU, but it could be useful for RA
backends that don't expose rgba16f, like Vulkan. It's definitely useful
for the WIP D3D11 backend.
2017-10-18 23:55:13 +11:00
wm4 872c2403a4 video: fix poitential NULL deref
Regression introduced by direct rendering code additions. Found by same
static analyzer.
2017-10-18 12:14:56 +02:00
wm4 14f01bd398 aframe: fix logically dead code
Detected by a well known static analyzer.
2017-10-18 12:11:37 +02:00
Ilya Tumaykin c7824f7c9d tests: fix include after 6597998 2017-10-17 09:29:02 +02:00
wm4 747892209f vo_rpi: fix build (probably)
Untested. If it works, fixes #4919.
2017-10-17 09:28:00 +02:00
wm4 77945b2c16 vo_gpu: remove weird p->vo indirection
That's just unnecessary.
2017-10-17 09:09:00 +02:00
wm4 c90f76d322 vo_gpu: fix video sometimes not being rerendered on equalizer change
With video paused, changing the brightness controls (or similar) would
sometimes not rerender the video frame. So the OSD would redraw, but the
video wouldn't change. This is caused by output caching, and a redraw
request is free to return the cached frame. Change it such to invalidate
the cached frame if any of the options or the equalizer change.

In theory, gl_video_reset_surfaces() could be called if the equalizer
changes - this would apparently force interpolatzion to redraw all
frames. But this looks kind of crappy when changing the equalizer during
playback. It'll "eventually" use the correct settings anyway, and when
paused interpolation is off.
2017-10-17 09:07:35 +02:00
wm4 b299a3f546 vdpau: remove some more dead code 2017-10-16 18:19:19 +02:00
wm4 2defa64d3b av_common: fix Libav build
Fucking shit.
2017-10-16 17:24:07 +02:00
wm4 ddfccd67d5 video: remove special path for hwdec screenshots
This was phased out, and was used only by vdpau by now. Drop the
mechanism and the vdpau special code, which means screenshots won't
include the vf_vdpaupp processing anymore. (I don't care enough about
vdpau, it's on its way out.)
2017-10-16 17:07:35 +02:00
wm4 9e140775bc video: fix previous commit
Sigh.
2017-10-16 17:06:01 +02:00
wm4 1ff6a1c8c7 video: make previously added hwdec params mechanism more generic
The mechanism introduced in b135af6842 assumed AVHWFramesContext would
be enough. Apparently it's not - the intended use with Rockchip (not
Rokchip btw.) requires accessing actual frame data in order to access
the AVDRMFrameDescriptor struct.

Just pass the entire mp_image to the new function. This is more
flexible, although it slightly worries me that it will be less reusable
for things which require setting up mp_image_params before any real
frames are processed (such as filters).
2017-10-16 17:00:38 +02:00
wm4 0a7c5a130e video: properly pass through ICC data
The same should happen with any other side data that matters to mpv,
otherwise filters will drop it.

(No, don't try to argue that mpv should use AVFrame. That won't work.)

ffmpeg_garbage() is copy&paste from frame_new_side_data() in FFmpeg
(roughly feed201849b8f91), because it's not public API. The name
reflects my opinion about FFmpeg's API.

In mp_image_to_av_frame(), change the too-fragile

  *new_ref = (struct mp_image){0};

into explicitly zeroing out the fields that are "transferred" to the
created AVFrame.
2017-10-16 16:36:51 +02:00
wm4 a7464c4ed8 mp_image: merge AVFrame conversion functions
Merge mp_image_copy_fields_to_av_frame() into mp_image_from_av_frame(),
same for the other direction.

There isn't any good reason to keep them separate, and the refcounting
handling makes it only more awkward.
2017-10-16 16:19:22 +02:00
wm4 b135af6842 video: add mp_image_params.hw_flags and add an example
It seems this will be useful for Rokchip DRM hwcontext integration.

DRM hwcontexts have additional internal structure which can be different
depending on the decoder, and which is not part of the generic hwcontext
API. Rockchip has 1 layer, which EGL interop happens to translate to a
RGB texture, while VAAPI (mapped as DRM hwcontext) will use multiple
layers. Both will use sw_format=nv12, and thus are indistinguishable on
the mp_image_params level. But this is needed to initialize the EGL
mapping and the vo_gpu video renderer correctly.

We hope that the layer count is enough to tell whether EGL will
translate the data to a RGB texture (vs. 2 texture resembling raw nv12
data). For that we introduce MP_IMAGE_HW_FLAG_OPAQUE.

This commit adds the flag, infrastructure to set it, and an "example"
for D3D11.

The D3D11 addition is quite useless at this point. But later we want to
get rid of d3d11_update_image_attribs() anyway, while we still need a
way to force d3d11vpp filter insertion, so maybe it has some
justification (who knows). In any case it makes testing this easier.
Obviously it also adds some basic support for triggering the opaque
format for decoding, which will use a driver-specific format, but which
is not supported in shaders. The opaque flag is not used to determine
whether d3d11vpp needs to be inserted, though.
2017-10-16 15:02:12 +02:00
wm4 ac295960b8 video: make it possible to always override hardware decoding format
Mostly an obscure option for testing. But --videotoolbox-format can be
deprecated, as it becomes redundant.

We rely on the libavutil hwcontext implementation to reject invalid
pixfmts, or not to blow up if they are incompatible.
2017-10-16 15:02:12 +02:00
James Ross-Gowan 23da3ed21a restore-old-bindings.conf: add old macOS/Wayland AXIS bindings
These were changed in 7897f79217 to match X11 and Windows.
2017-10-16 22:51:12 +11:00
wm4 54d14f5fa8 vo_gpu: remove some minor dead code
This was for the "opengl" compat VO entry, which is now handled
differently.
2017-10-16 11:00:02 +02:00
wm4 7cfae5adce vo_gpu: semi-fix --gpu-context/--gpu-api options and help output
This was confusing at best. Change it to output the actual choices.
(Seems like in the end it's always me who has to clean up other people's
bullshit.)

Context names were not unique - but they should be, so fix it. The whole
point of the original --opengl-backend option was to side-step the
tricky auto-detection, so you know exactly what you get. The goal of
this commit is to make --gpu-context work the same way. Fix the
non-unique names by appending "vk" to the names.

Keep in mind that this was not suitable for slecting the "UI" backend
anyway, since "x11" would force GLX, whereas people on not-NVIDIA
actually want "x11egl". Users trying to use --gpu-context=x11 to force
the X11 backend would always end up with GLX, which would at least break
VAAPI hardware decoding for them. Basically the idea that this option
could select the "UI" type is completely broken - it selects an
implementation, which implies a UI. Selecting the UI type This would
require a separate mechanism. (Although in theory this separate
mechanism could be part of the --gpu-context option - in any case,
someone would have to implement it.)

To achieve help output that can actually be understood, just duplicate
the code. Most of that code is duplicated anyway, and trying to share
just the list code with the result of making the output unreadable
doesn't make too much sense. If we wanted to save code/effort, we could
just remove the help output altogether.

--gpu-api has non-unique entries, and it would be nice to group them
(e.g. list all OpenGL capable contexts with "opengl"), but C makes this
simple idea too much of a pain, so don't do it.

Also remove a stray tab from the android entry on the manpage.
2017-10-16 10:57:51 +02:00
wm4 c6b97a4935 mp_image: select an explicit fallback for chroma location
If the chroma location is missing, vo_gpu will use centered chroma.
Select a better chroma location by default: normally, it will always be
MPEG video chroma location. If full levels are used, use JPEG chroma
location, because that sort of sounds like it could make sense as it
might coincide with JPEG being decoded.

See e.g. #4804.
2017-10-16 10:35:37 +02:00
James Ross-Gowan 6d534138ed manpage: add Vulkan WSI extension name for --gpu-context=win
This matches the other Vulkan contexts.
2017-10-14 17:48:13 +11:00
Tobias Jakobi 47b1390b80 vo_gpu: mali-fbdev: fix build error
Apparantly the context was renamed.
2017-10-13 17:10:52 +02:00
wm4 fc013ea8ac Copyright: some more licensing clarifications
Unfortunately I'm also adding the full text of the LGPL license text,
because the GPL one was already present in this repository, and I don't
want to imply that the GPL somehow has priority.
2017-10-13 15:44:55 +02:00
wm4 902ae9ae41 options: add --vlang switch
For symmetry with --alang and --slang. 100% useless, but why not?
2017-10-13 00:31:43 +02:00
Julian 5f8438bce6 stats: add file size
also one minor cosmetic change: comment the "coming soon" dummy page
2017-10-13 00:28:41 +02:00
Julian 8dfd728ba1 stats: clarify documentation
Change true/false to yes/no because lua script configs only take these
values for booleans.
2017-10-13 00:28:41 +02:00
Julian 57654cc19e input.conf: explicit bindings for stats overlay 2017-10-13 00:28:41 +02:00
Rostislav Pehlivanov c052849e52 wayland_common: init output_list during main struct init
Otherwise if display connection or xkb init failed the uninit function
could segfault.
2017-10-12 23:18:55 +01:00
wm4 b4c1f0aae3 manpage: correct some comments about ordered chapters
Ordered chapters behavior changed at some point, and all of this was
outdated.
2017-10-11 22:45:47 +02:00
Rostislav Pehlivanov 91ebc34344 wayland_common: require wl_output v2 and send MP_INPUT_RELEASE_ALL on uninit
Every compositor (including toy compositors) has had support for wl_output v2
since forever, so there's little point in supporting degraded output for 5 year
old releases (especially considering we require zxdg6 which is far more recent).
2017-10-11 19:59:42 +01:00
James Ross-Gowan b3178eb59e vo_gpu: shaderc: include debug info when --gpu-debug is set
This adds symbol information to the generated SPIR-V, which shows up in
the SPIR-V assembly dump. It's also useful for potential RA backends
that use SPIRV-Cross, since the symbol information is used in the
generated shader source.
2017-10-11 12:22:21 +11:00
wm4 5f012f2d16 audio: clarify GPL-only parts 2017-10-10 17:36:35 +02:00
wm4 b7f90be567 demux_mkv: remove remaining GPL code
Fuck this thing.
2017-10-10 17:35:47 +02:00
wm4 474a7c26f2 build: make LGPL mode final (via --enable-gpl)
Rename --enable-preliminary-lgpl2 to --enable-gpl. This concludes the
relicensing. Some things are still to do (relicensing some still-GPL
optional code), but we consider the code included by --enable-gpl to be
fully relicensed.

The relicensing was performed by asking every known author for
permission for relicensing it to LGPL version 2.1 "or later". If an
author could not be contacted or permission could not be obtained, and
the contribution was considered relevant for copyright purposes, the
affected code was either excluded from LGPL mode (not built), or removed
or rewritten. This is the standard in open source relicensing processes.

Keep in mind that using LGPL mode is still on the user's own risk. Even
though I claim that the relicensing was pretty clean and thorough
(measured on the standards of the open source community¹), and I
followed the advice of some actual experts, there is still a residual
uncertainty due to the fact that I'm not an all-knowing entity (authors
could have taken someone else's code and pretend it's their own) nor a
lawyer (meaning I might lack associated authority or expertise), and the
fact that the judicial system is far from deterministic. The relicensing
was performed merely to the best of my knowledge. I reject all
responsibility outside of that.

This commit also cleans up the "Copyright" file to reflect the finalized
relicensing process.

¹ Not to imply that the standards of commercial companies are much
higher. Some major tech companies get away with stuff I would not
consider clean.

See #2033.
2017-10-10 16:33:38 +02:00
wm4 14541ae258 Add checks for HAVE_GPL to various GPL-only source files
This should actually cover all of them, if you take into account that
some unchanged GPL source files include header files with such checks.
Also this was done already for the libaf derived code.

This is only for "safety" and to avoid misunderstandings.
2017-10-10 15:51:16 +02:00
Rostislav Pehlivanov 7c66c2bb75 wayland_common: adjust default cursor size and scale its buffer
It turns out compositors which do scaling scale the cursor as well,
so every single surface needs to get scaled too.

Also, 32 corresponds to the default size for both GTK+ and KDE.
2017-10-10 02:39:39 +01:00
Aman Gupta 1abac5f4aa vo: fix reference to mediacodec_embed 2017-10-09 21:49:01 +02:00
Aman Gupta 502d074a31 vo_gpu: android: fix gpu context 2017-10-09 21:49:01 +02:00
Mark Thompson 05cb8d28af vo_opengl: hwdec_vaegl: Use vaExportSurfaceHandle() if present
This new interface in libva2 offers a cleaner way to export surfaces
which can then be imported to EGL.  In particular, this works with
the Mesa driver, so we can have proper playback without a pointless
download and upload on AMD cards.

This change does nothing with libva1, and will fall back to the
libva1 interface (vaDeriveImage() + vaAcquireBufferHandle()) if
vaExportSurfaceHandle() is not present.
2017-10-09 21:35:49 +02:00
Mark Thompson 2ecf240b1c vaapi: Use libva2 message callbacks
They are no longer global, so they work vaguely sensibly.
2017-10-09 21:35:47 +02:00
Julian 81cf58c8c4 stats: add documentation
stats.rst is heavily based on osc.rst
2017-10-09 20:48:44 +02:00
Julian 92a9150cc2 lua: integrate stats.lua script
Signed-off-by: wm4 <wm4@nowhere>

Rename --stats to --load-stats-overlay and add an entry to options.rst
over the original commit.

Signed-off-by: wm4 <wm4@nowhere>
2017-10-09 20:47:33 +02:00
Julian c38ad6ae6f stats: change the way toggling/oneshot works internally
Previously multiple timers were used to realize oneshot, toggling
(redrawing) and page keybindings. The oneshot case in particular also
relied on mp.osd_message to display text only for a given duration.
This was changed to only use one timer in total now. Because now each
case has a defined "start" and "end" point (including oneshot)
mp.set_osd_ass() can be used to print stats as well. This is currently
optional and has to be activated using the config option
persistent_overlay=true.

One shortcoming: oneshot and toggling are mutual exclusive right now.
Previously you could enter toggling while oneshot stats were shown,
this is not possible anymore to reduce the number of cases to be
considered. This can be added later on if desired.
2017-10-09 20:40:32 +02:00
Julian eadec19d22 stats: stop coloring timing values
It used a bad heuristic that got even worse/less reliable with recent
changes in mpv. In fact, it's not reliable at all.
Watch out for dropped frames instead. That's a useful indicator.
2017-10-09 20:40:32 +02:00
Julian 54b3a9fdb0 stats: add current and total chapter number
Fixes #44
(well, partially, I'm still not sure about the time)
2017-10-09 20:40:32 +02:00
Jan Janssen 01f2798e04 stats: add audio and video filters 2017-10-09 20:40:32 +02:00
Niklas Haas 055fc5ced3 stats: reorganize the framedrop counters
Clarified the relationship between `Dropped` and `VO`, and also merged
the DS-exclusive stats into the DS line.
2017-10-09 20:40:32 +02:00
Julian 1016ff34ea stats: revert DR indicator as it's unnecessary
It's apparently already stated as part of the upload pass name.
This reverts commit ec837f64c29a1b825e28b65edc34059b6c1cad40.
2017-10-09 20:40:32 +02:00
Julian 9bcb8f3bd9 stats: reduce default font size to 8 2017-10-09 20:40:32 +02:00
Julian 19b8dfbd2b stats: visually indicate direct rendering 2017-10-09 20:40:32 +02:00
Julian 5c8e9e8072 stats: change font weight of % sign as well
Due to popular demand
2017-10-09 20:40:32 +02:00
Julian d0608d3fdf stats: fix indentation/newline of frame timing page
There was a superfluous newline and some indentation
2017-10-09 20:40:32 +02:00
Julian 471b152527 stats: show % of a pass on frame timing page 2017-10-09 20:40:32 +02:00
Julian f0719727cc stats: always print perfdata total
There's no point in disabling it anyway
2017-10-09 20:40:32 +02:00
Julian 1231b1ae68 stats: make add_header() append at current position 2017-10-09 20:40:32 +02:00
Julian 96ef2aa48b stats: print perfdata total by default
There is enough space now
2017-10-09 20:40:32 +02:00
Julian 56029b6b59 stats: mark dummy as such 2017-10-09 20:40:32 +02:00
Julian 9470ccd8ae stats: correctly re-eval ASS tag usage
Fixes #42
2017-10-09 20:40:32 +02:00
Julian b93efd0a52 stats: make page keybinding repeatable
There's no reason it's not.
2017-10-09 20:40:32 +02:00
Julian 6c7aae769a stats: remove table in table
Almost cosmetic change.
This tables-in-table was done back when we actually processed strings
but that's long ago now and no longer needed nor useful.
2017-10-09 20:40:32 +02:00
Julian 783046f5ff stats: resilience against accidential timer removal
Previously I could trigger a bug with intense button mashing, however,
was unable to reproduce it and therefore debug it.
This change now seems to be resilient against button mashing, let's hope
it really is.
2017-10-09 20:40:32 +02:00
Julian 21603dd5af stats: allow keybindings for specific page
A keybinding in input.conf like:
   e script-binding stats/display-page-2
can be used to directly show the respective page (2, in this case)
2017-10-09 20:40:32 +02:00
Julian 98ddbf8c34 stats: support for multiple "pages" of stats
Please note that the latest version of this script needs a very recent
version of mpv (from yesterday, to be precise, see the readme).
For older versions, please go to "releases".

HOW IT WORKS:
While the stats are visible (i.e. text is printed to the OSD) a
subsequent click on a numeric key (1, 2, ...) will display the
corresponding "page".
This works no matter if the stats are toggled or just shown as a single
invocation. In case of a single invocation, the newly displayed page
will be shown for the full duration again.
The selected page will be remembered (not persistantly though).

So far, only 3 pages are available.
1: the default page, stats as they used to be
2: extensive VO performance stats (to be redesigned/changed soon)
3: dummy

In the future, many more pages are possible.

Implementation is likely to change again (functionality will stay
the same). A new timer had to be introduced to remove the forced
keybindings in the oneshot case. The toggle case can remove them without
a timer. Ensuring that each mode won't remove timers of the other mode
didn't really turn out neat.
Therefore, I intend to change this again, maybe by merging the
oneshot case into the toggle case.
2017-10-09 20:40:32 +02:00
Julian c04ff9dce0 stats: remove check for lua timer function
We now require a modern mpv version.
`property_aliases` is kept for future use.
2017-10-09 20:40:32 +02:00
Niklas Haas 1691b978cf stats: rescale graphs to make the average align with the center, if possible
For vsync measurements this is not currently done because they don't
track their average
2017-10-09 20:40:32 +02:00
Niklas Haas 22a8b99f7a stats: add support for vo-passes, which replaces vo-performance
Due to the large amount of per-pass data, the function takes a parameter
indicating whether or not to print a simplified view instead.

The overall intent is to print the simplified view for now, but supposed
printing the full view on a dedicated "tab" (or extra view type), and as
such, `o.print_perfdata_passes` will go away again. I've only introduced
it for now so users can play around with this functionality if they want
to, until Argon- gets around to implementing stats "tabs".
2017-10-09 20:40:32 +02:00
Niklas Haas 6d10d5a29f stats: update HDR peak for upstream changes
This no longer reports cd/m² but now reports a relative peak as a
multiple of the SDR reference brightness.
2017-10-09 20:40:32 +02:00
Julian fa80ac13b6 stats: add support for deprecated properties
Previously, we used a property and when it was unavailable we assumed it
doesn't exist before assuming it really is just unavailable. This lead
to unnecessarily falling back to deprecated properties which made mpv
print deprecation warnings.
Now we can really check if a property is not known to mpv.
The alternative would've been to check the error part of mp.get_property
and perform string comparisons on the returned error message.

Not sure if supporting old mpv versions is actually worth it though.

Fixes #37 #36
2017-10-09 20:40:32 +02:00
Julian 6f9a7d1fdb stats: comment to remind me about deprecated properties 2017-10-09 20:40:32 +02:00
Ricardo Constantino 7429eace57 stats: add new versions of decoder and VO dropped frame counts 2017-10-09 20:40:32 +02:00
Julian bd0d0befc0 stats: put vsync ratio and jitter on the same line
Free some vertical space. Hope this doesn't hurt visibility.
2017-10-09 20:40:32 +02:00
Julian 8bc6c91f4a stats: declare function as local
Apparently forgot this one
2017-10-09 20:40:32 +02:00
Julian c02d89fcd1 stats: use container-fps together with fps (as fallback)
This was already done for the actual stats a few months ago.
Now it is also used by the perfdata coloring code.
2017-10-09 20:40:32 +02:00
Julian c4ea382894 stats: rename option timing_total to print_perfdata_total
Should make its purpose more clear. Also add a comment to further
explain its use.
2017-10-09 20:40:31 +02:00
Julian 5a9ccfdcb8 stats: add vsync-ratio and vsync-jitter
Both come with graphs enabled by default.
They can be disabled using the options plot_vsync_ratio and
plot_vsync_jitter (see the readme regarding customization).

In case both graphs are deactivated the ratio and jitter properties will
be printed on the same line to save some space.

One more user-visible/noticeable change: the maximum used to scale the
values for each graph is no longer calculated each time the stats are
shown but instead when collecting the data. This means the maximum
can actually be higher than all values currently present in a graph's
data buffer. This makes it easier to judge a graph's values, especially
since as we have no axis labels.
To prevent high values staying max forever graph data buffers are
cleared when toggling (can be disabled). It was never useful to
keep old data and simply append newer data (with a time skip) anyway.
2017-10-09 20:40:31 +02:00
Julian 78cbe40fa5 stats: add some documentation for generate_graph() 2017-10-09 20:40:31 +02:00
Julian b58b812384 stats: access less variables outside function's state 2017-10-09 20:40:31 +02:00
Ricardo Constantino (:RiCON) fa0b1f071a stats: add new container-fps that deprecates fps 2017-10-09 20:40:31 +02:00
Ricardo Constantino (:RiCON) 49d64997ef stats: remove hwdec-active property 2017-10-09 20:40:31 +02:00
Julian 97c1cd6658 stats: fix bug introduced in earlier commit
Commit 76387aba26574d0d96af688cf11d10bd165171f7 broke the script in case
of timing_total=true.
2017-10-09 20:40:31 +02:00
Julian 3f4fd36aa8 stats: fix comment typo 2017-10-09 20:40:31 +02:00
Julian 6c7385c539 stats: disable coloring peak performance data
The peak value is probably not very well suited to draw many conclusions
from it.
2017-10-09 20:40:31 +02:00
Julian 0242165b3c stats: change coloring of performance data
Previously it used display-fps to determine coloration even when
display-sync was not even used.
2017-10-09 20:40:31 +02:00
Julian 9d8495a960 stats: save ASS sequences locally
Instead of querying them constantly.
Also add a tiny bit of documentation to some variables.
2017-10-09 20:40:31 +02:00
Julian 9b439e9453 stats: only print graphs when ASS tags are good 2017-10-09 20:40:31 +02:00
Julian 4ee669e4db stats: clearify a few descriptions/labels 2017-10-09 20:40:31 +02:00
Julian 7dcebb016c stats: don't show video/audio-speed-correction when 0
This used to be the case, I'm not sure when it changed.
The current way of 'hiding' it in case of 0 is not exactly
good and relies on the OSD representation. It could be done
better by querying the video-sync-active property but that would
require querying yet one more thing...
2017-10-09 20:40:31 +02:00
Niklas Haas aace3e4cde stats: add HDR signal peak information
Added to mpv in commit a14f9249. Simply shown after the gamma curve if
available, since it's semantically attached to it.

Also regroup some of the colorimetry options to make this fit (and for
them to make more sense)
2017-10-09 20:40:31 +02:00
Julian 90ecf52a45 stats: add sum of timing values
Display an additional line with the sum of all three timing values.
Disabled by default.

I didn't see the necessity to also create a graph for this line
2017-10-09 20:40:31 +02:00
Julian 3663a411d3 stats: put colormatrix, primaries and gamma together
Saves a bit of space.
2017-10-09 20:40:31 +02:00
Julian 8bbbab9523 stats: change highlighting of performance data
Add a yellow highlight to the existing red highlight.
Red is still used once the available time is exhausted, yellow is
supposed to be a warning when the headroom is getting small.
The threshold is configurable.
2017-10-09 20:40:31 +02:00
Julian 485c3549d7 stats: declare functions as local
Because why not.
Simply reorder functions instead of forward declaring stuff.
2017-10-09 20:40:31 +02:00
Julian 5e0d36c515 stats: align graphs
Graphs are now aligned. This required a change in the layout of
performance data. Reason is a wrong (but intended) calculation
of vector drawing sizes in libass to maintain compatibility.
This essentially prevents text following the graph.
To achieve alignment only monospaced text can precede the graph.
This led to the layout changing slightly when graphs are shown.
2017-10-09 20:40:31 +02:00
Julian 946d45a421 stats: change the way the output is built
Instead of creating new strings with the content of the previous
one followed by some new content we now write all content into
tables that are concatenated in the end.
This is unlikely to improve performance but at least it will
cut down on all these temporary, growing strings polluting memory.
2017-10-09 20:40:31 +02:00
Julian a256d61ef4 stats: rewrite parts of performance data
Major changes:
  - graphs are only drawn when in toggled mode
  - performance data is retrieved every ith frame (default: 5)
  - highlighting of performance data (numbers): add a highlight
    when the summed numbers (last/avg/peak) exceed 1/display-fps
2017-10-09 20:40:31 +02:00
Julian de38bd0f81 stats: add performance data
Display various performance data about frames and their
display/rendering. Additionally plot graphs for this data.

This is experimental and pretty much just a test at this point and by
far not final.
2017-10-09 20:40:31 +02:00
Julian 2de778f699 stats: update stats when file changes
Only in toggled mode and actually only when the video output is
reconfigured. This should cover the relevant cases.

Fixes #22
2017-10-09 20:40:31 +02:00
Julian fcacf82865 stats: small spelling correction 2017-10-09 20:40:31 +02:00
Julian f8bafd4734 stats: use redraw_delay for timer period
Previously the delay was slightly shortened but a user explicitly
setting a specific delay most likely expects the stats to refresh
in exactly the frequency he desired.
2017-10-09 20:40:31 +02:00
Ricardo Constantino (:RiCON) 8db09be51a stats: always print title if different from filename 2017-10-09 20:40:31 +02:00
Julian c387b1db6f stats: make a warning more visible
Print it to console and especially OSD upon each invocation
2017-10-09 20:40:31 +02:00
Julian a87af63365 stats: rename some functions
More useful names
2017-10-09 20:40:31 +02:00
Julian 2f5ee99509 stats: add toggling of stats
You can now either show the stats once or toggle their display. Both are
using different key bindings which are additionally configurable now.

Please bear in mind that "toggling" means "redraw every x seconds for x
seconds". Therefore, this approach is prone to problems especially when
something else is printing text to the OSD as well as every of these
calls will overwrite each other. This is currently a limitation of mpv.

Fixes #18
2017-10-09 20:40:31 +02:00
Ricardo Constantino (:RiCON) fe5b042b74 stats: add hwdec-current
Fallback to hwdec-active if not available. This one will be removed in
mpv 0.19.0.
2017-10-09 20:40:31 +02:00
Ricardo Constantino (:RiCON) 7c261899cf stats: add cache-speed 2017-10-09 20:40:31 +02:00
Julian 5fb8dc5943 stats: decrease default font size
It's getting a bit cramped
2017-10-09 20:40:31 +02:00
Niklas Haas bee7404efc stats: add video-params/gamma property 2017-10-09 20:40:31 +02:00
Kevin Mitchell 1f41c729bb stats: update frame drop diagnostics 2017-10-09 20:40:31 +02:00
Kevin Mitchell 41246c8a34 stats: add display fps 2017-10-09 20:40:31 +02:00
Julian 1a1e5b87fb stats: rename some variables for consistency 2017-10-09 20:40:31 +02:00
Niklas Haas 47016bf45e stats: add support for video-sync=display 2017-10-09 20:40:31 +02:00
Julian f22361727e stats: fix line wrapping
These spaces were not displayed on screen, however they were taken into
account for line wrapping.
2017-10-09 20:40:31 +02:00
Julian 6402f88de4 stats: remove dead link from comment 2017-10-09 20:40:31 +02:00
Rostislav Pehlivanov 918774b5aa stats: print bold text in terminals
This simply prints ASCII codes to display any text marked as bold in the
terminal. Supported by every sane terminal since 1986. For those insane,
there's a check. The check has been copied from the ansicolors.lua
script floating around and it checks if the directory path uses "\"
instead of "/", and in case it does, it checks whether ANSICON env
variable has been set (which is used to indicate the Windows terminal
supports ACII escape sequences).
2017-10-09 20:40:31 +02:00
Julian 89c854dc09 stats: minor simplification 2017-10-09 20:40:31 +02:00
Julian 3dbd031da0 stats: remove countless hardcoded strings
feels a bit better that way
2017-10-09 20:40:31 +02:00
Julian 6ed69cb132 stats: document append_property return value 2017-10-09 20:40:31 +02:00
Julian ab8b6e3c16 stats: fix oversight
this one slipped through my "tests"
2017-10-09 20:40:31 +02:00
Julian 95b6bc31b0 stats: unify redundant functions
Unify both append_property* functions and greatly refactor them.
Instead of thousands of arguments we now use a table.
While this is in theory cleaner it does not exactly look like it.
However, it's way more flexible and extendable this way.
Also, since the new append_property() might look a bit confusing
I felt the need to add a comment.
2017-10-09 20:40:31 +02:00
Julian d88adcfbc7 stats: proper usage of imported module
and comment nitpicking
2017-10-09 20:40:31 +02:00
Julian 0bf4b0d18a stats: add debug option
print a warning for properties without value
2017-10-09 20:40:31 +02:00
Julian f9fe3b264e stats: reflect latest changes to mpv
Some properties were renamed recently.
Of course this requires a recent mpv built (>
https://github.com/mpv-player/mpv/commit/f9507f) now.
2017-10-09 20:40:31 +02:00
Julian a78fce4676 stats: don't add superfluous EOL characters
Previously we unnecessarily added newline characters at the end.
Only noticeable when printed on terminal, though.
2017-10-09 20:40:31 +02:00
Julian 81efbc3921 stats: make non-ASS styling configurable
Also add a few convenience functions and remove the unused italic and
underlined formatting functions.
2017-10-09 20:40:31 +02:00
Rostislav Pehlivanov 9e57927af1 stats: make the OSD usable in audio-only mode
Previously, the script would throw garbage (ASS tags) at the terminal
when the bound key was pressed. This changes the behaviour to _not_
print any ASS tags (and replace those which can be interpreted by the
terminal) if there's no video.

I cleaned the patch up since you mentioned you were busy. As I said
before, there is absolutely no problem with calling mpv to display
strings to the OSD without any video. They'll just go straight to the
terminal just as they would with an active VO.
2017-10-09 20:40:31 +02:00
Julian 74e215e9bf stats: avoid clashing with similar named scripts 2017-10-09 20:40:31 +02:00
Julian c2f0557977 stats: initial commit 2017-10-09 20:40:31 +02:00
Oliver Freyermuth 6b05c774a4 dvb: SYS_DVBC_ANNEX_B is now supported if ATSC is activated.
Signed-off-by: Oliver Freyermuth <o.freyermuth@googlemail.com>
2017-10-09 20:06:29 +02:00
Oliver Freyermuth de0c1dd4f5 dvb: Skip channel if ATSC device does not support cable / terr.
This matches what is done for the other multi-delivery-system
cards.

Signed-off-by: Oliver Freyermuth <o.freyermuth@googlemail.com>
2017-10-09 20:06:29 +02:00
Oliver Freyermuth add0cbea2a dvb: Implement parsing of modulation for VDR-style channels config.
This is required for ATSC cable / terrestrial support.

Signed-off-by: Oliver Freyermuth <o.freyermuth@googlemail.com>
2017-10-09 20:06:29 +02:00
Oliver Freyermuth e46338c66a dvb: Fixes for ATSC tuning.
ATSC is a mix of terrestrial and cable,
and depending on modulation is actually using
DVBC_ANNEX_B. Thus, we need to override the delivery
system depending on the modulation, channel by channel.

Signed-off-by: Oliver Freyermuth <o.freyermuth@googlemail.com>
2017-10-09 20:06:29 +02:00
Oliver Freyermuth 20381a5f5a stream_dvb: Multiply frequency and sample rate by 1000 for VDR.
These values are kept with a different unit in VDR style config
for all delivery systems, not only for DVB-S / DVB-S2.

Signed-off-by: Oliver Freyermuth <o.freyermuth@googlemail.com>
2017-10-09 20:06:29 +02:00
Oliver Freyermuth 668598e133 dvb_tune: Pull out DVBv5 raw tuning part, add verbosity.
Dump the complete raw tuning commands to allow for debugging
on low level.
Also, remove code duplication and some variable shadowing.

Signed-off-by: Oliver Freyermuth <o.freyermuth@googlemail.com>
2017-10-09 20:06:29 +02:00
Oliver Freyermuth b9af4409bc dvb: Explicitly clear via DVBv5 before reverting to DVBv3.
Signed-off-by: Oliver Freyermuth <o.freyermuth@googlemail.com>
2017-10-09 20:06:29 +02:00
Oliver Freyermuth 22442b421c dvb: Use more elaborate tuning for DVBv5 tuning.
Also, in case tuning fails with timeout even though the ioctl
was accepted by the device, fall back to DVBv3 tuning.
This may go wrong for multi-delivery-system cards,
so issue an error message in that case.

Signed-off-by: Oliver Freyermuth <o.freyermuth@googlemail.com>
2017-10-09 20:06:29 +02:00
wm4 cdef69103a vo_gpu: simplify opengl alias
This makes the replacement warning message worse, but I don't think I
care enough.
2017-10-09 18:55:44 +02:00
wm4 b43bf12fa6 vo_gpu: remove duplicated options
All these options (like --gpu-context etc.) were duplicated. It's
amazing that it didn't cause more problems than it did.
2017-10-09 18:53:32 +02:00
Mark Thompson c6e7ced7f4 vo_opengl: context_drm_egl: Don't create a new framebuffer for every frame 2017-10-09 18:40:45 +02:00
Aman Gupta 8fc21fd0d5 vo_gpu: add android opengl backend
At the moment, rendering on Android requires ``--vo=opengl-cb`` and
a lot of java<->c++ bridging code to receive the receive and react to
the render callback in java. Performance also suffers with opengl-cb,
due to the overhead of context switching in JNI.

With this patch, Android can render using ``--vo=gpu --gpu-context=android``
(after setting ``--wid`` to point to an android.view.Surface on-screen).
2017-10-09 18:36:54 +02:00
Aman Gupta e80a2a572d vo: add mediacodec_embed output driver
Allows rendering IMGFMT_MEDIACODEC frames directly onto an
android.view.Surface
2017-10-09 18:36:54 +02:00
Aman Gupta 61a1612de9 hwdec: add mediacodec hardware decoder for IMGFMT_MEDIACODEC frames 2017-10-09 18:36:54 +02:00
Aman Gupta 6f0fdac6f1 vo: add VO_CAP_NOREDRAW for upcoming vo_mediacodec_embed
MediaCodec uses a fixed number of output buffers to hold frames, and
expects that output buffers will be released as soon as possible. Once
rendered, the underlying frame is automatically released and cannot be
reused or rerendered.

The new VO_CAP_NOREDRAW forces mpv to release frames immediately after
they are rendered or dropped, to ensure that MediaCodec decoder does not
run out of buffers and stall out.
2017-10-09 18:36:54 +02:00
Aman Gupta d08e407c9e hwdec: rename mediacodec to mediacodec-copy 2017-10-09 18:36:54 +02:00
wm4 cabb1ca549 README.md: explicitly link contribute.md
Also move the license section, because it looks strange how the link
list is above it.
2017-10-09 16:00:08 +02:00
wm4 b6af3db568 command: drop "audio-out-detected-device" property
Coreaudio stopped setting it a few releases ago (66a958bb4f). There is
not much of a user- or API-visible change, so remove it without
deprecation.
2017-10-09 15:48:47 +02:00
wm4 622610bad5 img_format: AV_PIX_FMT_PAL8 is RGB
This partiular format is not marked as AV_PIX_FMT_FLAG_RGB in FFmpeg's
pixdesc table, so mpv assumed it's a YUV format.

This is a regression, since the old code in mp_imgfmt_get_desc() also
treated this format specially to avoid this problem. Another format
which was special-cased in the old code was AV_PIX_FMT_MONOBLACK, so
make an exception for it as well.

Maybe this problem could be avoided by mp_image_params_guess_csp() not
forcing certain colorimetric parameters by the implied colorspace, but
certainly that would cause other problems. At least there are mistagged
files out there that would break. (Do we actually care?)

Fixes #4965.
2017-10-09 15:15:53 +02:00
Rostislav Pehlivanov 4c7c8daf9c wayland_common: implement output tracking, cleanups and bugfixes
This commit:
    - Implements output tracking (e.g. monitor plug/unplug)
    - Creates the surface during registry (no other dependencies)
    - Queues the callback immediately after surface creation
    - Cleaner and better event handling (functions return directly)
    - Better reconfigure handling (resizes reduced to 1 during init)
    - Don't unnecessarily resize  (if dimensions match)

Apart from that fixes 2 potential memory leaks (mime type and window
title), 2 string ownership issues (output name and make need to be
dup'd), fixes some style issues (switches were indented) and finally
adds messages when disabling/enabling idle inhibition.

The callback setter function was removed in preparation for the commit
which will use the frame event cb because it was unnecessary.
2017-10-09 02:23:04 +01:00
Akemi 318e2e53f0 osx: add right MacPorts paths to our bundle $PATH
also add another path for homebrew.
2017-10-07 22:18:22 +02:00
Niklas Haas 2c046c48ec wayland_common: allow vo_wayland_uninit(NULL)
...again
2017-10-07 21:49:03 +02:00
Rostislav Pehlivanov 9c806bc299 Revert "wayland_common: add support for embedding"
This reverts commit 8d8d4c5cb1.
2017-10-05 17:43:47 +01:00
Rostislav Pehlivanov da30f0ba2b wayland_common: respect close events
Overlooked.
Also add a comment and only set the parent if WinID is set.
2017-10-05 16:58:29 +01:00
Rostislav Pehlivanov 8d8d4c5cb1 wayland_common: add support for embedding 2017-10-05 16:23:15 +01:00
Rostislav Pehlivanov bee6ca5225 wayland_common: reset the LIVE_RESIZING flag when resizing ends
The VO code resets each flag individually, and it doesn't do it for this one.
Also make the prints use the struct names rather than the hardcoded ones,
forgot to add those to the last wayland_common commit.
2017-10-05 15:42:08 +01:00
wm4 158b69f04c build: switch preliminary LGPL mode from v3 to v2.1
iive agreed to relicense things that are still in mpv to LGPLv2.1. So
change the licenses of the affected files, and rename the configure
switch for LGPL mode to --enable-preliminary-lgpl2.

(The "preliminary" part will probably be removed from the configure
switch soon as well.)

Also player/main.c hasn't had GPL parts since a few commits ago.
2017-10-05 15:57:30 +02:00
wm4 4eb8623945 DOCS/interface-changes.rst: mention --log-file behavior change
See previous commit.
2017-10-05 11:23:33 +02:00
wm4 10dd120baa msg: make --msg-level affect --log-file too
But --msg-level can only raise the log level used for --log-file,
because the original idea with --log-file was that it'd log verbose
messages to disk even if terminal logging is lower than -v or fully
disabled.
2017-10-04 22:08:19 +02:00
wm4 bfae72a278 player: change a minor code fragment to LGPL
Seems absurd to keep this under GPL, since it's only a tiny code
fragment (that would always look the same, no matter if you rewrote it
independently), but now I got proper permission from the original author
anyway.
2017-10-04 19:10:52 +02:00
Rostislav Pehlivanov 72901bb16b wayland_common: don't hardcode protocol names during registry
Use the interface names from the wl_interface structs they provide.
2017-10-04 02:24:01 +01:00
Martin Herkt 4ab9aac196 README: drop support for Windows Vista
See #4952.
2017-10-04 03:07:12 +02:00
Rostislav Pehlivanov 68f9ee7e0b wayland_common: rewrite from scratch
The wayland code was written more than 4 years ago when wayland wasn't
even at version 1.0. This commit rewrites everything in a more modern way,
switches to using the new xdg v6 shell interface which solves a lot of bugs
and makes mpv tiling-friedly, adds support for drag and drop, adds support
for touchscreens, adds support for KDE's server decorations protocol,
and finally adds support for the new idle-inhibitor protocol.

It does not yet use the frame callback as a main rendering loop driver,
this will happen with a later commit.
2017-10-03 19:36:02 +01:00
Rostislav Pehlivanov 980116360b vo_wayland: remove
This VO was buggy and never worked correctly. Like with wayland_common,
it needs to be rewritten from scratch.
2017-10-03 19:35:59 +01:00
wm4 4e5d7cbf21 demux_mkv: replace deprecated av_copy_packet_side_data()
It's deprecated, and av_packet_copy_props() is nearly equivalent. It's
also more widely supported.
2017-10-03 14:45:18 +02:00
Akemi 6132323911 osx: add some common paths to our $PATH when started from bundle
with the previous commit we removed the ability of loading the standard
shell environment. this exact behaviour can only be re-added by either
invoking the standard shell in a background process and reading it's
environment vars or by manually reading all the various shell configs.
both ways are kinda dirty and the former was already rejected before.
for now we will just add some commonly used paths, when started from the
bundle, so it can find the binaries used by mpv again. for example the
youtube-dl one for our youtube-dl hook.
2017-10-03 11:30:56 +02:00
Akemi 77021cf6fe osx: fix bundle on macOS High Sierra (10.13)
Apple slightly changed the App bundle mechanism which broke wrapper
scripts that invoke the actual binary. it caused the bundle to always
open a new instance of mpv instead of reusing the currently running one.

just removing the wrapper script would lead to several regressions, so
it was replaced with a symlink to the bundle binary. detection if mpv
was started from the bundle was replaced by comparing the execution name
of the binary, eg the name of the symlink "mpv-bundle". additionally,
because we load a standard config from the Resources folder of the
bundle again, we prevent that config from being loaded if mpv wasn't
started via the bundle. the psn argument has to be removed manually
again.

the ability of loading your standard shell environment has been removed
with the wrapper. a substitution will be added with another commit. as a
side effect this fixes an issues when zsh was used with common NodeJS
configuration scripts.

Fixes #4926 #4866
2017-10-03 11:30:56 +02:00
wm4 0c04ce5f0d vo_gpu: gl: implement proper extension string search
The existing code in check_ext() avoided false positive due to
sub-strings, but allowed false negatives. Fix this with slightly better
search code, and make it available as function to other source files.
(There are some cases of strstr() still around.)
2017-10-02 17:30:27 +02:00
James Ross-Gowan 51985e3dd6 DOCS/compile-windows.md: update for changes to mpv and MSYS2
- Don't recommend libdvdnav, since DVD support isn't compiled by default
  anymore.
- Take advantage of the new $MINGW_PACKAGE_PREFIX and $MSYSTEM_PREFIX
  variables to make the build commands independent from the mingw-w64
  build environment being used.
- Invoke /usr/bin/python3 directly, since I've heard some packages have
  started to depend on mingw-w64 versions of Python, but our build
  scripts only work with the MSYS2 version.
- Reword the MSYS2 install instructions to try to prevent common errors.
2017-10-02 01:28:54 +11:00
Kranky K. Krackpot 910600a36f Man page: fix typo
Man page: fix typo as of https://github.com/mpv-player/mpv/issues/4913
2017-10-01 20:51:21 +11:00
Niklas Haas eb69e73eb4 vo_gpu: enable 3DLUTs in dumb mode
Unless FBOs are unsupported, this works. In particular, it's required to
get ICC profiles working in voluntary dumb mode. So instead of
blanket-disabling it, only disable it in the !have_fbo false case.
2017-09-30 19:03:34 +02:00
wm4 5597db7081 vf_vavpp: restrict allowed sw upload formats to nv12/yuv420p
We allowed any input format that was generally supported by libva, but
this is probably nonsense, as the actual surface format was always fixed
to nv12. We would have to check whether libva can upload a given pixel
format to a nv12 surface. Or we would have to use a separate frame pool
for input surfaces with the exact sw_format - but then we'd also need to
check whether the vaapi VideoProc supports the surface type.

Hardcode nv12 and yuv420p as input formats, which we know can be
uploaded to nv12 surfaces. In theory we could get a list of supported
upload formats from libavutil, but that also require allocating a dummy
hw frames context just for the query.

Add a comment to the upload code why we can allocate an output surface
for input.

In the long run, we'll probably want to use libavfilter's vaapi
deinterlacer, but for now this would break at least user options.
2017-09-30 16:22:16 +02:00
wm4 f3512686ee vaapi: replace error macro implementation
The current check_va_status() function could probably be argued to be
derived from the original VAAPI's patch check_status() function, thus
GPL-only. While I have my doubts that it applies to an idiom on this
level, it's better to replace it. Similar idea, different expression
equals no copyright association.

An earlier commit message promised this, but it was forgotten.
2017-09-30 16:07:00 +02:00
wm4 4516707848 Copyright: remove deleted file from list 2017-09-30 14:20:01 +02:00
wm4 b12b928221 video: fix green shit 2017-09-30 14:19:34 +02:00
Leo Izen 052ae5393a manpage: update --blend-subtitles affected options
Changed the reference from --gpu-gamma to --gamma-factor,
and changed the reference from --post-shader to --glsl-shaders,
in order to reflect actual changes to the option names.
2017-09-29 14:38:47 -04:00
wm4 e544c3f7b3 vaapi: change license to LGPL
Originally mpv vaapi support was based on the MPlayer-vaapi patches.
These were never merged in upstream MPlayer. The license headers
indicated they were GPL-only. Although the actual author agreed to
relicensing, the company employing him to write this code did not, so
the original code is unusable to us.

Fortunately, vaapi support was refactored and rewritten several times,
meaning little code is actually left. The previous commits removed or
moved that to GPL-only code. Namely, vo_vaapi.c remains GPL-only. The
other code went away or became unnecessary mainly because libavcodec
itself gained the ability to manage the hw decoder, and libavutil
provides code to manage vaapi surfaces. We also changed to mainly using
EGL interop, making any of the old rendering code unnecessary.

hwdec_vaglx.c is still GPL. It's possibly relicensable, because much of
it was changed, but I'm not too sure and further investigation would be
required. Also, this has been disabled by default for a while now, so
bothering with this is a waste of time. This commit simply disables it
at compile time as well in LGPL mode.
2017-09-29 18:44:47 +02:00
wm4 6a69e897ff vaapi: move legacy code to vo_vaapi.c
Done for license reasons. vo_vaapi.c is turned into some kind of
dumpster fire, and we'll remove it as soon as I'm mentally ready for
unkind users to complain about removal of this old POS.
2017-09-29 18:32:56 +02:00
wm4 3ca5977c1e vf_vavpp: use error checking macro 2017-09-29 18:19:33 +02:00
wm4 d462a2a321 vf_vavpp: use libavutil hw frames API for frame pool and upload
Another step to get rid of the legacy crap in vaapi.c. (Most is still
kept, because it's in use by vo_vaapi.c.)
2017-09-29 18:17:51 +02:00
wm4 1f79b26529 vaapi: use newer libavutil vaapi pixfmt name
AV_PIX_FMT_VAAPI_VLD is clearly deprecated - it just doesn't raise any
compiler warnings.
2017-09-29 17:53:00 +02:00
wm4 6265a2d779 vaapi: minor changes
This is for relicensing. Some of this code is loosely based on
vo_vaapi.c from the original MPlayer-vaapi patches. Most of the code has
changed, and only the initialization code and check_status() look
remotely similar. The initialization code is changed to be like Libav's
(hwcontext_vaapi.c). check_va_status() is just a C idiom, but to play it
safe, we'll either drop it from LGPL code (or recreate it).

vaapi.c still contains plenty of code from the original patches, but the
next commits will move them out of the LGPL code paths.
2017-09-29 16:51:30 +02:00
Niklas Haas f6fd2a05c4 vo_gpu: vulkan: reword comment
This is fixed upstream (and we now know it's a driver bug) so reword the
comment.
2017-09-29 00:48:39 +02:00
Niklas Haas 22311a767d vo_gpu: force layout std430 for PCs
Seems to be fixed upstream in the nvidia driver, so it's probably a good
idea to 1. force the layout and 2. remove the warning, as it now
actually works. Users with older drivers would run into errors, but they
can still use shaderc as a replacement. (And it's not like the old
status quo was any better)
2017-09-29 00:41:50 +02:00
Niklas Haas 07fa5c8a8f vo_gpu: fix --opengl-gamma redirect
It still pointed at --gpu-gamma, but we decided on --gamma-factor
instead.
2017-09-28 17:21:56 +02:00
Niklas Haas 791b9c4024 vo_gpu: set the correct number of vertex attribs
This was always set to the length of the VAO, but it should have been
set to the number of vertex attribs actually in use for this frame. No
idea how that managed to survive the test framework on nvidia/linux, but
ANGLE caught it.
2017-09-28 12:50:45 +02:00
James Ross-Gowan a65abe2447 vo_gpu: vulkan: add support for Windows 2017-09-28 10:02:22 +10:00
Niklas Haas 67fd5882b8 vo_gpu: make the vertex attribs dynamic
This has several advantages:

1. no more redundant texcoords when we don't need them
2. no more arbitrary limit on how many textures we can bind
3. (that extends to user shaders as well)
4. no more arbitrary limits on tscale radius

To realize this, the VAO was moved from a hacky stateful approach
(gl_sc_set_vertex_attribs) - which always bothered me since it was
required for compute shaders as well even though they ignored it - to be
a proper parameter of gl_sc_dispatch_draw, and internally plumbed into
gl_sc_generate, which will make a (properly mangled) deep copy into
params.vertex_attribs.
2017-09-28 01:54:38 +02:00
Niklas Haas 002a0ce232 vo_gpu: kill some static arrays
This gets rid of the hard-coded limits on the number of hooks, textures
and hook points.
2017-09-28 01:54:33 +02:00
wm4 77547d7c19 manpage: remove aphasemeter examples
Apparently this filter is broken in a weird way, which even makes some
libavfilter functions segfault in certain conditions. Don't waste time
with it and just remove the examples.

Also adjust the "life" example description (certainly this filter is
100% worthless, but the example does demonstrate how to use source
filters without any available input).
2017-09-27 16:23:59 +02:00
wm4 4582b8993d audio: fix channel conversion with NA channels
The case at hand was 5.1 -> fl-fr-fc-lfe-na-na (apparently triggered by
ALSA). That means only the NA channels have to be cleared, but the
result was actually that fc and lfe were cleared. This is due to a
simple regression in the reorder code, which quite obviously got the
index of the first NA channel wrong.
2017-09-27 16:22:06 +02:00
Niklas Haas 868bf4da7d vo_gpu: vulkan: indent queue family enumeration
Consistency
2017-09-27 00:46:20 +02:00
Niklas Haas 5b6b77b8dc vo_gpu: vulkan: normalize use of *Flags and *FlagBits
FlagBits is just the name of the enum. The actual data type representing
a combination of these flags follows the *Flags convention. (The
relevant difference is that the latter is defined to be uint32_t instead
of left implicit)

For consistency, use *Flags everywhere instead of randomly switching
between *Flags and *FlagBits.

Also fix a wrong type name on `stageFlags`, pointed out by @atomnuker
2017-09-27 00:25:18 +02:00
Niklas Haas 0ba6c7d73f vo_gpu: vulkan: optimize redundant pipeline barriers
Using renderpass layout transitions is more optimal and doesn't require
a redundant pipeline barrier.

Since our render passes are static and don't change throughout the
lifetime of a ra_renderpass, we unfortunately don't have much
flexibility here - so just hard-code SHADER_READ_ONLY_OPTIMAL as the
output format as this will be the most common case.

We also can't short-circuit the transition when we need to preserve the
framebuffer contents, since that depends on the current layout; so we
still use an explicit tex_barrier in this case. (Most optimal for this
scenario would be an input attachment anyway)
2017-09-26 23:50:01 +02:00
wm4 dc5fcced23 vd_lavc: cuda requires setting hw_device_ctx
This restores cuda/cuvid under Windows.

Cuvid is relatively useless under Windows, but this was requested.
2017-09-26 23:20:20 +02:00
wm4 2f5ba78a0b manpage: some --hwdec corrections
auto-copy selects more modes than the ones listed. It will always be
outdated anyway.

The GLX vaapi backend is never selected anymore, because it sucks.
2017-09-26 22:19:48 +02:00
wm4 9b60398f4e video: remove old videotoolbox support
Like as in previous commits, you need a very recent FFmpeg (probably git
master).
2017-09-26 19:13:26 +02:00
wm4 a730717281 wscript: remove redundant check
We're not using this function directly.
2017-09-26 19:00:55 +02:00
wm4 ae7db6503b video: drop old D3D11/DXVA2 support
Now you need FFmpeg git, or something.

This also gets rid of the last real use of gpu_memcpy(). libavutil does
that itself. (vaapi.c still used it, but it was essentially unused,
because the code path isn't really in use anymore. It wasn't even
included due to the d3d-hwaccel dependency in wscript.)
2017-09-26 18:58:45 +02:00
wm4 5d57e9b1be video: drop old cuda/cuvid hwaccel
Just use FFmpeg 3.3 (or whatever it was) to get Cuvid support.
2017-09-26 18:00:46 +02:00
Niklas Haas 83678f76b7 manpage: document --gpu-api=vulkan 2017-09-26 17:46:29 +02:00
Niklas Haas e569050fe4 vo_gpu: fix memleak in spirv.c 2017-09-26 17:32:36 +02:00
Niklas Haas a4e951e80c vo_gpu: explicitly label storage image formats
This is apparently required to get storage images working on
windows/vulkan, and probably good practice either way. Not entirely sure
if it's the best idea to be always storing the value as 32-bit float,
but it should hardly matter in practice (since we're only writing one
sample per thread).

(Leaving them implicit requires the shaderStorageImageWriteWithoutFormat
feature to be enabled, which the windows nvidia vulkan driver doesn't
support, at least not for a GTX 670)
2017-09-26 17:25:46 +02:00
Niklas Haas 47af509e1f vo_gpu: attempt to avoid UBOs for dynamic variables
This makes the radeon driver shut up about frequently updating
STATIC_DRAW UBOs (--opengl-debug), and also reduces the amount of
synchronization necessary for vulkan uniform buffers.

Also add some extra debugging/tracing code paths. I went with a
flags-based approach in case we ever want to extend this.
2017-09-26 17:25:35 +02:00
Niklas Haas ca85a153b4 vo_gpu: vulkan: add support for push constants
Can in theory avoid updating the uniform buffer every frame
2017-09-26 17:25:35 +02:00
Rostislav Pehlivanov ed345ffc2f vo_gpu: vulkan: add support for wayland 2017-09-26 17:25:35 +02:00
Niklas Haas 258487370f vo_gpu: vulkan: generalize SPIR-V compiler
In addition to the built-in nvidia compiler, we now also support a
backend based on libshaderc. shaderc is sort of like glslang except it
has a C API and is available as a dynamic library.

The generated SPIR-V is now cached alongside the VkPipeline in the
cached_program. We use a special cache header to ensure validity of this
cache before passing it blindly to the vulkan implementation, since
passing invalid SPIR-V can cause all sorts of nasty things. It's also
designed to self-invalidate if the compiler gets better, by offering a
catch-all `int compiler_version` that implementations can use as a cache
invalidation marker.
2017-09-26 17:25:35 +02:00
Niklas Haas 91f23c7067 vo_gpu: vulkan: initial implementation
This time based on ra/vo_gpu. 2017 is the year of the vulkan desktop!

Current problems / limitations / improvement opportunities:

1. The swapchain/flipping code violates the vulkan spec, by assuming
   that the presentation queue will be bounded (in cases where rendering
   is significantly faster than vsync). But apparently, there's simply
   no better way to do this right now, to the point where even the
   stupid cube.c examples from LunarG etc. do it wrong.
   (cf. https://github.com/KhronosGroup/Vulkan-Docs/issues/370)

2. The memory allocator could be improved. (This is a universal
   constant)

3. Could explore using push descriptors instead of descriptor sets,
   especially since we expect to switch descriptors semi-often for some
   passes (like interpolation). Probably won't make a difference, but
   the synchronization overhead might be a factor. Who knows.

4. Parallelism across frames / async transfer is not well-defined, we
   either need to use a better semaphore / command buffer strategy or a
   resource pooling layer to safely handle cross-frame parallelism.
   (That said, I gave resource pooling a try and was not happy with the
   result at all - so I'm still exploring the semaphore strategy)

5. We aggressively use pipeline barriers where events would offer a much
   more fine-grained synchronization mechanism. As a result of this, we
   might be suffering from GPU bubbles due to too-short dependencies on
   objects. (That said, I'm also exploring the use of semaphores as a an
   ordering tactic which would allow cross-frame time slicing in theory)

Some minor changes to the vo_gpu and infrastructure, but nothing
consequential.

NOTE: For safety, all use of asynchronous commands / multiple command
pools is currently disabled completely. There are some left-over relics
of this in the code (e.g. the distinction between dev_poll and
pool_poll), but that is kept in place mostly because this will be
re-extended in the future (vulkan rev 2).

The queue count is also currently capped to 1, because of the lack of
cross-frame semaphores means we need the implicit synchronization from
the same-queue semantics to guarantee a correct result.
2017-09-26 17:25:35 +02:00
Niklas Haas c82022f349 vo_opengl_cb: fix deprecated option usage
opengl-debug was renamed to gpu-debug
2017-09-26 17:24:39 +02:00
Niklas Haas 89cdccfa6c vo_gpu: fix possible segfault on shader miscompile
Iterations after the first time will fail to realize that the pass was
never created. This function's logic and control flow is so annoying...
2017-09-23 16:36:58 +02:00
Avi Halachmi (:avih) 365b1d4f3d osc: fix rare stack overflow when changing visibility mode
Under some conditions, hide_osc() was calling render(), which then called
hide_osc() again, and so forth, until the stack overflows.

Tracking the exact conditions where this happens (and then managing them
to prevent it) is an excercise in futility.

Remove the osc directly - instead of going through the entire rendering
procedure just to end up rendering nothing.

Fixes #4900 .
2017-09-23 14:41:17 +03:00
Avi Halachmi (:avih) 2dd2acac89 js: fix broken mp.set_property_number, mp.set_property_native
Also implicitly fixes memory leak when mp.set_property_native was used,
because the cleanup did not expect more allocations from the accidental
use of mpv_get_property.
2017-09-23 14:41:17 +03:00
James Ross-Gowan 3d119a0e41 vo_gpu: angle: fix misleading struct name
This should have been renamed when it stopped being empty.
2017-09-23 18:33:33 +10:00
Niklas Haas b0ba193b66 vo_gpu: handle texture initialization errors gracefully
Tested by making the ra_tex_resize function always fail (apart from the
initial FBO check). This required a few changes:

1. reset shaders on failed dispatch
2. reset cleanup binds on failed dispatch
3. fall back to initializing the struct image to 1x1 on failure
4. handle output_fbo_valid gracefully
2017-09-23 09:58:27 +02:00
Niklas Haas f3ec494613 vo_gpu: reduce the --alpha=blend-tiles checkerboard intensity
This was sort of grating by default and made it really hard to actually
read e.g. text on top of a transparent background. I decided to approach
the problem from both directions, making the whites darker and the grays
lighter. This brings it closer to the dynamic range of e.g. the
wikipedia transparent svg preview.
2017-09-22 21:14:27 +02:00
Niklas Haas e3288c4597 vo_gpu: simplify compute shader coordinate calculation
Since the removal of FBOTEX_FUZZY, this can be made slightly simpler.
2017-09-22 17:22:53 +02:00
Niklas Haas 62ddc85d17 vo_gpu: simplify structs / names
Due to the plethora of historical baggage from different eras getting
confusing, I decided to simplify and unify the struct organization and
naming scheme.

Structs that got renamed:

1. fbodst     -> ra_fbo  (and moved to gpu/context.h)
2. fbotex     -> removed (redundant after 2af2fa7a)
3. fbosurface -> surface
4. img_tex    -> image

In addition to these structs being renamed, all of the names have been
made consistent. The new scheme is as follows:

struct image img;
struct ra_tex *tex;
struct ra_fbo fbo;

This also affects derived names, e.g. indirect_fbo -> indirect_tex.
Notably also, finish_pass_fbo -> finish_pass_tex and finish_pass_direct
-> finish_pass_fbo.

The new equivalent of fbotex_change() is called ra_tex_resize().

This commit (should) contain no logic changes, just renaming a bunch of
crap.
2017-09-22 16:58:55 +02:00
Niklas Haas 2af2fa7a27 vo_gpu: kill off FBOTEX_FUZZY
I've observed the garbage pixels in more scenarios. They also were never
really needed to begin with, originally being a discovered work-around
for bug that we fixed since then anyway. Doesn't really seem to even
help resizing, since the OpenGL drivers are all smart enough to pool
resources internally anyway.

Fixes #1814
2017-09-22 16:33:25 +02:00
James Ross-Gowan fab0448c5e Revert "cocoa: re-enable double buffering"
Enabling double buffering fixed some graphical glitches when entering
fullscreen, but it also caused a fullscreen performance regression. We
decided that the glitches were preferable to the performance regression.

This reverts commit cee764849e.
2017-09-22 23:08:46 +10:00
James Ross-Gowan 1d5620a658 vo_gpu: override ra_swapchain_fns for the d3d11 surface
ANGLE can take advantage of some of these when using the external
swapchain-backed surface.
2017-09-22 14:22:14 +02:00
Niklas Haas aabe12b0bc vo_gpu: opengl: fix possible screenshot window crash
gl_read_fbo_contents can fail

Fixes #4905
2017-09-22 14:20:22 +02:00
Niklas Haas d325f30fb5 vo_opengl_cb: fix segfault on uninit
The code used ra_ctx_destroy even though ra_ctx_create was never called
(since it's just a dummy ctx), which led to a conflict of assumptions.
The proper fix is to only use ra_gl_ctx_uninit (mirroring the
ra_gl_ctx_init) and free the dummy ctx manually.

Fixes https://github.com/cmdrkotori/mpc-qt/issues/129
2017-09-22 14:20:11 +02:00
wm4 0b5c1d2912 m_config: better variable name 2017-09-22 11:31:23 +02:00
wm4 fba927de41 options: properly handle deprecated options with CLI actions
We want e.g. --opengl-shaders-append=foo to resolve to the new option,
all while printing an option name. --opengl-shader is a similar case.
These options are special, because they apply "actions" on actual
options by specifying a suffix. So the alias/deprecation handling has to
be part of resolving the actual option from prefix and suffix.
2017-09-22 11:31:03 +02:00
sfan5 acfd1a1929 android: posix_spawn(p) replacement
Signed-off-by: wm4 <wm4@nowhere>
2017-09-22 09:24:19 +02:00
orbea c09760d948 build: fix build for waf 2.0
Thanks to ita1024 for the patch.

Fixes https://github.com/mpv-player/mpv/issues/4894

Signed-off-by: wm4 <wm4@nowhere>
2017-09-22 09:14:37 +02:00
wm4 baffe6bcbc vo_gpu: fix autoprobing message 2017-09-22 05:37:54 +02:00
wm4 2b5da4804c build: make vo_gpu + infrastructure non-optional
Also readd the the error message for when no GL backends are found (why
was this removed?).
2017-09-22 05:35:26 +02:00
wm4 2b855739d5 vd_lavc: revert accidental vaapi changes revert
Commit bfa9b62858 accidentally reverted these (because my editor did
not reload the file correctly).

Fixes #4904.
2017-09-22 05:19:37 +02:00
Aman Gupta 6254b6d637 vo_opengl_cb: hwdec_ios: fix build
[179/188] Compiling video/out/vo_lavc.c
../../video/out/opengl/hwdec_ios.m:135:9: warning: unused variable 'gl' [-Wunused-variable]
    GL *gl = ra_gl_get(mapper->ra);
        ^
../../video/out/opengl/hwdec_ios.m:247:48: warning: incompatible pointer to integer conversion passing 'CVOpenGLESTextureRef' (aka 'struct __CVBuffer *') to parameter of type 'GLuint' (aka 'unsigned int') [-Wint-conversion]
                                               p->gl_planes[i]);
                                               ^~~~~~~~~~~~~~~
../../video/out/opengl/ra_gl.h:9:45: note: passing argument to parameter 'gl_texture' here
                                     GLuint gl_texture);
                                            ^
2 warnings generated.
2017-09-22 05:03:52 +02:00
Niklas Haas 52789d6ca0 vo_gpu: fix vo=opengl legacy alias
Turns out the option code apparently tries to directly talloc_free() the
allocated strings, instead of going through a tactx wrapper or
something. So we can't directly overwrite it. Do something else
instead..
2017-09-21 16:13:52 +02:00
Niklas Haas aefd7a90c9 vo_gpu: fix memleak in ra_gl_ctx
The ctx->ra was never freed propely, nor was p->wrapped_fb.

(TIL: MPV_LEAK_REPORT exists)
2017-09-21 15:51:47 +02:00
Niklas Haas b940691784 vo_gpu: drop the RA_CAP_NESTED_ARRAY req from EWA compute
Almost as fast as the old code, but more general. Notably, glslang
doesn't support nested arrays.

(cf. https://github.com/KhronosGroup/glslang/issues/1057)

Also much cleaner code-wise, so I think I'll keep it even if glslang
implements array_of_arrays.
2017-09-21 15:15:59 +02:00
Niklas Haas 03fee22c4d wayland: allow vo_wayland_uninit(NULL) 2017-09-21 15:15:55 +02:00
Niklas Haas 28b2fa4b7e vo_gpu: fix possible segfault in shader_cache.c
If shader compilation fails in an unexpected way, it can end up calling
renderpass_run on an invalid pass, since current_shader is never cleared.
2017-09-21 15:15:15 +02:00
Niklas Haas db0fb3c48b vo_gpu: fix gamma scale
This never really made sense since the BT.1886 changes. It should get
*brighter* for bright rooms, not darker for dark rooms. Picked some new
values that seemed reasonable-ish.
2017-09-21 15:01:26 +02:00
Niklas Haas 61f5c423be vo_gpu: fix comment on ra_buf_type
This hasn't been true for several iterations of this API.
2017-09-21 15:01:22 +02:00
Niklas Haas e92effb14f vo_gpu: describe the plane merging pass
This can get left unknown if something hooks NATIVE
2017-09-21 15:01:22 +02:00
James Ross-Gowan cee764849e cocoa: re-enable double buffering
This causes a performance regression on 10.11 and newer, but the single
buffered method was broken and could cause partially rendered frames to
be presented to the screen.

This reverts 9f30cd8292 and
e543853a7f.
2017-09-21 15:01:22 +02:00
James Ross-Gowan 75c0c06640 vo_gpu: convert windows/osx hwdecs/contexts to new API 2017-09-21 15:01:17 +02:00
Niklas Haas 65979986a9 vo_opengl: refactor into vo_gpu
This is done in several steps:

1. refactor MPGLContext -> struct ra_ctx
2. move GL-specific stuff in vo_opengl into opengl/context.c
3. generalize context creation to support other APIs, and add --gpu-api
4. rename all of the --opengl- options that are no longer opengl-specific
5. move all of the stuff from opengl/* that isn't GL-specific into gpu/
   (note: opengl/gl_utils.h became opengl/utils.h)
6. rename vo_opengl to vo_gpu
7. to handle window screenshots, the short-term approach was to just add
   it to ra_swchain_fns. Long term (and for vulkan) this has to be moved to
   ra itself (and vo_gpu altered to compensate), but this was a stop-gap
   measure to prevent this commit from getting too big
8. move ra->fns->flush to ra_gl_ctx instead
9. some other minor changes that I've probably already forgotten

Note: This is one half of a major refactor, the other half of which is
provided by rossy's following commit. This commit enables support for
all linux platforms, while his version enables support for all non-linux
platforms.

Note 2: vo_opengl_cb.c also re-uses ra_gl_ctx so it benefits from the
--opengl- options like --opengl-early-flush, --opengl-finish etc. Should
be a strict superset of the old functionality.

Disclaimer: Since I have no way of compiling mpv on all platforms, some
of these ports were done blindly. Specifically, the blind ports included
context_mali_fbdev.c and context_rpi.c. Since they're both based on
egl_helpers, the port should have gone smoothly without any major
changes required. But if somebody complains about a compile error on
those platforms (assuming anybody actually uses them), you know where to
complain.
2017-09-21 15:00:55 +02:00
wm4 20f958c977 audio: fix resampling
Let's blame FFmpeg for just overwriting the samplerate in
av_frame_copy_props(). Can't fully hide my own brain damage though,
since mp_aframe_config_copy() expected that the rate is copied (that
function also copies format and channel layout).
2017-09-21 14:34:50 +02:00
wm4 bfa9b62858 build: add preliminary LGPL mode
See "Copyright" file for caveats.

This changes the remaining "almost LGPL" files to LGPL, because we think
that the conditions the author set for these was finally fulfilled.
2017-09-21 13:56:27 +02:00
wm4 fdb300b983 audio: make libaf derived code optional
This code could not be relicensed. The intention was to write new filter
code (which could handle both audio and video), but that's a bit of
work. Write some code that can do audio conversion (resampling,
downmixing, etc.) without the old audio filter chain code in order to
speed up the LGPL relicensing.

If you build with --disable-libaf, nothing in audio/filter/* is compiled
in. It breaks a few features, such as --volume, --af, pitch correction
on speed changes, replaygain.

Most likely this adds some bugs, even if --disable-libaf is not used.
(How the fuck does EOF notification work again anyway?)
2017-09-21 12:48:30 +02:00
wm4 3a2d5e68ac audio: move libswresample wrapper out of audio filter code
Move it from af_lavrresample.c to a new aconverter.c file, which is
independent from the filter chain code. It also doesn't use mp_audio,
and thus has no GPL dependencies.

Preparation for later commits. Not particularly well tested, so have
fun.
2017-09-21 12:42:09 +02:00
wm4 caaa1189ba audio_buffer: remove dependency on mp_audio
Just reimplement it in some way, as mp_audio is GPL-only.

Actually I wanted to get rid of audio_buffer.c completely (and instead
have a list of mp_aframes), but to do so would require rewriting some
more player core audio code. So to get this LGPL relicensing over
quickly, just do some extra work.
2017-09-21 04:10:19 +02:00
wm4 a4de782272 mp_image: don't guess colorspace params in mp_image_copy_attributes()
This is "wrong", because you might want mp_image_copy_attributes() to
preserve the information that the colorspace parameters are unknown.
This is important for hwdec -copy modes, which call this function before
fix_image_params() and mp_colorspace_merge() are called.

Instead, just wipe the colorspace attributes if the pixel format changes
in an apparently incompatible way. Use mp_image_params_guess_csp() logic
for this and factor that into its own function.

mp_image_set_attributes() attempts to do something similar, so change
that in the same way. Also, mp_image_params_guess_csp() just returned if
the imgfmt was invalid or unset - just remove that part, because it
annoyingly doesn't fit into the new code, and had little reason to exist
to begin with. (Probably.)
2017-09-19 19:20:27 +02:00
wm4 06927fefdd mp_image: always copy pixel aspect ratio
I see no reason not to do this. I think the check comes from the time
when mp_image stored the image aspect ratio, instead of the pixel aspect
ratio, where the logic might have made more sense.
2017-09-19 19:04:47 +02:00
wm4 810990a746 mp_image: always copy color attributes on hw download
It was noticed that -copy hwdec modes typically dropped the
chroma_location field. This happened because the attributes on hw
download are copied with mp_image_copy_attributes(), which tries to copy
these parameters only if src and dst were both YUV (in an attempt to
copy parameters only if it makes sense).

But hardware formats did not have the YUV flag set (anymore?), and code
shouldn't attempt to check the flag in this way anyway. Drop the check,
and always copy the whole color metadata struct. There is a call to
mp_image_params_guess_csp() below, which tries to unset nonsense
metadata if it was copied from a YUV format to RGB. This function would
also do the right thing for hw formats (although for the cited bug only
the software case matters).

Fixes #4804.
2017-09-19 18:59:01 +02:00
wm4 0169da86df build: remove some dead code 2017-09-19 18:37:11 +02:00
wm4 b881881dbd Revert "vd_lavc: change auto-probe order to prefer cuda over vdpau-copy"
This reverts commit 96462040ec.

I guess the autoprobing is still too primitive to handle this well. What
it really should be trying is initializing the wrapper decoder, and if
that doesn't work, try another method. This is complicated by hwaccels
initializing in a delayed way, so there is no easy solution yet.

Probably fixes #4865.
2017-09-19 18:35:29 +02:00
wm4 80e3173aa1 options: remove --heartbeat-cmd and --heartbeat--interval
This mechanism uses system() and shouldn't even exist. x11_common.c has
its own solution for the original problem (disabling Linux DE
screensavers without MPlayer/mpv having to link a dbus lib). If that is
not sufficient, you can create a simple Lua script.

Incidentally fixes #4888.
2017-09-18 22:54:03 +02:00
wm4 6b013133e5 RELEASE_NOTES: remove old releases
I'm not going to let this file grow forever.
2017-09-18 22:49:20 +02:00
wm4 acb28e922b build: use unified dependency expressions instead of weird fields
Instead of "deps", "deps_neg", and "deps_any" fields, just have a single
"deps" field, which changes from an array to a string. The string is now
an expression, which can contain the operators &&, ||, !, and allows
grouping with ( ).

It's probably overkill. If it gets a maintenance burden, we can switch
to specifiying the dep expressions as ASTs (or maybe eval()-able Python
expressions), and we could simplify the code that determines the reason
why a dependency is not fulfilled. The latter involves a complicated
conversion of the expression AST to DNF.

The parser is actually pretty simple, and pretty much follows:
https://en.wikipedia.org/wiki/Shunting_yard_algorithm
2017-09-18 22:35:37 +02:00
Jan Ekström f4c80d4402 osdep/io: add android related bullshit
This fixes >2GiB files with at least API level 21.
See: https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md
for the gritty details.

* Based on libavformat's things, except we do not care about API
  versions or NDKs without unistd.h, which contains all sorts of
  things that we utilize.
* Redefines lseek to always point to the 64bit version.
* Redefines fseeko to always point towards an inlined static
  implementation that utilizes the 64bit version of lseek underneath.
2017-09-18 20:28:46 +03:00
Ilya Tumaykin 8810c1fc05 build: remove duplicate android option after 72a8120da
The first one (line 140) comes from 69650851f8 and is the correct one.
The second one (line 731) comes from 72a8120daa and slipped in with the
revert commit.

Remove the second one.
2017-09-17 21:54:37 +03:00
Niklas Haas 2f41b834b3 vo_opengl: make the ra_renderpass names consistent
The random space kept screwing me over
2017-09-13 20:53:19 +02:00
Niklas Haas 293c696ddb vo_opengl: use GLX_MESA_swap_control where available
This overrides the use of GLX_SGI_swap_control, because apparently
GLX_SGI_swap_control doesn't support SwapInterval(0), but the
GLX_MESA_swap_interval does.

Of course, everybody except mesa just accepts SwapInterval(0) even for
GLX_SGI_swap_control, but mesa needs to be the special snowflake here
and reject it, forcing us to load their stupid named extension instead.

Meanwhile khronos has done nothing except spit out GLX_EXT_swap_control
(not to be confused with GL_EXT_swap_control, which is exported by
WGL_EXT_swap_control), that doesn't fix the problem because mesa doesn't
implement it anyway.

What a fucking mess.
2017-09-13 20:53:17 +02:00
Martin Herkt 67d1ec8fad Update VERSION 2017-09-13 03:42:28 +02:00
Martin Herkt d18f7bb8cd Release 0.27.0 2017-09-13 03:40:14 +02:00
Niklas Haas 0bb67b1055 vo_opengl: always initialize uniforms on first use
Even if the contents are entirely zero. In the current code, these
entries were left uninitialized. (Which always worked for nvidia - but
randomly blew up for AMD)
2017-09-12 03:00:47 +02:00
Niklas Haas 0c2cb69597 vo_opengl: generalize UBO packing/handling
This is simultaneously generalized into two directions:
1. Support more sc_uniform types (needed for SC_UNIFORM_TYPE_PUSHC)
2. Support more flexible packing (needed for both PUSHC and ra_d3d11)
2017-09-12 02:57:45 +02:00
Niklas Haas 3faf1fb0a4 vo: avoid putting large voctrl_performance_data on stack
This is around 512 kB, which is just way too much. Heap-allocate it
instead. Also cut down the max pass count to 64, since 128 was
unrealistically high even for vo_opengl.
2017-09-11 18:20:18 +02:00
Niklas Haas 71c25df5e6 vo_opengl: refactor timer_pool_measure (again)
Instead of relying on power-of-two buffer sizes and unsigned overflow,
make this code more robust (and also cleaner).

Why can't C get a real modulo operator?
2017-09-11 02:42:50 +02:00
Niklas Haas 8a4f2f0ac0 vo_opengl: fix out-of-bounds access in timer_pool_measure
This was there even before the refactor, but the refactor exposed the
bug. I hate C's useless fucking modulo operator so much. I've gotten hit
by this exact bug way too many times.
2017-09-11 02:07:04 +02:00
Niklas Haas 0fe4a492c4 vo_opengl: fix out-of-bounds read in update_uniform
Since the addition of UBOs, the assumption that the uniform index
corresponds to the pass->params.inputs index is no longer true. Also,
there's no reason it would even need this - since the `input` is also
available directly in sc_uniform.

I have no idea how I've been using this code for as long as I have
without any segfaults until earlier today.
2017-09-11 01:04:08 +02:00
Niklas Haas 1da53248ab vo_opengl: refactor/fix mp_pass_perf code
This was needlessly complicated and prone to breakage, because even the
references to the ring buffer could end up getting invalidated and
containing garbage data on e.g. shader cache flush. For much the same
reason why we can't keep around the *timer_pool, we're also forced to
hard-copy the entire sample buffer per pass per frame.

Not a huge deal, though. This is, what, a few kB per frame? We have more
pressing CPU performance concerns anyway.

Also simplified/fixed some other code.
2017-09-11 00:35:23 +02:00
Niklas Haas d0c87dd579 vo_opengl: add a gamut warning feature
This clearly highlights all out-of-gamut/clipped pixels. (Either too
bright or too saturated)

Has some (documented) caveats. Also make TONE_MAPPING_CLIP stop actually
clamping the value range (it's unnecessary and breaks this feature).
2017-09-10 18:19:46 +02:00
Martin Herkt b19b0869d6 man: correct default for --audio-file-auto
Fixes #4851
2017-09-10 07:05:33 +02:00
Akemi 9cb7f87b86 osx: fix media keys input when other Apps steal the priority
other Apps do the same as mpv and tap into the global event chain.
events that are handled are not being propagated down the event chain.
that can lead to mpv not getting any media key events anymore when they
are held back by other Apps. we will just move mpv back to the top of
the event list when mpv is refocused and is not at the top of the list
any more.

Fixes #4834
2017-09-07 20:42:26 +02:00
Niklas Haas 5771f7abf4 vo_opengl: add support for vulkan GLSL dialect
Redefining texture1D / texture3D seems to be illegal, they are already
built-in macros or something. So just use tex1D and tex3D instead.

Additionally, GL_KHR_vulkan_glsl requires using explicit vertex
locations and bindings, so make some changes to facilitate this. (It
also requires explicitly setting location=0 for the color attachment
output)
2017-09-04 13:53:23 +02:00
Niklas Haas 62f0677614 vo_opengl: use rgba16 for 3DLUTs instead of rgb16
Vulkan compat. rgb16 doesn't exist on hardware anyway, might as well
just generate the 3DLUT against rgba16 as well. We've decided this is
the simplest way to do vulkan compatibility: just make sure we never
actually need 3-component textures.
2017-09-04 13:53:14 +02:00
Niklas Haas 8cf5799ab1 vo_opengl: refactor scaler LUT weight packing/loading
This is mostly done so we can support using textures with more
components than the scaler LUTs have entries. But while we're at it,
also change the way the weights are packed so that they're always
sequential with no gaps. This allows us to simplify
pass_sample_separated_get_weights as well.
2017-09-04 13:53:14 +02:00
Niklas Haas f589a3bd78 vo_opengl: scale deband-grain to the signal range
This prevents blowing up for high dynamic range sources, where a noise
level of 48 can suddenly mean 4800.
2017-09-03 21:51:48 +02:00
James Ross-Gowan 9a28088e74 filter_kernels: correct spline64 kernel
This seems to have had some copy/paste errors. It should now match the
implementation in fmtconv:
https://github.com/EleonoreMizo/fmtconv/blob/00453a86dd73/src/fmtcl/ContFirSpline64.cpp#L58-L76
2017-09-03 21:18:06 +02:00
Ricardo Constantino d280b3db93 ytdl_hook: resolve relative paths when joining segment urls
FFmpeg/mpv don't do it automatically.
See #4827
2017-09-03 13:42:51 +01:00
wm4 181b071431 audio: fix format change regression
Ever since the mp_aframe change, audio mid-stream format changes crash.
I have no idea why the recent mp_aframe change triggers this. Didn't
look too deeply into it either. It appears to work now, though.

Fixes #4828.
2017-09-03 13:09:49 +02:00
James Ross-Gowan 650d4e3401 input: fix error in MP_KEY_IS_WHEEL
Whoops.
2017-09-03 20:46:06 +10:00
James Ross-Gowan 7897f79217 input: merge mouse wheel and axis keycodes
Mouse wheel bindings have always been a cause of user confusion.
Previously, on Wayland and macOS, precise touchpads would generate AXIS
keycodes and notched mouse wheels would generate mouse button keycodes.
On Windows, both types of device would generate AXIS keycodes and on
X11, both types of device would generate mouse button keycodes. This
made it pretty difficult for users to modify their mouse-wheel bindings,
since it differed between platforms and in some cases, between devices.

To make it more confusing, the keycodes used on Windows were changed in
18a45a42d5 without a deprecation period or adequate communication to
users.

This change aims to make mouse wheel binds less confusing. Both the
mouse button and AXIS keycodes are now deprecated aliases of the new
WHEEL keycodes. This will technically break input configs on Wayland and
macOS that assign different commands to precise and non-precise scroll
events, but this is probably uncommon (if anyone does it at all) and I
think it's a fair tradeoff for finally fixing mouse wheel-related
confusion on other platforms.
2017-09-03 20:31:44 +10:00
James Ross-Gowan 8fe4aa94ee cocoa: fix button numbering for back/forward
It seems like the Cocoa backend used to return the same mpv keycodes for
mouse back/forward as it did for scrolling up and down. Fix this by
explicitly mapping all Cocoa button numbers to the right mpv keycodes.
2017-09-03 20:31:44 +10:00
James Ross-Gowan 957e9a37db input: use mnemonic names for mouse buttons
mpv's mouse button numbering is based on X11 button numbering, which
allows for an arbitrary number of buttons and includes mouse wheel input
as buttons 3-6. This button numbering was used throughout the codebase
and exposed in input.conf, and it was difficult to remember which
physical button each number actually referred to and which referred to
the scroll wheel.

In practice, PC mice only have between two and five buttons and one or
two scroll wheel axes, which are more or less in the same location and
have more or less the same function. This allows us to use names to
refer to the buttons instead of numbers, which makes input.conf syntax a
lot easier to remember. It also makes the syntax robust to changes in
mpv's underlying numbering. The old MOUSE_BTNx names are still
understood as deprecated aliases of the named buttons.

This changes both the input.conf syntax and the MP_MOUSE_BTNx symbols in
the codebase, since I think both would benefit from using names over
numbers, especially since some platforms don't use X11 button numbering
and handle different mouse buttons in different windowing system events.

This also makes the names shorter, since otherwise they would be pretty
long, and it removes the high-numbered MOUSE_BTNx_DBL names, since they
weren't used.

Names are the same as used in Qt:
https://doc.qt.io/qt-5/qt.html#MouseButton-enum
2017-09-03 20:31:44 +10:00
wm4 449d9725c9 stream_lavf: use avio_read_partial()
Possibly improves latency and such things.
2017-09-01 17:59:03 +02:00
wm4 9f0e358827 vo_opengl: fix overlay mode (again)
Did I mention yet that I regret this overlay mode thing?
2017-08-30 12:19:32 +02:00
wm4 96462040ec vd_lavc: change auto-probe order to prefer cuda over vdpau-copy
This aims at making --opengl-hwdec-interop=cuda --hwdec=yes select the
correct decoding mode: cuda instead of vdpau-copy.
2017-08-30 12:08:40 +02:00
wm4 93d40ac480 DOCS/contribute.md: coding style exception 2017-08-30 10:34:16 +02:00
wm4 a9571fcc0f vo_opengl: don't discard buffered video on redundant resize calls
If a VO-area option changes, gl_video_resize() is called
unconditionally. This function does something even if the size does not
change (at least it discards buffered frames for interpolation), which
can lead to stutter when you keep firing option change events during
playback.

Check for an actual resize, and if nothing changes, exit early.
2017-08-29 15:15:34 +02:00
wm4 a46500a2c8 vo_opengl: don't assume imgfmt=0 is valid
Could cause a crash if anything called ra_get_imgfmt_desc(imgfmt=0). Let
it fail correctly. This can happen if a hwdec backend does not set
hw_subfmt correctly.
2017-08-29 15:05:32 +02:00
Niklas Haas cc79d48d22 vo_opengl: fix the renderpass target format at creation time
Required for vulkan.
2017-08-27 14:37:47 +02:00
Niklas Haas 7baa18d5f8 vo_opengl: fix misleading comment in ra.h
tex_upload is not just for buffers
2017-08-27 14:36:28 +02:00
Niklas Haas 1d47473a7b vo_opengl: use UBOs where supported/required
This also introduces RA_CAP_GLOBAL_UNIFORM. If this is not set, UBOs
*must* be used for non-bindings. Currently the cap is ignored though,
and the shader_cache *always* generates UBO-using code where it can.
Could be made an option in principle.

Only enabled for drivers new enough to support explicit UBO offsets,
just in case...

No change to performance, which is probably what we expect.
2017-08-27 14:36:04 +02:00
Niklas Haas 136cf2b770 vo_opengl: add support for UBOs
Not actually used by anything yet, but straightforward enough to add to
the RA API for starters.
2017-08-27 14:36:00 +02:00
Niklas Haas 8404a354e5 vo_opengl: clarify RA_CAP_DIRECT_UPLOAD
This no longer concerns the API user except in as much as the API user
probably wants to know whether or not PBOs are active, so keep around
the CAP field even though it's mostly useless now.
2017-08-27 14:36:00 +02:00
Niklas Haas 7684fda6ac vo_opengl: refactor shader_cache binding
There's no reason to be needlessly wasteful with our binding points
here. Just add a CAP for it.
2017-08-27 14:36:00 +02:00
Niklas Haas 45bae90f4d vo_opengl: be explicit about IMG_RW
Both vulkan and opengl distinguish between rendering to an image and
using an image as a storage attachment. So make this an explicit
capability instead of lumping it in with render_dst. (That way we could
support, for example, using an image as a storage attachment without
requiring a framebuffer)

The real reason for this change is that you can directly use the output
FBO as a storage attachment on vulkan but you can't on opengl, which
makes this param structly separate from render_dst.
2017-08-27 14:36:00 +02:00
Niklas Haas f40717a664 vo_opengl: use size_t offset for vertex offsets
I don't like the feeling of "reusing" the int binding for this. It
feels... wrong, somehow. I'd prefer to use an explicit "offset" field.
(Plus, I might re-use this for uniform buffers or something)

YMMV
2017-08-27 14:36:00 +02:00
Akemi d355cb618c osx: fix build on macOS 10.11 and earlier
98f5579 added a safeguard for the deactivation of the automatic tab bar
but it still needs a compile time guard. add a forward declaration for
the setAllowsAutomaticWindowTabbing method of NSWindow.

Fixes #4783
2017-08-26 11:42:50 +02:00
James Ross-Gowan eacd97d536 mp_image: include config.h directly
This is needed for HAVE_SSE4_INTRINSICS. config.h used to be included as
a transitive dependency of vf.h, but the include statement was removed
from vf.h in 8f2ccba71b.

Also silence an unused variable warning that was introduced in the same
commit.
2017-08-26 00:41:04 +10:00
James Ross-Gowan 9aa091615e video: increase --monitorpixelaspect range
Some people use very wide display modes such as 3840x240 with their CRT
televisions because it lessens scaling artifacts in video game
emulators. When using a 3840x240 display mode on a 4:3 CRT television,
the pixel aspect ratio is 1:12, so in order to watch a video with mpv on
the same television without changing the display mode, the user should
use --monitorpixelaspect=1:12.

Unfortunately, 1:12 (or 0.083) was out of range for the
--monitorpixelaspect option. There was no good reason for this, so
extend the range of the option to 1:32-32:1 (0.03125-32,) which should
be more than enough to support "super-wide" display modes like these.

This is related to #4483, but it doesn't fix the issue (which was to do
with subtitle rendering.)
2017-08-26 00:40:11 +10:00
wm4 68dc7d1695 vo_opengl: allow selection of true 32 bit float if float16 unavailable
Shouldn't make a difference for OpenGL (even with the weird duplication
of these functions removed). Might be useful for the WIP vulkan backend.
2017-08-24 22:44:41 +02:00
wm4 ecef999d19 vd_lavc: work around some more idiotic FFmpeg nonsense
Like in commit bd356333c7, but for the other hwaccels as well.

Fixes #4794.
2017-08-24 11:35:17 +02:00
wm4 b62150bd6b command: restore OSD marker for video equalizer properties
Commit 03cf150ff3 accidentally dropped these. Readd them in a simpler
way (so only a property_osd_display[] entry is enough). This commit
doesn't actually touch the video equalizer properties, because the
default value of 0 for the marker is what they require anyway.
2017-08-23 14:23:37 +02:00
wm4 60ba7eebd7 vd_lavc: fix mid-stream hwdec fallback
Not resetting hwdec_request_reinit caused it to flush on every packet,
which not only caused it to fail triggering the actual fallback, and let
it never decode a new frame, but also to get stuck on EOF.
2017-08-23 14:02:44 +02:00
wm4 997e1fb621 audio: fix spdif mode
Not sure how this was not caught before. It crashed when trying to use
spdif mode.
2017-08-23 12:14:11 +02:00
wm4 f6c4e4ab76 DOCS/interface-changes.rst: don't suggest @deinterlace label
--vf-defaults always applies, and the label is ignored. So don't suggest
using it, it would be misleading.
2017-08-23 12:11:56 +02:00
wm4 8f2ccba71b video: change --deinterlace behavior
This removes all GPL only code from it, and that's the whole purpose.
Also happens to be much simpler.

The "deinterlace" option still sort of exists, but only as runtime
changeable option. The main change in behavior is that the property will
not report back the actual deint state. Or in other words, if inserting
or initializing the filter fails, the deinterlace property will still
return "yes". This is in line with most recent behavior changes to
properties and options.
2017-08-22 19:08:07 +02:00
wm4 0c88b661f9 manpage: video equalizer properties now behave differently
No more special behavior.
2017-08-22 18:28:21 +02:00
wm4 ab39518719 manpage: remove removed "osd" command
Someone pointed this out on github.
2017-08-22 17:33:30 +02:00
wm4 1b2185657f vo_direct3d: fix build
Broken by previous commit. Fix completely untested.
2017-08-22 17:32:05 +02:00
wm4 03cf150ff3 video: redo video equalizer option handling
I really wouldn't care much about this, but some parts of the core code
are under HAVE_GPL, so there's some need to get rid of it. Simply turn
the video equalizer from its current fine-grained handling with vf/vo
fallbacks into global options. This makes updating them much simpler.

This removes any possibility of applying video equalizers in filters,
which affects vf_scale, and the previously removed vf_eq. Not a big
loss, since the preferred VOs have this builtin.

Remove video equalizer handling from vo_direct3d, vo_sdl, vo_vaapi, and
vo_xv. I'm not going to waste my time on these legacy VOs.

vo.eq_opts_cache exists _only_ to send a VOCTRL_SET_EQUALIZER, which
exists _only_ to trigger a redraw. This seems silly, but for now I feel
like this is less of a pain. The rest of the equalizer using code is
self-updating.

See commit 96b906a51d for how some video equalizer code was GPL only.
Some command line option names and ranges can probably be traced back to
a GPL only committer, but we don't consider these copyrightable.
2017-08-22 17:01:35 +02:00
wm4 d67aa6da6b vf_eq: remove this filter
Both the video equalizer command/option glue, which drives this filter,
as well as the filter itself are slightly GPL contaminated. So it goes.

After this commit, "--vf=eq" will actually use libavfilter's vf_eq (if
FFmpeg was compiled in GPL mode), but it has different options and will
not listen to the equalizer VOCTRLs.
2017-08-22 15:58:49 +02:00
wm4 d2bdb72b69 options: add a thread-safe way to notify option updates
So far, we had a thread-safe way to read options, but no option update
notification mechanism. Everything was funneled though the main thread's
central mp_option_change_callback() function. For example, if the
panscan options were changed, the function called vo_control() with
VOCTRL_SET_PANSCAN to manually notify the VO thread of updates. This
worked, but's pretty inconvenient. Most of these problems come from the
fact that MPlayer was written as a single-threaded program.

This commit works towards a more flexible mechanism. It adds an update
callback to m_config_cache (the thing that is already used for
thread-safe access of global options).

This alone would still be rather inconvenient, at least in context of
VOs. Add another mechanism on top of it that uses mp_dispatch_queue, and
takes care of some annoying synchronization issues. We extend
mp_dispatch_queue itself to make this easier and slightly more
efficient.

As a first application, use this to reimplement certain VO scaling and
renderer options. The update_opts() function translates these to the
"old" VOCTRLs, though.

An annoyingly subtle issue is that m_config_cache's destructor now
releases pending notifications, and must be released before the
associated dispatch queue. Otherwise, it could happen that option
updates during e.g. VO destruction queue or run stale entries, which is
not expected.

Rather untested. The singly-linked list code in dispatch.c is probably
buggy, and I bet some aspects about synchronization are not entirely
sane.
2017-08-22 15:50:33 +02:00
wm4 5361c0b5d8 build: pick a main-fn source file only if cplayer is built
libmpv does not need this.
2017-08-22 11:40:39 +02:00
Niklas Haas 09c501a40e vo_opengl: refactor tex_upload to ra_buf_pool
Also refactors the usage of tex_upload to make ra_tex_upload_pbo a
RA-internal thing again.

ra_buf_pool has the main advantage of being dynamically sized depending
on buf_poll, so for OpenGL we'll end up only using one buffer (when not
persistently mapping) - while for vulkan we'll use as many as necessary,
which depends on the swapchain depth anyway.
2017-08-22 09:55:49 +02:00
Ricardo Constantino 371000108a TOOLS/lua/autodeint: update to lavfi-bridge
Also use lavfi setfield instead of removed field-dominance.
Remove missing remainder of field-dominance in docs.
2017-08-21 18:12:10 +01:00
wm4 0bfeba2d9a win32: fix massive memory corruption (take 2)
As pointed out by uau on IRC, the pointer to info is still used outside
of the lock. An extremely small race condition window, but still a race
condition.
2017-08-21 18:42:04 +02:00
wm4 d431111b06 win32: fix massive memory corruption
The struct m_thread_info pointer is part of an array, that will be
reallocated if another thread is created while the run_thread is just
being called. In previous versions of this code, the pointer was stable
(as long as the thread existed), so this was overlooked.

Fixes #4770. I'm not sure why this triggers it so reliably, while it
remained undetected otherwise.
2017-08-21 17:47:00 +02:00
wm4 b21e0746f6 ao_rsound: allow setting the host
Completely untested (rsound dev libs unavailable on my system). Trivial
enough that it's very likely that it'll just work. No port selection,
but could be added by parsing it as part of the device name.

Should fix #4714.
2017-08-21 15:46:00 +02:00
wm4 437469c103 x11: fix that window could be resized when using embedding
Somewhat lazy fix. The code isn't particularly robust or correct wrt.
window embedding.

Fixes #4784.
2017-08-21 15:15:55 +02:00
wm4 028faacff5 video: add metadata handling for spherical video
This adds handling of spherical video metadata: retrieving it from
demux_lavf and demux_mkv, passing it through filters, and adjusting it
with vf_format. This does not include support for rendering this type of
video.

We don't expect we need/want to support the other projection types like
cube maps, so we don't include that for now. They can be added later as
needed.

Also raise the maximum sizes of stringified image params, since they
can get really long.
2017-08-21 14:56:07 +02:00
Martin Herkt 82d9419f62 Revert "x11: drop xscrnsaver use"
This broke screensaver/powersave inhibition with at least KDE and
LXDE. This is a release blocker.

Since fdo, KDE and GNOME idiots seem to be unable to reach
a consensus on a simple protocol, this seems unlikely to get
fixed upstream this year, so revert this change.

Fixes #4752.
Breaks #4706 but I don’t give a damn.

This reverts commit 3f75b3c343.
2017-08-20 09:18:39 +02:00
Martin Herkt a82007dd1e Revert "x11: use xdg-screensaver suspend/resume"
This reverts commit 6694048272.
2017-08-20 09:11:07 +02:00
James Ross-Gowan 2d78705b73 context_angle: remove unused variable
Unused since 16e0a39482.
2017-08-20 16:46:02 +10:00
James Ross-Gowan 08ec444ba5 context_angle: replace hard-coded array size 2017-08-19 22:05:29 +10:00
Akemi 98f5579c02 osx: remove the standard "Show Tab Bar" menu item
it's unused and added automatically. we need to guard the deactivation
since it's a 10.12+ feature.
2017-08-18 21:44:33 +02:00
Akemi 344b75f52d osx: code cleanups and cosmetic fixes
silence build warnings, clean up code style and remove unused code.
2017-08-18 19:47:47 +02:00
Akemi e0a2d15216 osx: refactor menu bar creation
make the menu bar look more like a standard macOS menu bar, with all the
standard menu items like About, Help, Open, etc.
2017-08-18 19:20:41 +02:00
Akemi 48ab72b478 osx: move menu bar creation into its own file 2017-08-18 19:20:41 +02:00
wm4 1f7fe1597d audio: fix uninitialized data access
dst was not supposed to be initialized, the mp_audio_ setters (which
initialize dst's fields) assume it is -> shit happens. Regression from
recent changes. Was probably harmless.
2017-08-18 17:53:38 +02:00
Niklas Haas 01058b16f9 vo_opengl: allow texture uploads to fail
Surprisingly makes the code shorter, not longer
2017-08-18 02:33:29 +02:00
Frédéric Brière be05c9eb58 options: correct two remaining instances of singular file-path options
These were left behind by e4bc563fd2.
2017-08-18 00:51:52 +01:00
Niklas Haas abb7e88e3c vo_opengl: clarify the ra_fns.debug_marker 2017-08-18 01:10:37 +02:00
Niklas Haas 46d86da630 vo_opengl: refactor RA texture and buffer updates
- tex_uploads args are moved to a struct
- the ability to directly upload texture data without going through a
  buffer is made explicit
- the concept of buffer updates and buffer polling is made more explicit
  and generalized to buf_update as well (not just mapped buffers)
- the ability to call tex_upload/buf_update on a tex/buf is made
  explicit during tex/buf creation
- uploading from buffers now uses an explicit offset instead of
  implicitly comparing *src against buf->data, because not all buffers
  may actually be persistently mapped
- the initial_data = immutable requirement is dropped. (May be re-added
  later for D3D11 if that ever becomes a thing)

This change helps the vulkan abstraction immensely and also helps move
common code (like the PBO pooling) out of ra_gl and into the
opengl/utils.c

This also technically has the side-benefit / side-constraint of using
PBOs for OSD texture uploads as well, which actually seems to help
performance on machines where --opengl-pbo is faster than the naive code
path. Because of this, I decided to hook up the OSD code to the
opengl-pbo option as well.

One drawback of this refactor is that the GL_STREAM_COPY hack for
texture uploads "got lost", but I think I'm happy with that going away
anyway since DR almost fully deprecates it, and it's not the "right
thing" anyway - but instead an nvidia-only hack to make this stuff work
somewhat better on NUMA systems with discrete GPUs.

Another change is that due to the way fencing works with ra_buf (we get
one fence per ra_buf per upload) we have to use multiple ra_bufs instead
of offsets into a shared buffer. But for OpenGL this is probably better
anyway. It's possible that in future, we could support having
independent “buffer slices” (each with their own fence/sync object), but
this would be an optimization more than anything. I also think that we
could address the underlying problem (memory closeness) differently by
making the ra_vk memory allocator smart enough to chunk together
allocations under the hood.
2017-08-18 00:34:34 +02:00
Niklas Haas 9ca5a2a5d8 vo_opengl: make blitting an explicit capability
Instead of merging it into render_dst. This is better for vulkan,
because blitting in vulkan both does not require a FBO *and* requires a
different image layout.

Also less "hacky" for OpenGL, since now the weird blit=FBO requirement
is an implementation detail of ra_gl
2017-08-18 00:19:14 +02:00
Niklas Haas 8209376468 vo_opengl: make ra_fns.timer_create optional 2017-08-18 00:19:14 +02:00
Ricardo Constantino 1171f92beb TOOLS/autocrop.lua: fix cropdetect black limit for 10-bit videos
Also update to use newer lavfi-bridges for the relevant filters to
shut up warnings about deprecated crop filter.
2017-08-17 20:43:25 +01:00
wm4 b9430309ec stream: add an assert() to an obscure seek case
This affects small seeks backwards while within the buffer. Demuxers
usually avoid this, so it's probably not triggered very often. (Although
demux_mkv.c potentially triggers it often, and it uses stream_peek() to
explicitly guarantee that it can use this code to seek back.) The
condition is complex enough to warrant an assertion.
2017-08-17 17:38:07 +02:00
wm4 79a39aeebd demux_lavf: use partial read for AVIOContext.read_packet
More betterer.
2017-08-17 17:28:01 +02:00
wm4 d7b893cf35 manpage: update --lavfi-complex description 2017-08-17 10:56:53 +02:00
Niklas Haas b74067bc74 vo_opengl: remove redundant #defines in unsharp_hook
These are no longer valid anyway, and the code doesn't use them.
2017-08-17 09:12:28 +02:00
wm4 158768513c audio: fix build on Libav
Sigh...
2017-08-16 21:26:16 +02:00
wm4 1f593beeb4 audio: introduce a new type to hold audio frames
This is pretty pointless, but I believe it allows us to claim that the
new code is not affected by the copyright of the old code. This is
needed, because the original mp_audio struct was written by someone who
has disagreed with LGPL relicensing (it was called af_data at the time,
and was defined in af.h).

The "GPL'ed" struct contents that surive are pretty trivial: just the
data pointer, and some metadata like the format, samplerate, etc. - but
at least in this case, any new code would be extremely similar anyway,
and I'm not really sure whether it's OK to claim different copyright. So
what we do is we just use AVFrame (which of course is LGPL with 100%
certainty), and add some accessors around it to adapt it to mpv
conventions.

Also, this gets rid of some annoying conventions of mp_audio, like the
struct fields that require using an accessor to write to them anyway.

For the most part, this change is only dumb replacements of mp_audio
related functions and fields. One minor actual change is that you can't
allocate the new type on the stack anymore.

Some code still uses mp_audio. All audio filter code will be deleted, so
it makes no sense to convert this code. (Audio filters which are LGPL
and which we keep will have to be ported to a new filter infrastructure
anyway.) player/audio.c uses it because it interacts with the old filter
code. push.c has some complex use of mp_audio and mp_audio_buffer, but
this and pull.c will most likely be rewritten to do something else.
2017-08-16 21:10:54 +02:00
James Ross-Gowan 16e0a39482 vo_opengl: extract non-ANGLE specific D3D11 code
This extracts non-ANGLE specific code to d3d11_helpers.c, which is
modeled after egl_helpers.c. Currently the only consumer is
context_angle.c, but in future this may allow the D3D11 device and
swapchain creation logic to be reused in other backends.

Also includes small improvements to D3D11 device creation. It is now
possible to create feature level 11_1 devices (though ANGLE does not
support these,) and BGRA swapchains, which might be slightly more
efficient than ARGB, since its the same format used by the compositor.
2017-08-17 00:28:38 +10:00
wm4 f24612db44 img_format: #if -> #ifdef
Oops.
2017-08-16 11:15:52 +02:00
Ricardo Constantino 257dbdf06f TOOLS/autoload.lua: implement natural sorting 2017-08-16 10:00:27 +01:00
wm4 6694048272 x11: use xdg-screensaver suspend/resume
If it doesn't work this time, I'll remove all X11 screensaver code.

Fixes #4763.
2017-08-15 20:32:44 +02:00
wm4 34ab0386cb vo_rpi: fix operation
Commit 697c4389a9 worked "almost". I couldn't test it at the time.
2017-08-15 19:41:23 +02:00
wm4 935df644af vo_opengl: fix incorrect glBindFramebuffer() call
Used the wrong binding.
2017-08-15 19:08:54 +02:00
wm4 b44e81d9c3 vo_opengl: fix dangling pointers when VAOs are not available
This is for legacy GL: if VAOs are not available, the helper has to
specify vertex attributes again on every rendering. gl_vao_init() keeps
the vertex array for this purpose. Unfortunately, a temporary argument
was passed to the function, instead of the permanent copy.

Also, it didn't use num_entries (instead expected the array being
terminated by a {0} entry). Fix that source code indentation too.
2017-08-15 18:59:59 +02:00
wm4 72a8120daa Revert "build: rpi: rely on pkgconfig for compiler flags"
This reverts commit ea40fa36ee.

This caused strange runtime failure on Raspbian (when running mpv,
vc_dispmanx_display_open() returned 0, while other dispmanx using
programs were fine). The problem must have been something about the
compiler flags, maybe linking order or set of include paths.
2017-08-15 18:41:16 +02:00
wm4 16d22ea02a img_format: better exclusion of bayer formats
These are useless and shouldn't be confused with normal RGB formats.
Replace the earlier hack checking the format name with a proper check.
(Not sure when this flag was added. Libav won't have it anyway, but also
no bayer formats.)
2017-08-15 17:03:35 +02:00
wm4 63b1031ca2 vo_opengl: support float pixel formats
Like AV_PIX_FMT_GBRPF32LE.
2017-08-15 17:00:35 +02:00
wm4 817bb2bbbe options: change --loop semantics
As announced by the previous deprecation.
2017-08-14 20:01:08 +02:00
wm4 df8cc84f47 vo_opengl: remove DR image layouting code to renderer
No reason to have it in a higher level.
2017-08-14 19:57:44 +02:00
wm4 68201f4591 player: make refresh seeks slightly more robust
Refresh seeks are automatically issued when changing filters, which
improves user experience if these filters change buffering or such.

The refresh seek could actually overwrite a previously ongoing seek:

	set pause yes
	set time-pos 10
	set vf ""

Here, the video code issued a refresh seek to the previous video
position, which could be different from the previously triggered (and
still ongoing) seek, this overwriting the seek.

Factor all refresh seek handling into a new function, and make it handle
ongoing seeks correctly.

Remove the weird new canonical_pts field, which actually had no use.

Fixes #4757.
2017-08-14 14:02:13 +02:00
wm4 b6d79deebb player: do not destroy VO immediately if there is no video track
Commit f1d161d55f accidentally added the handle_force_window() call if
no track is selected.

This was OK, but breaks something like "mpv *", where some files are not
playable (like subtitle files) - the unplayable files would remove and
recreate the VO window, which is annoying.

Just drop the call again.
2017-08-14 12:19:54 +02:00
wm4 cacc6db2a3 vo_opengl: hwdec_vdpau: use correct source texture size
In commit c6fafbffac we accidentally set the logical texture size to
the cropped video size, which is not correct. This caused rendering
artifacts in some cases.

Use the video surfaces size instead. Since the current mp_image_params
contains the cropped size only, wrapper texture creation has to be moved
to the _map function. Move the same code for the mixer case (strictly
speaking this is not needed, but seems more symmetric).

(Also there is no need to clear gl_textures on uninit - leftover from
the old hwdec mapper API. So we just drop that part.)

Fixes #4760.
2017-08-14 12:17:39 +02:00
wm4 c6628a5fb6 player: add --track-auto-selection option
I imagine this is useful. Or maybe it isn't.
2017-08-12 23:44:47 +02:00
wm4 b531332835 player: fix another audio resync issue
This oddly triggers bogus EOF when switching filter graphs between two
audio files (in this case, "[vid1]f[vo];[aid2]f[ao]"->"[aid1]f[ao]",
with aid2 being an external audio source).

This commit also fixes desync when seeking with an external file
connected via --lavfi-complex.

(Yes, the audio resync code is cursed.)
2017-08-12 23:35:12 +02:00
wm4 f1d161d55f player: make --lavfi-complex changeable at runtime
Tends to be somewhat glitchy if subtitles are enabled, and you enable
and disable tracks.

On error, this will disable --lavfi-complex, which will result in
whatever behavior.
2017-08-12 23:10:40 +02:00
wm4 baead23ea0 af_lavrresample: don't call swr_set_compensation() unless necessary
This was _always_ called, even if the resampling was static, or the
filter was inserted for format conversion only. This should have been
fine, as I expected the function not to enable resampling when the
compensation is unset, and the source/target rates are the same. But
this is not the case, and it always enables resampling.

So explicitly avoid the call. If we have already called it successfully,
it's better not do avoid it (to overwrite the previous compensation
value), but it will also be cheap/no-op then.

Probably fixes #4716.
2017-08-12 12:12:52 +02:00
wm4 c20df5b3e1 vo_opengl: hwdec_ios: fix build 2017-08-11 22:00:44 +02:00
wm4 c391640645 player: fix --lavfi-complex freeze
Commit 0e0b87b6f3 fixed that dropped packets did not trigger further
work correctly. But it also made trivial --lavfi-complex freeze. The
reason is that the meaning if DATA_AGAIN was overloaded: the decoders
meant that they should be called again, while lavfi.c meant that other
outputs needed to be checked again. Rename the latter meaning to
DATA_STARVE, which means that the current input will deliver no more
data, until "other" work has been done (like reading other outputs, or
feeding input).

The decoders never return DATA_STARVE, because they don't get input from
the player core (instead, they get it from the demuxer directly, which
is why they still can return DATA_WAIT).

Also document the DATA_* semantics in the enum.

Fixes #4746.
2017-08-11 21:29:35 +02:00
wm4 8b1d4b978d vo_opengl: remove some dead code
These were replaced by ra equivalents, and with the recent changes, all
of them became fully unused.
2017-08-11 21:29:35 +02:00
wm4 1d0bf4073b vo_opengl: handle probing GL texture formats better
Retrieve the depth for each component and internal texture format
separately. Only for 8 bit per component textures we assume that all
bits are used (or else we would in my opinion create too many probe
textures).

Assuming 8 bit components are always correct also fixes operation in
GLES3, where we assumed that each component had -1 bits depth, and this
all UNORM formats were considered unusable. On GLES, the function to
check the real bit depth is not available. Since GLES has no 16 bit
UNORM textures at all, except with the MPGL_CAP_EXT16 extension, just
drop the special condition for it. (Of course GLES still manages to
introduce a funny special case by allowing GL_LUMINANCE , but not
defining GL_TEXTURE_LUMINANCE_SIZE.)

Should fix #4749.
2017-08-11 21:29:35 +02:00
wm4 e7a9bd6937 vo_opengl: remove another unneeded GL include
Getting mp_pass_perf seriously requires including vo.h???
2017-08-11 21:29:35 +02:00
wm4 697c4389a9 rpi: fix build
Runtime untested, because I get this:

  [vo/rpi] Could not get DISPMANX objects.

This happened even when building older git versions, and on a RPI image
that hasn't changed in the recent years. I don't know how to make this
POS work again, so I guess if there's a bug in the new code, it will
remain broken.
2017-08-11 21:29:35 +02:00
wm4 de3eecce7f vo_opengl: move strictly private ra_gl structs to .c file
So that nothing accidentally accesses these.
2017-08-11 21:29:35 +02:00
Ricardo Constantino 1a1f6e8581 man/mpv: document bd:// expected titles and title list 2017-08-11 19:37:01 +01:00
wm4 fba4e8aa40 vo_opengl: remove some indirect GL header inclusions from core renderer 2017-08-10 21:36:57 +02:00
wm4 c6fafbffac vo_opengl: separate hwdec context and mapping, port it to use ra
This does two separate rather intrusive things:

 1. Make the hwdec context (which does initialization, provides the
    device to the decoder, and other basic state) and frame mapping
    (getting textures from a mp_image) separate. This is more
    flexible, and you could map multiple images at once. It will
    help removing some hwdec special-casing from video.c.
 2. Switch all hwdec API use to ra. Of course all code is still
    GL specific, but in theory it would be possible to support other
    backends. The most important change is that the hwdec interop
    returns ra objects, instead of anything GL specific. This removes
    the last dependency on GL-specific header files from video.c.

I'm mixing these separate changes because both requires essentially
rewriting all the glue code, so better do them at once. For the same
reason, this change isn't done incrementally.

hwdec_ios.m is untested, since I can't test it. Apart from superficial
mistakes, this also requires dealing with Apple's texture format
fuckups: they force you to use GL_LUMINANCE[_ALPHA] instead of GL_RED
and GL_RG. We also need to report the correct format via ra_tex to
the renderer, which is done by find_la_variant(). It's unknown whether
this works correctly.

hwdec_rpi.c as well as vo_rpi.c are still broken. (I need to pull my
RPI out of a dusty pile of devices and cables, so, later.)
2017-08-10 21:24:31 +02:00
wm4 b2fb3f1340 vo_opengl: hwdec_cuda: fix filtering mode
Probably explains quality issues in some cases.
2017-08-09 21:02:23 +02:00
wm4 9c5dcf9398 vo_opengl: shrink the hwdec overlay API
Just remove one callback, and fold the functionality into the other one.
RPI will still not compile, so the hwdec_rpi.c changes are untested.
2017-08-09 20:57:37 +02:00
wm4 de6d3f8ca1 vd_lavc: fix device leak with copy-mode hwaccels
Apparently this was broken by the "ctx->hwdec" check in the if condition
guarding the destroy call, and "ctx->hwdec = NULL;" was moved up
earlier, making this always dead code.

This should probably be refcounted or so, although that could make it
worse as well. For now, add a flag whether the device should be
destroyed.

Fixes #4735.
2017-08-09 12:00:56 +02:00
wm4 7397e8ab42 vo_opengl: add a hack for Apple's broken iOS hwdec stuff
As seen in hwdec_ios.m, it insists on using the legacy luminance alpha
formats for mapped textures.
2017-08-08 17:53:19 +02:00
Niklas Haas 6087f63003 vo_opengl: go back to using GL_TIME_ELAPSED
Less flexible than GL_TIMESTAMP but supported by more platforms. This
will mean that nested queries have to be detected and silently omitted,
but oh well. Not much use for them anyway.

Fixes #4721.
2017-08-08 17:08:25 +02:00
wm4 7f9193b353 Revert "mp_image_pool: disallow adding read only frames"
This reverts commit 0ce3dce03a.

We actually explicitly add read-only frames in some of the hwaccel code
via mp_image_new_custom_ref(), which sets AV_BUFFER_FLAG_READONLY. It's
probably better to keep it this way.

Fixes #4652 (and some related issues with D3D).
2017-08-08 16:16:55 +02:00
wm4 f7fb6e186a options: fix --include
This is really obnoxious. --include parses into the default profile, but
when used on the command line, it did never get applied. So we have to
apply it when the exact conditions for this are met.

Fixes #4673.
2017-08-08 15:54:51 +02:00
wm4 0e36b77aae demux_mkv: avoid an error message in a corner case
If --demuxer-mkv-probe-start-time=no is used, and a seek is triggered on
start, then cluster_start will be 0, and the packet reading code will
print an error message about not finding valid data. This fixes itself
since it invokes the resync code, but it's still pretty ugly. Avoid this
by always initializing cluster_start.
2017-08-08 15:19:50 +02:00
wm4 2ad79785cc build: use main-fn-cocoa.c on OSX
Broken by a434892208.
2017-08-08 14:56:44 +02:00
wm4 0e0b87b6f3 player: fix confusion in audio resync code
Just the audio resync code in its normal state: buggy. This time,
AD_NO_PROGRESS was handled about the same as AD_WAIT. But it means the
decoder didn't output data, even though input is still readily
available.

This happened in particular when the timeline code was used (potentially
skipping many packets), and thus should fix #4688.
2017-08-08 14:55:02 +02:00
wm4 8ef50016be player: fix --end with large values
Causea a simple integer overflow.

Fixes #4650.
2017-08-08 14:11:58 +02:00
wm4 0b10a07b63 vo_opengl: don't call glGetProgramBinary if GL_PROGRAM_BINARY_LENGTH==0
Noticed in #4717, although the issue might be about something else.
2017-08-08 13:16:37 +02:00
wm4 3f75b3c343 x11: drop xscrnsaver use
It's an ancient X11 protocol extension that apparently nobody uses
anymore (desktop environments in particular have replaced it with
equally bad protocols that require tons of dependencies). Users keep
complaining about it being a required dependency.

The impact is likely minimal to none.

Fixes #4706 and other annoying people.
2017-08-08 12:55:41 +02:00
feixm1 a434892208 build: fix dependencies for Cygwin environment
This replaces previous commit with same intentions. This time, with
proper formating (no tabs in code).
2017-08-08 11:41:56 +02:00
wm4 c1bcd30b09 vo_opengl: cosmetics to comments 2017-08-08 11:38:29 +02:00
wm4 fd135cf73e player: readd smi subtitle extension
Fixes #4626. Previously removed because the original smi entry was added
by someone who did not agree to LGPL relicensing. I'm not sure if the
original change was copyrightable, but this commit for sure does not
fall under that author's copyright.
2017-08-08 11:37:04 +02:00
Kevin Mitchell 12cafdc868 ao_wasapi: remove old comment 2017-08-07 16:33:29 -07:00
Kevin Mitchell 6f40c211a5 ao_wasapi: reorganize wasapi.h
Remove dead declarations. Move macro only used in wasapi_utils.c closer to use.
Rearrange declaration order.
2017-08-07 14:33:03 -07:00
Kevin Mitchell 434d3d4976 ao_wasapi: deduplicate wasapi sample format selection 2017-08-07 14:33:03 -07:00
Kevin Mitchell 15eb1e1ad3 ao_wasapi: clean up find_formats logic
There were too many functions within functions, too much going on in if
clauses and duplicated code. Fix it.
2017-08-07 14:33:03 -07:00
Kevin Mitchell bee602da82 ao_wasapi: return bool instead of HRESULT from thread_init
Any bad HRESULTs should have been printed already and lots of failure modes
don't have an HRESULT leading to awkward hr = E_FAIL business.

This also checks the exit status of GetBufferSize in the align hack. A final
fatal message is added if either of the retry hacks fail.
2017-08-07 14:33:03 -07:00
wm4 61c8a147b5 vo_opengl: call ra_free() in the correct context
This also fixes a double free in vo_opengl_cb.c.
2017-08-07 19:57:15 +02:00
wm4 bbb57694b0 vf_vapoursynth: fix inverted sign and restore 10 bit support
Fixes #4720, I think.
2017-08-07 19:31:15 +02:00
wm4 168ffbaf23 client API: more opengl_cb clarifications
Also fix a typo in ra_gl.c. Too greedy for a separate commit.
2017-08-07 19:24:25 +02:00
wm4 d45fbecbb5 vo_opengl: add another ra_format field to exclude insane formats
Generic description of pixel formats is hard. In this case, the Apple
special format for packed YUV could have been interpreted as a RGB
format with funny packing.
2017-08-07 19:18:58 +02:00
wm4 47ea771b7a vo_opengl: further GL API use separation
Move multiple GL-specific things from the renderer to other places like
vo_opengl.c, vo_opengl_cb.c, and ra_gl.c.

The vp_w/vp_h parameters to gl_video_resize() make no sense anymore, and
are implicitly part of struct fbodst.

Checking the main framebuffer depth is moved to vo_opengl.c. For
vo_opengl_cb.c it always assumes 8. The API user now has to override
this manually. The previous heuristic didn't make much sense anyway.

The only remaining dependency on GL is the hwdec stuff, which is harder
to change.
2017-08-07 19:17:28 +02:00
wm4 1adf324d8b vo_opengl: fix minor memory leak
Don't leak the buffer if glGetProgramBinary() fails.
2017-08-07 18:46:40 +02:00
Niklas Haas bed421d483 vo_opengl: nuke ra_gl->first_run
Completely unnecessary, we can just update the uniforms immediately
after creating the program. In theory, for GLSL 4.20+, we could even
skip this, but oh well.
2017-08-07 17:47:04 +02:00
Niklas Haas ecbb02148b vo_opengl: better formatting for enum RA_CAP
Also fixes an issue where 1 << 5 was used twice, probably because of the
terrible formatting obscuring this bug
2017-08-07 17:46:04 +02:00
Niklas Haas 01a40bb1ee vo_opengl: also support RA_VARTYPE_INT vertex attribs
No reason not to.
2017-08-07 17:46:04 +02:00
wm4 346ac1e09f vo_opengl: simplify mirroring and fix it if glBlitFramebuffer is used
The vp_w/vp_h variables and parameters were not really used anymore
(they were redundant with ra_tex w/h) - but vp_h was still used to
identify whether rendering should be done mirrored.

Simplify this by adding a fbodst struct (some bad naming), which
contains the render target texture, and some parameters how it should be
rendered to (for now only flipping). It would not be appropriate to make
this a member of ra_tex, so it's a separate struct.

Introduces a weird regression for the first frame rendered after
interpolation is toggled at runtime, but seems to work otherwise. This
is possibly due to the change that blit() now mirrors, instead of just
copying. (This is also why ra_fns.blit is changed.)

Fixes #4719.
2017-08-07 16:44:15 +02:00
Ricardo Constantino 46f7a4352e travis: install missing x11 deps 2017-08-07 13:53:52 +01:00
Ricardo Constantino 5fb0d7dbef travis: print config.log on failure like appveyor 2017-08-07 13:53:51 +01:00
wm4 41ee66d566 vo_opengl: drop pointless fbotex_init() function 2017-08-07 14:34:18 +02:00
Niklas Haas 9581fbe569 vo_opengl: generalize ra_buf to support other buffer objects
This allows us to integrate PBOs and SSBOs into the same abstraction,
with the potential to easily add UBOs if the need arises.
2017-08-07 12:46:30 +02:00
Jan Janssen 207458c7a9 acompressor.lua: Convert to use mp.options and lavfi filter bridge 2017-08-07 11:42:20 +02:00
Akemi f550fdaa91 cocoa: add an option to disable the native macOS fullscreen
Fixes #4014
2017-08-06 22:48:26 +02:00
Ricardo Constantino 2b83f7e391 ytdl_hook: support fragments with relative paths
Unbreaks segmented DASH with the change in
https://github.com/rg3/youtube-dl/commit/1141e9104 which made each
segment URL only use relative path from fragment_base_url with a
different key.
2017-08-06 13:27:53 +01:00
Niklas Haas 494aa0f651 vo_opengl: only mark frames as fresh if they contain a new image
When using dumb mode, we can actually redraw a frame without uploading
it. Marking this as fresh as well results in unpredictable pass
behavior, which is confusing and makes debugging harder. So mark it as a
redraw instead, in that case.
2017-08-06 02:51:11 +02:00
Niklas Haas 988d188d96 vo_opengl: drop ra_gl.h from shader_cache.c
Since the GL *gl is no longer needed for the timers, we can get rid of
the sc->gl dependency. This requires moving a utility function (which is
not GL-specific anyway) out of gl_utils.h and into utils.h
2017-08-06 00:10:22 +02:00
Niklas Haas e5748e891f vo_opengl: measure pass_draw_osd as a whole
In the past, this always measured the per-shader execution times of the
individual OSD parts, which was thrown off because the shader was reused
anyway. (And apparently recording the OSD shader execution times was
removed completely, probably because of them being so unrealiably
anyway)

Since ra_timer no longer has the restriction of not allowing timers to
run concurrently, we can just wrap the entire OSD block inside a single
osd_timer now, and record that. (Technically, this can still be off when
using --blend-subtitles=video/yes and showing a full-screen OSD at the
same time. Maybe this can be done better?)
2017-08-06 00:10:20 +02:00
Niklas Haas f2298f394e vo_opengl: move timers to struct ra
In order to prevent code duplication and keep the ra abstraction as
small as possible, `ra` only implements the actual timer queries,
it does not do pooling/averaging of the results. This is instead moved
to a ra-neutral struct timer_pool in utils.c.
2017-08-06 00:10:20 +02:00
Aman Gupta a680c643eb wscript: fix build of videotoolbox hwaccel for iOS 2017-08-05 22:10:14 +03:00
wm4 56742ecdc9 vo_opengl: ra_gl: make getting GL ptr slightly less tedious 2017-08-05 17:09:25 +02:00
wm4 dddda6e4a5 vo_opengl: move GL state resetting to vo_opengl_cb
This code is pretty much for the sake of vo_opengl_cb API users. It
resets certain state that either the user or our code doesn't reset
correctly. This is somewhat outdated. With GL implicit state being
so awfully large, it seems more reasonable require that any code
restores the default state when returning to the caller. Some
exceptions are defined in opengl_cb.h.
2017-08-05 16:27:09 +02:00
wm4 333cae74ef vo_opengl: move shader handling to ra
Now all GL-specifics of shader compilation are abstracted through ra.
Of course we still have everything hardcoded to GLSL - that isn't going
to change.

Some things will probably change later - in particular, the way we pass
uniforms and textures to the shader. Currently, there is a confusing
mismatch between "primitive" uniforms like floats, and others like
textures.

Also, SSBOs are not abstracted yet.
2017-08-05 16:27:09 +02:00
wm4 f72a33d2cb vo_opengl: organize ra PBO flag slightly differently
Instead of having a mutable ra_tex field (and the only one), move the
flag to struct ra, since we have only 2 tex_upload user calls anyway,
and both want the same PBO behavior. (At first I considered making it
a RA_TEX_UPLOAD_ flag, but why bother. PBOs are a terribly GL-specific
thing, so we can't expect a reasonable abstraction of it anyway.)
2017-08-05 13:48:46 +02:00
wm4 dd096863fa vo_opengl: make OSD code use ra for textures
This requires a silly extension to ra_fns.tex_upload: since the OSD
texture can be much larger than the actual OSD image data to upload, a
mechanism for uploading only to a small part of the texture is needed.
Otherwise, we'd have to realloc/copy the data, just to pad it, and then
pay for uploading the padding too.

The RA_TEX_UPLOAD_DISCARD flag is not interpreted by GL (not sure how
you'd tell GL about this), but it clarifies the API and might be
helpful if we support other backend APIs in the future.
2017-08-05 13:44:30 +02:00
wm4 8dd4ae13ff vo_opengl: restore OSX "old" hwdec
Probably. Untested.
2017-08-05 13:09:05 +02:00
wm4 aac04c0d64 vo_opengl: split utils.c/h
Actually GL-specific parts go into gl_utils.c/h, the shader cache
(gl_sc*) into shader_cache.c/h.

No semantic changes of any kind, except that the VAO helper is made
public again as part of gl_utils.c (all while the goal for gl_utils.c
itself is to be included by GL-specific code).
2017-08-05 13:09:05 +02:00
wm4 fa4a1c4675 vo_opengl: always use GL_TRIANGLES for all primitives
Will make the ra layer _slightly_ simpler.
2017-08-05 13:09:05 +02:00
wm4 0206efa94a vo_opengl: pass ra objects during rendering instead of GL objects
Another "small" step towards removing GL dependencies from the renderer.
This commit generally passes ra_tex objects instead of GL FBO integer
IDs to various rendering functions. video.c still manually binds the
FBOs when calling shaders.

This also happens to fix a memory leak with output_fbo.
2017-08-05 13:09:05 +02:00
wm4 a796745fd2 vo_opengl: make fbotex helper use ra
Further work removing GL dependencies from the actual video renderer,
and moving them into ra backends.

Use of glInvalidateFramebuffer() falls away. I'd like to keep this, but
it's better to readd it once shader runs are in ra.
2017-08-05 13:09:05 +02:00
wm4 90b53fede6 vo_opengl: drop unused custom texture filter for FBO helper 2017-08-05 13:09:05 +02:00
Jan Ekström 0389852db0 {demux_mf,osdep/io}: disable glob usage when it is not available
This currently is only limited to Android. Its stdlib contains the
things that mpv's POSIX check checks for, but unfortunately not
glob().

This fixes Android compilation broken in 70a70b9da .
2017-08-05 01:51:29 +03:00
Jan Ekström 1a0d92aeca build: re-add and re-structurize the glob() checks
* If we have glob() supported, we have `HAVE_GLOB = 1'.
* If we have specifically POSIX glob(), we have
  `HAVE_GLOB_POSIX = 1`.
* If we have specifically Win32 glob(), we have
  `HAVE_GLOB_WIN32 = 1`
2017-08-05 01:51:29 +03:00
Jan Ekström 69650851f8 build: move Android environment check to main dependencies
Additionally change the description to better match what Android is,
which is an "environment". The original positioning of this check
was unfortunate.
2017-08-05 01:51:29 +03:00
James Ross-Gowan 037c7a9279 w32_common: handle media keys
This was attempted before in fc9695e63b, but it was reverted in
1b7ce759b1 because it caused conflicts with other software watching
the same keys (See #2041.) It seems like some PCs ship with OEM software
that watches the volume keys without consuming key events and this
causes them to be handled twice, once by mpv and once by the other
software.

In order to prevent conflicts like this, use the WM_APPCOMMAND message
to handle media keys. Returning TRUE from the WM_APPCOMMAND handler
should indicate to the operating system that we consumed the key event
and it should not be propogated to the shell. Also, we now only listen
for keys that are directly related to multimedia playback (eg. the
APPCOMMAND_MEDIA_* keys.) Keys like APPCOMMAND_VOLUME_* are ignored, so
they can be handled by the shell, or by other mixer software.
2017-08-05 02:38:44 +10:00
Rostislav Pehlivanov e406e81477 vo_opengl: always print when getting embedded ICC profile data
The printout in get_vid_profile() gets skipped if icc caching has
been enabled, so always print if an embedded ICC profile has been
provided.
2017-08-04 09:50:13 +01:00
Rostislav Pehlivanov 5ea390c07f TOOLS/lua/status-line: improve and update
Updates the line once per second rather than once per frame, saving
quite a bit of CPU. Also completely stops the script while paused.
That aside, fixes the swapped checks for video and audio-only files and
adds bitrate printing.
2017-08-04 09:07:37 +01:00
Niklas Haas 779031ad8f bstr: short-circuit bstr_equals on pointer equality
More efficient in cases where we're comparing a bstr against itself,
which can happen in e.g. the ICC profile code.
2017-08-03 21:48:25 +02:00
Niklas Haas fee6b287a5 vo_opengl: support embedded ICC profiles
This currently only works when using lcms-based color management
(--icc-profile-*).

In principle, we could also support using lcms even when the user has
not specified an ICC profile, by generating the profile against a fixed
reference (--target-prim/--target-trc) instead. I still might do that
some day, simply because 3dlut provides a higher quality conversion than
our simple gamut mapping does for stuff like BT.2020, and also because
it's now needed to enable embedded ICC profiles. But that would be a
separate change, so preserve the status quo for now.

(Besides, my opinion is still that you should be using an ICC profile if
you care about colors being accurate _at all_)
2017-08-03 21:48:25 +02:00
Niklas Haas 1aab037601 vd_lavc: decode embedded ICC profiles
Since these need to be refcounted, we throw them directly into struct
mp_image instead of being part of mp_colorspace. Even though they would
semantically make more sense in mp_colorspace, having them there is
really awkward because mp_colorspace is passed around and stored a lot,
and this way their lifetime is exactly tied to the lifetime of the
mp_image associated with it.
2017-08-03 21:48:25 +02:00
Niklas Haas 0f956f0929 vo_opengl: use GL_CLIENT_STORAGE_BIT for DR
mesa won't pick client storage unless this bit is set, and we
*absolutely* want to be using client storage for our DR PBOs.
Performance is shit on AMD otherwise. (Nvidia always uses client storage
for persistent coherent buffers whether you tell it it or not, probably
because it's way faster and nvidia doesn't trust users to figure that
out on their own)
2017-08-03 20:06:58 +02:00
wm4 7625bcc716 vo_opengl: remove unused ra_mapped_buffer.preferred_align field
It makes no sense to have this on an already created buffer.

If anything, the ra backend would have to export this as a global value
(e.g. struct ra field), so that whatever allocates the buffer can
account for the required alignment. Since this code is in vo_opengl.c in
the first place, and since GL doesn't dictate any special alignment
here, it doesn't make sense in the first place to export this. (Maybe
something like this will be required later.)
2017-08-03 18:59:43 +02:00
Niklas Haas 2bf094cd55 vo_opengl: don't hardcode texmap0 for polar compute
This was an oversight. The ID shouldn't be hard-coded here, so add it to
sampler_prelude instead.
2017-08-03 18:55:52 +02:00
Niklas Haas 5e89aed934 vo_opengl: don't precompute texcoord in global scope
Breaks on mesa for whatever reason... even though it doesn't generate a
GLSL shader compiler error

Shouldn't make a performance difference for us because we cache `pos`
anyway, and most compute shaders will probably cache all of their
samples to shmem. Might have to re-visit this when we have an actual use
case for repeated sampling inside CS though. (RAVU + anti-ringing is a
possible candidate for that)
2017-08-03 18:50:07 +02:00
Niklas Haas 83f3910398 vo_opengl: make compute shaders more flexible
This allows users to do their own custom sample writing, mainly meant to
address use cases such as RAVU. Also clean up the compute shader code a
bit.
2017-08-03 18:27:36 +02:00
wm4 e7d31d12be vo_opengl: add legend for texture format debug dump 2017-08-03 16:19:57 +02:00
wm4 1479c7bd0d vo_opengl: give special Apple name a more appropriate name
Or less appropriate, as some would argue. The new name is short for
"Apple YUV packed".

(This format is needed only for hardware decoding on rather old Apple
hardware, and a very annoying special case.)
2017-08-03 16:19:56 +02:00
wm4 ffe0526064 vo_opengl: simplify/fix user shader textures
This broke float textures, which were actually used by some shaders.
There were probably some other bugs as well.

Lots of code can be avoided by using ra_tex_params directly, so do that.

The main change is that COMPONENT/FORMAT are replaced by a single FORMAT
directive, which takes different parameters now. Due to the mess with
16/32 bit float textures, and because we want to support other APIs than
just GL in the future, it's not really clear how this should be handled,
and the nice component/type separation makes things actually harder. So
just jump the gun and use the ra_format.name names, which were
originally meant mostly for debugging. (This is probably something that
will be regretted later.)

Still only superficially tested, but seems to work.

Fixes #4708.
2017-08-03 16:19:49 +02:00
wm4 7ec8bd168e travis: drop libav-stable support
For libav-stable, we download the Libav tarball, which is failing,
because their certificate is broken:

ERROR: cannot verify libav.org's certificate, issued by `/C=US/O=Let\'s Encrypt/CN=Let\'s Encrypt Authority X3':
  Issued certificate has expired.

I don't intend to support Libav's overly old releases anymore anyway,
so if you want to use Libav, use its git master.
2017-08-03 14:43:04 +02:00
Niklas Haas 2bcf04a7bd vo_opengl: fix constexprs on ANGLE
I hate GLES
2017-08-03 14:27:38 +02:00
Niklas Haas 8f484567fc vo_opengl: fix HLG OOTF inverse
Got the "sign" of the second multiplication wrong.
2017-08-03 14:26:35 +02:00
Niklas Haas 5e1e7d32e8 vo_opengl: generalize HDR tone mapping to gamut mapping
Since this code was already written for HDR, and is now per-channel
(because it works better for HDR as well), we can actually reuse this to
get very high quality gamut mapping without clipping. The only required
change is to move the tone mapping from before the gamut map to after
the gamut map. Additonally, we need to also account for changes in the
signal range as a result of applying the CMS when we compute ref_peak,
which is fortunately pretty easy because we only need to consider the
case of primaries mapping to themselves.

Since `HDR` no longer really makes sense as a label, rename it to
`--tone-mapping` in general. Also fits better with
`--tone-mapping-desat` etc.

Arguably we could also rename `--hdr-compute-peak`, but that option is
basically only useful for HDR content anyway because we don't need
information about the signal range for gamut mapping.

This (finally!) gives us reasonably high quality gamut mapping even in
the absence of an ICC profile / 3DLUT.
2017-08-03 12:46:57 +02:00
Niklas Haas 6074cfdfd4 vo_opengl: implement HLG OOTF inverse
Huge thanks to @rusxg for finding this solution, which was previously
believed not to exist. Of course, we still don't actually need it, but I
don't want to leave this half-implemented in case somebody does in the
future.
2017-08-03 12:05:37 +02:00
wm4 955cc50e1b options: --priority can be LGPL
Original author has agreed now.

Also fix the notice in dec_video.c - all GPL-only code is gone
(unrelated to --priority/its author).
2017-08-03 09:44:36 +02:00
Akemi 12ee13101b osx: load the proper profiles and configs in the bundle
different shells need different args to load the expected profiles and
configs, so we added a small heuristic to decide those args. also don't
always load the profiles for a bash login shell and instead only use the
standard shell without any args.
2017-07-31 20:23:58 +02:00
Akemi 67506f21b8 osx: fix bundle for paths that need escaping
this fixes the mpv binary call in our bundle wrapper script, in the case
that the path to the binary needs escaping. examples are white spaces or
special chars.
2017-07-31 20:23:58 +02:00
Alex Notes bda32d99d7 cocoa: fix the support of multiple renderers (GPU switch)
So far, switching between integrated and discrete GPU would cause the
kernel to kill mpv due to an indecipherable buffer error. The technical
note TN2229 from Apple recommends to enable OpenGL Offline Renderers for
every Mac with more GPUs than displays to handle the switch between GPU.

By ordering the array from the least commonly rejected to the most,
we can sequentially remove PixelFormat attributes to fit the host.

Fixes #2371
2017-07-31 20:23:58 +02:00
Akemi 80758eda17 cocoa: remove usage of FFABS and the dependency on libavutil/common.h 2017-07-31 20:22:33 +02:00
Akemi b726f1eb90 cocoa: distinguish between horizontal and vertical scroll
we need to switch the x and y deltas when Shift is being held because
macOS switches them around. otherwise we would get a horizontal scroll
on a vertical one and vice versa.

additional we switch from deltaX/Y to scrollingDeltaX/Y since the Apple
docs suggest it's the preferred way now. in my tests both reported the
same values on imprecise scrolls though.
2017-07-31 20:22:33 +02:00
wm4 53188a14bf vo_opengl: manage user shader textures with ra
Drops some features I guess, no idea if those were needed. Untested due
to lack of test cases.
2017-07-30 11:38:52 +02:00
wm4 5429dbf2a2 vo_opengl: fix dither texture filter
Should be GL_NEAREST, not GL_LINEAR.
2017-07-30 09:43:41 +02:00
wm4 ab1ffa1382 vo_opengl: manage ICC LUT texture via ra
Also move the capability check to gl_video_get_lut3d(), because it
seems more convenient (ra won't have a _CAP_EXT16).
2017-07-29 21:23:31 +02:00
wm4 37b7b32d61 vo_opengl: manage scaler LUT textures via ra
Also fix the RA_CAP_ bitmask nonsense.
2017-07-29 20:15:59 +02:00
wm4 8494fdadae vo_opengl: manage dither texture via ra
Also add some more helpers.

Fix the broken math.h include statement.

utils.c uses ra_gl.h internals, which it shouldn't, and which will be
removed again as soon as this code gets converted to ra fully.
2017-07-29 20:14:48 +02:00
wm4 0f9fcf0ed4 vo_opengl: do not use GL format conversion on texture upload
The dither texture data is created as a float array, but uploaded to a
texture with GL_R16 as internal format. We relied on GL to do the
conversion from float to uint16_t. Not all GL variants even support
this: GLES does not provide this conversion (one of the reasons why this
code has a float16 code path). Also, ra is not going to do this. So just
convert on the fly.

Still keep the float16 texture format fallback, because not all GLES
implementations provide GL_R16.

There is some possibility that we'll need to provide some kind of upload
conversion anyway for float->float16. We still rely on GL doing this
implicitly, and all GL variants support it, but with RA there might be
the need for explicit conversion. Even then, it might be best to reduce
the number of conversion cases. I'll worry about this later.
2017-07-29 20:12:43 +02:00
wm4 6fcc09ff3d vo_opengl: use ra_* for format negotiation too
Format handling via ra_* was added earlier, but the format negotiation
part was forgotten.

Actually move some aspects of it to ra_get_imgfmt_desc(). Also make sure
the unorm and float formats selected by the common format lookup
functions are linear filterable. (For OpenGL, this is implicitly
guaranteed, so it wasn't done before.) Whether these assumptions should
be checked/enforced in the ra code at all is a bit fuzzy, but with ra
being helper code only for the actual video renderer, it's probably
justified.
2017-07-29 20:11:51 +02:00
Martin Herkt 67cda60da0 options: fix --external-file alias typo 2017-07-29 16:40:08 +02:00
James Ross-Gowan 28e3618e79 subprocess-win: fix swprintf usage
The count parameter refers to the number of wide-characters to write to
the buffer (including the terminating NUL character, which is always
added,) not the number of bytes. See C99 7.24.2.3 or
https://msdn.microsoft.com/en-us/library/ybk95axf.aspx
2017-07-29 21:13:07 +10:00
James Ross-Gowan df12f76910 appveyor: use a clean %PATH%
AppVeyor build workers have Git for Windows on the %PATH%, which
includes some MSYS2 binaries. Having multiple MSYS2 installations on the
%PATH% causes cygheap errors, so remove them and make sure %PATH% only
has stuff we need.
2017-07-28 23:33:30 +10:00
James Ross-Gowan 5453604606 subprocess-win: don't leak pipe handle on error 2017-07-28 23:00:46 +10:00
Niklas Haas 345bb193fe vo_opengl: support loading custom user textures
Parsing the texture data as raw strings makes the textures the most
portable and self-contained. In order to facilitate different types of
shaders, the parse_user_shader interaction has been changed to instead
have it loop through blocks and call the passed functions for each valid
block parsed. This is more modular and also cleaner, with better code
separation.

Closes #4586.
2017-07-27 23:51:05 +02:00
Niklas Haas f1af6e53f0 vo_opengl: slightly refactor user_shaders code
- Each struct tex_hook now stores multiple hooks, this allows us to
  avoid the awkward way of the current code has to add the same pass
  multiple times.

- As a consequence, SHADER_MAX_HOOKS was split up into SHADER_MAX_PASSES
  (number of tex_hooks) and SHADER_MAX_HOOKS (number of hooked textures
  per tex_hook), and both numbers decreased correspondingly.

- Instead of having a weird free() callback, we can just leverage
  talloc's recursive free behavior. The only user is the user shaders code
  anyway.
2017-07-27 23:45:17 +02:00
Niklas Haas ea76f79e5d vo_opengl: tone map on the maximum signal component
This actually makes sure we don't decolor due to clipping even when the
signal itself exceeds the luma by a significant factor, which was pretty
common for saturated blues (and to a lesser degree, reds) - most
noticeable in skies etc.

This prevents the turn-the-sky-cyan effect of mobius tone mapping, and
should also improve the other tone mapping modes in quality.
2017-07-27 09:40:12 +02:00
Niklas Haas e1cc43182c vo_opengl: fix mpgl_caps bit check
As pointed out by @bjin, this would match if _any_ of the reqs are set.
Need to test for explicit equality.
2017-07-27 00:38:54 +02:00
wm4 81851febc4 vo_opengl: start work on rendering API abstraction
This starts work on moving OpenGL-specific code out of the general
renderer code, so that we can support other other GPU APIs. This is in
a very early stage and it's only a proof of concept. It's unknown
whether this will succeed or result in other backends.

For now, the GL rendering API ("ra") and its only provider (ra_gl) does
texture creation/upload/destruction only. And it's used for the main
video texture only. All other code is still hardcoded to GL.

There is some duplication with ra_format and gl_format handling. In the
end, only the ra variants will be needed (plus the gl_format table of
course). For now, this is simpler, because for some reason lots of hwdec
code still requires the GL variants, and would have to be updated to
use the ra ones.

Currently, the video.c code accesses private ra_gl fields. In the end,
it should not do that of course, and it would not include ra_gl.h.

Probably adds bugs, but you can keep them.
2017-07-26 11:31:43 +02:00
Niklas Haas 5904eddb38 vo_opengl: describe the texture uploading mode
Be a bit more transparent here, which is especially helpful when people
are sending me screenshots of stats pages.
2017-07-26 02:42:23 +02:00
Niklas Haas b31020b193 vo_opengl: check against shmem limits
The radius check was not strict enough, especially not for all
platforms. To fix this, actually check the hardware capabilities instead
of relying on a hard-coded maximum radius.
2017-07-26 01:54:33 +02:00
James Ross-Gowan 9875f14ad4 vo_opengl: fix image uniforms for older OpenGL
This explicitly enables the GL_ARB_shader_image_load_store extension,
which seems to fix compute shaders for Intel/GL 3.0.
2017-07-26 08:02:03 +10:00
Niklas Haas 49a648447f vo_opengl: cosmetic change 2017-07-25 20:14:03 +02:00
James Ross-Gowan 7097b6f81c subprocess-win: remove VLA usage
This only ever waits on four handles at most anyway.
2017-07-26 00:20:11 +10:00
Niklas Haas f2809e19f0 vo_opengl: add PRINTF_ATTRIBUTE to gl_sc_ssbo
Doesn't uncover any bugs, but apparently we're getting in the habit of
this anyway.
2017-07-25 06:35:10 +02:00
Niklas Haas 62de84cbe3 vo_opengl: kill off FBOTEX_COMPUTE again
The textures not having an FBO actually caused regressions when trying
to render the subtitles on top of this texture (--blend-subtitles),
which still relied on an FBO.

So just kill off the logic entirely. Why worry about a single FBO wasted
when we're allocating like 10 anyway.

Fixes #4657.
2017-07-25 06:32:29 +02:00
Niklas Haas d099e037ef vo_opengl: fix incoherent SSBO usage
According to the OpenGL spec, atomic access to SSBO variables is *not*
guaranteed to be coherent, even when reusing the same SSBO attached to
the same shader across different frames. So we actually need a
glMemoryBarrier here, at least in theory.
2017-07-25 06:11:57 +02:00
Niklas Haas 6c06e7e2a0 vo_opengl: cosmetic fix 2017-07-25 05:23:52 +02:00
Niklas Haas cd226bdfd8 vo_opengl: fix incoherent texture usage
This bug slipped past my attention because nvidia ignores memory
barriers, but this is not necessarily always the case. Since
image_load_store is incoherent (specifically, writing to images from
compute shaders is incoherent) we need to insert a memory barrier to
make it coherent again. Since we only care about texture fetches, that's
the only barrier we need.
2017-07-25 05:22:29 +02:00
Niklas Haas 241d5ebc46 vo_opengl: adjust the rules for linearization
Two changes, compounded into one since they affect the same logic:

1. Never use linearization for HDR downscaling
2. Always use linearization for interpolation

Instead of fixing p->use_linear at the beginning of pass_render_frame,
we flip it on "dynamically" as needed. I plan on killing this
p->use_linear frame (along with other per-pass metadata) and moving them
into their own struct for tracking the "current" state of the video, but
that's a separate/upcoming refactor.

As a small bonus, reduce some code duplication in the interpolation
logic.

Fixes #4631
2017-07-24 23:26:15 +02:00
Bin Jin 13ef6bcf6f vo_opengl: enable compute shader for mesa
Mesa 17.1 supports compute shader but not full specs of OpenGL 4.3.
Change the code to detect OpenGL extension "GL_ARB_compute_shader"
rather than OpenGL version 4.3.

HDR peak detection requires SSBO, and polar scaler requires 2D array
extension. Add these extensions as requirement as well.
2017-07-25 04:07:26 +08:00
Niklas Haas dbef5b737e manpage: expand --hwdec warnings
I've found more test cases where hwdec=cuda shits itself, even
hwdec=cuda-copy. So the whole “copyback is no worse than swdec” is
simply not true. Also, in the light of 10 bit media files and APIs
silently truncating to 8 bit, the warnings need to be generalized a bit.
It's no longer safe to say that “doesn't convert to RGB” means “perfect
playback”.

I've also added a very strong disclaimer to the whole hwdec scenario
clarifying why hwdec is usually a bad idea unless absolutely needed,
because I've seen issue after issue that is resolved by disabling hwdec.
2017-07-24 19:16:30 +02:00
Niklas Haas 0c84ee01d5 vo_opengl: support user compute shaders
These are identical to regular fragment shader hooks, but with extra
metadata indicating the preferred block size.
2017-07-24 17:19:34 +02:00
Niklas Haas f338ec4591 vo_opengl: implement compute shader based EWA kernel
This performs almost 50% faster on my machine (!!), from 4650μs down to
about 3176μs for ewa_lanczossharp.

It's possible we could use a similar approach to speed up the separable
scalers, although with vastly simpler code. For separable scalers we'd
also have the additional huge benefit of only needing padding in one
direction, so we could potentially use a big 256x1 kernel or something
to essentially compute an entire row at once.
2017-07-24 17:19:31 +02:00
Niklas Haas b196cadf9f vo_opengl: support HDR peak detection
This is done via compute shaders. As a consequence, the tone mapping
algorithms had to be rewritten to compute their known constants in GLSL
(ahead of time), instead of doing it once. Didn't affect performance.

Using shmem/SSBO atomics in this way is extremely fast on nvidia, but it
might be slow on other platforms. Needs testing.

Unfortunately, setting up the SSBO still requires OpenGL calls, which
means I can't have it in video_shaders.c, where it belongs. But I'll
defer worrying about that until the backend refactor, since then I'll be
breaking up the video/video_shaders structure anyway.
2017-07-24 17:19:31 +02:00
Niklas Haas aad6ba018a vo_opengl: support compute shaders
These can either be invoked as dispatch_compute to do a single
computation, or finish_pass_fbo (after setting compute_size_minimum) to
render to a new texture using a compute shader. To make this stuff all
work transparently, we try really, really hard to make compute shaders
as identical to fragment shaders as possible in their behavior.
2017-07-24 17:19:31 +02:00
Niklas Haas eb54d2ad4d vo_opengl: cut down on FBOTEX_FUZZY abuse
Don't use FBOTEX_FUZZY where the FBO is sized according to
p->texture_w/h, since this changes infrequently (and when it does, we
need to reset everything anyway). No real reason to make this change
other than that it possibly prevents nasty surprises in the future, so I
feel more comfortable about it.
2017-07-24 16:41:38 +02:00
wm4 38b367c039 build: warn against VLA
Although C99 supports them, they are optional in C11, and we don't
like/use them anyway.
2017-07-24 08:12:42 +02:00
wm4 24dc91907a common, vo_opengl: add/use helper for formatted strings on the stack
Seems like I really like this C99 idiom. No reason not to generalize it
do snprintf(). Introduce mp_tprintf(), which basically this idiom to
snprintf(). This macro looks like it returns a string that was allocated
with alloca() on the caller site, except it's portable C99/C11. (And
unlike alloca(), the result is valid only within block scope.)

Use it in 2 places in the vo_opengl code. But it has the potential to
make a whole bunch of weird looking code look slightly nicer.
2017-07-24 08:12:42 +02:00
wm4 3d0f86145c vo_opengl: check format on some printf-like calls
Fix 1 incorrect use.
2017-07-24 08:08:02 +02:00
wm4 64d56114ed vo_opengl: add direct rendering support
Can be enabled via --vd-lavc-dr=yes. See manpage additions for what it
does.

This reminds of the MPlayer -dr flag, but the implementation is
completely different. It's the same basic concept: letting the decoder
render into a GPU buffer to avoid a copy. Unlike MPlayer, this doesn't
try to go through filters (libavfilter doesn't support this anyway).
Unless a filter can work in-place, DR will be silently disabled. MPlayer
had very complex semantics about buffer types and management (which
apparently nobody ever understood) and weird restrictions that mostly
limited it to mpeg2 style codecs. The mpv code does not do any of this,
and just lets the decoder allocate an arbitrary number of untyped
images. (No MPlayer code was used.)

Parts of the code based on work by atomnuker (starting point for the
generic code) and haasn (some GL definitions, some basic PBO code, and
correct fencing).
2017-07-24 04:32:55 +02:00
wm4 9e7665b21b mp_image: expose some image allocation code as helpers, refactor
Refactor the image allocation code, and expose part of it as helper
code. This aims towards allowing callers to easily allocate mp_image
references from custom-allocated linear buffers. This is exposing only
as much as what should be actually required.
2017-07-23 09:31:27 +02:00
wm4 0ce3dce03a mp_image_pool: disallow adding read only frames
Remove the feature of adding read-only frames to mp_image_pool_add().
This makes no sense, because an image pool is an allocator, and must
always return writable images. Also check these assumptions earlier.
2017-07-23 09:28:36 +02:00
wm4 bbfd9b5a29 vo_opengl: osd: remove stale declaration
Was missed in the previous changes.
2017-07-23 00:02:02 +02:00
wm4 87e9cd13aa vo_opengl: add printf format checking to pass_describe() 2017-07-22 22:08:23 +02:00
wm4 95885bbaa2 vo_opengl: make VAO helper private, remove old VAO mechanism
The struct describing vertex attributes is still public, of course.
2017-07-22 21:56:23 +02:00
wm4 d3dfffdf02 vo_opengl: osd: use new VAO mechanism
In addition to using the new VAO mechanism introduced in the previous
commit, this tries to keep the OSD code self-contained. This doesn't
work all too well (because of the pass and CMS stuff), but it's still
better than before.
2017-07-22 21:55:38 +02:00
wm4 a24df94fed vo_opengl: add mechanism to create/cache VAO on the fly
This removes VAO handling from video.c. Instead the shader cache will
create the VAO as needed. The consequence is that this creates a VAO
per shader, which might be a bit wasteful, but doesn't matter anyway.
2017-07-22 21:51:32 +02:00
wm4 1c81311673 vo_opengl: osd: refactor and simplify
Reduce this to 1 draw call per OSD pass. This removes the need for some
annoying special handling regarding 3D video support (we supported
duplicating the OSD/subtitles for side-by-side 3D output etc.).

Remove the unneeded texture sampler uniform thing.
2017-07-22 21:46:59 +02:00
wm4 2378acc3b3 options: drop --video-aspect-method=hybrid
Remove this code because it could be argued that it contains GPL-only
code (see commit 642e963c86 for details).

The remaining aspect methods appear to work just as well, are
potentially more compatible to other players, and the code becomes much
simpler.
2017-07-21 20:19:39 +02:00
wm4 533ff28574 client API: drop some compatibility handling
See commit e4bc563fd2 for more information.
2017-07-21 20:09:22 +02:00
wm4 a22ff44f7b input: drop deprecated "osd" command
Complicated situation due to changes by GPL-only author, but also
unnecessary due to newer mechanisms.
2017-07-21 20:02:58 +02:00
wm4 4bc29c1730 options: kill --field-dominance
GPL-only author, no chance of relicensing.
2017-07-21 20:00:09 +02:00
wm4 7a51271d3d demux_lavf: don't free AVFormatContext.key field
We don't even set it anymore. This really should be up to libavformat.
2017-07-21 19:54:26 +02:00
wm4 8c82555e41 ao_oss: fix a dumb calculation
period_size used the wrong unit, and even if the unit had been correct,
was assigned the wrong value.

Probably fixes #4642.
2017-07-21 19:45:59 +02:00
James Cowgill f676f6d2b9 manpage: fix minor spelling mistake in mpv.rst
Found by https://lintian.debian.org/
2017-07-19 19:05:25 +01:00
Ricardo Constantino e0739378dd travis: trigger website rebuild on VERSION changes too
Needed to update the stable manual if no DOCS were changed.
2017-07-19 19:03:08 +01:00
Martin Herkt 9e124933e5 Update VERSION 2017-07-18 21:15:58 +02:00
390 changed files with 33585 additions and 24591 deletions

No files matched your search

+2 -1
View File
@@ -22,4 +22,5 @@ or ignored.
### 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.)
or similar sites. (Only needed if the issue cannot be reproduced without it.)
Do not use garbage like "cloud storage", especially not Google Drive.
+2 -7
View File
@@ -5,10 +5,8 @@ os:
#- osx
env:
matrix:
- LIBAV=libav-stable
- LIBAV=libav-git
- LIBAV=ffmpeg-stable
- LIBAV=ffmpeg-git
- LIBAV=libav-git
global:
# Coverity token
- secure: "H21mSRlMhk4BKS0xHZvCFGJxteCP0hRVUxTuNfM2Z9HBsyutuLEYMtViLO86VtM+Tqla3xXPzUdS4ozLwI72Ax/5ZUDXACROj73yW6QhFB5D6rLut12+FjqC7M33Qv2hl0xwgNBmR5dsm1ToP37+Wn+ecJQNvN8fkTXF+HVzOEw="
@@ -26,16 +24,12 @@ branches:
matrix:
exclude:
- os: osx
env: LIBAV=libav-stable
- os: osx
env: LIBAV=libav-git
- os: osx
env: LIBAV=ffmpeg-git
- os: osx
compiler: gcc
- os: linux
env: LIBAV=ffmpeg-stable
- os: linux
compiler: clang
@@ -44,6 +38,7 @@ script:
- ./bootstrap.py
- ./waf configure
- ./waf build
after_failure: cat ./build/config.log
after_script: TOOLS/travis-rebuild-website
notifications:
+56 -313
View File
@@ -1,352 +1,95 @@
mpv is a fork of mplayer2, which is a fork of MPlayer.
mpv as a whole is licensed as GPL version 2 or later (see LICENSE). Most source
files are GPLv2+, but some files are available under a more liberal license,
such as LGPLv2.1+, BSD, MIT, ISC, and possibly others. Look at the copyright
header of each source file, and grep the sources for "Copyright" if you need
to know details. C source files without Copyright notice are licensed as
LGPLv2.1+. Also see the list of files with specific licenses below (not all
files can have a standard license header).
mpv as a whole is licensed under the GNU General Public License GPL version 2
or later (called GPLv2+ in this document, see LICENSE.GPL for full license
text) by default, or the GNU Lesser General Public License LGPL version 2 or
later (LGPLv2.1+ in this document, see LICENSE.LGPL for full license text) if
built with the --enable-lgpl configure switch.
All new contributions must be LGPLv2.1+ licensed, or if the changes are done on
GPL code, must come with the implicit agreement that the project can relicense
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.
Most source files are LGPLv2.1+ or GPLv2+, but some files are available under
more liberal licenses, such as BSD, MIT, ISC, and possibly others. Look at the
copyright header of each source file, and grep the sources for "Copyright" if
you need to know details. C source files without Copyright notice are usually
licensed as LGPLv2.1+. Also see the list of files with specific licenses below
(not all files can have a standard license header).
All new contributions must be LGPLv2.1+ licensed. Using a more liberal license
compatible to LGPLv2.1+ is also ok.
If changes are done on GPL code, must come with the implicit agreement that the
project can relicense the changes to LGPLv2.1+ at a later point without asking
the contributor. This is a safeguard for making potential relicensing of
remaining GPL code to LGPLv2.1+ easier.
For information about authors and contributors, consult the git log, which
contains the complete SVN and CVS history as well.
Note that mplayer2 as a whole is licensed under GPLv3+. This is because it uses
a copy of talloc (part of Samba), which is LGPLv3+, and the next compatible
license for this mix is GPLv3+.
MPlayer as a whole is licensed under GPLv2 (incompatible to GPLv3!), because
some files are licensed to GPLv2 (and _not_ any later version of the license).
In particular, this affects the file libmpdemux/demux_ty_osd.c. It is disabled
under mplayer2, and has been removed from mpv.
"v2.1+" in this context means "version 2.1 or later".
Some libraries are GPLv2+ or GPLv3+ only. Building mpv with Samba support makes
it GPLv3+.
Source files with specific licenses:
- etc/input.conf is LGPLv2.1+
- etc/builtin.conf is LGPLv2.1+
- etc/encoding-profiles.conf is LGPLv2.1+
- all mpv icons and derived files are LGPLv2.1+ (mpv-icon-8bit-16x16.png etc.)
- everything else under etc/ is unknown
- everything under DOCS/man/ is GPLv2+
- sub/osd_font.otf is LGPLv2.1+
- version.sh is LGPLv2+
- bootstrap.py is unknown (probably GPLv2+ or LGPLv2+)
- the build system (wscript, waftools/*) is LGPLv2+, some parts BSD
mpv can be built as LGPLv2.1+ with the --enable-lgpl configure option. To add
a LGPL mode to mpv, MPlayer code had to be relicensed from GPLv2+ to LGPLv2.1+
by asking the MPlayer authors for permission. Since permission could not be
obtained from everyone, LGPL mode disables the following features, some of
them quite central:
- no audio filtering, which breaks: --af, pitch correction, fine control over
downmix/upmix/resampling behavior
- Linux X11 video output
- BSD audio output via OSS
- NVIDIA/Linux hardware decoding (vdpau, although nvdec usually works)
- Linux TV input
- minor features: jack, DVD, CDDA, SMB, CACA, legacy direct3d VO
Some of these will be fixed in the future. The intended use for LGPL mode is
with libmpv, and currently it's not recommended to build mpv CLI in LGPL mode
at all.
Some files are marked with "Almost LGPL." These files are GPL, but all authors
have agreed to relicense them to LGPL. the problem is that one of the authors is
Michael Niedermayer, who cited the following conditions for relicensing:
The following files are still GPL only (--enable-lgpl disables them):
http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2016-September/073535.html
We assume the first 3 conditions are fulfilled. The last condition can be
interpreted as that his code can be changed to LGPL only as soon as the "core"
of mpv changes to LGPL. We interpret "core" as something minimal, that can
actually be built and run, with all GPL code disabled.
Some files are LGPLv3+. This is due to the contributions of a single developer
going by the SVN username "iive". The chosen license of this project is
LGPLv2.1+. The affected files will be changed to LGPLv2.1+ at the earliest
opportunity, for example if his contributions disappear by being replaced
or removed. All new contributions to these files are implied to be LGPLv2.1+.
LGPL relicensing status. Files which require some sort of action to get a basic
LGPL player core (relicensing, replacement, or partial/full rewrites) are marked
with an "x".
audio/decode/ad.h LGPL
audio/decode/ad_lavc.c LGPL
audio/decode/ad_spdif.c LGPL
audio/decode/dec_audio.* LGPL
x audio/filter/af.* must be killed (main author disagreed)
(required for LGPL core: a new filter chain must be written)
audio/filter/af_channel.c must be killed (main author disagreed)
audio/filter/af_equalizer.c must be killed (main author disagreed)
audio/filter/af_pan.c must be killed (main author disagreed)
audio/filter/af_volume.c must be killed (main author disagreed)
audio/filter/equalizer.h must be killed (main author disagreed)
audio/filter/tools.c must be killed (main author disagreed)
audio/filter/af_format.c LGPL
audio/filter/af_lavc3enc.c LGPL
audio/filter/af_lavfi.c LGPL
audio/filter/af_scaletempo.c LGPL
audio/filter/af_rubberband.c LGPL
audio/out/ao.c LGPL
audio/out/ao.h LGPL
audio/out/ao_alsa.c extremely hard (original author did not decide)
audio/out/ao_audiounit.m LGPL
audio/out/ao_coreaudio.c LGPL
audio/out/ao_coreaudio_chmap.c LGPL
audio/out/ao_coreaudio_chmap.h LGPL
audio/out/ao_coreaudio_exclusiv LGPL
audio/out/ao_coreaudio_properti LGPL
audio/out/ao_coreaudio_properti LGPL
audio/out/ao_coreaudio_utils.c LGPL
audio/out/ao_coreaudio_utils.h LGPL
audio/filter/* will be replaced with new filter chain
audio/filter/af_format.c mostly LGPL (except af glue code)
audio/filter/af_lavc3enc.c as above
audio/filter/af_lavfi.c as above
audio/filter/af_scaletempo.c as above
audio/filter/af_rubberband.c as above
audio/out/ao_jack.c will stay GPL
audio/out/ao_lavc.c LGPL
audio/out/ao_null.c LGPL
audio/out/ao_openal.c LGPL
audio/out/ao_opensles.c LGPL
audio/out/ao_oss.c will stay GPL
audio/out/ao_pcm.c LGPL
audio/out/ao_pulse.c LGPL
audio/out/ao_rsound.c LGPL
audio/out/ao_sdl.c LGPL
audio/out/ao_sndio.c LGPL (BSD)
audio/out/ao_wasapi.c LGPL
audio/out/ao_wasapi_changenotif LGPL
audio/out/ao_wasapi.h LGPL
audio/out/ao_wasapi_utils.c LGPL
audio/out/internal.h LGPL
audio/out/pull.c LGPL
audio/out/push.c LGPL
x audio/audio.* very hard (mp_audio based of anders' af_audio)
(required for LGPL core: determine if the struct can be used anyway, or
devise a cheap AVFrame wrapper)
audio/audio_buffer.* LGPL
audio/chmap.* LGPL
audio/chmap_sel.* LGPL
audio/fmt-conversion.* LGPL
audio/format.* LGPL
common/av_common.* LGPL
common/av_log.c almost LGPL
common/av_log.h LGPL
common/codecs.* LGPL
common/common.* LGPL
common/encode.h LGPL
common/encode_lavc.* LGPL
common/global.h LGPL
common/msg.c almost LGPL
common/msg_control.h LGPL
common/msg.h LGPL
common/playlist.* LGPL
common/recorder.* LGPL
common/tags.* LGPL
common/version.c LGPL
demux/codec_tags.* LGPL
demux/cue.* LGPL
demux/demux.* LGPL
demux/demux_cue.c LGPL
demux/demux_disc.c LGPL
demux/demux_edl.c LGPL
demux/demux_lavf.c almost LGPL
demux/demux_libarchive.c LGPL
demux/demux_mf.c LGPLv3+
demux/demux_mkv.c LGPL (mostly)
demux/demux_mkv_timeline.c LGPL
demux/demux_null.c LGPL
demux/demux_playlist.c LGPL
demux/demux_rar.c LGPL
demux/demux_raw.c almost LGPL
demux/demux_timeline.c LGPL
audio/audio.* needed by af code only
demux/demux_tv.c will stay GPL
demux/ebml.* LGPL
demux/matroska.h LGPL
demux/packet.* LGPL
demux/stheader.h LGPL
demux/timeline.* LGPL
input/cmd_* LGPL
input/event.* LGPL
input/input.* LGPL
input/ipc.c LGPL
input/ipc-unix.c LGPL
input/ipc-win.c LGPL
input/keycodes.* LGPL
input/pipe-win32.c LGPL
libmpv/*.* LGPL
misc/*.* LGPL
options/m_config.* LGPL
options/m_option.c almost LGPL
options/m_option.h LGPL
options/m_property.* LGPL
options/options.* LGPL
options/parse_commandline.* LGPL
options/parse_configfile.* LGPL
options/path.* LGPL
osdep/android/* LGPL (BSD)
osdep/ar/* LGPL (BSD)
osdep/atomic.h LGPL
osdep/compiler.h LGPL
osdep/endian.h LGPL
osdep/glob-win.c LGPL
osdep/io.* LGPL
osdep/macosx_application.h LGPL
osdep/macosx_application.m LGPL
osdep/macosx_application_objc.h LGPL
osdep/macosx_compat.h LGPL
osdep/macosx_events.* LGPL
osdep/macosx_events_objc.h LGPL
osdep/macosx_touchbar.* LGPL
osdep/macosx_versions.h LGPL
osdep/main-fn-cocoa.c LGPL
osdep/main-fn.h LGPL
osdep/main-fn-unix.c LGPL
osdep/main-fn-win.c LGPL
osdep/mpv.exe.manifest LGPL
osdep/mpv.rc LGPL
osdep/path.h LGPL
osdep/path-macosx.m LGPL
osdep/path-unix.c LGPL
osdep/path-win.c LGPL
osdep/semaphore.h LGPL
osdep/semaphore_osx.c LGPL
osdep/strnlen.h LGPL
osdep/subprocess.* LGPL
osdep/subprocess-posix.c LGPL
osdep/subprocess-win.c LGPL
osdep/terminal.h LGPL
osdep/terminal-unix.c LGPL
osdep/terminal-win.c LGPL
osdep/threads.* LGPL
osdep/timer.c LGPL
osdep/timer.h LGPL
osdep/timer-darwin.c LGPL (MIT)
osdep/timer-linux.c LGPL
osdep/timer-win2.c LGPL
osdep/w32_keyboard.c LGPL
osdep/w32_keyboard.h LGPL
osdep/win32-console-wrapper.c LGPL (BSD)
osdep/win32/* LGPL (ISC)
osdep/windows_utils.* LGPL
x player/audio.c LGPL (dysfunctional due to libaf)
player/client.* LGPL (ISC)
player/command.c LGPL
player/command.h LGPL
player/configfiles.c LGPL
player/core.h LGPL
player/external_files.* LGPL
player/lavfi.* LGPL
player/loadfile.c LGPL
player/lua/*.* LGPL
player/lua.c LGPL
player/misc.c LGPL
player/osd.c LGPL
player/playloop.c LGPL
player/screenshot.* LGPL
player/scripting.* LGPL
player/sub.c LGPL
player/video.c LGPL
stream/ai_* will stay GPL (TV code)
stream/audio_in.* will stay GPL (TV code)
stream/cache.c LGPLv3+
stream/cache_file.c LGPL
stream/cookies.* LGPL
stream/dvb* must stay GPL
stream/frequencies.* must stay GPL
stream/rar.* LGPL
stream/stream_avdevice.c LGPL
stream/stream_bluray.c LGPL
stream/stream.* LGPL
stream/stream_cb.c LGPL
stream/stream_cdda.c unknown
stream/stream_dvb.* must stay GPL
stream/stream_dvd.c unknown
stream/stream_dvd_common.* unknown
stream/stream_dvdnav.c unknown
stream/stream_edl.c LGPL
stream/stream_file.c LGPL
stream/stream_lavf.c LGPL
stream/stream_libarchive.* LGPL
stream/stream_memory.c LGPL
stream/stream_mf.c LGPL
stream/stream_null.c LGPL
stream/stream_rar.c LGPL
stream/stream_smb.c will stay GPLv3
stream/stream_tv.c will stay GPL
stream/tv* will stay GPL
sub/* LGPL
ta/* LGPL (ISC)
video/decode/d3d.* LGPL
video/decode/dec_video.* almost LGPL
video/decode/hw_cuda.c LGPL
video/decode/hw_d3d11va.c LGPL
video/decode/hw_dxva2.c LGPL
video/decode/hw_videotoolbox.c LGPL
video/decode/lavc.h almost LGPLv3+
video/decode/vd.h LGPL
video/decode/vd_lavc.c almost LGPLv3+
video/filter/refqueue.* LGPL
video/filter/vf.c LGPL
video/filter/vf.h LGPL (mostly)
video/filter/vf_buffer.c LGPL
video/filter/vf_crop.c will be deleted
video/filter/vf_d3d11vpp.c LGPL
video/filter/vf_dsize.c will be deleted
video/filter/vf_eq.c will be deleted
video/filter/vf_expand.c will be deleted
video/filter/vf_flip.c will be deleted
video/filter/vf_format.c will be deleted
video/filter/vf_gradfun.c will be deleted
video/filter/vf_lavfi.* LGPL
video/filter/vf_mirror.c will be deleted
video/filter/vf_noformat.c will be deleted
video/filter/vf_pullup.c will be deleted
video/filter/vf_rotate.c will be deleted
video/filter/vf_scale.c will be deleted
video/filter/vf_stereo3d.c will be deleted
video/filter/vf_sub.c will be deleted
video/filter/vf_vapoursynth.c LGPL
video/filter/vf_vavpp.c LGPL
video/filter/vf_vdpaupp.c LGPL
video/filter/vf_yadif.c will be deleted
video/csputils.* LGPL
video/fmt-conversion.* LGPL
video/gpu_memcpy.* will be deleted
video/hwdec.* LGPL
video/image_writer.* LGPL
video/img_format.* LGPL
video/mp_image.* almost LGPL
video/mp_image_pool.* LGPL
video/out/aspect.* LGPL
video/out/bitmap_packer.* LGPL
video/out/cocoa* LGPL
video/out/d3d_shader_420p.h LGPL
video/out/d3d_shader_nv12.h LGPL
video/out/d3d_shader_yuv.hlsl LGPL
video/out/dither.* LGPL
video/out/drm_common.* LGPL
video/out/filter_kernels.* LGPL (BSD)
video/out/opengl/hwdec_vaglx.c GPL
video/out/opengl/* LGPL
video/out/vo.c LGPL
video/out/vo.h LGPL
video/out/vo_caca.c unknown
video/out/vo_direct3d.c unknown
video/out/vo_drm.c LGPL
video/out/vo_image.c LGPL
video/out/vo_lavc.c LGPL
video/out/vo_null.c LGPL
video/out/vo_opengl.c LGPL
video/out/vo_opengl_cb.c LGPL
video/out/vo_rpi.c LGPL
video/out/vo_sdl.c LGPL
video/out/vo_tct.c LGPL
video/out/vo_vaapi.c probably impossible (some company's code)
video/out/vo_vdpau.c probably impossible (nVidia's code)
video/out/vo_wayland.c LGPL
video/out/vo_x11.c probably impossible
video/out/vo_xv.c probably impossible
video/out/w32_common.* LGPL
video/out/wayland* LGPL
video/out/win32/* LGPL
video/out/win_state.* LGPL
video/out/x11_common.* probably impossible
video/out/x11_icon.bin LGPL
video/sws_utils.* almost LGPL
video/vaapi.* hard (GPL-only parts must be ifdefed)
video/vdpau.c hard (GPL-only parts must be ifdefed)
video/vdpau_functions.inc LGPL
video/vdpau.h unknown
video/vdpau_mixer.* actual code must be rewritten
video/vt.* LGPL
DOCS/man/ GPLv2+
bootstrap.py unknown license, probably GPLv2+ or LGPLv2+
etc/mplayer-input.conf unknown license, probably GPLv2+
mpv.desktop unknown license, probably GPLv2+
etc/restore-old-bindings.conf unknown license, probably GPLv2+
The following files contain some optional GPL code (--enable-lgpl disables it):
options/parse_commandline.c dvd:// expansion
player/audio.c libaf glue code
None of the exceptions listed above affect the final binary if it's built as
LGPL. Linked libraries still can affect the final license (for example if
FFmpeg was built as GPL).
+7 -1
View File
@@ -32,7 +32,13 @@ API changes
::
--- mpv 0.26.0 ---
--- mpv 0.29.0 ---
1.26 - remove glMPGetNativeDisplay("drm") support
- add mpv_opengl_cb_window_pos and mpv_opengl_cb_drm_params and
support via glMPGetNativeDisplay() for using it
- make --stop-playback-on-init-failure=no the default in libmpv (just
like in mpv CLI)
--- mpv 0.27.0 ---
1.25 - remove setting "no-" options via mpv_set_option*(). (See corresponding
deprecation in 0.23.0.)
--- mpv 0.25.0 ---
+19 -21
View File
@@ -101,11 +101,14 @@ Installing MSYS2
1. Download an installer from https://msys2.github.io/
It doesn't matter whether the i686 or the x86_64 version is used. Both can
build 32-bit and 64-bit binaries when running on a 64-bit version of Windows.
Both the i686 and the x86_64 version of MSYS2 can build 32-bit and 64-bit
mpv binaries when running on a 64-bit version of Windows, but the x86_64
version is preferred since the larger address space makes it less prone to
fork() errors.
2. Start a MinGW-w64 shell (``mingw64.exe``). Note that this is different
from the MSYS2 shell that is started from the final installation dialog.
2. Start a MinGW-w64 shell (``mingw64.exe``). **Note:** This is different from
the MSYS2 shell that is started from the final installation dialog. You must
close that shell and open a new one.
For a 32-bit build, use ``mingw32.exe``.
@@ -129,42 +132,37 @@ Installing mpv dependencies
```bash
# Install MSYS2 build dependencies and a MinGW-w64 compiler
pacman -S git mingw-w64-x86_64-pkg-config python mingw-w64-x86_64-gcc
pacman -S git python $MINGW_PACKAGE_PREFIX-{pkg-config,gcc}
# Install the most important MinGW-w64 dependencies. libass, libbluray and
# lcms2 are also pulled in as dependencies of ffmpeg.
pacman -S mingw-w64-x86_64-ffmpeg mingw-w64-x86_64-libjpeg-turbo mingw-w64-x86_64-lua51
# Install additional (optional) dependencies
pacman -S mingw-w64-x86_64-libdvdnav mingw-w64-x86_64-libguess mingw-w64-x86_64-angleproject-git
# Install the most important MinGW-w64 dependencies. libass and lcms2 are also
# pulled in as dependencies of ffmpeg.
pacman -S $MINGW_PACKAGE_PREFIX-{ffmpeg,libjpeg-turbo,lua51,angleproject-git}
```
For a 32-bit build, install ``mingw-w64-i686-*`` packages instead.
Building mpv
------------
Clone the latest mpv from git and install waf:
Clone the latest mpv from git and install waf. **Note:** ``/usr/bin/python3``
is invoked directly here, since an MSYS2 version of Python is required.
```bash
git clone https://github.com/mpv-player/mpv.git && cd mpv
./bootstrap.py
/usr/bin/python3 bootstrap.py
```
Finally, compile and install mpv. Binaries will be installed to
``/mingw64/bin``.
``/mingw64/bin`` or ``/mingw32/bin``.
```bash
# For a 32-bit build, use --prefix=/mingw32 instead
./waf configure CC=gcc.exe --check-c-compiler=gcc --prefix=/mingw64
./waf install
/usr/bin/python3 waf configure CC=gcc.exe --check-c-compiler=gcc --prefix=$MSYSTEM_PREFIX
/usr/bin/python3 waf install
```
Or, compile and install both libmpv and mpv:
```bash
./waf configure CC=gcc.exe --check-c-compiler=gcc --enable-libmpv-shared --prefix=/mingw64
./waf install
/usr/bin/python3 waf configure CC=gcc.exe --check-c-compiler=gcc --enable-libmpv-shared --prefix=$MSYSTEM_PREFIX
/usr/bin/python3 waf install
```
Linking libmpv with MSVC programs
+3 -1
View File
@@ -68,7 +68,7 @@ Sending patches
be documented in input.rst. All changes to the user interface (options,
properties, commands) must be documented with a small note in
interface-changes.rst (although documenting additions is optional, and
obscure corner cases and potentially be skipped too). Changes to the libmpv
obscure corner cases can potentially be skipped too). Changes to the libmpv
API must be reflected in the libmpv's headers doxygen, and should be
documented in client-api-changes.rst.
@@ -140,6 +140,8 @@ mpv uses C99 with K&R formatting, with some exceptions.
...
}
```
(If the if body is simple enough, this rule can be skipped.)
- Remove any trailing whitespace.
General coding
+92
View File
@@ -19,6 +19,98 @@ Interface changes
::
--- mpv 0.28.0 ---
- rename --hwdec=mediacodec option to mediacodec-copy, to reflect
conventions followed by other hardware video decoding APIs
- drop previously deprecated --heartbeat-cmd and --heartbeat--interval
options
- rename --vo=opengl to --vo=gpu
- rename --opengl-backend to --gpu-context
- rename --opengl-shaders to --glsl-shaders
- rename --opengl-shader-cache-dir to --gpu-shader-cache-dir
- rename --opengl-tex-pad-x/y to --gpu-tex-pad-x/y
- rename --opengl-fbo-format to --fbo-format
- rename --opengl-gamma to --gamma-factor
- rename --opengl-debug to --gpu-debug
- rename --opengl-sw to --gpu-sw
- rename --opengl-vsync-fences to --swapchain-depth, and the interpretation
slightly changed. Now defaults to 3.
- rename the built-in profile `opengl-hq` to `gpu-hq`
- the semantics of --opengl-es=yes are slightly changed -> now requires GLES
- remove the (deprecated) alias --gpu-context=drm-egl
- remove the (deprecated) --vo=opengl-hq
- remove --opengl-es=force2 (use --opengl-es=yes --opengl-restrict=300)
- the --msg-level option now affects --log-file
- drop "audio-out-detected-device" property - this was unavailable on all
audio output drivers for quite a while (coreaudio used to provide it)
- deprecate --videotoolbox-format (use --hwdec-image-format, which affects
most other hwaccels)
- remove deprecated --demuxer-max-packets
- remove most of the deprecated audio and video filters
- remove the deprecated --balance option/property
- rename the --opengl-hwdec-interop option to --gpu-hwdec-interop, and
change some of its semantics: extend it take the strings "auto" and
"all". "all" loads all backends. "auto" behaves like "all" for
vo_opengl_cb, while on vo_gpu it loads nothing, but allows on demand
loading by the decoder. The empty string as option value behaves like
"auto". Old --hwdec values do not work anymore.
This option is hereby declared as unstable and may change any time - its
old use is deprecated, and it has very little use outside of debugging
now.
- change the --hwdec option from a choice to a plain string (affects
introspection of the option/property), also affects some properties
- rename --hwdec=rpi to --hwdec=mmal, sane for the -copy variant (no
backwards compatibility)
- deprecate the --ff-aid, --ff-vid, -ff-sid options and properties (there is
no replacement, but you can manually query the track property and use the
"ff-index" field to find the mpv track ID to imitate this behavior)
--- mpv 0.27.0 ---
- drop previously deprecated --field-dominance option
- drop previously deprecated "osd" command
- remove client API compatibility handling for "script", "sub-file",
"audio-file", "external-file" (these cases used to log a deprecation
warning)
- drop deprecated --video-aspect-method=hybrid option choice
- rename --hdr-tone-mapping to --tone-mapping (and generalize it)
- --opengl-fbo-format changes from a choice to a string. Also, its value
will be checked only on renderer initialization, rather than when the
option is set.
- Using opengl-cb now always assumes 8 bit per component depth, and dithers
to this size. Before, it tried to figure out the depth of the first
framebuffer that was ever passed to the renderer. Having GL framebuffers
with a size larger than 8 bit per component is quite rare. If you need
it, set the --dither-depth option instead.
- --lavfi-complex can now be set during runtime. If you set this in
expectation it would be applied only after a reload, you might observe
weird behavior.
- add --track-auto-selection to help with scripts/applications that
make exclusive use of --lavfi-complex.
- undeprecate --loop, and map it from --loop-playlist to --loop-file (the
deprecation was to make sure no API user gets broken by a sudden behavior
change)
- remove previously deprecated vf_eq
- remove that hardware deinterlace filters (vavpp, d3d11vpp, vdpaupp)
changed their deinterlacing-enabled setting depending on what the
--deinterlace option or property was set to. Now, a filter always does
what its filter options and defaults imply. The --deinterlace option and
property strictly add/remove its own filters. For example, if you run
"mpv --vf=vavpp --deinterlace=yes", this will insert another, redundant
filter, which is probably not what you want. For toggling a deinterlace
filter manually, use the "vf toggle" command, and do not set the
deinterlace option/property. To customize the filter that will be
inserted automatically, use --vf-defaults. Details how this works will
probably change in the future.
- remove deinterlace=auto (this was not deprecated, but had only a very
obscure use that stopped working with the change above. It was also
prone to be confused with a feature not implemented by it: auto did _not_
mean that deinterlacing was enabled on demand.)
- add shortened mnemonic names for mouse button bindings, eg. mbtn_left
the old numeric names (mouse_btn0) are deprecated
- remove mouse_btn3_dbl and up, since they are only generated for buttons
0-2 (these now print an error when sent from the 'mouse' command)
- rename the axis bindings to wheel_up/down/etc. axis scrolling and mouse
wheel scrolling are now conceptually the same thing
the old axis_up/down names remain as deprecated aliases
--- mpv 0.26.0 ---
- remove remaining deprecated audio device options, like --alsa-device
Some of them were removed in earlier releases.
-176
View File
@@ -91,81 +91,6 @@ Available filters are:
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
being played back. The center frequencies for the 10 bands are:
=== ==========
No. frequency
=== ==========
0 31.25 Hz
1 62.50 Hz
2 125.00 Hz
3 250.00 Hz
4 500.00 Hz
5 1.00 kHz
6 2.00 kHz
7 4.00 kHz
8 8.00 kHz
9 16.00 kHz
=== ==========
If the sample rate of the sound being played is lower than the center
frequency for a frequency band, then that band will be disabled. A known
bug with this filter is that the characteristics for the uppermost band
are not completely symmetric if the sample rate is close to the center
frequency of that band. This problem can be worked around by upsampling
the sound using a resampling filter before it reaches this filter.
``<g1>:<g2>:<g3>:...:<g10>``
floating point numbers representing the gain in dB for each frequency
band (-12-12)
.. admonition:: Example
``mpv --af=equalizer=11:11:10:5:0:-12:0:5:12:12 media.avi``
Would amplify the sound in the upper and lower frequency region
while canceling it almost completely around 1 kHz.
``channels=nch[:routes]``
Can be used for adding, removing, routing and copying audio channels. If
only ``<nch>`` is given, the default routing is used. It works as follows:
If the number of output channels is greater than the number of input
channels, empty channels are inserted (except when mixing from mono to
stereo; then the mono channel is duplicated). If the number of output
channels is less than the number of input channels, the exceeding
channels are truncated.
``<nch>``
number of output channels (1-8)
``<routes>``
List of ``,`` separated routes, in the form ``from1-to1,from2-to2,...``.
Each pair defines where to route each channel. There can be at most
8 routes. Without this argument, the default routing is used. Since
``,`` is also used to separate filters, you must quote this argument
with ``[...]`` or similar.
.. admonition:: Examples
``mpv --af=channels=4:[0-1,1-0,2-2,3-3] media.avi``
Would change the number of channels to 4 and set up 4 routes that
swap channel 0 and channel 1 and leave channel 2 and 3 intact.
Observe that if media containing two channels were played back,
channels 2 and 3 would contain silence but 0 and 1 would still be
swapped.
``mpv --af=channels=6:[0-0,0-1,0-2,0-3] media.avi``
Would change the number of channels to 6 and set up 4 routes that
copy channel 0 to channels 0 to 3. Channel 4 and 5 will contain
silence.
.. note::
You should probably not use this filter. If you want to change the
output channel layout, try the ``format`` filter, which can make mpv
automatically up- and downmix standard channel layouts.
``format=format:srate:channels:out-format:out-srate:out-channels``
Does not do any format conversion itself. Rather, it may cause the
filter system to insert necessary conversion filters before or after this
@@ -205,107 +130,6 @@ Available filters are:
used to do conversion itself, unlike this one which lets the filter system
handle the conversion.
``volume[=<volumedb>[:...]]``
Implements software volume control. Use this filter with caution since it
can reduce the signal to noise ratio of the sound. In most cases it is
best to use the *Master* volume control of your sound card or the volume
knob on your amplifier.
*WARNING*: This filter is deprecated. Use the top-level options like
``--volume`` and ``--replaygain...`` instead.
*NOTE*: This filter is not reentrant and can therefore only be enabled
once for every audio stream.
``<volumedb>``
Sets the desired gain in dB for all channels in the stream from -200 dB
to +60 dB, where -200 dB mutes the sound completely and +60 dB equals a
gain of 1000 (default: 0).
``replaygain-track``
Adjust volume gain according to the track-gain replaygain value stored
in the file metadata.
``replaygain-album``
Like replaygain-track, but using the album-gain value instead.
``replaygain-preamp``
Pre-amplification gain in dB to apply to the selected replaygain gain
(default: 0).
``replaygain-clip=yes|no``
Prevent clipping caused by replaygain by automatically lowering the
gain (default). Use ``replaygain-clip=no`` to disable this.
``replaygain-fallback``
Gain in dB to apply if the file has no replay gain tags. This option
is always applied if the replaygain logic is somehow inactive. If this
is applied, no other replaygain options are applied.
``softclip``
Turns soft clipping on. Soft-clipping can make the
sound more smooth if very high volume levels are used. Enable this
option if the dynamic range of the loudspeakers is very low.
*WARNING*: This feature creates distortion and should be considered a
last resort.
``s16``
Force S16 sample format if set. Lower quality, but might be faster
in some situations.
``detach``
Remove the filter if the volume is not changed at audio filter config
time. Useful with replaygain: if the current file has no replaygain
tags, then the filter will be removed if this option is enabled.
(If ``--softvol=yes`` is used and the player volume controls are used
during playback, a different volume filter will be inserted.)
.. admonition:: Example
``mpv --af=volume=10.1 media.avi``
Would amplify the sound by 10.1 dB and hard-clip if the sound level
is too high.
``pan=n:[<matrix>]``
Mixes channels arbitrarily. Basically a combination of the volume and the
channels filter that can be used to down-mix many channels to only a few,
e.g. stereo to mono, or vary the "width" of the center speaker in a
surround sound system. This filter is hard to use, and will require some
tinkering before the desired result is obtained. The number of options for
this filter depends on the number of output channels. An example how to
downmix a six-channel file to two channels with this filter can be found
in the examples section near the end.
``<n>``
Number of output channels (1-8).
``<matrix>``
A list of values ``[L00,L01,L02,...,L10,L11,L12,...,Ln0,Ln1,Ln2,...]``,
where each element ``Lij`` means how much of input channel i is mixed
into output channel j (range 0-1). So in principle you first have n
numbers saying what to do with the first input channel, then n numbers
that act on the second input channel etc. If you do not specify any
numbers for some input channels, 0 is assumed.
Note that the values are separated by ``,``, which is already used
by the option parser to separate filters. This is why you must quote
the value list with ``[...]`` or similar.
.. admonition:: Examples
``mpv --af=pan=1:[0.5,0.5] media.avi``
Would downmix from stereo to mono.
``mpv --af=pan=3:[1,0,0.5,0,1,0.5] media.avi``
Would give 3 channel output leaving channels 0 and 1 intact, and mix
channels 0 and 1 into output channel 2 (which could be sent to a
subwoofer for example).
.. note::
If you just want to force remixing to a certain output channel layout,
it is easier to use the ``format`` filter. For example,
``mpv '--af=format=channels=5.1' '--audio-channels=5.1'`` would always force
remixing audio to 5.1 and output it like this.
This filter supports the following ``af-command`` commands:
``set-matrix``
Set the ``<matrix>`` argument dynamically. This can be used to change
the mixing matrix at runtime, without reinitializing the entire filter
chain.
``scaletempo[=option1:option2:...]``
Scales audio tempo without altering pitch, optionally synced to playback
speed (default).
+2 -1
View File
@@ -216,7 +216,8 @@ Available audio output drivers are:
it will write a WAVE header every time the file is opened.
``rsound``
Audio output to an RSound daemon
Audio output to an RSound daemon. Use ``--audio-device=rsound/<hostname>``
to set the host name (with ``<hostname>`` replaced, without the ``< >``).
.. note:: Completely useless, unless you intend to run RSound. Not to be
confused with RoarAudio, which is something completely
+58 -28
View File
@@ -346,10 +346,6 @@ List of Input Commands
events that have already been displayed, or are within a short prefetch
range.
``osd [<level>]``
Toggle OSD level. If ``<level>`` is specified, set the OSD mode
(see ``--osd-level`` for valid values).
``print-text "<string>"``
Print text to stdout. The string can contain properties (see
`Property Expansion`_).
@@ -917,8 +913,8 @@ Property list
``file-size``
Length in bytes of the source file/stream. (This is the same as
``${stream-end}``. For ordered chapters and such, the
size of the currently played segment is returned.)
``${stream-end}``. For segmented/multi-part files, this will return the
size of the main or manifest file, whatever it is.)
``estimated-frame-count``
Total number of frames in current file.
@@ -958,8 +954,7 @@ Property list
``stream-path``
Filename (full path) of the stream layer filename. (This is probably
useless. It looks like this can be different from ``path`` only when
using e.g. ordered chapters.)
useless and is almost never different from ``path``.)
``stream-pos``
Raw byte position in source stream. Technically, this returns the position
@@ -1263,6 +1258,58 @@ Property list
Returns ``yes`` if the demuxer is idle, which means the demuxer cache is
filled to the requested amount, and is currently not reading more data.
``demuxer-cache-state``
Various undocumented or half-documented things.
Each entry in ``seekable-ranges`` represents a region in the demuxer cache
that can be seeked to. If there are multiple demuxers active, this only
returns information about the "main" demuxer, but might be changed in
future to return unified information about all demuxers. The ranges are in
arbitrary order. Often, ranges will overlap for a bit, before being joined.
In broken corner cases, ranges may overlap all over the place.
The end of a seek range is usually smaller than the value returned by the
``demuxer-cache-time`` property, because that property returns the guessed
buffering amount, while the seek ranges represent the buffered data that
can actually be used for cached seeking.
``fw-bytes`` is the number of bytes of packets buffered in the range
starting from the current decoding position.
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
"seekable-ranges" MPV_FORMAT_NODE_ARRAY
MPV_FORMAT_NODE_MAP
"start" MPV_FORMAT_DOUBLE
"end" MPV_FORMAT_DOUBLE
"fw-bytes" MPV_FORMAT_INT64
Other fields (might be changed or removed in the future):
``eof``
True if the reader thread has hit the end of the file.
``underrun``
True if the reader thread could not satisfy a decoder's request for a
new packet.
``idle``
True if the thread is currently not reading.
``total-bytes``
Sum of packet bytes (plus some overhead estimation) of the entire packet
queue, including cached seekable ranges.
``fw-bytes``
Sum of packet bytes (plus some overhead estimation) of the readahead
packet queue (packets between current decoder reader positions and
demuxer position).
``demuxer-via-network``
Returns ``yes`` if the stream demuxed via the main demuxer is most likely
played via network. What constitutes "network" is not always clear, might
@@ -1291,8 +1338,8 @@ Property list
``seeking``
Returns ``yes`` if the player is currently seeking, or otherwise trying
to restart playback. (It's possible that it returns ``yes`` while a file
is loaded, or when switching ordered chapter segments. This is because
the same underlying code is used for seeking and resyncing.)
is loadedThis is because the same underlying code is used for seeking and
resyncing.)
``mixer-active``
Return ``yes`` if the audio mixer is active, ``no`` otherwise.
@@ -1390,7 +1437,7 @@ Property list
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
``--opengl-hwdec-interop`` can load it eagerly.) If there are multiple
``--gpu-hwdec-interop`` 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
@@ -1400,9 +1447,6 @@ Property list
multiple interop drivers for the same hardware decoder, depending on
platform and VO.
This is somewhat similar to the ``--opengl-hwdec-interop`` option, but
it returns the actually loaded backend, not the value of this option.
``video-format``
Video format as string.
@@ -2021,10 +2065,6 @@ Property list
``current-ao``
Current audio output driver (name as used with ``--ao``).
``audio-out-detected-device``
Return the audio device selected by the AO driver (only implemented for
some drivers: currently only ``coreaudio``).
``working-directory``
Return the working directory of the mpv process. Can be useful for JSON IPC
users, because the command line player usually works with relative paths.
@@ -2171,22 +2211,12 @@ caveats with some properties (due to historical reasons):
Option changes at runtime are affected by this as well.
``deinterlace``
While video is active, this behaves differently from the option. It will
never return the ``auto`` value (but the state as observed by the video
chain). If you set ``auto``, the property will set this as the option value,
and will return the actual video chain state as observed instead of auto.
``video-aspect``
While video is active, always returns the effective aspect ratio. Setting
a special value (like ``no``, values ``<= 0``) will make the property
set this as option, and return whatever actual aspect was derived from the
option setting.
``brightness`` (and other color options)
If ``--vo=xv`` is used, these properties may return the adapter's current
values instead of the option values.
``display-fps``
If a VO is created, this will return either the actual display FPS, or
an invalid value, instead of the option value.
+5 -1
View File
@@ -164,10 +164,14 @@ Otherwise, where the Lua APIs return ``nil`` on error, JS returns ``undefined``.
``mp.msg.debug(...)``
``mp.msg.trace(...)``
``mp.utils.getcwd()`` (LE)
``mp.utils.readdir(path [, filter])`` (LE)
``mp.utils.file_info(path)`` (LE)
``mp.utils.split_path(path)``
``mp.utils.join_path(p1, p2)``
@@ -222,7 +226,7 @@ Note: ``read_file`` and ``write_file`` throw on errors, allow text content only.
``exit()`` (global)
Make the script exit at the end of the current event loop iteration.
Note: please reomve added key bindings before calling ``exit()``.
Note: please remove added key bindings before calling ``exit()``.
``mp.utils.compile_js(fname, content_str)``
Compiles the JS code ``content_str`` as file name ``fname`` (without loading
+37 -5
View File
@@ -39,7 +39,10 @@ option. Some scripts are loaded internally (like ``--osc``). Each script runs in
its own thread. Your script is first run "as is", and once that is done, the event loop
is entered. This event loop will dispatch events received by mpv and call your
own event handlers which you have registered with ``mp.register_event``, or
timers added with ``mp.add_timeout`` or similar.
timers added with ``mp.add_timeout`` or similar. Note that since the
script starts execution concurrently with player initialization, some properties
may not be populated with meaningful values until the relevant subsystems have
initialized.
When the player quits, all scripts will be asked to terminate. This happens via
a ``shutdown`` event, which by default will make the event loop return. If your
@@ -484,16 +487,17 @@ with ``require 'mp.msg'``.
``msg.log(level, ...)``
The level parameter is the message priority. It's a string and one of
``fatal``, ``error``, ``warn``, ``info``, ``v``, ``debug``. The user's
settings will determine which of these messages will be visible. Normally,
all messages are visible, except ``v`` and ``debug``.
``fatal``, ``error``, ``warn``, ``info``, ``v``, ``debug``, ``trace``. The
user's settings will determine which of these messages will be
visible. Normally, all messages are visible, except ``v``, ``debug`` and
``trace``.
The parameters after that are all converted to strings. Spaces are inserted
to separate multiple parameters.
You don't need to add newlines.
``msg.fatal(...)``, ``msg.error(...)``, ``msg.warn(...)``, ``msg.info(...)``, ``msg.verbose(...)``, ``msg.debug(...)``
``msg.fatal(...)``, ``msg.error(...)``, ``msg.warn(...)``, ``msg.info(...)``, ``msg.verbose(...)``, ``msg.debug(...)``, ``msg.trace(...)``
All of these are shortcuts and equivalent to the corresponding
``msg.log(level, ...)`` call.
@@ -588,6 +592,34 @@ strictly part of the guaranteed API.
On error, ``nil, error`` is returned.
``utils.file_info(path)``
Stats the given path for information and returns a table with the
following entries:
``mode``
protection bits (on Windows, always 755 (octal) for directories
and 644 (octal) for files)
``size``
size in bytes
``atime``
time of last access
``mtime``
time of last modification
``ctime``
time of last metadata change (Linux) / time of creation (Windows)
``is_file``
Whether ``path`` is a regular file (boolean)
``is_dir``
Whether ``path`` is a directory (boolean)
``mode`` and ``size`` are integers.
Timestamps (``atime``, ``mtime`` and ``ctime``) are integer seconds since
the Unix epoch (Unix time).
The booleans ``is_file`` and ``is_dir`` are provided as a convenience;
they can be and are derived from ``mode``.
On error (eg. path does not exist), ``nil, error`` is returned.
``utils.split_path(path)``
Split a path into directory component and filename component, and return
them. The first return value is always the directory. The second return
+18 -7
View File
@@ -437,12 +437,12 @@ Suffix Meaning
-set Set a list of items
============= ===============================================
Although some operations allow specifiying multiple ``,``-separated items, using
Although some operations allow specifying multiple ``,``-separated items, using
this is strongly discouraged and deprecated, except for ``-set``.
Without suffix, the action taken is normally ``-set``.
Some options (like ``--sub-file``, ``--audio-file``, ``--opengl-shader``) are
Some options (like ``--sub-file``, ``--audio-file``, ``--glsl-shader``) are
aliases for the proper option with ``-append`` action. For example,
``--sub-file`` is an alias for ``--sub-files-append``.
@@ -510,8 +510,8 @@ setting them to *no*. Even suboptions can be specified in this way.
::
# Use opengl video output by default.
vo=opengl
# Use GPU-accelerated video output by default.
vo=gpu
# Use quotes for text that can contain spaces:
status-msg="Time: ${time-pos}"
@@ -582,7 +582,7 @@ profile name ``default`` to continue with normal options.
[slow]
profile-desc="some profile name"
# reference a builtin profile
profile=opengl-hq
profile=gpu-hq
[fast]
vo=vdpau
@@ -683,8 +683,10 @@ listed.
(``drop-frame-count`` property.)
- Cache state, e.g. ``Cache: 2s+134KB``. Visible if the stream cache is enabled.
The first value shows the amount of video buffered in the demuxer in seconds,
the second value shows *additional* data buffered in the stream cache in
kilobytes. (``demuxer-cache-duration`` and ``cache-used`` properties.)
the second value shows the sum of the demuxer forward cache size and the
*additional* data buffered in the stream cache in kilobytes.
(``demuxer-cache-duration``, ``demuxer-cache-state``, ``cache-used``
properties.)
PROTOCOLS
@@ -728,6 +730,13 @@ PROTOCOLS
you must mount the ISO file as filesystem, and point ``--bluray-device``
to the mounted directory directly.
``title`` can be: ``longest`` or ``first`` (selects the default
playlist); ``mpls/<number>`` (selects <number>.mpls playlist);
``<number>`` (select playlist with the same index). You can list
the available playlists with ``--msg-level=bd=v``.
``bluray://`` is an alias.
``dvd://[title|[starttitle]-endtitle][/device]`` ``--dvd-device=PATH``
Play a DVD. DVD menus are not supported. If no title is given, the longest
@@ -872,6 +881,8 @@ works like in older mpv releases. The profiles are currently defined as follows:
.. include:: osc.rst
.. include:: stats.rst
.. include:: lua.rst
.. include:: javascript.rst
+571 -317
View File
File diff suppressed because it is too large. Load diff
+162
View File
@@ -0,0 +1,162 @@
STATS
=====
This builtin script displays information and statistics for the currently
played file. It is enabled by default if mpv was compiled with Lua support.
It can be disabled entirely using the ``--load-stats-overlay=no`` option.
Usage
-----
The following key bindings are active by default unless something else is
already bound to them:
==== ==============================================
i Show stats for a fixed duration
I Toggle stats (shown until toggled again)
==== ==============================================
While the stats are visible on screen the following key bindings are active,
regardless of existing bindings. They allow you to switch between *pages* of
stats:
==== ==================
1 Show usual stats
2 Show frame timings
==== ==================
Font
~~~~
For optimal visual experience, a font with support for many font weights and
monospaced digits is recommended. By default, the open source font
`Source Sans Pro <https://github.com/adobe-fonts/source-sans-pro>`_ is used.
Configuration
-------------
This script can be customized through a config file ``lua-settings/stats.conf``
placed in mpv's user directory and through the ``--script-opts`` command-line
option. The configuration syntax is described in `ON SCREEN CONTROLLER`_.
Configurable Options
~~~~~~~~~~~~~~~~~~~~
``key_oneshot``
Default: i
``key_toggle``
Default: I
Key bindings to display stats.
``key_page_1``
Default: 1
``key_page_2``
Default: 2
Key bindings for page switching while stats are displayed.
``duration``
Default: 4
How long the stats are shown in seconds (oneshot).
``redraw_delay``
Default: 1
How long it takes to refresh the displayed stats in seconds (toggling).
``persistent_overlay``
Default: no
When `no`, other scripts printing text to the screen can overwrite the
displayed stats. When `yes`, displayed stats are persistently shown for the
respective duration. This can result in overlapping text when multiple
scripts decide to print text at the same time.
``plot_perfdata``
Default: yes
Show graphs for performance data (page 2).
``plot_vsync_ratio``
Default: yes
``plot_vsync_jitter``
Default: yes
Show graphs for vsync and jitter values (page 1). Only when toggled.
``flush_graph_data``
Default: yes
Clear data buffers used for drawing graphs when toggling.
``font``
Default: Source Sans Pro
Font name. Should support as many font weights as possible for optimal
visual experience.
``font_mono``
Default: Source Sans Pro
Font name for parts where monospaced characters are necessary to align
text. Currently, monospaced digits are sufficient.
``font_size``
Default: 8
Font size used to render text.
``font_color``
Default: FFFFFF
Font color.
``border_size``
Default: 0.8
Size of border drawn around the font.
``border_color``
Default: 262626
Color of drawn border.
``alpha``
Default: 11
Transparency for drawn text.
``plot_bg_border_color``
Default: 0000FF
Border color used for drawing graphs.
``plot_bg_color``
Default: 262626
Background color used for drawing graphs.
``plot_color``
Default: FFFFFF
Color used for drawing graphs.
Note: colors are given as hexadecimal values and use ASS tag order: BBGGRR
(blue green red).
Different key bindings
~~~~~~~~~~~~~~~~~~~~~~
A different key binding can be defined with the aforementioned options
``key_oneshot`` and ``key_toggle`` but also with commands in ``input.conf``,
for example::
e script-binding stats/display-stats
E script-binding stats/display-stats-toggle
Using ``input.conf``, it is also possible to directly display a certain page::
i script-binding stats/display-page-1
e script-binding stats/display-page-2
+14 -338
View File
@@ -100,159 +100,6 @@ With filters that support it, you can access parameters by their name.
Available mpv-only filters are:
``crop[=w:h:x:y]``
Crops the given part of the image and discards the rest. Useful to remove
black bands from widescreen videos.
``<w>,<h>``
Cropped width and height, defaults to original width and height.
``<x>,<y>``
Position of the cropped picture, defaults to center.
``expand[=w:h:x:y:aspect:round]``
Expands (not scales) video resolution to the given value and places the
unscaled original at coordinates x, y.
``<w>,<h>``
Expanded width,height (default: original width,height). Negative
values for w and h are treated as offsets to the original size.
.. admonition:: Example
``expand=0:-50:0:0``
Adds a 50 pixel border to the bottom of the picture.
``<x>,<y>``
position of original image on the expanded image (default: center)
``<aspect>``
Expands to fit an aspect instead of a resolution (default: 0).
.. admonition:: Example
``expand=800::::4/3``
Expands to 800x600, unless the source is higher resolution, in
which case it expands to fill a 4/3 aspect.
``<round>``
Rounds up to make both width and height divisible by <r> (default: 1).
``flip``
Flips the image upside down.
``mirror``
Mirrors the image on the Y axis.
``rotate[=0|90|180|270]``
Rotates the image by a multiple of 90 degrees clock-wise.
``scale[=w:h:param:param2:chr-drop:noup:arnd``
Scales the image with the software scaler (slow) and performs a YUV<->RGB
color space conversion (see also ``--sws``).
All parameters are optional.
``<w>:<h>``
scaled width/height (default: original width/height)
:0: scaled d_width/d_height
:-1: original width/height
:-2: Calculate w/h using the other dimension and the prescaled
aspect ratio.
:-3: Calculate w/h using the other dimension and the original
aspect ratio.
:-(n+8): Like -n above, but rounding the dimension to the closest
multiple of 16.
``<param>[:<param2>]`` (see also ``--sws``)
Set some scaling parameters depending on the type of scaler selected
with ``--sws``::
--sws=2 (bicubic): B (blurring) and C (ringing)
0.00:0.60 default
0.00:0.75 VirtualDub's "precise bicubic"
0.00:0.50 Catmull-Rom spline
0.33:0.33 Mitchell-Netravali spline
1.00:0.00 cubic B-spline
--sws=7 (Gaussian): sharpness (0 (soft) - 100 (sharp))
--sws=9 (Lanczos): filter length (1-10)
``<chr-drop>``
chroma skipping
:0: Use all available input lines for chroma (default).
:1: Use only every 2. input line for chroma.
:2: Use only every 4. input line for chroma.
:3: Use only every 8. input line for chroma.
``<noup>``
Disallow upscaling past the original dimensions.
:0: Allow upscaling (default).
:1: Disallow upscaling if one dimension exceeds its original value.
:2: Disallow upscaling if both dimensions exceed their original values.
``<arnd>``
Accurate rounding for the vertical scaler, which may be faster or
slower than the default rounding.
:no: Disable accurate rounding (default).
:yes: Enable accurate rounding.
``dsize[=w:h:aspect-method:r:aspect]``
Changes the intended display aspect at an arbitrary point in the
filter chain. Aspect can be given as a fraction (4/3) or floating point
number (1.33). Note that this filter does *not* do any scaling itself; it
just affects what later scalers (software or hardware) will do when
auto-scaling to the correct aspect.
``<w>,<h>``
New aspect ratio given by a display width and height. Unlike older mpv
versions or MPlayer, this does not set the display size.
Can also be these special values:
:0: original display width and height
:-1: original video width and height (default)
:-2: Calculate w/h using the other dimension and the original display
aspect ratio.
:-3: Calculate w/h using the other dimension and the original video
aspect ratio.
.. admonition:: Example
``dsize=800:-2``
Specifies a display resolution of 800x600 for a 4/3 aspect
video, or 800x450 for a 16/9 aspect video.
``<aspect-method>``
Modifies width and height according to original aspect ratios.
:-1: Ignore original aspect ratio (default).
:0: Keep display aspect ratio by using ``<w>`` and ``<h>`` as maximum
resolution.
:1: Keep display aspect ratio by using ``<w>`` and ``<h>`` as minimum
resolution.
:2: Keep video aspect ratio by using ``<w>`` and ``<h>`` as maximum
resolution.
:3: Keep video aspect ratio by using ``<w>`` and ``<h>`` as minimum
resolution.
.. admonition:: Example
``dsize=800:600:0``
Specifies a display resolution of at most 800x600, or smaller,
in order to keep aspect.
``<r>``
Rounds up to make both width and height divisible by ``<r>``
(default: 1).
``<aspect>``
Force an aspect ratio.
``format=fmt=<value>:colormatrix=<value>:...``
Restricts the color space for the next filter without doing any conversion.
Use together with the scale filter for a real conversion.
@@ -414,16 +261,16 @@ Available mpv-only filters are:
but values such as ``[16:9]`` can be passed too (``[...]`` for quoting
to prevent the option parser from interpreting the ``:`` character).
``<spherical-type>``
Type of the spherical projection:
``noformat[=fmt]``
Restricts the color space for the next filter without doing any conversion.
Unlike the format filter, this will allow any color space except the one
you specify.
:auto: As indicated by the file (default)
:none: Normal video
:equirect: Equirectangular
:unknown: Unknown projection
.. note:: For a list of available formats, see ``noformat=fmt=help``.
``<fmt>``
Format name, e.g. rgb15, bgr24, 420p, etc. (default: 420p).
``<spherical-yaw>``, ``<spherical-pitch>``, ``<spherical-roll>``
Reference angle in degree, if spherical video is used.
``lavfi=graph[:sws-flags[:o=opts]]``
Filter video using FFmpeg's libavfilter.
@@ -439,11 +286,14 @@ Available mpv-only filters are:
If you want to use the full filter syntax with this option, you have
to quote the filter graph in order to prevent mpv's syntax and the
filter graph syntax from clashing.
filter graph syntax from clashing. To prevent a quoting and escaping
mess, consider using ``--lavfi-complex`` if you know which video
track you want to use from the input file. (There is only one video
track for nearly all video files anyway.)
.. admonition:: Examples
``-vf lavfi=[gradfun=20:30,vflip]``
``--vf=lavfi=[gradfun=20:30,vflip]``
``gradfun`` filter with nonsense parameters, followed by a
``vflip`` filter. (This demonstrates how libavfilter takes a
graph and not just a single filter.) The filter graph string is
@@ -474,88 +324,6 @@ Available mpv-only filters are:
``'--vf=lavfi=yadif:o="threads=2,thread_type=slice"'``
forces a specific threading configuration.
``eq[=gamma:contrast:brightness:saturation:rg:gg:bg:weight]``
Software equalizer that uses lookup tables (slow), allowing gamma correction
in addition to simple brightness and contrast adjustment. The parameters are
given as floating point values.
``<0.1-10>``
initial gamma value (default: 1.0)
``<-2-2>``
initial contrast, where negative values result in a negative image
(default: 1.0)
``<-1-1>``
initial brightness (default: 0.0)
``<0-3>``
initial saturation (default: 1.0)
``<0.1-10>``
gamma value for the red component (default: 1.0)
``<0.1-10>``
gamma value for the green component (default: 1.0)
``<0.1-10>``
gamma value for the blue component (default: 1.0)
``<0-1>``
The weight parameter can be used to reduce the effect of a high gamma
value on bright image areas, e.g. keep them from getting overamplified
and just plain white. A value of 0.0 turns the gamma correction all
the way down while 1.0 leaves it at its full strength (default: 1.0).
``pullup[=jl:jr:jt:jb:sb:mp]``
Pulldown reversal (inverse telecine) filter, capable of handling mixed
hard-telecine, 24000/1001 fps progressive, and 30000/1001 fps progressive
content. The ``pullup`` filter makes use of future context in making its
decisions. It is stateless in the sense that it does not lock onto a pattern
to follow, but it instead looks forward to the following fields in order to
identify matches and rebuild progressive frames.
``jl``, ``jr``, ``jt``, and ``jb``
These options set the amount of "junk" to ignore at the left, right,
top, and bottom of the image, respectively. Left/right are in units of
8 pixels, while top/bottom are in units of 2 lines. The default is 8
pixels on each side.
``sb`` (strict breaks)
Setting this option to 1 will reduce the chances of ``pullup``
generating an occasional mismatched frame, but it may also cause an
excessive number of frames to be dropped during high motion sequences.
Conversely, setting it to -1 will make ``pullup`` match fields more
easily. This may help process video with slight blurring between the
fields, but may also cause interlaced frames in the output.
``mp`` (metric plane)
This option may be set to ``u`` or ``v`` to use a chroma plane instead of the
luma plane for doing ``pullup``'s computations. This may improve accuracy
on very clean source material, but more likely will decrease accuracy,
especially if there is chroma noise (rainbow effect) or any grayscale
video. The main purpose of setting ``mp`` to a chroma plane is to reduce
CPU load and make pullup usable in realtime on slow machines.
``yadif=[mode:interlaced-only]``
Yet another deinterlacing filter
``<mode>``
:frame: Output 1 frame for each frame.
:field: Output 1 frame for each field (default).
:frame-nospatial: Like ``frame`` but skips spatial interlacing check.
:field-nospatial: Like ``field`` but skips spatial interlacing check.
``<interlaced-only>``
:no: Deinterlace all frames.
:yes: Only deinterlace frames marked as interlaced (default).
This filter is automatically inserted when using the ``d`` key (or any
other key that toggles the ``deinterlace`` property or when using the
``--deinterlace`` switch), assuming the video output does not have native
deinterlacing support.
If you just want to set the default mode, put this filter and its options
into ``--vf-defaults`` instead, and enable deinterlacing with ``d`` or
``--deinterlace``.
Also, note that the ``d`` key is stupid enough to insert a deinterlacer twice
when inserting yadif with ``--vf``, so using the above methods is
recommended.
``sub=[=bottom-margin:top-margin]``
Moves subtitle rendering to an arbitrary point in the filter chain, or force
subtitle rendering in the video filter as opposed to using video output OSD
@@ -574,91 +342,6 @@ Available mpv-only filters are:
subtitle colors and video under the influence of the video equalizer
settings.
``stereo3d[=in:out]``
Stereo3d converts between different stereoscopic image formats.
``<in>``
Stereoscopic image format of input. Possible values:
``sbsl`` or ``side_by_side_left_first``
side by side parallel (left eye left, right eye right)
``sbsr`` or ``side_by_side_right_first``
side by side crosseye (right eye left, left eye right)
``abl`` or ``above_below_left_first``
above-below (left eye above, right eye below)
``abr`` or ``above_below_right_first``
above-below (right eye above, left eye below)
``ab2l`` or ``above_below_half_height_left_first``
above-below with half height resolution (left eye above, right eye
below)
``ab2r`` or ``above_below_half_height_right_first``
above-below with half height resolution (right eye above, left eye
below)
``<out>``
Stereoscopic image format of output. Possible values are all the input
formats as well as:
``arcg`` or ``anaglyph_red_cyan_gray``
anaglyph red/cyan gray (red filter on left eye, cyan filter on
right eye)
``arch`` or ``anaglyph_red_cyan_half_color``
anaglyph red/cyan half colored (red filter on left eye, cyan filter
on right eye)
``arcc`` or ``anaglyph_red_cyan_color``
anaglyph red/cyan color (red filter on left eye, cyan filter on
right eye)
``arcd`` or ``anaglyph_red_cyan_dubois``
anaglyph red/cyan color optimized with the least-squares
projection of Dubois (red filter on left eye, cyan filter on right
eye)
``agmg`` or ``anaglyph_green_magenta_gray``
anaglyph green/magenta gray (green filter on left eye, magenta
filter on right eye)
``agmh`` or ``anaglyph_green_magenta_half_color``
anaglyph green/magenta half colored (green filter on left eye,
magenta filter on right eye)
``agmc`` or ``anaglyph_green_magenta_color``
anaglyph green/magenta colored (green filter on left eye, magenta
filter on right eye)
``aybg`` or ``anaglyph_yellow_blue_gray``
anaglyph yellow/blue gray (yellow filter on left eye, blue filter
on right eye)
``aybh`` or ``anaglyph_yellow_blue_half_color``
anaglyph yellow/blue half colored (yellow filter on left eye, blue
filter on right eye)
``aybc`` or ``anaglyph_yellow_blue_color``
anaglyph yellow/blue colored (yellow filter on left eye, blue
filter on right eye)
``irl`` or ``interleave_rows_left_first``
Interleaved rows (left eye has top row, right eye starts on next
row)
``irr`` or ``interleave_rows_right_first``
Interleaved rows (right eye has top row, left eye starts on next
row)
``ml`` or ``mono_left``
mono output (left eye only)
``mr`` or ``mono_right``
mono output (right eye only)
``gradfun[=strength[:radius|:size=<size>]]``
Fix the banding artifacts that are sometimes introduced into nearly flat
regions by truncation to 8-bit color depth. Interpolates the gradients that
should go where the bands are, and dithers them.
``<strength>``
Maximum amount by which the filter will change any one pixel. Also the
threshold for detecting nearly flat regions (default: 1.5).
``<radius>``
Neighborhood to fit the gradient to. Larger radius makes for smoother
gradients, but also prevents the filter from modifying pixels near
detailed regions (default: disabled).
``<size>``
size of the filter in percent of the image diagonal size. This is
used to calculate the final radius size (default: 1).
``vapoursynth=file:buffered-frames:concurrent-frames``
Loads a VapourSynth filter script. This is intended for streamed
processing: mpv actually provides a source filter, instead of using a
@@ -787,7 +470,7 @@ Available mpv-only filters are:
no
Don't perform deinterlacing.
first-field
Show only first field (going by ``--field-dominance``).
Show only first field.
bob
bob deinterlacing (default).
weave, motion-adaptive, motion-compensated
@@ -828,7 +511,6 @@ Available mpv-only filters are:
the mode selected with ``deint-mode``.
``deint-mode=<first-field|bob|temporal|temporal-spatial>``
Select deinterlacing mode (default: temporal).
All modes respect ``--field-dominance``.
Note that there's currently a mechanism that allows the ``vdpau`` VO to
change the ``deint-mode`` of auto-inserted ``vdpaupp`` filters. To avoid
@@ -874,9 +556,3 @@ Available mpv-only filters are:
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
latencies with decoding, because the filter will never output a frame if
the buffer isn't full, except on EOF.)
+32 -19
View File
@@ -14,7 +14,7 @@ in the list.
See ``--vo=help`` for a list of compiled-in video output drivers.
The recommended output driver is ``--vo=opengl``, which is the default. All
The recommended output driver is ``--vo=gpu``, which is the default. All
other drivers are for compatibility or special purposes. If the default
does not work, it will fallback to other drivers (in the same order as
listed by ``--vo=help``).
@@ -273,37 +273,34 @@ Available video output drivers are:
``--vo-direct3d-exact-backbuffer``
Always resize the backbuffer to window size.
``opengl``
OpenGL video output driver. It supports extended scaling methods, dithering
and color management.
``gpu``
General purpose, customizable, GPU-accelerated video output driver. It
supports extended scaling methods, dithering, color management, custom
shaders, HDR, and more.
See `OpenGL renderer options`_ for options specific to this VO.
See `GPU renderer options`_ for options specific to this VO.
By default, it tries to use fast and fail-safe settings. Use the
``opengl-hq`` profile to use this driver with defaults set to high
quality rendering. (This profile is also the replacement for
``--vo=opengl-hq``.) The profile can be applied with ``--profile=opengl-hq``
and its contents can be viewed with ``--show-profile=opengl-hq``.
``gpu-hq`` profile to use this driver with defaults set to high quality
rendering. The profile can be applied with ``--profile=gpu-hq`` and its
contents can be viewed with ``--show-profile=gpu-hq``.
Requires at least OpenGL 2.1.
Some features are available with OpenGL 3 capable graphics drivers only
(or if the necessary extensions are available).
OpenGL ES 2.0 and 3.0 are supported as well.
This VO abstracts over several possible graphics APIs and windowing
contexts, which can be influenced using the ``--gpu-api`` and
``--gpu-context`` options.
Hardware decoding over OpenGL-interop is supported to some degree. Note
that in this mode, some corner case might not be gracefully handled, and
color space conversion and chroma upsampling is generally in the hand of
the hardware decoder APIs.
``opengl`` makes use of FBOs by default. Sometimes you can achieve better
quality or performance by changing the ``--opengl-fbo-format`` option to
``gpu`` makes use of FBOs by default. Sometimes you can achieve better
quality or performance by changing the ``--gpu-fbo-format`` option to
``rgb16f``, ``rgb32f`` or ``rgb``. Known problems include Mesa/Intel not
accepting ``rgb16``, Mesa sometimes not being compiled with float texture
support, and some OS X setups being very slow with ``rgb16`` but fast
with ``rgb32f``. If you have problems, you can also try enabling the
``--opengl-dumb-mode=yes`` option.
``--gpu-dumb-mode=yes`` option.
``sdl``
SDL 2.0+ Render video output driver, depending on system with or without
@@ -356,7 +353,7 @@ Available video output drivers are:
no
Don't allow deinterlacing (default for newer libva).
first-field
Show only first field (going by ``--field-dominance``).
Show only first field.
bob
bob deinterlacing (default for older libva).
@@ -507,3 +504,19 @@ Available video output drivers are:
Mode ID to use (resolution, bit depth and frame rate).
(default: 0)
``--drm-overlay=<number>``
Select the DRM overlay index to use.
Overlay index is zero based, and related to crtc.
(default: 0)
``mediacodec_embed`` (Android)
Renders ``IMGFMT_MEDIACODEC`` frames directly to an ``android.view.Surface``.
Requires ``--hwdec=mediacodec`` for hardware decoding, along with
``--vo=mediacodec_embed`` and ``--wid=(intptr_t)(*android.view.Surface)``.
Since this video output driver uses native decoding and rendering routines,
many of mpv's features (subtitle rendering, OSD/OSC, video filters, etc)
are not available with this driver.
To use hardware decoding with ``--vo-gpu`` instead, use
``--hwdec=mediacodec-copy`` along with ``--gpu-context=android``.
+3 -3
View File
@@ -76,8 +76,8 @@ Video
* Wayland support.
* Native support for VAAPI and VDA. Improved VDPAU video output.
* Improved OpenGL output (see the ``opengl-hq`` video output).
* Make hardware decoding work with the ``opengl`` video output.
* Improved GPU-accelerated video output (see the ``gpu-hq`` preset).
* Make hardware decoding work with the ``gpu`` video output.
* Support for libavfilter (for video->video and audio->audio). This allows
using most of FFmpeg's filters, which improve greatly on the old MPlayer
filters in features, performance, and correctness.
@@ -85,7 +85,7 @@ Video
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).
* High-quality image resamplers (see the ``--scale`` suboption).
* Support for scaling in (sigmoidized) linear light.
* Better subtitle rendering using libass by default.
* Improvements when playing multiple files (``-fixed-vo`` is default, do not
View File
File renamed without changes.
+502
View File
@@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
+33 -39
View File
@@ -5,20 +5,29 @@
--------------
* [External links](#external-links)
* [Overview](#overview)
* [System requirements](#system-requirements)
* [Downloads](#downloads)
* [Changelog](#changelog)
* [Compilation](#compilation)
* [FFmpeg vs. Libav](#ffmpeg-vs-libav)
* [FFmpeg ABI compatibility](#ffmpeg-abi-compatibility)
* [Release cycle](#release-cycle)
* [Bug reports](#bug-reports)
* [Contributing](#contributing)
* [Relation to MPlayer and mplayer2](#relation-to-mplayer-and-mplayer2)
* [License](#license)
* [Contact](#contact)
## External links
* [Wiki](https://github.com/mpv-player/mpv/wiki)
* [FAQ](https://github.com/mpv-player/mpv/wiki/FAQ)
* [Man pages](http://mpv.io/manual/master/)
* [Contact](#contact)
* [License](#license)
* [Manual](http://mpv.io/manual/master/)
## Overview
@@ -30,10 +39,10 @@ Releases can be found on the [release list][releases].
## System requirements
- A not too ancient Linux, or Windows Vista or later, or OSX 10.8 or later.
- A somewhat capable CPU. Hardware decoding might sometimes help if the CPU
is too slow to decode video realtime, but must be explicitly enabled with
the `--hwdec` option.
- A not too ancient Linux, Windows 7 or later, or OSX 10.8 or later.
- A somewhat capable CPU. Hardware decoding might help if the CPU is too slow to
decode video in realtime, but must be explicitly enabled with the `--hwdec`
option.
- A not too crappy GPU. mpv is not intended to be used with bad GPUs. There are
many caveats with drivers or system compositors causing tearing, stutter,
etc. On Windows, you might want to make sure the graphics drivers are
@@ -45,7 +54,7 @@ Releases can be found on the [release list][releases].
For semi-official builds and third-party packages please see
[mpv.io](http://mpv.io/installation/).
[mpv.io/installation](http://mpv.io/installation/).
## Changelog
@@ -67,9 +76,9 @@ Changes to the default key bindings are indicated in
Compiling with full features requires development files for several
external libraries. Below is a list of some important requirements.
The mpv build system uses *waf*, but we don't store it in your source tree. The
script './bootstrap.py' will download the latest version of waf that was tested
with the build system.
The mpv build system uses [waf](https://waf.io/), but we don't store it in the
repository. The `./bootstrap.py` script will download the latest version
of waf that was tested with the build system.
For a list of the available build options use `./waf configure --help`. If
you think you have support for some feature installed but configure fails to
@@ -101,9 +110,6 @@ Essential dependencies (incomplete list):
- Audio output development headers (libasound/ALSA, pulseaudio)
- FFmpeg libraries (libavutil libavcodec libavformat libswscale libavfilter
and either libswresample or libavresample)
At least FFmpeg 3.2.2 or Libav 12 is required.
For hardware decoding with vaapi and vdpau, FFmpeg 3.3 or Libav git is
required.
- zlib
- iconv (normally provided by the system libc)
- libass (OSD, OSC, text subtitles)
@@ -111,7 +117,6 @@ Essential dependencies (incomplete list):
- libjpeg (optional, used for screenshots only)
- uchardet (optional, for subtitle charset detection)
- vdpau and vaapi libraries for hardware decoding on Linux (optional)
(FFmpeg 3.3 or Libav git is also required.)
Libass dependencies:
@@ -130,11 +135,10 @@ FFmpeg dependencies:
- Libav also works, but some features will not work. (See section below.)
Most of the above libraries are available in suitable versions on normal
Linux distributions. However, FFmpeg is an exception (distro versions may be
too old to work well or at all). For that reason you may want to use
the separately available build wrapper ([mpv-build][mpv-build]) that first
compiles FFmpeg libraries and libass, and then compiles the player statically
linked against those.
Linux distributions. For ease of compiling the latest git master of everything,
you may wish to use the separately available build wrapper ([mpv-build][mpv-build])
which first compiles FFmpeg libraries and libass, and then compiles the player
statically linked against those.
If you want to build a Windows binary, you either have to use MSYS2 and MinGW,
or cross-compile from Linux with MinGW. See
@@ -149,20 +153,6 @@ of both FFmpeg and Libav. But FFmpeg is preferred, and some mpv features work
with FFmpeg only (subtitle formats in particular).
## Preferred FFmpeg version
Using the latest FFmpeg release (or FFmpeg git master) is strongly recommended.
Older versions are unsupported, even if the build system still happens to
accept them. The main reason mpv still builds with older FFmpeg versions is to
evade arguing with people (users, distros) who insist on using older FFmpeg
versions for no rational reason.
If you want to use a stable FFmpeg release, use the latest release, which has
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
@@ -203,6 +193,8 @@ recommended (see [Contact](#Contact) below).
## Contributing
Please read [contribute.md][contribute.md].
For small changes you can just send us pull requests through GitHub. For bigger
changes come and talk to us on IRC before you start working on them. It will
make code review easier for both parties later on.
@@ -221,6 +213,12 @@ For details see [FAQ entry](https://github.com/mpv-player/mpv/wiki/FAQ#How_is_mp
If you are wondering what's different from mplayer2 and MPlayer, an incomplete
and largely unmaintained list of changes is located [here][mplayer-changes].
## License
GPLv2 "or later" by default, LGPLv2.1 "or later" with `--enable-lgpl`.
See [details.](https://github.com/mpv-player/mpv/blob/master/Copyright)
## Contact
@@ -244,8 +242,4 @@ only if discretion is required.
[interface-changes]: https://github.com/mpv-player/mpv/blob/master/DOCS/interface-changes.rst
[api-changes]: https://github.com/mpv-player/mpv/blob/master/DOCS/client-api-changes.rst
[restore-old-bindings]: https://github.com/mpv-player/mpv/blob/master/etc/restore-old-bindings.conf
## License
Mostly GPLv2 or later. See [details.](https://github.com/mpv-player/mpv/blob/master/Copyright)
[contribute.md]: https://github.com/mpv-player/mpv/blob/master/DOCS/contribute.md
+113 -2697
View File
File diff suppressed because it is too large. Load diff
+7 -2
View File
@@ -10,7 +10,10 @@ export PYTHON=/usr/bin/python3
"$PYTHON" bootstrap.py
"$PYTHON" waf configure \
--check-c-compiler=gcc \
--disable-cdda \
--disable-egl-angle-lib \
--enable-crossc \
--enable-d3d-hwaccel \
--enable-d3d11 \
--enable-egl-angle \
--enable-jpeg \
--enable-lcms2 \
@@ -18,5 +21,7 @@ export PYTHON=/usr/bin/python3
--enable-libass \
--enable-lua \
--enable-rubberband \
--enable-uchardet
--enable-shaderc \
--enable-uchardet \
--enable-vulkan
"$PYTHON" waf build
+49 -12
View File
@@ -1,15 +1,6 @@
#!/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
@@ -20,16 +11,62 @@ EOF
# Install build dependencies for mpv
pacman -S --noconfirm --needed \
$MINGW_PACKAGE_PREFIX-gcc \
$MINGW_PACKAGE_PREFIX-toolchain \
$MINGW_PACKAGE_PREFIX-angleproject-git \
$MINGW_PACKAGE_PREFIX-ffmpeg \
$MINGW_PACKAGE_PREFIX-cmake \
$MINGW_PACKAGE_PREFIX-lcms2 \
$MINGW_PACKAGE_PREFIX-libarchive \
$MINGW_PACKAGE_PREFIX-libass \
$MINGW_PACKAGE_PREFIX-libjpeg-turbo \
$MINGW_PACKAGE_PREFIX-lua51 \
$MINGW_PACKAGE_PREFIX-ninja \
$MINGW_PACKAGE_PREFIX-rubberband \
$MINGW_PACKAGE_PREFIX-uchardet
$MINGW_PACKAGE_PREFIX-uchardet \
$MINGW_PACKAGE_PREFIX-vulkan
# Delete unused packages to reduce space used in the Appveyor cache
pacman -Sc --noconfirm
# Compile ffmpeg
(
git clone --depth=1 https://github.com/FFmpeg/ffmpeg.git && cd ffmpeg
mkdir build && cd build
../configure \
--prefix=$MINGW_PREFIX \
--target-os=mingw32 \
--arch=$MSYSTEM_CARCH \
--disable-static \
--disable-doc \
--disable-asm \
--enable-gpl \
--enable-version3 \
--enable-shared \
--enable-pic \
--enable-d3d11va \
--enable-dxva2 \
--enable-schannel
make -j4 install
)
# Compile shaderc
(
git clone --depth=1 https://github.com/google/shaderc && cd shaderc
git clone --depth=1 https://github.com/google/glslang.git third_party/glslang
git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Tools.git third_party/spirv-tools
git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers.git third_party/spirv-headers
mkdir build && cd build
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DSHADERC_SKIP_TESTS=ON \
-DCMAKE_INSTALL_PREFIX=$MINGW_PREFIX ..
ninja install
cp -f libshaderc/libshaderc_shared.dll $MINGW_PREFIX/bin/
)
# Compile crossc
(
git clone --depth=1 https://github.com/rossy/crossc && cd crossc
git submodule update --init
make -j4 install prefix=$MINGW_PREFIX
)
+108 -79
View File
@@ -3,48 +3,80 @@
--
-- See https://ffmpeg.org/ffmpeg-filters.html#acompressor for explanation
-- of the parameteres.
--
-- Default key bindings:
-- n: Toggle dynamic range compression on or off
-- F1/Shift+F1: Increase/Decrease threshold parameter
-- F2/Shift+F2: Increase/Decrease ratio parameter
-- F3/Shift+F3: Increase/Decrease knee parameter
-- F4/Shift+F4: Increase/Decrease makeup gain parameter
-- F5/Shift+F5: Increase/Decrease attack parameter
-- F6/Shift+F6: Increase/Decrease release parameter
--
-- To change key bindings in input.conf use:
-- BINDING script-message-to acompressor toggle-acompressor
-- BINDING script-message-to acompressor update-param PARAM INCREMENT
-- BINDING is the key binding to use, PARAM is either 'attack', 'release',
-- 'threshold', 'ratio', 'knee' or 'makeup' and INCREMENT is a signed floating
-- point value to add to the current parameter value.
--
-- You may also just adjust default parameters to your liking in this table.
local mp = require 'mp'
local options = require 'mp.options'
local o = {
default_enable = false,
show_osd = true,
osd_timeout = 4000,
filter_label = mp.get_script_name(),
key_toggle = 'n',
key_increase_threshold = 'F1',
key_decrease_threshold = 'Shift+F1',
key_increase_ratio = 'F2',
key_decrease_ratio = 'Shift+F2',
key_increase_knee = 'F3',
key_decrease_knee = 'Shift+F3',
key_increase_makeup = 'F4',
key_decrease_makeup = 'Shift+F4',
key_increase_attack = 'F5',
key_decrease_attack = 'Shift+F5',
key_increase_release = 'F6',
key_decrease_release = 'Shift+F6',
default_threshold = -25.0,
default_ratio = 3.0,
default_knee = 2.0,
default_makeup = 8.0,
default_attack = 20.0,
default_release = 250.0,
step_threshold = -2.5,
step_ratio = 1.0,
step_knee = 1.0,
step_makeup = 1.0,
step_attack = 10.0,
step_release = 10.0,
}
options.read_options(o)
local params = {
-- 'hide' defines wether the parameter should be hidden from OSD display (it will still be included in ffmpeg filter graph).
-- 'input_format' is used to parse the value back from a obtained filter graph.
-- 'output_format' defines how the value shall be formatted for creating the filter graph.
{ name = 'Attack', value= 20, min=0.01, max=2000, hide= 20, input_format='attack=(%d+[.%d+]*)', output_format='%g' },
{ name = 'Release', value=250, min=0.01, max=9000, hide=250, input_format='release=(%d+[.%d+]*)', output_format='%g' },
{ name = 'Threshold', value=-25, min= -30, max= 0, hide=nil, input_format='threshold=(-%d+[.%d+]*)dB', output_format='%gdB' },
{ name = 'Ratio', value= 3, min= 1, max= 20, hide=nil, input_format='ratio=(%d+[.%d+]*)', output_format='%g' },
{ name = 'Knee', value= 2, min= 1, max= 10, hide= 2, input_format='knee=(%d+[.%d+]*)dB', output_format='%gdB' },
{ name = 'Makeup', value= 8, min= 0, max= 24, hide=nil, input_format='makeup=(%d+[.%d+]*)dB', output_format='%gdB' }
{ name = 'attack', min=0.01, max=2000, hide_default=true, dB='' },
{ name = 'release', min=0.01, max=9000, hide_default=true, dB='' },
{ name = 'threshold', min= -30, max= 0, hide_default=false, dB='dB' },
{ name = 'ratio', min= 1, max= 20, hide_default=false, dB='' },
{ name = 'knee', min= 1, max= 10, hide_default=true, dB='dB' },
{ name = 'makeup', min= 0, max= 24, hide_default=false, dB='dB' },
}
-- Defines the mpv filter label to be used. This allows us to easily add/replace/remove it, so
-- it should be left so something meaningful and unique.
local filter_label = 'acompressor'
local function parse_value(value)
-- Using nil here because tonumber differs between lua 5.1 and 5.2 when parsing fractions in combination with explicit base argument set to 10.
-- And we can't omit it because gsub returns 2 values which would get unpacked and cause more problems. Gotta love scripting languages.
return tonumber(value:gsub('dB$', ''), nil)
end
local function format_value(value, dB)
return string.format('%g%s', value, dB)
end
local function show_osd(filter)
if not o.show_osd then
return
end
if not filter.enabled then
mp.commandv('show-text', 'Dynamic range compressor: disabled', o.osd_timeout)
return
end
local function update_filter()
local graph = {}
local pretty = {}
for _,param in pairs(params) do
graph[#graph+1] = string.format('%s=' .. param.output_format, string.lower(param.name), param.value)
if param.hide ~= param.value then
pretty[#pretty+1] = string.format('%s: ' .. param.output_format, param.name, param.value)
for _,param in ipairs(params) do
local value = parse_value(filter.params[param.name])
if not (param.hide_default and value == o['default_' .. param.name]) then
pretty[#pretty+1] = string.format('%s: %g%s', param.name:gsub("^%l", string.upper), value, param.dB)
end
end
@@ -54,49 +86,49 @@ local function update_filter()
pretty = '\n(' .. table.concat(pretty, ', ') .. ')'
end
mp.command(string.format('no-osd af add @%s:lavfi=[acompressor=%s]; show-text "Dynamic range compressor: enabled%s" 4000', filter_label, table.concat(graph, ':'), pretty))
mp.commandv('show-text', 'Dynamic range compressor: enabled' .. pretty, o.osd_timeout)
end
local function read_filter()
local graph = nil
local function get_filter()
local af = mp.get_property_native('af', {})
for i = 1, #af do
if af[i]['name'] == 'lavfi' and af[i]['label'] == 'acompressor' then
graph = af[i]['params']['graph']
break
if af[i].label == o.filter_label then
return af, i
end
end
if graph == nil then
return false
end
af[#af+1] = {
name = 'acompressor',
label = o.filter_label,
enabled = false,
params = {},
}
for _,param in pairs(params) do
local value = tonumber(string.match(graph, param.input_format))
if value ~= nil and value >= param.min and value <= param.max then
param.value = value
end
af[#af].params[param.name] = format_value(o['default_' .. param.name], param.dB)
end
return true
return af, #af
end
local function toggle_acompressor()
if read_filter() then
mp.command(string.format('no-osd af del @%s; show-text "Dynamic range compressor: disabled"', filter_label))
else
update_filter()
end
local af, i = get_filter()
af[i].enabled = not af[i].enabled
mp.set_property_native('af', af)
show_osd(af[i])
end
local function update_param(name, increment)
-- The current filter values could come from a watch_later config.
-- read_filter() will parse them, so that we don't clobber those with our default values.
read_filter()
for _,param in pairs(params) do
if string.lower(param.name) == string.lower(name) then
param.value = math.max(param.min, math.min(param.value + increment, param.max))
update_filter()
if param.name == string.lower(name) then
local af, i = get_filter()
local value = parse_value(af[i].params[param.name])
value = math.max(param.min, math.min(value + increment, param.max))
af[i].params[param.name] = format_value(value, param.dB)
af[i].enabled = true
mp.set_property_native('af', af)
show_osd(af[i])
return
end
end
@@ -104,23 +136,20 @@ local function update_param(name, increment)
mp.msg.error('Unknown parameter "' .. name .. '"')
end
mp.add_key_binding("n", "toggle-acompressor", toggle_acompressor)
mp.add_key_binding(o.key_toggle, "toggle-acompressor", toggle_acompressor)
mp.register_script_message('update-param', update_param)
mp.add_key_binding("F1", 'acompressor-inc-threshold', function() update_param('threshold', -5); end, { repeatable = true })
mp.add_key_binding("Shift+F1", 'acompressor-dec-threshold', function() update_param('Threshold', 5); end, { repeatable = true })
for _,param in pairs(params) do
for direction,step in pairs({increase=1, decrease=-1}) do
mp.add_key_binding(o['key_' .. direction .. '_' .. param.name],
'acompressor-' .. direction .. '-' .. param.name,
function() update_param(param.name, step*o['step_' .. param.name]); end,
{ repeatable = true })
end
end
mp.add_key_binding("F2", 'acompressor-inc-ratio', function() update_param('Ratio', 1); end, { repeatable = true })
mp.add_key_binding("Shift+F2", 'acompressor-dec-ratio', function() update_param('Ratio', -1); end, { repeatable = true })
mp.add_key_binding("F3", 'acompressor-inc-knee', function() update_param('Knee', 1); end, { repeatable = true })
mp.add_key_binding("Shift+F3", 'acompressor-dec-knee', function() update_param('Knee', -1); end, { repeatable = true })
mp.add_key_binding("F4", 'acompressor-inc-makeup', function() update_param('Makeup', 1); end, { repeatable = true })
mp.add_key_binding("Shift+F4", 'acompressor-dec-makeup', function() update_param('Makeup', -1); end, { repeatable = true })
mp.add_key_binding("F5", 'acompressor-inc-attack', function() update_param('Attack', 10); end, { repeatable = true })
mp.add_key_binding("Shift+F5", 'acompressor-dec-attack', function() update_param('Attack', -10); end, { repeatable = true })
mp.add_key_binding("F6", 'acompressor-inc-release', function() update_param('Release', 10); end, { repeatable = true })
mp.add_key_binding("Shift+F6", 'acompressor-dec-release', function() update_param('Release', -10); end, { repeatable = true })
if o.default_enable then
local af, i = get_filter()
af[i].enabled = true
mp.set_property_native('af', af)
end
-5
View File
@@ -6,8 +6,3 @@ mp.observe_property("audio-device-list", "native", function(name, val)
print(" - '" .. e.name .. "' (" .. e.description .. ")")
end
end)
mp.observe_property("audio-out-detected-device", "native", function(name, val)
print("Detected audio device changed:")
print(" - '" .. val)
end)
+4 -3
View File
@@ -66,8 +66,8 @@ function autocrop_start()
-- insert the cropdetect filter
ret=mp.command(
string.format(
'vf add @%s:lavfi=graph="cropdetect=limit=24:round=2:reset=0"',
cropdetect_label
'vf add @%s:cropdetect=limit=%f:round=2:reset=0',
cropdetect_label, 24/255
)
)
-- wait to gather data
@@ -79,6 +79,7 @@ function do_crop()
local cropdetect_metadata = mp.get_property_native(
string.format("vf-metadata/%s", cropdetect_label)
)
-- use it to crop if its valid
if cropdetect_metadata then
if cropdetect_metadata["lavfi.cropdetect.w"]
@@ -86,7 +87,7 @@ function do_crop()
and cropdetect_metadata["lavfi.cropdetect.x"]
and cropdetect_metadata["lavfi.cropdetect.y"]
then
mp.command(string.format("vf add @%s:crop=%s:%s:%s:%s",
mp.command(string.format("vf add @%s:lavfi-crop=w=%s:h=%s:x=%s:y=%s",
crop_label,
cropdetect_metadata["lavfi.cropdetect.w"],
cropdetect_metadata["lavfi.cropdetect.h"],
+38 -27
View File
@@ -3,13 +3,13 @@
-- currently playing video.
--
-- It registers the key-binding ctrl+d, which when pressed, inserts the filters
-- ``vf=lavfi=idet,pullup,vf=lavfi=idet``. After 4 seconds, it removes these
-- ``vf=idet,lavfi-pullup,idet``. After 4 seconds, it removes these
-- filters and decides whether the content is progressive, interlaced, or
-- telecined and the interlacing field dominance.
--
-- Based on this information, it may set mpv's ``deinterlace`` property (which
-- usually inserts the yadif filter), or insert the ``pullup`` filter if the
-- content is telecined. It also sets mpv's ``field-dominance`` property.
-- content is telecined. It also sets field dominance with lavfi setfield.
--
-- OPTIONS:
-- The default detection time may be overridden by adding
@@ -22,16 +22,14 @@
-- To see counts of the various types of frames for each detection phase,
-- the verbosity can be increased with
--
-- --msg-level autodeint=v
--
-- This script requires a recent version of ffmpeg for which the idet
-- filter adds the required metadata.
-- --msg-level=autodeint=v
require "mp.msg"
script_name = mp.get_script_name()
detect_label = string.format("%s-detect", script_name)
pullup_label = string.format("%s", script_name)
dominance_label = string.format("%s-dominance", script_name)
ivtc_detect_label = string.format("%s-ivtc-detect", script_name)
-- number of seconds to gather cropdetect data
@@ -55,6 +53,10 @@ function del_filter_if_present(label)
return false
end
local function add_vf(label, filter)
return mp.command(('vf add @%s:%s'):format(label, filter))
end
function start_detect()
-- exit if detection is already in progress
if timer then
@@ -64,11 +66,13 @@ function start_detect()
mp.set_property("deinterlace","no")
del_filter_if_present(pullup_label)
del_filter_if_present(dominance_label)
-- insert the detection filter
local cmd = string.format('vf add @%s:lavfi=graph="idet",@%s:pullup,@%s:lavfi=graph="idet"',
detect_label, pullup_label, ivtc_detect_label)
if not mp.command(cmd) then
-- insert the detection filters
if not (add_vf(detect_label, 'idet') and
add_vf(dominance_label, 'setfield=mode=auto') and
add_vf(pullup_label, 'lavfi-pullup') and
add_vf(ivtc_detect_label, 'idet')) then
mp.msg.error("failed to insert detection filters")
return
end
@@ -88,12 +92,12 @@ progressive, interlaced_tff, interlaced_bff, interlaced = 0, 1, 2, 3, 4
function judge(label)
-- get the metadata
local result = mp.get_property_native(string.format("vf-metadata/%s", label))
num_tff = tonumber(result["lavfi.idet.multiple.tff"])
num_bff = tonumber(result["lavfi.idet.multiple.bff"])
num_progressive = tonumber(result["lavfi.idet.multiple.progressive"])
num_undetermined = tonumber(result["lavfi.idet.multiple.undetermined"])
num_interlaced = num_tff + num_bff
num_determined = num_interlaced + num_progressive
local num_tff = tonumber(result["lavfi.idet.multiple.tff"])
local num_bff = tonumber(result["lavfi.idet.multiple.bff"])
local num_progressive = tonumber(result["lavfi.idet.multiple.progressive"])
local num_undetermined = tonumber(result["lavfi.idet.multiple.undetermined"])
local num_interlaced = num_tff + num_bff
local num_determined = num_interlaced + num_progressive
mp.msg.verbose(label.." progressive = "..num_progressive)
mp.msg.verbose(label.." interlaced-tff = "..num_tff)
@@ -116,26 +120,33 @@ end
function select_filter()
-- handle the first detection filter results
verdict = judge(detect_label)
local verdict = judge(detect_label)
local ivtc_verdict = judge(ivtc_detect_label)
local dominance = "auto"
if verdict == progressive then
mp.msg.info("progressive: doing nothing")
stop_detect()
del_filter_if_present(dominance_label)
del_filter_if_present(pullup_label)
return
elseif verdict == interlaced_tff then
mp.set_property("field-dominance", "top")
elseif verdict == interlaced_bff then
mp.set_property("field-dominance", "bottom")
elseif verdict == interlaced then
mp.set_property("field-dominance", "auto")
else
if verdict == interlaced_tff then
dominance = "tff"
add_vf(dominance_label, 'setfield=mode='..dominance)
elseif verdict == interlaced_bff then
dominance = "bff"
add_vf(dominance_label, 'setfield=mode='..dominance)
else
del_filter_if_present(dominance_label)
end
end
-- handle the ivtc detection filter results
verdict = judge(ivtc_detect_label)
if verdict == progressive then
mp.msg.info(string.format("telecinied with %s field dominance: using pullup", mp.get_property("field-dominance")))
if ivtc_verdict == progressive then
mp.msg.info(string.format("telecined with %s field dominance: using pullup", dominance))
stop_detect()
else
mp.msg.info(string.format("interlaced with %s field dominance: setting deinterlace property", mp.get_property("field-dominance")))
mp.msg.info(string.format("interlaced with %s field dominance: setting deinterlace property", dominance))
del_filter_if_present(pullup_label)
mp.set_property("deinterlace","yes")
stop_detect()
+33 -10
View File
@@ -22,7 +22,7 @@ end
EXTENSIONS = Set {
'mkv', 'avi', 'mp4', 'ogv', 'webm', 'rmvb', 'flv', 'wmv', 'mpeg', 'mpg', 'm4v', '3gp',
'mp3', 'wav', 'ogv', 'flac', 'm4a', 'wma',
'mp3', 'wav', 'ogm', 'flac', 'm4a', 'wma', 'ogg', 'opus',
}
mputils = require 'mp.utils'
@@ -53,6 +53,37 @@ table.filter = function(t, iter)
end
end
-- splitbynum and alnumcomp from alphanum.lua (C) Andre Bogus
-- Released under the MIT License
-- http://www.davekoelle.com/files/alphanum.lua
-- split a string into a table of number and string values
function splitbynum(s)
local result = {}
for x, y in (s or ""):gmatch("(%d*)(%D*)") do
if x ~= "" then table.insert(result, tonumber(x)) end
if y ~= "" then table.insert(result, y) end
end
return result
end
function clean_key(k)
k = (' '..k..' '):gsub("%s+", " "):sub(2, -2):lower()
return splitbynum(k)
end
-- compare two strings
function alnumcomp(x, y)
local xt, yt = clean_key(x), clean_key(y)
for i = 1, math.min(#xt, #yt) do
local xe, ye = xt[i], yt[i]
if type(xe) == "string" then ye = tostring(ye)
elseif type(ye) == "string" then xe = tostring(xe) end
if xe ~= ye then return xe < ye end
end
return #xt < #yt
end
function find_and_add_entries()
local path = mp.get_property("path", "")
local dir, filename = mputils.split_path(path)
@@ -81,15 +112,7 @@ function find_and_add_entries()
end
return EXTENSIONS[string.lower(ext)]
end)
table.sort(files, function (a, b)
local len = string.len(a) - string.len(b)
if len ~= 0 then -- case for ordering filename ending with such as X.Y.Z
local ext = string.len(get_extension(a)) + 1
a = string.sub(a, 1, -ext)
b = string.sub(b, 1, -ext)
end
return string.lower(a) < string.lower(b)
end)
table.sort(files, alnumcomp)
if dir == "." then
dir = ""
+27 -6
View File
@@ -18,10 +18,10 @@ function update_status_line()
atsl("(Buffering) ")
end
if mp.get_property("vid") ~= "no" then
if mp.get_property("aid") ~= "no" then
atsl("A")
end
if mp.get_property("aid") ~= "no" then
if mp.get_property("vid") ~= "no" then
atsl("V")
end
@@ -43,7 +43,7 @@ function update_status_line()
r = mp.get_property_number("avsync", nil)
if r ~= nil then
atsl(string.format(" A-V: %7.3f", r))
atsl(string.format(" A-V: %f", r))
end
r = mp.get_property("total-avsync-change", 0)
@@ -51,12 +51,24 @@ function update_status_line()
atsl(string.format(" ct:%7.3f", r))
end
r = mp.get_property_number("drop-frame-count", -1)
r = mp.get_property_number("decoder-drop-frame-count", -1)
if r > 0 then
atsl(" Late: ")
atsl(r)
end
r = mp.get_property_osd("video-bitrate")
if r ~= nil and r ~= "" then
atsl(" Vb: ")
atsl(r)
end
r = mp.get_property_osd("audio-bitrate")
if r ~= nil and r ~= "" then
atsl(" Ab: ")
atsl(r)
end
r = mp.get_property_number("cache", 0)
if r > 0 then
atsl(string.format(" Cache: %d%% ", r))
@@ -66,6 +78,15 @@ function update_status_line()
mp.set_property("options/term-status-msg", newStatus)
end
-- Register the event
mp.register_event("tick", update_status_line)
timer = mp.add_periodic_timer(1, update_status_line)
function on_pause_change(name, value)
if value == false then
timer:resume()
else
timer:stop()
end
mp.add_timeout(0.1, update_status_line)
end
mp.observe_property("pause", "bool", on_pause_change)
mp.register_event("seek", update_status_line)
+7
View File
@@ -137,6 +137,13 @@ elements_matroska = (
'LuminanceMin, 55DA, float',
),
),
'Projection, 7670, sub', (
'ProjectionType, 7671, uint',
'ProjectionPrivate, 7672, binary',
'ProjectionPoseYaw, 7673, float',
'ProjectionPosePitch, 7674, float',
'ProjectionPoseRoll, 7675, float',
),
),
'Audio, e1, sub', (
'SamplingFrequency, b5, float',
+6
View File
@@ -39,6 +39,10 @@ def apply_plist_template(plist_file, version):
for line in fileinput.input(plist_file, inplace=1):
print (line.rstrip().replace('${VERSION}', version))
def create_bundle_symlink(binary_name, symlink_name):
os.symlink(os.path.basename(binary_name),
os.path.join(target_directory(binary_name), symlink_name))
def bundle_version():
if os.path.exists('VERSION'):
x = open('VERSION')
@@ -69,6 +73,8 @@ def main():
copy_bundle(binary_name)
print("> copying binary")
copy_binary(binary_name)
print("> create bundle symlink")
create_bundle_symlink(binary_name, "mpv-bundle")
print("> generating Info.plist")
apply_plist_template(target_plist(binary_name), version)
+1 -1
View File
@@ -173,7 +173,7 @@
</dict>
</array>
<key>CFBundleExecutable</key>
<string>mpv-wrapper.sh</string>
<string>mpv-bundle</string>
<key>CFBundleIconFile</key>
<string>icon</string>
<key>CFBundleIdentifier</key>
@@ -1,3 +0,0 @@
#!/bin/bash -l
export MPVBUNDLE="true"
$SHELL -c "$(dirname "$0")/mpv --player-operation-mode=pseudo-gui"
@@ -0,0 +1 @@
player-operation-mode=pseudo-gui
+3 -11
View File
@@ -87,21 +87,13 @@ end
class Libav < TravisDepsBuilder
def build_map
{
"libav-stable" => {
:action => :stable,
:url => 'http://libav.org/releases/libav-12.tar.gz'
},
"libav-git" => {
:action => :git,
:url => "git://git.libav.org/libav.git"
},
"ffmpeg-stable" => {
:action => :stable,
:url => 'http://www.ffmpeg.org/releases/ffmpeg-3.2.2.tar.gz'
},
"ffmpeg-git" => {
:action => :git,
:url => "git://github.com/FFmpeg/FFmpeg.git"
:url => "https://github.com/FFmpeg/FFmpeg.git"
}
}
end
@@ -114,7 +106,7 @@ end
class LibavOsx < Libav
def build_map
{
"ffmpeg-stable" => { :action => :package, :url => 'ffmpeg' },
"ffmpeg-git" => { :action => :package, :url => 'ffmpeg' },
}
end
end
@@ -133,7 +125,7 @@ end
class Dependencies < TravisDepsBuilder
def deps
packages = {
'linux' => 'pkg-config fontconfig libfribidi-dev yasm',
'linux' => 'pkg-config fontconfig libfribidi-dev yasm libxinerama-dev libxrandr-dev',
'osx' => 'pkg-config fontconfig freetype fribidi yasm'
}
package_manager_update
+1 -1
View File
@@ -11,7 +11,7 @@ if [ "x$TRAVIS_BRANCH" != "xmaster" ]; then
fi
TRAVIS_COMMIT_RANGE=${TRAVIS_COMMIT_RANGE:-HEAD^..}
if git diff --quiet --name-only --exit-code "$TRAVIS_COMMIT_RANGE" DOCS/; then
if git diff --quiet --name-only --exit-code "$TRAVIS_COMMIT_RANGE" DOCS/ VERSION; then
exit;
fi
+1 -1
View File
@@ -1 +1 @@
0.26.0
0.28.0
+4 -2
View File
@@ -4,6 +4,8 @@ branches:
- appveyor
environment:
global:
PATH: C:\msys64\usr\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem
matrix:
- MSYSTEM: MINGW64
- MSYSTEM: MINGW32
@@ -17,9 +19,9 @@ install:
# 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
- C:\msys64\usr\bin\pacman -S --noconfirm --needed base-devel 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"
- C:\msys64\usr\bin\bash -lc "cd && exec \"$APPVEYOR_BUILD_FOLDER\"/TOOLS/appveyor-install.sh"
build_script:
- C:\msys64\usr\bin\bash -lc "cd \"$APPVEYOR_BUILD_FOLDER\" && exec ./TOOLS/appveyor-build.sh"
on_failure:
+641
View File
@@ -0,0 +1,641 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libavutil/opt.h>
#include <libavutil/common.h>
#include <libavutil/samplefmt.h>
#include <libavutil/channel_layout.h>
#include <libavutil/mathematics.h>
#include "config.h"
#include "common/common.h"
#include "common/av_common.h"
#include "common/msg.h"
#include "options/m_config.h"
#include "options/m_option.h"
#include "aconverter.h"
#include "aframe.h"
#include "fmt-conversion.h"
#include "format.h"
#define HAVE_LIBSWRESAMPLE (!HAVE_LIBAV)
#define HAVE_LIBAVRESAMPLE HAVE_LIBAV
#if HAVE_LIBAVRESAMPLE
#include <libavresample/avresample.h>
#elif HAVE_LIBSWRESAMPLE
#include <libswresample/swresample.h>
#define AVAudioResampleContext SwrContext
#define avresample_alloc_context swr_alloc
#define avresample_open swr_init
#define avresample_close(x) do { } while(0)
#define avresample_free swr_free
#define avresample_available(x) 0
#define avresample_convert(ctx, out, out_planesize, out_samples, in, in_planesize, in_samples) \
swr_convert(ctx, out, out_samples, (const uint8_t**)(in), in_samples)
#define avresample_set_channel_mapping swr_set_channel_mapping
#define avresample_set_compensation swr_set_compensation
#else
#error "config.h broken or no resampler found"
#endif
struct mp_aconverter {
struct mp_log *log;
struct mpv_global *global;
double playback_speed;
bool is_resampling;
bool passthrough_mode;
struct AVAudioResampleContext *avrctx;
struct mp_aframe *avrctx_fmt; // output format of avrctx
struct mp_aframe *pool_fmt; // format used to allocate frames for avrctx output
struct mp_aframe *pre_out_fmt; // format before final conversion
struct AVAudioResampleContext *avrctx_out; // for output channel reordering
const struct mp_resample_opts *opts; // opts requested by the user
// At least libswresample keeps a pointer around for this:
int reorder_in[MP_NUM_CHANNELS];
int reorder_out[MP_NUM_CHANNELS];
struct mp_aframe_pool *reorder_buffer;
struct mp_aframe_pool *out_pool;
int in_rate_user; // user input sample rate
int in_rate; // actual rate (used by lavr), adjusted for playback speed
int in_format;
struct mp_chmap in_channels;
int out_rate;
int out_format;
struct mp_chmap out_channels;
struct mp_aframe *input; // queued input frame
bool input_eof; // queued input EOF
struct mp_aframe *output; // queued output frame
bool output_eof; // queued output EOF
};
#if HAVE_LIBAVRESAMPLE
static double get_delay(struct mp_aconverter *p)
{
return avresample_get_delay(p->avrctx) / (double)p->in_rate +
avresample_available(p->avrctx) / (double)p->out_rate;
}
static int get_out_samples(struct mp_aconverter *p, int in_samples)
{
return avresample_get_out_samples(p->avrctx, in_samples);
}
#else
static double get_delay(struct mp_aconverter *p)
{
int64_t base = p->in_rate * (int64_t)p->out_rate;
return swr_get_delay(p->avrctx, base) / (double)base;
}
static int get_out_samples(struct mp_aconverter *p, int in_samples)
{
return swr_get_out_samples(p->avrctx, in_samples);
}
#endif
static void close_lavrr(struct mp_aconverter *p)
{
if (p->avrctx)
avresample_close(p->avrctx);
avresample_free(&p->avrctx);
if (p->avrctx_out)
avresample_close(p->avrctx_out);
avresample_free(&p->avrctx_out);
TA_FREEP(&p->pre_out_fmt);
TA_FREEP(&p->avrctx_fmt);
TA_FREEP(&p->pool_fmt);
}
static int rate_from_speed(int rate, double speed)
{
return lrint(rate * speed);
}
static struct mp_chmap fudge_pairs[][2] = {
{MP_CHMAP2(BL, BR), MP_CHMAP2(SL, SR)},
{MP_CHMAP2(SL, SR), MP_CHMAP2(BL, BR)},
{MP_CHMAP2(SDL, SDR), MP_CHMAP2(SL, SR)},
{MP_CHMAP2(SL, SR), MP_CHMAP2(SDL, SDR)},
};
// Modify out_layout and return the new value. The intention is reducing the
// loss libswresample's rematrixing will cause by exchanging similar, but
// strictly speaking incompatible channel pairs. For example, 7.1 should be
// changed to 7.1(wide) without dropping the SL/SR channels. (We still leave
// it to libswresample to create the remix matrix.)
static uint64_t fudge_layout_conversion(struct mp_aconverter *p,
uint64_t in, uint64_t out)
{
for (int n = 0; n < MP_ARRAY_SIZE(fudge_pairs); n++) {
uint64_t a = mp_chmap_to_lavc(&fudge_pairs[n][0]);
uint64_t b = mp_chmap_to_lavc(&fudge_pairs[n][1]);
if ((in & a) == a && (in & b) == 0 &&
(out & a) == 0 && (out & b) == b)
{
out = (out & ~b) | a;
MP_VERBOSE(p, "Fudge: %s -> %s\n",
mp_chmap_to_str(&fudge_pairs[n][0]),
mp_chmap_to_str(&fudge_pairs[n][1]));
}
}
return out;
}
// mp_chmap_get_reorder() performs:
// to->speaker[n] = from->speaker[src[n]]
// but libavresample does:
// to->speaker[dst[n]] = from->speaker[n]
static void transpose_order(int *map, int num)
{
int nmap[MP_NUM_CHANNELS] = {0};
for (int n = 0; n < num; n++) {
for (int i = 0; i < num; i++) {
if (map[n] == i)
nmap[i] = n;
}
}
memcpy(map, nmap, sizeof(nmap));
}
static bool configure_lavrr(struct mp_aconverter *p, bool verbose)
{
close_lavrr(p);
p->in_rate = rate_from_speed(p->in_rate_user, p->playback_speed);
p->passthrough_mode = p->opts->allow_passthrough &&
p->in_rate == p->out_rate &&
p->in_format == p->out_format &&
mp_chmap_equals(&p->in_channels, &p->out_channels);
if (p->passthrough_mode)
return true;
p->avrctx = avresample_alloc_context();
p->avrctx_out = avresample_alloc_context();
if (!p->avrctx || !p->avrctx_out)
goto error;
enum AVSampleFormat in_samplefmt = af_to_avformat(p->in_format);
enum AVSampleFormat out_samplefmt = af_to_avformat(p->out_format);
enum AVSampleFormat out_samplefmtp = av_get_planar_sample_fmt(out_samplefmt);
if (in_samplefmt == AV_SAMPLE_FMT_NONE ||
out_samplefmt == AV_SAMPLE_FMT_NONE ||
out_samplefmtp == AV_SAMPLE_FMT_NONE)
goto error;
av_opt_set_int(p->avrctx, "filter_size", p->opts->filter_size, 0);
av_opt_set_int(p->avrctx, "phase_shift", p->opts->phase_shift, 0);
av_opt_set_int(p->avrctx, "linear_interp", p->opts->linear, 0);
double cutoff = p->opts->cutoff;
if (cutoff <= 0.0)
cutoff = MPMAX(1.0 - 6.5 / (p->opts->filter_size + 8), 0.80);
av_opt_set_double(p->avrctx, "cutoff", cutoff, 0);
int global_normalize;
mp_read_option_raw(p->global, "audio-normalize-downmix", &m_option_type_flag,
&global_normalize);
int normalize = p->opts->normalize;
if (normalize < 0)
normalize = global_normalize;
#if HAVE_LIBSWRESAMPLE
av_opt_set_double(p->avrctx, "rematrix_maxval", normalize ? 1 : 1000, 0);
#else
av_opt_set_int(p->avrctx, "normalize_mix_level", !!normalize, 0);
#endif
if (mp_set_avopts(p->log, p->avrctx, p->opts->avopts) < 0)
goto error;
struct mp_chmap map_in = p->in_channels;
struct mp_chmap map_out = p->out_channels;
// Try not to do any remixing if at least one is "unknown". Some corner
// cases also benefit from disabling all channel handling logic if the
// src/dst layouts are the same (like fl-fr-na -> fl-fr-na).
if (mp_chmap_is_unknown(&map_in) || mp_chmap_is_unknown(&map_out) ||
mp_chmap_equals(&map_in, &map_out))
{
mp_chmap_set_unknown(&map_in, map_in.num);
mp_chmap_set_unknown(&map_out, map_out.num);
}
// unchecked: don't take any channel reordering into account
uint64_t in_ch_layout = mp_chmap_to_lavc_unchecked(&map_in);
uint64_t out_ch_layout = mp_chmap_to_lavc_unchecked(&map_out);
struct mp_chmap in_lavc, out_lavc;
mp_chmap_from_lavc(&in_lavc, in_ch_layout);
mp_chmap_from_lavc(&out_lavc, out_ch_layout);
if (verbose && !mp_chmap_equals(&in_lavc, &out_lavc)) {
MP_VERBOSE(p, "Remix: %s -> %s\n", mp_chmap_to_str(&in_lavc),
mp_chmap_to_str(&out_lavc));
}
if (in_lavc.num != map_in.num) {
// For handling NA channels, we would have to add a planarization step.
MP_FATAL(p, "Unsupported input channel layout %s.\n",
mp_chmap_to_str(&map_in));
goto error;
}
mp_chmap_get_reorder(p->reorder_in, &map_in, &in_lavc);
transpose_order(p->reorder_in, map_in.num);
if (mp_chmap_equals(&out_lavc, &map_out)) {
// No intermediate step required - output new format directly.
out_samplefmtp = out_samplefmt;
} else {
// Verify that we really just reorder and/or insert NA channels.
struct mp_chmap withna = out_lavc;
mp_chmap_fill_na(&withna, map_out.num);
if (withna.num != map_out.num)
goto error;
}
mp_chmap_get_reorder(p->reorder_out, &out_lavc, &map_out);
p->pre_out_fmt = mp_aframe_create();
mp_aframe_set_rate(p->pre_out_fmt, p->out_rate);
mp_aframe_set_chmap(p->pre_out_fmt, &p->out_channels);
mp_aframe_set_format(p->pre_out_fmt, p->out_format);
p->avrctx_fmt = mp_aframe_create();
mp_aframe_config_copy(p->avrctx_fmt, p->pre_out_fmt);
mp_aframe_set_chmap(p->avrctx_fmt, &out_lavc);
mp_aframe_set_format(p->avrctx_fmt, af_from_avformat(out_samplefmtp));
// If there are NA channels, the final output will have more channels than
// the avrctx output. Also, avrctx will output planar (out_samplefmtp was
// not overwritten). Allocate the output frame with more channels, so the
// NA channels can be trivially added.
p->pool_fmt = mp_aframe_create();
mp_aframe_config_copy(p->pool_fmt, p->avrctx_fmt);
if (map_out.num > out_lavc.num)
mp_aframe_set_chmap(p->pool_fmt, &map_out);
out_ch_layout = fudge_layout_conversion(p, in_ch_layout, out_ch_layout);
// Real conversion; output is input to avrctx_out.
av_opt_set_int(p->avrctx, "in_channel_layout", in_ch_layout, 0);
av_opt_set_int(p->avrctx, "out_channel_layout", out_ch_layout, 0);
av_opt_set_int(p->avrctx, "in_sample_rate", p->in_rate, 0);
av_opt_set_int(p->avrctx, "out_sample_rate", p->out_rate, 0);
av_opt_set_int(p->avrctx, "in_sample_fmt", in_samplefmt, 0);
av_opt_set_int(p->avrctx, "out_sample_fmt", out_samplefmtp, 0);
// Just needs the correct number of channels for deplanarization.
struct mp_chmap fake_chmap;
mp_chmap_set_unknown(&fake_chmap, map_out.num);
uint64_t fake_out_ch_layout = mp_chmap_to_lavc_unchecked(&fake_chmap);
if (!fake_out_ch_layout)
goto error;
av_opt_set_int(p->avrctx_out, "in_channel_layout", fake_out_ch_layout, 0);
av_opt_set_int(p->avrctx_out, "out_channel_layout", fake_out_ch_layout, 0);
av_opt_set_int(p->avrctx_out, "in_sample_fmt", out_samplefmtp, 0);
av_opt_set_int(p->avrctx_out, "out_sample_fmt", out_samplefmt, 0);
av_opt_set_int(p->avrctx_out, "in_sample_rate", p->out_rate, 0);
av_opt_set_int(p->avrctx_out, "out_sample_rate", p->out_rate, 0);
// API has weird requirements, quoting avresample.h:
// * This function can only be called when the allocated context is not open.
// * Also, the input channel layout must have already been set.
avresample_set_channel_mapping(p->avrctx, p->reorder_in);
p->is_resampling = false;
if (avresample_open(p->avrctx) < 0 || avresample_open(p->avrctx_out) < 0) {
MP_ERR(p, "Cannot open Libavresample context.\n");
goto error;
}
return true;
error:
close_lavrr(p);
return false;
}
bool mp_aconverter_reconfig(struct mp_aconverter *p,
int in_rate, int in_format, struct mp_chmap in_channels,
int out_rate, int out_format, struct mp_chmap out_channels)
{
close_lavrr(p);
TA_FREEP(&p->input);
TA_FREEP(&p->output);
p->input_eof = p->output_eof = false;
p->playback_speed = 1.0;
p->in_rate_user = in_rate;
p->in_format = in_format;
p->in_channels = in_channels;
p->out_rate = out_rate;
p->out_format = out_format;
p->out_channels = out_channels;
return configure_lavrr(p, true);
}
void mp_aconverter_flush(struct mp_aconverter *p)
{
if (!p->avrctx)
return;
#if HAVE_LIBSWRESAMPLE
swr_close(p->avrctx);
if (swr_init(p->avrctx) < 0)
close_lavrr(p);
#else
while (avresample_read(p->avrctx, NULL, 1000) > 0) {}
#endif
}
void mp_aconverter_set_speed(struct mp_aconverter *p, double speed)
{
p->playback_speed = speed;
}
static void extra_output_conversion(struct mp_aframe *mpa)
{
int format = af_fmt_from_planar(mp_aframe_get_format(mpa));
int num_planes = mp_aframe_get_planes(mpa);
uint8_t **planes = mp_aframe_get_data_rw(mpa);
if (!planes)
return;
for (int p = 0; p < num_planes; p++) {
void *ptr = planes[p];
int total = mp_aframe_get_total_plane_samples(mpa);
if (format == AF_FORMAT_FLOAT) {
for (int s = 0; s < total; s++)
((float *)ptr)[s] = av_clipf(((float *)ptr)[s], -1.0f, 1.0f);
} else if (format == AF_FORMAT_DOUBLE) {
for (int s = 0; s < total; s++)
((double *)ptr)[s] = MPCLAMP(((double *)ptr)[s], -1.0, 1.0);
}
}
}
// This relies on the tricky way mpa was allocated.
static bool reorder_planes(struct mp_aframe *mpa, int *reorder,
struct mp_chmap *newmap)
{
if (!mp_aframe_set_chmap(mpa, newmap))
return false;
int num_planes = newmap->num;
uint8_t **planes = mp_aframe_get_data_rw(mpa);
uint8_t *old_planes[MP_NUM_CHANNELS];
assert(num_planes <= MP_NUM_CHANNELS);
for (int n = 0; n < num_planes; n++)
old_planes[n] = planes[n];
int next_na = 0;
for (int n = 0; n < num_planes; n++)
next_na += newmap->speaker[n] != MP_SPEAKER_ID_NA;
for (int n = 0; n < num_planes; n++) {
int src = reorder[n];
assert(src >= -1 && src < num_planes);
if (src >= 0) {
planes[n] = old_planes[src];
} else {
assert(next_na < num_planes);
planes[n] = old_planes[next_na++];
// The NA planes were never written by avrctx, so clear them.
af_fill_silence(planes[n],
mp_aframe_get_sstride(mpa) * mp_aframe_get_size(mpa),
mp_aframe_get_format(mpa));
}
}
return true;
}
static int resample_frame(struct AVAudioResampleContext *r,
struct mp_aframe *out, struct mp_aframe *in)
{
// Be aware that the channel layout and count can be different for in and
// out frames. In some situations the caller will fix up the frames before
// or after conversion. The sample rates can also be different.
AVFrame *av_i = in ? mp_aframe_get_raw_avframe(in) : NULL;
AVFrame *av_o = out ? mp_aframe_get_raw_avframe(out) : NULL;
return avresample_convert(r,
av_o ? av_o->extended_data : NULL,
av_o ? av_o->linesize[0] : 0,
av_o ? av_o->nb_samples : 0,
av_i ? av_i->extended_data : NULL,
av_i ? av_i->linesize[0] : 0,
av_i ? av_i->nb_samples : 0);
}
static void filter_resample(struct mp_aconverter *p, struct mp_aframe *in)
{
struct mp_aframe *out = NULL;
if (!p->avrctx)
goto error;
int samples = get_out_samples(p, in ? mp_aframe_get_size(in) : 0);
out = mp_aframe_create();
mp_aframe_config_copy(out, p->pool_fmt);
if (mp_aframe_pool_allocate(p->out_pool, out, samples) < 0)
goto error;
int out_samples = 0;
if (samples) {
out_samples = resample_frame(p->avrctx, out, in);
if (out_samples < 0 || out_samples > samples)
goto error;
mp_aframe_set_size(out, out_samples);
}
struct mp_chmap out_chmap;
if (!mp_aframe_get_chmap(p->pool_fmt, &out_chmap))
goto error;
if (!reorder_planes(out, p->reorder_out, &out_chmap))
goto error;
if (!mp_aframe_config_equals(out, p->pre_out_fmt)) {
struct mp_aframe *new = mp_aframe_create();
mp_aframe_config_copy(new, p->pre_out_fmt);
if (mp_aframe_pool_allocate(p->reorder_buffer, new, out_samples) < 0) {
talloc_free(new);
goto error;
}
int got = 0;
if (out_samples)
got = resample_frame(p->avrctx_out, new, out);
talloc_free(out);
out = new;
if (got != out_samples)
goto error;
}
extra_output_conversion(out);
if (in)
mp_aframe_copy_attributes(out, in);
if (out_samples) {
p->output = out;
} else {
talloc_free(out);
}
p->output_eof = !in; // we've read everything
return;
error:
talloc_free(out);
MP_ERR(p, "Error on resampling.\n");
}
static void filter(struct mp_aconverter *p)
{
if (p->output || p->output_eof || !(p->input || p->input_eof))
return;
int new_rate = rate_from_speed(p->in_rate_user, p->playback_speed);
if (p->passthrough_mode && new_rate != p->in_rate)
configure_lavrr(p, false);
if (p->passthrough_mode) {
p->output = p->input;
p->input = NULL;
p->output_eof = p->input_eof;
p->input_eof = false;
return;
}
if (p->avrctx && !(!p->is_resampling && new_rate == p->in_rate)) {
AVRational r = av_d2q(p->playback_speed * p->in_rate_user / p->in_rate,
INT_MAX / 2);
// Essentially, swr/avresample_set_compensation() does 2 things:
// - adjust output sample rate by sample_delta/compensation_distance
// - reset the adjustment after compensation_distance output samples
// Increase the compensation_distance to avoid undesired reset
// semantics - we want to keep the ratio for the whole frame we're
// feeding it, until the next filter() call.
int mult = INT_MAX / 2 / MPMAX(MPMAX(abs(r.num), abs(r.den)), 1);
r = (AVRational){ r.num * mult, r.den * mult };
if (avresample_set_compensation(p->avrctx, r.den - r.num, r.den) >= 0) {
new_rate = p->in_rate;
p->is_resampling = true;
}
}
bool need_reinit = fabs(new_rate / (double)p->in_rate - 1) > 0.01;
if (need_reinit && new_rate != p->in_rate) {
// Before reconfiguring, drain the audio that is still buffered
// in the resampler.
filter_resample(p, NULL);
// Reinitialize resampler.
configure_lavrr(p, false);
p->output_eof = false;
if (p->output)
return; // need to read output before continuing filtering
}
filter_resample(p, p->input);
TA_FREEP(&p->input);
p->input_eof = false;
}
// Queue input. If true, ownership of in passes to mp_aconverted and the input
// was accepted. Otherwise, return false and reject in.
// in==NULL means trigger EOF.
bool mp_aconverter_write_input(struct mp_aconverter *p, struct mp_aframe *in)
{
if (p->input || p->input_eof)
return false;
p->input = in;
p->input_eof = !in;
return true;
}
// Return output frame, or NULL if nothing available.
// *eof is set to true if NULL is returned, and it was due to EOF.
struct mp_aframe *mp_aconverter_read_output(struct mp_aconverter *p, bool *eof)
{
*eof = false;
filter(p);
if (p->output) {
struct mp_aframe *out = p->output;
p->output = NULL;
return out;
}
*eof = p->output_eof;
p->output_eof = false;
return NULL;
}
double mp_aconverter_get_latency(struct mp_aconverter *p)
{
double delay = get_delay(p);
if (p->input)
delay += mp_aframe_duration(p->input);
// In theory this is influenced by playback speed, but other parts of the
// player get it wrong anyway.
if (p->output)
delay += mp_aframe_duration(p->output);
return delay;
}
static void destroy_aconverter(void *ptr)
{
struct mp_aconverter *p = ptr;
close_lavrr(p);
talloc_free(p->input);
talloc_free(p->output);
}
// If opts is not NULL, the pointer must be valid for the lifetime of the
// mp_aconverter.
struct mp_aconverter *mp_aconverter_create(struct mpv_global *global,
struct mp_log *log,
const struct mp_resample_opts *opts)
{
struct mp_aconverter *p = talloc_zero(NULL, struct mp_aconverter);
p->log = log;
p->global = global;
static const struct mp_resample_opts defs = MP_RESAMPLE_OPTS_DEF;
p->opts = opts ? opts : &defs;
p->reorder_buffer = mp_aframe_pool_create(p);
p->out_pool = mp_aframe_pool_create(p);
talloc_set_destructor(p, destroy_aconverter);
return p;
}
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include <stdbool.h>
#include "chmap.h"
struct mp_aconverter;
struct mp_aframe;
struct mpv_global;
struct mp_log;
struct mp_resample_opts {
int filter_size;
int phase_shift;
int linear;
double cutoff;
int normalize;
int allow_passthrough;
char **avopts;
};
#define MP_RESAMPLE_OPTS_DEF { \
.filter_size = 16, \
.cutoff = 0.0, \
.phase_shift = 10, \
.normalize = -1, \
}
struct mp_aconverter *mp_aconverter_create(struct mpv_global *global,
struct mp_log *log,
const struct mp_resample_opts *opts);
bool mp_aconverter_reconfig(struct mp_aconverter *p,
int in_rate, int in_format, struct mp_chmap in_channels,
int out_rate, int out_format, struct mp_chmap out_channels);
void mp_aconverter_flush(struct mp_aconverter *p);
void mp_aconverter_set_speed(struct mp_aconverter *p, double speed);
bool mp_aconverter_write_input(struct mp_aconverter *p, struct mp_aframe *in);
struct mp_aframe *mp_aconverter_read_output(struct mp_aconverter *p, bool *eof);
double mp_aconverter_get_latency(struct mp_aconverter *p);
+467
View File
@@ -0,0 +1,467 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libavutil/frame.h>
#include <libavutil/mem.h>
#include "common/common.h"
#include "chmap.h"
#include "fmt-conversion.h"
#include "format.h"
#include "aframe.h"
struct mp_aframe {
AVFrame *av_frame;
// We support channel layouts different from AVFrame channel masks
struct mp_chmap chmap;
// We support spdif formats, which are allocated as AV_SAMPLE_FMT_S16.
int format;
double pts;
};
static void free_frame(void *ptr)
{
struct mp_aframe *frame = ptr;
av_frame_free(&frame->av_frame);
}
struct mp_aframe *mp_aframe_create(void)
{
struct mp_aframe *frame = talloc_zero(NULL, struct mp_aframe);
frame->pts = MP_NOPTS_VALUE;
frame->av_frame = av_frame_alloc();
if (!frame->av_frame)
abort();
talloc_set_destructor(frame, free_frame);
return frame;
}
struct mp_aframe *mp_aframe_new_ref(struct mp_aframe *frame)
{
if (!frame)
return NULL;
struct mp_aframe *dst = mp_aframe_create();
dst->chmap = frame->chmap;
dst->format = frame->format;
dst->pts = frame->pts;
if (mp_aframe_is_allocated(frame)) {
if (av_frame_ref(dst->av_frame, frame->av_frame) < 0)
abort();
} else {
// av_frame_ref() would fail.
mp_aframe_config_copy(dst, frame);
}
return dst;
}
// Revert to state after mp_aframe_create().
void mp_aframe_reset(struct mp_aframe *frame)
{
av_frame_unref(frame->av_frame);
frame->chmap.num = 0;
frame->format = 0;
frame->pts = MP_NOPTS_VALUE;
}
// Remove all actual audio data and leave only the metadata.
void mp_aframe_unref_data(struct mp_aframe *frame)
{
// In a fucked up way, this is less complex than just unreffing the data.
struct mp_aframe *tmp = mp_aframe_create();
MPSWAP(struct mp_aframe, *tmp, *frame);
mp_aframe_reset(frame);
mp_aframe_config_copy(frame, tmp);
talloc_free(tmp);
}
// Return a new reference to the data in av_frame. av_frame itself is not
// touched. Returns NULL if not representable, or if input is NULL.
// Does not copy the timestamps.
struct mp_aframe *mp_aframe_from_avframe(struct AVFrame *av_frame)
{
if (!av_frame || av_frame->width > 0 || av_frame->height > 0)
return NULL;
int format = af_from_avformat(av_frame->format);
if (!format && av_frame->format != AV_SAMPLE_FMT_NONE)
return NULL;
struct mp_aframe *frame = mp_aframe_create();
// This also takes care of forcing refcounting.
if (av_frame_ref(frame->av_frame, av_frame) < 0)
abort();
frame->format = format;
mp_chmap_from_lavc(&frame->chmap, frame->av_frame->channel_layout);
#if LIBAVUTIL_VERSION_MICRO >= 100
// FFmpeg being a stupid POS again
if (frame->chmap.num != frame->av_frame->channels)
mp_chmap_from_channels(&frame->chmap, av_frame->channels);
#endif
return frame;
}
// Return a new reference to the data in frame. Returns NULL is not
// representable (), or if input is NULL.
// Does not copy the timestamps.
struct AVFrame *mp_aframe_to_avframe(struct mp_aframe *frame)
{
if (!frame)
return NULL;
if (af_to_avformat(frame->format) != frame->av_frame->format)
return NULL;
if (!mp_chmap_is_lavc(&frame->chmap))
return NULL;
return av_frame_clone(frame->av_frame);
}
struct AVFrame *mp_aframe_to_avframe_and_unref(struct mp_aframe *frame)
{
AVFrame *av = mp_aframe_to_avframe(frame);
talloc_free(frame);
return av;
}
// You must not use this.
struct AVFrame *mp_aframe_get_raw_avframe(struct mp_aframe *frame)
{
return frame->av_frame;
}
// Return whether it has associated audio data. (If not, metadata only.)
bool mp_aframe_is_allocated(struct mp_aframe *frame)
{
return frame->av_frame->buf[0] || frame->av_frame->extended_data[0];
}
// Clear dst, and then copy the configuration to it.
void mp_aframe_config_copy(struct mp_aframe *dst, struct mp_aframe *src)
{
mp_aframe_reset(dst);
dst->chmap = src->chmap;
dst->format = src->format;
mp_aframe_copy_attributes(dst, src);
dst->av_frame->sample_rate = src->av_frame->sample_rate;
dst->av_frame->format = src->av_frame->format;
dst->av_frame->channel_layout = src->av_frame->channel_layout;
#if LIBAVUTIL_VERSION_MICRO >= 100
// FFmpeg being a stupid POS again
dst->av_frame->channels = src->av_frame->channels;
#endif
}
// Copy "soft" attributes from src to dst, excluding things which affect
// frame allocation and organization.
void mp_aframe_copy_attributes(struct mp_aframe *dst, struct mp_aframe *src)
{
dst->pts = src->pts;
int rate = dst->av_frame->sample_rate;
if (av_frame_copy_props(dst->av_frame, src->av_frame) < 0)
abort();
dst->av_frame->sample_rate = rate;
}
// Return whether a and b use the same physical audio format. Extra metadata
// such as PTS, per-frame signalling, and AVFrame side data is not compared.
bool mp_aframe_config_equals(struct mp_aframe *a, struct mp_aframe *b)
{
struct mp_chmap ca = {0}, cb = {0};
mp_aframe_get_chmap(a, &ca);
mp_aframe_get_chmap(b, &cb);
return mp_chmap_equals(&ca, &cb) &&
mp_aframe_get_rate(a) == mp_aframe_get_rate(b) &&
mp_aframe_get_format(a) == mp_aframe_get_format(b);
}
// Return whether all required format fields have been set.
bool mp_aframe_config_is_valid(struct mp_aframe *frame)
{
return frame->format && frame->chmap.num && frame->av_frame->sample_rate;
}
// Return the pointer to the first sample for each plane. The pointers stay
// valid until the next call that mutates frame somehow. You must not write to
// the audio data. Returns NULL if no frame allocated.
uint8_t **mp_aframe_get_data_ro(struct mp_aframe *frame)
{
return mp_aframe_is_allocated(frame) ? frame->av_frame->extended_data : NULL;
}
// Like mp_aframe_get_data_ro(), but you can write to the audio data.
// Additionally, it will return NULL if copy-on-write fails.
uint8_t **mp_aframe_get_data_rw(struct mp_aframe *frame)
{
if (!mp_aframe_is_allocated(frame))
return NULL;
if (av_frame_make_writable(frame->av_frame) < 0)
return NULL;
return frame->av_frame->extended_data;
}
int mp_aframe_get_format(struct mp_aframe *frame)
{
return frame->format;
}
bool mp_aframe_get_chmap(struct mp_aframe *frame, struct mp_chmap *out)
{
if (!mp_chmap_is_valid(&frame->chmap))
return false;
*out = frame->chmap;
return true;
}
int mp_aframe_get_channels(struct mp_aframe *frame)
{
return frame->chmap.num;
}
int mp_aframe_get_rate(struct mp_aframe *frame)
{
return frame->av_frame->sample_rate;
}
int mp_aframe_get_size(struct mp_aframe *frame)
{
return frame->av_frame->nb_samples;
}
double mp_aframe_get_pts(struct mp_aframe *frame)
{
return frame->pts;
}
bool mp_aframe_set_format(struct mp_aframe *frame, int format)
{
if (mp_aframe_is_allocated(frame))
return false;
enum AVSampleFormat av_format = af_to_avformat(format);
if (av_format == AV_SAMPLE_FMT_NONE && format) {
if (!af_fmt_is_spdif(format))
return false;
av_format = AV_SAMPLE_FMT_S16;
}
frame->format = format;
frame->av_frame->format = av_format;
return true;
}
bool mp_aframe_set_chmap(struct mp_aframe *frame, struct mp_chmap *in)
{
if (!mp_chmap_is_valid(in) && !mp_chmap_is_empty(in))
return false;
if (mp_aframe_is_allocated(frame) && in->num != frame->chmap.num)
return false;
uint64_t lavc_layout = mp_chmap_to_lavc_unchecked(in);
if (!lavc_layout && in->num)
return false;
frame->chmap = *in;
frame->av_frame->channel_layout = lavc_layout;
#if LIBAVUTIL_VERSION_MICRO >= 100
// FFmpeg being a stupid POS again
frame->av_frame->channels = frame->chmap.num;
#endif
return true;
}
bool mp_aframe_set_rate(struct mp_aframe *frame, int rate)
{
if (rate < 1 || rate > 10000000)
return false;
frame->av_frame->sample_rate = rate;
return true;
}
bool mp_aframe_set_size(struct mp_aframe *frame, int samples)
{
if (!mp_aframe_is_allocated(frame) || mp_aframe_get_size(frame) < samples)
return false;
frame->av_frame->nb_samples = MPMAX(samples, 0);
return true;
}
void mp_aframe_set_pts(struct mp_aframe *frame, double pts)
{
frame->pts = pts;
}
// Return number of data pointers.
int mp_aframe_get_planes(struct mp_aframe *frame)
{
return af_fmt_is_planar(mp_aframe_get_format(frame))
? mp_aframe_get_channels(frame) : 1;
}
// Return number of bytes between 2 consecutive samples on the same plane.
size_t mp_aframe_get_sstride(struct mp_aframe *frame)
{
int format = mp_aframe_get_format(frame);
return af_fmt_to_bytes(format) *
(af_fmt_is_planar(format) ? 1 : mp_aframe_get_channels(frame));
}
// Return total number of samples on each plane.
int mp_aframe_get_total_plane_samples(struct mp_aframe *frame)
{
return frame->av_frame->nb_samples *
(af_fmt_is_planar(mp_aframe_get_format(frame))
? 1 : mp_aframe_get_channels(frame));
}
// Set data to the audio after the given number of samples (i.e. slice it).
void mp_aframe_skip_samples(struct mp_aframe *f, int samples)
{
assert(samples >= 0 && samples <= mp_aframe_get_size(f));
int num_planes = mp_aframe_get_planes(f);
size_t sstride = mp_aframe_get_sstride(f);
for (int n = 0; n < num_planes; n++)
f->av_frame->extended_data[n] += samples * sstride;
f->av_frame->nb_samples -= samples;
if (f->pts != MP_NOPTS_VALUE)
f->pts += samples / (double)mp_aframe_get_rate(f);
}
// Return the timestamp of the sample just after the end of this frame.
double mp_aframe_end_pts(struct mp_aframe *f)
{
int rate = mp_aframe_get_rate(f);
if (f->pts == MP_NOPTS_VALUE || rate < 1)
return MP_NOPTS_VALUE;
return f->pts + f->av_frame->nb_samples / (double)rate;
}
// Return the duration in seconds of the frame (0 if invalid).
double mp_aframe_duration(struct mp_aframe *f)
{
int rate = mp_aframe_get_rate(f);
if (rate < 1)
return 0;
return f->av_frame->nb_samples / (double)rate;
}
// Clip the given frame to the given timestamp range. Adjusts the frame size
// and timestamp.
void mp_aframe_clip_timestamps(struct mp_aframe *f, double start, double end)
{
double f_end = mp_aframe_end_pts(f);
int rate = mp_aframe_get_rate(f);
if (f_end == MP_NOPTS_VALUE)
return;
if (end != MP_NOPTS_VALUE) {
if (f_end >= end) {
if (f->pts >= end) {
f->av_frame->nb_samples = 0;
} else {
int new = (end - f->pts) * rate;
f->av_frame->nb_samples = MPCLAMP(new, 0, f->av_frame->nb_samples);
}
}
}
if (start != MP_NOPTS_VALUE) {
if (f->pts < start) {
if (f_end <= start) {
f->av_frame->nb_samples = 0;
f->pts = f_end;
} else {
int skip = (start - f->pts) * rate;
skip = MPCLAMP(skip, 0, f->av_frame->nb_samples);
mp_aframe_skip_samples(f, skip);
}
}
}
}
struct mp_aframe_pool {
AVBufferPool *avpool;
int element_size;
};
struct mp_aframe_pool *mp_aframe_pool_create(void *ta_parent)
{
return talloc_zero(ta_parent, struct mp_aframe_pool);
}
static void mp_aframe_pool_destructor(void *p)
{
struct mp_aframe_pool *pool = p;
av_buffer_pool_uninit(&pool->avpool);
}
// Like mp_aframe_allocate(), but use the pool to allocate data.
int mp_aframe_pool_allocate(struct mp_aframe_pool *pool, struct mp_aframe *frame,
int samples)
{
int planes = mp_aframe_get_planes(frame);
size_t sstride = mp_aframe_get_sstride(frame);
int plane_size = MP_ALIGN_UP(sstride * MPMAX(samples, 1), 32);
int size = plane_size * planes;
if (size <= 0 || mp_aframe_is_allocated(frame))
return -1;
if (!pool->avpool || size > pool->element_size) {
size_t alloc = ta_calc_prealloc_elems(size);
if (alloc >= INT_MAX)
return -1;
av_buffer_pool_uninit(&pool->avpool);
pool->element_size = alloc;
pool->avpool = av_buffer_pool_init(pool->element_size, NULL);
if (!pool->avpool)
return -1;
talloc_set_destructor(pool, mp_aframe_pool_destructor);
}
// Yes, you have to do all this shit manually.
// At least it's less stupid than av_frame_get_buffer(), which just wipes
// the entire frame struct on error for no reason.
AVFrame *av_frame = frame->av_frame;
if (av_frame->extended_data != av_frame->data)
av_freep(&av_frame->extended_data); // sigh
av_frame->extended_data =
av_mallocz_array(planes, sizeof(av_frame->extended_data[0]));
if (!av_frame->extended_data)
abort();
av_frame->buf[0] = av_buffer_pool_get(pool->avpool);
if (!av_frame->buf[0])
return -1;
av_frame->linesize[0] = samples * sstride;
for (int n = 0; n < planes; n++)
av_frame->extended_data[n] = av_frame->buf[0]->data + n * plane_size;
av_frame->nb_samples = samples;
return 0;
}
+56
View File
@@ -0,0 +1,56 @@
#pragma once
#include <stdint.h>
struct mp_aframe;
struct AVFrame;
struct mp_chmap;
struct mp_aframe *mp_aframe_from_avframe(struct AVFrame *av_frame);
struct mp_aframe *mp_aframe_create(void);
struct mp_aframe *mp_aframe_new_ref(struct mp_aframe *frame);
void mp_aframe_reset(struct mp_aframe *frame);
void mp_aframe_unref_data(struct mp_aframe *frame);
struct AVFrame *mp_aframe_to_avframe(struct mp_aframe *frame);
struct AVFrame *mp_aframe_to_avframe_and_unref(struct mp_aframe *frame);
struct AVFrame *mp_aframe_get_raw_avframe(struct mp_aframe *frame);
bool mp_aframe_is_allocated(struct mp_aframe *frame);
void mp_aframe_config_copy(struct mp_aframe *dst, struct mp_aframe *src);
bool mp_aframe_config_equals(struct mp_aframe *a, struct mp_aframe *b);
bool mp_aframe_config_is_valid(struct mp_aframe *frame);
void mp_aframe_copy_attributes(struct mp_aframe *dst, struct mp_aframe *src);
uint8_t **mp_aframe_get_data_ro(struct mp_aframe *frame);
uint8_t **mp_aframe_get_data_rw(struct mp_aframe *frame);
int mp_aframe_get_format(struct mp_aframe *frame);
bool mp_aframe_get_chmap(struct mp_aframe *frame, struct mp_chmap *out);
int mp_aframe_get_channels(struct mp_aframe *frame);
int mp_aframe_get_rate(struct mp_aframe *frame);
int mp_aframe_get_size(struct mp_aframe *frame);
double mp_aframe_get_pts(struct mp_aframe *frame);
bool mp_aframe_set_format(struct mp_aframe *frame, int format);
bool mp_aframe_set_chmap(struct mp_aframe *frame, struct mp_chmap *in);
bool mp_aframe_set_rate(struct mp_aframe *frame, int rate);
bool mp_aframe_set_size(struct mp_aframe *frame, int samples);
void mp_aframe_set_pts(struct mp_aframe *frame, double pts);
int mp_aframe_get_planes(struct mp_aframe *frame);
int mp_aframe_get_total_plane_samples(struct mp_aframe *frame);
size_t mp_aframe_get_sstride(struct mp_aframe *frame);
void mp_aframe_skip_samples(struct mp_aframe *f, int samples);
double mp_aframe_end_pts(struct mp_aframe *f);
double mp_aframe_duration(struct mp_aframe *f);
void mp_aframe_clip_timestamps(struct mp_aframe *f, double start, double end);
struct mp_aframe_pool;
struct mp_aframe_pool *mp_aframe_pool_create(void *ta_parent);
int mp_aframe_pool_allocate(struct mp_aframe_pool *pool, struct mp_aframe *frame,
int samples);
+59 -3
View File
@@ -29,6 +29,7 @@
#include "common/common.h"
#include "fmt-conversion.h"
#include "audio.h"
#include "aframe.h"
static void update_redundant_info(struct mp_audio *mpa)
{
@@ -357,8 +358,8 @@ struct mp_audio *mp_audio_from_avframe(struct AVFrame *avframe)
#if LIBAVUTIL_VERSION_MICRO >= 100
// 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));
if (lavc_chmap.num != avframe->channels)
mp_chmap_from_channels(&lavc_chmap, avframe->channels);
#endif
new->rate = avframe->sample_rate;
@@ -403,6 +404,61 @@ fail:
return NULL;
}
struct mp_audio *mp_audio_from_aframe(struct mp_aframe *aframe)
{
if (!aframe)
return NULL;
struct AVFrame *av = mp_aframe_get_raw_avframe(aframe);
struct mp_audio *res = mp_audio_from_avframe(av);
if (!res)
return NULL;
struct mp_chmap chmap = {0};
mp_aframe_get_chmap(aframe, &chmap);
mp_audio_set_channels(res, &chmap);
mp_audio_set_format(res, mp_aframe_get_format(aframe));
res->pts = mp_aframe_get_pts(aframe);
return res;
}
void mp_audio_config_from_aframe(struct mp_audio *dst, struct mp_aframe *src)
{
*dst = (struct mp_audio){0};
struct mp_chmap chmap = {0};
mp_aframe_get_chmap(src, &chmap);
mp_audio_set_channels(dst, &chmap);
mp_audio_set_format(dst, mp_aframe_get_format(src));
dst->rate = mp_aframe_get_rate(src);
}
struct mp_aframe *mp_audio_to_aframe(struct mp_audio *mpa)
{
if (!mpa)
return NULL;
struct mp_aframe *aframe = mp_aframe_create();
struct AVFrame *av = mp_aframe_get_raw_avframe(aframe);
mp_aframe_set_format(aframe, mpa->format);
mp_aframe_set_chmap(aframe, &mpa->channels);
mp_aframe_set_rate(aframe, mpa->rate);
// bullshit it into ffmpeg-compatible parameters
struct mp_audio mpb = *mpa;
struct mp_chmap chmap;
mp_chmap_set_unknown(&chmap, mpb.channels.num);
mp_audio_set_channels(&mpb, &chmap);
if (af_fmt_is_spdif(mpb.format))
mp_audio_set_format(&mpb, AF_FORMAT_S16);
// put the reference into av, which magically puts it into aframe
// aframe keeps its parameters, so the bullshit doesn't matter
if (mp_audio_to_avframe(&mpb, av) < 0) {
talloc_free(aframe);
return NULL;
}
return aframe;
}
int mp_audio_to_avframe(struct mp_audio *frame, struct AVFrame *avframe)
{
av_frame_unref(avframe);
@@ -417,7 +473,7 @@ int mp_audio_to_avframe(struct mp_audio *frame, struct AVFrame *avframe)
goto fail;
#if LIBAVUTIL_VERSION_MICRO >= 100
// FFmpeg being a stupid POS again
av_frame_set_channels(avframe, frame->channels.num);
avframe->channels = frame->channels.num;
#endif
avframe->sample_rate = frame->rate;
+7
View File
@@ -83,6 +83,11 @@ 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_aframe;
struct mp_audio *mp_audio_from_aframe(struct mp_aframe *aframe);
void mp_audio_config_from_aframe(struct mp_audio *dst, struct mp_aframe *src);
struct mp_aframe *mp_audio_to_aframe(struct mp_audio *mpa);
struct mp_audio_pool;
struct mp_audio_pool *mp_audio_pool_create(void *ta_parent);
struct mp_audio *mp_audio_pool_get(struct mp_audio_pool *pool,
@@ -92,4 +97,6 @@ struct mp_audio *mp_audio_pool_new_copy(struct mp_audio_pool *pool,
int mp_audio_pool_make_writeable(struct mp_audio_pool *pool,
struct mp_audio *frame);
#include "filter/af.h"
#endif
+66 -70
View File
@@ -21,141 +21,137 @@
#include "common/common.h"
#include "chmap.h"
#include "audio_buffer.h"
#include "audio.h"
#include "format.h"
struct mp_audio_buffer {
struct mp_audio *buffer;
int format;
struct mp_chmap channels;
int srate;
int sstride;
int num_planes;
uint8_t *data[MP_NUM_CHANNELS];
int allocated;
int num_samples;
};
struct mp_audio_buffer *mp_audio_buffer_create(void *talloc_ctx)
{
struct mp_audio_buffer *ab = talloc(talloc_ctx, struct mp_audio_buffer);
*ab = (struct mp_audio_buffer) {
.buffer = talloc_zero(ab, struct mp_audio),
};
return ab;
return talloc_zero(talloc_ctx, struct mp_audio_buffer);
}
// Reinitialize the buffer, set a new format, drop old data.
// The audio data in fmt is not used, only the format.
void mp_audio_buffer_reinit(struct mp_audio_buffer *ab, struct mp_audio *fmt)
{
mp_audio_copy_config(ab->buffer, fmt);
mp_audio_realloc(ab->buffer, 1);
ab->buffer->samples = 0;
}
void mp_audio_buffer_reinit_fmt(struct mp_audio_buffer *ab, int format,
const struct mp_chmap *channels, int srate)
{
struct mp_audio mpa = {0};
mp_audio_set_format(&mpa, format);
mp_audio_set_channels(&mpa, channels);
mpa.rate = srate;
mp_audio_buffer_reinit(ab, &mpa);
}
void mp_audio_buffer_get_format(struct mp_audio_buffer *ab,
struct mp_audio *out_fmt)
{
*out_fmt = (struct mp_audio){0};
mp_audio_copy_config(out_fmt, ab->buffer);
for (int n = 0; n < MP_NUM_CHANNELS; n++)
TA_FREEP(&ab->data[n]);
ab->format = format;
ab->channels = *channels;
ab->srate = srate;
ab->allocated = 0;
ab->num_samples = 0;
ab->sstride = af_fmt_to_bytes(ab->format);
ab->num_planes = 1;
if (af_fmt_is_planar(ab->format)) {
ab->num_planes = ab->channels.num;
} else {
ab->sstride *= ab->channels.num;
}
}
// Make the total size of the internal buffer at least this number of samples.
void mp_audio_buffer_preallocate_min(struct mp_audio_buffer *ab, int samples)
{
mp_audio_realloc_min(ab->buffer, samples);
if (samples > ab->allocated) {
for (int n = 0; n < ab->num_planes; n++) {
ab->data[n] = talloc_realloc(ab, ab->data[n], char,
ab->sstride * samples);
}
ab->allocated = samples;
}
}
// Get number of samples that can be written without forcing a resize of the
// internal buffer.
int mp_audio_buffer_get_write_available(struct mp_audio_buffer *ab)
{
return mp_audio_get_allocated_size(ab->buffer) - ab->buffer->samples;
return ab->allocated - ab->num_samples;
}
// Get a pointer to the end of the buffer (where writing would append). If the
// internal buffer is too small for the given number of samples, it's resized.
// After writing to the buffer, mp_audio_buffer_finish_write() has to be used
// to make the written data part of the readable buffer.
void mp_audio_buffer_get_write_buffer(struct mp_audio_buffer *ab, int samples,
struct mp_audio *out_buffer)
// All integer parameters are in samples.
// dst and src can overlap.
static void copy_planes(struct mp_audio_buffer *ab,
uint8_t **dst, int dst_offset,
uint8_t **src, int src_offset, int length)
{
assert(samples >= 0);
mp_audio_realloc_min(ab->buffer, ab->buffer->samples + samples);
*out_buffer = *ab->buffer;
out_buffer->samples = ab->buffer->samples + samples;
mp_audio_skip_samples(out_buffer, ab->buffer->samples);
}
void mp_audio_buffer_finish_write(struct mp_audio_buffer *ab, int samples)
{
assert(samples >= 0 && samples <= mp_audio_buffer_get_write_available(ab));
ab->buffer->samples += samples;
for (int n = 0; n < ab->num_planes; n++) {
memmove((char *)dst[n] + dst_offset * ab->sstride,
(char *)src[n] + src_offset * ab->sstride,
length * ab->sstride);
}
}
// Append data to the end of the buffer.
// If the buffer is not large enough, it is transparently resized.
// For now always copies the data.
void mp_audio_buffer_append(struct mp_audio_buffer *ab, struct mp_audio *mpa)
void mp_audio_buffer_append(struct mp_audio_buffer *ab, void **ptr, int samples)
{
int offset = ab->buffer->samples;
ab->buffer->samples += mpa->samples;
mp_audio_realloc_min(ab->buffer, ab->buffer->samples);
mp_audio_copy(ab->buffer, offset, mpa, 0, mpa->samples);
mp_audio_buffer_preallocate_min(ab, ab->num_samples + samples);
copy_planes(ab, ab->data, ab->num_samples, (uint8_t **)ptr, 0, samples);
ab->num_samples += samples;
}
// Prepend silence to the start of the buffer.
void mp_audio_buffer_prepend_silence(struct mp_audio_buffer *ab, int samples)
{
assert(samples >= 0);
int oldlen = ab->buffer->samples;
ab->buffer->samples += samples;
mp_audio_realloc_min(ab->buffer, ab->buffer->samples);
mp_audio_copy(ab->buffer, samples, ab->buffer, 0, oldlen);
mp_audio_fill_silence(ab->buffer, 0, samples);
mp_audio_buffer_preallocate_min(ab, ab->num_samples + samples);
copy_planes(ab, ab->data, samples, ab->data, 0, ab->num_samples);
ab->num_samples += samples;
for (int n = 0; n < ab->num_planes; n++)
af_fill_silence(ab->data[n], samples * ab->sstride, ab->format);
}
void mp_audio_buffer_duplicate(struct mp_audio_buffer *ab, int samples)
{
assert(samples >= 0 && samples <= ab->buffer->samples);
int oldlen = ab->buffer->samples;
ab->buffer->samples += samples;
mp_audio_realloc_min(ab->buffer, ab->buffer->samples);
mp_audio_copy(ab->buffer, oldlen, ab->buffer, oldlen - samples, samples);
assert(samples >= 0 && samples <= ab->num_samples);
mp_audio_buffer_preallocate_min(ab, ab->num_samples + samples);
copy_planes(ab, ab->data, ab->num_samples,
ab->data, ab->num_samples - samples, samples);
ab->num_samples += samples;
}
// Get the start of the current readable buffer.
void mp_audio_buffer_peek(struct mp_audio_buffer *ab, struct mp_audio *out_mpa)
void mp_audio_buffer_peek(struct mp_audio_buffer *ab, uint8_t ***ptr,
int *samples)
{
*out_mpa = *ab->buffer;
*ptr = ab->data;
*samples = ab->num_samples;
}
// Skip leading samples. (Used with mp_audio_buffer_peek() to read data.)
void mp_audio_buffer_skip(struct mp_audio_buffer *ab, int samples)
{
assert(samples >= 0 && samples <= ab->buffer->samples);
mp_audio_copy(ab->buffer, 0, ab->buffer, samples,
ab->buffer->samples - samples);
ab->buffer->samples -= samples;
assert(samples >= 0 && samples <= ab->num_samples);
copy_planes(ab, ab->data, 0, ab->data, samples, ab->num_samples - samples);
ab->num_samples -= samples;
}
void mp_audio_buffer_clear(struct mp_audio_buffer *ab)
{
ab->buffer->samples = 0;
ab->num_samples = 0;
}
// Return number of buffered audio samples
int mp_audio_buffer_samples(struct mp_audio_buffer *ab)
{
return ab->buffer->samples;
return ab->num_samples;
}
// Return amount of buffered audio in seconds.
double mp_audio_buffer_seconds(struct mp_audio_buffer *ab)
{
return ab->buffer->samples / (double)ab->buffer->rate;
return ab->num_samples / (double)ab->srate;
}
+3 -9
View File
@@ -19,24 +19,18 @@
#define MP_AUDIO_BUFFER_H
struct mp_audio_buffer;
struct mp_audio;
struct mp_chmap;
struct mp_audio_buffer *mp_audio_buffer_create(void *talloc_ctx);
void mp_audio_buffer_reinit(struct mp_audio_buffer *ab, struct mp_audio *fmt);
void mp_audio_buffer_reinit_fmt(struct mp_audio_buffer *ab, int format,
const struct mp_chmap *channels, int srate);
void mp_audio_buffer_get_format(struct mp_audio_buffer *ab,
struct mp_audio *out_fmt);
void mp_audio_buffer_preallocate_min(struct mp_audio_buffer *ab, int samples);
int mp_audio_buffer_get_write_available(struct mp_audio_buffer *ab);
void mp_audio_buffer_get_write_buffer(struct mp_audio_buffer *ab, int minsamples,
struct mp_audio *out_buffer);
void mp_audio_buffer_finish_write(struct mp_audio_buffer *ab, int samples);
void mp_audio_buffer_append(struct mp_audio_buffer *ab, struct mp_audio *mpa);
void mp_audio_buffer_append(struct mp_audio_buffer *ab, void **ptr, int samples);
void mp_audio_buffer_prepend_silence(struct mp_audio_buffer *ab, int samples);
void mp_audio_buffer_duplicate(struct mp_audio_buffer *ab, int samples);
void mp_audio_buffer_peek(struct mp_audio_buffer *ab, struct mp_audio *out_mpa);
void mp_audio_buffer_peek(struct mp_audio_buffer *ab, uint8_t ***ptr,
int *samples);
void mp_audio_buffer_skip(struct mp_audio_buffer *ab, int samples);
void mp_audio_buffer_clear(struct mp_audio_buffer *ab);
int mp_audio_buffer_samples(struct mp_audio_buffer *ab);
+2 -2
View File
@@ -23,7 +23,7 @@
#include "demux/demux.h"
#include "audio/format.h"
#include "audio/audio.h"
#include "audio/aframe.h"
#include "dec_audio.h"
struct mp_decoder_list;
@@ -39,7 +39,7 @@ struct ad_functions {
bool (*send_packet)(struct dec_audio *da, struct demux_packet *pkt);
// Return whether decoding is still going on (false if EOF was reached).
// Never returns false & *out set, but can return true with !*out.
bool (*receive_frame)(struct dec_audio *da, struct mp_audio **out);
bool (*receive_frame)(struct dec_audio *da, struct mp_aframe **out);
};
enum ad_ctrl {
+12 -21
View File
@@ -40,7 +40,6 @@
struct priv {
AVCodecContext *avctx;
AVFrame *avframe;
struct mp_audio frame;
bool force_channel_map;
uint32_t skip_samples, trim_samples;
bool preroll_done;
@@ -191,7 +190,7 @@ static bool send_packet(struct dec_audio *da, struct demux_packet *mpkt)
return true;
}
static bool receive_frame(struct dec_audio *da, struct mp_audio **out)
static bool receive_frame(struct dec_audio *da, struct mp_aframe **out)
{
struct priv *priv = da->priv;
AVCodecContext *avctx = priv->avctx;
@@ -217,25 +216,18 @@ static bool receive_frame(struct dec_audio *da, struct mp_audio **out)
double out_pts = mp_pts_from_av(priv->avframe->pts, &priv->codec_timebase);
struct mp_audio *mpframe = mp_audio_from_avframe(priv->avframe);
struct mp_aframe *mpframe = mp_aframe_from_avframe(priv->avframe);
if (!mpframe)
return true;
struct mp_chmap lavc_chmap = mpframe->channels;
if (lavc_chmap.num != avctx->channels)
mp_chmap_from_channels(&lavc_chmap, avctx->channels);
if (priv->force_channel_map) {
if (lavc_chmap.num == da->codec->channels.num)
lavc_chmap = da->codec->channels;
}
mp_audio_set_channels(mpframe, &lavc_chmap);
if (priv->force_channel_map)
mp_aframe_set_chmap(mpframe, &da->codec->channels);
mpframe->pts = out_pts;
if (out_pts == MP_NOPTS_VALUE)
out_pts = priv->next_pts;
mp_aframe_set_pts(mpframe, out_pts);
if (mpframe->pts == MP_NOPTS_VALUE)
mpframe->pts = priv->next_pts;
if (mpframe->pts != MP_NOPTS_VALUE)
priv->next_pts = mpframe->pts + mpframe->samples / (double)mpframe->rate;
priv->next_pts = mp_aframe_end_pts(mpframe);
#if LIBAVCODEC_VERSION_MICRO >= 100
AVFrameSideData *sd =
@@ -254,14 +246,14 @@ static bool receive_frame(struct dec_audio *da, struct mp_audio **out)
priv->preroll_done = true;
}
uint32_t skip = MPMIN(priv->skip_samples, mpframe->samples);
uint32_t skip = MPMIN(priv->skip_samples, mp_aframe_get_size(mpframe));
if (skip) {
mp_audio_skip_samples(mpframe, skip);
mp_aframe_skip_samples(mpframe, skip);
priv->skip_samples -= skip;
}
uint32_t trim = MPMIN(priv->trim_samples, mpframe->samples);
uint32_t trim = MPMIN(priv->trim_samples, mp_aframe_get_size(mpframe));
if (trim) {
mpframe->samples -= trim;
mp_aframe_set_size(mpframe, mp_aframe_get_size(mpframe) - trim);
priv->trim_samples -= trim;
}
@@ -269,7 +261,6 @@ static bool receive_frame(struct dec_audio *da, struct mp_audio **out)
av_frame_unref(priv->avframe);
MP_DBG(da, "Decoded %d samples\n", mpframe->samples);
return true;
}
+29 -12
View File
@@ -40,8 +40,9 @@ struct spdifContext {
uint8_t out_buffer[OUTBUF_SIZE];
bool need_close;
bool use_dts_hd;
struct mp_audio fmt;
struct mp_audio_pool *pool;
struct mp_aframe *fmt;
int sstride;
struct mp_aframe_pool *pool;
bool got_eof;
struct demux_packet *queued_packet;
};
@@ -84,7 +85,7 @@ static int init(struct dec_audio *da, const char *decoder)
da->priv = spdif_ctx;
spdif_ctx->log = da->log;
spdif_ctx->use_dts_hd = da->opts->dtshd;
spdif_ctx->pool = mp_audio_pool_create(spdif_ctx);
spdif_ctx->pool = mp_aframe_pool_create(spdif_ctx);
if (strcmp(decoder, "spdif_dts_hd") == 0)
spdif_ctx->use_dts_hd = true;
@@ -198,6 +199,9 @@ static int init_filter(struct dec_audio *da, AVPacket *pkt)
AVDictionary *format_opts = NULL;
spdif_ctx->fmt = mp_aframe_create();
talloc_steal(spdif_ctx, spdif_ctx->fmt);
int num_channels = 0;
int sample_format = 0;
int samplerate = 0;
@@ -246,9 +250,14 @@ static int init_filter(struct dec_audio *da, AVPacket *pkt)
default:
abort();
}
mp_audio_set_num_channels(&spdif_ctx->fmt, num_channels);
mp_audio_set_format(&spdif_ctx->fmt, sample_format);
spdif_ctx->fmt.rate = samplerate;
struct mp_chmap chmap;
mp_chmap_from_channels(&chmap, num_channels);
mp_aframe_set_chmap(spdif_ctx->fmt, &chmap);
mp_aframe_set_format(spdif_ctx->fmt, sample_format);
mp_aframe_set_rate(spdif_ctx->fmt, samplerate);
spdif_ctx->sstride = mp_aframe_get_sstride(spdif_ctx->fmt);
if (avformat_write_header(lavf_ctx, &format_opts) < 0) {
MP_FATAL(da, "libavformat spdif initialization failed.\n");
@@ -279,7 +288,7 @@ static bool send_packet(struct dec_audio *da, struct demux_packet *mpkt)
return true;
}
static bool receive_frame(struct dec_audio *da, struct mp_audio **out)
static bool receive_frame(struct dec_audio *da, struct mp_aframe **out)
{
struct spdifContext *spdif_ctx = da->priv;
@@ -308,13 +317,21 @@ static bool receive_frame(struct dec_audio *da, struct mp_audio **out)
goto done;
}
int samples = spdif_ctx->out_buffer_len / spdif_ctx->fmt.sstride;
*out = mp_audio_pool_get(spdif_ctx->pool, &spdif_ctx->fmt, samples);
if (!*out)
*out = mp_aframe_new_ref(spdif_ctx->fmt);
int samples = spdif_ctx->out_buffer_len / spdif_ctx->sstride;
if (mp_aframe_pool_allocate(spdif_ctx->pool, *out, samples) < 0) {
TA_FREEP(out);
goto done;
}
memcpy((*out)->planes[0], spdif_ctx->out_buffer, spdif_ctx->out_buffer_len);
(*out)->pts = pts;
uint8_t **data = mp_aframe_get_data_rw(*out);
if (!data) {
TA_FREEP(out);
goto done;
}
memcpy(data[0], spdif_ctx->out_buffer, spdif_ctx->out_buffer_len);
mp_aframe_set_pts(*out, pts);
done:
talloc_free(spdif_ctx->queued_packet);
+21 -25
View File
@@ -29,6 +29,7 @@
#include "common/msg.h"
#include "common/recorder.h"
#include "misc/bstr.h"
#include "options/options.h"
#include "stream/stream.h"
#include "demux/demux.h"
@@ -38,10 +39,6 @@
#include "dec_audio.h"
#include "ad.h"
#include "audio/format.h"
#include "audio/audio.h"
#include "audio/audio_buffer.h"
#include "audio/filter/af.h"
extern const struct ad_functions ad_lavc;
@@ -179,25 +176,30 @@ static void fix_audio_pts(struct dec_audio *da)
if (!da->current_frame)
return;
if (da->current_frame->pts != MP_NOPTS_VALUE) {
double newpts = da->current_frame->pts;
double frame_pts = mp_aframe_get_pts(da->current_frame);
if (frame_pts != MP_NOPTS_VALUE) {
if (da->pts != MP_NOPTS_VALUE)
MP_STATS(da, "value %f audio-pts-err", da->pts - newpts);
MP_STATS(da, "value %f audio-pts-err", da->pts - frame_pts);
// Keep the interpolated timestamp if it doesn't deviate more
// than 1 ms from the real one. (MKV rounded timestamps.)
if (da->pts == MP_NOPTS_VALUE || fabs(da->pts - newpts) > 0.001)
da->pts = newpts;
if (da->pts == MP_NOPTS_VALUE || fabs(da->pts - frame_pts) > 0.001)
da->pts = frame_pts;
}
if (da->pts == MP_NOPTS_VALUE && da->header->missing_timestamps)
da->pts = 0;
da->current_frame->pts = da->pts;
mp_aframe_set_pts(da->current_frame, da->pts);
if (da->pts != MP_NOPTS_VALUE)
da->pts += da->current_frame->samples / (double)da->current_frame->rate;
da->pts += mp_aframe_duration(da->current_frame);
}
static bool is_new_segment(struct dec_audio *da, struct demux_packet *p)
{
return p->segmented &&
(p->start != da->start || p->end != da->end || p->codec != da->codec);
}
void audio_work(struct dec_audio *da)
@@ -212,7 +214,7 @@ void audio_work(struct dec_audio *da)
return;
}
if (da->packet && da->packet->new_segment) {
if (da->packet && is_new_segment(da, da->packet)) {
assert(!da->new_segment);
da->new_segment = da->packet;
da->packet = NULL;
@@ -228,11 +230,6 @@ void audio_work(struct dec_audio *da)
bool progress = da->ad_driver->receive_frame(da, &da->current_frame);
if (da->current_frame && !mp_audio_config_valid(da->current_frame)) {
talloc_free(da->current_frame);
da->current_frame = NULL;
}
da->current_state = da->current_frame ? DATA_OK : DATA_AGAIN;
if (!progress)
da->current_state = DATA_EOF;
@@ -242,10 +239,11 @@ void audio_work(struct dec_audio *da)
bool segment_end = da->current_state == DATA_EOF;
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->end;
if (da->current_frame->samples == 0) {
mp_aframe_clip_timestamps(da->current_frame, da->start, da->end);
double frame_pts = mp_aframe_get_pts(da->current_frame);
if (frame_pts != MP_NOPTS_VALUE && da->start != MP_NOPTS_VALUE)
segment_end = frame_pts >= da->end;
if (mp_aframe_get_size(da->current_frame) == 0) {
talloc_free(da->current_frame);
da->current_frame = NULL;
}
@@ -268,8 +266,6 @@ void audio_work(struct dec_audio *da)
da->start = new_segment->start;
da->end = new_segment->end;
new_segment->new_segment = false;
da->packet = new_segment;
da->current_state = DATA_AGAIN;
}
@@ -280,7 +276,7 @@ void audio_work(struct dec_audio *da)
// DATA_WAIT: waiting for demuxer; will receive a wakeup signal
// DATA_EOF: end of file, no more frames to be expected
// DATA_AGAIN: dropped frame or something similar
int audio_get_frame(struct dec_audio *da, struct mp_audio **out_frame)
int audio_get_frame(struct dec_audio *da, struct mp_aframe **out_frame)
{
*out_frame = NULL;
if (da->current_frame) {
+3 -4
View File
@@ -19,11 +19,10 @@
#define MPLAYER_DEC_AUDIO_H
#include "audio/chmap.h"
#include "audio/audio.h"
#include "audio/aframe.h"
#include "demux/demux.h"
#include "demux/stheader.h"
struct mp_audio_buffer;
struct mp_decoder_list;
struct dec_audio {
@@ -48,7 +47,7 @@ struct dec_audio {
double start, end;
struct demux_packet *packet;
struct demux_packet *new_segment;
struct mp_audio *current_frame;
struct mp_aframe *current_frame;
int current_state;
};
@@ -57,7 +56,7 @@ int audio_init_best_codec(struct dec_audio *d_audio);
void audio_uninit(struct dec_audio *d_audio);
void audio_work(struct dec_audio *d_audio);
int audio_get_frame(struct dec_audio *d_audio, struct mp_audio **out_frame);
int audio_get_frame(struct dec_audio *d_audio, struct mp_aframe **out_frame);
void audio_reset_decoding(struct dec_audio *d_audio);
+2 -10
View File
@@ -31,25 +31,16 @@
#include "af.h"
// Static list of filters
extern const struct af_info af_info_channels;
extern const struct af_info af_info_format;
extern const struct af_info af_info_volume;
extern const struct af_info af_info_equalizer;
extern const struct af_info af_info_pan;
extern const struct af_info af_info_lavcac3enc;
extern const struct af_info af_info_lavrresample;
extern const struct af_info af_info_scaletempo;
extern const struct af_info af_info_bs2b;
extern const struct af_info af_info_lavfi;
extern const struct af_info af_info_lavfi_bridge;
extern const struct af_info af_info_rubberband;
static const struct af_info *const filter_list[] = {
&af_info_channels,
&af_info_format,
&af_info_volume,
&af_info_equalizer,
&af_info_pan,
&af_info_lavcac3enc,
&af_info_lavrresample,
#if HAVE_RUBBERBAND
@@ -175,7 +166,7 @@ static struct af_instance *af_create(struct af_stream *s, char *name,
.data = talloc_zero(af, struct mp_audio),
.log = mp_log_new(af, s->log, name),
.opts = s->opts,
.replaygain_data = s->replaygain_data,
.global = s->global,
.out_pool = mp_audio_pool_create(af),
};
struct m_config *config =
@@ -546,6 +537,7 @@ struct af_stream *af_new(struct mpv_global *global)
s->first->next = s->last;
s->last->prev = s->first;
s->opts = global->opts;
s->global = global;
return s;
}
+7 -7
View File
@@ -22,6 +22,11 @@
#include <stdbool.h>
#include <sys/types.h>
#include "config.h"
#if !(HAVE_LIBAF && HAVE_GPL)
#error "libaf/GPL disabled"
#endif
#include "options/options.h"
#include "audio/format.h"
#include "audio/chmap.h"
@@ -55,7 +60,7 @@ struct af_instance {
char *full_name;
struct mp_log *log;
struct MPOpts *opts;
struct replaygain_data *replaygain_data;
struct mpv_global *global;
int (*control)(struct af_instance *af, int cmd, void *arg);
void (*uninit)(struct af_instance *af);
/* Feed a frame. The frame is NULL if EOF was reached, and the filter
@@ -98,7 +103,7 @@ struct af_stream {
struct mp_log *log;
struct MPOpts *opts;
struct replaygain_data *replaygain_data;
struct mpv_global *global;
};
// Return values
@@ -113,11 +118,6 @@ struct af_stream {
enum af_control {
AF_CONTROL_REINIT = 1,
AF_CONTROL_RESET,
AF_CONTROL_SET_VOLUME,
AF_CONTROL_SET_PAN_LEVEL,
AF_CONTROL_SET_PAN_NOUT,
AF_CONTROL_SET_PAN_BALANCE,
AF_CONTROL_GET_PAN_BALANCE,
AF_CONTROL_SET_PLAYBACK_SPEED,
AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE,
AF_CONTROL_GET_METADATA,
-255
View File
@@ -1,255 +0,0 @@
/*
* Audio filter that adds and removes channels, according to the
* command line parameter channels. It is stupid and can only add
* silence or copy channels, not mix or filter.
*
* 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 FR 0
#define TO 1
typedef struct af_channels_s{
int route[AF_NCH][2];
int nch, nr;
int router;
char *routes;
}af_channels_t;
// Local function for copying data
static void copy(struct af_instance *af, void* in, void* out,
int ins, int inos,int outs, int outos, int len, int bps)
{
switch(bps){
case 1:{
int8_t* tin = (int8_t*)in;
int8_t* tout = (int8_t*)out;
tin += inos;
tout += outos;
len = len/ins;
while(len--){
*tout=*tin;
tin +=ins;
tout+=outs;
}
break;
}
case 2:{
int16_t* tin = (int16_t*)in;
int16_t* tout = (int16_t*)out;
tin += inos;
tout += outos;
len = len/(2*ins);
while(len--){
*tout=*tin;
tin +=ins;
tout+=outs;
}
break;
}
case 3:{
int8_t* tin = (int8_t*)in;
int8_t* tout = (int8_t*)out;
tin += 3 * inos;
tout += 3 * outos;
len = len / ( 3 * ins);
while (len--) {
tout[0] = tin[0];
tout[1] = tin[1];
tout[2] = tin[2];
tin += 3 * ins;
tout += 3 * outs;
}
break;
}
case 4:{
int32_t* tin = (int32_t*)in;
int32_t* tout = (int32_t*)out;
tin += inos;
tout += outos;
len = len/(4*ins);
while(len--){
*tout=*tin;
tin +=ins;
tout+=outs;
}
break;
}
case 8:{
int64_t* tin = (int64_t*)in;
int64_t* tout = (int64_t*)out;
tin += inos;
tout += outos;
len = len/(8*ins);
while(len--){
*tout=*tin;
tin +=ins;
tout+=outs;
}
break;
}
default:
MP_ERR(af, "Unsupported number of bytes/sample: %i"
" please report this error on the MPlayer mailing list. \n",bps);
}
}
// Make sure the routes are sane
static int check_routes(struct af_instance *af, int nin, int nout)
{
af_channels_t* s = af->priv;
int i;
if((s->nr < 1) || (s->nr > AF_NCH)){
MP_ERR(af, "The number of routing pairs must be"
" between 1 and %i. Current value is %i\n",AF_NCH,s->nr);
return AF_ERROR;
}
for(i=0;i<s->nr;i++){
if((s->route[i][FR] >= nin) || (s->route[i][TO] >= nout)){
MP_ERR(af, "Invalid routing in pair nr. %i.\n", i);
return AF_ERROR;
}
}
return AF_OK;
}
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
af_channels_t* s = af->priv;
switch(cmd){
case AF_CONTROL_REINIT: ;
struct mp_chmap chmap;
mp_chmap_set_unknown(&chmap, s->nch);
mp_audio_set_channels(af->data, &chmap);
// Set default channel assignment
if(!s->router){
int i;
// Make sure this filter isn't redundant
if(af->data->nch == ((struct mp_audio*)arg)->nch)
return AF_DETACH;
// If mono: fake stereo
if(((struct mp_audio*)arg)->nch == 1){
s->nr = MPMIN(af->data->nch,2);
for(i=0;i<s->nr;i++){
s->route[i][FR] = 0;
s->route[i][TO] = i;
}
}
else{
s->nr = MPMIN(af->data->nch, ((struct mp_audio*)arg)->nch);
for(i=0;i<s->nr;i++){
s->route[i][FR] = i;
s->route[i][TO] = i;
}
}
}
af->data->rate = ((struct mp_audio*)arg)->rate;
mp_audio_force_interleaved_format((struct mp_audio*)arg);
mp_audio_set_format(af->data, ((struct mp_audio*)arg)->format);
return check_routes(af,((struct mp_audio*)arg)->nch,af->data->nch);
}
return AF_UNKNOWN;
}
static int filter_frame(struct af_instance *af, struct mp_audio *c)
{
af_channels_t* s = af->priv;
int i;
if (!c)
return 0;
struct mp_audio *l = mp_audio_pool_get(af->out_pool, &af->fmt_out, c->samples);
if (!l) {
talloc_free(c);
return -1;
}
mp_audio_copy_attributes(l, c);
// Reset unused channels
memset(l->planes[0],0,mp_audio_psize(c) / c->nch * l->nch);
if(AF_OK == check_routes(af,c->nch,l->nch))
for(i=0;i<s->nr;i++)
copy(af, c->planes[0],l->planes[0],c->nch,s->route[i][FR],
l->nch,s->route[i][TO],mp_audio_psize(c),c->bps);
talloc_free(c);
af_add_output_frame(af, l);
return 0;
}
// Allocate memory and set function pointers
static int af_open(struct af_instance* af){
af->control=control;
af->filter_frame = filter_frame;
af_channels_t *s = af->priv;
MP_WARN(af, "This filter is deprecated (no replacement).\n");
// If router scan commandline for routing pairs
if(s->routes && s->routes[0]){
char* cp = s->routes;
int ch = 0;
// Scan for pairs on commandline
do {
int n = 0;
if (ch >= AF_NCH) {
MP_FATAL(af, "Can't have more than %d routes.\n", AF_NCH);
return AF_ERROR;
}
sscanf(cp, "%i-%i%n" ,&s->route[ch][FR], &s->route[ch][TO], &n);
MP_VERBOSE(af, "Routing from channel %i to"
" channel %i\n",s->route[ch][FR],s->route[ch][TO]);
cp = &cp[n];
ch++;
} while(*cp == ',' && *(cp++));
s->nr = ch;
if (s->nr > 0)
s->router = 1;
}
return AF_OK;
}
#define OPT_BASE_STRUCT af_channels_t
const struct af_info af_info_channels = {
.info = "Insert or remove channels",
.name = "channels",
.open = af_open,
.priv_size = sizeof(af_channels_t),
.options = (const struct m_option[]) {
OPT_INTRANGE("nch", nch, 0, 1, AF_NCH, OPTDEF_INT(2)),
OPT_STRING("routes", routes, 0),
{0}
},
};
-215
View File
@@ -1,215 +0,0 @@
/*
* Equalizer filter, implementation of a 10 band time domain graphic
* equalizer using IIR filters. The IIR filters are implemented using a
* Direct Form II approach, but has been modified (b1 == 0 always) to
* save computation.
*
* Copyright (C) 2001 Anders Johansson ajh@atri.curtin.edu.au
*
* 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 <inttypes.h>
#include <math.h>
#include "common/common.h"
#include "af.h"
#define L 2 // Storage for filter taps
#define KM 10 // Max number of bands
#define Q 1.2247449 /* Q value for band-pass filters 1.2247=(3/2)^(1/2)
gives 4dB suppression @ Fc*2 and Fc/2 */
/* Center frequencies for band-pass filters
The different frequency bands are:
nr. center frequency
0 31.25 Hz
1 62.50 Hz
2 125.0 Hz
3 250.0 Hz
4 500.0 Hz
5 1.000 kHz
6 2.000 kHz
7 4.000 kHz
8 8.000 kHz
9 16.00 kHz
*/
#define CF {31.25,62.5,125,250,500,1000,2000,4000,8000,16000}
// Maximum and minimum gain for the bands
#define G_MAX +12.0
#define G_MIN -12.0
// Data for specific instances of this filter
typedef struct af_equalizer_s
{
float a[KM][L]; // A weights
float b[KM][L]; // B weights
float wq[AF_NCH][KM][L]; // Circular buffer for W data
float g[AF_NCH][KM]; // Gain factor for each channel and band
int K; // Number of used eq bands
int channels; // Number of channels
float gain_factor; // applied at output to avoid clipping
double p[KM];
} af_equalizer_t;
// 2nd order Band-pass Filter design
static void bp2(float* a, float* b, float fc, float q){
double th= 2.0 * M_PI * fc;
double C = (1.0 - tan(th*q/2.0))/(1.0 + tan(th*q/2.0));
a[0] = (1.0 + C) * cos(th);
a[1] = -1 * C;
b[0] = (1.0 - C)/2.0;
b[1] = -1.0050;
}
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
af_equalizer_t* s = (af_equalizer_t*)af->priv;
switch(cmd){
case AF_CONTROL_REINIT:{
int k =0, i =0;
float F[KM] = CF;
s->gain_factor=0.0;
// Sanity check
if(!arg) return AF_ERROR;
mp_audio_copy_config(af->data, (struct mp_audio*)arg);
mp_audio_set_format(af->data, AF_FORMAT_FLOAT);
// Calculate number of active filters
s->K=KM;
while(F[s->K-1] > (float)af->data->rate/2.2)
s->K--;
if(s->K != KM)
MP_INFO(af, "Limiting the number of filters to"
" %i due to low sample rate.\n",s->K);
// Generate filter taps
for(k=0;k<s->K;k++)
bp2(s->a[k],s->b[k],F[k]/((float)af->data->rate),Q);
// Calculate how much this plugin adds to the overall time delay
af->delay = 2.0 / (double)af->data->rate;
// Calculate gain factor to prevent clipping at output
for(k=0;k<AF_NCH;k++)
{
for(i=0;i<KM;i++)
{
if(s->gain_factor < s->g[k][i]) s->gain_factor=s->g[k][i];
}
}
s->gain_factor=log10(s->gain_factor + 1.0) * 20.0;
if(s->gain_factor > 0.0)
{
s->gain_factor=0.1+(s->gain_factor/12.0);
}else{
s->gain_factor=1;
}
return af_test_output(af,arg);
}
}
return AF_UNKNOWN;
}
static int filter(struct af_instance* af, struct mp_audio* data)
{
struct mp_audio* c = data; // Current working data
if (!c)
return 0;
af_equalizer_t* s = (af_equalizer_t*)af->priv; // Setup
uint32_t ci = af->data->nch; // Index for channels
uint32_t nch = af->data->nch; // Number of channels
if (af_make_writeable(af, data) < 0) {
talloc_free(data);
return -1;
}
while(ci--){
float* g = s->g[ci]; // Gain factor
float* in = ((float*)c->planes[0])+ci;
float* out = ((float*)c->planes[0])+ci;
float* end = in + c->samples*c->nch; // Block loop end
while(in < end){
register int k = 0; // Frequency band index
register float yt = *in; // Current input sample
in+=nch;
// Run the filters
for(;k<s->K;k++){
// Pointer to circular buffer wq
register float* wq = s->wq[ci][k];
// Calculate output from AR part of current filter
register float w=yt*s->b[k][0] + wq[0]*s->a[k][0] + wq[1]*s->a[k][1];
// Calculate output form MA part of current filter
yt+=(w + wq[1]*s->b[k][1])*g[k];
// Update circular buffer
wq[1] = wq[0];
wq[0] = w;
}
// Calculate output
*out=yt*s->gain_factor;
out+=nch;
}
}
af_add_output_frame(af, data);
return 0;
}
// Allocate memory and set function pointers
static int af_open(struct af_instance* af){
MP_WARN(af, "This filter is deprecated. Use 'anequalizer' or 'firequalizer' instead.\n");
af->control=control;
af->filter_frame = filter;
af_equalizer_t *priv = af->priv;
for(int i=0;i<AF_NCH;i++){
for(int j=0;j<KM;j++){
priv->g[i][j] = pow(10.0,MPCLAMP(priv->p[j],G_MIN,G_MAX)/20.0)-1.0;
}
}
return AF_OK;
}
#define OPT_BASE_STRUCT af_equalizer_t
const struct af_info af_info_equalizer = {
.info = "Equalizer audio filter",
.name = "equalizer",
.open = af_open,
.priv_size = sizeof(af_equalizer_t),
.options = (const struct m_option[]) {
#define BAND(n) OPT_DOUBLE("e" #n, p[n], 0)
BAND(0), BAND(1), BAND(2), BAND(3), BAND(4),
BAND(5), BAND(6), BAND(7), BAND(8), BAND(9),
{0}
},
};
+1 -1
View File
@@ -400,7 +400,7 @@ static int af_open(struct af_instance* af){
}
}
if (i >= 19) {
MP_WARN(af, "unable set unsupported bitrate %d, use default "
MP_WARN(af, "unable set unsupported bitrate %d, using default "
"bitrate (check manpage to see supported bitrates).\n",
s->cfg_bit_rate);
}
+11 -7
View File
@@ -92,6 +92,7 @@ static bool recreate_graph(struct af_instance *af, struct mp_audio *config)
void *tmp = talloc_new(NULL);
struct priv *p = af->priv;
AVFilterContext *in = NULL, *out = NULL;
bool ok = false;
if (!p->is_bridge && bstr0(p->cfg_graph).len == 0) {
MP_FATAL(af, "lavfi: no filter graph set\n");
@@ -177,14 +178,17 @@ static bool recreate_graph(struct af_instance *af, struct mp_audio *config)
assert(out->nb_inputs == 1);
assert(in->nb_outputs == 1);
talloc_free(tmp);
return true;
ok = true;
error:
MP_FATAL(af, "Can't configure libavfilter graph.\n");
avfilter_graph_free(&graph);
if (!ok) {
MP_FATAL(af, "Can't configure libavfilter graph.\n");
avfilter_graph_free(&graph);
}
avfilter_inout_free(&inputs);
avfilter_inout_free(&outputs);
talloc_free(tmp);
return false;
return ok;
}
static void reset(struct af_instance *af)
@@ -261,7 +265,7 @@ static void get_metadata_from_av_frame(struct af_instance *af, AVFrame *frame)
if (!p->metadata)
p->metadata = talloc_zero(p, struct mp_tags);
mp_tags_copy_from_av_dictionary(p->metadata, av_frame_get_metadata(frame));
mp_tags_copy_from_av_dictionary(p->metadata, frame->metadata);
#endif
}
+37 -457
View File
@@ -27,323 +27,24 @@
#include <math.h>
#include <assert.h>
#include <libavutil/opt.h>
#include <libavutil/common.h>
#include <libavutil/samplefmt.h>
#include <libavutil/channel_layout.h>
#include <libavutil/mathematics.h>
#include "common/common.h"
#include "config.h"
#define HAVE_LIBSWRESAMPLE HAVE_IS_FFMPEG
#define HAVE_LIBAVRESAMPLE HAVE_IS_LIBAV
#if HAVE_LIBAVRESAMPLE
#include <libavresample/avresample.h>
#elif HAVE_LIBSWRESAMPLE
#include <libswresample/swresample.h>
#define AVAudioResampleContext SwrContext
#define avresample_alloc_context swr_alloc
#define avresample_open swr_init
#define avresample_close(x) do { } while(0)
#define avresample_free swr_free
#define avresample_available(x) 0
#define avresample_convert(ctx, out, out_planesize, out_samples, in, in_planesize, in_samples) \
swr_convert(ctx, out, out_samples, (const uint8_t**)(in), in_samples)
#define avresample_set_channel_mapping swr_set_channel_mapping
#define avresample_set_compensation swr_set_compensation
#else
#error "config.h broken or no resampler found"
#endif
#include "common/av_common.h"
#include "common/msg.h"
#include "options/m_option.h"
#include "audio/filter/af.h"
#include "audio/fmt-conversion.h"
#include "osdep/endian.h"
struct af_resample_opts {
int filter_size;
int phase_shift;
int linear;
double cutoff;
int normalize;
};
#include "audio/aconverter.h"
struct af_resample {
int allow_detach;
char **avopts;
double playback_speed;
struct AVAudioResampleContext *avrctx;
struct mp_audio avrctx_fmt; // output format of avrctx
struct mp_audio pool_fmt; // format used to allocate frames for avrctx output
struct mp_audio pre_out_fmt; // format before final conversion (S24)
struct AVAudioResampleContext *avrctx_out; // for output channel reordering
struct af_resample_opts opts; // opts requested by the user
// At least libswresample keeps a pointer around for this:
int reorder_in[MP_NUM_CHANNELS];
int reorder_out[MP_NUM_CHANNELS];
struct mp_audio_pool *reorder_buffer;
int in_rate_af; // filter input sample rate
int in_rate; // actual rate (used by lavr), adjusted for playback speed
int in_format;
struct mp_chmap in_channels;
int out_rate;
int out_format;
struct mp_chmap out_channels;
struct mp_resample_opts opts;
struct mp_aconverter *converter;
};
#if HAVE_LIBAVRESAMPLE
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 int get_out_samples(struct af_resample *s, int in_samples)
{
return avresample_get_out_samples(s->avrctx, in_samples);
}
#else
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 int get_out_samples(struct af_resample *s, int in_samples)
{
return swr_get_out_samples(s->avrctx, in_samples);
}
#endif
static void close_lavrr(struct af_instance *af)
{
struct af_resample *s = af->priv;
if (s->avrctx)
avresample_close(s->avrctx);
avresample_free(&s->avrctx);
if (s->avrctx_out)
avresample_close(s->avrctx_out);
avresample_free(&s->avrctx_out);
}
static int resample_frame(struct AVAudioResampleContext *r,
struct mp_audio *out, struct mp_audio *in)
{
return avresample_convert(r,
out ? (uint8_t **)out->planes : NULL,
out ? mp_audio_get_allocated_size(out) : 0,
out ? out->samples : 0,
in ? (uint8_t **)in->planes : NULL,
in ? mp_audio_get_allocated_size(in) : 0,
in ? in->samples : 0);
}
static double af_resample_default_cutoff(int filter_size)
{
return FFMAX(1.0 - 6.5 / (filter_size + 8), 0.80);
}
static int rate_from_speed(int rate, double speed)
{
return lrint(rate * speed);
}
static struct mp_chmap fudge_pairs[][2] = {
{MP_CHMAP2(BL, BR), MP_CHMAP2(SL, SR)},
{MP_CHMAP2(SL, SR), MP_CHMAP2(BL, BR)},
{MP_CHMAP2(SDL, SDR), MP_CHMAP2(SL, SR)},
{MP_CHMAP2(SL, SR), MP_CHMAP2(SDL, SDR)},
};
// Modify out_layout and return the new value. The intention is reducing the
// loss libswresample's rematrixing will cause by exchanging similar, but
// strictly speaking incompatible channel pairs. For example, 7.1 should be
// changed to 7.1(wide) without dropping the SL/SR channels. (We still leave
// it to libswresample to create the remix matrix.)
static uint64_t fudge_layout_conversion(struct af_instance *af,
uint64_t in, uint64_t out)
{
for (int n = 0; n < MP_ARRAY_SIZE(fudge_pairs); n++) {
uint64_t a = mp_chmap_to_lavc(&fudge_pairs[n][0]);
uint64_t b = mp_chmap_to_lavc(&fudge_pairs[n][1]);
if ((in & a) == a && (in & b) == 0 &&
(out & a) == 0 && (out & b) == b)
{
out = (out & ~b) | a;
MP_VERBOSE(af, "Fudge: %s -> %s\n",
mp_chmap_to_str(&fudge_pairs[n][0]),
mp_chmap_to_str(&fudge_pairs[n][1]));
}
}
return out;
}
// mp_chmap_get_reorder() performs:
// to->speaker[n] = from->speaker[src[n]]
// but libavresample does:
// to->speaker[dst[n]] = from->speaker[n]
static void transpose_order(int *map, int num)
{
int nmap[MP_NUM_CHANNELS] = {0};
for (int n = 0; n < num; n++) {
for (int i = 0; i < num; i++) {
if (map[n] == i)
nmap[i] = n;
}
}
memcpy(map, nmap, sizeof(nmap));
}
static int configure_lavrr(struct af_instance *af, struct mp_audio *in,
struct mp_audio *out, bool verbose)
{
struct af_resample *s = af->priv;
close_lavrr(af);
s->avrctx = avresample_alloc_context();
s->avrctx_out = avresample_alloc_context();
if (!s->avrctx || !s->avrctx_out)
goto error;
enum AVSampleFormat in_samplefmt = af_to_avformat(in->format);
enum AVSampleFormat out_samplefmt = af_to_avformat(out->format);
enum AVSampleFormat out_samplefmtp = av_get_planar_sample_fmt(out_samplefmt);
if (in_samplefmt == AV_SAMPLE_FMT_NONE ||
out_samplefmt == AV_SAMPLE_FMT_NONE ||
out_samplefmtp == AV_SAMPLE_FMT_NONE)
goto error;
s->out_rate = out->rate;
s->in_rate_af = in->rate;
s->in_rate = rate_from_speed(in->rate, s->playback_speed);
s->out_format = out->format;
s->in_format = in->format;
s->out_channels= out->channels;
s->in_channels = in->channels;
av_opt_set_int(s->avrctx, "filter_size", s->opts.filter_size, 0);
av_opt_set_int(s->avrctx, "phase_shift", s->opts.phase_shift, 0);
av_opt_set_int(s->avrctx, "linear_interp", s->opts.linear, 0);
av_opt_set_double(s->avrctx, "cutoff", s->opts.cutoff, 0);
int normalize = s->opts.normalize;
if (normalize < 0)
normalize = af->opts->audio_normalize;
#if HAVE_LIBSWRESAMPLE
av_opt_set_double(s->avrctx, "rematrix_maxval", normalize ? 1 : 1000, 0);
#else
av_opt_set_int(s->avrctx, "normalize_mix_level", !!normalize, 0);
#endif
if (mp_set_avopts(af->log, s->avrctx, s->avopts) < 0)
goto error;
struct mp_chmap map_in = in->channels;
struct mp_chmap map_out = out->channels;
// Try not to do any remixing if at least one is "unknown".
if (mp_chmap_is_unknown(&map_in) || mp_chmap_is_unknown(&map_out)) {
mp_chmap_set_unknown(&map_in, map_in.num);
mp_chmap_set_unknown(&map_out, map_out.num);
}
// unchecked: don't take any channel reordering into account
uint64_t in_ch_layout = mp_chmap_to_lavc_unchecked(&map_in);
uint64_t out_ch_layout = mp_chmap_to_lavc_unchecked(&map_out);
struct mp_chmap in_lavc, out_lavc;
mp_chmap_from_lavc(&in_lavc, in_ch_layout);
mp_chmap_from_lavc(&out_lavc, out_ch_layout);
if (verbose && !mp_chmap_equals(&in_lavc, &out_lavc)) {
MP_VERBOSE(af, "Remix: %s -> %s\n", mp_chmap_to_str(&in_lavc),
mp_chmap_to_str(&out_lavc));
}
if (in_lavc.num != map_in.num) {
// For handling NA channels, we would have to add a planarization step.
MP_FATAL(af, "Unsupported channel remapping.\n");
goto error;
}
mp_chmap_get_reorder(s->reorder_in, &map_in, &in_lavc);
transpose_order(s->reorder_in, map_in.num);
if (mp_chmap_equals(&out_lavc, &map_out)) {
// No intermediate step required - output new format directly.
out_samplefmtp = out_samplefmt;
} else {
// Verify that we really just reorder and/or insert NA channels.
struct mp_chmap withna = out_lavc;
mp_chmap_fill_na(&withna, map_out.num);
if (withna.num != map_out.num)
goto error;
}
mp_chmap_get_reorder(s->reorder_out, &out_lavc, &map_out);
s->avrctx_fmt = *out;
mp_audio_set_channels(&s->avrctx_fmt, &out_lavc);
mp_audio_set_format(&s->avrctx_fmt, af_from_avformat(out_samplefmtp));
s->pre_out_fmt = *out;
// If there are NA channels, the final output will have more channels than
// the avrctx output. Also, avrctx will output planar (out_samplefmtp was
// not overwritten). Allocate the output frame with more channels, so the
// NA channels can be trivially added.
s->pool_fmt = s->avrctx_fmt;
if (map_out.num > out_lavc.num)
mp_audio_set_channels(&s->pool_fmt, &map_out);
out_ch_layout = fudge_layout_conversion(af, in_ch_layout, out_ch_layout);
// Real conversion; output is input to avrctx_out.
av_opt_set_int(s->avrctx, "in_channel_layout", in_ch_layout, 0);
av_opt_set_int(s->avrctx, "out_channel_layout", out_ch_layout, 0);
av_opt_set_int(s->avrctx, "in_sample_rate", s->in_rate, 0);
av_opt_set_int(s->avrctx, "out_sample_rate", s->out_rate, 0);
av_opt_set_int(s->avrctx, "in_sample_fmt", in_samplefmt, 0);
av_opt_set_int(s->avrctx, "out_sample_fmt", out_samplefmtp, 0);
// Just needs the correct number of channels for deplanarization.
struct mp_chmap fake_chmap;
mp_chmap_set_unknown(&fake_chmap, map_out.num);
uint64_t fake_out_ch_layout = mp_chmap_to_lavc_unchecked(&fake_chmap);
if (!fake_out_ch_layout)
goto error;
av_opt_set_int(s->avrctx_out, "in_channel_layout", fake_out_ch_layout, 0);
av_opt_set_int(s->avrctx_out, "out_channel_layout", fake_out_ch_layout, 0);
av_opt_set_int(s->avrctx_out, "in_sample_fmt", out_samplefmtp, 0);
av_opt_set_int(s->avrctx_out, "out_sample_fmt", out_samplefmt, 0);
av_opt_set_int(s->avrctx_out, "in_sample_rate", s->out_rate, 0);
av_opt_set_int(s->avrctx_out, "out_sample_rate", s->out_rate, 0);
// API has weird requirements, quoting avresample.h:
// * This function can only be called when the allocated context is not open.
// * Also, the input channel layout must have already been set.
avresample_set_channel_mapping(s->avrctx, s->reorder_in);
if (avresample_open(s->avrctx) < 0 || avresample_open(s->avrctx_out) < 0) {
MP_ERR(af, "Cannot open Libavresample Context. \n");
goto error;
}
return AF_OK;
error:
close_lavrr(af);
return AF_ERROR;
}
static int control(struct af_instance *af, int cmd, void *arg)
{
struct af_resample *s = af->priv;
@@ -375,8 +76,12 @@ static int control(struct af_instance *af, int cmd, void *arg)
mp_chmap_equals(&in->channels, &orig_in.channels))
? AF_OK : AF_FALSE;
if (r == AF_OK)
r = configure_lavrr(af, in, out, true);
if (r == AF_OK) {
if (!mp_aconverter_reconfig(s->converter,
in->rate, in->format, in->channels,
out->rate, out->format, out->channels))
r = AF_ERROR;
}
return r;
}
case AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE: {
@@ -384,166 +89,48 @@ static int control(struct af_instance *af, int cmd, void *arg)
return AF_OK;
}
case AF_CONTROL_RESET:
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
}
mp_aconverter_flush(s->converter);
return AF_OK;
}
return AF_UNKNOWN;
}
static void uninit(struct af_instance *af)
{
close_lavrr(af);
}
// The LSB is always ignored.
#if BYTE_ORDER == BIG_ENDIAN
#define SHIFT24(x) ((3-(x))*8)
#else
#define SHIFT24(x) (((x)+1)*8)
#endif
static void extra_output_conversion(struct af_instance *af, struct mp_audio *mpa)
{
for (int p = 0; p < mpa->num_planes; p++) {
void *ptr = mpa->planes[p];
int total = mpa->samples * mpa->spf;
if (af_fmt_from_planar(mpa->format) == AF_FORMAT_FLOAT) {
for (int s = 0; s < total; s++)
((float *)ptr)[s] = av_clipf(((float *)ptr)[s], -1.0f, 1.0f);
} else if (af_fmt_from_planar(mpa->format) == AF_FORMAT_DOUBLE) {
for (int s = 0; s < total; s++)
((double *)ptr)[s] = MPCLAMP(((double *)ptr)[s], -1.0, 1.0);
}
}
}
// This relies on the tricky way mpa was allocated.
static void reorder_planes(struct mp_audio *mpa, int *reorder,
struct mp_chmap *newmap)
{
struct mp_audio prev = *mpa;
mp_audio_set_channels(mpa, newmap);
// The trailing planes were never written by avrctx, they're the NA channels.
int next_na = prev.num_planes;
for (int n = 0; n < mpa->num_planes; n++) {
int src = reorder[n];
assert(src >= -1 && src < prev.num_planes);
if (src >= 0) {
mpa->planes[n] = prev.planes[src];
} else {
assert(next_na < mpa->num_planes);
mpa->planes[n] = prev.planes[next_na++];
af_fill_silence(mpa->planes[n], mpa->sstride * mpa->samples,
mpa->format);
}
}
}
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;
out = mp_audio_pool_get(af->out_pool, &out_format, samples);
if (!out)
goto error;
if (in)
mp_audio_copy_attributes(out, in);
if (out->samples) {
out->samples = resample_frame(s->avrctx, out, in);
if (out->samples < 0)
goto error;
}
struct mp_audio real_out = *out;
mp_audio_copy_config(out, &s->avrctx_fmt);
if (out->samples && !mp_audio_config_equals(out, &s->pre_out_fmt)) {
assert(af_fmt_is_planar(out->format) && out->format == real_out.format);
reorder_planes(out, s->reorder_out, &s->pool_fmt.channels);
if (!mp_audio_config_equals(out, &s->pre_out_fmt)) {
struct mp_audio *new = mp_audio_pool_get(s->reorder_buffer,
&s->pre_out_fmt,
out->samples);
if (!new)
goto error;
mp_audio_copy_attributes(new, out);
int out_samples = resample_frame(s->avrctx_out, new, out);
talloc_free(out);
out = new;
if (out_samples != new->samples)
goto error;
}
}
extra_output_conversion(af, out);
talloc_free(in);
if (out->samples) {
af_add_output_frame(af, out);
} else {
talloc_free(out);
}
af->delay = get_delay(s);
return 0;
error:
talloc_free(in);
talloc_free(out);
return -1;
talloc_free(s->converter);
}
static int filter(struct af_instance *af, struct mp_audio *in)
{
struct af_resample *s = af->priv;
int new_rate = rate_from_speed(s->in_rate_af, s->playback_speed);
bool need_reinit = fabs(new_rate / (double)s->in_rate - 1) > 0.01;
mp_aconverter_set_speed(s->converter, s->playback_speed);
if (s->avrctx) {
AVRational r = av_d2q(s->playback_speed * s->in_rate_af / s->in_rate,
INT_MAX / 2);
// Essentially, swr/avresample_set_compensation() does 2 things:
// - adjust output sample rate by sample_delta/compensation_distance
// - reset the adjustment after compensation_distance output samples
// Increase the compensation_distance to avoid undesired reset
// semantics - we want to keep the ratio for the whole frame we're
// feeding it, until the next filter() call.
int mult = INT_MAX / 2 / MPMAX(MPMAX(abs(r.num), abs(r.den)), 1);
r = (AVRational){ r.num * mult, r.den * mult };
if (avresample_set_compensation(s->avrctx, r.den - r.num, r.den) < 0)
need_reinit = true;
}
af->filter_out(af);
if (need_reinit && new_rate != s->in_rate) {
// Before reconfiguring, drain the audio that is still buffered
// in the resampler.
filter_resample(af, NULL);
// Reinitialize resampler.
configure_lavrr(af, &af->fmt_in, &af->fmt_out, false);
}
struct mp_aframe *aframe = mp_audio_to_aframe(in);
if (!aframe && in)
return -1;
talloc_free(in);
bool ok = mp_aconverter_write_input(s->converter, aframe);
if (!ok)
talloc_free(aframe);
return filter_resample(af, in);
return ok ? 0 : -1;
}
static int filter_out(struct af_instance *af)
{
struct af_resample *s = af->priv;
bool eof;
struct mp_aframe *out = mp_aconverter_read_output(s->converter, &eof);
if (out)
af_add_output_frame(af, mp_audio_from_aframe(out));
talloc_free(out);
af->delay = mp_aconverter_get_latency(s->converter);
return 0;
}
static int af_open(struct af_instance *af)
@@ -553,11 +140,9 @@ static int af_open(struct af_instance *af)
af->control = control;
af->uninit = uninit;
af->filter_frame = filter;
af->filter_out = filter_out;
if (s->opts.cutoff <= 0.0)
s->opts.cutoff = af_resample_default_cutoff(s->opts.filter_size);
s->reorder_buffer = mp_audio_pool_create(s);
s->converter = mp_aconverter_create(af->global, af->log, &s->opts);
return AF_OK;
}
@@ -570,12 +155,7 @@ const struct af_info af_info_lavrresample = {
.open = af_open,
.priv_size = sizeof(struct af_resample),
.priv_defaults = &(const struct af_resample) {
.opts = {
.filter_size = 16,
.cutoff = 0.0,
.phase_shift = 10,
.normalize = -1,
},
.opts = MP_RESAMPLE_OPTS_DEF,
.playback_speed = 1.0,
.allow_detach = 1,
},
@@ -587,7 +167,7 @@ const struct af_info af_info_lavrresample = {
OPT_FLAG("detach", allow_detach, 0),
OPT_CHOICE("normalize", opts.normalize, 0,
({"no", 0}, {"yes", 1}, {"auto", -1})),
OPT_KEYVALUELIST("o", avopts, 0),
OPT_KEYVALUELIST("o", opts.avopts, 0),
{0}
},
};
-206
View File
@@ -1,206 +0,0 @@
/*
* Copyright (C) 2002 Anders Johansson ajh@atri.curtin.edu.au
*
* 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 <inttypes.h>
#include <math.h>
#include <limits.h>
#include "common/common.h"
#include "af.h"
// Data for specific instances of this filter
typedef struct af_pan_s {
int nch; // Number of output channels; zero means same as input
float level[AF_NCH][AF_NCH]; // Gain level for each channel
char *matrixstr;
} af_pan_t;
static void set_channels(struct mp_audio *mpa, int num)
{
struct mp_chmap map;
// "unknown" channel layouts make it easier to pass through audio data,
// without triggering remixing.
mp_chmap_set_unknown(&map, num);
mp_audio_set_channels(mpa, &map);
}
static void parse_matrix(struct af_instance *af, const char *cp)
{
af_pan_t *s = af->priv;
int j = 0, k = 0, n;
while (*cp && k < AF_NCH) {
sscanf(cp, "%f%n" , &s->level[j][k], &n);
MP_VERBOSE(af, "Pan level from channel %i to"
" channel %i = %f\n", k, j, s->level[j][k]);
cp = &cp[n];
j++;
if (j >= s->nch) {
j = 0;
k++;
}
if (*cp != ',')
break;
cp++;
}
}
// Initialization and runtime control
static int control(struct af_instance *af, int cmd, void *arg)
{
af_pan_t* s = af->priv;
switch(cmd){
case AF_CONTROL_REINIT:
// Sanity check
if (!arg)
return AF_ERROR;
af->data->rate = ((struct mp_audio*)arg)->rate;
mp_audio_set_format(af->data, AF_FORMAT_FLOAT);
set_channels(af->data, s->nch ? s->nch : ((struct mp_audio*)arg)->nch);
if ((af->data->format != ((struct mp_audio*)arg)->format) ||
(af->data->bps != ((struct mp_audio*)arg)->bps)) {
mp_audio_set_format((struct mp_audio*)arg, af->data->format);
return AF_FALSE;
}
return AF_OK;
case AF_CONTROL_SET_PAN_LEVEL: {
int i;
int ch = ((af_control_ext_t*)arg)->ch;
float *level = ((af_control_ext_t*)arg)->arg;
if (ch >= AF_NCH)
return AF_FALSE;
for (i = 0; i < AF_NCH; i++)
s->level[ch][i] = level[i];
return AF_OK;
}
case AF_CONTROL_SET_PAN_NOUT:
// Reinit must be called after this function has been called
// Sanity check
if (((int*)arg)[0] <= 0 || ((int*)arg)[0] > AF_NCH) {
MP_ERR(af, "The number of output channels must be"
" between 1 and %i. Current value is %i\n",
AF_NCH, ((int*)arg)[0]);
return AF_ERROR;
}
s->nch = ((int*)arg)[0];
return AF_OK;
case AF_CONTROL_SET_PAN_BALANCE: {
float val = *(float*)arg;
if (s->nch)
return AF_ERROR;
if (af->data->nch >= 2) {
s->level[0][0] = MPMIN(1.f, 1.f - val);
s->level[0][1] = MPMAX(0.f, val);
s->level[1][0] = MPMAX(0.f, -val);
s->level[1][1] = MPMIN(1.f, 1.f + val);
}
return AF_OK;
}
case AF_CONTROL_GET_PAN_BALANCE:
if (s->nch)
return AF_ERROR;
*(float*)arg = s->level[0][1] - s->level[1][0];
return AF_OK;
case AF_CONTROL_COMMAND: {
char **args = arg;
if (!strcmp(args[0], "set-matrix")) {
parse_matrix(af, args[1]);
return CONTROL_OK;
} else {
return CONTROL_ERROR;
}
}
}
return AF_UNKNOWN;
}
static int filter_frame(struct af_instance *af, struct mp_audio *c)
{
if (!c)
return 0;
struct mp_audio *l = mp_audio_pool_get(af->out_pool, &af->fmt_out, c->samples);
if (!l) {
talloc_free(c);
return -1;
}
mp_audio_copy_attributes(l, c);
af_pan_t* s = af->priv; // Setup for this instance
float *in = c->planes[0]; // Input audio data
float *out = NULL; // Output audio data
float *end = in+c->samples * c->nch; // End of loop
int nchi = c->nch; // Number of input channels
int ncho = l->nch; // Number of output channels
register int j, k;
out = l->planes[0];
// Execute panning
// FIXME: Too slow
while (in < end) {
for (j = 0; j < ncho; j++) {
register float x = 0.0;
register float *tin = in;
for (k = 0; k < nchi; k++)
x += tin[k] * s->level[j][k];
out[j] = x;
}
out += ncho;
in += nchi;
}
talloc_free(c);
af_add_output_frame(af, l);
return 0;
}
// Allocate memory and set function pointers
static int af_open(struct af_instance *af)
{
af->control = control;
af->filter_frame = filter_frame;
MP_WARN(af, "This filter is deprecated. Use lavfi pan instead.\n");
af_pan_t *s = af->priv;
int nch = s->nch;
if (nch && AF_OK != control(af, AF_CONTROL_SET_PAN_NOUT, &nch))
return AF_ERROR;
// Read pan values
if (s->matrixstr)
parse_matrix(af, s->matrixstr);
return AF_OK;
}
#define OPT_BASE_STRUCT af_pan_t
const struct af_info af_info_pan = {
.info = "Panning audio filter",
.name = "pan",
.open = af_open,
.priv_size = sizeof(af_pan_t),
.options = (const struct m_option[]) {
OPT_INTRANGE("channels", nch, 0, 0, AF_NCH),
OPT_STRING("matrix", matrixstr, 0),
{0}
},
};
-188
View File
@@ -1,188 +0,0 @@
/*
* Copyright (C)2002 Anders Johansson ajh@atri.curtin.edu.au
*
* 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 <math.h>
#include <limits.h>
#include "common/common.h"
#include "af.h"
#include "demux/demux.h"
struct priv {
float level; // User-specified gain level for each channel
float rgain; // Replaygain level
int rgain_track; // Enable/disable track based replaygain
int rgain_album; // Enable/disable album based replaygain
float rgain_preamp; // Set replaygain pre-amplification
int rgain_clip; // Enable/disable clipping prevention
float replaygain_fallback;
int soft; // Enable/disable soft clipping
int fast; // Use fix-point volume control
int detach; // Detach if gain volume is neutral
float cfg_volume;
int warn;
};
// Convert to gain value from dB. input <= -200dB will become 0 gain.
static float from_dB(float in, float k, float mi, float ma)
{
if (in <= -200)
return 0.0;
return pow(10.0, MPCLAMP(in, mi, ma) / k);
}
static int control(struct af_instance *af, int cmd, void *arg)
{
struct priv *s = af->priv;
switch (cmd) {
case AF_CONTROL_REINIT: {
struct mp_audio *in = arg;
mp_audio_copy_config(af->data, in);
mp_audio_force_interleaved_format(af->data);
if (s->fast && af_fmt_from_planar(in->format) != AF_FORMAT_FLOAT) {
mp_audio_set_format(af->data, AF_FORMAT_S16);
} else {
mp_audio_set_format(af->data, AF_FORMAT_FLOAT);
}
if (af_fmt_is_planar(in->format))
mp_audio_set_format(af->data, af_fmt_to_planar(af->data->format));
s->rgain = 1.0;
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 = rg->track_gain;
peak = rg->track_peak;
} else {
gain = rg->album_gain;
peak = rg->album_peak;
}
gain += s->rgain_preamp;
s->rgain = from_dB(gain, 20.0, -200.0, 60.0);
MP_VERBOSE(af, "Applying replay-gain: %f\n", s->rgain);
if (!s->rgain_clip) { // clipping prevention
s->rgain = MPMIN(s->rgain, 1.0 / peak);
MP_VERBOSE(af, "...with clipping prevention: %f\n", s->rgain);
}
} else if (s->replaygain_fallback) {
s->rgain = from_dB(s->replaygain_fallback, 20.0, -200.0, 60.0);
MP_VERBOSE(af, "Applying fallback gain: %f\n", s->rgain);
}
if (s->detach && fabs(s->level * s->rgain - 1.0) < 0.00001)
return AF_DETACH;
return af_test_output(af, in);
}
case AF_CONTROL_SET_VOLUME:
s->level = *(float *)arg;
MP_VERBOSE(af, "volume gain: %f\n", s->level);
return AF_OK;
}
return AF_UNKNOWN;
}
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 * 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) {
int vol = 256.0 * level;
if (vol != 256) {
if (af_make_writeable(af, data) < 0)
return; // oom
int16_t *a = data->planes[p];
for (int i = 0; i < num_samples; i++) {
int x = (a[i] * vol) >> 8;
a[i] = MPCLAMP(x, SHRT_MIN, SHRT_MAX);
}
}
} else if (af_fmt_from_planar(af->data->format) == AF_FORMAT_FLOAT) {
float vol = level;
if (vol != 1.0) {
if (af_make_writeable(af, data) < 0)
return; // oom
float *a = data->planes[p];
for (int i = 0; i < num_samples; i++) {
float x = a[i] * vol;
a[i] = s->soft ? af_softclip(x) : MPCLAMP(x, -1.0, 1.0);
}
}
}
}
static int filter(struct af_instance *af, struct mp_audio *data)
{
if (data) {
for (int n = 0; n < data->num_planes; n++)
filter_plane(af, data, n);
af_add_output_frame(af, data);
}
return 0;
}
static int af_open(struct af_instance *af)
{
struct priv *s = af->priv;
if (s->warn)
MP_WARN(af, "This filter is deprecated. Use --volume directly.\n");
af->control = control;
af->filter_frame = filter;
s->level = 1.0;
return AF_OK;
}
#define OPT_BASE_STRUCT struct priv
// Description of this filter
const struct af_info af_info_volume = {
.info = "Volume control audio filter",
.name = "volume",
.open = af_open,
.priv_size = sizeof(struct priv),
.options = (const struct m_option[]) {
OPT_FLOATRANGE("volumedb", cfg_volume, 0, -200, 60),
OPT_FLAG("replaygain-track", rgain_track, 0),
OPT_FLAG("replaygain-album", rgain_album, 0),
OPT_FLOATRANGE("replaygain-preamp", rgain_preamp, 0, -15, 15),
OPT_FLAG("replaygain-clip", rgain_clip, 0),
OPT_FLOATRANGE("replaygain-fallback", replaygain_fallback, 0, -200, 60),
OPT_FLAG("softclip", soft, 0),
OPT_FLAG("s16", fast, 0),
OPT_FLAG("detach", detach, 0),
OPT_FLAG("warn", warn, 0, OPTDEF_INT(1)),
{0}
},
};
+1 -1
View File
@@ -20,7 +20,7 @@
#include <limits.h>
#include "common/common.h"
#include "audio/filter/af.h"
#include "format.h"
// number of bytes per sample, 0 if invalid/unknown
int af_fmt_to_bytes(int format)
+58 -13
View File
@@ -18,6 +18,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include "mpv_talloc.h"
@@ -26,7 +27,6 @@
#include "ao.h"
#include "internal.h"
#include "audio/format.h"
#include "audio/audio.h"
#include "options/options.h"
#include "options/m_config.h"
@@ -160,6 +160,7 @@ static struct ao *ao_alloc(bool probing, struct mpv_global *global,
ao->priv = m_config_group_from_desc(ao, ao->log, global, &desc, name);
if (!ao->priv)
goto error;
ao_set_gain(ao, 1.0f);
return ao;
error:
talloc_free(ao);
@@ -480,12 +481,12 @@ bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s,
// --- The following functions just return immutable information.
void ao_get_format(struct ao *ao, struct mp_audio *format)
void ao_get_format(struct ao *ao,
int *samplerate, int *format, struct mp_chmap *channels)
{
*format = (struct mp_audio){0};
mp_audio_set_format(format, ao->format);
mp_audio_set_channels(format, &ao->channels);
format->rate = ao->samplerate;
*samplerate = ao->samplerate;
*format = ao->format;
*channels = ao->channels;
}
const char *ao_get_name(struct ao *ao)
@@ -551,13 +552,6 @@ bool ao_hotplug_check_update(struct ao_hotplug *hp)
return false;
}
const char *ao_hotplug_get_detected_device(struct ao_hotplug *hp)
{
if (!hp || !hp->ao)
return NULL;
return hp->ao->detected_device;
}
// The return value is valid until the next call to this API.
struct ao_device_list *ao_hotplug_get_device_list(struct ao_hotplug *hp)
{
@@ -646,6 +640,57 @@ void ao_print_devices(struct mpv_global *global, struct mp_log *log)
ao_hotplug_destroy(hp);
}
void ao_set_gain(struct ao *ao, float gain)
{
atomic_store(&ao->gain, gain);
}
#define MUL_GAIN_i(d, num_samples, gain, low, center, high) \
for (int n = 0; n < (num_samples); n++) \
(d)[n] = MPCLAMP( \
((((int64_t)((d)[n]) - (center)) * (gain) + 128) >> 8) + (center), \
(low), (high))
#define MUL_GAIN_f(d, num_samples, gain) \
for (int n = 0; n < (num_samples); n++) \
(d)[n] = MPCLAMP(((d)[n]) * (gain), -1.0, 1.0)
static void process_plane(struct ao *ao, void *data, int num_samples)
{
float gain = atomic_load_explicit(&ao->gain, memory_order_relaxed);
int gi = lrint(256.0 * gain);
if (gi == 256)
return;
switch (af_fmt_from_planar(ao->format)) {
case AF_FORMAT_U8:
MUL_GAIN_i((uint8_t *)data, num_samples, gi, 0, 128, 255);
break;
case AF_FORMAT_S16:
MUL_GAIN_i((int16_t *)data, num_samples, gi, INT16_MIN, 0, INT16_MAX);
break;
case AF_FORMAT_S32:
MUL_GAIN_i((int32_t *)data, num_samples, gi, INT32_MIN, 0, INT32_MAX);
break;
case AF_FORMAT_FLOAT:
MUL_GAIN_f((float *)data, num_samples, gain);
break;
case AF_FORMAT_DOUBLE:
MUL_GAIN_f((double *)data, num_samples, gain);
break;
default:;
// all other sample formats are simply not supported
}
}
void ao_post_process_data(struct ao *ao, void **data, int num_samples)
{
bool planar = af_fmt_is_planar(ao->format);
int planes = planar ? ao->channels.num : 1;
int plane_samples = num_samples * (planar ? 1: ao->channels.num);
for (int n = 0; n < planes; n++)
process_plane(ao, data[n], plane_samples);
}
static int get_conv_type(struct ao_convert_fmt *fmt)
{
if (af_fmt_to_bytes(fmt->src_fmt) * 8 == fmt->dst_bits && !fmt->pad_msb)
+3 -3
View File
@@ -81,7 +81,6 @@ struct ao;
struct mpv_global;
struct input_ctx;
struct encode_lavc_context;
struct mp_audio;
struct ao *ao_init_best(struct mpv_global *global,
int init_flags,
@@ -89,12 +88,14 @@ struct ao *ao_init_best(struct mpv_global *global,
struct encode_lavc_context *encode_lavc_ctx,
int samplerate, int format, struct mp_chmap channels);
void ao_uninit(struct ao *ao);
void ao_get_format(struct ao *ao, struct mp_audio *format);
void ao_get_format(struct ao *ao,
int *samplerate, int *format, struct mp_chmap *channels);
const char *ao_get_name(struct ao *ao);
const char *ao_get_description(struct ao *ao);
bool ao_untimed(struct ao *ao);
int ao_play(struct ao *ao, void **data, int samples, int flags);
int ao_control(struct ao *ao, enum aocontrol cmd, void *arg);
void ao_set_gain(struct ao *ao, float gain);
double ao_get_delay(struct ao *ao);
int ao_get_space(struct ao *ao);
void ao_reset(struct ao *ao);
@@ -112,7 +113,6 @@ struct ao_hotplug *ao_hotplug_create(struct mpv_global *global,
void *wakeup_ctx);
void ao_hotplug_destroy(struct ao_hotplug *hp);
bool ao_hotplug_check_update(struct ao_hotplug *hp);
const char *ao_hotplug_get_detected_device(struct ao_hotplug *hp);
struct ao_device_list *ao_hotplug_get_device_list(struct ao_hotplug *hp);
void ao_print_devices(struct mpv_global *global, struct mp_log *log);
+16 -25
View File
@@ -12,18 +12,18 @@
*
* 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 free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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.
* GNU Lesser 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/>.
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
@@ -182,15 +182,13 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
ao_control_vol_t *vol = arg;
set_vol = vol->left / f_multi + pmin + 0.5;
err = snd_mixer_selem_set_playback_volume
(elem, SND_MIXER_SCHN_FRONT_LEFT, set_vol);
err = snd_mixer_selem_set_playback_volume(elem, 0, set_vol);
CHECK_ALSA_ERROR("Error setting left channel");
MP_DBG(ao, "left=%li, ", set_vol);
set_vol = vol->right / f_multi + pmin + 0.5;
err = snd_mixer_selem_set_playback_volume
(elem, SND_MIXER_SCHN_FRONT_RIGHT, set_vol);
err = snd_mixer_selem_set_playback_volume(elem, 1, set_vol);
CHECK_ALSA_ERROR("Error setting right channel");
MP_DBG(ao, "right=%li, pmin=%li, pmax=%li, mult=%f\n",
set_vol, pmin, pmax, f_multi);
@@ -198,11 +196,9 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
}
case AOCONTROL_GET_VOLUME: {
ao_control_vol_t *vol = arg;
snd_mixer_selem_get_playback_volume
(elem, SND_MIXER_SCHN_FRONT_LEFT, &get_vol);
snd_mixer_selem_get_playback_volume(elem, 0, &get_vol);
vol->left = (get_vol - pmin) * f_multi;
snd_mixer_selem_get_playback_volume
(elem, SND_MIXER_SCHN_FRONT_RIGHT, &get_vol);
snd_mixer_selem_get_playback_volume(elem, 1, &get_vol);
vol->right = (get_vol - pmin) * f_multi;
MP_DBG(ao, "left=%f, right=%f\n", vol->left, vol->right);
break;
@@ -212,11 +208,9 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
if (!snd_mixer_selem_has_playback_switch(elem))
goto alsa_error;
if (!snd_mixer_selem_has_playback_switch_joined(elem)) {
snd_mixer_selem_set_playback_switch
(elem, SND_MIXER_SCHN_FRONT_RIGHT, !*mute);
snd_mixer_selem_set_playback_switch(elem, 1, !*mute);
}
snd_mixer_selem_set_playback_switch
(elem, SND_MIXER_SCHN_FRONT_LEFT, !*mute);
snd_mixer_selem_set_playback_switch(elem, 0, !*mute);
break;
}
case AOCONTROL_GET_MUTE: {
@@ -224,12 +218,10 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
if (!snd_mixer_selem_has_playback_switch(elem))
goto alsa_error;
int tmp = 1;
snd_mixer_selem_get_playback_switch
(elem, SND_MIXER_SCHN_FRONT_LEFT, &tmp);
snd_mixer_selem_get_playback_switch(elem, 0, &tmp);
*mute = !tmp;
if (!snd_mixer_selem_has_playback_switch_joined(elem)) {
snd_mixer_selem_get_playback_switch
(elem, SND_MIXER_SCHN_FRONT_RIGHT, &tmp);
snd_mixer_selem_get_playback_switch(elem, 1, &tmp);
*mute &= !tmp;
}
break;
@@ -1098,10 +1090,9 @@ static int play(struct ao *ao, void **data, int samples, int flags)
if (samples == 0)
return 0;
ao_convert_inplace(&p->convert, data, samples);
do {
ao_convert_inplace(&p->convert, data, samples);
if (af_fmt_is_planar(ao->format)) {
res = snd_pcm_writen(p->alsa, data, samples);
} else {
+4
View File
@@ -40,6 +40,10 @@
#include <jack/jack.h>
#if !HAVE_GPL
#error GPL only
#endif
struct jack_opts {
char *port;
char *client_name;
+7 -2
View File
@@ -49,6 +49,10 @@
#include "ao.h"
#include "internal.h"
#if !HAVE_GPL
#error GPL only
#endif
// Define to 0 if the device must be reopened to reset it (stop all playback,
// clear the buffer), and the device should be closed when unused.
// Define to 1 if SNDCTL_DSP_RESET should be used to reset without close.
@@ -387,8 +391,9 @@ static int reopen_device(struct ao *ao, bool allow_format_changes)
}
}
ao->period_size = channels.num * af_fmt_to_bytes(format);
p->outburst -= p->outburst % ao->period_size; // round down
int sstride = channels.num * af_fmt_to_bytes(format);
p->outburst -= p->outburst % sstride; // round down
ao->period_size = p->outburst / sstride;
return 0;
+3
View File
@@ -64,6 +64,9 @@ static int init(struct ao *ao)
if (rsd_init(&priv->rd) < 0)
return -1;
if (ao->device)
rsd_set_param(priv->rd, RSD_HOST, ao->device);
// Actual channel layout unknown.
struct mp_chmap_sel sel = {0};
mp_chmap_sel_add_waveext_def(&sel);
+4 -4
View File
@@ -201,9 +201,9 @@ static DWORD __stdcall AudioThread(void *lpParameter)
mpthread_set_name("wasapi event");
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
state->init_ret = wasapi_thread_init(ao);
state->init_ok = wasapi_thread_init(ao);
SetEvent(state->hInitDone);
if (FAILED(state->init_ret))
if (!state->init_ok)
goto exit_label;
MP_DBG(ao, "Entering dispatch loop\n");
@@ -302,7 +302,7 @@ static int init(struct ao *ao)
state->dispatch = mp_dispatch_create(state);
mp_dispatch_set_wakeup_fn(state->dispatch, thread_wakeup, ao);
state->init_ret = E_FAIL;
state->init_ok = false;
state->hAudioThread = CreateThread(NULL, 0, &AudioThread, ao, 0, NULL);
if (!state->hAudioThread) {
MP_FATAL(ao, "Failed to create audio thread\n");
@@ -312,7 +312,7 @@ static int init(struct ao *ao)
WaitForSingleObject(state->hInitDone, INFINITE); // wait on init complete
SAFE_DESTROY(state->hInitDone,CloseHandle(state->hInitDone));
if (FAILED(state->init_ret)) {
if (!state->init_ok) {
if (!ao->probing)
MP_FATAL(ao, "Received failure from audio thread\n");
uninit(ao);
+6 -14
View File
@@ -45,15 +45,6 @@ typedef struct change_notify {
HRESULT wasapi_change_init(struct ao* ao, bool is_hotplug);
void wasapi_change_uninit(struct ao* ao);
#define EXIT_ON_ERROR(hres) \
do { if (FAILED(hres)) { goto exit_label; } } while(0)
#define SAFE_DESTROY(unk, release) \
do { if ((unk) != NULL) { release; (unk) = NULL; } } while(0)
#define mp_format_res_str(hres) \
(SUCCEEDED(hres) ? "ok" : ((hres) == AUDCLNT_E_UNSUPPORTED_FORMAT) \
? "unsupported" : mp_HRESULT_to_str(hres))
enum wasapi_thread_state {
WASAPI_THREAD_FEED = 0,
WASAPI_THREAD_RESUME,
@@ -64,8 +55,8 @@ enum wasapi_thread_state {
typedef struct wasapi_state {
struct mp_log *log;
bool init_ok; // status of init phase
// Thread handles
HRESULT init_ret; // status of init phase
HANDLE hInitDone; // set when init is complete in audio thread
HANDLE hAudioThread; // the audio thread itself
HANDLE hWake; // thread wakeup event
@@ -113,11 +104,12 @@ void wasapi_list_devs(struct ao *ao, struct ao_device_list *list);
bstr wasapi_get_specified_device_string(struct ao *ao);
LPWSTR wasapi_find_deviceID(struct ao *ao);
void wasapi_dispatch(struct ao *ao);
HRESULT wasapi_thread_init(struct ao *ao);
bool wasapi_thread_init(struct ao *ao);
void wasapi_thread_uninit(struct ao *ao);
void wasapi_receive_proxies(wasapi_state *state);
void wasapi_release_proxies(wasapi_state *state);
#define EXIT_ON_ERROR(hres) \
do { if (FAILED(hres)) { goto exit_label; } } while(0)
#define SAFE_DESTROY(unk, release) \
do { if ((unk) != NULL) { release; (unk) = NULL; } } while(0)
#endif
+130 -155
View File
@@ -81,7 +81,7 @@ static const struct wasapi_sample_fmt wasapi_formats[] = {
{AF_FORMAT_S32, 32, 32, &KSDATAFORMAT_SUBTYPE_PCM},
// compatible, assume LSBs are ignored
{AF_FORMAT_S32, 32, 24, &KSDATAFORMAT_SUBTYPE_PCM},
// aka S24 (with conversion) - untested, thus commented.
// aka S24 (with conversion on output)
{AF_FORMAT_S32, 24, 24, &KSDATAFORMAT_SUBTYPE_PCM},
{AF_FORMAT_FLOAT, 32, 32, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT},
{AF_FORMAT_S_AC3, 16, 16, &mp_KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL},
@@ -94,6 +94,20 @@ static const struct wasapi_sample_fmt wasapi_formats[] = {
{0},
};
static void wasapi_get_best_sample_formats(
int src_format, struct wasapi_sample_fmt *out_formats)
{
int mp_formats[AF_FORMAT_COUNT];
af_get_best_sample_formats(src_format, mp_formats);
for (int n = 0; mp_formats[n]; n++) {
for (int i = 0; wasapi_formats[i].mp_format; i++) {
if (wasapi_formats[i].mp_format == mp_formats[n])
*out_formats++ = wasapi_formats[i];
}
}
*out_formats = (struct wasapi_sample_fmt) {0};
}
static const GUID *format_to_subtype(int format)
{
for (int i = 0; wasapi_formats[i].mp_format; i++) {
@@ -103,18 +117,6 @@ static const GUID *format_to_subtype(int format)
return &KSDATAFORMAT_SPECIFIER_NONE;
}
// "solve" the under-determined inverse of format_to_subtype by assuming the
// input subtype is "special" (i.e. IEC61937)
static int special_subtype_to_format(const GUID *subtype)
{
for (int i = 0; wasapi_formats[i].mp_format; i++) {
if (IsEqualGUID(subtype, wasapi_formats[i].subtype) &&
af_fmt_is_spdif(wasapi_formats[i].mp_format))
return wasapi_formats[i].mp_format;
}
return 0;
}
char *mp_PKEY_to_str_buf(char *buf, size_t buf_size, const PROPERTYKEY *pkey)
{
buf = mp_GUID_to_str_buf(buf, buf_size, &pkey->fmtid);
@@ -132,54 +134,21 @@ static void update_waveformat_datarate(WAVEFORMATEXTENSIBLE *wformat)
}
static void set_waveformat(WAVEFORMATEXTENSIBLE *wformat,
struct wasapi_sample_fmt format,
struct wasapi_sample_fmt *format,
DWORD samplerate, struct mp_chmap *channels)
{
wformat->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
wformat->Format.nChannels = channels->num;
wformat->Format.nSamplesPerSec = samplerate;
wformat->Format.wBitsPerSample = format.bits;
wformat->Format.wBitsPerSample = format->bits;
wformat->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
wformat->SubFormat = *format_to_subtype(format.mp_format);
wformat->Samples.wValidBitsPerSample = format.used_msb;
wformat->SubFormat = *format_to_subtype(format->mp_format);
wformat->Samples.wValidBitsPerSample = format->used_msb;
wformat->dwChannelMask = mp_chmap_to_waveext(channels);
update_waveformat_datarate(wformat);
}
// This implicitly transforms all pcm formats to: interleaved / signed (except
// 8-bit is unsigned) / waveext channel order. "Special" formats should be
// exempt as they should already satisfy these properties.
static void set_waveformat_with_ao(WAVEFORMATEXTENSIBLE *wformat, struct ao *ao)
{
struct mp_chmap channels = ao->channels;
if (mp_chmap_is_unknown(&channels))
mp_chmap_from_channels(&channels, channels.num);
mp_chmap_reorder_to_waveext(&channels);
if (!mp_chmap_is_valid(&channels))
mp_chmap_from_channels(&channels, 2);
// First find a format that is actually representable.
// (Notably excludes AF_FORMAT_DOUBLE.)
struct wasapi_sample_fmt format =
{AF_FORMAT_S16, 16, 16, &KSDATAFORMAT_SUBTYPE_PCM};
int alt_formats[AF_FORMAT_COUNT];
af_get_best_sample_formats(ao->format, alt_formats);
for (int n = 0; alt_formats[n]; n++) {
for (int i = 0; wasapi_formats[i].mp_format; i++) {
if (wasapi_formats[i].mp_format == alt_formats[n]) {
format = wasapi_formats[i];
goto found_format;
}
}
}
found_format:
set_waveformat(wformat, format, ao->samplerate, &channels);
}
// other wformat parameters must already be set with set_waveformat
static void change_waveformat_samplerate(WAVEFORMATEXTENSIBLE *wformat,
DWORD samplerate)
@@ -319,9 +288,20 @@ static bool set_ao_format(struct ao *ao, WAVEFORMATEX *wf,
}
waveformat_copy(&state->format, wf);
state->share_mode = share_mode;
MP_VERBOSE(ao, "Accepted as %s %s @ %dhz -> %s (%s)\n",
mp_chmap_to_str(&ao->channels),
af_fmt_to_str(ao->format), ao->samplerate,
waveformat_to_str(wf),
state->share_mode == AUDCLNT_SHAREMODE_EXCLUSIVE
? "exclusive" : "shared");
return true;
}
#define mp_format_res_str(hres) \
(SUCCEEDED(hres) ? "ok" : ((hres) == AUDCLNT_E_UNSUPPORTED_FORMAT) \
? "unsupported" : mp_HRESULT_to_str(hres))
static bool try_format_exclusive(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat)
{
struct wasapi_state *state = ao->priv;
@@ -333,36 +313,15 @@ static bool try_format_exclusive(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat)
return SUCCEEDED(hr);
}
// This works like try_format_exclusive(), but will try to fallback to the AC3
// format if the format is a non-AC3 passthrough format. *wformat will be
// adjusted accordingly.
static bool try_format_exclusive_with_spdif_fallback(struct ao *ao,
WAVEFORMATEXTENSIBLE *wformat)
{
if (try_format_exclusive(ao, wformat))
return true;
int special_format = special_subtype_to_format(&wformat->SubFormat);
if (special_format && special_format != AF_FORMAT_S_AC3) {
MP_VERBOSE(ao, "Retrying as AC3.\n");
wformat->SubFormat = *format_to_subtype(AF_FORMAT_S_AC3);
return try_format_exclusive(ao, wformat);
}
return false;
}
static bool search_sample_formats(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat,
int samplerate, struct mp_chmap *channels)
{
int alt_formats[AF_FORMAT_COUNT];
af_get_best_sample_formats(ao->format, alt_formats);
for (int n = 0; alt_formats[n]; n++) {
for (int i = 0; wasapi_formats[i].mp_format; i++) {
if (wasapi_formats[i].mp_format == alt_formats[n]) {
set_waveformat(wformat, wasapi_formats[i], samplerate, channels);
if (try_format_exclusive(ao, wformat))
return true;
}
}
struct wasapi_sample_fmt alt_formats[MP_ARRAY_SIZE(wasapi_formats)];
wasapi_get_best_sample_formats(ao->format, alt_formats);
for (int n = 0; alt_formats[n].mp_format; n++) {
set_waveformat(wformat, &alt_formats[n], samplerate, channels);
if (try_format_exclusive(ao, wformat))
return true;
}
wformat->Format.wBitsPerSample = 0;
@@ -441,40 +400,39 @@ static bool search_channels(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat)
return false;
}
static bool find_formats_exclusive(struct ao *ao, bool do_search)
static bool find_formats_exclusive(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat)
{
WAVEFORMATEXTENSIBLE wformat;
set_waveformat_with_ao(&wformat, ao);
// Try the specified format as is
if (try_format_exclusive(ao, wformat))
return true;
// Try the requested format as is. If that doesn't work, and the do_search
// argument is set, do the pcm format search.
if (!try_format_exclusive_with_spdif_fallback(ao, &wformat) &&
(!do_search || !search_channels(ao, &wformat)))
if (af_fmt_is_spdif(ao->format)) {
if (ao->format != AF_FORMAT_S_AC3) {
// If the requested format failed and it is passthrough, but not
// AC3, try lying and saying it is.
MP_VERBOSE(ao, "Retrying as AC3.\n");
wformat->SubFormat = *format_to_subtype(AF_FORMAT_S_AC3);
if (try_format_exclusive(ao, wformat))
return true;
}
return false;
}
if (!set_ao_format(ao, &wformat.Format, AUDCLNT_SHAREMODE_EXCLUSIVE))
return false;
MP_VERBOSE(ao, "Accepted as %s %s @ %dhz (exclusive) -> %s\n",
mp_chmap_to_str(&ao->channels),
af_fmt_to_str(ao->format), ao->samplerate,
waveformat_to_str(&wformat.Format));
return true;
// Fallback on the PCM format search
return search_channels(ao, wformat);
}
static bool find_formats_shared(struct ao *ao)
static bool find_formats_shared(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat)
{
struct wasapi_state *state = ao->priv;
WAVEFORMATEXTENSIBLE wformat;
set_waveformat_with_ao(&wformat, ao);
WAVEFORMATEX *closestMatch;
HRESULT hr = IAudioClient_IsFormatSupported(state->pAudioClient,
AUDCLNT_SHAREMODE_SHARED,
&wformat.Format, &closestMatch);
&wformat->Format,
&closestMatch);
MP_VERBOSE(ao, "Trying %s (shared) -> %s\n",
waveformat_to_str(&wformat.Format), mp_format_res_str(hr));
waveformat_to_str(&wformat->Format), mp_format_res_str(hr));
if (hr != AUDCLNT_E_UNSUPPORTED_FORMAT)
EXIT_ON_ERROR(hr);
@@ -482,27 +440,20 @@ static bool find_formats_shared(struct ao *ao)
case S_OK:
break;
case S_FALSE:
waveformat_copy(&wformat, closestMatch);
waveformat_copy(wformat, closestMatch);
CoTaskMemFree(closestMatch);
MP_VERBOSE(ao, "Closest match is %s\n",
waveformat_to_str(&wformat.Format));
waveformat_to_str(&wformat->Format));
break;
default:
hr = IAudioClient_GetMixFormat(state->pAudioClient, &closestMatch);
EXIT_ON_ERROR(hr);
waveformat_copy(&wformat, closestMatch);
waveformat_copy(wformat, closestMatch);
MP_VERBOSE(ao, "Fallback to mix format %s\n",
waveformat_to_str(&wformat.Format));
waveformat_to_str(&wformat->Format));
CoTaskMemFree(closestMatch);
}
if (!set_ao_format(ao, &wformat.Format, AUDCLNT_SHAREMODE_SHARED))
return false;
MP_VERBOSE(ao, "Accepted as %s %s @ %dhz (shared) -> %s\n",
mp_chmap_to_str(&ao->channels),
af_fmt_to_str(ao->format), ao->samplerate,
waveformat_to_str(&wformat.Format));
return true;
exit_label:
MP_ERR(state, "Error finding shared mode format: %s\n",
@@ -513,22 +464,36 @@ exit_label:
static bool find_formats(struct ao *ao)
{
struct wasapi_state *state = ao->priv;
struct mp_chmap channels = ao->channels;
if (state->opt_exclusive) {
// If exclusive is requested, try the requested format (which
// might be passthrough). If that fails, do a pcm format
// search.
return find_formats_exclusive(ao, true);
} else if (af_fmt_is_spdif(ao->format)) {
// If a passthrough format is requested, but exclusive mode
// was not explicitly set, try only the requested passthrough
// format in exclusive mode. Fall back on shared mode if that
// fails without doing the exclusive pcm format search.
if (find_formats_exclusive(ao, false))
return true;
if (mp_chmap_is_unknown(&channels))
mp_chmap_from_channels(&channels, channels.num);
mp_chmap_reorder_to_waveext(&channels);
if (!mp_chmap_is_valid(&channels))
mp_chmap_from_channels(&channels, 2);
struct wasapi_sample_fmt alt_formats[MP_ARRAY_SIZE(wasapi_formats)];
wasapi_get_best_sample_formats(ao->format, alt_formats);
struct wasapi_sample_fmt wasapi_format =
{AF_FORMAT_S16, 16, 16, &KSDATAFORMAT_SUBTYPE_PCM};;
if (alt_formats[0].mp_format)
wasapi_format = alt_formats[0];
AUDCLNT_SHAREMODE share_mode;
WAVEFORMATEXTENSIBLE wformat;
set_waveformat(&wformat, &wasapi_format, ao->samplerate, &channels);
if (state->opt_exclusive || af_fmt_is_spdif(ao->format)) {
share_mode = AUDCLNT_SHAREMODE_EXCLUSIVE;
if(!find_formats_exclusive(ao, &wformat))
return false;
} else {
share_mode = AUDCLNT_SHAREMODE_SHARED;
if(!find_formats_shared(ao, &wformat))
return false;
}
// Default is to use shared mode
return find_formats_shared(ao);
return set_ao_format(ao, &wformat.Format, share_mode);
}
static HRESULT init_clock(struct wasapi_state *state) {
@@ -833,7 +798,7 @@ exit_label:
destroy_enumerator(enumerator);
}
static HRESULT load_device(struct mp_log *l,
static bool load_device(struct mp_log *l,
IMMDevice **ppDevice, LPWSTR deviceID)
{
IMMDeviceEnumerator *pEnumerator = NULL;
@@ -849,7 +814,7 @@ exit_label:
if (FAILED(hr))
mp_err(l, "Error loading selected device: %s\n", mp_HRESULT_to_str(hr));
SAFE_RELEASE(pEnumerator);
return hr;
return SUCCEEDED(hr);
}
static LPWSTR select_device(struct mp_log *l, struct device_desc *d)
@@ -934,7 +899,7 @@ exit_label:
return deviceID;
}
HRESULT wasapi_thread_init(struct ao *ao)
bool wasapi_thread_init(struct ao *ao)
{
struct wasapi_state *state = ao->priv;
MP_DBG(ao, "Init wasapi thread\n");
@@ -946,14 +911,18 @@ HRESULT wasapi_thread_init(struct ao *ao)
retry:
if (state->deviceID) {
hr = load_device(ao->log, &state->pDevice, state->deviceID);
EXIT_ON_ERROR(hr);
if (!load_device(ao->log, &state->pDevice, state->deviceID))
return false;
MP_DBG(ao, "Activating pAudioClient interface\n");
hr = IMMDeviceActivator_Activate(state->pDevice, &IID_IAudioClient,
CLSCTX_ALL, NULL,
(void **)&state->pAudioClient);
EXIT_ON_ERROR(hr);
if (FAILED(hr)) {
MP_FATAL(ao, "Error activating device: %s\n",
mp_HRESULT_to_str(hr));
return false;
}
} else {
MP_VERBOSE(ao, "Trying UWP wrapper.\n");
@@ -961,67 +930,73 @@ retry:
HANDLE lib = LoadLibraryW(L"wasapiuwp2.dll");
if (!lib) {
MP_ERR(ao, "Wrapper not found: %d\n", (int)GetLastError());
hr = E_FAIL;
EXIT_ON_ERROR(hr);
}
if (lib) {
wuCreateDefaultAudioRenderer =
(void*)GetProcAddress(lib, "wuCreateDefaultAudioRenderer");
return false;
}
wuCreateDefaultAudioRenderer =
(void*)GetProcAddress(lib, "wuCreateDefaultAudioRenderer");
if (!wuCreateDefaultAudioRenderer) {
MP_ERR(ao, "Function not found.\n");
hr = E_FAIL;
EXIT_ON_ERROR(hr);
return false;
}
IUnknown *res = NULL;
hr = wuCreateDefaultAudioRenderer(&res);
MP_VERBOSE(ao, "Device: %s %p\n", mp_HRESULT_to_str(hr), res);
EXIT_ON_ERROR(hr);
if (FAILED(hr)) {
MP_FATAL(ao, "Error activating device: %s\n",
mp_HRESULT_to_str(hr));
return false;
}
hr = IUnknown_QueryInterface(res, &IID_IAudioClient,
(void **)&state->pAudioClient);
IUnknown_Release(res);
EXIT_ON_ERROR(hr);
if (FAILED(hr)) {
MP_FATAL(ao, "Failed to get UWP audio client: %s\n",
mp_HRESULT_to_str(hr));
return false;
}
}
// In the event of an align hack, we've already done this.
if (!align_hack) {
MP_DBG(ao, "Probing formats\n");
if (!find_formats(ao)) {
hr = E_FAIL;
EXIT_ON_ERROR(hr);
}
if (!find_formats(ao))
return false;
}
MP_DBG(ao, "Fixing format\n");
hr = fix_format(ao, align_hack);
switch (hr) {
case AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED:
if (align_hack)
if (align_hack) {
MP_FATAL(ao, "Align hack failed\n");
break;
}
// According to MSDN, we must use this as base after the failure.
IAudioClient_GetBufferSize(state->pAudioClient,
&state->bufferFrameCount);
hr = IAudioClient_GetBufferSize(state->pAudioClient,
&state->bufferFrameCount);
if (FAILED(hr)) {
MP_FATAL(ao, "Error getting buffer size for align hack: %s\n",
mp_HRESULT_to_str(hr));
return false;
}
wasapi_thread_uninit(ao);
align_hack = true;
MP_WARN(ao, "This appears to require a weird Windows 7 hack. Retrying.\n");
goto retry;
case AUDCLNT_E_DEVICE_IN_USE:
case AUDCLNT_E_DEVICE_INVALIDATED:
if (retry_wait > 8)
break;
if (retry_wait > 8) {
MP_FATAL(ao, "Bad device retry failed\n");
return false;
}
wasapi_thread_uninit(ao);
MP_WARN(ao, "Retrying in %"PRId64" us\n", retry_wait);
mp_sleep_us(retry_wait);
retry_wait *= 2;
goto retry;
}
EXIT_ON_ERROR(hr);
MP_DBG(ao, "Init wasapi thread done\n");
return S_OK;
exit_label:
MP_FATAL(state, "Error setting up audio thread: %s\n", mp_HRESULT_to_str(hr));
return hr;
return SUCCEEDED(hr);
}
void wasapi_thread_uninit(struct ao *ao)
+5 -3
View File
@@ -61,9 +61,6 @@ struct ao {
// default device should be used, this is set to NULL.
char *device;
// Device actually chosen by the AO
char *detected_device;
// Application name to report to the audio API.
char *client_name;
@@ -73,6 +70,9 @@ struct ao {
// Internal events (use ao_request_reload(), ao_hotplug_event())
atomic_int events_;
// Float gain multiplicator
mp_atomic_float gain;
int buffer;
double def_buffer;
void *api_priv;
@@ -215,6 +215,8 @@ bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s,
void ao_device_list_add(struct ao_device_list *list, struct ao *ao,
struct ao_device_desc *e);
void ao_post_process_data(struct ao *ao, void **data, int num_samples);
struct ao_convert_fmt {
int src_fmt; // source AF_FORMAT_*
int channels; // number of channels
+3 -1
View File
@@ -179,6 +179,8 @@ end:
for (int n = 0; n < ao->num_planes; n++)
af_fill_silence((char *)data[n] + bytes, full_bytes - bytes, ao->format);
ao_post_process_data(ao, data, samples);
return bytes / ao->sstride;
}
@@ -190,7 +192,7 @@ int ao_read_data_converted(struct ao *ao, struct ao_convert_fmt *fmt,
assert(ao->api == &ao_api_pull);
struct ao_pull_state *p = ao->api_priv;
void *ndata[MP_NUM_CHANNELS];
void *ndata[MP_NUM_CHANNELS] = {0};
if (!ao_need_conversion(fmt))
return ao_read_data(ao, data, samples, out_time_us);
+45 -47
View File
@@ -37,7 +37,6 @@
#include "osdep/timer.h"
#include "osdep/atomic.h"
#include "audio/audio.h"
#include "audio/audio_buffer.h"
struct ao_push_state {
@@ -49,7 +48,8 @@ struct ao_push_state {
struct mp_audio_buffer *buffer;
struct mp_audio *silence;
uint8_t *silence[MP_NUM_CHANNELS];
int silence_samples;
bool terminate;
bool wait_on_ao;
@@ -237,12 +237,7 @@ static int play(struct ao *ao, void **data, int samples, int flags)
flags = flags & ~AOPLAY_FINAL_CHUNK;
bool is_final = flags & AOPLAY_FINAL_CHUNK;
struct mp_audio audio;
mp_audio_buffer_get_format(p->buffer, &audio);
for (int n = 0; n < ao->num_planes; n++)
audio.planes[n] = data[n];
audio.samples = write_samples;
mp_audio_buffer_append(p->buffer, &audio);
mp_audio_buffer_append(p->buffer, data, samples);
bool got_data = write_samples > 0 || p->paused || p->final_chunk != is_final;
@@ -260,22 +255,26 @@ static int play(struct ao *ao, void **data, int samples, int flags)
return write_samples;
}
static void ao_get_silence(struct ao *ao, struct mp_audio *data, int size)
static bool realloc_silence(struct ao *ao, int samples)
{
struct ao_push_state *p = ao->api_priv;
if (!p->silence) {
p->silence = talloc_zero(p, struct mp_audio);
mp_audio_set_format(p->silence, ao->format);
mp_audio_set_channels(p->silence, &ao->channels);
p->silence->rate = ao->samplerate;
if (samples <= 0 || !af_fmt_is_pcm(ao->format))
return false;
if (samples > p->silence_samples) {
talloc_free(p->silence[0]);
int bytes = af_fmt_to_bytes(ao->format) * samples * ao->channels.num;
p->silence[0] = talloc_size(p, bytes);
for (int n = 1; n < MP_NUM_CHANNELS; n++)
p->silence[n] = p->silence[0];
p->silence_samples = samples;
af_fill_silence(p->silence[0], bytes, ao->format);
}
if (p->silence->samples < size) {
mp_audio_realloc_min(p->silence, size);
p->silence->samples = size;
mp_audio_fill_silence(p->silence, 0, size);
}
*data = *p->silence;
data->samples = size;
return true;
}
// called locked
@@ -287,39 +286,42 @@ static void ao_play_data(struct ao *ao)
space = MPMAX(space, 0);
if (space % ao->period_size)
MP_ERR(ao, "Audio device reports unaligned available buffer size.\n");
struct mp_audio data;
uint8_t **planes;
int samples;
if (play_silence) {
ao_get_silence(ao, &data, space);
planes = p->silence;
samples = realloc_silence(ao, space) ? space : 0;
} else {
mp_audio_buffer_peek(p->buffer, &data);
mp_audio_buffer_peek(p->buffer, &planes, &samples);
}
int max = data.samples;
if (data.samples > space)
data.samples = space;
int max = samples;
if (samples > space)
samples = space;
int flags = 0;
if (p->final_chunk && data.samples == max) {
if (p->final_chunk && samples == max) {
flags |= AOPLAY_FINAL_CHUNK;
} else {
data.samples = data.samples / ao->period_size * ao->period_size;
samples = samples / ao->period_size * ao->period_size;
}
MP_STATS(ao, "start ao fill");
ao_post_process_data(ao, (void **)planes, samples);
int r = 0;
if (data.samples)
r = ao->driver->play(ao, data.planes, data.samples, flags);
if (samples)
r = ao->driver->play(ao, (void **)planes, samples, flags);
MP_STATS(ao, "end ao fill");
if (r > data.samples) {
MP_ERR(ao, "Audio device returned non-sense value.\n");
r = data.samples;
if (r > samples) {
MP_ERR(ao, "Audio device returned nonsense value.\n");
r = samples;
} else if (r < 0) {
MP_ERR(ao, "Error writing audio to device.\n");
} else if (r != data.samples) {
} else if (r != samples) {
MP_ERR(ao, "Audio device returned broken buffer state (sent %d samples, "
"got %d samples, %d period%s)!\n", data.samples, r,
"got %d samples, %d period%s)!\n", samples, r,
ao->period_size, flags & AOPLAY_FINAL_CHUNK ? " final" : "");
}
r = MPMAX(r, 0);
// Probably can't copy the rest of the buffer due to period alignment.
bool stuck_eof = r <= 0 && space >= max && data.samples > 0;
bool stuck_eof = r <= 0 && space >= max && samples > 0;
if ((flags & AOPLAY_FINAL_CHUNK) && stuck_eof) {
MP_ERR(ao, "Audio output driver seems to ignore AOPLAY_FINAL_CHUNK.\n");
r = max;
@@ -491,17 +493,13 @@ const struct ao_driver ao_api_push = {
int ao_play_silence(struct ao *ao, int samples)
{
assert(ao->api == &ao_api_push);
if (samples <= 0 || !af_fmt_is_pcm(ao->format) || !ao->driver->play)
struct ao_push_state *p = ao->api_priv;
if (!realloc_silence(ao, samples) || !ao->driver->play)
return 0;
int bytes = af_fmt_to_bytes(ao->format) * samples * ao->channels.num;
char *p = talloc_size(NULL, bytes);
af_fill_silence(p, bytes, ao->format);
void *tmp[MP_NUM_CHANNELS];
for (int n = 0; n < MP_NUM_CHANNELS; n++)
tmp[n] = p;
int r = ao->driver->play(ao, tmp, samples, 0);
talloc_free(p);
return r;
return ao->driver->play(ao, (void **)p->silence, samples, 0);
}
#ifndef __MINGW32__
+49 -6
View File
@@ -217,11 +217,6 @@ void mp_set_avcodec_threads(struct mp_log *l, AVCodecContext *avctx, int threads
avctx->thread_count = threads;
}
static bool is_crap(AVCodec *codec)
{
return !!strstr(codec->name, "_vdpau");
}
void mp_add_lavc_decoders(struct mp_decoder_list *list, enum AVMediaType type)
{
AVCodec *cur = NULL;
@@ -229,7 +224,7 @@ void mp_add_lavc_decoders(struct mp_decoder_list *list, enum AVMediaType type)
cur = av_codec_next(cur);
if (!cur)
break;
if (av_codec_is_decoder(cur) && cur->type == type && !is_crap(cur)) {
if (av_codec_is_decoder(cur) && cur->type == type) {
mp_add_decoder(list, "lavc", mp_codec_from_av_codec_id(cur->id),
cur->name, cur->long_name);
}
@@ -352,3 +347,51 @@ int mp_set_avopts(struct mp_log *log, void *avobj, char **kv)
}
return success;
}
#if LIBAVUTIL_VERSION_MICRO >= 100
AVFrameSideData *ffmpeg_garbage(AVFrame *frame,
enum AVFrameSideDataType type,
AVBufferRef *buf)
{
AVFrameSideData *ret, **tmp;
if (!buf)
return NULL;
if (frame->nb_side_data > INT_MAX / sizeof(*frame->side_data) - 1)
goto fail;
tmp = av_realloc(frame->side_data,
(frame->nb_side_data + 1) * sizeof(*frame->side_data));
if (!tmp)
goto fail;
frame->side_data = tmp;
ret = av_mallocz(sizeof(*ret));
if (!ret)
goto fail;
ret->buf = buf;
ret->data = ret->buf->data;
ret->size = buf->size;
ret->type = type;
frame->side_data[frame->nb_side_data++] = ret;
return ret;
fail:
av_buffer_unref(&buf);
return NULL;
}
#else
AVFrameSideData *ffmpeg_garbage(AVFrame *frame,
enum AVFrameSideDataType type,
AVBufferRef *buf)
{
AVFrameSideData *sd = av_frame_new_side_data(frame, type, buf->size);
if (sd)
memcpy(sd->data, buf->data, buf->size);
av_buffer_unref(&buf);
return sd;
}
#endif
+3
View File
@@ -46,5 +46,8 @@ const char *mp_codec_from_av_codec_id(int codec_id);
void mp_set_avdict(struct AVDictionary **dict, char **kv);
void mp_avdict_print_unset(struct mp_log *log, int msgl, struct AVDictionary *d);
int mp_set_avopts(struct mp_log *log, void *avobj, char **kv);
AVFrameSideData *ffmpeg_garbage(AVFrame *frame,
enum AVFrameSideDataType type,
AVBufferRef *buf);
#endif
+13 -17
View File
@@ -5,20 +5,18 @@
*
* 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 free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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.
* GNU Lesser 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/>.
*
* Almost LGPL.
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
@@ -44,10 +42,9 @@
#include <libavdevice/avdevice.h>
#endif
#if HAVE_IS_LIBAV
#if HAVE_LIBAV
#include <libavresample/avresample.h>
#endif
#if HAVE_IS_FFMPEG
#else
#include <libswresample/swresample.h>
#endif
@@ -67,9 +64,9 @@ static bool log_print_prefix = true;
static int av_log_level_to_mp_level(int av_level)
{
if (av_level > AV_LOG_VERBOSE)
return MSGL_DEBUG;
return MSGL_TRACE;
if (av_level > AV_LOG_INFO)
return MSGL_V;
return MSGL_DEBUG;
if (av_level > AV_LOG_WARNING)
return MSGL_V;
if (av_level > AV_LOG_ERROR)
@@ -199,10 +196,9 @@ bool print_libav_versions(struct mp_log *log, int v)
{"libavformat", LIBAVFORMAT_VERSION_INT, avformat_version()},
{"libswscale", LIBSWSCALE_VERSION_INT, swscale_version()},
{"libavfilter", LIBAVFILTER_VERSION_INT, avfilter_version()},
#if HAVE_IS_LIBAV
#if HAVE_LIBAV
{"libavresample", LIBAVRESAMPLE_VERSION_INT, avresample_version()},
#endif
#if HAVE_IS_FFMPEG
#else
{"libswresample", LIBSWRESAMPLE_VERSION_INT, swresample_version()},
#endif
};
+15
View File
@@ -115,6 +115,12 @@ bool mp_rect_intersection(struct mp_rect *rc, const struct mp_rect *rc2)
return rc->x1 > rc->x0 && rc->y1 > rc->y0;
}
bool mp_rect_equals(struct mp_rect *rc1, struct mp_rect *rc2)
{
return rc1->x0 == rc2->x0 && rc1->y0 == rc2->y0 &&
rc1->x1 == rc2->x1 && rc1->y1 == rc2->y1;
}
// This works like snprintf(), except that it starts writing the first output
// character to str[strlen(str)]. This returns the number of characters the
// string would have *appended* assuming a large enough buffer, will make sure
@@ -287,3 +293,12 @@ char *mp_tag_str_buf(char *buf, size_t buf_size, uint32_t tag)
}
return buf;
}
char *mp_tprintf_buf(char *buf, size_t buf_size, const char *format, ...)
{
va_list ap;
va_start(ap, format);
vsnprintf(buf, buf_size, format, ap);
va_end(ap);
return buf;
}
+14 -4
View File
@@ -59,10 +59,11 @@ enum stream_type {
};
enum {
DATA_OK = 1,
DATA_WAIT = 0,
DATA_AGAIN = -1,
DATA_EOF = -2,
DATA_OK = 1, // data is actually being returned
DATA_WAIT = 0, // async wait: check state again after next wakeup
DATA_AGAIN = -2, // repeat request (internal progress was made)
DATA_STARVE = -1, // need input (might require to drain other outputs)
DATA_EOF = -3, // no more data available
};
extern const char mpv_version[];
@@ -82,6 +83,7 @@ struct mp_rect {
void mp_rect_union(struct mp_rect *rc, const struct mp_rect *src);
bool mp_rect_intersection(struct mp_rect *rc, const struct mp_rect *rc2);
bool mp_rect_contains(struct mp_rect *rc, int x, int y);
bool mp_rect_equals(struct mp_rect *rc1, struct mp_rect *rc2);
int mp_snprintf_cat(char *str, size_t size, const char *format, ...)
PRINTF_ATTRIBUTE(3, 4);
@@ -101,4 +103,12 @@ char *mp_strerror_buf(char *buf, size_t buf_size, int errnum);
char *mp_tag_str_buf(char *buf, size_t buf_size, uint32_t tag);
#define mp_tag_str(t) mp_tag_str_buf((char[22]){0}, 22, t)
// Return a printf(format, ...) formatted string of the given SIZE. SIZE must
// be a compile time constant. The result is allocated on the stack and valid
// only within the current block scope.
#define mp_tprintf(SIZE, format, ...) \
mp_tprintf_buf((char[SIZE]){0}, (SIZE), (format), __VA_ARGS__)
char *mp_tprintf_buf(char *buf, size_t buf_size, const char *format, ...)
PRINTF_ATTRIBUTE(3, 4);
#endif /* MPLAYER_MPCOMMON_H */
+1 -1
View File
@@ -793,7 +793,7 @@ int encode_lavc_write_frame(struct encode_lavc_context *ctx, AVStream *stream,
if (ctx->header_written <= 0)
return -1;
MP_DBG(ctx,
MP_TRACE(ctx,
"write frame: stream %d ptsi %d (%f) dtsi %d (%f) size %d\n",
(int)packet->stream_index,
(int)packet->pts,
+9 -11
View File
@@ -1,20 +1,18 @@
/*
* 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 free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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.
* GNU Lesser 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/>.
*
* Almost LGPL.
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
@@ -122,7 +120,7 @@ static void update_loglevel(struct mp_log *log)
for (int n = 0; n < log->root->num_buffers; n++)
log->level = MPMAX(log->level, log->root->buffers[n]->level);
if (log->root->log_file)
log->level = MPMAX(log->level, MSGL_V);
log->level = MPMAX(log->level, MSGL_DEBUG);
if (log->root->stats_file)
log->level = MPMAX(log->level, MSGL_STATS);
atomic_store(&log->reload_counter, atomic_load(&log->root->reload_counter));
@@ -287,7 +285,7 @@ static void write_log_file(struct mp_log *log, int lev, char *text)
{
struct mp_log_root *root = log->root;
if (lev > MSGL_V || !root->log_file)
if (!root->log_file || lev > MPMAX(MSGL_DEBUG, log->terminal_level))
return;
fprintf(root->log_file, "[%8.3f][%c][%s] %s",
+1 -1
View File
@@ -160,7 +160,7 @@ struct mp_recorder *mp_recorder_create(struct mpv_global *global,
av_dict_set(&priv->mux->metadata, "encoding_tool", version, 0);
if (avformat_write_header(priv->mux, NULL) < 0) {
MP_ERR(priv, "Write header failed.\n");
MP_ERR(priv, "Writing header failed.\n");
goto error;
}
+1412 -314
View File
File diff suppressed because it is too large. Load diff
+19 -2
View File
@@ -40,10 +40,23 @@ enum demux_ctrl {
DEMUXER_CTRL_REPLACE_STREAM,
};
#define MAX_SEEK_RANGES 10
struct demux_seek_range {
double start, end;
};
struct demux_ctrl_reader_state {
bool eof, underrun, idle;
double ts_range[2]; // start, end
double ts_duration;
double ts_reader; // approx. timerstamp of decoder position
double ts_end; // approx. timestamp of end of buffered range
int64_t total_bytes;
int64_t fw_bytes;
// Positions that can be seeked to without incurring the latency of a low
// level seek.
int num_seek_ranges;
struct demux_seek_range seek_ranges[MAX_SEEK_RANGES];
};
struct demux_ctrl_stream_ctrl {
@@ -54,7 +67,8 @@ struct demux_ctrl_stream_ctrl {
#define SEEK_FACTOR (1 << 1) // argument is in range [0,1]
#define SEEK_FORWARD (1 << 2) // prefer later time if not exact
#define SEEK_BACKWARD (1 << 3) // prefer earlier time if not exact
// (if unset, prefer earlier time)
#define SEEK_CACHED (1 << 3) // allow packet cache seeks only
#define SEEK_HR (1 << 5) // hr-seek (this is a weak hint only)
// Strictness of the demuxer open format check.
@@ -77,6 +91,7 @@ enum demux_event {
DEMUX_EVENT_INIT = 1 << 0, // complete (re-)initialization
DEMUX_EVENT_STREAMS = 1 << 1, // a stream was added
DEMUX_EVENT_METADATA = 1 << 2, // metadata or stream_metadata changed
DEMUX_EVENT_DURATION = 1 << 3, // duration updated
DEMUX_EVENT_ALL = 0xFFFF,
};
@@ -285,6 +300,8 @@ int demux_stream_control(demuxer_t *demuxer, int ctrl, void *arg);
void demux_changed(demuxer_t *demuxer, int events);
void demux_update(demuxer_t *demuxer);
void demux_disable_cache(demuxer_t *demuxer);
struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d,
enum stream_type t, int id);
+24 -23
View File
@@ -3,20 +3,18 @@
*
* 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 free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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.
* GNU Lesser 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/>.
*
* Almost LGPL.
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
@@ -35,6 +33,7 @@
#include <libavutil/avstring.h>
#include <libavutil/mathematics.h>
#include <libavutil/replaygain.h>
#include <libavutil/spherical.h>
#include <libavutil/display.h>
#include <libavutil/opt.h>
@@ -234,13 +233,13 @@ static int mp_read(void *opaque, uint8_t *buf, int size)
memcpy(buf, priv->init_fragment.start + priv->stream_pos, ret);
priv->stream_pos += ret;
} else {
ret = stream_read(stream, buf, size);
ret = stream_read_partial(stream, buf, size);
priv->stream_pos = priv->init_fragment.len + stream_tell(stream);
}
MP_TRACE(demuxer, "%d=mp_read(%p, %p, %d), pos: %"PRId64", eof:%d\n",
ret, stream, buf, size, stream_tell(stream), stream->eof);
return ret;
return ret ? ret : AVERROR_EOF;
}
static int64_t mp_seek(void *opaque, int64_t pos, int whence)
@@ -404,7 +403,7 @@ static int lavf_check_file(demuxer_t *demuxer, enum demux_check check)
AVProbeData avpd = {
// Disable file-extension matching with normal checks
.filename = check <= DEMUX_CHECK_REQUEST ? priv->filename : "",
.filename = priv->filename,
.buf_size = 0,
.buf = av_mallocz(PROBE_BUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE),
};
@@ -641,6 +640,17 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
sh->codec->rotate = (((int)(-r) % 360) + 360) % 360;
}
sd = av_stream_get_side_data(st, AV_PKT_DATA_SPHERICAL, NULL);
if (sd) {
AVSphericalMapping *sp = (void *)sd;
struct mp_spherical_params *mpsp = &sh->codec->spherical;
mpsp->type = sp->projection == AV_SPHERICAL_EQUIRECTANGULAR ?
MP_SPHERICAL_EQUIRECTANGULAR : MP_SPHERICAL_UNKNOWN;
mpsp->ref_angles[0] = sp->yaw / (float)(1 << 16);
mpsp->ref_angles[1] = sp->pitch / (float)(1 << 16);
mpsp->ref_angles[2] = sp->roll / (float)(1 << 16);
}
// This also applies to vfw-muxed mkv, but we can't detect these easily.
sh->codec->avi_dts = matches_avinputformat_name(priv, "avi");
@@ -795,13 +805,6 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
if (index_mode != 1)
avfc->flags |= AVFMT_FLAG_IGNIDX;
#if LIBAVFORMAT_VERSION_MICRO >= 100
/* Keep side data as side data instead of mashing it into the packet
* stream.
* Note: Libav doesn't have this horrible insanity. */
av_opt_set(avfc, "fflags", "+keepside", 0);
#endif
if (lavfdopts->probesize) {
if (av_opt_set_int(avfc, "probesize", lavfdopts->probesize, 0) < 0)
MP_ERR(demuxer, "couldn't set option probesize to %u\n",
@@ -999,7 +1002,7 @@ static void demux_seek_lavf(demuxer_t *demuxer, double seek_pts, int flags)
int avsflags = 0;
int64_t seek_pts_av = 0;
if (flags & SEEK_BACKWARD)
if (!(flags & SEEK_FORWARD))
avsflags = AVSEEK_FLAG_BACKWARD;
if (flags & SEEK_FACTOR) {
@@ -1016,7 +1019,7 @@ static void demux_seek_lavf(demuxer_t *demuxer, double seek_pts, int flags)
seek_pts_av = seek_pts * priv->avfc->duration;
}
} else {
if (flags & SEEK_BACKWARD)
if (!(flags & SEEK_FORWARD))
seek_pts -= priv->seek_delay;
seek_pts_av = seek_pts * AV_TIME_BASE;
}
@@ -1146,8 +1149,6 @@ static void demux_close_lavf(demuxer_t *demuxer)
{
lavf_priv_t *priv = demuxer->priv;
if (priv) {
if (priv->avfc)
av_freep(&priv->avfc->key);
avformat_close_input(&priv->avfc);
if (priv->pb)
av_freep(&priv->pb->buffer);
+3 -7
View File
@@ -4,7 +4,7 @@
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
* version 2.1 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
@@ -13,12 +13,6 @@
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*
* The parts making this file LGPL v3 (instead of v2.1 or later) are:
* 0aa37a0db23c allow autodetection of pictures type when using mf://@fil...
* (iive agreed to LGPL v3+ only.)
* Once these changes are not relevant to for copyright anymore (e.g. because
* they have been removed), this file will change to LGPLv2.1+.
*/
#include <stdio.h>
@@ -115,6 +109,7 @@ static mf_t *open_mf_pattern(void *talloc_ctx, struct mp_log *log, char *filenam
char *fname = talloc_size(mf, strlen(filename) + 32);
#if HAVE_GLOB
if (!strchr(filename, '%')) {
strcpy(fname, filename);
if (!strchr(filename, '*'))
@@ -137,6 +132,7 @@ static mf_t *open_mf_pattern(void *talloc_ctx, struct mp_log *log, char *filenam
globfree(&gg);
goto exit_mf;
}
#endif
mp_info(log, "search expr: %s\n", filename);
+164 -120
View File
@@ -18,8 +18,6 @@
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*
* Parts under HAVE_GPL are licensed under GNU General Public License.
*/
#include <stdlib.h>
@@ -109,6 +107,7 @@ typedef struct mkv_track {
uint32_t colorspace;
int stereo_mode;
struct mp_colorspace color;
struct mp_spherical_params spherical;
uint32_t a_channels, a_bps;
float a_sfreq;
@@ -160,8 +159,9 @@ struct block_info {
bool simple, keyframe, duration_known;
int64_t timecode;
mkv_track_t *track;
bstr data;
void *alloc;
// Actual packet data.
AVBufferRef *laces[MAX_NUM_LACES];
int num_laces;
int64_t filepos;
struct ebml_block_additions *additions;
};
@@ -237,7 +237,6 @@ const struct m_sub_options demux_mkv_conf = {
.subtitle_preroll = 2,
.subtitle_preroll_secs = 1.0,
.subtitle_preroll_secs_index = 10.0,
.probe_start_time = 1,
},
};
@@ -584,6 +583,49 @@ static void parse_trackcolour(struct demuxer *demuxer, struct mkv_track *track,
}
}
static void parse_trackprojection(struct demuxer *demuxer, struct mkv_track *track,
struct ebml_projection *projection)
{
if (projection->n_projection_type) {
const char *name;
switch (projection->projection_type) {
case 0:
name = "rectangular";
track->spherical.type = MP_SPHERICAL_NONE;
break;
case 1:
name = "equirectangular";
track->spherical.type = MP_SPHERICAL_EQUIRECTANGULAR;
break;
default:
name = "unknown";
track->spherical.type = MP_SPHERICAL_UNKNOWN;
}
MP_VERBOSE(demuxer, "| + ProjectionType: %s (%"PRIu64")\n", name,
projection->projection_type);
}
if (projection->n_projection_private) {
MP_VERBOSE(demuxer, "| + ProjectionPrivate: %zd bytes\n",
projection->projection_private.len);
MP_WARN(demuxer, "Unknown ProjectionPrivate element.\n");
}
if (projection->n_projection_pose_yaw) {
track->spherical.ref_angles[0] = projection->projection_pose_yaw;
MP_VERBOSE(demuxer, "| + ProjectionPoseYaw: %f\n",
projection->projection_pose_yaw);
}
if (projection->n_projection_pose_pitch) {
track->spherical.ref_angles[1] = projection->projection_pose_pitch;
MP_VERBOSE(demuxer, "| + ProjectionPosePitch: %f\n",
projection->projection_pose_pitch);
}
if (projection->n_projection_pose_roll) {
track->spherical.ref_angles[2] = projection->projection_pose_roll;
MP_VERBOSE(demuxer, "| + ProjectionPoseRoll: %f\n",
projection->projection_pose_roll);
}
}
static void parse_trackvideo(struct demuxer *demuxer, struct mkv_track *track,
struct ebml_video *video)
{
@@ -628,6 +670,8 @@ static void parse_trackvideo(struct demuxer *demuxer, struct mkv_track *track,
}
if (video->n_colour)
parse_trackcolour(demuxer, track, &video->colour);
if (video->n_projection)
parse_trackprojection(demuxer, track, &video->projection);
}
/**
@@ -656,12 +700,7 @@ static void parse_trackentry(struct demuxer *demuxer,
}
track->uid = entry->track_uid;
if (entry->name) {
track->name = talloc_strdup(track, entry->name);
#if HAVE_GPL
MP_VERBOSE(demuxer, "| + Name: %s\n", track->name);
#endif
}
track->name = talloc_strdup(track, entry->name);
track->type = entry->track_type;
MP_VERBOSE(demuxer, "| + Track type: ");
@@ -1337,6 +1376,7 @@ static const char *const mkv_video_tags[][2] = {
{"V_DIRAC", "dirac"},
{"V_PRORES", "prores"},
{"V_MPEGH/ISO/HEVC", "hevc"},
{"V_SNOW", "snow"},
{0}
};
@@ -1422,12 +1462,8 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
}
const char *codec = sh_v->codec ? sh_v->codec : "";
if (!strcmp(codec, "vp9")) {
track->parse = true;
track->parse_timebase = 1e9;
} else if (!strcmp(codec, "mjpeg")) {
if (!strcmp(codec, "mjpeg"))
sh_v->codec_tag = MKTAG('m', 'j', 'p', 'g');
}
if (extradata_size > 0x1000000) {
MP_WARN(demuxer, "Invalid CodecPrivate\n");
@@ -1454,6 +1490,7 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
sh_v->stereo_mode = track->stereo_mode;
sh_v->color = track->color;
sh_v->spherical = track->spherical;
done:
demux_add_sh_stream(demuxer, sh);
@@ -1965,6 +2002,7 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check)
}
if (id == MATROSKA_ID_CLUSTER) {
MP_VERBOSE(demuxer, "|+ found cluster\n");
mkv_d->cluster_start = start_pos;
break;
}
int res = read_header_element(demuxer, id, start_pos);
@@ -2040,86 +2078,91 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check)
return 0;
}
static bool bstr_read_u8(bstr *buffer, uint8_t *out_u8)
// Read the laced block data at the current stream position (until endpos as
// indicated by the block length field) into individual buffers.
static int demux_mkv_read_block_lacing(struct block_info *block, int type,
struct stream *s, uint64_t endpos)
{
if (buffer->len > 0) {
*out_u8 = buffer->start[0];
buffer->len -= 1;
buffer->start += 1;
return true;
} else {
return false;
}
}
int laces;
uint32_t lace_size[MAX_NUM_LACES];
static int demux_mkv_read_block_lacing(bstr *buffer, int *laces,
uint32_t lace_size[MAX_NUM_LACES])
{
uint32_t total = 0;
uint8_t flags, t;
int i;
/* lacing flags */
if (!bstr_read_u8(buffer, &flags))
goto error;
int type = (flags >> 1) & 0x03;
if (type == 0) { /* no lacing */
*laces = 1;
lace_size[0] = buffer->len;
laces = 1;
lace_size[0] = endpos - stream_tell(s);
} else {
if (!bstr_read_u8(buffer, &t))
laces = stream_read_char(s);
if (laces < 0 || stream_tell(s) > endpos)
goto error;
*laces = t + 1;
laces += 1;
switch (type) {
case 1: /* xiph lacing */
for (i = 0; i < *laces - 1; i++) {
case 1: { /* xiph lacing */
uint32_t total = 0;
for (int i = 0; i < laces - 1; i++) {
lace_size[i] = 0;
uint8_t t;
do {
if (!bstr_read_u8(buffer, &t))
t = stream_read_char(s);
if (stream_eof(s) || stream_tell(s) >= endpos)
goto error;
lace_size[i] += t;
} while (t == 0xFF);
total += lace_size[i];
}
lace_size[i] = buffer->len - total;
uint32_t rest_length = endpos - stream_tell(s);
lace_size[laces - 1] = rest_length - total;
break;
}
case 2: /* fixed-size lacing */
for (i = 0; i < *laces; i++)
lace_size[i] = buffer->len / *laces;
case 2: { /* fixed-size lacing */
uint32_t full_length = endpos - stream_tell(s);
for (int i = 0; i < laces; i++)
lace_size[i] = full_length / laces;
break;
}
case 3:; /* EBML lacing */
uint64_t num = ebml_read_vlen_uint(buffer);
if (num == EBML_UINT_INVALID)
goto error;
if (num > buffer->len)
case 3: { /* EBML lacing */
uint64_t num = ebml_read_length(s);
if (num == EBML_UINT_INVALID || stream_tell(s) >= endpos)
goto error;
total = lace_size[0] = num;
for (i = 1; i < *laces - 1; i++) {
int64_t snum = ebml_read_vlen_int(buffer);
if (snum == EBML_INT_INVALID)
uint32_t total = lace_size[0] = num;
for (int i = 1; i < laces - 1; i++) {
int64_t snum = ebml_read_signed_length(s);
if (snum == EBML_INT_INVALID || stream_tell(s) >= endpos)
goto error;
lace_size[i] = lace_size[i - 1] + snum;
total += lace_size[i];
}
lace_size[i] = buffer->len - total;
uint32_t rest_length = endpos - stream_tell(s);
lace_size[laces - 1] = rest_length - total;
break;
}
default: abort();
default:
goto error;
}
}
total = buffer->len;
for (i = 0; i < *laces; i++) {
if (lace_size[i] > total)
for (int i = 0; i < laces; i++) {
uint32_t size = lace_size[i];
if (stream_tell(s) + size > endpos || size > (1 << 30))
goto error;
total -= lace_size[i];
int pad = MPMAX(AV_INPUT_BUFFER_PADDING_SIZE, AV_LZO_INPUT_PADDING);
AVBufferRef *buf = av_buffer_alloc(size + pad);
if (!buf)
goto error;
buf->size = size;
if (stream_read(s, buf->data, buf->size) != buf->size) {
av_buffer_unref(&buf);
goto error;
}
memset(buf->data + buf->size, 0, pad);
block->laces[block->num_laces++] = buf;
}
if (total != 0)
if (stream_tell(s) != endpos)
goto error;
return 0;
@@ -2400,12 +2443,10 @@ static void mkv_parse_and_add_packet(demuxer_t *demuxer, mkv_track_t *track,
struct demux_packet *new = new_demux_packet_from(data, size);
if (!new)
break;
demux_packet_copy_attribs(new, dp);
#if LIBAVCODEC_VERSION_MICRO >= 100
if (copy_sidedata)
av_copy_packet_side_data(new->avpacket, dp->avpacket);
#endif
av_packet_copy_props(new->avpacket, dp->avpacket);
copy_sidedata = false;
demux_packet_copy_attribs(new, dp);
if (track->parse_timebase) {
new->pts = track->av_parser->pts == AV_NOPTS_VALUE
? MP_NOPTS_VALUE : track->av_parser->pts / tb;
@@ -2426,11 +2467,10 @@ static void mkv_parse_and_add_packet(demuxer_t *demuxer, mkv_track_t *track,
static void free_block(struct block_info *block)
{
free(block->alloc);
block->alloc = NULL;
block->data = (bstr){0};
talloc_free(block->additions);
block->additions = NULL;
for (int n = 0; n < block->num_laces; n++)
av_buffer_unref(&block->laces[n]);
block->num_laces = 0;
TA_FREEP(&block->additions);
}
static void index_block(demuxer_t *demuxer, struct block_info *block)
@@ -2450,33 +2490,38 @@ static int read_block(demuxer_t *demuxer, int64_t end, struct block_info *block)
uint64_t num;
int16_t time;
uint64_t length;
int res = -1;
free_block(block);
length = ebml_read_length(s);
if (length > 500000000 || stream_tell(s) + length > (uint64_t)end)
goto exit;
block->alloc = malloc(length + AV_LZO_INPUT_PADDING);
if (!block->alloc)
goto exit;
block->data = (bstr){block->alloc, length};
block->filepos = stream_tell(s);
if (stream_read(s, block->data.start, block->data.len) != block->data.len)
goto exit;
if (!length || length > 500000000 || stream_tell(s) + length > (uint64_t)end)
return -1;
uint64_t endpos = stream_tell(s) + length;
int res = -1;
// Parse header of the Block element
/* first byte(s): track num */
num = ebml_read_vlen_uint(&block->data);
if (num == EBML_UINT_INVALID)
num = ebml_read_length(s);
if (num == EBML_UINT_INVALID || stream_tell(s) >= endpos)
goto exit;
/* time (relative to cluster time) */
if (block->data.len < 3)
if (stream_tell(s) + 3 > endpos)
goto exit;
time = block->data.start[0] << 8 | block->data.start[1];
block->data.start += 2;
block->data.len -= 2;
uint8_t c1 = stream_read_char(s);
uint8_t c2 = stream_read_char(s);
time = c1 << 8 | c2;
uint8_t header_flags = stream_read_char(s);
block->filepos = stream_tell(s);
int lace_type = (header_flags >> 1) & 0x03;
if (demux_mkv_read_block_lacing(block, lace_type, s, endpos))
goto exit;
if (block->simple)
block->keyframe = block->data.start[0] & 0x80;
block->keyframe = header_flags & 0x80;
block->timecode = time * mkv_d->tc_scale + mkv_d->cluster_tc;
for (int i = 0; i < mkv_d->num_tracks; i++) {
if (mkv_d->tracks[i]->tnum == num) {
@@ -2489,35 +2534,31 @@ static int read_block(demuxer_t *demuxer, int64_t end, struct block_info *block)
goto exit;
}
if (stream_tell(s) != endpos)
goto exit;
res = 1;
exit:
if (res <= 0)
free_block(block);
stream_seek(s, endpos);
return res;
}
static int handle_block(demuxer_t *demuxer, struct block_info *block_info)
{
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
int laces;
double current_pts;
bstr data = block_info->data;
bool keyframe = block_info->keyframe;
uint64_t block_duration = block_info->duration;
int64_t tc = block_info->timecode;
mkv_track_t *track = block_info->track;
struct sh_stream *stream = track->stream;
uint32_t lace_size[MAX_NUM_LACES];
bool use_this_block = tc >= mkv_d->skip_to_timecode;
if (!demux_stream_is_selected(stream))
return 0;
if (demux_mkv_read_block_lacing(&data, &laces, lace_size)) {
MP_ERR(demuxer, "Bad input [lacing]\n");
return 0;
}
current_pts = tc / 1e9 - track->codec_delay;
if (track->require_keyframes && !keyframe) {
@@ -2549,7 +2590,7 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info)
}
}
if (use_this_block) {
if (laces > 1) {
if (block_info->num_laces > 1) {
MP_WARN(demuxer, "Subtitles use Matroska "
"lacing. This is abnormal and not supported.\n");
use_this_block = 0;
@@ -2563,15 +2604,22 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info)
if (use_this_block) {
uint64_t filepos = block_info->filepos;
for (int i = 0; i < laces; i++) {
bstr block = bstr_splice(data, 0, lace_size[i]);
data = bstr_cut(data, lace_size[i]);
for (int i = 0; i < block_info->num_laces; i++) {
AVBufferRef *data = block_info->laces[i];
demux_packet_t *dp = NULL;
block = demux_mkv_decode(demuxer->log, track, block, 1);
bstr block = {data->data, data->size};
bstr nblock = demux_mkv_decode(demuxer->log, track, block, 1);
demux_packet_t *dp = new_demux_packet_from(block.start, block.len);
if (block.start != nblock.start || block.len != nblock.len) {
// (avoidable copy of the entire data)
dp = new_demux_packet_from(nblock.start, nblock.len);
} else {
dp = new_demux_packet_from_buf(data);
}
if (!dp)
break;
dp->keyframe = keyframe;
dp->pos = filepos;
/* If default_duration is 0, assume no pts value is known
@@ -2603,7 +2651,7 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info)
mkv_parse_and_add_packet(demuxer, track, dp);
talloc_free_children(track->parser_tmp);
filepos += block.len;
filepos += data->size;
}
if (stream->type == STREAM_VIDEO) {
@@ -2681,7 +2729,7 @@ static int read_block_group(demuxer_t *demuxer, int64_t end,
}
}
return block->data.start ? 1 : 0;
return block->num_laces ? 1 : 0;
error:
free_block(block);
@@ -2693,7 +2741,7 @@ static int read_next_block(demuxer_t *demuxer, struct block_info *block)
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
stream_t *s = demuxer->stream;
if (mkv_d->tmp_block.alloc) {
if (mkv_d->tmp_block.num_laces) {
*block = mkv_d->tmp_block;
mkv_d->tmp_block = (struct block_info){0};
return 1;
@@ -2854,8 +2902,6 @@ static int create_index_until(struct demuxer *demuxer, int64_t timecode)
return 0;
}
#define FLAG_BACKWARD 1
#define FLAG_SUBPREROLL 2
static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id,
int64_t target_timecode, int flags)
{
@@ -2866,8 +2912,8 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id,
for (size_t i = 0; i < mkv_d->num_indexes; i++) {
if (seek_id < 0 || mkv_d->indexes[i].tnum == seek_id) {
int64_t diff =
target_timecode - mkv_d->indexes[i].timecode * mkv_d->tc_scale;
if (flags & FLAG_BACKWARD)
mkv_d->indexes[i].timecode * mkv_d->tc_scale - target_timecode;
if (flags & SEEK_FORWARD)
diff = -diff;
if (min_diff != INT64_MIN) {
if (diff <= 0) {
@@ -2883,7 +2929,7 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id,
if (index) { /* We've found an entry. */
uint64_t seek_pos = index->filepos;
if (flags & FLAG_SUBPREROLL) {
if (flags & SEEK_HR) {
// Find the cluster with the highest filepos, that has a timestamp
// still lower than min_tc.
double secs = mkv_d->opts->subtitle_preroll_secs;
@@ -2948,14 +2994,12 @@ static void demux_mkv_seek(demuxer_t *demuxer, double seek_pts, int flags)
}
}
int cueflags = (flags & SEEK_BACKWARD) ? FLAG_BACKWARD : 0;
mkv_d->subtitle_preroll = NUM_SUB_PREROLL_PACKETS;
int preroll_opt = mkv_d->opts->subtitle_preroll;
if (((flags & SEEK_HR) || preroll_opt == 1 ||
(preroll_opt == 2 && mkv_d->index_has_durations))
&& st_active[STREAM_SUB] && st_active[STREAM_VIDEO])
cueflags |= FLAG_SUBPREROLL;
if (preroll_opt == 1 || (preroll_opt == 2 && mkv_d->index_has_durations))
flags |= SEEK_HR;
if (!st_active[STREAM_SUB])
flags &= ~SEEK_HR;
// Adjust the target a little bit to catch cases where the target position
// specifies a keyframe with high, but not perfect, precision.
@@ -2969,9 +3013,9 @@ static void demux_mkv_seek(demuxer_t *demuxer, double seek_pts, int flags)
if (create_index_until(demuxer, target_timecode) >= 0) {
int seek_id = st_active[STREAM_VIDEO] ? v_tnum : a_tnum;
index = seek_with_cues(demuxer, seek_id, target_timecode, cueflags);
index = seek_with_cues(demuxer, seek_id, target_timecode, flags);
if (!index)
index = seek_with_cues(demuxer, -1, target_timecode, cueflags);
index = seek_with_cues(demuxer, -1, target_timecode, flags);
}
if (!index)
+16 -4
View File
@@ -177,12 +177,13 @@ static int parse_ref_init(struct pl_parser *p)
return 0;
}
static int parse_pls(struct pl_parser *p)
static int parse_ini_thing(struct pl_parser *p, const char *header,
const char *entry)
{
bstr line = {0};
while (!line.len && !pl_eof(p))
line = bstr_strip(pl_get_line(p));
if (bstrcasecmp0(line, "[playlist]") != 0)
if (bstrcasecmp0(line, header) != 0)
return -1;
if (p->probing)
return 0;
@@ -190,7 +191,7 @@ static int parse_pls(struct pl_parser *p)
line = bstr_strip(pl_get_line(p));
bstr key, value;
if (bstr_split_tok(line, "=", &key, &value) &&
bstr_case_startswith(key, bstr0("File")))
bstr_case_startswith(key, bstr0(entry)))
{
value = bstr_strip(value);
if (bstr_startswith0(value, "\"") && bstr_endswith0(value, "\""))
@@ -201,6 +202,16 @@ static int parse_pls(struct pl_parser *p)
return 0;
}
static int parse_pls(struct pl_parser *p)
{
return parse_ini_thing(p, "[playlist]", "File");
}
static int parse_url(struct pl_parser *p)
{
return parse_ini_thing(p, "[InternetShortcut]", "URL");
}
static int parse_txt(struct pl_parser *p)
{
if (!p->force)
@@ -221,7 +232,7 @@ static int parse_txt(struct pl_parser *p)
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 st1->st_dev == st2->st_dev && st1->st_ino == st2->st_ino;
}
// Return true if this was a readable directory.
@@ -319,6 +330,7 @@ static const struct pl_format formats[] = {
{"ini", parse_ref_init},
{"pls", parse_pls,
MIME_TYPES("audio/x-scpls")},
{"url", parse_url},
{"txt", parse_txt},
};
+21 -17
View File
@@ -46,7 +46,6 @@ struct segment {
struct virtual_stream {
struct sh_stream *sh; // stream exported by demux_timeline
bool selected; // ==demux_stream_is_selected(sh)
bool new_segment; // whether a new segment needs to be signaled
int eos_packets; // deal with b-frame delay
};
@@ -61,7 +60,7 @@ struct priv {
struct segment *current;
// As the demuxer user sees it.
struct virtual_stream *streams;
struct virtual_stream **streams;
int num_streams;
// Total number of packets received past end of segment. Used
@@ -97,7 +96,7 @@ static void associate_streams(struct demuxer *demuxer, struct segment *seg)
if (!other || !target_stream_used(seg, other->index)) {
// Try to associate the first unused stream with matching media type.
for (int i = 0; i < p->num_streams; i++) {
struct sh_stream *cur = p->streams[i].sh;
struct sh_stream *cur = p->streams[i]->sh;
if (cur->type == sh->type && !target_stream_used(seg, cur->index))
{
other = cur;
@@ -118,7 +117,7 @@ static void reselect_streams(struct demuxer *demuxer)
struct priv *p = demuxer->priv;
for (int n = 0; n < p->num_streams; n++) {
struct virtual_stream *vs = &p->streams[n];
struct virtual_stream *vs = p->streams[n];
vs->selected = demux_stream_is_selected(vs->sh);
}
@@ -131,7 +130,7 @@ static void reselect_streams(struct demuxer *demuxer)
struct sh_stream *sh = demux_get_stream(seg->d, i);
bool selected = false;
if (seg->stream_map[i] >= 0)
selected = p->streams[seg->stream_map[i]].selected;
selected = p->streams[seg->stream_map[i]]->selected;
// This stops demuxer readahead for inactive segments.
if (!p->current || seg->d != p->current->d)
selected = false;
@@ -171,6 +170,8 @@ static void reopen_lazy_segments(struct demuxer *demuxer)
demuxer->stream->cancel, demuxer->global);
if (!p->current->d && !demux_cancel_test(demuxer))
MP_ERR(demuxer, "failed to load segment\n");
if (p->current->d)
demux_disable_cache(p->current->d);
associate_streams(demuxer, p->current);
}
@@ -179,8 +180,8 @@ static void switch_segment(struct demuxer *demuxer, struct segment *new,
{
struct priv *p = demuxer->priv;
if (!(flags & (SEEK_FORWARD | SEEK_BACKWARD)))
flags |= SEEK_BACKWARD | SEEK_HR;
if (!(flags & SEEK_FORWARD))
flags |= SEEK_HR;
MP_VERBOSE(demuxer, "switch to segment %d\n", new->index);
@@ -195,8 +196,7 @@ static void switch_segment(struct demuxer *demuxer, struct segment *new,
demux_seek(new->d, start_pts, flags);
for (int n = 0; n < p->num_streams; n++) {
struct virtual_stream *vs = &p->streams[n];
vs->new_segment = true;
struct virtual_stream *vs = p->streams[n];
vs->eos_packets = 0;
}
@@ -209,7 +209,7 @@ static void d_seek(struct demuxer *demuxer, double seek_pts, int flags)
double pts = seek_pts * ((flags & SEEK_FACTOR) ? p->duration : 1);
flags &= SEEK_FORWARD | SEEK_BACKWARD | SEEK_HR;
flags &= SEEK_FORWARD | SEEK_HR;
struct segment *new = p->segments[p->num_segments - 1];
for (int n = 0; n < p->num_segments; n++) {
@@ -244,7 +244,7 @@ static int d_fill_buffer(struct demuxer *demuxer)
bool eos_reached = p->eos_packets > 0;
if (eos_reached && p->eos_packets < 100) {
for (int n = 0; n < p->num_streams; n++) {
struct virtual_stream *vs = &p->streams[n];
struct virtual_stream *vs = p->streams[n];
if (vs->selected) {
int max_packets = 0;
if (vs->sh->type == STREAM_AUDIO)
@@ -276,6 +276,7 @@ static int d_fill_buffer(struct demuxer *demuxer)
goto drop;
if (!p->dash) {
pkt->segmented = true;
if (!pkt->codec)
pkt->codec = demux_get_stream(seg->d, pkt->stream)->codec;
if (pkt->start == MP_NOPTS_VALUE || pkt->start < seg->start)
@@ -293,7 +294,7 @@ static int d_fill_buffer(struct demuxer *demuxer)
if (pkt->pos >= 0)
pkt->pos |= (seg->index & 0x7FFFULL) << 48;
struct virtual_stream *vs = &p->streams[pkt->stream];
struct virtual_stream *vs = p->streams[pkt->stream];
if (pkt->pts != MP_NOPTS_VALUE && pkt->pts >= seg->end) {
// Trust the keyframe flag. Might not always be a good idea, but will
@@ -307,10 +308,6 @@ static int d_fill_buffer(struct demuxer *demuxer)
}
}
if (!p->dash)
pkt->new_segment |= vs->new_segment;
vs->new_segment = false;
demux_add_packet(vs->sh, pkt);
return 1;
@@ -377,8 +374,10 @@ static int d_open(struct demuxer *demuxer, enum demux_check check)
new->forced_track = sh->forced_track;
new->hls_bitrate = sh->hls_bitrate;
new->missing_timestamps = sh->missing_timestamps;
new->attached_picture = sh->attached_picture;
demux_add_sh_stream(demuxer, new);
struct virtual_stream vs = {
struct virtual_stream *vs = talloc_ptrtype(p, vs);
*vs = (struct virtual_stream){
.sh = new,
};
MP_TARRAY_APPEND(p, p->streams, p->num_streams, vs);
@@ -388,6 +387,11 @@ static int d_open(struct demuxer *demuxer, enum demux_check check)
struct timeline_part *part = &p->tl->parts[n];
struct timeline_part *next = &p->tl->parts[n + 1];
// demux_timeline already does caching, doing it for the sub-demuxers
// would be pointless and wasteful.
if (part->source)
demux_disable_cache(part->source);
struct segment *seg = talloc_ptrtype(p, seg);
*seg = (struct segment){
.d = part->source,
+21 -52
View File
@@ -73,56 +73,6 @@ uint32_t ebml_read_id(stream_t *s)
return id;
}
/*
* Read a variable length unsigned int.
*/
uint64_t ebml_read_vlen_uint(bstr *buffer)
{
int i, j, num_ffs = 0, len_mask = 0x80;
uint64_t num;
if (buffer->len == 0)
return EBML_UINT_INVALID;
for (i = 0, num = buffer->start[0]; i < 8 && !(num & len_mask); i++)
len_mask >>= 1;
if (i >= 8)
return EBML_UINT_INVALID;
j = i + 1;
if ((int) (num &= (len_mask - 1)) == len_mask - 1)
num_ffs++;
if (j > buffer->len)
return EBML_UINT_INVALID;
for (int n = 0; n < i; n++) {
num = (num << 8) | buffer->start[n + 1];
if ((num & 0xFF) == 0xFF)
num_ffs++;
}
if (j == num_ffs)
return EBML_UINT_INVALID;
buffer->start += j;
buffer->len -= j;
return num;
}
/*
* Read a variable length signed int.
*/
int64_t ebml_read_vlen_int(bstr *buffer)
{
uint64_t unum;
int l;
/* read as unsigned number first */
size_t len = buffer->len;
unum = ebml_read_vlen_uint(buffer);
if (unum == EBML_UINT_INVALID)
return EBML_INT_INVALID;
l = len - buffer->len;
return unum - ((1LL << ((7 * l) - 1)) - 1);
}
/*
* Read: element content length.
*/
@@ -150,6 +100,25 @@ uint64_t ebml_read_length(stream_t *s)
return len;
}
/*
* Read a variable length signed int.
*/
int64_t ebml_read_signed_length(stream_t *s)
{
uint64_t unum;
int l;
/* read as unsigned number first */
uint64_t offset = stream_tell(s);
unum = ebml_read_length(s);
if (unum == EBML_UINT_INVALID)
return EBML_INT_INVALID;
l = stream_tell(s) - offset;
return unum - ((1LL << ((7 * l) - 1)) - 1);
}
/*
* Read the next element as an unsigned int.
*/
@@ -509,8 +478,8 @@ static void ebml_parse_element(struct ebml_parse_ctx *ctx, void *target,
bool multiple = fd->multiple;
int *countptr = (int *) (s + fd->count_offset);
if (*countptr >= num_elems[field_idx]) {
// Shouldn't happen with on any sane file without bugs
MP_ERR(ctx, "Too many subelems?\n");
// Shouldn't happen on any sane file without bugs
MP_ERR(ctx, "Too many subelements.\n");
ctx->has_errors = true;
data += length;
continue;
+1 -2
View File
@@ -80,9 +80,8 @@ struct ebml_parse_ctx {
bool ebml_is_mkv_level1_id(uint32_t id);
uint32_t ebml_read_id (stream_t *s);
uint64_t ebml_read_vlen_uint (bstr *buffer);
int64_t ebml_read_vlen_int (bstr *buffer);
uint64_t ebml_read_length (stream_t *s);
int64_t ebml_read_signed_length(stream_t *s);
uint64_t ebml_read_uint (stream_t *s);
int64_t ebml_read_int (stream_t *s);
int ebml_read_skip(struct mp_log *log, int64_t end, stream_t *s);
+14 -1
View File
@@ -54,6 +54,7 @@ struct demux_packet *new_demux_packet_from_avpacket(struct AVPacket *avpkt)
.end = MP_NOPTS_VALUE,
.stream = -1,
.avpacket = talloc_zero(dp, AVPacket),
.kf_seek_pts = MP_NOPTS_VALUE,
};
av_init_packet(dp->avpacket);
int r = -1;
@@ -74,6 +75,17 @@ struct demux_packet *new_demux_packet_from_avpacket(struct AVPacket *avpkt)
return dp;
}
// (buf must include proper padding)
struct demux_packet *new_demux_packet_from_buf(struct AVBufferRef *buf)
{
AVPacket pkt = {
.size = buf->size,
.data = buf->data,
.buf = buf,
};
return new_demux_packet_from_avpacket(&pkt);
}
// Input data doesn't need to be padded.
struct demux_packet *new_demux_packet_from(void *data, size_t len)
{
@@ -109,9 +121,10 @@ void demux_packet_copy_attribs(struct demux_packet *dst, struct demux_packet *sr
dst->dts = src->dts;
dst->duration = src->duration;
dst->pos = src->pos;
dst->segmented = src->segmented;
dst->start = src->start;
dst->end = src->end;
dst->new_segment = src->new_segment;
dst->codec = src->codec;
dst->keyframe = src->keyframe;
dst->stream = src->stream;
}
+7 -3
View File
@@ -36,18 +36,22 @@ typedef struct demux_packet {
int stream; // source stream index
// segmentation (ordered chapters, EDL)
struct mp_codec_params *codec;
double start, end;
bool new_segment;
bool segmented;
struct mp_codec_params *codec; // set to non-NULL iff segmented is set
double start, end; // set to non-NOPTS iff segmented is set
// private
struct demux_packet *next;
struct AVPacket *avpacket; // keep the buffer allocation and sidedata
double kf_seek_pts; // demux.c internal: seek pts for keyframe range
} demux_packet_t;
struct AVBufferRef;
struct demux_packet *new_demux_packet(size_t len);
struct demux_packet *new_demux_packet_from_avpacket(struct AVPacket *avpkt);
struct demux_packet *new_demux_packet_from(void *data, size_t len);
struct demux_packet *new_demux_packet_from_buf(struct AVBufferRef *buf);
void demux_packet_shorten(struct demux_packet *dp, size_t len);
void free_demux_packet(struct demux_packet *dp);
struct demux_packet *demux_copy_packet(struct demux_packet *dp);
+2 -1
View File
@@ -22,7 +22,7 @@
#include "common/common.h"
#include "audio/chmap.h"
#include "video/csputils.h"
#include "video/mp_image.h"
struct MPOpts;
struct demuxer;
@@ -93,6 +93,7 @@ struct mp_codec_params {
int rotate; // intended display rotation, in degrees, [0, 359]
int stereo_mode; // mp_stereo3d_mode (0 if none/unknown)
struct mp_colorspace color; // colorspace info where available
struct mp_spherical_params spherical;
// STREAM_VIDEO + STREAM_AUDIO
int bits_per_coded_sample;
+5 -2
View File
@@ -20,7 +20,6 @@ osc=no
ytdl=no
input-default-bindings=no
input-vo-keyboard=no
stop-playback-on-init-failure=yes
# OSX/Cocoa global input hooks
input-appleremote=no
input-media-keys=no
@@ -36,7 +35,7 @@ load-scripts=no
osc=no
framedrop=no
[opengl-hq]
[gpu-hq]
scale=spline36
cscale=spline36
dscale=mitchell
@@ -44,3 +43,7 @@ dither-depth=auto
correct-downscaling=yes
sigmoid-upscaling=yes
deband=yes
# Compatibility alias (deprecated)
[opengl-hq]
profile=gpu-hq
+10 -11
View File
@@ -28,21 +28,17 @@
# If this is enabled, treat all the following bindings as default.
#default-bindings start
#MOUSE_BTN0 ignore # don't do anything
#MOUSE_BTN0_DBL cycle fullscreen # toggle fullscreen on/off
#MOUSE_BTN2 cycle pause # toggle pause on/off
#MOUSE_BTN3 seek 10
#MOUSE_BTN4 seek -10
#MOUSE_BTN5 add volume -2
#MOUSE_BTN6 add volume 2
#MBTN_LEFT ignore # don't do anything
#MBTN_LEFT_DBL cycle fullscreen # toggle fullscreen on/off
#MBTN_RIGHT cycle pause # toggle pause on/off
# Mouse wheels, touchpad or other input devices that have axes
# if the input devices supports precise scrolling it will also scale the
# numeric value accordingly
#AXIS_UP seek 10
#AXIS_DOWN seek -10
#AXIS_LEFT seek 5
#AXIS_RIGHT seek -5
#WHEEL_UP seek 10
#WHEEL_DOWN seek -10
#WHEEL_LEFT add volume -2
#WHEEL_RIGHT add volume 2
## Seek units are in seconds, but note that these are limited by keyframes
#RIGHT seek 5
@@ -82,6 +78,8 @@
#O no-osd cycle-values osd-level 3 1 # cycle through OSD mode
#o show-progress
#P show-progress
#i script-binding stats/display-stats
#I script-binding stats/display-stats-toggle
#z add sub-delay -0.1 # subtract 100 ms delay from subs
#x add sub-delay +0.1 # add
#ctrl++ add audio-delay 0.100 # this changes audio/video sync
@@ -144,6 +142,7 @@
#l ab-loop # Set/clear A-B loop points
#L cycle-values loop-file "inf" "no" # toggle infinite looping
#ctrl+c quit 4
#DEL script-binding osc/visibility # cycle OSC display
# Apple Remote section
#AR_PLAY cycle pause
+2 -2
View File
@@ -52,9 +52,9 @@
# Keep the player window on top of all other windows.
#ontop=yes
# Specify high quality video rendering preset (for OpenGL VO only)
# Specify high quality video rendering preset (for --vo=gpu only)
# Can cause performance problems with some drivers and GPUs.
#profile=opengl-hq
#profile=gpu-hq
# Force video to lock on the display's refresh rate, and change video and audio
# speed to some degree to ensure synchronous playback - can cause problems
+7
View File
@@ -9,6 +9,13 @@
#
# Older installations use ~/.mpv/input.conf instead.
# changed in mpv 0.27.0 (macOS and Wayland only)
# WHEEL_UP seek 10
# WHEEL_DOWN seek -10
# WHEEL_LEFT seek 5
# WHEEL_RIGHT seek -5
# changed in mpv 0.26.0
h cycle tv-channel -1 # previous channel
-9
View File
@@ -13,8 +13,6 @@
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*
* Parts under HAVE_GPL are licensed under GNU General Public License.
*/
#include <limits.h>
@@ -98,20 +96,15 @@ const struct mp_cmd_def mp_cmds[] = {
{ MP_CMD_PLAYLIST_SHUFFLE, "playlist-shuffle", },
{ MP_CMD_SUB_STEP, "sub-step", { ARG_INT }, .allow_auto_repeat = true },
{ MP_CMD_SUB_SEEK, "sub-seek", { ARG_INT }, .allow_auto_repeat = true },
#if HAVE_GPL
{ MP_CMD_OSD, "osd", { OARG_INT(-1) } },
#endif
{ MP_CMD_PRINT_TEXT, "print-text", { ARG_STRING }, .allow_auto_repeat = true },
{ MP_CMD_SHOW_TEXT, "show-text", { ARG_STRING, OARG_INT(-1), OARG_INT(0) },
.allow_auto_repeat = true},
{ MP_CMD_EXPAND_TEXT, "expand-text", { ARG_STRING } },
{ MP_CMD_SHOW_PROGRESS, "show-progress", .allow_auto_repeat = true},
#if HAVE_GPL
{ MP_CMD_SUB_ADD, "sub-add", { ARG_STRING,
OARG_CHOICE(0, ({"select", 0}, {"auto", 1}, {"cached", 2})),
OARG_STRING(""), OARG_STRING("") } },
{ MP_CMD_SUB_REMOVE, "sub-remove", { OARG_INT(-1) } },
#endif
{ MP_CMD_SUB_RELOAD, "sub-reload", { OARG_INT(-1) } },
{ MP_CMD_TV_LAST_CHANNEL, "tv-last-channel", },
@@ -156,7 +149,6 @@ const struct mp_cmd_def mp_cmds[] = {
{ MP_CMD_RUN, "run", { ARG_STRING, ARG_STRING }, .vararg = true },
{ MP_CMD_SET, "set", { ARG_STRING, ARG_STRING } },
#if HAVE_GPL
{ MP_CMD_ADD, "add", { ARG_STRING, OARG_DOUBLE(1) },
.allow_auto_repeat = true,
.scalable = true,
@@ -168,7 +160,6 @@ const struct mp_cmd_def mp_cmds[] = {
.allow_auto_repeat = true,
.scalable = true,
},
#endif
{ MP_CMD_MULTIPLY, "multiply", { ARG_STRING, ARG_DOUBLE },
.allow_auto_repeat = true},
-1
View File
@@ -46,7 +46,6 @@ enum mp_command_type {
MP_CMD_QUIT_WATCH_LATER,
MP_CMD_PLAYLIST_NEXT,
MP_CMD_PLAYLIST_PREV,
MP_CMD_OSD,
MP_CMD_SCREENSHOT,
MP_CMD_SCREENSHOT_TO_FILE,
MP_CMD_SCREENSHOT_RAW,
Loaded 100 of 390 files, more files were not shown because too many files have changed in this diff. Show more