1 /* GStreamer
2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) 2005-2012 David Schleef <ds@schleef.org>
4 * Copyright (C) <2019> Seungha Yang <seungha.yang@navercorp.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library 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 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 /**
23 * SECTION:element-cudascale
24 * @title: cudascale
25 * @see_also: cudaconvert
26 *
27 * This element resizes video frames. By default the element will try to
28 * negotiate to the same size on the source and sinkpad so that no scaling
29 * is needed. It is therefore safe to insert this element in a pipeline to
30 * get more robust behaviour without any cost if no scaling is needed.
31 *
32 * This element supports some YUV formats which are are also supported by
33 * nvidia encoders and decoders.
34 *
35 * ## Example pipelines
36 * |[
37 * gst-launch-1.0 -v filesrc location=videotestsrc.mp4 ! qtdemux ! h264parse ! nvh264dec ! cudaconvert ! cudascale ! cudaconvert ! cudadownload ! autovideosink
38 * ]|
39 * Decode a mp4/h264 and display the video. If the video sink chosen
40 * cannot perform scaling, the video scaling will be performed by cudascale
41 * |[
42 * gst-launch-1.0 -v filesrc location=videotestsrc.mp4 ! qtdemux ! h264parse ! nvh264dec ! cudaconvert ! cudascale ! cudaconvert ! cudadownload ! video/x-raw,width=100 ! autovideosink
43 * ]|
44 * Decode an mp4/h264 and display the video with a width of 100.
45 *
46 * Since: 1.20
47 */
48
49 #ifdef HAVE_CONFIG_H
50 # include <config.h>
51 #endif
52
53 #include "gstcudascale.h"
54 #include "gstcudautils.h"
55
56 GST_DEBUG_CATEGORY_STATIC (gst_cuda_scale_debug);
57 #define GST_CAT_DEFAULT gst_cuda_scale_debug
58
59 #define gst_cuda_scale_parent_class parent_class
60 G_DEFINE_TYPE (GstCudaScale, gst_cuda_scale, GST_TYPE_CUDA_BASE_FILTER);
61
62 static GstCaps *gst_cuda_scale_transform_caps (GstBaseTransform * trans,
63 GstPadDirection direction, GstCaps * caps, GstCaps * filter);
64 static GstCaps *gst_cuda_scale_fixate_caps (GstBaseTransform * base,
65 GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
66 static gboolean gst_cuda_scale_set_info (GstCudaBaseTransform * filter,
67 GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
68 GstVideoInfo * out_info);
69
70 static void
gst_cuda_scale_class_init(GstCudaScaleClass * klass)71 gst_cuda_scale_class_init (GstCudaScaleClass * klass)
72 {
73 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
74 GstBaseTransformClass *trans_class = GST_BASE_TRANSFORM_CLASS (klass);
75 GstCudaBaseTransformClass *btrans_class =
76 GST_CUDA_BASE_TRANSFORM_CLASS (klass);
77
78 gst_element_class_set_static_metadata (element_class,
79 "CUDA Video scaler",
80 "Filter/Converter/Video/Scaler/Hardware",
81 "Resizes Video using CUDA", "Seungha Yang <seungha.yang@navercorp.com>");
82
83 trans_class->transform_caps =
84 GST_DEBUG_FUNCPTR (gst_cuda_scale_transform_caps);
85 trans_class->fixate_caps = GST_DEBUG_FUNCPTR (gst_cuda_scale_fixate_caps);
86
87 btrans_class->set_info = GST_DEBUG_FUNCPTR (gst_cuda_scale_set_info);
88
89 GST_DEBUG_CATEGORY_INIT (gst_cuda_scale_debug,
90 "cudascale", 0, "Video Resize using CUDA");
91 }
92
93 static void
gst_cuda_scale_init(GstCudaScale * cuda)94 gst_cuda_scale_init (GstCudaScale * cuda)
95 {
96 }
97
98 static GstCaps *
gst_cuda_scale_transform_caps(GstBaseTransform * trans,GstPadDirection direction,GstCaps * caps,GstCaps * filter)99 gst_cuda_scale_transform_caps (GstBaseTransform * trans,
100 GstPadDirection direction, GstCaps * caps, GstCaps * filter)
101 {
102 GstCaps *ret;
103 GstStructure *structure;
104 GstCapsFeatures *features;
105 gint i, n;
106
107 GST_DEBUG_OBJECT (trans,
108 "Transforming caps %" GST_PTR_FORMAT " in direction %s", caps,
109 (direction == GST_PAD_SINK) ? "sink" : "src");
110
111 ret = gst_caps_new_empty ();
112 n = gst_caps_get_size (caps);
113 for (i = 0; i < n; i++) {
114 structure = gst_caps_get_structure (caps, i);
115 features = gst_caps_get_features (caps, i);
116
117 /* If this is already expressed by the existing caps
118 * skip this structure */
119 if (i > 0 && gst_caps_is_subset_structure_full (ret, structure, features))
120 continue;
121
122 /* make copy */
123 structure = gst_structure_copy (structure);
124
125 gst_structure_set (structure, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
126 "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
127
128 /* if pixel aspect ratio, make a range of it */
129 if (gst_structure_has_field (structure, "pixel-aspect-ratio")) {
130 gst_structure_set (structure, "pixel-aspect-ratio",
131 GST_TYPE_FRACTION_RANGE, 1, G_MAXINT, G_MAXINT, 1, NULL);
132 }
133
134 gst_caps_append_structure_full (ret, structure,
135 gst_caps_features_copy (features));
136 }
137
138 if (filter) {
139 GstCaps *intersection;
140
141 intersection =
142 gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
143 gst_caps_unref (ret);
144 ret = intersection;
145 }
146
147 GST_DEBUG_OBJECT (trans, "returning caps: %" GST_PTR_FORMAT, ret);
148
149 return ret;
150 }
151
152 /* fork of gstvideoscale */
153 static GstCaps *
gst_cuda_scale_fixate_caps(GstBaseTransform * base,GstPadDirection direction,GstCaps * caps,GstCaps * othercaps)154 gst_cuda_scale_fixate_caps (GstBaseTransform * base, GstPadDirection direction,
155 GstCaps * caps, GstCaps * othercaps)
156 {
157 GstStructure *ins, *outs;
158 const GValue *from_par, *to_par;
159 GValue fpar = { 0, }, tpar = {
160 0,};
161
162 othercaps = gst_caps_truncate (othercaps);
163 othercaps = gst_caps_make_writable (othercaps);
164
165 GST_DEBUG_OBJECT (base, "trying to fixate othercaps %" GST_PTR_FORMAT
166 " based on caps %" GST_PTR_FORMAT, othercaps, caps);
167
168 ins = gst_caps_get_structure (caps, 0);
169 outs = gst_caps_get_structure (othercaps, 0);
170
171 from_par = gst_structure_get_value (ins, "pixel-aspect-ratio");
172 to_par = gst_structure_get_value (outs, "pixel-aspect-ratio");
173
174 /* If we're fixating from the sinkpad we always set the PAR and
175 * assume that missing PAR on the sinkpad means 1/1 and
176 * missing PAR on the srcpad means undefined
177 */
178 if (direction == GST_PAD_SINK) {
179 if (!from_par) {
180 g_value_init (&fpar, GST_TYPE_FRACTION);
181 gst_value_set_fraction (&fpar, 1, 1);
182 from_par = &fpar;
183 }
184 if (!to_par) {
185 g_value_init (&tpar, GST_TYPE_FRACTION_RANGE);
186 gst_value_set_fraction_range_full (&tpar, 1, G_MAXINT, G_MAXINT, 1);
187 to_par = &tpar;
188 }
189 } else {
190 if (!to_par) {
191 g_value_init (&tpar, GST_TYPE_FRACTION);
192 gst_value_set_fraction (&tpar, 1, 1);
193 to_par = &tpar;
194
195 gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
196 NULL);
197 }
198 if (!from_par) {
199 g_value_init (&fpar, GST_TYPE_FRACTION);
200 gst_value_set_fraction (&fpar, 1, 1);
201 from_par = &fpar;
202 }
203 }
204
205 /* we have both PAR but they might not be fixated */
206 {
207 gint from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d;
208 gint w = 0, h = 0;
209 gint from_dar_n, from_dar_d;
210 gint num, den;
211
212 /* from_par should be fixed */
213 g_return_val_if_fail (gst_value_is_fixed (from_par), othercaps);
214
215 from_par_n = gst_value_get_fraction_numerator (from_par);
216 from_par_d = gst_value_get_fraction_denominator (from_par);
217
218 gst_structure_get_int (ins, "width", &from_w);
219 gst_structure_get_int (ins, "height", &from_h);
220
221 gst_structure_get_int (outs, "width", &w);
222 gst_structure_get_int (outs, "height", &h);
223
224 /* if both width and height are already fixed, we can't do anything
225 * about it anymore */
226 if (w && h) {
227 guint n, d;
228
229 GST_DEBUG_OBJECT (base, "dimensions already set to %dx%d, not fixating",
230 w, h);
231 if (!gst_value_is_fixed (to_par)) {
232 if (gst_video_calculate_display_ratio (&n, &d, from_w, from_h,
233 from_par_n, from_par_d, w, h)) {
234 GST_DEBUG_OBJECT (base, "fixating to_par to %dx%d", n, d);
235 if (gst_structure_has_field (outs, "pixel-aspect-ratio"))
236 gst_structure_fixate_field_nearest_fraction (outs,
237 "pixel-aspect-ratio", n, d);
238 else if (n != d)
239 gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
240 n, d, NULL);
241 }
242 }
243 goto done;
244 }
245
246 /* Calculate input DAR */
247 if (!gst_util_fraction_multiply (from_w, from_h, from_par_n, from_par_d,
248 &from_dar_n, &from_dar_d)) {
249 GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
250 ("Error calculating the output scaled size - integer overflow"));
251 goto done;
252 }
253
254 GST_DEBUG_OBJECT (base, "Input DAR is %d/%d", from_dar_n, from_dar_d);
255
256 /* If either width or height are fixed there's not much we
257 * can do either except choosing a height or width and PAR
258 * that matches the DAR as good as possible
259 */
260 if (h) {
261 GstStructure *tmp;
262 gint set_w, set_par_n, set_par_d;
263
264 GST_DEBUG_OBJECT (base, "height is fixed (%d)", h);
265
266 /* If the PAR is fixed too, there's not much to do
267 * except choosing the width that is nearest to the
268 * width with the same DAR */
269 if (gst_value_is_fixed (to_par)) {
270 to_par_n = gst_value_get_fraction_numerator (to_par);
271 to_par_d = gst_value_get_fraction_denominator (to_par);
272
273 GST_DEBUG_OBJECT (base, "PAR is fixed %d/%d", to_par_n, to_par_d);
274
275 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_d,
276 to_par_n, &num, &den)) {
277 GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
278 ("Error calculating the output scaled size - integer overflow"));
279 goto done;
280 }
281
282 w = (guint) gst_util_uint64_scale_int_round (h, num, den);
283 gst_structure_fixate_field_nearest_int (outs, "width", w);
284
285 goto done;
286 }
287
288 /* The PAR is not fixed and it's quite likely that we can set
289 * an arbitrary PAR. */
290
291 /* Check if we can keep the input width */
292 tmp = gst_structure_copy (outs);
293 gst_structure_fixate_field_nearest_int (tmp, "width", from_w);
294 gst_structure_get_int (tmp, "width", &set_w);
295
296 /* Might have failed but try to keep the DAR nonetheless by
297 * adjusting the PAR */
298 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, h, set_w,
299 &to_par_n, &to_par_d)) {
300 GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
301 ("Error calculating the output scaled size - integer overflow"));
302 gst_structure_free (tmp);
303 goto done;
304 }
305
306 if (!gst_structure_has_field (tmp, "pixel-aspect-ratio"))
307 gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par);
308 gst_structure_fixate_field_nearest_fraction (tmp, "pixel-aspect-ratio",
309 to_par_n, to_par_d);
310 gst_structure_get_fraction (tmp, "pixel-aspect-ratio", &set_par_n,
311 &set_par_d);
312 gst_structure_free (tmp);
313
314 /* Check if the adjusted PAR is accepted */
315 if (set_par_n == to_par_n && set_par_d == to_par_d) {
316 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
317 set_par_n != set_par_d)
318 gst_structure_set (outs, "width", G_TYPE_INT, set_w,
319 "pixel-aspect-ratio", GST_TYPE_FRACTION, set_par_n, set_par_d,
320 NULL);
321 goto done;
322 }
323
324 /* Otherwise scale the width to the new PAR and check if the
325 * adjusted with is accepted. If all that fails we can't keep
326 * the DAR */
327 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_par_d,
328 set_par_n, &num, &den)) {
329 GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
330 ("Error calculating the output scaled size - integer overflow"));
331 goto done;
332 }
333
334 w = (guint) gst_util_uint64_scale_int_round (h, num, den);
335 gst_structure_fixate_field_nearest_int (outs, "width", w);
336 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
337 set_par_n != set_par_d)
338 gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
339 set_par_n, set_par_d, NULL);
340
341 goto done;
342 } else if (w) {
343 GstStructure *tmp;
344 gint set_h, set_par_n, set_par_d;
345
346 GST_DEBUG_OBJECT (base, "width is fixed (%d)", w);
347
348 /* If the PAR is fixed too, there's not much to do
349 * except choosing the height that is nearest to the
350 * height with the same DAR */
351 if (gst_value_is_fixed (to_par)) {
352 to_par_n = gst_value_get_fraction_numerator (to_par);
353 to_par_d = gst_value_get_fraction_denominator (to_par);
354
355 GST_DEBUG_OBJECT (base, "PAR is fixed %d/%d", to_par_n, to_par_d);
356
357 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_d,
358 to_par_n, &num, &den)) {
359 GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
360 ("Error calculating the output scaled size - integer overflow"));
361 goto done;
362 }
363
364 h = (guint) gst_util_uint64_scale_int_round (w, den, num);
365 gst_structure_fixate_field_nearest_int (outs, "height", h);
366
367 goto done;
368 }
369
370 /* The PAR is not fixed and it's quite likely that we can set
371 * an arbitrary PAR. */
372
373 /* Check if we can keep the input height */
374 tmp = gst_structure_copy (outs);
375 gst_structure_fixate_field_nearest_int (tmp, "height", from_h);
376 gst_structure_get_int (tmp, "height", &set_h);
377
378 /* Might have failed but try to keep the DAR nonetheless by
379 * adjusting the PAR */
380 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_h, w,
381 &to_par_n, &to_par_d)) {
382 GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
383 ("Error calculating the output scaled size - integer overflow"));
384 gst_structure_free (tmp);
385 goto done;
386 }
387 if (!gst_structure_has_field (tmp, "pixel-aspect-ratio"))
388 gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par);
389 gst_structure_fixate_field_nearest_fraction (tmp, "pixel-aspect-ratio",
390 to_par_n, to_par_d);
391 gst_structure_get_fraction (tmp, "pixel-aspect-ratio", &set_par_n,
392 &set_par_d);
393 gst_structure_free (tmp);
394
395 /* Check if the adjusted PAR is accepted */
396 if (set_par_n == to_par_n && set_par_d == to_par_d) {
397 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
398 set_par_n != set_par_d)
399 gst_structure_set (outs, "height", G_TYPE_INT, set_h,
400 "pixel-aspect-ratio", GST_TYPE_FRACTION, set_par_n, set_par_d,
401 NULL);
402 goto done;
403 }
404
405 /* Otherwise scale the height to the new PAR and check if the
406 * adjusted with is accepted. If all that fails we can't keep
407 * the DAR */
408 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_par_d,
409 set_par_n, &num, &den)) {
410 GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
411 ("Error calculating the output scaled size - integer overflow"));
412 goto done;
413 }
414
415 h = (guint) gst_util_uint64_scale_int_round (w, den, num);
416 gst_structure_fixate_field_nearest_int (outs, "height", h);
417 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
418 set_par_n != set_par_d)
419 gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
420 set_par_n, set_par_d, NULL);
421
422 goto done;
423 } else if (gst_value_is_fixed (to_par)) {
424 GstStructure *tmp;
425 gint set_h, set_w, f_h, f_w;
426
427 to_par_n = gst_value_get_fraction_numerator (to_par);
428 to_par_d = gst_value_get_fraction_denominator (to_par);
429
430 /* Calculate scale factor for the PAR change */
431 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_n,
432 to_par_d, &num, &den)) {
433 GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
434 ("Error calculating the output scaled size - integer overflow"));
435 goto done;
436 }
437
438 /* Try to keep the input height (because of interlacing) */
439 tmp = gst_structure_copy (outs);
440 gst_structure_fixate_field_nearest_int (tmp, "height", from_h);
441 gst_structure_get_int (tmp, "height", &set_h);
442
443 /* This might have failed but try to scale the width
444 * to keep the DAR nonetheless */
445 w = (guint) gst_util_uint64_scale_int_round (set_h, num, den);
446 gst_structure_fixate_field_nearest_int (tmp, "width", w);
447 gst_structure_get_int (tmp, "width", &set_w);
448 gst_structure_free (tmp);
449
450 /* We kept the DAR and the height is nearest to the original height */
451 if (set_w == w) {
452 gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
453 G_TYPE_INT, set_h, NULL);
454 goto done;
455 }
456
457 f_h = set_h;
458 f_w = set_w;
459
460 /* If the former failed, try to keep the input width at least */
461 tmp = gst_structure_copy (outs);
462 gst_structure_fixate_field_nearest_int (tmp, "width", from_w);
463 gst_structure_get_int (tmp, "width", &set_w);
464
465 /* This might have failed but try to scale the width
466 * to keep the DAR nonetheless */
467 h = (guint) gst_util_uint64_scale_int_round (set_w, den, num);
468 gst_structure_fixate_field_nearest_int (tmp, "height", h);
469 gst_structure_get_int (tmp, "height", &set_h);
470 gst_structure_free (tmp);
471
472 /* We kept the DAR and the width is nearest to the original width */
473 if (set_h == h) {
474 gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
475 G_TYPE_INT, set_h, NULL);
476 goto done;
477 }
478
479 /* If all this failed, keep the dimensions with the DAR that was closest
480 * to the correct DAR. This changes the DAR but there's not much else to
481 * do here.
482 */
483 if (set_w * ABS (set_h - h) < ABS (f_w - w) * f_h) {
484 f_h = set_h;
485 f_w = set_w;
486 }
487 gst_structure_set (outs, "width", G_TYPE_INT, f_w, "height", G_TYPE_INT,
488 f_h, NULL);
489 goto done;
490 } else {
491 GstStructure *tmp;
492 gint set_h, set_w, set_par_n, set_par_d, tmp2;
493
494 /* width, height and PAR are not fixed but passthrough is not possible */
495
496 /* First try to keep the height and width as good as possible
497 * and scale PAR */
498 tmp = gst_structure_copy (outs);
499 gst_structure_fixate_field_nearest_int (tmp, "height", from_h);
500 gst_structure_get_int (tmp, "height", &set_h);
501 gst_structure_fixate_field_nearest_int (tmp, "width", from_w);
502 gst_structure_get_int (tmp, "width", &set_w);
503
504 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_h, set_w,
505 &to_par_n, &to_par_d)) {
506 GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
507 ("Error calculating the output scaled size - integer overflow"));
508 gst_structure_free (tmp);
509 goto done;
510 }
511
512 if (!gst_structure_has_field (tmp, "pixel-aspect-ratio"))
513 gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par);
514 gst_structure_fixate_field_nearest_fraction (tmp, "pixel-aspect-ratio",
515 to_par_n, to_par_d);
516 gst_structure_get_fraction (tmp, "pixel-aspect-ratio", &set_par_n,
517 &set_par_d);
518 gst_structure_free (tmp);
519
520 if (set_par_n == to_par_n && set_par_d == to_par_d) {
521 gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
522 G_TYPE_INT, set_h, NULL);
523
524 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
525 set_par_n != set_par_d)
526 gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
527 set_par_n, set_par_d, NULL);
528 goto done;
529 }
530
531 /* Otherwise try to scale width to keep the DAR with the set
532 * PAR and height */
533 if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_par_d,
534 set_par_n, &num, &den)) {
535 GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
536 ("Error calculating the output scaled size - integer overflow"));
537 goto done;
538 }
539
540 w = (guint) gst_util_uint64_scale_int_round (set_h, num, den);
541 tmp = gst_structure_copy (outs);
542 gst_structure_fixate_field_nearest_int (tmp, "width", w);
543 gst_structure_get_int (tmp, "width", &tmp2);
544 gst_structure_free (tmp);
545
546 if (tmp2 == w) {
547 gst_structure_set (outs, "width", G_TYPE_INT, tmp2, "height",
548 G_TYPE_INT, set_h, NULL);
549 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
550 set_par_n != set_par_d)
551 gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
552 set_par_n, set_par_d, NULL);
553 goto done;
554 }
555
556 /* ... or try the same with the height */
557 h = (guint) gst_util_uint64_scale_int_round (set_w, den, num);
558 tmp = gst_structure_copy (outs);
559 gst_structure_fixate_field_nearest_int (tmp, "height", h);
560 gst_structure_get_int (tmp, "height", &tmp2);
561 gst_structure_free (tmp);
562
563 if (tmp2 == h) {
564 gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
565 G_TYPE_INT, tmp2, NULL);
566 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
567 set_par_n != set_par_d)
568 gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
569 set_par_n, set_par_d, NULL);
570 goto done;
571 }
572
573 /* If all fails we can't keep the DAR and take the nearest values
574 * for everything from the first try */
575 gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
576 G_TYPE_INT, set_h, NULL);
577 if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
578 set_par_n != set_par_d)
579 gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
580 set_par_n, set_par_d, NULL);
581 }
582 }
583
584 done:
585 GST_DEBUG_OBJECT (base, "fixated othercaps to %" GST_PTR_FORMAT, othercaps);
586
587 if (from_par == &fpar)
588 g_value_unset (&fpar);
589 if (to_par == &tpar)
590 g_value_unset (&tpar);
591
592 return othercaps;
593 }
594
595 static gboolean
gst_cuda_scale_set_info(GstCudaBaseTransform * btrans,GstCaps * incaps,GstVideoInfo * in_info,GstCaps * outcaps,GstVideoInfo * out_info)596 gst_cuda_scale_set_info (GstCudaBaseTransform * btrans, GstCaps * incaps,
597 GstVideoInfo * in_info, GstCaps * outcaps, GstVideoInfo * out_info)
598 {
599 if (GST_VIDEO_INFO_WIDTH (in_info) == GST_VIDEO_INFO_WIDTH (out_info) &&
600 GST_VIDEO_INFO_HEIGHT (in_info) == GST_VIDEO_INFO_HEIGHT (out_info) &&
601 GST_VIDEO_INFO_FORMAT (in_info) == GST_VIDEO_INFO_FORMAT (out_info)) {
602 gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (btrans), TRUE);
603 }
604
605 return GST_CUDA_BASE_TRANSFORM_CLASS (parent_class)->set_info (btrans,
606 incaps, in_info, outcaps, out_info);
607 }
608