2 #include "libmythbase/mythconfig.h"
11 #define LOC QString("NVDECInterop: ")
14 #define CUDA_CHECK(CUDA_FUNCS, CUDA_CALL) \
16 CUresult res = (CUDA_FUNCS)->CUDA_CALL; \
17 if (res != CUDA_SUCCESS) { \
19 (CUDA_FUNCS)->cuGetErrorString(res, &desc); \
20 LOG(VB_GENERAL, LOG_ERR, LOC + QString("CUDA error %1 (%2)").arg(res).arg(desc)); \
47 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Deleting CUDA resources");
50 std::vector<MythVideoTextureOpenGL*> textures = it.value();
51 for (
auto & texture : textures)
53 auto *data =
reinterpret_cast<QPair<CUarray,CUgraphicsResource>*
>(texture->m_data);
54 if (data && data->second)
57 texture->m_data =
nullptr;
62 CUcontext dummy =
nullptr;
88 if (std::any_of(nvdec->second.cbegin(), nvdec->second.cend(), matchType))
107 std::vector<MythVideoTextureOpenGL*>
113 std::vector<MythVideoTextureOpenGL*> result;
118 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Mismatched OpenGL contexts");
121 QSize surfacesize(
Frame->m_width,
Frame->m_height);
126 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Video texture size changed! %1x%2->%3x%4")
152 auto cudabuffer =
reinterpret_cast<CUdeviceptr
>(
Frame->m_buffer);
157 CUcontext dummy =
nullptr;
166 std::vector<QSize> sizes;
167 sizes.emplace_back(
Frame->m_width,
Frame->m_height);
168 sizes.emplace_back(
Frame->m_width,
Frame->m_height >> 1);
169 std::vector<MythVideoTextureOpenGL*> textures =
171 if (textures.empty())
178 for (
uint plane = 0; plane < textures.size(); ++plane)
185 QOpenGLTexture::PixelFormat format = QOpenGLTexture::Red;
186 QOpenGLTexture::PixelType pixtype = p010 ? QOpenGLTexture::UInt16 : QOpenGLTexture::UInt8;
187 QOpenGLTexture::TextureFormat
internal = p010 ? QOpenGLTexture::R16_UNorm : QOpenGLTexture::R8_UNorm;
188 int width = tex->
m_size.width();
192 internal = p010 ? QOpenGLTexture::RG16_UNorm : QOpenGLTexture::RG8_UNorm;
193 format = QOpenGLTexture::RG;
198 0, format, pixtype,
nullptr);
200 CUarray array =
nullptr;
201 CUgraphicsResource graphicsResource =
nullptr;
203 QOpenGLTexture::Target2D, CU_GRAPHICS_REGISTER_FLAGS_WRITE_DISCARD))
204 if (graphicsResource)
209 tex->
m_data =
reinterpret_cast<unsigned char*
>(
new QPair<CUarray,CUgraphicsResource>(array, graphicsResource));
224 for (
auto & texture : textures)
226 auto *data =
reinterpret_cast<QPair<CUarray,CUgraphicsResource>*
>(texture->m_data);
227 if (data && data->second)
230 texture->m_data =
nullptr;
231 if (texture->m_textureId)
249 for (
uint i = 0; i < result.size(); ++i)
251 auto *data =
reinterpret_cast<QPair<CUarray,CUgraphicsResource>*
>(result[i]->m_data);
253 memset(&cpy, 0,
sizeof(cpy));
254 cpy.srcMemoryType = CU_MEMORYTYPE_DEVICE;
255 cpy.srcDevice = cudabuffer +
static_cast<CUdeviceptr
>(
Frame->m_offsets[i]);
256 cpy.srcPitch =
static_cast<size_t>(
Frame->m_pitches[i]);
257 cpy.dstMemoryType = CU_MEMORYTYPE_ARRAY;
258 cpy.dstArray = data->first;
259 cpy.WidthInBytes =
static_cast<size_t>(result[i]->m_size.width()) * (p010 ? 2 : 1);
260 cpy.Height =
static_cast<size_t>(result[i]->m_size.height());
269 bool needreferences =
false;
294 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Reference frame error");
319 CUcontext& CudaContext,
bool& Retry)
329 if (cuda_load_functions(&CudaFuncs,
nullptr) != 0)
331 LOG(VB_PLAYBACK, LOG_ERR,
LOC +
"Failed to load functions");
336 CUdevice cudevice = 0;
337 CUcontext dummy =
nullptr;
338 CUresult res = CudaFuncs->cuInit(0);
339 if (res != CUDA_SUCCESS)
341 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to initialise CUDA API");
345 unsigned int devicecount = 0;
346 res = CudaFuncs->cuGLGetDevices(&devicecount, &cudevice, 1, CU_GL_DEVICE_LIST_ALL);
347 if (res != CUDA_SUCCESS)
349 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to get CUDA device");
355 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No CUDA devices");
359 res = CudaFuncs->cuCtxCreate(&CudaContext, CU_CTX_SCHED_BLOCKING_SYNC, cudevice);
360 if (res != CUDA_SUCCESS)
362 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to create CUDA context (Err: %1)")
368 CudaFuncs->cuCtxPopCurrent(&dummy);
369 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Created CUDA context");
374 CUcontext& CudaContext)
378 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Must create CUDA context from main thread");
384 while (retries++ < 5)
391 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Will retry in 50ms");
392 std::this_thread::sleep_for(50ms);
398 CUcontext& CudaContext)
407 CUDA_CHECK(CudaFuncs, cuCtxDestroy(CudaContext))
408 cuda_free_functions(&CudaFuncs);