815 lines
25 KiB
C++
815 lines
25 KiB
C++
/*
|
|
* 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/hal_public.h>
|
|
#include <hardware/gralloc.h>
|
|
#include <sync/sync.h>
|
|
|
|
//#define GFX_DUMP
|
|
|
|
#define OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar 0x7FA00E00
|
|
|
|
static hw_module_t const *gModule = NULL;
|
|
static gralloc_module_t const *gAllocMod = NULL; /* get by force hw_module_t */
|
|
static alloc_device_t *gAllocDev = NULL;
|
|
|
|
static int gfx_init(void) {
|
|
|
|
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &gModule);
|
|
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");
|
|
gAllocMod = (gralloc_module_t const *)gModule;
|
|
|
|
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 (!gAllocDev) {
|
|
if (!gModule) {
|
|
if (gfx_init()) {
|
|
LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
err = gralloc_open(gModule, &gAllocDev);
|
|
if (err) {
|
|
LOG_E("FATAL: gralloc open failed\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
err = gAllocDev->alloc(gAllocDev, 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 (!gAllocDev) {
|
|
if (!gModule) {
|
|
if (gfx_init()) {
|
|
LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
err = gralloc_open(gModule, &gAllocDev);
|
|
if (err) {
|
|
LOG_E("FATAL: gralloc open failed\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
err = gAllocDev->free(gAllocDev, 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 (!gAllocMod) {
|
|
if (gfx_init()) {
|
|
LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
err = gAllocMod->lock(gAllocMod, handle, usage,
|
|
left, top, width, height, vaddr);
|
|
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;
|
|
|
|
if (!gAllocMod) {
|
|
if (gfx_init()) {
|
|
LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
err = gAllocMod->unlock(gAllocMod, handle);
|
|
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;
|
|
|
|
if (!gAllocMod) {
|
|
if (gfx_init()) {
|
|
LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
#ifdef MRFLD_GFX
|
|
#ifdef ASUS_ZENFONE2_LP_BLOBS
|
|
IMG_gralloc_module_public_t* GrallocMod = (IMG_gralloc_module_public_t*)gModule;
|
|
err = GrallocMod->Blit(GrallocMod, src, dest, w, h, 0, 0, 0, 0);
|
|
#else
|
|
{
|
|
int fenceFd;
|
|
err = gAllocMod->perform(gAllocMod, GRALLOC_MODULE_BLIT_HANDLE_TO_HANDLE_IMG, src, dest, w, h, 0, 0, 0, -1, &fenceFd);
|
|
if (!err) {
|
|
sync_wait(fenceFd, -1);
|
|
close(fenceFd);
|
|
}
|
|
}
|
|
#endif
|
|
#else
|
|
IMG_gralloc_module_public_t* GrallocMod = (IMG_gralloc_module_public_t*)gModule;
|
|
err = GrallocMod->Blit2(GrallocMod, src, dest, w, h, 0, 0);
|
|
#endif
|
|
|
|
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;
|
|
}
|