bool VaapiImage::unmap() { VAStatus status; if (!m_isMapped) return true; switch(m_rawImage.memoryType) { case VIDEO_DATA_MEMORY_TYPE_RAW_POINTER: case VIDEO_DATA_MEMORY_TYPE_RAW_COPY: status = vaUnmapBuffer(m_display->getID(), m_image->buf); if (!checkVaapiStatus(status, "vaUnmapBuffer()")) return false; break; case VIDEO_DATA_MEMORY_TYPE_DRM_NAME: case VIDEO_DATA_MEMORY_TYPE_DMA_BUF: status = vaReleaseBufferHandle(m_display->getID(), m_image->buf); if (!checkVaapiStatus(status, "vaReleaseBufferHandle()")) return false; break; default: ASSERT(0); break; } m_isMapped = false; return true; }
VaapiImageRaw *VaapiImage::map(VideoDataMemoryType memoryType) { uint32_t i; void *data; VAStatus status; if (m_isMapped) { return &m_rawImage; } m_rawImage.format = m_image->format.fourcc; m_rawImage.width = m_image->width; m_rawImage.height = m_image->height; m_rawImage.numPlanes = m_image->num_planes; m_rawImage.size = m_image->data_size; for (i = 0; i < m_image->num_planes; i++) { m_rawImage.strides[i] = m_image->pitches[i]; } if (memoryType == VIDEO_DATA_MEMORY_TYPE_RAW_POINTER || memoryType == VIDEO_DATA_MEMORY_TYPE_RAW_COPY) { status = vaMapBuffer(m_display->getID(), m_image->buf, &data); if (!checkVaapiStatus(status, "vaMapBuffer()")) return NULL; for (i = 0; i < m_image->num_planes; i++) { m_rawImage.handles[i] = (intptr_t) data + m_image->offsets[i]; } } else { VABufferInfo bufferInfo; if (memoryType == VIDEO_DATA_MEMORY_TYPE_DRM_NAME) bufferInfo.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM; else if (memoryType == VIDEO_DATA_MEMORY_TYPE_DMA_BUF) bufferInfo.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; else ASSERT(0); status = vaAcquireBufferHandle(m_display->getID(), m_image->buf, &bufferInfo); if (!checkVaapiStatus(status, "vaAcquireBufferHandle()")) return NULL; for (i = 0; i < m_image->num_planes; i++) { m_rawImage.handles[i] = (intptr_t) bufferInfo.handle; } } m_rawImage.memoryType = memoryType; m_isMapped = true; return &m_rawImage; }
ImageRawPtr VaapiImageRaw::create(const DisplayPtr& display, const ImagePtr& image, VideoDataMemoryType memoryType) { ImageRawPtr raw; RealeaseCallback release; uintptr_t handle; VAStatus status; VAImagePtr& vaImage = image->m_image; if (memoryType == VIDEO_DATA_MEMORY_TYPE_RAW_POINTER || memoryType == VIDEO_DATA_MEMORY_TYPE_RAW_COPY) { void* data; status = vaMapBuffer(display->getID(), vaImage->buf, &data); release = vaUnmapBuffer; handle = (uintptr_t)data; } else { VABufferInfo bufferInfo; if (memoryType == VIDEO_DATA_MEMORY_TYPE_DRM_NAME) bufferInfo.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM; else if (memoryType == VIDEO_DATA_MEMORY_TYPE_DMA_BUF) bufferInfo.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; else ASSERT(0); status = vaAcquireBufferHandle(display->getID(), vaImage->buf, &bufferInfo); release = vaReleaseBufferHandle; handle = (uintptr_t)bufferInfo.handle; } if (!checkVaapiStatus(status, "VaapiImageRaw::create()")) return raw; raw.reset(new VaapiImageRaw(display, image, memoryType, handle, release)); return raw; }
bool EglVaapiImage::acquireBufferHandle(VideoDataMemoryType memoryType) { uint32_t i; if (m_acquired) { ASSERT(memoryType = m_frameInfo.memoryType); return true; } // FIXME, more type can be supported if (memoryType == VIDEO_DATA_MEMORY_TYPE_DRM_NAME) m_bufferInfo.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM; else if (memoryType == VIDEO_DATA_MEMORY_TYPE_DMA_BUF) m_bufferInfo.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; else ASSERT(0); VAStatus vaStatus = vaAcquireBufferHandle(m_display, m_image.buf, &m_bufferInfo); m_frameInfo.memoryType = memoryType; m_frameInfo.width = m_width; m_frameInfo.height = m_height; for (i=0; i<m_image.num_planes; i++) { m_frameInfo.pitch[i] = m_image.pitches[i]; m_frameInfo.offset[i] = m_image.offsets[i]; } m_frameInfo.fourcc = m_image.format.fourcc; m_frameInfo.size = m_image.data_size; // not interest for bufferhandle m_frameInfo.handle = m_bufferInfo.handle; m_acquired = true; return checkVaapiStatus(vaStatus, "vaAcquireBufferHandle"); }
const VAImageFormat * VaapiDisplay::getVaFormat(uint32_t fourcc) { AutoLock locker(m_lock); int i; if (m_vaImageFormats.empty()) { VAStatus vaStatus; int numImageFormats; numImageFormats = vaMaxNumImageFormats(m_vaDisplay); if (numImageFormats == 0) return NULL; m_vaImageFormats.reserve(numImageFormats); m_vaImageFormats.resize(numImageFormats); vaStatus = vaQueryImageFormats(m_vaDisplay, &m_vaImageFormats[0], &numImageFormats); checkVaapiStatus(vaStatus, "vaQueryImageFormats()"); for (i=0; i< m_vaImageFormats.size(); i++) DEBUG_FOURCC("supported image format: ", m_vaImageFormats[i].fourcc); } for (i = 0; i < m_vaImageFormats.size(); i++) { VAImageFormat vaImageFormat = m_vaImageFormats[i]; if (vaImageFormat.fourcc == fourcc) return &m_vaImageFormats[i]; } return NULL; }
static bool vaInit(VADisplay vaDisplay) { int majorVersion, minorVersion; VAStatus vaStatus; vaStatus= vaInitialize(vaDisplay, &majorVersion, &minorVersion); return checkVaapiStatus(vaStatus, "vaInitialize"); }
/* Creates and maps VA buffer */ bool vaapiCreateBuffer(VADisplay dpy, VAContextID ctx, int type, uint32_t size, const void *buf, VABufferID * bufIdPtr, void **mappedData) { VABufferID bufId; VAStatus status; void *data = (void *) buf; status = vaCreateBuffer(dpy, ctx, (VABufferType) type, size, 1, data, &bufId); if (!checkVaapiStatus(status, "vaCreateBuffer()")) return false; if (mappedData) { data = vaapiMapBuffer(dpy, bufId); if (!data) goto error; *mappedData = data; } *bufIdPtr = bufId; return true; error: vaapiDestroyBuffer(dpy, &bufId); return false; }
bool VaapiSurface::putImage(VaapiImage * image) { VAImageID imageID; VAStatus status; uint32_t width, height; if (!image) return false; width = image->getWidth(); height = image->getHeight(); if (width != m_width || height != m_height) { ERROR("Image resolution does not match with surface"); return false; } imageID = image->getID(); status = vaGetImage(m_display->getID(), m_ID, 0, 0, width, height, imageID); if (!checkVaapiStatus(status, "vaPutImage()")) return false; return true; }
bool getVaFormat(VADisplay display, VAImageFormat& format) { int num = vaMaxNumImageFormats(display); if (!num) return false; std::vector<VAImageFormat> vaFormats; vaFormats.resize(num); VAStatus vaStatus = vaQueryImageFormats(display, &vaFormats[0], &num); if (!checkVaapiStatus(vaStatus, "vaQueryImageFormats")) return false; if (vaStatus != VA_STATUS_SUCCESS) { ERROR("query image formats return %d", vaStatus); return false; } vaFormats.resize(num); for (size_t i = 0; i < vaFormats.size(); i++) { const VAImageFormat& fmt = vaFormats[i]; if (fmt.fourcc == VA_FOURCC_BGRX) { format = fmt; return true; } } return false; }
bool VaapiEncoderBase::initVA() { FUNC_ENTER(); if (!m_externalDisplay) m_xDisplay = XOpenDisplay(NULL); if (!m_xDisplay) { ERROR("no x display."); return false; } int majorVersion, minorVersion; VAStatus vaStatus; m_display = vaGetDisplay(m_xDisplay); if (m_display == NULL) { ERROR("vaGetDisplay failed."); goto error; } vaStatus= vaInitialize(m_display, &majorVersion, &minorVersion); DEBUG("vaInitialize \n"); if (!checkVaapiStatus(vaStatus, "vaInitialize")) goto error; DEBUG("profile = %d", m_videoParamCommon.profile); vaStatus = vaCreateConfig(m_display, m_videoParamCommon.profile, m_entrypoint, NULL, 0, &m_config); if (!checkVaapiStatus(vaStatus, "vaCreateConfig ")) goto error; vaStatus = vaCreateContext(m_display, m_config, m_videoParamCommon.resolution.width, m_videoParamCommon.resolution.height, VA_PROGRESSIVE, 0, 0, &m_context); if (!checkVaapiStatus(vaStatus, "vaCreateContext ")) goto error; return true; error: cleanupVA(); return false; }
static bool vaSelectDriver(VADisplay vaDisplay, const std::string& driverName) { VAStatus vaStatus=VA_STATUS_SUCCESS; if (!driverName.empty()) { vaStatus = vaSetDriverName(vaDisplay, const_cast<char*>(driverName.c_str())); } return checkVaapiStatus(vaStatus, "vaSetDriverName"); }
VaapiImage::~VaapiImage() { VAStatus status; status = vaDestroyImage(m_display->getID(), m_image->image_id); if (!checkVaapiStatus(status, "vaDestoryImage()")) return; }
/* Unmaps VA buffer */ void vaapiUnmapBuffer(VADisplay dpy, VABufferID bufId, void **pbuf) { VAStatus status; if (pbuf) *pbuf = NULL; status = vaUnmapBuffer(dpy, bufId); if (!checkVaapiStatus(status, "vaUnmapBuffer()")) return; }
bool VaapiSurface::sync() { VAStatus status; status = vaSyncSurface((VADisplay) m_display->getID(), (VASurfaceID) m_ID); if (!checkVaapiStatus(status, "vaSyncSurface()")) return false; return true; }
VaapiSurface::~VaapiSurface() { VAStatus status; delete m_derivedImage; status = vaDestroySurfaces(m_display->getID(), &m_ID, 1); if (!checkVaapiStatus(status, "vaDestroySurfaces()")) WARNING("failed to destroy surface"); }
bool EglVaapiImage::init() { if (m_inited) { ERROR("do not init twice"); return false; } if (!getVaFormat(m_display, m_format)) return false; VAStatus vaStatus = vaCreateImage(m_display, &m_format, m_width, m_height, &m_image); if (!checkVaapiStatus(vaStatus, "vaCreateImage")) return false; m_inited = true; return true; }
/* Maps VA buffer */ void *vaapiMapBuffer(VADisplay dpy, VABufferID bufId) { VAStatus status; void *data = NULL; status = vaMapBuffer(dpy, bufId, &data); if (!checkVaapiStatus(status, "vaMapBuffer()")) { ERROR("fail to map bufId = %x", bufId); return NULL; } return data; }
bool VaapiDisplay::setRotation(int degree) { VAStatus vaStatus; VADisplayAttribute* attrList = NULL; VADisplayAttribute rotate; int i, numAttributes; rotate.type = VADisplayAttribRotation; rotate.value = VA_ROTATION_NONE; if (degree == 0) //no need to set rotation when degree is zero return true; else if (degree == 90) rotate.value = VA_ROTATION_90; else if (degree == 180) rotate.value = VA_ROTATION_180; else if (degree == 270) rotate.value = VA_ROTATION_270; /* should query before set display attributres */ vaStatus = vaQueryDisplayAttributes(m_vaDisplay, attrList, &numAttributes); if (!checkVaapiStatus(vaStatus, "vaQueryDisplayAttributes") || !attrList) return false; for (i = 0; i < numAttributes; i++) { if (attrList[i].type == VADisplayAttribRotation) break; } if ((i == numAttributes) || !(attrList[i].flags & VA_DISPLAY_ATTRIB_SETTABLE) ) return false; vaStatus = vaSetDisplayAttributes(m_vaDisplay, &rotate, 1); if (!checkVaapiStatus(vaStatus, "vaSetDisplayAttributes")) return false; return true; }
bool EglVaapiImage::blt(const SharedPtr<VideoFrame>& src) { if (!m_inited) { ERROR("call init before blt!"); return false; } if (m_acquired) vaReleaseBufferHandle(m_display, m_image.buf); VAStatus vaStatus = vaGetImage(m_display, (VASurfaceID)src->surface, src->crop.x, src->crop.y, src->crop.width, src->crop.height, m_image.image_id); // incomplete data yet m_frameInfo.timeStamp = src->timeStamp; m_frameInfo.flags = src->flags; return checkVaapiStatus(vaStatus, "vaGetImage"); }
bool EglVaapiImage::blt(const VideoFrameRawData& src) { if (!m_inited) { ERROR("call init before blt!"); return false; } if (m_acquired) vaReleaseBufferHandle(m_display, m_image.buf); VAStatus vaStatus = vaGetImage(m_display, src.internalID, 0, 0, src.width, src.height, m_image.image_id); // incomplete data yet m_frameInfo.timeStamp = src.timeStamp; m_frameInfo.flags = src.flags; return checkVaapiStatus(vaStatus, "vaGetImage"); }
bool VaapiSurface::queryStatus(VaapiSurfaceStatus * pStatus) { VASurfaceStatus surfaceStatus; VAStatus status; if (!pStatus) return false; status = vaQuerySurfaceStatus((VADisplay) m_display->getID(), (VASurfaceID) m_ID, &surfaceStatus); if (!checkVaapiStatus(status, "vaQuerySurfaceStatus()")) return false; *pStatus = (VaapiSurfaceStatus) toVaapiSurfaceStatus(surfaceStatus); return true; }
ImagePtr VaapiImage::derive(const SurfacePtr& surface) { ImagePtr image; if (!surface) return image; DisplayPtr display = surface->getDisplay(); VAImagePtr vaImage(new VAImage); VAStatus status = vaDeriveImage(display->getID(), surface->getID(), vaImage.get()); if (!checkVaapiStatus(status, "vaDeriveImage()")) { return image; } image.reset(new VaapiImage(display, surface, vaImage)); return image; }
VaapiImage *VaapiSurface::getDerivedImage() { VAImage va_image; VAStatus status; if (m_derivedImage) return m_derivedImage; va_image.image_id = VA_INVALID_ID; va_image.buf = VA_INVALID_ID; status = vaDeriveImage(m_display->getID(), m_ID, &va_image); if (!checkVaapiStatus(status, "vaDeriveImage()")) return NULL; m_derivedImage = new VaapiImage(m_display->getID(), &va_image); return m_derivedImage; }
bool VaapiDisplay::setRotation(int degree) { VAStatus vaStatus; VADisplayAttribute rotate; rotate.type = VADisplayAttribRotation; rotate.value = VA_ROTATION_NONE; if (degree == 0) rotate.value = VA_ROTATION_NONE; else if (degree == 90) rotate.value = VA_ROTATION_90; else if (degree == 180) rotate.value = VA_ROTATION_180; else if (degree == 270) rotate.value = VA_ROTATION_270; vaStatus = vaSetDisplayAttributes(m_vaDisplay, &rotate, 1); if (!checkVaapiStatus(vaStatus, "vaSetDisplayAttributes")) return false; return true; }
bool VaapiPicture::renderVaBuffer(VaapiBufObject * &buffer, const char *bufferInfo) { VAStatus status = VA_STATUS_SUCCESS; VABufferID bufferID = VA_INVALID_ID; if (!buffer) return false; bufferID = buffer->getID(); if (bufferID == VA_INVALID_ID) return false; status = vaRenderPicture(m_display, m_context, &bufferID, 1); if (!checkVaapiStatus(status, bufferInfo)) return false; delete buffer; buffer = NULL; return true; }
SurfacePtr VaapiSurface::create(const DisplayPtr& display, VaapiChromaType chromaType, uint32_t width, uint32_t height, void *surfAttribArray, uint32_t surfAttribNum) { VAStatus status; uint32_t format, i; VASurfaceAttrib *surfAttribs = (VASurfaceAttrib *) surfAttribArray; SurfacePtr surface; VASurfaceID id; assert((surfAttribs && surfAttribNum) || (!surfAttribs && !surfAttribNum)); format = vaapiChromaToVaChroma(chromaType); uint32_t externalBufHandle = 0; status = vaCreateSurfaces(display->getID(), format, width, height, &id, 1, surfAttribs, surfAttribNum); if (!checkVaapiStatus(status, "vaCreateSurfacesWithAttribute()")) return surface; for (int i = 0; i < surfAttribNum; i++) { if (surfAttribs[i].type == VASurfaceAttribExternalBufferDescriptor) { VASurfaceAttribExternalBuffers *surfAttribExtBuf = (VASurfaceAttribExternalBuffers *) surfAttribs[i].value. value.p; externalBufHandle = surfAttribExtBuf->buffers[0]; break; } } surface.reset(new VaapiSurface(display, id, chromaType, width, height,externalBufHandle)); return surface; }
bool VaapiPicture::decodePicture() { VAStatus status; uint32_t i; vector < VaapiSlice * >::iterator iter; DEBUG("VaapiPicture::decodePicture 0x%08x", m_surfaceID); status = vaBeginPicture(m_display, m_context, m_surfaceID); if (!checkVaapiStatus(status, "vaBeginPicture()")) return false; if (m_picParam) { if (!renderVaBuffer (m_picParam, "vaRenderPicture(), render pic param")) return false; } if (m_probTable) { if (!renderVaBuffer (m_probTable, "vaRenderPicture(), render probability table")) return false; } if (m_iqMatrix) { if (!renderVaBuffer (m_iqMatrix, "vaRenderPicture(), render IQ matrix")) return false; } if (m_bitPlane) { if (!renderVaBuffer (m_bitPlane, "vaRenderPicture(), render bit plane")) return false; } if (m_hufTable) { if (!renderVaBuffer (m_hufTable, "vaRenderPicture(), render huffman table")) return false; } for (iter = m_sliceArray.begin(); iter != m_sliceArray.end(); ++iter) { VaapiBufObject *paramBuf = (*iter)->m_param; VaapiBufObject *dataBuf = (*iter)->m_data; if (!renderVaBuffer (paramBuf, "vaRenderPicture(), render slice param")) break; if (!renderVaBuffer (dataBuf, "vaRenderPicture(), render slice data")) break; } if (iter != m_sliceArray.end()) { m_sliceArray.clear(); return false; } m_sliceArray.clear(); status = vaEndPicture(m_display, m_context); if (!checkVaapiStatus(status, "vaEndPicture()")) return false; return true; }
VaapiImageRaw::~VaapiImageRaw() { VAImagePtr& image = m_image->m_image; VAStatus status = m_release(m_display->getID(), image->buf); checkVaapiStatus(status, "vaReleaseBufferHandle()"); }
Decode_Status VaapiDecoderBase::setupVA(uint32_t numSurface, VAProfile profile) { INFO("base: setup VA"); uint32_t i; VASurfaceID *surfaces; VideoSurfaceBuffer *buf; VaapiSurface *suf; Decode_Status status; VAStatus vaStatus = VA_STATUS_SUCCESS; if (m_enableNativeBuffersFlag == true) { numSurface = 20; //NATIVE_WINDOW_COUNT; } if (m_VAStarted) { return DECODE_SUCCESS; } if (m_VADisplay != NULL) { WARNING("VA is partially started."); return DECODE_FAIL; } #ifdef ANDROID m_display = new Display; *m_display = ANDROID_DISPLAY_HANDLE; #else if (!m_display) { m_display = XOpenDisplay(NULL); m_ownNativeDisplay = true; } #if __PLATFORM_BYT__ if (setenv("LIBVA_DRIVER_NAME", "wrapper", 1) == 0) { INFO("setting LIBVA_DRIVER_NAME to wrapper for chromeos"); } #endif #endif m_VADisplay = vaGetDisplay(m_display); if (m_VADisplay == NULL) { ERROR("vaGetDisplay failed."); return DECODE_DRIVER_FAIL; } int majorVersion, minorVersion; vaStatus = vaInitialize(m_VADisplay, &majorVersion, &minorVersion); checkVaapiStatus(vaStatus, "vaInitialize"); VAConfigAttrib attrib; attrib.type = VAConfigAttribRTFormat; attrib.value = VA_RT_FORMAT_YUV420; INFO("base:the profile = %d", profile); vaStatus = vaCreateConfig(m_VADisplay, profile, VAEntrypointVLD, &attrib, 1, &m_VAConfig); checkVaapiStatus(vaStatus, "vaCreateConfig"); m_configBuffer.surfaceNumber = numSurface; m_bufPool = new VaapiSurfaceBufferPool(m_VADisplay, &m_configBuffer); surfaces = new VASurfaceID[numSurface]; for (i = 0; i < numSurface; i++) { surfaces[i] = VA_INVALID_SURFACE; buf = m_bufPool->getBufferByIndex(i); suf = m_bufPool->getVaapiSurface(buf); if (suf) surfaces[i] = suf->getID(); } vaStatus = vaCreateContext(m_VADisplay, m_VAConfig, m_videoFormatInfo.width, m_videoFormatInfo.height, 0, surfaces, numSurface, &m_VAContext); checkVaapiStatus(vaStatus, "vaCreateContext"); VADisplayAttribute rotate; rotate.type = VADisplayAttribRotation; rotate.value = VA_ROTATION_NONE; if (m_configBuffer.rotationDegrees == 0) rotate.value = VA_ROTATION_NONE; else if (m_configBuffer.rotationDegrees == 90) rotate.value = VA_ROTATION_90; else if (m_configBuffer.rotationDegrees == 180) rotate.value = VA_ROTATION_180; else if (m_configBuffer.rotationDegrees == 270) rotate.value = VA_ROTATION_270; vaStatus = vaSetDisplayAttributes(m_VADisplay, &rotate, 1); m_videoFormatInfo.surfaceNumber = numSurface; m_videoFormatInfo.ctxSurfaces = surfaces; if (!(m_configBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER)) { m_videoFormatInfo.surfaceWidth = m_videoFormatInfo.width; m_videoFormatInfo.surfaceHeight = m_videoFormatInfo.height; } m_VAStarted = true; return DECODE_SUCCESS; }