| /* |
| * 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 <[email protected]> |
| */ |
| |
| #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; |
| } |