blob: 09d2f927027510fce172a065da4fd67696514a40 [file] [log] [blame]
//#define LOG_NDEBUG 0
#define LOG_TAG "VideoVPPBase"
#include "VideoVPPBase.h"
#define NATIVE_DISPLAY 0x18c34078
#define CHECK_VA_STATUS(FUNC) \
if (vret != VA_STATUS_SUCCESS) {\
LOGE("[%d] " FUNC" failed with 0x%x\n", __LINE__, vret);\
return vret;\
}
VPParameters::VPParameters(VideoVPPBase *vvb) {
va_display = vvb->va_display;
va_context = vvb->va_context;
vret = init();
if (vret != VA_STATUS_SUCCESS)
mInitialized = false;
else
mInitialized = true;
}
VPParameters* VPParameters::create(VideoVPPBase *vvb) {
VPParameters* v = new VPParameters(vvb);
if (v->mInitialized)
return v;
else
return NULL;
}
VAStatus VPParameters::init() {
num_supported_filters = VAProcFilterCount;
vret = vaQueryVideoProcFilters(va_display,
va_context, supported_filters,
&num_supported_filters);
CHECK_VA_STATUS("vaQueryVideoProcFilters");
for (size_t i = 0; i < num_supported_filters; i++) {
switch(supported_filters[i]) {
case VAProcFilterNoiseReduction:
num_denoise_caps = 1;
vret = vaQueryVideoProcFilterCaps(va_display, va_context,
VAProcFilterNoiseReduction, &denoise_caps, &num_denoise_caps);
CHECK_VA_STATUS("vaQueryVideoProcFilterCaps");
nr.valid = true;
nr.min = denoise_caps.range.min_value;
nr.max = denoise_caps.range.max_value;
nr.def = denoise_caps.range.default_value;
nr.step = denoise_caps.range.step;
nr.cur = 0.0;
break;
case VAProcFilterSharpening:
num_sharpen_caps = 1;
vret = vaQueryVideoProcFilterCaps(va_display, va_context,
VAProcFilterSharpening, &sharpen_caps, &num_sharpen_caps);
CHECK_VA_STATUS("vaQueryVideoProcFilterCaps");
sharpen.valid = true;
sharpen.min = sharpen_caps.range.min_value;
sharpen.max = sharpen_caps.range.max_value;
sharpen.def = sharpen_caps.range.default_value;
sharpen.step = sharpen_caps.range.step;
sharpen.cur = 0.0;
break;
case VAProcFilterDeblocking:
num_denoise_caps = 1;
vret = vaQueryVideoProcFilterCaps(va_display, va_context,
VAProcFilterDeblocking, &deblock_caps, &num_deblock_caps);
CHECK_VA_STATUS("vaQueryVideoProcFilterCaps");
deblock.valid = true;
deblock.min = deblock_caps.range.min_value;
deblock.max = deblock_caps.range.max_value;
deblock.def = deblock_caps.range.default_value;
deblock.step = deblock_caps.range.step;
deblock.cur = 0.0;
break;
case VAProcFilterColorBalance:
num_color_balance_caps = VAProcColorBalanceCount;
vret = vaQueryVideoProcFilterCaps(va_display, va_context,
VAProcFilterColorBalance, &color_balance_caps, &num_color_balance_caps);
CHECK_VA_STATUS("vaQueryVideoProcFilterCaps");
for (size_t i = 0; i< num_color_balance_caps; i++) {
colorbalance[i].type = color_balance_caps[i].type;
colorbalance[i].valid = true;
colorbalance[i].min = color_balance_caps[i].range.min_value;
colorbalance[i].max = color_balance_caps[i].range.max_value;
colorbalance[i].def = color_balance_caps[i].range.default_value;
colorbalance[i].step = color_balance_caps[i].range.step;
colorbalance[i].cur = 0.0;
}
break;
default:
break;
}
}
vret = reset(true);
CHECK_VA_STATUS("reset");
return vret;
}
VAStatus VPParameters::buildfilters() {
for (size_t i = 0; i < num_supported_filters; i++) {
switch (supported_filters[i]) {
case VAProcFilterNoiseReduction:
if (nr.cur != -1) {
denoise_buf.type = VAProcFilterNoiseReduction;
denoise_buf.value = nr.min + nr.cur * nr.step;
vret = vaCreateBuffer(va_display, va_context,
VAProcFilterParameterBufferType,
sizeof(denoise_buf), 1, &denoise_buf, &denoise_buf_id);
CHECK_VA_STATUS("vaCreateBuffer");
filter_bufs[num_filter_bufs] = denoise_buf_id;
num_filter_bufs++;
}
break;
case VAProcFilterDeblocking:
if (deblock.cur != -1) {
deblock_buf.type = VAProcFilterDeblocking;
deblock_buf.value = deblock.min + deblock.cur * deblock.step;
vret = vaCreateBuffer(va_display, va_context,
VAProcFilterParameterBufferType,
sizeof(deblock_buf), 1, &deblock_buf, &deblock_buf_id);
CHECK_VA_STATUS("vaCreateBuffer");
filter_bufs[num_filter_bufs] = deblock_buf_id;
num_filter_bufs++;
}
break;
case VAProcFilterSharpening:
if (sharpen.cur != -1) {
sharpen_buf.type = VAProcFilterSharpening;
sharpen_buf.value = sharpen.cur;
vret = vaCreateBuffer(va_display, va_context,
VAProcFilterParameterBufferType,
sizeof(sharpen_buf), 1, &sharpen_buf, &sharpen_buf_id);
CHECK_VA_STATUS("vaCreateBuffer");
filter_bufs[num_filter_bufs] = sharpen_buf_id;
num_filter_bufs++;
}
break;
case VAProcFilterColorBalance:
break;
default:
break;
}
}
return vret;
}
VAStatus VPParameters::reset(bool start) {
for (size_t i = 0; i < VAProcFilterCount; i++) {
if (start) {
filter_bufs[i] = VA_INVALID_ID;
} else {
if (filter_bufs[i] != VA_INVALID_ID) {
vret = vaDestroyBuffer(va_display, filter_bufs[i]);
CHECK_VA_STATUS("vaDestroyBuffer");
filter_bufs[i] = VA_INVALID_ID;
}
}
}
num_filter_bufs = 0;
sharpen_buf_id = denoise_buf_id = deblock_buf_id = balance_buf_id = VA_INVALID_ID;
memset(&deblock_buf, 0, sizeof(VAProcFilterParameterBuffer));
memset(&sharpen_buf, 0, sizeof(VAProcFilterParameterBuffer));
memset(&denoise_buf, 0, sizeof(VAProcFilterParameterBuffer));
memset(&balance_buf, 0,
sizeof(VAProcFilterParameterBufferColorBalance)* VAProcColorBalanceCount);
nr.cur = deblock.cur = sharpen.cur = -1;
for (size_t i = 0; i < VAProcColorBalanceCount; i++)
colorbalance[i].cur = -1;
return vret;
}
VPParameters::~VPParameters() {
reset(false);
}
VideoVPPBase::VideoVPPBase()
: mInitialized(false),
width(1280),
height(720),
va_display(NULL),
va_config(VA_INVALID_ID),
va_context(VA_INVALID_ID),
vpp_pipeline_buf(VA_INVALID_ID),
SrcSurf(VA_INVALID_SURFACE),
DstSurf(VA_INVALID_SURFACE) {
}
VAStatus VideoVPPBase::start() {
if (mInitialized)
return VA_STATUS_SUCCESS;
int va_major_version, va_minor_version;
unsigned int nativeDisplay = NATIVE_DISPLAY;
VAConfigAttrib vaAttrib;
va_display = vaGetDisplay(&nativeDisplay);
vret = vaInitialize(va_display, &va_major_version, &va_minor_version);
CHECK_VA_STATUS("vaInitialize");
vaAttrib.type = VAConfigAttribRTFormat;
vaAttrib.value = VA_RT_FORMAT_YUV420;
vret = vaCreateConfig(va_display, VAProfileNone,
VAEntrypointVideoProc, &vaAttrib, 1, &va_config);
CHECK_VA_STATUS("vaCreateConfig");
vret = vaCreateContext(va_display, va_config, width,
height, 0, NULL, 0, &va_context);
CHECK_VA_STATUS("vaCreateContext");
mInitialized = true;
return vret;
}
VAStatus VideoVPPBase::stop() {
if (!mInitialized)
return VA_STATUS_SUCCESS;
int c = SrcSurfHandleMap.size();
for (int i = 0; i < c; i++) {
SrcSurf = SrcSurfHandleMap.valueAt(i);
if (SrcSurf != VA_INVALID_SURFACE) {
vret = vaDestroySurfaces(va_display, &SrcSurf, 1);
CHECK_VA_STATUS("vaDestroySurfaces");
}
LOGV("remove src surf %x\n", SrcSurf);
}
SrcSurfHandleMap.clear();
c = DstSurfHandleMap.size();
for (int i = 0; i < c; i++) {
DstSurf = DstSurfHandleMap.valueAt(i);
if (DstSurf != VA_INVALID_SURFACE) {
vret = vaDestroySurfaces(va_display, &DstSurf, 1);
CHECK_VA_STATUS("vaDestroySurfaces");
}
LOGV("remove dst surf %x\n", DstSurf);
}
DstSurfHandleMap.clear();
if (vpp_pipeline_buf != VA_INVALID_ID) {
vret = vaDestroyBuffer(va_display, vpp_pipeline_buf);
CHECK_VA_STATUS("vaDestroyBuffer");
vpp_pipeline_buf = VA_INVALID_ID;
}
if (va_context != VA_INVALID_ID) {
vret = vaDestroyContext(va_display, va_context);
CHECK_VA_STATUS("vaDestroyContext");
va_context = VA_INVALID_ID;
}
if (va_config != VA_INVALID_ID) {
vret = vaDestroyConfig(va_display, va_config);
CHECK_VA_STATUS("vaDestroyConfig");
va_config = VA_INVALID_ID;
}
if (va_display != NULL) {
vret = vaTerminate(va_display);
CHECK_VA_STATUS("vaTerminate");
va_display = NULL;
}
mInitialized = false;
return vret;
}
VAStatus VideoVPPBase::_CreateSurfaceFromGrallocHandle(RenderTarget rt, VASurfaceID *surf) {
unsigned int buffer;
VASurfaceAttrib SurfAttrib;
VASurfaceAttribExternalBuffers SurfExtBuf;
SurfExtBuf.pixel_format = rt.pixel_format;
SurfExtBuf.width = rt.width;
SurfExtBuf.height = rt.height;
SurfExtBuf.pitches[0] = rt.stride;
buffer = rt.handle;
SurfExtBuf.buffers = (unsigned long*)&buffer;
SurfExtBuf.num_buffers = 1;
if (rt.type == RenderTarget::KERNEL_DRM)
SurfExtBuf.flags = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM;
else
SurfExtBuf.flags = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC;
SurfAttrib.type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor;
SurfAttrib.flags = VA_SURFACE_ATTRIB_SETTABLE;
SurfAttrib.value.type = VAGenericValueTypePointer;
SurfAttrib.value.value.p = &SurfExtBuf;
vret = vaCreateSurfaces(va_display, rt.format,
rt.width, rt.height, surf, 1,
&SurfAttrib, 1);
CHECK_VA_STATUS("vaCreateSurfaces");
return vret;
}
VAStatus VideoVPPBase::_perform(VASurfaceID SrcSurf, VARectangle SrcRect,
VASurfaceID DstSurf, VARectangle DstRect, bool no_wait) {
vpp_param.surface = SrcSurf;
vpp_param.output_region = &DstRect;
vpp_param.surface_region = &SrcRect;
vpp_param.surface_color_standard = VAProcColorStandardBT601;
vpp_param.output_background_color = 0;
vpp_param.output_color_standard = VAProcColorStandardBT601;
vpp_param.filter_flags = VA_FRAME_PICTURE;
vpp_param.filters = filter_bufs;
vpp_param.num_filters = num_filter_bufs;
vpp_param.forward_references = NULL;
vpp_param.num_forward_references = 0;
vpp_param.backward_references = NULL;
vpp_param.num_backward_references = 0;
vpp_param.blend_state = NULL;
vpp_param.rotation_state = VA_ROTATION_NONE;
vpp_param.mirror_state = VA_MIRROR_NONE;
vret = vaCreateBuffer(va_display, va_context,
VAProcPipelineParameterBufferType,
sizeof(VAProcPipelineParameterBuffer),
1, &vpp_param, &vpp_pipeline_buf);
CHECK_VA_STATUS("vaCreateBuffer");
vret = vaBeginPicture(va_display, va_context, DstSurf);
CHECK_VA_STATUS("vaBeginPicture");
vret = vaRenderPicture(va_display, va_context, &vpp_pipeline_buf, 1);
CHECK_VA_STATUS("vaRenderPicture");
vret = vaEndPicture(va_display, va_context);
CHECK_VA_STATUS("vaEndPicture");
if (!no_wait) {
vret = vaSyncSurface(va_display, DstSurf);
CHECK_VA_STATUS("vaSyncSurface");
}
vret = vaDestroyBuffer(va_display, vpp_pipeline_buf);
CHECK_VA_STATUS("vaDestroyBuffer");
vpp_pipeline_buf = VA_INVALID_ID;
return vret;
}
VAStatus VideoVPPBase::perform(RenderTarget Src, RenderTarget Dst, VPParameters *vpp, bool no_wait) {
if (!mInitialized) {
vret = start();
CHECK_VA_STATUS("start");
}
ssize_t i = SrcSurfHandleMap.indexOfKey(Src.handle);
if (i >= 0) {
SrcSurf = SrcSurfHandleMap.valueAt(i);
} else {
vret = _CreateSurfaceFromGrallocHandle(Src, &SrcSurf);
CHECK_VA_STATUS("_CreateSurfaceFromGrallocHandle");
SrcSurfHandleMap.add(Src.handle, SrcSurf);
LOGV("add src surface %x\n", SrcSurf);
}
i = DstSurfHandleMap.indexOfKey(Dst.handle);
if (i >= 0) {
DstSurf = DstSurfHandleMap.valueAt(i);
} else {
vret = _CreateSurfaceFromGrallocHandle(Dst, &DstSurf);
CHECK_VA_STATUS("_CreateSurfaceFromGrallocHandle");
DstSurfHandleMap.add(Dst.handle, DstSurf);
LOGV("add dst surface %x\n", DstSurf);
}
if (vpp != NULL && (vpp->num_filter_bufs > 0 && vpp->num_filter_bufs < VAProcFilterCount)) {
memcpy(filter_bufs, vpp->filter_bufs, sizeof(VABufferID) * vpp->num_filter_bufs);
num_filter_bufs = vpp->num_filter_bufs;
} else {
num_filter_bufs = 0;
}
vret = _perform(SrcSurf, Src.rect, DstSurf, Dst.rect, no_wait);
CHECK_VA_STATUS("_perform");
return vret;
}
VideoVPPBase::~VideoVPPBase() {
stop();
}