Last active
July 3, 2017 22:08
-
-
Save tmm1/886d11406d66c5f9fe65384da81d87c9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst | |
index a0ac7017dc..5a8f23424e 100644 | |
--- a/DOCS/man/options.rst | |
+++ b/DOCS/man/options.rst | |
@@ -2458,6 +2458,10 @@ Window | |
support window embedding of foreign processes, this works only with libmpv, | |
and will crash when used from the command line. | |
+ On Android, the ID is interpreted as ``android.view.Surface``. Pass it as a | |
+ value cast to ``intptr_t``. Use with ``--vo=android`` and | |
+ ``--hwdec=mediacodec`` for direct rendering using MediaCodec. | |
+ | |
``--no-window-dragging`` | |
Don't move the window when clicking on it and moving the mouse pointer. | |
diff --git a/options/options.c b/options/options.c | |
index a803dccf5d..a4fc446863 100644 | |
--- a/options/options.c | |
+++ b/options/options.c | |
@@ -108,6 +108,7 @@ const struct m_opt_choice_alternatives mp_hwdec_names[] = { | |
{"rpi", HWDEC_RPI}, | |
{"rpi-copy", HWDEC_RPI_COPY}, | |
{"mediacodec", HWDEC_MEDIACODEC}, | |
+ {"mediacodec-copy",HWDEC_MEDIACODEC_COPY}, | |
{"cuda", HWDEC_CUDA}, | |
{"cuda-copy", HWDEC_CUDA_COPY}, | |
{"crystalhd", HWDEC_CRYSTALHD}, | |
diff --git a/video/decode/hw_mediacodec.c b/video/decode/hw_mediacodec.c | |
new file mode 100644 | |
index 0000000000..18fec01f1e | |
--- /dev/null | |
+++ b/video/decode/hw_mediacodec.c | |
@@ -0,0 +1,78 @@ | |
+/* | |
+ * This file is part of mpv. | |
+ * | |
+ * mpv is free software; you can redistribute it and/or | |
+ * modify it under the terms of the GNU Lesser General Public | |
+ * License as published by the Free Software Foundation; either | |
+ * version 2.1 of the License, or (at your option) any later version. | |
+ * | |
+ * mpv is distributed in the hope that it will be useful, | |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
+ * GNU Lesser General Public License for more details. | |
+ * | |
+ * You should have received a copy of the GNU Lesser General Public | |
+ * License along with mpv. If not, see <http://www.gnu.org/licenses/>. | |
+ */ | |
+ | |
+#include <stdio.h> | |
+#include <stdlib.h> | |
+#include <assert.h> | |
+#include <time.h> | |
+#include <stdbool.h> | |
+#include <sys/types.h> | |
+ | |
+#include <libavcodec/mediacodec.h> | |
+ | |
+#include "common/av_common.h" | |
+#include "video/decode/lavc.h" | |
+#include "options/options.h" | |
+ | |
+static int probe(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec, | |
+ const char *codec) | |
+{ | |
+ if (ctx->opts->vo->WinID == 0) | |
+ return HWDEC_ERR_NO_CTX; | |
+ | |
+ return 0; | |
+} | |
+ | |
+static int init(struct lavc_ctx *ctx) | |
+{ | |
+ return 0; | |
+} | |
+ | |
+static int init_decoder(struct lavc_ctx *ctx, int w, int h) | |
+{ | |
+ av_mediacodec_default_free(ctx->avctx); | |
+ | |
+ AVMediaCodecContext *mcctx = av_mediacodec_alloc_context(); | |
+ if (!mcctx) | |
+ return -1; | |
+ | |
+ void *surface = (void *)(intptr_t)(ctx->opts->vo->WinID); | |
+ return av_mediacodec_default_init(ctx->avctx, mcctx, surface); | |
+} | |
+ | |
+ | |
+static void uninit(struct lavc_ctx *ctx) | |
+{ | |
+ if (ctx->avctx) | |
+ av_mediacodec_default_free(ctx->avctx); | |
+} | |
+ | |
+const struct vd_lavc_hwdec mp_vd_lavc_mediacodec = { | |
+ .type = HWDEC_MEDIACODEC, | |
+ .image_format = IMGFMT_MEDIACODEC, | |
+ .lavc_suffix = "_mediacodec", | |
+ .probe = probe, | |
+ .init = init, | |
+ .uninit = uninit, | |
+ .init_decoder = init_decoder, | |
+}; | |
+ | |
+const struct vd_lavc_hwdec mp_vd_lavc_mediacodec_copy = { | |
+ .type = HWDEC_MEDIACODEC_COPY, | |
+ .lavc_suffix = "_mediacodec", | |
+ .copying = true, | |
+}; | |
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c | |
index 6c6bf3f6b0..366441830c 100644 | |
--- a/video/decode/vd_lavc.c | |
+++ b/video/decode/vd_lavc.c | |
@@ -135,6 +135,8 @@ const struct m_sub_options vd_lavc_conf = { | |
}, | |
}; | |
+extern const struct vd_lavc_hwdec mp_vd_lavc_mediacodec; | |
+extern const struct vd_lavc_hwdec mp_vd_lavc_mediacodec_copy; | |
extern const struct vd_lavc_hwdec mp_vd_lavc_videotoolbox; | |
extern const struct vd_lavc_hwdec mp_vd_lavc_videotoolbox_copy; | |
extern const struct vd_lavc_hwdec mp_vd_lavc_dxva2; | |
@@ -156,14 +158,6 @@ static const struct vd_lavc_hwdec mp_vd_lavc_rpi_copy = { | |
}; | |
#endif | |
-#if HAVE_ANDROID | |
-static const struct vd_lavc_hwdec mp_vd_lavc_mediacodec = { | |
- .type = HWDEC_MEDIACODEC, | |
- .lavc_suffix = "_mediacodec", | |
- .copying = true, | |
-}; | |
-#endif | |
- | |
#if NEW_CUDA_HWACCEL | |
static const struct vd_lavc_hwdec mp_vd_lavc_cuda = { | |
.type = HWDEC_CUDA, | |
@@ -271,6 +265,7 @@ static const struct vd_lavc_hwdec *const hwdec_list[] = { | |
#endif | |
#if HAVE_ANDROID | |
&mp_vd_lavc_mediacodec, | |
+ &mp_vd_lavc_mediacodec_copy, | |
#endif | |
#if HAVE_CUDA_HWACCEL | |
#if NEW_CUDA_HWACCEL | |
diff --git a/video/fmt-conversion.c b/video/fmt-conversion.c | |
index 2dc3743be1..ff7cfa3969 100644 | |
--- a/video/fmt-conversion.c | |
+++ b/video/fmt-conversion.c | |
@@ -90,6 +90,9 @@ static const struct { | |
#if HAVE_VIDEOTOOLBOX_HWACCEL | |
{IMGFMT_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX}, | |
#endif | |
+#if HAVE_ANDROID | |
+ {IMGFMT_MEDIACODEC, AV_PIX_FMT_MEDIACODEC}, | |
+#endif | |
{IMGFMT_VAAPI, AV_PIX_FMT_VAAPI_VLD}, | |
{IMGFMT_DXVA2, AV_PIX_FMT_DXVA2_VLD}, | |
#if HAVE_D3D_HWACCEL | |
diff --git a/video/hwdec.h b/video/hwdec.h | |
index 637014d049..461ea6a3e6 100644 | |
--- a/video/hwdec.h | |
+++ b/video/hwdec.h | |
@@ -23,6 +23,7 @@ enum hwdec_type { | |
HWDEC_RPI, | |
HWDEC_RPI_COPY, | |
HWDEC_MEDIACODEC, | |
+ HWDEC_MEDIACODEC_COPY, | |
HWDEC_CUDA, | |
HWDEC_CUDA_COPY, | |
HWDEC_CRYSTALHD, | |
diff --git a/video/img_format.h b/video/img_format.h | |
index 11d3fc92b8..f200c4110b 100644 | |
--- a/video/img_format.h | |
+++ b/video/img_format.h | |
@@ -203,6 +203,7 @@ enum mp_imgfmt { | |
IMGFMT_DXVA2, // IDirect3DSurface9 (NV12/P010/P016) | |
IMGFMT_MMAL, // MMAL_BUFFER_HEADER_T | |
IMGFMT_VIDEOTOOLBOX, // CVPixelBufferRef | |
+ IMGFMT_MEDIACODEC, // AVMediaCodecBuffer | |
IMGFMT_CUDA, // CUDA Buffer | |
// Generic pass-through of AV_PIX_FMT_*. Used for formats which don't have | |
diff --git a/video/out/vo.c b/video/out/vo.c | |
index 79fc4f3bb4..921a0252bc 100644 | |
--- a/video/out/vo.c | |
+++ b/video/out/vo.c | |
@@ -44,6 +44,7 @@ | |
#include "osdep/io.h" | |
#include "osdep/threads.h" | |
+extern const struct vo_driver video_out_android; | |
extern const struct vo_driver video_out_x11; | |
extern const struct vo_driver video_out_vdpau; | |
extern const struct vo_driver video_out_xv; | |
@@ -63,6 +64,9 @@ extern const struct vo_driver video_out_tct; | |
const struct vo_driver *const video_out_drivers[] = | |
{ | |
+#if HAVE_ANDROID | |
+ &video_out_android, | |
+#endif | |
#if HAVE_RPI | |
&video_out_rpi, | |
#endif | |
@@ -834,6 +838,11 @@ static bool render_frame(struct vo *vo) | |
in->rendering = false; | |
update_vsync_timing_after_swap(vo); | |
+ | |
+ if (vo->driver->caps & VO_CAP_NOREDRAW) { | |
+ talloc_free(in->current_frame); | |
+ in->current_frame = NULL; | |
+ } | |
} | |
if (in->dropped_frame) { | |
@@ -857,7 +866,7 @@ static void do_redraw(struct vo *vo) | |
{ | |
struct vo_internal *in = vo->in; | |
- if (!vo->config_ok) | |
+ if (!vo->config_ok || (vo->driver->caps & VO_CAP_NOREDRAW)) | |
return; | |
pthread_mutex_lock(&in->lock); | |
diff --git a/video/out/vo.h b/video/out/vo.h | |
index c59e1b04c8..f0dbbfa6a8 100644 | |
--- a/video/out/vo.h | |
+++ b/video/out/vo.h | |
@@ -157,6 +157,8 @@ enum { | |
VO_CAP_ROTATE90 = 1 << 0, | |
// VO does framedrop itself (vo_vdpau). Untimed/encoding VOs never drop. | |
VO_CAP_FRAMEDROP = 1 << 1, | |
+ // VO does not support redraws (vo_android). | |
+ VO_CAP_NOREDRAW = 1 << 2, | |
}; | |
#define VO_MAX_REQ_FRAMES 10 | |
diff --git a/video/out/vo_android.c b/video/out/vo_android.c | |
new file mode 100644 | |
index 0000000000..a796d90ebc | |
--- /dev/null | |
+++ b/video/out/vo_android.c | |
@@ -0,0 +1,106 @@ | |
+/* | |
+ * This file is part of mpv. | |
+ * | |
+ * mpv is free software; you can redistribute it and/or | |
+ * modify it under the terms of the GNU Lesser General Public | |
+ * License as published by the Free Software Foundation; either | |
+ * version 2.1 of the License, or (at your option) any later version. | |
+ * | |
+ * mpv is distributed in the hope that it will be useful, | |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
+ * GNU Lesser General Public License for more details. | |
+ * | |
+ * You should have received a copy of the GNU Lesser General Public | |
+ * License along with mpv. If not, see <http://www.gnu.org/licenses/>. | |
+ */ | |
+ | |
+#include <stdio.h> | |
+#include <stdlib.h> | |
+#include <string.h> | |
+#include <math.h> | |
+#include <stdbool.h> | |
+#include <assert.h> | |
+ | |
+#include <libavcodec/mediacodec.h> | |
+ | |
+#include "common/common.h" | |
+#include "common/msg.h" | |
+#include "options/m_config.h" | |
+#include "osdep/timer.h" | |
+#include "vo.h" | |
+#include "video/mp_image.h" | |
+ | |
+struct priv { | |
+ struct mp_image *next_image; | |
+}; | |
+ | |
+static int preinit(struct vo *vo) | |
+{ | |
+ return 0; | |
+} | |
+ | |
+static void flip_page(struct vo *vo) | |
+{ | |
+ struct priv *p = vo->priv; | |
+ if (!p->next_image) | |
+ return; | |
+ | |
+ AVMediaCodecBuffer *buffer = (AVMediaCodecBuffer *)p->next_image->planes[3]; | |
+ av_mediacodec_release_buffer(buffer, 1); | |
+ talloc_free(p->next_image); | |
+ p->next_image = NULL; | |
+} | |
+ | |
+static void draw_frame(struct vo *vo, struct vo_frame *frame) | |
+{ | |
+ struct priv *p = vo->priv; | |
+ | |
+ mp_image_t *mpi = NULL; | |
+ if (!frame->redraw && !frame->repeat) | |
+ mpi = mp_image_new_ref(frame->current); | |
+ | |
+ talloc_free(p->next_image); | |
+ p->next_image = mpi; | |
+} | |
+ | |
+static int query_format(struct vo *vo, int format) | |
+{ | |
+ return format == IMGFMT_MEDIACODEC; | |
+} | |
+ | |
+static int control(struct vo *vo, uint32_t request, void *data) | |
+{ | |
+ return VO_NOTIMPL; | |
+} | |
+ | |
+static int reconfig(struct vo *vo, struct mp_image_params *params) | |
+{ | |
+ return 0; | |
+} | |
+ | |
+static void uninit(struct vo *vo) | |
+{ | |
+ struct priv *p = vo->priv; | |
+ talloc_free(p->next_image); | |
+} | |
+ | |
+#define OPT_BASE_STRUCT struct priv | |
+static const struct m_option options[] = { | |
+ {0}, | |
+}; | |
+ | |
+const struct vo_driver video_out_android = { | |
+ .description = "Android (MediaCodec Surface)", | |
+ .name = "android", | |
+ .caps = VO_CAP_NOREDRAW, | |
+ .preinit = preinit, | |
+ .query_format = query_format, | |
+ .control = control, | |
+ .draw_frame = draw_frame, | |
+ .flip_page = flip_page, | |
+ .reconfig = reconfig, | |
+ .uninit = uninit, | |
+ .priv_size = sizeof(struct priv), | |
+ .options = options, | |
+}; | |
diff --git a/wscript_build.py b/wscript_build.py | |
index 38281ceac7..7a21d5f6e7 100644 | |
--- a/wscript_build.py | |
+++ b/wscript_build.py | |
@@ -317,6 +317,7 @@ def build(ctx): | |
( "video/decode/hw_cuda.c", "cuda-hwaccel" ), | |
( "video/decode/hw_dxva2.c", "d3d-hwaccel" ), | |
( "video/decode/hw_d3d11va.c", "d3d-hwaccel" ), | |
+ ( "video/decode/hw_mediacodec.c", "android" ), | |
( "video/decode/hw_videotoolbox.c", "videotoolbox-hwaccel" ), | |
( "video/decode/vd_lavc.c" ), | |
( "video/filter/refqueue.c" ), | |
@@ -386,6 +387,7 @@ def build(ctx): | |
( "video/out/opengl/video.c", "gl" ), | |
( "video/out/opengl/video_shaders.c", "gl" ), | |
( "video/out/vo.c" ), | |
+ ( "video/out/vo_android.c", "android" ), | |
( "video/out/vo_caca.c", "caca" ), | |
( "video/out/vo_drm.c", "drm" ), | |
( "video/out/vo_direct3d.c", "direct3d" ), |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment