| /* |
| * Copyright (c) 2009-2011 Intel Corporation. All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "VideoEncoderLog.h" |
| #include "VideoEncoderUtils.h" |
| #include <va/va_android.h> |
| #include <va/va_drmcommon.h> |
| |
| #ifdef IMG_GFX |
| #include "hal_public.h" |
| #include <sync/sync.h> |
| |
| //#define GFX_DUMP |
| |
| #define OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar 0x7FA00E00 |
| |
| static const hw_device_t *gGralloc; |
| |
| static int gfx_init(void) { |
| |
| int err = gralloc_open_img(&gGralloc); |
| if (err) { |
| LOG_E("FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); |
| return -1; |
| } else |
| LOG_V("hw_get_module returned\n"); |
| |
| return 0; |
| } |
| |
| static int gfx_alloc(uint32_t w, uint32_t h, int format, |
| int usage, buffer_handle_t* handle, int32_t* stride) { |
| |
| int err; |
| |
| if (!gGralloc) { |
| if (gfx_init()) { |
| LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); |
| return -1; |
| } |
| } |
| |
| err = gralloc_device_alloc_img(gGralloc, w, h, format, usage, handle, |
| stride); |
| if (err) { |
| LOG_E("alloc(%u, %u, %d, %08x, ...) failed %d (%s)\n", |
| w, h, format, usage, err, strerror(-err)); |
| } |
| |
| return err; |
| } |
| |
| static int gfx_free(buffer_handle_t handle) { |
| |
| int err; |
| |
| if (!gGralloc) { |
| if (gfx_init()) { |
| LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); |
| return -1; |
| } |
| } |
| |
| err = gralloc_device_free_img(gGralloc, handle); |
| if (err) { |
| LOG_E("free(...) failed %d (%s)\n", err, strerror(-err)); |
| } |
| |
| return err; |
| } |
| |
| static int gfx_lock(buffer_handle_t handle, int usage, |
| int left, int top, int width, int height, void** vaddr) { |
| |
| int err; |
| |
| if (!gGralloc) { |
| if (gfx_init()) { |
| LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); |
| return -1; |
| } |
| } |
| |
| const gralloc1_rect_t r = { |
| .left = left, |
| .top = top, |
| .width = width, |
| .height = height |
| }; |
| |
| err = gralloc_lock_async_img(gGralloc, handle, usage, &r, vaddr, -1); |
| |
| LOG_V("gfx_lock: handle is %x, usage is %x, vaddr is %x.\n", |
| (unsigned int)handle, usage, (unsigned int)*vaddr); |
| |
| if (err) { |
| LOG_E("lock(...) failed %d (%s).\n", err, strerror(-err)); |
| return -1; |
| } else |
| LOG_V("lock returned with address %p\n", *vaddr); |
| |
| return err; |
| } |
| |
| static int gfx_unlock(buffer_handle_t handle) { |
| |
| int err, releaseFence = -1; |
| |
| if (!gGralloc) { |
| if (gfx_init()) { |
| LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); |
| return -1; |
| } |
| } |
| |
| err = gralloc_unlock_async_img(gGralloc, handle, &releaseFence); |
| if (releaseFence >= 0) { |
| sync_wait(releaseFence, -1); |
| close(releaseFence); |
| } |
| if (err) { |
| LOG_E("unlock(...) failed %d (%s)", err, strerror(-err)); |
| return -1; |
| } else |
| LOG_V("unlock returned\n"); |
| |
| return err; |
| } |
| |
| static int gfx_Blit(buffer_handle_t src, buffer_handle_t dest, |
| int w, int h, int , int ) |
| { |
| int err, releaseFence = -1; |
| |
| if (!gGralloc) { |
| if (gfx_init()) { |
| LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); |
| return -1; |
| } |
| } |
| |
| err = gralloc_blit_handle_to_handle_img(gGralloc, src, dest, w, h, 0, 0, |
| 0, -1, &releaseFence); |
| if (releaseFence >= 0) { |
| sync_wait(releaseFence, -1); |
| close(releaseFence); |
| } |
| if (err) { |
| LOG_E("Blit failed %d (%s)", err, strerror(-err)); |
| return -1; |
| } else |
| LOG_V("Blit returned\n"); |
| |
| return err; |
| } |
| |
| Encode_Status GetGfxBufferInfo(intptr_t handle, ValueInfo& vinfo){ |
| |
| /* only support OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar |
| HAL_PIXEL_FORMAT_NV12 |
| HAL_PIXEL_FORMAT_BGRA_8888 |
| HAL_PIXEL_FORMAT_RGBA_8888 |
| HAL_PIXEL_FORMAT_RGBX_8888 |
| HAL_PIXEL_FORMAT_BGRX_8888 */ |
| IMG_native_handle_t* h = (IMG_native_handle_t*) handle; |
| |
| vinfo.width = h->iWidth; |
| vinfo.height = h->iHeight; |
| vinfo.lumaStride = h->iWidth; |
| |
| LOG_V("GetGfxBufferInfo: gfx iWidth=%d, iHeight=%d, iFormat=%x in handle structure\n", h->iWidth, h->iHeight, h->iFormat); |
| |
| if (h->iFormat == HAL_PIXEL_FORMAT_NV12) { |
| #ifdef MRFLD_GFX |
| vinfo.lumaStride = (h->iWidth + 63) & ~63; //64 aligned |
| #else //on CTP |
| if (h->iWidth > 512) |
| vinfo.lumaStride = (h->iWidth + 63) & ~63; //64 aligned |
| else |
| vinfo.lumaStride = 512; |
| #endif |
| } else if ((h->iFormat == HAL_PIXEL_FORMAT_BGRA_8888)|| |
| (h->iFormat == HAL_PIXEL_FORMAT_RGBA_8888)|| |
| (h->iFormat == HAL_PIXEL_FORMAT_RGBX_8888)|| |
| (h->iFormat == HAL_PIXEL_FORMAT_BGRX_8888)) { |
| vinfo.lumaStride = (h->iWidth + 31) & ~31; |
| } else if (h->iFormat == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar) { |
| //nothing to do |
| } else |
| return ENCODE_NOT_SUPPORTED; |
| |
| vinfo.format = h->iFormat; |
| |
| LOG_V("Actual Width=%d, Height=%d, Stride=%d\n\n", vinfo.width, vinfo.height, vinfo.lumaStride); |
| return ENCODE_SUCCESS; |
| } |
| |
| #ifdef GFX_DUMP |
| void DumpGfx(intptr_t handle, char* filename) { |
| ValueInfo vinfo; |
| void* vaddr[3]; |
| FILE* fp; |
| int usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN; |
| |
| GetGfxBufferInfo(handle, vinfo); |
| if (gfx_lock((buffer_handle_t)handle, usage, 0, 0, vinfo.width, vinfo.height, &vaddr[0]) != 0) |
| return ENCODE_DRIVER_FAIL; |
| fp = fopen(filename, "wb"); |
| fwrite(vaddr[0], 1, vinfo.lumaStride * vinfo.height * 4, fp); |
| fclose(fp); |
| LOG_I("dump %d bytes data to %s\n", vinfo.lumaStride * vinfo.height * 4, filename); |
| gfx_unlock((buffer_handle_t)handle); |
| |
| return; |
| } |
| #endif |
| |
| #endif |
| |
| extern "C" { |
| VAStatus vaLockSurface(VADisplay dpy, |
| VASurfaceID surface, |
| unsigned int *fourcc, |
| unsigned int *luma_stride, |
| unsigned int *chroma_u_stride, |
| unsigned int *chroma_v_stride, |
| unsigned int *luma_offset, |
| unsigned int *chroma_u_offset, |
| unsigned int *chroma_v_offset, |
| unsigned int *buffer_name, |
| void **buffer |
| ); |
| |
| VAStatus vaUnlockSurface(VADisplay dpy, |
| VASurfaceID surface |
| ); |
| } |
| |
| VASurfaceMap::VASurfaceMap(VADisplay display, int hwcap) { |
| |
| mVADisplay = display; |
| mSupportedSurfaceMemType = hwcap; |
| mValue = 0; |
| mVASurface = VA_INVALID_SURFACE; |
| mTracked = false; |
| mAction = 0; |
| memset(&mVinfo, 0, sizeof(ValueInfo)); |
| #ifdef IMG_GFX |
| mGfxHandle = NULL; |
| #endif |
| } |
| |
| VASurfaceMap::~VASurfaceMap() { |
| |
| if (!mTracked && (mVASurface != VA_INVALID_SURFACE)) |
| vaDestroySurfaces(mVADisplay, &mVASurface, 1); |
| |
| #ifdef IMG_GFX |
| if (mGfxHandle) |
| gfx_free(mGfxHandle); |
| #endif |
| } |
| |
| Encode_Status VASurfaceMap::doMapping() { |
| |
| Encode_Status ret = ENCODE_SUCCESS; |
| |
| if (mVASurface == VA_INVALID_SURFACE) { |
| |
| int width = mVASurfaceWidth = mVinfo.width; |
| int height = mVASurfaceHeight = mVinfo.height; |
| int stride = mVASurfaceStride = mVinfo.lumaStride; |
| |
| if (mAction & MAP_ACTION_COLORCONVERT) { |
| |
| //only support gfx buffer |
| if (mVinfo.mode != MEM_MODE_GFXHANDLE) |
| return ENCODE_NOT_SUPPORTED; |
| |
| #ifdef IMG_GFX //only enable on IMG chip |
| |
| //do not trust valueinfo for gfx case, directly get from structure |
| ValueInfo tmp; |
| |
| ret = GetGfxBufferInfo(mValue, tmp); |
| CHECK_ENCODE_STATUS_RETURN("GetGfxBufferInfo"); |
| width = tmp.width; |
| height = tmp.height; |
| stride = tmp.lumaStride; |
| |
| if (HAL_PIXEL_FORMAT_NV12 == tmp.format || OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar == tmp.format) |
| mAction &= ~MAP_ACTION_COLORCONVERT; |
| else { |
| //allocate new gfx buffer if format is not NV12 |
| int usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; |
| |
| //use same size with original and HAL_PIXEL_FORMAT_NV12 format |
| if (gfx_alloc(width, height, HAL_PIXEL_FORMAT_NV12, usage, &mGfxHandle, &stride) != 0) |
| return ENCODE_DRIVER_FAIL; |
| |
| LOG_V("Create an new gfx buffer handle 0x%p for color convert, width=%d, height=%d, stride=%d\n", |
| mGfxHandle, width, height, stride); |
| } |
| |
| #else |
| return ENCODE_NOT_SUPPORTED; |
| #endif |
| } |
| |
| if (mAction & MAP_ACTION_ALIGN64 && stride % 64 != 0) { |
| //check if stride is not 64 aligned, must allocate new 64 aligned vasurface |
| stride = (stride + 63 ) & ~63; |
| mAction |= MAP_ACTION_COPY; |
| } |
| |
| if(mAction & MAP_ACTION_ALIGN64 && width <= 320 && height <= 240) { |
| mAction |= MAP_ACTION_COPY; |
| } |
| |
| if (mAction & MAP_ACTION_COPY) { //must allocate new vasurface(EXternalMemoryNULL, uncached) |
| //allocate new vasurface |
| mVASurface = CreateNewVASurface(mVADisplay, stride, height); |
| if (mVASurface == VA_INVALID_SURFACE) |
| return ENCODE_DRIVER_FAIL; |
| mVASurfaceWidth = mVASurfaceStride = stride; |
| mVASurfaceHeight = height; |
| LOGI("create new vaSurface for MAP_ACTION_COPY\n"); |
| } else { |
| #ifdef IMG_GFX |
| if (mGfxHandle != NULL) { |
| //map new gfx handle to vasurface |
| ret = MappingGfxHandle((intptr_t)mGfxHandle); |
| CHECK_ENCODE_STATUS_RETURN("MappingGfxHandle"); |
| LOGV("map new allocated gfx handle to vaSurface\n"); |
| } else |
| #endif |
| { |
| //map original value to vasurface |
| ret = MappingToVASurface(); |
| CHECK_ENCODE_STATUS_RETURN("MappingToVASurface"); |
| } |
| } |
| } |
| |
| if (mAction & MAP_ACTION_COLORCONVERT) { |
| ret = doActionColConv(); |
| CHECK_ENCODE_STATUS_RETURN("doActionColConv"); |
| } |
| |
| if (mAction & MAP_ACTION_COPY) { |
| //keep src color format is NV12, then do copy |
| ret = doActionCopy(); |
| CHECK_ENCODE_STATUS_RETURN("doActionCopy"); |
| } |
| |
| return ENCODE_SUCCESS; |
| } |
| |
| Encode_Status VASurfaceMap::MappingToVASurface() { |
| |
| Encode_Status ret = ENCODE_SUCCESS; |
| |
| if (mVASurface != VA_INVALID_SURFACE) { |
| LOG_I("VASurface is already set before, nothing to do here\n"); |
| return ENCODE_SUCCESS; |
| } |
| LOG_V("MappingToVASurface mode=%d, value=%p\n", mVinfo.mode, (void*)mValue); |
| |
| const char *mode = NULL; |
| switch (mVinfo.mode) { |
| case MEM_MODE_SURFACE: |
| mode = "SURFACE"; |
| ret = MappingSurfaceID(mValue); |
| break; |
| case MEM_MODE_GFXHANDLE: |
| mode = "GFXHANDLE"; |
| ret = MappingGfxHandle(mValue); |
| break; |
| case MEM_MODE_KBUFHANDLE: |
| mode = "KBUFHANDLE"; |
| ret = MappingKbufHandle(mValue); |
| break; |
| case MEM_MODE_MALLOC: |
| case MEM_MODE_NONECACHE_USRPTR: |
| mode = "MALLOC or NONCACHE_USRPTR"; |
| ret = MappingMallocPTR(mValue); |
| break; |
| case MEM_MODE_ION: |
| case MEM_MODE_V4L2: |
| case MEM_MODE_USRPTR: |
| case MEM_MODE_CI: |
| default: |
| LOG_I("UnSupported memory mode 0x%08x", mVinfo.mode); |
| return ENCODE_NOT_SUPPORTED; |
| } |
| |
| LOG_V("%s: Format=%x, lumaStride=%d, width=%d, height=%d\n", mode, mVinfo.format, mVinfo.lumaStride, mVinfo.width, mVinfo.height); |
| LOG_V("vaSurface 0x%08x is created for value = 0x%p\n", mVASurface, (void*)mValue); |
| |
| return ret; |
| } |
| |
| Encode_Status VASurfaceMap::MappingSurfaceID(intptr_t value) { |
| |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| |
| //try to get kbufhandle from SurfaceID |
| uint32_t fourCC = 0; |
| uint32_t lumaStride = 0; |
| uint32_t chromaUStride = 0; |
| uint32_t chromaVStride = 0; |
| uint32_t lumaOffset = 0; |
| uint32_t chromaUOffset = 0; |
| uint32_t chromaVOffset = 0; |
| uint32_t kBufHandle = 0; |
| |
| vaStatus = vaLockSurface( |
| (VADisplay)mVinfo.handle, (VASurfaceID)value, |
| &fourCC, &lumaStride, &chromaUStride, &chromaVStride, |
| &lumaOffset, &chromaUOffset, &chromaVOffset, &kBufHandle, NULL); |
| |
| CHECK_VA_STATUS_RETURN("vaLockSurface"); |
| LOG_V("Surface incoming = 0x%p\n", (void*)value); |
| LOG_V("lumaStride = %d, chromaUStride = %d, chromaVStride=%d\n", lumaStride, chromaUStride, chromaVStride); |
| LOG_V("lumaOffset = %d, chromaUOffset = %d, chromaVOffset = %d\n", lumaOffset, chromaUOffset, chromaVOffset); |
| LOG_V("kBufHandle = 0x%08x, fourCC = %d\n", kBufHandle, fourCC); |
| |
| vaStatus = vaUnlockSurface((VADisplay)mVinfo.handle, (VASurfaceID)value); |
| CHECK_VA_STATUS_RETURN("vaUnlockSurface"); |
| |
| mVinfo.mode = MEM_MODE_KBUFHANDLE; |
| mVinfo.size = mVinfo.lumaStride * mVinfo.height * 1.5; |
| |
| mVASurface = CreateSurfaceFromExternalBuf(kBufHandle, mVinfo); |
| if (mVASurface == VA_INVALID_SURFACE) |
| return ENCODE_INVALID_SURFACE; |
| |
| mVASurfaceWidth = mVinfo.width; |
| mVASurfaceHeight = mVinfo.height; |
| mVASurfaceStride = mVinfo.lumaStride; |
| return ENCODE_SUCCESS; |
| } |
| |
| Encode_Status VASurfaceMap::MappingGfxHandle(intptr_t value) { |
| |
| LOG_V("MappingGfxHandle %p......\n", (void*)value); |
| LOG_V("format = 0x%08x, lumaStride = %d in ValueInfo\n", mVinfo.format, mVinfo.lumaStride); |
| |
| //default value for all HW platforms, maybe not accurate |
| mVASurfaceWidth = mVinfo.width; |
| mVASurfaceHeight = mVinfo.height; |
| mVASurfaceStride = mVinfo.lumaStride; |
| |
| #ifdef IMG_GFX |
| Encode_Status ret; |
| ValueInfo tmp; |
| |
| ret = GetGfxBufferInfo(value, tmp); |
| CHECK_ENCODE_STATUS_RETURN("GetGfxBufferInfo"); |
| mVASurfaceWidth = tmp.width; |
| mVASurfaceHeight = tmp.height; |
| mVASurfaceStride = tmp.lumaStride; |
| #endif |
| |
| LOG_V("Mapping vasurface Width=%d, Height=%d, Stride=%d\n", mVASurfaceWidth, mVASurfaceHeight, mVASurfaceStride); |
| |
| ValueInfo vinfo; |
| memset(&vinfo, 0, sizeof(ValueInfo)); |
| vinfo.mode = MEM_MODE_GFXHANDLE; |
| vinfo.width = mVASurfaceWidth; |
| vinfo.height = mVASurfaceHeight; |
| vinfo.lumaStride = mVASurfaceStride; |
| mVASurface = CreateSurfaceFromExternalBuf(value, vinfo); |
| if (mVASurface == VA_INVALID_SURFACE) |
| return ENCODE_INVALID_SURFACE; |
| |
| return ENCODE_SUCCESS; |
| } |
| |
| Encode_Status VASurfaceMap::MappingKbufHandle(intptr_t value) { |
| |
| LOG_V("MappingKbufHandle value=%p\n", (void*)value); |
| |
| mVinfo.size = mVinfo.lumaStride * mVinfo.height * 1.5; |
| mVASurface = CreateSurfaceFromExternalBuf(value, mVinfo); |
| if (mVASurface == VA_INVALID_SURFACE) |
| return ENCODE_INVALID_SURFACE; |
| |
| mVASurfaceWidth = mVinfo.width; |
| mVASurfaceHeight = mVinfo.height; |
| mVASurfaceStride = mVinfo.lumaStride; |
| |
| return ENCODE_SUCCESS; |
| } |
| |
| Encode_Status VASurfaceMap::MappingMallocPTR(intptr_t value) { |
| |
| mVASurface = CreateSurfaceFromExternalBuf(value, mVinfo); |
| if (mVASurface == VA_INVALID_SURFACE) |
| return ENCODE_INVALID_SURFACE; |
| |
| mVASurfaceWidth = mVinfo.width; |
| mVASurfaceHeight = mVinfo.height; |
| mVASurfaceStride = mVinfo.lumaStride; |
| |
| return ENCODE_SUCCESS; |
| } |
| |
| //always copy with same color format NV12 |
| Encode_Status VASurfaceMap::doActionCopy() { |
| |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| |
| uint32_t width = 0, height = 0, stride = 0; |
| uint8_t *pSrcBuffer, *pDestBuffer; |
| intptr_t handle = 0; |
| |
| LOG_V("Copying Src Buffer data to VASurface\n"); |
| |
| if (mVinfo.mode != MEM_MODE_MALLOC && mVinfo.mode != MEM_MODE_GFXHANDLE) { |
| LOG_E("Not support copy in mode %d", mVinfo.mode); |
| return ENCODE_NOT_SUPPORTED; |
| } |
| |
| LOG_V("Src Buffer information\n"); |
| LOG_V("Mode = %d, width = %d, stride = %d, height = %d\n", |
| mVinfo.mode, mVinfo.width, mVinfo.lumaStride, mVinfo.height); |
| |
| uint32_t srcY_offset, srcUV_offset; |
| uint32_t srcY_pitch, srcUV_pitch; |
| |
| if (mVinfo.mode == MEM_MODE_MALLOC) { |
| width = mVinfo.width; |
| height = mVinfo.height; |
| stride = mVinfo.lumaStride; |
| pSrcBuffer = (uint8_t*) mValue; |
| srcY_offset = 0; |
| srcUV_offset = stride * height; |
| srcY_pitch = stride; |
| srcUV_pitch = stride; |
| } else { |
| |
| #ifdef IMG_GFX //only enable on IMG chips |
| int usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN; |
| |
| //do not trust valueinfo, directly get from structure |
| Encode_Status ret; |
| ValueInfo tmp; |
| |
| if (mGfxHandle) |
| handle = (intptr_t) mGfxHandle; |
| else |
| handle = mValue; |
| |
| ret = GetGfxBufferInfo(handle, tmp); |
| CHECK_ENCODE_STATUS_RETURN("GetGfxBufferInfo"); |
| width = tmp.width; |
| height = tmp.height; |
| stride = tmp.lumaStride; |
| |
| //only support HAL_PIXEL_FORMAT_NV12 & OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar |
| if (HAL_PIXEL_FORMAT_NV12 != tmp.format && OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar != tmp.format) { |
| LOG_E("Not support gfx buffer format %x", tmp.format); |
| return ENCODE_NOT_SUPPORTED; |
| } |
| |
| srcY_offset = 0; |
| srcUV_offset = stride * height; |
| srcY_pitch = stride; |
| srcUV_pitch = stride; |
| |
| //lock gfx handle with buffer real size |
| void* vaddr[3]; |
| if (gfx_lock((buffer_handle_t) handle, usage, 0, 0, width, height, &vaddr[0]) != 0) |
| return ENCODE_DRIVER_FAIL; |
| pSrcBuffer = (uint8_t*)vaddr[0]; |
| #else |
| |
| return ENCODE_NOT_SUPPORTED; |
| #endif |
| } |
| |
| |
| VAImage destImage; |
| vaStatus = vaDeriveImage(mVADisplay, mVASurface, &destImage); |
| CHECK_VA_STATUS_RETURN("vaDeriveImage"); |
| vaStatus = vaMapBuffer(mVADisplay, destImage.buf, (void **)&pDestBuffer); |
| CHECK_VA_STATUS_RETURN("vaMapBuffer"); |
| |
| LOG_V("\nDest VASurface information\n"); |
| LOG_V("pitches[0] = %d\n", destImage.pitches[0]); |
| LOG_V("pitches[1] = %d\n", destImage.pitches[1]); |
| LOG_V("offsets[0] = %d\n", destImage.offsets[0]); |
| LOG_V("offsets[1] = %d\n", destImage.offsets[1]); |
| LOG_V("num_planes = %d\n", destImage.num_planes); |
| LOG_V("width = %d\n", destImage.width); |
| LOG_V("height = %d\n", destImage.height); |
| |
| if (width > destImage.width || height > destImage.height) { |
| LOG_E("src buffer is bigger than destination buffer\n"); |
| return ENCODE_INVALID_PARAMS; |
| } |
| |
| uint8_t *srcY, *dstY; |
| uint8_t *srcUV, *dstUV; |
| |
| srcY = pSrcBuffer + srcY_offset; |
| dstY = pDestBuffer + destImage.offsets[0]; |
| srcUV = pSrcBuffer + srcUV_offset; |
| dstUV = pDestBuffer + destImage.offsets[1]; |
| |
| for (uint32_t i = 0; i < height; i++) { |
| memcpy(dstY, srcY, width); |
| srcY += srcY_pitch; |
| dstY += destImage.pitches[0]; |
| } |
| |
| for (uint32_t i = 0; i < height / 2; i++) { |
| memcpy(dstUV, srcUV, width); |
| srcUV += srcUV_pitch; |
| dstUV += destImage.pitches[1]; |
| } |
| |
| vaStatus = vaUnmapBuffer(mVADisplay, destImage.buf); |
| CHECK_VA_STATUS_RETURN("vaUnmapBuffer"); |
| vaStatus = vaDestroyImage(mVADisplay, destImage.image_id); |
| CHECK_VA_STATUS_RETURN("vaDestroyImage"); |
| |
| #ifdef IMG_GFX |
| if (mVinfo.mode == MEM_MODE_GFXHANDLE) { |
| //unlock gfx handle |
| gfx_unlock((buffer_handle_t) handle); |
| } |
| #endif |
| LOG_V("Copying Src Buffer data to VASurface Complete\n"); |
| |
| return ENCODE_SUCCESS; |
| } |
| |
| Encode_Status VASurfaceMap::doActionColConv() { |
| |
| #ifdef IMG_GFX |
| if (mGfxHandle == NULL) { |
| LOG_E("something wrong, why new gfxhandle is not allocated? \n"); |
| return ENCODE_FAIL; |
| } |
| |
| LOG_V("doActionColConv gfx_Blit width=%d, height=%d\n", mVinfo.width, mVinfo.height); |
| if (gfx_Blit((buffer_handle_t)mValue, mGfxHandle, |
| mVinfo.width, mVinfo.height, 0, 0) != 0) |
| return ENCODE_DRIVER_FAIL; |
| |
| #ifdef GFX_DUMP |
| LOG_I("dumpping gfx data.....\n"); |
| DumpGfx(mValue, "/data/dump.rgb"); |
| DumpGfx((intptr_t)mGfxHandle, "/data/dump.yuv"); |
| #endif |
| return ENCODE_SUCCESS; |
| |
| #else |
| return ENCODE_NOT_SUPPORTED; |
| #endif |
| } |
| |
| VASurfaceID VASurfaceMap::CreateSurfaceFromExternalBuf(intptr_t value, ValueInfo& vinfo) { |
| |
| VAStatus vaStatus; |
| VASurfaceAttribExternalBuffers extbuf; |
| VASurfaceAttrib attribs[2]; |
| VASurfaceID surface = VA_INVALID_SURFACE; |
| int type; |
| unsigned long data = value; |
| |
| extbuf.pixel_format = VA_FOURCC_NV12; |
| extbuf.width = vinfo.width; |
| extbuf.height = vinfo.height; |
| extbuf.data_size = vinfo.size; |
| if (extbuf.data_size == 0) |
| extbuf.data_size = vinfo.lumaStride * vinfo.height * 1.5; |
| extbuf.num_buffers = 1; |
| extbuf.num_planes = 3; |
| extbuf.pitches[0] = vinfo.lumaStride; |
| extbuf.pitches[1] = vinfo.lumaStride; |
| extbuf.pitches[2] = vinfo.lumaStride; |
| extbuf.pitches[3] = 0; |
| extbuf.offsets[0] = 0; |
| extbuf.offsets[1] = vinfo.lumaStride * vinfo.height; |
| extbuf.offsets[2] = extbuf.offsets[1]; |
| extbuf.offsets[3] = 0; |
| extbuf.buffers = &data; |
| extbuf.flags = 0; |
| extbuf.private_data = NULL; |
| |
| switch(vinfo.mode) { |
| case MEM_MODE_GFXHANDLE: |
| type = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC; |
| break; |
| case MEM_MODE_KBUFHANDLE: |
| type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM; |
| break; |
| case MEM_MODE_MALLOC: |
| type = VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR; |
| break; |
| case MEM_MODE_NONECACHE_USRPTR: |
| type = VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR; |
| extbuf.flags |= VA_SURFACE_EXTBUF_DESC_UNCACHED; |
| break; |
| case MEM_MODE_SURFACE: |
| case MEM_MODE_ION: |
| case MEM_MODE_V4L2: |
| case MEM_MODE_USRPTR: |
| case MEM_MODE_CI: |
| default: |
| //not support |
| return VA_INVALID_SURFACE; |
| } |
| |
| if (!(mSupportedSurfaceMemType & type)) |
| return VA_INVALID_SURFACE; |
| |
| attribs[0].type = (VASurfaceAttribType)VASurfaceAttribMemoryType; |
| attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE; |
| attribs[0].value.type = VAGenericValueTypeInteger; |
| attribs[0].value.value.i = type; |
| |
| attribs[1].type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor; |
| attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE; |
| attribs[1].value.type = VAGenericValueTypePointer; |
| attribs[1].value.value.p = (void *)&extbuf; |
| |
| vaStatus = vaCreateSurfaces(mVADisplay, VA_RT_FORMAT_YUV420, vinfo.width, |
| vinfo.height, &surface, 1, attribs, 2); |
| if (vaStatus != VA_STATUS_SUCCESS){ |
| LOG_E("vaCreateSurfaces failed. vaStatus = %d\n", vaStatus); |
| surface = VA_INVALID_SURFACE; |
| } |
| return surface; |
| } |
| |
| VASurfaceID CreateNewVASurface(VADisplay display, int32_t width, int32_t height) { |
| |
| VAStatus vaStatus; |
| VASurfaceID surface = VA_INVALID_SURFACE; |
| VASurfaceAttrib attribs[2]; |
| VASurfaceAttribExternalBuffers extbuf; |
| unsigned long data; |
| |
| extbuf.pixel_format = VA_FOURCC_NV12; |
| extbuf.width = width; |
| extbuf.height = height; |
| extbuf.data_size = width * height * 3 / 2; |
| extbuf.num_buffers = 1; |
| extbuf.num_planes = 3; |
| extbuf.pitches[0] = width; |
| extbuf.pitches[1] = width; |
| extbuf.pitches[2] = width; |
| extbuf.pitches[3] = 0; |
| extbuf.offsets[0] = 0; |
| extbuf.offsets[1] = width * height; |
| extbuf.offsets[2] = extbuf.offsets[1]; |
| extbuf.offsets[3] = 0; |
| extbuf.buffers = &data; |
| extbuf.flags = 0; |
| extbuf.private_data = NULL; |
| |
| attribs[0].type = (VASurfaceAttribType)VASurfaceAttribMemoryType; |
| attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE; |
| attribs[0].value.type = VAGenericValueTypeInteger; |
| attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA; |
| |
| attribs[1].type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor; |
| attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE; |
| attribs[1].value.type = VAGenericValueTypePointer; |
| attribs[1].value.value.p = (void *)&extbuf; |
| |
| vaStatus = vaCreateSurfaces(display, VA_RT_FORMAT_YUV420, width, |
| height, &surface, 1, attribs, 2); |
| if (vaStatus != VA_STATUS_SUCCESS) |
| LOG_E("vaCreateSurfaces failed. vaStatus = %d\n", vaStatus); |
| |
| return surface; |
| } |