blob: 917e8da1be3360256306561905e1deef7ecd5416 [file] [log] [blame]
#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>
//#define GFX_DUMP
#define OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar 0x7FA00E00
static hw_module_t const *gModule = NULL;
static gralloc_module_t *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 *)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 x, int y)
{
int err;
if (!gAllocMod) {
if (gfx_init()) {
LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
return -1;
}
}
IMG_gralloc_module_public_t* GrallocMod = (IMG_gralloc_module_public_t*)gModule;
#ifdef MRFLD_GFX
err = GrallocMod->Blit(GrallocMod, src, dest, w, h, 0, 0, 0);
#else
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(int32_t handle, ValueInfo& vinfo){
/* only support OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar
HAL_PIXEL_FORMAT_NV12
HAL_PIXEL_FORMAT_BGRA_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_I("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 + 31) & ~31; //32 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_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_I(" Actual Width=%d, Height=%d, Stride=%d\n\n", vinfo.width, vinfo.height, vinfo.lumaStride);
return ENCODE_SUCCESS;
}
#ifdef GFX_DUMP
void DumpGfx(int32_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_I("Create an new gfx buffer handle 0x%08x for color convert, width=%d, height=%d, stride=%d\n",
(unsigned int)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_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((int32_t)mGfxHandle);
CHECK_ENCODE_STATUS_RETURN("MappingGfxHandle");
LOGI("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_I("MappingToVASurface mode=%d, value=%x\n", mVinfo.mode, 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_I("%s: Format=%x, lumaStride=%d, width=%d, height=%d\n", mode, mVinfo.format, mVinfo.lumaStride, mVinfo.width, mVinfo.height);
LOG_I("vaSurface 0x%08x is created for value = 0x%08x", mVASurface, mValue);
return ret;
}
Encode_Status VASurfaceMap::MappingSurfaceID(int32_t value) {
VAStatus vaStatus = VA_STATUS_SUCCESS;
VASurfaceID surface;
//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_I("Surface incoming = 0x%08x\n", value);
LOG_I("lumaStride = %d, chromaUStride = %d, chromaVStride=%d\n", lumaStride, chromaUStride, chromaVStride);
LOG_I("lumaOffset = %d, chromaUOffset = %d, chromaVOffset = %d\n", lumaOffset, chromaUOffset, chromaVOffset);
LOG_I("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_DRIVER_FAIL;
mVASurfaceWidth = mVinfo.width;
mVASurfaceHeight = mVinfo.height;
mVASurfaceStride = mVinfo.lumaStride;
return ENCODE_SUCCESS;
}
Encode_Status VASurfaceMap::MappingGfxHandle(int32_t value) {
LOG_I("MappingGfxHandle %x......\n", value);
LOG_I("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_I("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_DRIVER_FAIL;
return ENCODE_SUCCESS;
}
Encode_Status VASurfaceMap::MappingKbufHandle(int32_t value) {
LOG_I("MappingKbufHandle value=%d\n", value);
mVinfo.size = mVinfo.lumaStride * mVinfo.height * 1.5;
mVASurface = CreateSurfaceFromExternalBuf(value, mVinfo);
if (mVASurface == VA_INVALID_SURFACE)
return ENCODE_DRIVER_FAIL;
mVASurfaceWidth = mVinfo.width;
mVASurfaceHeight = mVinfo.height;
mVASurfaceStride = mVinfo.lumaStride;
return ENCODE_SUCCESS;
}
Encode_Status VASurfaceMap::MappingMallocPTR(int32_t value) {
mVASurface = CreateSurfaceFromExternalBuf(value, mVinfo);
if (mVASurface == VA_INVALID_SURFACE)
return ENCODE_DRIVER_FAIL;
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;
int32_t handle = 0;
LOG_I("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_I("Src Buffer information\n");
LOG_I("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 = (int32_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_I("\nDest VASurface information\n");
LOG_I("pitches[0] = %d\n", destImage.pitches[0]);
LOG_I("pitches[1] = %d\n", destImage.pitches[1]);
LOG_I("offsets[0] = %d\n", destImage.offsets[0]);
LOG_I("offsets[1] = %d\n", destImage.offsets[1]);
LOG_I("num_planes = %d\n", destImage.num_planes);
LOG_I("width = %d\n", destImage.width);
LOG_I("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 *srcU, *srcV;
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_I("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_I("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((int32_t)mGfxHandle, "/data/dump.yuv");
#endif
return ENCODE_SUCCESS;
#else
return ENCODE_NOT_SUPPORTED;
#endif
}
VASurfaceID VASurfaceMap::CreateSurfaceFromExternalBuf(int32_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);
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;
}