/*
|
* xcam_handle.cpp - xcam handle implementation
|
*
|
* Copyright (c) 2017 Intel Corporation
|
*
|
* 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.
|
*
|
* Author: Wind Yuan <feng.yuan@intel.com>
|
*/
|
|
#include <xcam_utils.h>
|
#include <xcam_handle.h>
|
#include <dma_video_buffer.h>
|
#include "context_priv.h"
|
#include <stdarg.h>
|
#if HAVE_LIBDRM
|
#include <drm_bo_buffer.h>
|
#endif
|
|
using namespace XCam;
|
|
XCamHandle *
|
xcam_create_handle (const char *name)
|
{
|
ContextBase *context = NULL;
|
|
if (handle_name_equal (name, HandleType3DNR)) {
|
context = new NR3DContext;
|
} else if (handle_name_equal (name, HandleTypeWaveletNR)) {
|
context = new NRWaveletContext;
|
} else if (handle_name_equal (name, HandleTypeFisheye)) {
|
context = new FisheyeContext;
|
} else if (handle_name_equal (name, HandleTypeDefog)) {
|
context = new DefogContext;
|
} else if (handle_name_equal (name, HandleTypeDVS)) {
|
context = new DVSContext;
|
} else if (handle_name_equal (name, HandleTypeStitch)) {
|
context = new StitchContext;
|
} else {
|
XCAM_LOG_ERROR ("create handle failed with unsupported type:%s", name);
|
return NULL;
|
}
|
|
return HANDLE_CAST (context);
|
}
|
|
void
|
xcam_destroy_handle (XCamHandle *handle)
|
{
|
if (handle)
|
delete CONTEXT_BASE_CAST (handle);
|
}
|
|
XCamReturn
|
xcam_handle_init (XCamHandle *handle)
|
{
|
ContextBase *context = CONTEXT_BASE_CAST (handle);
|
SmartPtr<CLImageHandler> handler_ptr;
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
XCAM_FAIL_RETURN (
|
ERROR, context, XCAM_RETURN_ERROR_PARAM,
|
"xcam_handler_init failed, handle can NOT be NULL, did you have xcam_create_handler first?");
|
|
ret = context->init_handler ();
|
XCAM_FAIL_RETURN (
|
ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
|
"xcam_handler_init, create handle ptr(%s) failed", context->get_type_name ());
|
|
return XCAM_RETURN_NO_ERROR;
|
}
|
|
XCamReturn
|
xcam_handle_uinit (XCamHandle *handle)
|
{
|
ContextBase *context = CONTEXT_BASE_CAST (handle);
|
|
XCAM_FAIL_RETURN (
|
ERROR, context, XCAM_RETURN_ERROR_PARAM,
|
"xcam_handler_uinit failed, handle can NOT be NULL");
|
|
return context->uinit_handler ();
|
}
|
|
XCamReturn
|
xcam_handle_get_usage (XCamHandle *handle, char *usage_buf, int *usage_len)
|
{
|
ContextBase *context = CONTEXT_BASE_CAST (handle);
|
XCAM_FAIL_RETURN (
|
ERROR, context, XCAM_RETURN_ERROR_PARAM,
|
"xcam_handle_get_usage failed, handle can NOT be NULL");
|
|
const char *usage = context->get_usage ();
|
int len = strlen (usage) + 1;
|
if (len < *usage_len)
|
len = *usage_len;
|
strncpy (usage_buf, usage, len - 1);
|
*usage_len = len;
|
return XCAM_RETURN_NO_ERROR;
|
}
|
|
XCamReturn
|
xcam_handle_set_parameters (
|
XCamHandle *handle, const char *field, ...)
|
{
|
ContextBase *context = CONTEXT_BASE_CAST (handle);
|
ContextParams params;
|
|
XCAM_FAIL_RETURN (
|
ERROR, context, XCAM_RETURN_ERROR_PARAM,
|
"xcam_handle_set_parameters failed, handle can NOT be NULL");
|
|
const char *vfield, *vvalue;
|
vfield = field;
|
va_list args;
|
va_start (args, field);
|
while (vfield) {
|
vvalue = va_arg (args, const char *);
|
XCAM_FAIL_RETURN (
|
ERROR, vvalue, XCAM_RETURN_ERROR_PARAM,
|
"xcam_handle(%s) set_parameters failed, param(field:%s) value should never be NULL",
|
context->get_type_name (), vfield);
|
|
params[vfield] = vvalue;
|
vfield = va_arg (args, const char *);
|
}
|
va_end (args);
|
|
return context->set_parameters (params);
|
}
|
|
SmartPtr<VideoBuffer>
|
external_buf_to_drm_buf (XCamVideoBuffer *buf)
|
{
|
#if HAVE_LIBDRM
|
SmartPtr<DrmDisplay> display = DrmDisplay::instance ();
|
SmartPtr<DmaVideoBuffer> dma_buf;
|
SmartPtr<VideoBuffer> drm_buf;
|
SmartPtr<VideoBuffer> video_buf;
|
|
dma_buf = external_buf_to_dma_buf (buf);
|
|
XCAM_FAIL_RETURN (
|
ERROR, dma_buf.ptr (), NULL,
|
"external_buf_to_drm_buf failed");
|
|
video_buf = dma_buf;
|
XCAM_ASSERT (display.ptr ());
|
drm_buf = display->convert_to_drm_bo_buf (display, video_buf);
|
return drm_buf;
|
#else
|
XCAM_LOG_ERROR ("VideoBuffer doesn't support drm buf");
|
|
XCAM_UNUSED (buf);
|
return NULL;
|
#endif
|
}
|
|
SmartPtr<VideoBuffer>
|
copy_external_buf_to_drm_buf (XCamHandle *handle, XCamVideoBuffer *buf)
|
{
|
if (!handle || !buf) {
|
XCAM_LOG_WARNING ("xcam handle can NOT be NULL");
|
return NULL;
|
}
|
|
ContextBase *context = CONTEXT_BASE_CAST (handle);
|
if (!context) {
|
XCAM_LOG_WARNING ("xcam handle context can NOT be NULL");
|
return NULL;
|
}
|
|
const XCamVideoBufferInfo src_info = buf->info;
|
uint8_t* src = buf->map (buf);
|
uint8_t* p_src = src;
|
if (!src) {
|
XCAM_LOG_WARNING ("xcam handle map buffer failed");
|
return NULL;
|
}
|
uint32_t height = src_info.height;
|
|
SmartPtr<BufferPool> buf_pool = context->get_input_buffer_pool();
|
XCAM_ASSERT (buf_pool.ptr ());
|
SmartPtr<VideoBuffer> video_buf = buf_pool->get_buffer (buf_pool);
|
XCAM_ASSERT (video_buf.ptr ());
|
const XCamVideoBufferInfo dest_info = video_buf->get_video_info ();
|
|
uint8_t* dest = video_buf->map ();
|
uint8_t* p_dest = dest;
|
|
for (uint32_t index = 0; index < src_info.components; index++) {
|
src += (int32_t)src_info.offsets[index];
|
p_src = src;
|
|
dest += dest_info.offsets[index];
|
p_dest = dest;
|
if (src_info.format == V4L2_PIX_FMT_NV12) {
|
height = height >> index;
|
}
|
for (uint32_t i = 0; i < height; i++) {
|
memcpy (p_dest, p_src, src_info.strides[index]);
|
p_src += src_info.strides[index];
|
p_dest += dest_info.strides[index];
|
}
|
}
|
|
buf->unmap (buf);
|
video_buf->unmap ();
|
|
return video_buf;
|
}
|
|
XCamReturn
|
xcam_handle_execute (XCamHandle *handle, XCamVideoBuffer *buf_in, XCamVideoBuffer **buf_out)
|
{
|
ContextBase *context = CONTEXT_BASE_CAST (handle);
|
SmartPtr<VideoBuffer> input, output;
|
|
XCAM_FAIL_RETURN (
|
ERROR, context && buf_in && buf_out, XCAM_RETURN_ERROR_PARAM,
|
"xcam_handle_execute failed, either of handle/buf_in/buf_out can NOT be NULL");
|
|
XCAM_FAIL_RETURN (
|
ERROR, context->get_handler().ptr (), XCAM_RETURN_ERROR_PARAM,
|
"context (%s) failed, handler was not initialized", context->get_type_name ());
|
|
if (buf_in->mem_type == XCAM_MEM_TYPE_GPU) {
|
input = external_buf_to_drm_buf (buf_in);
|
} else {
|
input = copy_external_buf_to_drm_buf (handle, buf_in);
|
}
|
XCAM_FAIL_RETURN (
|
ERROR, input.ptr (), XCAM_RETURN_ERROR_MEM,
|
"xcam_handle(%s) execute failed, buf_in convert to DRM buffer failed.",
|
context->get_type_name ());
|
|
if (*buf_out) {
|
output = external_buf_to_drm_buf (*buf_out);
|
XCAM_FAIL_RETURN (
|
ERROR, output.ptr (), XCAM_RETURN_ERROR_MEM,
|
"xcam_handle(%s) execute failed, buf_out set but convert to DRM buffer failed.",
|
context->get_type_name ());
|
}
|
|
XCamReturn ret = context->execute (input, output);
|
|
XCAM_FAIL_RETURN (
|
ERROR, ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS,
|
ret,
|
"context (%s) failed, handler execute failed", context->get_type_name ());
|
|
if (*buf_out == NULL && output.ptr ()) {
|
XCamVideoBuffer *new_buf = convert_to_external_buffer (output);
|
XCAM_FAIL_RETURN (
|
ERROR, new_buf, XCAM_RETURN_ERROR_MEM,
|
"xcam_handle(%s) execute failed, out buffer can't convert to external buffer.",
|
context->get_type_name ());
|
*buf_out = new_buf;
|
}
|
return ret;
|
}
|