mirror of
https://github.com/mpv-player/mpv
synced 2025-03-25 04:38:01 +00:00
videotoolbox: factor some duplicated code
The code for copying a videotoolbox surface to mp_image was duplicated (with some minor differences - I picked the hw_videotoolbox.c version, because it was "better"). mp_imgfmt_from_cvpixelformat() is somewhat duplicated with the vt_formats[] table, but this will be fixed in a later commit, and moving the function to shared code is preparation.
This commit is contained in:
parent
e8137ee881
commit
1e4fd996bb
@ -25,6 +25,7 @@
|
||||
#include "video/mp_image.h"
|
||||
#include "video/decode/lavc.h"
|
||||
#include "video/mp_image_pool.h"
|
||||
#include "video/vt.h"
|
||||
#include "config.h"
|
||||
|
||||
struct priv {
|
||||
@ -138,55 +139,11 @@ static void uninit(struct lavc_ctx *ctx)
|
||||
ctx->hwdec_priv = NULL;
|
||||
}
|
||||
|
||||
static int mp_imgfmt_from_cvpixelformat(uint32_t cvpixfmt)
|
||||
{
|
||||
switch (cvpixfmt) {
|
||||
case kCVPixelFormatType_420YpCbCr8Planar: return IMGFMT_420P;
|
||||
case kCVPixelFormatType_422YpCbCr8: return IMGFMT_UYVY;
|
||||
case kCVPixelFormatType_32BGRA: return IMGFMT_RGB0;
|
||||
case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: return IMGFMT_NV12;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mp_image *copy_image(struct lavc_ctx *ctx, struct mp_image *hw_image)
|
||||
{
|
||||
if (hw_image->imgfmt != IMGFMT_VIDEOTOOLBOX)
|
||||
return hw_image;
|
||||
|
||||
struct priv *p = ctx->hwdec_priv;
|
||||
struct mp_image *image = NULL;
|
||||
CVPixelBufferRef pbuf = (CVPixelBufferRef)hw_image->planes[3];
|
||||
CVPixelBufferLockBaseAddress(pbuf, kCVPixelBufferLock_ReadOnly);
|
||||
size_t width = CVPixelBufferGetWidth(pbuf);
|
||||
size_t height = CVPixelBufferGetHeight(pbuf);
|
||||
uint32_t cvpixfmt = CVPixelBufferGetPixelFormatType(pbuf);
|
||||
int pixfmt = mp_imgfmt_from_cvpixelformat(cvpixfmt);
|
||||
if (!pixfmt)
|
||||
goto unlock;
|
||||
|
||||
struct mp_image img = {0};
|
||||
mp_image_setfmt(&img, pixfmt);
|
||||
mp_image_set_size(&img, width, height);
|
||||
|
||||
if (CVPixelBufferIsPlanar(pbuf)) {
|
||||
int planes = CVPixelBufferGetPlaneCount(pbuf);
|
||||
for (int i = 0; i < planes; i++) {
|
||||
img.planes[i] = CVPixelBufferGetBaseAddressOfPlane(pbuf, i);
|
||||
img.stride[i] = CVPixelBufferGetBytesPerRowOfPlane(pbuf, i);
|
||||
}
|
||||
} else {
|
||||
img.planes[0] = CVPixelBufferGetBaseAddress(pbuf);
|
||||
img.stride[0] = CVPixelBufferGetBytesPerRow(pbuf);
|
||||
}
|
||||
|
||||
mp_image_copy_attributes(&img, hw_image);
|
||||
|
||||
image = mp_image_pool_new_copy(p->sw_pool, &img);
|
||||
|
||||
unlock:
|
||||
CVPixelBufferUnlockBaseAddress(pbuf, kCVPixelBufferLock_ReadOnly);
|
||||
|
||||
struct mp_image *image = mp_vt_download_image(NULL, hw_image, p->sw_pool);
|
||||
if (image) {
|
||||
talloc_free(hw_image);
|
||||
return image;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <OpenGL/CGLIOSurface.h>
|
||||
|
||||
#include "video/mp_image_pool.h"
|
||||
#include "video/vt.h"
|
||||
#include "hwdec.h"
|
||||
#include "common/global.h"
|
||||
#include "options/options.h"
|
||||
@ -107,44 +108,6 @@ static struct vt_format *vt_get_gl_format_from_imgfmt(uint32_t imgfmt)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct mp_image *download_image(struct mp_hwdec_ctx *ctx,
|
||||
struct mp_image *hw_image,
|
||||
struct mp_image_pool *swpool)
|
||||
{
|
||||
if (hw_image->imgfmt != IMGFMT_VIDEOTOOLBOX)
|
||||
return NULL;
|
||||
|
||||
struct mp_image *image = NULL;
|
||||
CVPixelBufferRef pbuf = (CVPixelBufferRef)hw_image->planes[3];
|
||||
CVPixelBufferLockBaseAddress(pbuf, kCVPixelBufferLock_ReadOnly);
|
||||
size_t width = CVPixelBufferGetWidth(pbuf);
|
||||
size_t height = CVPixelBufferGetHeight(pbuf);
|
||||
uint32_t cvpixfmt = CVPixelBufferGetPixelFormatType(pbuf);
|
||||
struct vt_format *f = vt_get_gl_format(cvpixfmt);
|
||||
if (!f)
|
||||
goto unlock;
|
||||
|
||||
struct mp_image img = {0};
|
||||
mp_image_setfmt(&img, f->imgfmt);
|
||||
mp_image_set_size(&img, width, height);
|
||||
|
||||
for (int i = 0; i < f->planes; i++) {
|
||||
void *base = CVPixelBufferGetBaseAddressOfPlane(pbuf, i);
|
||||
size_t stride = CVPixelBufferGetBytesPerRowOfPlane(pbuf, i);
|
||||
img.planes[i] = base;
|
||||
img.stride[i] = stride;
|
||||
}
|
||||
|
||||
mp_image_copy_attributes(&img, hw_image);
|
||||
|
||||
image = mp_image_pool_new_copy(swpool, &img);
|
||||
|
||||
unlock:
|
||||
CVPixelBufferUnlockBaseAddress(pbuf, kCVPixelBufferLock_ReadOnly);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
static bool check_hwdec(struct gl_hwdec *hw)
|
||||
{
|
||||
if (hw->gl->version < 300) {
|
||||
@ -184,7 +147,7 @@ static int create(struct gl_hwdec *hw)
|
||||
};
|
||||
p->hwctx = (struct mp_hwdec_ctx){
|
||||
.type = HWDEC_VIDEOTOOLBOX,
|
||||
.download_image = download_image,
|
||||
.download_image = mp_vt_download_image,
|
||||
.ctx = &p->vtctx,
|
||||
};
|
||||
hwdec_devices_add(hw->devs, &p->hwctx);
|
||||
|
60
video/vt.c
Normal file
60
video/vt.c
Normal file
@ -0,0 +1,60 @@
|
||||
#include <CoreVideo/CoreVideo.h>
|
||||
|
||||
#include "video/decode/lavc.h"
|
||||
|
||||
#include "mp_image.h"
|
||||
#include "mp_image_pool.h"
|
||||
#include "vt.h"
|
||||
|
||||
int mp_imgfmt_from_cvpixelformat(uint32_t cvpixfmt)
|
||||
{
|
||||
switch (cvpixfmt) {
|
||||
case kCVPixelFormatType_420YpCbCr8Planar: return IMGFMT_420P;
|
||||
case kCVPixelFormatType_422YpCbCr8: return IMGFMT_UYVY;
|
||||
case kCVPixelFormatType_32BGRA: return IMGFMT_RGB0;
|
||||
case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: return IMGFMT_NV12;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// (ctx is unused - it's for compatibility with mp_hwdec_ctx.download_image())
|
||||
struct mp_image *mp_vt_download_image(struct mp_hwdec_ctx *ctx,
|
||||
struct mp_image *hw_image,
|
||||
struct mp_image_pool *swpool)
|
||||
{
|
||||
if (hw_image->imgfmt != IMGFMT_VIDEOTOOLBOX)
|
||||
return NULL;
|
||||
|
||||
struct mp_image *image = NULL;
|
||||
CVPixelBufferRef pbuf = (CVPixelBufferRef)hw_image->planes[3];
|
||||
CVPixelBufferLockBaseAddress(pbuf, kCVPixelBufferLock_ReadOnly);
|
||||
size_t width = CVPixelBufferGetWidth(pbuf);
|
||||
size_t height = CVPixelBufferGetHeight(pbuf);
|
||||
uint32_t cvpixfmt = CVPixelBufferGetPixelFormatType(pbuf);
|
||||
int imgfmt = mp_imgfmt_from_cvpixelformat(cvpixfmt);
|
||||
if (!imgfmt)
|
||||
goto unlock;
|
||||
|
||||
struct mp_image img = {0};
|
||||
mp_image_setfmt(&img, imgfmt);
|
||||
mp_image_set_size(&img, width, height);
|
||||
|
||||
if (CVPixelBufferIsPlanar(pbuf)) {
|
||||
int planes = CVPixelBufferGetPlaneCount(pbuf);
|
||||
for (int i = 0; i < planes; i++) {
|
||||
img.planes[i] = CVPixelBufferGetBaseAddressOfPlane(pbuf, i);
|
||||
img.stride[i] = CVPixelBufferGetBytesPerRowOfPlane(pbuf, i);
|
||||
}
|
||||
} else {
|
||||
img.planes[0] = CVPixelBufferGetBaseAddress(pbuf);
|
||||
img.stride[0] = CVPixelBufferGetBytesPerRow(pbuf);
|
||||
}
|
||||
|
||||
mp_image_copy_attributes(&img, hw_image);
|
||||
|
||||
image = mp_image_pool_new_copy(swpool, &img);
|
||||
|
||||
unlock:
|
||||
CVPixelBufferUnlockBaseAddress(pbuf, kCVPixelBufferLock_ReadOnly);
|
||||
return image;
|
||||
}
|
15
video/vt.h
Normal file
15
video/vt.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef MPV_VT_H
|
||||
#define MPV_VT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int mp_imgfmt_from_cvpixelformat(uint32_t cvpixfmt);
|
||||
|
||||
struct mp_image;
|
||||
struct mp_image_pool;
|
||||
struct mp_hwdec_ctx;
|
||||
struct mp_image *mp_vt_download_image(struct mp_hwdec_ctx *ctx,
|
||||
struct mp_image *hw_image,
|
||||
struct mp_image_pool *swpool);
|
||||
|
||||
#endif
|
@ -303,6 +303,7 @@ def build(ctx):
|
||||
( "video/vaapi.c", "vaapi" ),
|
||||
( "video/vdpau.c", "vdpau" ),
|
||||
( "video/vdpau_mixer.c", "vdpau" ),
|
||||
( "video/vt.c", "videotoolbox-hwaccel" ),
|
||||
( "video/decode/d3d.c", "win32" ),
|
||||
( "video/decode/dec_video.c"),
|
||||
( "video/decode/hw_cuda.c", "cuda-hwaccel" ),
|
||||
|
Loading…
Reference in New Issue
Block a user