1 /*
2 * gstmsdkvpputil.c - MediaSDK video post processing utilities
3 *
4 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
5 * Copyright (C) 2005-2012 David Schleef <ds@schleef.org>
6 * Copyright (C) 2016 Intel Corporation
7 * Copyright (C) 2018 Intel Corporation
8 * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
9 * Author: Victor Jaquez <victorx.jaquez@intel.com>
10 * Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this program; if not, write to the Free
24 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 * Boston, MA 02110-1301 USA
26 */
27
28 #include "gstmsdkvpputil.h"
29 #include "msdk-enums.h"
30
31 #define SWAP_GINT(a, b) do { \
32 const gint t = a; a = b; b = t; \
33 } while (0)
34
35 gboolean
gst_msdkvpp_is_deinterlace_enabled(GstMsdkVPP * msdkvpp,GstVideoInfo * vip)36 gst_msdkvpp_is_deinterlace_enabled (GstMsdkVPP * msdkvpp, GstVideoInfo * vip)
37 {
38 gboolean deinterlace;
39
40 switch (msdkvpp->deinterlace_mode) {
41 case GST_MSDKVPP_DEINTERLACE_MODE_AUTO:
42 deinterlace = GST_VIDEO_INFO_IS_INTERLACED (vip);
43 break;
44 case GST_MSDKVPP_DEINTERLACE_MODE_INTERLACED:
45 deinterlace = TRUE;
46 break;
47 default:
48 deinterlace = FALSE;
49 break;
50 }
51 return deinterlace;
52 }
53
54 static gboolean
fixate_output_frame_size(GstMsdkVPP * thiz,GstVideoInfo * vinfo,GstStructure * outs)55 fixate_output_frame_size (GstMsdkVPP * thiz, GstVideoInfo * vinfo,
56 GstStructure * outs)
57 {
58 const GValue *to_par;
59 GValue tpar = G_VALUE_INIT;
60 gboolean ret;
61
62 ret = TRUE;
63 to_par = gst_structure_get_value (outs, "pixel-aspect-ratio");
64 if (!to_par) {
65 g_value_init (&tpar, GST_TYPE_FRACTION_RANGE);
66 gst_value_set_fraction_range_full (&tpar, 1, G_MAXINT, G_MAXINT, 1);
67 to_par = &tpar;
68 }
69
70 /* we have both PAR but they might not be fixated */
71 {
72 gint from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d;
73 gint w = 0, h = 0;
74 gint from_dar_n, from_dar_d;
75 gint num, den;
76
77 from_par_n = GST_VIDEO_INFO_PAR_N (vinfo);
78 from_par_d = GST_VIDEO_INFO_PAR_D (vinfo);
79 from_w = GST_VIDEO_INFO_WIDTH (vinfo);
80 from_h = GST_VIDEO_INFO_HEIGHT (vinfo);
81
82 /* adjust for crop settings (NOTE: msdk min frame size is 2x2) */
83 if ((thiz->crop_left + thiz->crop_right >= from_w - 1)
84 || (thiz->crop_top + thiz->crop_bottom >= from_h - 1)) {
85 GST_WARNING_OBJECT (thiz, "ignoring crop... cropping too much!");
86 } else {
87 from_w -= thiz->crop_left + thiz->crop_right;
88 from_h -= thiz->crop_top + thiz->crop_bottom;
89 }
90
91 /* compensate for rotation if needed */
92 if (thiz->rotation == 90 || thiz->rotation == 270) {
93 SWAP_GINT (from_w, from_h);
94 SWAP_GINT (from_par_n, from_par_d);
95 }
96
97 gst_structure_get_int (outs, "width", &w);
98 gst_structure_get_int (outs, "height", &h);
99
100 /* if both width and height are already fixed, we can't do anything
101 * about it anymore */
102 if (w && h) {
103 guint n, d;
104
105 GST_DEBUG_OBJECT (thiz,
106 "dimensions already set to %dx%d, not fixating", w, h);
107
108 if (!gst_value_is_fixed (to_par)) {
109 if (gst_video_calculate_display_ratio (&n, &d, from_w, from_h,
110 from_par_n, from_par_d, w, h)) {
111 GST_DEBUG_OBJECT (thiz, "fixating to_par to %dx%d", n, d);
112 if (gst_structure_has_field (outs, "pixel-aspect-ratio"))
113 gst_structure_fixate_field_nearest_fraction (outs,
114 "pixel-aspect-ratio", n, d);
115 else if (n != d)
116 gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
117 n, d, NULL);
118 }
119 }
120
121 goto done;
122 }
123
124 /* Calculate input DAR */
125 if (!gst_util_fraction_multiply (from_w, from_h, from_par_n, from_par_d,
126 &from_dar_n, &from_dar_d))
127 goto overflow_error;
128
129 GST_DEBUG_OBJECT (thiz, "Input DAR is %d/%d", from_dar_n, from_dar_d);
130
131 /* If either width or height are fixed there's not much we
132 * can do either except choosing a height or width and PAR
133 * that matches the DAR as good as possible
134 */
135 if (h) {
136 GstStructure *tmp;
137 gint set_w, set_par_n, set_par_d;
138
139 GST_DEBUG_OBJECT (thiz, "height is fixed (%d)", h);
140
141 /* If the PAR is fixed too, there's not much to do
142 * except choosing the width that is nearest to the
143 * width with the same DAR */
144 if (gst_value_is_fixed (to_par)) {
145 to_par_n = gst_value_get_fraction_numerator (to_par);
146 to_par_d = gst_value_get_fraction_denominator (to_par);
147
148 GST_DEBUG_OBJECT (thiz, "PAR is fixed %d/%d", to_par_n, to_par_d);
149
150 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_d,
151 to_par_n, &num, &den))
152 goto overflow_error;
153
154 w = (guint) gst_util_uint64_scale_int (h, num, den);
155 gst_structure_fixate_field_nearest_int (outs, "width", w);
156
157 goto done;
158 }
159
160 /* The PAR is not fixed and it's quite likely that we can set
161 * an arbitrary PAR. */
162
163 /* Check if we can keep the input width */
164 tmp = gst_structure_copy (outs);
165 gst_structure_fixate_field_nearest_int (tmp, "width", from_w);
166 gst_structure_get_int (tmp, "width", &set_w);
167
168 /* Might have failed but try to keep the DAR nonetheless by
169 * adjusting the PAR */
170 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, h, set_w,
171 &to_par_n, &to_par_d)) {
172 gst_structure_free (tmp);
173 goto overflow_error;
174 }
175
176 if (!gst_structure_has_field (tmp, "pixel-aspect-ratio"))
177 gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par);
178 gst_structure_fixate_field_nearest_fraction (tmp, "pixel-aspect-ratio",
179 to_par_n, to_par_d);
180 gst_structure_get_fraction (tmp, "pixel-aspect-ratio", &set_par_n,
181 &set_par_d);
182 gst_structure_free (tmp);
183
184 /* Check if the adjusted PAR is accepted */
185 if (set_par_n == to_par_n && set_par_d == to_par_d) {
186 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
187 set_par_n != set_par_d)
188 gst_structure_set (outs, "width", G_TYPE_INT, set_w,
189 "pixel-aspect-ratio", GST_TYPE_FRACTION, set_par_n, set_par_d,
190 NULL);
191 goto done;
192 }
193
194 /* Otherwise scale the width to the new PAR and check if the
195 * adjusted with is accepted. If all that fails we can't keep
196 * the DAR */
197 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_par_d,
198 set_par_n, &num, &den))
199 goto overflow_error;
200
201 w = (guint) gst_util_uint64_scale_int (h, num, den);
202 gst_structure_fixate_field_nearest_int (outs, "width", w);
203 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
204 set_par_n != set_par_d)
205 gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
206 set_par_n, set_par_d, NULL);
207
208 goto done;
209 } else if (w) {
210 GstStructure *tmp;
211 gint set_h, set_par_n, set_par_d;
212
213 GST_DEBUG_OBJECT (thiz, "width is fixed (%d)", w);
214
215 /* If the PAR is fixed too, there's not much to do
216 * except choosing the height that is nearest to the
217 * height with the same DAR */
218 if (gst_value_is_fixed (to_par)) {
219 to_par_n = gst_value_get_fraction_numerator (to_par);
220 to_par_d = gst_value_get_fraction_denominator (to_par);
221
222 GST_DEBUG_OBJECT (thiz, "PAR is fixed %d/%d", to_par_n, to_par_d);
223
224 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_d,
225 to_par_n, &num, &den))
226 goto overflow_error;
227
228 h = (guint) gst_util_uint64_scale_int (w, den, num);
229 gst_structure_fixate_field_nearest_int (outs, "height", h);
230
231 goto done;
232 }
233
234 /* The PAR is not fixed and it's quite likely that we can set
235 * an arbitrary PAR. */
236
237 /* Check if we can keep the input height */
238 tmp = gst_structure_copy (outs);
239 gst_structure_fixate_field_nearest_int (tmp, "height", from_h);
240 gst_structure_get_int (tmp, "height", &set_h);
241
242 /* Might have failed but try to keep the DAR nonetheless by
243 * adjusting the PAR */
244 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_h, w,
245 &to_par_n, &to_par_d)) {
246 gst_structure_free (tmp);
247 goto overflow_error;
248 }
249
250 if (!gst_structure_has_field (tmp, "pixel-aspect-ratio"))
251 gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par);
252 gst_structure_fixate_field_nearest_fraction (tmp, "pixel-aspect-ratio",
253 to_par_n, to_par_d);
254 gst_structure_get_fraction (tmp, "pixel-aspect-ratio", &set_par_n,
255 &set_par_d);
256 gst_structure_free (tmp);
257
258 /* Check if the adjusted PAR is accepted */
259 if (set_par_n == to_par_n && set_par_d == to_par_d) {
260 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
261 set_par_n != set_par_d)
262 gst_structure_set (outs, "height", G_TYPE_INT, set_h,
263 "pixel-aspect-ratio", GST_TYPE_FRACTION, set_par_n, set_par_d,
264 NULL);
265 goto done;
266 }
267
268 /* Otherwise scale the height to the new PAR and check if the
269 * adjusted with is accepted. If all that fails we can't keep
270 * the DAR */
271 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_par_d,
272 set_par_n, &num, &den))
273 goto overflow_error;
274
275 h = (guint) gst_util_uint64_scale_int (w, den, num);
276 gst_structure_fixate_field_nearest_int (outs, "height", h);
277 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
278 set_par_n != set_par_d)
279 gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
280 set_par_n, set_par_d, NULL);
281
282 goto done;
283 } else if (gst_value_is_fixed (to_par)) {
284 GstStructure *tmp;
285 gint set_h, set_w, f_h, f_w;
286
287 to_par_n = gst_value_get_fraction_numerator (to_par);
288 to_par_d = gst_value_get_fraction_denominator (to_par);
289
290 /* Calculate scale factor for the PAR change */
291 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_n,
292 to_par_d, &num, &den))
293 goto overflow_error;
294
295 /* Try to keep the input height (because of interlacing) */
296 tmp = gst_structure_copy (outs);
297 gst_structure_fixate_field_nearest_int (tmp, "height", from_h);
298 gst_structure_get_int (tmp, "height", &set_h);
299
300 /* This might have failed but try to scale the width
301 * to keep the DAR nonetheless */
302 w = (guint) gst_util_uint64_scale_int (set_h, num, den);
303 gst_structure_fixate_field_nearest_int (tmp, "width", w);
304 gst_structure_get_int (tmp, "width", &set_w);
305 gst_structure_free (tmp);
306
307 /* We kept the DAR and the height is nearest to the original height */
308 if (set_w == w) {
309 gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
310 G_TYPE_INT, set_h, NULL);
311 goto done;
312 }
313
314 f_h = set_h;
315 f_w = set_w;
316
317 /* If the former failed, try to keep the input width at least */
318 tmp = gst_structure_copy (outs);
319 gst_structure_fixate_field_nearest_int (tmp, "width", from_w);
320 gst_structure_get_int (tmp, "width", &set_w);
321
322 /* This might have failed but try to scale the width
323 * to keep the DAR nonetheless */
324 h = (guint) gst_util_uint64_scale_int (set_w, den, num);
325 gst_structure_fixate_field_nearest_int (tmp, "height", h);
326 gst_structure_get_int (tmp, "height", &set_h);
327 gst_structure_free (tmp);
328
329 /* We kept the DAR and the width is nearest to the original width */
330 if (set_h == h) {
331 gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
332 G_TYPE_INT, set_h, NULL);
333 goto done;
334 }
335
336 /* If all this failed, keep the height that was nearest to the original
337 * height and the nearest possible width. This changes the DAR but
338 * there's not much else to do here.
339 */
340 gst_structure_set (outs, "width", G_TYPE_INT, f_w, "height", G_TYPE_INT,
341 f_h, NULL);
342 goto done;
343 } else {
344 GstStructure *tmp;
345 gint set_h, set_w, set_par_n, set_par_d, tmp2;
346
347 /* width, height and PAR are not fixed but passthrough is not possible */
348
349 /* First try to keep the height and width as good as possible
350 * and scale PAR */
351 tmp = gst_structure_copy (outs);
352 gst_structure_fixate_field_nearest_int (tmp, "height", from_h);
353 gst_structure_get_int (tmp, "height", &set_h);
354 gst_structure_fixate_field_nearest_int (tmp, "width", from_w);
355 gst_structure_get_int (tmp, "width", &set_w);
356
357 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_h, set_w,
358 &to_par_n, &to_par_d)) {
359 gst_structure_free (tmp);
360 goto overflow_error;
361 }
362
363 if (!gst_structure_has_field (tmp, "pixel-aspect-ratio"))
364 gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par);
365 gst_structure_fixate_field_nearest_fraction (tmp, "pixel-aspect-ratio",
366 to_par_n, to_par_d);
367 gst_structure_get_fraction (tmp, "pixel-aspect-ratio", &set_par_n,
368 &set_par_d);
369 gst_structure_free (tmp);
370
371 if (set_par_n == to_par_n && set_par_d == to_par_d) {
372 gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
373 G_TYPE_INT, set_h, NULL);
374
375 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
376 set_par_n != set_par_d)
377 gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
378 set_par_n, set_par_d, NULL);
379 goto done;
380 }
381
382 /* Otherwise try to scale width to keep the DAR with the set
383 * PAR and height */
384 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_par_d,
385 set_par_n, &num, &den))
386 goto overflow_error;
387
388 w = (guint) gst_util_uint64_scale_int (set_h, num, den);
389 tmp = gst_structure_copy (outs);
390 gst_structure_fixate_field_nearest_int (tmp, "width", w);
391 gst_structure_get_int (tmp, "width", &tmp2);
392 gst_structure_free (tmp);
393
394 if (tmp2 == w) {
395 gst_structure_set (outs, "width", G_TYPE_INT, tmp2, "height",
396 G_TYPE_INT, set_h, NULL);
397 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
398 set_par_n != set_par_d)
399 gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
400 set_par_n, set_par_d, NULL);
401 goto done;
402 }
403
404 /* ... or try the same with the height */
405 h = (guint) gst_util_uint64_scale_int (set_w, den, num);
406 tmp = gst_structure_copy (outs);
407 gst_structure_fixate_field_nearest_int (tmp, "height", h);
408 gst_structure_get_int (tmp, "height", &tmp2);
409 gst_structure_free (tmp);
410
411 if (tmp2 == h) {
412 gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
413 G_TYPE_INT, tmp2, NULL);
414 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
415 set_par_n != set_par_d)
416 gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
417 set_par_n, set_par_d, NULL);
418 goto done;
419 }
420
421 /* If all fails we can't keep the DAR and take the nearest values
422 * for everything from the first try */
423 gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
424 G_TYPE_INT, set_h, NULL);
425 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
426 set_par_n != set_par_d)
427 gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
428 set_par_n, set_par_d, NULL);
429 }
430 }
431
432 done:
433 if (to_par == &tpar)
434 g_value_unset (&tpar);
435
436 return ret;
437
438 /* ERRORS */
439 overflow_error:
440 {
441 ret = FALSE;
442 GST_ELEMENT_ERROR (thiz, CORE, NEGOTIATION, (NULL),
443 ("Error calculating the output scaled size - integer overflow"));
444 goto done;
445 }
446 }
447
448 static gboolean
fixate_frame_rate(GstMsdkVPP * thiz,GstVideoInfo * vinfo,GstStructure * outs)449 fixate_frame_rate (GstMsdkVPP * thiz, GstVideoInfo * vinfo, GstStructure * outs)
450 {
451 gint fps_n = 0, fps_d;
452
453 /* fixate the srcpad fps */
454 if (gst_structure_fixate_field (outs, "framerate"))
455 gst_structure_get (outs, "framerate", GST_TYPE_FRACTION, &fps_n, &fps_d,
456 NULL);
457
458 /* if we don't have a fixed non-zero fps_n, use the sinkpad fps */
459 if (!fps_n) {
460 fps_n = GST_VIDEO_INFO_FPS_N (vinfo);
461 fps_d = GST_VIDEO_INFO_FPS_D (vinfo);
462 }
463
464 if (gst_msdkvpp_is_deinterlace_enabled (thiz, vinfo)) {
465 /* Fixme: set double framerate?:
466 * msdk is not outputting double framerate for bob or adv deinterlace */
467 if (!gst_util_fraction_multiply (fps_n, fps_d, 1, 1, &fps_n, &fps_d))
468 goto overflow_error;
469 }
470 gst_structure_set (outs, "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
471 return TRUE;
472
473 /* ERRORS */
474 overflow_error:
475 {
476 GST_ELEMENT_ERROR (thiz, CORE, NEGOTIATION, (NULL),
477 ("Error calculating the output framerate - integer overflow"));
478 return FALSE;
479 }
480 }
481
482 static gboolean
set_multiview_mode(GstMsdkVPP * thiz,GstVideoInfo * vinfo,GstStructure * outs)483 set_multiview_mode (GstMsdkVPP * thiz, GstVideoInfo * vinfo,
484 GstStructure * outs)
485 {
486 const gchar *caps_str;
487
488 caps_str =
489 gst_video_multiview_mode_to_caps_string (GST_VIDEO_INFO_MULTIVIEW_MODE
490 (vinfo));
491 if (!caps_str)
492 return TRUE;
493
494 gst_structure_set (outs, "multiview-mode", G_TYPE_STRING, caps_str,
495 "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
496 GST_VIDEO_INFO_MULTIVIEW_FLAGS (vinfo), GST_FLAG_SET_MASK_EXACT, NULL);
497
498 if (GST_VIDEO_INFO_VIEWS (vinfo) > 1) {
499 gst_structure_set (outs, "views", G_TYPE_INT, GST_VIDEO_INFO_VIEWS (vinfo),
500 NULL);
501 }
502 return TRUE;
503 }
504
505 static gboolean
set_interlace_mode(GstMsdkVPP * thiz,GstVideoInfo * vinfo,GstStructure * outs)506 set_interlace_mode (GstMsdkVPP * thiz, GstVideoInfo * vinfo,
507 GstStructure * outs)
508 {
509 const gchar *interlace_mode = NULL;
510
511 if (gst_msdkvpp_is_deinterlace_enabled (thiz, vinfo)) {
512 interlace_mode = "progressive";
513 } else {
514 interlace_mode =
515 gst_video_interlace_mode_to_string (GST_VIDEO_INFO_INTERLACE_MODE
516 (vinfo));
517 }
518
519 if (!interlace_mode)
520 return FALSE;
521
522 gst_structure_set (outs, "interlace-mode", G_TYPE_STRING, interlace_mode,
523 NULL);
524 return TRUE;
525 }
526
527 static GstCaps *
_get_preferred_src_caps(GstMsdkVPP * thiz,GstVideoInfo * vinfo,GstCaps * srccaps)528 _get_preferred_src_caps (GstMsdkVPP * thiz, GstVideoInfo * vinfo,
529 GstCaps * srccaps)
530 {
531 GstStructure *structure;
532 GstCaps *outcaps;
533
534 structure = gst_caps_get_structure (srccaps, 0);
535
536 /* make a copy */
537 structure = gst_structure_copy (structure);
538
539 if (thiz->keep_aspect)
540 gst_structure_set (structure, "pixel-aspect-ratio", GST_TYPE_FRACTION, 1,
541 1, NULL);
542
543 /* Fixate the format */
544 if (!gst_structure_fixate_field (structure, "format"))
545 goto fixate_failed;
546
547 /* Fixate the frame size */
548 if (!fixate_output_frame_size (thiz, vinfo, structure))
549 goto fixate_failed;
550
551 /* Fixate the framerate */
552 if (!fixate_frame_rate (thiz, vinfo, structure))
553 goto fixate_failed;
554
555 /* set multiview mode based on input caps */
556 if (!set_multiview_mode (thiz, vinfo, structure))
557 goto fixate_failed;
558
559 /*Fixme: Set colorimetry */
560
561 /* set interlace mode */
562 if (!set_interlace_mode (thiz, vinfo, structure))
563 goto interlace_mode_failed;
564
565 outcaps = gst_caps_new_empty ();
566 gst_caps_append_structure (outcaps, structure);
567
568 return outcaps;
569
570 /* ERRORS */
571 fixate_failed:
572 {
573 GST_WARNING_OBJECT (thiz, "Could not fixate src caps");
574 gst_structure_free (structure);
575 return NULL;
576 }
577 interlace_mode_failed:
578 {
579 GST_WARNING_OBJECT (thiz, "Invalid sink caps interlace mode");
580 return NULL;
581 }
582 }
583
584 /**
585 * gst_msdkvpp_fixate_srccaps:
586 * @vpp: a #GstMsdkVPP instance
587 * @sinkcaps: fixed #GstCaps from sink pad
588 * @srccaps: #GstCaps from src pad to fixate
589 *
590 * Given @srccaps and @sinkcaps returns a new allocated #GstCaps with
591 * the fixated caps for the src pad.
592 *
593 * Returns: A new allocated #GstCaps
594 **/
595 GstCaps *
gst_msdkvpp_fixate_srccaps(GstMsdkVPP * msdkvpp,GstCaps * sinkcaps,GstCaps * srccaps)596 gst_msdkvpp_fixate_srccaps (GstMsdkVPP * msdkvpp,
597 GstCaps * sinkcaps, GstCaps * srccaps)
598 {
599 GstVideoInfo vi;
600 if (!gst_video_info_from_caps (&vi, sinkcaps))
601 return NULL;
602 return _get_preferred_src_caps (msdkvpp, &vi, srccaps);
603 }
604