opencl.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  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. #include <stdio.h>
  19. #include <string.h>
  20. #include "libavutil/file_open.h"
  21. #include "libavutil/mem.h"
  22. #include "libavutil/pixdesc.h"
  23. #include "formats.h"
  24. #include "opencl.h"
  25. static int opencl_filter_set_device(AVFilterContext *avctx,
  26. AVBufferRef *device)
  27. {
  28. OpenCLFilterContext *ctx = avctx->priv;
  29. av_buffer_unref(&ctx->device_ref);
  30. ctx->device_ref = av_buffer_ref(device);
  31. if (!ctx->device_ref)
  32. return AVERROR(ENOMEM);
  33. ctx->device = (AVHWDeviceContext*)ctx->device_ref->data;
  34. ctx->hwctx = ctx->device->hwctx;
  35. return 0;
  36. }
  37. int ff_opencl_filter_config_input(AVFilterLink *inlink)
  38. {
  39. AVFilterContext *avctx = inlink->dst;
  40. OpenCLFilterContext *ctx = avctx->priv;
  41. AVHWFramesContext *input_frames;
  42. int err;
  43. if (!inlink->hw_frames_ctx) {
  44. av_log(avctx, AV_LOG_ERROR, "OpenCL filtering requires a "
  45. "hardware frames context on the input.\n");
  46. return AVERROR(EINVAL);
  47. }
  48. // Extract the device and default output format from the first input.
  49. if (avctx->inputs[0] != inlink)
  50. return 0;
  51. input_frames = (AVHWFramesContext*)inlink->hw_frames_ctx->data;
  52. if (input_frames->format != AV_PIX_FMT_OPENCL)
  53. return AVERROR(EINVAL);
  54. err = opencl_filter_set_device(avctx, input_frames->device_ref);
  55. if (err < 0)
  56. return err;
  57. // Default output parameters match input parameters.
  58. if (ctx->output_format == AV_PIX_FMT_NONE)
  59. ctx->output_format = input_frames->sw_format;
  60. if (!ctx->output_width)
  61. ctx->output_width = inlink->w;
  62. if (!ctx->output_height)
  63. ctx->output_height = inlink->h;
  64. return 0;
  65. }
  66. int ff_opencl_filter_config_output(AVFilterLink *outlink)
  67. {
  68. AVFilterContext *avctx = outlink->src;
  69. OpenCLFilterContext *ctx = avctx->priv;
  70. AVBufferRef *output_frames_ref = NULL;
  71. AVHWFramesContext *output_frames;
  72. int err;
  73. av_buffer_unref(&outlink->hw_frames_ctx);
  74. if (!ctx->device_ref) {
  75. if (!avctx->hw_device_ctx) {
  76. av_log(avctx, AV_LOG_ERROR, "OpenCL filtering requires an "
  77. "OpenCL device.\n");
  78. return AVERROR(EINVAL);
  79. }
  80. err = opencl_filter_set_device(avctx, avctx->hw_device_ctx);
  81. if (err < 0)
  82. return err;
  83. }
  84. output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref);
  85. if (!output_frames_ref) {
  86. err = AVERROR(ENOMEM);
  87. goto fail;
  88. }
  89. output_frames = (AVHWFramesContext*)output_frames_ref->data;
  90. output_frames->format = AV_PIX_FMT_OPENCL;
  91. output_frames->sw_format = ctx->output_format;
  92. output_frames->width = ctx->output_width;
  93. output_frames->height = ctx->output_height;
  94. err = av_hwframe_ctx_init(output_frames_ref);
  95. if (err < 0) {
  96. av_log(avctx, AV_LOG_ERROR, "Failed to initialise output "
  97. "frames: %d.\n", err);
  98. goto fail;
  99. }
  100. outlink->hw_frames_ctx = output_frames_ref;
  101. outlink->w = ctx->output_width;
  102. outlink->h = ctx->output_height;
  103. return 0;
  104. fail:
  105. av_buffer_unref(&output_frames_ref);
  106. return err;
  107. }
  108. int ff_opencl_filter_init(AVFilterContext *avctx)
  109. {
  110. OpenCLFilterContext *ctx = avctx->priv;
  111. ctx->output_format = AV_PIX_FMT_NONE;
  112. return 0;
  113. }
  114. void ff_opencl_filter_uninit(AVFilterContext *avctx)
  115. {
  116. OpenCLFilterContext *ctx = avctx->priv;
  117. cl_int cle;
  118. if (ctx->program) {
  119. cle = clReleaseProgram(ctx->program);
  120. if (cle != CL_SUCCESS)
  121. av_log(avctx, AV_LOG_ERROR, "Failed to release "
  122. "program: %d.\n", cle);
  123. }
  124. av_buffer_unref(&ctx->device_ref);
  125. }
  126. int ff_opencl_filter_load_program(AVFilterContext *avctx,
  127. const char **program_source_array,
  128. int nb_strings)
  129. {
  130. OpenCLFilterContext *ctx = avctx->priv;
  131. cl_int cle;
  132. ctx->program = clCreateProgramWithSource(ctx->hwctx->context, nb_strings,
  133. program_source_array,
  134. NULL, &cle);
  135. if (!ctx->program) {
  136. av_log(avctx, AV_LOG_ERROR, "Failed to create program: %d.\n", cle);
  137. return AVERROR(EIO);
  138. }
  139. cle = clBuildProgram(ctx->program, 1, &ctx->hwctx->device_id,
  140. NULL, NULL, NULL);
  141. if (cle != CL_SUCCESS) {
  142. av_log(avctx, AV_LOG_ERROR, "Failed to build program: %d.\n", cle);
  143. if (cle == CL_BUILD_PROGRAM_FAILURE) {
  144. char *log;
  145. size_t log_length;
  146. clGetProgramBuildInfo(ctx->program, ctx->hwctx->device_id,
  147. CL_PROGRAM_BUILD_LOG, 0, NULL, &log_length);
  148. log = av_malloc(log_length);
  149. if (log) {
  150. cle = clGetProgramBuildInfo(ctx->program,
  151. ctx->hwctx->device_id,
  152. CL_PROGRAM_BUILD_LOG,
  153. log_length, log, NULL);
  154. if (cle == CL_SUCCESS)
  155. av_log(avctx, AV_LOG_ERROR, "Build log:\n%s\n", log);
  156. }
  157. av_free(log);
  158. }
  159. clReleaseProgram(ctx->program);
  160. ctx->program = NULL;
  161. return AVERROR(EIO);
  162. }
  163. return 0;
  164. }
  165. int ff_opencl_filter_load_program_from_file(AVFilterContext *avctx,
  166. const char *filename)
  167. {
  168. FILE *file;
  169. char *src = NULL;
  170. size_t pos, len, rb;
  171. const char *src_const;
  172. int err;
  173. file = avpriv_fopen_utf8(filename, "r");
  174. if (!file) {
  175. av_log(avctx, AV_LOG_ERROR, "Unable to open program "
  176. "source file \"%s\".\n", filename);
  177. return AVERROR(ENOENT);
  178. }
  179. len = 1 << 16;
  180. pos = 0;
  181. err = av_reallocp(&src, len);
  182. if (err < 0)
  183. goto fail;
  184. err = snprintf(src, len, "#line 1 \"%s\"\n", filename);
  185. if (err < 0) {
  186. err = AVERROR(errno);
  187. goto fail;
  188. }
  189. if (err > len / 2) {
  190. err = AVERROR(EINVAL);
  191. goto fail;
  192. }
  193. pos = err;
  194. while (1) {
  195. rb = fread(src + pos, 1, len - pos - 1, file);
  196. if (rb == 0 && ferror(file)) {
  197. err = AVERROR(EIO);
  198. goto fail;
  199. }
  200. pos += rb;
  201. if (pos + 1 < len)
  202. break;
  203. len <<= 1;
  204. err = av_reallocp(&src, len);
  205. if (err < 0)
  206. goto fail;
  207. }
  208. src[pos] = 0;
  209. src_const = src;
  210. err = ff_opencl_filter_load_program(avctx, &src_const, 1);
  211. fail:
  212. fclose(file);
  213. av_freep(&src);
  214. return err;
  215. }
  216. int ff_opencl_filter_work_size_from_image(AVFilterContext *avctx,
  217. size_t *work_size,
  218. AVFrame *frame, int plane,
  219. int block_alignment)
  220. {
  221. cl_mem image;
  222. cl_mem_object_type type;
  223. size_t width, height;
  224. cl_int cle;
  225. if (frame->format != AV_PIX_FMT_OPENCL) {
  226. av_log(avctx, AV_LOG_ERROR, "Invalid frame format %s, "
  227. "opencl required.\n", av_get_pix_fmt_name(frame->format));
  228. return AVERROR(EINVAL);
  229. }
  230. image = (cl_mem)frame->data[plane];
  231. if (!image) {
  232. av_log(avctx, AV_LOG_ERROR, "Plane %d required but not set.\n",
  233. plane);
  234. return AVERROR(EINVAL);
  235. }
  236. cle = clGetMemObjectInfo(image, CL_MEM_TYPE, sizeof(type),
  237. &type, NULL);
  238. if (cle != CL_SUCCESS) {
  239. av_log(avctx, AV_LOG_ERROR, "Failed to query object type of "
  240. "plane %d: %d.\n", plane, cle);
  241. return AVERROR_UNKNOWN;
  242. }
  243. if (type != CL_MEM_OBJECT_IMAGE2D) {
  244. av_log(avctx, AV_LOG_ERROR, "Plane %d is not a 2D image.\n",
  245. plane);
  246. return AVERROR(EINVAL);
  247. }
  248. cle = clGetImageInfo(image, CL_IMAGE_WIDTH, sizeof(size_t),
  249. &width, NULL);
  250. if (cle != CL_SUCCESS) {
  251. av_log(avctx, AV_LOG_ERROR, "Failed to query plane %d width: %d.\n",
  252. plane, cle);
  253. return AVERROR_UNKNOWN;
  254. }
  255. cle = clGetImageInfo(image, CL_IMAGE_HEIGHT, sizeof(size_t),
  256. &height, NULL);
  257. if (cle != CL_SUCCESS) {
  258. av_log(avctx, AV_LOG_ERROR, "Failed to query plane %d height: %d.\n",
  259. plane, cle);
  260. return AVERROR_UNKNOWN;
  261. }
  262. if (block_alignment) {
  263. width = FFALIGN(width, block_alignment);
  264. height = FFALIGN(height, block_alignment);
  265. }
  266. work_size[0] = width;
  267. work_size[1] = height;
  268. return 0;
  269. }
  270. void ff_opencl_print_const_matrix_3x3(AVBPrint *buf, const char *name_str,
  271. double mat[3][3])
  272. {
  273. int i, j;
  274. av_bprintf(buf, "__constant float %s[9] = {\n", name_str);
  275. for (i = 0; i < 3; i++) {
  276. for (j = 0; j < 3; j++)
  277. av_bprintf(buf, " %.5ff,", mat[i][j]);
  278. av_bprintf(buf, "\n");
  279. }
  280. av_bprintf(buf, "};\n");
  281. }
  282. cl_ulong ff_opencl_get_event_time(cl_event event) {
  283. cl_ulong time_start;
  284. cl_ulong time_end;
  285. clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START, sizeof(time_start), &time_start, NULL);
  286. clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END, sizeof(time_end), &time_end, NULL);
  287. return time_end - time_start;
  288. }