2 * This file is part of FFmpeg.
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libavutil/hwcontext.h"
23 #include "libavutil/hwcontext_opencl.h"
24 #include "libavutil/mem.h"
30 int ff_opencl_filter_query_formats(AVFilterContext *avctx)
32 const static enum AVPixelFormat pix_fmts[] = {
36 AVFilterFormats *formats;
38 formats = ff_make_format_list(pix_fmts);
40 return AVERROR(ENOMEM);
42 return ff_set_common_formats(avctx, formats);
45 static int opencl_filter_set_device(AVFilterContext *avctx,
48 OpenCLFilterContext *ctx = avctx->priv;
50 av_buffer_unref(&ctx->device_ref);
52 ctx->device_ref = av_buffer_ref(device);
54 return AVERROR(ENOMEM);
56 ctx->device = (AVHWDeviceContext*)ctx->device_ref->data;
57 ctx->hwctx = ctx->device->hwctx;
62 int ff_opencl_filter_config_input(AVFilterLink *inlink)
64 AVFilterContext *avctx = inlink->dst;
65 OpenCLFilterContext *ctx = avctx->priv;
66 AVHWFramesContext *input_frames;
69 if (!inlink->hw_frames_ctx) {
70 av_log(avctx, AV_LOG_ERROR, "OpenCL filtering requires a "
71 "hardware frames context on the input.\n");
72 return AVERROR(EINVAL);
75 // Extract the device and default output format from the first input.
76 if (avctx->inputs[0] != inlink)
79 input_frames = (AVHWFramesContext*)inlink->hw_frames_ctx->data;
80 if (input_frames->format != AV_PIX_FMT_OPENCL)
81 return AVERROR(EINVAL);
83 err = opencl_filter_set_device(avctx, input_frames->device_ref);
87 // Default output parameters match input parameters.
88 if (ctx->output_format == AV_PIX_FMT_NONE)
89 ctx->output_format = input_frames->sw_format;
90 if (!ctx->output_width)
91 ctx->output_width = inlink->w;
92 if (!ctx->output_height)
93 ctx->output_height = inlink->h;
98 int ff_opencl_filter_config_output(AVFilterLink *outlink)
100 AVFilterContext *avctx = outlink->src;
101 OpenCLFilterContext *ctx = avctx->priv;
102 AVBufferRef *output_frames_ref = NULL;
103 AVHWFramesContext *output_frames;
106 av_buffer_unref(&outlink->hw_frames_ctx);
108 if (!ctx->device_ref) {
109 if (!avctx->hw_device_ctx) {
110 av_log(avctx, AV_LOG_ERROR, "OpenCL filtering requires an "
112 return AVERROR(EINVAL);
115 err = opencl_filter_set_device(avctx, avctx->hw_device_ctx);
120 output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref);
121 if (!output_frames_ref) {
122 err = AVERROR(ENOMEM);
125 output_frames = (AVHWFramesContext*)output_frames_ref->data;
127 output_frames->format = AV_PIX_FMT_OPENCL;
128 output_frames->sw_format = ctx->output_format;
129 output_frames->width = ctx->output_width;
130 output_frames->height = ctx->output_height;
132 err = av_hwframe_ctx_init(output_frames_ref);
134 av_log(avctx, AV_LOG_ERROR, "Failed to initialise output "
135 "frames: %d.\n", err);
139 outlink->hw_frames_ctx = output_frames_ref;
140 outlink->w = ctx->output_width;
141 outlink->h = ctx->output_height;
145 av_buffer_unref(&output_frames_ref);
149 int ff_opencl_filter_init(AVFilterContext *avctx)
151 OpenCLFilterContext *ctx = avctx->priv;
153 ctx->output_format = AV_PIX_FMT_NONE;
158 void ff_opencl_filter_uninit(AVFilterContext *avctx)
160 OpenCLFilterContext *ctx = avctx->priv;
164 cle = clReleaseProgram(ctx->program);
165 if (cle != CL_SUCCESS)
166 av_log(avctx, AV_LOG_ERROR, "Failed to release "
167 "program: %d.\n", cle);
170 av_buffer_unref(&ctx->device_ref);
173 int ff_opencl_filter_load_program(AVFilterContext *avctx,
174 const char **program_source_array,
177 OpenCLFilterContext *ctx = avctx->priv;
180 ctx->program = clCreateProgramWithSource(ctx->hwctx->context, nb_strings,
181 program_source_array,
184 av_log(avctx, AV_LOG_ERROR, "Failed to create program: %d.\n", cle);
188 cle = clBuildProgram(ctx->program, 1, &ctx->hwctx->device_id,
190 if (cle != CL_SUCCESS) {
191 av_log(avctx, AV_LOG_ERROR, "Failed to build program: %d.\n", cle);
193 if (cle == CL_BUILD_PROGRAM_FAILURE) {
197 clGetProgramBuildInfo(ctx->program, ctx->hwctx->device_id,
198 CL_PROGRAM_BUILD_LOG, 0, NULL, &log_length);
200 log = av_malloc(log_length);
202 cle = clGetProgramBuildInfo(ctx->program,
203 ctx->hwctx->device_id,
204 CL_PROGRAM_BUILD_LOG,
205 log_length, log, NULL);
206 if (cle == CL_SUCCESS)
207 av_log(avctx, AV_LOG_ERROR, "Build log:\n%s\n", log);
213 clReleaseProgram(ctx->program);
221 int ff_opencl_filter_load_program_from_file(AVFilterContext *avctx,
222 const char *filename)
227 const char *src_const;
230 file = fopen(filename, "r");
232 av_log(avctx, AV_LOG_ERROR, "Unable to open program "
233 "source file \"%s\".\n", filename);
234 return AVERROR(ENOENT);
240 err = av_reallocp(&src, len);
244 err = snprintf(src, len, "#line 1 \"%s\"\n", filename);
246 err = AVERROR(errno);
250 err = AVERROR(EINVAL);
256 rb = fread(src + pos, 1, len - pos - 1, file);
257 if (rb == 0 && ferror(file)) {
265 err = av_reallocp(&src, len);
273 err = ff_opencl_filter_load_program(avctx, &src_const, 1);