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/mem.h"
23 #include "libavutil/pixdesc.h"
24 
25 #include "formats.h"
26 #include "opencl.h"
27 
29 {
30  const static enum AVPixelFormat pix_fmts[] = {
33  };
35 
36  formats = ff_make_format_list(pix_fmts);
37  if (!formats)
38  return AVERROR(ENOMEM);
39 
40  return ff_set_common_formats(avctx, formats);
41 }
42 
44  AVBufferRef *device)
45 {
46  OpenCLFilterContext *ctx = avctx->priv;
47 
49 
50  ctx->device_ref = av_buffer_ref(device);
51  if (!ctx->device_ref)
52  return AVERROR(ENOMEM);
53 
54  ctx->device = (AVHWDeviceContext*)ctx->device_ref->data;
55  ctx->hwctx = ctx->device->hwctx;
56 
57  return 0;
58 }
59 
61 {
62  AVFilterContext *avctx = inlink->dst;
63  OpenCLFilterContext *ctx = avctx->priv;
64  AVHWFramesContext *input_frames;
65  int err;
66 
67  if (!inlink->hw_frames_ctx) {
68  av_log(avctx, AV_LOG_ERROR, "OpenCL filtering requires a "
69  "hardware frames context on the input.\n");
70  return AVERROR(EINVAL);
71  }
72 
73  // Extract the device and default output format from the first input.
74  if (avctx->inputs[0] != inlink)
75  return 0;
76 
77  input_frames = (AVHWFramesContext*)inlink->hw_frames_ctx->data;
78  if (input_frames->format != AV_PIX_FMT_OPENCL)
79  return AVERROR(EINVAL);
80 
81  err = opencl_filter_set_device(avctx, input_frames->device_ref);
82  if (err < 0)
83  return err;
84 
85  // Default output parameters match input parameters.
86  if (ctx->output_format == AV_PIX_FMT_NONE)
87  ctx->output_format = input_frames->sw_format;
88  if (!ctx->output_width)
89  ctx->output_width = inlink->w;
90  if (!ctx->output_height)
91  ctx->output_height = inlink->h;
92 
93  return 0;
94 }
95 
97 {
98  AVFilterContext *avctx = outlink->src;
99  OpenCLFilterContext *ctx = avctx->priv;
100  AVBufferRef *output_frames_ref = NULL;
101  AVHWFramesContext *output_frames;
102  int err;
103 
104  av_buffer_unref(&outlink->hw_frames_ctx);
105 
106  if (!ctx->device_ref) {
107  if (!avctx->hw_device_ctx) {
108  av_log(avctx, AV_LOG_ERROR, "OpenCL filtering requires an "
109  "OpenCL device.\n");
110  return AVERROR(EINVAL);
111  }
112 
113  err = opencl_filter_set_device(avctx, avctx->hw_device_ctx);
114  if (err < 0)
115  return err;
116  }
117 
118  output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref);
119  if (!output_frames_ref) {
120  err = AVERROR(ENOMEM);
121  goto fail;
122  }
123  output_frames = (AVHWFramesContext*)output_frames_ref->data;
124 
125  output_frames->format = AV_PIX_FMT_OPENCL;
126  output_frames->sw_format = ctx->output_format;
127  output_frames->width = ctx->output_width;
128  output_frames->height = ctx->output_height;
129 
130  err = av_hwframe_ctx_init(output_frames_ref);
131  if (err < 0) {
132  av_log(avctx, AV_LOG_ERROR, "Failed to initialise output "
133  "frames: %d.\n", err);
134  goto fail;
135  }
136 
137  outlink->hw_frames_ctx = output_frames_ref;
138  outlink->w = ctx->output_width;
139  outlink->h = ctx->output_height;
140 
141  return 0;
142 fail:
143  av_buffer_unref(&output_frames_ref);
144  return err;
145 }
146 
148 {
149  OpenCLFilterContext *ctx = avctx->priv;
150 
152 
153  return 0;
154 }
155 
157 {
158  OpenCLFilterContext *ctx = avctx->priv;
159  cl_int cle;
160 
161  if (ctx->program) {
162  cle = clReleaseProgram(ctx->program);
163  if (cle != CL_SUCCESS)
164  av_log(avctx, AV_LOG_ERROR, "Failed to release "
165  "program: %d.\n", cle);
166  }
167 
169 }
170 
172  const char **program_source_array,
173  int nb_strings)
174 {
175  OpenCLFilterContext *ctx = avctx->priv;
176  cl_int cle;
177 
178  ctx->program = clCreateProgramWithSource(ctx->hwctx->context, nb_strings,
179  program_source_array,
180  NULL, &cle);
181  if (!ctx->program) {
182  av_log(avctx, AV_LOG_ERROR, "Failed to create program: %d.\n", cle);
183  return AVERROR(EIO);
184  }
185 
186  cle = clBuildProgram(ctx->program, 1, &ctx->hwctx->device_id,
187  NULL, NULL, NULL);
188  if (cle != CL_SUCCESS) {
189  av_log(avctx, AV_LOG_ERROR, "Failed to build program: %d.\n", cle);
190 
191  if (cle == CL_BUILD_PROGRAM_FAILURE) {
192  char *log;
193  size_t log_length;
194 
195  clGetProgramBuildInfo(ctx->program, ctx->hwctx->device_id,
196  CL_PROGRAM_BUILD_LOG, 0, NULL, &log_length);
197 
198  log = av_malloc(log_length);
199  if (log) {
200  cle = clGetProgramBuildInfo(ctx->program,
201  ctx->hwctx->device_id,
202  CL_PROGRAM_BUILD_LOG,
203  log_length, log, NULL);
204  if (cle == CL_SUCCESS)
205  av_log(avctx, AV_LOG_ERROR, "Build log:\n%s\n", log);
206  }
207 
208  av_free(log);
209  }
210 
211  clReleaseProgram(ctx->program);
212  ctx->program = NULL;
213  return AVERROR(EIO);
214  }
215 
216  return 0;
217 }
218 
220  const char *filename)
221 {
222  FILE *file;
223  char *src = NULL;
224  size_t pos, len, rb;
225  const char *src_const;
226  int err;
227 
228  file = fopen(filename, "r");
229  if (!file) {
230  av_log(avctx, AV_LOG_ERROR, "Unable to open program "
231  "source file \"%s\".\n", filename);
232  return AVERROR(ENOENT);
233  }
234 
235  len = 1 << 16;
236  pos = 0;
237 
238  err = av_reallocp(&src, len);
239  if (err < 0)
240  goto fail;
241 
242  err = snprintf(src, len, "#line 1 \"%s\"\n", filename);
243  if (err < 0) {
244  err = AVERROR(errno);
245  goto fail;
246  }
247  if (err > len / 2) {
248  err = AVERROR(EINVAL);
249  goto fail;
250  }
251  pos = err;
252 
253  while (1) {
254  rb = fread(src + pos, 1, len - pos - 1, file);
255  if (rb == 0 && ferror(file)) {
256  err = AVERROR(EIO);
257  goto fail;
258  }
259  pos += rb;
260  if (pos < len)
261  break;
262  len <<= 1;
263  err = av_reallocp(&src, len);
264  if (err < 0)
265  goto fail;
266  }
267  src[pos] = 0;
268 
269  src_const = src;
270 
271  err = ff_opencl_filter_load_program(avctx, &src_const, 1);
272 fail:
273  fclose(file);
274  av_freep(&src);
275  return err;
276 }
277 
279  size_t *work_size,
280  AVFrame *frame, int plane,
281  int block_alignment)
282 {
283  cl_mem image;
284  cl_mem_object_type type;
285  size_t width, height;
286  cl_int cle;
287 
288  if (frame->format != AV_PIX_FMT_OPENCL) {
289  av_log(avctx, AV_LOG_ERROR, "Invalid frame format %s, "
290  "opencl required.\n", av_get_pix_fmt_name(frame->format));
291  return AVERROR(EINVAL);
292  }
293 
294  image = (cl_mem)frame->data[plane];
295  if (!image) {
296  av_log(avctx, AV_LOG_ERROR, "Plane %d required but not set.\n",
297  plane);
298  return AVERROR(EINVAL);
299  }
300 
301  cle = clGetMemObjectInfo(image, CL_MEM_TYPE, sizeof(type),
302  &type, NULL);
303  if (cle != CL_SUCCESS) {
304  av_log(avctx, AV_LOG_ERROR, "Failed to query object type of "
305  "plane %d: %d.\n", plane, cle);
306  return AVERROR_UNKNOWN;
307  }
308  if (type != CL_MEM_OBJECT_IMAGE2D) {
309  av_log(avctx, AV_LOG_ERROR, "Plane %d is not a 2D image.\n",
310  plane);
311  return AVERROR(EINVAL);
312  }
313 
314  cle = clGetImageInfo(image, CL_IMAGE_WIDTH, sizeof(size_t),
315  &width, NULL);
316  if (cle != CL_SUCCESS) {
317  av_log(avctx, AV_LOG_ERROR, "Failed to query plane %d width: %d.\n",
318  plane, cle);
319  return AVERROR_UNKNOWN;
320  }
321 
322  cle = clGetImageInfo(image, CL_IMAGE_HEIGHT, sizeof(size_t),
323  &height, NULL);
324  if (cle != CL_SUCCESS) {
325  av_log(avctx, AV_LOG_ERROR, "Failed to query plane %d height: %d.\n",
326  plane, cle);
327  return AVERROR_UNKNOWN;
328  }
329 
330  if (block_alignment) {
331  width = FFALIGN(width, block_alignment);
332  height = FFALIGN(height, block_alignment);
333  }
334 
335  work_size[0] = width;
336  work_size[1] = height;
337 
338  return 0;
339 }
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
int plane
Definition: avisynth_c.h:422
#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
This structure describes decoded (raw) audio or video data.
Definition: frame.h:218
int ff_opencl_filter_work_size_from_image(AVFilterContext *avctx, size_t *work_size, AVFrame *frame, int plane, int block_alignment)
Find the work size needed needed for a given plane of an image.
Definition: opencl.c:278
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:60
int ff_opencl_filter_query_formats(AVFilterContext *avctx)
Return that all inputs and outputs support only AV_PIX_FMT_OPENCL.
Definition: opencl.c:28
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:147
AVOpenCLDeviceContext * hwctx
Definition: opencl.h:40
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:39
static AVFrame * frame
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:91
#define height
int ff_opencl_filter_config_output(AVFilterLink *outlink)
Create a suitable hardware frames context for the output.
Definition: opencl.c:96
#define FFALIGN(x, a)
Definition: macros.h:48
#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
uint16_t width
Definition: gdv.c:47
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:329
#define fail()
Definition: checkasm.h:117
enum AVPixelFormat output_format
Definition: opencl.h:44
AVFormatContext * ctx
Definition: movenc.c:48
static int opencl_filter_set_device(AVFilterContext *avctx, AVBufferRef *device)
Definition: opencl.c:43
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:219
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:291
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
GLint GLenum type
Definition: opengl_enc.c:105
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
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:232
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:156
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
AVBufferRef * device_ref
Definition: opencl.h:38
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
#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:42
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:171
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:2300
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