Skip to content

Commit

Permalink
hwdec: support videotoolbox with libplacebo
Browse files Browse the repository at this point in the history
  • Loading branch information
rcombs committed Nov 16, 2023
1 parent 62b1ce0 commit ca45b71
Show file tree
Hide file tree
Showing 8 changed files with 568 additions and 149 deletions.
17 changes: 15 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -1362,7 +1362,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 @@ -1443,8 +1443,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')
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

0 comments on commit ca45b71

Please sign in to comment.