0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 12:02:23 +02:00
mpv/video/out/vo_mediacodec_embed.c
Philip Langdale e50db42927 vo: hwdec: do hwdec interop lookup by image format
It turns out that it's generally more useful to look up hwdecs by image
format, rather than device type. In the situations where we need to
find one, we generally know the image format we're dealing with. Doing
this avoids us having to create mappings from image format to device
type.

The most significant part of this change is filling in the image format
for the various hw interops. There is a hw_imgfmt field today today, but
only a couple of the interops fill it in, and that seems to be because
we've never actually used this piece of metadata before. Well, now we
have a good use for it.
2022-09-21 09:39:34 -07:00

121 lines
3.2 KiB
C

/*
* 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 <libavcodec/mediacodec.h>
#include <libavutil/hwcontext.h>
#include <libavutil/hwcontext_mediacodec.h>
#include "common/common.h"
#include "vo.h"
#include "video/mp_image.h"
#include "video/hwdec.h"
struct priv {
struct mp_image *next_image;
struct mp_hwdec_ctx hwctx;
};
static AVBufferRef *create_mediacodec_device_ref(struct vo *vo)
{
AVBufferRef *device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_MEDIACODEC);
if (!device_ref)
return NULL;
AVHWDeviceContext *ctx = (void *)device_ref->data;
AVMediaCodecDeviceContext *hwctx = ctx->hwctx;
hwctx->surface = (void *)(intptr_t)(vo->opts->WinID);
if (av_hwdevice_ctx_init(device_ref) < 0)
av_buffer_unref(&device_ref);
return device_ref;
}
static int preinit(struct vo *vo)
{
struct priv *p = vo->priv;
vo->hwdec_devs = hwdec_devices_create();
p->hwctx = (struct mp_hwdec_ctx){
.driver_name = "mediacodec_embed",
.av_device_ref = create_mediacodec_device_ref(vo),
.hw_imgfmt = IMGFMT_MEDIACODEC,
};
hwdec_devices_add(vo->hwdec_devs, &p->hwctx);
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);
mp_image_unrefp(&p->next_image);
}
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;
mp_image_unrefp(&p->next_image);
hwdec_devices_remove(vo->hwdec_devs, &p->hwctx);
av_buffer_unref(&p->hwctx.av_device_ref);
}
const struct vo_driver video_out_mediacodec_embed = {
.description = "Android (Embedded MediaCodec Surface)",
.name = "mediacodec_embed",
.caps = VO_CAP_NORETAIN,
.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),
};