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 <string.h>
20
24
29
30 #define MAX_REFERENCES 8
31
34
38
39 VAProcFilterCapDeinterlacing
43
48
52
54 {
56 #define D(name) case VAProcDeinterlacing ## name: return #name
61 #undef D
62 default:
63 return "Invalid";
64 }
65 }
66
68 {
71
72 for (
i = 0;
i <
ctx->queue_count;
i++)
75
77 }
78
80 {
83 VAStatus vas;
84 VAProcFilterParameterBufferDeinterlacing params;
86
87 ctx->nb_deint_caps = VAProcDeinterlacingCount;
88 vas = vaQueryVideoProcFilterCaps(vpp_ctx->
hwctx->
display,
90 VAProcFilterDeinterlacing,
93 if (vas != VA_STATUS_SUCCESS) {
95 "caps: %d (%s).\n", vas, vaErrorStr(vas));
97 }
98
99 if (
ctx->mode == VAProcDeinterlacingNone) {
100 for (
i = 0;
i <
ctx->nb_deint_caps;
i++) {
101 if (
ctx->deint_caps[
i].type >
ctx->mode)
102 ctx->mode =
ctx->deint_caps[
i].type;
103 }
105 "deinterlacing mode.\n",
ctx->mode,
107 } else {
108 for (
i = 0;
i <
ctx->nb_deint_caps;
i++) {
109 if (
ctx->deint_caps[
i].type ==
ctx->mode)
110 break;
111 }
112 if (
i >=
ctx->nb_deint_caps) {
114 "not supported.\n",
ctx->mode,
117 }
118 }
119
120 params.type = VAProcFilterDeinterlacing;
121 params.algorithm =
ctx->mode;
123
125 VAProcFilterParameterBufferType,
126 ¶ms,
127 sizeof(params),
128 1);
129 if (vas)
130 return vas;
131
132 vas = vaQueryVideoProcPipelineCaps(vpp_ctx->
hwctx->
display,
135 &
ctx->pipeline_caps);
136 if (vas != VA_STATUS_SUCCESS) {
138 "caps: %d (%s).\n", vas, vaErrorStr(vas));
140 }
141
142 ctx->extra_delay_for_timestamps =
ctx->field_rate == 2 &&
143 ctx->pipeline_caps.num_backward_references == 0;
144
145 ctx->queue_depth =
ctx->pipeline_caps.num_backward_references +
146 ctx->pipeline_caps.num_forward_references +
147 ctx->extra_delay_for_timestamps + 1;
150 "references (%u forward, %u back).\n",
151 ctx->pipeline_caps.num_forward_references,
152 ctx->pipeline_caps.num_backward_references);
154 }
155
156 return 0;
157 }
158
160 {
166 int err;
167
169 if (err < 0)
170 return err;
175
176 return 0;
177 }
178
180 {
186 VASurfaceID input_surface;
189 VAProcPipelineParameterBuffer params;
190 VAProcFilterParameterBufferDeinterlacing *filter_params;
191 VAStatus vas;
192 void *filter_params_addr =
NULL;
193 int err,
i,
field, current_frame_index;
194
195 // NULL frame is used to flush the queue in field mode
196 if (input_frame)
200
201 if (
ctx->queue_count <
ctx->queue_depth) {
202 ctx->frame_queue[
ctx->queue_count++] = input_frame;
203 if (
ctx->queue_count <
ctx->queue_depth) {
204 // Need more reference surfaces before we can continue.
205 return 0;
206 }
207 } else {
209 for (
i = 0;
i + 1 <
ctx->queue_count;
i++)
210 ctx->frame_queue[
i] =
ctx->frame_queue[
i + 1];
211 ctx->frame_queue[
i] = input_frame;
212 }
213
214 current_frame_index =
ctx->pipeline_caps.num_forward_references;
215
216 input_frame =
ctx->frame_queue[current_frame_index];
217 if (!input_frame)
218 return 0;
219
220 input_surface = (VASurfaceID)(uintptr_t)input_frame->
data[3];
221 for (
i = 0;
i <
ctx->pipeline_caps.num_forward_references;
i++)
222 forward_references[
i] = (VASurfaceID)(uintptr_t)
223 ctx->frame_queue[current_frame_index -
i - 1]->data[3];
224 for (
i = 0;
i <
ctx->pipeline_caps.num_backward_references;
i++)
225 backward_references[
i] = (VASurfaceID)(uintptr_t)
226 ctx->frame_queue[current_frame_index +
i + 1]->data[3];
227
229 "deinterlace input.\n", input_surface);
231 for (
i = 0;
i <
ctx->pipeline_caps.num_backward_references;
i++)
235 for (
i = 0;
i <
ctx->pipeline_caps.num_forward_references;
i++)
238
245 }
246
248 if (err < 0)
250
253 if (err < 0)
255
258 &filter_params_addr);
259 if (vas != VA_STATUS_SUCCESS) {
261 "buffer: %d (%s).\n", vas, vaErrorStr(vas));
264 }
265 filter_params = filter_params_addr;
266 filter_params->flags = 0;
268 filter_params->flags |=
field ? VA_DEINTERLACING_BOTTOM_FIELD : 0;
269 } else {
270 filter_params->flags |= VA_DEINTERLACING_BOTTOM_FIELD_FIRST;
271 filter_params->flags |=
field ? 0 : VA_DEINTERLACING_BOTTOM_FIELD;
272 }
273 filter_params_addr =
NULL;
275 if (vas != VA_STATUS_SUCCESS)
277 "buffer: %d (%s).\n", vas, vaErrorStr(vas));
278
280 params.num_filters = 1;
281
282 params.forward_references = forward_references;
283 params.num_forward_references =
284 ctx->pipeline_caps.num_forward_references;
285 params.backward_references = backward_references;
286 params.num_backward_references =
287 ctx->pipeline_caps.num_backward_references;
288
289 } else {
290 params.filters =
NULL;
291 params.num_filters = 0;
292 }
293
295 if (err < 0)
297
298 if (
ctx->field_rate == 2) {
303 else
305 ctx->frame_queue[current_frame_index + 1]->pts;
306 }
307 #if FF_API_INTERLACED_FRAME
311 #endif
313
317
319 if (err < 0)
320 break;
321 }
322
323 ctx->prev_pts = input_frame->
pts;
324
325 return err;
326
328 if (filter_params_addr)
331 return err;
332 }
333
335 {
339
342
349
350 return 0;
351 }
352
354 {
356
361
362 return 0;
363 }
364
365 #define OFFSET(x) offsetof(DeintVAAPIContext, x)
366 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM)
368 { "mode", "Deinterlacing mode",
370 VAProcDeinterlacingNone, VAProcDeinterlacingCount - 1,
FLAGS, .unit =
"mode" },
371 { "default", "Use the highest-numbered (and therefore possibly most advanced) deinterlacing algorithm",
373 { "bob", "Use the bob deinterlacing algorithm",
375 { "weave", "Use the weave deinterlacing algorithm",
377 { "motion_adaptive", "Use the motion adaptive deinterlacing algorithm",
379 { "motion_compensated", "Use the motion compensated deinterlacing algorithm",
381
382 { "rate", "Generate output at frame rate or field rate",
384 { "frame", "Output at frame rate (one frame of output for each field-pair)",
386 { "field", "Output at field rate (one frame of output for each field)",
388
389 { "auto", "Only deinterlace fields, passing frames through unchanged",
391
393 };
394
400 };
401
403 {
408 },
409 };
410
412 {
417 },
418 };
419
421 .
name =
"deinterlace_vaapi",
431 };