FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
opencl.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
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.
8  *
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.
13  *
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
17  */
18 
19 #include <stdio.h>
20 #include <string.h>
21 
22 #include "libavutil/hwcontext.h"
24 #include "libavutil/mem.h"
25 
26 #include "avfilter.h"
27 #include "formats.h"
28 #include "opencl.h"
29 
31 {
32  const static enum AVPixelFormat pix_fmts[] = {
35  };
37 
38  formats = ff_make_format_list(pix_fmts);
39  if (!formats)
40  return AVERROR(ENOMEM);
41 
42  return ff_set_common_formats(avctx, formats);
43 }
44 
46  AVBufferRef *device)
47 {
48  OpenCLFilterContext *ctx = avctx->priv;
49 
51 
52  ctx->device_ref = av_buffer_ref(device);
53  if (!ctx->device_ref)
54  return AVERROR(ENOMEM);
55 
56  ctx->device = (AVHWDeviceContext*)ctx->device_ref->data;
57  ctx->hwctx = ctx->device->hwctx;
58 
59  return 0;
60 }
61 
63 {
64  AVFilterContext *avctx = inlink->dst;
65  OpenCLFilterContext *ctx = avctx->priv;
66  AVHWFramesContext *input_frames;
67  int err;
68 
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);
73  }
74 
75  // Extract the device and default output format from the first input.
76  if (avctx->inputs[0] != inlink)
77  return 0;
78 
79  input_frames = (AVHWFramesContext*)inlink->hw_frames_ctx->data;
80  if (input_frames->format != AV_PIX_FMT_OPENCL)
81  return AVERROR(EINVAL);
82 
83  err = opencl_filter_set_device(avctx, input_frames->device_ref);
84  if (err < 0)
85  return err;
86 
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;
94 
95  return 0;
96 }
97 
99 {
100  AVFilterContext *avctx = outlink->src;
101  OpenCLFilterContext *ctx = avctx->priv;
102  AVBufferRef *output_frames_ref = NULL;
103  AVHWFramesContext *output_frames;
104  int err;
105 
106  av_buffer_unref(&outlink->hw_frames_ctx);
107 
108  if (!ctx->device_ref) {
109  if (!avctx->hw_device_ctx) {
110  av_log(avctx, AV_LOG_ERROR, "OpenCL filtering requires an "
111  "OpenCL device.\n");
112  return AVERROR(EINVAL);
113  }
114 
115  err = opencl_filter_set_device(avctx, avctx->hw_device_ctx);
116  if (err < 0)
117  return err;
118  }
119 
120  output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref);
121  if (!output_frames_ref) {
122  err = AVERROR(ENOMEM);
123  goto fail;
124  }
125  output_frames = (AVHWFramesContext*)output_frames_ref->data;
126 
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;
131 
132  err = av_hwframe_ctx_init(output_frames_ref);
133  if (err < 0) {
134  av_log(avctx, AV_LOG_ERROR, "Failed to initialise output "
135  "frames: %d.\n", err);
136  goto fail;
137  }
138 
139  outlink->hw_frames_ctx = output_frames_ref;
140  outlink->w = ctx->output_width;
141  outlink->h = ctx->output_height;
142 
143  return 0;
144 fail:
145  av_buffer_unref(&output_frames_ref);
146  return err;
147 }
148 
150 {
151  OpenCLFilterContext *ctx = avctx->priv;
152 
154 
155  return 0;
156 }
157 
159 {
160  OpenCLFilterContext *ctx = avctx->priv;
161  cl_int cle;
162 
163  if (ctx->program) {
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);
168  }
169 
171 }
172 
174  const char **program_source_array,
175  int nb_strings)
176 {
177  OpenCLFilterContext *ctx = avctx->priv;
178  cl_int cle;
179 
180  ctx->program = clCreateProgramWithSource(ctx->hwctx->context, nb_strings,
181  program_source_array,
182  NULL, &cle);
183  if (!ctx->program) {
184  av_log(avctx, AV_LOG_ERROR, "Failed to create program: %d.\n", cle);
185  return AVERROR(EIO);
186  }
187 
188  cle = clBuildProgram(ctx->program, 1, &ctx->hwctx->device_id,
189  NULL, NULL, NULL);
190  if (cle != CL_SUCCESS) {
191  av_log(avctx, AV_LOG_ERROR, "Failed to build program: %d.\n", cle);
192 
193  if (cle == CL_BUILD_PROGRAM_FAILURE) {
194  char *log;
195  size_t log_length;
196 
197  clGetProgramBuildInfo(ctx->program, ctx->hwctx->device_id,
198  CL_PROGRAM_BUILD_LOG, 0, NULL, &log_length);
199 
200  log = av_malloc(log_length);
201  if (log) {
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);
208  }
209 
210  av_free(log);
211  }
212 
213  clReleaseProgram(ctx->program);
214  ctx->program = NULL;
215  return AVERROR(EIO);
216  }
217 
218  return 0;
219 }
220 
222  const char *filename)
223 {
224  FILE *file;
225  char *src = NULL;
226  size_t pos, len, rb;
227  const char *src_const;
228  int err;
229 
230  file = fopen(filename, "r");
231  if (!file) {
232  av_log(avctx, AV_LOG_ERROR, "Unable to open program "
233  "source file \"%s\".\n", filename);
234  return AVERROR(ENOENT);
235  }
236 
237  len = 1 << 16;
238  pos = 0;
239 
240  err = av_reallocp(&src, len);
241  if (err < 0)
242  goto fail;
243 
244  err = snprintf(src, len, "#line 1 \"%s\"\n", filename);
245  if (err < 0) {
246  err = AVERROR(errno);
247  goto fail;
248  }
249  if (err > len / 2) {
250  err = AVERROR(EINVAL);
251  goto fail;
252  }
253  pos = err;
254 
255  while (1) {
256  rb = fread(src + pos, 1, len - pos - 1, file);
257  if (rb == 0 && ferror(file)) {
258  err = AVERROR(EIO);
259  goto fail;
260  }
261  pos += rb;
262  if (pos < len)
263  break;
264  len <<= 1;
265  err = av_reallocp(&src, len);
266  if (err < 0)
267  goto fail;
268  }
269  src[pos] = 0;
270 
271  src_const = src;
272 
273  err = ff_opencl_filter_load_program(avctx, &src_const, 1);
274 fail:
275  fclose(file);
276  av_freep(&src);
277  return err;
278 }
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
API-specific header for AV_HWDEVICE_TYPE_OPENCL.
#define NULL
Definition: coverity.c:32
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it...
Definition: buffer.c:125
int ff_opencl_filter_config_input(AVFilterLink *inlink)
Check that the input link contains a suitable hardware frames context and extract the device from it...
Definition: opencl.c:62
int ff_opencl_filter_query_formats(AVFilterContext *avctx)
Return that all inputs and outputs support only AV_PIX_FMT_OPENCL.
Definition: opencl.c:30
Main libavfilter public API header.
Memory handling functions.
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:228
AVBufferRef * hw_device_ctx
For filters which will create hardware frames, sets the device the filter should create them in...
Definition: avfilter.h:394
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:208
#define src
Definition: vp8dsp.c:254
int ff_opencl_filter_init(AVFilterContext *avctx)
Initialise an OpenCL filter context.
Definition: opencl.c:149
AVOpenCLDeviceContext * hwctx
Definition: opencl.h:34
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:346
#define av_malloc(s)
cl_device_id device_id
The primary device ID of the device.
AVHWDeviceContext * device
Definition: opencl.h:33
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:91
int ff_opencl_filter_config_output(AVFilterLink *outlink)
Create a suitable hardware frames context for the output.
Definition: opencl.c:98
#define av_log(a,...)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:568
#define AVERROR(e)
Definition: error.h:43
void * priv
private data for use by the filter
Definition: avfilter.h:353
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:329
#define fail()
Definition: checkasm.h:113
enum AVPixelFormat output_format
Definition: opencl.h:38
AVFormatContext * ctx
Definition: movenc.c:48
static int opencl_filter_set_device(AVFilterContext *avctx, AVBufferRef *device)
Definition: opencl.c:45
Hardware surfaces for OpenCL.
Definition: pixfmt.h:331
int ff_opencl_filter_load_program_from_file(AVFilterContext *avctx, const char *filename)
Load a new OpenCL program from a file.
Definition: opencl.c:221
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition: mem.c:163
uint8_t * data
The data buffer.
Definition: buffer.h:89
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:123
#define snprintf
Definition: snprintf.h:34
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:266
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition: hwcontext.h:140
A reference to a data buffer.
Definition: buffer.h:81
if(ret< 0)
Definition: vf_mcdeint.c:279
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:243
void ff_opencl_filter_uninit(AVFilterContext *avctx)
Uninitialise an OpenCL filter context.
Definition: opencl.c:158
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
AVBufferRef * device_ref
Definition: opencl.h:32
#define av_free(p)
int len
cl_context context
The OpenCL context which will contain all operations and frames on this device.
A list of supported formats for one end of a filter link.
Definition: formats.h:64
An instance of a filter.
Definition: avfilter.h:338
#define av_freep(p)
cl_program program
Definition: opencl.h:36
formats
Definition: signature.h:48
int ff_opencl_filter_load_program(AVFilterContext *avctx, const char **program_source_array, int nb_strings)
Load a new OpenCL program from strings in memory.
Definition: opencl.c:173
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:221
AVPixelFormat
Pixel format.
Definition: pixfmt.h:60