35 using MakeEncoder = std::function<std::unique_ptr<score::gfx::GPUVideoEncoder>()>;
36 using GetOutputTexture
40 Lock lock, MakeEncoder makeEncoder, GetOutputTexture getOutputTexture,
41 const char*
name) noexcept
43 , m_makeEncoder{std::move(makeEncoder)}
44 , m_getOutputTexture{std::move(getOutputTexture)}
50 MakeEncoder m_makeEncoder;
51 GetOutputTexture m_getOutputTexture;
52 const char* m_name{
"DVP-GL"};
56 QOpenGLContext* m_glCtx{};
58 NvDvpContextHandle m_dvpCtx{};
59 NvDvpResourceHandle m_dvpTex{};
60 NvDvpResourceHandle m_dvpBuf{};
61 bool m_threadStarted{};
63 std::unique_ptr<score::gfx::GPUVideoEncoder> m_encoder;
64 QRhiTexture* m_encoderOutput{};
67 uint32_t m_sysmemBytes{};
68 uint32_t m_sysmemStrideBytes{};
69 uint32_t m_sysmemRows{};
72 const char*
name() const noexcept
override {
return m_name; }
74 static bool isSupported(QRhi* rhi) {
return rhi !=
nullptr; }
79 if(!isSupported(cfg.rhi) || !cfg.
state || !m_lock.valid())
83 =
static_cast<const QRhiGles2NativeHandles*
>(cfg.rhi->nativeHandles());
84 if(!native || !native->context)
86 m_glCtx = native->context;
90 qWarning() <<
"DVP(GL): no offscreen surface available to bind the GL "
91 "context; cannot init DVP";
94 if(!m_glCtx->makeCurrent(cfg.
state->surface))
96 qWarning() <<
"DVP(GL): makeCurrent() failed; cannot bind DVP to the "
105 auto colorShader = score::gfx::colorMatrixOut(
106 AVCOL_SPC_BT709, AVCOL_TRC_BT709, AVCOL_RANGE_MPEG, AVCOL_PRI_BT709);
108 m_encoder = m_makeEncoder();
111 qWarning() <<
"DVP(GL): no fragment encoder for format";
117 m_encoderOutput = m_getOutputTexture(m_encoder.get());
120 qWarning() <<
"DVP(GL): encoder did not produce an output texture";
125 const QSize texSize = m_encoderOutput->pixelSize();
126 m_sysmemRows = uint32_t(texSize.height());
127 m_sysmemStrideBytes = uint32_t(texSize.width()) * 4u;
128 m_sysmemBytes = m_sysmemStrideBytes * m_sysmemRows;
132 qWarning() <<
"DVP(GL): encoder output size" << m_sysmemBytes
138 qDebug() <<
"DVP(GL): loading dvp.dll...";
139 if(nv_dvp_init_gl(&m_dvpCtx) != NV_DVP_SUCCESS || !m_dvpCtx)
141 qWarning() <<
"DVP(GL): init failed:" << nv_dvp_get_error_string(m_dvpCtx);
145 qDebug() <<
"DVP(GL): dvp.dll loaded + GL context bound";
146 if(nv_dvp_thread_begin(m_dvpCtx) != NV_DVP_SUCCESS)
148 qWarning() <<
"DVP(GL): thread_begin failed:"
149 << nv_dvp_get_error_string(m_dvpCtx);
153 m_threadStarted =
true;
155 m_sysmem = nv_dvp_aligned_alloc(m_sysmemBytes);
158 qWarning() <<
"DVP(GL): nv_dvp_aligned_alloc(" << m_sysmemBytes
163 std::memset(m_sysmem, 0, m_sysmemBytes);
165 if(!m_lock.lock(m_sysmem, m_sysmemBytes))
167 qWarning() <<
"DVP(GL): DMABufferLock(sysmem) failed";
173 auto nt = m_encoderOutput->nativeTexture();
176 qWarning() <<
"DVP(GL): encoder texture has no native handle";
180 const uint32_t glTexId = uint32_t(nt.object);
182 if(nv_dvp_register_gl_texture(
183 m_dvpCtx, glTexId, NV_DVP_FORMAT_RGBA8,
184 uint32_t(texSize.width()), uint32_t(texSize.height()), &m_dvpTex)
187 qWarning() <<
"DVP(GL): register_gl_texture failed:"
188 << nv_dvp_get_error_string(m_dvpCtx);
192 if(nv_dvp_register_sysmem_buffer(
193 m_dvpCtx, m_sysmem, NV_DVP_FORMAT_RGBA8, uint32_t(texSize.width()),
194 uint32_t(texSize.height()), m_sysmemStrideBytes, &m_dvpBuf)
197 qWarning() <<
"DVP(GL): register_sysmem_buffer failed:"
198 << nv_dvp_get_error_string(m_dvpCtx);
206 void release()
override
210 if(m_dvpCtx && m_glCtx && cfg.
state && cfg.
state->surface
211 && QOpenGLContext::currentContext() != m_glCtx)
212 m_glCtx->makeCurrent(cfg.
state->surface);
218 nv_dvp_unregister(m_dvpCtx, m_dvpTex);
223 nv_dvp_unregister(m_dvpCtx, m_dvpBuf);
228 nv_dvp_thread_end(m_dvpCtx);
229 m_threadStarted =
false;
231 nv_dvp_shutdown(m_dvpCtx);
236 m_encoder->release();
239 m_encoderOutput =
nullptr;
241 if(m_dmaLocked && m_sysmem)
243 m_lock.unlock(m_sysmem, m_sysmemBytes);
248 nv_dvp_aligned_free(m_sysmem);
258 if(nv_dvp_acquire_texture(m_dvpCtx, m_dvpTex) != NV_DVP_SUCCESS)
260 qWarning() <<
"DVP(GL): acquire_texture failed:"
261 << nv_dvp_get_error_string(m_dvpCtx);
263 m_encoder->exec(*cfg.rhi, cb);
268 if(nv_dvp_release_texture(m_dvpCtx, m_dvpTex) != NV_DVP_SUCCESS)
270 qWarning() <<
"DVP(GL): release_texture failed:"
271 << nv_dvp_get_error_string(m_dvpCtx);
274 if(nv_dvp_copy_texture_to_buffer(m_dvpCtx, m_dvpTex, m_dvpBuf)
277 qWarning() <<
"DVP(GL): copy_texture_to_buffer failed:"
278 << nv_dvp_get_error_string(m_dvpCtx);