101 if (frame->format != AV_PIX_FMT_VAAPI || !eglDisplay) {
102 qCDebug(qLHWAccelVAAPI) <<
"format/egl error" << frame->format << eglDisplay;
106 if (!frame->hw_frames_ctx)
109 auto *ctx = avFrameDeviceContext(frame);
113 auto *vaCtx = (AVVAAPIDeviceContext *)ctx->hwctx;
114 auto vaDisplay = vaCtx->display;
116 qCDebug(qLHWAccelVAAPI) <<
" no VADisplay, disabling";
120 VASurfaceID vaSurface = (uintptr_t)frame->data[3];
122 VADRMPRIMESurfaceDescriptor prime = {};
123 if (vaExportSurfaceHandle(vaDisplay, vaSurface, VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
124 VA_EXPORT_SURFACE_READ_ONLY
126 : VA_EXPORT_SURFACE_COMPOSED_LAYERS),
128 != VA_STATUS_SUCCESS) {
129 qWarning() <<
"vaExportSurfaceHandle failed";
134 QScopeGuard closeObjectsGuard([&prime]() {
135 for (uint32_t i = 0; i < prime.num_objects; ++i)
136 close(prime.objects[i].fd);
140 vaSyncSurface(vaDisplay, vaSurface);
147 AVPixelFormat fmt = HWAccel::format(frame);
148 bool needsConversion;
149 auto qtFormat = QFFmpegVideoBuffer::toQtPixelFormat(fmt, &needsConversion);
150 QSpan<
const DRMFormat> drm_formats = QtMultimediaPrivate::dmaBufFourccFromPixelFormat(qtFormat);
151 if (drm_formats.empty() || needsConversion) {
152 qWarning() <<
"can't use DMA transfer for pixel format" << fmt << qtFormat;
156 auto *desc = QVideoTextureHelper::textureDescription(qtFormat);
157 int nPlanes =
int(drm_formats.size());
158 Q_ASSERT(nPlanes == desc->nplanes);
159 nPlanes = desc->nplanes;
162 rhi->makeThreadLocalNativeContextCurrent();
164 std::array<EGLImage, 4> images = {};
165 std::array<GLuint, 4> glTextures = {};
166 functions.glGenTextures(nPlanes, glTextures.data());
168 auto releaseTextures = qScopeGuard([&] {
169 for (EGLImage img : images) {
171 eglDestroyImage(eglDisplay, img);
173 functions.glDeleteTextures(nPlanes, glTextures.data());
176 for (
int i = 0; i < nPlanes; ++i) {
181 if (prime.layers[i].drm_format != quint32(drm_formats[i])) {
182 qWarning() <<
"expected DRM format check failed expected" << Qt::hex
183 << quint32(drm_formats[i]) <<
"got" << prime.layers[i].drm_format;
187 QSize planeSize = desc->rhiPlaneSize(QSize(frame->width, frame->height), i, rhi);
188 constexpr uint32_t maxAttrCount = 18;
189 EGLAttrib img_attr[maxAttrCount] = {
190 EGL_LINUX_DRM_FOURCC_EXT, EGLint(drm_formats[i]),
191 EGL_WIDTH, planeSize.width(),
192 EGL_HEIGHT, planeSize.height(),
193 EGL_DMA_BUF_PLANE0_FD_EXT, prime.objects[prime.layers[layer].object_index[plane]].fd,
194 EGL_DMA_BUF_PLANE0_OFFSET_EXT, (EGLint)prime.layers[layer].offset[plane],
195 EGL_DMA_BUF_PLANE0_PITCH_EXT, (EGLint)prime.layers[layer].pitch[plane],
197 uint32_t img_attr_idx = 12;
198 uint64_t modifier = prime.objects[prime.layers[layer].object_index[plane]].drm_format_modifier;
199 if (modifier != QtMultimediaPrivate::DmaBufFormatModifierInvalid) {
200 img_attr[img_attr_idx++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
201 img_attr[img_attr_idx++] = modifier & 0xFFFFFFFF;
202 img_attr[img_attr_idx++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
203 img_attr[img_attr_idx++] = modifier >> 32;
205 img_attr[img_attr_idx++] = EGL_NONE;
206 Q_ASSERT(img_attr_idx <= maxAttrCount);
207 images[i] = eglCreateImage(eglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
nullptr, img_attr);
209 const GLenum error = eglGetError();
210 if (error == EGL_BAD_MATCH) {
211 qWarning() <<
"eglCreateImage failed for plane" << i <<
"with error code EGL_BAD_MATCH, "
212 "disabling hardware acceleration. This could indicate an EGL implementation issue."
213 "\nVAAPI driver: " << vaQueryVendorString(vaDisplay)
214 <<
"\nEGL vendor:" << eglQueryString(eglDisplay, EGL_VENDOR);
219 qWarning() <<
"eglCreateImage failed for plane" << i <<
"with error code" << error;
223 functions.glActiveTexture(GL_TEXTURE0 + i);
224 functions.glBindTexture(GL_TEXTURE_2D, glTextures[i]);
226 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC eglImageTargetTexture2D = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)
this->eglImageTargetTexture2D;
227 eglImageTargetTexture2D(GL_TEXTURE_2D, images[i]);
228 GLenum error = glGetError();
230 qWarning() <<
"eglImageTargetTexture2D failed with error code" << error;
233 releaseTextures.dismiss();
235 for (
int i = 0; i < nPlanes; ++i) {
236 functions.glActiveTexture(GL_TEXTURE0 + i);
237 functions.glBindTexture(GL_TEXTURE_2D, 0);
238 eglDestroyImage(eglDisplay, images[i]);
241 auto textureHandles = std::make_unique<VAAPITextureHandles>();
242 textureHandles->parentConverterBackend = shared_from_this();
243 textureHandles->nPlanes = nPlanes;
244 textureHandles->rhi = rhi;
246 textureHandles->textures = glTextures;
249 return textureHandles;