Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hwdec: support videotoolbox with libplacebo #12776

Merged
merged 1 commit into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -1379,7 +1379,7 @@ endif
ios_gl = cc.has_header_symbol('OpenGLES/ES3/glext.h', 'GL_RGB32F', required: get_option('ios-gl'))
features += {'ios-gl': ios_gl}
if features['ios-gl']
sources += files('video/out/opengl/hwdec_ios.m')
sources += files('video/out/hwdec/hwdec_ios_gl.m')
endif

rpi_mmal_opt = get_option('rpi-mmal').require(
Expand Down Expand Up @@ -1460,8 +1460,21 @@ videotoolbox_gl = get_option('videotoolbox-gl').require(
error_message: 'gl-cocoa nor ios-gl could be found!',
)
features += {'videotoolbox-gl': videotoolbox_gl.allowed()}
corevideo = dependency('appleframeworks', modules: ['CoreVideo'], required: get_option('videotoolbox-pl'))
videotoolbox_pl = get_option('videotoolbox-pl').require(
features['vulkan'] and corevideo.found(),
error_message: 'vulkan or CV metal support could be found!',
)
features += {'videotoolbox-pl': videotoolbox_pl.allowed()}
if features['videotoolbox-gl'] or features['videotoolbox-pl']
sources += files('video/out/hwdec/hwdec_vt.c')
endif
if features['videotoolbox-gl']
sources += files('video/out/opengl/hwdec_osx.c')
sources += files('video/out/hwdec/hwdec_mac_gl.c')
endif
if features['videotoolbox-pl']
dependencies += corevideo
sources += files('video/out/hwdec/hwdec_vt_pl.m')
Dudemanguy marked this conversation as resolved.
Show resolved Hide resolved
endif


Expand Down
1 change: 1 addition & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ option('gl-dxinterop-d3d9', type: 'feature', value: 'auto', description: 'OpenGL
option('ios-gl', type: 'feature', value: 'auto', description: 'iOS OpenGL ES hardware decoding interop support')
option('rpi-mmal', type: 'feature', value: 'auto', description: 'Raspberry Pi MMAL hwaccel')
option('videotoolbox-gl', type: 'feature', value: 'auto', description: 'Videotoolbox with OpenGL')
option('videotoolbox-pl', type: 'feature', value: 'auto', description: 'Videotoolbox with libplacebo')
option('vulkan-interop', type: 'feature', value: 'auto', description: 'Vulkan graphics interop')

# macOS features
Expand Down
2 changes: 1 addition & 1 deletion video/out/gpu/hwdec.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const struct ra_hwdec_driver *const ra_hwdec_drivers[] = {
#if HAVE_VAAPI
&ra_hwdec_vaapi,
#endif
#if HAVE_VIDEOTOOLBOX_GL || HAVE_IOS_GL
#if HAVE_VIDEOTOOLBOX_GL || HAVE_IOS_GL || HAVE_VIDEOTOOLBOX_PL
&ra_hwdec_videotoolbox,
#endif
#if HAVE_D3D_HWACCEL
Expand Down
90 changes: 17 additions & 73 deletions video/out/opengl/hwdec_ios.m → video/out/hwdec/hwdec_ios_gl.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,10 @@

#include "video/out/gpu/hwdec.h"
#include "video/mp_image_pool.h"
#include "ra_gl.h"
#include "video/out/opengl/ra_gl.h"
#include "hwdec_vt.h"

struct priv_owner {
struct mp_hwdec_ctx hwctx;
};

struct priv {
CVPixelBufferRef pbuf;
CVOpenGLESTextureCacheRef gl_texture_cache;
CVOpenGLESTextureRef gl_planes[MP_MAX_PLANES];
struct ra_imgfmt_desc desc;
};

static bool check_hwdec(struct ra_hwdec *hw)
static bool check_hwdec(const struct ra_hwdec *hw)
{
if (!ra_is_gl(hw->ra_ctx->ra))
return false;
Expand All @@ -59,38 +49,6 @@ static bool check_hwdec(struct ra_hwdec *hw)
return true;
}

static int init(struct ra_hwdec *hw)
{
struct priv_owner *p = hw->priv;

if (!check_hwdec(hw))
return -1;

p->hwctx = (struct mp_hwdec_ctx){
.driver_name = hw->driver->name,
.hw_imgfmt = IMGFMT_VIDEOTOOLBOX,
};

int ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
AV_HWDEVICE_TYPE_VIDEOTOOLBOX, NULL, NULL, 0);
if (ret != 0) {
MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
return -1;
}

hwdec_devices_add(hw->devs, &p->hwctx);

return 0;
}

static void uninit(struct ra_hwdec *hw)
{
struct priv_owner *p = hw->priv;

hwdec_devices_remove(hw->devs, &p->hwctx);
av_buffer_unref(&p->hwctx.av_device_ref);
}

// In GLES3 mode, CVOpenGLESTextureCacheCreateTextureFromImage()
// will return error -6683 unless invoked with GL_LUMINANCE and
// GL_LUMINANCE_ALPHA (http://stackoverflow.com/q/36213994/332798)
Expand Down Expand Up @@ -130,20 +88,6 @@ static int mapper_init(struct ra_hwdec_mapper *mapper)
{
struct priv *p = mapper->priv;

mapper->dst_params = mapper->src_params;
mapper->dst_params.imgfmt = mapper->src_params.hw_subfmt;
mapper->dst_params.hw_subfmt = 0;

if (!mapper->dst_params.imgfmt) {
MP_ERR(mapper, "Unsupported CVPixelBuffer format.\n");
return -1;
}

if (!ra_get_imgfmt_desc(mapper->ra, mapper->dst_params.imgfmt, &p->desc)) {
MP_ERR(mapper, "Unsupported texture format.\n");
return -1;
}

for (int n = 0; n < p->desc.num_planes; n++) {
p->desc.planes[n] = find_la_variant(mapper->ra, p->desc.planes[n]);
if (!p->desc.planes[n] || p->desc.planes[n]->ctype != RA_CTYPE_UNORM) {
Expand Down Expand Up @@ -262,17 +206,17 @@ static void mapper_uninit(struct ra_hwdec_mapper *mapper)
}
}

const struct ra_hwdec_driver ra_hwdec_videotoolbox = {
.name = "videotoolbox",
.priv_size = sizeof(struct priv_owner),
.imgfmts = {IMGFMT_VIDEOTOOLBOX, 0},
.init = init,
.uninit = uninit,
.mapper = &(const struct ra_hwdec_mapper_driver){
.priv_size = sizeof(struct priv),
.init = mapper_init,
.uninit = mapper_uninit,
.map = mapper_map,
.unmap = mapper_unmap,
},
};
bool vt_gl_init(const struct ra_hwdec *hw)
{
struct priv_owner *p = hw->priv;

if (!check_hwdec(hw))
return false;

p->interop_init = mapper_init;
p->interop_uninit = mapper_uninit;
p->interop_map = mapper_map;
p->interop_unmap = mapper_unmap;

return true;
}
91 changes: 18 additions & 73 deletions video/out/opengl/hwdec_osx.c → video/out/hwdec/hwdec_mac_gl.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,10 @@

#include "video/mp_image_pool.h"
#include "video/out/gpu/hwdec.h"
#include "ra_gl.h"
#include "video/out/opengl/ra_gl.h"
#include "hwdec_vt.h"

struct priv_owner {
struct mp_hwdec_ctx hwctx;
};

struct priv {
CVPixelBufferRef pbuf;
GLuint gl_planes[MP_MAX_PLANES];

struct ra_imgfmt_desc desc;
};

static bool check_hwdec(struct ra_hwdec *hw)
static bool check_hwdec(const struct ra_hwdec *hw)
{
if (!ra_is_gl(hw->ra_ctx->ra))
return false;
Expand All @@ -60,65 +50,20 @@ static bool check_hwdec(struct ra_hwdec *hw)
return true;
}

static int init(struct ra_hwdec *hw)
{
struct priv_owner *p = hw->priv;

if (!check_hwdec(hw))
return -1;

p->hwctx = (struct mp_hwdec_ctx){
.driver_name = hw->driver->name,
.hw_imgfmt = IMGFMT_VIDEOTOOLBOX,
};

int ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
AV_HWDEVICE_TYPE_VIDEOTOOLBOX, NULL, NULL, 0);
if (ret != 0) {
MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
return -1;
}

hwdec_devices_add(hw->devs, &p->hwctx);

return 0;
}

static void uninit(struct ra_hwdec *hw)
{
struct priv_owner *p = hw->priv;

hwdec_devices_remove(hw->devs, &p->hwctx);
av_buffer_unref(&p->hwctx.av_device_ref);
}

static int mapper_init(struct ra_hwdec_mapper *mapper)
{
struct priv *p = mapper->priv;
GL *gl = ra_gl_get(mapper->ra);

gl->GenTextures(MP_MAX_PLANES, p->gl_planes);

mapper->dst_params = mapper->src_params;
mapper->dst_params.imgfmt = mapper->src_params.hw_subfmt;
mapper->dst_params.hw_subfmt = 0;

if (!mapper->dst_params.imgfmt) {
MP_ERR(mapper, "Unsupported CVPixelBuffer format.\n");
return -1;
}

if (!ra_get_imgfmt_desc(mapper->ra, mapper->dst_params.imgfmt, &p->desc)) {
MP_ERR(mapper, "Unsupported texture format.\n");
return -1;
}

for (int n = 0; n < p->desc.num_planes; n++) {
if (p->desc.planes[n]->ctype != RA_CTYPE_UNORM) {
MP_ERR(mapper, "Format unsupported.\n");
return -1;
}
}

return 0;
}

Expand Down Expand Up @@ -208,17 +153,17 @@ static void mapper_uninit(struct ra_hwdec_mapper *mapper)
gl->DeleteTextures(MP_MAX_PLANES, p->gl_planes);
}

const struct ra_hwdec_driver ra_hwdec_videotoolbox = {
.name = "videotoolbox",
.priv_size = sizeof(struct priv_owner),
.imgfmts = {IMGFMT_VIDEOTOOLBOX, 0},
.init = init,
.uninit = uninit,
.mapper = &(const struct ra_hwdec_mapper_driver){
.priv_size = sizeof(struct priv),
.init = mapper_init,
.uninit = mapper_uninit,
.map = mapper_map,
.unmap = mapper_unmap,
},
};
bool vt_gl_init(const struct ra_hwdec *hw)
{
struct priv_owner *p = hw->priv;

if (!check_hwdec(hw))
return false;

p->interop_init = mapper_init;
p->interop_uninit = mapper_uninit;
p->interop_map = mapper_map;
p->interop_unmap = mapper_unmap;

return true;
}
Loading