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 {
164 int err;
165
167 if (err < 0)
168 return err;
173
174 return 0;
175 }
176
178 {
184 VASurfaceID input_surface;
187 VAProcPipelineParameterBuffer params;
188 VAProcFilterParameterBufferDeinterlacing *filter_params;
189 VAStatus vas;
190 void *filter_params_addr =
NULL;
191 int err,
i,
field, current_frame_index;
192
193 // NULL frame is used to flush the queue in field mode
194 if (input_frame)
198
199 if (
ctx->queue_count <
ctx->queue_depth) {
200 ctx->frame_queue[
ctx->queue_count++] = input_frame;
201 if (
ctx->queue_count <
ctx->queue_depth) {
202 // Need more reference surfaces before we can continue.
203 return 0;
204 }
205 } else {
207 for (
i = 0;
i + 1 <
ctx->queue_count;
i++)
208 ctx->frame_queue[
i] =
ctx->frame_queue[
i + 1];
209 ctx->frame_queue[
i] = input_frame;
210 }
211
212 current_frame_index =
ctx->pipeline_caps.num_forward_references;
213
214 input_frame =
ctx->frame_queue[current_frame_index];
215 if (!input_frame)
216 return 0;
217
218 input_surface = (VASurfaceID)(uintptr_t)input_frame->
data[3];
219 for (
i = 0;
i <
ctx->pipeline_caps.num_forward_references;
i++)
220 forward_references[
i] = (VASurfaceID)(uintptr_t)
221 ctx->frame_queue[current_frame_index -
i - 1]->data[3];
222 for (
i = 0;
i <
ctx->pipeline_caps.num_backward_references;
i++)
223 backward_references[
i] = (VASurfaceID)(uintptr_t)
224 ctx->frame_queue[current_frame_index +
i + 1]->data[3];
225
227 "deinterlace input.\n", input_surface);
229 for (
i = 0;
i <
ctx->pipeline_caps.num_backward_references;
i++)
233 for (
i = 0;
i <
ctx->pipeline_caps.num_forward_references;
i++)
236
243 }
244
246 if (err < 0)
248
251 if (err < 0)
253
256 &filter_params_addr);
257 if (vas != VA_STATUS_SUCCESS) {
259 "buffer: %d (%s).\n", vas, vaErrorStr(vas));
262 }
263 filter_params = filter_params_addr;
264 filter_params->flags = 0;
266 filter_params->flags |=
field ? VA_DEINTERLACING_BOTTOM_FIELD : 0;
267 } else {
268 filter_params->flags |= VA_DEINTERLACING_BOTTOM_FIELD_FIRST;
269 filter_params->flags |=
field ? 0 : VA_DEINTERLACING_BOTTOM_FIELD;
270 }
271 filter_params_addr =
NULL;
273 if (vas != VA_STATUS_SUCCESS)
275 "buffer: %d (%s).\n", vas, vaErrorStr(vas));
276
278 params.num_filters = 1;
279
280 params.forward_references = forward_references;
281 params.num_forward_references =
282 ctx->pipeline_caps.num_forward_references;
283 params.backward_references = backward_references;
284 params.num_backward_references =
285 ctx->pipeline_caps.num_backward_references;
286
287 } else {
288 params.filters =
NULL;
289 params.num_filters = 0;
290 }
291
293 if (err < 0)
295
296 if (
ctx->field_rate == 2) {
301 else
303 ctx->frame_queue[current_frame_index + 1]->pts;
304 }
305 #if FF_API_INTERLACED_FRAME
309 #endif
311
315
317 if (err < 0)
318 break;
319 }
320
321 ctx->prev_pts = input_frame->
pts;
322
323 return err;
324
326 if (filter_params_addr)
329 return err;
330 }
331
333 {
337
340
347
348 return 0;
349 }
350
352 {
354
359
360 return 0;
361 }
362
363 #define OFFSET(x) offsetof(DeintVAAPIContext, x)
364 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM)
366 { "mode", "Deinterlacing mode",
368 VAProcDeinterlacingNone, VAProcDeinterlacingCount - 1,
FLAGS, .unit =
"mode" },
369 { "default", "Use the highest-numbered (and therefore possibly most advanced) deinterlacing algorithm",
371 { "bob", "Use the bob deinterlacing algorithm",
373 { "weave", "Use the weave deinterlacing algorithm",
375 { "motion_adaptive", "Use the motion adaptive deinterlacing algorithm",
377 { "motion_compensated", "Use the motion compensated deinterlacing algorithm",
379
380 { "rate", "Generate output at frame rate or field rate",
382 { "frame", "Output at frame rate (one frame of output for each field-pair)",
384 { "field", "Output at field rate (one frame of output for each field)",
386
387 { "auto", "Only deinterlace fields, passing frames through unchanged",
389
391 };
392
398 };
399
401 {
406 },
407 };
408
410 {
415 },
416 };
417
419 .
name =
"deinterlace_vaapi",
429 };