From db7d56b19f24d2e1bc7fe989aae78b0d5ee828a3 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 9 Apr 2015 14:37:37 +0200 Subject: vo_opengl: remove unused function --- video/out/gl_video.c | 5 ----- video/out/gl_video.h | 1 - 2 files changed, 6 deletions(-) diff --git a/video/out/gl_video.c b/video/out/gl_video.c index e5320fc184..3a6cb9ca62 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -2612,11 +2612,6 @@ void gl_video_set_options(struct gl_video *p, struct gl_video_opts *opts, uninit_rendering(p); } -void gl_video_get_colorspace(struct gl_video *p, struct mp_image_params *params) -{ - *params = p->image_params; // supports everything -} - struct mp_csp_equalizer *gl_video_eq_ptr(struct gl_video *p) { return &p->video_eq; diff --git a/video/out/gl_video.h b/video/out/gl_video.h index d28473d58f..30647153b5 100644 --- a/video/out/gl_video.h +++ b/video/out/gl_video.h @@ -89,7 +89,6 @@ void gl_video_render_frame(struct gl_video *p, int fbo, struct frame_timing *t); void gl_video_resize(struct gl_video *p, int vp_w, int vp_h, struct mp_rect *src, struct mp_rect *dst, struct mp_osd_res *osd); -void gl_video_get_colorspace(struct gl_video *p, struct mp_image_params *params); struct mp_csp_equalizer; struct mp_csp_equalizer *gl_video_eq_ptr(struct gl_video *p); void gl_video_eq_update(struct gl_video *p); -- cgit v1.2.3 From 11556e05305c3d4e46e27c1d4a4521e334844755 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 9 Apr 2015 14:38:43 +0200 Subject: vo_opengl: log used GLXFBConfig Now don't ask me why the GLXFBConfig type is a pointer, but stores an integer ID. --- video/out/gl_x11.c | 1 + 1 file changed, 1 insertion(+) diff --git a/video/out/gl_x11.c b/video/out/gl_x11.c index 8a67e0e13f..9d3d06711c 100644 --- a/video/out/gl_x11.c +++ b/video/out/gl_x11.c @@ -231,6 +231,7 @@ static bool config_window_x11(struct MPGLContext *ctx, int flags) MP_ERR(vo, "no GLX support present\n"); return false; } + MP_VERBOSE(vo, "GLX chose FB config with ID 0x%x\n", (int)(intptr_t)fbc); glx_ctx->fbc = fbc; glx_ctx->vinfo = glXGetVisualFromFBConfig(vo->x11->display, fbc); -- cgit v1.2.3 From 4e8ee522f4df73a74befc093640fdf60a43053ec Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 9 Apr 2015 19:22:54 +0200 Subject: vo_opengl_cb: fix video timing somewhat Increase the default queue size. This helps with "missed" frames due to the asynchronous nature of the API. All the other VOs are synchronous, so if rendering and displaying takes a while, the common code in vo.c will be blocked until it can continue. But with opengl-cb, vo.c might immediately push the next ready frame, which causes the current frame to be dropped _if_ it wasn't rendered yet. One could fix this by making vo.c wait a while (until the API user calls the render function, which pulls the frame). But setting the default queue size to 2 seems much simpler: instead of dropping the frame, it will be pushed to the API user once the next renderer call finishes. (This is still a bit strange, and will hopefully be cleaned up when video scheduling is redone, but for now this appears to deliver relatively good results.) --- video/out/vo_opengl_cb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/video/out/vo_opengl_cb.c b/video/out/vo_opengl_cb.c index f9f781c17a..551a650d15 100644 --- a/video/out/vo_opengl_cb.c +++ b/video/out/vo_opengl_cb.c @@ -405,7 +405,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params, int flags) #define OPT_BASE_STRUCT struct vo_priv static const struct m_option change_opts[] = { OPT_FLAG("debug", use_gl_debug, 0), - OPT_INTRANGE("frame-queue-size", frame_queue_size, 0, 1, 100, OPTDEF_INT(1)), + OPT_INTRANGE("frame-queue-size", frame_queue_size, 0, 1, 100, OPTDEF_INT(2)), OPT_CHOICE("frame-drop-mode", frame_drop_mode, 0, ({"pop", FRAME_DROP_POP}, {"clear", FRAME_DROP_CLEAR})), @@ -531,7 +531,7 @@ static int preinit(struct vo *vo) #define OPT_BASE_STRUCT struct vo_priv static const struct m_option options[] = { OPT_FLAG("debug", use_gl_debug, 0), - OPT_INTRANGE("frame-queue-size", frame_queue_size, 0, 1, 100, OPTDEF_INT(1)), + OPT_INTRANGE("frame-queue-size", frame_queue_size, 0, 1, 100, OPTDEF_INT(2)), OPT_CHOICE("frame-drop-mode", frame_drop_mode, 0, ({"pop", FRAME_DROP_POP}, {"clear", FRAME_DROP_CLEAR})), -- cgit v1.2.3 From 8dc7156bc0271965ea1e6768cfc7bbe67cef1876 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 9 Apr 2015 19:30:26 +0200 Subject: vo_opengl_cb: add a function to report vsync time And also let vo.c know of it. Currently, this does not help much, but will facilitate future improvements. --- DOCS/client-api-changes.rst | 1 + DOCS/client_api_examples/qml_direct/main.cpp | 7 +++++++ DOCS/client_api_examples/qml_direct/main.h | 1 + libmpv/client.h | 2 +- libmpv/mpv.def | 1 + libmpv/opengl_cb.h | 12 ++++++++++++ player/client.c | 4 ++++ video/out/vo_opengl_cb.c | 21 +++++++++++++++++++++ 8 files changed, 48 insertions(+), 1 deletion(-) diff --git a/DOCS/client-api-changes.rst b/DOCS/client-api-changes.rst index 258e9653e2..594cd42968 100644 --- a/DOCS/client-api-changes.rst +++ b/DOCS/client-api-changes.rst @@ -26,6 +26,7 @@ API changes :: --- mpv 0.9.0 will be released --- + 1.16 - add mpv_opengl_cb_report_flip() 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. diff --git a/DOCS/client_api_examples/qml_direct/main.cpp b/DOCS/client_api_examples/qml_direct/main.cpp index 5f1f1468cf..93a843dfd0 100644 --- a/DOCS/client_api_examples/qml_direct/main.cpp +++ b/DOCS/client_api_examples/qml_direct/main.cpp @@ -96,6 +96,8 @@ void MpvObject::handleWindowChanged(QQuickWindow *win) this, &MpvObject::sync, Qt::DirectConnection); connect(win, &QQuickWindow::sceneGraphInvalidated, this, &MpvObject::cleanup, Qt::DirectConnection); + connect(win, &QQuickWindow::frameSwapped, + this, &MpvObject::swapped, Qt::DirectConnection); win->setClearBeforeRendering(false); } @@ -110,6 +112,11 @@ void MpvObject::sync() renderer->size = window()->size() * window()->devicePixelRatio(); } +void MpvObject::swapped() +{ + mpv_opengl_cb_report_flip(mpv_gl, 0); +} + void MpvObject::cleanup() { if (renderer) { diff --git a/DOCS/client_api_examples/qml_direct/main.h b/DOCS/client_api_examples/qml_direct/main.h index 66fe8c94a5..b0310ff0be 100644 --- a/DOCS/client_api_examples/qml_direct/main.h +++ b/DOCS/client_api_examples/qml_direct/main.h @@ -37,6 +37,7 @@ public: public slots: void command(const QVariant& params); void sync(); + void swapped(); void cleanup(); signals: void onUpdate(); diff --git a/libmpv/client.h b/libmpv/client.h index 2ace0f54cf..511c4794b4 100644 --- a/libmpv/client.h +++ b/libmpv/client.h @@ -195,7 +195,7 @@ extern "C" { * relational operators (<, >, <=, >=). */ #define MPV_MAKE_VERSION(major, minor) (((major) << 16) | (minor) | 0UL) -#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 15) +#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 16) /** * Return the MPV_CLIENT_API_VERSION the mpv source has been compiled with. diff --git a/libmpv/mpv.def b/libmpv/mpv.def index d4d45874fa..4cdcf6b06b 100644 --- a/libmpv/mpv.def +++ b/libmpv/mpv.def @@ -23,6 +23,7 @@ mpv_initialize mpv_load_config_file mpv_observe_property mpv_opengl_cb_init_gl +mpv_opengl_cb_report_flip mpv_opengl_cb_render mpv_opengl_cb_set_update_callback mpv_opengl_cb_uninit_gl diff --git a/libmpv/opengl_cb.h b/libmpv/opengl_cb.h index 0e679e5edf..225f44fd50 100644 --- a/libmpv/opengl_cb.h +++ b/libmpv/opengl_cb.h @@ -198,6 +198,18 @@ int mpv_opengl_cb_init_gl(mpv_opengl_cb_context *ctx, const char *exts, */ int mpv_opengl_cb_render(mpv_opengl_cb_context *ctx, int fbo, int vp[4]); +/** + * Tell the renderer that a frame was flipped at the given time. This is + * optional, but can help the player to achieve better timing. + * + * If this is called while no video or no OpenGL is initialized, it is ignored. + * + * @param time The mpv time (using mpv_get_time_us()) at which the flip call + * returned. If 0 is passed, mpv_get_time_us() is used instead. + * @return error code + */ +int mpv_opengl_cb_report_flip(mpv_opengl_cb_context *ctx, int64_t time); + /** * Destroy the mpv OpenGL state. * diff --git a/player/client.c b/player/client.c index 3593b1d99f..ef1aa4f52e 100644 --- a/player/client.c +++ b/player/client.c @@ -1709,6 +1709,10 @@ int mpv_opengl_cb_render(mpv_opengl_cb_context *ctx, int fbo, int vp[4]) { return MPV_ERROR_NOT_IMPLEMENTED; } +int mpv_opengl_cb_report_flip(mpv_opengl_cb_context *ctx, int64_t time) +{ + return MPV_ERROR_NOT_IMPLEMENTED; +} int mpv_opengl_cb_uninit_gl(mpv_opengl_cb_context *ctx) { return MPV_ERROR_NOT_IMPLEMENTED; diff --git a/video/out/vo_opengl_cb.c b/video/out/vo_opengl_cb.c index 551a650d15..a7f7657889 100644 --- a/video/out/vo_opengl_cb.c +++ b/video/out/vo_opengl_cb.c @@ -19,6 +19,7 @@ #include "vo.h" #include "video/mp_image.h" #include "sub/osd.h" +#include "osdep/timer.h" #include "common/global.h" #include "player/client.h" @@ -76,6 +77,7 @@ struct mpv_opengl_cb_context { struct m_config *new_opts_cfg; bool eq_changed; struct mp_csp_equalizer eq; + int64_t recent_flip; // --- All of these can only be accessed from the thread where the host // application's OpenGL context is current - i.e. only while the @@ -342,6 +344,15 @@ int mpv_opengl_cb_render(struct mpv_opengl_cb_context *ctx, int fbo, int vp[4]) return left; } +int mpv_opengl_cb_report_flip(mpv_opengl_cb_context *ctx, int64_t time) +{ + pthread_mutex_lock(&ctx->lock); + ctx->recent_flip = time > 0 ? time : mp_time_us(); + pthread_mutex_unlock(&ctx->lock); + + return 0; +} + static void draw_image(struct vo *vo, mp_image_t *mpi) { struct vo_priv *p = vo->priv; @@ -486,6 +497,16 @@ static int control(struct vo *vo, uint32_t request, void *data) *arg = p->ctx ? &p->ctx->hwdec_info : NULL; return true; } + case VOCTRL_GET_RECENT_FLIP_TIME: { + int r = VO_FALSE; + pthread_mutex_lock(&p->ctx->lock); + if (p->ctx->recent_flip) { + *(int64_t *)data = p->ctx->recent_flip; + r = VO_TRUE; + } + pthread_mutex_unlock(&p->ctx->lock); + return r; + } } return VO_NOTIMPL; -- cgit v1.2.3 From e76f6929e52ff3a9d2159ad15876d9343ad88788 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 9 Apr 2015 19:31:01 +0200 Subject: vo_opengl_cb: deprecate mpv_opengl_cb_render() Its vp parameter made no sense anymore. Introduce a new one. --- DOCS/client-api-changes.rst | 1 + DOCS/client_api_examples/qml/main.cpp | 3 +- DOCS/client_api_examples/qml_direct/main.cpp | 6 ++-- libmpv/mpv.def | 1 + libmpv/opengl_cb.h | 45 ++++++++++++++++++---------- player/client.c | 7 ++++- video/out/vo_opengl_cb.c | 3 +- 7 files changed, 42 insertions(+), 24 deletions(-) diff --git a/DOCS/client-api-changes.rst b/DOCS/client-api-changes.rst index 594cd42968..62640889b6 100644 --- a/DOCS/client-api-changes.rst +++ b/DOCS/client-api-changes.rst @@ -27,6 +27,7 @@ API changes --- mpv 0.9.0 will be released --- 1.16 - add mpv_opengl_cb_report_flip() + - introduce mpv_opengl_cb_draw() and deprecate mpv_opengl_cb_render() 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. diff --git a/DOCS/client_api_examples/qml/main.cpp b/DOCS/client_api_examples/qml/main.cpp index 69552e982c..2122cd8c5c 100644 --- a/DOCS/client_api_examples/qml/main.cpp +++ b/DOCS/client_api_examples/qml/main.cpp @@ -46,9 +46,8 @@ public: void render() { QOpenGLFramebufferObject *fbo = framebufferObject(); - int vp[4] = {0, 0, fbo->width(), fbo->height()}; window->resetOpenGLState(); - mpv_opengl_cb_render(mpv_gl, fbo->handle(), vp); + mpv_opengl_cb_draw(mpv_gl, fbo->handle(), fbo->width(), fbo->height()); window->resetOpenGLState(); } }; diff --git a/DOCS/client_api_examples/qml_direct/main.cpp b/DOCS/client_api_examples/qml_direct/main.cpp index 93a843dfd0..37c6119707 100644 --- a/DOCS/client_api_examples/qml_direct/main.cpp +++ b/DOCS/client_api_examples/qml_direct/main.cpp @@ -39,15 +39,13 @@ void MpvRenderer::paint() { window->resetOpenGLState(); - // Render to the whole window. - int vp[4] = {0, 0, size.width(), -size.height()}; - // This uses 0 as framebuffer, which indicates that mpv will render directly // to the frontbuffer. Note that mpv will always switch framebuffers // explicitly. Some QWindow setups (such as using QQuickWidget) actually // want you to render into a FBO in the beforeRendering() signal, and this // code won't work there. - mpv_opengl_cb_render(mpv_gl, 0, vp); + // The negation is used for rendering with OpenGL's flipped coordinates. + mpv_opengl_cb_draw(mpv_gl, 0, size.width(), -size.height()); window->resetOpenGLState(); } diff --git a/libmpv/mpv.def b/libmpv/mpv.def index 4cdcf6b06b..840ba1e5ed 100644 --- a/libmpv/mpv.def +++ b/libmpv/mpv.def @@ -22,6 +22,7 @@ mpv_get_wakeup_pipe mpv_initialize mpv_load_config_file mpv_observe_property +mpv_opengl_cb_draw mpv_opengl_cb_init_gl mpv_opengl_cb_report_flip mpv_opengl_cb_render diff --git a/libmpv/opengl_cb.h b/libmpv/opengl_cb.h index 225f44fd50..fd1409a253 100644 --- a/libmpv/opengl_cb.h +++ b/libmpv/opengl_cb.h @@ -44,7 +44,7 @@ extern "C" { * the OpenGL API, because it's simpler and more flexible on the mpv side. * * The renderer needs to be explicitly initialized with mpv_opengl_cb_init_gl(), - * and then video can be drawn with mpv_opengl_cb_render(). The user thread can + * and then video can be drawn with mpv_opengl_cb_draw(). The user thread can * be notified by new frames with mpv_opengl_cb_set_update_callback(). * * OpenGL interop @@ -53,7 +53,7 @@ extern "C" { * This assumes the OpenGL context lives on a certain thread controlled by the * API user. The following functions require access to the OpenGL context: * mpv_opengl_cb_init_gl - * mpv_opengl_cb_render + * mpv_opengl_cb_draw * mpv_opengl_cb_uninit_gl * * The OpenGL context is indirectly accessed through the OpenGL function @@ -172,30 +172,45 @@ int mpv_opengl_cb_init_gl(mpv_opengl_cb_context *ctx, const char *exts, /** * Render video. Requires that the OpenGL state is initialized. * - * The video will use the provided viewport rectangle as window size. Options - * like "panscan" are applied to determine which part of the video should be - * visible and how the video should be scaled. You can change these options - * at runtime by using the mpv property API. + * The video will use the full provided framebuffer. Options like "panscan" are + * applied to determine which part of the video should be visible and how the + * video should be scaled. You can change these options at runtime by using the + * mpv property API. * * The renderer will reconfigure itself every time the output rectangle/size * is changed. (If you want to do animations, it might be better to do the * animation on a FBO instead.) * + * This function implicitly pulls a video frame from the internal queue and + * renders it. If no new frame is available, the previous frame is redrawn. + * The update callback set with mpv_opengl_cb_set_update_callback() notifies + * you when a new frame was added. + * * @param fbo The framebuffer object to render on. Because the renderer might * manage multiple FBOs internally for the purpose of video * postprocessing, it will always bind and unbind FBOs itself. If * you want mpv to render on the main framebuffer, pass 0. - * @param vp Viewport to render on. The renderer will essentially call: - * glViewport(0, 0, vp[2], vp[3]); - * before rendering. The height (vp[3]) can be negative to flip the - * image - the renderer will flip it before setting the viewport - * (typically you want to flip the image if you are rendering - * directly to the main framebuffer). - * vp[0] and vp[1] should be set to 0. - * The viewport width and height imply the target FBO or framebuffer's - * size. It will always render to the full size of it. + * @param w Width of the framebuffer. This is either the video size if the fbo + * parameter is 0, or the allocated size of the texture backing the + * fbo. The renderer will always use the full size of the fbo. + * @param h Height of the framebuffer. Same as with the w parameter, except + * that this parameter can be negative. In this case, the video + * frame will be rendered flipped. * @return the number of left frames in the internal queue to be rendered */ +int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int w, int h); + +/** + * Deprecated. Use mpv_opengl_cb_draw(). This function is equivalent to: + * + * int mpv_opengl_cb_render(mpv_opengl_cb_context *ctx, int fbo, int vp[4]) + * { return mpv_opengl_cb_draw(ctx, fbo, vp[2], vp[3]); } + * + * vp[0] and vp[1] used to have a meaning, but are ignored in newer versions. + * + * This function will be removed in the future without version bump (this API + * was never marked as stable). + */ int mpv_opengl_cb_render(mpv_opengl_cb_context *ctx, int fbo, int vp[4]); /** diff --git a/player/client.c b/player/client.c index ef1aa4f52e..614d64205f 100644 --- a/player/client.c +++ b/player/client.c @@ -1705,7 +1705,7 @@ int mpv_opengl_cb_init_gl(mpv_opengl_cb_context *ctx, const char *exts, { return MPV_ERROR_NOT_IMPLEMENTED; } -int mpv_opengl_cb_render(mpv_opengl_cb_context *ctx, int fbo, int vp[4]) +int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int w, int h) { return MPV_ERROR_NOT_IMPLEMENTED; } @@ -1719,6 +1719,11 @@ int mpv_opengl_cb_uninit_gl(mpv_opengl_cb_context *ctx) } #endif +int mpv_opengl_cb_render(mpv_opengl_cb_context *ctx, int fbo, int vp[4]) +{ + return mpv_opengl_cb_draw(ctx, fbo, vp[2], vp[3]); +} + void *mpv_get_sub_api(mpv_handle *ctx, mpv_sub_api sub_api) { if (!ctx->mpctx->initialized) diff --git a/video/out/vo_opengl_cb.c b/video/out/vo_opengl_cb.c index a7f7657889..2f2ac63f21 100644 --- a/video/out/vo_opengl_cb.c +++ b/video/out/vo_opengl_cb.c @@ -269,7 +269,7 @@ int mpv_opengl_cb_uninit_gl(struct mpv_opengl_cb_context *ctx) return 0; } -int mpv_opengl_cb_render(struct mpv_opengl_cb_context *ctx, int fbo, int vp[4]) +int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int vp_w, int vp_h) { assert(ctx->renderer); @@ -281,7 +281,6 @@ int mpv_opengl_cb_render(struct mpv_opengl_cb_context *ctx, int fbo, int vp[4]) ctx->force_update |= ctx->reconfigured; - int vp_w = vp[2], vp_h = vp[3]; if (ctx->vp_w != vp_w || ctx->vp_h != vp_h) ctx->force_update = true; -- cgit v1.2.3 From d453600b4fe3fb7080cc41f0af11513140693eed Mon Sep 17 00:00:00 2001 From: robin Date: Thu, 9 Apr 2015 15:26:12 +0200 Subject: ytdl_hook.lua: Disable video when vid option is "no" When setting options like --no-video, ytdl_hook adds the "-x" argument to youtube-dl, so that bandwith is saved by not downloading the video on some sites. --- player/lua/ytdl_hook.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/player/lua/ytdl_hook.lua b/player/lua/ytdl_hook.lua index 7b0e9222e9..c3a48941c3 100644 --- a/player/lua/ytdl_hook.lua +++ b/player/lua/ytdl_hook.lua @@ -93,6 +93,13 @@ mp.add_hook("on_load", 10, function () table.insert(command, "--format") table.insert(command, format) end + + -- Checks if no-video option is set and disables video in ytdl if set + if (mp.get_property("options/vid") == "no") then + table.insert(command, "-x") + msg.verbose("Video disabled. Only using audio") + end + for param, arg in pairs(raw_options) do table.insert(command, "--" .. param) if (arg ~= "") then -- cgit v1.2.3 From f1746741dee6000b7fd139e7a10f72aba0674b3b Mon Sep 17 00:00:00 2001 From: "Avi Halachmi (:avih)" Date: Tue, 17 Mar 2015 13:12:11 +0200 Subject: opengl: drop less frames when clip and display have similar fps adds 1 vsync interval "slack" before deciding to drop the first frame. it should help on cases of timing jitter (sleep duration, container timestamps, compositor vsync timing, etc). once the drop threshold has been crossed, it will keep dropping until perfect timing alignment. this prevents crossing the drop threshold back and forth repeatedly and therefore more resilient to frame drops --- video/out/vo.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/video/out/vo.c b/video/out/vo.c index e9b1cbfc1d..13727fad01 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -605,7 +605,15 @@ static bool render_frame(struct vo *vo) if (!in->hasframe_rendered) duration = -1; // disable framedrop - in->dropped_frame = duration >= 0 && end_time < next_vsync; + // if the clip and display have similar/identical fps, it's possible that + // we'll be very slightly late frequently due to timing jitter, or if the + // clip/container timestamps are not very accurate. + // so if we dropped the previous frame, keep dropping until we're aligned + // perfectly, else, allow some slack (1 vsync) to let it settle into a rhythm. + in->dropped_frame = duration >= 0 && + ((in->dropped_frame && end_time < next_vsync) || + (end_time < prev_vsync)); // hard threshold - 1 vsync late + in->dropped_frame &= !(vo->driver->caps & VO_CAP_FRAMEDROP); in->dropped_frame &= (vo->global->opts->frame_dropping & 1); // Even if we're hopelessly behind, rather degrade to 10 FPS playback, -- cgit v1.2.3 From c97f014576143c706e9d5189a89fa9959a651c71 Mon Sep 17 00:00:00 2001 From: "Avi Halachmi (:avih)" Date: Tue, 17 Mar 2015 20:04:46 +0200 Subject: opengl: smoothmotion: wake up for next vsync a bit earlier on my windows system this allows smoothmotion to work perfectly also in windowed mode. There's no real right or wrong here, with the the only goal being to always hit the next vsync. however, on cases where vsync timing is jittery (as could happen with DWM), this patch tries to aim to the middle of the vsync cycle to get as least affected as possible by such jitter. --- video/out/vo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/video/out/vo.c b/video/out/vo.c index 13727fad01..59b25591a9 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -623,7 +623,7 @@ static bool render_frame(struct vo *vo) if (in->vsync_timed) { // this is a heuristic that wakes the thread up some // time before the next vsync - target = next_vsync - MPMIN(in->vsync_interval / 3, 4e3); + target = next_vsync - MPMIN(in->vsync_interval / 2, 8e3); // We are very late with the frame and using vsync timing: probably // no new frames are coming in. This must be done whether or not -- cgit v1.2.3 From 843bc822a8a7974c7fbeea62525cb56bbab23fde Mon Sep 17 00:00:00 2001 From: "Avi Halachmi (:avih)" Date: Tue, 17 Mar 2015 01:15:28 +0200 Subject: opengl: win32 - add option 'dwmflush' to sync in DWM This could help in cases where the DWM (Windows desktop compositor) adds another layer of bufferring and therefore the SwapBuffers timing could get messed up. Signed-off-by: wm4 --- DOCS/man/vo.rst | 10 ++++++++++ video/out/gl_common.h | 6 ++++++ video/out/gl_w32.c | 42 ++++++++++++++++++++++++++++++++++++++++++ video/out/vo_opengl.c | 11 +++++++++++ 4 files changed, 69 insertions(+) diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst index 5d4bbe1c61..1696b51a53 100644 --- a/DOCS/man/vo.rst +++ b/DOCS/man/vo.rst @@ -548,6 +548,16 @@ Available video output drivers are: X11/GLX only. + ``dwmflush`` + Calls ``DwmFlush`` after swapping buffers on Windows (default: 0). + It also sets ``SwapInterval(0)`` to ignore the OpenGL timing. Values + are: 0 (disabled), 1 (only in windowed mode), 2 (also in full screen). + This may help getting more consistent frame intervals, especially with + high-fps clips - which might also reduce dropped frames. Typically a + value of 1 should be enough since full screen may bypass the DWM. + + Windows only. + ``sw`` Continue even if a software renderer is detected. diff --git a/video/out/gl_common.h b/video/out/gl_common.h index 2e25d331c7..06960f75ea 100644 --- a/video/out/gl_common.h +++ b/video/out/gl_common.h @@ -93,6 +93,12 @@ typedef struct MPGLContext { void (*releaseGlContext)(struct MPGLContext *); void (*set_current)(struct MPGLContext *, bool current); + // Used on windows only, tries to vsync with the DWM, and modifies SwapInterval + // when it does so. Returns the possibly modified swapinterval value. + int (*DwmFlush)(struct MPGLContext *, int opt_dwmflush, + int opt_swapinterval, int current_swapinterval); + + // Resize the window, or create a new window if there isn't one yet. // On the first call, it creates a GL context according to what's specified // in MPGLContext.requested_gl_version. This is just a hint, and if the diff --git a/video/out/gl_w32.c b/video/out/gl_w32.c index f2b7cf63d3..b1985e5e1f 100644 --- a/video/out/gl_w32.c +++ b/video/out/gl_w32.c @@ -24,10 +24,15 @@ #include "w32_common.h" #include "gl_common.h" +typedef HRESULT (WINAPI *DwmFlush_t)(void); + struct w32_context { HGLRC context; HDC hdc; int flags; + + HINSTANCE dwmapi_dll; + DwmFlush_t dwmflush; }; static bool create_dc(struct MPGLContext *ctx, int flags) @@ -202,6 +207,11 @@ static void create_ctx(void *ptr) create_context_w32_gl3(ctx); if (!w32_ctx->context) create_context_w32_old(ctx); + + w32_ctx->dwmapi_dll = LoadLibrary(L"Dwmapi.dll"); + if (w32_ctx->dwmapi_dll) + w32_ctx->dwmflush = (DwmFlush_t)GetProcAddress(w32_ctx->dwmapi_dll, "DwmFlush"); + wglMakeCurrent(w32_ctx->hdc, NULL); } @@ -240,6 +250,11 @@ static void releaseGlContext_w32(MPGLContext *ctx) if (w32_ctx->context) wglMakeCurrent(w32_ctx->hdc, 0); vo_w32_run_on_thread(ctx->vo, destroy_gl, ctx); + + w32_ctx->dwmflush = NULL; + if (w32_ctx->dwmapi_dll) + FreeLibrary(w32_ctx->dwmapi_dll); + w32_ctx->dwmapi_dll = NULL; } static void swapGlBuffers_w32(MPGLContext *ctx) @@ -248,6 +263,32 @@ static void swapGlBuffers_w32(MPGLContext *ctx) SwapBuffers(w32_ctx->hdc); } +// opt_dwmflush: 0 - never DwmFlush, 1 - only in windowed mode, 2 - always +// return: the current (applied if modified) SwapInterval value. +// DwmFlush waits on DWM vsync similar to SwapBuffers but a bit more noisy. +// SwapBuffers still needs to be called, but we SwapInterval(0) when DwmFLush is +// used (will get applied for the following SwapBuffers calls) +static int DwmFlush_w32(MPGLContext *ctx, int opt_dwmflush, + int opt_swapinterval, int current_swapinterval) +{ + struct w32_context *w32_ctx = ctx->priv; + int new_swapinterval = opt_swapinterval; // default if we don't DwmFLush + + if (w32_ctx->dwmflush && + (opt_dwmflush == 2 || (opt_dwmflush == 1 && !ctx->vo->opts->fullscreen)) && + S_OK == w32_ctx->dwmflush()) + { + new_swapinterval = 0; + } + + if ((new_swapinterval != current_swapinterval) && ctx->gl->SwapInterval) { + ctx->gl->SwapInterval(new_swapinterval); + MP_VERBOSE(ctx->vo, "DwmFlush: set SwapInterval(%d)\n", new_swapinterval); + } + + return new_swapinterval; +} + void mpgl_set_backend_w32(MPGLContext *ctx) { ctx->priv = talloc_zero(ctx, struct w32_context); @@ -257,4 +298,5 @@ void mpgl_set_backend_w32(MPGLContext *ctx) ctx->vo_init = vo_w32_init; ctx->vo_uninit = vo_w32_uninit; ctx->vo_control = vo_w32_control; + ctx->DwmFlush = DwmFlush_w32; } diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index 589ae7b0db..fb47464e9a 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -72,6 +72,9 @@ struct gl_priv { int use_gl_debug; int allow_sw; int swap_interval; + int current_swap_interval; + int dwm_flush; + char *backend; int vo_flipped; @@ -154,6 +157,12 @@ static void flip_page(struct vo *vo) } } + if (p->glctx->DwmFlush) { + p->current_swap_interval = p->glctx->DwmFlush(p->glctx, p->dwm_flush, + p->swap_interval, + p->current_swap_interval); + } + mpgl_unlock(p->glctx); } @@ -463,6 +472,7 @@ static int preinit(struct vo *vo) } else { MP_VERBOSE(vo, "swap_control extension missing.\n"); } + p->current_swap_interval = p->swap_interval; p->renderer = gl_video_init(p->gl, vo->log); if (!p->renderer) @@ -498,6 +508,7 @@ static const struct m_option options[] = { OPT_FLAG("glfinish", use_glFinish, 0), OPT_FLAG("waitvsync", waitvsync, 0), OPT_INT("swapinterval", swap_interval, 0, OPTDEF_INT(1)), + OPT_INT("dwmflush", dwm_flush, 0, OPTDEF_INT(0)), OPT_FLAG("debug", use_gl_debug, 0), OPT_STRING_VALIDATE("backend", backend, 0, mpgl_validate_backend_opt), OPT_FLAG("sw", allow_sw, 0), -- cgit v1.2.3 From c4faab48714e6597cb12abe7be4aada694bac897 Mon Sep 17 00:00:00 2001 From: Sebastian Mayr Date: Fri, 3 Apr 2015 19:04:31 +0200 Subject: ytdl: set additional properties for rtmp streams --- player/lua/ytdl_hook.lua | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/player/lua/ytdl_hook.lua b/player/lua/ytdl_hook.lua index c3a48941c3..508c43f543 100644 --- a/player/lua/ytdl_hook.lua +++ b/player/lua/ytdl_hook.lua @@ -37,6 +37,20 @@ local function set_http_headers(http_headers) end end +local function append_rtmp_prop(props, name, value) + if not name or not value then + return props + end + + if props and props ~= "" then + props = props.."," + else + props = "" + end + + return props..name.."=\""..value.."\"" +end + mp.add_hook("on_load", 10, function () local url = mp.get_property("stream-open-filename") @@ -241,9 +255,13 @@ mp.add_hook("on_load", 10, function () -- for rtmp if not (json.play_path == nil) then - mp.set_property("file-local-options/stream-lavf-o", - "rtmp_tcurl=\""..streamurl.. - "\",rtmp_playpath=\""..json.play_path.."\"") + local rtmp_prop = append_rtmp_prop(nil, "rtmp_tcurl", streamurl) + rtmp_prop = append_rtmp_prop(rtmp_prop, "rtmp_pageurl", json.page_url) + rtmp_prop = append_rtmp_prop(rtmp_prop, "rtmp_playpath", json.play_path) + rtmp_prop = append_rtmp_prop(rtmp_prop, "rtmp_swfverify", json.player_url) + rtmp_prop = append_rtmp_prop(rtmp_prop, "rtmp_app", json.app) + + mp.set_property("file-local-options/stream-lavf-o", rtmp_prop) end end end -- cgit v1.2.3 From 13a0ff8cb79473e971c2de3090616bae1905b78f Mon Sep 17 00:00:00 2001 From: Cris Date: Fri, 3 Apr 2015 17:20:59 +0100 Subject: Update README.md Signed-off-by: wm4 --- README.md | 62 ++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 7c4b18b340..0ca0193c48 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,39 @@ -mpv -=== +![http://mpv.io/](https://raw.githubusercontent.com/mpv-player/mpv.io/master/source/images/mpv-logo-128.png) + +## mpv + +-------------- + + +* [Overview](#overview) +* [Downloads](#downloads) +* [Compilation](#compilation) +* [FFmpeg vs. Libav](#ffmpeg-vs-libav) +* [Release cycle](#release-cycle) +* [Bug reports](#bug-reports) +* [Contributing](#contributing) +* [Relation to MPlayer and mplayer2](#relation-to-mplayer-and-mplayer2) +* [Wiki](https://github.com/mpv-player/mpv/wiki) +* [Man pages](http://mpv.io/manual/master/) +* [Contact](#contact) +* [License](#license) + +## Overview -Overview --------- **mpv** is a media player based on MPlayer and mplayer2. It supports a wide variety of video file formats, audio and video codecs, and subtitle types. Releases can be found on the [release list][releases]. -Downloads ---------- +## Downloads + For semi-official builds and third-party packages please see [mpv.io](http://mpv.io/installation/). -Compilation ------------ +## Compilation + Compiling with full features requires development files for several external libraries. Below is a list of some important requirements. @@ -89,16 +106,16 @@ OSX. If you want to build a Windows binary, you either have to use MSYS2 and MinGW, or cross-compile from Linux with MinGW. See [Windows compilation][windows_compilation]. -FFmpeg vs. Libav ----------------- +## FFmpeg vs. Libav + Generally, mpv should work with the latest release as well as the git version of both FFmpeg and Libav. But FFmpeg is preferred, and some mpv features work with FFmpeg only. See the [wiki article][ffmpeg_vs_libav] about the issue. -Release cycle -------------- +## Release cycle + Every few months, a new release is cut off of the master branch and is assigned a 0.X.0 version number. @@ -116,21 +133,21 @@ Releases other than the latest release are unsupported and unmaintained. See the [release policy document][release-policy] for more information. -Bug reports ------------ +## Bug reports + Please use the [issue tracker][issue-tracker] provided by GitHub to send us bug reports or feature requests. -Contributing ------------- +## Contributing + For small changes you can just send us pull requests through GitHub. For bigger changes come and talk to us on IRC before you start working on them. It will make code review easier for both parties later on. -Relation to MPlayer and mplayer2 --------------------------------- +## Relation to MPlayer and mplayer2 + mpv is based on mplayer2, which in turn is based on the original MPlayer (also called mplayer, mplayer-svn, mplayer1). Many changes have been made, a @@ -151,8 +168,8 @@ MPlayer drop-in replacement. If you are wondering what's different from mplayer2 and MPlayer, an incomplete list of changes is located [here][mplayer-changes]. -Contact -------- +## Contact + Most activity happens on the IRC channel and the github issue tracker. The mailing lists are mostly unused. @@ -176,3 +193,8 @@ only if discretion is required. [release-policy]: https://github.com/mpv-player/mpv/blob/master/DOCS/release-policy.md [windows_compilation]: https://github.com/mpv-player/mpv/blob/master/DOCS/compile-windows.md [mplayer-changes]: https://github.com/mpv-player/mpv/blob/master/DOCS/mplayer-changes.rst + +## License + + +[GPLv2](https://github.com/mpv-player/mpv/blob/master/LICENSE) -- cgit v1.2.3 From 8d3c826ad867441cb5e77afd88098190b55d73b2 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 9 Apr 2015 21:01:34 +0200 Subject: screenshots: write jpg files with original subsampling A screenshot from a 4:2:0 video will use 4:2:0, RGB will use 4:4:4, and so on. (The image data still goes through RGB conversion always.) --- video/image_writer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/video/image_writer.c b/video/image_writer.c index 939b435787..1da43feca6 100644 --- a/video/image_writer.c +++ b/video/image_writer.c @@ -77,6 +77,7 @@ struct image_writer_ctx { struct mp_log *log; const struct image_writer_opts *opts; const struct img_writer *writer; + struct mp_imgfmt_desc original_format; }; struct img_writer { @@ -200,6 +201,9 @@ static int write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp) cinfo.optimize_coding = ctx->opts->jpeg_optimize; cinfo.smoothing_factor = ctx->opts->jpeg_smooth; + cinfo.comp_info[0].h_samp_factor = 1 << ctx->original_format.chroma_xs; + cinfo.comp_info[0].v_samp_factor = 1 << ctx->original_format.chroma_ys; + if (ctx->opts->jpeg_progressive) jpeg_simple_progression(&cinfo); @@ -299,7 +303,7 @@ int write_image(struct mp_image *image, const struct image_writer_opts *opts, opts = &defs; const struct img_writer *writer = get_writer(opts); - struct image_writer_ctx ctx = { log, opts, writer }; + struct image_writer_ctx ctx = { log, opts, writer, image->fmt }; int destfmt = get_target_format(&ctx, image->imgfmt); // Caveat: no colorspace/levels conversion done if pixel formats equal -- cgit v1.2.3 From d737939f1f8cd2a3c53c6963c0af1cea029c454a Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 9 Apr 2015 21:05:26 +0200 Subject: screenshots: drop some useless jpeg writer options --- video/image_writer.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/video/image_writer.c b/video/image_writer.c index 1da43feca6..658e38d302 100644 --- a/video/image_writer.c +++ b/video/image_writer.c @@ -47,8 +47,6 @@ const struct image_writer_opts image_writer_opts_defaults = { .jpeg_quality = 90, .jpeg_optimize = 100, .jpeg_smooth = 0, - .jpeg_dpi = 72, - .jpeg_progressive = 0, .jpeg_baseline = 1, .tag_csp = 1, }; @@ -60,8 +58,6 @@ const struct m_sub_options image_writer_conf = { OPT_INTRANGE("jpeg-quality", jpeg_quality, 0, 0, 100), OPT_INTRANGE("jpeg-optimize", jpeg_optimize, 0, 0, 100), OPT_INTRANGE("jpeg-smooth", jpeg_smooth, 0, 0, 100), - OPT_INTRANGE("jpeg-dpi", jpeg_dpi, M_OPT_MIN, 1, 99999), - OPT_FLAG("jpeg-progressive", jpeg_progressive, 0), OPT_FLAG("jpeg-baseline", jpeg_baseline, 0), OPT_INTRANGE("png-compression", png_compression, 0, 0, 9), OPT_INTRANGE("png-filter", png_filter, 0, 0, 5), @@ -191,10 +187,6 @@ static int write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp) cinfo.write_JFIF_header = TRUE; cinfo.JFIF_major_version = 1; cinfo.JFIF_minor_version = 2; - cinfo.density_unit = 1; /* 0=unknown, 1=dpi, 2=dpcm */ - cinfo.X_density = ctx->opts->jpeg_dpi; - cinfo.Y_density = ctx->opts->jpeg_dpi; - cinfo.write_Adobe_marker = TRUE; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, ctx->opts->jpeg_quality, ctx->opts->jpeg_baseline); @@ -204,9 +196,6 @@ static int write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp) cinfo.comp_info[0].h_samp_factor = 1 << ctx->original_format.chroma_xs; cinfo.comp_info[0].v_samp_factor = 1 << ctx->original_format.chroma_ys; - if (ctx->opts->jpeg_progressive) - jpeg_simple_progression(&cinfo); - jpeg_start_compress(&cinfo, TRUE); while (cinfo.next_scanline < cinfo.image_height) { -- cgit v1.2.3 From be259be15c762abe4aa67dd0c932c389105cabd4 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 9 Apr 2015 21:11:20 +0200 Subject: mp_image: get rid of chroma_width/height fields They are redundant. They were used by draw_bmp.c only, and only in a special code path that 1. used fixed image formats, and 2. had image sized perfectly aligned to chroma boundaries (so computing the chroma width/height is trivial). --- sub/draw_bmp.c | 9 ++++----- video/mp_image.h | 2 -- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c index d9cb0522df..228d8a2dde 100644 --- a/sub/draw_bmp.c +++ b/sub/draw_bmp.c @@ -481,9 +481,9 @@ static struct mp_image *chroma_up(struct mp_draw_sub_cache *cache, int imgfmt, // The whole point is not having swscale copy the Y plane struct mp_image t_dst = *temp; mp_image_setfmt(&t_dst, IMGFMT_Y8); - mp_image_set_size(&t_dst, temp->chroma_width, temp->chroma_height); + mp_image_set_size(&t_dst, temp->w, temp->h); struct mp_image t_src = t_dst; - mp_image_set_size(&t_src, src->chroma_width, src->chroma_height); + mp_image_set_size(&t_src, src->w >> 1, src->h >> 1); for (int c = 0; c < 2; c++) { t_dst.planes[0] = temp->planes[1 + c]; t_dst.stride[0] = temp->stride[1 + c]; @@ -511,10 +511,9 @@ static void chroma_down(struct mp_image *old_src, struct mp_image *temp) assert(temp->planes[0] == old_src->planes[0]); struct mp_image t_dst = *temp; mp_image_setfmt(&t_dst, IMGFMT_Y8); - mp_image_set_size(&t_dst, old_src->chroma_width, - old_src->chroma_height); + mp_image_set_size(&t_dst, old_src->w >> 1, old_src->h >> 1); struct mp_image t_src = t_dst; - mp_image_set_size(&t_src, temp->chroma_width, temp->chroma_height); + mp_image_set_size(&t_src, temp->w, temp->h); for (int c = 0; c < 2; c++) { t_dst.planes[0] = old_src->planes[1 + c]; t_dst.stride[0] = old_src->stride[1 + c]; diff --git a/video/mp_image.h b/video/mp_image.h index 70931ffb55..16862f9882 100644 --- a/video/mp_image.h +++ b/video/mp_image.h @@ -96,8 +96,6 @@ typedef struct mp_image { int fields; /* redundant */ - int chroma_width; - int chroma_height; int plane_w[MP_MAX_PLANES]; int plane_h[MP_MAX_PLANES]; -- cgit v1.2.3 From 8fe640c47d128b886d82df1e04702c568ff59077 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 9 Apr 2015 21:46:28 +0200 Subject: mp_image: fix build --- video/mp_image.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/video/mp_image.c b/video/mp_image.c index da644d57fe..aa0bb5cf25 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -175,8 +175,6 @@ void mp_image_set_size(struct mp_image *mpi, int w, int h) mpi->plane_w[n] = mp_chroma_div_up(mpi->w, mpi->fmt.xs[n]); mpi->plane_h[n] = mp_chroma_div_up(mpi->h, mpi->fmt.ys[n]); } - mpi->chroma_width = mpi->plane_w[1]; - mpi->chroma_height = mpi->plane_h[1]; } void mp_image_set_params(struct mp_image *image, -- cgit v1.2.3 From be6cca78491a949e3892a4c2edc2f4fcfc5e8145 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 10 Apr 2015 12:50:02 +0200 Subject: README: remove dead link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0ca0193c48..4f8676552f 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ or cross-compile from Linux with MinGW. See [Windows compilation][windows_compil Generally, mpv should work with the latest release as well as the git version of both FFmpeg and Libav. But FFmpeg is preferred, and some mpv features work -with FFmpeg only. See the [wiki article][ffmpeg_vs_libav] about the issue. +with FFmpeg only (subtitle formats in particular). ## Release cycle -- cgit v1.2.3 From 46eb04f3c26a14a738ae1c09f341f322cae4371d Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 10 Apr 2015 13:07:24 +0200 Subject: player: do not accidentally init terminal Starting the command line player with --no-terminal, the terminal was sitll initialized. This happened because update_logging() used the option value before the options were parsed. Fix by moving down the initialization to before the point where it's actually needed. --- player/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/player/main.c b/player/main.c index 77ec8053d5..0c5d39fdf8 100644 --- a/player/main.c +++ b/player/main.c @@ -386,8 +386,6 @@ int mp_initialize(struct MPContext *mpctx, char **options) assert(!mpctx->initialized); - update_logging(mpctx); - if (options) { // Preparse the command line, so we can init the terminal early. m_config_preparse_command_line(mpctx->mconfig, mpctx->global, options); @@ -400,6 +398,7 @@ int mp_initialize(struct MPContext *mpctx, char **options) MP_VERBOSE(mpctx, "\n"); } + update_logging(mpctx); mp_print_version(mpctx->log, false); mp_parse_cfgfiles(mpctx); -- cgit v1.2.3 From 77869e5914d306d49d605ce0734b2a6145d02089 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 10 Apr 2015 13:51:13 +0200 Subject: ao_coreaudio: fix inverted condition And also use the correct type for the printf call below. --- audio/out/ao_coreaudio_utils.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/audio/out/ao_coreaudio_utils.c b/audio/out/ao_coreaudio_utils.c index 8485011722..d606587866 100644 --- a/audio/out/ao_coreaudio_utils.c +++ b/audio/out/ao_coreaudio_utils.c @@ -141,16 +141,17 @@ char *fourcc_repr(void *talloc_ctx, uint32_t code) }; bool valid_fourcc = true; - for (int i = 0; i < 4; i++) - if (fcc[i] >= 32 && fcc[i] < 128) + for (int i = 0; i < 4; i++) { + if (fcc[i] < 32 || fcc[i] >= 128) valid_fourcc = false; + } char *repr; if (valid_fourcc) repr = talloc_asprintf(talloc_ctx, "'%c%c%c%c'", fcc[0], fcc[1], fcc[2], fcc[3]); else - repr = talloc_asprintf(NULL, "%d", code); + repr = talloc_asprintf(NULL, "%u", (unsigned int)code); return repr; } -- cgit v1.2.3 From 6efd095dfd6abc02ea1a1daa34f8b21080012931 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 10 Apr 2015 19:10:07 +0200 Subject: vo_opengl: use correct texture coordinates for nv12 --- video/out/gl_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/video/out/gl_video.c b/video/out/gl_video.c index 3a6cb9ca62..b61d27aeee 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -1358,7 +1358,7 @@ static void pass_read_video(struct gl_video *p) GLSL(vec4 color;) if (p->plane_count == 2) { gl_transform_rect(chromafix, &p->pass_tex[1].src); - GLSL(vec2 chroma = texture(texture1, texcoord0).rg;) // NV formats + GLSL(vec2 chroma = texture(texture1, texcoord1).rg;) // NV formats } else { gl_transform_rect(chromafix, &p->pass_tex[1].src); gl_transform_rect(chromafix, &p->pass_tex[2].src); -- cgit v1.2.3 From 1e692cb043ac109d734de366859298d28d96b2ed Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 10 Apr 2015 20:31:21 +0200 Subject: player: change pseudo-gui settings Remove --keep-open. Switch to --idle=once. This effectively makes the player quit after end of playback, but still shows the idle screen if it was started with no files. --- player/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/player/main.c b/player/main.c index 0c5d39fdf8..2f64c3b67e 100644 --- a/player/main.c +++ b/player/main.c @@ -318,8 +318,7 @@ static void add_default_profiles(struct m_config *cfg) struct m_profile *ui = m_config_add_profile(cfg, "pseudo-gui"); m_config_set_profile_option(cfg, ui, bstr0("terminal"), bstr0("no")); m_config_set_profile_option(cfg, ui, bstr0("force-window"), bstr0("yes")); - m_config_set_profile_option(cfg, ui, bstr0("idle"), bstr0("yes")); - m_config_set_profile_option(cfg, ui, bstr0("keep-open"), bstr0("yes")); + m_config_set_profile_option(cfg, ui, bstr0("idle"), bstr0("once")); } struct MPContext *mp_create(void) -- cgit v1.2.3 From cf55fa64710bdd5999b437f0cccdb036324ae11e Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 10 Apr 2015 20:40:50 +0200 Subject: player: use config parser for setting up pseudo-gui profile --- options/parse_configfile.c | 4 ++-- options/parse_configfile.h | 3 +++ player/main.c | 16 +++++++--------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/options/parse_configfile.c b/options/parse_configfile.c index b97fd382ed..42e47689db 100644 --- a/options/parse_configfile.c +++ b/options/parse_configfile.c @@ -42,8 +42,8 @@ static bool skip_ws(bstr *s) return s->len; } -static int m_config_parse(m_config_t *config, const char *location, bstr data, - char *initial_section, int flags) +int m_config_parse(m_config_t *config, const char *location, bstr data, + char *initial_section, int flags) { m_profile_t *profile = m_config_add_profile(config, initial_section); void *tmp = talloc_new(NULL); diff --git a/options/parse_configfile.h b/options/parse_configfile.h index 4a42cee001..3cf54b54db 100644 --- a/options/parse_configfile.h +++ b/options/parse_configfile.h @@ -24,4 +24,7 @@ int m_config_parse_config_file(m_config_t* config, const char *conffile, char *initial_section, int flags); +int m_config_parse(m_config_t *config, const char *location, bstr data, + char *initial_section, int flags); + #endif /* MPLAYER_PARSER_CFG_H */ diff --git a/player/main.c b/player/main.c index 2f64c3b67e..c517e871f6 100644 --- a/player/main.c +++ b/player/main.c @@ -99,6 +99,12 @@ const char mp_help_text[] = " --list-options list all mpv options\n" "\n"; +static const char def_config[] = + "[pseudo-gui]\n" + "terminal=no\n" + "force-window=yes\n" + "idle=once\n"; + static pthread_mutex_t terminal_owner_lock = PTHREAD_MUTEX_INITIALIZER; static struct MPContext *terminal_owner; @@ -313,14 +319,6 @@ static int cfg_include(void *ctx, char *filename, int flags) return r; } -static void add_default_profiles(struct m_config *cfg) -{ - struct m_profile *ui = m_config_add_profile(cfg, "pseudo-gui"); - m_config_set_profile_option(cfg, ui, bstr0("terminal"), bstr0("no")); - m_config_set_profile_option(cfg, ui, bstr0("force-window"), bstr0("yes")); - m_config_set_profile_option(cfg, ui, bstr0("idle"), bstr0("once")); -} - struct MPContext *mp_create(void) { mp_time_init(); @@ -354,7 +352,7 @@ struct MPContext *mp_create(void) mpctx->mconfig->includefunc_ctx = mpctx; mpctx->mconfig->use_profiles = true; mpctx->mconfig->is_toplevel = true; - add_default_profiles(mpctx->mconfig); + m_config_parse(mpctx->mconfig, "", bstr0(def_config), NULL, 0); mpctx->global->opts = mpctx->opts; -- cgit v1.2.3 From b3495d9ccf5ad1d5d84284affed1083eee5887ee Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 10 Apr 2015 20:58:26 +0200 Subject: mp_image: remove redundant plane_w/h fields Seems relatively painful in this case, but they are morally wrong. --- video/filter/vf_mirror.c | 5 +++-- video/mp_image.c | 32 +++++++++++++++++++++----------- video/mp_image.h | 6 ++---- video/out/gl_video.c | 9 +++++---- 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/video/filter/vf_mirror.c b/video/filter/vf_mirror.c index 90316b2be9..3b4138c535 100644 --- a/video/filter/vf_mirror.c +++ b/video/filter/vf_mirror.c @@ -63,10 +63,11 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) mp_image_copy_attributes(dmpi, mpi); for (int p = 0; p < mpi->num_planes; p++) { - for (int y = 0; y < mpi->plane_h[p]; y++) { + int plane_h = mp_image_plane_h(mpi, p); + for (int y = 0; y < plane_h; y++) { void *p_src = mpi->planes[p] + mpi->stride[p] * y; void *p_dst = dmpi->planes[p] + dmpi->stride[p] * y; - int w = dmpi->plane_w[p]; + int w = mp_image_plane_w(dmpi, p); if (mpi->imgfmt == IMGFMT_YUYV) { mirror_4_m(p_dst, p_src, w / 2, 2, 1, 0, 3); } else if (mpi->imgfmt == IMGFMT_UYVY) { diff --git a/video/mp_image.c b/video/mp_image.c index aa0bb5cf25..2c1e01cef9 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -119,7 +119,7 @@ static bool mp_image_alloc_planes(struct mp_image *mpi) size_t plane_size[MP_MAX_PLANES]; for (int n = 0; n < MP_MAX_PLANES; n++) { int alloc_h = MP_ALIGN_UP(mpi->h, 32) >> mpi->fmt.ys[n]; - int line_bytes = (mpi->plane_w[n] * mpi->fmt.bpp[n] + 7) / 8; + int line_bytes = (mp_image_plane_w(mpi, n) * mpi->fmt.bpp[n] + 7) / 8; mpi->stride[n] = FFALIGN(line_bytes, SWS_MIN_BYTE_ALIGN); plane_size[n] = mpi->stride[n] * alloc_h; } @@ -165,16 +165,24 @@ int mp_chroma_div_up(int size, int shift) return (size + (1 << shift) - 1) >> shift; } +// Return the storage width in pixels of the given plane. +int mp_image_plane_w(struct mp_image *mpi, int plane) +{ + return mp_chroma_div_up(mpi->w, mpi->fmt.xs[plane]); +} + +// Return the storage height in pixels of the given plane. +int mp_image_plane_h(struct mp_image *mpi, int plane) +{ + return mp_chroma_div_up(mpi->h, mpi->fmt.ys[plane]); +} + // Caller has to make sure this doesn't exceed the allocated plane data/strides. void mp_image_set_size(struct mp_image *mpi, int w, int h) { assert(w >= 0 && h >= 0); mpi->w = mpi->params.w = mpi->params.d_w = w; mpi->h = mpi->params.h = mpi->params.d_h = h; - for (int n = 0; n < mpi->num_planes; n++) { - mpi->plane_w[n] = mp_chroma_div_up(mpi->w, mpi->fmt.xs[n]); - mpi->plane_h[n] = mp_chroma_div_up(mpi->h, mpi->fmt.ys[n]); - } } void mp_image_set_params(struct mp_image *image, @@ -328,8 +336,9 @@ void mp_image_copy(struct mp_image *dst, struct mp_image *src) assert(dst->w == src->w && dst->h == src->h); assert(mp_image_is_writeable(dst)); for (int n = 0; n < dst->num_planes; n++) { - int line_bytes = (dst->plane_w[n] * dst->fmt.bpp[n] + 7) / 8; - memcpy_pic(dst->planes[n], src->planes[n], line_bytes, dst->plane_h[n], + int line_bytes = (mp_image_plane_w(dst, n) * dst->fmt.bpp[n] + 7) / 8; + int plane_h = mp_image_plane_h(dst, n); + memcpy_pic(dst->planes[n], src->planes[n], line_bytes, plane_h, dst->stride[n], src->stride[n]); } // Watch out for AV_PIX_FMT_FLAG_PSEUDOPAL retardation @@ -417,13 +426,13 @@ void mp_image_clear(struct mp_image *img, int x0, int y0, int x1, int y1) for (int p = 0; p < area.num_planes; p++) { int bpp = area.fmt.bpp[p]; - int bytes = (area.plane_w[p] * bpp + 7) / 8; + int bytes = (mp_image_plane_w(&area, p) * bpp + 7) / 8; if (bpp <= 8) { memset_pic(area.planes[p], plane_clear[p], bytes, - area.plane_h[p], area.stride[p]); + mp_image_plane_h(&area, p), area.stride[p]); } else { memset16_pic(area.planes[p], plane_clear[p], (bytes + 1) / 2, - area.plane_h[p], area.stride[p]); + mp_image_plane_h(&area, p), area.stride[p]); } } } @@ -431,7 +440,8 @@ void mp_image_clear(struct mp_image *img, int x0, int y0, int x1, int y1) void mp_image_vflip(struct mp_image *img) { for (int p = 0; p < img->num_planes; p++) { - img->planes[p] = img->planes[p] + img->stride[p] * (img->plane_h[p] - 1); + int plane_h = mp_image_plane_h(img, p); + img->planes[p] = img->planes[p] + img->stride[p] * (plane_h - 1); img->stride[p] = -img->stride[p]; } } diff --git a/video/mp_image.h b/video/mp_image.h index 16862f9882..95fe8ad20e 100644 --- a/video/mp_image.h +++ b/video/mp_image.h @@ -95,10 +95,6 @@ typedef struct mp_image { int pict_type; // 0->unknown, 1->I, 2->P, 3->B int fields; - /* redundant */ - int plane_w[MP_MAX_PLANES]; - int plane_h[MP_MAX_PLANES]; - /* only inside filter chain */ double pts; /* memory management */ @@ -125,6 +121,8 @@ void mp_image_crop_rc(struct mp_image *img, struct mp_rect rc); void mp_image_vflip(struct mp_image *img); void mp_image_set_size(struct mp_image *mpi, int w, int h); +int mp_image_plane_w(struct mp_image *mpi, int plane); +int mp_image_plane_h(struct mp_image *mpi, int plane); void mp_image_setfmt(mp_image_t* mpi, int out_fmt); void mp_image_steal_data(struct mp_image *dst, struct mp_image *src); diff --git a/video/out/gl_video.c b/video/out/gl_video.c index b61d27aeee..3e915d9d0a 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -2086,8 +2086,8 @@ static bool get_image(struct gl_video *p, struct mp_image *mpi) for (int n = 0; n < p->plane_count; n++) { struct texplane *plane = &vimg->planes[n]; - mpi->stride[n] = mpi->plane_w[n] * p->image_desc.bytes[n]; - int needed_size = mpi->plane_h[n] * mpi->stride[n]; + mpi->stride[n] = mp_image_plane_w(mpi, n) * p->image_desc.bytes[n]; + int needed_size = mp_image_plane_h(mpi, n) * mpi->stride[n]; if (!plane->gl_buffer) gl->GenBuffers(1, &plane->gl_buffer); gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, plane->gl_buffer); @@ -2132,8 +2132,9 @@ void gl_video_upload_image(struct gl_video *p, struct mp_image *mpi) bool pbo = false; if (!vimg->planes[0].buffer_ptr && get_image(p, &mpi2)) { for (int n = 0; n < p->plane_count; n++) { - int line_bytes = mpi->plane_w[n] * p->image_desc.bytes[n]; - memcpy_pic(mpi2.planes[n], mpi->planes[n], line_bytes, mpi->plane_h[n], + int line_bytes = mp_image_plane_w(mpi, n) * p->image_desc.bytes[n]; + int plane_h = mp_image_plane_h(mpi, n); + memcpy_pic(mpi2.planes[n], mpi->planes[n], line_bytes, plane_h, mpi2.stride[n], mpi->stride[n]); } pbo = true; -- cgit v1.2.3 From 41151122e73f82d0bc9a806c80165878e930dc07 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 10 Apr 2015 21:02:16 +0200 Subject: mp_image: remove redundant chroma_x/y_shift fields --- sub/draw_bmp.c | 6 +++--- video/filter/vf_dlopen.c | 8 ++++---- video/filter/vf_eq.c | 4 ++-- video/mp_image.c | 2 -- video/mp_image.h | 2 -- 5 files changed, 9 insertions(+), 13 deletions(-) diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c index 228d8a2dde..78fb33ca9f 100644 --- a/sub/draw_bmp.c +++ b/sub/draw_bmp.c @@ -334,13 +334,13 @@ static void draw_ass(struct mp_draw_sub_cache *cache, struct mp_rect bb, static void get_swscale_alignment(const struct mp_image *img, int *out_xstep, int *out_ystep) { - int sx = (1 << img->chroma_x_shift); - int sy = (1 << img->chroma_y_shift); + int sx = (1 << img->fmt.chroma_xs); + int sy = (1 << img->fmt.chroma_ys); for (int p = 0; p < img->num_planes; ++p) { int bits = img->fmt.bpp[p]; // the * 2 fixes problems with writing past the destination width - while (((sx >> img->chroma_x_shift) * bits) % (SWS_MIN_BYTE_ALIGN * 8 * 2)) + while (((sx >> img->fmt.chroma_xs) * bits) % (SWS_MIN_BYTE_ALIGN * 8 * 2)) sx *= 2; } diff --git a/video/filter/vf_dlopen.c b/video/filter/vf_dlopen.c index 00e6245a2e..0424e83a61 100644 --- a/video/filter/vf_dlopen.c +++ b/video/filter/vf_dlopen.c @@ -82,11 +82,11 @@ static void set_imgprop(struct vf_dlopen_picdata *out, const mp_image_t *mpi) out->plane[i] = mpi->planes[i]; out->planestride[i] = mpi->stride[i]; out->planewidth[i] = - i ? (/*mpi->chroma_width*/ mpi->w >> mpi->chroma_x_shift) : mpi->w; + i ? (/*mpi->chroma_width*/ mpi->w >> mpi->fmt.chroma_xs) : mpi->w; out->planeheight[i] = - i ? (/*mpi->chroma_height*/ mpi->h >> mpi->chroma_y_shift) : mpi->h; - out->planexshift[i] = i ? mpi->chroma_x_shift : 0; - out->planeyshift[i] = i ? mpi->chroma_y_shift : 0; + i ? (/*mpi->chroma_height*/ mpi->h >> mpi->fmt.chroma_ys) : mpi->h; + out->planexshift[i] = i ? mpi->fmt.chroma_xs : 0; + out->planeyshift[i] = i ? mpi->fmt.chroma_ys : 0; } } diff --git a/video/filter/vf_eq.c b/video/filter/vf_eq.c index 3381f248f7..deacfff0e6 100644 --- a/video/filter/vf_eq.c +++ b/video/filter/vf_eq.c @@ -191,8 +191,8 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *src) if ((eq2->buf_w[0] != src->w) || (eq2->buf_h[0] != src->h)) { eq2->buf_w[0] = src->w; eq2->buf_h[0] = src->h; - eq2->buf_w[1] = eq2->buf_w[2] = src->w >> src->chroma_x_shift; - eq2->buf_h[1] = eq2->buf_h[2] = src->h >> src->chroma_y_shift; + eq2->buf_w[1] = eq2->buf_w[2] = src->w >> src->fmt.chroma_xs; + eq2->buf_h[1] = eq2->buf_h[2] = src->h >> src->fmt.chroma_ys; img_n = eq2->buf_w[0]*eq2->buf_h[0]; if(src->num_planes>1){ img_c = eq2->buf_w[1]*eq2->buf_h[1]; diff --git a/video/mp_image.c b/video/mp_image.c index 2c1e01cef9..c4ad6bd4c2 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -148,8 +148,6 @@ void mp_image_setfmt(struct mp_image *mpi, int out_fmt) mpi->fmt = fmt; mpi->flags = fmt.flags; mpi->imgfmt = fmt.id; - mpi->chroma_x_shift = fmt.chroma_xs; - mpi->chroma_y_shift = fmt.chroma_ys; mpi->num_planes = fmt.num_planes; mp_image_set_size(mpi, mpi->w, mpi->h); } diff --git a/video/mp_image.h b/video/mp_image.h index 95fe8ad20e..92f779136c 100644 --- a/video/mp_image.h +++ b/video/mp_image.h @@ -85,8 +85,6 @@ typedef struct mp_image { struct mp_imgfmt_desc fmt; enum mp_imgfmt imgfmt; int num_planes; - int chroma_x_shift; // horizontal - int chroma_y_shift; // vertical int w,h; // visible dimensions uint8_t *planes[MP_MAX_PLANES]; -- cgit v1.2.3 From 37a71e57d404a708505f920f610061ec5c424917 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 10 Apr 2015 21:06:18 +0200 Subject: mp_image: remove redundant flags field Because gcc (and clang) is a goddamn PITA and unnecessarily warns if the universal initializer for structs is used (like mp_image x = {}) and the first member of the struct is also a struct, move the w/h fields to the top. --- sub/draw_bmp.c | 4 ++-- video/mp_image.c | 7 +++---- video/mp_image.h | 3 +-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c index 78fb33ca9f..7a60215dba 100644 --- a/sub/draw_bmp.c +++ b/sub/draw_bmp.c @@ -295,7 +295,7 @@ static void draw_ass(struct mp_draw_sub_cache *cache, struct mp_rect bb, cspar.int_bits_out = 8; struct mp_cmat yuv2rgb, rgb2yuv; - bool need_conv = temp->flags & MP_IMGFLAG_YUV; + bool need_conv = temp->fmt.flags & MP_IMGFLAG_YUV; if (need_conv) { mp_get_yuv2rgb_coeffs(&cspar, &yuv2rgb); mp_invert_yuv2rgb(&rgb2yuv, &yuv2rgb); @@ -470,7 +470,7 @@ static struct mp_image *chroma_up(struct mp_draw_sub_cache *cache, int imgfmt, // The temp image is always YUV, but src not necessarily. // Reduce amount of conversions in YUV case (upsampling/shifting only) - if (src->flags & MP_IMGFLAG_YUV) { + if (src->fmt.flags & MP_IMGFLAG_YUV) { temp->params.colorspace = src->params.colorspace; temp->params.colorlevels = src->params.colorlevels; } diff --git a/video/mp_image.c b/video/mp_image.c index c4ad6bd4c2..12b8fc437c 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -146,7 +146,6 @@ void mp_image_setfmt(struct mp_image *mpi, int out_fmt) struct mp_imgfmt_desc fmt = mp_imgfmt_get_desc(out_fmt); mpi->params.imgfmt = fmt.id; mpi->fmt = fmt; - mpi->flags = fmt.flags; mpi->imgfmt = fmt.id; mpi->num_planes = fmt.num_planes; mp_image_set_size(mpi, mpi->w, mpi->h); @@ -358,7 +357,7 @@ void mp_image_copy_attributes(struct mp_image *dst, struct mp_image *src) } dst->params.primaries = src->params.primaries; dst->params.gamma = src->params.gamma; - if ((dst->flags & MP_IMGFLAG_YUV) == (src->flags & MP_IMGFLAG_YUV)) { + if ((dst->fmt.flags & MP_IMGFLAG_YUV) == (src->fmt.flags & MP_IMGFLAG_YUV)) { dst->params.colorspace = src->params.colorspace; dst->params.colorlevels = src->params.colorlevels; dst->params.chroma_location = src->params.chroma_location; @@ -414,9 +413,9 @@ void mp_image_clear(struct mp_image *img, int x0, int y0, int x1, int y1) plane_clear[0]