c6fa99607a194a6ba4ea555cd26a4eb9b63d49fe
[platform/core/multimedia/vision-source.git] / src / vision_source.c
1 /**
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <dlfcn.h>
18 #include <stddef.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <memory.h>
22 #include <vision_source_interface.h>
23 #include <vision_source.h>
24 #include <stdlib.h>
25 #include <iniparser.h>
26 #include "vision_source_private.h"
27
28 #define MAX_BACKEND_NAME 32
29
30 typedef struct vision_source_internal
31 {
32         void *backend_handle;
33         void *dl_handle;
34         vision_source_func_s funcs;
35 } vision_source_internal_s;
36
37 int _vision_source_dlsym(vision_source_internal_s *handle)
38 {
39         void (*attach_backend)(vision_source_func_s *) =
40                         dlsym(handle->dl_handle, "attach_backend");
41
42         char *error = dlerror();
43         if (error != NULL) {
44                 LOGE("Failed dlsym : %s\n", error);
45                 return VISION_SOURCE_ERROR_INTERNAL;
46         }
47         attach_backend(&(handle->funcs));
48
49         int ret = handle->funcs.init(&(handle->backend_handle));
50         if (ret != VISION_SOURCE_ERROR_NONE) {
51                 return ret;
52         }
53         return VISION_SOURCE_ERROR_NONE;
54 }
55
56 int _vision_source_attach(const char *backend_name,
57                                                   vision_source_internal_s *handle)
58 {
59         LOGD("ENTER");
60         LOGI("backend %s connected", backend_name);
61         handle->dl_handle = dlopen(backend_name, RTLD_LAZY);
62         VISION_SOURCE_NULL_ARG_CHECK(handle->dl_handle);
63
64         int ret = _vision_source_dlsym(handle);
65         if (ret != VISION_SOURCE_ERROR_NONE) {
66                 dlclose(handle->dl_handle);
67                 return ret;
68         }
69         LOGD("EXIT");
70         return VISION_SOURCE_ERROR_NONE;
71 }
72
73 int _vision_source_get_backend(char *name)
74 {
75         LOGD("ENTER");
76
77         dictionary *ini = iniparser_load(HAL_INI_PATH);
78         if (!ini) {
79                 LOGI("hal ini not exist path : %s", HAL_INI_PATH);
80                 ini = iniparser_load(INI_PATH);
81                 if (!ini) {
82                         LOGE("ini not exist path : %s", INI_PATH);
83                         return VISION_SOURCE_ERROR_INVALID_PARAMETER;
84                 }
85         }
86
87         const char *backend_name = iniparser_getstring(ini, "common:name", NULL);
88
89         if (backend_name == NULL) {
90                 iniparser_freedict(ini);
91                 return VISION_SOURCE_ERROR_INVALID_PARAMETER;
92         }
93
94         snprintf(name, MAX_BACKEND_NAME, "libvision-source-%s.so", backend_name);
95
96         iniparser_freedict(ini);
97         LOGD("EXIT");
98         return VISION_SOURCE_ERROR_NONE;
99 }
100
101 int vision_source_init(vision_source_h *handle)
102 {
103         LOGD("ENTER");
104         VISION_SOURCE_NULL_ARG_CHECK(handle);
105
106         vision_source_internal_s *source_handle = NULL;
107
108         char backend_tmp[MAX_BACKEND_NAME];
109         int ret = _vision_source_get_backend(backend_tmp);
110         if (ret != VISION_SOURCE_ERROR_NONE) {
111                 return ret;
112         }
113
114         source_handle = malloc(sizeof(vision_source_internal_s));
115         VISION_SOURCE_NULL_ARG_CHECK(source_handle);
116
117         const char *backend_name = backend_tmp;
118         ret = _vision_source_attach(backend_name, source_handle);
119         if (ret != VISION_SOURCE_ERROR_NONE) {
120                 free(source_handle);
121                 return ret;
122         }
123         *handle = source_handle;
124
125         LOGD("EXIT");
126         return VISION_SOURCE_ERROR_NONE;
127 }
128
129 int vision_source_exit(vision_source_h handle)
130 {
131         LOGD("ENTER");
132         VISION_SOURCE_NULL_ARG_CHECK(handle);
133         vision_source_internal_s *source_handle =
134                         (vision_source_internal_s *) handle;
135
136         int ret = source_handle->funcs.exit(source_handle->backend_handle);
137         if (ret != VISION_SOURCE_ERROR_NONE) {
138                 return ret;
139         }
140
141         VISION_SOURCE_NULL_ARG_CHECK(source_handle->dl_handle);
142         ret = dlclose(source_handle->dl_handle);
143         if (ret) {
144                 LOGE("Failed to close shared object : %s", dlerror());
145                 return VISION_SOURCE_ERROR_INTERNAL;
146         }
147
148         free(source_handle);
149         LOGD("EXIT");
150         return VISION_SOURCE_ERROR_NONE;
151 }
152
153 int vision_source_open_device(vision_source_h handle, int device_index)
154 {
155         VISION_SOURCE_NULL_ARG_CHECK(handle);
156         vision_source_internal_s *source_handle =
157                         (vision_source_internal_s *) handle;
158         return source_handle->funcs.open_device(source_handle->backend_handle,
159                                                                                         device_index);
160 }
161 int vision_source_close_device(vision_source_h handle)
162 {
163         VISION_SOURCE_NULL_ARG_CHECK(handle);
164         vision_source_internal_s *source_handle =
165                         (vision_source_internal_s *) handle;
166         return source_handle->funcs.close_device(source_handle->backend_handle);
167 }
168 int vision_source_start_stream(vision_source_h handle, stream_cb callback,
169                                                            void *user_data)
170 {
171         VISION_SOURCE_NULL_ARG_CHECK(handle);
172         vision_source_internal_s *source_handle =
173                         (vision_source_internal_s *) handle;
174         return source_handle->funcs.start_stream(source_handle->backend_handle,
175                                                                                          callback, user_data);
176 }
177 int vision_source_stop_stream(vision_source_h handle)
178 {
179         VISION_SOURCE_NULL_ARG_CHECK(handle);
180         vision_source_internal_s *source_handle =
181                         (vision_source_internal_s *) handle;
182         return source_handle->funcs.stop_stream(source_handle->backend_handle);
183 }
184
185 int vision_source_enumerate_devices(vision_source_h handle,
186                                                                         vision_source_device_info_list_s *info_list)
187 {
188         VISION_SOURCE_NULL_ARG_CHECK(handle);
189         vision_source_internal_s *source_handle =
190                         (vision_source_internal_s *) handle;
191         return source_handle->funcs.enumerate_devices(source_handle->backend_handle,
192                                                                                                   info_list);
193 }
194
195 int vision_source_set_stream_format(vision_source_h handle,
196                                                                         vision_source_format_s *format)
197 {
198         VISION_SOURCE_NULL_ARG_CHECK(handle);
199         vision_source_internal_s *source_handle =
200                         (vision_source_internal_s *) handle;
201         return source_handle->funcs.set_stream_format(source_handle->backend_handle,
202                                                                                                   format);
203 }
204 int vision_source_get_capture_frame(vision_source_h handle,
205                                                                         vision_source_buffer_s *buffer)
206 {
207         VISION_SOURCE_NULL_ARG_CHECK(handle);
208         vision_source_internal_s *source_handle =
209                         (vision_source_internal_s *) handle;
210         return source_handle->funcs.get_capture_frame(source_handle->backend_handle,
211                                                                                                   buffer);
212 }
213
214 int vision_source_release_capture_frame(vision_source_h handle,
215                                                                                 int buffer_index)
216 {
217         VISION_SOURCE_NULL_ARG_CHECK(handle);
218         vision_source_internal_s *source_handle =
219                         (vision_source_internal_s *) handle;
220         return source_handle->funcs.release_capture_frame(
221                         source_handle->backend_handle, buffer_index);
222 }