Compare commits

..
184 Commits
Author SHA1 Message Date
Diogo Franco (Kovensky) 4db470e08a Release 0.8.3 2015-03-17 10:50:21 +09:00
Diogo Franco (Kovensky) cf3819ece9 Update RELEASE_NOTES 2015-03-17 10:49:57 +09:00
wm4 575b631d67 video: don't drop anamorphic scaling if it's too minor
This played e.g. a 1264x722 file as 1264x720. There was some code which
dropped the aspect ratio if the video (in original resolution) wasn't
scaled by more than 4 pixels. Commit 5f3c3f8c introduced this (although
I'm not really sure what the code replaced by it did).

Just remove this "feature".

(cherry picked from commit d96fad04be)
2015-03-17 10:49:56 +09:00
wm4 4c1b45b5ab command: don't drop audio buffers when switching filters
This partially reverts commit ae7228c6. I guess the old behavior was
slightly more popular.

Fixes #1693 (probably).

(cherry picked from commit 699fc0e51e)
2015-03-17 10:49:56 +09:00
wm4 8932d90ec6 demux_lavf: fix rejection of image2 demuxer
This was probably broken for some time in git master, and the later
commit which happened to fix it was not picked.

Fixes #1689.
2015-03-16 11:58:24 +01:00
Diogo Franco (Kovensky) fc4da23c64 Update RELEASE_NOTES 2015-03-16 17:26:05 +09:00
Martin Herkt 017c2808e4 bootstrap: add waf mirror
(cherry picked from commit 958dbca3ef)
2015-03-16 17:08:16 +09:00
wm4 c5a8fc793c audio: fix off by one error in channel map selection code
The consequence was that some AOs (like ao_jack) could not output 8
channels.

Fixes #1688.

(cherry picked from commit c4f4b09014)
2015-03-16 17:08:01 +09:00
Martin Herkt 3dcd3476c6 man: fix PDF build
(cherry picked from commit add4c9ee03)
2015-03-16 17:07:47 +09:00
Stefano Pigozzi ad119460d7 cocoa: signal VO_EVENT_WIN_STATE on fps change
Fixes #1686

(cherry picked from commit efe0fb75bc)
2015-03-15 21:33:38 +09:00
James Ross-Gowan e865543be2 w32_common: don't hide cursor when the menu is open
Previously, mpv would hide the cursor when the autohide timer expired,
even if the window menu was open. This made it difficult to use the menu
with the mouse.

When handling VOCTRL_SET_CURSOR_VISIBILITY, instead of determining
whether to call SetCursor by checking if the cursor is in the client
area, call it based on the parameters to the last WM_SETCURSOR message.
When the window enters "menu mode," it gets a WM_SETCURSOR message with
HIWORD(lParam) set to 0 to indicate that the cursor shouldn't be set.

(cherry picked from commit acbac01a73)
2015-03-15 20:09:00 +09:00
wm4 e84a00651a vo: update FPS only on state changes
I'm not comfortable with VOCTRL_GET_DISPLAY_FPS being called every
frame.

This requires the VO to set VO_EVENT_WIN_STATE if the FPS could have
changed. At least the X11 backend does this.

(cherry picked from commit 209f8225ed)
2015-03-15 20:08:00 +09:00
wm4 b17ccd1c43 demux_mkv: make matroska.pl script output deterministic
Work around the randomized Perl hashtables by sorting the elements.

Fixes #1673.

(cherry picked from commit 7e9c441d41)
2015-03-15 20:07:14 +09:00
wm4 62d922e4f0 command: allow changing some VO options even if VO wasn't created yet
Instead of refusing to set properties like "fullscreen" if no VO was
created, always allow it. So if no VO is created, setting the property
merely changes the options (and will be applied once the VO is created).
This is consistent with similar behavior changes to some other
properties.

Improves the behavior reported in #1676.

Also, we shouldn't check the config_ok variable - the VO should do this.

(cherry picked from commit e9841630ad)
2015-03-15 20:07:06 +09:00
wm4 eaa5393c4a player: fix crash when taking screenshots in idle mode
mpctx->filename is obviously not set if no file is playing.

When this code was written, it probably couldn't happen, because the
normal screenshot path fails much earlier in idle mode. But you can
still take screenshots in "full window" mode, and recently the
screenshot code was changed to use the "full window" mode if the normal
path does not work.

(cherry picked from commit ca474d22c9)
2015-03-15 20:06:50 +09:00
wm4 50b74bf407 x11: ignore mouse enter/leave events due to pointer grab
If you click on a window that doesn't have a focus, a LeaveNotify
followed by a EnterNotify event can be generated. The former will have
mode set to NotifyGrab, the latter to NotifyUngrab. This will make the
player think the mouse left the window, even though this is not the
case. Ignore these and only react to those with mode set to
NotifyNormal.

Probably fixes #1672, and some other strange issues on some WMs.

(cherry picked from commit 30860f7b10)
2015-03-15 20:06:28 +09:00
Stefano Pigozzi 414cdc9da6 build: disable tests by default
Having them autodetect is a bad idea since it would link cmocka in the main
mpv binary (which users don't want).

(cherry picked from commit ca0b33e9b1)
2015-03-11 12:49:40 +09:00
wm4 1c4bdfaf9c vo: hide opengl-cb in --vo=help
Avoids stupid questions.

(cherry picked from commit c7790b4526)
2015-03-11 12:49:40 +09:00
wm4 76809e5ef7 vo_opengl_cb: clear last video frame on uninit()
mpv_opengl_cb_render() is supposed to clear the screen with the
background color if there's no video... I think.

It didn't do this, because although uninit() requested gl_video_config()
to be called, this didn't happen, because this function checks whether
the VO is set - and it's unsert after uninit() releases the lock.

Also call the user wakeup callback in this situation, so the user
actually redraws immediately.

(cherry picked from commit eff265c140)
2015-03-11 12:49:40 +09:00
wm4 efc72daea9 client API: clarify mpv_opengl_cb_render() viewport parameter
Basically, the idea behind the vp parameter is broken - I guess the
intention was to enable rendering to a specific subrectangle of the
target framebuffer, but there's nothing to specify the actual target
rectangle (the VO will still clear e.g. the borders between video and
framebuffer borders).

We're not going to keep the current semantics either with the upcoming
rework of vo_opengl, so declare this for broken. Maybe we can introduce
a function later which does this properly.

(cherry picked from commit 90adf2904e)
2015-03-11 12:49:40 +09:00
wm4 b414d9a9a7 stream: use relaxed atomic loads for checking playback aborts
Seems appropriate, and will probably avoid performance surprises with
scary architectures which don't have trivial implementations for atomic
loads. (Consider that demux_mkv calls this very often now, and
libavformat demuxers and streams did this for a while now.)

(cherry picked from commit b9307b7175)
2015-03-11 12:49:40 +09:00
wm4 2b737f8bfc demux_mkv: never warn when trying to resync on EOF
If this happens, the file is actually broken, but the assumption is
simply that the file was truncated, and printing a warning would be
strange.

(cherry picked from commit 112d9aeda1)
2015-03-11 12:49:40 +09:00
wm4 9e99a0c8b9 demux_mkv: check for playback aborts
Check async abort notification. libavformat already do something
equivalent.

Before this commit, the demuxer could enter resync mode (and print silly
warning messages) when the stream stopped returning data because of an
abort.

(cherry picked from commit 39fa05d374)
2015-03-11 12:49:40 +09:00
James Ross-Gowan e22ecb1585 w32_common: remove redundant is_maximized function
This already exists as IsMaximized in the Windows API.

(cherry picked from commit 5f0eda7b94)
2015-03-11 12:49:40 +09:00
wm4 6358e9be5c x11: fix VOCTRL_GET_WIN_STATE
Do not rely on the pointed-to argument to be initialized; VOCTRLs are
supposed to completely overwrite them on success (or not to touch them
on failure).

The currently only caller of VOCTRL_GET_WIN_STATE initializes the value
before calling this, so this is merely about correctness and didn't lead
to any actual bugs.

(cherry picked from commit b7f242dfcf)
2015-03-11 12:49:40 +09:00
Kevin Mitchell d57a48c64e stream/smb: mark as network stream for --cache=auto
This causes the cache to be enabled with --cache=auto. It was not done
previously because the small cache size 320k actually led to worse
performance. However, with the current default cache size of 25000kb,
caching notably improves performance.

(cherry picked from commit 3efbc1a9a3)
2015-03-11 12:49:40 +09:00
Niklas Haas 22691f2e6a manpage: document swapinterval default
(cherry picked from commit 6983430c35)
2015-03-11 12:49:39 +09:00
Filip Milivojevic 623a259eee vf_vavpp: fix deinterlacing
Add filter parameters to VAAPI deinterlacing filter to actually process
bottom fields instead of deinterlacing top field twice.

Signed-off-by: wm4 <wm4@nowhere>
(cherry picked from commit 5c3a6ca96e)
2015-03-11 12:49:39 +09:00
wm4 fa81e835bc DOCS: minor update to coding style
(cherry picked from commit 6f507d14c1)
2015-03-11 12:49:39 +09:00
Stefano Pigozzi 46cc45223c cocoa: fix autohide in fullscreen
(cherry picked from commit 8ec9bce2d3)
2015-03-11 12:49:39 +09:00
Stefano Pigozzi 0e160123fd cocoa: fix mouse hiding with launchpad and dock folders
Some UI elements in OS X – like Launchpad and Dock folders – are implemented
using borderless windows in background demonized applications.
When we use these elements, mpv doesn't stop to be the active application, but
the mpv window leaves keyWindow state while we use the OS controls.

This commit just keeps track of window state to update the cursor visibility
accordingly.

Fixes #513

(cherry picked from commit ce239f1577)
2015-03-11 12:49:39 +09:00
torque 710979e0e8 cocoa: clamp mouse position to window.
Prevents out-of-window coordinates being reported for mouse coordinates.
Previously they could be out-of-window coordinates on init or on resize.

(cherry picked from commit 39537f6474)
2015-03-11 12:49:39 +09:00
torque 18d3c2ab85 cocoa: update mouse coordinates when window is initialized.
Make MpvEventsView -signalMousePosition a public method so it can be
called without a compiler warning. Previously, the mouse position would
be reported as (0,0) until the cursor was moved.

(cherry picked from commit bce753060e)
2015-03-11 12:49:39 +09:00
Martin Herkt f84ca3a516 vo_opengl/x11: fix automatic ICC profile loading
mpv would attempt to load ICC profiles several times during VO init
even if no window is displayed. This potentially causes it to load
a profile for a different screen than it is going to be displayed
on, thereby invalidating the profile cache and rebuilding the LUT
every single time.
It would not unload a previously loaded profile when the video
window is moved to a display without an installed profile.

Fix these issues and tweak the log messages a little.

(cherry picked from commit 1bab7f69ae)
2015-03-11 12:49:39 +09:00
Stefano Pigozzi 324a40d2e1 cocoa: remove possible use after free
(cherry picked from commit 5cddd4ccca)
2015-03-11 12:49:33 +09:00
Stefano Pigozzi 83e98d3ada cocoa: fix some crashes caused by async uninit
Always keep around our private state and destroy it when we are really done in
the async uninit callback.

Fixes #1657

(cherry picked from commit c66b51dab0)
2015-03-11 12:39:56 +09:00
wm4 a424fe1296 demux_mkv: actually skip elements out of reach
This is missing from the previous commit. Not that harmful, but also
slightly un-nice since even a failed seek will reset the cache.

(cherry picked from commit f0ab1f2048)
2015-03-11 12:34:26 +09:00
wm4 e09803ae6b demux_mkv: fix issues with unseekable streams
A user reported a webm stream that couldn't be played. The issue was
that this stream 1. was on an unseekable HTTP connection, and 2. had a
SeekHead element (wtf?). The code reading the SeekHead marked the
element as unreadable too early: although you can't seek in the stream,
reading the header elements after the SeekHead read them anyway. Marking
them as unreadable only after the normal header reading fixes this.

(The way the failing stream was setup was pretty retarded: inserting
these SeekHead elements makes absolutely no sense for a stream that
cannot be seeked.)

Fixes #1656.

(cherry picked from commit 12dcc5eaac)
2015-03-11 12:34:02 +09:00
torque 80669188d6 Lua: add unpack shim for Lua 5.2/5.3 compatibility.
The global unpack function got moved to table.unpack in Lua 5.2, and
it's only available as the global if 5.2 is built with compatibility
enabled (the default). Lua 5.3 does not build with 5.1 compatibility by
default.

Fixes #1648.

(cherry picked from commit 4ff29f33b0)
2015-03-11 12:33:53 +09:00
wm4 1a3a3aba63 player: allow changing playback speed in early audio init stages
If the audio decoder was created, but no audio filter chain created yet
(still trying to decode a first audio frame), setting the "speed"
property could explode. It tried to recreate the filter chain, even
though no format was set yet.

This is inconvenient and should not happen.

(cherry picked from commit 720d4a5a1a)
2015-03-11 12:33:22 +09:00
wm4 0b141eaa82 DOCS/compile-window.md: add Lua package to MXE instructions
The MSYS2 ones already mention Lua.

(cherry picked from commit 3fe61ada84)
2015-03-11 12:33:00 +09:00
wm4 cac071dc23 build: make vdpau and dxva2 checks nicer
Using check_statement() with an empty statement just to check for the
header is quite a hack. Fix check_headers() (so it takes a "use"
parameter), and use it for the checks instead.

(cherry picked from commit dfa562b5db)
2015-03-11 12:32:51 +09:00
ChrisK2 c77f076ae4 DOCS, options: fix example
(cherry picked from commit e9ff136dd3)
2015-03-11 12:32:03 +09:00
wm4 f4393eaa6c build: check whether hwaccels are enabled in FFmpeg
FFmpeg can be compiled with them disabled, and then it won't provide the
public headers specific to these APIs, causing mpv compilation failure.

(cherry picked from commit baa354c64c)
2015-03-11 12:31:53 +09:00
wm4 bbd6501bd3 vd_lavc: let --hwdec=auto select "vaapi-copy"
Instead of "vaapi", simply by changing the probe order.

"vaapi" uses the GLX GL interop, which has causing us more problems than
it solved.

Unfortunately this leads also to copying if "--hwdec=auto --vo=vaapi" is
used, even though GLX is not involved in this case - but I don't care
enough to make the probe logic cleverer just for this. You can still get
the zero-copy path with --hwdec=vaapi.

(cherry picked from commit 27b5492a82)
2015-03-11 12:31:40 +09:00
wm4 dc29a21b5c vd_lavc: request 1 more threads than CPU cores
This duplicates the logic which FFmpeg's libavcodec uses. The effects
are unknown, though it's somewhat clear that a single thread doesn't
necessarily saturate a single CPU.

(Eventually we should just let FFmpeg auto-init the thread count, but
for now I prefer it this way, so e.g. verbose mode will print the
thread count.)

(cherry picked from commit 9657e5a2ca)
2015-03-11 12:31:16 +09:00
wm4 4d87844508 vo_vaapi: fix video equalizer (second try)
The vaapi equalizer have a custom range, and can have a smaller range
than mpv's normalized video equalizer values. The result is that a vaapi
equalizer value can map to multiple mpv values, so changing a mpv value
by 1 can get "stuck". Fix by remember the mpv value, and returning it if
it still corresponds to the vaapi value.

Really fixes #1647.

(Why am I even bothering with this irredeemable crap?)

(cherry picked from commit fc571e0adb)
2015-03-11 12:30:50 +09:00
wm4 cced4bf4d6 vo_vaapi: round equalizer values
Probably fixes #1647 (if it's correct at all). I couldn't reproduce with
the vdpau libva driver, but a driver can use different ranges.

(cherry picked from commit 4e3f8ccb9d)
2015-03-11 12:30:50 +09:00
wm4 5734cd7063 README: fix typos
(cherry picked from commit 6d4a758295)
2015-03-05 10:48:31 +09:00
wm4 52324a494c ad_spdif: remove per-packet message
It was annoying and didn't ever help with anything.

(cherry picked from commit 55f69605fb)
2015-03-05 10:48:25 +09:00
wm4 7ee8237e66 cache: assume file size from EOF position
If we're caching a stream with unknown size, and we reach EOF, then
consider the EOF position the file size. Typically makes sense when
reading from a pipe or a http connection that did not send a size.

(cherry picked from commit 3cd394995f)
2015-03-05 10:47:36 +09:00
wm4 6fc0b4e24b README: add some better links
Also write something about MPlayer, since this is a frequently asked
question.

(cherry picked from commit 771cb34932)
2015-03-05 10:47:24 +09:00
wm4 3d3b1b8bba win32: fix some more -Wparentheses warnings
Stupid compiler.

For decode_surrogate_pair(), I changed the order of evaluation; it
shouldn't matter, but this order is more readable in my opinion.

(cherry picked from commit 85bf102f54)
2015-03-05 10:47:14 +09:00
Stefano Pigozzi 21a90cc49c cocoa: silence -Wlogical-op-parentheses
(cherry picked from commit 3c3f9a8042)
2015-03-05 10:47:03 +09:00
wm4 83119f05c4 build: fix warnings with --disable-libass
This crap seems to break every other fullmoon.

(cherry picked from commit 0bbf36b796)
2015-03-05 10:46:49 +09:00
wm4 081ddd26b4 stream_cdda: fix parameter passing
All cdda options (except --cdrom-drive) were ignored, because the priv
struct (with the options set) was just replaced. Oops.

(cherry picked from commit 1ba24d2585)
2015-03-04 13:08:25 +09:00
wm4 78349cc188 player: refine rar:// playlist-safety handling
It was possible to make the player play local files by putting rar://
links into remote playlists, and some other potentially unsafe things.

Redo the handling of it. Now the rar-redirector (the thing in
demux_playlist.c) sets disable_safety, which makes the player open any
playlist entries returned. This is fine, because it redirects to the
same file anyway (just with different selection/interpretation of the
contents). On the other hand, rar:// itself is now considered fully
unsafe, which means that it is ignored if found in normal playlists.

(cherry picked from commit a4b6bf8c41)
2015-03-03 16:08:43 +09:00
wm4 931f614257 msg: use relaxed atomics for log level test
This should be sufficient.

If stdatomic.h is not available, we make no difference.

(cherry picked from commit 01b87e509c)
2015-03-03 16:08:24 +09:00
wm4 e682d82527 vf_scale: libswscale is being stupid
This time (there are a lot of times), libswscale randomly ignores
brightness/saturation/contrast settings.

Looking at MPlayer code, it appears the return value of
sws_setColorspaceDetails() signals if changing these settings is
supported at all.

(Nevermind that supporting this feature has almost 0 value, and
obviously eats maintenance time.)

(cherry picked from commit 08199a64d2)
2015-03-03 16:07:04 +09:00
torque 76fd4b4e33 Lua: add mp.get_screen_margins().
When used with mp.get_screen_size(), mp.get_screen_margins() allows a
Lua script to determine what portion of the mpv window actually has the
video in it.

(cherry picked from commit 1bbf1eb3ce)
2015-03-03 16:06:46 +09:00
Oliver Freyermuth 623b0a77e1 stream_dvb: Always define NO_STREAM_ID_FILTER if missing.
It is also used for initialization in channel-list setup.
Should fix compilation on FreeBSD, and is more correct
since it is used unconditionally.
Reverts 6445648 .

(cherry picked from commit 40c9e79068)
2015-03-03 16:05:24 +09:00
Stefano Pigozzi c6c4c3ea9c cocoa: remove the setNextKeyView hack
Just use makeFirstResponder on the mpv events view from client code
if you need the built in keyboard events (this is easier for dealing with view
nesting).

(cherry picked from commit 03a69bac95)
2015-03-03 16:05:24 +09:00
Stefano Pigozzi 8e5a854374 examples/cocoabasic: allow to send stop command
(cherry picked from commit 721e430cd2)
2015-03-03 16:05:24 +09:00
zymos 90a0add131 manpage: fix typo
Signed-off-by: wm4 <wm4@nowhere>
(cherry picked from commit b742384162)
2015-03-03 16:05:24 +09:00
wm4 443fd456a1 vo_opengl: delete 16 bit test texture
Essentially a leak, but not that bad since it's small and allocated only
once.

(cherry picked from commit 73c5c3df53)
2015-03-03 16:02:22 +09:00
wm4 910da3af6a vo_opengl: fix some comments
(cherry picked from commit e7b7a5a476)
2015-03-03 16:02:16 +09:00
wm4 517f15dc49 stream: remove stream filter concept
Unused since the previous commit. (Apparently it was a stupid idea.)

(cherry picked from commit fbf76da913)
2015-03-03 16:02:07 +09:00
wm4 62cf557b5f stream_rar: treat rar files as playlists
Refactors an older hack, which for some reason used a more complicated
way. This generates the playlist representing the contents of the rar
file in demux_playlist.c. The pseudo-demuxer could easily be separate
from the the playlist parsers (and in fact there's almost no shared
code), but I don't think this obscure feature deserves a separate file.

Sample files created with:

    rar a -v20000k -m0 files.rar file1.mkv file1.mkv

(cherry picked from commit 5824eb7107)
2015-03-03 16:02:02 +09:00
wm4 95e1952377 build: improve DVB check
A use of NO_STREAM_ID_FILTER was added to the DVB code recently. While I
have no idea what it's needed for, it makes mpv fail to compile on
FreeBSD 10.1. Add it to the dvb configure check.

(cherry picked from commit 64456488b3)
2015-03-03 16:01:37 +09:00
Niklas Haas 90126b9f88 manpage: update wording on speed
The way I interpreted it, it seemed like this was not default behavior
and could be enabled with --audio-pitch-correction - it should be made
clearer that this is actually *the default behavior*.

(cherry picked from commit 0f99b302f5)
2015-03-03 16:00:38 +09:00
wm4 01223a3e0f player: adjust A/V desync message
Broken drivers are an issue rather often. Maybe this gives the user an
idea that this could be the reason. (We can't dump much more info on a
80x24 terminal.)

(cherry picked from commit a5f3083ae7)
2015-03-03 15:58:57 +09:00
wm4 76b0291bf2 vo_opengl: test FBOs only if they're going to be used
Change test_fbo() so that it checks the FBO lazily, and restructure
check_gl_features() to invoke it only if we know that a FBO will be
needed for a certain enabled feature.

This can avoid strange error messages when using --vo=opengl and the
FBO format does not work. It's also less confusing when reading the
verbose log (users might think that the FBO is actually used, etc.).

(cherry picked from commit 280c826379)
2015-03-03 15:58:43 +09:00
wm4 3fc0c18997 vo_xv: don't attempt to clear window before mapped
This can happen with the "no-colorkey" suboption. Then the code in
xv_draw_colorkey() can be run before vo_x11_config_vo_window(), when
vo_gc is not allocated yet.

Fixes #1629.

(cherry picked from commit a2e0cd7f25)
2015-03-03 15:58:28 +09:00
wm4 7fe9126bba Release 0.8.2 2015-02-26 19:13:34 +01:00
wm4 22863d6a79 Revert "osd: force alignment for OSD bar"
This reverts commit ff10bd65d6.

Fixes #1631.
2015-02-26 19:11:42 +01:00
Diogo Franco (Kovensky) 5ccd91d639 Fix typo... 2015-02-26 17:20:01 +09:00
Diogo Franco (Kovensky) 37bf8de258 Release 0.8.1 2015-02-26 11:08:23 +09:00
wm4 2d3e4fb1b9 cache: use MPCLAMP() macro
(cherry picked from commit e85bcc1223)
2015-02-26 11:03:15 +09:00
wm4 78cd25388c cache: limit to file size
Saves some memory. Should be especially helpful if many small files are
loaded, like when mass-loading subtitle files and the cache is enabled.

(cherry picked from commit 899f0cd51e)
2015-02-26 11:03:08 +09:00
Stefano Pigozzi 32f0adaeae remove dead comment
(cherry picked from commit f3eb6ae783)
2015-02-26 11:02:44 +09:00
Stefano Pigozzi 70a7d9d2c5 build: move QuartzCore linking to the cocoa check
It's needed for the DisplayLink functions so it must be enabled for the basic
cocoa code.

(cherry picked from commit 8e80b3fd2f)
2015-02-26 11:02:38 +09:00
wm4 cf14511b1d demux_mkv_timeline: fix potential issue when enabling cache
If the cache is enabled, the demuxer is closed and opened again (because
currently, the cache can not be enabled atfer data was already read).
The call for opening a new demuxer uses the same params struct, which
references the ctx->uids array. But there is a MP_TARRAY_GROW()
invocation somewhere on the way, which can reallocate the ctx->uids
array, making params.uids a dangling pointer.

This issue probably existed for a longer time, probably since 5cd33853
(slightly more obvious since f50b105d).

(cherry picked from commit 9349cfca91)
2015-02-26 11:01:25 +09:00
wm4 a6d57d654a demux_mkv_timeline: move uids array to context too
Again removes some indirections and extra arguments.

Also replace some memcpy/memmoves with assignments. (Assignments became
possible only later, when reference UIDs were turned into a struct.)

(cherry picked from commit 02bd54c0ac)
2015-02-26 10:45:42 +09:00
wm4 63671a4fbb demux_mkv_timeline: pass sources array as part of context
Removes tripple pointer indirections and such.

(cherry picked from commit 2bf0a5f2bc)
2015-02-26 10:40:35 +09:00
wm4 8ace70cfa6 demux_mkv: minor refactor for deferred cue reading
Should behave about the same, but reduces code some duplication with
seeking and reading a header element pointed to by a SeekHead. It also
makes behavior with incomplete files slightly better.

(cherry picked from commit 2e23be5a7b)
2015-02-26 10:39:02 +09:00
wm4 1e0edb3e6f demux_mkv: don't spam too many warnings with partial files
Limit it to a single message. It often printed more than that, and in
some cases (old files with "cluster" index), spammed a lot.

(cherry picked from commit a761a1531a)
2015-02-26 10:38:53 +09:00
Diogo Franco (Kovensky) 4ed46bfa25 Update RELEASE_NOTES 2015-02-25 15:26:03 +09:00
Diogo Franco (Kovensky) 423d47130a Fix compilation
Broken by unchecked cherry-picking of 53867aa.
2015-02-25 11:16:18 +09:00
Niklas Haas 7a02593dc4 vo_opengl: greatly increase smoothmotion performance
Instead of rendering and upscaling each video frame on every vsync, this
version of the algorithm only draws them once and caches the result,
so the only operation that has to run on every vsync is a cheap linear
interpolation, plus CMS/dithering.

On my machine, this is a huge speedup for 24 Hz content (on a 60 Hz
monitor), up to 120% faster. (The speedup is not quite 250% because of
the overhead that the larger FBOs and CMS provides)

In terms of the implementation, this commit basically swaps
interpolation and upscaling - upscaling is moved to inter_program, and
interpolation is moved to the final_program.

Furthermore, the main bulk of the frame rendering logic (upscaling etc.)
was moved to a separete function, which is called from
gl_video_interpolate_frame only if it's actually necessarily, and
skipped otherwise.

(cherry picked from commit 010cf183fe)
2015-02-25 11:10:27 +09:00
Niklas Haas 220d28b902 manpage: update documentation for smoothmotion
Hopefully, this will really clear up how the thing is supposed to work
(and that it's not SVP, nor MVTools).

I also removed instances of the word "interpolation", since that's a
term that's easily misleading.

Finally, I expanded on smoothmotion-threshold since the purpose/meaning
was a bit confusing.

(cherry picked from commit 9fa73b6f64)
2015-02-25 11:10:01 +09:00
wm4 ff10bd65d6 osd: force alignment for OSD bar
Overwrite the alignment applied by the OSD style. Additionally, remove
the initialization of the Alignment field in create_ass_track(); the
value is always overwritten by mp_ass_set_style() later.

Fixes #1626.

(cherry picked from commit 53641a689d)
2015-02-25 11:09:20 +09:00
wm4 e2895e9684 osd: always reset style params
There was some logic to set certain things on init only. Not sure why
this was done (saving some cheap calculations?) - but since the next
call would override these style settings by applying the usual subtitle
style, I don't think this was intended.

(cherry picked from commit 9fbcb56bee)
2015-02-25 11:09:10 +09:00
wm4 83be06c0ad vo_opengl: another GLES2 issue
GLES2 randomly does not support the transpose parameter in matrix
uniform calls. So we have to do this manually. Sure it was worth to
mutilate the standard just so all these shitty SoC vendors can safe 3
lines of code.

(Obviously trying to handle all of GLES2 to GL 4.x in a single codebase
was a mistake.)

(cherry picked from commit cc011415ff)
2015-02-25 11:08:53 +09:00
wm4 fd7077ade9 vo_opengl: extend ifdef against shader arrays
GLES2 shaders do not have line continuation characters. Abuse the
HAVE_ARRAYS define to exclude code which uses arrays, and which also
happens to cover all code that defines multi-line macros. (So yes, this
is a hack.)

(cherry picked from commit 2c8d16d89f)
2015-02-25 11:08:39 +09:00
wm4 d40ccc3416 old-build: proper atomics are not strictly required
(cherry picked from commit a92cab736f)
2015-02-25 11:08:27 +09:00
wm4 57f5ad445d video: remove redundant codec parameters
Remove coded_width and coded_height. This was originally added in commit
fd7dde40, when BITMAPINFOHEADER was killed. The separate fields became
redundant in commit e68f4be1. Remove them (nothing passed to the
decoders actually changes with _this_ commit).

(cherry picked from commit 5baf74fa24)
2015-02-25 11:08:15 +09:00
wm4 a5458a624d ytdl: add --no-warnings
Silences "[ytdl_hook] WARNING: video doesn't have subtitles", which was
an annoying and pointless message printed with almost all youtube
videos.

(cherry picked from commit 7cff2e4131)
2015-02-25 11:01:05 +09:00
Jaime Marquínez Ferrándiz edf0b93703 ytdl: Adapt to new subtitles structure
The requested formats can be sorted by preference and the result gives now an url or the subtitles file content

(cherry picked from commit 7281a72fab)
2015-02-25 11:00:55 +09:00
Kevin Mitchell 6bf46eae23 ao/wasapi: move resume to audio thread
This echanges the two events hForceFeed/hFeedDone for hResume. This
like the last commit makes things more deterministic.

Importantly, the forcefeed is only done if there is not already a full
buffer yet to be played by the device. This should fix some of the
problems with exclusive mode.

This commit also removes the necessity to have a proxy to the
AudioClient object in the main thread.

fixes #1529

(cherry picked from commit c52833bf16)
2015-02-25 10:59:25 +09:00
Kevin Mitchell 774e818371 ao_wasapi: move reset into audio thread
This makes things a bit more deterministic. It ensures that the audio
thread isn't doing anything between IAudioClient_Stop(),
IAudioClient_Reset() and setting the sample_count to 0.

Buffer overfilling on resume is still a problem in exclusive mode (see
next commit).

(cherry picked from commit 446fd5a43a)
2015-02-25 10:59:19 +09:00
wm4 352c00fd08 encoding: allow encoding to channel configurations other than stereo
A while ago, we made mpv output the native number of channels by
default, instead of stereo. I assumed this was not wanted for encode
mode.

This commit keeps the assumption, but allows setting the number of audio
output channels at all, instead of always forcing stereo. (Pretty much a
hack.)

(cherry picked from commit 636d6d724d)
2015-02-25 10:51:05 +09:00
wm4 589b38c187 vf: fix indentation level of verbose output
Just so that it has the same indentation as the extremely similar audio
filter output.

(cherry picked from commit 24e7280178)
2015-02-25 10:50:50 +09:00
wm4 62bc8442be DOCS/client_api_examples/simple: fix option
"input-x11-keyboard" still works, but is a deprecated alias with the
same functionality.

(cherry picked from commit cf395e1754)
2015-02-25 10:50:39 +09:00
wm4 0edd08a1f6 client API: hint that opengl_cb is an alternative to window embedding
(cherry picked from commit d77fdc8f82)
2015-02-25 10:50:31 +09:00
Niklas Haas 7f5378680b vo_opengl: slightly improve ewa_lanczos windowing
The original filter window was design for a radius based on the true
zero, but we always cut it off at our selection of radius either way (by
necessity, due to the square matrix we sample from).

This window is tweaked from the original (true radius) to our actual
cut-off radius, and hence improves the result in a few edge cases. The
main win is the reduction of code complexity, since we no longer need to
know what the true radius actually is.

(cherry picked from commit 1ecd9727f0)
2015-02-25 10:50:16 +09:00
wm4 4753a92b80 player: fix demuxer lifetime management
Commit f54220d9 attempted to improve this, but it got worse. Now there
was a crash when ytdl_hook.lua added external tracks. This happened
because close_unused_demuxers() assumed that sources[0] was the main
demuxer (so that it didn't close it). This assumption failed, because
the ytdl script can add external tracks before the main file is loaded.
The easy fix would have been to check for master_demuxer, and not i==0.
But instead give up on the old idea, make some stricter assumptions how
demuxers and external tracks map, and simplify the code.

(cherry picked from commit 53867aa9d8)
2015-02-24 12:16:00 +09:00
Stefano Pigozzi 584a27e3b8 build: print pkg-config query on failure
(cherry picked from commit 0466ce2f98)
2015-02-24 12:13:05 +09:00
wm4 b4abc0a037 manpage: ipc: add a socat example
Requested, and should be quite good at giving an overview how it works.

(cherry picked from commit af435e0a02)
2015-02-24 12:12:34 +09:00
wm4 192318a216 video: un-discourage "vaapi-copy" hwdec mode
Maybe I don't know what I'm doing. I'm fairly certain though that Intel
does not know what they're doing.

(cherry picked from commit d71bbcbc98)
2015-02-21 21:00:50 +09:00
wm4 822e6e0dd1 player: move timeline scanning (ordered chapters etc.) to a thread
Do timeline building (scanning & opening reference files for ordered
chapters, and more) in a thread. As a result, this process can actually
be stopped without having to kill the player.

This is pretty simple: just reuse the demuxer opening thread. We have
to give up on the idea that open_demux_reentrant() is reusable, though.

(Althoughthe timeline readers still need some fixes before they react to
the quit request.)

(cherry picked from commit 44411674eb)
2015-02-21 20:49:50 +09:00
wm4 45b63c78cd player: cosmetics: async/non-blocking -> reentrant
These functions do blocking work on a separate thread, but wait until
they return. So they are not async or non-blocking. But they do react to
user-input and client API accesses, which makes them reentrant.

(cherry picked from commit 2c305d5b29)
2015-02-21 20:49:32 +09:00
wm4 de47273716 stream_file: open pipes non-blocking
Now the player can actually be quit if a pipe was opened, but nobody is
writing to it.

(cherry picked from commit 3c9344a1a9)
2015-02-21 20:49:11 +09:00
wm4 7ace4f2115 vo_opengl: minor robustness improvement in function loader
Check the scanf() return value, and don't continue if it doesn't find
both numbers (can happen with GLES 1.0). Also, some implementations can
return NULL from glGetString() if something is "broken".

(cherry picked from commit 9861abf8ff)
2015-02-21 20:48:43 +09:00
Niklas Haas f67dfcbec6 vo_opengl: fix smoothmotion coefficient calculation, for real this time
I've reworked pretty much all the logic to correspond to what the theory
actually describes. With this commit, playback is wonderfully smooth on
my machine.

(cherry picked from commit 4356e893a1)
2015-02-21 20:48:24 +09:00
wm4 6b9f7923af demux_lavf: apply hacks even if format is forced
Some of the hacks were not applied if the file format was forced. Commit
37a0c914 moved them to a table, which is checked with normal probing
only.

Fixes #1612 (DVD forces mpeg, which in turn has to export native stream
IDs specifically).

Do some code restructuring on the way. For example, the probescore can
simply be set to the correct initial value, instead of checking whether
it was set at all.

(cherry picked from commit 611f9ab0a8)
2015-02-21 20:48:15 +09:00
wm4 c36b1d01c1 manpage: fix vf_scale arnd parameter
It probably was always a flag, so the documentation became invalid as
soon as mpv stopped accepting 0/1 for flags.

Fixes #1608.

(cherry picked from commit b230f32624)
2015-02-21 20:47:55 +09:00
wm4 07222d14f9 build: fix Python 3 unicode issue with waf 1.8.6
Starting with waf 1.8.6 (in Python 3), the hcode variable isn't a
string, but a byte string.

This commit adds the solution proposed in the upstream waf bug report:
https://code.google.com/p/waf/issues/detail?id=1535

It seems a bit overly verbose, but on the other hand, this solution has
the chance of being most correct/compatible.

Fixes #1604.

(cherry picked from commit 14b231119d)
2015-02-19 19:33:49 +09:00
Diogo Franco (Kovensky) 28fbee7f03 Update RELEASE_NOTES 2015-02-19 13:44:57 +09:00
wm4 b3d2daaa1d demux_lavf: blacklist bintext files
Whatever the hell that is. FFmpeg tries to open any files with .bin file
extension with this demuxer (unless it finds a better demuxer), and then
reads the whole damn file, along with spamming dumb crap.

(cherry picked from commit 79006ef66d)
2015-02-19 13:39:39 +09:00
wm4 3437ea23f6 cache: silence "EOF reached" message
This message will be printed relatively often once EOF is reached. In
some cases this is rather annoying, for example when playing HLS. (With
HLS, the stream is just a playlist file, while libavformat opens actual
media files without mpv's knowledge, so the cache is completely useless
and hits EOF instantly.)

That it retries reading is apparently a good thing: at least local files
can grow, and even after the player got the EOF, playback _could_ be
resumed by basically polling and detecting that there is more data. So
I'm not changing this behavior yet.

(cherry picked from commit 3f5b5b758d)
2015-02-19 13:39:39 +09:00
wm4 16856994e9 demux_lavf: reorganize hacks
An attempt to make format-specifics more declarative. (In my opinion,
all of this should be either provided by libavformat, or should not be
needed.)

I'm still leaving many checks with matches_avinputformat_name(), because
they're so specific.

Also useful for the following commit.

(cherry picked from commit 37a0c9140a)
2015-02-19 13:39:39 +09:00
wm4 c22c440c9c demux_lavf: set interrupt_callback
Helps with terminating the stream if e.g. HLS streams are stuck. (For
other demuxers, the stream's interrupt callback already takes care of
this.)

(cherry picked from commit ff992e093b)
2015-02-19 13:39:39 +09:00
Jaime Marquínez Ferrándiz be42f4c212 find_subfiles: Add 'vtt' to subtitle extensions
(cherry picked from commit aa98049877)
2015-02-19 13:39:39 +09:00
wm4 1b5f127cb0 demux, matroska: remove demuxer type field
The Matroska timeline code was the only thing which still used the
demuxer.type field. This field explicitly identifies a demuxer
implementation. The purpose of the Matroska timeline code was to reject
files that are not Matroska. But it already forces the Matroska format,
meaning loading will explicitly only use the Matroska demuxer. If the
demuxer can't open the file, no other demuxer will be tried, and thus
checking the field is redundant.

The change in demux_mkv_timeline.c removes the if condition, and
unindents the if body.

(cherry picked from commit fa9b587426)
2015-02-19 13:39:39 +09:00
wm4 7ea82eb7bc demux: remove file_contents field
Only demux_cue and demux_edl used it. It's a weird field and doesn't
help with anything anymore - by now, it only saves a priv context in the
mentioned demuxers. Reducing the number of confusing things the demuxer
struct has is more important than minimizing the code.

(cherry picked from commit 082371a160)
2015-02-19 13:39:39 +09:00
wm4 3be989dcd0 demux_edl: make independent from MPContext
(cherry picked from commit d7a4cb14ff)
2015-02-19 13:39:38 +09:00
wm4 0adc8ee5c1 demux_edl: move implementation
Same deal as with demux_cue, and a separate commit for the same reasons.

(cherry picked from commit 1e44c811f3)
2015-02-19 13:39:38 +09:00
wm4 55fe8aab6a demux_cue: make independent from MPContext
Also see previous commit(s).

(cherry picked from commit 10781c2a9c)
2015-02-19 13:39:38 +09:00
wm4 b2aa388f27 demux_cue: move implementation
Move the implementation, of which most was in tl_cue.c, to demux_cue.c.
Currently, this is illogical, because tl_cue.c still accesses MPContext.
This is going to change, and then it will be better if everything is in
demux_cue.c. This is only a separate commit to distinguish code movement
and actual work; the next commit will do the actual work.

(cherry picked from commit 7f03f46882)
2015-02-19 13:39:38 +09:00
wm4 fea1dc0cd5 demux: copy priv pointer too
Weird, but helps with the case a demuxer gets handed its own instance
from outside.

(cherry picked from commit f9872ab26f)
2015-02-19 13:39:38 +09:00
wm4 8161b47e73 matroska: move timeline code to demux/
Separate from previous commit, because git is bad at tracking file
renames when the file contents are also changed.

(cherry picked from commit edc0007e74)
2015-02-19 13:39:38 +09:00
wm4 f113e03b89 matroska: make timeline code independent of MPContext
(cherry picked from commit 5a186d5942)
2015-02-19 13:39:38 +09:00
wm4 630a7b7d82 player: use a separate context for timeline loader stuff
Instead of accessing MPContext in player/timeline/*, create a separate
context struct, which the timeline loaders fill out. It turns out that
there's not much in the way too big MPContext that these need to access.

One major PITA is managing (and closing) the set of open demuxers. The
problem is that we need a list of all demuxers to make sure no unneeded
streams are enabled.

This adds a callback to the demuxer_desc struct, with the intention of
leaving to to the demuxer to call the right loader, instead of
explicitly checking the demuxer type and dispatching manually in common
code. I also considered making the timeline part of the demuxer state,
but decided against: it's too much of a mess wrt. memory management and
threading, and also doesn't make it clear who owns the child demuxers.
With the struct timeline decoupled from the demuxer state, it's at least
somewhat clear that the child demuxers are independent from the "main"
demuxer.

The actual changes to player/timeline/* are separated in the following
commits, because they're quite verbose. Some artifacts will be removed
later as soon as there's only 1 timeline loading mechanism.

(cherry picked from commit a0a089f6a4)
2015-02-19 13:39:38 +09:00
wm4 a4e766a77f demux: chapters without metadata are allowed
Makes some of the following commits slightly simpler. Also fix a typo.

(cherry picked from commit 3efeee446e)
2015-02-19 13:39:38 +09:00
wm4 57deaa02d5 player: use a macro to remove an element from an array
Should be equivalent.

(cherry picked from commit 969edb9e0b)
2015-02-19 13:39:38 +09:00
wm4 a6accfdad7 player: actually close files when using sub_remove
Also effects some other cases.

The real reason for this is for keeping track of which demuxers can be
closed (see following commit). Since I don't want to use reference
counting for this, some sort of simplistic mark-and-sweep is done to
determine whether a demuxer is still needed.

(cherry picked from commit f54220d951)
2015-02-19 13:39:38 +09:00
wm4 8813fe090d DOCS/client-api-changes: mark 0.8.0 release
(There was a missing version bump for the msg-level change; just move it
under 1.14.)

(cherry picked from commit 0283815ee1)
2015-02-19 13:39:38 +09:00
wm4 72ba8515d5 demux_lavf: hack against hls showing "100%" position
The HLs protocol consists of a "playlist" main file, which mpv downloads
and passes to the HLS demuxer. The HLS demuxer actually requests segment
files containing media data on its own. The packets read from the
demuxer have a source file position set, but it's not from the main
file. This leads to a strange effect: as a last fallback, the player
will calculate the approximate playback position from the file
position/size ratio, and since the main file is tiny, this will always
show 100%. Fix this by resetting the packet file position.

This doesn't affect the case when HLS actually reports a duration.

(cherry picked from commit a64b1deaa6)
2015-02-19 13:39:38 +09:00
wm4 21f5d82dc5 etc/input.conf: remove a leftover
This is already mapped by default.

(cherry picked from commit 8b784fb1ca)
2015-02-19 13:24:59 +09:00
wm4 8c992458c3 vo_opengl: glsl: remove trailing \
This should be no problem... but it _might_ help with #1536, so it's
worth a try.

(cherry picked from commit 0063d94927)
2015-02-19 13:24:31 +09:00
wm4 40149c017c m_config: log options set by the client API too
(cherry picked from commit d34eabe286)
2015-02-19 13:24:09 +09:00
Diogo Franco (Kovensky) 0c9f10e0d1 Release v0.8.0 2015-02-17 14:06:06 +09:00
Diogo Franco (Kovensky) 5b0d06ca74 Fix typo in RELEASE_NOTES 2015-02-17 14:05:50 +09:00
Diogo Franco (Kovensky) a410451463 Fix typo on RELEASE_NOTES 2015-02-16 18:54:13 +09:00
Skyrainfit 3152eed6d8 mpv.desktop: Add zh-TW and zh-CN translations
(cherry picked from commit 31ac0574ad)
2015-02-16 18:45:05 +09:00
Diogo Franco (Kovensky) 02260882ce Bump VERSION to v0.8.0_rc3 2015-02-16 18:37:46 +09:00
Diogo Franco (Kovensky) cd5f0a8612 Update RELEASE_NOTES 2015-02-16 18:37:32 +09:00
wm4 23959eb5b4 osxbundle: config file special case isn't needed anymore
The previous commit effectively fixes the mess caused by 'config' vs.
'mpv.conf', and the hack introduced by commit e01a6dac and extended by
commit db167cd4 isn't needed anymore.

(cherry picked from commit 816d7bba1f)
2015-02-16 18:16:36 +09:00
wm4 21a95f5ed9 player: undeprecate 'config' files
Actually, it's pretty simple to look for multiple filenames at once,
since mp_find_all_config_files() is already a bit "special" anyway.

See #1569. Reverts most of commit db167cd4 (keeps osx-bundle.conf).

(cherry picked from commit a27aa68dd3)
2015-02-16 18:16:28 +09:00
wm4 6dc2a23cda vd_lavc: uninit the hwdec backend after closing the decoder
A recent behavior change in libavcodec's h264 decoder keeps at least 1
surface even after avcodec_flush_buffers() has been called. We used to
flush the decoder in order to make sure all surfaces are free'd, so that
the hw decoder can be safely uninitialized. This doesn't work anymore.

Fix it by closing the AVCodecContext before the hw decoder is
uninitialized. This is actually simpler and more robust. It seems to be
well-supported too.

Fixes invalid read accesses with vaapi-copy and dxva2-copy. These
destroyed the hwdec API fully on uninit, and could not deal with
surfaces surviving the decoder.

Probably fixes #1587.

(cherry picked from commit cf073138b2)
2015-02-16 18:15:20 +09:00
wm4 f94318babc x11: fix uninitialized variable reads
This line of code ended up in the wrong block in commit cd6dfcbe.

(cherry picked from commit f247294d73)
2015-02-16 18:15:05 +09:00
wm4 b476d21d0a client API: clarify filename string encoding
Admittedly, the behavior on Windows is not quite straightforward. The
behavior on the other platforms is equivalent to fopen().

Fixes #1585.

(cherry picked from commit a799a4c57f)
2015-02-16 18:14:10 +09:00
Stefano Pigozzi 16c7de4aab cocoa: remove unused function
(cherry picked from commit bf46f4c997)
2015-02-16 18:13:44 +09:00
Martin Herkt 8fdd688d48 x11: add XK_Cancel to the list of special keys
Some IR receivers emit this key by default for remote control
buttons. Make it mappable.

(cherry picked from commit 9aaec7cffb)
2015-02-16 18:13:36 +09:00
wm4 63304b95a1 Fix build on OSX broken by previous commit
Hopefully.

(cherry picked from commit 5247416735)
2015-02-16 18:13:29 +09:00
Julian f4263a811f vf_vapoursynth: add display refresh rate property
This value is not necessarily trustworthy (it might change) and can be
0.

(cherry picked from commit 349067a6ab)
2015-02-16 18:13:22 +09:00
wm4 a6bf8e7c36 x11: return a framerate even if no window is mapped
Falls back to the first display in the list returned by xrandr. Not
entirely correct, but makes some people happy (see #1575).

(cherry picked from commit cd6dfcbef4)
2015-02-16 18:13:15 +09:00
wm4 6488e77d8a player: deprecate 'config' files (use mpv.conf), warn against clashes
Apparently there's at least one distro which ships a /etc/mpv/mpv.conf
file (mpv doesn't install such a file). This breaks config files named
'config' located in the user's mpv config directory, because mpv first
loads files named 'config' and then 'mpv.conf'. There is no mechanism
for putting files with different names into the same config path order.
(Even worse, that mpv.conf file only set an option to the default value.
Why do distros always do very stupid things?)

Print a warning on collisions.

Although using 'config' was well-supported, supporting both names is
starting to become messy, so deprecate 'config' and print a warning if
one is found.

At least we will be able to remove the whole mess once 'config' files
are ignored...

This also affects the osx-bundle, which intentionally used these not-so-
optimal semantics. Solve it in a different way. (Unfortunately with an
ifdef - it's not required, but having to explain everyone why mpv tries
to load a osx-bundle.mpv file on Linux and Windows would consume
energy.)

Closes #1569.

(cherry picked from commit db167cd438)
2015-02-16 18:13:01 +09:00
wm4 34a856f465 command: mark get_property as deprecated
Using it just makes no sense. But we're really being nice about this and
don't remove it immediately.

(cherry picked from commit fd5403cb40)
2015-02-16 18:12:17 +09:00
wm4 db218a8d25 x11: make all XF86 special keys mappable
Makes all keys documented in XF86keysym.h mappable. This requires the
user to deal with numeric keycodes; no names are queried or exported.

This is an easy way to avoid adding all the hundreds of XF86 keys to
our X11 lookup table and mpv's keycode/name list.

(cherry picked from commit 417869f845)
2015-02-16 18:12:04 +09:00
wm4 e3064c3cb7 ipc: put playback core to sleep while dequeuing commands
Happens to fix #1581 due to an unfortunate interaction with the way the
VO does not react to commands for a while if a video frame is queued.
Slightly improves other situations as well, if the client spams mpv with
commands during playback.

(cherry picked from commit 32b56c56ba)
2015-02-16 18:11:52 +09:00
Stefano Pigozzi df4d15be7b vo_opengl: fix smoothmotion coefficient calculation
Using prev_pts as the start of the scale was plain wrong. Change it to
prev_vsync.

(cherry picked from commit 3931544ef3)
2015-02-16 18:09:45 +09:00
wm4 cb5adf4d72 cocoa: fix exiting the command line player
Commit e920a00eb assumed that terminate_cocoa_application() actually
would exit. But apparently that is not always the case; e.g. mpv --help
will just hang. The old code had a dummy exit(0), which was apparently
actually called. Fix by explicitly exiting if mpv_main() returns and
terminate_cocoa_application() does nothing.

(cherry picked from commit 9e14042e57)
2015-02-16 18:09:35 +09:00
wm4 440ba33639 encoding: fixed-vo option was removed
(cherry picked from commit 96547a810e)
2015-02-16 18:09:22 +09:00
wm4 e4eb9c5469 player: add a --loop=force mode
Requested. See manpage additions.

This also makes the magical loop_times constants slightly saner, but
shouldn't change the semantics of any existing --loop option values.

(cherry picked from commit aee0978d50)
2015-02-16 18:09:12 +09:00
wm4 4387919753 osx: move code to unset input context to the right place
Setting the input context is always called, both in cplayer and libmpv,
and under HAVE_COCOA. Unsetting the input context was done only the
cplayer uninit call. Also it was under HAVE_COCOA_APPLICATION, so it was
not unset in libmpv (dangling pointer).

(cherry picked from commit c59a4f12db)
2015-02-16 18:08:58 +09:00
wm4 94123474a4 osx: move cocoa specific call out of common code
This is almost equivalent, and gets rid of the ifdef.
2015-02-16 18:08:52 +09:00
wm4 50a7aac4d7 player: drop explicit exit() calls
The code in main.c calls exit() explicitly, but the code is actually
easier to follow by simply exiting from main() instead. The exit() call
in av_log.c happens only on severely broken builds, so replace it with
abort().

(Shuts up rpmlint warnings.)

(cherry picked from commit e920a00eba)
2015-02-16 18:08:38 +09:00
wm4 2051243a0f ao: set correct client name when listing devices
This is a small oversight. The client name (as set on command line
options or, more importantly, the client API) was not set when listing
devices e.g. via the "audio-device-list" property.

Might or might not fix #1578.

Also adjust the log level for an unrelated message.

(cherry picked from commit c152c59084)
2015-02-16 18:08:17 +09:00
Diogo Franco (Kovensky) a21d09d9f8 Update RELEASE_NOTES formatting 2015-02-13 13:27:38 +09:00
Diogo Franco (Kovensky) b95a0bfa77 Merge remote-tracking branch 'Cpuroast/release/0.8' into release/0.8
* Cpuroast/release/0.8:
  A few tweaks to the 0.80_rc2 release notes
2015-02-13 13:24:30 +09:00
Cpuroast 43f831b6ba A few tweaks to the 0.80_rc2 release notes
scale-radius=3 is the default, so use 2 as an example
Point out that ewa_lanczos (Jinc) is actually new.
2015-02-12 11:39:57 -05:00
wm4 b3eba216b7 Revert "player: make --force-window create the window immediately on start"
This reverts commit acc5e8f574.

As expected, some didn't like this. Others won't like this revert.
Whatever.

See #1561.

This should go into mpv 0.8.0 before it's released.

(cherry picked from commit 7bbc617019)
2015-02-12 21:39:10 +09:00
Diogo Franco (Kovensky) 0668c82da5 Bump version to v0.8.0_rc2 2015-02-12 21:23:45 +09:00
Diogo Franco (Kovensky) c1e8f3b479 Update RELEASE_NOTES 2015-02-12 13:31:03 +09:00
wm4 64a45f972c video/filters: simplify libavfilter bridge
Remove the confusing crap that allowed a filter using the libavfilter
bridge to be compiled without libavfilter. Instead, compile the wrappers
only if libavfilter is enabled at compile time.

The only filter which still requires it is vf_stereo3d (unfortunately).
Special-case this one. (The whole filter and how it interacts with lavfi
is pure braindeath anyway.)

(cherry picked from commit 2522bff565)
2015-02-12 09:53:43 +09:00
wm4 d4207c64e6 vf_noise: remove internal implementation
It requires libavfilter now, just like many other filters. Not sure if
it even makes sense to keep this wrapper.

(cherry picked from commit 73d23a9405)
2015-02-12 09:53:37 +09:00
wm4 abf1fc9a77 af: account for queued frames in audio position calculation
af_rubberband exposed this issue.

(cherry picked from commit d85aa35ffb)
2015-02-12 09:53:27 +09:00
Diogo Franco (Kovensky) da8e573b45 Bump version to -rc1 2015-02-12 00:06:37 +09:00
wm4 25c0097c67 dvb_tune: fix invalid syntax
Oops.
2015-02-11 23:59:35 +09:00
wm4 20d5efb419 audio: fix pool allocation
It reallocated the pool on every request, making the pool completely
useless. Oops.
2015-02-11 23:59:16 +09:00
Diogo Franco (Kovensky) a18b4b2b19 Add preliminary RELEASE_NOTES 2015-02-11 23:57:57 +09:00
wm4 a468e2869d manpage: fix af_scaletempo suggested commands 2015-02-11 23:55:12 +09:00
Diogo Franco (Kovensky) cb9975b942 Branch release/0.8, add -beta VERSION 2015-02-10 22:59:51 +09:00
482 changed files with 24088 additions and 25548 deletions

No files matched your search

+1
View File
@@ -14,6 +14,7 @@
/input/input_conf.h
/tags
/TAGS
/video/out/gl_video_shaders.h
/video/out/x11_icon.inc
/demux/ebml_defs.c
/demux/ebml_types.h
+2 -2
View File
@@ -2,7 +2,7 @@ language: c
os:
- linux
- osx
# - osx
env:
matrix:
- LIBAV=libav-stable
@@ -47,7 +47,7 @@ notifications:
email: false
irc:
channels:
- "irc.freenode.org#mpv-devel"
- "irc.freenode.org#mpv-player-dev"
on_success: change
on_failure: always
+2 -10
View File
@@ -2,15 +2,9 @@ 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
such as LGPLv2+, 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. Files without Copyright notice are licensed as LGPLv2.1+.
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.
to know details. Files without Copyright notice are licensed as LGPLv2+.
For information about authors and contributors, consult the git log, which
contains the complete SVN and CVS history as well.
@@ -23,5 +17,3 @@ 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".
+8 -32
View File
@@ -4,7 +4,9 @@ Introduction
This file lists all changes that can cause compatibility issues when using
mpv through the client API (libmpv and ``client.h``). Since the client API
interfaces to input handling (commands, properties) as well as command line
options, you should also look at ``interface-changes.rst``.
options, this list is interesting for other uses of mpv, such as the Lua
scripting interface, key bindings in ``input.rst``, or plain command line
usage.
Normally, changes to the C API that are incompatible to previous iterations
receive a major version bump (i.e. the first version number is increased),
@@ -18,38 +20,12 @@ The version number is the same as used for MPV_CLIENT_API_VERSION (see
Also, read the section ``Compatibility`` in ``client.h``.
Options, commands, properties
=============================
Changes to these are not listed here, but in ``interface-changes.rst``. (Before
client API version 1.17, they were listed here partially.)
This listing includes changes to the bare C API and behavior only, not what
you can access with them.
API changes
===========
::
--- mpv 0.11.0 ---
1.19 - add "GL_MP_D3D_interfaces" pseudo extension to make it possible to
use DXVA2 in OpenGL fullscreen mode in some situations
- mpv_request_log_messages() now accepts "terminal-default" as parameter
1.18 - add MPV_END_FILE_REASON_REDIRECT, and change behavior of
MPV_EVENT_END_FILE accordingly
- a bunch of interface-changes.rst changes
1.17 - mpv_initialize() now blocks SIGPIPE (details see client.h)
--- mpv 0.9.0 ---
1.16 - add mpv_opengl_cb_report_flip()
- introduce mpv_opengl_cb_draw() and deprecate mpv_opengl_cb_render()
- add MPV_FORMAT_BYTE_ARRAY
1.15 - mpv_initialize() will now load config files. This requires setting
the "config" and "config-dir" options. In particular, it will load
mpv.conf.
- minor backwards-compatible change to the "seek" and "screenshot"
commands (new flag syntax, old additional args deprecated)
--- mpv 0.8.0 ---
--- mpv 0.8.0 is released ---
1.14 - add mpv_wait_async_requests()
- the --msg-level option changes its native type from a flat string to
a key-value list (setting/reading the option as string still works)
@@ -62,7 +38,7 @@ API changes
its own and mpv's OpenGL rendering
Warning: this API is not stable yet - anything in opengl_cb.h might
be changed in completely incompatible ways in minor API bumps
--- mpv 0.7.0 ---
--- mpv 0.7.0 is released ---
1.10 - deprecate/disable everything directly related to script_dispatch
(most likely affects nobody)
1.9 - add enum mpv_end_file_reason for mpv_event_end_file.reason
@@ -85,7 +61,7 @@ API changes
1.6 - modify "core-idle" property behavior
- MPV_EVENT_LOG_MESSAGE now always sends complete lines
- introduce numeric log levels (mpv_log_level)
--- mpv 0.6.0 ---
--- mpv 0.6.0 is released ---
1.5 - change in X11 and "--wid" behavior again. The previous change didn't
work as expected, and now the behavior can be explicitly controlled
with the "input-x11-keyboard" option. This is only a temporary
@@ -94,7 +70,7 @@ API changes
although the old option name still works.
1.4 - subtle change in X11 and "--wid" behavior
(this change was added to 0.5.2, and broke some things, see #1090)
--- mpv 0.5.0 ---
--- mpv 0.5.0 is released ---
1.3 - add MPV_MAKE_VERSION()
1.2 - remove "stream-time-pos" property (no replacement)
1.1 - remap dvdnav:// to dvd://
@@ -106,6 +82,6 @@ API changes
insignificant is now significant
- add "cache-free" and "cache-used" properties
- OSX: the "coreaudio" AO spdif code is split into a separate AO
--- mpv 0.4.0 ---
--- mpv 0.4.0 is released ---
1.0 - the API is declared stable
-5
View File
@@ -24,11 +24,6 @@ qml_direct
Alternative example, which typically avoids a FBO indirection. Might be
slightly faster, but is less flexible and harder to use.
sdl
---
Show how to embed the mpv OpenGL renderer in SDL.
simple
------
@@ -1,304 +0,0 @@
// Plays a video from the command line in an opengl view in its own window.
// Build with: clang -o cocoa-openglcb cocoa-openglcb.m `pkg-config --libs --cflags mpv` -framework Cocoa -framework OpenGL
#import <mpv/client.h>
#import <mpv/opengl_cb.h>
#import <stdio.h>
#import <stdlib.h>
#import <OpenGL/gl.h>
#import <Cocoa/Cocoa.h>
static inline void check_error(int status)
{
if (status < 0) {
printf("mpv API error: %s\n", mpv_error_string(status));
exit(1);
}
}
static void *get_proc_address(void *ctx, const char *name)
{
CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
void *addr = CFBundleGetFunctionPointerForName(CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")), symbolName);
CFRelease(symbolName);
return addr;
}
static void glupdate(void *ctx);
@interface MpvClientOGLView : NSOpenGLView
@property mpv_opengl_cb_context *mpvGL;
- (instancetype)initWithFrame:(NSRect)frame;
- (void)drawRect;
- (void)fillBlack;
@end
@implementation MpvClientOGLView
- (instancetype)initWithFrame:(NSRect)frame
{
// make sure the pixel format is double buffered so we can use
// [[self openGLContext] flushBuffer].
NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFADoubleBuffer,
0
};
self = [super initWithFrame:frame
pixelFormat:[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]];
if (self) {
[self setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
// swap on vsyncs
GLint swapInt = 1;
[[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
[[self openGLContext] makeCurrentContext];
self.mpvGL = nil;
}
return self;
}
- (void)fillBlack
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
}
- (void)drawRect
{
if (self.mpvGL)
mpv_opengl_cb_draw(self.mpvGL, 0, self.bounds.size.width, -self.bounds.size.height);
else
[self fillBlack];
[[self openGLContext] flushBuffer];
}
- (void)drawRect:(NSRect)dirtyRect
{
[self drawRect];
}
@end
@interface CocoaWindow : NSWindow
@property(retain, readonly) MpvClientOGLView *glView;
@property(retain, readonly) NSButton *pauseButton;
@end
@implementation CocoaWindow
- (BOOL)canBecomeMainWindow { return YES; }
- (BOOL)canBecomeKeyWindow { return YES; }
- (void)initOGLView {
NSRect bounds = [[self contentView] bounds];
// window coordinate origin is bottom left
NSRect glFrame = NSMakeRect(bounds.origin.x, bounds.origin.y + 30, bounds.size.width, bounds.size.height - 30);
_glView = [[MpvClientOGLView alloc] initWithFrame:glFrame];
[self.contentView addSubview:_glView];
NSRect buttonFrame = NSMakeRect(bounds.origin.x, bounds.origin.y, 60, 30);
_pauseButton = [[NSButton alloc] initWithFrame:buttonFrame];
_pauseButton.buttonType = NSToggleButton;
// button target has to be the delegate (it holds the mpv context
// pointer), so that's set later.
_pauseButton.action = @selector(togglePause:);
_pauseButton.title = @"Pause";
_pauseButton.alternateTitle = @"Play";
[self.contentView addSubview:_pauseButton];
}
@end
@interface AppDelegate : NSObject <NSApplicationDelegate>
{
mpv_handle *mpv;
dispatch_queue_t queue;
CocoaWindow *window;
}
@end
static void wakeup(void *);
@implementation AppDelegate
- (void)createWindow {
int mask = NSTitledWindowMask|NSClosableWindowMask|
NSMiniaturizableWindowMask|NSResizableWindowMask;
window = [[CocoaWindow alloc]
initWithContentRect:NSMakeRect(0, 0, 1280, 720)
styleMask:mask
backing:NSBackingStoreBuffered
defer:NO];
// force a minimum size to stop opengl from exploding.
[window setMinSize:NSMakeSize(200, 200)];
[window initOGLView];
[window setTitle:@"cocoa-openglcb example"];
[window makeMainWindow];
[window makeKeyAndOrderFront:nil];
NSMenu *m = [[NSMenu alloc] initWithTitle:@"AMainMenu"];
NSMenuItem *item = [m addItemWithTitle:@"Apple" action:nil keyEquivalent:@""];
NSMenu *sm = [[NSMenu alloc] initWithTitle:@"Apple"];
[m setSubmenu:sm forItem:item];
[sm addItemWithTitle: @"quit" action:@selector(terminate:) keyEquivalent:@"q"];
[NSApp setMenu:m];
[NSApp activateIgnoringOtherApps:YES];
}
- (void) applicationDidFinishLaunching:(NSNotification *)notification {
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
atexit_b(^{
// Because activation policy has just been set to behave like a real
// application, that policy must be reset on exit to prevent, among
// other things, the menubar created here from remaining on screen.
[NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];
});
// Read filename
NSArray *args = [NSProcessInfo processInfo].arguments;
if (args.count < 2) {
NSLog(@"Expected filename on command line");
exit(1);
}
NSString *filename = args[1];
[self createWindow];
window.pauseButton.target = self;
mpv = mpv_create();
if (!mpv) {
printf("failed creating context\n");
exit(1);
}
check_error(mpv_set_option_string(mpv, "input-media-keys", "yes"));
// request important errors
check_error(mpv_request_log_messages(mpv, "warn"));
check_error(mpv_initialize(mpv));
check_error(mpv_set_option_string(mpv, "vo", "opengl-cb"));
mpv_opengl_cb_context *mpvGL = mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB);
if (!mpvGL) {
puts("libmpv does not have the opengl-cb sub-API.");
exit(1);
}
// pass the mpvGL context to our view
window.glView.mpvGL = mpvGL;
int r = mpv_opengl_cb_init_gl(mpvGL, NULL, get_proc_address, NULL);
if (r < 0) {
puts("gl init has failed.");
exit(1);
}
mpv_opengl_cb_set_update_callback(mpvGL, glupdate, (__bridge void *)window.glView);
// Deal with MPV in the background.
queue = dispatch_queue_create("mpv", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
// Register to be woken up whenever mpv generates new events.
mpv_set_wakeup_callback(mpv, wakeup, (__bridge void *)self);
// Load the indicated file
const char *cmd[] = {"loadfile", filename.UTF8String, NULL};
check_error(mpv_command(mpv, cmd));
});
}
static void glupdate(void *ctx)
{
MpvClientOGLView *glView = (__bridge MpvClientOGLView *)ctx;
// I'm still not sure what the best way to handle this is, but this
// works.
dispatch_async(dispatch_get_main_queue(), ^{
[glView drawRect];
});
}
- (void) handleEvent:(mpv_event *)event
{
switch (event->event_id) {
case MPV_EVENT_SHUTDOWN: {
mpv_detach_destroy(mpv);
mpv_opengl_cb_uninit_gl(window.glView.mpvGL);
mpv = NULL;
printf("event: shutdown\n");
break;
}
case MPV_EVENT_LOG_MESSAGE: {
struct mpv_event_log_message *msg = (struct mpv_event_log_message *)event->data;
printf("[%s] %s: %s", msg->prefix, msg->level, msg->text);
}
default:
printf("event: %s\n", mpv_event_name(event->event_id));
}
}
- (void)togglePause:(NSButton *)button
{
if (mpv) {
switch (button.state) {
case NSOffState:
{
int pause = 0;
mpv_set_property(mpv, "pause", MPV_FORMAT_FLAG, &pause);
}
break;
case NSOnState:
{
int pause = 1;
mpv_set_property(mpv, "pause", MPV_FORMAT_FLAG, &pause);
}
break;
default:
NSLog(@"This should never happen.");
}
}
}
- (void) readEvents
{
dispatch_async(queue, ^{
while (mpv) {
mpv_event *event = mpv_wait_event(mpv, 0);
if (event->event_id == MPV_EVENT_NONE)
break;
[self handleEvent:event];
}
});
}
static void wakeup(void *context)
{
AppDelegate *a = (__bridge AppDelegate *) context;
[a readEvents];
}
// quit when the window is closed.
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app
{
return YES;
}
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
NSLog(@"Terminating.");
const char *args[] = {"quit", NULL};
mpv_command(mpv, args);
[window.glView clearGLContext];
return NSTerminateNow;
}
@end
// Delete this if you already have a main.m.
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSApplication *app = [NSApplication sharedApplication];
AppDelegate *delegate = [AppDelegate new];
app.delegate = delegate;
[app run];
}
return 0;
}
+6 -4
View File
@@ -1,7 +1,9 @@
// Plays a video from the command line in a view provided by the client
// application.
// Plays a video from the command line in a window provided by mpv.
// You likely want to play the video in your own window instead,
// but that's not quite ready yet.
// You may need a basic Info.plist and MainMenu.xib to make this work.
// Build with: clang -o cocoabasic cocoabasic.m `pkg-config --libs --cflags mpv` -framework cocoa
// Build with: clang -o cocoabasic cocoabasic.m `pkg-config --libs --cflags mpv`
#include <mpv/client.h>
@@ -205,5 +207,5 @@ int main(int argc, const char * argv[]) {
app.delegate = delegate;
[app run];
}
return 0;
return EXIT_SUCCESS;
}
+2 -1
View File
@@ -46,8 +46,9 @@ public:
void render()
{
QOpenGLFramebufferObject *fbo = framebufferObject();
int vp[4] = {0, 0, fbo->width(), fbo->height()};
window->resetOpenGLState();
mpv_opengl_cb_draw(mpv_gl, fbo->handle(), fbo->width(), fbo->height());
mpv_opengl_cb_render(mpv_gl, fbo->handle(), vp);
window->resetOpenGLState();
}
};
-1
View File
@@ -3,7 +3,6 @@ QT += qml quick
HEADERS += main.h
SOURCES += main.cpp
QT_CONFIG -= no-pkg-config
CONFIG += link_pkgconfig debug
PKGCONFIG += mpv
+4 -9
View File
@@ -39,13 +39,15 @@ void MpvRenderer::paint()
{
window->resetOpenGLState();
// Render to the whole window.
int vp[4] = {0, 0, size.width(), -size.height()};
// This uses 0 as framebuffer, which indicates that mpv will render directly
// to the frontbuffer. Note that mpv will always switch framebuffers
// explicitly. Some QWindow setups (such as using QQuickWidget) actually
// want you to render into a FBO in the beforeRendering() signal, and this
// code won't work there.
// The negation is used for rendering with OpenGL's flipped coordinates.
mpv_opengl_cb_draw(mpv_gl, 0, size.width(), -size.height());
mpv_opengl_cb_render(mpv_gl, 0, vp);
window->resetOpenGLState();
}
@@ -94,8 +96,6 @@ void MpvObject::handleWindowChanged(QQuickWindow *win)
this, &MpvObject::sync, Qt::DirectConnection);
connect(win, &QQuickWindow::sceneGraphInvalidated,
this, &MpvObject::cleanup, Qt::DirectConnection);
connect(win, &QQuickWindow::frameSwapped,
this, &MpvObject::swapped, Qt::DirectConnection);
win->setClearBeforeRendering(false);
}
@@ -110,11 +110,6 @@ void MpvObject::sync()
renderer->size = window()->size() * window()->devicePixelRatio();
}
void MpvObject::swapped()
{
mpv_opengl_cb_report_flip(mpv_gl, 0);
}
void MpvObject::cleanup()
{
if (renderer) {
@@ -37,7 +37,6 @@ public:
public slots:
void command(const QVariant& params);
void sync();
void swapped();
void cleanup();
signals:
void onUpdate();
@@ -3,7 +3,6 @@ QT += qml quick
HEADERS += main.h
SOURCES += main.cpp
QT_CONFIG -= no-pkg-config
CONFIG += link_pkgconfig debug
PKGCONFIG += mpv
@@ -5,7 +5,6 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = qtexample
TEMPLATE = app
QT_CONFIG -= no-pkg-config
CONFIG += link_pkgconfig debug
PKGCONFIG += mpv
-158
View File
@@ -1,158 +0,0 @@
// Build with: gcc -o main main.c `pkg-config --libs --cflags mpv sdl2`
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include <mpv/client.h>
#include <mpv/opengl_cb.h>
static Uint32 wakeup_on_mpv_redraw, wakeup_on_mpv_events;
static void die(const char *msg)
{
fprintf(stderr, "%s\n", msg);
exit(1);
}
static void *get_proc_address_mpv(void *fn_ctx, const char *name)
{
return SDL_GL_GetProcAddress(name);
}
static void on_mpv_events(void *ctx)
{
SDL_Event event = {.type = wakeup_on_mpv_events};
SDL_PushEvent(&event);
}
static void on_mpv_redraw(void *ctx)
{
SDL_Event event = {.type = wakeup_on_mpv_redraw};
SDL_PushEvent(&event);
}
int main(int argc, char *argv[])
{
if (argc != 2)
die("pass a single media file as argument");
mpv_handle *mpv = mpv_create();
if (!mpv)
die("context init failed");
// Some minor options can only be set before mpv_initialize().
if (mpv_initialize(mpv) < 0)
die("mpv init failed");
if (SDL_Init(SDL_INIT_VIDEO) < 0)
die("SDL init failed");
SDL_Window *window =
SDL_CreateWindow("hi", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
1000, 500, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN |
SDL_WINDOW_RESIZABLE);
if (!window)
die("failed to create SDL window");
// The OpenGL API is somewhat separate from the normal mpv API. This only
// returns NULL if no OpenGL support is compiled.
mpv_opengl_cb_context *mpv_gl = mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB);
if (!mpv_gl)
die("failed to create mpv GL API handle");
SDL_GLContext glcontext = SDL_GL_CreateContext(window);
if (!glcontext)
die("failed to create SDL GL context");
// This makes mpv use the currently set GL context. It will use the callback
// to resolve GL builtin functions, as well as extensions.
if (mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address_mpv, NULL) < 0)
die("failed to initialize mpv GL context");
// Actually using the opengl_cb state has to be explicitly requested.
// Otherwise, mpv will create a separate platform window.
if (mpv_set_option_string(mpv, "vo", "opengl-cb") < 0)
die("failed to set VO");
// We use events for thread-safe notification of the SDL main loop.
// Generally, the wakeup callbacks (set further below) should do as least
// work as possible, and merely wake up another thread to do actual work.
// On SDL, waking up the mainloop is the ideal course of action. SDL's
// SDL_PushEvent() is thread-safe, so we use that.
wakeup_on_mpv_redraw = SDL_RegisterEvents(1);
wakeup_on_mpv_events = SDL_RegisterEvents(1);
if (wakeup_on_mpv_redraw == (Uint32)-1 || wakeup_on_mpv_events == (Uint32)-1)
die("could not register events");
// When normal mpv events are available.
mpv_set_wakeup_callback(mpv, on_mpv_events, NULL);
// When a new frame should be drawn with mpv_opengl_cb_draw().
// (Separate from the normal event handling mechanism for the sake of
// users which run OpenGL on a different thread.)
mpv_opengl_cb_set_update_callback(mpv_gl, on_mpv_redraw, NULL);
// Play this file. Note that this starts playback asynchronously.
const char *cmd[] = {"loadfile", argv[1], NULL};
mpv_command(mpv, cmd);
while (1) {
SDL_Event event;
if (SDL_WaitEvent(&event) != 1)
die("event loop error");
int redraw = 0;
switch (event.type) {
case SDL_QUIT:
goto done;
case SDL_WINDOWEVENT:
if (event.window.event == SDL_WINDOWEVENT_EXPOSED)
redraw = 1;
break;
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_SPACE)
mpv_command_string(mpv, "cycle pause");
break;
default:
// Happens when a new video frame should be rendered, or if the
// current frame has to be redrawn e.g. due to OSD changes.
if (event.type == wakeup_on_mpv_redraw)
redraw = 1;
// Happens when at least 1 new event is in the mpv event queue.
if (event.type == wakeup_on_mpv_events) {
// Handle all remaining mpv events.
while (1) {
mpv_event *mp_event = mpv_wait_event(mpv, 0);
if (mp_event->event_id == MPV_EVENT_NONE)
break;
printf("event: %s\n", mpv_event_name(mp_event->event_id));
}
}
}
if (redraw) {
int w, h;
SDL_GetWindowSize(window, &w, &h);
// Note:
// - The 0 is the FBO to use; 0 is the default framebuffer (i.e.
// render to the window directly.
// - The negative height tells mpv to flip the coordinate system.
// - If you do not want the video to cover the whole screen, or want
// to apply any form of fancy transformation, you will have to
// render to a FBO.
// - See opengl_cb.h on what OpenGL environment mpv expects, and
// other API details.
mpv_opengl_cb_draw(mpv_gl, 0, w, -h);
SDL_GL_SwapWindow(window);
}
}
done:
// Destroy the GL renderer and all of the GL objects it allocated. If video
// is still running, the video track will be deselected.
mpv_opengl_cb_uninit_gl(mpv_gl);
mpv_terminate_destroy(mpv);
return 0;
}
+2 -3
View File
@@ -79,7 +79,6 @@ export PATH=/opt/mxe/usr/bin/:$PATH
cd ..
git clone https://github.com/mpv-player/mpv.git
cd mpv
python ./bootstrap.py
DEST_OS=win32 TARGET=i686-w64-mingw32.static ./waf configure
# Or, if 64 bit version,
# DEST_OS=win32 TARGET=x86_64-w64-mingw32.static ./waf configure
@@ -134,10 +133,10 @@ pacman -S git pkg-config python3 mingw-w64-x86_64-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
pacman -S mingw-w64-x86_64-ffmpeg mingw-w64-x86_64-libjpeg-turbo mingw-w64-x86_64-lua
# Install additional (optional) dependencies
pacman -S mingw-w64-x86_64-libdvdnav mingw-w64-x86_64-libguess
pacman -S mingw-w64-x86_64-libdvdnav mingw-w64-x86_64-mpg123 mingw-w64-x86_64-libguess
```
For a 32-bit build, install ``mingw-w64-i686-*`` packages instead.
+2 -8
View File
@@ -4,8 +4,8 @@ How to contribute
General
-------
The main contact for mpv development is IRC, specifically #mpv
and #mpv-devel on Freenode.
The main contact for mpv development is IRC, specifically #mpv-player
and #mpv-player-dev on Freenode.
Sending patches
---------------
@@ -14,9 +14,6 @@ Sending patches
``git format-patch``. diffs posted as pastebins (especially if the http link
returns HTML) just cause extra work for everyone, because they lack commit
message and authorship information.
- When creating pull requests, be sure to test your changes. If you didn't, please
say so in the pull request message.
- Write informative commit messages. Use present tense to describe the
situation with the patch applied, and past tense for the situation before
the change.
@@ -54,9 +51,6 @@ Sending patches
change in the same commit.
- If you add a new command line option, document it in options.rst. If you
add a new input property, document it in input.rst.
- All new code must be LGPLv2.1+ licensed, or come with the implicit agreement
that it will be relicensed to LGPLv2.1+ later (see ``Copyright`` in the
repository root directory).
Code formatting
---------------
-90
View File
@@ -1,90 +0,0 @@
Introduction
============
mpv provides access to its internal via the following means:
- options
- commands
- properties
- events
All of these are important for interfacing both with end users and API users
(which include Lua scripts, libmpv, and the JSON IPC). As such, they constitute
a large part of the user interface and APIs.
This document lists changes to them. New changes are added to the top.
Interface changes
=================
::
--- mpv 0.11.0 ---
- add "af-metadata" property
--- mpv 0.10.0 ---
- add --video-aspect-method option
- add --playlist-pos option
- add --video-sync* options
"display-sync-active" property
"vo-missed-frame-count" property
"audio-speed-correction" and "video-speed-correction" properties
- remove --demuxer-readahead-packets and --demuxer-readahead-bytes
add --demuxer-max-packets and --demuxer-max-bytes
(the new options are not replacement and have very different semantics)
- change "video-aspect" property: always settable, even if no video is
running; always return the override - if no override is set, return
the video's aspect ratio
- remove disc-nav (DVD, BD) related properties and commands
- add "option-info/<name>/set-locally" property
- add --cache-backbuffer; change --cache-default default to 75MB
the new total cache size is the sum of backbuffer and the cache size
specified by --cache-default or --cache
- add ``track-list/N/audio-channels`` property
- change --screenshot-tag-colorspace default value
- add --stretch-image-subs-to-screen
- add "playlist/N/title" property
- add --video-stereo-mode=no to disable auto-conversions
- add --force-seekable, and change default seekability in some cases
- add vf yadif/vavpp/vdpaupp interlaced-only suboptions
Also, the option is enabled by default (Except vf_yadif, which has
it enabled only if it's inserted by the deinterlace property.)
- add --hwdec-preload
- add ao coreaudio exclusive suboption
- add ``track-list/N/forced`` property
- add audio-params/channel-count and ``audio-params-out/channel-count props.
- add af volume replaygain-fallback suboption
- add video-params/stereo-in property
- add "keypress", "keydown", and "keyup" commands
- deprecate --ad-spdif-dtshd and enabling passthrough via --ad
add --audio-spdif as replacement
- remove "get_property" command
- remove --slave-broken
- add vo opengl custom shader suboptions (source-shader, scale-shader,
pre-shaders, post-shaders)
- completely change how the hwdec properties work:
- "hwdec" now reflects the --hwdec option
- "hwdec-detected" does partially what the old "hwdec" property did
(and also, "detected-hwdec" is removed)
- "hwdec-active" is added
- add protocol-list property
- deprecate audio-samplerate and audio-channels properties
(audio-params sub-properties are the replacement)
- add audio-params and audio-out-params properties
- deprecate "audio-format" property, replaced with "audio-codec-name"
- deprecate --media-title, replaced with --force-media-title
- deprecate "length" property, replaced with "duration"
- change volume property:
- the value 100 is now always "unchanged volume" - with softvol, the
range is 0 to --softvol-max, without it is 0-100
- the minimum value of --softvol-max is raised to 100
- remove vo opengl npot suboption
- add relative seeking by percentage to "seek" command
- add playlist_shuffle command
- add --force-window=immediate
- add ao coreaudio change-physical-format suboption
- remove vo opengl icc-cache suboption, add icc-cache-dir suboption
- add --screenshot-directory
- add --screenshot-high-bit-depth
- add --screenshot-jpeg-source-chroma
- default action for "rescan_external_files" command changes
--- mpv 0.9.0 ---
+205 -48
View File
@@ -11,10 +11,6 @@ syntax is:
To get a full list of available audio filters, see ``--af=help``.
Also, keep in mind that most actual filters are available via the ``lavfi``
wrapper, which gives you access to most of libavfilter's filters. This
includes all filters that have been ported from MPlayer to libavfilter.
You can also set defaults for each filter. The defaults are applied before the
normal filter parameters.
@@ -63,18 +59,11 @@ Available filters are:
(If you just want to set defaults for this filter that will be used
even by automatically inserted lavrresample instances, you should
prefer setting them with ``--af-defaults=lavrresample:...``.)
``normalize=<yes|no>``
Whether to normalize when remixing channel layouts (default: yes). This
is e.g. applied when downmixing surround audio to stereo. The advantage
is that this guarantees that no clipping can happen. Unfortunately,
this can also lead to too low volume levels. Whether you enable or
disable this is essentially a matter of taste, but the default uses
the safer choice.
``o=<string>``
Set AVOptions on the SwrContext or AVAudioResampleContext. These should
be documented by FFmpeg or Libav.
``lavcac3enc[=tospdif[:bitrate[:minch]]]``
``lavcac3enc[=tospdif[:bitrate[:minchn]]]``
Encode multi-channel audio to AC-3 at runtime using libavcodec. Supports
16-bit native-endian input format, maximum 6 channels. The output is
big-endian when outputting a raw AC-3 stream, native-endian when
@@ -103,10 +92,63 @@ Available filters are:
:5ch: 448
:6ch: 448
``minch=<n>``
If the input channel number is less than ``<minch>``, the filter will
``minchn=<n>``
If the input channel number is less than ``<minchn>``, the filter will
detach itself (default: 3).
``sweep[=speed]``
Produces a sine sweep.
``<0.0-1.0>``
Sine function delta, use very low values to hear the sweep.
``sinesuppress[=freq:decay]``
Remove a sine at the specified frequency. Useful to get rid of the 50/60 Hz
noise on low quality audio equipment. It only works on mono input.
``<freq>``
The frequency of the sine which should be removed (in Hz) (default:
50)
``<decay>``
Controls the adaptivity (a larger value will make the filter adapt to
amplitude and phase changes quicker, a smaller value will make the
adaptation slower) (default: 0.0001). Reasonable values are around
0.001.
``bs2b[=option1:option2:...]``
Bauer stereophonic to binaural transformation using libbs2b. Improves the
headphone listening experience by making the sound similar to that from
loudspeakers, allowing each ear to hear both channels and taking into
account the distance difference and the head shadowing effect. It is
applicable only to 2-channel audio.
``fcut=<300-1000>``
Set cut frequency in Hz.
``feed=<10-150>``
Set feed level for low frequencies in 0.1*dB.
``profile=<value>``
Several profiles are available for convenience:
:default: will be used if nothing else was specified (fcut=700,
feed=45)
:cmoy: Chu Moy circuit implementation (fcut=700, feed=60)
:jmeier: Jan Meier circuit implementation (fcut=650, feed=95)
If ``fcut`` or ``feed`` options are specified together with a profile, they
will be applied on top of the selected profile.
``hrtf[=flag]``
Head-related transfer function: Converts multichannel audio to 2-channel
output for headphones, preserving the spatiality of the sound.
==== ===================================
Flag Meaning
==== ===================================
m matrix decoding of the rear channel
s 2-channel matrix decoding
0 no matrix decoding (default)
==== ===================================
``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
@@ -183,21 +225,14 @@ Available filters are:
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
filter if needed. It is primarily useful for controlling the audio format
going into other filters. To specify the format for audio output, see
``--audio-format``, ``--audio-samplerate``, and ``--audio-channels``. This
filter is able to force a particular format, whereas ``--audio-*``
may be overridden by the ao based on output compatibility.
Force a specific audio format/configuration without actually changing the
audio data. Keep in mind that the filter system might auto-insert actual
conversion filters before or after this filter if needed.
All parameters are optional. The first 3 parameters restrict what the filter
accepts as input. They will therefore cause conversion filters to be
inserted before this one. The ``out-`` parameters tell the filters or audio
outputs following this filter how to interpret the data without actually
doing a conversion. Setting these will probably just break things unless you
really know you want this for some reason, such as testing or dealing with
broken media.
accepts as input. The ``out-`` parameters change the audio format, without
actually doing a conversion. The data will be 'reinterpreted' by the
filters or audio outputs following this filter.
``<format>``
Force conversion to this format. Use ``--af=format=format=help`` to get
@@ -217,9 +252,21 @@ Available filters are:
``<out-channels>``
*NOTE*: this filter used to be named ``force``. The old ``format`` filter
used to do conversion itself, unlike this one which lets the filter system
handle the conversion.
See also ``--audio-format``, ``--audio-samplerate``, and
``--audio-channels`` for related options. Keep in mind that
``--audio-channels`` does not actually force the number of
channels in most cases, while this filter can do this.
*NOTE*: this filter used to be named ``force``. Also, unlike the old
``format`` filter, this does not do any actual conversion anymore.
Conversion is done by other, automatically inserted filters.
``convert24``
Filter for internal use only. Converts between 24-bit and 32-bit sample
formats.
``convertsign``
Filter for internal use only. Converts between signed/unsigned formats.
``volume[=<volumedb>[:...]]``
Implements software volume control. Use this filter with caution since it
@@ -245,10 +292,6 @@ Available filters are:
``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
@@ -312,6 +355,64 @@ Available filters are:
``mpv '--af=format=channels=5.1' '--audio-channels=5.1'`` would always force
remixing audio to 5.1 and output it like this.
``sub[=fc:ch]``
Adds a subwoofer channel to the audio stream. The audio data used for
creating the subwoofer channel is an average of the sound in channel 0 and
channel 1. The resulting sound is then low-pass filtered by a 4th order
Butterworth filter with a default cutoff frequency of 60Hz and added to a
separate channel in the audio stream.
.. warning::
Disable this filter when you are playing media with an LFE channel
(e.g. 5.1 surround sound), otherwise this filter will disrupt the sound
to the subwoofer.
``<fc>``
cutoff frequency in Hz for the low-pass filter (20 Hz to 300 Hz)
(default: 60 Hz) For the best result try setting the cutoff frequency
as low as possible. This will improve the stereo or surround sound
experience.
``<ch>``
Determines the channel number in which to insert the sub-channel
audio. Channel number can be between 0 and 7 (default: 5). Observe
that the number of channels will automatically be increased to <ch> if
necessary.
.. admonition:: Example
``mpv --af=sub=100:4 --audio-channels=5 media.avi``
Would add a subwoofer channel with a cutoff frequency of 100 Hz to
output channel 4.
``center``
Creates a center channel from the front channels. May currently be low
quality as it does not implement a high-pass filter for proper extraction
yet, but averages and halves the channels instead.
``<ch>``
Determines the channel number in which to insert the center channel.
Channel number can be between 0 and 7 (default: 5). Observe that the
number of channels will automatically be increased to ``<ch>`` if
necessary.
``surround[=delay]``
Decoder for matrix encoded surround sound like Dolby Surround. Some files
with 2-channel audio actually contain matrix encoded surround sound.
``<delay>``
delay time in ms for the rear speakers (0 to 1000) (default: 20) This
delay should be set as follows: If d1 is the distance from the
listening position to the front speakers and d2 is the distance from
the listening position to the rear speakers, then the delay should be
set to 15ms if d1 <= d2 and to 15 + 5*(d1-d2) if d1 > d2.
.. admonition:: Example
``mpv --af=surround=15 --audio-channels=4 media.avi``
Would add surround sound decoding with 15 ms delay for the sound to
the rear speakers.
``delay[=[ch1,ch2,...]]``
Delays the sound to the loudspeakers such that the sound from the
different channels arrives at the listening position simultaneously. It is
@@ -340,6 +441,36 @@ Available filters are:
Would delay front left and right by 10.5 ms, the two rear channels
and the subwoofer by 0 ms and the center channel by 7 ms.
``export=mmapped_file:nsamples]``
Exports the incoming signal to other processes using memory mapping
(``mmap()``). Memory mapped areas contain a header::
int nch /* number of channels */
int size /* buffer size */
unsigned long long counter /* Used to keep sync, updated every time
new data is exported. */
The rest is payload (non-interleaved) 16-bit data.
``<mmapped_file>``
File to map data to (required)
``<nsamples>``
number of samples per channel (default: 512).
.. admonition:: Example
``mpv --af=export=/tmp/mpv-af_export:1024 media.avi``
Would export 1024 samples per channel to ``/tmp/mpv-af_export``.
``extrastereo[=mul]``
(Linearly) increases the difference between left and right channels which
adds some sort of "live" effect to playback.
``<mul>``
Sets the difference coefficient (default: 2.5). 0.0 means mono sound
(average of both channels), with 1.0 sound will be unchanged, with
-1.0 left and right channels will be swapped.
``drc[=method:target]``
Applies dynamic range compression. This maximizes the volume by compressing
the audio signal's dynamic range. (Formerly called ``volnorm``.)
@@ -363,6 +494,45 @@ Available filters are:
This filter can cause distortion with audio signals that have a very
large dynamic range.
``ladspa=file:label:[<control0>,<control1>,...]``
Load a LADSPA (Linux Audio Developer's Simple Plugin API) plugin. This
filter is reentrant, so multiple LADSPA plugins can be used at once.
``<file>``
Specifies the LADSPA plugin library file.
.. note::
See also the note about the ``LADSPA_PATH`` variable in the
`ENVIRONMENT VARIABLES`_ section.
``<label>``
Specifies the filter within the library. Some libraries contain only
one filter, but others contain many of them. Entering 'help' here
will list all available filters within the specified library, which
eliminates the use of 'listplugins' from the LADSPA SDK.
``[<control0>,<control1>,...]``
Controls are zero or more ``,`` separated floating point values that
determine the behavior of the loaded plugin (for example delay,
threshold or gain).
In verbose mode (add ``-v`` to the mpv command line), all
available controls and their valid ranges are printed. This eliminates
the use of 'analyseplugin' from the LADSPA SDK.
Note that ``,`` is already used by the option parser to separate
filters, so you must quote the list of values with ``[...]`` or
similar.
.. admonition:: Example
``mpv --af=ladspa='/usr/lib/ladspa/delay.so':delay_5s:[0.5,0.2] media.avi``
Does something.
``karaoke``
Simple voice removal filter exploiting the fact that voice is usually
recorded with mono gear and later 'center' mixed onto the final audio
stream. Beware that this filter will turn your signal into mono. Works
well for 2 channel tracks; do not bother trying it on anything but 2
channel stereo.
``scaletempo[=option1:option2:...]``
Scales audio tempo without altering pitch, optionally synced to playback
speed (default).
@@ -431,20 +601,6 @@ Available filters are:
Changing playback speed would change pitch, leaving audio tempo at
1.2x.
``rubberband``
High quality pitch correction with librubberband. This can be used in place
of ``scaletempo``, and will be used to adjust audio pitch when playing
at speed different from normal.
This filter has a number of sub-options. You can list them with
``mpv --af=rubberband=help``. This will also show the default values
for each option. The options are not documented here, because they are
merely passed to librubberband. Look at the librubberband documentation
to learn what each option does:
http://breakfastquay.com/rubberband/code-doc/classRubberBand_1_1RubberBandStretcher.html
(The mapping of the mpv rubberband filter sub-option names and values to
those of librubberband follows a simple pattern: ``"Option" + Name + Value``.)
``lavfi=graph``
Filter audio using FFmpeg's libavfilter.
@@ -459,3 +615,4 @@ Available filters are:
``o=<string>``
AVOptions.
+17 -42
View File
@@ -55,14 +55,6 @@ Available audio output drivers are:
Allow output of non-interleaved formats (if the audio decoder uses
this format). Currently disabled by default, because some popular
ALSA plugins are utterly broken with non-interleaved formats.
``ignore-chmap``
Don't read or set the channel map of the ALSA device - only request the
required number of channels, and then pass the audio as-is to it. This
option most likely should not be used. It can be useful for debugging,
or for static setups with a specially engineered ALSA configuration (in
this case you should always force the same layout with ``--audio-channels``,
or it will work only for files which use the layout implicit to your
ALSA device).
.. note::
@@ -107,10 +99,8 @@ Available audio output drivers are:
``--audio-device`` to select the device (use ``--audio-device=help``
to get a list of all devices and their mpv name).
You can also try `using the upmix plugin <http://git.io/vfuAy>`_.
This setup enables multichannel audio on the ``default`` device
with automatic upmixing with shared access, so playing stereo
and multichannel audio at the same time will work as expected.
You can also try
`Using the upmix plugin <https://github.com/mpv-player/mpv/wiki/ALSA:-Surround-Sound-and-Upmixing>`_.
``oss``
OSS audio output driver
@@ -162,23 +152,12 @@ Available audio output drivers are:
Automatically redirects to ``coreaudio_exclusive`` when playing compressed
formats.
``change-physical-format=<yes|no>``
Change the physical format to one similar to the requested audio format
(default: no). This has the advantage that multichannel audio output
will actually work. The disadvantage is that it will change the
system-wide audio settings. This is equivalent to changing the ``Format``
setting in the ``Audio Devices`` dialog in the ``Audio MIDI Setup``
utility. Note that this does not effect the selected speaker setup.
``exclusive``
Use exclusive mode access. This merely redirects to
``coreaudio_exclusive``, but should be preferred over using that AO
directly.
``coreaudio_exclusive`` (Mac OS X only)
Native Mac OS X audio output driver using direct device access and
exclusive mode (bypasses the sound server).
Supports only compressed formats (AC3 and DTS).
``openal``
Experimental OpenAL audio output driver
@@ -271,10 +250,6 @@ Available audio output drivers are:
``broken-delay``
Simulate broken audio drivers, which don't report latency correctly.
``channel-layouts``
If not empty, this is a ``,`` separated list of channel layouts the
AO allows. This can be used to test channel layout selection.
``pcm``
Raw PCM/WAVE file writer audio output
@@ -319,19 +294,19 @@ Available audio output drivers are:
``wasapi``
Audio output to the Windows Audio Session API.
``device=<id>``
Uses the requested endpoint instead of the system's default audio
endpoint. Both the number and the ID String are valid; the ID String
is guaranteed to not change unless the driver is uninstalled.
Also supports searching active devices by name. If more than one
device matches the name, refuses loading it.
To get a list of the valid devices, give ``help`` as the id. The
list is the same as the ``list`` suboption, but stops the player
initialization.
``exclusive``
Requests exclusive, direct hardware access. By definition prevents
sound playback of any other program until mpv exits.
``device=<id>``
Uses the requested endpoint instead of the system's default audio
endpoint. Both an ordinal number (0,1,2,...) and the GUID
String are valid; the GUID string is guaranteed to not change
unless the driver is uninstalled.
Also supports searching active devices by human readable name. If more
than one device matches the name, refuses loading it.
This option is mostly deprecated in favour of the more general
``--audio-device`` option. That said, ``--audio-device=help`` will give
a list of valid device GUIDs (prefixed with ``wasapi/``), as well as
their human readable names, which should work here.
``list``
Lists all audio endpoints (output devices) present in the system.
+1 -1
View File
@@ -111,7 +111,7 @@ You can encode files from one format/codec to another using this facility.
.. admonition:: Examples
``"--ovc=mpeg4 --ovcopts=qscale=5"``
``"--ovc=mpeg4 --oacopts=qscale=5"``
selects constant quantizer scale 5 for MPEG-4 encoding.
``"--ovc=libx264 --ovcopts=crf=23"``
+163 -364
View File
@@ -65,11 +65,11 @@ C-style escaping can be used.
You can bind multiple commands to one key. For example:
| a show-text "command 1" ; show-text "command 2"
| a show_text "command 1" ; show_text "command 2"
It's also possible to bind a command to a sequence of keys:
| a-b-c show-text "command run after a, b, c have been pressed"
| a-b-c show_text "command run after a, b, c have been pressed"
(This is not shown in the general command syntax.)
@@ -86,11 +86,11 @@ List of Input Commands
disabling default bindings, without disabling all bindings with
``--no-input-default-bindings``.
``seek <seconds> [relative|absolute|absolute-percent|relative-percent|exact|keyframes]``
``seek <seconds> [relative|absolute|absolute-percent|- [default-precise|exact|keyframes]]``
Change the playback position. By default, seeks by a relative amount of
seconds.
The second argument consists of flags controlling the seek mode:
The second argument sets the seek mode:
relative (default)
Seek relative to current position (a negative value seeks backwards).
@@ -98,41 +98,36 @@ List of Input Commands
Seek to a given time.
absolute-percent
Seek to a given percent position.
relative-percent
Seek relative to current position in percent.
keyframes
Always restart playback at keyframe boundaries (fast).
The third argument defines how exact the seek is:
default-precise (default)
Follow the default behavior as set by ``--hr-seek``, which by default
does imprecise seeks (like ``keyframes``).
exact
Always do exact/hr/precise seeks (slow).
keyframes
Always restart playback at keyframe boundaries (fast).
Multiple flags can be combined, e.g.: ``absolute+keyframes``.
By default, ``keyframes`` is used for relative seeks, and ``exact`` is used
for absolute seeks.
Before mpv 0.9, the ``keyframes`` and ``exact`` flags had to be passed as
3rd parameter (essentially using a space instead of ``+``). The 3rd
parameter is still parsed, but is considered deprecated.
``revert-seek [mode]``
``revert_seek [mode]``
Undoes the ``seek`` command, and some other commands that seek (but not
necessarily all of them). Calling this command once will jump to the
playback position before the seek. Calling it a second time undoes the
``revert-seek`` command itself. This only works within a single file.
``revert_seek`` command itself. This only works within a single file.
The first argument is optional, and can change the behavior:
mark
Mark the current time position. The next normal ``revert-seek`` command
Mark the current time position. The next normal ``revert_seek`` command
will seek back to this point, no matter how many seeks happened since
last time.
Using it without any arguments gives you the default behavior.
``frame-step``
``frame_step``
Play one frame, then pause. Does nothing with audio-only playback.
``frame-back-step``
``frame_back_step``
Go back by one frame, then pause. Note that this can be very slow (it tries
to be precise, not fast), and sometimes fails to behave as expected. How
well this works depends on whether precise seeking works correctly (e.g.
@@ -175,26 +170,31 @@ List of Input Commands
Save the contents of the mpv window. Typically scaled, with OSD and
subtitles. The exact behavior depends on the selected video output, and
if no support is available, this will act like ``video``.
Second argument:
<single> (default)
Take a single screenshot.
<each-frame>
Take a screenshot each frame. Issue this command again to stop taking
screenshots. Note that you should disable frame-dropping when using
this mode - or you might receive duplicate images in cases when a
frame was dropped. This flag can be combined with the other flags,
e.g. ``video+each-frame``.
frame was dropped.
``screenshot-to-file "<filename>" [subtitles|video|window]``
``screenshot_to_file "<filename>" [subtitles|video|window]``
Take a screenshot and save it to a given file. The format of the file will
be guessed by the extension (and ``--screenshot-format`` is ignored - the
behavior when the extension is missing or unknown is arbitrary).
The second argument is like the first argument to ``screenshot``.
If the file already exists, it's overwritten.
This command tries to never overwrite files. If the file already exists,
it fails.
Like all input command parameters, the filename is subject to property
expansion as described in `Property Expansion`_.
``playlist-next [weak|force]``
``playlist_next [weak|force]``
Go to the next entry on the playlist.
weak (default)
@@ -202,7 +202,7 @@ List of Input Commands
force
Terminate playback if there are no more files on the playlist.
``playlist-prev [weak|force]``
``playlist_prev [weak|force]``
Go to the previous entry on the playlist.
weak (default)
@@ -232,26 +232,22 @@ List of Input Commands
``loadlist "<playlist>" [replace|append]``
Load the given playlist file (like ``--playlist``).
``playlist-clear``
``playlist_clear``
Clear the playlist, except the currently played file.
``playlist-remove current|<index>``
``playlist_remove current|<index>``
Remove the playlist entry at the given index. Index values start counting
with 0. The special value ``current`` removes the current entry. Note that
removing the current entry also stops playback and starts playing the next
entry.
``playlist-move <index1> <index2>``
``playlist_move <index1> <index2>``
Move the playlist entry at index1, so that it takes the place of the
entry index2. (Paradoxically, the moved playlist entry will not have
the index value index2 after moving if index1 was lower than index2,
because index2 refers to the target entry, not the index the entry
will have after moving.)
``playlist-shuffle``
Shuffle the playlist. This is similar to what is done on start if the
``--shuffle`` option is used.
``run "command" "arg1" "arg2" ...``
Run the given command. Unlike in MPlayer/mplayer2 and earlier versions of
mpv (0.2.x and older), this doesn't call the shell. Instead, the command
@@ -277,12 +273,12 @@ List of Input Commands
``quit [<code>]``
Exit the player. If an argument is given, it's used as process exit code.
``quit-watch-later [<code>]``
``quit_watch_later [<code>]``
Exit player, and store current playback position. Playing that file later
will seek to the previous position on start. The (optional) argument is
exactly as in the ``quit`` command.
``sub-add "<file>" [<flags> [<title> [<lang>]]]``
``sub_add "<file>" [<flags> [<title> [<lang>]]]``
Load the given subtitle file. It is selected as current subtitle after
loading.
@@ -309,27 +305,27 @@ List of Input Commands
The ``lang`` argument sets the track language, and can also influence
stream selection with ``flags`` set to ``auto``.
``sub-remove [<id>]``
``sub_remove [<id>]``
Remove the given subtitle track. If the ``id`` argument is missing, remove
the current track. (Works on external subtitle files only.)
``sub-reload [<id>]``
``sub_reload [<id>]``
Reload the given subtitle tracks. If the ``id`` argument is missing, reload
the current track. (Works on external subtitle files only.)
This works by unloading and re-adding the subtitle track.
``sub-step <skip>``
``sub_step <skip>``
Change subtitle timing such, that the subtitle event after the next
``<skip>`` subtitle events is displayed. ``<skip>`` can be negative to step
backwards.
``sub-seek <skip>``
``sub_seek <skip>``
Seek to the next (skip set to 1) or the previous (skip set to -1) subtitle.
This is similar to ``sub-step``, except that it seeks video and audio
This is similar to ``sub_step``, except that it seeks video and audio
instead of adjusting the subtitle delay.
Like with ``sub-step``, this works with external text subtitles only. For
Like with ``sub_step``, this works with external text subtitles only. For
embedded text subtitles (like with Matroska), this works only with subtitle
events that have already been displayed.
@@ -337,11 +333,11 @@ List of Input Commands
Toggle OSD level. If ``<level>`` is specified, set the OSD mode
(see ``--osd-level`` for valid values).
``print-text "<string>"``
``print_text "<string>"``
Print text to stdout. The string can contain properties (see
`Property Expansion`_).
``show-text "<string>" [<duration>|- [<level>]]``
``show_text "<string>" [<duration>|- [<level>]]``
Show text on the OSD. The string can contain properties, which are expanded
as described in `Property Expansion`_. This can be used to show playback
time, filename, and so on.
@@ -353,12 +349,24 @@ List of Input Commands
<level>
The minimum OSD level to show the text at (see ``--osd-level``).
``show-progress``
``show_progress``
Show the progress bar, the elapsed time and the total duration of the file
on the OSD.
``write-watch-later-config``
Write the resume config file that the ``quit-watch-later`` command writes,
``discnav "<command>"``
Send a menu control command to the DVD/BD menu implementation. The following
commands are defined: ``up``, ``down``, ``left``, ``right``,
``menu`` (request to enter menu), ``prev`` (previous screen),
``select`` (activate current button), ``mouse`` (the mouse was clicked),
``mouse_move`` (the mouse cursor changed position).
``mouse_move`` will use the current mouse position.
Note that while the menu is active, the input section ``discnav-menu`` will
be enabled, so different key bindings can be mapped for menu mode.
``write_watch_later_config``
Write the resume config file that the ``quit_watch_later`` command writes,
but continue playback normally.
``stop``
@@ -383,46 +391,14 @@ List of Input Commands
<double>
The mouse event represents double-click.
``keypress <key_name>``
Send a key event through mpv's input handler, triggering whatever
behavior is configured to that key. ``key_name`` uses the ``input.conf``
naming scheme for keys and modifiers. Useful for the client API: key events
can be sent to libmpv to handle internally.
``audio_add "<file>" [<flags> [<title> [<lang>]]]``
Load the given audio file. See ``sub_add`` command.
``keydown <key_name>``
Similar to ``keypress``, but sets the ``KEYDOWN`` flag so that if the key is
bound to a repeatable command, it will be run repeatedly with mpv's key
repeat timing until the ``keyup`` command is called.
``audio_remove [<id>]``
Remove the given audio track. See ``sub_remove`` command.
``keyup [<key_name>]``
Set the ``KEYUP`` flag, stopping any repeated behavior that had been
triggered. ``key_name`` is optional. If ``key_name`` is not given or is an
empty string, ``KEYUP`` will be set on all keys. Otherwise, ``KEYUP`` will
only be set on the key specified by ``key_name``.
``audio-add "<file>" [<flags> [<title> [<lang>]]]``
Load the given audio file. See ``sub-add`` command.
``audio-remove [<id>]``
Remove the given audio track. See ``sub-remove`` command.
``audio-reload [<id>]``
Reload the given audio tracks. See ``sub-reload`` command.
``rescan-external-files [<mode>]``
Rescan external files according to the current ``--sub-auto`` and
``--audio-file-auto`` settings. This can be used to auto-load external
files *after* the file was loaded.
The ``mode`` argument is one of the following:
<reselect> (default)
Select the default audio and subtitle streams, which typically selects
external files with highest preference. (The implementation is not
perfect, and could be improved on request.)
<keep-selection>
Do not change current track selections.
``audio_reload [<id>]``
Reload the given audio tracks. See ``sub_reload`` command.
Input Commands that are Possibly Subject to Change
@@ -466,7 +442,7 @@ Input Commands that are Possibly Subject to Change
The ``vf`` command shows the list of requested filters on the OSD after
changing the filter chain. This is roughly equivalent to
``show-text ${vf}``. Note that auto-inserted filters for format conversion
``show_text ${vf}``. Note that auto-inserted filters for format conversion
are not shown on the list, only what was requested by the user.
Normally, the commands will check whether the video chain is recreated
@@ -481,7 +457,7 @@ Input Commands that are Possibly Subject to Change
- ``b vf set ""`` remove all video filters on ``b``
- ``c vf toggle lavfi=gradfun`` toggle debanding on ``c``
``cycle-values ["!reverse"] <property> "<value1>" "<value2>" ...``
``cycle_values ["!reverse"] <property> "<value1>" "<value2>" ...``
Cycle through a list of values. Each invocation of the command will set the
given property to the next value in the list. The command maintains an
internal counter which value to pick next, and which is initially 0. It is
@@ -499,7 +475,7 @@ Input Commands that are Possibly Subject to Change
Note that there is a static limit of (as of this writing) 10 arguments
(this limit could be raised on demand).
``enable-section "<section>" [flags]``
``enable_section "<section>" [default|exclusive]``
Enable all key bindings in the named input section.
The enabled input sections form a stack. Bindings in sections on the top of
@@ -508,45 +484,14 @@ Input Commands that are Possibly Subject to Change
implicitly removed beforehand. (A section cannot be on the stack more than
once.)
The ``flags`` parameter can be a combination (separated by ``+``) of the
following flags:
If ``exclusive`` is specified as second argument, all sections below the
newly enabled section are disabled. They will be re-enabled as soon as
all exclusive sections above them are removed.
<exclusive>
All sections enabled before the newly enabled section are disabled.
They will be re-enabled as soon as all exclusive sections above them
are removed. In other words, the new section shadows all previous
sections.
<allow-hide-cursor>
This feature can't be used through the public API.
<allow-vo-dragging>
Same.
``disable_section "<section>"``
Disable the named input section. Undoes ``enable_section``.
``disable-section "<section>"``
Disable the named input section. Undoes ``enable-section``.
``define-section "<section>" "<contents>" [default|forced]``
Create a named input section, or replace the contents of an already existing
input section. The ``contents`` parameter uses the same syntax as the
``input.conf`` file (except that using the section syntax in it is not
allowed), including the need to separate bindings with a newline character.
If the ``contents`` parameter is an empty string, the section is removed.
The section with the name ``default`` is the normal input section.
In general, input sections have to be enabled with the ``enable-section``
command, or they are ignored.
The last parameter has the following meaning:
<default> (also used if parameter omitted)
Use a key binding defined by this section only if the user hasn't
already bound this key to a command.
<forced>
Always bind a key. (The input section that was made active most recently
wins if there are ambiguities.)
``overlay-add <id> <x> <y> "<file>" <offset> "<fmt>" <w> <h> <stride>``
``overlay_add <id> <x> <y> "<file>" <offset> "<fmt>" <w> <h> <stride>``
Add an OSD overlay sourced from raw data. This might be useful for scripts
and applications controlling mpv, and which want to display things on top
of the video window.
@@ -562,7 +507,7 @@ Input Commands that are Possibly Subject to Change
``id`` is an integer between 0 and 63 identifying the overlay element. The
ID can be used to add multiple overlay parts, update a part by using this
command with an already existing ID, or to remove a part with
``overlay-remove``. Using a previously unused ID will add a new overlay,
``overlay_remove``. Using a previously unused ID will add a new overlay,
while reusing an ID will update it. (Future directions: there should be
something to ensure different programs wanting to create overlays don't
conflict with each others, should that ever be needed.)
@@ -576,11 +521,11 @@ Input Commands that are Possibly Subject to Change
vdpau), so no actual copying is involved. Truncating the source file while
the overlay is active will crash the player. You shouldn't change the data
while the overlay is active, because the data is essentially accessed at
random points. Instead, call ``overlay-add`` again (preferably with a
random points. Instead, call ``overlay_add`` again (preferably with a
different memory region to prevent tearing).
It is also possible to pass a raw memory address for use as bitmap memory
by passing a memory address as integer prefixed with an ``&`` character.
by passing a memory address as integer prefixed with a ``&`` character.
Passing the wrong thing here will crash the player. This mode might be
useful for use with libmpv. The ``offset`` parameter is simply added to the
memory address (since mpv 0.8.0, ignored before).
@@ -620,22 +565,22 @@ Input Commands that are Possibly Subject to Change
an overlay's memory at random times whenever it feels the need to do
so, for example when redrawing the screen.
``overlay-remove <id>``
Remove an overlay added with ``overlay-add`` and the same ID. Does nothing
``overlay_remove <id>``
Remove an overlay added with ``overlay_add`` and the same ID. Does nothing
if no overlay with this ID exists.
``script-message "<arg1>" "<arg2>" ...``
``script_message "<arg1>" "<arg2>" ...``
Send a message to all clients, and pass it the following list of arguments.
What this message means, how many arguments it takes, and what the arguments
mean is fully up to the receiver and the sender. Every client receives the
message, so be careful about name clashes (or use ``script_message_to``).
``script-message-to "<target>" "<arg1>" "<arg2>" ...``
``script_message_to "<target>" "<arg1>" "<arg2>" ...``
Same as ``script_message``, but send it only to the client named
``<target>``. Each client (scripts etc.) has a unique name. For example,
Lua scripts can get their name via ``mp.get_script_name()``.
``script-binding "<name>"``
``script_binding "<name>"``
Invoke a script-provided key binding. This can be used to remap key
bindings provided by external Lua scripts.
@@ -656,40 +601,31 @@ Input Commands that are Possibly Subject to Change
tracked). The second letter whether the event originates from the mouse,
either ``m`` (mouse button) or ``-`` (something else).
``ab-loop``
``ab_loop``
Cycle through A-B loop states. The first command will set the ``A`` point
(the ``ab-loop-a`` property); the second the ``B`` point, and the third
will clear both points.
``vo-cmdline "<args>"``
``vo_cmdline "<args>"``
Reset the sub-option of the current VO. Currently works with ``opengl``
(including ``opengl-hq``). The argument is the sub-option string usually
passed to the VO on the command line. Not all sub-options can be set, but
those which can will be reset even if they don't appear in the argument.
This command might be changed or removed in the future.
``drop-buffers``
``drop_buffers``
Drop audio/video/demuxer buffers, and restart from fresh. Might help with
unseekable streams that are going out of sync.
This command might be changed or removed in the future.
``screenshot-raw [subtitles|video|window]``
Return a screenshot in memory. This can be used only through the client
API. The MPV_FORMAT_NODE_MAP returned by this command has the ``w``, ``h``,
``stride`` fields set to obvious contents. A ``format`` field is set to
``bgr0`` by default. This format is organized as ``B8G8R8X8`` (where ``B``
is the LSB). The contents of the padding ``X`` is undefined. The ``data``
field is of type MPV_FORMAT_BYTE_ARRAY with the actual image data. The image
is freed as soon as the result node is freed.
Undocumented commands: ``tv-last-channel`` (TV/DVB only),
``ao-reload`` (experimental/internal).
Undocumented commands: ``tv_last_channel`` (TV/DVB only),
``get_property`` (deprecated), ``ao_reload`` (experimental/internal).
Hooks
~~~~~
Hooks are synchronous events between player core and a script or similar. This
applies to client API (including the Lua scripting interface). Normally,
applies to the Lua scripting interface and the client API and only. Normally,
events are supposed to be asynchronous, and the hook API provides an awkward
and obscure way to handle events that require stricter coordination. There are
no API stability guarantees made. Not following the protocol exactly can make
@@ -698,7 +634,7 @@ the player freeze randomly. Basically, nobody should use this API.
There are two special commands involved. Also, the client must listen for
client messages (``MPV_EVENT_CLIENT_MESSAGE`` in the C API).
``hook-add <hook-name> <id> <priority>``
``hook_add <hook-name> <id> <priority>``
Subscribe to the hook identified by the first argument (basically, the
name of event). The ``id`` argument is an arbitrary integer chosen by the
user. ``priority`` is used to sort all hook handlers globally across all
@@ -723,9 +659,9 @@ client messages (``MPV_EVENT_CLIENT_MESSAGE`` in the C API).
typically be stopped.
When the client is done, it must continue the core's hook execution by
running the ``hook-ack`` command.
running the ``hook_ack`` command.
``hook-ack <string>``
``hook_ack <string>``
Run the next hook in the global chain of hooks. The argument is the 3rd
argument of the client message that starts hook execution for the
current client.
@@ -798,7 +734,7 @@ Properties
Properties are used to set mpv options during runtime, or to query arbitrary
information. They can be manipulated with the ``set``/``add``/``cycle``
commands, and retrieved with ``show-text``, or anything else that uses property
commands, and retrieved with ``show_text``, or anything else that uses property
expansion. (See `Property Expansion`_.)
The property name is annotated with RW to indicate whether the property is
@@ -826,16 +762,6 @@ Property list
``speed`` (RW)
See ``--speed``.
``audio-speed-correction``, ``video-speed-correction``
Factor multiplied with ``speed`` at which the player attempts to play the
file. Usually it's exactly 1. (Display sync mode will make this useful.)
OSD formatting will display it in the form of ``+1.23456%``, with the number
being ``(raw - 1) * 100`` for the given raw property value.
``display-sync-active``
Return whether ``--video-sync=display`` is actually active.
``filename``
Currently played file, with path stripped. If this is an URL, try to undo
percent encoding as well. (The result is not necessarily correct, but
@@ -888,14 +814,11 @@ Property list
``stream-end``
Raw end position in bytes in source stream.
``duration``
Duration of the current file in seconds. If the duration is unknown, the
``length``
Length of the current file in seconds. If the length is unknown, the
property is unavailable. Note that the file duration is not always exactly
known, so this is an estimate.
This replaces the ``length`` property, which was deprecated after the
mpv 0.9 release. (The semantics are the same.)
``avsync``
Last A/V synchronization difference. Unavailable if audio or video is
disabled.
@@ -931,12 +854,10 @@ Property list
always exactly known, so this is an estimate.
``playtime-remaining``
``time-remaining`` scaled by the current ``speed``.
``time-remaining`` scaled by the the current ``speed``.
``playback-time`` (RW)
The playback time, which is the time relative to playback start. (This can
be different from the ``time-pos`` property if the file does not start at
position ``0``, in which case ``time-pos`` is the source timestamp.)
``playback-time``
Return the playback time, which is the time difference between start PTS and current PTS.
``chapter`` (RW)
Current chapter number. The number of the first chapter is 0.
@@ -979,6 +900,12 @@ Property list
Current BD/DVD title number. Writing works only for ``dvdnav://`` and
``bd://`` (and aliases for these).
``disc-menu-active``
Return ``yes`` if the BD/DVD menu is active, or ``no`` on normal video
playback. The property is unavailable when playing something that is not
a BD or DVD. Use the ``discnav menu`` command to actually enter or leave
menu mode.
``chapters``
Number of chapters.
@@ -1091,9 +1018,6 @@ Property list
An example of these kind of metadata are the cropping parameters
added by ``--vf=lavfi=cropdetect``.
``af-metadata/<filter-label>``
Equivalent to ``vf-metadata/<filter-label>``, but for audio filters.
``pause`` (RW)
Pause status. This is usually ``yes`` or ``no``. See ``--pause``.
@@ -1114,13 +1038,11 @@ Property list
Network cache fill state (0-100.0).
``cache-size`` (RW)
Network cache size in KB. This is similar to ``--cache``. This allows
Total network cache size in KB. This is similar to ``--cache``. This allows
to set the cache size at runtime. Currently, it's not possible to enable
or disable the cache at runtime using this property, just to resize an
existing cache.
This does not include the backbuffer size (changed after mpv 0.10.0).
Note that this tries to keep the cache contents as far as possible. To make
this easier, the cache resizing code will allocate the new cache while the
old cache is still allocated.
@@ -1142,11 +1064,6 @@ Property list
guess is very unreliable, and often the property will not be available
at all, even if data is buffered.
``demuxer-cache-time``
Approximate time of video buffered in the demuxer, in seconds. Same as
``demuxer-cache-duration`` but returns the last timestamp of buffered
data in demuxer.
``demuxer-cache-idle``
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.
@@ -1178,7 +1095,7 @@ Property list
See ``--hr-seek``.
``volume`` (RW)
Current volume (see ``--volume`` for details).
Current volume (0-100).
``mute`` (RW)
Current mute status (``yes``/``no``).
@@ -1186,52 +1103,21 @@ Property list
``audio-delay`` (RW)
See ``--audio-delay``.
``audio-format``
Audio format as string.
``audio-codec``
Audio codec selected for decoding.
``audio-codec-name``
Audio codec.
``audio-bitrate``
Audio bitrate. This is probably a very bad guess in most cases.
``audio-params``
Audio format as output by the audio decoder.
This has a number of sub-properties:
``audio-samplerate``
Audio samplerate.
``audio-params/format``
The sample format as string. This uses the same names as used in other
places of mpv.
``audio-params/samplerate``
Samplerate.
``audio-params/channels``
The channel layout as a string. This is similar to what the
``--audio-channels`` accepts.
``audio-params/hr-channels``
As ``channels``, but instead of the possibly cryptic actual layout
sent to the audio device, return a hopefully more human readable form.
(Usually only ``audio-out-params/hr-channels`` makes sense.)
``audio-params/channel-count``
Number of audio channels. This is redundant to the ``channels`` field
described above.
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
"format" MPV_FORMAT_STRING
"samplerate" MPV_FORMAT_INT64
"channels" MPV_FORMAT_STRING
"channel-count" MPV_FORMAT_INT64
"hr-channels" MPV_FORMAT_STRING
``audio-out-params``
Same as ``audio-params``, but the format of the data written to the audio
API.
``audio-channels``
Number of audio channels. The OSD value of this property is actually the
channel layout, while the raw value returns the number of channels only.
``aid`` (RW)
Current audio track (similar to ``--aid``).
@@ -1242,7 +1128,7 @@ Property list
``balance`` (RW)
Audio channel balance. (The implementation of this feature is rather odd.
It doesn't change the volumes of each channel, but instead sets up a pan
matrix to mix the left and right channels.)
matrix to mix the the left and right channels.)
``fullscreen`` (RW)
See ``--fullscreen``.
@@ -1253,18 +1139,17 @@ Property list
``field-dominance`` (RW)
See ``--field-dominance``
``colormatrix`` (R)
Redirects to ``video-params/colormatrix``. This parameter (as well as
similar ones) can be overridden with the ``format`` video filter.
``colormatrix`` (RW)
See ``--colormatrix``.
``colormatrix-input-range`` (R)
See ``colormatrix``.
``colormatrix-input-range`` (RW)
See ``--colormatrix-input-range``.
``colormatrix-output-range`` (R)
See ``colormatrix``.
``colormatrix-output-range`` (RW)
See ``--colormatrix-output-range``.
``colormatrix-primaries`` (R)
See ``colormatrix``.
``colormatrix-primaries`` (RW)
See ``--colormatrix-primaries``.
``ontop`` (RW)
See ``--ontop``.
@@ -1294,29 +1179,25 @@ Property list
See ``--hue``.
``hwdec`` (RW)
Reflects the ``--hwdec`` option.
Return the current hardware decoder that is used. This uses the same values
as the ``--hwdec`` option. If software decoding is active, this returns
``no``. You can write this property. Then the ``--hwdec`` option is set to
the new value, and video decoding will be reinitialized (internally, the
player will perform a seek to refresh the video properly).
Writing to it may change the currently used hardware decoder, if possible.
(Internally, the player may reinitialize the decoder, and will perform a
seek to refresh the video properly.) You can watch the other hwdec
properties to see whether this was successful.
Note that you don't know the success of the operation immediately after
writing this property. It happens with a delay as video is reinitialized.
Unlike in mpv 0.9.x and before, this does not return the currently active
hardware decoder.
``detected-hwdec``
Return the current hardware decoder that was detected and opened. Returns
the same values as ``hwdec``.
``hwdec-active``
Return ``yes`` or ``no``, depending on whether any type of hardware decoding
is actually in use.
``hwdec-detected``
If software decoding is active, this returns the hardware decoder in use.
Otherwise, it returns either ``no``, or if applicable, the currently loaded
hardware decoding API. This is known only once the VO has opened (and
possibly later). With some VOs (like ``opengl``), this is never known in
advance, but only when the decoder attempted to create the hw decoder
successfully. Also, hw decoders with ``-copy`` suffix will return ``no``
while no video is being decoded. All this reflects how detecting hw decoders
are detected and used internally in mpv.
This is known only once the VO has opened (and possibly later). With some
VOs (like ``opengl``), this is never known in advance, but only when the
decoder attempted to create the hw decoder successfully. Also, hw decoders
with ``-copy`` suffix are returned only while hw decoding is active (and
unset afterwards). All this reflects how detecting hw decoders are
detected and used internally in mpv.
``panscan`` (RW)
See ``--panscan``.
@@ -1327,6 +1208,9 @@ Property list
``video-codec``
Video codec selected for decoding.
``video-bitrate``
Video bitrate (a bad guess).
``width``, ``height``
Video size. This uses the size of the video as decoded, or if no video
frame has been decoded yet, the (possibly incorrect) container indicated
@@ -1371,38 +1255,32 @@ Property list
``video-params/primaries``
The primaries in use as string. (Exact values subject to change.)
``video-params/gamma``
The gamma function in use as string. (Exact values subject to change.)
``video-params/chroma-location``
Chroma location as string. (Exact values subject to change.)
``video-params/rotate``
Intended display rotation in degrees (clockwise).
``video-params/stereo-in``
Source file stereo 3D mode. (See ``--video-stereo-mode`` option.)
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
"pixelformat" MPV_FORMAT_STRING
"w" MPV_FORMAT_INT64
"h" MPV_FORMAT_INT64
"dw" MPV_FORMAT_INT64
"dh" MPV_FORMAT_INT64
"aspect" MPV_FORMAT_DOUBLE
"par" MPV_FORMAT_DOUBLE
"colormatrix" MPV_FORMAT_STRING
"colorlevels" MPV_FORMAT_STRING
"primaries" MPV_FORMAT_STRING
"chroma-location" MPV_FORMAT_STRING
"rotate" MPV_FORMAT_INT64
"stereo-in" MPV_FORMAT_STRING
MPV_FORMAT_NODE_ARRAY
MPV_FORMAT_NODE_MAP (for each track)
"pixelformat" MPV_FORMAT_STRING
"w" MPV_FORMAT_INT64
"h" MPV_FORMAT_INT64
"dw" MPV_FORMAT_INT64
"dh" MPV_FORMAT_INT64
"aspect" MPV_FORMAT_DOUBLE
"par" MPV_FORMAT_DOUBLE
"colormatrix" MPV_FORMAT_STRING
"colorlevels" MPV_FORMAT_STRING
"primaries" MPV_FORMAT_STRING
"chroma-location" MPV_FORMAT_STRING
"rotate" MPV_FORMAT_INT64
``dwidth``, ``dheight``
Video display size. This is the video size after filters and aspect scaling
@@ -1447,13 +1325,6 @@ Property list
Names of the displays that the mpv window covers. On X11, these
are the xrandr names (LVDS1, HDMI1, DP1, VGA1, etc.).
``display-fps``
The refresh rate of the current display. Currently, this is the lowest FPS
of any display covered by the video, as retrieved by the underlying system
APIs (e.g. xrandr on X11). It is not the measured FPS. It's not necessarily
available on all platforms. Note that any of the listed facts may change
any time without a warning.
``video-aspect`` (RW)
Video aspect, see ``--video-aspect``.
@@ -1510,11 +1381,8 @@ Property list
``sub-scale`` (RW)
Subtitle font size multiplier.
``ass-force-margins`` (RW)
See ``--ass-force-margins``.
``sub-use-margins`` (RW)
See ``--sub-use-margins``.
``ass-use-margins`` (RW)
See ``--ass-use-margins``.
``ass-vsfilter-aspect-compat`` (RW)
See ``--ass-vsfilter-aspect-compat``.
@@ -1556,11 +1424,6 @@ Property list
been unloaded yet; in this case, ``current`` refers to the new
selection. (Since mpv 0.7.0.)
``playlist/N/title``
Name of the Nth entry. Only available if the playlist file contains
such fields, and only if mpv's parser supports it for the given
playlist format.
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:
@@ -1572,7 +1435,6 @@ Property list
"filename" MPV_FORMAT_STRING
"current" MPV_FORMAT_FLAG (might be missing; since mpv 0.7.0)
"playing" MPV_FORMAT_FLAG (same)
"title" MPV_FORMAT_STRING (optional)
``track-list``
List of audio/video/sub tracks, current entry marked. Currently, the raw
@@ -1600,10 +1462,6 @@ Property list
``track-list/N/lang``
Track language as identified by the file. Not always available.
``track-list/N/audio-channels``
For audio tracks, the number of audio channels in the audio stream.
Not always accurate (depends on container hints). Not always available.
``track-list/N/albumart``
``yes`` if this is a video track that consists of a single picture,
``no`` or unavailable otherwise. This is used for video tracks that are
@@ -1613,10 +1471,6 @@ Property list
``yes`` if the track has the default flag set in the file, ``no``
otherwise.
``track-list/N/forced``
``yes`` if the track has the forced flag set in the file, ``no``
otherwise.
``track-list/N/codec``
The codec name used by this track, for example ``h264``. Unavailable
in some rare cases.
@@ -1632,13 +1486,6 @@ Property list
``track-list/N/selected``
``yes`` if the track is currently decoded, ``no`` otherwise.
``track-list/N/ff-index``
The stream index as usually used by the FFmpeg utilities. Note that
this can be potentially wrong if a demuxer other than libavformat
(``--demuxer=lavf``) is used. For mkv files, the index will usually
match even if the default (builtin) demuxer is used, but there is
no hard guarantee.
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:
@@ -1652,10 +1499,8 @@ Property list
"src-id" MPV_FORMAT_INT64
"title" MPV_FORMAT_STRING
"lang" MPV_FORMAT_STRING
"audio-channels" MPV_FORMAT_INT64
"albumart" MPV_FORMAT_FLAG
"default" MPV_FORMAT_FLAG
"forced" MPV_FORMAT_FLAG
"external" MPV_FORMAT_FLAG
"external-filename" MPV_FORMAT_STRING
"codec" MPV_FORMAT_STRING
@@ -1734,7 +1579,7 @@ Property list
``osd-sym-cc``
Inserts the current OSD symbol as opaque OSD control code (cc). This makes
sense only with the ``show-text`` command or options which set OSD messages.
sense only with the ``show_text`` command or options which set OSD messages.
The control code is implementation specific and is useless for anything else.
``osd-ass-cc``
@@ -1742,13 +1587,13 @@ Property list
``${osd-ass-cc/1}`` enables it again. By default, ASS sequences are
escaped to avoid accidental formatting, and this property can disable
this behavior. Note that the properties return an opaque OSD control
code, which only makes sense for the ``show-text`` command or options
code, which only makes sense for the ``show_text`` command or options
which set OSD messages.
.. admonition:: Example
- ``--osd-status-msg='This is ${osd-ass-cc/0}{\\b1}bold text'``
- ``show-text "This is ${osd-ass-cc/0}{\b1}bold text"``
- ``show_text "This is ${osd-ass-cc/0}{\b1}bold text"``
Any ASS override tags as understood by libass can be used.
@@ -1762,7 +1607,7 @@ Property list
whether the video window is visible. If the ``--force-window`` option is
used, this is usually always returns ``yes``.
``video-bitrate``, ``audio-bitrate``, ``sub-bitrate``
``packet-video-bitrate``, ``packet-audio-bitrate``, ``packet-sub-bitrate``
Bitrate values calculated on the packet level. This works by dividing the
bit size of all packets between two keyframes by their presentation
timestamp distance. (This uses the timestamps are stored in the file, so
@@ -1771,29 +1616,8 @@ Property list
bitrate. To make the property more UI friendly, updates to these properties
are throttled in a certain way.
The unit is bits per second. OSD formatting turns these values in kilobits
(or megabits, if appropriate), which can be prevented by using the
raw property value, e.g. with ``${=video-bitrate}``.
Note that the accuracy of these properties is influenced by a few factors.
If the underlying demuxer rewrites the packets on demuxing (done for some
file formats), the bitrate might be slightly off. If timestamps are bad
or jittery (like in Matroska), even constant bitrate streams might show
fluctuating bitrate.
How exactly these values are calculated might change in the future.
In earlier versions of mpv, these properties returned a static (but bad)
guess using a completely different method.
``packet-video-bitrate``, ``packet-audio-bitrate``, ``packet-sub-bitrate``
Old and deprecated properties for ``video-bitrate``, ``audio-bitrate``,
``sub-bitrate``. They behave exactly the same, but return a value in
kilobits. Also, they don't have any OSD formatting, though the same can be
achieved with e.g. ``${=video-bitrate}``.
These properties shouldn't be used anymore.
``audio-device-list``
Return the list of discovered audio devices. This is mostly for use with
the client API, and reflects what ``--audio-device=help`` with the command
@@ -1815,13 +1639,6 @@ Property list
human readable free form text. The description is an empty string if none
was received.
The special entry with the name set to ``auto`` selects the default audio
output driver and the default device.
The property can be watched with the property observation mechanism in
the client API and in Lua scripts. (Technically, change notification is
enabled the first time this property is read.)
``audio-device`` (RW)
Set the audio device. This directly reads/writes the ``--audio-device``
option, but on write accesses, the audio output will be scheduled for
@@ -1845,16 +1662,6 @@ Property list
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.
``protocol-list``
List of protocol prefixes potentially recognized by the player. They are
returned without trailing ``://`` suffix (which is still always required).
In some cases, the protocol will not actually be supported (consider
``https`` if ffmpeg is not compiled with TLS support).
``mpv-version``
Return the mpv version/copyright string. Depending on how the binary was
built, it might contain either a release version, or just a git hash.
@@ -1894,16 +1701,11 @@ Property list
For many complex types, this isn't very accurate.
``option-info/<name>/set-from-commandline``
Return ``yes`` if the option was set from the mpv command line,
``no`` otherwise. What this is set to if the option is e.g. changed
at runtime is left undefined (meaning it could change in the future).
``option-info/<name>/set-locally``
Return ``yes`` if the option was set per-file. This is the case with
automatically loaded profiles, file-dir configs, and other cases. It
means the option value will be restored to the value before playback
start when playback ends.
``option-info/<name>/default-value``
The default value of the option. May not always be available.
@@ -1926,14 +1728,11 @@ Property Expansion
------------------
All string arguments to input commands as well as certain options (like
``--term-playing-msg``) are subject to property expansion. Note that property
expansion does not work in places where e.g. numeric parameters are expected.
(For example, the ``add`` command does not do property expansion. The ``set``
command is an exception and not a general rule.)
``--term-playing-msg``) are subject to property expansion.
.. admonition:: Example for input.conf
``i show-text "Filename: ${filename}"``
``i show_text "Filename: ${filename}"``
shows the filename of the current file when pressing the ``i`` key
Within ``input.conf``, property expansion can be inhibited by putting the
-21
View File
@@ -79,27 +79,6 @@ mpv will also send events to clients with JSON messages of the following form:
where ``event_name`` is the name of the event. Additional event-specific fields
can also be present. See `List of events`_ for a list of all supported events.
Because events can occur at any time, it may be difficult at times to determine
which response goes with which command. Commands may optionally include a
``request_id`` which, if provided in the command request, will be copied
verbatim into the response. mpv does not intrepret the ``request_id`` in any
way; it is solely for the use of the requester.
For example, this request:
::
{ "command": ["get_property", "time-pos"], "request_id": 100 }
Would generate this response:
::
{ "error": "success", "data": 1.468135, "request_id": 100 }
All commands, replies, and events are separated from each other with a line
break character (``\n``).
If the first character (after skipping whitespace) is not ``{``, the command
will be interpreted as non-JSON text command, as they are used in input.conf
(or ``mpv_command_string()`` in the client API). Additionally, line starting
+2 -64
View File
@@ -73,10 +73,6 @@ The ``mp`` module is preloaded, although it can be loaded manually with
Run the given command. This is similar to the commands used in input.conf.
See `List of Input Commands`_.
By default, this will show something on the OSD (depending on the command),
as if it was used in ``input.conf``. See `Input Command Prefixes`_ how
to influence OSD usage per command.
Returns ``true`` on success, or ``nil, error`` on error.
``mp.commandv(arg1, arg2, ...)``
@@ -98,9 +94,6 @@ The ``mp`` module is preloaded, although it can be loaded manually with
the ``expand-properties`` prefix, or the ``mp.get_property`` family of
functions.
Unlike ``mp.command``, this will not use OSD by default either (except
for some OSD-specific commands).
``mp.command_native(table [,def])``
Similar to ``mp.commandv``, but pass the argument list as table. This has
the advantage that in at least some cases, arguments can be passed as
@@ -333,6 +326,7 @@ The ``mp`` module is preloaded, although it can be loaded manually with
the timer is re-added after the function fn is run.
Returns a timer object. The timer object provides the following methods:
``stop()``
Disable the timer. Does nothing if the timer is already disabled.
This will remember the current elapsed time when stopping, so that
@@ -363,23 +357,6 @@ The ``mp`` module is preloaded, although it can be loaded manually with
(``true``). This value is used when the timer expires (but before
the timer callback function fn is run).
Note that these are method, and you have to call them using ``:`` instead
of ``.`` (Refer to http://www.lua.org/manual/5.2/manual.html#3.4.9 .)
Example:
::
seconds = 0
timer = mp.add_periodic_timer(1, function()
print("called every second")
# stop it after 10 seconds
seconds = seconds + 1
if seconds >= 10 then
timer:kill()
end
end)
``mp.get_opt(key)``
Return a setting from the ``--script-opts`` option. It's up to the user and
@@ -519,7 +496,7 @@ Example implementation::
optionC = true,
}
read_options(options, "myscript")
print(options.optionA)
print(option.optionA)
The config file will be stored in ``lua-settings/identifier.conf`` in mpv's user
@@ -630,10 +607,6 @@ strictly part of the guaranteed API.
On Windows, ``killed`` is only returned when the process has been
killed by mpv as a result of ``cancellable`` being set to ``true``.
``killed_by_us``
Set to ``true`` if the process has been killed by mpv as a result
of ``cancellable`` being set to ``true``.
In all cases, ``mp.resume_all()`` is implicitly called.
``utils.parse_json(str [, trail])``
@@ -650,14 +623,6 @@ strictly part of the guaranteed API.
trailing text is returned as 3rd return value. (The 3rd return value is
always there, but with ``trail`` set, no error is raised.)
``utils.format_json(v)``
Format the given Lua table (or value) as a JSON string and return it. On
error, returns ``nil, error``. (Errors usually only happen on value types
incompatible with JSON.)
The argument value uses similar conventions as ``mp.set_property_native()``
to distinguish empty objects and arrays.
``utils.to_string(v)``
Turn the given value into a string. Formats tables and their contents. This
doesn't do anything special; it is only needed because Lua is terrible.
@@ -694,33 +659,6 @@ List of events
Happens after a file was unloaded. Typically, the player will load the
next file right away, or quit if this was the last file.
The event has the ``reason`` field, which takes one of these values:
``eof``
The file has ended. This can (but doesn't have to) include
incomplete files or broken network connections under
circumstances.
``stop``
Playback was ended by a command.
``quit``
Playback was ended by sending the quit command.
``error``
An error happened. In this case, an ``error`` field is present with
the error string.
``redirect``
Happens with playlists and similar. Details see
``MPV_END_FILE_REASON_REDIRECT`` in the C API.
``unknown``
Unknown. Normally doesn't happen, unless the Lua API is out of sync
with the C API. (Likewise, it could happen that your script gets
reason strings that did not exist yet at the time your script was
written.)
``file-loaded``
Happens after a file was loaded and begins playback.
+39 -116
View File
@@ -32,10 +32,8 @@ INTERACTIVE CONTROL
===================
mpv has a fully configurable, command-driven control layer which allows you
to control mpv using keyboard, mouse, or remote control (there is no
LIRC support - configure remotes as input devices instead).
See the ``--input-`` options for ways to customize it.
to control mpv using keyboard, mouse, joystick or remote control (with
LIRC). See the ``--input-`` options for ways to customize it.
Keyboard Control
----------------
@@ -116,7 +114,11 @@ o (also P)
Show progression bar, elapsed time and total duration on the OSD.
O
Toggle OSD states between normal and playback time/duration.
Toggle OSD states: none / seek / seek + timer / seek + timer + total time.
d
Toggle frame dropping states: none / skip display / skip decoding (see
``--framedrop``).
v
Toggle subtitle visibility.
@@ -130,17 +132,9 @@ x and z
l
Set/clear A-B loop points. See ``ab_loop`` command for details.
L
Toggle infinite looping.
Ctrl + and Ctrl -
Adjust audio delay by +/- 0.1 seconds.
u
Switch between applying no style overrides to SSA/ASS subtitles, and
overriding them almost completely with the normal subtitle style. See
``--ass-style-override`` for more info.
V
Toggle subtitle VSFilter aspect compatibility mode. See
``--ass-vsfilter-aspect-compat`` for more info.
@@ -155,10 +149,6 @@ S
Take a screenshot, without subtitles. (Whether this works depends on VO
driver support.)
Ctrl s
Take a screenshot, as the window shows it (with subtitles, OSD, and scaled
video).
I
Show filename on the OSD.
@@ -171,7 +161,7 @@ Shift+PGUP and Shift+PGDWN
Seek backward or forward by 10 minutes. (This used to be mapped to
PGUP/PGDWN without Shift.)
d
D
Activate/deactivate deinterlacer.
A
@@ -276,19 +266,17 @@ spaces or characters like ``,`` or ``:``, you need to quote them:
``mpv '--vo=opengl:icc-profile="file with spaces.icc",xv'``
Shells may actually strip some quotes from the string passed to the commandline,
so the example quotes the string twice, ensuring that mpv receives the ``"``
so the example quotes the string twice, ensuring that mpv recieves the ``"``
quotes.
The ``[...]`` form of quotes wraps everything between ``[`` and ``]``. It's
The ``[...]`` from of quotes wraps everything between ``[`` and ``]``. It's
useful with shells that don't interpret these characters in the middle of
an argument (like bash). These quotes are balanced (since mpv 0.9.0): the ``[``
and ``]`` nest, and the quote terminates on the last ``]`` that has no matching
``[`` within the string. (For example, ``[a[b]c]`` results in ``a[b]c``.)
an argument (like bash).
The fixed-length quoting syntax is intended for use with external
scripts and programs.
A special kind of string-escaping intended for use with external scripts and
programs is started with ``%``.
It is started with ``%`` and has the following format::
It has the following format::
%n%string_of_length_n
@@ -305,7 +293,7 @@ Suboptions passed to the client API are also subject to escaping. Using
command line (but without shell processing of the string). Some options
support passing values in a more structured way instead of flat strings, and
can avoid the suboption parsing mess. For example, ``--vf`` supports
``MPV_FORMAT_NODE``, which lets you pass suboptions as a nested data structure
``MPV_FORMAT_NODE``, which let's you pass suboptions as a nested data structure
of maps and arrays. (``--vo`` supports this in the same way, although this
fact is undocumented.)
@@ -324,23 +312,12 @@ console controls. (Which makes it suitable for playing data piped to stdin.)
For paths passed to suboptions, the situation is further complicated by the
need to escape special characters. To work this around, the path can be
additionally wrapped in the fixed-length syntax, e.g. ``%n%string_of_length_n``
(see above).
additionally wrapped in the ``%n%string_of_length_n`` syntax (see above).
Some mpv options interpret paths starting with ``~``. Currently, the prefix
``~~/`` expands to the mpv configuration directory (usually ``~/.config/mpv/``).
``~/`` expands to the user's home directory. (The trailing ``/`` is always
required.) There are the following paths as well:
================ ===============================================================
Name Meaning
================ ===============================================================
``~~home/`` same as ``~~/``
``~~global/`` the global config path, if available (not on win32)
``~~osxbundle/`` the OSX bundle resource path (OSX only)
``~~desktop/`` the path to the desktop (win32, OSX)
================ ===============================================================
required.)
Per-File Options
----------------
@@ -391,8 +368,7 @@ Location and Syntax
You can put all of the options in configuration files which will be read every
time mpv is run. The system-wide configuration file 'mpv.conf' is in your
configuration directory (e.g. ``/etc/mpv`` or ``/usr/local/etc/mpv``), the
user-specific one is ``~/.config/mpv/mpv.conf``. For details and platform
specifics see the `FILES`_ section.
user-specific one is ``~/.config/mpv/mpv.conf``.
User-specific options override system-wide options and options given on the
command line override either. The syntax of the configuration files is
``option=<value>``; everything after a *#* is considered a comment. Options
@@ -414,10 +390,10 @@ Escaping spaces and special characters
This is done like with command line options. The shell is not involved here,
but option values still need to be quoted as a whole if it contains certain
characters like spaces. A config entry can be quoted with ``"`` and ``'``,
as well as with the fixed-length syntax (``%n%``) mentioned before. This is like
passing the exact contents of the quoted string as command line option. C-style
escapes are currently _not_ interpreted on this level, although some options do
this manually. (This is a mess and should probably be changed at some point.)
as well as with the ``%n%`` syntax mentioned before. This is like passing
the exact contents of the quoted string as command line option. C-style escapes
are currently _not_ interpreted on this level, although some options to this
manually. (This is a mess and should probably be changed at some point.)
Putting Command Line Options into the Configuration File
--------------------------------------------------------
@@ -492,8 +468,11 @@ A screenshot will usually contain the unscaled video contents at the end of the
video filter chain and subtitles. By default, ``S`` takes screenshots without
subtitles, while ``s`` includes subtitles.
Unlike with MPlayer, the ``screenshot`` video filter is not required. This
filter was never required in mpv, and has been removed.
The ``screenshot`` video filter is not required when using a recommended GUI
video output driver. It should normally not be added to the config file, as
taking screenshots is handled by the VOs, and adding the screenshot filter will
break hardware decoding. (The filter may still be useful for taking screenshots
at a certain point within the video chain when using multiple video filters.)
TERMINAL STATUS LINE
====================
@@ -526,22 +505,15 @@ listed.
if there is audio "missing", or not enough frames can be dropped. Usually
this will indicate a problem. (``total-avsync-change`` property.)
- Encoding state in ``{...}``, only shown in encoding mode.
- Display sync state. If display sync is active (``display-sync-active``
property), this shows ``DS: +0.02598%``, where the number is the speed change
factor applied to audio to achieve sync to display, expressed in percent
deviation from 1.0 (``audio-speed-correction`` property). In sync modes which
don't resample, this will always be ``+0.00000%``.
- Missed frames, e.g. ``Missed: 4``. (``vo-missed-frame-count`` property.) Shows
up in display sync mode only. This is incremented each time a frame took
longer to display than intended.
- Dropped frames, e.g. ``Dropped: 4``. Shows up only if the count is not 0. Can
grow if the video framerate is higher than that of the display, or if video
rendering is too slow. Also can be incremented on "hiccups" and when the video
frame couldn't be displayed on time. (``vo-drop-frame-count`` property.)
If the decoder drops frames, the number of decoder-dropped frames is appended
to the display as well, e.g.: ``Dropped: 4/34``. This happens only if
decoder frame dropping is enabled with the ``--framedrop`` options.
(``drop-frame-count`` property.)
to the display as well, e.g.: ``Dropped: 4/34``. This should almost never
happen, unless decoder-framedropping is enabled with one of the
``--framedrop`` options, the stream contains errors, or a weird codec is in
use. (``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
@@ -571,9 +543,13 @@ PROTOCOLS
you must mount the ISO file as filesystem, and point ``--bluray-device``
to the mounted directory directly.
``bdnav://[title][/device]``
Play a Blu-Ray disc, with navigation features enabled. This feature is
permanently experimental.
``dvd://[title|[starttitle]-endtitle][/device]`` ``--dvd-device=PATH``
Play a DVD. DVD menus are not supported. If no title is given, the longest
title is auto-selected.
Play a DVD. If you want dvdnav menus, use ``dvd://menu``. If no title
is given, the longest title is auto-selected.
``dvdnav://`` is an old alias for ``dvd://`` and does exactly the same
thing.
@@ -618,11 +594,6 @@ PROTOCOLS
``PATH`` itself should start with a third ``/`` to make the path an
absolute path.
``fd://123``
Read data from the given UNIX FD (for example 123). This is similar to
piping data to stdin via ``-``, but can use an arbitrary file descriptor.
Will not work correctly on MS Windows.
``edl://[edl specification as in edl-mpv.rst]``
Stitch together parts of multiple files and play them.
@@ -632,40 +603,6 @@ PROTOCOLS
``memory://data``
Use the ``data`` part as source data.
PSEUDO GUI MODE
===============
mpv has no official GUI, other than the OSC (`ON SCREEN CONTROLLER`_), which
is not a full GUI and is not meant to be. However, to compensate for the lack
of expected GUI behavior, mpv will in some cases start with some settings
changed to behave slightly more like a GUI mode.
Currently this happens only in the following cases:
- if started using the ``mpv.desktop`` file on Linux (e.g. started from menus
or file associations provided by desktop environments)
- if started from explorer.exe on Windows (technically, if it was started on
Windows, and all of the stdout/stderr/stdin handles are unset)
- manually adding ``--profile=pseudo-gui`` to the command line
This mode implicitly adds ``--profile=pseudo-gui`` to the command line, with
the ``pseudo-gui`` profile being predefined with the following contents:
::
[pseudo-gui]
terminal=no
force-window=yes
idle=once
screenshot-directory=~~desktop/
This follows the mpv config file format. To customize pseudo-GUI mode, you can
put your own ``pseudo-gui`` profile into your ``mpv.conf``. This profile will
enhance the default profile, rather than overwrite it.
The profile always overrides other settings in ``mpv.conf``.
.. include:: options.rst
.. include:: ao.rst
@@ -812,8 +749,6 @@ If errors happen, the following exit codes can be returned:
immediately after initialization.
:3: There were some files that could be played, and some files which
couldn't (using the definition of success from above).
:4: Quit due to a signal, Ctrl+c in a VO window (by default), or from the
default quit key bindings in encoding mode.
Note that quitting the player manually will always lead to exit code 0,
overriding the exit code that would be returned normally. Also, the ``quit``
@@ -822,15 +757,11 @@ input command can take an exit code: in this case, that exit code is returned.
FILES
=====
For Windows-specifics, see `FILES ON WINDOWS`_ section.
``/usr/local/etc/mpv/mpv.conf``
mpv system-wide settings (depends on ``--prefix`` passed to configure - mpv
in default configuration will use ``/usr/local/etc/mpv/`` as config
directory, while most Linux distributions will set it to ``/etc/mpv/``).
mpv system-wide settings (depends on ``--prefix`` passed to configure)
``~/.config/mpv/mpv.conf``
mpv user settings (see `CONFIGURATION FILES`_ section)
mpv user settings
``~/.config/mpv/input.conf``
key bindings (see `INPUT.CONF`_ section)
@@ -885,14 +816,6 @@ Other config files (such as ``input.conf``) are in the same directory. See the
The environment variable ``$MPV_HOME`` completely overrides these, like on
UNIX.
If a directory named ``portable_config`` next to the mpv.exe exists, all
config will be loaded from this directory only. Watch later config files are
written to this directory as well. (This exists on Windows only and is redundant
with ``$MPV_HOME``. However, since Windows is very scripting unfriendly, a
wrapper script just setting ``$MPV_HOME``, like you could do it on other
systems, won't work. ``portable_config`` is provided for convenience to get
around this restriction.)
Config files located in the same directory as ``mpv.exe`` are loaded with
lower priority. Some config files are loaded only once, which means that
e.g. of 2 ``input.conf`` files located in two config directories, only the
+234 -405
View File
File diff suppressed because it is too large. Load diff
+11 -20
View File
@@ -5,7 +5,7 @@ The On Screen Controller (short: OSC) is a minimal GUI integrated with mpv to
offer basic mouse-controllability. It is intended to make interaction easier
for new users and to enable precise and direct seeking.
The OSC is enabled by default if mpv was compiled with Lua support. It can be
The OSC is enabled by default if mpv was compiled with lua support. It can be
disabled entirely using the ``--osc=no`` option.
Using the OSC
@@ -169,35 +169,34 @@ Configurable Options
``showwindowed``
| Default: yes
| Enable the OSC when windowed
| Show OSC when windowed?
``showfullscreen``
| Default: yes
| Enable the OSC when fullscreen
| Show OSC when fullscreen?
``scalewindowed``
| Default: 1.0
| Scale factor of the OSC when windowed
| Default: 1
| Scaling of the controller when windowed
``scalefullscreen``
| Default: 1.0
| Scale factor of the OSC when fullscreen
| Default: 1
| Scaling of the controller when fullscreen
``scaleforcedwindow``
| Default: 2.0
| Scale factor of the OSC when rendered on a forced (dummy) window
| Default: 2
| Scaling of the controller when rendered on a forced (dummy) window
``vidscale``
| Default: yes
| Scale the OSC with the video
| ``no`` tries to keep the OSC size constant as much as the window size allows
| Scale the controller with the video?
``valign``
| Default: 0.8
| Vertical alignment, -1 (top) to 1 (bottom)
``halign``
| Default: 0.0
| Default: 0
| Horizontal alignment, -1 (left) to 1 (right)
``boxalpha``
@@ -235,14 +234,6 @@ Configurable Options
| Default: slider
| Sets the style of the seekbar, slider (diamond marker) or bar (fill)
``timetotal``
| Default: no
| Show total time instead of time remaining
``timems``
| Default: no
| Display timecodes with milliseconds
Script Commands
~~~~~~~~~~~~~~~
+95 -169
View File
@@ -17,10 +17,6 @@ normal filter parameters.
To get a full list of available video filters, see ``--vf=help``.
Also, keep in mind that most actual filters are available via the ``lavfi``
wrapper, which gives you access to most of libavfilter's filters. This
includes all filters that have been ported from MPlayer to libavfilter.
Video filters are managed in lists. There are a few commands to manage the
filter list.
@@ -101,7 +97,7 @@ Available filters are:
All parameters are optional.
``<w>:<h>``
``<w>,<h>``
scaled width/height (default: original width/height)
:0: scaled d_width/d_height
@@ -156,7 +152,7 @@ Available filters are:
number (1.33). Alternatively, you may specify the exact display width and
height desired. 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.
auto-scaling to correct aspect.
``<w>,<h>``
New display width and height.
@@ -202,7 +198,7 @@ Available filters are:
``<aspect>``
Force an aspect ratio.
``format=fmt=<value>:colormatrix=<value>:...``
``format[=fmt[:outfmt]]``
Restricts the color space for the next filter without doing any conversion.
Use together with the scale filter for a real conversion.
@@ -211,148 +207,19 @@ Available filters are:
For a list of available formats, see ``format=fmt=help``.
``<fmt>``
Format name, e.g. rgb15, bgr24, 420p, etc. (default: don't change).
Format name, e.g. rgb15, bgr24, 420p, etc. (default: yuyv).
``<outfmt>``
Format name that should be substituted for the output. If they do not
have the same bytes per pixel and chroma subsamplimg, it will fail.
``<colormatrix>``
Controls the YUV to RGB color space conversion when playing video. There
are various standards. Normally, BT.601 should be used for SD video, and
BT.709 for HD video. (This is done by default.) Using incorrect color space
results in slightly under or over saturated and shifted colors.
Format name that should be substituted for the output. If this is not
100% compatible with the ``<fmt>`` value, it will crash.
These options are not always supported. Different video outputs provide
varying degrees of support. The ``opengl`` and ``vdpau`` video output
drivers usually offer full support. The ``xv`` output can set the color
space if the system video driver supports it, but not input and output
levels. The ``scale`` video filter can configure color space and input
levels, but only if the output format is RGB (if the video output driver
supports RGB output, you can force this with ``-vf scale,format=rgba``).
If this option is set to ``auto`` (which is the default), the video's
color space flag will be used. If that flag is unset, the color space
will be selected automatically. This is done using a simple heuristic that
attempts to distinguish SD and HD video. If the video is larger than
1279x576 pixels, BT.709 (HD) will be used; otherwise BT.601 (SD) is
selected.
Available color spaces are:
:auto: automatic selection (default)
:bt.601: ITU-R BT.601 (SD)
:bt.709: ITU-R BT.709 (HD)
:bt.2020-ncl: ITU-R BT.2020 non-constant luminance system
:bt.2020-cl: ITU-R BT.2020 constant luminance system
:smpte-240m: SMPTE-240M
``<colorlevels>``
YUV color levels used with YUV to RGB conversion. This option is only
necessary when playing broken files which do not follow standard color
levels or which are flagged wrong. If the video does not specify its
color range, it is assumed to be limited range.
The same limitations as with ``<colormatrix>`` apply.
Available color ranges are:
:auto: automatic selection (normally limited range) (default)
:limited: limited range (16-235 for luma, 16-240 for chroma)
:full: full range (0-255 for both luma and chroma)
``<outputlevels>``
RGB color levels used with YUV to RGB conversion. Normally, output devices
such as PC monitors use full range color levels. However, some TVs and
video monitors expect studio RGB levels. Providing full range output to a
device expecting studio level input results in crushed blacks and whites,
the reverse in dim gray blacks and dim whites.
The same limitations as with ``<colormatrix>`` apply.
Available color ranges are:
:auto: automatic selection (equals to full range) (default)
:limited: limited range (16-235 per component), studio levels
:full: full range (0-255 per component), PC levels
.. note::
It is advisable to use your graphics driver's color range option
instead, if available.
``<primaries>``
RGB primaries the source file was encoded with. Normally this should be set
in the file header, but when playing broken or mistagged files this can be
used to override the setting.
This option only affects video output drivers that perform color
management, for example ``opengl`` with the ``target-prim`` or
``icc-profile`` suboptions set.
If this option is set to ``auto`` (which is the default), the video's
primaries flag will be used. If that flag is unset, the color space will
be selected automatically, using the following heuristics: If the
``<colormatrix>`` is set or determined as BT.2020 or BT.709, the
corresponding primaries are used. Otherwise, if the video height is
exactly 576 (PAL), BT.601-625 is used. If it's exactly 480 or 486 (NTSC),
BT.601-525 is used. If the video resolution is anything else, BT.709 is
used.
Available primaries are:
:auto: automatic selection (default)
:bt.601-525: ITU-R BT.601 (SD) 525-line systems (NTSC, SMPTE-C)
:bt.601-625: ITU-R BT.601 (SD) 625-line systems (PAL, SECAM)
:bt.709: ITU-R BT.709 (HD) (same primaries as sRGB)
:bt.2020: ITU-R BT.2020 (UHD)
:apple: Apple RGB
:adobe: Adobe RGB (1998)
:prophoto: ProPhoto RGB (ROMM)
:cie1931: CIE 1931 RGB
``<gamma>``
Gamma function the source file was encoded with. Normally this should be set
in the file header, but when playing broken or mistagged files this can be
used to override the setting.
This option only affects video output drivers that perform color management.
If this option is set to ``auto`` (which is the default), the gamma will
be set to BT.1886 for YCbCr content, sRGB for RGB content and Linear for
XYZ content.
Available gamma functions are:
:auto: automatic selection (default)
:bt.1886: ITU-R BT.1886 (approximation of BT.601/BT.709/BT.2020 curve)
:srgb: IEC 61966-2-4 (sRGB)
:linear: Linear light
:gamma1.8: Pure power curve (gamma 1.8)
:gamma2.2: Pure power curve (gamma 2.2)
:gamma2.8: Pure power curve (gamma 2.8)
:prophoto: ProPhoto RGB (ROMM) curve
``<stereo-in>``
Set the stereo mode the video is assumed to be encoded in. Takes the
same values as the ``--video-stereo-mode`` option.
``<stereo-out>``
Set the stereo mode the video should be displayed as. Takes the
same values as the ``--video-stereo-mode`` option.
``<rotate>``
Set the rotation the video is assumed to be encoded with in degrees.
The special value ``-1`` uses the input format.
``<dw>``, ``<dh>``
Set the display size. Note that setting the display size such that
the video is scaled in both directions instead of just changing the
aspect ratio is an implementation detail, and might change later.
``<dar>``
Set the display aspect ratio of the video frame. This is a float,
but values such as ``[16:9]`` can be passed too (``[...]`` for quoting
to prevent the option parser from interpreting the ``:`` character).
.. admonition:: Examples
====================== =====================
Valid Invalid (will crash)
====================== =====================
``format=rgb24:bgr24`` ``format=rgb24:420p``
``format=yuyv:uyvy``
====================== =====================
``noformat[=fmt]``
Restricts the color space for the next filter without doing any conversion.
@@ -413,6 +280,41 @@ Available filters are:
``'--vf=lavfi=yadif:o="threads=2,thread_type=slice"'``
forces a specific threading configuration.
``noise[=<strength>[:averaged][:pattern][:temporal][:uniform][:hq]``
Adds noise.
``strength``
Set the noise for all components. If you want different strength
values for luma and chroma, use libavfilter's noise filter directly
(using ``--vf=lavfi=[noise=...]``), or tell the libavfilter developers
to stop being stupid.
``averaged``
averaged temporal noise (smoother, but a lot slower)
``pattern``
mix random noise with a (semi)regular pattern
``temporal``
temporal noise (noise pattern changes between frames)
``uniform``
uniform noise (Gaussian otherwise)
``hqdn3d[=luma_spatial:chroma_spatial:luma_tmp:chroma_tmp]``
This filter aims to reduce image noise producing smooth images and making
still images really still (This should enhance compressibility.).
``<luma_spatial>``
spatial luma strength (default: 4)
``<chroma_spatial>``
spatial chroma strength (default: 3)
``<luma_tmp>``
luma temporal strength (default: 6)
``<chroma_tmp>``
chroma temporal strength (default:
``luma_tmp*chroma_spatial/luma_spatial``)
``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
@@ -439,6 +341,23 @@ Available filters are:
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).
``unsharp[=lx:ly:la:cx:cy:ca]``
unsharp mask / Gaussian blur
``l`` is for the luma component, ``c`` for the chroma component. ``x``/``y``
is the filter size. ``a`` is the amount.
``lx``, ``ly``, ``cx``, ``cy``
width and height of the matrix, odd sized in both directions (min =
3:3, max = 13:11 or 11:13, usually something between 3:3 and 7:7)
``la``, ``ca``
Relative amount of sharpness/blur to add to the image (a sane range
should be -1.5-1.5).
:<0: blur
:>0: sharpen
``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
@@ -470,7 +389,7 @@ Available filters are:
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]``
``yadif=[mode[:enabled=yes|no]]``
Yet another deinterlacing filter
``<mode>``
@@ -479,10 +398,10 @@ Available filters are:
:frame-nospatial: Like ``frame`` but skips spatial interlacing check.
:field-nospatial: Like ``field`` but skips spatial interlacing check.
``<interlaced-only>``
:no: Deinterlace all frames (default).
:yes: Only deinterlace frames marked as interlaced (default if this
filter is inserted via ``deinterlace`` property).
``<enabled>``
:yes: Filter is active (default).
:no: Filter is not active, but can be activated with the ``D`` key
(or any other key that toggles the ``deinterlace`` property).
This filter, is automatically inserted when using the ``D`` key (or any
other key that toggles the ``deinterlace`` property or when using the
@@ -497,6 +416,28 @@ Available filters are:
when inserting yadif with ``--vf``, so using the above methods is
recommended.
``delogo[=x:y:w:h:t:show]``
Suppresses a TV station logo by a simple interpolation of the surrounding
pixels. Just set a rectangle covering the logo and watch it disappear (and
sometimes something even uglier appear - your mileage may vary).
``<x>,<y>``
top left corner of the logo
``<w>,<h>``
width and height of the cleared rectangle
``<t>``
Thickness of the fuzzy edge of the rectangle (added to ``w`` and
``h``). When set to -1, a green rectangle is drawn on the screen to
simplify finding the right ``x``,``y``,``w``,``h`` parameters.
``show``
Draw a rectangle showing the area defined by x/y/w/h.
``screenshot``
Optional filter for screenshot support. This is only needed if the video
output does not provide working direct screenshot support. Note that it is
not always safe to insert this filter by default. See `TAKING SCREENSHOTS`_
for details.
``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
@@ -504,9 +445,9 @@ Available filters are:
``<bottom-margin>``
Adds a black band at the bottom of the frame. The SSA/ASS renderer can
place subtitles there (with ``--sub-use-margins``).
place subtitles there (with ``--ass-use-margins``).
``<top-margin>``
Black band on the top for toptitles (with ``--sub-use-margins``).
Black band on the top for toptitles (with ``--ass-use-margins``).
.. admonition:: Examples
@@ -605,8 +546,6 @@ Available filters are:
Loads an external library to filter the image. The library interface
is the ``vf_dlopen`` interface specified using ``libmpcodecs/vf_dlopen.h``.
.. warning:: This filter is deprecated.
``dll=<library>``
Specify the library to load. This may require a full file system path
in some cases. This argument is required.
@@ -716,7 +655,7 @@ Available filters are:
``vapoursynth-lazy``
The same as ``vapoursynth``, but doesn't load Python scripts. Instead, a
custom backend using Lua and the raw VapourSynth API is used. The syntax
is completely different, and absolutely no convenience features are
is completely different, and absolutely no conveniencve features are
provided. There's no type checking either, and you can trigger crashes.
.. admonition:: Example:
@@ -758,10 +697,6 @@ Available filters are:
depends on the GPU hardware, the GPU drivers, driver bugs, and
mpv bugs.
``<interlaced-only>``
:no: Deinterlace all frames.
:yes: Only deinterlace frames marked as interlaced (default).
``vdpaupp``
VDPAU video post processing. Works with ``--vo=vdpau`` and ``--vo=opengl``
only. This filter is automatically inserted if deinterlacing is requested
@@ -806,21 +741,12 @@ Available filters are:
``pullup``
Try to apply inverse telecine, needs motion adaptive temporal
deinterlacing.
``interlaced-only=<yes|no>``
If ``yes`` (default), only deinterlace frames marked as interlaced.
``hqscaling=<0-9>``
0
Use default VDPAU scaling (default).
1-9
Apply high quality VDPAU scaling (needs capable hardware).
``vdpaurb``
VDPAU video read back. Works with ``--vo=vdpau`` and ``--vo=opengl`` only.
This filter will read back frames decoded by VDPAU so that other filters,
which are not normally compatible with VDPAU, can be used like normal.
This filter must be specified before ``vdpaupp`` in the filter chain if
``vdpaupp`` is used.
``buffer=<num>``
Buffer ``<num>`` frames in the filter chain. This filter is probably pretty
useless, except for debugging. (Note that this won't help smoothing out
+130 -388
View File
@@ -69,11 +69,11 @@ Available video output drivers are:
``no-colorkey``
Disables color-keying.
``buffers=<number>``
Number of image buffers to use for the internal ringbuffer (default: 2).
Increasing this will use more memory, but might help with the X server
not responding quickly enough if video FPS is close to or higher than
the display refresh rate.
``x11`` (X11 only)
Shared memory video output driver without hardware acceleration that works
whenever X11 is present.
.. note:: This is a fallback only, and should not be normally used.
``vdpau`` (X11 only)
Uses the VDPAU interface to display and optionally also decode video.
@@ -290,26 +290,6 @@ Available video output drivers are:
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 ``fbo-format`` suboption 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 passing the
``dumb-mode=yes`` sub-option.
``dumb-mode=<yes|no>``
This mode is extremely restricted, and will disable most extended
OpenGL features. This includes high quality scalers and custom
shaders!
It is intended for hardware that does not support FBOs (including GLES,
which supports it insufficiently), or to get some more performance out
of bad or old hardware.
This mode is forced automatically if needed, and this option is mostly
useful for debugging.
``scale=<filter>``
``bilinear``
@@ -328,75 +308,36 @@ Available video output drivers are:
This filter corresponds to the old ``lanczos3`` alias if the default
radius is used, while ``lanczos2`` corresponds to a radius of 2.
(This filter is an alias for ``sinc``-windowed ``sinc``)
``ewa_lanczos``
Elliptic weighted average Lanczos scaling. Also known as Jinc.
Relatively slow, but very good quality. The radius can be
controlled with ``scale-radius``. Increasing the radius makes the
Relatively slow, but very good quality. The number of taps can
be controlled with ``scale-radius``. Adding extra taps makes the
filter sharper but adds more ringing.
(This filter is an alias for ``jinc``-windowed ``jinc``)
``ewa_lanczossharp``
A slightly sharpened version of ewa_lanczos, preconfigured to use
an ideal radius and parameter. If your hardware can run it, this is
probably what you should use by default.
This filter supports antiringing (see ``scale-antiring``).
``mitchell``
Mitchell-Netravali. The ``B`` and ``C`` parameters can be set with
``scale-param1`` and ``scale-param2``. This filter is very good at
downscaling (see ``dscale``).
``oversample``
A version of nearest neighbour that (naively) oversamples pixels,
so that pixels overlapping edges get linearly interpolated instead
of rounded. This essentially removes the small imperfections and
judder artifacts caused by nearest-neighbour interpolation, in
exchange for adding some blur. This filter is good at temporal
interpolation, and also known as "smoothmotion" (see ``tscale``).
``custom``
A user-defined custom shader (see ``scale-shader``).
Mitchell-Netravali. The ``b`` and ``c`` parameters can be set with
``scale-param1`` and ``scale-param2``. Both are set to 1/3 by default.
This filter is very good at downscaling (see ``scale-down``).
There are some more filters, but most are not as useful. For a complete
list, pass ``help`` as value, e.g.::
mpv --vo=opengl:scale=help
``scale-param1=<value>``, ``scale-param2=<value>``
Set filter parameters. Ignored if the filter is not tunable.
Currently, this affects the following filter parameters:
``scale-param1=<value>``
Set filter parameters. Ignored if the filter is not tunable. These are
unset by default, and use the filter specific default if applicable.
bcspline
Spline parameters (``B`` and ``C``). Defaults to 0.5 for both.
``scale-param2=<value>``
See ``scale-param1``.
gaussian
Scale parameter (``t``). Increasing this makes the result blurrier.
Defaults to 1.
``scale-radius=<r>``
Set radius for filters listed below, must be a float number between 1.0
and 16.0. Defaults to be 3.0 if not specified.
sharpen3, sharpen5
Sharpening strength. Increasing this makes the image sharper but
adds more ringing and aliasing. Defaults to 0.5.
oversample
Minimum distance to an edge before interpolation is used. Setting
this to 0 will always interpolate edges, whereas setting it to 0.5
will never interpolate, thus behaving as if the regular nearest
neighbour algorithm was used. Defaults to 0.0.
``scale-blur=<value>``
Kernel scaling factor (also known as a blur factor). Decreasing this
makes the result sharper, increasing it makes it blurrier (default 0).
If set to 0, the kernel's preferred blur factor is used. Note that
setting this too low (eg. 0.5) leads to bad results. It's generally
recommended to stick to values between 0.8 and 1.2.
``scale-radius=<value>``
Set radius for filters listed below, must be a float number between 0.5
and 16.0. Defaults to the filter's preferred radius if not specified.
``sinc`` and derivatives, ``jinc`` and derivatives, ``gaussian``, ``box`` and ``triangle``
``sinc``, ``lanczos``, ``ewa_lanczos``, ``blackman``, ``gaussian``
Note that depending on filter implementation details and video scaling
ratio, the radius that actually being used might be different
@@ -408,26 +349,7 @@ Available video output drivers are:
between 0.0 and 1.0. The default value of 0.0 disables antiringing
entirely.
Note that this doesn't affect the special filters ``bilinear``,
``bicubic_fast`` or ``sharpen``.
``scale-window=<window>``
(Advanced users only) Choose a custom windowing function for the kernel.
Defaults to the filter's preferred window if unset. Use
``scale-window=help`` to get a list of supported windowing functions.
``scale-wparam=<window>``
(Advanced users only) Configure the parameter for the window function
given by ``scale-window``. Ignored if the window is not tunable.
Currently, this affects the following window parameters:
kaiser
Window parameter (alpha). Defaults to 6.33.
blackman
Window parameter (alpha). Defaults to 0.16.
gaussian
Scale parameter (t). Increasing this makes the window wider.
Defaults to 1.
Note that this currently only affects ``ewa_lanczos``.
``scaler-resizes-only``
Disable the scaler if the video image is not resized. In that case,
@@ -435,6 +357,21 @@ Available video output drivers are:
will reproduce the source image perfectly if no scaling is performed.
Note that this option never affects ``cscale``.
``srgb``
Convert and color correct the output to sRGB before displaying it on
the screen. This option enables ``linear-scaling``.
This option is equivalent to using ``icc-profile`` with an sRGB ICC
profile, but it is implemented without a 3DLUT and does not require
LittleCMS 2. If both ``srgb`` and ``icc-profile`` are present, the
latter takes precedence, as they are somewhat redundant.
Note: When playing back BT.2020 content with this option enabled, out
of gamut colors will be numerically clipped, which can potentially
change the hue and/or luminance. If this is not desired, it is
recommended to use ``icc-profile`` with an sRGB ICC profile instead,
when playing back wide-gamut BT.2020 content.
``pbo``
Enable use of PBOs. This is slightly faster, but can sometimes lead to
sporadic and temporary image corruption (in theory, because reupload
@@ -475,72 +412,37 @@ Available video output drivers are:
Unfortunately, this can lead to flicker on LCD displays, since these
have a high reaction time.
``temporal-dither-period=<1-128>``
Determines how often the dithering pattern is updated when
``temporal-dither`` is in use. 1 (the default) will update on every
video frame, 2 on every other frame, etc.
``debug``
Check for OpenGL errors, i.e. call ``glGetError()``. Also request a
debug OpenGL context (which does nothing with current graphics drivers
as of this writing).
``interpolation``
Reduce stuttering caused by mismatches in the video fps and display
refresh rate (also known as judder).
This essentially attempts to interpolate the missing frames by
convoluting the video along the temporal axis. The filter used can be
controlled using the ``tscale`` setting.
Note that this relies on vsync to work, see ``swapinterval`` for more
information.
``swapinterval=<n>``
Interval in displayed frames between two buffer swaps.
1 is equivalent to enable VSYNC, 0 to disable VSYNC. Defaults to 1 if
not specified.
Note that this depends on proper OpenGL vsync support. On some platforms
and drivers, this only works reliably when in fullscreen mode. It may
also require driver-specific hacks if using multiple monitors, to
ensure mpv syncs to the right one. Compositing window managers can
also lead to bad results, as can missing or incorrect display FPS
information (see ``--display-fps``).
``cscale=<filter>``
As ``scale``, but for interpolating chroma information. If the image
is not subsampled, this option is ignored entirely. Note that the
implementation is currently always done as a single pass, so using
it with separable filters will result in slow performance for very
little visible benefit.
``dscale=<filter>``
``scale-down=<filter>``
Like ``scale``, but apply these filters on downscaling instead. If this
option is unset, the filter implied by ``scale`` will be applied.
``cscale=<filter>``
As ``scale``, but for interpolating chroma information. If the image
is not subsampled, this option is ignored entirely.
``cscale-param1``, ``cscale-param2``, ``cscale-radius``, ``cscale-antiring``
Set filter parameters and radius for ``cscale``.
``tscale=<filter>``
The filter used for interpolating the temporal axis (frames). This is
only used if ``interpolation`` is enabled. The only valid choices
for ``tscale`` are separable convolution filters (use ``tscale=help``
to get a list). The default is ``oversample``.
Note that the maximum supported filter radius is currently 3, due to
limitations in the number of video textures that can be loaded
simultaneously.
``tscale-clamp``
Clamp the ``tscale`` filter kernel's value range to [0-1]. This reduces
excessive ringing artifacts in the temporal domain (which typically
manifest themselves as short flashes or fringes of black, mostly
around moving edges) in exchange for potentially adding more blur.
``dscale-radius``, ``cscale-radius``, ``tscale-radius``, etc.
Set filter parameters for ``dscale``, ``cscale`` and ``tscale``,
respectively.
See the corresponding options for ``scale``.
See ``scale-param1``, ``scale-param2``, ``scale-radius`` and
``scale-antiring``.
``linear-scaling``
Scale in linear light. It should only be used with a ``fbo-format``
that has at least 16 bit precision.
Scale in linear light. This is automatically enabled if ``srgb``,
``icc-profile`` or ``sigmoid-upscaling`` is set. It should only
be used with a ``fbo-format`` that has at least 16 bit precision.
``fancy-downscaling``
When using convolution based filters, extend the filter size
@@ -550,92 +452,9 @@ Available video output drivers are:
feature doesn't work correctly with different scale factors in
different directions.
``pre-shaders=<files>``, ``post-shaders=<files>``, ``scale-shader=<file>``
Custom GLSL fragment shaders.
pre-shaders (list)
These get applied after conversion to RGB and before linearization
and upscaling. Operates on non-linear RGB (same as input). This is
the best place to put things like sharpen filters.
scale-shader
This gets used instead of scale/cscale when those options are set
to ``custom``. The colorspace it operates on depends on the values
of ``linear-scaling`` and ``sigmoid-upscaling``, so no assumptions
should be made here.
post-shaders (list)
These get applied after upscaling and subtitle blending (when
``blend-subtitles`` is enabled), but before color management.
Operates on linear RGB if ``linear-scaling`` is in effect,
otherwise non-linear RGB. This is the best place for colorspace
transformations (eg. saturation mapping).
These files must define a function with the following signature::
vec4 sample(sampler2D tex, vec2 pos, vec2 tex_size)
The meanings of the parameters are as follows:
sampler2D tex
The source texture for the shader.
vec2 pos
The position to be sampled, in coordinate space [0-1].
vec2 tex_size
The size of the texture, in pixels. This may differ from image_size,
eg. for subsampled content or for post-shaders.
In addition to these parameters, the following uniforms are also
globally available:
float random
A random number in the range [0-1], different per frame.
int frame
A simple count of frames rendered, increases by one per frame and
never resets (regardless of seeks).
vec2 image_size
The size in pixels of the input image.
For example, a shader that inverts the colors could look like this::
vec4 sample(sampler2D tex, vec2 pos, vec2 tex_size)
{
vec4 color = texture(tex, pos);
return vec4(1.0 - color.rgb, color.a);
}
``deband``
Enable the debanding algorithm. This greatly reduces the amount of
visible banding, blocking and other quantization artifacts, at the
expensive of very slightly blurring some of the finest details. In
practice, it's virtually always an improvement - the only reason to
disable it would be for performance.
``deband-iterations=<1..16>``
The number of debanding steps to perform per sample. Each step reduces
a bit more banding, but takes time to compute. Note that the strength
of each step falls off very quickly, so high numbers are practically
useless. (Default 4)
If the performance hit of debanding is too great, you can reduce this
to 2 or 1 with marginal visual quality loss.
``deband-threshold=<0..4096>``
The debanding filter's cut-off threshold. Higher numbers increase the
debanding strength dramatically but progressively diminish image
details. (Default 64)
``deband-range=<1..64>``
The debanding filter's initial radius. The radius increases linearly
for each iteration. A higher radius will find more gradients, but
a lower radius will smooth more aggressively. (Default 8)
``deband-grain=<0..4096>``
Add some extra noise to the image. This significantly helps cover up
remaining quantization artifacts. Higher numbers add more noise.
(Default 48)
``sigmoid-upscaling``
When upscaling, use a sigmoidal color transform to avoid emphasizing
ringing artifacts. This also implies ``linear-scaling``.
ringing artifacts. This also enables ``linear-scaling``.
``sigmoid-center``
The center of the sigmoid curve used for ``sigmoid-upscaling``, must
@@ -645,6 +464,10 @@ Available video output drivers are:
The slope of the sigmoid curve used for ``sigmoid-upscaling``, must
be a float between 1.0 and 20.0. Defaults to 6.5 if not specified.
``no-npot``
Force use of power-of-2 texture sizes. For debugging only.
Borders will be distorted due to filtering.
``glfinish``
Call ``glFinish()`` before and after swapping buffers (default: disabled).
Slower, but might help getting better results when doing framedropping.
@@ -658,18 +481,6 @@ Available video output drivers are:
X11/GLX only.
``dwmflush=<no|windowed|yes>``
Calls ``DwmFlush`` after swapping buffers on Windows (default: no).
It also sets ``SwapInterval(0)`` to ignore the OpenGL timing. Values
are: no (disabled), windowed (only in windowed mode), yes (also in
full screen).
This may help getting more consistent frame intervals, especially with
high-fps clips - which might also reduce dropped frames. Typically a
value of ``windowed`` should be enough since full screen may bypass the
DWM.
Windows only.
``sw``
Continue even if a software renderer is detected.
@@ -684,22 +495,20 @@ Available video output drivers are:
Cocoa/OS X
win
Win32/WGL
x11
X11/GLX
x11, x11es
X11/GLX (the ``es`` variant forces GLES)
wayland
Wayland/EGL
x11egl
X11/EGL
``es``
Force or prefer GLES2/3 over desktop OpenGL, if supported.
x11egl, x11egles
X11/EGL (the ``es`` variant forces GLES)
``fbo-format=<fmt>``
Selects the internal format of textures used for FBOs. The format can
influence performance and quality of the video output.
influence performance and quality of the video output. (FBOs are not
always used, and typically only when using extended scalers.)
``fmt`` can be one of: rgb, rgba, rgb8, rgb10, rgb10_a2, rgb16, rgb16f,
rgb32f, rgba12, rgba16, rgba16f, rgba32f.
Default: rgba16.
Default: rgba.
``gamma=<0.1..2.0>``
Set a gamma value (default: 1.0). If gamma is adjusted in other ways
@@ -715,65 +524,12 @@ Available video output drivers are:
0.8
Pitch black room
``gamma-auto``
Automatically corrects the gamma value depending on ambient lighting
conditions (adding a gamma boost for dark rooms).
With ambient illuminance of 64lux, mpv will pick the 1.0 gamma value
(no boost), and slightly increase the boost up until 0.8 for 16lux.
NOTE: Only implemented on OS X.
``target-prim=<value>``
Specifies the primaries of the display. Video colors will be adapted
to this colorspace if necessary. Valid values are:
auto
Disable any adaptation (default)
bt.470m
ITU-R BT.470 M
bt.601-525
ITU-R BT.601 (525-line SD systems, eg. NTSC), SMPTE 170M/240M
bt.601-625
ITU-R BT.601 (625-line SD systems, eg. PAL/SECAM), ITU-R BT.470 B/G
bt.709
ITU-R BT.709 (HD), IEC 61966-2-4 (sRGB), SMPTE RP177 Annex B
bt.2020
ITU-R BT.2020 (UHD)
apple
Apple RGB
adobe
Adobe RGB (1998)
prophoto
ProPhoto RGB (ROMM)
cie1931
CIE 1931 RGB (not to be confused with CIE XYZ)
``target-trc=<value>``
Specifies the transfer characteristics (gamma) of the display. Video
colors will be adjusted to this curve. Valid values are:
auto
Disable any adaptation (default)
bt.1886
ITU-R BT.1886 curve, without the brightness drop (approx. 1.961)
srgb
IEC 61966-2-4 (sRGB)
linear
Linear light output
gamma1.8
Pure power curve (gamma 1.8), also used for Apple RGB
gamma2.2
Pure power curve (gamma 2.2)
gamma2.8
Pure power curve (gamma 2.8), also used for BT.470-BG
prophoto
ProPhoto RGB (ROMM)
``icc-profile=<file>``
Load an ICC profile and use it to transform linear RGB to screen output.
Needs LittleCMS 2 support compiled in. This option overrides the
``target-prim``, ``target-trc`` and ``icc-profile-auto`` options.
Needs LittleCMS 2 support compiled in. This option overrides the ``srgb``
property, as using both is somewhat redundant. It also enables
``linear-scaling``.
``icc-profile-auto``
Automatically select the ICC display profile currently specified by
@@ -781,18 +537,16 @@ Available video output drivers are:
NOTE: Only implemented on OS X and X11
``icc-cache-dir=<dirname>``
Store and load the 3D LUTs created from the ICC profile in this directory.
``icc-cache=<file>``
Store and load the 3D LUT created from the ICC profile in this file.
This can be used to speed up loading, since LittleCMS 2 can take a while
to create a 3D LUT. Note that these files contain uncompressed LUTs.
Their size depends on the ``3dlut-size``, and can be very big.
NOTE: This is not cleaned automatically, so old, unused cache files
may stick around indefinitely.
to create the 3D LUT. Note that this file contains an uncompressed LUT.
Its size depends on the ``3dlut-size``, and can be very big.
``icc-intent=<value>``
Specifies the ICC intent used for the color transformation (when using
``icc-profile``).
Specifies the ICC Intent used for transformations between color spaces.
This affects the rendering when using ``icc-profile`` or ``srgb`` and
also affects the way DCP XYZ content gets converted to RGB.
0
perceptual
@@ -808,28 +562,6 @@ Available video output drivers are:
Default is 128x256x64.
Sizes must be a power of two, and 512 at most.
``blend-subtitles=<yes|video|no>``
Blend subtitles directly onto upscaled video frames, before
interpolation and/or color management (default: no). Enabling this
causes subtitles to be affected by ``icc-profile``, ``target-prim``,
``target-trc``, ``interpolation``, ``gamma`` and ``post-shader``. It
also increases subtitle performance when using ``interpolation``.
The downside of enabling this is that it restricts subtitles to the
visible portion of the video, so you can't have subtitles exist in the
black margins below a video (for example).
If ``video`` is selected, the behavior is similar to ``yes``, but subs
are drawn at the video's native resolution, and scaled along with the
video.
.. warning:: This changes the way subtitle colors are handled. Normally,
subtitle colors are assumed to be in sRGB and color managed
as such. Enabling this makes them treated as being in the
video's color space instead. This is good if you want
things like softsubbed ASS signs to match the video colors,
but may cause SRT subtitles or similar to look slightly off.
``alpha=<blend|yes|no>``
Decides what to do if the input has an alpha component (default: blend).
@@ -845,6 +577,10 @@ Available video output drivers are:
no
Ignore alpha component.
``chroma-location=<auto|center|left>``
Set the YUV chroma sample location. auto means use the bitstream
flags (default: auto).
``rectangle-textures``
Force use of rectangle textures (default: no). Normally this shouldn't
have any advantages over normal textures. Note that hardware decoding
@@ -854,16 +590,65 @@ Available video output drivers are:
Color used to draw parts of the mpv window not covered by video.
See ``--osd-color`` option how colors are defined.
``smoothmotion``
Reduce stuttering caused by mismatches in video fps and display
refresh rate (also known as judder).
Instead of drawing source frames for variable durations, smoothmotion
will blend frames that overlap the transition between two frames in
the source material.
For example, a 24 Hz clip played back on a 60 Hz display would normally
result in a pattern like this::
A A A B B C C C D D E E E F F
which has different lengths, alternating between 3 and 2. This
difference in frame duration is what causes judder.
With smoothmotion enabled, the pattern changes to::
A A A+B B B C C C+D D D E E E+F F F
where A+B is a blend of A and B. In this pattern, each frame gets a
(consistent) duration of roughly 2.5 - resulting in smooth motion.
GPU drivers or compositing window managers overriding vsync behavior
can lead to bad results. If the framerate is close to or over the
display refresh rate, results can be bad as well.
.. note:: On systems other than Linux or OS X, you currently must set
the ``--display-fps`` option, or the results will be bad.
``smoothmotion-threshold=<0.0-0.5>``
Mix threshold at which interpolation is skipped (default: 0.0 – never
skip).
For example, with a ``smoothmotion-threshold`` of 0.1, if the
smoothmotion algorithm would try to blend two frames by a ratio of
95% A + 5% B, it would simply display A instead. (Since the
distance, 0.05, is lower than the threshold)
Setting this to 0.5 would be similar to disabling smoothmotion
completely, since it would always just display the nearest frame.
``opengl-hq``
Same as ``opengl``, but with default settings for high quality rendering.
This is equivalent to::
--vo=opengl:scale=spline36:cscale=spline36:dscale=mitchell:dither-depth=auto:fancy-downscaling:sigmoid-upscaling:pbo:deband
--vo=opengl:scale=spline36:scale-down=mitchell:dither-depth=auto:fbo-format=rgba16:fancy-downscaling:sigmoid-upscaling
Note that some cheaper LCDs do dithering that gravely interferes with
``opengl``'s dithering. Disabling dithering with ``dither-depth=no`` helps.
Unlike ``opengl``, ``opengl-hq`` makes use of FBOs by default. Sometimes you
can achieve better quality or performance by changing the ``fbo-format``
suboption 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``.
``sdl``
SDL 2.0+ Render video output driver, depending on system with or without
hardware acceleration. Should work on all platforms supported by SDL 2.0.
@@ -924,12 +709,6 @@ Available video output drivers are:
``null``
Produces no video output. Useful for benchmarking.
Usually, it's better to disable video with ``--no-video`` instead.
``fps=<value>``
Simulate display FPS. This artificially limits how many frames the
VO accepts per second.
``caca``
Color ASCII art video output driver that works on a text console.
@@ -1009,52 +788,15 @@ Available video output drivers are:
``frame-queue-size=<1..100>``
The maximum count of frames which the frame queue can hold (default: 1)
``frame-drop-mode=<pop|clear|block>``
``frame-drop-mode=<pop|clear>``
Select the behavior when the frame queue is full.
pop
Drop the oldest frame in the frame queue.
Drop the oldest frame in the frame queue. (default)
clear
Drop all frames in the frame queue.
block
Wait for a short time, behave like ``clear`` on timeout. (default)
This also supports many of the suboptions the ``opengl`` VO has. Run
This also supports many of the suboptions the ``opengl`` VO has. Runs
``mpv --vo=opengl-cb:help`` for a list.
This also supports the ``vo_cmdline`` command.
``rpi`` (Raspberry Pi)
Native video output on the Raspberry Pi using the MMAL API.
``display=<number>``
Select the display number on which the video overlay should be shown
(default: 0).
``layer=<number>``
Select the dispmanx layer on which the video overlay should be shown
(default: -10). Note that mpv will also use the 2 layers above the
selected layer, to handle the window background and OSD. Actual video
rendering will happen on the layer above the selected layer.
``background=<yes|no>``
Whether to render a black background behind the video (default: no).
Normally it's better to kill the console framebuffer instead, which
gives better performance.
``drm`` (Direct Rendering Manager)
Video output driver using Kernel Mode Setting / Direct Rendering Manager.
Does not support hardware acceleration. Should be used when one doesn't
want to install full-blown graphical environment (e.g. no X).
``connector=<number>``
Select the connector to use (usually this is a monitor.) If set to -1,
mpv renders the output on the first available connector. (default: -1)
``devpath=<filename>``
Path to graphic card device.
(default: /dev/dri/card0)
``mode=<number>``
Mode ID to use (resolution, bit depth and frame rate).
(default: 0)
+4 -12
View File
@@ -46,13 +46,6 @@ Input
* Allow customizing whether a key binding for seeking shows the video time, the
OSD bar, or nothing (see the `Input Command Prefixes`_ section).
* Support mapping multiple commands to one key.
* Classic LIRC support was removed. Install remotes as input devices instead.
This way they will send X11 key events to the mpv window, which can be bound
using the normal ``input.conf``.
Also see: http://github.com/mpv-player/mpv/wiki/IR-remotes
* Joystick support was removed. It was considered useless and was the cause
of some problems (e.g. a laptop's accelerator being recognized as joystick).
* Support for relative seeking by percentage.
Audio
~~~~~
@@ -94,8 +87,6 @@ Video
* Image subtitles (DVDs etc.) are rendered in color and use more correct
positioning (color for image subs can be disabled with ``--sub-gray``).
* Support for the X11 video output is removed, since it was considered
deprecated. SDL video output can still be used as a fallback.
OSD and terminal
~~~~~~~~~~~~~~~~
@@ -236,6 +227,7 @@ Command Line Switches
``-idx`` ``--index``
``-lavdopts ...`` ``--vd-lavc-...``
``-lavfdopts`` ``--demuxer-lavf-...``
``-lircconf`` ``--input-lirc-conf``
``-loop 0`` ``--loop=inf``
``-mixer-channel`` AO suboptions (``alsa``, ``oss``)
``-mixer`` AO suboptions (``alsa``, ``oss``)
@@ -247,6 +239,7 @@ Command Line Switches
``-noar`` ``--no-input-appleremote``
``-noautosub`` ``--no-sub-auto``
``-noconsolecontrols`` ``--no-input-terminal``
``-nojoystick`` ``--no-input-joystick``
``-nosound`` ``--no-audio``
``-osdlevel`` ``--osd-level``
``-panscanrange`` ``--video-zoom``, ``--video-pan-x/y``
@@ -279,7 +272,7 @@ Command Line Switches
``-xineramascreen`` ``--screen`` (different values)
``-xy W`` ``--autofit=W``
``-zoom`` Inverse available as ``--video-unscaled``
``dvdnav://`` Removed.
``dvdnav://`` ``dvdnav://menu``
``dvd://1`` ``dvd://0`` (0-based offset)
=========================== ========================================
@@ -399,8 +392,7 @@ Slave mode
Assuming the system supports ``/dev/stdin``.
(The option was added back in 0.5.1 and sets exactly these options. It was
removed in 0.10.x again.)
(The option was readded in 0.5.1 and sets exactly these options.)
* A JSON RPC protocol giving access to the client API is also supported. See
`JSON IPC`_ for more information.
+27 -69
View File
@@ -1,106 +1,64 @@
Release Policy
==============
Once or twice a month, a new release is cut off of the master branch and is
assigned a 0.X.Y version number, where X is incremented each time a release
contains breaking changes, such as changed options or added/removed features,
and Y is incremented if a release contains only bugfixes and other minor
changes.
Every few months, a new release is cut off of the master branch and is assigned
a 0.X.0 version number.
There is only one release branch that keeps track of the latest version and
will not be maintained separately.
As part of the maintenance process, minor releases are made, which are assigned
0.X.Y version numbers. Minor releases contain bug fixes only. They never merge
the master branch, and no features are added to it. Only the latest release is
maintained.
The goal of releases is to provide Linux distributions with something to
package. If you want the newest features, just use the master branch.
We try our best to keep it deployable at all times.
The goal of releases is to provide stability and an unchanged base for the sake
of Linux distributions. If you want the newest features, just use the master
branch, which is stable most of the time, except sometimes, when it's not.
Releases other than the latest release are unsupported and unmaintained.
Release procedure
-----------------
- Merge master into branch release/current.
- Create branch release/0.X or cherry-pick commits to the relevant branch.
- Create and/or update the `RELEASE_NOTES` file.
- Create and/or update the ``RELEASE_NOTES`` file.
- Create and/or update the `VERSION` file.
- Create and/or update the ``VERSION`` file.
- Update `DOCS/client-api-changes.rst` (on major releases).
- Update ``DOCS/client-api-changes.rst`` (on major releases).
- Create tag v0.X.Y.
- Push branch and tag to GitHub.
- Create a new GitHub release using the content of `RELEASE_NOTES` related to
- Create a new GitHub release using the content of ``RELEASE_NOTES`` related to
the new version.
Release notes template
----------------------
Here is a template that can be used for writing the `RELEASE_NOTES` file.
Here is a template that can be used for writing the ``RELEASE_NOTES`` file.
```markdown
Release 0.X.Y
=============
Features
--------
Changes
-------
New
~~~
- List of changes.
- List of new features
Bug fixes
---------
Removed
~~~~~~~
- List of bug fixes.
- List of removed features
New features
------------
Deprecated
~~~~~~~~~~
- List of deprecated features
Behavior
--------
- List of user-visible changes in behavior
Options and Commands
--------------------
Added
~~~~~
- List of added options and commands
Changed
~~~~~~~
- List of changed options and commands
Renamed
~~~~~~~
- List of renamed options and commands
Deprecated
~~~~~~~~~~
- List of deprecated options and commands
Removed
~~~~~~~
- List of removed options and commands
Fixes and Minor Enhancements
----------------------------
- List of fixes and minor enhancements
- List of new features.
This listing is not complete. There are many more bug fixes and changes. The
complete change log can be viewed by running `git log <start>..<end>` in
complete change log can be viewed by running ``git log <start>..<end>`` in
the git repository.
```
@@ -108,6 +66,6 @@ Note that the "Release 0.X.Y" title should be removed when creating a new GitHub
release.
When creating a new point release its changes should be added on top of the
`RELEASE_NOTES` file (with the appropriate title) so that all the changes in
the current 0.X branch will be included. This way the `RELEASE_NOTES` file
``RELEASE_NOTES`` file (with the appropriate title) so that all the changes in
the current 0.X branch will be included. This way the ``RELEASE_NOTES`` file
can be used by distributors as changelog for point releases too.
+2 -1
View File
@@ -75,7 +75,8 @@ talloc.h & talloc.c:
allocation call will never return NULL.
One very useful feature of talloc is fast tracking of memory leaks. ("Fast"
as in it doesn't require valgrind.) You can enable it by setting the
as in it doesn't require valgrind.) You can enable it by passing the option
--leak-report as first parameter, or better, setting the
MPV_LEAK_REPORT environment variable to "1":
export MPV_LEAK_REPORT=1
This will list all unfree'd allocations on exit.
+4 -5
View File
@@ -1,7 +1,7 @@
waf build system overview
=========================
mpv's new build system is based on waf and it should completely replace the
mpv's new build system is based on waf and it should completly replace the
custom ./configure + Makefile based system inherited from MPlayer.
Goals and the choice of waf
@@ -20,9 +20,8 @@ shortcomings:
part is this pieces are spread apart in the configure and copy pasted for
any single case. That brings us to..
2) --enable-feature has to be overridden by the user and helps them understand that
they have libraries missing and should install them for the feature to be
enabled.
2) --enable-feature has to override the user and help him understand that he
has libraries missing and should install them for the feature to be enabled.
3) Must be customizable, hackable, pleasant to the developer eyes and to work
with in general.
@@ -65,7 +64,7 @@ This defines a feature called ``vdpau`` which can be enabled or disabled by
the users with configure flags (that's the meaning of ``--``). This feature
depends on another feature whose name is ``x11``, and the autodetection check
consists of running ``pkg-config`` and looking for ``vdpau`` with version
``>= 0.2``. If the check succeeds a ``#define HAVE_VDPAU 1`` will be added to
``>= 0.2``. If the check succeds a ``#define HAVE_VDPAU 1`` will be added to
``config.h``, if not ``#define HAVE_VDPAU 0`` will be added.
The defines names are automatically prepended with ``HAVE_``, capitalized and
+33 -48
View File
@@ -1,39 +1,22 @@
![http://mpv.io/](https://raw.githubusercontent.com/mpv-player/mpv.io/master/source/images/mpv-logo-128.png)
## mpv
--------------
* [Overview](#overview)
* [Downloads](#downloads)
* [Compilation](#compilation)
* [FFmpeg vs. Libav](#ffmpeg-vs-libav)
* [Release cycle](#release-cycle)
* [Bug reports](#bug-reports)
* [Contributing](#contributing)
* [Relation to MPlayer and mplayer2](#relation-to-mplayer-and-mplayer2)
* [Wiki](https://github.com/mpv-player/mpv/wiki)
* [Man pages](http://mpv.io/manual/master/)
* [Contact](#contact)
* [License](#license)
## Overview
mpv
===
Overview
--------
**mpv** is a media player based on MPlayer and mplayer2. It supports a wide
variety of video file formats, audio and video codecs, and subtitle types.
Releases can be found on the [release list][releases].
## Downloads
Downloads
---------
For semi-official builds and third-party packages please see
[mpv.io](http://mpv.io/installation/).
## Compilation
Compilation
-----------
Compiling with full features requires development files for several
external libraries. Below is a list of some important requirements.
@@ -57,6 +40,9 @@ To build the software you can use `./waf build`: the result of the compilation
will be located in `build/mpv`. You can use `./waf install` to install mpv
to the *prefix* after it is compiled.
NOTE: Using the old build system (with `./old-configure`) should still work,
but will be removed in a future version of mpv.
Essential dependencies (incomplete list):
- gcc or clang
@@ -64,10 +50,10 @@ 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 2.4.0 or Libav 11 is required.
At least FFmpeg 2.1.4 or Libav 10 is required.
- zlib
- iconv (normally provided by the system libc)
- libass (OSD, OSC, text subtitles)
- libass
- Lua (optional, required for the OSC pseudo-GUI and youtube-dl integration)
- libjpeg (optional, used for screenshots only)
- Enca (optional, for subtitle charset detection)
@@ -103,16 +89,16 @@ OSX.
If you want to build a Windows binary, you either have to use MSYS2 and MinGW,
or cross-compile from Linux with MinGW. See [Windows compilation][windows_compilation].
## FFmpeg vs. Libav
FFmpeg vs. Libav
----------------
Generally, mpv should work with the latest release as well as the git version
of both FFmpeg and Libav. But FFmpeg is preferred, and some mpv features work
with FFmpeg only (subtitle formats in particular).
with FFmpeg only. See the [wiki article][ffmpeg_vs_libav] about the issue.
## Release cycle
Release cycle
-------------
Every few months, a new release is cut off of the master branch and is assigned
a 0.X.0 version number.
@@ -130,21 +116,21 @@ Releases other than the latest release are unsupported and unmaintained.
See the [release policy document][release-policy] for more information.
## Bug reports
Bug reports
-----------
Please use the [issue tracker][issue-tracker] provided by GitHub to send us bug
reports or feature requests.
## Contributing
Contributing
------------
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.
## Relation to MPlayer and mplayer2
Relation to MPlayer and mplayer2
--------------------------------
mpv is based on mplayer2, which in turn is based on the original MPlayer
(also called mplayer, mplayer-svn, mplayer1). Many changes have been made, a
@@ -165,15 +151,17 @@ MPlayer drop-in replacement.
If you are wondering what's different from mplayer2 and MPlayer, an incomplete
list of changes is located [here][mplayer-changes].
## Contact
Contact
-------
Most activity happens on the IRC channel and the github issue tracker. The
mailing lists are mostly unused.
- **GitHub issue tracker**: [issue tracker][issue-tracker] (report bugs here)
- **User IRC Channel**: `#mpv` on `irc.freenode.net`
- **Developer IRC Channel**: `#mpv-devel` on `irc.freenode.net`
- **Github issue tracker**: [issue tracker][issue-tracker] (report bugs here)
- **User IRC Channel**: `#mpv-player` on `irc.freenode.net`
- **Developer IRC Channel**: `#mpv-player-dev` on `irc.freenode.net`
- **Users Mailing List**: `mpv-users@googlegroups.com` ([Archive / Subscribe][mpv-users]).
- **Devel Mailing List**: `mpv-devel@googlegroups.com` ([Archive / Subscribe][mpv-devel])
To contact the `mpv` team in private write to `mpv-team@googlegroups.com`. Use
only if discretion is required.
@@ -182,12 +170,9 @@ only if discretion is required.
[mpv-build]: https://github.com/mpv-player/mpv-build
[homebrew-mpv]: https://github.com/mpv-player/homebrew-mpv
[issue-tracker]: https://github.com/mpv-player/mpv/issues
[mpv-users]: https://groups.google.com/forum/?hl=en#!forum/mpv-users
[mpv-devel]: https://groups.google.com/forum/?hl=en#!forum/mpv-devel
[ffmpeg_vs_libav]: https://github.com/mpv-player/mpv/wiki/FFmpeg-versus-Libav
[release-policy]: https://github.com/mpv-player/mpv/blob/master/DOCS/release-policy.md
[windows_compilation]: https://github.com/mpv-player/mpv/blob/master/DOCS/compile-windows.md
[mplayer-changes]: https://github.com/mpv-player/mpv/blob/master/DOCS/mplayer-changes.rst
## License
[GPLv2](https://github.com/mpv-player/mpv/blob/master/LICENSE)
+4 -828
View File
@@ -1,602 +1,3 @@
Release 0.11.0
==============
Features
--------
New
~~~
- vo_opengl: implement debanding
Removed
~~~~~~~
- audio/filter: remove center, extrastereo, karaoke, sinesuppress, sub,
surround, sweep, ladspa, hrtf, export and bs2b filters (these are either
considered useless or have replacements in lavfi)
- video/filter: remove lavfi wrappers for noise, hqdn3d, unsharp and delogo
(these filters remain usable through lavfi)
Behavior
--------
- vo_opengl: require FBOs by default (use dumb-mode suboption for old hardware
and broken drivers)
- vo_opengl: enable debanding by default for the opengl-hq preset
- audio/out: use new sample format determination code
- player: prefer logical current directory path (affects logic for resuming
playback)
- vf_vdpaurb: Pass through non-hardware-decoded content
- player: make force-window=immediate work in auto-profiles
Options and Commands
--------------------
Added
~~~~~
- af_lavrresample: add normalize suboption
- vo_opengl: add deband, deband-iterations, deband-threshold, deband-range and
deband-grain suboptions
- af_lavfi: implement af-metadata property (like vf-metadata)
Changed
~~~~~~~
- command: make "add <property> 0" not change the value
Removed
~~~~~~~
- vo_opengl: remove source-shader suboption
Fixes and Minor Enhancements
----------------------------
- options: fix --no-config
- cache: do not include backbuffer size in total stream cache size
- audio/format: actually prefer float over double sample format for
int->float conversions
- audio/format: fix interlaved vs. non-interleaved conversions
- audio/format: revise format conversion scoring
- video: make --field-dominance set interlaced flag
- vf: vf_stereo3d compilation depends on libavfilter
- vf_yadif: add hack for Libav compatibility
- player: add opus to list of external audio file extensions
- build: allow disabling vapoursynth completely
- libmpv/win32: allow multiple windows at the same time
This listing is not complete. Check DOCS/client-api-changes.rst for a history
of changes to the client API. A complete changelog can be seen by running
`git log v0.10.0..v0.11.0` in the git repository or by visiting either
https://github.com/mpv-player/mpv/compare/v0.10.0...v0.11.0 or
http://git.srsfckn.biz/mpv/log/?qt=range&q=v0.10.0..v0.11.0
Release 0.10.0
==============
Features
--------
New
~~~
- uchardet support
- Matroska: reading cue sheets embedded in tags
- Support for VideoToolbox hardware decoding
- Display sync mode (--display-sync)
- --force-window=immediate mode
- fd:// protocol
- libarchive wrapper for reading compressed archives
- TOOLS/lua: zones.lua
- Support for the "new" libavcodec VDPAU API
- vf_vdpaurb, Add a new filter for reading back VDPAU decoded frames
- DXVA2: HEVC support
- Enabled HEVC profiles with VA API
- HEVC added to whitelist of hwdec codecs
- vo_null: framerate emulation
- vo_opengl: support for custom shaders
- vo_opengl: temporal-dither-period option
- vo_opengl: tscale-clamp option
- vo_opengl: option to attach target-prim/target-csp to window screenshots
- vo_opengl_cb: "block" framedrop mode (now default)
- vo_opengl_cb: support for interpolation
- vo_vdpau: rotation support
- ytdl_hook: support for 'multi_video' results
Removed
~~~~~~~
- af_convert24 (af_lavrresample does this now)
- af_dummy
- audio: S8, U16, U24, U32 formats
- DVD and BD menu support
- TOOLS: youtube-starttime.lua
- VA API: compatibility crap (< 0.34.0) and vo_vaapi deinterlacer
- vo_x11
Deprecated
~~~~~~~~~~
- vf_dlopen
Behavior
--------
- audio: softvol scale is now cubic
- cache: readahead size is limited to half the cache size at the beginning
- charset_conv: "auto" encoding detection now prefers uchardet
- demux_playlist: skip hidden directories
- input.conf: O toggles between 2 states only
- input.conf: Ctrl+s key binding for window screenshots
- input.conf: mouse volume control (horizontal scrolling) inverted
- input.conf: L to toggle infinite looping
- input.conf: remap d/D keys (dropped framedrop cycle, replaced with deinterlacing toggle)
- player: disabled seeking on unseekable streams even if the cache is enabled
- player: parses and exposes m3u playlist titles
- player: --term-playing-msg is now in a separate log category
- player: removed automatic DVB channel advancement on no data
- player: now restores video-aspect on playback resume
- player: now uses exit code 0 by default for quit, 4 for signals, etc.
- player: warns against using HLS URLs with --playlist
- screenshots: changed the default directory in pseudo-gui mode to desktop
- screenshots: screenshot directory is now created automatically
- screenshots: default template is now prefixed with "mpv-"
- TOOLS/lua/autoload: adds all files on start
- vo: vo_wayland moved up in autoprobe list
- vo_opengl: enabled pbo by default with opengl-hq
- vo_opengl: cache dir for ICC profiles is now created automatically
- w32: shift drag and drop appends
- x11: shift drag and drop appends
Options and Commands
--------------------
Added
~~~~~
- af_volume: replaygain-fallback option
- ao_coreaudio: change-physical-format option
- ao_coreaudio: exclusive option
- ao_null: channel-layouts option for testing channel layout selection
- audio: --audio-spdif as new method for enabling passthrough
- cache: --cache-backbuffer to configure cache backbuffer size
- command: define-section command for defining input bindings
- command: audio-params and audio-out-params properties
- command: keypress, keydown, and keyup commands
- command: playlist_shuffle command
- command: option-info/N/set-locally property indicating per-file options
- command: protocol-list property
- command: track-list/N/audio-channels property
- demux: --demuxer-max-packets and --demuxer-max-bytes options to control maximum queue size
- input: relative percentage seek
- osc: time display configuration options
- player: --playlist-pos option
- screenshots: --screenshot-jpeg-source-chroma option to disable JPEG 4:4:4 output
- screenshots: --screenshot-high-bit-depth option to allow or disallow 16 bit output
- screenshots: --screenshot-directory option
- sub: --stretch-image-subs-to-screen option for stretching image subtitles to screen
- TOOLS/stats-conv: allow passing regex via command line
- video: --video-aspect-method option to configure container vs. bitstream aspect ratio
- vo_drm: mode suboption to set the mode ID to use
- vo_opengl_cb, vo_opengl: --hwdec-preload option for preloading hwdec context
- vo_rpi: background disabled by default
- vo_xv: buffers suboption to configure number of buffers
- win32: portable config mode
Changed
~~~~~~~
- audio: changed the range of the volume option/property (0 is still silence, and 100 now always means unchanged volume)
- command: allow changing deinterlace property any time
- command: allow changing track properties while no file is loaded
- command: always make video-aspect property accessible
- command: better choice when to allow playback-related commands
- command: change OSD symbol for absolute perc. seek
- command: change the default action for rescan_external_files
- command: change the hwdec properties
- command: define-section with empty contents removes a section
- command: export stereo 3D tags
- command: make auto-deinterlacing output at field rate
- command: make deinterlace property use interlaced-only yadif mode
- command: make property event mask matching more restrictive
- command: make the playback-time property writable
- input: allow - as separator between commands, instead of _
- options: --loop without argument means looping forever
- options: make keyvalue list parsing less strict
- player: extend --hls-bitrate option
- vf_yadif: expose interlaced frame mode
- video: --video-stereo-mode=no to disable automatic stereo conversion
- vo_opengl_cb, vo_opengl: --hwdec-preload for preloading hwdec context
- vo_opengl: replace icc-cache with icc-cache-dir
- vo_opengl: icc-profile overrides icc-profile-auto
Renamed
~~~~~~~
- command: rename audio-format property to audio-codec-name
- options: rename --media-title option to --force-media-title
- vo_opengl: rename use_full_range to use_normalized_range
Deprecated
~~~~~~~~~~
- --ad-spdif-dtshd (use --audio-spdif=dts-hd)
- audio-samplerate property
- length property
Removed
~~~~~~~
- get_property command
- --demuxer-readahead-packets and --demuxer-readahead-bytes
- image_writer: don't use jpeg baseline, and remove useless jpeg-optimize and jpeg-baseline options
- --leak-report
- --slave-broken
- vo_opengl: npot suboption
Fixes and Minor Enhancements
----------------------------
- ad_spdif: use DTS-HD passthrough only if the audio is really DTS-HD
- af: fix behavior with filter chains that require a large number of auto-inserted conversion filters
- af_lavcac3enc: fix A/V sync
- ao_alsa: accept 7.1 over HDMI
- ao_alsa: refuse to use spdif if AES flags can't be set
- ao_wasapi: fix crash on hotplug init error
- audio: avoid wasting CPU due to continuous wakeup
- audio: do not exit when loading small files in paused mode
- audio: fix channel map fallback selection
- audio: fix crash on uninit
- audio: fix --end handling
- audio: fix EOF state with --keep-open
- audio: fix restoring volume
- charset_conv: fix switched parameters
- charset_conv: use our own UTF-8 check with ENCA only
- cocoa: don't load hardcoded icon if running from bundle
- cocoa: hide cursor using a blank image instead of a system-wide API
- command: do not exit playback if the B point of A-B loop is past EOF
- command: fix audio-out-detected-device property
- command: fix track property when no file is loaded
- command: fix video-aspect property update notification
- command: let track properties return option value in idle mode
- demux: don't get stuck on some cases of timestamp resets
- demux: handle Matroska-style replaygain tags as well
- demux_lavf: do a better job at guessing the vobsub .sub filename
- demux_mkv: disable ordered chapters if ChapterTimeEnd is missing
- demux_mkv: discard broken index
- demux_mkv: fix mpeg2 mapping
- demux_mkv: ignore deprecated FrameRate, do not assume PAL
- demux_mkv: improve video duration detection heuristic
- demux_mkv: parse FLAC channel layouts
- demux_playlist: make mime type comparison case-insensitive
- dxva2: fix handling of cropped video
- idet.sh: Support larger files
- mp_image: fix vf_vdpaupp references
- options: fix conversion of flags to strings
- options: move program name to end of window title
- options: remove the period at the end of "No file."
- osc: completely disable if no VO window exists
- osc: exit tick immediately if disabled
- osc: reinit on playlist changes
- osx: add NULL check for input context in a missing case
- player: fix crashes when adding external tracks before loading main file
- player: increase tick event update frequency
- player: make decoding cover art more robust
- player: raise maximum idle time
- player: return better guess for playback time during seeks
- player: show larger cache sizes in MB on status line
- player: slim down A/V desync warning
- sd_ass: assume negative durations are unknown durations, and handle them
- terminal: disable terminal foreground state polling
- terminal-unix: set terminal mode on init
- timer: fix a corner case on clock changes
- TOOLS: make autodeint detect telecine in parallel
- TOOLS/zsh.pl: die loudly if mpv fails to run
- vaapi: prefer direct display over copy-back
- vaapi: fix some videos only showing up green
- vaapi: treat cropped decoder output slightly more correctly
- vda: add support for nv12 image formats
- vd_lavc: fix a hw decoding fallback case
- vf_stereo3d: drop internal implementation
- vf_vavpp: don't attempt to deinterlace progressive frames
- vf_vavpp: fix bob deinterlacing for bottom field first videos
- vf_vdpaupp: Don't crash when evaluating interlacing of NULL mpi
- video: always re-probe auto deint filter on filter reconfig
- video: better heuristic for timestamp resets
- video: fix panscan in vertical case
- video: fix VideoToolbox/VDA autodetection
- video: unbreak EOF with video-only files that have timestamp resets
- vo_direct3d: fix broken pseudo GUI drag and drop hint
- vo_drm: fix centering with regard to stride
- vo_drm: fix crashes with --profile=pseudo-gui
- vo_drm: fix resolution not restored after exiting
- vo_drm: fix stride problem for certain devices
- vo_drm: make VT switching non mandatory
- vo: free frames before killing VO
- vo_opengl: avoid broken shader if hwdec fails to provide textures
- vo_opengl_cb: drop frames eagerly if frames are not rendered
- vo_opengl: CMS no longer implies linear scaling
- vo_opengl: fix alpha video in one case
- vo_opengl: fix dangling pointers with vo_cmdline
- vo_opengl: fix framestepping/pausing + interpolation
- vo_opengl: fix "freezes" after seeking with interpolation on
- vo_opengl: fix scale=oversample's threshold calculations
- vo_opengl: framebuffers work under GLES 2
- vo_opengl: improve robustness against PBO failure
- vo_opengl: reimplement tscale=oversample
- vo_opengl: reject future images in different formats
- vo_opengl: X11: don't leak when GL init fails
- vo: restore frame-drop logic for high-fps clips
- vo_rpi: fix blackscreen before the first subtitle/OSD is rendered
- vo_rpi, vo_opengl: do not globally terminate EGL on VO uninit
- vo_sdl: fix glaring memory leak
- vo_vdpau: check maximum video size
- vo_vdpau: limit output surfaces to allowed maximum dimensions
- win32: fix window resize logic
- win32: fix crashes when changing system time
- x11: Handle external fullscreen toggles
- ytdl: catch bogus extractor info
- ytdl: do not use deprecated media-title option
- ytdl: don't print failure warning when youtube-dl was killed by us
- ytdl: get start_time
This listing is not complete. Check DOCS/client-api-changes.rst for a history
of changes to the client API. A complete changelog can be seen by running
`git log v0.9.2..v0.10.0` in the git repository or by visiting
https://github.com/mpv-player/mpv/compare/v0.9.2...v0.10.0.
Release 0.9.2
=============
Changes
-------
- The Lua check now also checks for `lua52.pc`, as used by Arch Linux testing.
- (X11) `vo_opengl`'s `icc-profile-auto` now queries the current ICC profile
relative to the center of the window.
- `ao_coreaudio`, `ao_alsa` now support adding dummy padding channels for
better compatibility with hardware decoders that only support specific
channel counts (e.g. 5.1 now should work on a decoder that only accepts 7.1).
- Channel fallback (in case the audio device doesn't natively support a given
channel layout) has been improved.
- `vf_vapoursynth` now rejects unaligned video instead of outputting corrupted
video.
- mpv now tries to autoload `.sup` subtitles as well.
Bug fixes
---------
- `vo_opengl`'s default for `fbo-format` is now `rgba16`, to avoid rounding
errors when using non-default `cscale` (issue #1918).
- Improved framedrop behavior when playing video that has higher framerate
than the display (issue #1897).
- Trying to play a directory will no longer spam `Connection lost!` to the
console log.
- (Linux) Several `vo_rpi` bugfixes.
- (Linux) Several `vo_drm` bugfixes. Pan&Scan is now supported.
- (X11) Fix fullscreen behavior on certain window managers (issues #1937,
#1920).
- (OSX) The OSD no longer always shows up on startup.
- (OSX) Several `ao_coreaudio` and `ao_coreaudio_exclusive` bugfixes.
- (OSX) Fixed potential crash on exit when using Cocoa.
- (ClientAPI) `vo_opengl_cb` now actually applies options changed at runtime.
- (OSX, ClientAPI) Cocoa now works when both the `cplayer` (`mpv`) and `libmpv`
are built at the same time; however, `libmpv` now always creates an
application singleton. Cocoa has to be disabled completely to prevent
`libmpv` from creating the singleton.
This listing is not complete. A complete changelog can be seen by running
`git log v0.9.1..v0.9.2` in the git repository or by visiting
https://github.com/mpv-player/mpv/compare/v0.9.1...v0.9.2.
Release 0.9.1
=============
Changes
-------
- mpv's IRC channel moved from #mpv-player to #mpv on chat.freenode.net.
- Documentation updates.
- The default value for the `--ytdl-format` option is now `best`, in order to
work around `youtube-dl`'s 2015.04.26 release enabling DASH by default, as
FFmpeg / Libav do not yet properly support DASH.
- When seeking, the current timestamp will show the predicted seek timestamp
instead, until the final timestamp is resolved. Improves UI responsiveness
on slow streams and/or large seeks.
Bug fixes
---------
- Corrected the release marker on DOCS/client-api-changes. The release manager
forgot to fix it before release...
- Fix `vo_vdpau` rendering garbage lines on H.264 video with non-mod16 size
(issue #1863).
- Fix a crash on exit if the "sub_reload" command had run successfully.
- Fixed seeking with the mouse when `osc-seekbarstyle=bar` is set (issue
#1876).
- (IPC) Fixed encoding of UTF-8 data in JSON (issue #1874).
New features
------------
This listing is not complete. A complete changelog can be seen by running
`git log v0.9.0..v0.9.1` in the git repository or by visiting
https://github.com/mpv-player/mpv/compare/v0.9.0...v0.9.1.
Release 0.9.0
=============
Changes
-------
Changes that may break users' config files have been annotated with a `(!)`.
- Note: mpv is not compatible with Lua 5.3. Lua 5.1 or 5.2 is required.
- The minimum required libass version is now 0.12.1 or newer.
- The minimum required FFmpeg version is now 2.4.0 (equiv. Libav 11) or newer.
- The internal libmpg123 support was removed. This was already not used by
default in the previous release.
- `(!)` The LIRC support was removed. Configure LIRC remotes as input devices
instead.
- `(!)` The Linux Joystick support was removed.
- `(!)` `vf_screenshot` was removed, as they are now handled at a VO level and
is compatible with all VOs.
- `(!)` `--ass-use-margins` has been renamed to `--sub-use-margins` and applies
only to plain-text (non-ASS) subtitles (enabled by default). The new
`--ass-force-margins` option applies only to ASS subtitles (disabled by
default). To get the old behaviour back, enable both at the same time.
- `(!)` The `--sub-scale-with-window` option now only applies to plain text
(non-ASS) subtitles (enabled by default). The new `--ass-scale-with-window`
option does the same but only with ASS subtitles (disabled by default).
- `(!)` The range for the `param1` for the `gaussian` `vo_opengl` scaler has
been redefined. Instead of being an arbitrary 1-100 range, have a default
value of 1.0, and anything higher is blurrier.
- `(!)` The `seek`, `playlist_next, `playlist_prev`, `loadfile` and `loadlist`
parameters no longer accept numerical parameters where symbolic parameter
names exist.
- `(!)` `vo_opengl` changes:
- `(!)` The `smoothmotion` suboption has been renamed to `interpolation`.
The old name is still supported for now.
- `(!)` The `bilinear_slow` scaler has been renamed to `triangle`.
- `(!)` `scale-down` has been renamed to `dscale` and now has its own set of
config options (e.g. `dscale-radius`).
- `(!)` Scaler radius no longer defaults to `3` but to a preferred value
that may be different for each filter.
- The `scale-radius` option may now go down as low as `0.5`, which is the
value used by the `nearest` filter.
- `spline36` is the new `cscale` default for `opengl-hq`. This might break
setups that use `fbo-format=rgb8`. To work around it, leave `fbo-format`
as its default, or set to something higher than 8, or set `cscale=bilinear`,
the previous default.
- `(!)` `vf_format` no longer converts video to YUYV if there is no parameter.
Video is now passed unchanged unless a format is specifically requested.
- `(!)` The `--colormatrix`, `--colormatrix-input-range`,
`--colormatrix-output-range` and `--colormatrix-primaries` options have been
converted into `vf_format` suboptions. See commit 27715b7 and the manual for
details.
- `vf_mirror`'s implementation was replaced with calling into `libavfilter`'s
`vf_hflip` filter, thus depending on `libavfilter` to function.
- The `device` subption to `ao_wasapi` has been deprecated in favor of
`--audio-device`.
- `--video-rotate` now allows 360 as an argument instead of stopping at 359.
- Several improvements to `af_scaletempo`.
- Options that have multiple options and also include a "yes" option now
default to that if specified with no arguments.
- The default value of `--cache-default` is now 150000 (153.6 MB, ~146 MiB).
- JPEG screenshots now use the same subsampling as the source video. The images
are still RGB regardless of source format though.
Bug fixes
---------
- mpv no longer saves position on files that can't be resumed (issue #1701).
- (X11) Fix the player thinking the mouse has left the window in some WMs /
embeddings (issue #1672).
- mpv no longer freezes on wayland when the compositor stops asking it to draw
itself (e.g. when minimized) (issue #249).
- `.ac3` files are no longer rejected by `--audio-file-auto` (issue #1759).
- `ao_wasapi` now automatically enables `exclusive` when passthrough is
attempted (issue #1742).
- Attempt to fix flickering on Intel VAAPI drivers with `--hwdec=vaapi` and
`--vo=opengl` (issue #1765).
- `youtube-dl` will no longer download video streams when video playback
is disabled with `--no-video`.
- (Windows) mpv now prevents system sleep when playing a video-only file.
Previously, only files with an opened audio track would prevent sleep.
New features
------------
- `vo_opengl` features:
- Added `ewa_ginseng`, `ewa_hanning`, `robidoux`, `robidouxsharp`,
`oversample` and `haasnsoft` scalers.
- There are now `ewa_lanczossoft` and `ewa_lanczossharp` aliases to
`ewa_lanczos` that are tuned to be blurrier and sharper, respectively.
- Added `gamma-auto` option that uses ambient light sensors to automatically
adjust the video gamma. See commit c028d78 for details.
- Added `blend-subtitles` option to draw subtitles directly into the video
instead of rendered afterwards. Potentially necessary for correct rendering
with files that use ASS subtitles for typesetting in combination with an
`icc-profile`. There is a default option for drawing after upscaling,
and a `video` option for drawing before upscaling. See details and warning
on the manual.
- There is now a `tscale` option, used to choose the temporal scaler used
in the `interpolation` mode (previously `smoothmotion`).
- There is a new `scale-blur` parameter to adjust the amount of blur that
most of the filters produce. Deviating from the default may introduce
artifacts in EWA filters.
- (Windows) There is now a `dwmflush` option that might help improve
rendering of high-fps video. Disabled by default. See manual for options.
- New Linux-only `vo_drm` video output driver. Uses the direct rendering /
kernel modesetting drivers to draw directly to the framebuffer, but with
no hardware acceleration. See manual for details.
- New `pseudo-gui` builtin profile, automatically used when launched from
`mpv.desktop` by opening `mpv.exe` on windows (`mpv.com` still works as
usual), or by opening the `mpv.app` bundle. The `pseudo-gui` tries to make
the player window behave closer to what a desktop player would do, by not
immediately closing and allowing the user to drag&drop files for playback.
See manual for details.
- mpv can now play directories by automatically playing their contents instead.
Works everywhere but on Windows, due to issues with Windows' C runtime.
- Add support to pitch correct stretched audio with librubberband.
- Add support for the Raspberry Pi 2's hardware decoder when FFmpeg (or Libav)
is built with `--enable-mmal`. See commit 8fff125 for details.
- The `--cache` option now accepts a "yes" option, that always enables a
`--cache-default`-sized cache on all cases a cache can be used, unless
`--cache-default` disables caching.
- `ao_pulse`, `ao_coreaudio` and `ao_wasapi` now support device hotplugging.
- New `--osd-align-x` and `--osd-align-y` options can be used to align the OSD
independently from subtitles.
- New `--osd-bold` and `--sub-text-bold` options can be enabled to bold all
OSD or plain-text subtitle text, respectively.
- Added a default keybind to the `u` key that enables/disables ASS style
overriding. When enabled, is equivalent to `--ass-style-override=force`.
- There is now a `MOUSE_ENTER` keybind, that is called when the mouse cursor
enters the VO from outside.
- The new `--ytdl-params` option can be set to arguments that are always given
to `youtube-dl` invocations. There is no sanity checking, so invalid options
can prevent `mpv` from working with http URLs.
- There's a new `--demuxer-mkv-fix-timestamps` option, enabled by default, that
tries to guess more accurate video timestamps by using FPS information, if
available. See manual for details.
- The new `--window-scale` option can be used to scale the video window by the
specified multiplier, before other options such as `--autofit` are applied.
- `vo_direct3d_shaders` now supports NV12 colorspace without using stretchrect,
but it seems no drivers actually support that.
- (Client API) Added a `rescan_external_files` command, as requested on issue
#1586.
- (Client API) If enabled, initializing the Client API will now also load the
user's `mpv.conf`.
- (Client API) There's a new `mpv_opengl_cb_report_flip()` call for API users
to call to inform mpv of when exactly a frame was displayed.
- (Client API) The `mpv_opengl_cb_render()` function was deprecated in favor
of the new, simpler `mpv_opengl_cb_draw()` function.
- (Client API) There is a new `screenshot_raw` command. See `input.rst` for
details.
- The `--input-file` argument may now also be a file descriptor in the form
"fd://N", where N is the FD number.
This listing is not complete. A complete changelog can be seen by running
`git log v0.8.0..v0.9.0` in the git repository or by visiting
https://github.com/mpv-player/mpv/compare/v0.8.0...v0.9.0 (only 250 commits).
Release 0.8.3
=============
@@ -610,9 +11,6 @@ Bug fixes
---------
- (X11) Fix crash on `vo_xv:no-colorkey` with the Overlay adapter. (bug #1629)
- (X11) `--stop-screensaver` is now implemented by calling into
`xdg-screensaver`, fixing some compatibility issues that prevented it from
actually stopping screensavers.
- Make the video equalizer work correctly on some VAAPI drivers. (bug #1647)
- Prevent OSD from disappearing when clicking on mozplugger. (bug #1672)
- The new DVB-S2 support code, using S2API, now builds on FreeBSD.
@@ -628,8 +26,7 @@ Bug fixes
- Fix anamorphic scaling being ignored if it was very minor.
This listing is not complete. A complete changelog can be seen by running
`git log v0.8.2..v0.8.3` in the git repository or by visiting
https://github.com/mpv-player/mpv/compare/v0.8.2...v0.8.3.
`git log v0.8.2..v0.8.3` in the git repository.
Release 0.8.2
=============
@@ -637,7 +34,7 @@ Release 0.8.2
Bug fixes
---------
- Fix OSD placement accidentally messed up in 0.8.1 (commit 22863d6).
- Fix OSD placement accidentally messed up in 0.8.1.
Release 0.8.1
=============
@@ -668,8 +65,7 @@ New features
- mpv now tries to load '.vtt' subtitles.
This listing is not complete. A complete changelog can be seen by running
`git log v0.8.0..v0.8.1` in the git repository or by visiting
https://github.com/mpv-player/mpv/compare/v0.8.0...v0.8.1.
`git log v0.8.0..v0.8.1` in the git repository.
Release 0.8.0
=============
@@ -835,224 +231,4 @@ New features
files.
This listing is not complete. A complete changelog can be seen by running
`git log v0.7.0..v0.8.0` in the git repository or by visiting
https://github.com/mpv-player/mpv/compare/v0.7.0...v0.8.0 (only 250 commits).
Release 0.7.3
=============
Changes
-------
- Several documentation updates and typo fixes.
- Don't show "0%" position when the stream is infinite / has unknown length.
- Fixes the config file loading order so that lower priority `mpv.conf` files
don't override higher priority `config` files.
- (OSX) Remove coreaudio_exclusive from the "auto" codec list.
- Failing to create a GL3 context is now a warning instead of error, to reduce
user confusion.
- The subtitle decoder now gets reset when cycling subtitles. This makes the
currently shown subtitle event disappear even if cycling back to the current
subtitle track.
- `--shuffle` and `--merge-files` now affects the contents of playlist files,
instead of just the list of files given as arguments to mpv.
- `./waf install` avoids installing a few additional data/config files if only
libmpv was built.
- Improved channel mapping when the file's channel map doesn't match the AO's
available channel maps.
- (OSX) VDA now gracefully refuses to run on non-OpenGL3-capable systems instead
of trying and failing to build its shaders.
- Add workaround for vf_vapoursynth filters that expect an FPS.
- The default value for `--screenshot-template` now shows up in
`--list-options`.
- `ao_pulse`'s `latency-hacks` suboption is now off by default, as it causes
issues with newer pulseaudio releases. If A/V Sync issues happen, either
add the `latency-hacks=on` pulse suboption in mpv.conf, or update the
pulseaudio daemon (bug #1430).
- (Linux) `ao_alsa` now deals better with audio device disconnection.
- Client API: timestamp properties that have no value return "no" instead of
magic number.
Bug fixes
---------
- (Windows, OSX) Many `ao_wasapi` and `ao_coreaudio` fixes.
- (OSX) Make the window title update correctly on OS X Yosemite.
- Fixes for handling mono audio on various AOs.
- (Linux) Fixes resuming from suspend on ao_alsa.
- Fixes for playlist file parsing.
- Overly long options in the --list-options output now break the column layout
instead of getting truncated; fixes shell completion scripts.
- Fix rendering resolution of certain DVB subtitles (bug #1425).
- Fix EDL or --merge-files breaking timestamps with .avi files.
- Workaround for libavcodec bug with the VP9 codec parser (bug #1448),
fixes possible crash.
- Improve robustness of the matroska parser with broken files (bugs #1457,
#1461).
- Improve 10bit video compatibility with older GPUs (specially Intel) (bug
#1383).
- Fixes flashing the VO window when playing a list of files that includes
non-media files (bug #1459).
- Workaround for window embedding in OpenBox (bug #1235)
- Fixes for several crashes and lockups (bugs #838, #1389, #1408, #1463, #1473,
#1474).
- Fixes for the zsh completion script (bugs #997)
New features
------------
- mpv now prints the contents of its config.h when running in verbose mode, to
aid with debugging.
- The `include=` option now accepts `~` to refer to the HOME dir (bug #1406).
- `af_volume` now prints ReplayGain values in verbose mode.
- m3u playlists that don't have the `#EXTM3U` header are now accepted if they
"look like" ASCII or UTF-8 text and have the .m3u extension.
- Chapter marks in the seek bar now update when switching files.
- Supports embedded cover art in MKV files (bug #1374).
- (Windows) Video window can now be resized even with --no-border.
- (Windows) Client API: the "run" command now works on Windows too.
- (Linux) vo_wayland now supports key modifiers (Meta, Alt, Control, Shift)
- Client API: "display-names" property is now observable.
This listing is not complete. A complete changelog can be seen by running
`git log v0.7.2..v0.7.3` in the git repository or by visiting
https://github.com/mpv-player/mpv/compare/v0.7.2...v0.7.3.
Release 0.7.2
=============
Changes
-------
- Give precedence to the DVD menu navigation keyboard bindings so that user
defined LEFT/RIGHT/... bindings don't break DVD menu navigation.
- Try to fallback to the "default" device if the selected device is busy in the
alsa AO.
- Don't create Dock icon for audio only files on OS X.
- Save screenshots to desktop when using the app bundle on OS X.
- Restore ab-loop settings with playback resume.
- Bump required youtube-dl version to 2014.11.26 and enable the ytdl_hook Lua
script by default (now playing videos from YouTube and the like will work
out of the box without any configuration change needed).
Bug fixes
---------
- Don't signal an error if --stream-dump is used.
- Fix removing key bindings from Lua scripts.
- Reject channel descriptions with too many channels in the coreaudio AO.
- Don't async redraw when waiting for VO redraw on OS X (this fixes the very
annoying glitch where the black bars disappear for a single frame when going
fullscreen).
- Fix mono playback with the also AO.
- Don't crash if framebuffers are not available in the opengl VO.
New features
------------
- Try to handle multi-arc videos in the ytdl_hook Lua script.
This listing is not complete. There are many more bug fixes and changes. The
complete change log can be viewed by running ``git log 47ec404..c7d6b21`` in
the git repository or by visiting
https://github.com/mpv-player/mpv/compare/47ec404...c7d6b21.
Release 0.7.1
=============
Changes
-------
- Don't show the volume neutral marker on the OSD if softvol is disabled.
- Don't select a subtitle track when executing the sub_add input command in
"auto" mode.
Bug fixes
---------
- Fix busy loop when seeking while paused (this fixes a problem with pulseaudio
that caused mpv and the pulseaudio daemon to use 100% CPU).
- Fix Lua function utils.subprocess() in Windows versions older than Vista.
- Avoid creating a window bigger than the screen on Windows.
- Don't ignore the last line in m3u playlists.
- Don't crash if a codec could not be opened.
- Dynamically allocate audio channel map entries (this should fix a crash in
the alsa and coreaudio AOs with audio devices that support more than 20
channel maps).
- Ignore the "srgb" option in the opengl VO if hardware decoding is enabled.
- Linearize non-RGB sRGB files correctly (eg. JPEG).
- Fix opening reference URLs (.file/id=) on OS X.
This listing is not complete. There are many more bug fixes and changes. The
complete change log can be viewed by running ``git log 8d8b36d..6583ad6`` in
the git repository or by visiting
https://github.com/mpv-player/mpv/compare/8d8b36d...6583ad6.
Release 0.7.0
=============
Changes
-------
- Buffer partial log messages in the client API (the client API will now only
pass full log messages to clients).
- Remove ncurses/terminfo/termcap support (it was disabled by default and
replaced by new code since v0.6.0).
- Enable cdda:// support by default again (it was disabled since v0.6.0).
- Cascade-load input.conf (if there are several input.confs in the set of valid
config paths, load them all).
- Draw the OSD twice in 3D mode (this fixes subtitles display in 3D mode).
- Make wasapi the default AO on Windows again since many of its problems have
been solved.
- Use "site-functions" subdir to install the zsh completion script instead of
the Debian-specific "vendor-completions" (also provide the --zshdir waf
configure option for changing this value).
- Improve synchronization between the Cocoa GUI and the player (this fixes some
long standing deadlock issues on Mac OS X).
- Remove --fs-missioncontrol option (only relevant to Mac OS X).
New features
------------
- Enable pitch correction by default when playing at higher speeds (this can be
controlled with the --audio-pitch-correction option).
- Open stream and demuxer asynchronously (this should avoid having the player
get blocked on network streams).
- Add cache-buffering-state property for querying the cache fill status until
the player unpauses.
- Add support for listing and selecting the audio device (note that it is not
implemented for all AOs, see the --audio-device option for more information).
- Add support for a JSON-based IPC mechanism (note that this is not currently
supported on Windows, see the JSON IPC section in the manpage for more
information).
- Add Lua utility function for starting processes (see utils.subprocess() in the
manpage).
- Add Lua utility function for parsing JSON (see utils.parse_json() in the
manpage).
- Add field-dominance property (see --field-dominance option).
- Add video-rotate property (see --video-rotate option).
- Add playback-abort property for querying whether playback is stopped or is to
be stopped.
- Add cursor-autohide property (see --cursor-autohide option).
- Add vo-configured property for querying whether a window is created.
- Add support for dxva2 hardware acceleration on Windows.
- Drop libquvi support (this has been replaced by a built-in Lua script that
invokes the youtube-dl tool, which needs to be installed, see the --ytdl
option).
- Add support for loading chapters from an external file (see the
--chapters-file option).
- Add window-minimized property for querying whether the window is minimized
(works for X11 only).
- Make it possible to configure the OSC seekbar style (see the "seekbarstyle"
OSC option).
- Add support for libmpv on Mac OS X (it used to be broken, now it's fully
functional and also provides support for embedding the mpv window inside a
Cocoa/Qt application).
- Try to use the audio channel map reported by ALSA in the alsa AO.
- Add option to disable text OSD rendering completely (useful for working around
certain fontconfig issues, see the --use-text-osd option).
This listing is not complete. There are many more bug fixes and changes. The
complete change log can be viewed by running ``git log 7759c18..9479daa`` in
the git repository or by visiting
https://github.com/mpv-player/mpv/compare/7759c18...9479daa (only 250 commits).
`git log v0.7.0..v0.8.0` in the git repository.
+7 -7
View File
@@ -47,7 +47,7 @@ judge()
progressive=$((progressive + progressive1))
undetermined=$((undetermined + undetermined1))
done <<EOF
$(testfun "$@" | sed 's/:/: /g')
$(testfun "$@")
EOF
interlaced=$((bff + tff))
@@ -95,18 +95,18 @@ case "$verdict" in
exit 0
;;
interlaced-tff)
judge "$@" --vf-clr --vf-pre=lavfi=\[setfield=tff\],pullup
judge "$@" --vf-clr --vf-pre=pullup --field-dominance=top
case "$verdict" in
progressive)
[ -n "$ILDETECT_DRY_RUN" ] || \
$ILDETECT_MPV "$@" --vf-pre=lavfi=\[setfield=tff\],pullup
$ILDETECT_MPV "$@" --vf-pre=pullup --field-dominance=top
r=$?
[ $r -eq 0 ] || exit $((r | 16))
exit 1
;;
*)
[ -n "$ILDETECT_DRY_RUN" ] || \
$ILDETECT_MPV "$@" --vf-pre=lavfi=\[setfield=tff\],yadif
$ILDETECT_MPV "$@" --vf-pre=yadif --field-dominance=top
r=$?
[ $r -eq 0 ] || exit $((r | 16))
exit 2
@@ -114,18 +114,18 @@ case "$verdict" in
esac
;;
interlaced-bff)
judge "$@" --vf-clr --vf-pre=lavfi=\[setfield=bff\],pullup
judge "$@" --vf-clr --vf-pre=pullup --field-dominance=bottom
case "$verdict" in
progressive)
[ -n "$ILDETECT_DRY_RUN" ] || \
$ILDETECT_MPV "$@" --vf-pre=lavfi=\[setfield=bff\],pullup
$ILDETECT_MPV "$@" --vf-pre=pullup --field-dominance=bottom
r=$?
[ $r -eq 0 ] || exit $((r | 16))
exit 1
;;
*)
[ -n "$ILDETECT_DRY_RUN" ] || \
$ILDETECT_MPV "$@" --vf-pre=lavfi=\[setfield=bff\],yadif
$ILDETECT_MPV "$@" --vf-pre=yadif --field-dominance=bottom
r=$?
[ $r -eq 0 ] || exit $((r | 16))
exit 2
+1 -1
View File
@@ -84,7 +84,7 @@ sub elem_by_hexid {
# used by elem when setting the 'valname' key
use constant TYPE_MAP => {
uint => 'uint64_t',
str => 'char *',
str => 'struct bstr',
binary => 'struct bstr',
ebml_id => 'uint32_t',
float => 'double',
-2
View File
@@ -10,5 +10,3 @@ to mpv's command line.
Where appropriate, they may also be placed in ~/.config/mpv/scripts/ from
where they will be automatically loaded when mpv starts.
Some of these are just for testing mpv internals.
-13
View File
@@ -1,13 +0,0 @@
local utils = require("mp.utils")
mp.observe_property("audio-device-list", "native", function(name, val)
print("Audio device list changed:")
for index, e in ipairs(val) do
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)
+45 -26
View File
@@ -2,16 +2,21 @@
-- appropriate deinterlacing filter based on a short section of the
-- 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
-- filters and decides whether the content is progressive, interlaced, or
-- telecined and the interlacing field dominance.
-- It registers the key-binding ctrl+d, which when pressed, inserts
-- the filter vf=lavfi=idet. After 4 second, it examines the results
-- to determine whether the content progressive or interlaced and the
-- interlacing field dominance. It immediately sets the latter within
-- mpv.
--
-- 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.
-- If the content is judged not to be progressive, it may be either
-- interlaced or telecined. To determine which one, the video is
-- seeked back to the detection starting point with the "pullup"
-- filter inserted. After another four seconds, if idet thinks that
-- the pulled up viedo is "progressive", then pullup is the correct
-- filter and this script leaves it in places while removing the idet
-- filter. Otherwise, the content plain interlaced and mpv's deinterlace
-- property is set. This will usually insert the yadif deinterlacing filter.
--
-- OPTIONS:
-- The default detection time may be overridden by adding
--
-- --script-opts=autodeint.detect_seconds=<number of seconds>
@@ -32,7 +37,6 @@ require "mp.msg"
script_name = mp.get_script_name()
detect_label = string.format("%s-detect", script_name)
pullup_label = string.format("%s", script_name)
ivtc_detect_label = string.format("%s-ivtc-detect", script_name)
-- number of seconds to gather cropdetect data
detect_seconds = tonumber(mp.get_opt(string.format("%s.detect_seconds", script_name)))
@@ -65,29 +69,30 @@ function start_detect()
mp.set_property("deinterlace","no")
del_filter_if_present(pullup_label)
percent_pos = mp.get_property("percent-pos")
-- 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)
local cmd = string.format('vf add @%s:lavfi=graph="idet"', detect_label)
if not mp.command(cmd) then
mp.msg.error("failed to insert detection filters")
mp.msg.error("failed to insert detection filter")
return
end
-- wait to gather data
timer = mp.add_timeout(detect_seconds, select_filter)
timer = mp.add_timeout(detect_seconds, judge_field_dominance)
end
function stop_detect()
del_filter_if_present(detect_label)
del_filter_if_present(ivtc_detect_label)
timer = nil
mp.set_property("playback-pos", percent_pos)
end
progressive, interlaced_tff, interlaced_bff, interlaced = 0, 1, 2, 3, 4
function judge(label)
function judge()
-- get the metadata
local result = mp.get_property_native(string.format("vf-metadata/%s", label))
local result = mp.get_property_native(string.format("vf-metadata/%s", detect_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"])
@@ -95,10 +100,10 @@ function judge(label)
num_interlaced = num_tff + num_bff
num_determined = num_interlaced + num_progressive
mp.msg.verbose(label.." progressive = "..num_progressive)
mp.msg.verbose(label.." interlaced-tff = "..num_tff)
mp.msg.verbose(label.." interlaced-bff = "..num_bff)
mp.msg.verbose(label.." undetermined = "..num_undetermined)
mp.msg.verbose("progressive = "..num_progressive)
mp.msg.verbose("interlaced-tff = "..num_tff)
mp.msg.verbose("interlaced-bff = "..num_bff)
mp.msg.verbose("undetermined = "..num_undetermined)
if num_determined < num_undetermined then
mp.msg.warn("majority undetermined frames")
@@ -114,12 +119,11 @@ function judge(label)
end
end
function select_filter()
-- handle the first detection filter results
verdict = judge(detect_label)
function judge_field_dominance()
verdict = judge()
if verdict == progressive then
mp.msg.info("progressive: doing nothing")
stop_detect()
mp.msg.info("progressive: doing nothing")
return
elseif verdict == interlaced_tff then
mp.set_property("field-dominance", "top")
@@ -129,8 +133,21 @@ function select_filter()
mp.set_property("field-dominance", "auto")
end
-- handle the ivtc detection filter results
verdict = judge(ivtc_detect_label)
local cmd = string.format("vf pre @%s:pullup", pullup_label)
if not mp.command(cmd) then
mp.msg.error("failed to insert pullup filter")
stop_detect()
return
end
-- redo the detection with the pullup filter to see if it's telecined
mp.set_property("percent-pos", percent_pos)
timer = mp.add_timeout(detect_seconds, judge_ivtc)
end
function judge_ivtc()
verdict = judge()
if verdict == progressive then
mp.msg.info(string.format("telecinied with %s field dominance: using pullup", mp.get_property("field-dominance")))
stop_detect()
@@ -140,6 +157,8 @@ function select_filter()
mp.set_property("deinterlace","yes")
stop_detect()
end
return
end
mp.add_key_binding("ctrl+d", script_name, start_detect)
+3 -49
View File
@@ -4,19 +4,8 @@
-- alphabetically, and adds entries before and after the current file to
-- the internal playlist. (It stops if the it would add an already existing
-- playlist entry at the same position - this makes it "stable".)
-- Add at most 5000 * 2 files when starting a file (before + after).
MAXENTRIES = 5000
function Set (t)
local set = {}
for _, v in pairs(t) do set[v] = true end
return set
end
EXTENSIONS = Set {
'mkv', 'avi', 'mp4', 'ogv', 'webm', 'rmvb', 'flv', 'wmv', 'mpeg', 'mpg', 'm4v', '3gp',
'mp3', 'wav', 'ogv', 'flac', 'm4a', 'wma',
}
-- Add at most 5 * 2 files when starting a file (before + after).
MAXENTRIES = 5
mputils = require 'mp.utils'
@@ -29,51 +18,20 @@ function add_files_at(index, files)
end
end
function get_extension(path)
return string.match(path, "%.([^%.]+)$" )
end
table.filter = function(t, iter)
for i = #t, 1, -1 do
if not iter(t[i]) then
table.remove(t, i)
end
end
end
function find_and_add_entries()
local path = mp.get_property("path", "")
local dir, filename = mputils.split_path(path)
if #dir == 0 then
return
end
local pl_count = mp.get_property_number("playlist-count", 1)
if (pl_count > 1 and autoload == nil) or
(pl_count == 1 and EXTENSIONS[string.lower(get_extension(filename))] == nil) then
return
else
autoload = true
end
local files = mputils.readdir(dir, "files")
if files == nil then
return
end
table.filter(files, function (v, k)
local ext = get_extension(v)
if ext == nil then
return false
end
return EXTENSIONS[string.lower(ext)]
end)
table.sort(files, function (a, b)
return string.lower(a) < string.lower(b)
end)
table.sort(files)
if dir == "." then
dir = ""
end
local pl = mp.get_property_native("playlist", {})
local pl_current = mp.get_property_number("playlist-pos", 0) + 1
-- Find the current pl entry (dir+"/"+filename) in the sorted dir list
@@ -87,7 +45,6 @@ function find_and_add_entries()
if current == nil then
return
end
local append = {[-1] = {}, [1] = {}}
for direction = -1, 1, 2 do -- 2 iterations, with direction = -1 and +1
for i = 1, MAXENTRIES do
@@ -96,7 +53,6 @@ function find_and_add_entries()
if file == nil or file[1] == "." then
break
end
local filepath = dir .. file
if pl_e then
-- If there's a playlist entry, and it's the same file, stop.
@@ -104,7 +60,6 @@ function find_and_add_entries()
break
end
end
if direction == -1 then
if pl_current == 1 then -- never add additional entries in the middle
mp.msg.info("Prepending " .. file)
@@ -116,7 +71,6 @@ function find_and_add_entries()
end
end
end
add_files_at(pl_current + 1, append[1])
add_files_at(pl_current, append[-1])
end
+2 -2
View File
@@ -4,7 +4,7 @@
-- parameters. See the entry for "drc" under the "AUDIO FILTERS"
-- section of the man page for a complete description of the filter.
--
-- This script registers the key-binding "\" to toggle the filter between
-- This script registers the key-binding "\" to toggle the filter between
--
-- * off
-- * method=1 (single-sample smoothing)
@@ -92,7 +92,7 @@ function drc_quieter_handler()
drc_scale_target(0.5)
end
-- toggle between off, method 1 and method 2
-- toggle between off, method 1 and method 2
mp.add_key_binding("\\", "drc_toggle_method", drc_toggle_method_handler)
-- increase or decrease target volume
mp.add_key_binding("ctrl+9", "drc_quieter", drc_quieter_handler)
-19
View File
@@ -1,19 +0,0 @@
--makes mpv disable ontop when pausing and re-enable it again when resuming playback
--please note that this won't do anything if ontop was not enabled before pausing
local was_ontop = false
mp.observe_property("pause", "bool", function(name, value)
local ontop = mp.get_property_native("ontop")
if value then
if ontop then
mp.set_property_native("ontop", false)
was_ontop = true
end
else
if was_ontop and not ontop then
mp.set_property_native("ontop", true)
end
was_ontop = false
end
end)
+2
View File
@@ -2,6 +2,8 @@
-- if it's brought back again. If the player was already paused when minimizing,
-- then try not to mess with the pause state.
-- Note: currently works with X11 only.
local did_minimize = false
mp.observe_property("window-minimized", "bool", function(name, value)
+1 -3
View File
@@ -1,7 +1,5 @@
-- Rebuild the terminal status line as a lua script
-- Be aware that this will require more cpu power!
-- Also, this is based on a rather old version of the
-- builtin mpv status line.
-- Add a string to the status line
function atsl(s)
@@ -30,7 +28,7 @@ function update_status_line()
atsl(mp.get_property_osd("time-pos"))
atsl(" / ");
atsl(mp.get_property_osd("duration"));
atsl(mp.get_property_osd("length"));
atsl(" (")
atsl(mp.get_property_osd("percent-pos", -1))
-74
View File
@@ -1,74 +0,0 @@
-- zones.lua: mpv script for handling commands depending on where the mouse pointer is at,
-- mostly for mouse wheel handling, by configuring it via input.conf, e.g.:
--
-- Ported from avih's ( https://github.com/avih ) zones.js
--
-- Vertical positions can be top, middle, bottom or "*" to represent the whole column.
-- Horizontal positions can be left, middle, bottom or "*" to represent the whole row.
-- "default" will be the fallback command to be used if no command is assigned to that area.
--
-- input.conf example of use:
-- # wheel up/down with mouse
-- MOUSE_BTN3 script_message_to zones commands "middle-right: add brightness 1" "*-left: add volume 5" "default: seek 10"
-- MOUSE_BTN4 script_message_to zones commands "middle-right: add brightness -1" "*-left: add volume -5" "default: seek -10"
local ZONE_THRESH_PERCENTAGE = 20;
-- sides get 20% each, mid gets 60%, same vertically
local msg = mp.msg
function getMouseZone()
-- returns the mouse zone as two strings [top/middle/bottom], [left/middle/right], e.g. "middle", "right"
local screenW, screenH = mp.get_osd_resolution()
local mouseX, mouseY = mp.get_mouse_pos()
local threshY = screenH * ZONE_THRESH_PERCENTAGE / 100
local threshX = screenW * ZONE_THRESH_PERCENTAGE / 100
local yZone = (mouseY < threshY) and "top" or (mouseY < (screenH - threshY)) and "middle" or "bottom"
local xZone = (mouseX < threshX) and "left" or (mouseX < (screenW - threshX)) and "middle" or "right"
return yZone, xZone
end
function main (...)
local arg={...}
msg.debug('commands: \n\t'..table.concat(arg,'\n\t'))
local keyY, keyX = getMouseZone()
msg.debug("mouse at: " .. keyY .. '-' .. keyX)
local fallback = nil
for i, v in ipairs(arg) do
cmdY = v:match("^([%w%*]+)%-?[%w%*]*:")
cmdX = v:match("^[%w%*]*%-([%w%*]+)%s*:")
cmd = v:match("^[%S]-%s*:%s*(.+)")
msg.debug('cmdY: '..tostring(cmdY))
msg.debug('cmdX: '..tostring(cmdX))
msg.debug('cmd : '..tostring(cmd))
if (cmdY == keyY and cmdX == keyX) then
msg.verbose("running cmd: "..cmd)
mp.command(cmd)
return
elseif (cmdY == "*" and cmdX == keyX) or
(cmdY == keyY and cmdX == "*") then
msg.verbose("running cmd: "..cmd)
mp.command(cmd)
return
elseif cmdY == "default" then
fallback = cmd
end
end
if fallback ~= nil then
msg.verbose("running cmd: "..fallback)
mp.command(fallback)
return
else
msg.debug("no command assigned for "..keyY .. '-' .. keyX)
return
end
end
mp.register_script_message("commands", main)
+1 -1
View File
@@ -40,7 +40,7 @@ def apply_plist_template(plist_file, version):
print (line.rstrip().replace('${VERSION}', version))
def main():
version = sh("./version.sh").strip()
version = sh("./version.sh --print").strip()
usage = "usage: %prog [options] arg"
parser = OptionParser(usage)
@@ -1 +1,3 @@
profile=pseudo-gui
screenshot-template=~/Desktop/shot%n
quiet
idle=once
+3 -15
View File
@@ -5,10 +5,7 @@ import re
filename = sys.argv[1]
events = ".*"
if len(sys.argv) > 2:
events = sys.argv[2]
event_regex = re.compile(events)
event_regex = re.compile(".*")
"""
This script is meant to display stats written by mpv --dump-stats=filename.
@@ -29,8 +26,8 @@ Currently, the following event types are supported:
'end' <name> end of the named event
'value' <float> <name> a normal value (as opposed to event)
'event-timed' <ts> <name> singular event at the given timestamp
'value-timed' <ts> <float> <name> a value for an event at the given timestamp
'range-timed' <ts1> <ts2> <name> like start/end, but explicit times
'value-timed' <ts> <float> <name>
a value for an event at the given timestamp
<name> singular event (same as 'signal')
"""
@@ -94,15 +91,6 @@ for line in [line.split("#")[0].strip() for line in open(filename, "r")]:
val = int(val) / SCALE - G.start
e = get_event(name, "event-signal")
e.vals.append((val, 1))
elif event.startswith("range-timed "):
_, ts1, ts2, name = event.split(" ", 3)
ts1 = int(ts1) / SCALE - G.start
ts2 = int(ts2) / SCALE - G.start
e = get_event(name, "event")
e.vals.append((ts1, 0))
e.vals.append((ts1, 1))
e.vals.append((ts2, 1))
e.vals.append((ts2, 0))
elif event.startswith("value-timed "):
_, tsval, val, name = event.split(" ", 3)
tsval = int(tsval) / SCALE - G.start
+1 -1
View File
@@ -21,7 +21,7 @@ script after that will start a new mpv instance.
Note that you can control the mpv instance by writing to the command fifo:
echo "cycle fullscreen" > ~/.umpv_fifo
echo "cycle fullscreen" > ~/.umpv-fifo
Note: you can supply custom mpv path and options with the MPV environment
variable. The environment variable will be split on whitespace, and the
+22
View File
@@ -0,0 +1,22 @@
#!/bin/sh
# Example of script for using mpv with youtube-dl
set -e
cookies_dir="$(mktemp -d /tmp/youtube-dl_mpv.XXXX)"
cookies_file="${cookies_dir}/cookies"
user_agent="$(youtube-dl --dump-user-agent)" # or set whatever you want
video_url=$(youtube-dl \
--user-agent="${user_agent}" \
--cookies="${cookies_file}" \
--get-url \
"$@")
set -f
${MPV:-mpv} \
--cookies \
--cookies-file="${cookies_file}" \
--user-agent="${user_agent}" \
-- ${video_url}
rm -rf "${cookies_dir}"
+55 -53
View File
@@ -7,15 +7,15 @@ use warnings;
my $mpv = $ARGV[0] || 'mpv';
my @opts = parse_main_opts('--list-options', '^ (\-\-[^\s\*]*)\*?\s*(.*)');
my @opts = parse_main_opts("$mpv --list-options", '^ (\-\-[^\s\*]*)\*?\s*(.*)');
my @ao = parse_opts('--ao=help', '^ ([^\s\:]*)\s*: (.*)');
my @vo = parse_opts('--vo=help', '^ ([^\s\:]*)\s*: (.*)');
my @ao = parse_opts("$mpv --ao=help", '^ ([^\s\:]*)\s*: (.*)');
my @vo = parse_opts("$mpv --vo=help", '^ ([^\s\:]*)\s*: (.*)');
my @af = parse_opts('--af=help', '^ ([^\s\:]*)\s*: (.*)');
my @vf = parse_opts('--vf=help', '^ ([^\s\:]*)\s*: (.*)');
my @af = parse_opts("$mpv --af=help", '^ ([^\s\:]*)\s*: (.*)');
my @vf = parse_opts("$mpv --vf=help", '^ ([^\s\:]*)\s*: (.*)');
my @protos = parse_opts('--list-protocols', '^ ([^\s]*)');
my @protos = parse_opts("$mpv --list-protocols", '^ ([^\s]*)');
my ($opts_str, $ao_str, $vo_str, $af_str, $vf_str, $protos_str);
@@ -34,35 +34,36 @@ chomp $af_str;
$vf_str .= qq{ '$_' \\\n} foreach (@vf);
chomp $vf_str;
$protos_str = join(' ', @protos);
$protos_str .= qq{$_ } foreach (@protos);
chomp $protos_str;
my $profile_comp = <<'EOS';
local -a profiles
local current
for current in "${(@f)$($words[1] --profile=help)}"; do
current=${current//\*/\\\*}
current=${current//\:/\\\:}
current=${current//\[/\\\[}
current=${current//\]/\\\]}
if [[ $current =~ $'\t'([^$'\t']*)$'\t'(.*) ]]; then
if [[ -n $match[2] ]]; then
current="$match[1][$match[2]]"
else
current="$match[1]"
local -a profiles
local current
for current in "${(@f)$($words[1] --profile=help)}"; do
current=${current//\*/\\\*}
current=${current//\:/\\\:}
current=${current//\[/\\\[}
current=${current//\]/\\\]}
if [[ $current =~ $'\t'([^$'\t']*)$'\t'(.*) ]]; then
if [[ -n $match[2] ]]; then
current="$match[1][$match[2]]"
else
current="$match[1]"
fi
profiles=($profiles $current)
fi
profiles=($profiles $current)
done
if [[ $state == show-profile ]]; then
# For --show-profile, only one allowed
if (( ${#profiles} > 0 )); then
_values 'profile' $profiles && rc=0
fi
else
# For --profile, multiple allowed
profiles=($profiles 'help[list profiles]')
_values -s , 'profile(s)' $profiles && rc=0
fi
done
if [[ $state == show-profile ]]; then
# For --show-profile, only one allowed
if (( ${#profiles} > 0 )); then
_values 'profile' $profiles && rc=0
fi
else
# For --profile, multiple allowed
profiles=($profiles 'help[list profiles]')
_values -s , 'profile(s)' $profiles && rc=0
fi
EOS
chomp $profile_comp;
@@ -82,27 +83,39 @@ $opts_str
case \$state in
ao)
_values -s , 'audio outputs' \\
local -a values
values=(
$ao_str
&& rc=0
)
_describe -t values 'audio outputs' values && rc=0
;;
vo)
_values -s , 'video outputs' \\
local -a values
values=(
$vo_str
&& rc=0
)
_describe -t values 'video outputs' values && rc=0
;;
af)
_values -s , 'audio filters' \\
local -a values
values=(
$af_str
&& rc=0
)
_describe -t values 'audio filters' values && rc=0
;;
vf)
_values -s , 'video filters' \\
local -a values
values=(
$vf_str
&& rc=0
)
_describe -t values 'video filters' values && rc=0
;;
profile|show-profile)
@@ -141,7 +154,7 @@ sub parse_main_opts {
my ($cmd, $regex) = @_;
my @list;
my @lines = call_mpv($cmd);
my @lines = split /\n/, `$cmd`;
foreach my $line (@lines) {
my ($name, $desc) = ($line =~ /^$regex/) or next;
@@ -206,7 +219,7 @@ sub parse_opts {
my ($cmd, $regex) = @_;
my @list;
my @lines = call_mpv($cmd);
my @lines = split /\n/, `$cmd`;
foreach my $line (@lines) {
if ($line !~ /^$regex/) {
@@ -218,7 +231,7 @@ sub parse_opts {
if (defined $2) {
my $desc = $2;
$desc =~ s/\:/\\:/g;
$entry .= "[$desc]";
$entry .= ':' . $desc;
}
push @list, $entry
@@ -226,14 +239,3 @@ sub parse_opts {
return @list;
}
sub call_mpv {
my ($cmd) = @_;
my $output = `"$mpv" --no-config $cmd`;
if ($? == -1) {
die "Could not run mpv: $!";
} elsif ((my $exit_code = $? >> 8) != 0) {
die "mpv returned $exit_code with output:\n$output";
}
return split /\n/, $output;
}
+1 -1
View File
@@ -1 +1 @@
0.11.0
0.8.3
+13 -20
View File
@@ -34,7 +34,7 @@ static void update_redundant_info(struct mp_audio *mpa)
assert(mp_chmap_is_empty(&mpa->channels) ||
mp_chmap_is_valid(&mpa->channels));
mpa->nch = mpa->channels.num;
mpa->bps = af_fmt_to_bytes(mpa->format);
mpa->bps = af_fmt2bps(mpa->format);
if (af_fmt_is_planar(mpa->format)) {
mpa->spf = 1;
mpa->num_planes = mpa->nch;
@@ -58,6 +58,13 @@ void mp_audio_set_num_channels(struct mp_audio *mpa, int num_channels)
update_redundant_info(mpa);
}
// Use old MPlayer/ALSA channel layout.
void mp_audio_set_channels_old(struct mp_audio *mpa, int num_channels)
{
mp_chmap_from_channels_alsa(&mpa->channels, num_channels);
update_redundant_info(mpa);
}
void mp_audio_set_channels(struct mp_audio *mpa, const struct mp_chmap *chmap)
{
mpa->channels = *chmap;
@@ -86,13 +93,9 @@ bool mp_audio_config_valid(const struct mp_audio *mpa)
char *mp_audio_config_to_str_buf(char *buf, size_t buf_sz, struct mp_audio *mpa)
{
char ch[128];
mp_chmap_to_str_buf(ch, sizeof(ch), &mpa->channels);
char *hr_ch = mp_chmap_to_str_hr(&mpa->channels);
if (strcmp(hr_ch, ch) != 0)
mp_snprintf_cat(ch, sizeof(ch), " (%s)", hr_ch);
snprintf(buf, buf_sz, "%dHz %s %dch %s", mpa->rate,
ch, mpa->channels.num, af_fmt_to_str(mpa->format));
mp_chmap_to_str(&mpa->channels), mpa->channels.num,
af_fmt_to_str(mpa->format));
return buf;
}
@@ -156,8 +159,8 @@ void mp_audio_realloc(struct mp_audio *mpa, int samples)
if (!mpa->allocated[n] || size != mpa->allocated[n]->size) {
if (av_buffer_realloc(&mpa->allocated[n], size) < 0)
abort(); // OOM
mpa->planes[n] = mpa->allocated[n]->data;
}
mpa->planes[n] = mpa->allocated[n]->data;
}
for (int n = mpa->num_planes; n < MP_NUM_CHANNELS; n++) {
av_buffer_unref(&mpa->allocated[n]);
@@ -188,18 +191,8 @@ int mp_audio_get_allocated_size(struct mp_audio *mpa)
{
int size = 0;
for (int n = 0; n < mpa->num_planes; n++) {
for (int i = 0; i < MP_NUM_CHANNELS && mpa->allocated[i]; i++) {
uint8_t *start = mpa->allocated[i]->data;
uint8_t *end = start + mpa->allocated[i]->size;
uint8_t *plane = mpa->planes[n];
if (plane >= start && plane < end) {
int s = MPMIN((end - plane) / mpa->sstride, INT_MAX);
size = n == 0 ? s : MPMIN(size, s);
goto next;
}
}
return 0; // plane is not covered by any buffer
next: ;
int s = mpa->allocated[n] ? mpa->allocated[n]->size / mpa->sstride : 0;
size = n == 0 ? s : MPMIN(size, s);
}
return size;
}
+3 -5
View File
@@ -35,17 +35,15 @@ struct mp_audio {
int nch; // number of channels (redundant with chmap)
int spf; // sub-samples per sample on each plane
int num_planes; // number of planes
int bps; // size of sub-samples (af_fmt_to_bytes(format))
int bps; // size of sub-samples (af_fmt2bps(format))
// --- private
// These do not necessarily map directly to planes[]. They can have
// different order or count. There shouldn't be more buffers than planes.
// If allocated[n] is NULL, allocated[n+1] must also be NULL.
// private
struct AVBufferRef *allocated[MP_NUM_CHANNELS];
};
void mp_audio_set_format(struct mp_audio *mpa, int format);
void mp_audio_set_num_channels(struct mp_audio *mpa, int num_channels);
void mp_audio_set_channels_old(struct mp_audio *mpa, int num_channels);
void mp_audio_set_channels(struct mp_audio *mpa, const struct mp_chmap *chmap);
void mp_audio_copy_config(struct mp_audio *dst, const struct mp_audio *src);
bool mp_audio_config_equals(const struct mp_audio *a, const struct mp_audio *b);
+59 -88
View File
@@ -18,8 +18,6 @@
#include <stdlib.h>
#include <assert.h>
#include <libavutil/common.h>
#include "common/common.h"
#include "common/msg.h"
#include "chmap.h"
@@ -52,7 +50,6 @@ static const char *const speaker_names[MP_SPEAKER_ID_COUNT][2] = {
[MP_SPEAKER_ID_SDL] = {"sdl", "surround direct left"},
[MP_SPEAKER_ID_SDR] = {"sdr", "surround direct right"},
[MP_SPEAKER_ID_LFE2] = {"lfe2", "low frequency 2"},
[MP_SPEAKER_ID_NA] = {"na", "not available"},
};
// Names taken from libavutil/channel_layout.c (Not accessible by API.)
@@ -60,9 +57,7 @@ static const char *const speaker_names[MP_SPEAKER_ID_COUNT][2] = {
static const char *const std_layout_names[][2] = {
{"empty", ""}, // not in lavc
{"mono", "fc"},
{"1.0", "fc"}, // not in lavc
{"stereo", "fl-fr"},
{"2.0", "fl-fr"}, // not in lavc
{"2.1", "fl-fr-lfe"},
{"3.0", "fl-fr-fc"},
{"3.0(back)", "fl-fr-bc"},
@@ -70,7 +65,6 @@ static const char *const std_layout_names[][2] = {
{"quad", "fl-fr-bl-br"},
{"quad(side)", "fl-fr-sl-sr"},
{"3.1", "fl-fr-fc-lfe"},
{"3.1(back)", "fl-fr-lfe-bc"}, // not in lavc
{"5.0", "fl-fr-fc-bl-br"},
{"5.0(alsa)", "fl-fr-bl-br-fc"}, // not in lavc
{"5.0(side)", "fl-fr-fc-sl-sr"},
@@ -84,11 +78,9 @@ static const char *const std_layout_names[][2] = {
{"hexagonal", "fl-fr-fc-bl-br-bc"},
{"6.1", "fl-fr-fc-lfe-bc-sl-sr"},
{"6.1(back)", "fl-fr-fc-lfe-bl-br-bc"}, // lavc calls this "6.1" too
{"6.1(top)", "fl-fr-fc-lfe-bl-br-tc"}, // not in lavc
{"6.1(front)", "fl-fr-lfe-flc-frc-sl-sr"},
{"7.0", "fl-fr-fc-bl-br-sl-sr"},
{"7.0(front)", "fl-fr-fc-flc-frc-sl-sr"},
{"7.0(rear)", "fl-fr-fc-bl-br-sdl-sdr"}, // not in lavc
{"7.1", "fl-fr-fc-lfe-bl-br-sl-sr"},
{"7.1(alsa)", "fl-fr-bl-br-fc-lfe-sl-sr"}, // not in lavc
{"7.1(wide)", "fl-fr-fc-lfe-bl-br-flc-frc"},
@@ -100,7 +92,7 @@ static const char *const std_layout_names[][2] = {
{0}
};
static const struct mp_chmap default_layouts[] = {
static const struct mp_chmap default_layouts[MP_NUM_CHANNELS + 1] = {
{0}, // empty
MP_CHMAP_INIT_MONO, // mono
MP_CHMAP2(FL, FR), // stereo
@@ -133,8 +125,7 @@ bool mp_chmap_is_valid(const struct mp_chmap *src)
int sp = src->speaker[n];
if (sp >= MP_SPEAKER_ID_COUNT || mapped[sp])
return false;
if (sp != MP_SPEAKER_ID_NA)
mapped[sp] = true;
mapped[sp] = true;
}
return src->num > 0;
}
@@ -149,10 +140,12 @@ bool mp_chmap_is_empty(const struct mp_chmap *src)
bool mp_chmap_is_unknown(const struct mp_chmap *src)
{
for (int n = 0; n < src->num; n++) {
if (src->speaker[n] != MP_SPEAKER_ID_NA)
return false;
int speaker = src->speaker[n];
if (speaker >= MP_SPEAKER_ID_UNKNOWN0 &&
speaker <= MP_SPEAKER_ID_UNKNOWN_LAST)
return true;
}
return mp_chmap_is_valid(src);
return false;
}
// Note: empty channel maps compare as equal. Invalid ones can equal too.
@@ -176,6 +169,15 @@ bool mp_chmap_equals_reordered(const struct mp_chmap *a, const struct mp_chmap *
return mp_chmap_equals(&t1, &t2);
}
bool mp_chmap_is_compatible(const struct mp_chmap *a, const struct mp_chmap *b)
{
if (mp_chmap_equals(a, b))
return true;
if (a->num == b->num && (mp_chmap_is_unknown(a) || mp_chmap_is_unknown(b)))
return true;
return false;
}
bool mp_chmap_is_stereo(const struct mp_chmap *src)
{
static const struct mp_chmap stereo = MP_CHMAP_INIT_STEREO;
@@ -195,36 +197,16 @@ void mp_chmap_reorder_norm(struct mp_chmap *map)
qsort(arr, map->num, 1, comp_uint8);
}
// Remove silent (NA) channels, if any.
void mp_chmap_remove_na(struct mp_chmap *map)
{
struct mp_chmap new = {0};
for (int n = 0; n < map->num; n++) {
int sp = map->speaker[n];
if (sp != MP_SPEAKER_ID_NA)
new.speaker[new.num++] = map->speaker[n];
}
*map = new;
}
// Add silent (NA) channels to map until map->num >= num.
void mp_chmap_fill_na(struct mp_chmap *map, int num)
{
assert(num <= MP_NUM_CHANNELS);
while (map->num < num)
map->speaker[map->num++] = MP_SPEAKER_ID_NA;
}
// Set *dst to a standard layout with the given number of channels.
// If the number of channels is invalid, an invalid map is set, and
// mp_chmap_is_valid(dst) will return false.
void mp_chmap_from_channels(struct mp_chmap *dst, int num_channels)
{
*dst = (struct mp_chmap) {0};
if (num_channels >= 0 && num_channels < MP_ARRAY_SIZE(default_layouts))
if (num_channels < 0 || num_channels > MP_NUM_CHANNELS) {
*dst = (struct mp_chmap) {0};
} else {
*dst = default_layouts[num_channels];
if (!dst->num)
mp_chmap_set_unknown(dst, num_channels);
}
}
// Try to do what mplayer/mplayer2/mpv did before channel layouts were
@@ -243,8 +225,6 @@ void mp_chmap_from_channels_alsa(struct mp_chmap *dst, int num_channels)
// Set *dst to an unknown layout for the given numbers of channels.
// If the number of channels is invalid, an invalid map is set, and
// mp_chmap_is_valid(dst) will return false.
// A mp_chmap with all entries set to NA is treated specially in some
// contexts (watch out for mp_chmap_is_unknown()).
void mp_chmap_set_unknown(struct mp_chmap *dst, int num_channels)
{
if (num_channels < 0 || num_channels > MP_NUM_CHANNELS) {
@@ -252,7 +232,7 @@ void mp_chmap_set_unknown(struct mp_chmap *dst, int num_channels)
} else {
dst->num = num_channels;
for (int n = 0; n < dst->num; n++)
dst->speaker[n] = MP_SPEAKER_ID_NA;
dst->speaker[n] = MP_SPEAKER_ID_UNKNOWN0 + n;
}
}
@@ -295,7 +275,6 @@ void mp_chmap_remove_useless_channels(struct mp_chmap *map,
}
// Return the ffmpeg/libav channel layout as in <libavutil/channel_layout.h>.
// Speakers not representable by ffmpeg/libav are dropped.
// Warning: this ignores the order of the channels, and will return a channel
// mask even if the order is different from libavcodec's.
uint64_t mp_chmap_to_lavc_unchecked(const struct mp_chmap *src)
@@ -305,10 +284,8 @@ uint64_t mp_chmap_to_lavc_unchecked(const struct mp_chmap *src)
if (mp_chmap_is_unknown(&t))
mp_chmap_from_channels(&t, t.num);
uint64_t mask = 0;
for (int n = 0; n < t.num; n++) {
if (t.speaker[n] < 64) // ignore MP_SPEAKER_ID_NA etc.
mask |= 1ULL << t.speaker[n];
}
for (int n = 0; n < t.num; n++)
mask |= 1ULL << t.speaker[n];
return mask;
}
@@ -369,43 +346,56 @@ void mp_chmap_reorder_to_lavc(struct mp_chmap *map)
// Get reordering array for from->to reordering. from->to must have the same set
// of speakers (i.e. same number and speaker IDs, just different order). Then,
// for each speaker n, src[n] will be set such that:
// to->speaker[n] = from->speaker[src[n]]
// (src[n] gives the source channel for destination channel n)
// If *from and *to don't contain the same set of speakers, then the above
// invariant is not guaranteed. Instead, src[n] can be set to -1 if the channel
// at to->speaker[n] is unmapped.
void mp_chmap_get_reorder(int src[MP_NUM_CHANNELS], const struct mp_chmap *from,
// for each speaker n, dst[n] will be set such that:
// to->speaker[dst[n]] = from->speaker[n]
// (dst[n] gives the source channel for destination channel n)
void mp_chmap_get_reorder(int dst[MP_NUM_CHANNELS], const struct mp_chmap *from,
const struct mp_chmap *to)
{
for (int n = 0; n < MP_NUM_CHANNELS; n++)
src[n] = -1;
assert(from->num == to->num);
if (mp_chmap_is_unknown(from) || mp_chmap_is_unknown(to)) {
for (int n = 0; n < to->num; n++)
src[n] = n < from->num ? n : -1;
for (int n = 0; n < from->num; n++)
dst[n] = n;
return;
}
for (int n = 0; n < to->num; n++) {
for (int i = 0; i < from->num; i++) {
if (to->speaker[n] == from->speaker[i]) {
src[n] = i;
// Same set of speakers required
assert(mp_chmap_equals_reordered(from, to));
for (int n = 0; n < from->num; n++) {
int src = from->speaker[n];
dst[n] = -1;
for (int i = 0; i < to->num; i++) {
if (src == to->speaker[i]) {
dst[n] = i;
break;
}
}
assert(dst[n] != -1);
}
for (int n = 0; n < to->num; n++)
assert(src[n] < 0 || (to->speaker[n] == from->speaker[src[n]]));
for (int n = 0; n < from->num; n++)
assert(to->speaker[dst[n]] == from->speaker[n]);
}
// Return the number of channels only in a.
int mp_chmap_diffn(const struct mp_chmap *a, const struct mp_chmap *b)
// Performs the difference between a and b, and store it in diff. If b has
// channels that do not appear in a, those will not appear in the difference.
// To get to those the argument ordering in the function call has to be
// inverted. For the same reason, the diff with a superset will return no
// speakers.
void mp_chmap_diff(const struct mp_chmap *a, const struct mp_chmap *b,
struct mp_chmap *diff)
{
uint64_t a_mask = mp_chmap_to_lavc_unchecked(a);
uint64_t b_mask = mp_chmap_to_lavc_unchecked(b);
return av_popcount64((a_mask ^ b_mask) & a_mask);
mp_chmap_from_lavc(diff, (a_mask ^ b_mask) & a_mask);
}
// Checks whether a contains all the speakers in b
bool mp_chmap_contains(const struct mp_chmap *a, const struct mp_chmap *b)
{
struct mp_chmap d1;
struct mp_chmap d2;
mp_chmap_diff(a, b, &d1);
mp_chmap_diff(b, a, &d2);
return a->num >= b->num && d1.num >= 0 && d2.num == 0;
}
// Returns something like "fl-fr-fc". If there's a standard layout in lavc
@@ -508,25 +498,6 @@ bool mp_chmap_from_str(struct mp_chmap *dst, bstr src)
return true;
}
// Output a human readable "canonical" channel map string. Converting this from
// a string back to a channel map can yield a different map, but the string
// looks nicer. E.g. "fc-fl-fr-na" becomes "3.0".
char *mp_chmap_to_str_hr_buf(char *buf, size_t buf_size, const struct mp_chmap *src)
{
struct mp_chmap map = *src;
mp_chmap_remove_na(&map);
for (int n = 0; std_layout_names[n][0]; n++) {
struct mp_chmap s;
if (mp_chmap_from_str(&s, bstr0(std_layout_names[n][0])) &&
mp_chmap_equals_reordered(&s, &map))
{
map = s;
break;
}
}
return mp_chmap_to_str_buf(buf, buf_size, &map);
}
void mp_chmap_print_help(struct mp_log *log)
{
mp_info(log, "Speakers:\n");
+11 -14
View File
@@ -47,7 +47,7 @@ enum mp_speaker_id {
MP_SPEAKER_ID_TBL, // TOP_BACK_LEFT
MP_SPEAKER_ID_TBC, // TOP_BACK_CENTER
MP_SPEAKER_ID_TBR, // TOP_BACK_RIGHT
// Unofficial/libav* extensions
// Inofficial/libav* extensions
MP_SPEAKER_ID_DL = 29, // STEREO_LEFT (stereo downmix special speakers)
MP_SPEAKER_ID_DR, // STEREO_RIGHT
MP_SPEAKER_ID_WL, // WIDE_LEFT
@@ -56,12 +56,10 @@ enum mp_speaker_id {
MP_SPEAKER_ID_SDR, // SURROUND_DIRECT_RIGHT
MP_SPEAKER_ID_LFE2, // LOW_FREQUENCY_2
// Speaker IDs >= 64 are not representable in WAVEFORMATEXTENSIBLE or libav*.
// "Silent" channels. These are sometimes used to insert padding for
// unused channels. Unlike other speaker types, multiple of these can
// occur in a single mp_chmap.
MP_SPEAKER_ID_NA = 64,
// Special mpv-specific speaker entries reserved for channels which have no
// known meaning.
MP_SPEAKER_ID_UNKNOWN0 = 64,
MP_SPEAKER_ID_UNKNOWN_LAST = MP_SPEAKER_ID_UNKNOWN0 + MP_NUM_CHANNELS - 1,
// Including the unassigned IDs in between. This is not a valid ID anymore,
// but is still within uint8_t.
@@ -100,11 +98,10 @@ bool mp_chmap_is_empty(const struct mp_chmap *src);
bool mp_chmap_is_unknown(const struct mp_chmap *src);
bool mp_chmap_equals(const struct mp_chmap *a, const struct mp_chmap *b);
bool mp_chmap_equals_reordered(const struct mp_chmap *a, const struct mp_chmap *b);
bool mp_chmap_is_compatible(const struct mp_chmap *a, const struct mp_chmap *b);
bool mp_chmap_is_stereo(const struct mp_chmap *src);
void mp_chmap_reorder_norm(struct mp_chmap *map);
void mp_chmap_remove_na(struct mp_chmap *map);
void mp_chmap_fill_na(struct mp_chmap *map, int num);
void mp_chmap_from_channels(struct mp_chmap *dst, int num_channels);
void mp_chmap_set_unknown(struct mp_chmap *dst, int num_channels);
@@ -120,17 +117,17 @@ void mp_chmap_from_lavc(struct mp_chmap *dst, uint64_t src);
bool mp_chmap_is_lavc(const struct mp_chmap *src);
void mp_chmap_reorder_to_lavc(struct mp_chmap *map);
void mp_chmap_get_reorder(int src[MP_NUM_CHANNELS], const struct mp_chmap *from,
void mp_chmap_get_reorder(int dst[MP_NUM_CHANNELS], const struct mp_chmap *from,
const struct mp_chmap *to);
int mp_chmap_diffn(const struct mp_chmap *a, const struct mp_chmap *b);
void mp_chmap_diff(const struct mp_chmap *a, const struct mp_chmap *b,
struct mp_chmap *diff);
bool mp_chmap_contains(const struct mp_chmap *a, const struct mp_chmap *b);
char *mp_chmap_to_str_buf(char *buf, size_t buf_size, const struct mp_chmap *src);
#define mp_chmap_to_str(m) mp_chmap_to_str_buf((char[64]){0}, 64, (m))
char *mp_chmap_to_str_hr_buf(char *buf, size_t buf_size, const struct mp_chmap *src);
#define mp_chmap_to_str_hr(m) mp_chmap_to_str_hr_buf((char[128]){0}, 128, (m))
bool mp_chmap_from_str(struct mp_chmap *dst, bstr src);
struct mp_log;
+70 -113
View File
@@ -58,29 +58,6 @@ static bool replace_speakers(struct mp_chmap *map, struct mp_chmap list[2])
return false;
}
// These go strictly from the first to the second entry and always use the
// full layout (possibly reordered and/or padding channels added).
static const struct mp_chmap preferred_remix[][2] = {
// mono can be perfectly played as stereo
{ MP_CHMAP_INIT_MONO, MP_CHMAP_INIT_STEREO },
};
// Conversion from src to dst is explicitly encouraged and should be preferred
// over "mathematical" upmixes or downmixes (which minimize lost channels).
static bool test_preferred_remix(const struct mp_chmap *src,
const struct mp_chmap *dst)
{
struct mp_chmap src_p = *src, dst_p = *dst;
mp_chmap_remove_na(&src_p);
mp_chmap_remove_na(&dst_p);
for (int n = 0; n < MP_ARRAY_SIZE(preferred_remix); n++) {
if (mp_chmap_equals_reordered(&src_p, &preferred_remix[n][0]) &&
mp_chmap_equals_reordered(&dst_p, &preferred_remix[n][1]))
return true;
}
return false;
}
// Allow all channel layouts that can be expressed with mp_chmap.
// (By default, all layouts are rejected.)
void mp_chmap_sel_add_any(struct mp_chmap_sel *s)
@@ -199,10 +176,6 @@ bool mp_chmap_sel_adjust(const struct mp_chmap_sel *s, struct mp_chmap *map)
return true;
}
}
if (mp_chmap_sel_fallback(s, map))
return true;
for (int i = 0; i < MP_ARRAY_SIZE(speaker_replacements); i++) {
struct mp_chmap t = *map;
struct mp_chmap *r = (struct mp_chmap *)speaker_replacements[i];
@@ -212,6 +185,9 @@ bool mp_chmap_sel_adjust(const struct mp_chmap_sel *s, struct mp_chmap *map)
}
}
if (mp_chmap_sel_fallback(s, map))
return true;
// Fallback to mono/stereo as last resort
*map = (struct mp_chmap) MP_CHMAP_INIT_STEREO;
if (test_layout(s, map))
@@ -223,95 +199,64 @@ bool mp_chmap_sel_adjust(const struct mp_chmap_sel *s, struct mp_chmap *map)
return false;
}
// Like mp_chmap_diffn(), but find the minimum difference with all possible
// speaker replacements considered.
static int mp_chmap_diffn_r(const struct mp_chmap *a, const struct mp_chmap *b)
{
int mindiff = INT_MAX;
#define UPMIX_IDX 0
#define DOWNMIX_IDX 1
#define FALLBACK_IDX 2
for (int i = -1; i < (int)MP_ARRAY_SIZE(speaker_replacements); i++) {
struct mp_chmap ar = *a;
if (i >= 0) {
struct mp_chmap *r = (struct mp_chmap *)speaker_replacements[i];
if (!replace_speakers(&ar, r))
continue;
}
int d = mp_chmap_diffn(&ar, b);
if (d < mindiff)
mindiff = d;
static bool test_fallbacks(struct mp_chmap *a, struct mp_chmap *b,
int best_diffs[2], struct mp_chmap best[2])
{
struct mp_chmap diff1, diff2;
mp_chmap_diff(a, b, &diff1);
if (mp_chmap_contains(a, b) && best_diffs[UPMIX_IDX] > diff1.num) {
best[UPMIX_IDX] = *a;
best_diffs[UPMIX_IDX] = diff1.num;
return true;
}
// Special-case: we consider stereo a replacement for mono. (This is not
// true in the other direction. Also, fl-fr is generally not a replacement
// for fc. Thus it's not part of the speaker replacement list.)
struct mp_chmap mono = MP_CHMAP_INIT_MONO;
struct mp_chmap stereo = MP_CHMAP_INIT_STEREO;
if (mp_chmap_equals(&mono, b) && mp_chmap_equals(&stereo, a))
mindiff = 0;
mp_chmap_diff(b, a, &diff2);
if (mp_chmap_contains(b, a) && best_diffs[DOWNMIX_IDX] > diff2.num) {
best[DOWNMIX_IDX] = *a;
best_diffs[DOWNMIX_IDX] = diff2.num;
return true;
}
return mindiff;
if (diff1.num > 0 && best_diffs[FALLBACK_IDX] > diff1.num) {
best[FALLBACK_IDX] = *a;
best_diffs[FALLBACK_IDX] = diff1.num;
return true;
}
if (diff2.num > 0 && best_diffs[FALLBACK_IDX] > diff2.num) {
best[FALLBACK_IDX] = *a;
best_diffs[FALLBACK_IDX] = diff2.num;
return true;
}
return false;
}
// Decide whether we should prefer old or new for the requested layout.
// Return true if new should be used, false if old should be used.
// If old is empty, always return new (initial case).
static bool mp_chmap_is_better(struct mp_chmap *req, struct mp_chmap *old,
struct mp_chmap *new)
{
// Initial case
if (!old->num)
return true;
// Exact pick - this also ensures that the best layout is chosen if the
// layouts are the same, but with different order of channels.
if (mp_chmap_equals(req, old))
return false;
if (mp_chmap_equals(req, new))
return true;
// If there's no exact match, strictly do a preferred conversion.
bool old_pref = test_preferred_remix(req, old);
bool new_pref = test_preferred_remix(req, new);
if (old_pref && !new_pref)
return false;
if (!old_pref && new_pref)
return true;
int old_lost_r = mp_chmap_diffn_r(req, old); // num. channels only in req
int new_lost_r = mp_chmap_diffn_r(req, new);
// Imperfect upmix (no real superset) - minimize lost channels
if (new_lost_r != old_lost_r)
return new_lost_r < old_lost_r;
int old_lost = mp_chmap_diffn(req, old);
int new_lost = mp_chmap_diffn(req, new);
// If the situation is equal with replaced speakers, but one of them loses
// less if no replacements are performed, pick the better one, even if it
// means an upmix. This prefers exact supersets over inexact equivalents.
if (new_lost != old_lost)
return new_lost < old_lost;
struct mp_chmap old_p = *old, new_p = *new;
mp_chmap_remove_na(&old_p);
mp_chmap_remove_na(&new_p);
// Some kind of upmix. If it's perfect, prefer the smaller one. Even if not,
// both have equal loss, so also prefer the smaller one.
// Drop padding channels (NA) for the sake of this check, as the number of
// padding channels isn't really meaningful.
if (new_p.num != old_p.num)
return new_p.num < old_p.num;
// Again, with physical channels (minimizes number of NA channels).
return new->num < old->num;
}
// Determine which channel map to fallback to given a source channel map.
// Determine which channel map to fallback to given a source channel map. It
// uses the following heuristic:
// 1) If mono is required always prefer stereo to a multichannel upmix.
// 2) Search for an upmix that is an exact superset of the required chmap.
// 3) Search for a downmix that is the exact subset of the required chmap.
// 4) Search for either an upmix or downmix that is the closest (minimum
// difference of speakers) to the required chmap.
bool mp_chmap_sel_fallback(const struct mp_chmap_sel *s, struct mp_chmap *map)
{
struct mp_chmap best = {0};
// special case: if possible always fallback mono to stereo (instead of
// looking for a multichannel upmix)
struct mp_chmap mono = MP_CHMAP_INIT_MONO;
struct mp_chmap stereo = MP_CHMAP_INIT_STEREO;
if (mp_chmap_equals(&mono, map) && test_layout(s, &stereo)) {
*map = stereo;
return true;
}
int best_diffs[] = { INT_MAX, INT_MAX, INT_MAX };
struct mp_chmap best[] = { {0}, {0}, {0} };
for (int n = 0; n < s->num_chmaps; n++) {
struct mp_chmap e = s->chmaps[n];
@@ -319,13 +264,25 @@ bool mp_chmap_sel_fallback(const struct mp_chmap_sel *s, struct mp_chmap *map)
if (mp_chmap_is_unknown(&e))
continue;
if (mp_chmap_is_better(map, &best, &e))
best = e;
if (test_fallbacks(&e, map, best_diffs, best))
continue;
// in case we didn't match any fallback retry after replacing speakers
for (int i = 0; i < MP_ARRAY_SIZE(speaker_replacements); i++) {
struct mp_chmap t = e;
struct mp_chmap *r = (struct mp_chmap *)speaker_replacements[i];
if (replace_speakers(&t, r)) {
if (test_fallbacks(&t, map, best_diffs, best))
continue;
}
}
}
if (best.num) {
*map = best;
return true;
for (int i = UPMIX_IDX; i < MP_ARRAY_SIZE(best); i++) {
if (best_diffs[i] < INT_MAX) {
*map = best[i];
return true;
}
}
return false;
+5 -4
View File
@@ -1,18 +1,19 @@
/*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPLAYER_AD_H
+16 -8
View File
@@ -1,18 +1,19 @@
/*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
@@ -58,7 +59,7 @@ struct ad_lavc_params {
const struct m_sub_options ad_lavc_conf = {
.opts = (const m_option_t[]) {
OPT_FLOATRANGE("ac3drc", ac3drc, 0, 0, 6),
OPT_FLOATRANGE("ac3drc", ac3drc, 0, 0, 2),
OPT_FLAG("downmix", downmix, 0),
OPT_INTRANGE("threads", threads, 0, 1, 16),
OPT_KEYVALUELIST("o", avopts, 0),
@@ -66,7 +67,7 @@ const struct m_sub_options ad_lavc_conf = {
},
.size = sizeof(struct ad_lavc_params),
.defaults = &(const struct ad_lavc_params){
.ac3drc = 0,
.ac3drc = 1.,
.downmix = 1,
.threads = 1,
},
@@ -116,7 +117,7 @@ static int init(struct dec_audio *da, const char *decoder)
mp_set_avopts(da->log, lavc_context, opts->avopts);
lavc_context->codec_tag = sh->codec_tag;
lavc_context->codec_tag = sh->format;
lavc_context->sample_rate = sh_audio->samplerate;
lavc_context->bit_rate = sh_audio->bitrate;
lavc_context->block_align = sh_audio->block_align;
@@ -126,7 +127,11 @@ static int init(struct dec_audio *da, const char *decoder)
lavc_context->channel_layout = mp_chmap_to_lavc(&sh_audio->channels);
// demux_mkv
mp_lavc_set_extradata(lavc_context, sh->extradata, sh->extradata_size);
if (sh_audio->codecdata_len && sh_audio->codecdata &&
!lavc_context->extradata) {
mp_lavc_set_extradata(lavc_context, sh_audio->codecdata,
sh_audio->codecdata_len);
}
if (sh->lav_headers)
mp_copy_lav_codec_headers(lavc_context, sh->lav_headers);
@@ -140,6 +145,9 @@ static int init(struct dec_audio *da, const char *decoder)
return 0;
}
if (lavc_context->bit_rate != 0)
da->bitrate = lavc_context->bit_rate;
return 1;
}
+304
View File
@@ -0,0 +1,304 @@
/*
* MPEG 1.0/2.0/2.5 audio layer I, II, III decoding with libmpg123
*
* Copyright (C) 2010-2013 Thomas Orgis <thomas@orgis.org>
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "config.h"
#include "ad.h"
#include "common/msg.h"
#include <mpg123.h>
#if (defined MPG123_API_VERSION) && (MPG123_API_VERSION < 33)
#error "This should not happen"
#endif
struct ad_mpg123_context {
mpg123_handle *handle;
int sample_size;
/* Running mean for bit rate, stream length estimation. */
float mean_rate;
unsigned int mean_count;
/* Time delay for updates. */
short delay;
/* If the stream is actually VBR. */
char vbr;
struct mp_audio frame;
};
static void uninit(struct dec_audio *da)
{
struct ad_mpg123_context *con = da->priv;
mpg123_close(con->handle);
mpg123_delete(con->handle);
mpg123_exit();
}
/* This initializes libmpg123 and prepares the handle, including funky
* parameters. */
static int init(struct dec_audio *da, const char *decoder)
{
int err;
struct ad_mpg123_context *con;
/* Assumption: You always call preinit + init + uninit, on every file.
* But you stop at preinit in case it fails.
* If that is not true, one must ensure not to call mpg123_init / exit
* twice in a row. */
if (mpg123_init() != MPG123_OK)
return 0;
da->priv = talloc_zero(NULL, struct ad_mpg123_context);
con = da->priv;
/* Auto-choice of optimized decoder (first argument NULL). */
con->handle = mpg123_new(NULL, &err);
if (!con->handle)
goto bad_end;
/* Basic settings.
* Don't spill messages, enable better resync with non-seekable streams.
* Give both flags individually without error checking to keep going with
* old libmpg123. Generally, it is not fatal if the flags are not
* honored */
mpg123_param(con->handle, MPG123_ADD_FLAGS, MPG123_QUIET, 0.0);
/* Do not bail out on malformed streams at all.
* MPlayer does not handle a decoder throwing the towel on crappy input. */
mpg123_param(con->handle, MPG123_RESYNC_LIMIT, -1, 0.0);
/* Open decisions: Configure libmpg123 to force encoding (or stay open about
* library builds that support only float or int32 output), (de)configure
* gapless decoding (won't work with seeking in MPlayer, though).
* Don't forget to eventually enable ReplayGain/RVA support, too.
* Let's try to run with the default for now. */
/* That would produce floating point output.
* You can get 32 and 24 bit ints, even 8 bit via format matrix.
* If wanting a specific encoding here, configure format matrix and
* make sure it is in set_format(). */
/* mpg123_param(con->handle, MPG123_ADD_FLAGS, MPG123_FORCE_FLOAT, 0.); */
/* Example for RVA choice (available since libmpg123 1.0.0):
mpg123_param(con->handle, MPG123_RVA, MPG123_RVA_MIX, 0.0) */
/* Prevent funky automatic resampling.
* This way, we can be sure that one frame will never produce
* more than 1152 stereo samples.
* Background:
* Going to decode directly to the output buffer. It is important to have
* MPG123_AUTO_RESAMPLE disabled for the buffer size being an all-time
* limit.
* We need at least 1152 samples. dec_audio.c normally guarantees this. */
mpg123_param(con->handle, MPG123_REMOVE_FLAGS, MPG123_AUTO_RESAMPLE, 0.);
err = mpg123_open_feed(con->handle);
if (err != MPG123_OK)
goto bad_end;
return 1;
bad_end:
if (!con->handle) {
MP_ERR(da, "mpg123 preinit error: %s\n", mpg123_plain_strerror(err));
} else {
MP_ERR(da, "mpg123 preinit error: %s\n", mpg123_strerror(con->handle));
}
uninit(da);
return 0;
}
static int mpg123_format_to_af(int mpg123_encoding)
{
/* Without external force, mpg123 will always choose signed encoding,
* and non-16-bit only on builds that don't support it.
* Be reminded that it doesn't matter to the MPEG file what encoding
* is produced from it. */
switch (mpg123_encoding) {
case MPG123_ENC_SIGNED_8: return AF_FORMAT_S8;
case MPG123_ENC_SIGNED_16: return AF_FORMAT_S16;
case MPG123_ENC_SIGNED_32: return AF_FORMAT_S32;
case MPG123_ENC_FLOAT_32: return AF_FORMAT_FLOAT;
}
return 0;
}
/* Compute bitrate from frame size. */
static int compute_bitrate(struct mpg123_frameinfo *i)
{
static const int samples_per_frame[4][4] = {
{-1, 384, 1152, 1152}, /* MPEG 1 */
{-1, 384, 1152, 576}, /* MPEG 2 */
{-1, 384, 1152, 576}, /* MPEG 2.5 */
{-1, -1, -1, -1}, /* Unknown */
};
return (int) ((i->framesize + 4) * 8 * i->rate /
samples_per_frame[i->version][i->layer] + 0.5);
}
/* Update mean bitrate. This could be dropped if accurate time display
* on audio file playback is not desired. */
static void update_info(struct dec_audio *da)
{
struct ad_mpg123_context *con = da->priv;
struct mpg123_frameinfo finfo;
if (mpg123_info(con->handle, &finfo) != MPG123_OK)
return;
/* finfo.bitrate is expressed in kilobits */
const int bitrate = finfo.bitrate * 1000;
if (finfo.vbr != MPG123_CBR) {
if (--con->delay < 1) {
if (++con->mean_count > ((unsigned int) -1) / 2)
con->mean_count = ((unsigned int) -1) / 4;
/* Might not be numerically optimal, but works fine enough. */
con->mean_rate = ((con->mean_count - 1) * con->mean_rate +
bitrate) / con->mean_count;
da->bitrate = (int) (con->mean_rate + 0.5);
con->delay = 10;
}
} else {
da->bitrate = bitrate ? bitrate : compute_bitrate(&finfo);
con->delay = 1;
con->mean_rate = 0.;
con->mean_count = 0;
}
}
/* libmpg123 has a new format ready; query and store, return return value
of mpg123_getformat() */
static int set_format(struct dec_audio *da)
{
struct ad_mpg123_context *con = da->priv;
int ret;
long rate;
int channels;
int encoding;
ret = mpg123_getformat(con->handle, &rate, &channels, &encoding);
if (ret == MPG123_OK) {
mp_audio_set_num_channels(&con->frame, channels);
con->frame.rate = rate;
int af = mpg123_format_to_af(encoding);
if (!af) {
/* This means we got a funny custom build of libmpg123 that only supports an unknown format. */
MP_ERR(da, "Bad encoding from mpg123: %i.\n", encoding);
return MPG123_ERR;
}
mp_audio_set_format(&con->frame, af);
con->sample_size = channels * af_fmt2bps(af);
}
return ret;
}
static int decode_packet(struct dec_audio *da, struct mp_audio **out)
{
struct ad_mpg123_context *con = da->priv;
int ret;
struct demux_packet *pkt;
if (demux_read_packet_async(da->header, &pkt) == 0)
return AD_WAIT;
if (!pkt)
return AD_EOF;
/* Next bytes from that presentation time. */
if (pkt->pts != MP_NOPTS_VALUE) {
da->pts = pkt->pts;
da->pts_offset = 0;
}
/* Have to use mpg123_feed() to avoid decoding here. */
ret = mpg123_feed(con->handle, pkt->buffer, pkt->len);
talloc_free(pkt);
if (ret != MPG123_OK)
goto mpg123_fail;
unsigned char *audio = NULL;
size_t bytes = 0;
ret = mpg123_decode_frame(con->handle, NULL, &audio, &bytes);
if (ret == MPG123_NEED_MORE)
return 0;
if (ret != MPG123_OK && ret != MPG123_DONE && ret != MPG123_NEW_FORMAT)
goto mpg123_fail;
ret = set_format(da);
if (ret != MPG123_OK)
goto mpg123_fail;
if (con->sample_size < 1) {
MP_ERR(da, "no sample size\n");
return AD_ERR;
}
int got_samples = bytes / con->sample_size;
*out = mp_audio_pool_get(da->pool, &con->frame, got_samples);
if (!*out)
return AD_ERR;
memcpy((*out)->planes[0], audio, bytes);
update_info(da);
return 0;
mpg123_fail:
MP_ERR(da, "mpg123 decoding error: %s\n", mpg123_strerror(con->handle));
return AD_ERR;
}
static int control(struct dec_audio *da, int cmd, void *arg)
{
struct ad_mpg123_context *con = da->priv;
switch (cmd) {
case ADCTRL_RESET:
mpg123_close(con->handle);
if (mpg123_open_feed(con->handle) != MPG123_OK) {
MP_ERR(da, "mpg123 failed to reopen stream: %s\n",
mpg123_strerror(con->handle));
return CONTROL_FALSE;
}
return CONTROL_TRUE;
}
return CONTROL_UNKNOWN;
}
static void add_decoders(struct mp_decoder_list *list)
{
mp_add_decoder(list, "mpg123", "mp3", "mp3",
"High-performance decoder using libmpg123");
}
const struct ad_functions ad_mpg123 = {
.name = "mpg123",
.add_decoders = add_decoders,
.init = init,
.uninit = uninit,
.control = control,
.decode_packet = decode_packet,
};
+31 -93
View File
@@ -1,20 +1,21 @@
/*
* This file is part of MPlayer.
*
* Copyright (C) 2012 Naoya OYAMA
*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
@@ -34,12 +35,11 @@
struct spdifContext {
struct mp_log *log;
enum AVCodecID codec_id;
AVFormatContext *lavf_ctx;
int iec61937_packet_size;
int out_buffer_len;
uint8_t out_buffer[OUTBUF_SIZE];
bool need_close;
bool use_dts_hd;
struct mp_audio fmt;
};
@@ -78,78 +78,17 @@ static int init(struct dec_audio *da, const char *decoder)
struct spdifContext *spdif_ctx = talloc_zero(NULL, struct spdifContext);
da->priv = spdif_ctx;
spdif_ctx->log = da->log;
spdif_ctx->use_dts_hd = da->opts->dtshd;
if (strcmp(decoder, "dts-hd") == 0) {
decoder = "dts";
spdif_ctx->use_dts_hd = true;
}
spdif_ctx->codec_id = mp_codec_to_av_codec_id(decoder);
return spdif_ctx->codec_id != AV_CODEC_ID_NONE;
}
static int determine_codec_profile(struct dec_audio *da, AVPacket *pkt)
{
struct spdifContext *spdif_ctx = da->priv;
int profile = FF_PROFILE_UNKNOWN;
AVCodecContext *ctx = NULL;
AVFrame *frame = NULL;
AVCodec *codec = avcodec_find_decoder(spdif_ctx->codec_id);
if (!codec)
goto done;
frame = av_frame_alloc();
if (!frame)
goto done;
ctx = avcodec_alloc_context3(codec);
if (!ctx)
goto done;
if (avcodec_open2(ctx, codec, NULL) < 0) {
av_free(ctx); // don't attempt to avcodec_close() an unopened ctx
ctx = NULL;
goto done;
}
int got_frame = 0;
if (avcodec_decode_audio4(ctx, frame, &got_frame, pkt) < 1 || !got_frame)
goto done;
profile = ctx->profile;
done:
av_frame_free(&frame);
if (ctx)
avcodec_close(ctx);
avcodec_free_context(&ctx);
if (profile == FF_PROFILE_UNKNOWN)
MP_WARN(da, "Failed to parse codec profile.\n");
return profile;
}
static int init_filter(struct dec_audio *da, AVPacket *pkt)
{
struct spdifContext *spdif_ctx = da->priv;
int profile = FF_PROFILE_UNKNOWN;
if (spdif_ctx->codec_id == AV_CODEC_ID_DTS)
profile = determine_codec_profile(da, pkt);
AVFormatContext *lavf_ctx = avformat_alloc_context();
if (!lavf_ctx)
goto fail;
spdif_ctx->lavf_ctx = lavf_ctx;
lavf_ctx->oformat = av_guess_format("spdif", NULL, NULL);
if (!lavf_ctx->oformat)
goto fail;
spdif_ctx->lavf_ctx = lavf_ctx;
void *buffer = av_mallocz(OUTBUF_SIZE);
if (!buffer)
abort();
@@ -169,50 +108,54 @@ static int init_filter(struct dec_audio *da, AVPacket *pkt)
if (!stream)
goto fail;
stream->codec->codec_id = spdif_ctx->codec_id;
stream->codec->codec_id = mp_codec_to_av_codec_id(decoder);
AVDictionary *format_opts = NULL;
int num_channels = 0;
int sample_format = 0;
int samplerate = 0;
switch (spdif_ctx->codec_id) {
switch (stream->codec->codec_id) {
case AV_CODEC_ID_AAC:
spdif_ctx->iec61937_packet_size = 16384;
sample_format = AF_FORMAT_S_AAC;
samplerate = 48000;
num_channels = 2;
break;
case AV_CODEC_ID_AC3:
spdif_ctx->iec61937_packet_size = 6144;
sample_format = AF_FORMAT_S_AC3;
samplerate = 48000;
num_channels = 2;
break;
case AV_CODEC_ID_DTS: {
bool is_hd = profile == FF_PROFILE_DTS_HD_HRA ||
profile == FF_PROFILE_DTS_HD_MA;
if (spdif_ctx->use_dts_hd && is_hd) {
case AV_CODEC_ID_DTS:
if (da->opts->dtshd) {
av_dict_set(&format_opts, "dtshd_rate", "768000", 0); // 4*192000
sample_format = AF_FORMAT_S_DTSHD;
samplerate = 192000;
num_channels = 2*4;
spdif_ctx->iec61937_packet_size = 32768;
sample_format = AF_FORMAT_S_DTSHD;
samplerate = 192000;
num_channels = 2*4;
} else {
sample_format = AF_FORMAT_S_DTS;
samplerate = 48000;
num_channels = 2;
spdif_ctx->iec61937_packet_size = 32768;
sample_format = AF_FORMAT_S_DTS;
samplerate = 48000;
num_channels = 2;
}
break;
}
case AV_CODEC_ID_EAC3:
spdif_ctx->iec61937_packet_size = 24576;
sample_format = AF_FORMAT_S_EAC3;
samplerate = 192000;
num_channels = 2;
break;
case AV_CODEC_ID_MP3:
spdif_ctx->iec61937_packet_size = 4608;
sample_format = AF_FORMAT_S_MP3;
samplerate = 48000;
num_channels = 2;
break;
case AV_CODEC_ID_TRUEHD:
spdif_ctx->iec61937_packet_size = 61440;
sample_format = AF_FORMAT_S_TRUEHD;
samplerate = 192000;
num_channels = 8;
@@ -233,16 +176,17 @@ static int init_filter(struct dec_audio *da, AVPacket *pkt)
spdif_ctx->need_close = true;
return 0;
return 1;
fail:
uninit(da);
return -1;
return 0;
}
static int decode_packet(struct dec_audio *da, struct mp_audio **out)
{
struct spdifContext *spdif_ctx = da->priv;
AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx;
spdif_ctx->out_buffer_len = 0;
@@ -260,13 +204,9 @@ static int decode_packet(struct dec_audio *da, struct mp_audio **out)
da->pts = mpkt->pts;
da->pts_offset = 0;
}
if (!spdif_ctx->lavf_ctx) {
if (init_filter(da, &pkt) < 0)
return AD_ERR;
}
int ret = av_write_frame(spdif_ctx->lavf_ctx, &pkt);
int ret = av_write_frame(lavf_ctx, &pkt);
talloc_free(mpkt);
avio_flush(spdif_ctx->lavf_ctx->pb);
avio_flush(lavf_ctx->pb);
if (ret < 0)
return AD_ERR;
@@ -304,8 +244,6 @@ static void add_decoders(struct mp_decoder_list *list)
"libavformat/spdifenc audio pass-through decoder");
}
}
mp_add_decoder(list, "spdif", "dts", "dts-hd",
"libavformat/spdifenc audio pass-through decoder");
}
const struct ad_functions ad_spdif = {
+18 -27
View File
@@ -1,18 +1,19 @@
/*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
@@ -24,6 +25,7 @@
#include "demux/codec_tags.h"
#include "config.h"
#include "common/codecs.h"
#include "common/msg.h"
#include "misc/bstr.h"
@@ -41,18 +43,21 @@
#include "audio/filter/af.h"
extern const struct ad_functions ad_mpg123;
extern const struct ad_functions ad_lavc;
extern const struct ad_functions ad_spdif;
static const struct ad_functions * const ad_drivers[] = {
&ad_lavc,
#if HAVE_MPG123
&ad_mpg123,
#endif
&ad_spdif,
NULL
};
static void uninit_decoder(struct dec_audio *d_audio)
{
audio_reset_decoding(d_audio);
if (d_audio->ad_driver) {
MP_VERBOSE(d_audio, "Uninit audio decoder.\n");
d_audio->ad_driver->uninit(d_audio);
@@ -60,8 +65,6 @@ static void uninit_decoder(struct dec_audio *d_audio)
d_audio->ad_driver = NULL;
talloc_free(d_audio->priv);
d_audio->priv = NULL;
d_audio->afilter->initialized = -1;
d_audio->decode_format = (struct mp_audio){0};
}
static int init_audio_codec(struct dec_audio *d_audio, const char *decoder)
@@ -84,21 +87,11 @@ struct mp_decoder_list *audio_decoder_list(void)
return list;
}
static struct mp_decoder_list *audio_select_decoders(struct dec_audio *d_audio)
static struct mp_decoder_list *audio_select_decoders(const char *codec,
char *selection)
{
struct MPOpts *opts = d_audio->opts;
const char *codec = d_audio->header->codec;
struct mp_decoder_list *list = audio_decoder_list();
struct mp_decoder_list *new =
mp_select_decoders(list, codec, opts->audio_decoders);
if (d_audio->spdif_passthrough) {
struct mp_decoder_list *spdif =
mp_select_decoder_list(list, codec, "spdif", opts->audio_spdif);
mp_append_decoders(spdif, new);
talloc_free(new);
new = spdif;
}
struct mp_decoder_list *new = mp_select_decoders(list, codec, selection);
talloc_free(list);
return new;
}
@@ -112,13 +105,14 @@ static const struct ad_functions *find_driver(const char *name)
return NULL;
}
int audio_init_best_codec(struct dec_audio *d_audio)
int audio_init_best_codec(struct dec_audio *d_audio, char *audio_decoders)
{
uninit_decoder(d_audio);
assert(!d_audio->ad_driver);
audio_reset_decoding(d_audio);
struct mp_decoder_entry *decoder = NULL;
struct mp_decoder_list *list = audio_select_decoders(d_audio);
struct mp_decoder_list *list =
audio_select_decoders(d_audio->header->codec, audio_decoders);
mp_print_decoders(d_audio->log, MSGL_V, "Codec list:", list);
@@ -157,8 +151,8 @@ void audio_uninit(struct dec_audio *d_audio)
if (!d_audio)
return;
MP_VERBOSE(d_audio, "Uninit audio filters...\n");
uninit_decoder(d_audio);
af_destroy(d_audio->afilter);
uninit_decoder(d_audio);
talloc_free(d_audio->waiting);
talloc_free(d_audio);
}
@@ -170,9 +164,6 @@ static int decode_new_frame(struct dec_audio *da)
if (ret < 0)
return ret;
if (da->pts == MP_NOPTS_VALUE && da->header->missing_timestamps)
da->pts = 0;
if (da->waiting) {
da->pts_offset += da->waiting->samples;
da->decode_format = *da->waiting;
+6 -6
View File
@@ -1,18 +1,19 @@
/*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPLAYER_DEC_AUDIO_H
@@ -30,7 +31,6 @@ struct dec_audio {
struct mp_log *log;
struct MPOpts *opts;
struct mpv_global *global;
bool spdif_passthrough;
const struct ad_functions *ad_driver;
struct sh_stream *header;
struct af_stream *afilter;
@@ -58,7 +58,7 @@ enum {
};
struct mp_decoder_list *audio_decoder_list(void);
int audio_init_best_codec(struct dec_audio *d_audio);
int audio_init_best_codec(struct dec_audio *d_audio, char *audio_decoders);
int audio_decode(struct dec_audio *d_audio, struct mp_audio_buffer *outbuf,
int minsamples);
int initial_audio_decode(struct dec_audio *d_audio);
+147 -80
View File
@@ -1,18 +1,19 @@
/*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
@@ -31,37 +32,68 @@
#include "af.h"
// Static list of filters
extern const struct af_info af_info_dummy;
extern const struct af_info af_info_delay;
extern const struct af_info af_info_channels;
extern const struct af_info af_info_format;
extern const struct af_info af_info_force;
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_surround;
extern const struct af_info af_info_sub;
extern const struct af_info af_info_export;
extern const struct af_info af_info_drc;
extern const struct af_info af_info_extrastereo;
extern const struct af_info af_info_lavcac3enc;
extern const struct af_info af_info_lavrresample;
extern const struct af_info af_info_sweep;
extern const struct af_info af_info_hrtf;
extern const struct af_info af_info_ladspa;
extern const struct af_info af_info_center;
extern const struct af_info af_info_sinesuppress;
extern const struct af_info af_info_karaoke;
extern const struct af_info af_info_scaletempo;
extern const struct af_info af_info_forcespeed;
extern const struct af_info af_info_bs2b;
extern const struct af_info af_info_lavfi;
extern const struct af_info af_info_rubberband;
extern const struct af_info af_info_convert24;
extern const struct af_info af_info_convertsignendian;
static const struct af_info *const filter_list[] = {
&af_info_dummy,
&af_info_delay,
&af_info_channels,
&af_info_format,
&af_info_volume,
&af_info_equalizer,
&af_info_pan,
&af_info_surround,
&af_info_sub,
&af_info_export,
&af_info_drc,
&af_info_extrastereo,
&af_info_lavcac3enc,
&af_info_lavrresample,
#if HAVE_RUBBERBAND
&af_info_rubberband,
&af_info_sweep,
&af_info_hrtf,
#if HAVE_LADSPA
&af_info_ladspa,
#endif
&af_info_center,
&af_info_sinesuppress,
&af_info_karaoke,
&af_info_forcespeed,
&af_info_scaletempo,
#if HAVE_LIBBS2B
&af_info_bs2b,
#endif
#if HAVE_LIBAVFILTER
&af_info_lavfi,
#endif
// Must come last, because they're fallback format conversion filter
&af_info_convert24,
&af_info_convertsignendian,
NULL
};
@@ -159,11 +191,24 @@ static struct af_instance *af_create(struct af_stream *s, char *name,
MP_ERR(s, "Couldn't find audio filter '%s'.\n", name);
return NULL;
}
const struct af_info *info = desc.p;
/* Make sure that the filter is not already in the list if it is
non-reentrant */
if (info->flags & AF_FLAGS_NOT_REENTRANT) {
for (struct af_instance *cur = s->first; cur; cur = cur->next) {
if (cur->info == info) {
MP_ERR(s, "There can only be one "
"instance of the filter '%s' in each stream\n", name);
return NULL;
}
}
}
MP_VERBOSE(s, "Adding filter %s \n", name);
struct af_instance *af = talloc_zero(NULL, struct af_instance);
*af = (struct af_instance) {
.info = desc.p,
.info = info,
.data = talloc_zero(af, struct mp_audio),
.log = mp_log_new(af, s->log, name),
.replaygain_data = s->replaygain_data,
@@ -288,9 +333,89 @@ static void af_print_filter_chain(struct af_stream *s, struct af_instance *at,
MP_MSG(s, msg_level, " [ao] %s\n", mp_audio_config_to_str(&s->output));
}
static int af_count_filters(struct af_stream *s)
{
int count = 0;
for (struct af_instance *af = s->first; af; af = af->next)
count++;
return count;
}
// Finds the first conversion filter on the way from srcfmt to dstfmt.
// Conversions form a DAG: each node is a format/filter pair, and possible
// conversions are edges. We search the DAG for the shortest path.
// Some cases visit the same filter multiple times, but with different formats
// (like u24le->s8), so one node per format or filter separate is not enough.
// Returns the filter and dest. format for the first conversion step.
// (So we know what conversion filter with what format to insert next.)
static char *af_find_conversion_filter(int srcfmt, int *dstfmt)
{
#define MAX_NODES (64 * 32)
int num_fmt = 0, num_filt = 0;
for (int n = 0; filter_list[n]; n++)
num_filt = n + 1;
for (int n = 0; af_fmtstr_table[n].format; n++)
num_fmt = n + 1;
int num_nodes = num_fmt * num_filt;
assert(num_nodes < MAX_NODES);
bool visited[MAX_NODES] = {0};
unsigned char distance[MAX_NODES];
short previous[MAX_NODES] = {0};
for (int n = 0; n < num_nodes; n++) {
distance[n] = 255;
if (af_fmtstr_table[n % num_fmt].format == srcfmt)
distance[n] = 0;
}
while (1) {
int next = -1;
for (int n = 0; n < num_nodes; n++) {
if (!visited[n] && (next < 0 || (distance[n] < distance[next])))
next = n;
}
if (next < 0 || distance[next] == 255)
return NULL;
visited[next] = true;
int fmt = next % num_fmt;
if (af_fmtstr_table[fmt].format == *dstfmt) {
// Best match found
for (int cur = next; cur >= 0; cur = previous[cur] - 1) {
if (distance[cur] == 1) {
*dstfmt = af_fmtstr_table[cur % num_fmt].format;
return (char *)filter_list[cur / num_fmt]->name;
}
}
return NULL;
}
for (int n = 0; filter_list[n]; n++) {
const struct af_info *af = filter_list[n];
if (!af->test_conversion)
continue;
for (int i = 0; af_fmtstr_table[i].format; i++) {
if (i != fmt && af->test_conversion(af_fmtstr_table[fmt].format,
af_fmtstr_table[i].format))
{
int other = n * num_fmt + i;
int ndist = distance[next] + 1;
if (ndist < distance[other]) {
distance[other] = ndist;
previous[other] = next + 1;
}
}
}
}
}
assert(0);
#undef MAX_NODES
}
static bool af_is_conversion_filter(struct af_instance *af)
{
return af && strcmp(af->info->name, "lavrresample") == 0;
return af && af->info->test_conversion != NULL;
}
// in is what af can take as input - insert a conversion filter if the actual
@@ -310,24 +435,21 @@ static int af_fix_format_conversion(struct af_stream *s,
if (actual.format == in.format)
return AF_FALSE;
int dstfmt = in.format;
char *filter = "lavrresample";
if (!af_lavrresample_test_conversion(actual.format, dstfmt))
char *filter = af_find_conversion_filter(actual.format, &dstfmt);
if (!filter)
return AF_ERROR;
if (strcmp(filter, prev->info->name) == 0) {
if (prev->control(prev, AF_CONTROL_SET_FORMAT, &dstfmt) == AF_OK) {
*p_af = prev;
return AF_OK;
}
return AF_ERROR;
}
struct af_instance *new = af_prepend(s, af, filter, NULL);
if (new == NULL)
return AF_ERROR;
new->auto_inserted = true;
if (AF_OK != (rv = new->control(new, AF_CONTROL_SET_FORMAT, &dstfmt))) {
af_remove(s, new);
if (AF_OK != (rv = new->control(new, AF_CONTROL_SET_FORMAT, &dstfmt)))
return rv;
}
*p_af = new;
return AF_OK;
}
@@ -381,15 +503,6 @@ static int af_fix_rate(struct af_stream *s, struct af_instance **p_af,
return AF_OK;
}
static void reset_formats(struct af_stream *s)
{
for (struct af_instance *af = s->first; af; af = af->next) {
af->control(af, AF_CONTROL_SET_RESAMPLE_RATE, &(int){0});
af->control(af, AF_CONTROL_SET_CHANNELS, &(struct mp_chmap){0});
af->control(af, AF_CONTROL_SET_FORMAT, &(int){0});
}
}
// Return AF_OK on success or AF_ERROR on failure.
// Warning:
// A failed af_reinit() leaves the audio chain behind in a useless, broken
@@ -400,13 +513,12 @@ static int af_reinit(struct af_stream *s)
{
remove_auto_inserted_filters(s);
af_chain_forget_frames(s);
reset_formats(s);
s->first->fmt_in = s->first->fmt_out = s->input;
// Start with the second filter, as the first filter is the special input
// filter which needs no initialization.
struct af_instance *af = s->first->next;
// Up to 4 retries per filter (channel, rate, format conversions)
int max_retry = 4;
// Up to 7 retries per filter (channel, rate, 5x format conversions)
int max_retry = af_count_filters(s) * 7;
int retry = 0;
while (af) {
if (retry >= max_retry)
@@ -447,23 +559,6 @@ static int af_reinit(struct af_stream *s)
retry++;
continue;
}
// If the format conversion is (probably) caused by spdif, then
// (as a feature) drop the filter, instead of failing hard.
int fmt_in1 = af->prev->data->format;
int fmt_in2 = in.format;
if (af_fmt_is_valid(fmt_in1) && af_fmt_is_valid(fmt_in2)) {
bool spd1 = af_fmt_is_spdif(fmt_in1);
bool spd2 = af_fmt_is_spdif(fmt_in2);
if (spd1 != spd2 && af->next) {
MP_WARN(af, "Filter %s apparently cannot be used due to "
"spdif passthrough - removing it.\n",
af->info->name);
struct af_instance *aft = af->prev;
af_remove(s, af);
af = aft->next;
break;
}
}
goto negotiate_error;
}
case AF_DETACH: { // Filter is redundant and wants to be unloaded
@@ -478,8 +573,6 @@ static int af_reinit(struct af_stream *s)
af->info->name, rv);
goto error;
}
if (af && !af->auto_inserted)
retry = 0;
}
/* Set previously unset fields in s->output to those of the filter chain
@@ -594,14 +687,8 @@ int af_init(struct af_stream *s)
to the stream s. The filter will be inserted somewhere nice in the
list of filters. The return value is a pointer to the new filter,
If the filter couldn't be added the return value is NULL. */
struct af_instance *af_add(struct af_stream *s, char *name, char *label,
char **args)
struct af_instance *af_add(struct af_stream *s, char *name, char **args)
{
assert(label);
if (af_find_by_label(s, label))
return NULL;
struct af_instance *new;
// Insert the filter somewhere nice
if (af_is_conversion_filter(s->first->next))
@@ -610,14 +697,17 @@ struct af_instance *af_add(struct af_stream *s, char *name, char *label,
new = af_prepend(s, s->first->next, name, args);
if (!new)
return NULL;
new->label = talloc_strdup(new, label);
// Reinitialize the filter list
// Reinitalize the filter list
if (af_reinit(s) != AF_OK) {
af_remove_by_label(s, label);
af_remove(s, new);
if (af_reinit(s) != AF_OK) {
af_uninit(s);
af_init(s);
}
return NULL;
}
return af_find_by_label(s, label);
return new;
}
struct af_instance *af_find_by_label(struct af_stream *s, char *label)
@@ -682,18 +772,6 @@ void af_control_all(struct af_stream *s, int cmd, void *arg)
af->control(af, cmd, arg);
}
int af_control_by_label(struct af_stream *s, int cmd, void *arg, bstr label)
{
char *label_str = bstrdup0(NULL, label);
struct af_instance *cur = af_find_by_label(s, label_str);
talloc_free(label_str);
if (cur) {
return cur->control ? cur->control(cur, cmd, arg) : CONTROL_NA;
} else {
return CONTROL_UNKNOWN;
}
}
// Used by filters to add a filtered frame to the output queue.
// Ownership of frame is transferred from caller to the filter chain.
void af_add_output_frame(struct af_instance *af, struct mp_audio *frame)
@@ -723,16 +801,6 @@ static struct mp_audio *af_dequeue_output_frame(struct af_instance *af)
return res;
}
static void read_remaining(struct af_instance *af)
{
int num_frames;
do {
num_frames = af->num_out_queued;
if (!af->filter_out || af->filter_out(af) < 0)
break;
} while (num_frames != af->num_out_queued);
}
static int af_do_filter(struct af_instance *af, struct mp_audio *frame)
{
if (frame)
@@ -772,7 +840,6 @@ int af_output_frame(struct af_stream *s, bool eof)
// Flush remaining frames on EOF, but do that only if the previous
// filters have been flushed (i.e. they have no more output).
if (eof && !last) {
read_remaining(cur);
int r = af_do_filter(cur, NULL);
if (r < 0)
return r;
+22 -17
View File
@@ -1,18 +1,19 @@
/*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPLAYER_AF_H
@@ -27,7 +28,6 @@
#include "audio/chmap.h"
#include "audio/audio.h"
#include "common/msg.h"
#include "common/common.h"
struct af_instance;
struct mpv_global;
@@ -35,6 +35,10 @@ struct mpv_global;
// Number of channels
#define AF_NCH MP_NUM_CHANNELS
// Flags used for defining the behavior of an audio filter
#define AF_FLAGS_REENTRANT 0x00000000
#define AF_FLAGS_NOT_REENTRANT 0x00000001
// Flags for af->filter()
#define AF_FILTER_FLAG_EOF 1
@@ -43,7 +47,9 @@ struct mpv_global;
struct af_info {
const char *info;
const char *name;
const int flags;
int (*open)(struct af_instance *vf);
bool (*test_conversion)(int src_format, int dst_format);
int priv_size;
const void *priv_defaults;
const struct m_option *options;
@@ -100,12 +106,13 @@ struct af_stream {
};
// Return values
#define AF_DETACH (CONTROL_OK + 1)
#define AF_OK CONTROL_OK
#define AF_TRUE CONTROL_TRUE
#define AF_FALSE CONTROL_FALSE
#define AF_UNKNOWN CONTROL_UNKNOWN
#define AF_ERROR CONTROL_ERROR
#define AF_DETACH 2
#define AF_OK 1
#define AF_TRUE 1
#define AF_FALSE 0
#define AF_UNKNOWN -1
#define AF_ERROR -2
#define AF_FATAL -3
// Parameters for af_control_*
enum af_control {
@@ -122,7 +129,6 @@ enum af_control {
AF_CONTROL_GET_PAN_BALANCE,
AF_CONTROL_SET_PLAYBACK_SPEED,
AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE,
AF_CONTROL_GET_METADATA,
};
// Argument for AF_CONTROL_SET_PAN_LEVEL
@@ -135,13 +141,11 @@ struct af_stream *af_new(struct mpv_global *global);
void af_destroy(struct af_stream *s);
int af_init(struct af_stream *s);
void af_uninit(struct af_stream *s);
struct af_instance *af_add(struct af_stream *s, char *name, char *label,
char **args);
struct af_instance *af_add(struct af_stream *s, char *name, char **args);
int af_remove_by_label(struct af_stream *s, char *label);
struct af_instance *af_find_by_label(struct af_stream *s, char *label);
struct af_instance *af_control_any_rev(struct af_stream *s, int cmd, void *arg);
void af_control_all(struct af_stream *s, int cmd, void *arg);
int af_control_by_label(struct af_stream *s, int cmd, void *arg, bstr label);
void af_seek_reset(struct af_stream *s);
void af_add_output_frame(struct af_instance *af, struct mp_audio *frame);
@@ -154,9 +158,10 @@ double af_calc_delay(struct af_stream *s);
int af_test_output(struct af_instance *af, struct mp_audio *out);
int af_from_dB(int n, float *in, float *out, float k, float mi, float ma);
int af_to_dB(int n, float *in, float *out, float k);
int af_from_ms(int n, float *in, int *out, int rate, float mi, float ma);
int af_to_ms(int n, int *in, float *out, int rate);
float af_softclip(float a);
bool af_lavrresample_test_conversion(int src_format, int dst_format);
#endif /* MPLAYER_AF_H */
+172
View File
@@ -0,0 +1,172 @@
/*
* The Bauer stereophonic-to-binaural DSP using bs2b library:
* http://bs2b.sourceforge.net/
*
* Copyright (c) 2009 Andrew Savchenko
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <bs2b.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include "af.h"
#include "options/m_option.h"
/// Internal specific data of the filter
struct af_bs2b {
int fcut; ///< cut frequency in Hz
int feed; ///< feed level for low frequencies in 0.1*dB
int profile ; ///< profile (available crossfeed presets)
t_bs2bdp filter; ///< instance of a library filter
};
#define DEF_FILTER(fmt, name) \
static int filter_##name(struct af_instance *af, struct mp_audio *data) \
{ \
if (!data) \
return 0; \
if (af_make_writeable(af, data) < 0) { \
talloc_free(data); \
return -1; \
} \
bs2b_cross_feed_##name(((struct af_bs2b*)(af->priv))->filter, \
(data->planes[0]), data->samples); \
af_add_output_frame(af, data); \
return 0; \
}
#define GET_FILTER(fmt, name) \
case AF_FORMAT_##fmt: return filter_##name;
#define FILTERS \
FILTER(FLOAT, f) \
FILTER(S32, s32) \
FILTER(U32, u32) \
FILTER(S24, s24) \
FILTER(U24, u24) \
FILTER(S16, s16) \
FILTER(U16, u16) \
FILTER(S8, s8) \
FILTER(U8, u8)
#define FILTER DEF_FILTER
FILTERS
#undef FILTER
typedef int (*filter)(struct af_instance *af, struct mp_audio *d);
static filter get_filter(int fmt)
{
switch (fmt) {
#define FILTER GET_FILTER
FILTERS
#undef FILTER
default: return NULL;
}
}
/// Initialization and runtime control
static int control(struct af_instance *af, int cmd, void *arg)
{
struct af_bs2b *s = af->priv;
switch (cmd) {
case AF_CONTROL_REINIT: {
int format;
// Sanity check
if (!arg) return AF_ERROR;
format = ((struct mp_audio*)arg)->format;
af->data->rate = ((struct mp_audio*)arg)->rate;
mp_audio_set_num_channels(af->data, 2); // bs2b is useful only for 2ch audio
mp_audio_set_format(af->data, format);
/* check for formats supported by libbs2b
and assign corresponding handlers */
af->filter_frame = get_filter(format);
if (!af->filter_frame) {
af->filter_frame = filter_f;
mp_audio_set_format(af->data, AF_FORMAT_FLOAT);
}
// bs2b have srate limits, try to resample if needed
if (af->data->rate > BS2B_MAXSRATE || af->data->rate < BS2B_MINSRATE) {
af->data->rate = BS2B_DEFAULT_SRATE;
MP_WARN(af, "Requested sample rate %d Hz is out of bounds [%d..%d] Hz.\n"
"Trying to resample to %d Hz.\n",
af->data->rate, BS2B_MINSRATE, BS2B_MAXSRATE, BS2B_DEFAULT_SRATE);
}
bs2b_set_srate(s->filter, (long)af->data->rate);
MP_VERBOSE(af, "using format %s\n",
af_fmt_to_str(af->data->format));
return af_test_output(af,(struct mp_audio*)arg);
}
}
return AF_UNKNOWN;
}
/// Deallocate memory and close library
static void uninit(struct af_instance *af)
{
struct af_bs2b *s = af->priv;
if (s->filter)
bs2b_close(s->filter);
}
/// Allocate memory, set function pointers and init library
static int af_open(struct af_instance *af)
{
struct af_bs2b *s = af->priv;
af->control = control;
af->uninit = uninit;
// NULL means failed initialization
if (!(s->filter = bs2b_open())) {
return AF_ERROR;
}
if (s->profile)
bs2b_set_level(s->filter, s->profile);
// set fcut and feed only if specified, otherwise defaults will be used
if (s->fcut)
bs2b_set_level_fcut(s->filter, s->fcut);
if (s->feed)
bs2b_set_level_feed(s->filter, s->feed);
return AF_OK;
}
#define OPT_BASE_STRUCT struct af_bs2b
/// Description of this filter
const struct af_info af_info_bs2b = {
.info = "Bauer stereophonic-to-binaural audio filter",
.name = "bs2b",
.open = af_open,
.priv_size = sizeof(struct af_bs2b),
.options = (const struct m_option[]) {
OPT_INTRANGE("fcut", fcut, 0, BS2B_MINFCUT, BS2B_MAXFCUT),
OPT_INTRANGE("feed", feed, 0, BS2B_MINFEED, BS2B_MAXFEED),
OPT_CHOICE("profile", profile, 0,
({"default", BS2B_DEFAULT_CLEVEL},
{"cmoy", BS2B_CMOY_CLEVEL},
{"jmeier", BS2B_JMEIER_CLEVEL})),
{0}
},
};
+105
View File
@@ -0,0 +1,105 @@
/*
* This filter adds a center channel to the audio stream by
* averaging the left and right channel.
* There are two runtime controls one for setting which channel
* to insert the center-audio into called AF_CONTROL_SUB_CH.
*
* FIXME: implement a high-pass filter for better results.
*
* copyright (c) 2005 Alex Beregszaszi
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common/common.h"
#include "af.h"
// Data for specific instances of this filter
typedef struct af_center_s
{
int ch; // Channel number which to insert the filtered data
}af_center_t;
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
af_center_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_channels_old(af->data, MPMAX(s->ch+1,((struct mp_audio*)arg)->nch));
mp_audio_set_format(af->data, AF_FORMAT_FLOAT);
return af_test_output(af,(struct mp_audio*)arg);
}
}
return AF_UNKNOWN;
}
static int filter_frame(struct af_instance* af, struct mp_audio* data)
{
if (!data)
return 0;
if (af_make_writeable(af, data) < 0) {
talloc_free(data);
return -1;
}
struct mp_audio* c = data; // Current working data
af_center_t* s = af->priv; // Setup for this instance
float* a = c->planes[0]; // Audio data
int nch = c->nch; // Number of channels
int len = c->samples*c->nch; // Number of samples in current audio block
int ch = s->ch; // Channel in which to insert the center audio
register int i;
// Run filter
for(i=0;i<len;i+=nch){
// Average left and right
a[i+ch] = (a[i]/2) + (a[i+1]/2);
}
af_add_output_frame(af, data);
return 0;
}
// Allocate memory and set function pointers
static int af_open(struct af_instance* af){
af->control=control;
af->filter_frame = filter_frame;
return AF_OK;
}
#define OPT_BASE_STRUCT af_center_t
const struct af_info af_info_center = {
.info = "Audio filter for adding a center channel",
.name = "center",
.flags = AF_FLAGS_NOT_REENTRANT,
.open = af_open,
.priv_size = sizeof(af_center_t),
.options = (const struct m_option[]) {
OPT_INTRANGE("channel", ch, 0, 0, AF_NCH - 1, OPTDEF_INT(1)),
{0}
},
};
+5 -4
View File
@@ -5,20 +5,21 @@
*
* Original author: Anders
*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
+122
View File
@@ -0,0 +1,122 @@
/*
* 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 <stdlib.h>
#include <assert.h>
#include "audio/format.h"
#include "af.h"
#include "osdep/endian.h"
static bool test_conversion(int src_format, int dst_format)
{
return (src_format == AF_FORMAT_U24 && dst_format == AF_FORMAT_U32) ||
(src_format == AF_FORMAT_S24 && dst_format == AF_FORMAT_S32) ||
(src_format == AF_FORMAT_U32 && dst_format == AF_FORMAT_U24) ||
(src_format == AF_FORMAT_S32 && dst_format == AF_FORMAT_S24);
}
static int control(struct af_instance *af, int cmd, void *arg)
{
switch (cmd) {
case AF_CONTROL_REINIT: {
struct mp_audio *in = arg;
struct mp_audio orig_in = *in;
struct mp_audio *out = af->data;
if (!test_conversion(in->format, out->format))
return AF_DETACH;
if ((in->format & AF_FORMAT_BITS_MASK) == AF_FORMAT_24BIT) {
mp_audio_set_format(out, af_fmt_change_bits(in->format, 32));
} else if ((in->format & AF_FORMAT_BITS_MASK) == AF_FORMAT_32BIT) {
mp_audio_set_format(out, af_fmt_change_bits(in->format, 24));
} else {
abort();
}
out->rate = in->rate;
mp_audio_set_channels(out, &in->channels);
assert(test_conversion(in->format, out->format));
return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE;
}
case AF_CONTROL_SET_FORMAT: {
mp_audio_set_format(af->data, *(int*)arg);
return AF_OK;
}
}
return AF_UNKNOWN;
}
// The LSB is always ignored.
#if BYTE_ORDER == BIG_ENDIAN
#define SHIFT(x) ((3-(x))*8)
#else
#define SHIFT(x) (((x)+1)*8)
#endif
static int filter(struct af_instance *af, struct mp_audio *data)
{
if (!data)
return 0;
struct mp_audio *out =
mp_audio_pool_get(af->out_pool, af->data, data->samples);
if (!out) {
talloc_free(data);
return -1;
}
mp_audio_copy_attributes(out, data);
size_t len = mp_audio_psize(data) / data->bps;
if (data->bps == 4) {
for (int s = 0; s < len; s++) {
uint32_t val = *((uint32_t *)data->planes[0] + s);
uint8_t *ptr = (uint8_t *)out->planes[0] + s * 3;
ptr[0] = val >> SHIFT(0);
ptr[1] = val >> SHIFT(1);
ptr[2] = val >> SHIFT(2);
}
} else {
for (int s = 0; s < len; s++) {
uint8_t *ptr = (uint8_t *)data->planes[0] + s * 3;
uint32_t val = ptr[0] << SHIFT(0)
| ptr[1] << SHIFT(1)
| ptr[2] << SHIFT(2);
*((uint32_t *)out->planes[0] + s) = val;
}
}
talloc_free(data);
af_add_output_frame(af, out);
return 0;
}
static int af_open(struct af_instance *af)
{
af->control = control;
af->filter_frame = filter;
return AF_OK;
}
const struct af_info af_info_convert24 = {
.info = "Convert between 24 and 32 bit sample format",
.name = "convert24",
.open = af_open,
.test_conversion = test_conversion,
};
+107
View File
@@ -0,0 +1,107 @@
/*
* 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 <stdlib.h>
#include <assert.h>
#include "af.h"
#include "audio/format.h"
#include "osdep/endian.h"
static bool test_conversion(int src_format, int dst_format)
{
if ((src_format & AF_FORMAT_PLANAR) ||
(dst_format & AF_FORMAT_PLANAR))
return false;
if (((src_format & ~AF_FORMAT_SIGN_MASK) ==
(dst_format & ~AF_FORMAT_SIGN_MASK)) &&
((src_format & AF_FORMAT_TYPE_MASK) == AF_FORMAT_I))
return true;
return false;
}
static int control(struct af_instance *af, int cmd, void *arg)
{
switch (cmd) {
case AF_CONTROL_REINIT: {
struct mp_audio *in = arg;
struct mp_audio orig_in = *in;
struct mp_audio *out = af->data;
if (!test_conversion(in->format, out->format))
return AF_DETACH;
out->rate = in->rate;
mp_audio_set_channels(out, &in->channels);
return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE;
}
case AF_CONTROL_SET_FORMAT: {
mp_audio_set_format(af->data, *(int*)arg);
return AF_OK;
}
}
return AF_UNKNOWN;
}
static void si2us(void *data, int len, int bps)
{
ptrdiff_t i = -(len * bps);
uint8_t *p = &((uint8_t *)data)[len * bps];
if (BYTE_ORDER == LITTLE_ENDIAN && bps > 1)
p += bps - 1;
if (len <= 0)
return;
do {
p[i] ^= 0x80;
} while (i += bps);
}
static int filter(struct af_instance *af, struct mp_audio *data)
{
if (!data)
return 0;
if (af_make_writeable(af, data) < 0) {
talloc_free(data);
return -1;
}
int infmt = data->format;
int outfmt = af->data->format;
size_t len = data->samples * data->nch;
if ((infmt & AF_FORMAT_SIGN_MASK) != (outfmt & AF_FORMAT_SIGN_MASK))
si2us(data->planes[0], len, data->bps);
mp_audio_set_format(data, outfmt);
af_add_output_frame(af, data);
return 0;
}
static int af_open(struct af_instance *af)
{
af->control = control;
af->filter_frame = filter;
return AF_OK;
}
const struct af_info af_info_convertsignendian = {
.info = "Convert between sample format sign",
.name = "convertsign",
.open = af_open,
.test_conversion = test_conversion,
};
+5 -4
View File
@@ -5,20 +5,21 @@
*
* Original author: Anders
*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
+10 -8
View File
@@ -1,20 +1,21 @@
/*
* Copyright (C) 2004 Alex Beregszaszi & Pierre Lombard
*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
@@ -131,7 +132,7 @@ static void method1_int16(af_drc_t *s, struct mp_audio *c)
data[i] = tmp;
}
// Evaluation of newavg (not 100% accurate because of values clamping)
// Evaulation of newavg (not 100% accurate because of values clamping)
newavg = s->mul * curavg;
// Stores computed values for future smoothing
@@ -168,7 +169,7 @@ static void method1_float(af_drc_t *s, struct mp_audio *c)
for (i = 0; i < len; i++)
data[i] *= s->mul;
// Evaluation of newavg (not 100% accurate because of values clamping)
// Evaulation of newavg (not 100% accurate because of values clamping)
newavg = s->mul * curavg;
// Stores computed values for future smoothing
@@ -216,7 +217,7 @@ static void method2_int16(af_drc_t *s, struct mp_audio *c)
data[i] = tmp;
}
// Evaluation of newavg (not 100% accurate because of values clamping)
// Evaulation of newavg (not 100% accurate because of values clamping)
newavg = s->mul * curavg;
// Stores computed values for future smoothing
@@ -262,7 +263,7 @@ static void method2_float(af_drc_t *s, struct mp_audio *c)
for (i = 0; i < len; i++)
data[i] *= s->mul;
// Evaluation of newavg (not 100% accurate because of values clamping)
// Evaulation of newavg (not 100% accurate because of values clamping)
newavg = s->mul * curavg;
// Stores computed values for future smoothing
@@ -324,6 +325,7 @@ static int af_open(struct af_instance* af){
const struct af_info af_info_drc = {
.info = "Dynamic range compression filter",
.name = "drc",
.flags = AF_FLAGS_NOT_REENTRANT,
.open = af_open,
.priv_size = sizeof(af_drc_t),
.options = (const struct m_option[]) {
+62
View File
@@ -0,0 +1,62 @@
/*
* The name speaks for itself. This filter is a dummy and will
* not blow up regardless of what you do with it.
*
* Original author: Anders
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "af.h"
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
switch(cmd){
case AF_CONTROL_REINIT: ;
*af->data = *(struct mp_audio*)arg;
MP_VERBOSE(af, "Was reinitialized: %iHz/%ich/%s\n",
af->data->rate,af->data->nch,af_fmt_to_str(af->data->format));
return AF_OK;
}
return AF_UNKNOWN;
}
// Filter data through filter
static int filter(struct af_instance* af, struct mp_audio* data)
{
af_add_output_frame(af, data);
return 0;
}
// Allocate memory and set function pointers
static int af_open(struct af_instance* af){
af->control=control;
af->filter_frame=filter;
return AF_OK;
}
// Description of this filter
const struct af_info af_info_dummy = {
.info = "dummy",
.name = "dummy",
.open = af_open,
};
+6 -4
View File
@@ -6,20 +6,21 @@
*
* Copyright (C) 2001 Anders Johansson ajh@atri.curtin.edu.au
*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
@@ -203,6 +204,7 @@ static int af_open(struct af_instance* af){
const struct af_info af_info_equalizer = {
.info = "Equalizer audio filter",
.name = "equalizer",
.flags = AF_FLAGS_NOT_REENTRANT,
.open = af_open,
.priv_size = sizeof(af_equalizer_t),
.options = (const struct m_option[]) {
+238
View File
@@ -0,0 +1,238 @@
/*
* This audio filter exports the incoming signal to other processes
* using memory mapping. The memory mapped area contains a header:
* int nch,
* int size,
* unsigned long long counter (updated every time the contents of
* the area changes),
* the rest is payload (non-interleaved).
*
* Authors: Anders; Gustavo Sverzut Barbieri <gustavo.barbieri@ic.unicamp.br>
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
#include "config.h"
#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "osdep/io.h"
#include "talloc.h"
#include "af.h"
#include "options/path.h"
#define DEF_SZ 512 // default buffer size (in samples)
#define SHARED_FILE "mpv-af_export" /* default file name
(relative to ~/.mpv/ */
#define SIZE_HEADER (2 * sizeof(int) + sizeof(unsigned long long))
// Data for specific instances of this filter
typedef struct af_export_s
{
unsigned long long count; // Used for sync
void* buf[AF_NCH]; // Buffers for storing the data before it is exported
int sz; // Size of buffer in samples
int wi; // Write index
int fd; // File descriptor to shared memory area
char* filename; // File to export data
uint8_t *mmap_area; // MMap shared area
} af_export_t;
/* Initialization and runtime control
af audio filter instance
cmd control command
arg argument
*/
static int control(struct af_instance* af, int cmd, void* arg)
{
af_export_t* s = af->priv;
switch (cmd){
case AF_CONTROL_REINIT:{
int i=0;
int mapsize;
// Free previous buffers
free(s->buf[0]);
// unmap previous area
if(s->mmap_area)
munmap(s->mmap_area, SIZE_HEADER + (af->data->bps*s->sz*af->data->nch));
// close previous file descriptor
if(s->fd)
close(s->fd);
// Accept only int16_t as input format (which sucks)
mp_audio_copy_config(af->data, (struct mp_audio*)arg);
mp_audio_set_format(af->data, AF_FORMAT_S16);
// Allocate new buffers (as one continuous block)
s->buf[0] = calloc(s->sz*af->data->nch, af->data->bps);
if(NULL == s->buf[0]) {
MP_FATAL(af, "Out of memory\n");
return AF_ERROR;
}
for(i = 1; i < af->data->nch; i++)
s->buf[i] = (uint8_t *)s->buf[0] + i*s->sz*af->data->bps;
if (!s->filename) {
MP_FATAL(af, "No filename set.\n");
return AF_ERROR;
}
// Init memory mapping
s->fd = open(s->filename, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0640);
MP_INFO(af, "Exporting to file: %s\n", s->filename);
if(s->fd < 0) {
MP_FATAL(af, "Could not open/create file: %s\n",
s->filename);
return AF_ERROR;
}
// header + buffer
mapsize = (SIZE_HEADER + (af->data->bps * s->sz * af->data->nch));
// grow file to needed size
for(i = 0; i < mapsize; i++){
char null = 0;
write(s->fd, (void*) &null, 1);
}
// mmap size
s->mmap_area = mmap(0, mapsize, PROT_READ|PROT_WRITE,MAP_SHARED, s->fd, 0);
if(s->mmap_area == NULL)
MP_FATAL(af, "Could not mmap file %s\n", s->filename);
MP_INFO(af, "Memory mapped to file: %s (%p)\n",
s->filename, s->mmap_area);
// Initialize header
*((int*)s->mmap_area) = af->data->nch;
*((int*)s->mmap_area + 1) = s->sz * af->data->bps * af->data->nch;
msync(s->mmap_area, mapsize, MS_ASYNC);
// Use test_output to return FALSE if necessary
return af_test_output(af, (struct mp_audio*)arg);
}
}
return AF_UNKNOWN;
}
/* Free allocated memory and clean up other stuff too.
af audio filter instance
*/
static void uninit( struct af_instance* af )
{
af_export_t* s = af->priv;
free(s->buf[0]);
// Free mmaped area
if(s->mmap_area)
munmap(s->mmap_area, sizeof(af_export_t));
if(s->fd > -1)
close(s->fd);
}
/* Filter data through filter
af audio filter instance
data audio data
*/
static int filter(struct af_instance *af, struct mp_audio *data)
{
if (!data)
return 0;
struct mp_audio* c = data; // Current working data
af_export_t* s = af->priv; // Setup for this instance
int16_t* a = c->planes[0]; // Incomming sound
int nch = c->nch; // Number of channels
int len = c->samples*c->nch; // Number of sample in data chunk
int sz = s->sz; // buffer size (in samples)
int flag = 0; // Set to 1 if buffer is filled
int ch, i;
// Fill all buffers
for(ch = 0; ch < nch; ch++){
int wi = s->wi; // Reset write index
int16_t* b = s->buf[ch]; // Current buffer
// Copy data to export buffers
for(i = ch; i < len; i += nch){
b[wi++] = a[i];
if(wi >= sz){ // Don't write outside the end of the buffer
flag = 1;
break;
}
}
s->wi = wi % s->sz;
}
// Export buffer to mmaped area
if(flag){
// update buffer in mapped area
memcpy(s->mmap_area + SIZE_HEADER, s->buf[0], sz * c->bps * nch);
s->count++; // increment counter (to sync)
memcpy(s->mmap_area + SIZE_HEADER - sizeof(s->count),
&(s->count), sizeof(s->count));
}
af_add_output_frame(af, data);
return 0;
}
/* Allocate memory and set function pointers
af audio filter instance
returns AF_OK or AF_ERROR
*/
static int af_open( struct af_instance* af )
{
af->control = control;
af->uninit = uninit;
af->filter_frame = filter;
af_export_t *priv = af->priv;
if (!priv->filename || !priv->filename[0]) {
MP_FATAL(af, "no export filename given");
return AF_ERROR;
}
return AF_OK;
}
#define OPT_BASE_STRUCT af_export_t
const struct af_info af_info_export = {
.info = "Sound export filter",
.name = "export",
.open = af_open,
.priv_size = sizeof(af_export_t),
.options = (const struct m_option[]) {
OPT_STRING("filename", filename, 0),
OPT_INTRANGE("buffersamples", sz, 0, 1, 2048, OPTDEF_INT(DEF_SZ)),
{0}
},
};
+133
View File
@@ -0,0 +1,133 @@
/*
* Copyright (C) 2004 Alex Beregszaszi & Pierre Lombard
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#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"
// Data for specific instances of this filter
typedef struct af_extrastereo_s
{
float mul;
}af_extrastereo_t;
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
switch(cmd){
case AF_CONTROL_REINIT:{
// Sanity check
if(!arg) return AF_ERROR;
mp_audio_copy_config(af->data, (struct mp_audio*)arg);
mp_audio_force_interleaved_format(af->data);
mp_audio_set_num_channels(af->data, 2);
if (af->data->format != AF_FORMAT_FLOAT)
mp_audio_set_format(af->data, AF_FORMAT_S16);
return af_test_output(af,(struct mp_audio*)arg);
}
}
return AF_UNKNOWN;
}
// Filter data through filter
static void play_s16(af_extrastereo_t *s, struct mp_audio* data)
{
register int i = 0;
int16_t *a = (int16_t*)data->planes[0]; // Audio data
int len = data->samples*data->nch; // Number of samples
int avg, l, r;
for (i = 0; i < len; i+=2)
{
avg = (a[i] + a[i + 1]) / 2;
l = avg + (int)(s->mul * (a[i] - avg));
r = avg + (int)(s->mul * (a[i + 1] - avg));
a[i] = MPCLAMP(l, SHRT_MIN, SHRT_MAX);
a[i + 1] = MPCLAMP(r, SHRT_MIN, SHRT_MAX);
}
}
static void play_float(af_extrastereo_t *s, struct mp_audio* data)
{
register int i = 0;
float *a = (float*)data->planes[0]; // Audio data
int len = data->samples * data->nch; // Number of samples
float avg, l, r;
for (i = 0; i < len; i+=2)
{
avg = (a[i] + a[i + 1]) / 2;
l = avg + (s->mul * (a[i] - avg));
r = avg + (s->mul * (a[i + 1] - avg));
a[i] = af_softclip(l);
a[i + 1] = af_softclip(r);
}
}
static int filter_frame(struct af_instance *af, struct mp_audio *data)
{
if (!data)
return 0;
if (af_make_writeable(af, data) < 0) {
talloc_free(data);
return -1;
}
if (data->format == AF_FORMAT_FLOAT) {
play_float(af->priv, data);
} else {
play_s16(af->priv, data);
}
af_add_output_frame(af, data);
return 0;
}
// Allocate memory and set function pointers
static int af_open(struct af_instance* af){
af->control=control;
af->filter_frame = filter_frame;
return AF_OK;
}
#define OPT_BASE_STRUCT af_extrastereo_t
const struct af_info af_info_extrastereo = {
.info = "Increase difference between audio channels",
.name = "extrastereo",
.flags = AF_FLAGS_NOT_REENTRANT,
.open = af_open,
.priv_size = sizeof(af_extrastereo_t),
.options = (const struct m_option[]) {
OPT_FLOAT("mul", mul, 0, OPTDEF_FLOAT(2.5)),
{0}
},
};
+71
View File
@@ -0,0 +1,71 @@
/*
* 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 "af.h"
struct priv {
double speed;
};
static int control(struct af_instance *af, int cmd, void *arg)
{
struct priv *priv = af->priv;
switch (cmd) {
case AF_CONTROL_REINIT: {
struct mp_audio *in = arg;
struct mp_audio orig_in = *in;
struct mp_audio *out = af->data;
mp_audio_copy_config(out, in);
out->rate = in->rate * priv->speed;
return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE;
}
case AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE: {
priv->speed = *(double *)arg;
return AF_OK;
}
}
return AF_UNKNOWN;
}
static int filter(struct af_instance *af, struct mp_audio *data)
{
if (data)
mp_audio_copy_config(data, af->data);
af_add_output_frame(af, data);
return 0;
}
static int af_open(struct af_instance *af)
{
struct priv *priv = af->priv;
af->control = control;
af->filter_frame = filter;
priv->speed = 1.0;
return AF_OK;
}
#define OPT_BASE_STRUCT struct priv
const struct af_info af_info_forcespeed = {
.info = "Force audio speed",
.name = "forcespeed",
.open = af_open,
.priv_size = sizeof(struct priv),
};
+671
View File
@@ -0,0 +1,671 @@
/*
* Experimental audio filter that mixes 5.1 and 5.1 with matrix
* encoded rear channels into headphone signal using FIR filtering
* with HRTF.
*
* Author: ylai
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
//#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <math.h>
#include <libavutil/common.h>
#include "af.h"
#include "dsp.h"
/* HRTF filter coefficients and adjustable parameters */
#include "af_hrtf.h"
typedef struct af_hrtf_s {
/* Lengths */
int dlbuflen, hrflen, basslen;
/* L, C, R, Ls, Rs channels */
float *lf, *rf, *lr, *rr, *cf, *cr;
const float *cf_ir, *af_ir, *of_ir, *ar_ir, *or_ir, *cr_ir;
int cf_o, af_o, of_o, ar_o, or_o, cr_o;
/* Bass */
float *ba_l, *ba_r;
float *ba_ir;
/* Whether to matrix decode the rear center channel */
int matrix_mode;
/* How to decode the input:
0 = 5/5+1 channels
1 = 2 channels
2 = matrix encoded 2 channels */
int decode_mode;
/* Full wave rectified (FWR) amplitudes and gain used to steer the
active matrix decoding of front channels (variable names
lpr/lmr means Lt + Rt, Lt - Rt) */
float l_fwr, r_fwr, lpr_fwr, lmr_fwr;
float adapt_l_gain, adapt_r_gain, adapt_lpr_gain, adapt_lmr_gain;
/* Matrix input decoding require special FWR buffer, since the
decoding is done in place. */
float *fwrbuf_l, *fwrbuf_r, *fwrbuf_lr, *fwrbuf_rr;
/* Rear channel delay buffer for matrix decoding */
float *rear_dlbuf;
/* Full wave rectified amplitude and gain used to steer the active
matrix decoding of center rear channel */
float lr_fwr, rr_fwr, lrprr_fwr, lrmrr_fwr;
float adapt_lr_gain, adapt_rr_gain;
float adapt_lrprr_gain, adapt_lrmrr_gain;
/* Cyclic position on the ring buffer */
int cyc_pos;
int print_flag;
int mode;
} af_hrtf_t;
/* Convolution on a ring buffer
* nx: length of the ring buffer
* nk: length of the convolution kernel
* sx: ring buffer
* sk: convolution kernel
* offset: offset on the ring buffer, can be
*/
static float conv(const int nx, const int nk, const float *sx, const float *sk,
const int offset)
{
/* k = reminder of offset / nx */
int k = offset >= 0 ? offset % nx : nx + (offset % nx);
if(nk + k <= nx)
return af_filter_fir(nk, sx + k, sk);
else
return af_filter_fir(nk + k - nx, sx, sk + nx - k) +
af_filter_fir(nx - k, sx + k, sk);
}
/* Detect when the impulse response starts (significantly) */
static int pulse_detect(const float *sx)
{
/* nmax must be the reference impulse response length (128) minus
s->hrflen */
const int nmax = 128 - HRTFFILTLEN;
const float thresh = IRTHRESH;
int i;
for(i = 0; i < nmax; i++)
if(fabs(sx[i]) > thresh)
return i;
return 0;
}
/* Fuzzy matrix coefficient transfer function to "lock" the matrix on
a effectively passive mode if the gain is approximately 1 */
static inline float passive_lock(float x)
{
const float x1 = x - 1;
const float ax1s = fabs(x - 1) * (1.0 / MATAGCLOCK);
return x1 - x1 / (1 + ax1s * ax1s) + 1;
}
/* Unified active matrix decoder for 2 channel matrix encoded surround
sources */
static inline void matrix_decode(short *in, const int k, const int il,
const int ir, const int decode_rear,
const int dlbuflen,
float l_fwr, float r_fwr,
float lpr_fwr, float lmr_fwr,
float *adapt_l_gain, float *adapt_r_gain,
float *adapt_lpr_gain, float *adapt_lmr_gain,
float *lf, float *rf, float *lr,
float *rr, float *cf)
{
const int kr = (k + MATREARDELAY) % dlbuflen;
float l_gain = (l_fwr + r_fwr) /
(1 + l_fwr + l_fwr);
float r_gain = (l_fwr + r_fwr) /
(1 + r_fwr + r_fwr);
/* The 2nd axis has strong gain fluctuations, and therefore require
limits. The factor corresponds to the 1 / amplification of (Lt
- Rt) when (Lt, Rt) is strongly correlated. (e.g. during
dialogues). It should be bigger than -12 dB to prevent
distortion. */
float lmr_lim_fwr = lmr_fwr > M9_03DB * lpr_fwr ?
lmr_fwr : M9_03DB * lpr_fwr;
float lpr_gain = (lpr_fwr + lmr_lim_fwr) /
(1 + lpr_fwr + lpr_fwr);
float lmr_gain = (lpr_fwr + lmr_lim_fwr) /
(1 + lmr_lim_fwr + lmr_lim_fwr);
float lmr_unlim_gain = (lpr_fwr + lmr_fwr) /
(1 + lmr_fwr + lmr_fwr);
float lpr, lmr;
float l_agc, r_agc, lpr_agc, lmr_agc;
float f, d_gain, c_gain, c_agc_cfk;
#if 0
static int counter = 0;
static FILE *fp_out;
if(counter == 0)
fp_out = fopen("af_hrtf.log", "w");
if(counter % 240 == 0)
fprintf(fp_out, "%g %g %g %g %g ", counter * (1.0 / 48000),
l_gain, r_gain, lpr_gain, lmr_gain);
#endif
/*** AXIS NO. 1: (Lt, Rt) -> (C, Ls, Rs) ***/
/* AGC adaption */
d_gain = (fabs(l_gain - *adapt_l_gain) +
fabs(r_gain - *adapt_r_gain)) * 0.5;
f = d_gain * (1.0 / MATAGCTRIG);
f = MATAGCDECAY - MATAGCDECAY / (1 + f * f);
*adapt_l_gain = (1 - f) * *adapt_l_gain + f * l_gain;
*adapt_r_gain = (1 - f) * *adapt_r_gain + f * r_gain;
/* Matrix */
l_agc = in[il] * passive_lock(*adapt_l_gain);
r_agc = in[ir] * passive_lock(*adapt_r_gain);
cf[k] = (l_agc + r_agc) * M_SQRT1_2;
if(decode_rear) {
lr[kr] = rr[kr] = (l_agc - r_agc) * M_SQRT1_2;
/* Stereo rear channel is steered with the same AGC steering as
the decoding matrix. Note this requires a fast updating AGC
at the order of 20 ms (which is the case here). */
lr[kr] *= (l_fwr + l_fwr) /
(1 + l_fwr + r_fwr);
rr[kr] *= (r_fwr + r_fwr) /
(1 + l_fwr + r_fwr);
}
/*** AXIS NO. 2: (Lt + Rt, Lt - Rt) -> (L, R) ***/
lpr = (in[il] + in[ir]) * M_SQRT1_2;
lmr = (in[il] - in[ir]) * M_SQRT1_2;
/* AGC adaption */
d_gain = fabs(lmr_unlim_gain - *adapt_lmr_gain);
f = d_gain * (1.0 / MATAGCTRIG);
f = MATAGCDECAY - MATAGCDECAY / (1 + f * f);
*adapt_lpr_gain = (1 - f) * *adapt_lpr_gain + f * lpr_gain;
*adapt_lmr_gain = (1 - f) * *adapt_lmr_gain + f * lmr_gain;
/* Matrix */
lpr_agc = lpr * passive_lock(*adapt_lpr_gain);
lmr_agc = lmr * passive_lock(*adapt_lmr_gain);
lf[k] = (lpr_agc + lmr_agc) * M_SQRT1_2;
rf[k] = (lpr_agc - lmr_agc) * M_SQRT1_2;
/*** CENTER FRONT CANCELLATION ***/
/* A heuristic approach exploits that Lt + Rt gain contains the
information about Lt, Rt correlation. This effectively reshapes
the front and rear "cones" to concentrate Lt + Rt to C and
introduce Lt - Rt in L, R. */
/* 0.67677 is the emprical lower bound for lpr_gain. */
c_gain = 8 * (*adapt_lpr_gain - 0.67677);
c_gain = c_gain > 0 ? c_gain : 0;
/* c_gain should not be too high, not even reaching full
cancellation (~ 0.50 - 0.55 at current AGC implementation), or
the center will s0und too narrow. */
c_gain = MATCOMPGAIN / (1 + c_gain * c_gain);
c_agc_cfk = c_gain * cf[k];
lf[k] -= c_agc_cfk;
rf[k] -= c_agc_cfk;
cf[k] += c_agc_cfk + c_agc_cfk;
#if 0
if(counter % 240 == 0)
fprintf(fp_out, "%g %g %g %g %g\n",
*adapt_l_gain, *adapt_r_gain,
*adapt_lpr_gain, *adapt_lmr_gain,
c_gain);
counter++;
#endif
}
static inline void update_ch(af_hrtf_t *s, short *in, const int k)
{
const int fwr_pos = (k + FWRDURATION) % s->dlbuflen;
/* Update the full wave rectified total amplitude */
/* Input matrix decoder */
if(s->decode_mode == HRTF_MIX_MATRIX2CH) {
s->l_fwr += abs(in[0]) - fabs(s->fwrbuf_l[fwr_pos]);
s->r_fwr += abs(in[1]) - fabs(s->fwrbuf_r[fwr_pos]);
s->lpr_fwr += abs(in[0] + in[1]) -
fabs(s->fwrbuf_l[fwr_pos] + s->fwrbuf_r[fwr_pos]);
s->lmr_fwr += abs(in[0] - in[1]) -
fabs(s->fwrbuf_l[fwr_pos] - s->fwrbuf_r[fwr_pos]);
}
/* Rear matrix decoder */
if(s->matrix_mode) {
s->lr_fwr += abs(in[2]) - fabs(s->fwrbuf_lr[fwr_pos]);
s->rr_fwr += abs(in[3]) - fabs(s->fwrbuf_rr[fwr_pos]);
s->lrprr_fwr += abs(in[2] + in[3]) -
fabs(s->fwrbuf_lr[fwr_pos] + s->fwrbuf_rr[fwr_pos]);
s->lrmrr_fwr += abs(in[2] - in[3]) -
fabs(s->fwrbuf_lr[fwr_pos] - s->fwrbuf_rr[fwr_pos]);
}
switch (s->decode_mode) {
case HRTF_MIX_51:
/* 5/5+1 channel sources */
s->lf[k] = in[0];
s->cf[k] = in[4];
s->rf[k] = in[1];
s->fwrbuf_lr[k] = s->lr[k] = in[2];
s->fwrbuf_rr[k] = s->rr[k] = in[3];
break;
case HRTF_MIX_MATRIX2CH:
/* Matrix encoded 2 channel sources */
s->fwrbuf_l[k] = in[0];
s->fwrbuf_r[k] = in[1];
matrix_decode(in, k, 0, 1, 1, s->dlbuflen,
s->l_fwr, s->r_fwr,
s->lpr_fwr, s->lmr_fwr,
&(s->adapt_l_gain), &(s->adapt_r_gain),
&(s->adapt_lpr_gain), &(s->adapt_lmr_gain),
s->lf, s->rf, s->lr, s->rr, s->cf);
break;
case HRTF_MIX_STEREO:
/* Stereo sources */
s->lf[k] = in[0];
s->rf[k] = in[1];
s->cf[k] = s->lr[k] = s->rr[k] = 0;
break;
}
/* We need to update the bass compensation delay line, too. */
// TODO: should this use lf/cf/rf etc. instead?
s->ba_l[k] = in[0];
s->ba_r[k] = in[1];
if (s->decode_mode == HRTF_MIX_51) {
s->ba_l[k] += in[4] + in[2];
s->ba_r[k] += in[4] + in[3];
}
}
static void clear_coeff(af_hrtf_t *s, float *c)
{
memset(c, 0, s->dlbuflen * sizeof(float));
}
static void reset(af_hrtf_t *s)
{
clear_coeff(s, s->lf);
clear_coeff(s, s->rf);
clear_coeff(s, s->lr);
clear_coeff(s, s->rr);
clear_coeff(s, s->cf);
clear_coeff(s, s->cr);
clear_coeff(s, s->ba_l);
clear_coeff(s, s->ba_r);
clear_coeff(s, s->fwrbuf_l);
clear_coeff(s, s->fwrbuf_r);
clear_coeff(s, s->fwrbuf_lr);
clear_coeff(s, s->fwrbuf_rr);
}
/* Initialization and runtime control */
static int control(struct af_instance *af, int cmd, void* arg)
{
af_hrtf_t *s = af->priv;
int test_output_res;
switch(cmd) {
case AF_CONTROL_REINIT:
reset(s);
af->data->rate = 48000;
mp_audio_set_channels_old(af->data, ((struct mp_audio*)arg)->nch);
if(af->data->nch == 2) {
/* 2 channel input */
if(s->decode_mode != HRTF_MIX_MATRIX2CH) {
/* Default behavior is stereo mixing. */
s->decode_mode = HRTF_MIX_STEREO;
}
} else if (af->data->nch < 5) {
mp_audio_set_channels_old(af->data, 5);
}
mp_audio_set_format(af->data, AF_FORMAT_S16);
test_output_res = af_test_output(af, (struct mp_audio*)arg);
// after testing input set the real output format
mp_audio_set_num_channels(af->data, 2);
s->print_flag = 1;
return test_output_res;
case AF_CONTROL_RESET:
reset(s);
return AF_OK;
}
return AF_UNKNOWN;
}
/* Deallocate memory */
static void uninit(struct af_instance *af)
{
af_hrtf_t *s = af->priv;
free(s->lf);
free(s->rf);
free(s->lr);
free(s->rr);
free(s->cf);
free(s->cr);
free(s->ba_l);
free(s->ba_r);
free(s->ba_ir);
free(s->fwrbuf_l);
free(s->fwrbuf_r);
free(s->fwrbuf_lr);
free(s->fwrbuf_rr);
}
/* Filter data through filter
Two "tricks" are used to compensate the "color" of the KEMAR data:
1. The KEMAR data is refiltered to ensure that the front L, R channels
on the same side of the ear are equalized (especially in the high
frequencies).
2. A bass compensation is introduced to ensure that 0-200 Hz are not
damped (without any real 3D acoustical image, however).
*/
static int filter(struct af_instance *af, struct mp_audio *data)
{
af_hrtf_t *s = af->priv;
if (!data)
return 0;
struct mp_audio *outframe =
mp_audio_pool_get(af->out_pool, &af->fmt_out, data->samples);
if (!outframe) {
talloc_free(data);
return -1;
}
mp_audio_copy_attributes(outframe, data);
short *in = data->planes[0]; // Input audio data
short *out = outframe->planes[0]; // Output audio data
short *end = in + data->samples * data->nch; // Loop end
float common, left, right, diff, left_b, right_b;
const int dblen = s->dlbuflen, hlen = s->hrflen, blen = s->basslen;
if(s->print_flag) {
s->print_flag = 0;
switch (s->decode_mode) {
case HRTF_MIX_51:
MP_INFO(af, "Using HRTF to mix %s discrete surround into "
"L, R channels\n", s->matrix_mode ? "5+1" : "5");
break;
case HRTF_MIX_STEREO:
MP_INFO(af, "Using HRTF to mix stereo into "
"L, R channels\n");
break;
case HRTF_MIX_MATRIX2CH:
MP_INFO(af, "Using active matrix to decode 2 channel "
"input, HRTF to mix %s matrix surround into "
"L, R channels\n", "3/2");
break;
default:
MP_WARN(af, "bogus decode_mode: %d\n", s->decode_mode);
break;
}
if(s->matrix_mode)
MP_INFO(af, "Using active matrix to decode rear center "
"channel\n");
}
/* MPlayer's 5 channel layout (notation for the variable):
*
* 0: L (LF), 1: R (RF), 2: Ls (LR), 3: Rs (RR), 4: C (CF), matrix
* encoded: Cs (CR)
*
* or: L = left, C = center, R = right, F = front, R = rear
*
* Filter notation:
*
* CF
* OF AF
* Ear->
* OR AR
* CR
*
* or: C = center, A = same side, O = opposite, F = front, R = rear
*/
while(in < end) {
const int k = s->cyc_pos;
update_ch(s, in, k);
/* Simulate a 7.5 ms -20 dB echo of the center channel in the
front channels (like reflection from a room wall) - a kind of
psycho-acoustically "cheating" to focus the center front
channel, which is normally hard to be perceived as front */
s->lf[k] += CFECHOAMPL * s->cf[(k + CFECHODELAY) % s->dlbuflen];
s->rf[k] += CFECHOAMPL * s->cf[(k + CFECHODELAY) % s->dlbuflen];
switch (s->decode_mode) {
case HRTF_MIX_51:
case HRTF_MIX_MATRIX2CH:
/* Mixer filter matrix */
common = conv(dblen, hlen, s->cf, s->cf_ir, k + s->cf_o);
if(s->matrix_mode) {
/* In matrix decoding mode, the rear channel gain must be
renormalized, as there is an additional channel. */
matrix_decode(in, k, 2, 3, 0, s->dlbuflen,
s->lr_fwr, s->rr_fwr,
s->lrprr_fwr, s->lrmrr_fwr,
&(s->adapt_lr_gain), &(s->adapt_rr_gain),
&(s->adapt_lrprr_gain), &(s->adapt_lrmrr_gain),
s->lr, s->rr, NULL, NULL, s->cr);
common +=
conv(dblen, hlen, s->cr, s->cr_ir, k + s->cr_o) *
M1_76DB;
left =
( conv(dblen, hlen, s->lf, s->af_ir, k + s->af_o) +
conv(dblen, hlen, s->rf, s->of_ir, k + s->of_o) +
(conv(dblen, hlen, s->lr, s->ar_ir, k + s->ar_o) +
conv(dblen, hlen, s->rr, s->or_ir, k + s->or_o)) *
M1_76DB + common);
right =
( conv(dblen, hlen, s->rf, s->af_ir, k + s->af_o) +
conv(dblen, hlen, s->lf, s->of_ir, k + s->of_o) +
(conv(dblen, hlen, s->rr, s->ar_ir, k + s->ar_o) +
conv(dblen, hlen, s->lr, s->or_ir, k + s->or_o)) *
M1_76DB + common);
} else {
left =
( conv(dblen, hlen, s->lf, s->af_ir, k + s->af_o) +
conv(dblen, hlen, s->rf, s->of_ir, k + s->of_o) +
conv(dblen, hlen, s->lr, s->ar_ir, k + s->ar_o) +
conv(dblen, hlen, s->rr, s->or_ir, k + s->or_o) +
common);
right =
( conv(dblen, hlen, s->rf, s->af_ir, k + s->af_o) +
conv(dblen, hlen, s->lf, s->of_ir, k + s->of_o) +
conv(dblen, hlen, s->rr, s->ar_ir, k + s->ar_o) +
conv(dblen, hlen, s->lr, s->or_ir, k + s->or_o) +
common);
}
break;
case HRTF_MIX_STEREO:
left =
( conv(dblen, hlen, s->lf, s->af_ir, k + s->af_o) +
conv(dblen, hlen, s->rf, s->of_ir, k + s->of_o));
right =
( conv(dblen, hlen, s->rf, s->af_ir, k + s->af_o) +
conv(dblen, hlen, s->lf, s->of_ir, k + s->of_o));
break;
default:
/* make gcc happy */
left = 0.0;
right = 0.0;
break;
}
/* Bass compensation for the lower frequency cut of the HRTF. A
cross talk of the left and right channel is introduced to
match the directional characteristics of higher frequencies.
The bass will not have any real 3D perception, but that is
OK (note at 180 Hz, the wavelength is about 2 m, and any
spatial perception is impossible). */
left_b = conv(dblen, blen, s->ba_l, s->ba_ir, k);
right_b = conv(dblen, blen, s->ba_r, s->ba_ir, k);
left += (1 - BASSCROSS) * left_b + BASSCROSS * right_b;
right += (1 - BASSCROSS) * right_b + BASSCROSS * left_b;
/* Also mix the LFE channel (if available) */
if(data->nch >= 6) {
left += in[5] * M3_01DB;
right += in[5] * M3_01DB;
}
/* Amplitude renormalization. */
left *= AMPLNORM;
right *= AMPLNORM;
switch (s->decode_mode) {
case HRTF_MIX_51:
case HRTF_MIX_STEREO:
/* "Cheating": linear stereo expansion to amplify the 3D
perception. Note: Too much will destroy the acoustic space
and may even result in headaches. */
diff = STEXPAND2 * (left - right);
out[0] = av_clip_int16(left + diff);
out[1] = av_clip_int16(right - diff);
break;
case HRTF_MIX_MATRIX2CH:
/* Do attempt any stereo expansion with matrix encoded
sources. The L, R channels are already stereo expanded
by the steering, any further stereo expansion will sound
very unnatural. */
out[0] = av_clip_int16(left);
out[1] = av_clip_int16(right);
break;
}
/* Next sample... */
in = &in[data->nch];
out = &out[af->data->nch];
(s->cyc_pos)--;
if(s->cyc_pos < 0)
s->cyc_pos += dblen;
}
talloc_free(data);
af_add_output_frame(af, outframe);
return 0;
}
static int allocate(af_hrtf_t *s)
{
if ((s->lf = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
if ((s->rf = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
if ((s->lr = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
if ((s->rr = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
if ((s->cf = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
if ((s->cr = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
if ((s->ba_l = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
if ((s->ba_r = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
if ((s->fwrbuf_l =
malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
if ((s->fwrbuf_r =
malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
if ((s->fwrbuf_lr =
malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
if ((s->fwrbuf_rr =
malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
return 0;
}
/* Allocate memory and set function pointers */
static int af_open(struct af_instance* af)
{
int i;
af_hrtf_t *s;
float fc;
af->control = control;
af->uninit = uninit;
af->filter_frame = filter;
s = af->priv;
s->dlbuflen = DELAYBUFLEN;
s->hrflen = HRTFFILTLEN;
s->basslen = BASSFILTLEN;
s->cyc_pos = s->dlbuflen - 1;
/* With a full (two axis) steering matrix decoder, s->matrix_mode
should not be enabled lightly (it will also steer the Ls, Rs
channels). */
s->matrix_mode = 0;
s->decode_mode = HRTF_MIX_51;
switch (s->mode) {
case 0: /* Use matrix rear decoding. */
s->matrix_mode = 1;
break;
case 1: /* Input needs matrix decoding. */
s->decode_mode = HRTF_MIX_MATRIX2CH;
break;
case 2:
s->matrix_mode = 0;
break;
}
s->print_flag = 1;
if (allocate(s) != 0) {
MP_ERR(af, "Memory allocation error.\n");
return AF_ERROR;
}
for(i = 0; i < s->dlbuflen; i++)
s->lf[i] = s->rf[i] = s->lr[i] = s->rr[i] = s->cf[i] =
s->cr[i] = 0;
s->lr_fwr =
s->rr_fwr = 0;
s->cf_ir = cf_filt + (s->cf_o = pulse_detect(cf_filt));
s->af_ir = af_filt + (s->af_o = pulse_detect(af_filt));
s->of_ir = of_filt + (s->of_o = pulse_detect(of_filt));
s->ar_ir = ar_filt + (s->ar_o = pulse_detect(ar_filt));
s->or_ir = or_filt + (s->or_o = pulse_detect(or_filt));
s->cr_ir = cr_filt + (s->cr_o = pulse_detect(cr_filt));
if((s->ba_ir = malloc(s->basslen * sizeof(float))) == NULL) {
MP_ERR(af, "Memory allocation error.\n");
return AF_ERROR;
}
fc = 2.0 * BASSFILTFREQ / (float)af->data->rate;
if(af_filter_design_fir(s->basslen, s->ba_ir, &fc, LP | KAISER, 4 * M_PI) ==
-1) {
MP_ERR(af, "Unable to design low-pass "
"filter.\n");
return AF_ERROR;
}
for(i = 0; i < s->basslen; i++)
s->ba_ir[i] *= BASSGAIN;
return AF_OK;
}
#define OPT_BASE_STRUCT af_hrtf_t
const struct af_info af_info_hrtf = {
.info = "HRTF Headphone",
.name = "hrtf",
.open = af_open,
.priv_size = sizeof(af_hrtf_t),
.options = (const struct m_option[]) {
OPT_CHOICE("mode", mode, 0, ({"m", 0}, {"s", 1}, {"0", 2})),
{0}
},
};
+511
View File
@@ -0,0 +1,511 @@
/*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPLAYER_AF_HRTF_H
#define MPLAYER_AF_HRTF_H
#define HRTF_MIX_51 0
#define HRTF_MIX_STEREO 1
#define HRTF_MIX_MATRIX2CH 2
/* Amplitude scaling factors */
#define M17_0DB 0.1414213562
#define M9_03DB 0.3535533906
#define M6_99DB 0.4472135955
#define M4_77DB 0.5773502692
#define M3_01DB 0.7071067812
#define M1_76DB 0.8164965809
#define DELAYBUFLEN 1024 /* Length of the delay buffer */
#define HRTFFILTLEN 64 /* HRTF filter length */
#define IRTHRESH 0.001 /* Impulse response pruning thresh. */
#define AMPLNORM M6_99DB /* Overall amplitude renormalization */
#define BASSFILTFREQ 180 /* Bass compensation filter cut (Hz) */
#define BASSFILTLEN 193 /* Bass compensation filter length */
#define BASSGAIN M_SQRT2 /* Bass compensation gain */
#define BASSCROSS 0.35 /* Bass cross talk */
#define FWRDURATION 240 /* FWR average duration (samples) */
#define MATREARDELAY 720 /* Matrix mode rear delay (samples) */
#define MATAGCTRIG 8.0 /* (Fuzzy) AGC trigger */
#define MATAGCDECAY 1.0 /* AGC baseline decay rate (1/samp.) */
#define MATAGCLOCK 0.2 /* AGC range (around 1) where the
matrix behaves passively */
#define MATCOMPGAIN 0.37 /* Cross talk compensation gain,
0.50 - 0.55 is full cancellation. */
#define CFECHODELAY 360 /* Center front echo delay (samples) */
#define CFECHOAMPL M17_0DB /* Center front echo amplitude */
#define STEXPAND2 0.07 /* Stereo expansion / 2 */
/* Head related impulse response (HRIR) derived from KEMAR measurement
data by Bill Gardner <billg@media.mit.edu> and Keith Martin
<kdm@media.mit.edu>
URL: http://sound.media.mit.edu/KEMAR.html
Distributed under GPL with authors' permission
*/
/* EQUALIZED KEMAR HRIR
How to generate these data:
1. You need the MIT Media Lab's KEMAR data, read it into an software
capable of signal/time series analysis (like Mathematica, Matlab,
...)
2. Construct an equalizing FIR inverse filter by calculating the
transfer function of the front, same side impulse response, then
take 1 over the absolute magnitude.
3. Cut the poles in the inverse filter's transfer function
specification by limiting the amplification to 2.5 (note, this
number assumes that you have correct signal processing
normalization of the Fourier transform).
4. Design the FIR inverse filter by calculating the inverse Fourier
transform, then chopping the coefficients down to a reasonable
number (N = 15 is used here), apply the Kaiser-Bessel window (alpha
= 2 is used here). Note the objective is remove the color bias
only (as if you are using an equalizer), _not_ to do a full inverse
filtering. (Note: beta = pi*alpha in other notation.)
For N = 15, alpha = 2, you should get the following impulse
response:
0.001001558668605168, 0.00698457265741865, 0.040453643039829436,
0.012230541722147855, -0.11939760844854072, 0.16468099899755967,
-0.30297563073747436, 1.3140211791355982, -0.30297563073747436,
0.16468099899755967, -0.11939760844854072, 0.012230541722147855,
0.040453643039829436, 0.00698457265741865, 0.001001558668605168
5. Linearly convolve all KEMAR HRIR with this inverse filter.
6. Resample from 44.1 kHz sampling frequency to 48 kHz.
*/
/* Center front (-5 degree) - not 0 degree in order to create a clear
front image from a finite distance */
static const float cf_filt[128] = {
-0.00008638082319075036, 0.0003198059946385229,
-0.0005010631339162132, 0.0011424741331126876,
-0.001584220794688753, 0.001742715363246275,
-0.0011080796626780694, 0.0001651829990860167,
0.005235028337314985, 0.0035223828473357776,
0.010057681388431303, -0.033469432129545514,
0.013391253316233523, 0.004858462839827063,
0.08172161220103627, 0.26158596134500023,
-0.12420314583323326, -0.14298458356097565,
0.14421897280453896, -0.1635792507629016,
-0.02187136722480014, 0.2426863044711817,
0.07229814207917194, 0.0942742651913879,
0.29856830878076834, 0.2944146162057754,
-0.12122157003421209, -0.19640092165631157,
0.11623836502034968, -0.05794027397995521,
-0.34313138341973776, -0.19487516249168105,
0.010118993953802401, -0.09460218797710966,
-0.16761521117359582, 0.004154461610153861,
0.052768641758969316, -0.00041823982226147407,
0.021634960445143514, 0.07562793486871108,
0.08895407129506479, 0.039857755093416214,
0.044257936180422945, 0.061557584906101664,
0.015547268541895703, -0.023908191934932484,
0.009498030443468223, 0.03816269003221337,
-0.009820500607303615, -0.042003975527908084,
-0.03335447117311547, -0.029294510859746596,
-0.05212623136198511, -0.073427547153205,
-0.061190797824958836, -0.04620925059966413,
-0.04204619420702159, -0.02331915902615157,
0.00211481411477094, 0.00852563995740107,
0.008766809731743399, 0.008666632180812078,
0.018279202191625352, 0.02924332751289675,
0.022293148257836494, 0.012362146008584188,
0.008572582458807008, 0.006491370763597344,
-0.0019366944997535774, -0.006318669309634434,
-0.006457921690218669, -0.015050265524669974,
-0.02110660282616213, -0.017027809096377904,
-0.01651052305334348, -0.022770064150046673,
-0.01999875754219472, -0.012294792027337775,
-0.011506057031057188, -0.011448970577312903,
-0.004823572302580925, 0.0022451134042777883,
0.004145473526859826, 0.005629030064546135,
0.008588029213398785, 0.010092048834844231,
0.007182013245552008, 0.0014600979508720656,
-0.0038314646272511756, -0.003443901997881347,
-0.0029483418254804047, -0.007609357112679647,
-0.006518368948030822, -0.004495803701497202,
-0.007109113004849672, -0.008346237278084265,
-0.005560847336252453, -0.002993453167553188,
-0.005122897816824269, -0.004389782626604215,
-0.0010912633695218108, -0.0019712029474458835,
-0.005870162265802235, -0.005626159534954128,
-0.00027254977910844407, 0.0013794425431633785,
-0.0005919083190430062, -0.0007861203545416682,
-0.0007049560240893946, -0.0032720188494468868,
-0.004460645567968504, -0.0032018528193571696,
-0.0030579229375062105, -0.003593998902656612,
-0.0038032977997776445, -0.004613776010454773,
-0.0059796549143736845, -0.00420126194319768,
-0.0012374419948287222, 0.0008572699213050608,
0.0021490971020081094, 0.00047295283198381995,
-0.0009670277915884887, -0.001354440866080231,
-0.002962902746547851, -0.00533935813338141,
-0.005469203016468759, -0.004355784273189485
};
/* Front, same side (30 degree) */
static const float af_filt[128] = {
-0.004140580614755493, 0.005790934614385445,
0.003318916682081112, 0.014257145544366063,
0.007328442487127339, -0.06550381777876194,
0.03502225818161845, -0.013090579770708259,
0.2517776798694195, 0.420770489950659,
-0.3418854608834852, -0.24371032493696737,
0.04901356150030018, -0.1778083521632833,
0.26448004245714163, 0.23245199964546834,
0.033053145803936305, 0.46811222821062415,
0.5359265986255611, -0.011912195468533787,
-0.39763432601411647, -0.034482864386898314,
0.029445398240649626, -0.3850940407863262,
-0.3272328478175581, -0.14701421403616477,
-0.08522137400169517, -0.14936851633336035,
-0.09432605283433723, 0.0991200405937827,
0.011075012089917331, -0.0051036489980274685,
0.0933903289749412, 0.1344189369609565,
0.10507466913017807, 0.04240159324684365,
0.06559270110638656, 0.026984119875617524,
-0.03359846103238096, -0.018000197099174275,
0.042031818548178244, 0.03849039666888434,
-0.02450829674011345, -0.03407882403088576,
-0.029230189282961977, -0.046964865291761734,
-0.09458258700116245, -0.1527349330901158,
-0.15411577687826097, -0.08761679790956928,
-0.033623549089171874, -0.007204768531481949,
0.008273425020444852, 0.021368717994908505,
0.04366608267875025, 0.05660907333076205,
0.06775726495503939, 0.05621881735271431,
0.03576231950669927, 0.02500825834889175,
0.015423811076054601, 0.007903258334503761,
-0.0053873014137761945, -0.006987955469434698,
-0.012027972007598602, -0.025228281243816594,
-0.026225091797257318, -0.023809293997344882,
-0.03250172017712295, -0.03195696301067249,
-0.01784813952189948, -0.01663267233760342,
-0.016184530450468065, -0.011659883749357463,
-0.0035378511240219163, -0.0005485800790443406,
0.0018432660108168625, 0.011634844139907534,
0.018333603402051105, 0.020447379185133056,
0.00850783664147828, 0.0004694148911037838,
-0.0017047130409786676, -0.0022409152834483997,
-0.000860472174892845, -0.004111075059198666,
-0.003527843382056666, -0.009640160874903018,
-0.01750044574231376, -0.015613389403672443,
-0.010790028120953001, -0.0095313499955768,
-0.007469721416726809, -0.0019186578145117315,
-0.00014977322572890802, -0.0029803838028179728,
-0.006520567233727221, 0.000035015132033882596,
0.009245098100543752, 0.009896930052308656,
0.008316744929565786, 0.004575207140193997,
-0.0000647420103997081, -0.004502916832871627,
-0.004225962213251224, -0.002886014126381486,
-0.006416834142585976, -0.007156609995423569,
-0.008840274447579472, -0.01441763751386817,
-0.015435817484659574, -0.00924487254924743,
-0.0021571721940235205, 0.0028540722992305453,
0.00273577475088536, -0.000788412365513805,
-0.0032650029728365907, -0.003880217646231338,
-0.0035302087299613778, -0.0038531436176586246,
-0.0011921632190514074, -0.0020722967099011938,
-0.004985351145629344, -0.0042375588844648735,
-0.003030360463006021, -0.0014161075428041471,
-0.0005083025643192044, 0.00035096963769606926
};
/* Front, opposite (-30 degree) */
static const float of_filt[128] = {
-0.000013472538374193126, -0.00008048061877079751,
0.000043927265781258155, -0.000017931700794858892,
-0.000034774602476112886, -0.00009576223008735474,
0.0001557797638630691, -0.00018742885883751094,
0.00026512448626705716, -0.0001451040203319678,
-0.00008263233117758043, 0.0006486245853639179,
-0.0010631408451846698, 0.0026571994100746143,
0.0014179177997092787, 0.0062326502956616256,
-0.008194149324545333, -0.006568029415878379,
0.009538759710818582, 0.012309193558632693,
0.12336638055838955, 0.046164307101829005,
-0.10228706407884815, 0.04047687260345798,
-0.00296595313977046, -0.07057949208414134,
0.08172114840714612, 0.08736490764127891,
0.05105250431333021, 0.11627179512747428,
0.20717888490340705, 0.09375052213570291,
-0.09784374168330194, -0.010493571845901443,
0.053131894303891716, -0.10157443971694806,
-0.16264032634244974, -0.05402369511361273,
-0.0274403608654217, -0.09860277022495063,
-0.06841875821090282, -0.004434574400066223,
-0.0005222661652743502, -0.006231881259827263,
0.014410397820340159, 0.04885649512730243,
0.04361962569042684, 0.03399214029009391,
0.04961073933475931, 0.04067325604132289,
0.007850647519227257, 0.004564440466905299,
0.02257107958021618, 0.008183791928884486,
-0.014913479343180557, -0.018685938460856224,
-0.01745737397226911, -0.02327177054233603,
-0.03723048632685227, -0.044739390162299685,
-0.042651220125613766, -0.03730017561004743,
-0.029039465434276192, -0.01885087458914294,
-0.01207127752277769, -0.006779800724164512,
-0.001930416967444157, 0.000029454577995528385,
0.0013822760965755472, 0.0014799128583230202,
0.0002068200609199832, 0.0022254295286201083,
0.005143858159434566, 0.0018580542060917013,
-0.0019426046325146259, -0.0014464042108543495,
-0.0034430083560735582, -0.009692758426099499,
-0.011840035292593485, -0.010716508855893968,
-0.012939889036853034, -0.0121846427935653,
-0.006198503315630782, -0.0023186723099380305,
-0.002679872498314837, -0.003086020446226295,
-0.0015709623347698936, -0.0008147490468332398,
-0.0012384575726770983, -0.0005212877089109362,
0.0017707578744906142, 0.001324932723905786,
-0.0017023653780617696, -0.0045108927752919425,
-0.005422155613096912, -0.0039489323837623835,
-0.005295995750506547, -0.00629706566356189,
-0.004685732198036754, -0.0048076735568143,
-0.005978864279217503, -0.005928999306332966,
-0.004187703549017582, -0.003213999896976475,
-0.0028068699816073414, -0.0010889703907593833,
0.0003276714243495386, -0.0013015007040186994,
-0.003208050402434782, -0.0025115319088208545,
-0.0013787553006401076, -0.0018279087370218635,
-0.0025904836507747754, -0.002071221947222004,
-0.0026424212922485594, -0.0039837031817577,
-0.0041635566057380965, -0.004355223489150822,
-0.004350395332709937, -0.0036693292471930263,
-0.003386384394185026, -0.003972568655001128,
-0.004332336840023821, -0.002648767912111827,
-0.001384410080218114, -0.0011353792711849466,
-0.0013726264946164232, -0.0020075119315034313
};
/* Rear, same side (135 degree) */
static const float ar_filt[128] = {
0.004573315040810066, 0.0013592578059426913,
0.01553271930902704, -0.0002356117224941317,
-0.05746098219774702, 0.03430688963370445,
0.00808371687447385, 0.21893535841158596,
0.2984357591724814, -0.3302799746504719,
-0.3194029149806245, 0.21633225051331056,
0.24371260938097083, -0.08843705549751085,
0.03939684701343366, 0.45386926431114494,
0.07599118140753386, -0.18114706160474578,
0.285640624686038, 0.4049515236666218,
-0.05347890222071792, -0.31464359045319074,
-0.1033502246468194, -0.04553593949283157,
-0.1880747731157464, -0.13629090230626037,
-0.10435789106123239, -0.19818232801888755,
-0.16701805476330397, -0.022793111199284,
0.058049696762683685, 0.007048321372693906,
-0.002966419183225961, 0.10140569697797763,
0.11648999956673124, 0.05218347182779882,
0.028427001212735392, 0.04151900310166159,
-0.0006960604221423734, -0.05898623212226975,
-0.03801934531173312, -0.029306970535287986,
-0.04549125782835908, -0.0599222718506552,
-0.058299618975430116, -0.03765579129720727,
-0.03559302657499581, -0.020647901025903054,
-0.005720957338744348, -0.0041915732688915545,
-0.0011470880098346143, 0.008737404798553,
0.023444168098121512, 0.024204226042172663,
0.01894897166475026, 0.020807655257479588,
0.021570431128040954, 0.006800556178576289,
-0.009000089216921362, -0.010969824547067934,
-0.0033653428332822374, -0.012676936164668659,
-0.026739938673413587, -0.023427869194287573,
-0.023302007105117244, -0.023647155590533712,
-0.021289317515613106, -0.009120487305069884,
0.0009251551667728967, 0.00004285344125653763,
-0.00009042365479456271, 0.00022573242339446494,
0.00720168491586098, 0.007111875505402431,
0.003186514817683482, 0.00810087718334745,
0.012619557025922575, 0.007854726400013397,
-0.0024013592881066267, -0.001452457473161119,
-0.0025535188366093945, -0.012428911627809337,
-0.013729251536694145, -0.0070099675146427344,
-0.007165284278706593, -0.01639289295622301,
-0.015831795079778305, -0.007305768485523729,
-0.003608863157004021, -0.0032640528878698084,
0.0030901263998481944, 0.00749497566124848,
0.002515185532327241, 0.00004840875738621367,
0.0017596043486043966, 0.0046229941553338144,
0.0034259167322926096, 0.003707347634186093,
0.0035584806528586328, -0.0019078936035275198,
-0.006057343815214898, -0.0069262470468817,
-0.004345020728618624, -0.004177623355574794,
-0.005373506556122508, -0.006624933928893836,
-0.008679541408588839, -0.010718719681595322,
-0.011392246979594496, -0.007893917064389902,
-0.0027572935365832536, -0.00006064707149834412,
-0.0012512537319656323, -0.0024501501002409786,
-0.0022106788572895998, -0.00234124933370301,
-0.0008953445167066823, 0.0005393670625637734,
-0.00033175600142209297, -0.004023994309351289,
-0.008655472335784443, -0.009899957354849682,
-0.008664952919996412, -0.00553483124503576,
-0.003735336089277662, -0.002754824348643885,
-0.0026884314856593368, -0.004084181815125924
};
/* Rear, opposite (-135 degree) */
static const float or_filt[128] = {
0.0001220944028243897, -0.000021785381808441314,
5.823057988603169e-6, -0.00001217768176447613,
-0.00006123604397345513, 5.574117262531134e-6,
-0.00004935331914366778, 1.1771577934768211e-6,
-0.000059236211621095756, 9.503536190497286e-6,
-0.0001494445696103564, 0.00012248858284145305,
-0.0000963975321456313, 6.017905197665205e-6,
0.00003353395360402643, -0.0001931511015359506,
0.0005113536523931485, -0.0005676652619386114,
0.0012057159755477467, 0.0009370492250339692,
0.004596472288877981, -0.0018831773384237068,
-0.008208535225621212, 0.0038178646400751056,
0.008726517739105965, 0.06664363898418262,
0.06788684221502142, -0.04492315162807267,
-0.04019906311255255, 0.026203059677375153,
0.013678129114847544, -0.014334962223993527,
0.010141709596167392, 0.11559131576945537,
0.1586402064538425, 0.059975334707967023,
0.004671725963777715, 0.031498678282775874,
0.014338626006524587, -0.014749719448472231,
-0.02055508237941379, -0.05407690143992048,
-0.07767559836886143, -0.05029091786216801,
-0.030808335706574427, -0.03401958135442541,
-0.030520368430288967, -0.014168302104259355,
0.011907621259989802, 0.014286081013069,
0.006377467879613449, 0.018546823568277478,
0.028297012771618273, 0.025222339408338186,
0.021931611353415138, 0.019708894333646355,
0.01729258494072014, 0.017468204169564034,
0.009729094845051928, -0.002976992018531901,
-0.00956986166277019, -0.016125733548332074,
-0.02934094241442545, -0.04133767871051455,
-0.043536981145416466, -0.0385966307108608,
-0.02784453599342459, -0.018995135307247116,
-0.012849534096536747, -0.004437491064613308,
0.00028385411598204655, 0.003776874988516643,
0.008069432041547833, 0.008764754183751848,
0.008020908861878062, 0.006830351461360802,
0.002218330884267235, -0.0020478725582339444,
-0.003997428121462543, -0.007066287373515421,
-0.00940847412544698, -0.010938998446237963,
-0.011775483016151306, -0.011391103919484287,
-0.010586061195163017, -0.009842793078929053,
-0.007753202010139829, -0.00569213732353025,
-0.006506783349722073, -0.005346134281903736,
-0.003913089814898934, -0.0036091443854759727,
-0.0020328564301266287, 0.00017932870773467683,
0.0032779786679056357, 0.003969695813293966,
0.0020339334412434987, -0.00011345940675415259,
-0.0018344103399567666, -0.003556764701666365,
-0.004263523639408391, -0.002940568582022133,
-0.0034341188272627556, -0.006023399920020824,
-0.0077456903203677865, -0.007912219312377842,
-0.00625202770436523, -0.00530785086116117,
-0.005569722659634311, -0.004664448462594344,
-0.0037747773914077747, -0.004175649656985592,
-0.004659601521384289, -0.005008602967819641,
-0.004730625079902729, -0.0034039554356604146,
-0.0017110333873406587, -0.0006091938771510242,
-0.0016051679050678297, -0.003312864664007262,
-0.004505512715977288, -0.004152222189861692,
-0.003218596419678823, -0.0027277806209877343,
-0.001715005444317267, -0.0012589960071233749,
-0.001852908777923165, -0.002540339553144362
};
/* Center rear (180 degree) */
static const float cr_filt[128] = {
-0.00005989110716536726, -0.00022790291829128702,
0.0002659166098971966, -0.0003774772716776257,
0.0004540309551867803, -0.000420238187386368,
0.00025518536450885686, 0.00028285526288953955,
-0.001016391007574093, 0.0028634984299063795,
0.0021574799687976045, 0.01035121276682072,
-0.010481720917298163, -0.013197198495899292,
0.0031928225328717195, 0.02903137843618603,
0.1632429772511569, 0.1047487989875262,
-0.10464685060623742, -0.09260196288035998,
-0.007514241993554443, 0.013596249226741712,
-0.019876166508450258, 0.1255626123599804,
0.3648170359521724, 0.19458249753223478,
-0.04434070930031298, 0.046582528121935265,
0.09484427347230277, -0.03137795311969644,
-0.10297437925363695, -0.09351091015917065,
-0.1129521092162064, -0.14925322995658827,
-0.1231466295584665, -0.06356719756705227,
-0.05442277895126282, -0.07568433015661316,
-0.023314932828602003, 0.04260950721318558,
0.02249026315598923, 0.02048195669571197,
0.05651342117268278, 0.05885038917623213,
0.03797102097397795, 0.011767394419953451,
0.00560502503429481, 0.005051125343961189,
-0.012925933188033823, -0.023918884651306566,
-0.013251659441678816, -0.010694772488866284,
-0.03080486448617846, -0.03661278237783158,
-0.0379227303416262, -0.042189005718490775,
-0.026595666344596286, -0.009759025956801257,
-0.002064986663513004, -0.002420117028098389,
-0.006629991977552491, 0.004619970897631026,
0.019450642967537877, 0.0173521119057514,
0.017641425439988062, 0.02270029598048491,
0.018976431925275348, 0.009299852902290885,
-0.001695039371619912, -0.00675162574265618,
-0.009380968871003034, -0.011208396125485165,
-0.01308640049201482, -0.0165636375633249,
-0.022004099870933345, -0.025173458684139286,
-0.016918759559175375, -0.00865150653575917,
-0.006999929082792643, -0.005454830010518988,
-0.0021129521131095317, 0.00018717090054046307,
-0.0002864344788569993, 0.0017615225381095569,
0.006985907557802283, 0.010577308310476465,
0.006466104789306027, -0.0014988738575948326,
-0.0039669755229277195, -0.0065156971200080235,
-0.009343206924192169, -0.0076430644693577495,
-0.004395214976600924, -0.003052735340422483,
-0.007019103043066595, -0.00974109267696527,
-0.007968015032797376, -0.007801513845528344,
-0.007535748903681969, -0.003543341967287925,
0.0015083125553729722, 0.0023345972556147025,
-0.0010043623069557037, -0.0025295765105203746,
-0.0023701840891643634, -0.0005908186035024362,
0.0029826252289082847, 0.004829048542117764,
0.004488360022902081, 0.00002643748103005408,
-0.0042100779212597295, -0.006170600558114495,
-0.007267149164680168, -0.006825522903494639,
-0.006899834372739123, -0.0073493916110062675,
-0.009554351265163382, -0.011790297433830197,
-0.010645796603734424, -0.0064661575394022106,
-0.002026743466524137, -0.0004337034584909932,
-0.0011172647031654614, -0.0017947816283674731,
-0.00255615052036616, -0.0017721562881944813,
-0.0002379619297227554, 0.0007130120121089036
};
#endif /* MPLAYER_AF_HRTF_H */
+87
View File
@@ -0,0 +1,87 @@
/*
* simple voice removal filter
*
* copyright (c) 2006 Reynaldo H. Verdejo Pinochet
* Based on code by Alex Beregszaszi for his 'center' filter.
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "af.h"
// Data for specific instances of this filter
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
switch(cmd){
case AF_CONTROL_REINIT:
mp_audio_copy_config(af->data, (struct mp_audio*)arg);
mp_audio_set_format(af->data, AF_FORMAT_FLOAT);
return af_test_output(af,(struct mp_audio*)arg);
}
return AF_UNKNOWN;
}
static int filter_frame(struct af_instance *af, struct mp_audio *c)
{
if (!c)
return 0;
if (af_make_writeable(af, c) < 0) {
talloc_free(c);
return 0;
}
float* a = c->planes[0]; // Audio data
int nch = c->nch; // Number of channels
int len = c->samples*nch; // Number of samples in current audio block
register int i;
/*
FIXME1 add a low band pass filter to avoid suppressing
centered bass/drums
FIXME2 better calculated* attenuation factor
*/
for(i=0;i<len;i+=nch)
{
a[i] = (a[i] - a[i+1]) * 0.7;
a[i+1]=a[i];
}
af_add_output_frame(af, c);
return 0;
}
// Allocate memory and set function pointers
static int af_open(struct af_instance* af){
af->control = control;
af->filter_frame = filter_frame;
return AF_OK;
}
// Description of this filter
const struct af_info af_info_karaoke = {
.info = "Simple karaoke/voice-removal audio filter",
.name = "karaoke",
.flags = AF_FLAGS_NOT_REENTRANT,
.open = af_open,
};
+852
View File
@@ -0,0 +1,852 @@
/*
* LADSPA plugin loader
*
* Written by Ivo van Poorten <ivop@euronet.nl>
* Copyright (C) 2004, 2005
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* ------------------------------------------------------------------------- */
/* Global Includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <math.h>
#include <limits.h>
#include <dlfcn.h>
#include <ladspa.h>
/* ------------------------------------------------------------------------- */
/* Local Includes */
#include "af.h"
#define _(x) (x)
/* ------------------------------------------------------------------------- */
/* Filter specific data */
typedef struct af_ladspa_s
{
int status; /**< Status of the filter.
* Either AF_OK or AF_ERROR
* Because MPlayer re-inits audio filters that
* _clearly_ returned AF_ERROR anyway, I use this
* in play() to skip the processing and return
* the data unchanged.
*/
int activated; /**< 0 or 1. Activate LADSPA filters only once, even
* if the buffers get resized, to avoid a stuttering
* filter.
*/
char *file;
char *label;
char *controls;
char *myname; /**< It's easy to have a concatenation of file and label */
void *libhandle;
const LADSPA_Descriptor *plugin_descriptor;
int nports;
int ninputs;
int *inputs;
int noutputs;
int *outputs;
int ninputcontrols;
int *inputcontrolsmap; /**< Map input port number [0-] to actual port */
float *inputcontrols;
int noutputcontrols;
int *outputcontrolsmap;
float *outputcontrols;
int nch; /**< number of channels */
int bufsize;
float **inbufs;
float **outbufs;
LADSPA_Handle *chhandles;
} af_ladspa_t;
/* ------------------------------------------------------------------------- */
static int af_open(struct af_instance *af);
static int af_ladspa_malloc_failed(char*);
/* ------------------------------------------------------------------------- */
#define OPT_BASE_STRUCT af_ladspa_t
const struct af_info af_info_ladspa = {
.info = "LADSPA plugin loader",
.name = "ladspa",
.open = af_open,
.priv_size = sizeof(af_ladspa_t),
.options = (const struct m_option[]) {
OPT_STRING("file", file, 0),
OPT_STRING("label", label, 0),
OPT_STRING("controls", controls, 0),
{0}
},
};
/* ------------------------------------------------------------------------- */
/* By lack of a better word (in my vocabulary) this is called 'parse'.
* Feel free to suggest an alternative.
*/
/** \brief Check for inputs, outputs and controls of a given filter.
*
* This function counts and checks all input, output and control ports
* of the filter that was loaded. If it turns out to be a valid
* filter for MPlayer use, it prints out a list of all controls and
* the corresponding range of its value at message level MSGL_V.
*
* \param setup Current setup of the filter. Must have its
* plugin_descriptor set!
*
* \return Returns AF_OK if it has a valid input/output/controls
* configuration. Else, it returns AF_ERROR.
*/
static int af_ladspa_parse_plugin(struct af_instance *af) {
af_ladspa_t *setup = af->priv;
int p, i;
const LADSPA_Descriptor *pdes = setup->plugin_descriptor;
LADSPA_PortDescriptor d;
LADSPA_PortRangeHint hint;
if (!setup->libhandle)
return AF_ERROR; /* only call parse after a succesful load */
if (!setup->plugin_descriptor)
return AF_ERROR; /* same as above */
/* let's do it */
setup->nports = pdes->PortCount;
/* allocate memory for all inputs/outputs/controls */
setup->inputs = calloc(setup->nports, sizeof(int));
if (!setup->inputs) return af_ladspa_malloc_failed(setup->myname);
setup->outputs = calloc(setup->nports, sizeof(int));
if (!setup->outputs) return af_ladspa_malloc_failed(setup->myname);
setup->inputcontrolsmap = calloc(setup->nports, sizeof(int));
if (!setup->inputcontrolsmap) return af_ladspa_malloc_failed(setup->myname);
setup->inputcontrols = calloc(setup->nports, sizeof(float));
if (!setup->inputcontrols) return af_ladspa_malloc_failed(setup->myname);
setup->outputcontrolsmap = calloc(setup->nports, sizeof(int));
if (!setup->outputcontrolsmap) return af_ladspa_malloc_failed(setup->myname);
setup->outputcontrols = calloc(setup->nports, sizeof(float));
if (!setup->outputcontrols) return af_ladspa_malloc_failed(setup->myname);
/* set counts to zero */
setup->ninputs = 0;
setup->noutputs = 0;
setup->ninputcontrols = 0;
setup->noutputcontrols = 0;
/* check all ports, see what type it is and set variables according to
* what we have found
*/
for (p=0; p<setup->nports; p++) {
d = pdes->PortDescriptors[p];
if (LADSPA_IS_PORT_AUDIO(d)) {
if (LADSPA_IS_PORT_INPUT(d)) {
setup->inputs[setup->ninputs] = p;
setup->ninputs++;
} else if (LADSPA_IS_PORT_OUTPUT(d)) {
setup->outputs[setup->noutputs] = p;
setup->noutputs++;
}
}
if (LADSPA_IS_PORT_CONTROL(d)) {
if (LADSPA_IS_PORT_INPUT(d)) {
setup->inputcontrolsmap[setup->ninputcontrols] = p;
setup->ninputcontrols++;
/* set control to zero. set values after reading the rest
* of the suboptions and check LADSPA_?_HINT's later.
*/
setup->inputcontrols[p] = 0.0f;
} else if (LADSPA_IS_PORT_OUTPUT(d)) {
/* read and handle these too, otherwise filters that have them
* will sig11
*/
setup->outputcontrolsmap[setup->noutputcontrols]=p;
setup->noutputcontrols++;
setup->outputcontrols[p] = 0.0f;
}
}
}
if (setup->ninputs == 0) {
MP_WARN(af, "%s: %s\n", setup->myname,
_("WARNING! This LADSPA plugin has no audio inputs.\n The incoming audio signal will be lost."));
} else if (setup->ninputs == 1) {
MP_VERBOSE(af, "%s: this is a mono effect\n", setup->myname);
} else if (setup->ninputs == 2) {
MP_VERBOSE(af, "%s: this is a stereo effect\n", setup->myname);
} else {
MP_VERBOSE(af, "%s: this is a %i-channel effect, "
"support is experimental\n", setup->myname, setup->ninputs);
}
if (setup->noutputs == 0) {
MP_ERR(af, "%s: %s\n", setup->myname,
_("This LADSPA plugin has no audio outputs."));
return AF_ERROR;
}
if (setup->noutputs != setup->ninputs ) {
MP_ERR(af, "%s: %s\n", setup->myname,
_("The number of audio inputs and audio outputs of the LADSPA plugin differ."));
return AF_ERROR;
}
MP_VERBOSE(af, "%s: this plugin has %d input control(s)\n",
setup->myname, setup->ninputcontrols);
/* Print list of controls and its range of values it accepts */
for (i=0; i<setup->ninputcontrols; i++) {
p = setup->inputcontrolsmap[i];
hint = pdes->PortRangeHints[p];
MP_VERBOSE(af, " --- %d %s [", i, pdes->PortNames[p]);
if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor)) {
MP_VERBOSE(af, "%0.2f , ", hint.LowerBound);
} else {
MP_VERBOSE(af, "... , ");
}
if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor)) {
MP_VERBOSE(af, "%0.2f]\n", hint.UpperBound);
} else {
MP_VERBOSE(af, "...]\n");
}
}
return AF_OK;
}
/* ------------------------------------------------------------------------- */
/* This function might "slightly" look like dlopenLADSPA in the LADSPA SDK :-)
* But, I changed a few things, because imho it was broken. It did not support
* relative paths, only absolute paths that start with a /
* I think ../../some/dir/foobar.so is just as valid. And if one wants to call
* his library '...somename...so' he's crazy, but it should be allowed.
* So, search the path first, try plain *filename later.
* Also, try adding .so first! I like the recursion the SDK did, but it's
* better the other way around. -af ladspa=cmt:amp_stereo:0.5 is easier to type
* than -af ladspa=cmt.so:amp_stereo:0.5 :-))
*/
/** \brief dlopen() wrapper
*
* This is a wrapper around dlopen(). It tries various variations of the
* filename (with or without the addition of the .so extension) in various
* directories specified by the LADSPA_PATH environment variable. If all fails
* it tries the filename directly as an absolute path to the library.
*
* \param filename filename of the library to load.
* \param flag see dlopen(3) for a description of the flags.
*
* \return returns a pointer to the loaded library on success, or
* NULL if it fails to load.
*/
static void* mydlopen(const char *filename, int flag) {
char *buf;
const char *end, *start, *ladspapath;
int endsinso;
size_t filenamelen;
void *result = NULL;
#if defined(__MINGW32__) || defined(__CYGWIN__)
/* For Windows there's only absolute path support.
* If you have a Windows machine, feel free to fix this.
* (path separator, shared objects extension, et cetera). */
MP_VERBOSE(af, "\ton windows, only absolute pathnames "
"are supported\n");
MP_VERBOSE(af, "\ttrying %s\n", filename);
return dlopen(filename, flag);
#endif
filenamelen = strlen(filename);
endsinso = 0;
if (filenamelen > 3)
endsinso = (strcmp(filename+filenamelen-3, ".so") == 0);
if (!endsinso) {
buf=malloc(filenamelen+4);
strcpy(buf, filename);
strcat(buf, ".so");
result=mydlopen(buf, flag);
free(buf);
}
if (result)
return result;
ladspapath=getenv("LADSPA_PATH");
if (ladspapath) {
start=ladspapath;
while (*start != '\0') {
int needslash;
end=start;
while ( (*end != ':') && (*end != '\0') )
end++;
buf=malloc(filenamelen + 2 + (end-start) );
if (end > start)
strncpy(buf, start, end-start);
needslash=0;
if (end > start)
if (*(end-1) != '/') {
needslash = 1;
buf[end-start] = '/';
}
strcpy(buf+needslash+(end-start), filename);
result=dlopen(buf, flag);
free(buf);
if (result)
return result;
start = end;
if (*start == ':')
start++;
} /* end while there's still more in the path */
} /* end if there's a ladspapath */
/* last resort, just open it again, so the dlerror() message is correct */
return dlopen(filename,flag);
}
/* ------------------------------------------------------------------------- */
/** \brief Load a LADSPA Plugin
*
* This function loads the LADSPA plugin specified by the file and label
* that are present in the setup variable. First, it loads the library.
* If it fails, it returns AF_ERROR. If not, it continues to look for the
* specified label. If it finds it, it sets the plugin_descriptor inside
* setup and returns AF_OK. If it doesn't, it returns AF_ERROR. Special case
* is a label called 'help'. In that case, it prints a list of all available
* labels (filters) in the library specified by file.
*
* \param setup Current setup of the filter. Contains filename and label.
*
* \return Either AF_ERROR or AF_OK, depending on the success of the operation.
*/
static int af_ladspa_load_plugin(struct af_instance *af) {
af_ladspa_t *setup = af->priv;
const LADSPA_Descriptor *ladspa_descriptor;
LADSPA_Descriptor_Function descriptor_function;
int i;
/* load library */
MP_VERBOSE(af, "%s: loading ladspa plugin library %s\n",
setup->myname, setup->file);
setup->libhandle = mydlopen(setup->file, RTLD_NOW);
if (!setup->libhandle) {
MP_ERR(af, "%s: %s %s\n\t%s\n", setup->myname,
_("failed to load"), setup->file, dlerror() );
return AF_ERROR;
}
MP_VERBOSE(af, "%s: library found.\n", setup->myname);
/* find descriptor function */
dlerror();
descriptor_function = (LADSPA_Descriptor_Function) dlsym (setup->libhandle,
"ladspa_descriptor");
if (!descriptor_function) {
MP_ERR(af, "%s: %s\n\t%s\n", setup->myname,
_("Couldn't find ladspa_descriptor() function in the specified library file."), dlerror());
return AF_ERROR;
}
/* if label == help, list all labels in library and exit */
if (strcmp(setup->label, "help") == 0) {
MP_INFO(af, "%s: %s %s:\n", setup->myname,
_("available labels in"), setup->file);
for (i=0; ; i++) {
ladspa_descriptor = descriptor_function(i);
if (ladspa_descriptor == NULL) {
return AF_ERROR;
}
MP_INFO(af, " %-16s - %s (%lu)\n",
ladspa_descriptor->Label,
ladspa_descriptor->Name,
ladspa_descriptor->UniqueID);
}
}
MP_VERBOSE(af, "%s: looking for label\n", setup->myname);
/* find label in library */
for (i=0; ; i++) {
ladspa_descriptor = descriptor_function(i);
if (ladspa_descriptor == NULL) {
MP_ERR(af, "%s: %s\n", setup->myname,
_("Couldn't find label in plugin library."));
return AF_ERROR;
}
if (strcmp(ladspa_descriptor->Label, setup->label) == 0) {
setup->plugin_descriptor = ladspa_descriptor;
MP_VERBOSE(af, "%s: %s found\n", setup->myname,
setup->label);
return AF_OK;
}
}
return AF_OK;
}
/* ------------------------------------------------------------------------- */
/** \brief Print a malloc() failed error message.
*
* Generic function which can be called if a call to malloc(), calloc(),
* strdup(), et cetera, failed. It prints a message to the console and
* returns AF_ERROR.
*
* \return AF_ERROR
*/
static int af_ladspa_malloc_failed(char *myname) {
return AF_ERROR;
}
/* ------------------------------------------------------------------------- */
/** \brief Controls the filter.
*
* Control the behaviour of the filter.
*
* Commands:
* CONTROL_REINIT Sets the af structure with proper values for number
* of channels, rate, format, et cetera.
* \param af Audio filter instance
* \param cmd The command to execute
* \param arg Arguments to the command
*
* \return Either AF_ERROR or AF_OK, depending on the succes of the
* operation.
*/
static int control(struct af_instance *af, int cmd, void *arg) {
af_ladspa_t *setup = (af_ladspa_t*) af->priv;
switch(cmd) {
case AF_CONTROL_REINIT:
MP_VERBOSE(af, "%s: (re)init\n", setup->myname);
if (!arg) return AF_ERROR;
/* accept FLOAT, let af_format do conversion */
mp_audio_copy_config(af->data, (struct mp_audio*)arg);
mp_audio_set_format(af->data, AF_FORMAT_FLOAT);
return af_test_output(af, (struct mp_audio*)arg);
}
return AF_UNKNOWN;
}
/* ------------------------------------------------------------------------- */
/** \brief Uninitialise the LADSPA Plugin Loader filter.
*
* This function deactivates the plugin(s), cleans up, frees all allocated
* memory and exits.
*
* \return No return value.
*/
static void uninit(struct af_instance *af) {
if (af->priv) {
af_ladspa_t *setup = (af_ladspa_t*) af->priv;
const LADSPA_Descriptor *pdes = setup->plugin_descriptor;
if (setup->myname) {
MP_VERBOSE(af, "%s: cleaning up\n", setup->myname);
free(setup->myname);
}
if (setup->chhandles) {
for (int i = 0; i < setup->nch; i+=setup->ninputs) {
if (pdes->deactivate) pdes->deactivate(setup->chhandles[i]);
if (pdes->cleanup) pdes->cleanup(setup->chhandles[i]);
}
free(setup->chhandles);
}
free(setup->inputcontrolsmap);
free(setup->inputcontrols);
free(setup->outputcontrolsmap);
free(setup->outputcontrols);
free(setup->inputs);
free(setup->outputs);
if (setup->inbufs) {
for(int i = 0; i < setup->nch; i++)
free(setup->inbufs[i]);
free(setup->inbufs);
}
if (setup->outbufs) {
for (int i = 0; i < setup->nch; i++)
free(setup->outbufs[i]);
free(setup->outbufs);
}
if (setup->libhandle)
dlclose(setup->libhandle);
}
}
/* ------------------------------------------------------------------------- */
/** \brief Process chunk of audio data through the selected LADSPA Plugin.
*
* \param af Pointer to audio filter instance
* \param data Pointer to chunk of audio data
*
* \return Either AF_ERROR or AF_OK
*/
static int filter_frame(struct af_instance *af, struct mp_audio *data)
{
if (!data)
return 0;
af_ladspa_t *setup = af->priv;
const LADSPA_Descriptor *pdes = setup->plugin_descriptor;
float *audio = (float*)data->planes[0];
int nsamples = data->samples*data->nch;
int nch = data->nch;
int rate = data->rate;
int i, p;
if (setup->status !=AF_OK) {
talloc_free(data);
return -1;
}
if (af_make_writeable(af, data) < 0) {
talloc_free(data);
return -1;
}
/* See if it's the first call. If so, setup inbufs/outbufs, instantiate
* plugin, connect ports and activate plugin
*/
if ( (setup->bufsize != nsamples/nch) || (setup->nch != nch) ) {
/* if setup->nch==0, it's the first call, if not, something has
* changed and all previous mallocs have to be freed
*/
if (setup->nch != 0) {
MP_TRACE(af, "%s: bufsize change; free old buffer\n",
setup->myname);
if(setup->inbufs) {
for(i=0; i<setup->nch; i++)
free(setup->inbufs[i]);
free(setup->inbufs);
}
if(setup->outbufs) {
for(i=0; i<setup->nch; i++)
free(setup->outbufs[i]);
free(setup->outbufs);
}
} /* everything is freed */
setup->bufsize = nsamples/nch;
setup->nch = nch;
setup->inbufs = calloc(nch, sizeof(float*));
setup->outbufs = calloc(nch, sizeof(float*));
MP_TRACE(af, "%s: bufsize = %d\n",
setup->myname, setup->bufsize);
for(i=0; i<nch; i++) {
setup->inbufs[i] = calloc(setup->bufsize, sizeof(float));
setup->outbufs[i] = calloc(setup->bufsize, sizeof(float));
}
/* only on the first call, there are no handles. */
if (!setup->chhandles) {
setup->chhandles = calloc(nch, sizeof(LADSPA_Handle));
/* create handles
* for stereo effects, create one handle for two channels
*/
for(i=0; i<nch; i++) {
if (i % setup->ninputs) { /* stereo effect */
/* copy the handle from previous channel */
setup->chhandles[i] = setup->chhandles[i-1];
continue;
}
setup->chhandles[i] = pdes->instantiate(pdes, rate);
}
}
/* connect input/output ports for each channel/filter instance
*
* always (re)connect ports
*/
for(i=0; i<nch; i++) {
pdes->connect_port(setup->chhandles[i],
setup->inputs[i % setup->ninputs],
setup->inbufs[i]);
pdes->connect_port(setup->chhandles[i],
setup->outputs[i % setup->ninputs],
setup->outbufs[i]);
/* connect (input) controls */
for (p=0; p<setup->nports; p++) {
LADSPA_PortDescriptor d = pdes->PortDescriptors[p];
if (LADSPA_IS_PORT_CONTROL(d)) {
if (LADSPA_IS_PORT_INPUT(d)) {
pdes->connect_port(setup->chhandles[i], p,
&(setup->inputcontrols[p]) );
} else {
pdes->connect_port(setup->chhandles[i], p,
&(setup->outputcontrols[p]) );
}
}
}
/* Activate filter (if it isn't already :) ) */
if (pdes->activate && !setup->activated && i % setup->ninputs == 0)
pdes->activate(setup->chhandles[i]);
} /* All channels/filters done! except for... */
setup->activated = 1;
/* Stereo effect with one channel left. Use same buffer for left
* and right. connect it to the second port.
*/
for (p = i; p % setup->ninputs; p++) {
pdes->connect_port(setup->chhandles[i-1],
setup->inputs[p % setup->ninputs],
setup->inbufs[i-1]);
pdes->connect_port(setup->chhandles[i-1],
setup->outputs[p % setup->ninputs],
setup->outbufs[i-1]);
} /* done! */
} /* setup for first call/change of bufsize is done.
* normal playing routine follows...
*/
/* Right now, I use a separate input and output buffer.
* I could change this to in-place processing (inbuf==outbuf), but some
* ladspa filters are broken and are not able to handle that. This seems
* fast enough, so unless somebody complains, it stays this way :)
*/
/* Fill inbufs */
for (p=0; p<setup->bufsize; p++) {
for (i=0; i<nch; i++) {
setup->inbufs[i][p] = audio[p*nch + i];
}
}
/* Run filter(s) */
for (i=0; i<nch; i+=setup->ninputs) {
pdes->run(setup->chhandles[i], setup->bufsize);
}
/* Extract outbufs */
for (p=0; p<setup->bufsize; p++) {
for (i=0; i<nch; i++) {
audio[p*nch + i] = setup->outbufs[i][p];
}
}
/* done */
af_add_output_frame(af, data);
return 0;
}
/* ------------------------------------------------------------------------- */
/** \brief Open LADSPA Plugin Loader Filter
*
* \param af Audio Filter instance
*
* \return Either AF_ERROR or AF_OK
*/
static int af_open(struct af_instance *af) {
af->control=control;
af->uninit=uninit;
af->filter_frame = filter_frame;
af_ladspa_t *setup = af->priv;
setup->status = AF_ERROR; /* will be set to AF_OK if
* all went OK and filter()
* should proceed.
*/
setup->myname = strdup(af_info_ladspa.name);
if (!setup->myname)
return af_ladspa_malloc_failed((char*)af_info_ladspa.name);
if (!setup->file || !setup->file[0]) {
MP_ERR(af, "%s: %s\n", setup->myname,
_("No library file specified."));
uninit(af);
return AF_ERROR;
}
if (!setup->label || !setup->label[0]) {
MP_ERR(af, "%s: %s\n", setup->myname,
_("No filter label specified."));
uninit(af);
return AF_ERROR;
}
free(setup->myname);
setup->myname = calloc(strlen(af_info_ladspa.name)+strlen(setup->file)+
strlen(setup->label)+6, 1);
snprintf(setup->myname, strlen(af_info_ladspa.name)+
strlen(setup->file)+strlen(setup->label)+6, "%s: (%s:%s)",
af_info_ladspa.name, setup->file, setup->label);
/* load plugin :) */
if ( af_ladspa_load_plugin(af) != AF_OK )
return AF_ERROR;
/* see what inputs, outputs and controls this plugin has */
if ( af_ladspa_parse_plugin(af) != AF_OK )
return AF_ERROR;
/* ninputcontrols is set by now, read control values from arg */
float val;
char *line = setup->controls;
for (int i = 0; i < setup->ninputcontrols; i++) {
if (!line || (i != 0 && *line != ',')) {
MP_ERR(af, "%s: %s\n", setup->myname,
_("Not enough controls specified on the command line."));
return AF_ERROR;
}
if (i != 0)
line++;
if (sscanf(line, "%f", &val) != 1) {
MP_ERR(af, "%s: %s\n", setup->myname,
_("Not enough controls specified on the command line."));
return AF_ERROR;
}
setup->inputcontrols[setup->inputcontrolsmap[i]] = val;
line = strchr(line, ',');
}
MP_VERBOSE(af, "%s: input controls: ", setup->myname);
for (int i = 0; i < setup->ninputcontrols; i++) {
MP_VERBOSE(af, "%0.4f ",
setup->inputcontrols[setup->inputcontrolsmap[i]]);
}
MP_VERBOSE(af, "\n");
/* check boundaries of inputcontrols */
MP_VERBOSE(af, "%s: checking boundaries of input controls\n",
setup->myname);
for (int i = 0; i < setup->ninputcontrols; i++) {
int p = setup->inputcontrolsmap[i];
LADSPA_PortRangeHint hint =
setup->plugin_descriptor->PortRangeHints[p];
val = setup->inputcontrols[p];
if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor) &&
val < hint.LowerBound) {
MP_ERR(af, "%s: Input control #%d is below lower boundary of %0.4f.\n",
setup->myname, i, hint.LowerBound);
return AF_ERROR;
}
if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor) &&
val > hint.UpperBound) {
MP_ERR(af, "%s: Input control #%d is above upper boundary of %0.4f.\n",
setup->myname, i, hint.UpperBound);
return AF_ERROR;
}
}
MP_VERBOSE(af, "%s: all controls have sane values\n",
setup->myname);
/* All is well! */
setup->status = AF_OK;
return AF_OK;
}
/* ------------------------------------------------------------------------- */
+10 -22
View File
@@ -3,20 +3,21 @@
*
* Copyright (C) 2007 Ulion <ulion A gmail P com>
*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
@@ -26,6 +27,7 @@
#include <assert.h>
#include <libavcodec/avcodec.h>
#include <libavutil/audioconvert.h>
#include <libavutil/intreadwrite.h>
#include <libavutil/common.h>
#include <libavutil/bswap.h>
@@ -74,7 +76,7 @@ static int control(struct af_instance *af, int cmd, void *arg)
struct mp_audio *in = arg;
struct mp_audio orig_in = *in;
if (!af_fmt_is_pcm(in->format) || in->nch < s->cfg_min_channel_num)
if (AF_FORMAT_IS_SPECIAL(in->format) || in->nch < s->cfg_min_channel_num)
return AF_DETACH;
mp_audio_set_format(in, s->in_sampleformat);
@@ -155,13 +157,6 @@ static void uninit(struct af_instance* af)
}
}
static void update_delay(struct af_instance *af)
{
af_ac3enc_t *s = af->priv;
af->delay = ((s->pending ? s->pending->samples : 0) + s->input->samples) /
(double)s->input->rate;
}
static int filter_frame(struct af_instance *af, struct mp_audio *audio)
{
af_ac3enc_t *s = af->priv;
@@ -172,7 +167,6 @@ static int filter_frame(struct af_instance *af, struct mp_audio *audio)
talloc_free(s->pending);
s->pending = audio;
update_delay(af);
return 0;
}
@@ -184,27 +178,22 @@ static void swap_16(uint16_t *ptr, size_t size)
// Copy data from input frame to encode frame (because libavcodec wants a full
// AC3 frame for encoding, while filter input frames can be smaller or larger).
// Return true if the frame is complete.
static bool fill_buffer(struct af_instance *af)
// Return true if the
static bool fill_buffer(af_ac3enc_t *s)
{
af_ac3enc_t *s = af->priv;
af->delay = 0;
if (s->pending) {
int copy = MPMIN(s->in_samples - s->input->samples, s->pending->samples);
s->input->samples += copy;
mp_audio_copy(s->input, s->input->samples - copy, s->pending, 0, copy);
mp_audio_skip_samples(s->pending, copy);
}
update_delay(af);
return s->input->samples >= s->in_samples;
}
static int filter_out(struct af_instance *af)
{
af_ac3enc_t *s = af->priv;
if (!fill_buffer(af))
if (!fill_buffer(s))
return 0; // need more input
AVFrame *frame = av_frame_alloc();
@@ -268,7 +257,6 @@ static int filter_out(struct af_instance *af)
swap_16((uint16_t *)(buf + header_len), s->pkt.size / 2);
out->samples = frame_size / out->sstride;
af_add_output_frame(af, out);
update_delay(af);
return 0;
}
+1 -50
View File
@@ -34,14 +34,11 @@
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include "config.h"
#include "audio/format.h"
#include "audio/fmt-conversion.h"
#include "af.h"
#include "common/av_common.h"
#include "common/tags.h"
#include "options/m_option.h"
@@ -64,10 +61,6 @@ struct priv {
AVRational timebase_out;
bool eof;
struct mp_tags *metadata;
// options
char *cfg_graph;
char **cfg_avopts;
@@ -78,8 +71,6 @@ static void destroy_graph(struct af_instance *af)
struct priv *p = af->priv;
avfilter_graph_free(&p->graph);
p->in = p->out = NULL;
p->samples_in = 0;
p->eof = false;
}
static bool recreate_graph(struct af_instance *af, struct mp_audio *config)
@@ -176,12 +167,6 @@ error:
return false;
}
static void reset(struct af_instance *af)
{
if (!recreate_graph(af, &af->fmt_in))
MP_FATAL(af, "Can't recreate libavfilter filter after a seek reset.\n");
}
static int control(struct af_instance *af, int cmd, void *arg)
{
struct priv *p = af->priv;
@@ -218,43 +203,16 @@ static int control(struct af_instance *af, int cmd, void *arg)
return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE;
}
case AF_CONTROL_GET_METADATA:
if (p->metadata) {
*(struct mp_tags *)arg = *p->metadata;
return CONTROL_OK;
}
return CONTROL_NA;
case AF_CONTROL_RESET:
reset(af);
return AF_OK;
}
return AF_UNKNOWN;
}
static void get_metadata_from_av_frame(struct af_instance *af, AVFrame *frame)
{
#if HAVE_AVFRAME_METADATA
struct priv *p = af->priv;
if (!p->metadata)
p->metadata = talloc_zero(p, struct mp_tags);
mp_tags_copy_from_av_dictionary(p->metadata, av_frame_get_metadata(frame));
#endif
}
static int filter_frame(struct af_instance *af, struct mp_audio *data)
{
struct priv *p = af->priv;
AVFrame *frame = NULL;
if (p->eof && data)
reset(af);
if (!p->graph)
goto error;
AVFilterLink *l_in = p->in->outputs[0];
AVFrame *frame = NULL;
if (data) {
frame = av_frame_alloc();
if (!frame)
@@ -297,9 +255,6 @@ static int filter_out(struct af_instance *af)
{
struct priv *p = af->priv;
if (!p->graph)
goto error;
AVFrame *frame = av_frame_alloc();
if (!frame)
goto error;
@@ -307,10 +262,7 @@ static int filter_out(struct af_instance *af)
int err = av_buffersink_get_frame(p->out, frame);
if (err == AVERROR(EAGAIN) || err == AVERROR_EOF) {
// Not an error situation - no more output buffers in queue.
// AVERROR_EOF means we shouldn't even give the filter more
// input, but we don't handle that completely correctly.
av_frame_free(&frame);
p->eof |= err == AVERROR_EOF;
return 0;
}
@@ -329,7 +281,6 @@ static int filter_out(struct af_instance *af)
af->delay = in_time - out_time;
}
get_metadata_from_av_frame(af, frame);
af_add_output_frame(af, out);
av_frame_free(&frame);
return 0;
+148 -284
View File
@@ -2,38 +2,37 @@
* Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
* Copyright (c) 2013 Stefano Pigozzi <stefano.pigozzi@gmail.com>
*
* This file is part of mpv.
* Based on Michael Niedermayer's lavcresample.
*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <math.h>
#include <assert.h>
#include <libavutil/opt.h>
#include <libavutil/audioconvert.h>
#include <libavutil/common.h>
#include <libavutil/samplefmt.h>
#include <libavutil/channel_layout.h>
#include <libavutil/mathematics.h>
#include "common/common.h"
#include "talloc.h"
#include "config.h"
#if HAVE_LIBAVRESAMPLE
@@ -58,33 +57,14 @@
#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;
};
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_rate;
int in_format;
struct mp_chmap in_channels;
int out_rate;
@@ -92,151 +72,100 @@ struct af_resample {
struct mp_chmap out_channels;
};
struct af_resample {
int allow_detach;
char **avopts;
struct AVAudioResampleContext *avrctx;
struct AVAudioResampleContext *avrctx_out; // for output channel reordering
struct af_resample_opts ctx; // opts in the context
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;
};
#if HAVE_LIBAVRESAMPLE
static double get_delay(struct af_resample *s)
static int get_delay(struct af_resample *s)
{
return avresample_get_delay(s->avrctx) / (double)s->in_rate +
avresample_available(s->avrctx) / (double)s->out_rate;
return avresample_get_delay(s->avrctx);
}
static void drop_all_output(struct af_resample *s)
{
while (avresample_read(s->avrctx, NULL, 1000) > 0) {}
}
static int get_out_samples(struct af_resample *s, int in_samples)
{
return avresample_get_out_samples(s->avrctx, in_samples);
}
#else
static double get_delay(struct af_resample *s)
static int 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;
return swr_get_delay(s->avrctx, s->ctx.in_rate);
}
static void drop_all_output(struct af_resample *s)
{
while (swr_drop_output(s->avrctx, 1000) > 0) {}
}
static int get_out_samples(struct af_resample *s, int in_samples)
{
#if LIBSWRESAMPLE_VERSION_MAJOR > 1 || LIBSWRESAMPLE_VERSION_MINOR >= 2
return swr_get_out_samples(s->avrctx, in_samples);
#else
return av_rescale_rnd(in_samples, s->out_rate, s->in_rate, AV_ROUND_UP)
+ swr_get_delay(s->avrctx, s->out_rate);
#endif
}
#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)
static bool needs_lavrctx_reconfigure(struct af_resample *s,
struct mp_audio *in,
struct mp_audio *out)
{
return lrint(rate * speed);
return s->ctx.in_rate != in->rate ||
s->ctx.in_format != in->format ||
!mp_chmap_equals(&s->ctx.in_channels, &in->channels) ||
s->ctx.out_rate != out->rate ||
s->ctx.out_format != out->format ||
!mp_chmap_equals(&s->ctx.out_channels, &out->channels) ||
s->ctx.filter_size != s->opts.filter_size ||
s->ctx.phase_shift != s->opts.phase_shift ||
s->ctx.linear != s->opts.linear ||
s->ctx.cutoff != s->opts.cutoff;
}
// Return the format libavresample should convert to, given the final output
// format mp_format. In some cases (S24) we perform an extra conversion step,
// and signal here what exactly libavresample should output. It will be the
// input to the final conversion to mp_format.
static int check_output_conversion(int mp_format)
{
if (mp_format == AF_FORMAT_S24)
return AV_SAMPLE_FMT_S32;
return af_to_avformat(mp_format);
}
bool af_lavrresample_test_conversion(int src_format, int dst_format)
static bool test_conversion(int src_format, int dst_format)
{
return af_to_avformat(src_format) != AV_SAMPLE_FMT_NONE &&
check_output_conversion(dst_format) != AV_SAMPLE_FMT_NONE;
}
// 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));
af_to_avformat(dst_format) != AV_SAMPLE_FMT_NONE;
}
static int configure_lavrr(struct af_instance *af, struct mp_audio *in,
struct mp_audio *out, bool verbose)
struct mp_audio *out)
{
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 = check_output_conversion(out->format);
enum AVSampleFormat out_samplefmtp = av_get_planar_sample_fmt(out_samplefmt);
enum AVSampleFormat out_samplefmt = af_to_avformat(out->format);
if (in_samplefmt == AV_SAMPLE_FMT_NONE ||
out_samplefmt == AV_SAMPLE_FMT_NONE ||
out_samplefmtp == AV_SAMPLE_FMT_NONE)
goto error;
if (in_samplefmt == AV_SAMPLE_FMT_NONE || out_samplefmt == AV_SAMPLE_FMT_NONE)
return AF_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;
avresample_close(s->avrctx);
avresample_close(s->avrctx_out);
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);
s->ctx.out_rate = out->rate;
s->ctx.in_rate = in->rate;
s->ctx.out_format = out->format;
s->ctx.in_format = in->format;
s->ctx.out_channels= out->channels;
s->ctx.in_channels = in->channels;
s->ctx.filter_size = s->opts.filter_size;
s->ctx.phase_shift = s->opts.phase_shift;
s->ctx.linear = s->opts.linear;
s->ctx.cutoff = s->opts.cutoff;
av_opt_set_double(s->avrctx, "cutoff", s->opts.cutoff, 0);
av_opt_set_int(s->avrctx, "filter_size", s->ctx.filter_size, 0);
av_opt_set_int(s->avrctx, "phase_shift", s->ctx.phase_shift, 0);
av_opt_set_int(s->avrctx, "linear_interp", s->ctx.linear, 0);
#if HAVE_LIBSWRESAMPLE
av_opt_set_double(s->avrctx, "rematrix_maxval", s->opts.normalize ? 1 : 1000, 0);
#else
av_opt_set_int(s->avrctx, "normalize_mix_level", s->opts.normalize, 0);
#endif
av_opt_set_double(s->avrctx, "cutoff", s->ctx.cutoff, 0);
if (mp_set_avopts(af->log, s->avrctx, s->avopts) < 0)
goto error;
return AF_ERROR;
struct mp_chmap map_in = in->channels;
struct mp_chmap map_out = out->channels;
@@ -251,103 +180,61 @@ static int configure_lavrr(struct af_instance *af, struct mp_audio *in,
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;
mp_audio_set_format(&s->pre_out_fmt, af_from_avformat(out_samplefmt));
// 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);
// 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_rate", s->ctx.in_rate, 0);
av_opt_set_int(s->avrctx, "out_sample_rate", s->ctx.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);
av_opt_set_int(s->avrctx, "out_sample_fmt", out_samplefmt, 0);
// Just needs the correct number of channels.
int fake_out_ch_layout = av_get_default_channel_layout(map_out.num);
if (!fake_out_ch_layout)
goto error;
struct mp_chmap in_lavc;
mp_chmap_from_lavc(&in_lavc, in_ch_layout);
mp_chmap_get_reorder(s->reorder_in, &map_in, &in_lavc);
// Deplanarize if needed.
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);
struct mp_chmap out_lavc;
mp_chmap_from_lavc(&out_lavc, out_ch_layout);
mp_chmap_get_reorder(s->reorder_out, &out_lavc, &map_out);
// Same configuration; we just reorder.
av_opt_set_int(s->avrctx_out, "in_channel_layout", out_ch_layout, 0);
av_opt_set_int(s->avrctx_out, "out_channel_layout", out_ch_layout, 0);
av_opt_set_int(s->avrctx_out, "in_sample_fmt", out_samplefmt, 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);
av_opt_set_int(s->avrctx_out, "in_sample_rate", s->ctx.out_rate, 0);
av_opt_set_int(s->avrctx_out, "out_sample_rate", s->ctx.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);
avresample_set_channel_mapping(s->avrctx_out, s->reorder_out);
if (avresample_open(s->avrctx) < 0 || avresample_open(s->avrctx_out) < 0) {
if (avresample_open(s->avrctx) < 0 ||
avresample_open(s->avrctx_out) < 0)
{
MP_ERR(af, "Cannot open Libavresample Context. \n");
goto error;
return AF_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;
struct af_resample *s = (struct af_resample *) af->priv;
struct mp_audio *in = (struct mp_audio *) arg;
struct mp_audio *out = (struct mp_audio *) af->data;
switch (cmd) {
case AF_CONTROL_REINIT: {
struct mp_audio *in = arg;
struct mp_audio *out = af->data;
struct mp_audio orig_in = *in;
if (((out->rate == in->rate) || (out->rate == 0)) &&
(out->format == in->format) &&
(mp_chmap_equals(&out->channels, &in->channels) || out->nch == 0) &&
s->allow_detach && s->playback_speed == 1.0)
s->allow_detach)
return AF_DETACH;
if (out->rate == 0)
@@ -358,23 +245,22 @@ static int control(struct af_instance *af, int cmd, void *arg)
if (af_to_avformat(in->format) == AV_SAMPLE_FMT_NONE)
mp_audio_set_format(in, AF_FORMAT_FLOAT);
if (check_output_conversion(out->format) == AV_SAMPLE_FMT_NONE)
if (af_to_avformat(out->format) == AV_SAMPLE_FMT_NONE)
mp_audio_set_format(out, in->format);
int r = ((in->format == orig_in.format) &&
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 && needs_lavrctx_reconfigure(s, in, out))
r = configure_lavrr(af, in, out);
return r;
}
case AF_CONTROL_SET_FORMAT: {
int format = *(int *)arg;
if (format && check_output_conversion(format) == AV_SAMPLE_FMT_NONE)
if (af_to_avformat(*(int*)arg) == AV_SAMPLE_FMT_NONE)
return AF_FALSE;
mp_audio_set_format(af->data, format);
mp_audio_set_format(af->data, *(int*)arg);
return AF_OK;
}
case AF_CONTROL_SET_CHANNELS: {
@@ -382,94 +268,75 @@ static int control(struct af_instance *af, int cmd, void *arg)
return AF_OK;
}
case AF_CONTROL_SET_RESAMPLE_RATE:
af->data->rate = *(int *)arg;
out->rate = *(int *)arg;
return AF_OK;
case AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE: {
s->playback_speed = *(double *)arg;
int new_rate = rate_from_speed(s->in_rate_af, s->playback_speed);
if (new_rate != s->in_rate && s->avrctx && af->fmt_out.format) {
// Before reconfiguring, drain the audio that is still buffered
// in the resampler.
af->filter_frame(af, NULL);
// Reinitialize resampler.
configure_lavrr(af, &af->fmt_in, &af->fmt_out, false);
}
return AF_OK;
}
case AF_CONTROL_RESET:
if (s->avrctx)
drop_all_output(s);
drop_all_output(s);
return AF_OK;
}
return AF_UNKNOWN;
}
#undef ctx_opt_set_int
#undef ctx_opt_set_dbl
static void uninit(struct af_instance *af)
{
close_lavrr(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);
}
// 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)
static bool needs_reorder(int *reorder, int num_ch)
{
if (mpa->format == AF_FORMAT_S32 && af->data->format == AF_FORMAT_S24) {
size_t len = mp_audio_psize(mpa) / mpa->bps;
for (int s = 0; s < len; s++) {
uint32_t val = *((uint32_t *)mpa->planes[0] + s);
uint8_t *ptr = (uint8_t *)mpa->planes[0] + s * 3;
ptr[0] = val >> SHIFT24(0);
ptr[1] = val >> SHIFT24(1);
ptr[2] = val >> SHIFT24(2);
}
mp_audio_set_format(mpa, AF_FORMAT_S24);
for (int n = 0; n < num_ch; n++) {
if (reorder[n] != n)
return true;
}
return false;
}
// This relies on the tricky way mpa was allocated.
static void reorder_planes(struct mp_audio *mpa, int *reorder,
struct mp_chmap *newmap)
static void reorder_planes(struct mp_audio *mpa, int *reorder)
{
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);
}
assert(reorder[n] >= 0 && reorder[n] < mpa->num_planes);
mpa->planes[n] = prev.planes[reorder[n]];
}
}
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 int filter(struct af_instance *af, struct mp_audio *in)
{
struct af_resample *s = af->priv;
int samples = get_out_samples(s, in ? in->samples : 0);
struct mp_audio out_format = s->pool_fmt;
struct mp_audio *out = mp_audio_pool_get(af->out_pool, &out_format, samples);
int samples = avresample_available(s->avrctx) +
av_rescale_rnd(get_delay(s) + (in ? in->samples : 0),
s->ctx.out_rate, s->ctx.in_rate, AV_ROUND_UP);
struct mp_audio *out = mp_audio_pool_get(af->out_pool, af->data, samples);
if (!out)
goto error;
if (in)
mp_audio_copy_attributes(out, in);
if (!s->avrctx)
goto error;
mp_audio_realloc_min(out, out->samples);
af->delay = get_delay(s) / (double)s->ctx.in_rate;
if (out->samples) {
out->samples = resample_frame(s->avrctx, out, in);
@@ -477,15 +344,11 @@ static int filter(struct af_instance *af, struct mp_audio *in)
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,
if (needs_reorder(s->reorder_out, out->nch)) {
if (af_fmt_is_planar(out->format)) {
reorder_planes(out, s->reorder_out);
} else if (out->samples) {
struct mp_audio *new = mp_audio_pool_get(s->reorder_buffer, out,
out->samples);
if (!new)
goto error;
@@ -498,17 +361,12 @@ static int filter(struct af_instance *af, struct mp_audio *in)
}
}
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);
@@ -527,9 +385,17 @@ static int af_open(struct af_instance *af)
if (s->opts.cutoff <= 0.0)
s->opts.cutoff = af_resample_default_cutoff(s->opts.filter_size);
s->avrctx = avresample_alloc_context();
s->avrctx_out = avresample_alloc_context();
s->reorder_buffer = mp_audio_pool_create(s);
return AF_OK;
if (s->avrctx && s->avrctx_out) {
return AF_OK;
} else {
MP_ERR(af, "Cannot initialize Libavresample Context. \n");
uninit(af);
return AF_ERROR;
}
}
#define OPT_BASE_STRUCT struct af_resample
@@ -538,15 +404,14 @@ const struct af_info af_info_lavrresample = {
.info = "Sample frequency conversion using libavresample",
.name = "lavrresample",
.open = af_open,
.test_conversion = test_conversion,
.priv_size = sizeof(struct af_resample),
.priv_defaults = &(const struct af_resample) {
.opts = {
.filter_size = 16,
.cutoff = 0.0,
.phase_shift = 10,
.normalize = 1,
},
.playback_speed = 1.0,
.allow_detach = 1,
},
.options = (const struct m_option[]) {
@@ -555,7 +420,6 @@ const struct af_info af_info_lavrresample = {
OPT_FLAG("linear", opts.linear, 0),
OPT_DOUBLE("cutoff", opts.cutoff, M_OPT_RANGE, .min = 0, .max = 1),
OPT_FLAG("detach", allow_detach, 0),
OPT_FLAG("normalize", opts.normalize, 0),
OPT_KEYVALUELIST("o", avopts, 0),
{0}
},
+5 -4
View File
@@ -1,20 +1,21 @@
/*
* Copyright (C) 2002 Anders Johansson ajh@atri.curtin.edu.au
*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
-225
View File
@@ -1,225 +0,0 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <assert.h>
#include <rubberband/rubberband-c.h>
#include "common/common.h"
#include "af.h"
struct priv {
RubberBandState rubber;
double speed;
struct mp_audio *pending;
bool needs_reset;
// Estimate how much librubberband has buffered internally.
// I could not find a way to do this with the librubberband API.
double rubber_delay;
// command line options
int opt_transients, opt_detector, opt_phase, opt_window,
opt_smoothing, opt_formant, opt_pitch, opt_channels;
};
static void update_speed(struct af_instance *af, double new_speed)
{
struct priv *p = af->priv;
p->speed = new_speed;
rubberband_set_time_ratio(p->rubber, 1.0 / p->speed);
}
static int control(struct af_instance *af, int cmd, void *arg)
{
struct priv *p = af->priv;
switch (cmd) {
case AF_CONTROL_REINIT: {
struct mp_audio *in = arg;
struct mp_audio orig_in = *in;
struct mp_audio *out = af->data;
in->format = AF_FORMAT_FLOATP;
mp_audio_copy_config(out, in);
if (p->rubber)
rubberband_delete(p->rubber);
int opts = p->opt_transients | p->opt_detector | p->opt_phase |
p->opt_window | p->opt_smoothing | p->opt_formant |
p->opt_pitch | p-> opt_channels |
RubberBandOptionProcessRealTime;
p->rubber = rubberband_new(in->rate, in->channels.num, opts, 1.0, 1.0);
if (!p->rubber) {
MP_FATAL(af, "librubberband initialization failed.\n");
return AF_ERROR;
}
update_speed(af, p->speed);
control(af, AF_CONTROL_RESET, NULL);
return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE;
}
case AF_CONTROL_SET_PLAYBACK_SPEED: {
update_speed(af, *(double *)arg);
return AF_OK;
}
case AF_CONTROL_RESET:
if (p->rubber)
rubberband_reset(p->rubber);
talloc_free(p->pending);
p->pending = NULL;
p->rubber_delay = 0;
return AF_OK;
}
return AF_UNKNOWN;
}
static int filter_frame(struct af_instance *af, struct mp_audio *data)
{
struct priv *p = af->priv;
talloc_free(p->pending);
p->pending = data;
return 0;
}
static int filter_out(struct af_instance *af)
{
struct priv *p = af->priv;
while (rubberband_available(p->rubber) <= 0) {
const float *dummy[MP_NUM_CHANNELS] = {0};
const float **in_data = dummy;
size_t in_samples = 0;
if (p->pending) {
if (!p->pending->samples)
break;
// recover from previous EOF
if (p->needs_reset) {
rubberband_reset(p->rubber);
p->rubber_delay = 0;
}
p->needs_reset = false;
size_t needs = rubberband_get_samples_required(p->rubber);
in_data = (void *)&p->pending->planes;
in_samples = MPMIN(p->pending->samples, needs);
}
if (p->needs_reset)
break; // previous EOF
p->needs_reset = !p->pending; // EOF
rubberband_process(p->rubber, in_data, in_samples, p->needs_reset);
p->rubber_delay += in_samples;
if (!p->pending)
break;
mp_audio_skip_samples(p->pending, in_samples);
}
int out_samples = rubberband_available(p->rubber);
if (out_samples > 0) {
struct mp_audio *out =
mp_audio_pool_get(af->out_pool, af->data, out_samples);
if (!out)
return -1;
if (p->pending)
mp_audio_copy_config(out, p->pending);
float **out_data = (void *)&out->planes;
out->samples = rubberband_retrieve(p->rubber, out_data, out->samples);
p->rubber_delay -= out->samples * p->speed;
af_add_output_frame(af, out);
}
int delay_samples = p->rubber_delay;
if (p->pending)
delay_samples += p->pending->samples;
af->delay = delay_samples / (af->data->rate * p->speed);
return 0;
}
static void uninit(struct af_instance *af)
{
struct priv *p = af->priv;
if (p->rubber)
rubberband_delete(p->rubber);
talloc_free(p->pending);
}
static int af_open(struct af_instance *af)
{
af->control = control;
af->filter_frame = filter_frame;
af->filter_out = filter_out;
af->uninit = uninit;
return AF_OK;
}
#define OPT_BASE_STRUCT struct priv
const struct af_info af_info_rubberband = {
.info = "Pitch conversion with librubberband",
.name = "rubberband",
.open = af_open,
.priv_size = sizeof(struct priv),
.priv_defaults = &(const struct priv) {
.speed = 1.0,
.opt_pitch = RubberBandOptionPitchHighConsistency,
.opt_transients = RubberBandOptionTransientsMixed,
.opt_formant = RubberBandOptionFormantPreserved,
},
.options = (const struct m_option[]) {
OPT_CHOICE("transients", opt_transients, 0,
({"crisp", RubberBandOptionTransientsCrisp},
{"mixed", RubberBandOptionTransientsMixed},
{"smooth", RubberBandOptionTransientsSmooth})),
OPT_CHOICE("detector", opt_detector, 0,
({"compound", RubberBandOptionDetectorCompound},
{"percussive", RubberBandOptionDetectorPercussive},
{"soft", RubberBandOptionDetectorSoft})),
OPT_CHOICE("phase", opt_phase, 0,
({"laminar", RubberBandOptionPhaseLaminar},
{"independent", RubberBandOptionPhaseIndependent})),
OPT_CHOICE("window", opt_window, 0,
({"standard", RubberBandOptionWindowStandard},
{"short", RubberBandOptionWindowShort},
{"long", RubberBandOptionWindowLong})),
OPT_CHOICE("smoothing", opt_smoothing, 0,
({"off", RubberBandOptionSmoothingOff},
{"on", RubberBandOptionSmoothingOn})),
OPT_CHOICE("formant", opt_formant, 0,
({"shifted", RubberBandOptionFormantShifted},
{"preserved", RubberBandOptionFormantPreserved})),
OPT_CHOICE("pitch", opt_pitch, 0,
({"quality", RubberBandOptionPitchHighQuality},
{"speed", RubberBandOptionPitchHighSpeed},
{"consistency", RubberBandOptionPitchHighConsistency})),
OPT_CHOICE("channels", opt_channels, 0,
({"apart", RubberBandOptionChannelsApart},
{"together", RubberBandOptionChannelsTogether})),
{0}
},
};
+39 -31
View File
@@ -14,20 +14,21 @@
*
* Copyright (c) 2007 Robert Juliano
*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdlib.h>
@@ -75,9 +76,9 @@ typedef struct af_scaletempo_s
float ms_stride;
float percent_overlap;
float ms_search;
#define SCALE_TEMPO 1
#define SCALE_PITCH 2
int speed_opt;
short speed_tempo;
short speed_pitch;
} af_scaletempo_t;
static int fill_queue(struct af_instance *af, struct mp_audio *data, int offset)
@@ -275,22 +276,6 @@ static int filter(struct af_instance *af, struct mp_audio *data)
return 0;
}
static void update_speed(struct af_instance *af, float speed)
{
af_scaletempo_t *s = af->priv;
s->speed = speed;
double factor = (s->speed_opt & SCALE_PITCH) ? 1.0 / s->speed : s->speed;
s->scale = factor * s->scale_nominal;
s->frames_stride_scaled = s->scale * s->frames_stride;
s->frames_stride_error = MPMIN(s->frames_stride_error, s->frames_stride_scaled);
MP_VERBOSE(af, "%.3f speed * %.3f scale_nominal = %.3f\n",
s->speed, s->scale_nominal, s->scale);
}
// Initialization and runtime control
static int control(struct af_instance *af, int cmd, void *arg)
{
@@ -302,9 +287,19 @@ static int control(struct af_instance *af, int cmd, void *arg)
int nch = data->nch;
int use_int = 0;
MP_VERBOSE(af, "%.3f speed * %.3f scale_nominal = %.3f\n",
s->speed, s->scale_nominal, s->scale);
mp_audio_force_interleaved_format(data);
mp_audio_copy_config(af->data, data);
if (s->scale == 1.0) {
if (s->speed_tempo && s->speed_pitch)
return AF_DETACH;
af->delay = 0;
return af_test_output(af, data);
}
if (data->format == AF_FORMAT_S16) {
use_int = 1;
} else {
@@ -314,10 +309,10 @@ static int control(struct af_instance *af, int cmd, void *arg)
s->frames_stride = srate * s->ms_stride;
s->bytes_stride = s->frames_stride * bps * nch;
s->frames_stride_scaled = s->scale * s->frames_stride;
s->frames_stride_error = 0;
af->delay = 0;
update_speed(af, s->speed);
int frames_overlap = s->frames_stride * s->percent_overlap;
if (frames_overlap <= 0) {
s->bytes_standing = s->bytes_stride;
@@ -427,14 +422,17 @@ static int control(struct af_instance *af, int cmd, void *arg)
return af_test_output(af, (struct mp_audio *)arg);
}
case AF_CONTROL_SET_PLAYBACK_SPEED: {
double speed = *(double *)arg;
if (s->speed_opt & SCALE_TEMPO) {
if (s->speed_opt & SCALE_PITCH)
if (s->speed_tempo) {
if (s->speed_pitch)
break;
update_speed(af, speed);
} else if (s->speed_opt & SCALE_PITCH) {
update_speed(af, speed);
break; // do not signal OK
s->speed = *(double *)arg;
s->scale = s->speed * s->scale_nominal;
} else {
if (s->speed_pitch) {
s->speed = 1 / *(double *)arg;
s->scale = s->speed * s->scale_nominal;
break;
}
}
return AF_OK;
}
@@ -458,12 +456,22 @@ static void uninit(struct af_instance *af)
free(s->table_window);
}
#define SCALE_TEMPO 1
#define SCALE_PITCH 2
// Allocate memory and set function pointers
static int af_open(struct af_instance *af)
{
af_scaletempo_t *s = af->priv;
af->control = control;
af->uninit = uninit;
af->filter_frame = filter;
s->speed_tempo = !!(s->speed_opt & SCALE_TEMPO);
s->speed_pitch = !!(s->speed_opt & SCALE_PITCH);
s->scale = s->speed * s->scale_nominal;
return AF_OK;
}
+118
View File
@@ -0,0 +1,118 @@
/*
* Copyright (C) 2006 Michael Niedermayer
* Copyright (C) 2004 Alex Beregszaszi
* based upon af_extrastereo.c by Pierre Lombard
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <math.h>
#include <limits.h>
#include "af.h"
// Data for specific instances of this filter
typedef struct af_sinesuppress_s
{
double freq;
double decay;
double real;
double imag;
double ref;
double pos;
}af_sinesuppress_t;
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
switch(cmd){
case AF_CONTROL_REINIT:{
// Sanity check
if(!arg) return AF_ERROR;
mp_audio_copy_config(af->data, (struct mp_audio*)arg);
mp_audio_set_num_channels(af->data, 1);
mp_audio_set_format(af->data, AF_FORMAT_S16);
return af_test_output(af,(struct mp_audio*)arg);
}
}
return AF_UNKNOWN;
}
static int play_s16(struct af_instance *af, struct mp_audio *data)
{
if (!data)
return 0;
if (af_make_writeable(af, data) < 0) {
talloc_free(data);
return -1;
}
af_sinesuppress_t *s = af->priv;
register int i = 0;
int16_t *a = (int16_t*)data->planes[0]; // Audio data
int len = data->samples*data->nch; // Number of samples
for (i = 0; i < len; i++)
{
double co= cos(s->pos);
double si= sin(s->pos);
s->real += co * a[i];
s->imag += si * a[i];
s->ref += co * co;
a[i] -= (s->real * co + s->imag * si) / s->ref;
s->real -= s->real * s->decay;
s->imag -= s->imag * s->decay;
s->ref -= s->ref * s->decay;
s->pos += 2 * M_PI * s->freq / data->rate;
}
MP_VERBOSE(af, "f:%8.2f: amp:%8.2f\n", s->freq, sqrt(s->real*s->real + s->imag*s->imag) / s->ref);
af_add_output_frame(af, data);
return 0;
}
// Allocate memory and set function pointers
static int af_open(struct af_instance* af){
af->control=control;
af->filter_frame = play_s16;
return AF_OK;
}
#define OPT_BASE_STRUCT af_sinesuppress_t
const struct af_info af_info_sinesuppress = {
.info = "Sine Suppress",
.name = "sinesuppress",
.open = af_open,
.priv_size = sizeof(af_sinesuppress_t),
.options = (const struct m_option[]) {
OPT_DOUBLE("freq", freq, 0, OPTDEF_DOUBLE(50.0)),
OPT_DOUBLE("decay", decay, 0, OPTDEF_DOUBLE(0.0001)),
{0}
},
};
+149
View File
@@ -0,0 +1,149 @@
/*
* Copyright (C) 2002 Anders Johansson ajh@watri.uwa.edu.au
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* This filter adds a sub-woofer channels to the audio stream by
averaging the left and right channel and low-pass filter them. The
low-pass filter is implemented as a 4th order IIR Butterworth
filter, with a variable cutoff frequency between 10 and 300 Hz. The
filter gives 24dB/octave attenuation. There are two runtime
controls one for setting which channel to insert the sub-audio into
called AF_CONTROL_SUB_CH and one for setting the cutoff frequency
called AF_CONTROL_SUB_FC.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common/common.h"
#include "af.h"
#include "dsp.h"
// Q value for low-pass filter
#define Q 1.0
// Analog domain biquad section
typedef struct{
float a[3]; // Numerator coefficients
float b[3]; // Denominator coefficients
} biquad_t;
// S-parameters for designing 4th order Butterworth filter
static const biquad_t sp[2] = {{{1.0,0.0,0.0},{1.0,0.765367,1.0}},
{{1.0,0.0,0.0},{1.0,1.847759,1.0}}};
// Data for specific instances of this filter
typedef struct af_sub_s
{
float w[2][4]; // Filter taps for low-pass filter
float q[2][2]; // Circular queues
float fc; // Cutoff frequency [Hz] for low-pass filter
float k; // Filter gain;
int ch; // Channel number which to insert the filtered data
}af_sub_t;
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
af_sub_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_channels_old(af->data, MPMAX(s->ch+1,((struct mp_audio*)arg)->nch));
mp_audio_set_format(af->data, AF_FORMAT_FLOAT);
// Design low-pass filter
s->k = 1.0;
if((-1 == af_filter_szxform(sp[0].a, sp[0].b, Q, s->fc,
(float)af->data->rate, &s->k, s->w[0])) ||
(-1 == af_filter_szxform(sp[1].a, sp[1].b, Q, s->fc,
(float)af->data->rate, &s->k, s->w[1])))
return AF_ERROR;
return af_test_output(af,(struct mp_audio*)arg);
}
}
return AF_UNKNOWN;
}
#ifndef IIR
#define IIR(in,w,q,out) { \
float h0 = (q)[0]; \
float h1 = (q)[1]; \
float hn = (in) - h0 * (w)[0] - h1 * (w)[1]; \
out = hn + h0 * (w)[2] + h1 * (w)[3]; \
(q)[1] = h0; \
(q)[0] = hn; \
}
#endif
static int filter_frame(struct af_instance *af, struct mp_audio *data)
{
if (!data)
return 0;
if (af_make_writeable(af, data) < 0) {
talloc_free(data);
return -1;
}
struct mp_audio* c = data; // Current working data
af_sub_t* s = af->priv; // Setup for this instance
float* a = c->planes[0]; // Audio data
int len = c->samples*c->nch; // Number of samples in current audio block
int nch = c->nch; // Number of channels
int ch = s->ch; // Channel in which to insert the sub audio
register int i;
// Run filter
for(i=0;i<len;i+=nch){
// Average left and right
register float x = 0.5 * (a[i] + a[i+1]);
IIR(x * s->k, s->w[0], s->q[0], x);
IIR(x , s->w[1], s->q[1], a[i+ch]);
}
af_add_output_frame(af, data);
return 0;
}
// Allocate memory and set function pointers
static int af_open(struct af_instance* af){
af->control=control;
af->filter_frame = filter_frame;
return AF_OK;
}
#define OPT_BASE_STRUCT af_sub_t
const struct af_info af_info_sub = {
.info = "Audio filter for adding a sub-base channel",
.name = "sub",
.flags = AF_FLAGS_NOT_REENTRANT,
.open = af_open,
.priv_size = sizeof(af_sub_t),
.options = (const struct m_option[]) {
OPT_FLOATRANGE("fc", fc, 0, 20, 300, OPTDEF_FLOAT(60.0)),
OPT_INTRANGE("ch", ch, 0, 0, AF_NCH - 1, OPTDEF_INT(5)),
{0}
},
};
+247
View File
@@ -0,0 +1,247 @@
/*
* Filter to do simple decoding of matrixed surround sound.
* This will provide a (basic) surround-sound effect from
* audio encoded for Dolby Surround, Pro Logic etc.
*
* original author: Steve Davies <steve@daviesfam.org>
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* The principle: Make rear channels by extracting anti-phase data
from the front channels, delay by 20ms and feed to rear in anti-phase
*/
/* SPLITREAR: Define to decode two distinct rear channels - this
doesn't work so well in practice because separation in a passive
matrix is not high. C (dialogue) to Ls and Rs 14dB or so - so
dialogue leaks to the rear. Still - give it a try and send
feedback. Comment this define for old behavior of a single
surround sent to rear in anti-phase */
#define SPLITREAR 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "af.h"
#include "dsp.h"
#define L 32 // Length of fir filter
#define LD 65536 // Length of delay buffer
// 32 Tap fir filter loop unrolled
#define FIR(x,w,y) \
y = ( w[0] *x[0] +w[1] *x[1] +w[2] *x[2] +w[3] *x[3] \
+ w[4] *x[4] +w[5] *x[5] +w[6] *x[6] +w[7] *x[7] \
+ w[8] *x[8] +w[9] *x[9] +w[10]*x[10]+w[11]*x[11] \
+ w[12]*x[12]+w[13]*x[13]+w[14]*x[14]+w[15]*x[15] \
+ w[16]*x[16]+w[17]*x[17]+w[18]*x[18]+w[19]*x[19] \
+ w[20]*x[20]+w[21]*x[21]+w[22]*x[22]+w[23]*x[23] \
+ w[24]*x[24]+w[25]*x[25]+w[26]*x[26]+w[27]*x[27] \
+ w[28]*x[28]+w[29]*x[29]+w[30]*x[30]+w[31]*x[31])
// Add to circular queue macro + update index
#ifdef SPLITREAR
#define ADDQUE(qi,rq,lq,r,l)\
lq[qi]=lq[qi+L]=(l);\
rq[qi]=rq[qi+L]=(r);\
qi=(qi-1)&(L-1);
#else
#define ADDQUE(qi,lq,l)\
lq[qi]=lq[qi+L]=(l);\
qi=(qi-1)&(L-1);
#endif
// Macro for updating queue index in delay queues
#define UPDATEQI(qi) qi=(qi+1)&(LD-1)
// instance data
typedef struct af_surround_s
{
float lq[2*L]; // Circular queue for filtering left rear channel
float rq[2*L]; // Circular queue for filtering right rear channel
float w[L]; // FIR filter coefficients for surround sound 7kHz low-pass
float* dr; // Delay queue right rear channel
float* dl; // Delay queue left rear channel
float d; // Delay time
int i; // Position in circular buffer
int wi; // Write index for delay queue
int ri; // Read index for delay queue
}af_surround_t;
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
af_surround_t *s = af->priv;
switch(cmd){
case AF_CONTROL_REINIT:{
struct mp_audio *in = arg;
float fc;
if (!mp_chmap_is_stereo(&in->channels)) {
MP_ERR(af, "Only stereo input is supported.\n");
return AF_DETACH;
}
mp_audio_set_format(in, AF_FORMAT_FLOAT);
mp_audio_copy_config(af->data, in);
mp_audio_set_channels_old(af->data, in->nch * 2);
// Surround filer coefficients
fc = 2.0 * 7000.0/(float)af->data->rate;
if (-1 == af_filter_design_fir(L, s->w, &fc, LP|HAMMING, 0)){
MP_ERR(af, "Unable to design low-pass filter.\n");
return AF_ERROR;
}
// Free previous delay queues
free(s->dl);
free(s->dr);
// Allocate new delay queues
s->dl = calloc(LD,af->data->bps);
s->dr = calloc(LD,af->data->bps);
if((NULL == s->dl) || (NULL == s->dr))
MP_FATAL(af, "Out of memory\n");
// Initialize delay queue index
if(AF_OK != af_from_ms(1, &s->d, &s->wi, af->data->rate, 0.0, 1000.0))
return AF_ERROR;
// printf("%i\n",s->wi);
s->ri = 0;
return AF_OK;
}
}
return AF_UNKNOWN;
}
// The beginnings of an active matrix...
static const float steering_matrix[][12] = {
// LL RL LR RR LS RS
// LLs RLs LRs RRs LC RC
{.707, .0, .0, .707, .5, -.5,
.5878, -.3928, .3928, -.5878, .5, .5},
};
// Experimental moving average dominance
//static int amp_L = 0, amp_R = 0, amp_C = 0, amp_S = 0;
static int filter_frame(struct af_instance *af, struct mp_audio *data)
{
if (!data)
return 0;
struct mp_audio *outframe =
mp_audio_pool_get(af->out_pool, &af->fmt_out, data->samples);
if (!outframe) {
talloc_free(data);
return -1;
}
mp_audio_copy_attributes(outframe, data);
af_surround_t* s = (af_surround_t*)af->priv;
const float* m = steering_matrix[0];
float* in = data->planes[0]; // Input audio data
float* out = outframe->planes[0]; // Output audio data
float* end = in + data->samples * data->nch;
int i = s->i; // Filter queue index
int ri = s->ri; // Read index for delay queue
int wi = s->wi; // Write index for delay queue
while(in < end){
/* Dominance:
abs(in[0]) abs(in[1]);
abs(in[0]+in[1]) abs(in[0]-in[1]);
10 * log( abs(in[0]) / (abs(in[1])|1) );
10 * log( abs(in[0]+in[1]) / (abs(in[0]-in[1])|1) ); */
/* About volume balancing...
Surround encoding does the following:
Lt=L+.707*C+.707*S, Rt=R+.707*C-.707*S
So S should be extracted as:
(Lt-Rt)
But we are splitting the S to two output channels, so we
must take 3dB off as we split it:
Ls=Rs=.707*(Lt-Rt)
Trouble is, Lt could be +1, Rt -1, so possibility that S will
overflow. So to avoid that, we cut L/R by 3dB (*.707), and S by
6dB (/2). This keeps the overall balance, but guarantees no
overflow. */
// Output front left and right
out[0] = m[0]*in[0] + m[1]*in[1];
out[1] = m[2]*in[0] + m[3]*in[1];
// Low-pass output @ 7kHz
FIR((&s->lq[i]), s->w, s->dl[wi]);
// Delay output by d ms
out[2] = s->dl[ri];
#ifdef SPLITREAR
// Low-pass output @ 7kHz
FIR((&s->rq[i]), s->w, s->dr[wi]);
// Delay output by d ms
out[3] = s->dr[ri];
#else
out[3] = -out[2];
#endif
// Update delay queues indexes
UPDATEQI(ri);
UPDATEQI(wi);
// Calculate and save surround in circular queue
#ifdef SPLITREAR
ADDQUE(i, s->rq, s->lq, m[6]*in[0]+m[7]*in[1], m[8]*in[0]+m[9]*in[1]);
#else
ADDQUE(i, s->lq, m[4]*in[0]+m[5]*in[1]);
#endif
// Next sample...
in = &in[data->nch];
out = &out[af->data->nch];
}
// Save indexes
s->i = i; s->ri = ri; s->wi = wi;
talloc_free(data);
af_add_output_frame(af, outframe);
return 0;
}
static int af_open(struct af_instance* af){
af->control=control;
af->filter_frame = filter_frame;
return AF_OK;
}
#define OPT_BASE_STRUCT af_surround_t
const struct af_info af_info_surround =
{
.info = "Surround decoder filter",
.name = "surround",
.flags = AF_FLAGS_NOT_REENTRANT,
.open = af_open,
.priv_size = sizeof(af_surround_t),
.options = (const struct m_option[]) {
OPT_FLOATRANGE("d", d, 0, 0, 1000, OPTDEF_FLOAT(20.0)),
{0}
},
};
+93
View File
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <math.h>
#include "config.h"
#include "af.h"
typedef struct af_sweep_s{
double x;
double delta;
}af_sweept;
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
struct mp_audio *data= (struct mp_audio*)arg;
switch(cmd){
case AF_CONTROL_REINIT:
mp_audio_copy_config(af->data, data);
mp_audio_set_format(af->data, AF_FORMAT_S16);
return af_test_output(af, data);
}
return AF_UNKNOWN;
}
static int filter_frame(struct af_instance *af, struct mp_audio *data)
{
if (!data)
return 0;
if (af_make_writeable(af, data) < 0) {
talloc_free(data);
return 0;
}
af_sweept *s = af->priv;
int i, j;
int16_t *in = (int16_t*)data->planes[0];
int chans = data->nch;
int in_len = data->samples;
for(i=0; i<in_len; i++){
for(j=0; j<chans; j++)
in[i*chans+j]= 32000*sin(s->x*s->x);
s->x += s->delta;
if(2*s->x*s->delta >= 3.141592) s->x=0;
}
af_add_output_frame(af, data);
return 0;
}
static int af_open(struct af_instance* af){
af->control=control;
af->filter_frame = filter_frame;
return AF_OK;
}
#define OPT_BASE_STRUCT af_sweept
const struct af_info af_info_sweep = {
.info = "sine sweep",
.name = "sweep",
.open = af_open,
.priv_size = sizeof(af_sweept),
.options = (const struct m_option[]) {
OPT_DOUBLE("delta", delta, 0),
{0}
},
};
+10 -24
View File
@@ -1,20 +1,21 @@
/*
* Copyright (C)2002 Anders Johansson ajh@atri.curtin.edu.au
*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
@@ -30,28 +31,18 @@
#include "demux/demux.h"
struct priv {
float vol; // User-specified non-linear volume
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;
};
// 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;
@@ -83,7 +74,7 @@ static int control(struct af_instance *af, int cmd, void *arg)
}
gain += s->rgain_preamp;
s->rgain = from_dB(gain, 20.0, -200.0, 60.0);
af_from_dB(1, &gain, &s->rgain, 20.0, -200.0, 60.0);
MP_VERBOSE(af, "Applying replay-gain: %f\n", s->rgain);
@@ -91,21 +82,16 @@ static int control(struct af_instance *af, int cmd, void *arg)
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->vol = *(float *)arg;
s->level = pow(s->vol, 3);
MP_VERBOSE(af, "volume gain: %f\n", s->level);
s->level = *(float *)arg;
return AF_OK;
case AF_CONTROL_GET_VOLUME:
*(float *)arg = s->vol;
*(float *)arg = s->level;
return AF_OK;
}
return AF_UNKNOWN;
@@ -158,7 +144,7 @@ static int af_open(struct af_instance *af)
struct priv *s = af->priv;
af->control = control;
af->filter_frame = filter;
s->level = from_dB(s->cfg_volume, 20.0, -200.0, 60.0);
af_from_dB(1, &s->cfg_volume, &s->level, 20.0, -200.0, 60.0);
return AF_OK;
}
@@ -168,6 +154,7 @@ static int af_open(struct af_instance *af)
const struct af_info af_info_volume = {
.info = "Volume control audio filter",
.name = "volume",
.flags = AF_FLAGS_NOT_REENTRANT,
.open = af_open,
.priv_size = sizeof(struct priv),
.options = (const struct m_option[]) {
@@ -176,7 +163,6 @@ const struct af_info af_info_volume = {
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),
+32
View File
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2002 Anders Johansson ajh@atri.curtin.edu.au
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPLAYER_DSP_H
#define MPLAYER_DSP_H
/* Implementation of routines used for DSP */
/* Size of floating point type used in routines */
#define FLOAT_TYPE float
#include "window.h"
#include "filter.h"
#endif /* MPLAYER_DSP_H */
+5 -4
View File
@@ -1,20 +1,21 @@
/*
* Copyright (C) 2002 Anders Johansson ajh@atri.curtin.edu.au
*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPLAYER_EQUALIZER_H
+360
View File
@@ -0,0 +1,360 @@
/*
* design and implementation of different types of digital filters
*
* Copyright (C) 2001 Anders Johansson ajh@atri.curtin.edu.au
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
#include <math.h>
#include "dsp.h"
/******************************************************************************
* FIR filter implementations
******************************************************************************/
/* C implementation of FIR filter y=w*x
n number of filter taps, where mod(n,4)==0
w filter taps
x input signal must be a circular buffer which is indexed backwards
*/
inline FLOAT_TYPE af_filter_fir(register unsigned int n, const FLOAT_TYPE* w,
const FLOAT_TYPE* x)
{
register FLOAT_TYPE y; // Output
y = 0.0;
do{
n--;
y+=w[n]*x[n];
}while(n != 0);
return y;
}
/******************************************************************************
* FIR filter design
******************************************************************************/
/* Design FIR filter using the Window method
n filter length must be odd for HP and BS filters
w buffer for the filter taps (must be n long)
fc cutoff frequencies (1 for LP and HP, 2 for BP and BS)
0 < fc < 1 where 1 <=> Fs/2
flags window and filter type as defined in filter.h
variables are ored together: i.e. LP|HAMMING will give a
low pass filter designed using a hamming window
opt beta constant used only when designing using kaiser windows
returns 0 if OK, -1 if fail
*/
int af_filter_design_fir(unsigned int n, FLOAT_TYPE* w, const FLOAT_TYPE* fc,
unsigned int flags, FLOAT_TYPE opt)
{
unsigned int o = n & 1; // Indicator for odd filter length
unsigned int end = ((n + 1) >> 1) - o; // Loop end
unsigned int i; // Loop index
FLOAT_TYPE k1 = 2 * M_PI; // 2*pi*fc1
FLOAT_TYPE k2 = 0.5 * (FLOAT_TYPE)(1 - o);// Constant used if the filter has even length
FLOAT_TYPE k3; // 2*pi*fc2 Constant used in BP and BS design
FLOAT_TYPE g = 0.0; // Gain
FLOAT_TYPE t1,t2,t3; // Temporary variables
FLOAT_TYPE fc1,fc2; // Cutoff frequencies
// Sanity check
if(!w || (n == 0)) return -1;
// Get window coefficients
switch(flags & WINDOW_MASK){
case(BOXCAR):
af_window_boxcar(n,w); break;
case(TRIANG):
af_window_triang(n,w); break;
case(HAMMING):
af_window_hamming(n,w); break;
case(HANNING):
af_window_hanning(n,w); break;
case(BLACKMAN):
af_window_blackman(n,w); break;
case(FLATTOP):
af_window_flattop(n,w); break;
case(KAISER):
af_window_kaiser(n,w,opt); break;
default:
return -1;
}
if(flags & (LP | HP)){
fc1=*fc;
// Cutoff frequency must be < 0.5 where 0.5 <=> Fs/2
fc1 = ((fc1 <= 1.0) && (fc1 > 0.0)) ? fc1/2 : 0.25;
k1 *= fc1;
if(flags & LP){ // Low pass filter
// If the filter length is odd, there is one point which is exactly
// in the middle. The value at this point is 2*fCutoff*sin(x)/x,
// where x is zero. To make sure nothing strange happens, we set this
// value separately.
if (o){
w[end] = fc1 * w[end] * 2.0;
g=w[end];
}
// Create filter
for (i=0 ; i<end ; i++){
t1 = (FLOAT_TYPE)(i+1) - k2;
w[end-i-1] = w[n-end+i] = w[end-i-1] * sin(k1 * t1)/(M_PI * t1); // Sinc
g += 2*w[end-i-1]; // Total gain in filter
}
}
else{ // High pass filter
if (!o) // High pass filters must have odd length
return -1;
w[end] = 1.0 - (fc1 * w[end] * 2.0);
g= w[end];
// Create filter
for (i=0 ; i<end ; i++){
t1 = (FLOAT_TYPE)(i+1);
w[end-i-1] = w[n-end+i] = -1 * w[end-i-1] * sin(k1 * t1)/(M_PI * t1); // Sinc
g += ((i&1) ? (2*w[end-i-1]) : (-2*w[end-i-1])); // Total gain in filter
}
}
}
if(flags & (BP | BS)){
fc1=fc[0];
fc2=fc[1];
// Cutoff frequencies must be < 1.0 where 1.0 <=> Fs/2
fc1 = ((fc1 <= 1.0) && (fc1 > 0.0)) ? fc1/2 : 0.25;
fc2 = ((fc2 <= 1.0) && (fc2 > 0.0)) ? fc2/2 : 0.25;
k3 = k1 * fc2; // 2*pi*fc2
k1 *= fc1; // 2*pi*fc1
if(flags & BP){ // Band pass
// Calculate center tap
if (o){
g=w[end]*(fc1+fc2);
w[end] = (fc2 - fc1) * w[end] * 2.0;
}
// Create filter
for (i=0 ; i<end ; i++){
t1 = (FLOAT_TYPE)(i+1) - k2;
t2 = sin(k3 * t1)/(M_PI * t1); // Sinc fc2
t3 = sin(k1 * t1)/(M_PI * t1); // Sinc fc1
g += w[end-i-1] * (t3 + t2); // Total gain in filter
w[end-i-1] = w[n-end+i] = w[end-i-1] * (t2 - t3);
}
}
else{ // Band stop
if (!o) // Band stop filters must have odd length
return -1;
w[end] = 1.0 - (fc2 - fc1) * w[end] * 2.0;
g= w[end];
// Create filter
for (i=0 ; i<end ; i++){
t1 = (FLOAT_TYPE)(i+1);
t2 = sin(k1 * t1)/(M_PI * t1); // Sinc fc1
t3 = sin(k3 * t1)/(M_PI * t1); // Sinc fc2
w[end-i-1] = w[n-end+i] = w[end-i-1] * (t2 - t3);
g += 2*w[end-i-1]; // Total gain in filter
}
}
}
// Normalize gain
g=1/g;
for (i=0; i<n; i++)
w[i] *= g;
return 0;
}
/******************************************************************************
* IIR filter design
******************************************************************************/
/* Helper functions for the bilinear transform */
/* Pre-warp the coefficients of a numerator or denominator.
Note that a0 is assumed to be 1, so there is no wrapping
of it.
*/
static void af_filter_prewarp(FLOAT_TYPE* a, FLOAT_TYPE fc, FLOAT_TYPE fs)
{
FLOAT_TYPE wp;
wp = 2.0 * fs * tan(M_PI * fc / fs);
a[2] = a[2]/(wp * wp);
a[1] = a[1]/wp;
}
/* Transform the numerator and denominator coefficients of s-domain
biquad section into corresponding z-domain coefficients.
The transfer function for z-domain is:
1 + alpha1 * z^(-1) + alpha2 * z^(-2)
H(z) = -------------------------------------
1 + beta1 * z^(-1) + beta2 * z^(-2)
Store the 4 IIR coefficients in array pointed by coef in following
order:
beta1, beta2 (denominator)
alpha1, alpha2 (numerator)
Arguments:
a - s-domain numerator coefficients
b - s-domain denominator coefficients
k - filter gain factor. Initially set to 1 and modified by each
biquad section in such a way, as to make it the
coefficient by which to multiply the overall filter gain
in order to achieve a desired overall filter gain,
specified in initial value of k.
fs - sampling rate (Hz)
coef - array of z-domain coefficients to be filled in.
Return: On return, set coef z-domain coefficients and k to the gain
required to maintain overall gain = 1.0;
*/
static void af_filter_bilinear(const FLOAT_TYPE* a, const FLOAT_TYPE* b, FLOAT_TYPE* k,
FLOAT_TYPE fs, FLOAT_TYPE *coef)
{
FLOAT_TYPE ad, bd;
/* alpha (Numerator in s-domain) */
ad = 4. * a[2] * fs * fs + 2. * a[1] * fs + a[0];
/* beta (Denominator in s-domain) */
bd = 4. * b[2] * fs * fs + 2. * b[1] * fs + b[0];
/* Update gain constant for this section */
*k *= ad/bd;
/* Denominator */
*coef++ = (2. * b[0] - 8. * b[2] * fs * fs)/bd; /* beta1 */
*coef++ = (4. * b[2] * fs * fs - 2. * b[1] * fs + b[0])/bd; /* beta2 */
/* Numerator */
*coef++ = (2. * a[0] - 8. * a[2] * fs * fs)/ad; /* alpha1 */
*coef = (4. * a[2] * fs * fs - 2. * a[1] * fs + a[0])/ad; /* alpha2 */
}
/* IIR filter design using bilinear transform and prewarp. Transforms
2nd order s domain analog filter into a digital IIR biquad link. To
create a filter fill in a, b, Q and fs and make space for coef and k.
Example Butterworth design:
Below are Butterworth polynomials, arranged as a series of 2nd
order sections:
Note: n is filter order.
n Polynomials
-------------------------------------------------------------------
2 s^2 + 1.4142s + 1
4 (s^2 + 0.765367s + 1) * (s^2 + 1.847759s + 1)
6 (s^2 + 0.5176387s + 1) * (s^2 + 1.414214 + 1) * (s^2 + 1.931852s + 1)
For n=4 we have following equation for the filter transfer function:
1 1
T(s) = --------------------------- * ----------------------------
s^2 + (1/Q) * 0.765367s + 1 s^2 + (1/Q) * 1.847759s + 1
The filter consists of two 2nd order sections since highest s power
is 2. Now we can take the coefficients, or the numbers by which s
is multiplied and plug them into a standard formula to be used by
bilinear transform.
Our standard form for each 2nd order section is:
a2 * s^2 + a1 * s + a0
H(s) = ----------------------
b2 * s^2 + b1 * s + b0
Note that Butterworth numerator is 1 for all filter sections, which
means s^2 = 0 and s^1 = 0
Let's convert standard Butterworth polynomials into this form:
0 + 0 + 1 0 + 0 + 1
--------------------------- * --------------------------
1 + ((1/Q) * 0.765367) + 1 1 + ((1/Q) * 1.847759) + 1
Section 1:
a2 = 0; a1 = 0; a0 = 1;
b2 = 1; b1 = 0.765367; b0 = 1;
Section 2:
a2 = 0; a1 = 0; a0 = 1;
b2 = 1; b1 = 1.847759; b0 = 1;
Q is filter quality factor or resonance, in the range of 1 to
1000. The overall filter Q is a product of all 2nd order stages.
For example, the 6th order filter (3 stages, or biquads) with
individual Q of 2 will have filter Q = 2 * 2 * 2 = 8.
Arguments:
a - s-domain numerator coefficients, a[1] is always assumed to be 1.0
b - s-domain denominator coefficients
Q - Q value for the filter
k - filter gain factor. Initially set to 1 and modified by each
biquad section in such a way, as to make it the
coefficient by which to multiply the overall filter gain
in order to achieve a desired overall filter gain,
specified in initial value of k.
fs - sampling rate (Hz)
coef - array of z-domain coefficients to be filled in.
Note: Upon return from each call, the k argument will be set to a
value, by which to multiply our actual signal in order for the gain
to be one. On second call to szxform() we provide k that was
changed by the previous section. During actual audio filtering
k can be used for gain compensation.
return -1 if fail 0 if success.
*/
int af_filter_szxform(const FLOAT_TYPE* a, const FLOAT_TYPE* b, FLOAT_TYPE Q, FLOAT_TYPE fc,
FLOAT_TYPE fs, FLOAT_TYPE *k, FLOAT_TYPE *coef)
{
FLOAT_TYPE at[3];
FLOAT_TYPE bt[3];
if(!a || !b || !k || !coef || (Q>1000.0 || Q< 1.0))
return -1;
memcpy(at,a,3*sizeof(FLOAT_TYPE));
memcpy(bt,b,3*sizeof(FLOAT_TYPE));
bt[1]/=Q;
/* Calculate a and b and overwrite the original values */
af_filter_prewarp(at, fc, fs);
af_filter_prewarp(bt, fc, fs);
/* Execute bilinear transform */
af_filter_bilinear(at, bt, k, fs, coef);
return 0;
}
+75
View File
@@ -0,0 +1,75 @@
/*
* Copyright (C) 2001 Anders Johansson ajh@atri.curtin.edu.au
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#if !defined MPLAYER_DSP_H
# error Never use filter.h directly; include dsp.h instead.
#endif
#ifndef MPLAYER_FILTER_H
#define MPLAYER_FILTER_H
// Design and implementation of different types of digital filters
// Flags used for filter design
// Filter characteristics
#define LP 0x00010000 // Low pass
#define HP 0x00020000 // High pass
#define BP 0x00040000 // Band pass
#define BS 0x00080000 // Band stop
#define TYPE_MASK 0x000F0000
// Window types
#define BOXCAR 0x00000001
#define TRIANG 0x00000002
#define HAMMING 0x00000004
#define HANNING 0x00000008
#define BLACKMAN 0x00000010
#define FLATTOP 0x00000011
#define KAISER 0x00000012
#define WINDOW_MASK 0x0000001F
// Parallel filter design
#define FWD 0x00000001 // Forward indexing of polyphase filter
#define REW 0x00000002 // Reverse indexing of polyphase filter
#define ODD 0x00000010 // Make filter HP
// Exported functions
FLOAT_TYPE af_filter_fir(unsigned int n, const FLOAT_TYPE* w, const FLOAT_TYPE* x);
int af_filter_design_fir(unsigned int n, FLOAT_TYPE* w, const FLOAT_TYPE* fc,
unsigned int flags, FLOAT_TYPE opt);
int af_filter_szxform(const FLOAT_TYPE* a, const FLOAT_TYPE* b, FLOAT_TYPE Q,
FLOAT_TYPE fc, FLOAT_TYPE fs, FLOAT_TYPE *k,
FLOAT_TYPE *coef);
/* Add new data to circular queue designed to be used with a FIR
filter. xq is the circular queue, in pointing at the new sample, xi
current index for xq and n the length of the filter. xq must be n*2
long.
*/
#define af_filter_updateq(n,xi,xq,in)\
xq[xi]=(xq)[(xi)+(n)]=*(in);\
xi=(++(xi))&((n)-1);
#endif /* MPLAYER_FILTER_H */
+55 -4
View File
@@ -1,18 +1,19 @@
/*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <math.h>
@@ -21,6 +22,42 @@
#include "common/common.h"
#include "af.h"
/* Convert to gain value from dB. Returns AF_OK if of and AF_ERROR if
* fail. input <= -200dB will become 0 gain. */
int af_from_dB(int n, float* in, float* out, float k, float mi, float ma)
{
int i = 0;
// Sanity check
if(!in || !out)
return AF_ERROR;
for(i=0;i<n;i++){
if(in[i]<=-200)
out[i]=0.0;
else
out[i]=pow(10.0,MPCLAMP(in[i],mi,ma)/k);
}
return AF_OK;
}
/* Convert from gain value to dB. Returns AF_OK if of and AF_ERROR if
* fail. gain=0 will become -200 dB. k is just a multiplier. */
int af_to_dB(int n, float* in, float* out, float k)
{
int i = 0;
// Sanity check
if(!in || !out)
return AF_ERROR;
for(i=0;i<n;i++){
if(in[i] == 0.0)
out[i]=-200.0;
else
out[i]=k*log10(in[i]);
}
return AF_OK;
}
/* Convert from ms to sample time */
int af_from_ms(int n, float* in, int* out, int rate, float mi, float ma)
{
@@ -35,6 +72,20 @@ int af_from_ms(int n, float* in, int* out, int rate, float mi, float ma)
return AF_OK;
}
/* Convert from sample time to ms */
int af_to_ms(int n, int* in, float* out, int rate)
{
int i = 0;
// Sanity check
if(!in || !out || !rate)
return AF_ERROR;
for(i=0;i<n;i++)
out[i]=1000.0 * (float)in[i]/((float)rate);
return AF_OK;
}
/*
* test if output format matches
* af: audio filter
+213
View File
@@ -0,0 +1,213 @@
/*
* Copyright (C) 2001 Anders Johansson ajh@atri.curtin.edu.au
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* Calculates a number of window functions. The following window
functions are currently implemented: Boxcar, Triang, Hanning,
Hamming, Blackman, Flattop and Kaiser. In the function call n is
the number of filter taps and w the buffer in which the filter
coefficients will be stored.
*/
#include <math.h>
#include "dsp.h"
/*
// Boxcar
//
// n window length
// w buffer for the window parameters
*/
void af_window_boxcar(int n, FLOAT_TYPE* w)
{
int i;
// Calculate window coefficients
for (i=0 ; i<n ; i++)
w[i] = 1.0;
}
/*
// Triang a.k.a Bartlett
//
// | (N-1)|
// 2 * |k - -----|
// | 2 |
// w = 1.0 - ---------------
// N+1
// n window length
// w buffer for the window parameters
*/
void af_window_triang(int n, FLOAT_TYPE* w)
{
FLOAT_TYPE k1 = (FLOAT_TYPE)(n & 1);
FLOAT_TYPE k2 = 1/((FLOAT_TYPE)n + k1);
int end = (n + 1) >> 1;
int i;
// Calculate window coefficients
for (i=0 ; i<end ; i++)
w[i] = w[n-i-1] = (2.0*((FLOAT_TYPE)(i+1))-(1.0-k1))*k2;
}
/*
// Hanning
// 2*pi*k
// w = 0.5 - 0.5*cos(------), where 0 < k <= N
// N+1
// n window length
// w buffer for the window parameters
*/
void af_window_hanning(int n, FLOAT_TYPE* w)
{
int i;
FLOAT_TYPE k = 2*M_PI/((FLOAT_TYPE)(n+1)); // 2*pi/(N+1)
// Calculate window coefficients
for (i=0; i<n; i++)
*w++ = 0.5*(1.0 - cos(k*(FLOAT_TYPE)(i+1)));
}
/*
// Hamming
// 2*pi*k
// w(k) = 0.54 - 0.46*cos(------), where 0 <= k < N
// N-1
//
// n window length
// w buffer for the window parameters
*/
void af_window_hamming(int n,FLOAT_TYPE* w)
{
int i;
FLOAT_TYPE k = 2*M_PI/((FLOAT_TYPE)(n-1)); // 2*pi/(N-1)
// Calculate window coefficients
for (i=0; i<n; i++)
*w++ = 0.54 - 0.46*cos(k*(FLOAT_TYPE)i);
}
/*
// Blackman
// 2*pi*k 4*pi*k
// w(k) = 0.42 - 0.5*cos(------) + 0.08*cos(------), where 0 <= k < N
// N-1 N-1
//
// n window length
// w buffer for the window parameters
*/
void af_window_blackman(int n,FLOAT_TYPE* w)
{
int i;
FLOAT_TYPE k1 = 2*M_PI/((FLOAT_TYPE)(n-1)); // 2*pi/(N-1)
FLOAT_TYPE k2 = 2*k1; // 4*pi/(N-1)
// Calculate window coefficients
for (i=0; i<n; i++)
*w++ = 0.42 - 0.50*cos(k1*(FLOAT_TYPE)i) + 0.08*cos(k2*(FLOAT_TYPE)i);
}
/*
// Flattop
// 2*pi*k 4*pi*k
// w(k) = 0.2810638602 - 0.5208971735*cos(------) + 0.1980389663*cos(------), where 0 <= k < N
// N-1 N-1
//
// n window length
// w buffer for the window parameters
*/
void af_window_flattop(int n,FLOAT_TYPE* w)
{
int i;
FLOAT_TYPE k1 = 2*M_PI/((FLOAT_TYPE)(n-1)); // 2*pi/(N-1)
FLOAT_TYPE k2 = 2*k1; // 4*pi/(N-1)
// Calculate window coefficients
for (i=0; i<n; i++)
*w++ = 0.2810638602 - 0.5208971735*cos(k1*(FLOAT_TYPE)i)
+ 0.1980389663*cos(k2*(FLOAT_TYPE)i);
}
/* Computes the 0th order modified Bessel function of the first kind.
// (Needed to compute Kaiser window)
//
// y = sum( (x/(2*n))^2 )
// n
*/
#define BIZ_EPSILON 1E-21 // Max error acceptable
static FLOAT_TYPE besselizero(FLOAT_TYPE x)
{
FLOAT_TYPE temp;
FLOAT_TYPE sum = 1.0;
FLOAT_TYPE u = 1.0;
FLOAT_TYPE halfx = x/2.0;
int n = 1;
do {
temp = halfx/(FLOAT_TYPE)n;
u *=temp * temp;
sum += u;
n++;
} while (u >= BIZ_EPSILON * sum);
return sum;
}
/*
// Kaiser
//
// n window length
// w buffer for the window parameters
// b beta parameter of Kaiser window, Beta >= 1
//
// Beta trades the rejection of the low pass filter against the
// transition width from passband to stop band. Larger Beta means a
// slower transition and greater stop band rejection. See Rabiner and
// Gold (Theory and Application of DSP) under Kaiser windows for more
// about Beta. The following table from Rabiner and Gold gives some
// feel for the effect of Beta:
//
// All ripples in dB, width of transition band = D*N where N = window
// length
//
// BETA D PB RIP SB RIP
// 2.120 1.50 +-0.27 -30
// 3.384 2.23 0.0864 -40
// 4.538 2.93 0.0274 -50
// 5.658 3.62 0.00868 -60
// 6.764 4.32 0.00275 -70
// 7.865 5.0 0.000868 -80
// 8.960 5.7 0.000275 -90
// 10.056 6.4 0.000087 -100
*/
void af_window_kaiser(int n, FLOAT_TYPE* w, FLOAT_TYPE b)
{
FLOAT_TYPE tmp;
FLOAT_TYPE k1 = 1.0/besselizero(b);
int k2 = 1 - (n & 1);
int end = (n + 1) >> 1;
int i;
// Calculate window coefficients
for (i=0 ; i<end ; i++){
tmp = (FLOAT_TYPE)(2*i + k2) / ((FLOAT_TYPE)n - 1.0);
w[end-(1&(!k2))+i] = w[end-1-i] = k1 * besselizero(b*sqrt(1.0 - tmp*tmp));
}
}
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2001 Anders Johansson ajh@atri.curtin.edu.au
*
* This file is part of MPlayer.
*
* MPlayer 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.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* Calculates a number of window functions. The following window
functions are currently implemented: Boxcar, Triang, Hanning,
Hamming, Blackman, Flattop and Kaiser. In the function call n is
the number of filter taps and w the buffer in which the filter
coefficients will be stored.
*/
#if !defined MPLAYER_DSP_H
# error Never use window.h directly; include dsp.h instead.
#endif
#ifndef MPLAYER_WINDOW_H
#define MPLAYER_WINDOW_H
void af_window_boxcar(int n, FLOAT_TYPE* w);
void af_window_triang(int n, FLOAT_TYPE* w);
void af_window_hanning(int n, FLOAT_TYPE* w);
void af_window_hamming(int n, FLOAT_TYPE* w);
void af_window_blackman(int n, FLOAT_TYPE* w);
void af_window_flattop(int n, FLOAT_TYPE* w);
void af_window_kaiser(int n, FLOAT_TYPE* w, FLOAT_TYPE b);
#endif /* MPLAYER_WINDOW_H */
+6 -5
View File
@@ -1,19 +1,20 @@
/*
* This file is part of mpv.
* This file is part of MPlayer.
*
* mpv is free software; you can redistribute it and/or modify
* MPlayer 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,
* MPlayer 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/>.
*/
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <libavutil/avutil.h>
#include <libavutil/samplefmt.h>
Loaded 100 of 482 files, more files were not shown because too many files have changed in this diff. Show more