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.

179 lines
8.2KB

  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. ret = av_opencl_init(NULL);
  94. if (ret < 0)
  95. return ret;
  96. deshake->opencl_ctx.matrix_size = MATRIX_SIZE;
  97. deshake->opencl_ctx.plane_num = PLANE_NUM;
  98. ret = av_opencl_buffer_create(&deshake->opencl_ctx.cl_matrix_y,
  99. deshake->opencl_ctx.matrix_size*sizeof(cl_float), CL_MEM_READ_ONLY, NULL);
  100. if (ret < 0)
  101. return ret;
  102. ret = av_opencl_buffer_create(&deshake->opencl_ctx.cl_matrix_uv,
  103. deshake->opencl_ctx.matrix_size*sizeof(cl_float), CL_MEM_READ_ONLY, NULL);
  104. if (ret < 0)
  105. return ret;
  106. if (!deshake->opencl_ctx.kernel_env.kernel) {
  107. ret = av_opencl_create_kernel(&deshake->opencl_ctx.kernel_env, "avfilter_transform");
  108. if (ret < 0) {
  109. av_log(ctx, AV_LOG_ERROR, "OpenCL failed to create kernel for name 'avfilter_transform'\n");
  110. return ret;
  111. }
  112. }
  113. return ret;
  114. }
  115. void ff_opencl_deshake_uninit(AVFilterContext *ctx)
  116. {
  117. DeshakeContext *deshake = ctx->priv;
  118. av_opencl_buffer_release(&deshake->opencl_ctx.cl_inbuf);
  119. av_opencl_buffer_release(&deshake->opencl_ctx.cl_outbuf);
  120. av_opencl_buffer_release(&deshake->opencl_ctx.cl_matrix_y);
  121. av_opencl_buffer_release(&deshake->opencl_ctx.cl_matrix_uv);
  122. av_opencl_release_kernel(&deshake->opencl_ctx.kernel_env);
  123. av_opencl_uninit();
  124. }
  125. int ff_opencl_deshake_process_inout_buf(AVFilterContext *ctx, AVFrame *in, AVFrame *out)
  126. {
  127. int ret = 0;
  128. AVFilterLink *link = ctx->inputs[0];
  129. DeshakeContext *deshake = ctx->priv;
  130. int chroma_height = -((-link->h) >> av_pix_fmt_desc_get(link->format)->log2_chroma_h);
  131. if ((!deshake->opencl_ctx.cl_inbuf) || (!deshake->opencl_ctx.cl_outbuf)) {
  132. deshake->opencl_ctx.in_plane_size[0] = (in->linesize[0] * in->height);
  133. deshake->opencl_ctx.in_plane_size[1] = (in->linesize[1] * chroma_height);
  134. deshake->opencl_ctx.in_plane_size[2] = (in->linesize[2] * chroma_height);
  135. deshake->opencl_ctx.out_plane_size[0] = (out->linesize[0] * out->height);
  136. deshake->opencl_ctx.out_plane_size[1] = (out->linesize[1] * chroma_height);
  137. deshake->opencl_ctx.out_plane_size[2] = (out->linesize[2] * chroma_height);
  138. deshake->opencl_ctx.cl_inbuf_size = deshake->opencl_ctx.in_plane_size[0] +
  139. deshake->opencl_ctx.in_plane_size[1] +
  140. deshake->opencl_ctx.in_plane_size[2];
  141. deshake->opencl_ctx.cl_outbuf_size = deshake->opencl_ctx.out_plane_size[0] +
  142. deshake->opencl_ctx.out_plane_size[1] +
  143. deshake->opencl_ctx.out_plane_size[2];
  144. if (!deshake->opencl_ctx.cl_inbuf) {
  145. ret = av_opencl_buffer_create(&deshake->opencl_ctx.cl_inbuf,
  146. deshake->opencl_ctx.cl_inbuf_size,
  147. CL_MEM_READ_ONLY, NULL);
  148. if (ret < 0)
  149. return ret;
  150. }
  151. if (!deshake->opencl_ctx.cl_outbuf) {
  152. ret = av_opencl_buffer_create(&deshake->opencl_ctx.cl_outbuf,
  153. deshake->opencl_ctx.cl_outbuf_size,
  154. CL_MEM_READ_WRITE, NULL);
  155. if (ret < 0)
  156. return ret;
  157. }
  158. }
  159. ret = av_opencl_buffer_write_image(deshake->opencl_ctx.cl_inbuf,
  160. deshake->opencl_ctx.cl_inbuf_size,
  161. 0, in->data,deshake->opencl_ctx.in_plane_size,
  162. deshake->opencl_ctx.plane_num);
  163. if(ret < 0)
  164. return ret;
  165. return ret;
  166. }