yading@11
|
1 /*
|
yading@11
|
2 * Copyright (C) 2012 Peng Gao <peng@multicorewareinc.com>
|
yading@11
|
3 * Copyright (C) 2012 Li Cao <li@multicorewareinc.com>
|
yading@11
|
4 * Copyright (C) 2012 Wei Gao <weigao@multicorewareinc.com>
|
yading@11
|
5 *
|
yading@11
|
6 * This file is part of FFmpeg.
|
yading@11
|
7 *
|
yading@11
|
8 * FFmpeg is free software; you can redistribute it and/or
|
yading@11
|
9 * modify it under the terms of the GNU Lesser General Public
|
yading@11
|
10 * License as published by the Free Software Foundation; either
|
yading@11
|
11 * version 2.1 of the License, or (at your option) any later version.
|
yading@11
|
12 *
|
yading@11
|
13 * FFmpeg is distributed in the hope that it will be useful,
|
yading@11
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@11
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@11
|
16 * Lesser General Public License for more details.
|
yading@11
|
17 *
|
yading@11
|
18 * You should have received a copy of the GNU Lesser General Public
|
yading@11
|
19 * License along with FFmpeg; if not, write to the Free Software
|
yading@11
|
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@11
|
21 */
|
yading@11
|
22
|
yading@11
|
23 #include "opencl.h"
|
yading@11
|
24 #include "avstring.h"
|
yading@11
|
25 #include "log.h"
|
yading@11
|
26 #include "avassert.h"
|
yading@11
|
27 #include "opt.h"
|
yading@11
|
28
|
yading@11
|
29 #if HAVE_PTHREADS
|
yading@11
|
30
|
yading@11
|
31 #include <pthread.h>
|
yading@11
|
32 static pthread_mutex_t atomic_opencl_lock = PTHREAD_MUTEX_INITIALIZER;
|
yading@11
|
33
|
yading@11
|
34 #define LOCK_OPENCL pthread_mutex_lock(&atomic_opencl_lock);
|
yading@11
|
35 #define UNLOCK_OPENCL pthread_mutex_unlock(&atomic_opencl_lock);
|
yading@11
|
36
|
yading@11
|
37 #elif !HAVE_THREADS
|
yading@11
|
38 #define LOCK_OPENCL
|
yading@11
|
39 #define UNLOCK_OPENCL
|
yading@11
|
40 #endif
|
yading@11
|
41
|
yading@11
|
42
|
yading@11
|
43 #define MAX_KERNEL_NUM 500
|
yading@11
|
44 #define MAX_KERNEL_CODE_NUM 200
|
yading@11
|
45
|
yading@11
|
46 typedef struct {
|
yading@11
|
47 int is_compiled;
|
yading@11
|
48 const char *kernel_string;
|
yading@11
|
49 } KernelCode;
|
yading@11
|
50
|
yading@11
|
51 typedef struct {
|
yading@11
|
52 const AVClass *class;
|
yading@11
|
53 int log_offset;
|
yading@11
|
54 void *log_ctx;
|
yading@11
|
55 int init_count;
|
yading@11
|
56 int opt_init_flag;
|
yading@11
|
57 /**
|
yading@11
|
58 * if set to 1, the OpenCL environment was created by the user and
|
yading@11
|
59 * passed as AVOpenCLExternalEnv when initing ,0:created by opencl wrapper.
|
yading@11
|
60 */
|
yading@11
|
61 int is_user_created;
|
yading@11
|
62 int platform_idx;
|
yading@11
|
63 int device_idx;
|
yading@11
|
64 char *build_options;
|
yading@11
|
65 cl_platform_id platform_id;
|
yading@11
|
66 cl_device_type device_type;
|
yading@11
|
67 cl_context context;
|
yading@11
|
68 cl_device_id device_id;
|
yading@11
|
69 cl_command_queue command_queue;
|
yading@11
|
70 int program_count;
|
yading@11
|
71 cl_program programs[MAX_KERNEL_CODE_NUM];
|
yading@11
|
72 int kernel_code_count;
|
yading@11
|
73 KernelCode kernel_code[MAX_KERNEL_CODE_NUM];
|
yading@11
|
74 int kernel_count;
|
yading@11
|
75 AVOpenCLDeviceList device_list;
|
yading@11
|
76 } OpenclContext;
|
yading@11
|
77
|
yading@11
|
78 #define OFFSET(x) offsetof(OpenclContext, x)
|
yading@11
|
79
|
yading@11
|
80 static const AVOption opencl_options[] = {
|
yading@11
|
81 { "platform_idx", "set platform index value", OFFSET(platform_idx), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX},
|
yading@11
|
82 { "device_idx", "set device index value", OFFSET(device_idx), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX},
|
yading@11
|
83 { "build_options", "build options of opencl", OFFSET(build_options), AV_OPT_TYPE_STRING, {.str="-I."}, CHAR_MIN, CHAR_MAX},
|
yading@11
|
84 };
|
yading@11
|
85
|
yading@11
|
86 static const AVClass openclutils_class = {
|
yading@11
|
87 .class_name = "OPENCLUTILS",
|
yading@11
|
88 .option = opencl_options,
|
yading@11
|
89 .item_name = av_default_item_name,
|
yading@11
|
90 .version = LIBAVUTIL_VERSION_INT,
|
yading@11
|
91 .log_level_offset_offset = offsetof(OpenclContext, log_offset),
|
yading@11
|
92 .parent_log_context_offset = offsetof(OpenclContext, log_ctx),
|
yading@11
|
93 };
|
yading@11
|
94
|
yading@11
|
95 static OpenclContext opencl_ctx = {&openclutils_class};
|
yading@11
|
96
|
yading@11
|
97 static const cl_device_type device_type[] = {CL_DEVICE_TYPE_GPU, CL_DEVICE_TYPE_CPU, CL_DEVICE_TYPE_DEFAULT};
|
yading@11
|
98
|
yading@11
|
99 typedef struct {
|
yading@11
|
100 int err_code;
|
yading@11
|
101 const char *err_str;
|
yading@11
|
102 } OpenclErrorMsg;
|
yading@11
|
103
|
yading@11
|
104 static const OpenclErrorMsg opencl_err_msg[] = {
|
yading@11
|
105 {CL_DEVICE_NOT_FOUND, "DEVICE NOT FOUND"},
|
yading@11
|
106 {CL_DEVICE_NOT_AVAILABLE, "DEVICE NOT AVAILABLE"},
|
yading@11
|
107 {CL_COMPILER_NOT_AVAILABLE, "COMPILER NOT AVAILABLE"},
|
yading@11
|
108 {CL_MEM_OBJECT_ALLOCATION_FAILURE, "MEM OBJECT ALLOCATION FAILURE"},
|
yading@11
|
109 {CL_OUT_OF_RESOURCES, "OUT OF RESOURCES"},
|
yading@11
|
110 {CL_OUT_OF_HOST_MEMORY, "OUT OF HOST MEMORY"},
|
yading@11
|
111 {CL_PROFILING_INFO_NOT_AVAILABLE, "PROFILING INFO NOT AVAILABLE"},
|
yading@11
|
112 {CL_MEM_COPY_OVERLAP, "MEM COPY OVERLAP"},
|
yading@11
|
113 {CL_IMAGE_FORMAT_MISMATCH, "IMAGE FORMAT MISMATCH"},
|
yading@11
|
114 {CL_IMAGE_FORMAT_NOT_SUPPORTED, "IMAGE FORMAT NOT_SUPPORTED"},
|
yading@11
|
115 {CL_BUILD_PROGRAM_FAILURE, "BUILD PROGRAM FAILURE"},
|
yading@11
|
116 {CL_MAP_FAILURE, "MAP FAILURE"},
|
yading@11
|
117 {CL_MISALIGNED_SUB_BUFFER_OFFSET, "MISALIGNED SUB BUFFER OFFSET"},
|
yading@11
|
118 {CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST, "EXEC STATUS ERROR FOR EVENTS IN WAIT LIST"},
|
yading@11
|
119 {CL_COMPILE_PROGRAM_FAILURE, "COMPILE PROGRAM FAILURE"},
|
yading@11
|
120 {CL_LINKER_NOT_AVAILABLE, "LINKER NOT AVAILABLE"},
|
yading@11
|
121 {CL_LINK_PROGRAM_FAILURE, "LINK PROGRAM FAILURE"},
|
yading@11
|
122 {CL_DEVICE_PARTITION_FAILED, "DEVICE PARTITION FAILED"},
|
yading@11
|
123 {CL_KERNEL_ARG_INFO_NOT_AVAILABLE, "KERNEL ARG INFO NOT AVAILABLE"},
|
yading@11
|
124 {CL_INVALID_VALUE, "INVALID VALUE"},
|
yading@11
|
125 {CL_INVALID_DEVICE_TYPE, "INVALID DEVICE TYPE"},
|
yading@11
|
126 {CL_INVALID_PLATFORM, "INVALID PLATFORM"},
|
yading@11
|
127 {CL_INVALID_DEVICE, "INVALID DEVICE"},
|
yading@11
|
128 {CL_INVALID_CONTEXT, "INVALID CONTEXT"},
|
yading@11
|
129 {CL_INVALID_QUEUE_PROPERTIES, "INVALID QUEUE PROPERTIES"},
|
yading@11
|
130 {CL_INVALID_COMMAND_QUEUE, "INVALID COMMAND QUEUE"},
|
yading@11
|
131 {CL_INVALID_HOST_PTR, "INVALID HOST PTR"},
|
yading@11
|
132 {CL_INVALID_MEM_OBJECT, "INVALID MEM OBJECT"},
|
yading@11
|
133 {CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, "INVALID IMAGE FORMAT DESCRIPTOR"},
|
yading@11
|
134 {CL_INVALID_IMAGE_SIZE, "INVALID IMAGE SIZE"},
|
yading@11
|
135 {CL_INVALID_SAMPLER, "INVALID SAMPLER"},
|
yading@11
|
136 {CL_INVALID_BINARY, "INVALID BINARY"},
|
yading@11
|
137 {CL_INVALID_BUILD_OPTIONS, "INVALID BUILD OPTIONS"},
|
yading@11
|
138 {CL_INVALID_PROGRAM, "INVALID PROGRAM"},
|
yading@11
|
139 {CL_INVALID_PROGRAM_EXECUTABLE, "INVALID PROGRAM EXECUTABLE"},
|
yading@11
|
140 {CL_INVALID_KERNEL_NAME, "INVALID KERNEL NAME"},
|
yading@11
|
141 {CL_INVALID_KERNEL_DEFINITION, "INVALID KERNEL DEFINITION"},
|
yading@11
|
142 {CL_INVALID_KERNEL, "INVALID KERNEL"},
|
yading@11
|
143 {CL_INVALID_ARG_INDEX, "INVALID ARG INDEX"},
|
yading@11
|
144 {CL_INVALID_ARG_VALUE, "INVALID ARG VALUE"},
|
yading@11
|
145 {CL_INVALID_ARG_SIZE, "INVALID ARG_SIZE"},
|
yading@11
|
146 {CL_INVALID_KERNEL_ARGS, "INVALID KERNEL ARGS"},
|
yading@11
|
147 {CL_INVALID_WORK_DIMENSION, "INVALID WORK DIMENSION"},
|
yading@11
|
148 {CL_INVALID_WORK_GROUP_SIZE, "INVALID WORK GROUP SIZE"},
|
yading@11
|
149 {CL_INVALID_WORK_ITEM_SIZE, "INVALID WORK ITEM SIZE"},
|
yading@11
|
150 {CL_INVALID_GLOBAL_OFFSET, "INVALID GLOBAL OFFSET"},
|
yading@11
|
151 {CL_INVALID_EVENT_WAIT_LIST, "INVALID EVENT WAIT LIST"},
|
yading@11
|
152 {CL_INVALID_EVENT, "INVALID EVENT"},
|
yading@11
|
153 {CL_INVALID_OPERATION, "INVALID OPERATION"},
|
yading@11
|
154 {CL_INVALID_GL_OBJECT, "INVALID GL OBJECT"},
|
yading@11
|
155 {CL_INVALID_BUFFER_SIZE, "INVALID BUFFER SIZE"},
|
yading@11
|
156 {CL_INVALID_MIP_LEVEL, "INVALID MIP LEVEL"},
|
yading@11
|
157 {CL_INVALID_GLOBAL_WORK_SIZE, "INVALID GLOBAL WORK SIZE"},
|
yading@11
|
158 {CL_INVALID_PROPERTY, "INVALID PROPERTY"},
|
yading@11
|
159 {CL_INVALID_IMAGE_DESCRIPTOR, "INVALID IMAGE DESCRIPTOR"},
|
yading@11
|
160 {CL_INVALID_COMPILER_OPTIONS, "INVALID COMPILER OPTIONS"},
|
yading@11
|
161 {CL_INVALID_LINKER_OPTIONS, "INVALID LINKER OPTIONS"},
|
yading@11
|
162 {CL_INVALID_DEVICE_PARTITION_COUNT, "INVALID DEVICE PARTITION COUNT"},
|
yading@11
|
163 };
|
yading@11
|
164
|
yading@11
|
165 static const char *opencl_errstr(cl_int status)
|
yading@11
|
166 {
|
yading@11
|
167 int i;
|
yading@11
|
168 for (i = 0; i < sizeof(opencl_err_msg); i++) {
|
yading@11
|
169 if (opencl_err_msg[i].err_code == status)
|
yading@11
|
170 return opencl_err_msg[i].err_str;
|
yading@11
|
171 }
|
yading@11
|
172 return "unknown error";
|
yading@11
|
173 }
|
yading@11
|
174
|
yading@11
|
175 static void free_device_list(AVOpenCLDeviceList *device_list)
|
yading@11
|
176 {
|
yading@11
|
177 int i, j;
|
yading@11
|
178 if (!device_list)
|
yading@11
|
179 return;
|
yading@11
|
180 for (i = 0; i < device_list->platform_num; i++) {
|
yading@11
|
181 if (!device_list->platform_node[i])
|
yading@11
|
182 continue;
|
yading@11
|
183 for (j = 0; j < device_list->platform_node[i]->device_num; j++) {
|
yading@11
|
184 av_freep(&(device_list->platform_node[i]->device_node[j]));
|
yading@11
|
185 }
|
yading@11
|
186 av_freep(&device_list->platform_node[i]->device_node);
|
yading@11
|
187 av_freep(&device_list->platform_node[i]);
|
yading@11
|
188 }
|
yading@11
|
189 av_freep(&device_list->platform_node);
|
yading@11
|
190 device_list->platform_num = 0;
|
yading@11
|
191 }
|
yading@11
|
192
|
yading@11
|
193 static int get_device_list(AVOpenCLDeviceList *device_list)
|
yading@11
|
194 {
|
yading@11
|
195 cl_int status;
|
yading@11
|
196 int i, j, k, device_num, total_devices_num,ret = 0;
|
yading@11
|
197 int *devices_num;
|
yading@11
|
198 cl_platform_id *platform_ids = NULL;
|
yading@11
|
199 cl_device_id *device_ids = NULL;
|
yading@11
|
200 AVOpenCLDeviceNode *device_node = NULL;
|
yading@11
|
201 status = clGetPlatformIDs(0, NULL, &device_list->platform_num);
|
yading@11
|
202 if (status != CL_SUCCESS) {
|
yading@11
|
203 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
204 "Could not get OpenCL platform ids: %s\n", opencl_errstr(status));
|
yading@11
|
205 return AVERROR_EXTERNAL;
|
yading@11
|
206 }
|
yading@11
|
207 platform_ids = av_mallocz(device_list->platform_num * sizeof(cl_platform_id));
|
yading@11
|
208 if (!platform_ids)
|
yading@11
|
209 return AVERROR(ENOMEM);
|
yading@11
|
210 status = clGetPlatformIDs(device_list->platform_num, platform_ids, NULL);
|
yading@11
|
211 if (status != CL_SUCCESS) {
|
yading@11
|
212 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
213 "Could not get OpenCL platform ids: %s\n", opencl_errstr(status));
|
yading@11
|
214 ret = AVERROR_EXTERNAL;
|
yading@11
|
215 goto end;
|
yading@11
|
216 }
|
yading@11
|
217 device_list->platform_node = av_mallocz(device_list->platform_num * sizeof(AVOpenCLPlatformNode *));
|
yading@11
|
218 if (!device_list->platform_node) {
|
yading@11
|
219 ret = AVERROR(ENOMEM);
|
yading@11
|
220 goto end;
|
yading@11
|
221 }
|
yading@11
|
222 devices_num = av_mallocz(sizeof(int) * FF_ARRAY_ELEMS(device_type));
|
yading@11
|
223 if (!devices_num) {
|
yading@11
|
224 ret = AVERROR(ENOMEM);
|
yading@11
|
225 goto end;
|
yading@11
|
226 }
|
yading@11
|
227 for (i = 0; i < device_list->platform_num; i++) {
|
yading@11
|
228 device_list->platform_node[i] = av_mallocz(sizeof(AVOpenCLPlatformNode));
|
yading@11
|
229 if (!device_list->platform_node[i]) {
|
yading@11
|
230 ret = AVERROR(ENOMEM);
|
yading@11
|
231 goto end;
|
yading@11
|
232 }
|
yading@11
|
233 device_list->platform_node[i]->platform_id = platform_ids[i];
|
yading@11
|
234 status = clGetPlatformInfo(platform_ids[i], CL_PLATFORM_VENDOR,
|
yading@11
|
235 sizeof(device_list->platform_node[i]->platform_name),
|
yading@11
|
236 device_list->platform_node[i]->platform_name, NULL);
|
yading@11
|
237 total_devices_num = 0;
|
yading@11
|
238 for (j = 0; j < FF_ARRAY_ELEMS(device_type); j++) {
|
yading@11
|
239 status = clGetDeviceIDs(device_list->platform_node[i]->platform_id,
|
yading@11
|
240 device_type[j], 0, NULL, &devices_num[j]);
|
yading@11
|
241 total_devices_num += devices_num[j];
|
yading@11
|
242 }
|
yading@11
|
243 device_list->platform_node[i]->device_node = av_mallocz(total_devices_num * sizeof(AVOpenCLDeviceNode *));
|
yading@11
|
244 if (!device_list->platform_node[i]->device_node) {
|
yading@11
|
245 ret = AVERROR(ENOMEM);
|
yading@11
|
246 goto end;
|
yading@11
|
247 }
|
yading@11
|
248 for (j = 0; j < FF_ARRAY_ELEMS(device_type); j++) {
|
yading@11
|
249 if (devices_num[j]) {
|
yading@11
|
250 device_ids = av_mallocz(devices_num[j] * sizeof(cl_device_id));
|
yading@11
|
251 if (!device_ids) {
|
yading@11
|
252 ret = AVERROR(ENOMEM);
|
yading@11
|
253 goto end;
|
yading@11
|
254 }
|
yading@11
|
255 status = clGetDeviceIDs(device_list->platform_node[i]->platform_id, device_type[j],
|
yading@11
|
256 devices_num[j], device_ids, NULL);
|
yading@11
|
257 if (status != CL_SUCCESS) {
|
yading@11
|
258 av_log(&opencl_ctx, AV_LOG_WARNING,
|
yading@11
|
259 "Could not get device ID: %s:\n", opencl_errstr(status));
|
yading@11
|
260 av_freep(&device_ids);
|
yading@11
|
261 continue;
|
yading@11
|
262 }
|
yading@11
|
263 for (k = 0; k < devices_num[j]; k++) {
|
yading@11
|
264 device_num = device_list->platform_node[i]->device_num;
|
yading@11
|
265 device_list->platform_node[i]->device_node[device_num] = av_mallocz(sizeof(AVOpenCLDeviceNode));
|
yading@11
|
266 if (!device_list->platform_node[i]->device_node[device_num]) {
|
yading@11
|
267 ret = AVERROR(ENOMEM);
|
yading@11
|
268 goto end;
|
yading@11
|
269 }
|
yading@11
|
270 device_node = device_list->platform_node[i]->device_node[device_num];
|
yading@11
|
271 device_node->device_id = device_ids[k];
|
yading@11
|
272 device_node->device_type = device_type[j];
|
yading@11
|
273 status = clGetDeviceInfo(device_node->device_id, CL_DEVICE_NAME,
|
yading@11
|
274 sizeof(device_node->device_name), device_node->device_name,
|
yading@11
|
275 NULL);
|
yading@11
|
276 if (status != CL_SUCCESS) {
|
yading@11
|
277 av_log(&opencl_ctx, AV_LOG_WARNING,
|
yading@11
|
278 "Could not get device name: %s\n", opencl_errstr(status));
|
yading@11
|
279 continue;
|
yading@11
|
280 }
|
yading@11
|
281 device_list->platform_node[i]->device_num++;
|
yading@11
|
282 }
|
yading@11
|
283 av_freep(&device_ids);
|
yading@11
|
284 }
|
yading@11
|
285 }
|
yading@11
|
286 }
|
yading@11
|
287 end:
|
yading@11
|
288 av_freep(&platform_ids);
|
yading@11
|
289 av_freep(&devices_num);
|
yading@11
|
290 av_freep(&device_ids);
|
yading@11
|
291 if (ret < 0)
|
yading@11
|
292 free_device_list(device_list);
|
yading@11
|
293 return ret;
|
yading@11
|
294 }
|
yading@11
|
295
|
yading@11
|
296 int av_opencl_get_device_list(AVOpenCLDeviceList **device_list)
|
yading@11
|
297 {
|
yading@11
|
298 int ret = 0;
|
yading@11
|
299 *device_list = av_mallocz(sizeof(AVOpenCLDeviceList));
|
yading@11
|
300 if (!(*device_list)) {
|
yading@11
|
301 av_log(&opencl_ctx, AV_LOG_ERROR, "Could not allocate opencl device list\n");
|
yading@11
|
302 return AVERROR(ENOMEM);
|
yading@11
|
303 }
|
yading@11
|
304 ret = get_device_list(*device_list);
|
yading@11
|
305 if (ret < 0) {
|
yading@11
|
306 av_log(&opencl_ctx, AV_LOG_ERROR, "Could not get device list from environment\n");
|
yading@11
|
307 free_device_list(*device_list);
|
yading@11
|
308 av_freep(device_list);
|
yading@11
|
309 return ret;
|
yading@11
|
310 }
|
yading@11
|
311 return ret;
|
yading@11
|
312 }
|
yading@11
|
313
|
yading@11
|
314 void av_opencl_free_device_list(AVOpenCLDeviceList **device_list)
|
yading@11
|
315 {
|
yading@11
|
316 free_device_list(*device_list);
|
yading@11
|
317 av_freep(device_list);
|
yading@11
|
318 }
|
yading@11
|
319
|
yading@11
|
320 int av_opencl_set_option(const char *key, const char *val)
|
yading@11
|
321 {
|
yading@11
|
322 int ret = 0;
|
yading@11
|
323 LOCK_OPENCL
|
yading@11
|
324 if (!opencl_ctx.opt_init_flag) {
|
yading@11
|
325 av_opt_set_defaults(&opencl_ctx);
|
yading@11
|
326 opencl_ctx.opt_init_flag = 1;
|
yading@11
|
327 }
|
yading@11
|
328 ret = av_opt_set(&opencl_ctx, key, val, 0);
|
yading@11
|
329 UNLOCK_OPENCL
|
yading@11
|
330 return ret;
|
yading@11
|
331 }
|
yading@11
|
332
|
yading@11
|
333 int av_opencl_get_option(const char *key, uint8_t **out_val)
|
yading@11
|
334 {
|
yading@11
|
335 int ret = 0;
|
yading@11
|
336 LOCK_OPENCL
|
yading@11
|
337 ret = av_opt_get(&opencl_ctx, key, 0, out_val);
|
yading@11
|
338 UNLOCK_OPENCL
|
yading@11
|
339 return ret;
|
yading@11
|
340 }
|
yading@11
|
341
|
yading@11
|
342 void av_opencl_free_option(void)
|
yading@11
|
343 {
|
yading@11
|
344 /*FIXME: free openclutils context*/
|
yading@11
|
345 LOCK_OPENCL
|
yading@11
|
346 av_opt_free(&opencl_ctx);
|
yading@11
|
347 UNLOCK_OPENCL
|
yading@11
|
348 }
|
yading@11
|
349
|
yading@11
|
350 AVOpenCLExternalEnv *av_opencl_alloc_external_env(void)
|
yading@11
|
351 {
|
yading@11
|
352 AVOpenCLExternalEnv *ext = av_mallocz(sizeof(AVOpenCLExternalEnv));
|
yading@11
|
353 if (!ext) {
|
yading@11
|
354 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
355 "Could not malloc external opencl environment data space\n");
|
yading@11
|
356 }
|
yading@11
|
357 return ext;
|
yading@11
|
358 }
|
yading@11
|
359
|
yading@11
|
360 void av_opencl_free_external_env(AVOpenCLExternalEnv **ext_opencl_env)
|
yading@11
|
361 {
|
yading@11
|
362 av_freep(ext_opencl_env);
|
yading@11
|
363 }
|
yading@11
|
364
|
yading@11
|
365 int av_opencl_register_kernel_code(const char *kernel_code)
|
yading@11
|
366 {
|
yading@11
|
367 int i, ret = 0;
|
yading@11
|
368 LOCK_OPENCL;
|
yading@11
|
369 if (opencl_ctx.kernel_code_count >= MAX_KERNEL_CODE_NUM) {
|
yading@11
|
370 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
371 "Could not register kernel code, maximum number of registered kernel code %d already reached\n",
|
yading@11
|
372 MAX_KERNEL_CODE_NUM);
|
yading@11
|
373 ret = AVERROR(EINVAL);
|
yading@11
|
374 goto end;
|
yading@11
|
375 }
|
yading@11
|
376 for (i = 0; i < opencl_ctx.kernel_code_count; i++) {
|
yading@11
|
377 if (opencl_ctx.kernel_code[i].kernel_string == kernel_code) {
|
yading@11
|
378 av_log(&opencl_ctx, AV_LOG_WARNING, "Same kernel code has been registered\n");
|
yading@11
|
379 goto end;
|
yading@11
|
380 }
|
yading@11
|
381 }
|
yading@11
|
382 opencl_ctx.kernel_code[opencl_ctx.kernel_code_count].kernel_string = kernel_code;
|
yading@11
|
383 opencl_ctx.kernel_code[opencl_ctx.kernel_code_count].is_compiled = 0;
|
yading@11
|
384 opencl_ctx.kernel_code_count++;
|
yading@11
|
385 end:
|
yading@11
|
386 UNLOCK_OPENCL;
|
yading@11
|
387 return ret;
|
yading@11
|
388 }
|
yading@11
|
389
|
yading@11
|
390 int av_opencl_create_kernel(AVOpenCLKernelEnv *env, const char *kernel_name)
|
yading@11
|
391 {
|
yading@11
|
392 cl_int status;
|
yading@11
|
393 int i, ret = 0;
|
yading@11
|
394 LOCK_OPENCL;
|
yading@11
|
395 if (strlen(kernel_name) + 1 > AV_OPENCL_MAX_KERNEL_NAME_SIZE) {
|
yading@11
|
396 av_log(&opencl_ctx, AV_LOG_ERROR, "Created kernel name %s is too long\n", kernel_name);
|
yading@11
|
397 ret = AVERROR(EINVAL);
|
yading@11
|
398 goto end;
|
yading@11
|
399 }
|
yading@11
|
400 if (!env->kernel) {
|
yading@11
|
401 if (opencl_ctx.kernel_count >= MAX_KERNEL_NUM) {
|
yading@11
|
402 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
403 "Could not create kernel with name '%s', maximum number of kernels %d already reached\n",
|
yading@11
|
404 kernel_name, MAX_KERNEL_NUM);
|
yading@11
|
405 ret = AVERROR(EINVAL);
|
yading@11
|
406 goto end;
|
yading@11
|
407 }
|
yading@11
|
408 if (opencl_ctx.program_count == 0) {
|
yading@11
|
409 av_log(&opencl_ctx, AV_LOG_ERROR, "Program count of OpenCL is 0, can not create kernel\n");
|
yading@11
|
410 ret = AVERROR(EINVAL);
|
yading@11
|
411 goto end;
|
yading@11
|
412 }
|
yading@11
|
413 for (i = 0; i < opencl_ctx.program_count; i++) {
|
yading@11
|
414 env->kernel = clCreateKernel(opencl_ctx.programs[i], kernel_name, &status);
|
yading@11
|
415 if (status == CL_SUCCESS)
|
yading@11
|
416 break;
|
yading@11
|
417 }
|
yading@11
|
418 if (status != CL_SUCCESS) {
|
yading@11
|
419 av_log(&opencl_ctx, AV_LOG_ERROR, "Could not create OpenCL kernel: %s\n", opencl_errstr(status));
|
yading@11
|
420 ret = AVERROR_EXTERNAL;
|
yading@11
|
421 goto end;
|
yading@11
|
422 }
|
yading@11
|
423 opencl_ctx.kernel_count++;
|
yading@11
|
424 env->command_queue = opencl_ctx.command_queue;
|
yading@11
|
425 av_strlcpy(env->kernel_name, kernel_name, sizeof(env->kernel_name));
|
yading@11
|
426 }
|
yading@11
|
427 end:
|
yading@11
|
428 UNLOCK_OPENCL;
|
yading@11
|
429 return ret;
|
yading@11
|
430 }
|
yading@11
|
431
|
yading@11
|
432 void av_opencl_release_kernel(AVOpenCLKernelEnv *env)
|
yading@11
|
433 {
|
yading@11
|
434 cl_int status;
|
yading@11
|
435 LOCK_OPENCL
|
yading@11
|
436 if (!env->kernel)
|
yading@11
|
437 goto end;
|
yading@11
|
438 status = clReleaseKernel(env->kernel);
|
yading@11
|
439 if (status != CL_SUCCESS) {
|
yading@11
|
440 av_log(&opencl_ctx, AV_LOG_ERROR, "Could not release kernel: %s\n",
|
yading@11
|
441 opencl_errstr(status));
|
yading@11
|
442 }
|
yading@11
|
443 env->kernel = NULL;
|
yading@11
|
444 env->command_queue = NULL;
|
yading@11
|
445 env->kernel_name[0] = 0;
|
yading@11
|
446 opencl_ctx.kernel_count--;
|
yading@11
|
447 end:
|
yading@11
|
448 UNLOCK_OPENCL
|
yading@11
|
449 }
|
yading@11
|
450
|
yading@11
|
451 static int init_opencl_env(OpenclContext *opencl_ctx, AVOpenCLExternalEnv *ext_opencl_env)
|
yading@11
|
452 {
|
yading@11
|
453 cl_int status;
|
yading@11
|
454 cl_context_properties cps[3];
|
yading@11
|
455 int i, ret = 0;
|
yading@11
|
456 AVOpenCLDeviceNode *device_node = NULL;
|
yading@11
|
457
|
yading@11
|
458 if (ext_opencl_env) {
|
yading@11
|
459 if (opencl_ctx->is_user_created)
|
yading@11
|
460 return 0;
|
yading@11
|
461 opencl_ctx->platform_id = ext_opencl_env->platform_id;
|
yading@11
|
462 opencl_ctx->is_user_created = 1;
|
yading@11
|
463 opencl_ctx->command_queue = ext_opencl_env->command_queue;
|
yading@11
|
464 opencl_ctx->context = ext_opencl_env->context;
|
yading@11
|
465 opencl_ctx->device_id = ext_opencl_env->device_id;
|
yading@11
|
466 opencl_ctx->device_type = ext_opencl_env->device_type;
|
yading@11
|
467 } else {
|
yading@11
|
468 if (!opencl_ctx->is_user_created) {
|
yading@11
|
469 if (!opencl_ctx->device_list.platform_num) {
|
yading@11
|
470 ret = get_device_list(&opencl_ctx->device_list);
|
yading@11
|
471 if (ret < 0) {
|
yading@11
|
472 return ret;
|
yading@11
|
473 }
|
yading@11
|
474 }
|
yading@11
|
475 if (opencl_ctx->platform_idx >= 0) {
|
yading@11
|
476 if (opencl_ctx->device_list.platform_num < opencl_ctx->platform_idx + 1) {
|
yading@11
|
477 av_log(opencl_ctx, AV_LOG_ERROR, "User set platform index not exist\n");
|
yading@11
|
478 return AVERROR(EINVAL);
|
yading@11
|
479 }
|
yading@11
|
480 if (!opencl_ctx->device_list.platform_node[opencl_ctx->platform_idx]->device_num) {
|
yading@11
|
481 av_log(opencl_ctx, AV_LOG_ERROR, "No devices in user specific platform with index %d\n",
|
yading@11
|
482 opencl_ctx->platform_idx);
|
yading@11
|
483 return AVERROR(EINVAL);
|
yading@11
|
484 }
|
yading@11
|
485 opencl_ctx->platform_id = opencl_ctx->device_list.platform_node[opencl_ctx->platform_idx]->platform_id;
|
yading@11
|
486 } else {
|
yading@11
|
487 /* get a usable platform by default*/
|
yading@11
|
488 for (i = 0; i < opencl_ctx->device_list.platform_num; i++) {
|
yading@11
|
489 if (opencl_ctx->device_list.platform_node[i]->device_num) {
|
yading@11
|
490 opencl_ctx->platform_id = opencl_ctx->device_list.platform_node[i]->platform_id;
|
yading@11
|
491 opencl_ctx->platform_idx = i;
|
yading@11
|
492 break;
|
yading@11
|
493 }
|
yading@11
|
494 }
|
yading@11
|
495 }
|
yading@11
|
496 if (!opencl_ctx->platform_id) {
|
yading@11
|
497 av_log(opencl_ctx, AV_LOG_ERROR, "Could not get OpenCL platforms\n");
|
yading@11
|
498 return AVERROR_EXTERNAL;
|
yading@11
|
499 }
|
yading@11
|
500 /* get a usable device*/
|
yading@11
|
501 if (opencl_ctx->device_idx >= 0) {
|
yading@11
|
502 if (opencl_ctx->device_list.platform_node[opencl_ctx->platform_idx]->device_num < opencl_ctx->device_idx + 1) {
|
yading@11
|
503 av_log(opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
504 "Could not get OpenCL device idx %d in the user set platform\n", opencl_ctx->platform_idx);
|
yading@11
|
505 return AVERROR(EINVAL);
|
yading@11
|
506 }
|
yading@11
|
507 } else {
|
yading@11
|
508 opencl_ctx->device_idx = 0;
|
yading@11
|
509 }
|
yading@11
|
510
|
yading@11
|
511 device_node = opencl_ctx->device_list.platform_node[opencl_ctx->platform_idx]->device_node[opencl_ctx->device_idx];
|
yading@11
|
512 opencl_ctx->device_id = device_node->device_id;
|
yading@11
|
513 opencl_ctx->device_type = device_node->device_type;
|
yading@11
|
514
|
yading@11
|
515 /*
|
yading@11
|
516 * Use available platform.
|
yading@11
|
517 */
|
yading@11
|
518 av_log(opencl_ctx, AV_LOG_VERBOSE, "Platform Name: %s, device id: 0x%x\n",
|
yading@11
|
519 opencl_ctx->device_list.platform_node[opencl_ctx->platform_idx]->platform_name,
|
yading@11
|
520 (unsigned int)opencl_ctx->device_id);
|
yading@11
|
521 cps[0] = CL_CONTEXT_PLATFORM;
|
yading@11
|
522 cps[1] = (cl_context_properties)opencl_ctx->platform_id;
|
yading@11
|
523 cps[2] = 0;
|
yading@11
|
524
|
yading@11
|
525 opencl_ctx->context = clCreateContextFromType(cps, opencl_ctx->device_type,
|
yading@11
|
526 NULL, NULL, &status);
|
yading@11
|
527 if (status != CL_SUCCESS) {
|
yading@11
|
528 av_log(opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
529 "Could not get OpenCL context from device type: %s\n", opencl_errstr(status));
|
yading@11
|
530 return AVERROR_EXTERNAL;
|
yading@11
|
531 }
|
yading@11
|
532 opencl_ctx->command_queue = clCreateCommandQueue(opencl_ctx->context, opencl_ctx->device_id,
|
yading@11
|
533 0, &status);
|
yading@11
|
534 if (status != CL_SUCCESS) {
|
yading@11
|
535 av_log(opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
536 "Could not create OpenCL command queue: %s\n", opencl_errstr(status));
|
yading@11
|
537 return AVERROR_EXTERNAL;
|
yading@11
|
538 }
|
yading@11
|
539 }
|
yading@11
|
540 }
|
yading@11
|
541 return ret;
|
yading@11
|
542 }
|
yading@11
|
543
|
yading@11
|
544 static int compile_kernel_file(OpenclContext *opencl_ctx)
|
yading@11
|
545 {
|
yading@11
|
546 cl_int status;
|
yading@11
|
547 char *temp, *source_str = NULL;
|
yading@11
|
548 size_t source_str_len = 0;
|
yading@11
|
549 int i, ret = 0;
|
yading@11
|
550
|
yading@11
|
551 for (i = 0; i < opencl_ctx->kernel_code_count; i++) {
|
yading@11
|
552 if (!opencl_ctx->kernel_code[i].is_compiled)
|
yading@11
|
553 source_str_len += strlen(opencl_ctx->kernel_code[i].kernel_string);
|
yading@11
|
554 }
|
yading@11
|
555 if (!source_str_len) {
|
yading@11
|
556 return 0;
|
yading@11
|
557 }
|
yading@11
|
558 source_str = av_mallocz(source_str_len + 1);
|
yading@11
|
559 if (!source_str) {
|
yading@11
|
560 return AVERROR(ENOMEM);
|
yading@11
|
561 }
|
yading@11
|
562 temp = source_str;
|
yading@11
|
563 for (i = 0; i < opencl_ctx->kernel_code_count; i++) {
|
yading@11
|
564 if (!opencl_ctx->kernel_code[i].is_compiled) {
|
yading@11
|
565 memcpy(temp, opencl_ctx->kernel_code[i].kernel_string,
|
yading@11
|
566 strlen(opencl_ctx->kernel_code[i].kernel_string));
|
yading@11
|
567 opencl_ctx->kernel_code[i].is_compiled = 1;
|
yading@11
|
568 temp += strlen(opencl_ctx->kernel_code[i].kernel_string);
|
yading@11
|
569 }
|
yading@11
|
570 }
|
yading@11
|
571 /* create a CL program using the kernel source */
|
yading@11
|
572 opencl_ctx->programs[opencl_ctx->program_count] = clCreateProgramWithSource(opencl_ctx->context,
|
yading@11
|
573 1, (const char **)(&source_str),
|
yading@11
|
574 &source_str_len, &status);
|
yading@11
|
575 if(status != CL_SUCCESS) {
|
yading@11
|
576 av_log(opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
577 "Could not create OpenCL program with source code: %s\n", opencl_errstr(status));
|
yading@11
|
578 ret = AVERROR_EXTERNAL;
|
yading@11
|
579 goto end;
|
yading@11
|
580 }
|
yading@11
|
581 if (!opencl_ctx->programs[opencl_ctx->program_count]) {
|
yading@11
|
582 av_log(opencl_ctx, AV_LOG_ERROR, "Created program is NULL\n");
|
yading@11
|
583 ret = AVERROR_EXTERNAL;
|
yading@11
|
584 goto end;
|
yading@11
|
585 }
|
yading@11
|
586 status = clBuildProgram(opencl_ctx->programs[opencl_ctx->program_count], 1, &(opencl_ctx->device_id),
|
yading@11
|
587 opencl_ctx->build_options, NULL, NULL);
|
yading@11
|
588 if (status != CL_SUCCESS) {
|
yading@11
|
589 av_log(opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
590 "Could not compile OpenCL kernel: %s\n", opencl_errstr(status));
|
yading@11
|
591 ret = AVERROR_EXTERNAL;
|
yading@11
|
592 goto end;
|
yading@11
|
593 }
|
yading@11
|
594 opencl_ctx->program_count++;
|
yading@11
|
595 end:
|
yading@11
|
596 av_free(source_str);
|
yading@11
|
597 return ret;
|
yading@11
|
598 }
|
yading@11
|
599
|
yading@11
|
600 int av_opencl_init(AVOpenCLExternalEnv *ext_opencl_env)
|
yading@11
|
601 {
|
yading@11
|
602 int ret = 0;
|
yading@11
|
603 LOCK_OPENCL
|
yading@11
|
604 if (!opencl_ctx.init_count) {
|
yading@11
|
605 if (!opencl_ctx.opt_init_flag) {
|
yading@11
|
606 av_opt_set_defaults(&opencl_ctx);
|
yading@11
|
607 opencl_ctx.opt_init_flag = 1;
|
yading@11
|
608 }
|
yading@11
|
609 ret = init_opencl_env(&opencl_ctx, ext_opencl_env);
|
yading@11
|
610 if (ret < 0)
|
yading@11
|
611 goto end;
|
yading@11
|
612 }
|
yading@11
|
613 ret = compile_kernel_file(&opencl_ctx);
|
yading@11
|
614 if (ret < 0)
|
yading@11
|
615 goto end;
|
yading@11
|
616 if (opencl_ctx.kernel_code_count <= 0) {
|
yading@11
|
617 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
618 "No kernel code is registered, compile kernel file failed\n");
|
yading@11
|
619 ret = AVERROR(EINVAL);
|
yading@11
|
620 goto end;
|
yading@11
|
621 }
|
yading@11
|
622 opencl_ctx.init_count++;
|
yading@11
|
623
|
yading@11
|
624 end:
|
yading@11
|
625 UNLOCK_OPENCL
|
yading@11
|
626 return ret;
|
yading@11
|
627 }
|
yading@11
|
628
|
yading@11
|
629 void av_opencl_uninit(void)
|
yading@11
|
630 {
|
yading@11
|
631 cl_int status;
|
yading@11
|
632 int i;
|
yading@11
|
633 LOCK_OPENCL
|
yading@11
|
634 opencl_ctx.init_count--;
|
yading@11
|
635 if (opencl_ctx.is_user_created)
|
yading@11
|
636 goto end;
|
yading@11
|
637 if (opencl_ctx.init_count > 0 || opencl_ctx.kernel_count > 0)
|
yading@11
|
638 goto end;
|
yading@11
|
639 for (i = 0; i < opencl_ctx.program_count; i++) {
|
yading@11
|
640 if (opencl_ctx.programs[i]) {
|
yading@11
|
641 status = clReleaseProgram(opencl_ctx.programs[i]);
|
yading@11
|
642 if (status != CL_SUCCESS) {
|
yading@11
|
643 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
644 "Could not release OpenCL program: %s\n", opencl_errstr(status));
|
yading@11
|
645 }
|
yading@11
|
646 opencl_ctx.programs[i] = NULL;
|
yading@11
|
647 }
|
yading@11
|
648 }
|
yading@11
|
649 if (opencl_ctx.command_queue) {
|
yading@11
|
650 status = clReleaseCommandQueue(opencl_ctx.command_queue);
|
yading@11
|
651 if (status != CL_SUCCESS) {
|
yading@11
|
652 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
653 "Could not release OpenCL command queue: %s\n", opencl_errstr(status));
|
yading@11
|
654 }
|
yading@11
|
655 opencl_ctx.command_queue = NULL;
|
yading@11
|
656 }
|
yading@11
|
657 if (opencl_ctx.context) {
|
yading@11
|
658 status = clReleaseContext(opencl_ctx.context);
|
yading@11
|
659 if (status != CL_SUCCESS) {
|
yading@11
|
660 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
661 "Could not release OpenCL context: %s\n", opencl_errstr(status));
|
yading@11
|
662 }
|
yading@11
|
663 opencl_ctx.context = NULL;
|
yading@11
|
664 }
|
yading@11
|
665 free_device_list(&opencl_ctx.device_list);
|
yading@11
|
666 end:
|
yading@11
|
667 if ((opencl_ctx.init_count <= 0) && (opencl_ctx.kernel_count <= 0))
|
yading@11
|
668 av_opt_free(&opencl_ctx); //FIXME: free openclutils context
|
yading@11
|
669 UNLOCK_OPENCL
|
yading@11
|
670 }
|
yading@11
|
671
|
yading@11
|
672 int av_opencl_buffer_create(cl_mem *cl_buf, size_t cl_buf_size, int flags, void *host_ptr)
|
yading@11
|
673 {
|
yading@11
|
674 cl_int status;
|
yading@11
|
675 *cl_buf = clCreateBuffer(opencl_ctx.context, flags, cl_buf_size, host_ptr, &status);
|
yading@11
|
676 if (status != CL_SUCCESS) {
|
yading@11
|
677 av_log(&opencl_ctx, AV_LOG_ERROR, "Could not create OpenCL buffer: %s\n", opencl_errstr(status));
|
yading@11
|
678 return AVERROR_EXTERNAL;
|
yading@11
|
679 }
|
yading@11
|
680 return 0;
|
yading@11
|
681 }
|
yading@11
|
682
|
yading@11
|
683 void av_opencl_buffer_release(cl_mem *cl_buf)
|
yading@11
|
684 {
|
yading@11
|
685 cl_int status = 0;
|
yading@11
|
686 if (!cl_buf)
|
yading@11
|
687 return;
|
yading@11
|
688 status = clReleaseMemObject(*cl_buf);
|
yading@11
|
689 if (status != CL_SUCCESS) {
|
yading@11
|
690 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
691 "Could not release OpenCL buffer: %s\n", opencl_errstr(status));
|
yading@11
|
692 }
|
yading@11
|
693 memset(cl_buf, 0, sizeof(*cl_buf));
|
yading@11
|
694 }
|
yading@11
|
695
|
yading@11
|
696 int av_opencl_buffer_write(cl_mem dst_cl_buf, uint8_t *src_buf, size_t buf_size)
|
yading@11
|
697 {
|
yading@11
|
698 cl_int status;
|
yading@11
|
699 void *mapped = clEnqueueMapBuffer(opencl_ctx.command_queue, dst_cl_buf,
|
yading@11
|
700 CL_TRUE, CL_MAP_WRITE, 0, sizeof(uint8_t) * buf_size,
|
yading@11
|
701 0, NULL, NULL, &status);
|
yading@11
|
702
|
yading@11
|
703 if (status != CL_SUCCESS) {
|
yading@11
|
704 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
705 "Could not map OpenCL buffer: %s\n", opencl_errstr(status));
|
yading@11
|
706 return AVERROR_EXTERNAL;
|
yading@11
|
707 }
|
yading@11
|
708 memcpy(mapped, src_buf, buf_size);
|
yading@11
|
709
|
yading@11
|
710 status = clEnqueueUnmapMemObject(opencl_ctx.command_queue, dst_cl_buf, mapped, 0, NULL, NULL);
|
yading@11
|
711 if (status != CL_SUCCESS) {
|
yading@11
|
712 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
713 "Could not unmap OpenCL buffer: %s\n", opencl_errstr(status));
|
yading@11
|
714 return AVERROR_EXTERNAL;
|
yading@11
|
715 }
|
yading@11
|
716 return 0;
|
yading@11
|
717 }
|
yading@11
|
718
|
yading@11
|
719 int av_opencl_buffer_read(uint8_t *dst_buf, cl_mem src_cl_buf, size_t buf_size)
|
yading@11
|
720 {
|
yading@11
|
721 cl_int status;
|
yading@11
|
722 void *mapped = clEnqueueMapBuffer(opencl_ctx.command_queue, src_cl_buf,
|
yading@11
|
723 CL_TRUE, CL_MAP_READ, 0, buf_size,
|
yading@11
|
724 0, NULL, NULL, &status);
|
yading@11
|
725
|
yading@11
|
726 if (status != CL_SUCCESS) {
|
yading@11
|
727 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
728 "Could not map OpenCL buffer: %s\n", opencl_errstr(status));
|
yading@11
|
729 return AVERROR_EXTERNAL;
|
yading@11
|
730 }
|
yading@11
|
731 memcpy(dst_buf, mapped, buf_size);
|
yading@11
|
732
|
yading@11
|
733 status = clEnqueueUnmapMemObject(opencl_ctx.command_queue, src_cl_buf, mapped, 0, NULL, NULL);
|
yading@11
|
734 if (status != CL_SUCCESS) {
|
yading@11
|
735 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
736 "Could not unmap OpenCL buffer: %s\n", opencl_errstr(status));
|
yading@11
|
737 return AVERROR_EXTERNAL;
|
yading@11
|
738 }
|
yading@11
|
739 return 0;
|
yading@11
|
740 }
|
yading@11
|
741
|
yading@11
|
742 int av_opencl_buffer_write_image(cl_mem dst_cl_buf, size_t cl_buffer_size, int dst_cl_offset,
|
yading@11
|
743 uint8_t **src_data, int *plane_size, int plane_num)
|
yading@11
|
744 {
|
yading@11
|
745 int i, buffer_size = 0;
|
yading@11
|
746 uint8_t *temp;
|
yading@11
|
747 cl_int status;
|
yading@11
|
748 void *mapped;
|
yading@11
|
749 if ((unsigned int)plane_num > 8) {
|
yading@11
|
750 return AVERROR(EINVAL);
|
yading@11
|
751 }
|
yading@11
|
752 for (i = 0;i < plane_num;i++) {
|
yading@11
|
753 buffer_size += plane_size[i];
|
yading@11
|
754 }
|
yading@11
|
755 if (buffer_size > cl_buffer_size) {
|
yading@11
|
756 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
757 "Cannot write image to OpenCL buffer: buffer too small\n");
|
yading@11
|
758 return AVERROR(EINVAL);
|
yading@11
|
759 }
|
yading@11
|
760 mapped = clEnqueueMapBuffer(opencl_ctx.command_queue, dst_cl_buf,
|
yading@11
|
761 CL_TRUE, CL_MAP_WRITE, 0, buffer_size + dst_cl_offset,
|
yading@11
|
762 0, NULL, NULL, &status);
|
yading@11
|
763 if (status != CL_SUCCESS) {
|
yading@11
|
764 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
765 "Could not map OpenCL buffer: %s\n", opencl_errstr(status));
|
yading@11
|
766 return AVERROR_EXTERNAL;
|
yading@11
|
767 }
|
yading@11
|
768 temp = mapped;
|
yading@11
|
769 temp += dst_cl_offset;
|
yading@11
|
770 for (i = 0; i < plane_num; i++) {
|
yading@11
|
771 memcpy(temp, src_data[i], plane_size[i]);
|
yading@11
|
772 temp += plane_size[i];
|
yading@11
|
773 }
|
yading@11
|
774 status = clEnqueueUnmapMemObject(opencl_ctx.command_queue, dst_cl_buf, mapped, 0, NULL, NULL);
|
yading@11
|
775 if (status != CL_SUCCESS) {
|
yading@11
|
776 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
777 "Could not unmap OpenCL buffer: %s\n", opencl_errstr(status));
|
yading@11
|
778 return AVERROR_EXTERNAL;
|
yading@11
|
779 }
|
yading@11
|
780 return 0;
|
yading@11
|
781 }
|
yading@11
|
782
|
yading@11
|
783 int av_opencl_buffer_read_image(uint8_t **dst_data, int *plane_size, int plane_num,
|
yading@11
|
784 cl_mem src_cl_buf, size_t cl_buffer_size)
|
yading@11
|
785 {
|
yading@11
|
786 int i,buffer_size = 0,ret = 0;
|
yading@11
|
787 uint8_t *temp;
|
yading@11
|
788 void *mapped;
|
yading@11
|
789 cl_int status;
|
yading@11
|
790 if ((unsigned int)plane_num > 8) {
|
yading@11
|
791 return AVERROR(EINVAL);
|
yading@11
|
792 }
|
yading@11
|
793 for (i = 0; i < plane_num; i++) {
|
yading@11
|
794 buffer_size += plane_size[i];
|
yading@11
|
795 }
|
yading@11
|
796 if (buffer_size > cl_buffer_size) {
|
yading@11
|
797 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
798 "Cannot write image to CPU buffer: OpenCL buffer too small\n");
|
yading@11
|
799 return AVERROR(EINVAL);
|
yading@11
|
800 }
|
yading@11
|
801 mapped = clEnqueueMapBuffer(opencl_ctx.command_queue, src_cl_buf,
|
yading@11
|
802 CL_TRUE, CL_MAP_READ, 0, buffer_size,
|
yading@11
|
803 0, NULL, NULL, &status);
|
yading@11
|
804
|
yading@11
|
805 if (status != CL_SUCCESS) {
|
yading@11
|
806 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
807 "Could not map OpenCL buffer: %s\n", opencl_errstr(status));
|
yading@11
|
808 return AVERROR_EXTERNAL;
|
yading@11
|
809 }
|
yading@11
|
810 temp = mapped;
|
yading@11
|
811 if (ret >= 0) {
|
yading@11
|
812 for (i = 0; i < plane_num; i++) {
|
yading@11
|
813 memcpy(dst_data[i], temp, plane_size[i]);
|
yading@11
|
814 temp += plane_size[i];
|
yading@11
|
815 }
|
yading@11
|
816 }
|
yading@11
|
817 status = clEnqueueUnmapMemObject(opencl_ctx.command_queue, src_cl_buf, mapped, 0, NULL, NULL);
|
yading@11
|
818 if (status != CL_SUCCESS) {
|
yading@11
|
819 av_log(&opencl_ctx, AV_LOG_ERROR,
|
yading@11
|
820 "Could not unmap OpenCL buffer: %s\n", opencl_errstr(status));
|
yading@11
|
821 return AVERROR_EXTERNAL;
|
yading@11
|
822 }
|
yading@11
|
823 return 0;
|
yading@11
|
824 }
|