1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,251 @@ |
0 |
+/* |
|
1 |
+ * This file is part of FFmpeg. |
|
2 |
+ * |
|
3 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
4 |
+ * modify it under the terms of the GNU Lesser General Public |
|
5 |
+ * License as published by the Free Software Foundation; either |
|
6 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
7 |
+ * |
|
8 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
9 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
11 |
+ * Lesser General Public License for more details. |
|
12 |
+ * |
|
13 |
+ * You should have received a copy of the GNU Lesser General Public |
|
14 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
15 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
16 |
+ */ |
|
17 |
+ |
|
18 |
+#include <stdio.h> |
|
19 |
+#include <string.h> |
|
20 |
+ |
|
21 |
+#include "libavutil/hwcontext.h" |
|
22 |
+#include "libavutil/hwcontext_opencl.h" |
|
23 |
+#include "libavutil/mem.h" |
|
24 |
+ |
|
25 |
+#include "avfilter.h" |
|
26 |
+#include "formats.h" |
|
27 |
+#include "opencl.h" |
|
28 |
+ |
|
29 |
+int ff_opencl_filter_query_formats(AVFilterContext *avctx) |
|
30 |
+{ |
|
31 |
+ const static enum AVPixelFormat pix_fmts[] = { |
|
32 |
+ AV_PIX_FMT_OPENCL, |
|
33 |
+ AV_PIX_FMT_NONE, |
|
34 |
+ }; |
|
35 |
+ AVFilterFormats *formats; |
|
36 |
+ |
|
37 |
+ formats = ff_make_format_list(pix_fmts); |
|
38 |
+ if (!formats) |
|
39 |
+ return AVERROR(ENOMEM); |
|
40 |
+ |
|
41 |
+ return ff_set_common_formats(avctx, formats); |
|
42 |
+} |
|
43 |
+ |
|
44 |
+int ff_opencl_filter_config_input(AVFilterLink *inlink) |
|
45 |
+{ |
|
46 |
+ AVFilterContext *avctx = inlink->dst; |
|
47 |
+ OpenCLFilterContext *ctx = avctx->priv; |
|
48 |
+ AVHWFramesContext *input_frames; |
|
49 |
+ |
|
50 |
+ if (!inlink->hw_frames_ctx) { |
|
51 |
+ av_log(avctx, AV_LOG_ERROR, "OpenCL filtering requires a " |
|
52 |
+ "hardware frames context on the input.\n"); |
|
53 |
+ return AVERROR(EINVAL); |
|
54 |
+ } |
|
55 |
+ |
|
56 |
+ // Extract the device and default output format from the first input. |
|
57 |
+ if (avctx->inputs[0] != inlink) |
|
58 |
+ return 0; |
|
59 |
+ |
|
60 |
+ input_frames = (AVHWFramesContext*)inlink->hw_frames_ctx->data; |
|
61 |
+ |
|
62 |
+ if (input_frames->format != AV_PIX_FMT_OPENCL) |
|
63 |
+ return AVERROR(EINVAL); |
|
64 |
+ |
|
65 |
+ ctx->device_ref = av_buffer_ref(input_frames->device_ref); |
|
66 |
+ if (!ctx->device_ref) |
|
67 |
+ return AVERROR(ENOMEM); |
|
68 |
+ ctx->device = input_frames->device_ctx; |
|
69 |
+ ctx->hwctx = ctx->device->hwctx; |
|
70 |
+ |
|
71 |
+ // Default output parameters match input parameters. |
|
72 |
+ if (ctx->output_format == AV_PIX_FMT_NONE) |
|
73 |
+ ctx->output_format = input_frames->sw_format; |
|
74 |
+ if (!ctx->output_width) |
|
75 |
+ ctx->output_width = inlink->w; |
|
76 |
+ if (!ctx->output_height) |
|
77 |
+ ctx->output_height = inlink->h; |
|
78 |
+ |
|
79 |
+ return 0; |
|
80 |
+} |
|
81 |
+ |
|
82 |
+int ff_opencl_filter_config_output(AVFilterLink *outlink) |
|
83 |
+{ |
|
84 |
+ AVFilterContext *avctx = outlink->src; |
|
85 |
+ OpenCLFilterContext *ctx = avctx->priv; |
|
86 |
+ AVBufferRef *output_frames_ref = NULL; |
|
87 |
+ AVHWFramesContext *output_frames; |
|
88 |
+ int err; |
|
89 |
+ |
|
90 |
+ av_buffer_unref(&outlink->hw_frames_ctx); |
|
91 |
+ |
|
92 |
+ output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref); |
|
93 |
+ if (!output_frames_ref) { |
|
94 |
+ err = AVERROR(ENOMEM); |
|
95 |
+ goto fail; |
|
96 |
+ } |
|
97 |
+ output_frames = (AVHWFramesContext*)output_frames_ref->data; |
|
98 |
+ |
|
99 |
+ output_frames->format = AV_PIX_FMT_OPENCL; |
|
100 |
+ output_frames->sw_format = ctx->output_format; |
|
101 |
+ output_frames->width = ctx->output_width; |
|
102 |
+ output_frames->height = ctx->output_height; |
|
103 |
+ |
|
104 |
+ err = av_hwframe_ctx_init(output_frames_ref); |
|
105 |
+ if (err < 0) { |
|
106 |
+ av_log(avctx, AV_LOG_ERROR, "Failed to initialise output " |
|
107 |
+ "frames: %d.\n", err); |
|
108 |
+ goto fail; |
|
109 |
+ } |
|
110 |
+ |
|
111 |
+ outlink->hw_frames_ctx = output_frames_ref; |
|
112 |
+ outlink->w = ctx->output_width; |
|
113 |
+ outlink->h = ctx->output_height; |
|
114 |
+ |
|
115 |
+ return 0; |
|
116 |
+fail: |
|
117 |
+ av_buffer_unref(&output_frames_ref); |
|
118 |
+ return err; |
|
119 |
+} |
|
120 |
+ |
|
121 |
+int ff_opencl_filter_init(AVFilterContext *avctx) |
|
122 |
+{ |
|
123 |
+ OpenCLFilterContext *ctx = avctx->priv; |
|
124 |
+ |
|
125 |
+ ctx->output_format = AV_PIX_FMT_NONE; |
|
126 |
+ |
|
127 |
+ return 0; |
|
128 |
+} |
|
129 |
+ |
|
130 |
+void ff_opencl_filter_uninit(AVFilterContext *avctx) |
|
131 |
+{ |
|
132 |
+ OpenCLFilterContext *ctx = avctx->priv; |
|
133 |
+ cl_int cle; |
|
134 |
+ |
|
135 |
+ if (ctx->program) { |
|
136 |
+ cle = clReleaseProgram(ctx->program); |
|
137 |
+ if (cle != CL_SUCCESS) |
|
138 |
+ av_log(avctx, AV_LOG_ERROR, "Failed to release " |
|
139 |
+ "program: %d.\n", cle); |
|
140 |
+ } |
|
141 |
+ |
|
142 |
+ av_buffer_unref(&ctx->device_ref); |
|
143 |
+} |
|
144 |
+ |
|
145 |
+int ff_opencl_filter_load_program(AVFilterContext *avctx, |
|
146 |
+ const char **program_source_array, |
|
147 |
+ int nb_strings) |
|
148 |
+{ |
|
149 |
+ OpenCLFilterContext *ctx = avctx->priv; |
|
150 |
+ cl_int cle; |
|
151 |
+ |
|
152 |
+ ctx->program = clCreateProgramWithSource(ctx->hwctx->context, nb_strings, |
|
153 |
+ program_source_array, |
|
154 |
+ NULL, &cle); |
|
155 |
+ if (!ctx->program) { |
|
156 |
+ av_log(avctx, AV_LOG_ERROR, "Failed to create program: %d.\n", cle); |
|
157 |
+ return AVERROR(EIO); |
|
158 |
+ } |
|
159 |
+ |
|
160 |
+ cle = clBuildProgram(ctx->program, 1, &ctx->hwctx->device_id, |
|
161 |
+ NULL, NULL, NULL); |
|
162 |
+ if (cle != CL_SUCCESS) { |
|
163 |
+ av_log(avctx, AV_LOG_ERROR, "Failed to build program: %d.\n", cle); |
|
164 |
+ |
|
165 |
+ if (cle == CL_BUILD_PROGRAM_FAILURE) { |
|
166 |
+ char *log; |
|
167 |
+ size_t log_length; |
|
168 |
+ |
|
169 |
+ clGetProgramBuildInfo(ctx->program, ctx->hwctx->device_id, |
|
170 |
+ CL_PROGRAM_BUILD_LOG, 0, NULL, &log_length); |
|
171 |
+ |
|
172 |
+ log = av_malloc(log_length); |
|
173 |
+ if (log) { |
|
174 |
+ cle = clGetProgramBuildInfo(ctx->program, |
|
175 |
+ ctx->hwctx->device_id, |
|
176 |
+ CL_PROGRAM_BUILD_LOG, |
|
177 |
+ log_length, log, NULL); |
|
178 |
+ if (cle == CL_SUCCESS) |
|
179 |
+ av_log(avctx, AV_LOG_ERROR, "Build log:\n%s\n", log); |
|
180 |
+ } |
|
181 |
+ |
|
182 |
+ av_free(log); |
|
183 |
+ } |
|
184 |
+ |
|
185 |
+ clReleaseProgram(ctx->program); |
|
186 |
+ ctx->program = NULL; |
|
187 |
+ return AVERROR(EIO); |
|
188 |
+ } |
|
189 |
+ |
|
190 |
+ return 0; |
|
191 |
+} |
|
192 |
+ |
|
193 |
+int ff_opencl_filter_load_program_from_file(AVFilterContext *avctx, |
|
194 |
+ const char *filename) |
|
195 |
+{ |
|
196 |
+ FILE *file; |
|
197 |
+ char *src = NULL; |
|
198 |
+ size_t pos, len, rb; |
|
199 |
+ const char *src_const; |
|
200 |
+ int err; |
|
201 |
+ |
|
202 |
+ file = fopen(filename, "r"); |
|
203 |
+ if (!file) { |
|
204 |
+ av_log(avctx, AV_LOG_ERROR, "Unable to open program " |
|
205 |
+ "source file \"%s\".\n", filename); |
|
206 |
+ return AVERROR(ENOENT); |
|
207 |
+ } |
|
208 |
+ |
|
209 |
+ len = 1 << 16; |
|
210 |
+ pos = 0; |
|
211 |
+ |
|
212 |
+ err = av_reallocp(&src, len); |
|
213 |
+ if (err < 0) |
|
214 |
+ goto fail; |
|
215 |
+ |
|
216 |
+ err = snprintf(src, len, "#line 1 \"%s\"\n", filename); |
|
217 |
+ if (err < 0) { |
|
218 |
+ err = AVERROR(errno); |
|
219 |
+ goto fail; |
|
220 |
+ } |
|
221 |
+ if (err > len / 2) { |
|
222 |
+ err = AVERROR(EINVAL); |
|
223 |
+ goto fail; |
|
224 |
+ } |
|
225 |
+ pos = err; |
|
226 |
+ |
|
227 |
+ while (1) { |
|
228 |
+ rb = fread(src + pos, 1, len - pos - 1, file); |
|
229 |
+ if (rb == 0 && ferror(file)) { |
|
230 |
+ err = AVERROR(EIO); |
|
231 |
+ goto fail; |
|
232 |
+ } |
|
233 |
+ pos += rb; |
|
234 |
+ if (pos < len) |
|
235 |
+ break; |
|
236 |
+ len <<= 1; |
|
237 |
+ err = av_reallocp(&src, len); |
|
238 |
+ if (err < 0) |
|
239 |
+ goto fail; |
|
240 |
+ } |
|
241 |
+ src[pos] = 0; |
|
242 |
+ |
|
243 |
+ src_const = src; |
|
244 |
+ |
|
245 |
+ err = ff_opencl_filter_load_program(avctx, &src_const, 1); |
|
246 |
+fail: |
|
247 |
+ fclose(file); |
|
248 |
+ av_freep(&src); |
|
249 |
+ return err; |
|
250 |
+} |
0 | 251 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,87 @@ |
0 |
+/* |
|
1 |
+ * This file is part of FFmpeg. |
|
2 |
+ * |
|
3 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
4 |
+ * modify it under the terms of the GNU Lesser General Public |
|
5 |
+ * License as published by the Free Software Foundation; either |
|
6 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
7 |
+ * |
|
8 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
9 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
11 |
+ * Lesser General Public License for more details. |
|
12 |
+ * |
|
13 |
+ * You should have received a copy of the GNU Lesser General Public |
|
14 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
15 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
16 |
+ */ |
|
17 |
+ |
|
18 |
+#ifndef AVFILTER_OPENCL_H |
|
19 |
+#define AVFILTER_OPENCL_H |
|
20 |
+ |
|
21 |
+#include "libavutil/buffer.h" |
|
22 |
+#include "libavutil/hwcontext.h" |
|
23 |
+#include "libavutil/hwcontext_opencl.h" |
|
24 |
+#include "libavutil/pixfmt.h" |
|
25 |
+ |
|
26 |
+#include "avfilter.h" |
|
27 |
+ |
|
28 |
+typedef struct OpenCLFilterContext { |
|
29 |
+ const AVClass *class; |
|
30 |
+ |
|
31 |
+ AVBufferRef *device_ref; |
|
32 |
+ AVHWDeviceContext *device; |
|
33 |
+ AVOpenCLDeviceContext *hwctx; |
|
34 |
+ |
|
35 |
+ cl_program program; |
|
36 |
+ |
|
37 |
+ enum AVPixelFormat output_format; |
|
38 |
+ int output_width; |
|
39 |
+ int output_height; |
|
40 |
+} OpenCLFilterContext; |
|
41 |
+ |
|
42 |
+/** |
|
43 |
+ * Return that all inputs and outputs support only AV_PIX_FMT_OPENCL. |
|
44 |
+ */ |
|
45 |
+int ff_opencl_filter_query_formats(AVFilterContext *avctx); |
|
46 |
+ |
|
47 |
+/** |
|
48 |
+ * Check that the input link contains a suitable hardware frames |
|
49 |
+ * context and extract the device from it. |
|
50 |
+ */ |
|
51 |
+int ff_opencl_filter_config_input(AVFilterLink *inlink); |
|
52 |
+ |
|
53 |
+/** |
|
54 |
+ * Create a suitable hardware frames context for the output. |
|
55 |
+ */ |
|
56 |
+int ff_opencl_filter_config_output(AVFilterLink *outlink); |
|
57 |
+ |
|
58 |
+/** |
|
59 |
+ * Initialise an OpenCL filter context. |
|
60 |
+ */ |
|
61 |
+int ff_opencl_filter_init(AVFilterContext *avctx); |
|
62 |
+ |
|
63 |
+/** |
|
64 |
+ * Uninitialise an OpenCL filter context. |
|
65 |
+ */ |
|
66 |
+void ff_opencl_filter_uninit(AVFilterContext *avctx); |
|
67 |
+ |
|
68 |
+/** |
|
69 |
+ * Load a new OpenCL program from strings in memory. |
|
70 |
+ * |
|
71 |
+ * Creates a new program and compiles it for the current device. |
|
72 |
+ * Will log any build errors if compilation fails. |
|
73 |
+ */ |
|
74 |
+int ff_opencl_filter_load_program(AVFilterContext *avctx, |
|
75 |
+ const char **program_source_array, |
|
76 |
+ int nb_strings); |
|
77 |
+ |
|
78 |
+/** |
|
79 |
+ * Load a new OpenCL program from a file. |
|
80 |
+ * |
|
81 |
+ * Same as ff_opencl_filter_load_program(), but from a file. |
|
82 |
+ */ |
|
83 |
+int ff_opencl_filter_load_program_from_file(AVFilterContext *avctx, |
|
84 |
+ const char *filename); |
|
85 |
+ |
|
86 |
+#endif /* AVFILTER_OPENCL_H */ |