mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2026-05-19 08:00:27 +00:00
Implement testRenderFrame() for the VTMetal renderer
This can be used to (hopefully) detect cases where importing the decoded frames onto the target GPU fails. See #1885
This commit is contained in:
@@ -398,15 +398,12 @@ public:
|
|||||||
return m_SwMappingTextures[planeIndex];
|
return m_SwMappingTextures[planeIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Caller frees frame after we return
|
bool createTexturesFromFrame(AVFrame* frame, std::array<CVMetalTextureRef, MAX_VIDEO_PLANES>& cvMetalTextures)
|
||||||
virtual void renderFrameIntoDrawable(AVFrame* frame, id<CAMetalDrawable> drawable)
|
{
|
||||||
{ @autoreleasepool {
|
SDL_assert(frame->format == AV_PIX_FMT_VIDEOTOOLBOX);
|
||||||
std::array<CVMetalTextureRef, MAX_VIDEO_PLANES> cvMetalTextures;
|
|
||||||
size_t planes = getFramePlaneCount(frame);
|
|
||||||
SDL_assert(planes <= MAX_VIDEO_PLANES);
|
|
||||||
|
|
||||||
if (frame->format == AV_PIX_FMT_VIDEOTOOLBOX) {
|
|
||||||
CVPixelBufferRef pixBuf = reinterpret_cast<CVPixelBufferRef>(frame->data[3]);
|
CVPixelBufferRef pixBuf = reinterpret_cast<CVPixelBufferRef>(frame->data[3]);
|
||||||
|
size_t planes = getFramePlaneCount(frame);
|
||||||
|
|
||||||
// Create Metal textures for the planes of the CVPixelBuffer
|
// Create Metal textures for the planes of the CVPixelBuffer
|
||||||
for (size_t i = 0; i < planes; i++) {
|
for (size_t i = 0; i < planes; i++) {
|
||||||
@@ -431,7 +428,7 @@ public:
|
|||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"Unknown pixel format: %x",
|
"Unknown pixel format: %x",
|
||||||
CVPixelBufferGetPixelFormatType(pixBuf));
|
CVPixelBufferGetPixelFormatType(pixBuf));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CVReturn err = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, m_TextureCache, pixBuf, nullptr, fmt,
|
CVReturn err = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, m_TextureCache, pixBuf, nullptr, fmt,
|
||||||
@@ -440,12 +437,53 @@ public:
|
|||||||
i,
|
i,
|
||||||
&cvMetalTextures[i]);
|
&cvMetalTextures[i]);
|
||||||
if (err != kCVReturnSuccess) {
|
if (err != kCVReturnSuccess) {
|
||||||
|
for (size_t j = 0; j < i; j++) {
|
||||||
|
CFRelease(cvMetalTextures[j]);
|
||||||
|
}
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"CVMetalTextureCacheCreateTextureFromImage() failed: %d",
|
"CVMetalTextureCacheCreateTextureFromImage() failed: %d",
|
||||||
err);
|
err);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool testRenderFrame(AVFrame *frame) override
|
||||||
|
{ @autoreleasepool {
|
||||||
|
if (frame->format == AV_PIX_FMT_VIDEOTOOLBOX) {
|
||||||
|
std::array<CVMetalTextureRef, MAX_VIDEO_PLANES> cvMetalTextures;
|
||||||
|
size_t planes = getFramePlaneCount(frame);
|
||||||
|
SDL_assert(planes <= MAX_VIDEO_PLANES);
|
||||||
|
|
||||||
|
// Test that we can actually create Metal textures from the CVPixelBufferRef
|
||||||
|
if (!createTexturesFromFrame(frame, cvMetalTextures)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < planes; i++) {
|
||||||
|
CFRelease(cvMetalTextures[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Mapping software frames should always work
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Caller frees frame after we return
|
||||||
|
virtual void renderFrameIntoDrawable(AVFrame* frame, id<CAMetalDrawable> drawable)
|
||||||
|
{ @autoreleasepool {
|
||||||
|
std::array<CVMetalTextureRef, MAX_VIDEO_PLANES> cvMetalTextures;
|
||||||
|
size_t planes = getFramePlaneCount(frame);
|
||||||
|
SDL_assert(planes <= MAX_VIDEO_PLANES);
|
||||||
|
|
||||||
|
if (frame->format == AV_PIX_FMT_VIDEOTOOLBOX) {
|
||||||
|
if (!createTexturesFromFrame(frame, cvMetalTextures)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare a render pass to render into the next drawable
|
// Prepare a render pass to render into the next drawable
|
||||||
|
|||||||
Reference in New Issue
Block a user