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