You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

182 lines
8.3KB

  1. /*
  2. * Copyright (C) 2013 Wei Gao <weigao@multicorewareinc.com>
  3. *
  4. * This file is part of FFmpeg.
  5. *
  6. * FFmpeg is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * FFmpeg is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with FFmpeg; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. /**
  21. * @file
  22. * transform input video
  23. */
  24. #include "libavutil/common.h"
  25. #include "libavutil/dict.h"
  26. #include "libavutil/pixdesc.h"
  27. #include "deshake_opencl.h"
  28. #define MATRIX_SIZE 6
  29. #define PLANE_NUM 3
  30. #define TRANSFORM_OPENCL_CHECK(method, ...) \
  31. status = method(__VA_ARGS__); \
  32. if (status != CL_SUCCESS) { \
  33. av_log(ctx, AV_LOG_ERROR, "error %s %d\n", # method, status); \
  34. return AVERROR_EXTERNAL; \
  35. }
  36. #define TRANSFORM_OPENCL_SET_KERNEL_ARG(arg_ptr) \
  37. status = clSetKernelArg((kernel),(arg_no++),(sizeof(arg_ptr)),(void*)(&(arg_ptr))); \
  38. if (status != CL_SUCCESS) { \
  39. av_log(ctx, AV_LOG_ERROR, "cannot set kernel argument: %d\n", status ); \
  40. return AVERROR_EXTERNAL; \
  41. }
  42. int ff_opencl_transform(AVFilterContext *ctx,
  43. int width, int height, int cw, int ch,
  44. const float *matrix_y, const float *matrix_uv,
  45. enum InterpolateMethod interpolate,
  46. enum FillMethod fill, AVFrame *in, AVFrame *out)
  47. {
  48. int arg_no, ret = 0;
  49. const size_t global_work_size = width * height + 2 * ch * cw;
  50. cl_kernel kernel;
  51. cl_int status;
  52. DeshakeContext *deshake = ctx->priv;
  53. ret = av_opencl_buffer_write(deshake->opencl_ctx.cl_matrix_y, (uint8_t *)matrix_y, deshake->opencl_ctx.matrix_size * sizeof(cl_float));
  54. if (ret < 0)
  55. return ret;
  56. ret = av_opencl_buffer_write(deshake->opencl_ctx.cl_matrix_uv, (uint8_t *)matrix_uv, deshake->opencl_ctx.matrix_size * sizeof(cl_float));
  57. if (ret < 0)
  58. return ret;
  59. kernel = deshake->opencl_ctx.kernel_env.kernel;
  60. arg_no = 0;
  61. if ((unsigned int)interpolate > INTERPOLATE_BIQUADRATIC) {
  62. av_log(ctx, AV_LOG_ERROR, "Selected interpolate method is invalid\n");
  63. return AVERROR(EINVAL);
  64. }
  65. TRANSFORM_OPENCL_SET_KERNEL_ARG(deshake->opencl_ctx.cl_inbuf);
  66. TRANSFORM_OPENCL_SET_KERNEL_ARG(deshake->opencl_ctx.cl_outbuf);
  67. TRANSFORM_OPENCL_SET_KERNEL_ARG(deshake->opencl_ctx.cl_matrix_y);
  68. TRANSFORM_OPENCL_SET_KERNEL_ARG(deshake->opencl_ctx.cl_matrix_uv);
  69. TRANSFORM_OPENCL_SET_KERNEL_ARG(interpolate);
  70. TRANSFORM_OPENCL_SET_KERNEL_ARG(fill);
  71. TRANSFORM_OPENCL_SET_KERNEL_ARG(in->linesize[0]);
  72. TRANSFORM_OPENCL_SET_KERNEL_ARG(out->linesize[0]);
  73. TRANSFORM_OPENCL_SET_KERNEL_ARG(in->linesize[1]);
  74. TRANSFORM_OPENCL_SET_KERNEL_ARG(out->linesize[1]);
  75. TRANSFORM_OPENCL_SET_KERNEL_ARG(height);
  76. TRANSFORM_OPENCL_SET_KERNEL_ARG(width);
  77. TRANSFORM_OPENCL_SET_KERNEL_ARG(ch);
  78. TRANSFORM_OPENCL_SET_KERNEL_ARG(cw);
  79. TRANSFORM_OPENCL_CHECK(clEnqueueNDRangeKernel, deshake->opencl_ctx.kernel_env.command_queue, deshake->opencl_ctx.kernel_env.kernel, 1, NULL,
  80. &global_work_size, NULL, 0, NULL, NULL);
  81. clFinish(deshake->opencl_ctx.kernel_env.command_queue);
  82. ret = av_opencl_buffer_read_image(out->data, deshake->opencl_ctx.out_plane_size,
  83. deshake->opencl_ctx.plane_num, deshake->opencl_ctx.cl_outbuf,
  84. deshake->opencl_ctx.cl_outbuf_size);
  85. if (ret < 0)
  86. return ret;
  87. return ret;
  88. }
  89. int ff_opencl_deshake_init(AVFilterContext *ctx)
  90. {
  91. int ret = 0;
  92. DeshakeContext *deshake = ctx->priv;
  93. AVDictionary *options = NULL;
  94. av_dict_set(&options, "build_options", "-I.", 0);
  95. ret = av_opencl_init(options, NULL);
  96. av_dict_free(&options);
  97. if (ret < 0)
  98. return ret;
  99. deshake->opencl_ctx.matrix_size = MATRIX_SIZE;
  100. deshake->opencl_ctx.plane_num = PLANE_NUM;
  101. ret = av_opencl_buffer_create(&deshake->opencl_ctx.cl_matrix_y,
  102. deshake->opencl_ctx.matrix_size*sizeof(cl_float), CL_MEM_READ_ONLY, NULL);
  103. if (ret < 0)
  104. return ret;
  105. ret = av_opencl_buffer_create(&deshake->opencl_ctx.cl_matrix_uv,
  106. deshake->opencl_ctx.matrix_size*sizeof(cl_float), CL_MEM_READ_ONLY, NULL);
  107. if (ret < 0)
  108. return ret;
  109. if (!deshake->opencl_ctx.kernel_env.kernel) {
  110. ret = av_opencl_create_kernel(&deshake->opencl_ctx.kernel_env, "avfilter_transform");
  111. if (ret < 0) {
  112. av_log(ctx, AV_LOG_ERROR, "OpenCL failed to create kernel for name 'avfilter_transform'\n");
  113. return ret;
  114. }
  115. }
  116. return ret;
  117. }
  118. void ff_opencl_deshake_uninit(AVFilterContext *ctx)
  119. {
  120. DeshakeContext *deshake = ctx->priv;
  121. av_opencl_buffer_release(&deshake->opencl_ctx.cl_inbuf);
  122. av_opencl_buffer_release(&deshake->opencl_ctx.cl_outbuf);
  123. av_opencl_buffer_release(&deshake->opencl_ctx.cl_matrix_y);
  124. av_opencl_buffer_release(&deshake->opencl_ctx.cl_matrix_uv);
  125. av_opencl_release_kernel(&deshake->opencl_ctx.kernel_env);
  126. av_opencl_uninit();
  127. }
  128. int ff_opencl_deshake_process_inout_buf(AVFilterContext *ctx, AVFrame *in, AVFrame *out)
  129. {
  130. int ret = 0;
  131. AVFilterLink *link = ctx->inputs[0];
  132. DeshakeContext *deshake = ctx->priv;
  133. int chroma_height = -((-link->h) >> av_pix_fmt_desc_get(link->format)->log2_chroma_h);
  134. if ((!deshake->opencl_ctx.cl_inbuf) || (!deshake->opencl_ctx.cl_outbuf)) {
  135. deshake->opencl_ctx.in_plane_size[0] = (in->linesize[0] * in->height);
  136. deshake->opencl_ctx.in_plane_size[1] = (in->linesize[1] * chroma_height);
  137. deshake->opencl_ctx.in_plane_size[2] = (in->linesize[2] * chroma_height);
  138. deshake->opencl_ctx.out_plane_size[0] = (out->linesize[0] * out->height);
  139. deshake->opencl_ctx.out_plane_size[1] = (out->linesize[1] * chroma_height);
  140. deshake->opencl_ctx.out_plane_size[2] = (out->linesize[2] * chroma_height);
  141. deshake->opencl_ctx.cl_inbuf_size = deshake->opencl_ctx.in_plane_size[0] +
  142. deshake->opencl_ctx.in_plane_size[1] +
  143. deshake->opencl_ctx.in_plane_size[2];
  144. deshake->opencl_ctx.cl_outbuf_size = deshake->opencl_ctx.out_plane_size[0] +
  145. deshake->opencl_ctx.out_plane_size[1] +
  146. deshake->opencl_ctx.out_plane_size[2];
  147. if (!deshake->opencl_ctx.cl_inbuf) {
  148. ret = av_opencl_buffer_create(&deshake->opencl_ctx.cl_inbuf,
  149. deshake->opencl_ctx.cl_inbuf_size,
  150. CL_MEM_READ_ONLY, NULL);
  151. if (ret < 0)
  152. return ret;
  153. }
  154. if (!deshake->opencl_ctx.cl_outbuf) {
  155. ret = av_opencl_buffer_create(&deshake->opencl_ctx.cl_outbuf,
  156. deshake->opencl_ctx.cl_outbuf_size,
  157. CL_MEM_READ_WRITE, NULL);
  158. if (ret < 0)
  159. return ret;
  160. }
  161. }
  162. ret = av_opencl_buffer_write_image(deshake->opencl_ctx.cl_inbuf,
  163. deshake->opencl_ctx.cl_inbuf_size,
  164. 0, in->data,deshake->opencl_ctx.in_plane_size,
  165. deshake->opencl_ctx.plane_num);
  166. if(ret < 0)
  167. return ret;
  168. return ret;
  169. }