bool VaApiMixer::upload(const VideoFrame &frame, bool deint) { if (!m_glSurface) return false; static const int specs[MP_CSP_COUNT] = { 0, //MP_CSP_AUTO, VA_SRC_BT601, //MP_CSP_BT_601, VA_SRC_BT709, //MP_CSP_BT_709, VA_SRC_SMPTE_240, //MP_CSP_SMPTE_240M, 0, //MP_CSP_RGB, 0, //MP_CSP_XYZ, 0, //MP_CSP_YCGCO, }; static const int field[] = { // Picture = 0, Top = 1, Bottom = 2 VA_FRAME_PICTURE, VA_TOP_FIELD, VA_BOTTOM_FIELD, VA_FRAME_PICTURE }; const auto id = (VASurfaceID)(quintptr)frame.data(3); int flags = specs[frame.format().colorspace()]; if (deint) flags |= field[frame.field() & VideoFrame::Interlaced]; if (!check(vaCopySurfaceGLX(VaApi::glx(), m_glSurface, id, flags), "Cannot copy OpenGL surface.")) return false; if (!check(vaSyncSurface(VaApi::glx(), id), "Cannot sync video surface.")) return false; return true; }
void VideoFrame::doDeepCopy(const VideoFrame &frame) { d.detach(); Q_ASSERT(d->format == frame.format()); auto p = d->buffer.data(); for (int i=0; i<d->format.planes(); ++i) { const int len = d->format.bytesPerPlain(i); memcpy(p, frame.data(i), len); p += len; } }
bool VdaMixer::upload(const VideoFrame &frame, bool /*deint*/) { Q_ASSERT(frame.format().imgfmt() == IMGFMT_VDA); CGLError error = kCGLNoError; for (auto &texture : m_textures) { const auto cgl = CGLGetCurrentContext(); const auto surface = CVPixelBufferGetIOSurface((CVPixelBufferRef)frame.data(3)); texture.bind(); const auto w = IOSurfaceGetWidthOfPlane(surface, texture.plane()); const auto h = IOSurfaceGetHeightOfPlane(surface, texture.plane()); if (_Change(error, CGLTexImageIOSurface2D(cgl, texture.target(), texture.format(), w, h, texture.transfer().format, texture.transfer().type, surface, texture.plane()))) { _Error("CGLError: %%(0x%%)", CGLErrorString(error), _N(error, 16)); return false; } } return true; }