/*
* 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;
}