1 /*
2 * xcam_handle.cpp - xcam handle implementation
3 *
4 * Copyright (c) 2017 Intel Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Wind Yuan <feng.yuan@intel.com>
19 */
20
21 #include <xcam_utils.h>
22 #include <xcam_handle.h>
23 #include <dma_video_buffer.h>
24 #include "context_priv.h"
25 #include <stdarg.h>
26 #if HAVE_LIBDRM
27 #include <drm_bo_buffer.h>
28 #endif
29
30 using namespace XCam;
31
32 XCamHandle *
xcam_create_handle(const char * name)33 xcam_create_handle (const char *name)
34 {
35 ContextBase *context = NULL;
36
37 if (handle_name_equal (name, HandleType3DNR)) {
38 context = new NR3DContext;
39 } else if (handle_name_equal (name, HandleTypeWaveletNR)) {
40 context = new NRWaveletContext;
41 } else if (handle_name_equal (name, HandleTypeFisheye)) {
42 context = new FisheyeContext;
43 } else if (handle_name_equal (name, HandleTypeDefog)) {
44 context = new DefogContext;
45 } else if (handle_name_equal (name, HandleTypeDVS)) {
46 context = new DVSContext;
47 } else if (handle_name_equal (name, HandleTypeStitch)) {
48 context = new StitchContext;
49 } else {
50 XCAM_LOG_ERROR ("create handle failed with unsupported type:%s", name);
51 return NULL;
52 }
53
54 return HANDLE_CAST (context);
55 }
56
57 void
xcam_destroy_handle(XCamHandle * handle)58 xcam_destroy_handle (XCamHandle *handle)
59 {
60 if (handle)
61 delete CONTEXT_BASE_CAST (handle);
62 }
63
64 XCamReturn
xcam_handle_init(XCamHandle * handle)65 xcam_handle_init (XCamHandle *handle)
66 {
67 ContextBase *context = CONTEXT_BASE_CAST (handle);
68 SmartPtr<CLImageHandler> handler_ptr;
69 XCamReturn ret = XCAM_RETURN_NO_ERROR;
70
71 XCAM_FAIL_RETURN (
72 ERROR, context, XCAM_RETURN_ERROR_PARAM,
73 "xcam_handler_init failed, handle can NOT be NULL, did you have xcam_create_handler first?");
74
75 ret = context->init_handler ();
76 XCAM_FAIL_RETURN (
77 ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
78 "xcam_handler_init, create handle ptr(%s) failed", context->get_type_name ());
79
80 return XCAM_RETURN_NO_ERROR;
81 }
82
83 XCamReturn
xcam_handle_uinit(XCamHandle * handle)84 xcam_handle_uinit (XCamHandle *handle)
85 {
86 ContextBase *context = CONTEXT_BASE_CAST (handle);
87
88 XCAM_FAIL_RETURN (
89 ERROR, context, XCAM_RETURN_ERROR_PARAM,
90 "xcam_handler_uinit failed, handle can NOT be NULL");
91
92 return context->uinit_handler ();
93 }
94
95 XCamReturn
xcam_handle_get_usage(XCamHandle * handle,char * usage_buf,int * usage_len)96 xcam_handle_get_usage (XCamHandle *handle, char *usage_buf, int *usage_len)
97 {
98 ContextBase *context = CONTEXT_BASE_CAST (handle);
99 XCAM_FAIL_RETURN (
100 ERROR, context, XCAM_RETURN_ERROR_PARAM,
101 "xcam_handle_get_usage failed, handle can NOT be NULL");
102
103 const char *usage = context->get_usage ();
104 int len = strlen (usage) + 1;
105 if (len < *usage_len)
106 len = *usage_len;
107 strncpy (usage_buf, usage, len - 1);
108 *usage_len = len;
109 return XCAM_RETURN_NO_ERROR;
110 }
111
112 XCamReturn
xcam_handle_set_parameters(XCamHandle * handle,const char * field,...)113 xcam_handle_set_parameters (
114 XCamHandle *handle, const char *field, ...)
115 {
116 ContextBase *context = CONTEXT_BASE_CAST (handle);
117 ContextParams params;
118
119 XCAM_FAIL_RETURN (
120 ERROR, context, XCAM_RETURN_ERROR_PARAM,
121 "xcam_handle_set_parameters failed, handle can NOT be NULL");
122
123 const char *vfield, *vvalue;
124 vfield = field;
125 va_list args;
126 va_start (args, field);
127 while (vfield) {
128 vvalue = va_arg (args, const char *);
129 XCAM_FAIL_RETURN (
130 ERROR, vvalue, XCAM_RETURN_ERROR_PARAM,
131 "xcam_handle(%s) set_parameters failed, param(field:%s) value should never be NULL",
132 context->get_type_name (), vfield);
133
134 params[vfield] = vvalue;
135 vfield = va_arg (args, const char *);
136 }
137 va_end (args);
138
139 return context->set_parameters (params);
140 }
141
142 SmartPtr<VideoBuffer>
external_buf_to_drm_buf(XCamVideoBuffer * buf)143 external_buf_to_drm_buf (XCamVideoBuffer *buf)
144 {
145 #if HAVE_LIBDRM
146 SmartPtr<DrmDisplay> display = DrmDisplay::instance ();
147 SmartPtr<DmaVideoBuffer> dma_buf;
148 SmartPtr<VideoBuffer> drm_buf;
149 SmartPtr<VideoBuffer> video_buf;
150
151 dma_buf = external_buf_to_dma_buf (buf);
152
153 XCAM_FAIL_RETURN (
154 ERROR, dma_buf.ptr (), NULL,
155 "external_buf_to_drm_buf failed");
156
157 video_buf = dma_buf;
158 XCAM_ASSERT (display.ptr ());
159 drm_buf = display->convert_to_drm_bo_buf (display, video_buf);
160 return drm_buf;
161 #else
162 XCAM_LOG_ERROR ("VideoBuffer doesn't support drm buf");
163
164 XCAM_UNUSED (buf);
165 return NULL;
166 #endif
167 }
168
169 SmartPtr<VideoBuffer>
copy_external_buf_to_drm_buf(XCamHandle * handle,XCamVideoBuffer * buf)170 copy_external_buf_to_drm_buf (XCamHandle *handle, XCamVideoBuffer *buf)
171 {
172 if (!handle || !buf) {
173 XCAM_LOG_WARNING ("xcam handle can NOT be NULL");
174 return NULL;
175 }
176
177 ContextBase *context = CONTEXT_BASE_CAST (handle);
178 if (!context) {
179 XCAM_LOG_WARNING ("xcam handle context can NOT be NULL");
180 return NULL;
181 }
182
183 const XCamVideoBufferInfo src_info = buf->info;
184 uint8_t* src = buf->map (buf);
185 uint8_t* p_src = src;
186 if (!src) {
187 XCAM_LOG_WARNING ("xcam handle map buffer failed");
188 return NULL;
189 }
190 uint32_t height = src_info.height;
191
192 SmartPtr<BufferPool> buf_pool = context->get_input_buffer_pool();
193 XCAM_ASSERT (buf_pool.ptr ());
194 SmartPtr<VideoBuffer> video_buf = buf_pool->get_buffer (buf_pool);
195 XCAM_ASSERT (video_buf.ptr ());
196 const XCamVideoBufferInfo dest_info = video_buf->get_video_info ();
197
198 uint8_t* dest = video_buf->map ();
199 uint8_t* p_dest = dest;
200
201 for (uint32_t index = 0; index < src_info.components; index++) {
202 src += (int32_t)src_info.offsets[index];
203 p_src = src;
204
205 dest += dest_info.offsets[index];
206 p_dest = dest;
207 if (src_info.format == V4L2_PIX_FMT_NV12) {
208 height = height >> index;
209 }
210 for (uint32_t i = 0; i < height; i++) {
211 memcpy (p_dest, p_src, src_info.strides[index]);
212 p_src += src_info.strides[index];
213 p_dest += dest_info.strides[index];
214 }
215 }
216
217 buf->unmap (buf);
218 video_buf->unmap ();
219
220 return video_buf;
221 }
222
223 XCamReturn
xcam_handle_execute(XCamHandle * handle,XCamVideoBuffer * buf_in,XCamVideoBuffer ** buf_out)224 xcam_handle_execute (XCamHandle *handle, XCamVideoBuffer *buf_in, XCamVideoBuffer **buf_out)
225 {
226 ContextBase *context = CONTEXT_BASE_CAST (handle);
227 SmartPtr<VideoBuffer> input, output;
228
229 XCAM_FAIL_RETURN (
230 ERROR, context && buf_in && buf_out, XCAM_RETURN_ERROR_PARAM,
231 "xcam_handle_execute failed, either of handle/buf_in/buf_out can NOT be NULL");
232
233 XCAM_FAIL_RETURN (
234 ERROR, context->get_handler().ptr (), XCAM_RETURN_ERROR_PARAM,
235 "context (%s) failed, handler was not initialized", context->get_type_name ());
236
237 if (buf_in->mem_type == XCAM_MEM_TYPE_GPU) {
238 input = external_buf_to_drm_buf (buf_in);
239 } else {
240 input = copy_external_buf_to_drm_buf (handle, buf_in);
241 }
242 XCAM_FAIL_RETURN (
243 ERROR, input.ptr (), XCAM_RETURN_ERROR_MEM,
244 "xcam_handle(%s) execute failed, buf_in convert to DRM buffer failed.",
245 context->get_type_name ());
246
247 if (*buf_out) {
248 output = external_buf_to_drm_buf (*buf_out);
249 XCAM_FAIL_RETURN (
250 ERROR, output.ptr (), XCAM_RETURN_ERROR_MEM,
251 "xcam_handle(%s) execute failed, buf_out set but convert to DRM buffer failed.",
252 context->get_type_name ());
253 }
254
255 XCamReturn ret = context->execute (input, output);
256
257 XCAM_FAIL_RETURN (
258 ERROR, ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS,
259 ret,
260 "context (%s) failed, handler execute failed", context->get_type_name ());
261
262 if (*buf_out == NULL && output.ptr ()) {
263 XCamVideoBuffer *new_buf = convert_to_external_buffer (output);
264 XCAM_FAIL_RETURN (
265 ERROR, new_buf, XCAM_RETURN_ERROR_MEM,
266 "xcam_handle(%s) execute failed, out buffer can't convert to external buffer.",
267 context->get_type_name ());
268 *buf_out = new_buf;
269 }
270 return ret;
271 }
272