pax_global_header00006660000000000000000000000064126326117550014522gustar00rootroot0000000000000052 comment=e1993d5ad2bdf3dd4c26474aaa2370cbc9c1cd1b mpv-0.14.0/000077500000000000000000000000001263261175500124065ustar00rootroot00000000000000mpv-0.14.0/.gitignore000066400000000000000000000006621263261175500144020ustar00rootroot00000000000000*.o *.a *.d *.exe *.pyc .depend /config.h /config.mak /config.log /mpv /mpv.app /version.h /input/input_conf.h /tags /TAGS /video/out/x11_icon.inc /video/out/opengl/nnedi3_weights.inc /demux/ebml_defs.c /demux/ebml_types.h /sub/osd_font.h /player/lua/*.inc /DOCS/man/mpv.1 /DOCS/man/mpv.aux /DOCS/man/mpv.log /DOCS/man/mpv.out /DOCS/man/mpv.pdf /DOCS/man/mpv.toc /waf /waf-* /waf3-* /build /.waf* /.lock-waf_* /old_build /Makefile mpv-0.14.0/.travis.yml000066400000000000000000000023701263261175500145210ustar00rootroot00000000000000language: c os: - linux - osx env: matrix: - LIBAV=libav-stable - LIBAV=libav-git - LIBAV=ffmpeg-stable - LIBAV=ffmpeg-git global: # Coverity token - secure: "H21mSRlMhk4BKS0xHZvCFGJxteCP0hRVUxTuNfM2Z9HBsyutuLEYMtViLO86VtM+Tqla3xXPzUdS4ozLwI72Ax/5ZUDXACROj73yW6QhFB5D6rLut12+FjqC7M33Qv2hl0xwgNBmR5dsm1ToP37+Wn+ecJQNvN8fkTXF+HVzOEw=" compiler: - clang - gcc branches: only: - master - ci - coverity_scan matrix: exclude: - os: osx env: LIBAV=libav-stable - os: osx env: LIBAV=libav-git - os: osx env: LIBAV=ffmpeg-git - os: osx compiler: gcc - os: linux env: LIBAV=ffmpeg-stable - os: linux compiler: clang before_install: ./travis-deps libass-stable $LIBAV script: - ./bootstrap.py - ./waf configure - ./waf build notifications: email: false irc: channels: - "irc.freenode.org#mpv-devel" on_success: change on_failure: always addons: coverity_scan: project: name: "mpv-player/mpv" description: "Build submitted via Travis CI" notification_email: mpv-team@googlegroups.com build_command_prepend: "./bootstrap.py && ./waf configure" build_command: "./waf build" branch_pattern: coverity_scan mpv-0.14.0/Copyright000066400000000000000000000031461263261175500143050ustar00rootroot00000000000000mpv is a fork of mplayer2, which is a fork of MPlayer. mpv as a whole is licensed as GPL version 2 or later (see LICENSE). Most source files are GPLv2+, but some files are available under a more liberal license, such as LGPLv2.1+, BSD, MIT, ISC, and possibly others. Look at the copyright header of each source file, and grep the sources for "Copyright" if you need to know details. 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. Some GPLv3 or LGPLv3 code in mpv can be enabled by building with --enable-gpl3, and in this case, the resulting binaries must be distributed under GPLv3. For information about authors and contributors, consult the git log, which contains the complete SVN and CVS history as well. Note that mplayer2 as a whole is licensed under GPLv3+. This is because it uses a copy of talloc (part of Samba), which is LGPLv3+, and the next compatible license for this mix is GPLv3+. MPlayer as a whole is licensed under GPLv2 (incompatible to GPLv3!), because some files are licensed to GPLv2 (and _not_ any later version of the license). In particular, this affects the file libmpdemux/demux_ty_osd.c. It is disabled under mplayer2, and has been removed from mpv. "v2.1+" in this context means "version 2.1 or later". mpv-0.14.0/DOCS/000077500000000000000000000000001263261175500131365ustar00rootroot00000000000000mpv-0.14.0/DOCS/client-api-changes.rst000066400000000000000000000126541263261175500173330ustar00rootroot00000000000000Introduction ============ 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``. 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), while C API additions bump the minor version (i.e. the second number is increased). Changes to properties/commands/options may also lead to a minor version bump, in particular if they are incompatible. The version number is the same as used for MPV_CLIENT_API_VERSION (see ``client.h`` how to convert between major/minor version numbers and the flat 32 bit integer). 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.12.0 --- 1.20 - deprecate "GL_MP_D3D_interfaces"/"glMPGetD3DInterface", and introduce "GL_MP_MPGetNativeDisplay"/"glMPGetNativeDisplay" (this is a backwards-compatible rename) --- mpv 0.11.0 --- --- mpv 0.10.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 --- 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) 1.13 - add MPV_EVENT_QUEUE_OVERFLOW 1.12 - add class Handle to qthelper.hpp - improve opengl_cb.h API uninitialization behavior, and fix the qml example - add mpv_create_client() function 1.11 - add OpenGL rendering interop API - allows an application to combine 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 --- 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 - add MPV_END_FILE_REASON_ERROR and the mpv_event_end_file.error field for slightly better error reporting on playback failure - add --stop-playback-on-init-failure option, and make it the default behavior for libmpv only - add qthelper.hpp set_option_variant() - mark the following events as deprecated: MPV_EVENT_TRACKS_CHANGED MPV_EVENT_TRACK_SWITCHED MPV_EVENT_PAUSE MPV_EVENT_UNPAUSE MPV_EVENT_METADATA_UPDATE MPV_EVENT_CHAPTER_CHANGE They are handled better with mpv_observe_property() as mentioned in the documentation comments. They are not removed and still work. 1.8 - add qthelper.hpp 1.7 - add mpv_command_node(), mpv_command_node_async() 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 --- 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 measure until XEmbed is implemented and confirmed working. Note: in 1.6, "input-x11-keyboard" was renamed to "input-vo-keyboard", 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 --- 1.3 - add MPV_MAKE_VERSION() 1.2 - remove "stream-time-pos" property (no replacement) 1.1 - remap dvdnav:// to dvd:// - add "--cache-file", "--cache-file-size" - add "--colormatrix-primaries" (and property) - add "primaries" sub-field to image format properties - add "playback-time" property - extend the "--start" option; a leading "+", which was previously 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 --- 1.0 - the API is declared stable mpv-0.14.0/DOCS/client_api_examples/000077500000000000000000000000001263261175500171435ustar00rootroot00000000000000mpv-0.14.0/DOCS/client_api_examples/Copyright000066400000000000000000000007461263261175500210450ustar00rootroot00000000000000All examples in this directory and its sub-directories are licensed under one of the following licenses: WTFPL, ISC, Ms-PL, AGPLv3, BSD (any) Pick any license of your liking, and disregard the others. (The full text of each license is available on this website: http://opensource.org/licenses/alphabetical ) Additionally, you may consider the example code to be public domain. You are free to use any of the example code without further requirements or need for attribution. mpv-0.14.0/DOCS/client_api_examples/README.md000066400000000000000000000105321263261175500204230ustar00rootroot00000000000000# Client API examples All these examples use the mpv client API through libmpv. ## Where are the docs? The libmpv C API is documented directly in the header files (on normal Unix systems, this is in `/usr/include/mpv/client.h`. libmpv merely gives you access to mpv's command interface, which is documented here: * Options (`mpv_set_option()` and friends): http://mpv.io/manual/master/#options * Commands (`mpv_command()` and friends): http://mpv.io/manual/master/#list-of-input-commands * Properties (`mpv_set_property()` and friends): http://mpv.io/manual/master/#properties Essentially everything is done with them, including loading a file, retrieving playback progress, and so on. ## Methods of embedding the video window All of these examples concentrate on how to integrate mpv's video renderers with your own GUI. This is generally the hardest part. libmpv enforces a somewhat efficient video output method, rather than e.g. returning a RGBA surface in memory for each frame. The latter would be prohibitively inefficient, because it would require conversion on the CPU. The goal is also not requiring the API users to reinvent their own video rendering/scaling/presentation mechanisms. There are currently 2 methods of embedding video. ### Native window embedding This uses the platform's native method of nesting multiple windows. For example, Linux/X11 can nest a window from a completely different process. The nested window can redraw contents on its own, and receive user input if the user interacts with this window. libmpv lets you specify a parent window for its own video window via the `wid` option. Then libmpv will create its window with your window as parent, and render its video inside of it. This method is highly OS-dependent. Some behavior is OS-specific. There are problems with focusing on X11 (the ancient X11 focus policy mismatches with that of modern UI toolkits - it's normally worked around, but this is not easily possible with raw window embedding). It seems to have stability problems on OSX when using the Qt toolkit. ### OpenGL embedding This method lets you use libmpv's OpenGL renderer directly. You create an OpenGL context, and then use `mpv_opengl_cb_draw()` to render the video on each frame. This is more complicated, because libmpv will work directly on your own OpenGL state. It's also not possible to have mpv automatically receive user input. You will have to simulate this with the `mouse`/`keypress`/`keydown`/`keyup` commands. You also get much more flexibility. For example, you can actually render your own OSD on top of the video, something that is not possible with raw window embedding. ### Which one to use? Due to the various platform-specific behavior and problems (in particular on OSX), OpenGL embedding is recommended. If you're not comfortable with requiring OpenGL, or want to support "direct" video output such as vdpau (which might win when it comes to performance and energy-saving), you should probably support both methods if possible. ## List of examples ### simple Very primitive terminal-only example. Shows some most basic API usage. ### cocoa Shows how to embed the mpv video window in Objective-C/Cocoa. ### cocoa-openglcb Similar to the cocoa sample, but shows how to integrate mpv's OpenGL renderer using libmpv's opengl-cb API. Since it does not require complicated interaction with Cocoa elements from different libraries, it's more robust. ### qt Shows how to embed the mpv video window in Qt (using normal desktop widgets). ### qt_opengl Shows how to use mpv's OpenGL video renderer in Qt. This uses the opengl-cb API for video. Since it does not rely on embedding "foreign" native Windows, it's usually more robust, potentially faster, and it's easier to control how your GUI interacts with the video. You can do your own OpenGL rendering on top of the video as well. ### qml Shows how to use mpv's OpenGL video renderer in QtQuick2 with QML. Uses the opengl-cb API for video. Since the video is a normal QML element, it's trivial to create OSD overlays with QML-native graphical elements as well. ### qml_direct Alternative example, which typically avoids a FBO indirection. Might be slightly faster, but is less flexible and harder to use. In particular, the video is not a normal QML element. Uses the opengl-cb API for video. ### sdl Show how to embed the mpv OpenGL renderer in SDL. Uses the opengl-cb API for video. mpv-0.14.0/DOCS/client_api_examples/cocoa-openglcb/000077500000000000000000000000001263261175500220165ustar00rootroot00000000000000mpv-0.14.0/DOCS/client_api_examples/cocoa-openglcb/cocoa-openglcb.m000066400000000000000000000213741263261175500250560ustar00rootroot00000000000000// 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 #import #import #import #import #import 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 { 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; } mpv-0.14.0/DOCS/client_api_examples/cocoa/000077500000000000000000000000001263261175500202275ustar00rootroot00000000000000mpv-0.14.0/DOCS/client_api_examples/cocoa/cocoabasic.m000066400000000000000000000136501263261175500225000ustar00rootroot00000000000000// Plays a video from the command line in a view provided by the client // application. // Build with: clang -o cocoabasic cocoabasic.m `pkg-config --libs --cflags mpv` -framework cocoa #include #include #include static inline void check_error(int status) { if (status < 0) { printf("mpv API error: %s\n", mpv_error_string(status)); exit(1); } } #import @interface CocoaWindow : NSWindow @end @implementation CocoaWindow - (BOOL)canBecomeMainWindow { return YES; } - (BOOL)canBecomeKeyWindow { return YES; } @end @interface AppDelegate : NSObject { mpv_handle *mpv; dispatch_queue_t queue; NSWindow *w; NSView *wrapper; } @end static void wakeup(void *); @implementation AppDelegate - (void)createWindow { int mask = NSTitledWindowMask|NSClosableWindowMask| NSMiniaturizableWindowMask|NSResizableWindowMask; self->w = [[CocoaWindow alloc] initWithContentRect:NSMakeRect(0,0, 1280, 720) styleMask:mask backing:NSBackingStoreBuffered defer:NO]; [self->w setTitle:@"cocoabasic example"]; [self->w makeMainWindow]; [self->w makeKeyAndOrderFront:nil]; NSRect frame = [[self->w contentView] bounds]; self->wrapper = [[NSView alloc] initWithFrame:frame]; [self->wrapper setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; [[self->w contentView] addSubview:self->wrapper]; [self->wrapper release]; 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: @"mpv_command('stop')" action:@selector(mpv_stop) keyEquivalent:@""]; [sm addItemWithTitle: @"mpv_command('quit')" action:@selector(mpv_quit) keyEquivalent:@""]; [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]; // Deal with MPV in the background. queue = dispatch_queue_create("mpv", DISPATCH_QUEUE_SERIAL); dispatch_async(queue, ^{ mpv = mpv_create(); if (!mpv) { printf("failed creating context\n"); exit(1); } int64_t wid = (intptr_t) self->wrapper; check_error(mpv_set_option(mpv, "wid", MPV_FORMAT_INT64, &wid)); // Maybe set some options here, like default key bindings. // NOTE: Interaction with the window seems to be broken for now. check_error(mpv_set_option_string(mpv, "input-default-bindings", "yes")); // for testing! check_error(mpv_set_option_string(mpv, "input-media-keys", "yes")); check_error(mpv_set_option_string(mpv, "input-cursor", "no")); check_error(mpv_set_option_string(mpv, "input-vo-keyboard", "yes")); // request important errors check_error(mpv_request_log_messages(mpv, "warn")); check_error(mpv_initialize(mpv)); // 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)); }); } - (void) handleEvent:(mpv_event *)event { switch (event->event_id) { case MPV_EVENT_SHUTDOWN: { mpv_detach_destroy(mpv); 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); } case MPV_EVENT_VIDEO_RECONFIG: { dispatch_async(dispatch_get_main_queue(), ^{ NSArray *subviews = [self->wrapper subviews]; if ([subviews count] > 0) { // mpv's events view NSView *eview = [self->wrapper subviews][0]; [self->w makeFirstResponder:eview]; } }); } default: printf("event: %s\n", mpv_event_name(event->event_id)); } } - (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]; } // Ostensibly, mpv's window would be hooked up to this. - (BOOL) windowShouldClose:(id)sender { return NO; } - (void) mpv_stop { if (mpv) { const char *args[] = {"stop", NULL}; mpv_command(mpv, args); } } - (void) mpv_quit { if (mpv) { const char *args[] = {"quit", NULL}; mpv_command(mpv, args); } } @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; } mpv-0.14.0/DOCS/client_api_examples/qml/000077500000000000000000000000001263261175500177345ustar00rootroot00000000000000mpv-0.14.0/DOCS/client_api_examples/qml/main.cpp000066400000000000000000000075361263261175500213770ustar00rootroot00000000000000#include "main.h" #include #include #include #include #include #include #include #include #include class MpvRenderer : public QQuickFramebufferObject::Renderer { static void *get_proc_address(void *ctx, const char *name) { (void)ctx; QOpenGLContext *glctx = QOpenGLContext::currentContext(); if (!glctx) return NULL; return (void *)glctx->getProcAddress(QByteArray(name)); } mpv::qt::Handle mpv; QQuickWindow *window; mpv_opengl_cb_context *mpv_gl; public: MpvRenderer(const MpvObject *obj) : mpv(obj->mpv), window(obj->window()), mpv_gl(obj->mpv_gl) { int r = mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address, NULL); if (r < 0) throw std::runtime_error("could not initialize OpenGL"); } virtual ~MpvRenderer() { // Until this call is done, we need to make sure the player remains // alive. This is done implicitly with the mpv::qt::Handle instance // in this class. mpv_opengl_cb_uninit_gl(mpv_gl); } void render() { QOpenGLFramebufferObject *fbo = framebufferObject(); window->resetOpenGLState(); mpv_opengl_cb_draw(mpv_gl, fbo->handle(), fbo->width(), fbo->height()); window->resetOpenGLState(); } }; MpvObject::MpvObject(QQuickItem * parent) : QQuickFramebufferObject(parent), mpv_gl(0) { mpv = mpv::qt::Handle::FromRawHandle(mpv_create()); if (!mpv) throw std::runtime_error("could not create mpv context"); mpv_set_option_string(mpv, "terminal", "yes"); mpv_set_option_string(mpv, "msg-level", "all=v"); if (mpv_initialize(mpv) < 0) throw std::runtime_error("could not initialize mpv context"); // Make use of the MPV_SUB_API_OPENGL_CB API. mpv::qt::set_option_variant(mpv, "vo", "opengl-cb"); // Request hw decoding, just for testing. mpv::qt::set_option_variant(mpv, "hwdec", "auto"); // Setup the callback that will make QtQuick update and redraw if there // is a new video frame. Use a queued connection: this makes sure the // doUpdate() function is run on the GUI thread. mpv_gl = (mpv_opengl_cb_context *)mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB); if (!mpv_gl) throw std::runtime_error("OpenGL not compiled in"); mpv_opengl_cb_set_update_callback(mpv_gl, MpvObject::on_update, (void *)this); connect(this, &MpvObject::onUpdate, this, &MpvObject::doUpdate, Qt::QueuedConnection); } MpvObject::~MpvObject() { if (mpv_gl) mpv_opengl_cb_set_update_callback(mpv_gl, NULL, NULL); } void MpvObject::on_update(void *ctx) { MpvObject *self = (MpvObject *)ctx; emit self->onUpdate(); } // connected to onUpdate(); signal makes sure it runs on the GUI thread void MpvObject::doUpdate() { update(); } void MpvObject::command(const QVariant& params) { mpv::qt::command_variant(mpv, params); } void MpvObject::setProperty(const QString& name, const QVariant& value) { mpv::qt::set_property_variant(mpv, name, value); } QQuickFramebufferObject::Renderer *MpvObject::createRenderer() const { window()->setPersistentOpenGLContext(true); window()->setPersistentSceneGraph(true); return new MpvRenderer(this); } int main(int argc, char **argv) { QGuiApplication app(argc, argv); // Qt sets the locale in the QGuiApplication constructor, but libmpv // requires the LC_NUMERIC category to be set to "C", so change it back. std::setlocale(LC_NUMERIC, "C"); qmlRegisterType("mpvtest", 1, 0, "MpvObject"); QQuickView view; view.setResizeMode(QQuickView::SizeRootObjectToView); view.setSource(QUrl("qrc:///mpvtest/main.qml")); view.show(); return app.exec(); } mpv-0.14.0/DOCS/client_api_examples/qml/main.h000066400000000000000000000013121263261175500210260ustar00rootroot00000000000000#ifndef MPVRENDERER_H_ #define MPVRENDERER_H_ #include #include #include #include class MpvRenderer; class MpvObject : public QQuickFramebufferObject { Q_OBJECT mpv::qt::Handle mpv; mpv_opengl_cb_context *mpv_gl; friend class MpvRenderer; public: MpvObject(QQuickItem * parent = 0); virtual ~MpvObject(); virtual Renderer *createRenderer() const; public slots: void command(const QVariant& params); void setProperty(const QString& name, const QVariant& value); signals: void onUpdate(); private slots: void doUpdate(); private: static void on_update(void *ctx); }; #endif mpv-0.14.0/DOCS/client_api_examples/qml/main.qml000066400000000000000000000034761263261175500214050ustar00rootroot00000000000000import QtQuick 2.0 import QtQuick.Controls 1.0 import mpvtest 1.0 Item { width: 1280 height: 720 MpvObject { id: renderer anchors.fill: parent MouseArea { anchors.fill: parent onClicked: renderer.command(["loadfile", "../../../test.mkv"]) } } Rectangle { id: labelFrame anchors.margins: -50 radius: 5 color: "white" border.color: "black" opacity: 0.8 anchors.fill: box } Row { id: box anchors.bottom: renderer.bottom anchors.left: renderer.left anchors.right: renderer.right anchors.margins: 100 Text { anchors.margins: 10 wrapMode: Text.WordWrap text: "QtQuick and mpv are both rendering stuff.\n Click to load ../../../test.mkv" } // Don't take these controls too seriously. They're for testing. Column { CheckBox { id: checkbox anchors.margins: 10 // Heavily filtered means good, right? text: "Make video look like on a Smart TV" onClicked: { if (checkbox.checked) { renderer.command(["vo_cmdline", "sharpen=5.0"]) } else { renderer.command(["vo_cmdline", ""]) } } } Slider { id: slider anchors.margins: 10 anchors.left: checkbox.left anchors.right: checkbox.right minimumValue: -100 maximumValue: 100 value: 0 onValueChanged: renderer.setProperty("gamma", slider.value | 0) } } } } mpv-0.14.0/DOCS/client_api_examples/qml/mpvtest.pro000066400000000000000000000002661263261175500221640ustar00rootroot00000000000000QT += qml quick HEADERS += main.h SOURCES += main.cpp QT_CONFIG -= no-pkg-config CONFIG += link_pkgconfig debug PKGCONFIG += mpv RESOURCES += mpvtest.qrc OTHER_FILES += main.qml mpv-0.14.0/DOCS/client_api_examples/qml/mpvtest.qrc000066400000000000000000000001361263261175500221450ustar00rootroot00000000000000 main.qml mpv-0.14.0/DOCS/client_api_examples/qml_direct/000077500000000000000000000000001263261175500212665ustar00rootroot00000000000000mpv-0.14.0/DOCS/client_api_examples/qml_direct/main.cpp000066400000000000000000000111101263261175500227100ustar00rootroot00000000000000#include "main.h" #include #include #include #include #include #include #include #include static void *get_proc_address(void *ctx, const char *name) { (void)ctx; QOpenGLContext *glctx = QOpenGLContext::currentContext(); if (!glctx) return NULL; return (void *)glctx->getProcAddress(QByteArray(name)); } MpvRenderer::MpvRenderer(mpv::qt::Handle a_mpv, mpv_opengl_cb_context *a_mpv_gl) : mpv(a_mpv), mpv_gl(a_mpv_gl), window(0), size() { int r = mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address, NULL); if (r < 0) throw std::runtime_error("could not initialize OpenGL"); } MpvRenderer::~MpvRenderer() { // Until this call is done, we need to make sure the player remains // alive. This is done implicitly with the mpv::qt::Handle instance // in this class. mpv_opengl_cb_uninit_gl(mpv_gl); } void MpvRenderer::paint() { window->resetOpenGLState(); // 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()); window->resetOpenGLState(); } MpvObject::MpvObject(QQuickItem * parent) : QQuickItem(parent), mpv_gl(0), renderer(0) { mpv = mpv::qt::Handle::FromRawHandle(mpv_create()); if (!mpv) throw std::runtime_error("could not create mpv context"); mpv_set_option_string(mpv, "terminal", "yes"); mpv_set_option_string(mpv, "msg-level", "all=v"); if (mpv_initialize(mpv) < 0) throw std::runtime_error("could not initialize mpv context"); // Make use of the MPV_SUB_API_OPENGL_CB API. mpv::qt::set_option_variant(mpv, "vo", "opengl-cb"); // Setup the callback that will make QtQuick update and redraw if there // is a new video frame. Use a queued connection: this makes sure the // doUpdate() function is run on the GUI thread. mpv_gl = (mpv_opengl_cb_context *)mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB); if (!mpv_gl) throw std::runtime_error("OpenGL not compiled in"); mpv_opengl_cb_set_update_callback(mpv_gl, MpvObject::on_update, (void *)this); connect(this, &MpvObject::onUpdate, this, &MpvObject::doUpdate, Qt::QueuedConnection); connect(this, &QQuickItem::windowChanged, this, &MpvObject::handleWindowChanged); } MpvObject::~MpvObject() { if (mpv_gl) mpv_opengl_cb_set_update_callback(mpv_gl, NULL, NULL); } void MpvObject::handleWindowChanged(QQuickWindow *win) { if (!win) return; connect(win, &QQuickWindow::beforeSynchronizing, 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); } void MpvObject::sync() { if (!renderer) { renderer = new MpvRenderer(mpv, mpv_gl); connect(window(), &QQuickWindow::beforeRendering, renderer, &MpvRenderer::paint, Qt::DirectConnection); } renderer->window = window(); renderer->size = window()->size() * window()->devicePixelRatio(); } void MpvObject::swapped() { mpv_opengl_cb_report_flip(mpv_gl, 0); } void MpvObject::cleanup() { if (renderer) { delete renderer; renderer = 0; } } void MpvObject::on_update(void *ctx) { MpvObject *self = (MpvObject *)ctx; emit self->onUpdate(); } // connected to onUpdate(); signal makes sure it runs on the GUI thread void MpvObject::doUpdate() { window()->update(); } void MpvObject::command(const QVariant& params) { mpv::qt::command_variant(mpv, params); } int main(int argc, char **argv) { QGuiApplication app(argc, argv); // Qt sets the locale in the QGuiApplication constructor, but libmpv // requires the LC_NUMERIC category to be set to "C", so change it back. std::setlocale(LC_NUMERIC, "C"); qmlRegisterType("mpvtest", 1, 0, "MpvObject"); QQuickView view; view.setResizeMode(QQuickView::SizeRootObjectToView); view.setSource(QUrl("qrc:///mpvtest/main.qml")); view.show(); return app.exec(); } mpv-0.14.0/DOCS/client_api_examples/qml_direct/main.h000066400000000000000000000017301263261175500223640ustar00rootroot00000000000000#ifndef MPVRENDERER_H_ #define MPVRENDERER_H_ #include #include #include #include class MpvRenderer : public QObject { Q_OBJECT mpv::qt::Handle mpv; mpv_opengl_cb_context *mpv_gl; QQuickWindow *window; QSize size; friend class MpvObject; public: MpvRenderer(mpv::qt::Handle a_mpv, mpv_opengl_cb_context *a_mpv_gl); virtual ~MpvRenderer(); public slots: void paint(); }; class MpvObject : public QQuickItem { Q_OBJECT mpv::qt::Handle mpv; mpv_opengl_cb_context *mpv_gl; MpvRenderer *renderer; public: MpvObject(QQuickItem * parent = 0); virtual ~MpvObject(); public slots: void command(const QVariant& params); void sync(); void swapped(); void cleanup(); signals: void onUpdate(); private slots: void doUpdate(); void handleWindowChanged(QQuickWindow *win); private: static void on_update(void *ctx); }; #endif mpv-0.14.0/DOCS/client_api_examples/qml_direct/main.qml000066400000000000000000000020671263261175500227320ustar00rootroot00000000000000import QtQuick 2.0 import QtQuick.Controls 1.0 import mpvtest 1.0 Item { width: 1280 height: 720 MpvObject { id: renderer // This object isn't real and not visible; it just renders into the // background of the containing Window. width: 0 height: 0 } MouseArea { anchors.fill: parent onClicked: renderer.command(["loadfile", "../../../test.mkv"]) } Rectangle { id: labelFrame anchors.margins: -50 radius: 5 color: "white" border.color: "black" opacity: 0.8 anchors.fill: box } Row { id: box anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right anchors.margins: 100 Text { anchors.margins: 10 wrapMode: Text.WordWrap text: "QtQuick and mpv are both rendering stuff.\n In this example, mpv is always in the background.\n Click to load ../../../test.mkv" } } } mpv-0.14.0/DOCS/client_api_examples/qml_direct/mpvtest.pro000066400000000000000000000002661263261175500235160ustar00rootroot00000000000000QT += qml quick HEADERS += main.h SOURCES += main.cpp QT_CONFIG -= no-pkg-config CONFIG += link_pkgconfig debug PKGCONFIG += mpv RESOURCES += mpvtest.qrc OTHER_FILES += main.qml mpv-0.14.0/DOCS/client_api_examples/qml_direct/mpvtest.qrc000066400000000000000000000001361263261175500234770ustar00rootroot00000000000000 main.qml mpv-0.14.0/DOCS/client_api_examples/qt/000077500000000000000000000000001263261175500175675ustar00rootroot00000000000000mpv-0.14.0/DOCS/client_api_examples/qt/qtexample.cpp000066400000000000000000000166371263261175500223100ustar00rootroot00000000000000// This example can be built with: qmake && make #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #endif #include #include "qtexample.h" static void wakeup(void *ctx) { // This callback is invoked from any mpv thread (but possibly also // recursively from a thread that is calling the mpv API). Just notify // the Qt GUI thread to wake up (so that it can process events with // mpv_wait_event()), and return as quickly as possible. MainWindow *mainwindow = (MainWindow *)ctx; emit mainwindow->mpv_events(); } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setWindowTitle("Qt embedding demo"); setMinimumSize(640, 480); QMenu *menu = menuBar()->addMenu(tr("&File")); QAction *on_open = new QAction(tr("&Open"), this); on_open->setShortcuts(QKeySequence::Open); on_open->setStatusTip(tr("Open a file")); connect(on_open, &QAction::triggered, this, &MainWindow::on_file_open); menu->addAction(on_open); QAction *on_new = new QAction(tr("&New window"), this); connect(on_new, &QAction::triggered, this, &MainWindow::on_new_window); menu->addAction(on_new); statusBar(); QMainWindow *log_window = new QMainWindow(this); log = new QTextEdit(log_window); log->setReadOnly(true); log_window->setCentralWidget(log); log_window->setWindowTitle("mpv log window"); log_window->setMinimumSize(500, 50); log_window->show(); mpv = mpv_create(); if (!mpv) throw std::runtime_error("can't create mpv instance"); // Create a video child window. Force Qt to create a native window, and // pass the window ID to the mpv wid option. Works on: X11, win32, Cocoa mpv_container = new QWidget(this); setCentralWidget(mpv_container); mpv_container->setAttribute(Qt::WA_DontCreateNativeAncestors); mpv_container->setAttribute(Qt::WA_NativeWindow); // If you have a HWND, use: int64_t wid = (intptr_t)hwnd; int64_t wid = mpv_container->winId(); mpv_set_option(mpv, "wid", MPV_FORMAT_INT64, &wid); // Enable default bindings, because we're lazy. Normally, a player using // mpv as backend would implement its own key bindings. mpv_set_option_string(mpv, "input-default-bindings", "yes"); // Enable keyboard input on the X11 window. For the messy details, see // --input-vo-keyboard on the manpage. mpv_set_option_string(mpv, "input-vo-keyboard", "yes"); // Let us receive property change events with MPV_EVENT_PROPERTY_CHANGE if // this property changes. mpv_observe_property(mpv, 0, "time-pos", MPV_FORMAT_DOUBLE); mpv_observe_property(mpv, 0, "track-list", MPV_FORMAT_NODE); mpv_observe_property(mpv, 0, "chapter-list", MPV_FORMAT_NODE); // Request log messages with level "info" or higher. // They are received as MPV_EVENT_LOG_MESSAGE. mpv_request_log_messages(mpv, "info"); // From this point on, the wakeup function will be called. The callback // can come from any thread, so we use the QueuedConnection mechanism to // relay the wakeup in a thread-safe way. connect(this, &MainWindow::mpv_events, this, &MainWindow::on_mpv_events, Qt::QueuedConnection); mpv_set_wakeup_callback(mpv, wakeup, this); if (mpv_initialize(mpv) < 0) throw std::runtime_error("mpv failed to initialize"); } void MainWindow::handle_mpv_event(mpv_event *event) { switch (event->event_id) { case MPV_EVENT_PROPERTY_CHANGE: { mpv_event_property *prop = (mpv_event_property *)event->data; if (strcmp(prop->name, "time-pos") == 0) { if (prop->format == MPV_FORMAT_DOUBLE) { double time = *(double *)prop->data; std::stringstream ss; ss << "At: " << time; statusBar()->showMessage(QString::fromStdString(ss.str())); } else if (prop->format == MPV_FORMAT_NONE) { // The property is unavailable, which probably means playback // was stopped. statusBar()->showMessage(""); } } else if (strcmp(prop->name, "chapter-list") == 0 || strcmp(prop->name, "track-list") == 0) { // Dump the properties as JSON for demo purposes. #if QT_VERSION >= 0x050000 if (prop->format == MPV_FORMAT_NODE) { QVariant v = mpv::qt::node_to_variant((mpv_node *)prop->data); // Abuse JSON support for easily printing the mpv_node contents. QJsonDocument d = QJsonDocument::fromVariant(v); append_log("Change property " + QString(prop->name) + ":\n"); append_log(d.toJson().data()); } #endif } break; } case MPV_EVENT_VIDEO_RECONFIG: { // Retrieve the new video size. int64_t w, h; if (mpv_get_property(mpv, "dwidth", MPV_FORMAT_INT64, &w) >= 0 && mpv_get_property(mpv, "dheight", MPV_FORMAT_INT64, &h) >= 0 && w > 0 && h > 0) { // Note that the MPV_EVENT_VIDEO_RECONFIG event doesn't necessarily // imply a resize, and you should check yourself if the video // dimensions really changed. // mpv itself will scale/letter box the video to the container size // if the video doesn't fit. std::stringstream ss; ss << "Reconfig: " << w << " " << h; statusBar()->showMessage(QString::fromStdString(ss.str())); } break; } case MPV_EVENT_LOG_MESSAGE: { struct mpv_event_log_message *msg = (struct mpv_event_log_message *)event->data; std::stringstream ss; ss << "[" << msg->prefix << "] " << msg->level << ": " << msg->text; append_log(QString::fromStdString(ss.str())); break; } case MPV_EVENT_SHUTDOWN: { mpv_terminate_destroy(mpv); mpv = NULL; break; } default: ; // Ignore uninteresting or unknown events. } } // This slot is invoked by wakeup() (through the mpv_events signal). void MainWindow::on_mpv_events() { // Process all events, until the event queue is empty. while (mpv) { mpv_event *event = mpv_wait_event(mpv, 0); if (event->event_id == MPV_EVENT_NONE) break; handle_mpv_event(event); } } void MainWindow::on_file_open() { QString filename = QFileDialog::getOpenFileName(this, "Open file"); if (mpv) { const QByteArray c_filename = filename.toUtf8(); const char *args[] = {"loadfile", c_filename.data(), NULL}; mpv_command_async(mpv, 0, args); } } void MainWindow::on_new_window() { (new MainWindow())->show(); } void MainWindow::append_log(const QString &text) { QTextCursor cursor = log->textCursor(); cursor.movePosition(QTextCursor::End); cursor.insertText(text); log->setTextCursor(cursor); } MainWindow::~MainWindow() { if (mpv) mpv_terminate_destroy(mpv); } int main(int argc, char *argv[]) { QApplication a(argc, argv); // Qt sets the locale in the QApplication constructor, but libmpv requires // the LC_NUMERIC category to be set to "C", so change it back. std::setlocale(LC_NUMERIC, "C"); MainWindow w; w.show(); return a.exec(); } mpv-0.14.0/DOCS/client_api_examples/qt/qtexample.h000066400000000000000000000011051263261175500217350ustar00rootroot00000000000000#ifndef QTEXAMPLE_H #define QTEXAMPLE_H #include #include class QTextEdit; class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void on_file_open(); void on_new_window(); void on_mpv_events(); signals: void mpv_events(); private: QWidget *mpv_container; mpv_handle *mpv; QTextEdit *log; void append_log(const QString &text); void create_player(); void handle_mpv_event(mpv_event *event); }; #endif // QTEXAMPLE_H mpv-0.14.0/DOCS/client_api_examples/qt/qtexample.pro000066400000000000000000000003461263261175500223140ustar00rootroot00000000000000QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = qtexample TEMPLATE = app QT_CONFIG -= no-pkg-config CONFIG += link_pkgconfig debug PKGCONFIG += mpv SOURCES += qtexample.cpp HEADERS += qtexample.h mpv-0.14.0/DOCS/client_api_examples/qt_opengl/000077500000000000000000000000001263261175500211335ustar00rootroot00000000000000mpv-0.14.0/DOCS/client_api_examples/qt_opengl/main.cpp000066400000000000000000000005361263261175500225670ustar00rootroot00000000000000#include #include "mainwindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); // Qt sets the locale in the QApplication constructor, but libmpv requires // the LC_NUMERIC category to be set to "C", so change it back. setlocale(LC_NUMERIC, "C"); MainWindow w; w.show(); return a.exec(); } mpv-0.14.0/DOCS/client_api_examples/qt_opengl/mainwindow.cpp000066400000000000000000000027471263261175500240250ustar00rootroot00000000000000#include "mainwindow.h" #include "mpvwidget.h" #include #include #include #include MainWindow::MainWindow(QWidget *parent) : QWidget(parent) { m_mpv = new MpvWidget(this); m_slider = new QSlider(); m_slider->setOrientation(Qt::Horizontal); m_openBtn = new QPushButton("Open"); m_playBtn = new QPushButton("Pause"); QHBoxLayout *hb = new QHBoxLayout(); hb->addWidget(m_openBtn); hb->addWidget(m_playBtn); QVBoxLayout *vl = new QVBoxLayout(); vl->addWidget(m_mpv); vl->addWidget(m_slider); vl->addLayout(hb); setLayout(vl); connect(m_slider, SIGNAL(sliderMoved(int)), SLOT(seek(int))); connect(m_openBtn, SIGNAL(clicked()), SLOT(openMedia())); connect(m_playBtn, SIGNAL(clicked()), SLOT(pauseResume())); connect(m_mpv, SIGNAL(positionChanged(int)), m_slider, SLOT(setValue(int))); connect(m_mpv, SIGNAL(durationChanged(int)), this, SLOT(setSliderRange(int))); } void MainWindow::openMedia() { QString file = QFileDialog::getOpenFileName(0, "Open a video"); if (file.isEmpty()) return; m_mpv->command(QStringList() << "loadfile" << file); } void MainWindow::seek(int pos) { m_mpv->command(QVariantList() << "seek" << pos << "absolute"); } void MainWindow::pauseResume() { const bool paused = m_mpv->getProperty("pause").toBool(); m_mpv->setProperty("pause", !paused); } void MainWindow::setSliderRange(int duration) { m_slider->setRange(0, duration); } mpv-0.14.0/DOCS/client_api_examples/qt_opengl/mainwindow.h000066400000000000000000000007721263261175500234660ustar00rootroot00000000000000#ifndef MainWindow_H #define MainWindow_H #include class MpvWidget; class QSlider; class QPushButton; class MainWindow : public QWidget { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); public Q_SLOTS: void openMedia(); void seek(int pos); void pauseResume(); private Q_SLOTS: void setSliderRange(int duration); private: MpvWidget *m_mpv; QSlider *m_slider; QPushButton *m_openBtn; QPushButton *m_playBtn; }; #endif // MainWindow_H mpv-0.14.0/DOCS/client_api_examples/qt_opengl/mpvwidget.cpp000066400000000000000000000072701263261175500236530ustar00rootroot00000000000000#include "mpvwidget.h" #include #include #include static void wakeup(void *ctx) { QMetaObject::invokeMethod((MpvWidget*)ctx, "on_mpv_events", Qt::QueuedConnection); } static void *get_proc_address(void *ctx, const char *name) { Q_UNUSED(ctx); QOpenGLContext *glctx = QOpenGLContext::currentContext(); if (!glctx) return NULL; return (void *)glctx->getProcAddress(QByteArray(name)); } MpvWidget::MpvWidget(QWidget *parent, Qt::WindowFlags f) : QOpenGLWidget(parent, f) { mpv = mpv::qt::Handle::FromRawHandle(mpv_create()); if (!mpv) throw std::runtime_error("could not create mpv context"); mpv_set_option_string(mpv, "terminal", "yes"); mpv_set_option_string(mpv, "msg-level", "all=v"); if (mpv_initialize(mpv) < 0) throw std::runtime_error("could not initialize mpv context"); // Make use of the MPV_SUB_API_OPENGL_CB API. mpv::qt::set_option_variant(mpv, "vo", "opengl-cb"); // Request hw decoding, just for testing. mpv::qt::set_option_variant(mpv, "hwdec", "auto"); mpv_gl = (mpv_opengl_cb_context *)mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB); if (!mpv_gl) throw std::runtime_error("OpenGL not compiled in"); mpv_opengl_cb_set_update_callback(mpv_gl, MpvWidget::on_update, (void *)this); connect(this, SIGNAL(frameSwapped()), SLOT(swapped())); mpv_observe_property(mpv, 0, "duration", MPV_FORMAT_DOUBLE); mpv_observe_property(mpv, 0, "time-pos", MPV_FORMAT_DOUBLE); mpv_set_wakeup_callback(mpv, wakeup, this); } MpvWidget::~MpvWidget() { makeCurrent(); if (mpv_gl) mpv_opengl_cb_set_update_callback(mpv_gl, NULL, NULL); // Until this call is done, we need to make sure the player remains // alive. This is done implicitly with the mpv::qt::Handle instance // in this class. mpv_opengl_cb_uninit_gl(mpv_gl); } void MpvWidget::command(const QVariant& params) { mpv::qt::command_variant(mpv, params); } void MpvWidget::setProperty(const QString& name, const QVariant& value) { mpv::qt::set_property_variant(mpv, name, value); } QVariant MpvWidget::getProperty(const QString &name) const { return mpv::qt::get_property_variant(mpv, name); } void MpvWidget::initializeGL() { int r = mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address, NULL); if (r < 0) throw std::runtime_error("could not initialize OpenGL"); } void MpvWidget::paintGL() { mpv_opengl_cb_draw(mpv_gl, defaultFramebufferObject(), width(), -height()); } void MpvWidget::swapped() { mpv_opengl_cb_report_flip(mpv_gl, 0); } void MpvWidget::on_mpv_events() { // Process all events, until the event queue is empty. while (mpv) { mpv_event *event = mpv_wait_event(mpv, 0); if (event->event_id == MPV_EVENT_NONE) { break; } handle_mpv_event(event); } } void MpvWidget::handle_mpv_event(mpv_event *event) { switch (event->event_id) { case MPV_EVENT_PROPERTY_CHANGE: { mpv_event_property *prop = (mpv_event_property *)event->data; if (strcmp(prop->name, "time-pos") == 0) { if (prop->format == MPV_FORMAT_DOUBLE) { double time = *(double *)prop->data; Q_EMIT positionChanged(time); } } else if (strcmp(prop->name, "duration") == 0) { if (prop->format == MPV_FORMAT_DOUBLE) { double time = *(double *)prop->data; Q_EMIT durationChanged(time); } } break; } default: ; // Ignore uninteresting or unknown events. } } void MpvWidget::on_update(void *ctx) { QMetaObject::invokeMethod((MpvWidget*)ctx, "update"); } mpv-0.14.0/DOCS/client_api_examples/qt_opengl/mpvwidget.h000066400000000000000000000016641263261175500233210ustar00rootroot00000000000000#ifndef PLAYERWINDOW_H #define PLAYERWINDOW_H #include #include #include #include class MpvWidget Q_DECL_FINAL: public QOpenGLWidget { Q_OBJECT public: MpvWidget(QWidget *parent = 0, Qt::WindowFlags f = 0); ~MpvWidget(); void command(const QVariant& params); void setProperty(const QString& name, const QVariant& value); QVariant getProperty(const QString& name) const; QSize sizeHint() const { return QSize(480, 270);} Q_SIGNALS: void durationChanged(int value); void positionChanged(int value); protected: void initializeGL() Q_DECL_OVERRIDE; void paintGL() Q_DECL_OVERRIDE; private Q_SLOTS: void swapped(); void on_mpv_events(); private: void handle_mpv_event(mpv_event *event); static void on_update(void *ctx); mpv::qt::Handle mpv; mpv_opengl_cb_context *mpv_gl; }; #endif // PLAYERWINDOW_H mpv-0.14.0/DOCS/client_api_examples/qt_opengl/qt_opengl.pro000066400000000000000000000003331263261175500236440ustar00rootroot00000000000000CONFIG -= app_bundle QT += widgets QT_CONFIG -= no-pkg-config CONFIG += link_pkgconfig debug PKGCONFIG += mpv HEADERS = \ mpvwidget.h \ mainwindow.h SOURCES = main.cpp \ mpvwidget.cpp \ mainwindow.cpp mpv-0.14.0/DOCS/client_api_examples/sdl/000077500000000000000000000000001263261175500177255ustar00rootroot00000000000000mpv-0.14.0/DOCS/client_api_examples/sdl/main.c000066400000000000000000000127661263261175500210310ustar00rootroot00000000000000// Build with: gcc -o main main.c `pkg-config --libs --cflags mpv sdl2` #include #include #include #include #include #include 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; } mpv-0.14.0/DOCS/client_api_examples/simple/000077500000000000000000000000001263261175500204345ustar00rootroot00000000000000mpv-0.14.0/DOCS/client_api_examples/simple/simple.c000066400000000000000000000026151263261175500220750ustar00rootroot00000000000000// Build with: gcc -o simple simple.c `pkg-config --libs --cflags mpv` #include #include #include #include static inline void check_error(int status) { if (status < 0) { printf("mpv API error: %s\n", mpv_error_string(status)); exit(1); } } int main(int argc, char *argv[]) { if (argc != 2) { printf("pass a single media file as argument\n"); return 1; } mpv_handle *ctx = mpv_create(); if (!ctx) { printf("failed creating context\n"); return 1; } // Enable default key bindings, so the user can actually interact with // the player (and e.g. close the window). check_error(mpv_set_option_string(ctx, "input-default-bindings", "yes")); mpv_set_option_string(ctx, "input-vo-keyboard", "yes"); int val = 1; check_error(mpv_set_option(ctx, "osc", MPV_FORMAT_FLAG, &val)); // Done setting up options. check_error(mpv_initialize(ctx)); // Play this file. const char *cmd[] = {"loadfile", argv[1], NULL}; check_error(mpv_command(ctx, cmd)); // Let it play, and wait until the user quits. while (1) { mpv_event *event = mpv_wait_event(ctx, 10000); printf("event: %s\n", mpv_event_name(event->event_id)); if (event->event_id == MPV_EVENT_SHUTDOWN) break; } mpv_terminate_destroy(ctx); return 0; } mpv-0.14.0/DOCS/compile-windows.md000066400000000000000000000144451263261175500166100ustar00rootroot00000000000000Compiling for Windows ===================== Compiling for Windows is supported with MinGW-w64. This can be used to produce both 32-bit and 64-bit executables, and it works for building on Windows and cross-compiling from Linux and Cygwin. MinGW-w64 is available from: http://mingw-w64.sourceforge.net. While building a complete MinGW-w64 toolchain yourself is possible, there are a few build environments and scripts to help ease the process, such as MSYS2 and MXE. Note that MinGW environments included in Linux distributions are often broken, outdated and useless, and usually don't use MinGW-w64. **Warning**: the original MinGW (http://www.mingw.org) is unsupported. Cross-compilation ================= When cross-compiling, you have to run mpv's configure with these arguments: ```bash DEST_OS=win32 TARGET=i686-w64-mingw32 ./waf configure ``` [MXE](http://mxe.cc) makes it very easy to bootstrap a complete MingGW-w64 environment from a Linux machine. See a working example below. Alternatively, you can try [mingw-w64-cmake](https://github.com/lachs0r/mingw-w64-cmake), which bootstraps a MinGW-w64 environment and builds mpv and dependencies. Example with MXE ---------------- ```bash # Before starting, make sure you install MXE prerequisites. MXE will download # and build all target dependencies, but no host dependencies. For example, # you need a working compiler, or MXE can't build the crosscompiler. # # Refer to # # http://mxe.cc/#requirements # # Scroll down for disto/OS-specific instructions to install them. # Download MXE. Note that compiling the required packages requires about 1.4 GB # or more! cd /opt git clone https://github.com/mxe/mxe mxe cd mxe # Set build options. # The JOBS environment variable controls threads to use when building. DO NOT # use the regular `make -j4` option with MXE as it will slow down the build. # Alternatively, you can set this in the make command by appending "JOBS=4" # to the end of command: echo "JOBS := 4" >> settings.mk # The MXE_TARGET environment variable builds MinGW-w64 for 32 bit targets. # Alternatively, you can specify this in the make command by appending # "MXE_TARGETS=i686-w64-mingw32" to the end of command: echo "MXE_TARGETS := i686-w64-mingw32.static" >> settings.mk # If you want to build 64 bit version, use this: # echo "MXE_TARGETS := x86_64-w64-mingw32.static" >> settings.mk # Build required packages. The following provide a minimum required to build # a reasonable mpv binary (though not an absolute minimum). make gcc ffmpeg libass jpeg pthreads lua # Add MXE binaries to $PATH export PATH=/opt/mxe/usr/bin/:$PATH # Build mpv. The target will be used to automatically select the name of the # build tools involved (e.g. it will use i686-w64-mingw32.static-gcc). 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 ./waf build ``` Native compilation with MSYS2 ============================= For Windows developers looking to get started quickly, MSYS2 can be used to compile mpv natively on a Windows machine. The MSYS2 repositories have binary packages for most of mpv's dependencies, so the process should only involve building mpv itself. To build 64-bit mpv on Windows: Installing MSYS2 ---------------- 1. Download an installer from https://msys2.github.io/ It doesn't matter whether the i686 or the x86_64 version is used. Both can build 32-bit and 64-bit binaries when running on a 64-bit version of Windows. 2. Add ``C:\msys64\mingw64\bin`` to your ``%PATH%``. mpv will depend on several DLLs in this folder. 3. Start a MinGW-w64 shell (``mingw64_shell.bat``). For a 32-bit build, use ``mingw32_shell.bat``. Updating MSYS2 -------------- To prevent errors during post-install, ``msys2-runtime`` and ``pacman`` must be updated first. ```bash # Check for updates to msys2-runtime and pacman. If there were updates, restart # MSYS2 before continuing. pacman -Sy --needed msys2-runtime pacman # Update everything else pacman -Su ``` Installing mpv dependencies --------------------------- ```bash # Install MSYS2 build dependencies and a MinGW-w64 compiler 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 # Install additional (optional) dependencies pacman -S mingw-w64-x86_64-libdvdnav mingw-w64-x86_64-libguess ``` For a 32-bit build, install ``mingw-w64-i686-*`` packages instead. Building mpv ------------ Clone the latest mpv from git and install waf: ```bash git clone https://github.com/mpv-player/mpv.git && cd mpv ./bootstrap.py ``` Finally, compile and install mpv. Binaries will be installed to ``/mingw64/bin``. ```bash # For a 32-bit build, use --prefix=/mingw32 instead ./waf configure CC=gcc --prefix=/mingw64 ./waf install ``` Or, compile and install both libmpv and mpv: ```bash ./waf configure CC=gcc --enable-libmpv-shared --prefix=/mingw64 ./waf install # waf installs libmpv to the wrong directory, so fix it up mv -f /mingw64/bin/pkgconfig/mpv.pc /mingw64/lib/pkgconfig/ mv -f /mingw64/bin/libmpv.dll.a /mingw64/lib/ sed -i 's_/mingw64/bin_/mingw64/lib_' /mingw64/lib/pkgconfig/mpv.pc rmdir /mingw64/bin/pkgconfig ``` Additional dependencies ======================= pthreads -------- mpv will use a pthreads wrapper by default. Either pthreads-win32 or winpthreads should work. The latter is packaged with most MinGW-w64 environments, including MSYS2, so it shouldn't be a problem. If you don't have a pthreads wrapper or you want to build mpv without one, configure with: ```bash ./waf configure --enable-win32-internal-pthreads ``` libwaio ------- If you want to use ``--input-file``, you need libwaio. It's available from git://midipix.org/waio To compile libwaio in MSYS2, run: ```bash git clone git://midipix.org/waio && cd waio # 32-bit build, run from mingw32_shell.bat ./build-mingw-nt32 lib-static CC=gcc AR=ar cp -r include/waio /mingw32/include cp lib32/libwaio.a /mingw32/lib # 64-bit build, run from mingw64_shell.bat ./build-mingw-nt64 lib-static CC=gcc AR=ar cp -r include/waio /mingw64/include cp lib64/libwaio.a /mingw64/lib ``` mpv-0.14.0/DOCS/contribute.md000066400000000000000000000133461263261175500156450ustar00rootroot00000000000000How to contribute ================= General ------- The main contact for mpv development is IRC, specifically #mpv and #mpv-devel on Freenode. Sending patches --------------- - Make a github pull request, or send a link to a plaintext patch created with ``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. - The subject line (the first line in a commit message) should contain a prefix identifying the sub system, followed by a short description what impact this commit has. This subject line shouldn't be longer than 72 characters, because it messes up the output of many git tools otherwise. For example, you fixed a crash in af_volume.c: Bad: ``fixed the bug (wtf?)`` Good: ``af_volume: fix crash due to null pointer access`` Having a prefix gives context, and is especially useful when trying to find a specific change by looking at the history, or when running ``git blame``. - The body of the commit message (everything else after the subject line) should be as informative as possible and contain everything that isn't obvious. Don't hesitate to dump as much information as you can - it doesn't cost you anything. Put some effort into it. If someone finds a bug months or years later, and finds that it's caused by your commit (even though your commit was supposed to fix another bug), it would be bad if there wasn't enough information to test the original bug. The old bug might be reintroduced while fixing the new bug. The commit message should be wrapped on 72 characters per line, because git tools usually do not break text automatically. On the other hand, you do not need to break text that would be unnatural to break (like data for test cases, or long URLs). Important: put an empty line between the subject line and the commit message. If this is missing, it will break display in common git tools. - Try to separate cosmetic and functional changes. It's ok to make a few additional cosmetic changes in the same file you're working on. But don't do something like reformatting a whole file, and hiding an actual functional 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 --------------- mpv uses C99 with K&R formatting, with some exceptions. - Use the K&R indent style. - Use 4 spaces of indentation, never use tabs (except in Makefiles). - Add a single space between keywords and binary operators. There are some other cases where spaces should be added. Example: ```C if ((a * b) > c) { // code some_function(a, b, c); } ``` - Break lines on 80 columns. There is a hard limit of 85 columns. You may ignore this limit if there's a strong case that not breaking the line will increase readability. Going over 85 columns might provoke endless discussions about whether such a limit is needed or not, so avoid it. - If the body of an if/for/while statement has more than 1 physical lines, then always add braces, even if they're technically redundant. Bad: ```C if (a) // do something if b if (b) do_something(); ``` Good: ```C if (a) { // do something if b if (b) do_something(); } ``` - If the body of an if statement uses braces, the else branch should also use braces (and reverse). Example: ```C if (a) { // do something something(); something_else(); } else { one_line(); } ``` - If an if condition spans multiple physical lines, then put the opening brace for the if body on the next physical line. (Also, preferably always add a brace, even if technically none is needed.) Example: ```C if (very_long_condition_a && very_long_condition_b) { code(); } else { ... } ``` - Remove any trailing whitespace. - If the file you're editing uses formatting different from from what is described here, it's probably an old file from times when nobody followed a consistent style. You're free to use the existing style, or the new style, or to send a patch to reformat the file to the new style before making functional changes. General coding -------------- - Use C99. Also freely make use of C99 features if it's appropriate, such as stdbool.h. - Don't use GNU-only features. In some cases they may be warranted, if they are optional (such as attributes enabling printf-like format string checks). But in general, standard C99 should be used. - The same applies to libc functions. We have to be Windows-compatible too. Use functions guaranteed by C99 or POSIX only, unless your use is guarded by a configure check. - Prefer fusing declaration and initialization, rather than putting declarations on the top of a block. Obvious data flow is more important than avoiding mixing declarations and statements, which is just a C90 artifact. - tech-overview.txt might help to get an overview how mpv is structured. - If you add features that require intrusive changes, discuss them on the dev channel first. There might be a better way to add a feature and it can avoid wasted work. mpv-0.14.0/DOCS/edl-mpv.rst000066400000000000000000000105621263261175500152400ustar00rootroot00000000000000EDL files ========= EDL files basically concatenate ranges of video/audio from multiple source files into a single continuous virtual file. Each such range is called a segment, and consists of source file, source offset, and segment length. For example:: # mpv EDL v0 f1.mkv,10,20 f2.mkv f1.mkv,40,10 This would skip the first 10 seconds of the file f1.mkv, then play the next 20 seconds, then switch to the file f2.mkv and play all of it, then switch back to f1.mkv, skip to the 40 second mark, and play 10 seconds, and then stop playback. The difference to specifying the files directly on command line (and using ``--{ --start=10 --length=20 f1.mkv --}`` etc.) is that the virtual EDL file appears as a virtual timeline (like a single file), instead as a playlist. The general simplified syntax is:: # mpv EDL v0 ,, If the start time is omitted, 0 is used. If the length is omitted, the estimated remaining duration of the source file is used. Note:: mpv can't use ordered chapter files in EDL entries. Usage of relative or absolute paths as well as any protocol prefixes is prevented for security reasons. Syntax of mpv EDL files ======================= Generally, the format is relatively strict. No superfluous whitespace (except empty lines and commented lines) are allowed. You must use UNIX line breaks. The first line in the file must be ``# mpv EDL v0``. This designates that the file uses format version 0, which is not frozen yet and may change any time. (If you need a stable EDL file format, make a feature request. Likewise, if you have suggestions for improvements, it's not too late yet.) The rest of the lines belong to one of these classes: 1) An empty or commented line. A comment starts with ``#``, which must be the first character in the line. The rest of the line (up until the next line break) is ignored. An empty line has 0 bytes between two line feed bytes. 2) A segment entry in all other cases. Each segment entry consists of a list of named or unnamed parameters. Parameters are separated with ``,``. Named parameters consist of a name, followed by ``=``, followed by the value. Unnamed parameters have only a value, and the name is implicit from the parameter position. Syntax:: segment_entry ::= ( ',' )* param ::= [ '=' ] ( | '%' '%' ) The ``name`` string can consist of any characters, except ``=%,;\n``. The ``value`` string can consist of any characters except of ``,;\n``. The construct starting with ``%`` allows defining any value with arbitrary contents inline, where ``number`` is an integer giving the number of bytes in ``valuebytes``. If a parameter value contains disallowed characters, it has to be guarded by a length specifier using this syntax. The parameter name defines the meaning of the parameter: 1) ``file``, the source file to use for this segment. 2) ``start``, a time value that specifies the start offset into the source file. 3) ``length``, a time value that specifies the length of the segment. See the section below for the format of timestamps. Unnamed parameters carry implicit names. The parameter position determines which of the parameters listed above is set. For example, the second parameter implicitly uses the name ``start``. Example:: # mpv EDL v0 %18%filename,with,.mkv,10,length=20,param3=%13%value,escaped,param4=value2 this sets ``file`` to ``filename,with,.mkv``, ``start`` to ``10``, ``length`` to ``20``, ``param3`` to ``value,escaped``, ``param4`` to ``value2``. Instead of line breaks, the character ``;`` can be used. Line feed bytes and ``;`` are treated equally. Timestamp format ================ Currently, time values are floating point values in seconds. As an extension, you can set the ``timestamps=chapters`` option. If this option is set, timestamps have to be integers, and refer to chapter numbers, starting with 0. Example:: # mpv EDL v0 file.mkv,2,4,timestamps=chapters Plays chapter 3 and ends with the start of chapter 7 (4 chapters later). Syntax of EDL URIs ================== mpv accepts inline EDL data in form of ``edl://`` URIs. Other than the header, the syntax is exactly the same. It's far more convenient to use ``;`` instead of line breaks, but that is orthogonal. Example: ``edl://f1.mkv,length=5,start=10;f2.mkv,30,20;f3.mkv`` mpv-0.14.0/DOCS/encoding.rst000066400000000000000000000123351263261175500154620ustar00rootroot00000000000000General usage ============= :: mpv infile -o outfile [-of outfileformat] [-ofopts formatoptions] \ [-ofps outfps | -oautofps] [-oharddup] [-ocopyts | -orawts] [-oneverdrop] \ [(any other mpv options)] \ -ovc outvideocodec [-ovcopts outvideocodecoptions] \ -oac outaudiocodec [-oacopts outaudiocodecoptions] Help for these options is provided if giving help as parameter, as in:: mpv -ovc help The suboptions of these generally are identical to ffmpeg's (as option parsing is simply delegated to ffmpeg). The option -ocopyts enables copying timestamps from the source as-is, instead of fixing them to match audio playback time (note: this doesn't work with all output container formats); -orawts even turns off discontinuity fixing. Note that if neither -ofps nor -oautofps is specified, VFR encoding is assumed and the time base is 24000fps. -oautofps sets -ofps to a guessed fps number from the input video. Note that not all codecs and not all formats support VFR encoding, and some which do have bugs when a target bitrate is specified - use -ofps or -oautofps to force CFR encoding in these cases. Of course, the options can be stored in a profile, like this .config/mpv/mpv.conf section:: [myencprofile] vf-add = scale=480:-2 ovc = libx264 ovcopts-add = preset=medium,tune=fastdecode ovcopts-add = crf=23 ovcopts-add = maxrate=1500k,bufsize=1000k,rc_init_occupancy=900k,refs=2 ovcopts-add = profile=baseline oac = aac oacopts-add = b=96k It's also possible to define default encoding options by putting them into the section named ``[encoding]``. (This behavior changed after mpv 0.3.x. In mpv 0.3.x, config options in the default section / no section were applied to encoding. This is not the case anymore.) One can then encode using this profile using the command:: mpv infile -o outfile.mp4 -profile myencprofile Some example profiles are provided in a file etc/encoding-profiles.conf; as for this, see below. Encoding examples ================= These are some examples of encoding targets this code has been used and tested for. Typical MPEG-4 Part 2 ("ASP", "DivX") encoding, AVI container:: mpv infile -o outfile.avi \ -ofps 25 \ -ovc mpeg4 -ovcopts qscale=4 \ -oac libmp3lame -oacopts ab=128k Note: AVI does not support variable frame rate, so -ofps must be used. The frame rate should ideally match the input (25 for PAL, 24000/1001 or 30000/1001 for NTSC) Typical MPEG-4 Part 10 ("AVC", "H.264") encoding, Matroska (MKV) container:: mpv infile -o outfile.mkv \ -ovc libx264 -ovcopts preset=medium,crf=23,profile=baseline \ -oac libvorbis -oacopts qscale=3 Typical MPEG-4 Part 10 ("AVC", "H.264") encoding, MPEG-4 (MP4) container:: mpv infile -o outfile.mp4 \ -ovc libx264 -ovcopts preset=medium,crf=23,profile=baseline \ -oac aac -oacopts ab=128k Typical VP8 encoding, WebM (restricted Matroska) container:: mpv infile -o outfile.mkv \ -of webm \ -ovc libvpx -ovcopts qmin=6,b=1000000k \ -oac libvorbis -oacopts qscale=3 Device targets ============== As the options for various devices can get complex, profiles can be used. An example profile file for encoding is provided in etc/encoding-profiles.conf in the source tree. This file is installed and loaded by default (if libavfilter is enabled at compilation). If you want to modify it, you can replace and it with your own copy by doing:: mkdir -p ~/.mpv cp /etc/mpv/encoding-profiles.conf ~/.mpv/encoding-profiles.conf Refer to the top of that file for more comments - in a nutshell, the following options are added by it:: -profile enc-to-dvdpal DVD-Video PAL, use dvdauthor -v pal+4:3 -a ac3+en -profile enc-to-dvdntsc DVD-Video NTSC, use dvdauthor -v ntsc+4:3 -a ac3+en -profile enc-to-bb-9000 MP4 for Blackberry Bold 9000 -profile enc-to-nok-6300 3GP for Nokia 6300 -profile enc-to-psp MP4 for PlayStation Portable -profile enc-to-iphone MP4 for iPhone -profile enc-to-iphone-4 MP4 for iPhone 4 (double res) -profile enc-to-iphone-5 MP4 for iPhone 5 (even larger res) You can encode using these with a command line like:: mpv infile -o outfile.mp4 -profile enc-to-bb-9000 Of course, you are free to override options set by these profiles by specifying them after the -profile option. What works ========== * Encoding at variable frame rate (default) * Encoding at constant frame rate using -ofps framerate -oharddup * 2-pass encoding (specify flags=+pass1 in the first pass's -ovcopts, specify flags=+pass2 in the second pass) * Hardcoding subtitles using vobsub, ass or srt subtitle rendering (just configure mpv for the subtitles as usual) * Hardcoding any other mpv OSD (e.g. time codes, using -osdlevel 3 and -vf expand=::::1) * Encoding directly from a DVD, network stream, webcam, or any other source mpv supports * Using x264 presets/tunings/profiles (by using profile=, tune=, preset= in the -ovcopts) * Deinterlacing/Inverse Telecine with any of mpv's filters for that * Audio file converting: mpv -o outfile.mp3 infile.flac -no-video -oac libmp3lame -oacopts ab=320k What does not work yet ====================== * 3-pass encoding (ensuring constant total size and bitrate constraints while having VBR audio; mencoder calls this "frameno") * Direct stream copy mpv-0.14.0/DOCS/interface-changes.rst000066400000000000000000000123741263261175500172450ustar00rootroot00000000000000Introduction ============ 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.14.0 --- - vo_opengl interpolation now requires --video-sync=display-... to be set - change some vo_opengl defaults (including changing tscale) - add "vsync-ratio", "estimated-display-fps" properties - add --rebase-start-time option This is a breaking change to start time handling. Instead of making start time handling an aspect of different options and properties (like "time-pos" vs. "playback-time"), make it dependent on the new option. For compatibility, the "time-start" property now always returns 0, so code which attempted to handle rebasing manually will not break. --- mpv 0.13.0 --- - remove VO opengl-cb frame queue suboptions (no replacement) --- mpv 0.12.0 --- - remove --use-text-osd (useless; fontconfig isn't a requirement anymore, and text rendering is also lazily initialized) - some time properties (at least "playback-time", "time-pos", "time-remaining", "playtime-remaining") now are unavailable if the time is unknown, instead of just assuming that the internal playback position is 0 - add --audio-fallback-to-null option - replace vf_format outputlevels suboption with "video-output-levels" global property/option; also remove "colormatrix-output-range" property - vo_opengl: remove sharpen3/sharpen5 scale filters, add sharpen sub-option --- 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//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 --- mpv-0.14.0/DOCS/man/000077500000000000000000000000001263261175500137115ustar00rootroot00000000000000mpv-0.14.0/DOCS/man/af.rst000066400000000000000000000456431263261175500150450ustar00rootroot00000000000000AUDIO FILTERS ============= Audio filters allow you to modify the audio stream and its properties. The syntax is: ``--af=`` Setup a chain of audio filters. .. note:: 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. ``--af-defaults=`` Set defaults for each filter. Audio filters are managed in lists. There are a few commands to manage the filter list: ``--af-add=`` Appends the filters given as arguments to the filter list. ``--af-pre=`` Prepends the filters given as arguments to the filter list. ``--af-del=`` Deletes the filters at the given indexes. Index numbers start at 0, negative numbers address the end of the list (-1 is the last). ``--af-clr`` Completely empties the filter list. Available filters are: ``lavrresample[=option1:option2:...]`` This filter uses libavresample (or libswresample, depending on the build) to change sample rate, sample format, or channel layout of the audio stream. This filter is automatically enabled if the audio output does not support the audio configuration of the file being played. It supports only the following sample formats: u8, s16, s32, float. ``filter-size=`` Length of the filter with respect to the lower sampling rate. (default: 16) ``phase-shift=`` Log2 of the number of polyphase entries. (..., 10->1024, 11->2048, 12->4096, ...) (default: 10->1024) ``cutoff=`` Cutoff frequency (0.0-1.0), default set depending upon filter length. ``linear`` If set then filters will be linearly interpolated between polyphase entries. (default: no) ``no-detach`` Do not detach if input and output audio format/rate/channels match. (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=`` 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=`` Set AVOptions on the SwrContext or AVAudioResampleContext. These should be documented by FFmpeg or Libav. ``lavcac3enc[=tospdif[:bitrate[:minch]]]`` 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 outputting to S/PDIF. If the input sample rate is not 48 kHz, 44.1 kHz or 32 kHz, it will be resampled to 48 kHz. ``tospdif=`` Output raw AC-3 stream if ``no``, output to S/PDIF for pass-through if ``yes`` (default). ``bitrate=`` The bitrate use for the AC-3 stream. Set it to 384 to get 384 kbps. The default is 640. Some receivers might not be able to handle this. Valid values: 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640. The special value ``auto`` selects a default bitrate based on the input channel number: :1ch: 96 :2ch: 192 :3ch: 224 :4ch: 384 :5ch: 448 :6ch: 448 ``minch=`` If the input channel number is less than ````, the filter will detach itself (default: 3). ``equalizer=g1:g2:g3:...:g10`` 10 octave band graphic equalizer, implemented using 10 IIR band-pass filters. This means that it works regardless of what type of audio is being played back. The center frequencies for the 10 bands are: === ========== No. frequency === ========== 0 31.25 Hz 1 62.50 Hz 2 125.00 Hz 3 250.00 Hz 4 500.00 Hz 5 1.00 kHz 6 2.00 kHz 7 4.00 kHz 8 8.00 kHz 9 16.00 kHz === ========== If the sample rate of the sound being played is lower than the center frequency for a frequency band, then that band will be disabled. A known bug with this filter is that the characteristics for the uppermost band are not completely symmetric if the sample rate is close to the center frequency of that band. This problem can be worked around by upsampling the sound using a resampling filter before it reaches this filter. ``:::...:`` floating point numbers representing the gain in dB for each frequency band (-12-12) .. admonition:: Example ``mpv --af=equalizer=11:11:10:5:0:-12:0:5:12:12 media.avi`` Would amplify the sound in the upper and lower frequency region while canceling it almost completely around 1 kHz. ``channels=nch[:routes]`` Can be used for adding, removing, routing and copying audio channels. If only ```` is given, the default routing is used. It works as follows: If the number of output channels is greater than the number of input channels, empty channels are inserted (except when mixing from mono to stereo; then the mono channel is duplicated). If the number of output channels is less than the number of input channels, the exceeding channels are truncated. ```` number of output channels (1-8) ```` List of ``,`` separated routes, in the form ``from1-to1,from2-to2,...``. Each pair defines where to route each channel. There can be at most 8 routes. Without this argument, the default routing is used. Since ``,`` is also used to separate filters, you must quote this argument with ``[...]`` or similar. .. admonition:: Examples ``mpv --af=channels=4:[0-1,1-0,2-2,3-3] media.avi`` Would change the number of channels to 4 and set up 4 routes that swap channel 0 and channel 1 and leave channel 2 and 3 intact. Observe that if media containing two channels were played back, channels 2 and 3 would contain silence but 0 and 1 would still be swapped. ``mpv --af=channels=6:[0-0,0-1,0-2,0-3] media.avi`` Would change the number of channels to 6 and set up 4 routes that copy channel 0 to channels 0 to 3. Channel 4 and 5 will contain silence. .. note:: You should probably not use this filter. If you want to change the output channel layout, try the ``format`` filter, which can make mpv automatically up- and downmix standard channel layouts. ``format=format:srate:channels:out-format:out-srate:out-channels`` Does not do any format conversion itself. Rather, it may cause the filter system to insert necessary conversion filters before or after this 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. 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. ```` Force conversion to this format. Use ``--af=format=format=help`` to get a list of valid formats. ```` Force conversion to a specific sample rate. The rate is an integer, 48000 for example. ```` Force mixing to a specific channel layout. See ``--audio-channels`` option for possible values. ```` ```` ```` *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. ``volume[=[:...]]`` Implements software volume control. Use this filter with caution since it can reduce the signal to noise ratio of the sound. In most cases it is best to use the *Master* volume control of your sound card or the volume knob on your amplifier. *NOTE*: This filter is not reentrant and can therefore only be enabled once for every audio stream. ```` Sets the desired gain in dB for all channels in the stream from -200 dB to +60 dB, where -200 dB mutes the sound completely and +60 dB equals a gain of 1000 (default: 0). ``replaygain-track`` Adjust volume gain according to the track-gain replaygain value stored in the file metadata. ``replaygain-album`` Like replaygain-track, but using the album-gain value instead. ``replaygain-preamp`` Pre-amplification gain in dB to apply to the selected replaygain gain (default: 0). ``replaygain-clip=yes|no`` Prevent clipping caused by replaygain by automatically lowering the gain (default). Use ``replaygain-clip=no`` to disable this. ``replaygain-fallback`` Gain in dB to apply if the file has no replay gain tags. This option is always applied if the replaygain logic is somehow inactive. If this is applied, no other replaygain options are applied. ``softclip`` Turns soft clipping on. Soft-clipping can make the sound more smooth if very high volume levels are used. Enable this option if the dynamic range of the loudspeakers is very low. *WARNING*: This feature creates distortion and should be considered a last resort. ``s16`` Force S16 sample format if set. Lower quality, but might be faster in some situations. ``detach`` Remove the filter if the volume is not changed at audio filter config time. Useful with replaygain: if the current file has no replaygain tags, then the filter will be removed if this option is enabled. (If ``--softvol=yes`` is used and the player volume controls are used during playback, a different volume filter will be inserted.) .. admonition:: Example ``mpv --af=volume=10.1 media.avi`` Would amplify the sound by 10.1 dB and hard-clip if the sound level is too high. ``pan=n:[]`` Mixes channels arbitrarily. Basically a combination of the volume and the channels filter that can be used to down-mix many channels to only a few, e.g. stereo to mono, or vary the "width" of the center speaker in a surround sound system. This filter is hard to use, and will require some tinkering before the desired result is obtained. The number of options for this filter depends on the number of output channels. An example how to downmix a six-channel file to two channels with this filter can be found in the examples section near the end. ```` Number of output channels (1-8). ```` A list of values ``[L00,L01,L02,...,L10,L11,L12,...,Ln0,Ln1,Ln2,...]``, where each element ``Lij`` means how much of input channel i is mixed into output channel j (range 0-1). So in principle you first have n numbers saying what to do with the first input channel, then n numbers that act on the second input channel etc. If you do not specify any numbers for some input channels, 0 is assumed. Note that the values are separated by ``,``, which is already used by the option parser to separate filters. This is why you must quote the value list with ``[...]`` or similar. .. admonition:: Examples ``mpv --af=pan=1:[0.5,0.5] media.avi`` Would downmix from stereo to mono. ``mpv --af=pan=3:[1,0,0.5,0,1,0.5] media.avi`` Would give 3 channel output leaving channels 0 and 1 intact, and mix channels 0 and 1 into output channel 2 (which could be sent to a subwoofer for example). .. note:: If you just want to force remixing to a certain output channel layout, it is easier to use the ``format`` filter. For example, ``mpv '--af=format=channels=5.1' '--audio-channels=5.1'`` would always force remixing audio to 5.1 and output it like this. ``delay[=[ch1,ch2,...]]`` Delays the sound to the loudspeakers such that the sound from the different channels arrives at the listening position simultaneously. It is only useful if you have more than 2 loudspeakers. ``[ch1,ch2,...]`` The delay in ms that should be imposed on each channel (floating point number between 0 and 1000). To calculate the required delay for the different channels, do as follows: 1. Measure the distance to the loudspeakers in meters in relation to your listening position, giving you the distances s1 to s5 (for a 5.1 system). There is no point in compensating for the subwoofer (you will not hear the difference anyway). 2. Subtract the distances s1 to s5 from the maximum distance, i.e. ``s[i] = max(s) - s[i]; i = 1...5``. 3. Calculate the required delays in ms as ``d[i] = 1000*s[i]/342; i = 1...5``. .. admonition:: Example ``mpv --af=delay=[10.5,10.5,0,0,7,0] media.avi`` Would delay front left and right by 10.5 ms, the two rear channels and the subwoofer by 0 ms and the center channel by 7 ms. ``drc[=method:target]`` Applies dynamic range compression. This maximizes the volume by compressing the audio signal's dynamic range. (Formerly called ``volnorm``.) ```` Sets the used method. 1 Use a single sample to smooth the variations via the standard weighted mean over past samples (default). 2 Use several samples to smooth the variations via the standard weighted mean over past samples. ```` Sets the target amplitude as a fraction of the maximum for the sample type (default: 0.25). .. note:: This filter can cause distortion with audio signals that have a very large dynamic range. ``scaletempo[=option1:option2:...]`` Scales audio tempo without altering pitch, optionally synced to playback speed (default). This works by playing 'stride' ms of audio at normal speed then consuming 'stride*scale' ms of input audio. It pieces the strides together by blending 'overlap'% of stride with audio following the previous stride. It optionally performs a short statistical analysis on the next 'search' ms of audio to determine the best overlap position. ``scale=`` Nominal amount to scale tempo. Scales this amount in addition to speed. (default: 1.0) ``stride=`` Length in milliseconds to output each stride. Too high of a value will cause noticeable skips at high scale amounts and an echo at low scale amounts. Very low values will alter pitch. Increasing improves performance. (default: 60) ``overlap=`` Percentage of stride to overlap. Decreasing improves performance. (default: .20) ``search=`` Length in milliseconds to search for best overlap position. Decreasing improves performance greatly. On slow systems, you will probably want to set this very low. (default: 14) ``speed=`` Set response to speed change. tempo Scale tempo in sync with speed (default). pitch Reverses effect of filter. Scales pitch without altering tempo. Add this to your ``input.conf`` to step by musical semi-tones:: [ multiply speed 0.9438743126816935 ] multiply speed 1.059463094352953 .. warning:: Loses sync with video. both Scale both tempo and pitch. none Ignore speed changes. .. admonition:: Examples ``mpv --af=scaletempo --speed=1.2 media.ogg`` Would play media at 1.2x normal speed, with audio at normal pitch. Changing playback speed would change audio tempo to match. ``mpv --af=scaletempo=scale=1.2:speed=none --speed=1.2 media.ogg`` Would play media at 1.2x normal speed, with audio at normal pitch, but changing playback speed would have no effect on audio tempo. ``mpv --af=scaletempo=stride=30:overlap=.50:search=10 media.ogg`` Would tweak the quality and performance parameters. ``mpv --af=format=float,scaletempo media.ogg`` Would make scaletempo use float code. Maybe faster on some platforms. ``mpv --af=scaletempo=scale=1.2:speed=pitch audio.ogg`` Would play media at 1.2x normal speed, with audio at normal pitch. 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. ```` Libavfilter graph. See ``lavfi`` video filter for details - the graph syntax is the same. .. warning:: Don't forget to quote libavfilter graphs as described in the lavfi video filter section. ``o=`` AVOptions. mpv-0.14.0/DOCS/man/ao.rst000066400000000000000000000344451263261175500150540ustar00rootroot00000000000000AUDIO OUTPUT DRIVERS ==================== Audio output drivers are interfaces to different audio output facilities. The syntax is: ``--ao=`` Specify a priority list of audio output drivers to be used. If the list has a trailing ',', mpv will fall back on drivers not contained in the list. Suboptions are optional and can mostly be omitted. You can also set defaults for each driver. The defaults are applied before the normal driver parameters. ``--ao-defaults=`` Set defaults for each driver. .. note:: See ``--ao=help`` for a list of compiled-in audio output drivers. The driver ``--ao=alsa`` is preferred. ``--ao=pulse`` is preferred on systems where PulseAudio is used. On Windows, ``--ao=wasapi`` is preferred, though it might cause trouble sometimes, in which case ``--ao=dsound`` should be used. On BSD systems, ``--ao=oss`` or `--ao=sndio`` may work (the latter being experimental). On OS X systems, use ``--ao=coreaudio``. .. admonition:: Examples - ``--ao=alsa,oss,`` Try the ALSA driver, then the OSS driver, then others. - ``--ao=alsa:resample=yes:device=[plughw:0,3]`` Lets ALSA resample and sets the device-name as first card, fourth device. Available audio output drivers are: ``alsa`` (Linux only) ALSA audio output driver ``device=`` Sets the device name. For ac3 output via S/PDIF, use an "iec958" or "spdif" device, unless you really know how to set it correctly. ``resample=yes`` Enable ALSA resampling plugin. (This is disabled by default, because some drivers report incorrect audio delay in some cases.) ``mixer-device=`` Set the mixer device used with ``--no-softvol`` (default: ``default``). ``mixer-name=`` Set the name of the mixer element (default: ``Master``). This is for example ``PCM`` or ``Master``. ``mixer-index=`` Set the index of the mixer channel (default: 0). Consider the output of "``amixer scontrols``", then the index is the number that follows the name of the element. ``non-interleaved`` 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:: MPlayer and mplayer2 required you to replace any ',' with '.' and any ':' with '=' in the ALSA device name. mpv does not do this anymore. Instead, quote the device name: ``--ao=alsa:device=[plug:surround50]`` Note that the ``[`` and ``]`` simply quote the device name. With some shells (like zsh), you have to quote the option string to prevent the shell from interpreting the brackets instead of passing them to mpv. Actually, you should use the ``--audio-device`` option, instead of setting the device directly. .. warning:: Handling of multichannel/surround audio changed in mpv 0.8.0 from the behavior in MPlayer/mplayer2 and older versions of mpv. The old behavior is that the player always downmixed to stereo by default. The ``--audio-channels`` (or ``--channels`` before that) option had to be set to get multichannel audio. Then playing stereo would use the ``default`` device (which typically allows multiple programs to play audio at the same time via dmix), while playing anything with more channels would open one of the hardware devices, e.g. via the ``surround51`` alias (typically with exclusive access). Whether the player would use exclusive access or not would depend on the file being played. The new behavior since mpv 0.8.0 always enables multichannel audio, i.e. ``--audio-channels=auto`` is the default. However, since ALSA provides no good way to play multichannel audio in a non-exclusive way (without blocking other applications from using audio), the player is restricted to the capabilities of the ``default`` device by default, which means it supports only stereo and mono (at least with current typical ALSA configurations). But if a hardware device is selected, then multichannel audio will typically work. The short story is: if you want multichannel audio with ALSA, use ``--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 `_. 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. ``oss`` OSS audio output driver ```` Sets the audio output device (default: ``/dev/dsp``). ```` Sets the audio mixer device (default: ``/dev/mixer``). ```` Sets the audio mixer channel (default: ``pcm``). Other valid values include **vol, pcm, line**. For a complete list of options look for ``SOUND_DEVICE_NAMES`` in ``/usr/include/linux/soundcard.h``. ``jack`` JACK (Jack Audio Connection Kit) audio output driver ``port=`` Connects to the ports with the given name (default: physical ports). ``name=`` Client name that is passed to JACK (default: ``mpv``). Useful if you want to have certain connections established automatically. ``(no-)autostart`` Automatically start jackd if necessary (default: disabled). Note that this tends to be unreliable and will flood stdout with server messages. ``(no-)connect`` Automatically create connections to output ports (default: enabled). When enabled, the maximum number of output channels will be limited to the number of available output ports. ``std-channel-layout=waveext|any`` Select the standard channel layout (default: waveext). JACK itself has no notion of channel layouts (i.e. assigning which speaker a given channel is supposed to map to) - it just takes whatever the application outputs, and reroutes it to whatever the user defines. This means the user and the application are in charge of dealing with the channel layout. ``waveext`` uses WAVE_FORMAT_EXTENSIBLE order, which, even though it was defined by Microsoft, is the standard on many systems. The value ``any`` makes JACK accept whatever comes from the audio filter chain, regardless of channel layout and without reordering. This mode is probably not very useful, other than for debugging or when used with fixed setups. ``coreaudio`` (Mac OS X only) Native Mac OS X audio output driver using AudioUnits and the CoreAudio sound server. Automatically redirects to ``coreaudio_exclusive`` when playing compressed formats. ``change-physical-format=`` 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). ``openal`` Experimental OpenAL audio output driver .. note:: This driver is not very useful. Playing multi-channel audio with it is slow. ``pulse`` PulseAudio audio output driver ``[][:]`` Specify the host and optionally output sink to use. An empty string uses a local connection, "localhost" uses network transfer (most likely not what you want). ``buffer=<1-2000|native>`` Set the audio buffer size in milliseconds. A higher value buffers more data, and has a lower probability of buffer underruns. A smaller value makes the audio stream react faster, e.g. to playback speed changes. Default: 250. ``latency-hacks=`` Enable hacks to workaround PulseAudio timing bugs (default: no). If enabled, mpv will do elaborate latency calculations on its own. If disabled, it will use PulseAudio automatically updated timing information. Disabling this might help with e.g. networked audio or some plugins, while enabling it might help in some unknown situations (it used to be required to get good behavior on old PulseAudio versions). If you have stuttering video when using pulse, try to enable this option. (Or alternatively, try to update PulseAudio.) ``dsound`` (Windows only) DirectX DirectSound audio output driver .. note:: This driver is for compatibility with old systems. ``device=`` Sets the device number to use. Playing a file with ``-v`` will show a list of available devices. ``buffersize=`` DirectSound buffer size in milliseconds (default: 200). ``sdl`` SDL 1.2+ audio output driver. Should work on any platform supported by SDL 1.2, but may require the ``SDL_AUDIODRIVER`` environment variable to be set appropriately for your system. .. note:: This driver is for compatibility with extremely foreign environments, such as systems where none of the other drivers are available. ``buflen=`` Sets the audio buffer length in seconds. Is used only as a hint by the sound system. Playing a file with ``-v`` will show the requested and obtained exact buffer size. A value of 0 selects the sound system default. ``bufcnt=`` Sets the number of extra audio buffers in mpv. Usually needs not be changed. ``null`` Produces no audio output but maintains video playback speed. Use ``--ao=null:untimed`` for benchmarking. ``untimed`` Do not simulate timing of a perfect audio device. This means audio decoding will go as fast as possible, instead of timing it to the system clock. ``buffer`` Simulated buffer length in seconds. ``outburst`` Simulated chunk size in samples. ``speed`` Simulated audio playback speed as a multiplier. Usually, a real audio device will not go exactly as fast as the system clock. It will deviate just a little, and this option helps simulating this. ``latency`` Simulated device latency. This is additional to EOF. ``broken-eof`` Simulate broken audio drivers, which always add the fixed device latency to the reported audio playback position. ``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 ``(no-)waveheader`` Include or do not include the WAVE header (default: included). When not included, raw PCM will be generated. ``file=`` Write the sound to ```` instead of the default ``audiodump.wav``. If ``no-waveheader`` is specified, the default is ``audiodump.pcm``. ``(no-)append`` Append to the file, instead of overwriting it. Always use this with the ``no-waveheader`` option - with ``waveheader`` it's broken, because it will write a WAVE header every time the file is opened. ``rsound`` Audio output to an RSound daemon .. note:: Completely useless, unless you intend to run RSound. Not to be confused with RoarAudio, which is something completely different. ``host=`` Set the address of the server (default: localhost). Can be either a network hostname for TCP connections or a Unix domain socket path starting with '/'. ``port=`` Set the TCP port used for connecting to the server (default: 12345). Not used if connecting to a Unix domain socket. ``sndio`` Audio output to the OpenBSD sndio sound system .. note:: Experimental. There are known bugs and issues. (Note: only supports mono, stereo, 4.0, 5.1 and 7.1 channel layouts.) ``device=`` sndio device to use (default: ``$AUDIODEVICE``, resp. ``snd0``). ``wasapi`` Audio output to the Windows Audio Session API. ``exclusive`` Requests exclusive, direct hardware access. By definition prevents sound playback of any other program until mpv exits. ``device=`` 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. mpv-0.14.0/DOCS/man/changes.rst000066400000000000000000000007721263261175500160610ustar00rootroot00000000000000CHANGELOG ========= There is no real changelog, but you can look at the following things: * The release changelog, which should contain most user-visible changes, including new features and bug fixes: https://github.com/mpv-player/mpv/releases * The git log, which is the "real" changelog * The file ``mplayer-changes.rst`` in the ``DOCS`` sub directory on the git repository, which used to be in place of this section. It documents some changes that happened since mplayer2 forked off MPlayer. mpv-0.14.0/DOCS/man/encode.rst000066400000000000000000000132511263261175500157020ustar00rootroot00000000000000ENCODING ======== You can encode files from one format/codec to another using this facility. ``--o=`` Enables encoding mode and specifies the output file name. ``--of=`` Specifies the output format (overrides autodetection by the file name extension of the file specified by ``-o``). This can be a comma separated list of possible formats to try. See ``--of=help`` for a full list of supported formats. ``--ofopts=`` Specifies the output format options for libavformat. See ``--ofopts=help`` for a full list of supported options. Options are managed in lists. There are a few commands to manage the options list. ``--ofopts-add=`` Appends the options given as arguments to the options list. ``--ofopts-pre=`` Prepends the options given as arguments to the options list. ``--ofopts-del=`` Deletes the options at the given indexes. Index numbers start at 0, negative numbers address the end of the list (-1 is the last). ``--ofopts-clr`` Completely empties the options list. ``--ofps=`` Specifies the output format time base (default: 24000). Low values like 25 limit video fps by dropping frames. ``--oautofps`` Sets the output format time base to the guessed frame rate of the input video (simulates MEncoder behavior, useful for AVI; may cause frame drops). Note that not all codecs and not all formats support VFR encoding, and some which do have bugs when a target bitrate is specified - use ``--ofps`` or ``--oautofps`` to force CFR encoding in these cases. ``--omaxfps=`` Specifies the minimum distance of adjacent frames (default: 0, which means unset). Content of lower frame rate is not readjusted to this frame rate; content of higher frame rate is decimated to this frame rate. ``--oharddup`` If set, the frame rate given by ``--ofps`` is attained not by skipping time codes, but by duplicating frames (constant frame rate mode). ``--oneverdrop`` If set, frames are never dropped. Instead, time codes of video are readjusted to always increase. This may cause AV desync, though; to work around this, use a high-fps time base using ``--ofps`` and absolutely avoid ``--oautofps``. ``--oac=`` Specifies the output audio codec. This can be a comma separated list of possible codecs to try. See ``--oac=help`` for a full list of supported codecs. ``--oaoffset=`` Shifts audio data by the given time (in seconds) by adding/removing samples at the start. ``--oacopts=`` Specifies the output audio codec options for libavcodec. See ``--oacopts=help`` for a full list of supported options. .. admonition:: Example "``--oac=libmp3lame --oacopts=b=128000``" selects 128 kbps MP3 encoding. Options are managed in lists. There are a few commands to manage the options list. ``--oacopts-add=`` Appends the options given as arguments to the options list. ``--oacopts-pre=`` Prepends the options given as arguments to the options list. ``--oacopts-del=`` Deletes the options at the given indexes. Index numbers start at 0, negative numbers address the end of the list (-1 is the last). ``--oacopts-clr`` Completely empties the options list. ``--oafirst`` Force the audio stream to become the first stream in the output. By default the order is unspecified. ``--ovc=`` Specifies the output video codec. This can be a comma separated list of possible codecs to try. See ``--ovc=help`` for a full list of supported codecs. ``--ovoffset=`` Shifts video data by the given time (in seconds) by shifting the pts values. ``--ovcopts `` Specifies the output video codec options for libavcodec. See --ovcopts=help for a full list of supported options. .. admonition:: Examples ``"--ovc=mpeg4 --ovcopts=qscale=5"`` selects constant quantizer scale 5 for MPEG-4 encoding. ``"--ovc=libx264 --ovcopts=crf=23"`` selects VBR quality factor 23 for H.264 encoding. Options are managed in lists. There are a few commands to manage the options list. ``--ovcopts-add=`` Appends the options given as arguments to the options list. ``--ovcopts-pre=`` Prepends the options given as arguments to the options list. ``--ovcopts-del=`` Deletes the options at the given indexes. Index numbers start at 0, negative numbers address the end of the list (-1 is the last). ``--ovcopts-clr`` Completely empties the options list. ``--ovfirst`` Force the video stream to become the first stream in the output. By default the order is unspecified. ``--ocopyts`` Copies input pts to the output video (not supported by some output container formats, e.g. AVI). Discontinuities are still fixed. By default, audio pts are set to playback time and video pts are synchronized to match audio pts, as some output formats do not support anything else. ``--orawts`` Copies input pts to the output video (not supported by some output container formats, e.g. AVI). In this mode, discontinuities are not fixed and all pts are passed through as-is. Never seek backwards or use multiple input files in this mode! ``--no-ometadata`` Turns off copying of metadata from input files to output files when encoding (which is enabled by default). mpv-0.14.0/DOCS/man/input.rst000066400000000000000000002353601263261175500156130ustar00rootroot00000000000000COMMAND INTERFACE ================= The mpv core can be controlled with commands and properties. A number of ways to interact with the player use them: key bindings (``input.conf``), OSD (showing information with properties), JSON IPC, the client API (``libmpv``), and the classic slave mode. input.conf ---------- The input.conf file consists of a list of key bindings, for example:: s screenshot # take a screenshot with the s key LEFT seek 15 # map the left-arrow key to seeking forward by 15 seconds Each line maps a key to an input command. Keys are specified with their literal value (upper case if combined with ``Shift``), or a name for special keys. For example, ``a`` maps to the ``a`` key without shift, and ``A`` maps to ``a`` with shift. The file is located in the mpv configuration directory (normally at ``~/.config/mpv/input.conf`` depending on platform). The default bindings are defined here:: https://github.com/mpv-player/mpv/blob/master/etc/input.conf A list of special keys can be obtained with ``mpv --input-keylist`` In general, keys can be combined with ``Shift``, ``Ctrl`` and ``Alt``:: ctrl+q quit **mpv** can be started in input test mode, which displays key bindings and the commands they're bound to on the OSD, instead of executing the commands:: mpv --input-test --force-window --idle (Only closing the window will make **mpv** exit, pressing normal keys will merely display the binding, even if mapped to quit.) General Input Command Syntax ---------------------------- ``[Shift+][Ctrl+][Alt+][Meta+] [{
}] [] ()* [; ]`` Note that by default, the right Alt key can be used to create special characters, and thus does not register as a modifier. The option ``--no-input-right-alt-gr`` changes this behavior. Newlines always start a new binding. ``#`` starts a comment (outside of quoted string arguments). To bind commands to the ``#`` key, ``SHARP`` can be used. ```` is either the literal character the key produces (ASCII or Unicode character), or a symbolic name (as printed by ``--input-keylist``). ``
`` (braced with ``{`` and ``}``) is the input section for this command. Arguments are separated by whitespace. This applies even to string arguments. For this reason, string arguments should be quoted with ``"``. Inside quotes, 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" 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" (This is not shown in the general command syntax.) If ``a`` or ``a-b`` or ``b`` are already bound, this will run the first command that matches, and the multi-key command will never be called. Intermediate keys can be remapped to ``ignore`` in order to avoid this issue. The maximum number of (non-modifier) keys for combinations is currently 4. List of Input Commands ---------------------- ``ignore`` Use this to "block" keys that should be unbound, and do nothing. Useful for disabling default bindings, without disabling all bindings with ``--no-input-default-bindings``. ``seek [relative|absolute|absolute-percent|relative-percent|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: relative (default) Seek relative to current position (a negative value seeks backwards). absolute 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). exact Always do exact/hr/precise seeks (slow). 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]`` 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. The first argument is optional, and can change the behavior: mark 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`` Play one frame, then pause. Does nothing with audio-only playback. ``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. see the ``--hr-seek-demuxer-offset`` option). Video filters or other video post-processing that modifies timing of frames (e.g. deinterlacing) should usually work, but might make backstepping silently behave incorrectly in corner cases. Using ``--hr-seek-framedrop=no`` should help, although it might make precise seeking slower. This does not work with audio-only playback. ``set ""`` Set the given property to the given value. ``add []`` Add the given value to the property. On overflow or underflow, clamp the property to the maximum. If ```` is omitted, assume ``1``. ``cycle [up|down]`` Cycle the given property. ``up`` and ``down`` set the cycle direction. On overflow, set the property back to the minimum, on underflow set it to the maximum. If ``up`` or ``down`` is omitted, assume ``up``. ``multiply `` Multiplies the value of a property with the numeric factor. ``screenshot [subtitles|video|window|- [single|each-frame]]`` Take a screenshot. First argument: (default) Save the video image, in its original resolution, and with subtitles. Some video outputs may still include the OSD in the output under certain circumstances.