1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-20 22:02:59 +00:00
mpv/wscript

1111 lines
39 KiB
Plaintext
Raw Normal View History

# vi: ft=python
import sys, os, re
sys.path.insert(0, os.path.join(os.getcwd(), 'waftools'))
sys.path.insert(0, os.getcwd())
from waflib.Configure import conf
from waflib.Tools import c_preproc
from waflib import Utils
from waftools.checks.generic import *
from waftools.checks.custom import *
c_preproc.go_absolute=True # enable system folders
c_preproc.standard_includes.append('/usr/local/include')
"""
Dependency identifiers (for win32 vs. Unix):
wscript / C source meaning
--------------------------------------------------------------------------
posix / HAVE_POSIX: defined on Linux, OSX, Cygwin
(Cygwin emulates POSIX APIs on Windows)
mingw / __MINGW32__: defined if posix is not defined
(Windows without Cygwin)
os-win32 / _WIN32: defined if basic windows.h API is available
win32-desktop / HAVE_WIN32_DESKTOP: defined if desktop windows.h API is available
uwp / HAVE_UWP: defined if building for UWP (basic Windows only)
"""
build_options = [
{
'name': '--preliminary-lgpl3',
'desc': 'Preliminary LGPLv3+ license',
'default': 'disable',
'func': check_true,
}, {
'name': 'gpl',
'desc': 'GPL build',
'deps': '!preliminary-lgpl3',
'func': check_true,
}, {
'name': 'libaf',
'desc': 'internal audio filter chain',
'deps': 'gpl',
'func': check_true,
}, {
'name': '--cplayer',
'desc': 'mpv CLI player',
'default': 'enable',
'func': check_true
}, {
'name': '--libmpv-shared',
'desc': 'shared library',
'default': 'disable',
'func': check_true
}, {
'name': '--libmpv-static',
'desc': 'static library',
'default': 'disable',
'deps': '!libmpv-shared',
'func': check_true
}, {
'name': '--static-build',
'desc': 'static build',
'default': 'disable',
'func': check_true
}, {
'name': '--build-date',
'desc': 'whether to include binary compile time',
'default': 'enable',
'func': check_true
}, {
'name': '--optimize',
'desc': 'whether to optimize',
'default': 'enable',
'func': check_true
}, {
'name': '--debug-build',
'desc': 'whether to compile-in debugging information',
'default': 'enable',
'func': check_true
}, {
'name': '--manpage-build',
'desc': 'manpage generation',
'func': check_ctx_vars('RST2MAN')
2015-12-29 19:57:09 +00:00
}, {
'name': '--html-build',
'desc': 'html manual generation',
'func': check_ctx_vars('RST2HTML'),
'default': 'disable',
}, {
'name': '--pdf-build',
'desc': 'pdf manual generation',
'func': check_ctx_vars('RST2PDF'),
'default': 'disable',
}, {
'name': 'libdl',
'desc': 'dynamic loader',
'func': check_libs(['dl'], check_statement('dlfcn.h', 'dlopen("", 0)'))
}, {
'name': '--cplugins',
'desc': 'C plugins',
'deps': 'libdl && !os-win32',
'func': check_cc(linkflags=['-rdynamic']),
}, {
'name': '--zsh-comp',
'desc': 'zsh completion',
'func': check_ctx_vars('BIN_PERL'),
'func': check_true,
'default': 'disable',
}, {
# does nothing - left for backward and forward compatibility
'name': '--asm',
'desc': 'inline assembly (currently without effect)',
'default': 'enable',
'func': check_true,
}, {
'name': '--test',
'desc': 'test suite (using cmocka)',
2015-06-12 17:31:55 +00:00
'func': check_pkg_config('cmocka', '>= 1.0.0'),
'default': 'disable',
}, {
'name': '--clang-database',
'desc': 'generate a clang compilation database',
'func': check_true,
'default': 'disable',
}
]
main_dependencies = [
{
'name': 'noexecstack',
'desc': 'compiler support for noexecstack',
'func': check_cc(linkflags='-Wl,-z,noexecstack')
}, {
'name': 'noexecstack',
'desc': 'linker support for --nxcompat --no-seh --dynamicbase',
'func': check_cc(linkflags=['-Wl,--nxcompat', '-Wl,--no-seh', '-Wl,--dynamicbase'])
} , {
'name': 'libm',
'desc': '-lm',
'func': check_cc(lib='m')
}, {
'name': 'mingw',
'desc': 'MinGW',
'deps': 'os-win32',
'func': check_statement('stdlib.h', 'int x = __MINGW32__;'
'int y = __MINGW64_VERSION_MAJOR'),
}, {
'name': 'posix',
'desc': 'POSIX environment',
# This should be good enough.
'func': check_statement(['poll.h', 'unistd.h', 'sys/mman.h'],
'struct pollfd pfd; poll(&pfd, 1, 0); fork(); int f[2]; pipe(f); munmap(f,0)'),
}, {
'name': '--android',
'desc': 'Android environment',
'func': check_statement('android/api-level.h', '(void)__ANDROID__'), # arbitrary android-specific header
}, {
'name': 'posix-or-mingw',
'desc': 'development environment',
'deps': 'posix || mingw',
'func': check_true,
'req': True,
'fmsg': 'Unable to find either POSIX or MinGW-w64 environment, ' \
'or compiler does not work.',
}, {
'name': '--uwp',
'desc': 'Universal Windows Platform',
'default': 'disable',
'deps': 'os-win32 && mingw && !cplayer',
'func': check_cc(lib=['windowsapp']),
}, {
'name': 'win32-desktop',
'desc': 'win32 desktop APIs',
'deps': '(os-win32 || os-cygwin) && !uwp',
'func': check_cc(lib=['winmm', 'gdi32', 'ole32', 'uuid', 'avrt', 'dwmapi']),
}, {
'name': '--win32-internal-pthreads',
'desc': 'internal pthread wrapper for win32 (Vista+)',
'deps': 'os-win32 && !posix',
'func': check_true,
}, {
'name': 'pthreads',
'desc': 'POSIX threads',
'func': check_pthreads,
'req': True,
'fmsg': 'Unable to find pthreads support.'
}, {
'name': 'gnuc',
'desc': 'GNU C extensions',
'func': check_statement([], "__GNUC__"),
}, {
'name': 'stdatomic',
'desc': 'stdatomic.h',
'func': check_libs(['atomic'],
check_statement('stdatomic.h',
'atomic_int_least64_t test = ATOMIC_VAR_INIT(123);'
'atomic_fetch_add(&test, 1)'))
}, {
'name': 'atomics',
'desc': 'stdatomic.h support or slow emulation',
'func': check_true,
'req': True,
'deps': 'stdatomic || gnuc',
}, {
'name': 'librt',
'desc': 'linking with -lrt',
'deps': 'pthreads',
'func': check_cc(lib='rt')
}, {
'name': '--iconv',
'desc': 'iconv',
'func': check_iconv,
'req': True,
'fmsg': "Unable to find iconv which should be part of a standard \
compilation environment. Aborting. If you really mean to compile without \
iconv support use --disable-iconv.",
}, {
'name': 'dos-paths',
'desc': 'w32/dos paths',
'deps': 'os-win32 || os-cygwin',
'func': check_true
}, {
'name': '--termios',
'desc': 'termios',
'func': check_headers('termios.h', 'sys/termios.h'),
}, {
'name': '--shm',
'desc': 'shm',
'func': check_statement(['sys/types.h', 'sys/ipc.h', 'sys/shm.h'],
'shmget(0, 0, 0); shmat(0, 0, 0); shmctl(0, 0, 0)')
}, {
'name': 'nanosleep',
'desc': 'nanosleep',
'func': check_statement('time.h', 'nanosleep(0,0)')
lua: add an utility function for starting processes Because 1) Lua is terrible, and 2) popen() is terrible. Unfortunately, since Unix is also terrible, this turned out more complicated than I hoped. As a consequence and to avoid that this code has to be maintained forever, add a disclaimer that any function in Lua's utils module can disappear any time. The complexity seems a bit ridiculous, especially for a feature so far removed from actual video playback, so if it turns out that we don't really need this function, it will be dropped again. The motivation for this commit is the same as with 8e4fa5fc. Note that there is an "#ifndef __GLIBC__". The GNU people are very special people and thought it'd be convenient to actually declare "environ", even though the POSIX people, which are also very special people, state that no header declares this and that the user has to declare this manually. Since the GNU people overtook the Unix world with their very clever "embrace, extend, extinguish" strategy, but not 100%, and trying to build without _GNU_SOURCE is hopeless; but since there might be Unix environments which support _GNU_SOURCE features partially, this means that in practice "environ" will be randomly declared or not declared by system headers. Also, gcc was written by very clever people too, and prints a warning if an external variable is declared twice (I didn't check, but I suppose redeclaring is legal C, and not even the gcc people are clever enough to only warn against a definitely not legal C construct, although sometimes they do this), ...and since we at mpv hate compiler warnings, we seek to silence them all. Adding a configure test just for a warning seems too radical, so we special-case this against __GLIBC__, which is hopefully not defined on other libcs, especially not libcs which don't implement all aspects of _GNU_SOURCE, and redefine "environ" on systems even if the headers define it already (because they support _GNU_SOURCE - as I mentioned before, the clever GNU people wrote software THAT portable that other libcs just gave up and implemented parts of _GNU_SOURCE, although probably not all), which means that compiling mpv will print a warning about "environ" being redefined, but at least this won't happen on my system, so all is fine. However, should someone complain about this warning, I will force whoever complained about this warning to read this ENTIRE commit message, and if possible, will also force them to eat a printed-out copy of the GNU Manifesto, and if that is not enough, maybe this person could even be forced to convince the very clever POSIX people of not doing crap like this: having the user to manually declare somewhat central symbols - but I doubt it's possible, because the POSIX people are too far gone and only care about maintaining compatibility with old versions of AIX and HP-UX. Oh, also, this code contains some subtle and obvious issues, but writing about this is not fun.
2014-10-18 23:42:28 +00:00
}, {
'name': 'posix-spawn-native',
'desc': 'spawnp()/kill() POSIX support',
2014-10-19 10:55:29 +00:00
'func': check_statement(['spawn.h', 'signal.h'],
'posix_spawnp(0,0,0,0,0,0); kill(0,0)'),
'deps': '!mingw',
}, {
'name': 'posix-spawn-android',
'desc': 'spawnp()/kill() Android replacement',
'func': check_true,
'deps': 'android && !posix-spawn-native',
},{
'name': 'posix-spawn',
'desc': 'any spawnp()/kill() support',
'deps': 'posix-spawn-native || posix-spawn-android',
'func': check_true,
}, {
'name': 'win32-pipes',
'desc': 'Windows pipe support',
'func': check_true,
'deps': 'win32-desktop && !posix',
}, {
'name': 'glob-posix',
'desc': 'glob() POSIX support',
'deps': '!(os-win32 || os-cygwin)',
'func': check_statement('glob.h', 'glob("filename", 0, 0, 0)'),
}, {
'name': 'glob-win32',
'desc': 'glob() win32 replacement',
'deps': '!posix && (os-win32 || os-cygwin)',
'func': check_true
}, {
'name': 'glob',
'desc': 'any glob() support',
'deps': 'glob-posix || glob-win32',
'func': check_true,
}, {
'name': 'fchmod',
'desc': 'fchmod()',
'func': check_statement('sys/stat.h', 'fchmod(0, 0)'),
}, {
'name': 'vt.h',
'desc': 'vt.h',
'func': check_statement(['sys/vt.h', 'sys/ioctl.h'],
'int m; ioctl(0, VT_GETMODE, &m)'),
vo_opengl: add DRM EGL backend Notes: - Unfortunately the only way to talk to EGL from within DRM I could find involves linking with GBM (generic buffer management for Mesa.) Because of this, I'm pretty sure it won't work with proprietary NVidia drivers, but then again, last time I checked NVidia didn't offer proper screen resolution for VT. - VT switching doesn't seem to work at all. It's worth mentioning that using vo_drm before introduction of VT switcher had an anomaly where user could switch to another VT and input text to it, while video played on top of that VT. However, that isn't the case with drm_egl: I can't switch to other VT during playback like this. This makes me think that it's either a limitation coming from my firmware or from EGL/KMS itself rather than a bug with my code. Nonetheless, I still left (untestable) VT switching code in place, in case it's useful to someone else. - The mode_id, connector_id and device_path should be configurable for power users and people who wish to watch videos on nonprimary screen. Unfortunately I didn't see anything that would allow OpenGL backends to register their own set of options. At the same time, adding them to global namespace is pointless. - A few dozens of lines could be shared with vo_drm (setting up VT switching, most of code behind page flipping). I don't have any strong opinion on this. - Sometimes I get minor visual glitches. I'm not sure if there's a race condition of some sort, unitialized variable (doubtful), or if it's buggy driver. (I'm using integrated Intel HD Graphics 4400 with Mesa) - .config and .control are very minimal. Signed-off-by: wm4 <wm4@nowhere>
2015-11-07 18:06:57 +00:00
}, {
'name': 'gbm.h',
'desc': 'gbm.h',
'func': check_cc(header_name=['stdio.h', 'gbm.h']),
}, {
'name': 'glibc-thread-name',
'desc': 'GLIBC API for setting thread name',
'func': check_statement('pthread.h',
'pthread_setname_np(pthread_self(), "ducks")',
use=['pthreads']),
}, {
'name': 'osx-thread-name',
'desc': 'OSX API for setting thread name',
'deps': '!glibc-thread-name',
'func': check_statement('pthread.h',
'pthread_setname_np("ducks")', use=['pthreads']),
}, {
'name': 'bsd-thread-name',
'desc': 'BSD API for setting thread name',
'deps': '!(glibc-thread-name || osx-thread-name)',
'func': check_statement('pthread.h',
'pthread_set_name_np(pthread_self(), "ducks")',
use=['pthreads']),
}, {
'name': 'bsd-fstatfs',
'desc': "BSD's fstatfs()",
'func': check_statement(['sys/param.h', 'sys/mount.h'],
'struct statfs fs; fstatfs(0, &fs); fs.f_fstypename')
}, {
'name': 'linux-fstatfs',
'desc': "Linux's fstatfs()",
'deps': 'os-linux',
'func': check_statement('sys/vfs.h',
'struct statfs fs; fstatfs(0, &fs); fs.f_namelen')
}, {
'name': '--libsmbclient',
'desc': 'Samba support (makes mpv GPLv3)',
'deps': 'libdl && gpl',
'func': check_pkg_config('smbclient'),
'default': 'disable',
'module': 'input',
}, {
'name' : '--lua',
'desc' : 'Lua',
'func': check_lua,
}, {
'name' : '--javascript',
'desc' : 'Javascript (MuJS backend)',
'func': check_pkg_config('mujs', '>= 1.0.0'),
}, {
'name': '--libass',
'desc': 'SSA/ASS support',
'func': check_pkg_config('libass', '>= 0.12.1'),
'req': True,
'fmsg': "Unable to find development files for libass, or the version " +
"found is too old. Aborting. If you really mean to compile " +
"without libass support use --disable-libass."
}, {
'name': '--libass-osd',
'desc': 'libass OSD support',
'deps': 'libass',
'func': check_true,
}, {
'name': 'dummy-osd',
'desc': 'dummy OSD support',
'deps': '!libass-osd',
'func': check_true,
} , {
'name': '--zlib',
'desc': 'zlib',
'func': check_libs(['z'],
check_statement('zlib.h', 'inflate(0, Z_NO_FLUSH)')),
'req': True,
'fmsg': 'Unable to find development files for zlib.'
} , {
'name' : '--encoding',
'desc' : 'Encoding',
'func': check_true,
}, {
'name': '--libbluray',
'desc': 'Bluray support',
'func': check_pkg_config('libbluray', '>= 0.3.0'),
#'default': 'disable',
}, {
'name': '--dvdread',
'desc': 'dvdread support',
'deps': 'gpl',
'func': check_pkg_config('dvdread', '>= 4.1.0'),
'default': 'disable',
}, {
'name': '--dvdnav',
'desc': 'dvdnav support',
'deps': 'gpl',
'func': check_pkg_config('dvdnav', '>= 4.2.0',
'dvdread', '>= 4.1.0'),
'default': 'disable',
}, {
'name': 'dvdread-common',
'desc': 'DVD/IFO support',
'deps': 'gpl && (dvdread || dvdnav)',
'func': check_true,
}, {
'name': '--cdda',
'desc': 'cdda support (libcdio)',
'deps': 'gpl',
'func': check_pkg_config('libcdio_paranoia'),
'default': 'disable',
}, {
'name': '--uchardet',
'desc': 'uchardet support',
'deps': 'iconv',
'func': check_pkg_config('uchardet'),
}, {
'name': '--rubberband',
'desc': 'librubberband support',
'deps': 'libaf',
'func': check_pkg_config('rubberband', '>= 1.8.0'),
}, {
'name': '--lcms2',
'desc': 'LCMS2 support',
'func': check_pkg_config('lcms2', '>= 2.6'),
}, {
'name': '--vapoursynth',
'desc': 'VapourSynth filter bridge (Python)',
'func': check_pkg_config('vapoursynth', '>= 24',
'vapoursynth-script', '>= 23'),
}, {
'name': '--vapoursynth-lazy',
'desc': 'VapourSynth filter bridge (Lazy Lua)',
'deps': 'lua',
'func': check_pkg_config('vapoursynth', '>= 24'),
}, {
'name': 'vapoursynth-core',
'desc': 'VapourSynth filter bridge (core)',
'deps': 'vapoursynth || vapoursynth-lazy',
'func': check_true,
}, {
'name': '--libarchive',
'desc': 'libarchive wrapper for reading zip files and more',
'func': check_pkg_config('libarchive >= 3.0.0'),
'default': 'disable',
}
]
ffmpeg_version = "3.2.2"
ffmpeg_pkg_config_checks = [
'libavutil', '>= 55.34.100',
'libavcodec', '>= 57.64.100',
'libavformat', '>= 57.56.100',
'libswscale', '>= 4.2.100',
'libavfilter', '>= 6.65.100',
'libswresample', '>= 2.3.100',
]
libav_version = "12"
libav_pkg_config_checks = [
'libavutil', '>= 55.20.0',
'libavcodec', '>= 57.25.0',
'libavformat', '>= 57.7.0',
'libswscale', '>= 4.0.0',
'libavfilter', '>= 6.7.0',
'libavresample', '>= 3.0.0',
]
libav_versions_string = "FFmpeg %s or Libav %s" % (ffmpeg_version, libav_version)
def check_ffmpeg_or_libav_versions():
def fn(ctx, dependency_identifier, **kw):
versions = ffmpeg_pkg_config_checks
if ctx.dependency_satisfied('is_libav'):
versions = libav_pkg_config_checks
return check_pkg_config(*versions)(ctx, dependency_identifier, **kw)
return fn
libav_dependencies = [
{
'name': 'libavcodec',
'desc': 'FFmpeg/Libav present',
'func': check_pkg_config('libavcodec'),
'req': True,
'fmsg': "FFmpeg/Libav development files not found.",
}, {
'name': 'is_ffmpeg',
'desc': 'libav* is FFmpeg',
# FFmpeg <=> LIBAVUTIL_VERSION_MICRO>=100
'func': check_statement('libavcodec/version.h',
'int x[LIBAVCODEC_VERSION_MICRO >= 100 ? 1 : -1]',
use='libavcodec')
}, {
# This check should always result in the opposite of is_ffmpeg.
# Run it to make sure is_ffmpeg didn't fail for some other reason than
# the actual version check.
'name': 'is_libav',
'desc': 'libav* is Libav',
# FFmpeg <=> LIBAVUTIL_VERSION_MICRO>=100
'func': check_statement('libavcodec/version.h',
'int x[LIBAVCODEC_VERSION_MICRO >= 100 ? -1 : 1]',
use='libavcodec')
}, {
'name': 'libav',
'desc': 'Libav/FFmpeg library versions',
'deps': 'is_ffmpeg || is_libav',
'func': check_ffmpeg_or_libav_versions(),
'req': True,
'fmsg': "Unable to find development files for some of the required \
FFmpeg/Libav libraries. You need at least {0}. Aborting.".format(libav_versions_string)
}, {
'name': '--libavdevice',
'desc': 'libavdevice',
'func': check_pkg_config('libavdevice', '>= 57.0.0'),
}, {
'name': 'avutil-content-light-level',
'desc': 'libavutil content light level struct',
'func': check_statement('libavutil/frame.h',
'AV_FRAME_DATA_CONTENT_LIGHT_LEVEL',
use='libav'),
}, {
'name': 'avutil-icc-profile',
'desc': 'libavutil ICC profile side data',
'func': check_statement('libavutil/frame.h',
'AV_FRAME_DATA_ICC_PROFILE',
use='libav'),
}, {
'name': 'avutil-spherical',
'desc': 'libavutil spherical side data',
'func': check_statement('libavutil/spherical.h',
'AV_SPHERICAL_EQUIRECTANGULAR',
use='libav'),
},
]
audio_output_features = [
{
'name': '--sdl2',
'desc': 'SDL2',
'func': check_pkg_config('sdl2'),
'default': 'disable'
}, {
'name': '--sdl1',
'desc': 'SDL (1.x)',
'deps': '!sdl2',
'func': check_pkg_config('sdl'),
'default': 'disable'
}, {
'name': '--oss-audio',
'desc': 'OSS',
'func': check_cc(header_name='sys/soundcard.h'),
'deps': 'posix && gpl',
}, {
'name': '--rsound',
'desc': 'RSound audio output',
'func': check_statement('rsound.h', 'rsd_init(NULL)', lib='rsound')
}, {
'name': '--sndio',
'desc': 'sndio audio input/output',
'func': check_statement('sndio.h',
'struct sio_par par; sio_initpar(&par); const char *s = SIO_DEVANY', lib='sndio'),
'default': 'disable'
}, {
'name': '--pulse',
'desc': 'PulseAudio audio output',
'func': check_pkg_config('libpulse', '>= 1.0')
}, {
'name': '--jack',
'desc': 'JACK audio output',
'deps': 'gpl',
'func': check_pkg_config('jack'),
}, {
'name': '--openal',
'desc': 'OpenAL audio output',
'func': check_openal,
'default': 'disable'
}, {
'name': '--opensles',
'desc': 'OpenSL ES audio output',
'func': check_statement('SLES/OpenSLES.h', 'slCreateEngine', lib="OpenSLES"),
}, {
'name': '--alsa',
'desc': 'ALSA audio output',
'deps': 'gpl',
'func': check_pkg_config('alsa', '>= 1.0.18'),
}, {
'name': '--coreaudio',
'desc': 'CoreAudio audio output',
'func': check_cc(
fragment=load_fragment('coreaudio.c'),
framework_name=['CoreFoundation', 'CoreAudio', 'AudioUnit', 'AudioToolbox'])
}, {
'name': '--audiounit',
'desc': 'AudioUnit output for iOS',
'deps': 'atomics',
'func': check_cc(
fragment=load_fragment('audiounit.c'),
framework_name=['Foundation', 'AudioToolbox'])
}, {
'name': '--wasapi',
'desc': 'WASAPI audio output',
'deps': 'os-win32 || os-cygwin',
'func': check_cc(fragment=load_fragment('wasapi.c')),
}
]
video_output_features = [
{
'name': '--cocoa',
'desc': 'Cocoa',
'func': check_cocoa
vo_opengl: add DRM EGL backend Notes: - Unfortunately the only way to talk to EGL from within DRM I could find involves linking with GBM (generic buffer management for Mesa.) Because of this, I'm pretty sure it won't work with proprietary NVidia drivers, but then again, last time I checked NVidia didn't offer proper screen resolution for VT. - VT switching doesn't seem to work at all. It's worth mentioning that using vo_drm before introduction of VT switcher had an anomaly where user could switch to another VT and input text to it, while video played on top of that VT. However, that isn't the case with drm_egl: I can't switch to other VT during playback like this. This makes me think that it's either a limitation coming from my firmware or from EGL/KMS itself rather than a bug with my code. Nonetheless, I still left (untestable) VT switching code in place, in case it's useful to someone else. - The mode_id, connector_id and device_path should be configurable for power users and people who wish to watch videos on nonprimary screen. Unfortunately I didn't see anything that would allow OpenGL backends to register their own set of options. At the same time, adding them to global namespace is pointless. - A few dozens of lines could be shared with vo_drm (setting up VT switching, most of code behind page flipping). I don't have any strong opinion on this. - Sometimes I get minor visual glitches. I'm not sure if there's a race condition of some sort, unitialized variable (doubtful), or if it's buggy driver. (I'm using integrated Intel HD Graphics 4400 with Mesa) - .config and .control are very minimal. Signed-off-by: wm4 <wm4@nowhere>
2015-11-07 18:06:57 +00:00
}, {
'name': '--drm',
'desc': 'DRM',
'deps': 'vt.h',
vo_opengl: add DRM EGL backend Notes: - Unfortunately the only way to talk to EGL from within DRM I could find involves linking with GBM (generic buffer management for Mesa.) Because of this, I'm pretty sure it won't work with proprietary NVidia drivers, but then again, last time I checked NVidia didn't offer proper screen resolution for VT. - VT switching doesn't seem to work at all. It's worth mentioning that using vo_drm before introduction of VT switcher had an anomaly where user could switch to another VT and input text to it, while video played on top of that VT. However, that isn't the case with drm_egl: I can't switch to other VT during playback like this. This makes me think that it's either a limitation coming from my firmware or from EGL/KMS itself rather than a bug with my code. Nonetheless, I still left (untestable) VT switching code in place, in case it's useful to someone else. - The mode_id, connector_id and device_path should be configurable for power users and people who wish to watch videos on nonprimary screen. Unfortunately I didn't see anything that would allow OpenGL backends to register their own set of options. At the same time, adding them to global namespace is pointless. - A few dozens of lines could be shared with vo_drm (setting up VT switching, most of code behind page flipping). I don't have any strong opinion on this. - Sometimes I get minor visual glitches. I'm not sure if there's a race condition of some sort, unitialized variable (doubtful), or if it's buggy driver. (I'm using integrated Intel HD Graphics 4400 with Mesa) - .config and .control are very minimal. Signed-off-by: wm4 <wm4@nowhere>
2015-11-07 18:06:57 +00:00
'func': check_pkg_config('libdrm'),
}, {
'name': '--gbm',
'desc': 'GBM',
'deps': 'gbm.h',
vo_opengl: add DRM EGL backend Notes: - Unfortunately the only way to talk to EGL from within DRM I could find involves linking with GBM (generic buffer management for Mesa.) Because of this, I'm pretty sure it won't work with proprietary NVidia drivers, but then again, last time I checked NVidia didn't offer proper screen resolution for VT. - VT switching doesn't seem to work at all. It's worth mentioning that using vo_drm before introduction of VT switcher had an anomaly where user could switch to another VT and input text to it, while video played on top of that VT. However, that isn't the case with drm_egl: I can't switch to other VT during playback like this. This makes me think that it's either a limitation coming from my firmware or from EGL/KMS itself rather than a bug with my code. Nonetheless, I still left (untestable) VT switching code in place, in case it's useful to someone else. - The mode_id, connector_id and device_path should be configurable for power users and people who wish to watch videos on nonprimary screen. Unfortunately I didn't see anything that would allow OpenGL backends to register their own set of options. At the same time, adding them to global namespace is pointless. - A few dozens of lines could be shared with vo_drm (setting up VT switching, most of code behind page flipping). I don't have any strong opinion on this. - Sometimes I get minor visual glitches. I'm not sure if there's a race condition of some sort, unitialized variable (doubtful), or if it's buggy driver. (I'm using integrated Intel HD Graphics 4400 with Mesa) - .config and .control are very minimal. Signed-off-by: wm4 <wm4@nowhere>
2015-11-07 18:06:57 +00:00
'func': check_pkg_config('gbm'),
} , {
'name': '--wayland',
'desc': 'Wayland',
'func': check_pkg_config('wayland-client', '>= 1.6.0',
'wayland-cursor', '>= 1.6.0',
'xkbcommon', '>= 0.3.0'),
} , {
'name': '--x11',
'desc': 'X11',
'deps': 'gpl',
'func': check_pkg_config('x11', '>= 1.0.0',
'xscrnsaver', '>= 1.0.0',
'xext', '>= 1.0.0',
'xinerama', '>= 1.0.0',
'xrandr', '>= 1.2.0'),
} , {
'name': '--xv',
'desc': 'Xv video output',
'deps': 'x11',
'func': check_pkg_config('xv'),
} , {
'name': '--gl-cocoa',
'desc': 'OpenGL Cocoa Backend',
'deps': 'cocoa',
'groups': [ 'gl' ],
'func': check_statement('IOSurface/IOSurface.h',
'IOSurfaceRef surface;',
framework='IOSurface')
} , {
'name': '--gl-x11',
'desc': 'OpenGL X11 Backend',
'deps': 'x11',
'groups': [ 'gl' ],
'func': check_libs(['GL', 'GL Xdamage'],
check_cc(fragment=load_fragment('gl_x11.c'),
use=['x11', 'libdl', 'pthreads']))
} , {
'name': '--egl-x11',
'desc': 'OpenGL X11 EGL Backend',
'deps': 'x11',
'groups': [ 'gl' ],
'func': check_pkg_config('egl'),
vo_opengl: add DRM EGL backend Notes: - Unfortunately the only way to talk to EGL from within DRM I could find involves linking with GBM (generic buffer management for Mesa.) Because of this, I'm pretty sure it won't work with proprietary NVidia drivers, but then again, last time I checked NVidia didn't offer proper screen resolution for VT. - VT switching doesn't seem to work at all. It's worth mentioning that using vo_drm before introduction of VT switcher had an anomaly where user could switch to another VT and input text to it, while video played on top of that VT. However, that isn't the case with drm_egl: I can't switch to other VT during playback like this. This makes me think that it's either a limitation coming from my firmware or from EGL/KMS itself rather than a bug with my code. Nonetheless, I still left (untestable) VT switching code in place, in case it's useful to someone else. - The mode_id, connector_id and device_path should be configurable for power users and people who wish to watch videos on nonprimary screen. Unfortunately I didn't see anything that would allow OpenGL backends to register their own set of options. At the same time, adding them to global namespace is pointless. - A few dozens of lines could be shared with vo_drm (setting up VT switching, most of code behind page flipping). I don't have any strong opinion on this. - Sometimes I get minor visual glitches. I'm not sure if there's a race condition of some sort, unitialized variable (doubtful), or if it's buggy driver. (I'm using integrated Intel HD Graphics 4400 with Mesa) - .config and .control are very minimal. Signed-off-by: wm4 <wm4@nowhere>
2015-11-07 18:06:57 +00:00
} , {
'name': '--egl-drm',
'desc': 'OpenGL DRM EGL Backend',
'deps': 'drm && gbm',
vo_opengl: add DRM EGL backend Notes: - Unfortunately the only way to talk to EGL from within DRM I could find involves linking with GBM (generic buffer management for Mesa.) Because of this, I'm pretty sure it won't work with proprietary NVidia drivers, but then again, last time I checked NVidia didn't offer proper screen resolution for VT. - VT switching doesn't seem to work at all. It's worth mentioning that using vo_drm before introduction of VT switcher had an anomaly where user could switch to another VT and input text to it, while video played on top of that VT. However, that isn't the case with drm_egl: I can't switch to other VT during playback like this. This makes me think that it's either a limitation coming from my firmware or from EGL/KMS itself rather than a bug with my code. Nonetheless, I still left (untestable) VT switching code in place, in case it's useful to someone else. - The mode_id, connector_id and device_path should be configurable for power users and people who wish to watch videos on nonprimary screen. Unfortunately I didn't see anything that would allow OpenGL backends to register their own set of options. At the same time, adding them to global namespace is pointless. - A few dozens of lines could be shared with vo_drm (setting up VT switching, most of code behind page flipping). I don't have any strong opinion on this. - Sometimes I get minor visual glitches. I'm not sure if there's a race condition of some sort, unitialized variable (doubtful), or if it's buggy driver. (I'm using integrated Intel HD Graphics 4400 with Mesa) - .config and .control are very minimal. Signed-off-by: wm4 <wm4@nowhere>
2015-11-07 18:06:57 +00:00
'groups': [ 'gl' ],
'func': check_pkg_config('egl'),
} , {
'name': '--gl-wayland',
'desc': 'OpenGL Wayland Backend',
'deps': 'wayland',
'groups': [ 'gl' ],
'func': check_pkg_config('wayland-egl', '>= 9.0.0',
'egl', '>= 9.0.0')
} , {
'name': '--gl-win32',
'desc': 'OpenGL Win32 Backend',
'deps': 'win32-desktop',
'groups': [ 'gl' ],
'func': check_statement('windows.h', 'wglCreateContext(0)',
lib='opengl32')
} , {
'name': '--gl-dxinterop',
'desc': 'OpenGL/DirectX Interop Backend',
'deps': 'gl-win32',
'groups': [ 'gl' ],
'func': compose_checks(
check_statement(['GL/gl.h', 'GL/wglext.h'], 'int i = WGL_ACCESS_WRITE_DISCARD_NV'),
check_statement('d3d9.h', 'IDirect3D9Ex *d'))
} , {
'name': '--egl-angle',
'desc': 'OpenGL ANGLE headers',
'deps': 'os-win32 || os-cygwin',
'groups': [ 'gl' ],
'func': check_statement(['EGL/egl.h', 'EGL/eglext.h'],
'int x = EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE')
2016-11-22 22:26:43 +00:00
} , {
'name': '--egl-angle-lib',
'desc': 'OpenGL Win32 ANGLE Library',
'deps': 'egl-angle',
2016-11-22 22:26:43 +00:00
'groups': [ 'gl' ],
'func': check_statement(['EGL/egl.h'],
'eglCreateWindowSurface(0, 0, 0, 0)',
cflags=['-DGL_APICALL=', '-DEGLAPI=',
'-DANGLE_NO_ALIASES', '-DANGLE_EXPORT='],
lib=['EGL', 'GLESv2', 'dxguid', 'd3d9',
'gdi32', 'stdc++'])
}, {
'name': '--egl-angle-win32',
'desc': 'OpenGL Win32 ANGLE Backend',
'deps': 'egl-angle && win32-desktop',
'groups': [ 'gl' ],
'func': check_true,
} , {
'name': '--vdpau',
'desc': 'VDPAU acceleration',
'deps': 'x11',
'func': check_pkg_config('vdpau', '>= 0.2'),
} , {
'name': '--vdpau-gl-x11',
'desc': 'VDPAU with OpenGL/X11',
'deps': 'vdpau && gl-x11',
'func': check_true,
}, {
'name': '--vaapi',
'desc': 'VAAPI acceleration',
'deps': 'gpl && libdl && (x11 || wayland || egl-drm)',
'func': check_pkg_config('libva', '>= 0.36.0'),
}, {
'name': '--vaapi-x11',
'desc': 'VAAPI (X11 support)',
'deps': 'vaapi && x11',
'func': check_pkg_config('libva-x11', '>= 0.36.0'),
}, {
'name': '--vaapi-wayland',
'desc': 'VAAPI (Wayland support)',
'deps': 'vaapi && gl-wayland',
'func': check_pkg_config('libva-wayland', '>= 0.36.0'),
}, {
'name': '--vaapi-drm',
'desc': 'VAAPI (DRM/EGL support)',
'deps': 'vaapi && egl-drm',
'func': check_pkg_config('libva-drm', '>= 0.36.0'),
}, {
'name': '--vaapi-glx',
'desc': 'VAAPI GLX',
'deps': 'vaapi-x11 && gl-x11',
'func': check_true,
}, {
'name': '--vaapi-x-egl',
'desc': 'VAAPI EGL on X11',
'deps': 'vaapi-x11 && egl-x11',
'func': check_true,
}, {
'name': 'vaapi-egl',
'desc': 'VAAPI EGL',
'deps': 'vaapi-x-egl || vaapi-wayland',
'func': check_true,
}, {
'name': '--caca',
'desc': 'CACA',
'deps': 'gpl',
'func': check_pkg_config('caca', '>= 0.99.beta18'),
}, {
'name': '--jpeg',
'desc': 'JPEG support',
'func': check_cc(header_name=['stdio.h', 'jpeglib.h'],
lib='jpeg', use='libm'),
}, {
'name': '--direct3d',
'desc': 'Direct3D support',
'deps': 'win32-desktop && gpl',
'func': check_cc(header_name='d3d9.h'),
}, {
# We need MMAL/bcm_host/dispmanx APIs. Also, most RPI distros require
# every project to hardcode the paths to the include directories. Also,
# these headers are so broken that they spam tons of warnings by merely
# including them (compensate with -isystem and -fgnu89-inline).
'name': '--rpi',
RPI support This requires FFmpeg git master for accelerated hardware decoding. Keep in mind that FFmpeg must be compiled with --enable-mmal. Libav will also work. Most things work. Screenshots don't work with accelerated/opaque decoding (except using full window screenshot mode). Subtitles are very slow - even simple but huge overlays can cause frame drops. This always uses fullscreen mode. It uses dispmanx and mmal directly, and there are no window managers or anything on this level. vo_opengl also kind of works, but is pretty useless and slow. It can't use opaque hardware decoding (copy back can be used by forcing the option --vd=lavc:h264_mmal). Keep in mind that the dispmanx backend is preferred over the X11 ones in case you're trying on X11; but X11 is even more useless on RPI. This doesn't correctly reject extended h264 profiles and thus doesn't fallback to software decoding. The hw supports only up to the high profile, and will e.g. return garbage for Hi10P video. This sets a precedent of enabling hw decoding by default, but only if RPI support is compiled (which most hopefully it will be disabled on desktop Linux platforms). While it's more or less required to use hw decoding on the weak RPI, it causes more problems than it solves on real platforms (Linux has the Intel GPU problem, OSX still has some cases with broken decoding.) So I can live with this compromise of having different defaults depending on the platform. Raspberry Pi 2 is required. This wasn't tested on the original RPI, though at least decoding itself seems to work (but full playback was not tested).
2015-03-29 13:12:11 +00:00
'desc': 'Raspberry Pi support',
'func': compose_checks(
check_cc(cflags="-isystem/opt/vc/include/ "+
"-isystem/opt/vc/include/interface/vcos/pthreads " +
"-isystem/opt/vc/include/interface/vmcs_host/linux " +
"-fgnu89-inline",
linkflags="-L/opt/vc/lib",
header_name="bcm_host.h",
lib=['mmal_core', 'mmal_util', 'mmal_vc_client', 'bcm_host']),
# We still need all OpenGL symbols, because the vo_opengl code is
# generic and supports anything from GLES2/OpenGL 2.1 to OpenGL 4 core.
check_cc(lib="EGL"),
check_cc(lib="GLESv2"),
),
} , {
'name': '--ios-gl',
vo_opengl: add our own copy of OpenGL headers gl_headers.h is basically header_fixes.h done consequently. It contains all OpenGL defines (and some typedefs) we need. We don't include GL headers provided by the system anymore. Some care has to be taken by certain windowing APIs including all of gl.h anyway. Then the definitions could clash. Fortunately, redefining preprocessor symbols to the same content is allowed and ignored. Also, redefining typedefs to the same thing is allowed in C11. Apparently the latter is not allowed in C99, so there is an imperfect attempt to avoid the typedefs if required API symbols are apparently present already. The nost risky part about this are the standard typedefs and GLAPIENTRY. The latter is different only on win32 (and at least consistently so). The typedefs are mostly based on stdint.h typedefs, which khrplatform.h clumsily emulates on platforms which don't have it. The biggest difference is that we define GLsizeiptr directly to ptrdiff_t, instead of checking for the _WIN64 symbol and defining it to long or long long. This also typedefs GLsync to __GLsync, just like the khronos headers. Although symbols prefixed with __ are implementation reserved, khronos also violates this rule, and having the same definition as khronos will avoid problems on duplicate definitions. We can simplify the build scripts too. The ios-gl check seems a bit wrong now (what we really want to test for is EAGLContext), but I can't test and thus can't improve it. cuda_dynamic.h redefined two GL symbols; just include the new headers directly instead.
2017-04-07 12:30:51 +00:00
'desc': 'iOS OpenGL ES hardware decoding interop support',
'func': check_statement('OpenGLES/ES3/glext.h', '(void)GL_RGB32F'), # arbitrary OpenGL ES 3.0 symbol
} , {
'name': '--plain-gl',
'desc': 'OpenGL without platform-specific code (e.g. for libmpv)',
'deps': 'libmpv-shared || libmpv-static',
'func': check_true,
}, {
'name': '--mali-fbdev',
'desc': 'MALI via Linux fbdev',
'deps': 'libdl',
'func': compose_checks(
check_cc(lib="EGL"),
check_statement('EGL/fbdev_window.h', 'struct fbdev_window test'),
check_statement('linux/fb.h', 'struct fb_var_screeninfo test'),
),
}, {
RPI support This requires FFmpeg git master for accelerated hardware decoding. Keep in mind that FFmpeg must be compiled with --enable-mmal. Libav will also work. Most things work. Screenshots don't work with accelerated/opaque decoding (except using full window screenshot mode). Subtitles are very slow - even simple but huge overlays can cause frame drops. This always uses fullscreen mode. It uses dispmanx and mmal directly, and there are no window managers or anything on this level. vo_opengl also kind of works, but is pretty useless and slow. It can't use opaque hardware decoding (copy back can be used by forcing the option --vd=lavc:h264_mmal). Keep in mind that the dispmanx backend is preferred over the X11 ones in case you're trying on X11; but X11 is even more useless on RPI. This doesn't correctly reject extended h264 profiles and thus doesn't fallback to software decoding. The hw supports only up to the high profile, and will e.g. return garbage for Hi10P video. This sets a precedent of enabling hw decoding by default, but only if RPI support is compiled (which most hopefully it will be disabled on desktop Linux platforms). While it's more or less required to use hw decoding on the weak RPI, it causes more problems than it solves on real platforms (Linux has the Intel GPU problem, OSX still has some cases with broken decoding.) So I can live with this compromise of having different defaults depending on the platform. Raspberry Pi 2 is required. This wasn't tested on the original RPI, though at least decoding itself seems to work (but full playback was not tested).
2015-03-29 13:12:11 +00:00
'name': '--gl',
vo_opengl: refactor into vo_gpu This is done in several steps: 1. refactor MPGLContext -> struct ra_ctx 2. move GL-specific stuff in vo_opengl into opengl/context.c 3. generalize context creation to support other APIs, and add --gpu-api 4. rename all of the --opengl- options that are no longer opengl-specific 5. move all of the stuff from opengl/* that isn't GL-specific into gpu/ (note: opengl/gl_utils.h became opengl/utils.h) 6. rename vo_opengl to vo_gpu 7. to handle window screenshots, the short-term approach was to just add it to ra_swchain_fns. Long term (and for vulkan) this has to be moved to ra itself (and vo_gpu altered to compensate), but this was a stop-gap measure to prevent this commit from getting too big 8. move ra->fns->flush to ra_gl_ctx instead 9. some other minor changes that I've probably already forgotten Note: This is one half of a major refactor, the other half of which is provided by rossy's following commit. This commit enables support for all linux platforms, while his version enables support for all non-linux platforms. Note 2: vo_opengl_cb.c also re-uses ra_gl_ctx so it benefits from the --opengl- options like --opengl-early-flush, --opengl-finish etc. Should be a strict superset of the old functionality. Disclaimer: Since I have no way of compiling mpv on all platforms, some of these ports were done blindly. Specifically, the blind ports included context_mali_fbdev.c and context_rpi.c. Since they're both based on egl_helpers, the port should have gone smoothly without any major changes required. But if somebody complains about a compile error on those platforms (assuming anybody actually uses them), you know where to complain.
2017-09-14 06:04:55 +00:00
'desc': 'OpenGL context support',
'deps': 'gl-cocoa || gl-x11 || egl-x11 || egl-drm || '
+ 'gl-win32 || gl-wayland || rpi || mali-fbdev || '
+ 'plain-gl',
'func': check_true,
'req': True,
'fmsg': "No OpenGL video output found or enabled. " +
"Aborting. If you really mean to compile without OpenGL " +
"video outputs use --disable-gl.",
vo_gpu: vulkan: initial implementation This time based on ra/vo_gpu. 2017 is the year of the vulkan desktop! Current problems / limitations / improvement opportunities: 1. The swapchain/flipping code violates the vulkan spec, by assuming that the presentation queue will be bounded (in cases where rendering is significantly faster than vsync). But apparently, there's simply no better way to do this right now, to the point where even the stupid cube.c examples from LunarG etc. do it wrong. (cf. https://github.com/KhronosGroup/Vulkan-Docs/issues/370) 2. The memory allocator could be improved. (This is a universal constant) 3. Could explore using push descriptors instead of descriptor sets, especially since we expect to switch descriptors semi-often for some passes (like interpolation). Probably won't make a difference, but the synchronization overhead might be a factor. Who knows. 4. Parallelism across frames / async transfer is not well-defined, we either need to use a better semaphore / command buffer strategy or a resource pooling layer to safely handle cross-frame parallelism. (That said, I gave resource pooling a try and was not happy with the result at all - so I'm still exploring the semaphore strategy) 5. We aggressively use pipeline barriers where events would offer a much more fine-grained synchronization mechanism. As a result of this, we might be suffering from GPU bubbles due to too-short dependencies on objects. (That said, I'm also exploring the use of semaphores as a an ordering tactic which would allow cross-frame time slicing in theory) Some minor changes to the vo_gpu and infrastructure, but nothing consequential. NOTE: For safety, all use of asynchronous commands / multiple command pools is currently disabled completely. There are some left-over relics of this in the code (e.g. the distinction between dev_poll and pool_poll), but that is kept in place mostly because this will be re-extended in the future (vulkan rev 2). The queue count is also currently capped to 1, because of the lack of cross-frame semaphores means we need the implicit synchronization from the same-queue semantics to guarantee a correct result.
2016-09-14 18:54:18 +00:00
}, {
'name': '--vulkan',
'desc': 'Vulkan context support',
'func': check_cc(header_name='vulkan/vulkan.h', lib='vulkan'),
}, {
'name': '--shaderc',
'desc': 'libshaderc SPIR-V compiler',
'func': check_cc(header_name='shaderc/shaderc.h', lib='shaderc_shared'),
}, {
'name': 'egl-helpers',
'desc': 'EGL helper functions',
'deps': 'egl-x11 || mali-fbdev || rpi || gl-wayland || egl-drm || ' +
'egl-angle-win32',
RPI support This requires FFmpeg git master for accelerated hardware decoding. Keep in mind that FFmpeg must be compiled with --enable-mmal. Libav will also work. Most things work. Screenshots don't work with accelerated/opaque decoding (except using full window screenshot mode). Subtitles are very slow - even simple but huge overlays can cause frame drops. This always uses fullscreen mode. It uses dispmanx and mmal directly, and there are no window managers or anything on this level. vo_opengl also kind of works, but is pretty useless and slow. It can't use opaque hardware decoding (copy back can be used by forcing the option --vd=lavc:h264_mmal). Keep in mind that the dispmanx backend is preferred over the X11 ones in case you're trying on X11; but X11 is even more useless on RPI. This doesn't correctly reject extended h264 profiles and thus doesn't fallback to software decoding. The hw supports only up to the high profile, and will e.g. return garbage for Hi10P video. This sets a precedent of enabling hw decoding by default, but only if RPI support is compiled (which most hopefully it will be disabled on desktop Linux platforms). While it's more or less required to use hw decoding on the weak RPI, it causes more problems than it solves on real platforms (Linux has the Intel GPU problem, OSX still has some cases with broken decoding.) So I can live with this compromise of having different defaults depending on the platform. Raspberry Pi 2 is required. This wasn't tested on the original RPI, though at least decoding itself seems to work (but full playback was not tested).
2015-03-29 13:12:11 +00:00
'func': check_true
}
]
hwaccel_features = [
{
'name': '--vaapi-hwaccel',
'desc': 'libavcodec VAAPI hwaccel (FFmpeg 3.3 API)',
'deps': 'vaapi',
'func': check_statement('libavcodec/version.h',
'int x[(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 26, 0) && '
' LIBAVCODEC_VERSION_MICRO < 100) ||'
' (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 74, 100) && '
' LIBAVCODEC_VERSION_MICRO >= 100)'
' ? 1 : -1]',
use='libav'),
}, {
'name': 'videotoolbox-hwaccel',
'desc': 'libavcodec videotoolbox hwaccel (new API)',
'deps': 'gl-cocoa || ios-gl',
'func': check_statement('libavcodec/version.h',
'int x[(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 96, 100) && '
' LIBAVCODEC_VERSION_MICRO >= 100)'
' ? 1 : -1]',
use='libav'),
}, {
'name': '--videotoolbox-gl',
'desc': 'Videotoolbox with OpenGL',
'deps': 'gl-cocoa && videotoolbox-hwaccel',
'func': check_true
}, {
'name': '--vdpau-hwaccel',
'desc': 'libavcodec VDPAU hwaccel (FFmpeg 3.3 API)',
'deps': 'vdpau',
'func': check_statement('libavcodec/version.h',
'int x[(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 1) && '
' LIBAVCODEC_VERSION_MICRO < 100) ||'
' (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 85, 101) && '
' LIBAVCODEC_VERSION_MICRO >= 100)'
' ? 1 : -1]',
use='libav'),
}, {
# (conflated with ANGLE for easier deps)
'name': '--d3d-hwaccel',
'desc': 'D3D11VA hwaccel (new API, plus ANGLE)',
'deps': 'os-win32 && egl-angle',
'func': check_statement('libavcodec/version.h',
'int x[(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 4, 0) && '
' LIBAVCODEC_VERSION_MICRO < 100) ||'
' (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 100, 100) && '
' LIBAVCODEC_VERSION_MICRO >= 100)'
' ? 1 : -1]',
use='libav'),
}, {
'name': '--d3d9-hwaccel',
'desc': 'DXVA2 hwaccel (plus ANGLE)',
'deps': 'd3d-hwaccel && egl-angle-win32',
'func': check_true,
}, {
'name': '--gl-dxinterop-d3d9',
'desc': 'OpenGL/DirectX Interop Backend DXVA2 interop',
'deps': 'gl-dxinterop && d3d9-hwaccel',
'groups': [ 'gl' ],
'func': check_true,
hwdec/opengl: Add support for CUDA and cuvid/NvDecode Nvidia's "NvDecode" API (up until recently called "cuvid" is a cross platform, but nvidia proprietary API that exposes their hardware video decoding capabilities. It is analogous to their DXVA or VDPAU support on Windows or Linux but without using platform specific API calls. As a rule, you'd rather use DXVA or VDPAU as these are more mature and well supported APIs, but on Linux, VDPAU is falling behind the hardware capabilities, and there's no sign that nvidia are making the investments to update it. Most concretely, this means that there is no VP8/9 or HEVC Main10 support in VDPAU. On the other hand, NvDecode does export vp8/9 and partial support for HEVC Main10 (more on that below). ffmpeg already has support in the form of the "cuvid" family of decoders. Due to the design of the API, it is best exposed as a full decoder rather than an hwaccel. As such, there are decoders like h264_cuvid, hevc_cuvid, etc. These decoders support two output paths today - in both cases, NV12 frames are returned, either in CUDA device memory or regular system memory. In the case of the system memory path, the decoders can be used as-is in mpv today with a command line like: mpv --vd=lavc:h264_cuvid foobar.mp4 Doing this will take advantage of hardware decoding, but the cost of the memcpy to system memory adds up, especially for high resolution video (4K etc). To avoid that, we need an hwdec that takes advantage of CUDA's OpenGL interop to copy from device memory into OpenGL textures. That is what this change implements. The process is relatively simple as only basic device context aquisition needs to be done by us - the CUDA buffer pool is managed by the decoder - thankfully. The hwdec looks a bit like the vdpau interop one - the hwdec maintains a single set of plane textures and each output frame is repeatedly mapped into these textures to pass on. The frames are always in NV12 format, at least until 10bit output supports emerges. The only slightly interesting part of the copying process is that CUDA works by associating PBOs, so we need to define these for each of the textures. TODO Items: * I need to add a download_image function for screenshots. This would do the same copy to system memory that the decoder's system memory output does. * There are items to investigate on the ffmpeg side. There appears to be a problem with timestamps for some content. Final note: I mentioned HEVC Main10. While there is no 10bit output support, NvDecode can return dithered 8bit NV12 so you can take advantage of the hardware acceleration. This particular mode requires compiling ffmpeg with a modified header (or possibly the CUDA 8 RC) and is not upstream in ffmpeg yet. Usage: You will need to specify vo=opengl and hwdec=cuda. Note that hwdec=auto will probably not work as it will try to use vdpau first. mpv --hwdec=cuda --vo=opengl foobar.mp4 If you want to use filters that require frames in system memory, just use the decoder directly without the hwdec, as documented above.
2016-09-04 22:23:55 +00:00
}, {
'name': '--cuda-hwaccel',
'desc': 'CUDA hwaccel',
'deps': 'gl',
'func': check_cc(fragment=load_fragment('cuda.c'),
use='libav'),
}
]
radio_and_tv_features = [
{
'name': '--tv',
'desc': 'TV interface',
'deps': 'gpl',
'func': check_true,
'default': 'disable',
}, {
'name': 'sys_videoio_h',
'desc': 'videoio.h',
'func': check_cc(header_name=['sys/time.h', 'sys/videoio.h']),
'deps': 'tv',
}, {
'name': 'videodev',
'desc': 'videodev2.h',
'func': check_cc(header_name=['sys/time.h', 'linux/videodev2.h']),
'deps': 'tv && !sys_videoio_h',
}, {
'name': '--tv-v4l2',
'desc': 'Video4Linux2 TV interface',
'deps': 'tv && (sys_videoio_h || videodev)',
'func': check_true,
}, {
'name': '--libv4l2',
'desc': 'libv4l2 support',
'func': check_pkg_config('libv4l2'),
'deps': 'tv-v4l2',
}, {
'name': '--audio-input',
'desc': 'audio input support',
'deps': 'tv-v4l2',
'func': check_true
} , {
'name': '--dvbin',
'desc': 'DVB input module',
'deps': 'gpl',
'func': check_true,
'default': 'disable',
}
]
standalone_features = [
{
'name': 'win32-executable',
'desc': 'w32 executable',
'deps': 'os-win32 || !(!(os-cygwin))',
'func': check_ctx_vars('WINDRES')
}, {
'name': '--apple-remote',
'desc': 'Apple Remote support',
'deps': 'cocoa',
'func': check_true
2017-02-25 20:56:59 +00:00
}, {
'name': '--macos-touchbar',
'desc': 'macOS Touch Bar support',
'deps': 'cocoa',
2017-02-25 20:56:59 +00:00
'func': check_cc(
fragment=load_fragment('touchbar.m'),
framework_name=['AppKit'],
compile_filename='test-touchbar.m',
linkflags='-fobjc-arc')
}
]
_INSTALL_DIRS_LIST = [
('bindir', '${PREFIX}/bin', 'binary files'),
('libdir', '${PREFIX}/lib', 'library files'),
('confdir', '${PREFIX}/etc/mpv', 'configuration files'),
('incdir', '${PREFIX}/include', 'include files'),
('datadir', '${PREFIX}/share', 'data files'),
('mandir', '${DATADIR}/man', 'man pages '),
('docdir', '${DATADIR}/doc/mpv', 'documentation files'),
('htmldir', '${DOCDIR}', 'html documentation files'),
('zshdir', '${DATADIR}/zsh/site-functions', 'zsh completion functions'),
('confloaddir', '${CONFDIR}', 'configuration files load directory'),
]
def options(opt):
opt.load('compiler_c')
opt.load('waf_customizations')
opt.load('features')
group = opt.get_option_group("build and install options")
for ident, default, desc in _INSTALL_DIRS_LIST:
group.add_option('--{0}'.format(ident),
type = 'string',
dest = ident,
default = default,
help = 'directory for installing {0} [{1}]' \
.format(desc, default))
group.add_option('--variant',
default = '',
help = 'variant name for saving configuration and build results')
opt.parse_features('build and install options', build_options)
optional_features = main_dependencies + libav_dependencies
2014-11-28 14:40:55 +00:00
opt.parse_features('optional features', optional_features)
opt.parse_features('audio outputs', audio_output_features)
opt.parse_features('video outputs', video_output_features)
opt.parse_features('hwaccels', hwaccel_features)
opt.parse_features('tv features', radio_and_tv_features)
opt.parse_features('standalone app', standalone_features)
2014-11-28 14:40:55 +00:00
group = opt.get_option_group("optional features")
group.add_option('--lua',
type = 'string',
dest = 'LUA_VER',
help = "select Lua package which should be autodetected. Choices: 51 51deb 51obsd 51fbsd 52 52deb 52arch 52fbsd luajit")
@conf
def is_optimization(ctx):
return getattr(ctx.options, 'enable_optimize')
@conf
def is_debug_build(ctx):
return getattr(ctx.options, 'enable_debug-build')
def configure(ctx):
ctx.resetenv(ctx.options.variant)
2014-12-04 20:55:00 +00:00
ctx.check_waf_version(mini='1.8.4')
target = os.environ.get('TARGET')
(cc, pkg_config, ar, windres) = ('cc', 'pkg-config', 'ar', 'windres')
if target:
cc = '-'.join([target, 'gcc'])
pkg_config = '-'.join([target, pkg_config])
ar = '-'.join([target, ar])
windres = '-'.join([target, windres])
ctx.find_program(cc, var='CC')
ctx.find_program(pkg_config, var='PKG_CONFIG')
ctx.find_program(ar, var='AR')
2015-12-29 19:57:09 +00:00
ctx.find_program('rst2html', var='RST2HTML', mandatory=False)
ctx.find_program('rst2man', var='RST2MAN', mandatory=False)
ctx.find_program('rst2pdf', var='RST2PDF', mandatory=False)
ctx.find_program(windres, var='WINDRES', mandatory=False)
ctx.find_program('perl', var='BIN_PERL', mandatory=False)
ctx.add_os_flags('LIBRARY_PATH')
ctx.load('compiler_c')
ctx.load('waf_customizations')
ctx.load('dependencies')
ctx.load('detections.compiler')
ctx.load('detections.devices')
for ident, _, _ in _INSTALL_DIRS_LIST:
varname = ident.upper()
ctx.env[varname] = getattr(ctx.options, ident)
# keep substituting vars, until the paths are fully expanded
while re.match('\$\{([^}]+)\}', ctx.env[varname]):
ctx.env[varname] = Utils.subst_vars(ctx.env[varname], ctx.env)
ctx.parse_dependencies(build_options)
ctx.parse_dependencies(main_dependencies)
ctx.parse_dependencies(audio_output_features)
ctx.parse_dependencies(video_output_features)
ctx.parse_dependencies(libav_dependencies)
ctx.parse_dependencies(hwaccel_features)
ctx.parse_dependencies(radio_and_tv_features)
if ctx.options.LUA_VER:
ctx.options.enable_lua = True
ctx.parse_dependencies(standalone_features)
ctx.load('generators.headers')
if not ctx.dependency_satisfied('build-date'):
ctx.env.CFLAGS += ['-DNO_BUILD_TIMESTAMPS']
if ctx.dependency_satisfied('clang-database'):
ctx.load('clang_compilation_database')
if ctx.dependency_satisfied('cplugins'):
# We need to export the libmpv symbols, since the mpv binary itself is
# not linked against libmpv. The C plugin needs to be able to pick
# up the libmpv symbols from the binary. We still restrict the set
# of exported symbols via mpv.def.
ctx.env.LINKFLAGS += ['-rdynamic']
ctx.store_dependencies_lists()
def __write_version__(ctx):
ctx.env.VERSIONH_ST = '--versionh="%s"'
ctx.env.CWD_ST = '--cwd="%s"'
ctx.env.VERSIONSH_CWD = [ctx.srcnode.abspath()]
ctx(
source = 'version.sh',
target = 'version.h',
rule = 'sh ${SRC} ${CWD_ST:VERSIONSH_CWD} ${VERSIONH_ST:TGT}',
always = True,
update_outputs = True)
def build(ctx):
if ctx.options.variant not in ctx.all_envs:
from waflib import Errors
raise Errors.WafError(
'The project was not configured: run "waf --variant={0} configure" first!'
.format(ctx.options.variant))
ctx.unpack_dependencies_lists()
__write_version__(ctx)
ctx.load('wscript_build')
def init(ctx):
from waflib.Build import BuildContext, CleanContext, InstallContext, UninstallContext
for y in (BuildContext, CleanContext, InstallContext, UninstallContext):
class tmp(y):
variant = ctx.options.variant
# This is needed because waf initializes the ConfigurationContext with
# an arbitrary setenv('') which would rewrite the previous configuration
# cache for the default variant if the configure step finishes.
# Ideally ConfigurationContext should just let us override this at class
# level like the other Context subclasses do with variant
from waflib.Configure import ConfigurationContext
class cctx(ConfigurationContext):
def resetenv(self, name):
self.all_envs = {}
self.setenv(name)