1 /* GStreamer Intel MSDK plugin
2 * Copyright (c) 2018, Intel Corporation
5 * Author: Sreerenj Balachaandran <sreerenj.balachandran@intel.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
17 * 3. Neither the name of the copyright holder nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 * SECTION: element-msdkvpp
37 * @short_description: MSDK Video Postprocessor
39 * A MediaSDK Video Postprocessing Filter
41 * ## Example launch line
43 * gst-launch-1.0 videotestsrc ! msdkvpp ! glimagesink
56 #include "gstmsdkvpp.h"
57 #include "gstmsdkbufferpool.h"
58 #include "gstmsdkvideomemory.h"
59 #include "gstmsdksystemmemory.h"
60 #include "gstmsdkcontextutil.h"
61 #include "gstmsdkvpputil.h"
63 #define EXT_FORMATS ""
66 #include "gstmsdkallocator_libva.h"
67 #include <gst/va/gstvaallocator.h>
68 #if VA_CHECK_VERSION(1, 4, 1)
70 #define EXT_FORMATS ", BGR10A2_LE"
73 #include <gst/d3d11/gstd3d11.h>
76 #if (MFX_VERSION >= 2004)
77 #define EXT_SINK_FORMATS ", RGB16, Y410, Y210, P012_LE, Y212_LE, Y412_LE"
78 #define EXT_SRC_FORMATS ", YV12, Y410, Y210, RGBP, BGRP, P012_LE, Y212_LE, Y412_LE"
79 #elif (MFX_VERSION >= 1032)
80 #define EXT_SINK_FORMATS ", RGB16, Y410, Y210, P012_LE, Y212_LE, Y412_LE"
81 #define EXT_SRC_FORMATS ", YV12, Y410, Y210, P012_LE, Y212_LE, Y412_LE"
82 #elif (MFX_VERSION >= 1031)
83 #define EXT_SINK_FORMATS ", RGB16, Y410, Y210, P012_LE, Y212_LE, Y412_LE"
84 #define EXT_SRC_FORMATS ", Y410, Y210, P012_LE, Y212_LE, Y412_LE"
85 #elif (MFX_VERSION >= 1028)
86 #define EXT_SINK_FORMATS ", RGB16, Y410, Y210"
87 #define EXT_SRC_FORMATS ", Y410, Y210"
88 #elif (MFX_VERSION >= 1027)
89 #define EXT_SINK_FORMATS ", Y410, Y210"
90 #define EXT_SRC_FORMATS ", Y410, Y210"
92 #define EXT_SINK_FORMATS ""
93 #define EXT_SRC_FORMATS ""
96 GST_DEBUG_CATEGORY_EXTERN (gst_msdkvpp_debug);
97 #define GST_CAT_DEFAULT gst_msdkvpp_debug
99 #define SUPPORTED_SYSTEM_FORMAT \
100 "{ NV12, YV12, I420, YUY2, UYVY, VUYA, BGRA, BGRx, P010_10LE" EXT_SINK_FORMATS "}"
101 #define SUPPORTED_DMABUF_FORMAT \
102 "{ NV12, BGRA, YUY2, UYVY, VUYA, P010_10LE" EXT_SINK_FORMATS "}"
103 #define SUPPORTED_VA_FORMAT \
104 "{ NV12, VUYA, P010_10LE }"
105 #define SUPPORTED_D3D11_FORMAT \
106 "{ NV12, VUYA, P010_10LE }"
107 #define SRC_SYSTEM_FORMAT \
108 "{ NV12, BGRA, YUY2, UYVY, VUYA, BGRx, P010_10LE" EXT_FORMATS EXT_SRC_FORMATS "}"
109 #define SRC_DMABUF_FORMAT \
110 "{ NV12, BGRA, YUY2, UYVY, VUYA, BGRx, P010_10LE" EXT_FORMATS EXT_SRC_FORMATS "}"
113 #define DMABUF_SINK_CAPS_STR \
114 GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_DMABUF, \
115 SUPPORTED_DMABUF_FORMAT) ";"
116 #define VA_SINK_CAPS_STR \
117 GST_VIDEO_CAPS_MAKE_WITH_FEATURES ("memory:VAMemory", SUPPORTED_VA_FORMAT)
119 #define D3D11_SINK_CAPS_STR \
120 GST_MSDK_CAPS_MAKE_WITH_D3D11_FEATURE (SUPPORTED_D3D11_FORMAT)
124 #define DMABUF_SRC_CAPS_STR \
125 GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_DMABUF, \
126 SRC_DMABUF_FORMAT) ";"
127 #define VA_SRC_CAPS_STR \
128 GST_VIDEO_CAPS_MAKE_WITH_FEATURES ("memory:VAMemory", SUPPORTED_VA_FORMAT)
130 #define D3D11_SRC_CAPS_STR \
131 GST_MSDK_CAPS_MAKE_WITH_D3D11_FEATURE (SUPPORTED_D3D11_FORMAT)
135 static GstStaticPadTemplate gst_msdkvpp_sink_factory =
136 GST_STATIC_PAD_TEMPLATE ("sink",
139 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (SUPPORTED_SYSTEM_FORMAT)
140 ", " "interlace-mode = (string){ progressive, interleaved, mixed }" ";"
141 DMABUF_SINK_CAPS_STR VA_SINK_CAPS_STR));
143 static GstStaticPadTemplate gst_msdkvpp_src_factory =
144 GST_STATIC_PAD_TEMPLATE ("src",
147 GST_STATIC_CAPS (DMABUF_SRC_CAPS_STR
148 GST_VIDEO_CAPS_MAKE (SRC_SYSTEM_FORMAT) ", "
149 "interlace-mode = (string){ progressive, interleaved, mixed }" ";"
152 static GstStaticPadTemplate gst_msdkvpp_sink_factory =
153 GST_STATIC_PAD_TEMPLATE ("sink",
156 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (SUPPORTED_SYSTEM_FORMAT)
157 ", " "interlace-mode = (string){ progressive, interleaved, mixed }" ";"
158 D3D11_SINK_CAPS_STR));
160 static GstStaticPadTemplate gst_msdkvpp_src_factory =
161 GST_STATIC_PAD_TEMPLATE ("src",
164 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (SRC_SYSTEM_FORMAT) ", "
165 "interlace-mode = (string){ progressive, interleaved, mixed }" ";"
166 D3D11_SRC_CAPS_STR));
174 #ifndef GST_REMOVE_DEPRECATED
177 PROP_DEINTERLACE_MODE,
178 PROP_DEINTERLACE_METHOD,
184 #ifndef GST_REMOVE_DEPRECATED
188 PROP_FORCE_ASPECT_RATIO,
190 PROP_VIDEO_DIRECTION,
198 #define PROP_HARDWARE_DEFAULT TRUE
199 #define PROP_ASYNC_DEPTH_DEFAULT 1
200 #define PROP_DENOISE_DEFAULT 0
201 #ifndef GST_REMOVE_DEPRECATED
202 #define PROP_ROTATION_DEFAULT MFX_ANGLE_0
203 #define PROP_MIRRORING_DEFAULT MFX_MIRRORING_DISABLED
205 #define PROP_DEINTERLACE_MODE_DEFAULT GST_MSDKVPP_DEINTERLACE_MODE_AUTO
206 #define PROP_DEINTERLACE_METHOD_DEFAULT MFX_DEINTERLACING_BOB
207 #define PROP_HUE_DEFAULT 0
208 #define PROP_SATURATION_DEFAULT 1
209 #define PROP_BRIGHTNESS_DEFAULT 0
210 #define PROP_CONTRAST_DEFAULT 1
211 #define PROP_DETAIL_DEFAULT 0
212 #define PROP_SCALING_MODE_DEFAULT MFX_SCALING_MODE_DEFAULT
213 #define PROP_FORCE_ASPECT_RATIO_DEFAULT TRUE
214 #define PROP_FRC_ALGORITHM_DEFAULT _MFX_FRC_ALGORITHM_NONE
215 #define PROP_VIDEO_DIRECTION_DEFAULT GST_VIDEO_ORIENTATION_IDENTITY
216 #define PROP_CROP_LEFT_DEFAULT 0
217 #define PROP_CROP_RIGHT_DEFAULT 0
218 #define PROP_CROP_TOP_DEFAULT 0
219 #define PROP_CROP_BOTTOM_DEFAULT 0
221 /* 8 should enough for a normal encoder */
222 #define SRC_POOL_SIZE_DEFAULT 8
224 #define gst_msdkvpp_parent_class parent_class
225 G_DEFINE_TYPE (GstMsdkVPP, gst_msdkvpp, GST_TYPE_BASE_TRANSFORM);
228 free_msdk_surface (gpointer p)
230 GstMsdkSurface *surface = (GstMsdkSurface *) p;
232 gst_buffer_unref (surface->buf);
233 g_slice_free (GstMsdkSurface, surface);
237 release_msdk_surface (GstMsdkVPP * thiz, GstMsdkSurface * surface,
240 if (surface->surface) {
241 if (surface->surface->Data.Locked) {
242 *list = g_list_append (*list, surface);
244 free_msdk_surface (surface);
250 release_in_surface (GstMsdkVPP * thiz, GstMsdkSurface * surface,
251 gboolean locked_by_others)
253 if (locked_by_others) {
254 /* mfxFrameSurface1 locked by others, others will hold the surface->buf reference */
255 /* we are good to release it here */
256 free_msdk_surface (surface);
258 release_msdk_surface (thiz, surface, &thiz->locked_in_surfaces);
263 release_out_surface (GstMsdkVPP * thiz, GstMsdkSurface * surface)
265 release_msdk_surface (thiz, surface, &thiz->locked_out_surfaces);
269 free_unlocked_msdk_surfaces_from_list (GstMsdkVPP * thiz, GList ** list)
272 GstMsdkSurface *surface;
274 for (l = *list; l;) {
275 GList *next = l->next;
277 if (surface->surface->Data.Locked == 0) {
278 free_msdk_surface (surface);
279 *list = g_list_delete_link (*list, l);
286 free_unlocked_msdk_surfaces (GstMsdkVPP * thiz)
288 free_unlocked_msdk_surfaces_from_list (thiz, &thiz->locked_in_surfaces);
289 free_unlocked_msdk_surfaces_from_list (thiz, &thiz->locked_out_surfaces);
293 free_all_msdk_surfaces (GstMsdkVPP * thiz)
295 g_list_free_full (thiz->locked_in_surfaces, free_msdk_surface);
296 thiz->locked_in_surfaces = NULL;
297 g_list_free_full (thiz->locked_out_surfaces, free_msdk_surface);
298 thiz->locked_out_surfaces = NULL;
302 gst_msdkvpp_add_extra_param (GstMsdkVPP * thiz, mfxExtBuffer * param)
304 if (thiz->num_extra_params < MAX_EXTRA_PARAMS) {
305 thiz->extra_params[thiz->num_extra_params] = param;
306 thiz->num_extra_params++;
311 gst_msdkvpp_context_prepare (GstMsdkVPP * thiz)
313 /* Try to find an existing context from the pipeline. This may (indirectly)
314 * invoke gst_msdkvpp_set_context, which will set thiz->context. */
315 if (!gst_msdk_context_find (GST_ELEMENT_CAST (thiz), &thiz->context))
318 if (thiz->context == thiz->old_context) {
319 GST_INFO_OBJECT (thiz, "Found old context %" GST_PTR_FORMAT
320 ", reusing as-is", thiz->context);
324 GST_INFO_OBJECT (thiz, "Found context %" GST_PTR_FORMAT " from neighbour",
327 /* Check GST_MSDK_JOB_VPP and GST_MSDK_JOB_ENCODER together to avoid sharing context
328 * between VPP and ENCODER
330 * gst-launch-1.0 videotestsrc ! msdkvpp ! video/x-raw,format=YUY2 ! msdkh264enc ! fakesink
332 if (!(gst_msdk_context_get_job_type (thiz->context) & (GST_MSDK_JOB_VPP |
333 GST_MSDK_JOB_ENCODER))) {
334 gst_msdk_context_add_job_type (thiz->context, GST_MSDK_JOB_VPP);
338 /* Found an existing context that's already being used as VPP, so clone the
339 * MFX session inside it to create a new one */
341 GstMsdkContext *parent_context, *msdk_context;
343 GST_INFO_OBJECT (thiz, "Creating new context %" GST_PTR_FORMAT " with "
344 "joined session", thiz->context);
345 parent_context = thiz->context;
346 msdk_context = gst_msdk_context_new_with_parent (parent_context);
349 GST_ERROR_OBJECT (thiz, "Failed to create a context with parent context "
350 "as %" GST_PTR_FORMAT, parent_context);
354 thiz->context = msdk_context;
355 gst_object_unref (parent_context);
362 ensure_context (GstBaseTransform * trans)
364 GstMsdkVPP *thiz = GST_MSDKVPP (trans);
366 if (!gst_msdkvpp_context_prepare (thiz)) {
367 if (!gst_msdk_ensure_new_context (GST_ELEMENT_CAST (thiz),
368 thiz->hardware, GST_MSDK_JOB_VPP, &thiz->context))
370 GST_INFO_OBJECT (thiz, "Creating new context %" GST_PTR_FORMAT,
374 /* Save the current context in a separate field so that we know whether it
375 * has changed between calls to _start() */
376 gst_object_replace ((GstObject **) & thiz->old_context,
377 (GstObject *) thiz->context);
379 gst_msdk_context_add_shared_async_depth (thiz->context, thiz->async_depth);
385 create_output_buffer (GstMsdkVPP * thiz)
389 GstBufferPool *pool = thiz->srcpad_buffer_pool;
391 g_return_val_if_fail (pool != NULL, NULL);
393 if (!gst_buffer_pool_is_active (pool) &&
394 !gst_buffer_pool_set_active (pool, TRUE))
395 goto error_activate_pool;
398 ret = gst_buffer_pool_acquire_buffer (pool, &outbuf, NULL);
399 if (ret != GST_FLOW_OK || !outbuf)
400 goto error_create_buffer;
407 GST_ERROR_OBJECT (thiz, "failed to activate output video buffer pool");
412 GST_ERROR_OBJECT (thiz, "failed to create output video buffer");
418 gst_msdkvpp_prepare_output_buffer (GstBaseTransform * trans,
419 GstBuffer * inbuf, GstBuffer ** outbuf_ptr)
421 GstMsdkVPP *thiz = GST_MSDKVPP (trans);
423 if (gst_base_transform_is_passthrough (trans)) {
428 *outbuf_ptr = create_output_buffer (thiz);
429 return *outbuf_ptr ? GST_FLOW_OK : GST_FLOW_ERROR;
433 static GstBufferPool *
434 gst_msdk_create_va_pool (GstVideoInfo * info, GstMsdkContext * msdk_context,
435 gboolean use_dmabuf, guint min_buffers)
437 GstBufferPool *pool = NULL;
438 GstAllocator *allocator;
439 GArray *formats = NULL;
440 GstAllocationParams alloc_params = { 0, 31, 0, 0 };
441 GstVaDisplay *display = NULL;
442 GstCaps *aligned_caps = NULL;
444 display = (GstVaDisplay *) gst_msdk_context_get_va_display (msdk_context);
447 allocator = gst_va_dmabuf_allocator_new (display);
449 formats = g_array_new (FALSE, FALSE, sizeof (GstVideoFormat));
450 g_array_append_val (formats, GST_VIDEO_INFO_FORMAT (info));
451 allocator = gst_va_allocator_new (display, formats);
454 GST_ERROR ("Failed to create allocator");
456 g_array_unref (formats);
459 aligned_caps = gst_video_info_to_caps (info);
461 gst_va_pool_new_with_config (aligned_caps,
462 GST_VIDEO_INFO_SIZE (info), min_buffers, 0,
463 VA_SURFACE_ATTRIB_USAGE_HINT_GENERIC, GST_VA_FEATURE_AUTO,
464 allocator, &alloc_params);
466 gst_object_unref (allocator);
467 gst_caps_unref (aligned_caps);
472 static GstBufferPool *
473 gst_msdk_create_d3d11_pool (GstMsdkVPP * thiz, GstVideoInfo * info,
474 guint num_buffers, gboolean propose)
476 GstBufferPool *pool = NULL;
477 GstD3D11Device *device;
478 GstStructure *config;
479 GstD3D11AllocationParams *params;
480 GstD3D11Format device_format;
481 guint bind_flags = 0;
482 GstCaps *aligned_caps = NULL;
483 GstVideoInfo aligned_info;
487 device = gst_msdk_context_get_d3d11_device (thiz->context);
489 aligned_width = GST_ROUND_UP_16 (info->width);
490 aligned_height = GST_ROUND_UP_32 (info->height);
492 gst_video_info_set_interlaced_format (&aligned_info,
493 GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_INTERLACE_MODE (info),
494 aligned_width, aligned_height);
496 gst_d3d11_device_get_format (device, GST_VIDEO_INFO_FORMAT (&aligned_info),
499 && ((device_format.format_support[0] & D3D11_FORMAT_SUPPORT_RENDER_TARGET)
500 == D3D11_FORMAT_SUPPORT_RENDER_TARGET)) {
501 bind_flags = D3D11_BIND_RENDER_TARGET;
504 aligned_caps = gst_video_info_to_caps (&aligned_info);
506 pool = gst_d3d11_buffer_pool_new (device);
507 config = gst_buffer_pool_get_config (pool);
508 params = gst_d3d11_allocation_params_new (device, &aligned_info,
509 GST_D3D11_ALLOCATION_FLAG_DEFAULT, bind_flags,
510 D3D11_RESOURCE_MISC_SHARED);
512 gst_buffer_pool_config_set_d3d11_allocation_params (config, params);
513 gst_d3d11_allocation_params_free (params);
514 gst_buffer_pool_config_set_params (config, aligned_caps,
515 GST_VIDEO_INFO_SIZE (&aligned_info), num_buffers, 0);
516 gst_buffer_pool_set_config (pool, config);
518 gst_caps_unref (aligned_caps);
519 GST_LOG_OBJECT (thiz, "Creating d3d11 pool");
525 static GstBufferPool *
526 gst_msdkvpp_create_buffer_pool (GstMsdkVPP * thiz, GstPadDirection direction,
527 GstCaps * caps, guint min_num_buffers, gboolean propose)
529 GstBufferPool *pool = NULL;
530 GstStructure *config;
532 GstVideoInfo *pool_info = NULL;
533 GstVideoAlignment align;
534 gboolean use_dmabuf = FALSE;
536 if (direction == GST_PAD_SINK) {
537 pool_info = &thiz->sinkpad_buffer_pool_info;
538 use_dmabuf = thiz->use_sinkpad_dmabuf;
539 } else if (direction == GST_PAD_SRC) {
540 pool_info = &thiz->srcpad_buffer_pool_info;
541 use_dmabuf = thiz->use_srcpad_dmabuf;
544 if (!gst_video_info_from_caps (&info, caps)) {
545 goto error_no_video_info;
548 gst_msdk_set_video_alignment (&info, 0, 0, &align);
549 gst_video_info_align (&info, &align);
552 pool = gst_msdk_create_va_pool (&info, thiz->context, use_dmabuf,
555 pool = gst_msdk_create_d3d11_pool (thiz, &info, min_num_buffers, propose);
557 if (!thiz->use_video_memory)
558 pool = gst_video_buffer_pool_new ();
563 config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
564 if (thiz->use_video_memory) {
565 gst_buffer_pool_config_add_option (config,
566 GST_BUFFER_POOL_OPTION_MSDK_USE_VIDEO_MEMORY);
568 gst_buffer_pool_config_add_option (config,
569 GST_BUFFER_POOL_OPTION_MSDK_USE_DMABUF);
572 gst_buffer_pool_config_set_params (config, caps,
573 GST_VIDEO_INFO_SIZE (&info), min_num_buffers, 0);
574 gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
575 gst_buffer_pool_config_add_option (config,
576 GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
577 gst_buffer_pool_config_set_video_alignment (config, &align);
579 if (!gst_buffer_pool_set_config (pool, config))
580 goto error_pool_config;
582 /* Updating pool_info with info which used to config pool */
589 GST_INFO_OBJECT (thiz, "Failed to create bufferpool");
594 GST_INFO_OBJECT (thiz, "Failed to get Video info from caps");
595 gst_object_unref (pool);
600 GST_INFO_OBJECT (thiz, "Failed to set config");
601 gst_object_unref (pool);
607 _gst_caps_has_feature (const GstCaps * caps, const gchar * feature)
611 for (i = 0; i < gst_caps_get_size (caps); i++) {
612 GstCapsFeatures *const features = gst_caps_get_features (caps, i);
613 /* Skip ANY features, we need an exact match for correct evaluation */
614 if (gst_caps_features_is_any (features))
616 if (gst_caps_features_contains (features, feature))
622 static GstBufferPool *
623 create_src_pool (GstMsdkVPP * thiz, GstQuery * query, GstCaps * caps)
625 GstBufferPool *pool = NULL;
626 guint size = 0, min_buffers = 0, max_buffers = 0;
627 gboolean update_pool = FALSE;
628 GstAllocator *allocator = NULL;
629 GstAllocationParams params;
630 mfxFrameAllocRequest request;
632 /* Check whether the query has pool */
633 if (gst_query_get_n_allocation_pools (query) > 0) {
635 gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
638 GstStructure *config = NULL;
639 /* get the configured pool properties inorder to set in query */
640 config = gst_buffer_pool_get_config (pool);
641 gst_object_unref (pool);
643 gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers,
645 if (gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms))
646 gst_query_add_allocation_param (query, allocator, ¶ms);
647 gst_structure_free (config);
649 /* if we have tee after msdkvpp, we will not have pool for src pad,
650 we need assign size for the internal pool
651 gst-launch-1.0 -v videotestsrc ! msdkvpp ! tee ! msdkh264enc ! fakesink silent=false
653 min_buffers = SRC_POOL_SIZE_DEFAULT;
656 /* Always create a pool for vpp out buffers. For vpp, we don't use
657 * external mfxFrameAllocator for video-memory allocation. */
658 request = thiz->request[1];
659 min_buffers += thiz->async_depth + request.NumFrameSuggested;
660 request.NumFrameSuggested = min_buffers;
663 gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SRC, caps, min_buffers,
667 /* we do not support dynamic buffer count change */
668 max_buffers = min_buffers;
670 gst_query_set_nth_allocation_pool (query, 0, pool, size, min_buffers,
673 gst_query_add_allocation_pool (query, pool, size, min_buffers, max_buffers);
679 gst_msdkvpp_decide_allocation (GstBaseTransform * trans, GstQuery * query)
681 GstMsdkVPP *thiz = GST_MSDKVPP (trans);
685 gst_query_parse_allocation (query, &caps, NULL);
687 GST_ERROR_OBJECT (thiz, "Failed to parse the decide_allocation caps");
690 if (!gst_video_info_from_caps (&info, caps)) {
691 GST_ERROR_OBJECT (thiz, "Failed to get video info");
694 /* We allocate the memory of type that downstream allocation requests */
696 if (_gst_caps_has_feature (caps, GST_CAPS_FEATURE_MEMORY_DMABUF)) {
697 GST_INFO_OBJECT (thiz, "MSDK VPP srcpad uses DMABuf memory");
698 thiz->use_srcpad_dmabuf = TRUE;
702 if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL))
703 thiz->add_video_meta = TRUE;
705 thiz->add_video_meta = FALSE;
707 gst_clear_object (&thiz->srcpad_buffer_pool);
708 thiz->srcpad_buffer_pool = create_src_pool (thiz, query, caps);
709 if (!thiz->srcpad_buffer_pool)
712 gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
714 /* Fixme if downstream doesn't have videometa support, msdkvpp should
715 * copy the output buffers */
721 gst_msdkvpp_propose_allocation (GstBaseTransform * trans,
722 GstQuery * decide_query, GstQuery * query)
724 GstMsdkVPP *thiz = GST_MSDKVPP (trans);
726 GstBufferPool *pool = NULL;
727 GstAllocator *allocator = NULL;
729 GstStructure *config;
731 GstAllocationParams params;
733 guint min_buffers = thiz->async_depth + 1;
735 gst_query_parse_allocation (query, &caps, &need_pool);
737 GST_ERROR_OBJECT (thiz, "Failed to parse the allocation caps");
741 if (!gst_video_info_from_caps (&info, caps)) {
742 GST_ERROR_OBJECT (thiz, "Failed to get video info");
746 /* if upstream allocation query supports dmabuf-capsfeatures,
747 * we do allocate dmabuf backed memory */
748 if (_gst_caps_has_feature (caps, GST_CAPS_FEATURE_MEMORY_DMABUF)) {
749 GST_INFO_OBJECT (thiz, "MSDK VPP srcpad uses DMABuf memory");
750 thiz->use_sinkpad_dmabuf = TRUE;
754 /* alwys provide a new pool for upstream to help re-negotiation
755 * more info here: https://bugzilla.gnome.org/show_bug.cgi?id=748344 */
756 pool = gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SINK, caps,
760 /* Update the internal pool if any allocation attribute changed */
761 if (!gst_video_info_is_equal (&thiz->sinkpad_buffer_pool_info, &info)) {
762 gst_object_unref (thiz->sinkpad_buffer_pool);
763 thiz->sinkpad_buffer_pool = gst_msdkvpp_create_buffer_pool (thiz,
764 GST_PAD_SINK, caps, min_buffers, FALSE);
767 /* get the size and allocator params from configured pool and set it in query */
769 pool = gst_object_ref (thiz->sinkpad_buffer_pool);
770 config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
771 gst_buffer_pool_config_get_params (config, NULL, &size, NULL, NULL);
772 if (gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms))
773 gst_query_add_allocation_param (query, allocator, ¶ms);
774 gst_structure_free (config);
776 /* if upstream doesn't have a pool requirement, set only
777 * size, min_buffers and max_buffers in query */
778 gst_query_add_allocation_pool (query, need_pool ? pool : NULL, size,
780 gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
782 gst_object_unref (pool);
784 return GST_BASE_TRANSFORM_CLASS (parent_class)->propose_allocation (trans,
785 decide_query, query);
788 static GstMsdkSurface *
789 gst_msdkvpp_get_surface_from_pool (GstMsdkVPP * thiz, GstBufferPool * pool,
792 GstBuffer *upload_buf;
793 GstMsdkSurface *msdk_surface = NULL;
794 GstVideoFrame src_frame, dst_frame;
796 if (!gst_buffer_pool_is_active (pool) &&
797 !gst_buffer_pool_set_active (pool, TRUE)) {
798 GST_ERROR_OBJECT (pool, "failed to activate buffer pool");
802 if (gst_buffer_pool_acquire_buffer (pool, &upload_buf, NULL) != GST_FLOW_OK) {
803 GST_ERROR_OBJECT (pool, "failed to acquire a buffer from pool");
807 if (!gst_video_frame_map (&src_frame, &thiz->sinkpad_info, buf, GST_MAP_READ)) {
808 GST_ERROR_OBJECT (thiz, "failed to map the frame for source");
809 gst_buffer_unref (upload_buf);
813 if (!gst_video_frame_map (&dst_frame, &thiz->sinkpad_buffer_pool_info,
814 upload_buf, GST_MAP_WRITE)) {
815 GST_ERROR_OBJECT (thiz, "failed to map the frame for destination");
816 gst_video_frame_unmap (&src_frame);
817 gst_buffer_unref (upload_buf);
821 for (guint i = 0; i < GST_VIDEO_FRAME_N_PLANES (&src_frame); i++) {
822 guint src_width_in_bytes, src_height;
823 guint dst_width_in_bytes, dst_height;
824 guint width_in_bytes, height;
825 guint src_stride, dst_stride;
826 guint8 *src_data, *dst_data;
828 src_width_in_bytes = GST_VIDEO_FRAME_COMP_WIDTH (&src_frame, i) *
829 GST_VIDEO_FRAME_COMP_PSTRIDE (&src_frame, i);
830 src_height = GST_VIDEO_FRAME_COMP_HEIGHT (&src_frame, i);
831 src_stride = GST_VIDEO_FRAME_COMP_STRIDE (&src_frame, i);
833 dst_width_in_bytes = GST_VIDEO_FRAME_COMP_WIDTH (&dst_frame, i) *
834 GST_VIDEO_FRAME_COMP_PSTRIDE (&src_frame, i);
835 dst_height = GST_VIDEO_FRAME_COMP_HEIGHT (&src_frame, i);
836 dst_stride = GST_VIDEO_FRAME_COMP_STRIDE (&dst_frame, i);
838 width_in_bytes = MIN (src_width_in_bytes, dst_width_in_bytes);
839 height = MIN (src_height, dst_height);
841 src_data = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&src_frame, i);
842 dst_data = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&dst_frame, i);
844 for (guint j = 0; j < height; j++) {
845 memcpy (dst_data, src_data, width_in_bytes);
846 dst_data += dst_stride;
847 src_data += src_stride;
851 gst_video_frame_unmap (&dst_frame);
852 gst_video_frame_unmap (&src_frame);
854 if (thiz->use_video_memory) {
855 msdk_surface = gst_msdk_import_to_msdk_surface (upload_buf, thiz->context,
856 &thiz->sinkpad_info, GST_MAP_READ);
859 gst_msdk_import_sys_mem_to_msdk_surface (upload_buf,
860 thiz->sinkpad_buffer_pool_info);
864 msdk_surface->buf = upload_buf;
869 static GstMsdkSurface *
870 get_msdk_surface_from_input_buffer (GstMsdkVPP * thiz, GstBuffer * inbuf)
872 GstMsdkSurface *msdk_surface = NULL;
874 if (gst_msdk_is_msdk_buffer (inbuf)) {
875 msdk_surface = g_slice_new0 (GstMsdkSurface);
876 msdk_surface->surface = gst_msdk_get_surface_from_buffer (inbuf);
877 msdk_surface->buf = gst_buffer_ref (inbuf);
881 msdk_surface = gst_msdk_import_to_msdk_surface (inbuf, thiz->context,
882 &thiz->sinkpad_info, GST_MAP_READ);
884 msdk_surface->buf = gst_buffer_ref (inbuf);
888 /* If upstream hasn't accpeted the proposed msdk bufferpool,
889 * just copy frame to msdk buffer and take a surface from it.
892 return gst_msdkvpp_get_surface_from_pool (thiz, thiz->sinkpad_buffer_pool,
897 gst_msdkvpp_transform (GstBaseTransform * trans, GstBuffer * inbuf,
900 GstMsdkVPP *thiz = GST_MSDKVPP (trans);
901 GstClockTime timestamp;
902 GstFlowReturn ret = GST_FLOW_OK;
904 mfxSyncPoint sync_point = NULL;
906 mfxFrameInfo *in_info = NULL;
907 GstMsdkSurface *in_surface = NULL;
908 GstMsdkSurface *out_surface = NULL;
909 GstBuffer *outbuf_new = NULL;
910 gboolean locked_by_others;
911 gboolean create_new_surface = FALSE;
913 free_unlocked_msdk_surfaces (thiz);
915 in_surface = get_msdk_surface_from_input_buffer (thiz, inbuf);
917 return GST_FLOW_ERROR;
919 if (!in_surface->surface) {
920 GST_ERROR_OBJECT (thiz, "mfx surface is NULL for the current input buffer");
921 free_msdk_surface (in_surface);
922 return GST_FLOW_ERROR;
924 locked_by_others = ! !in_surface->surface->Data.Locked;
926 /* always convert timestamp of input surface as msdk timestamp */
927 if (inbuf->pts == GST_CLOCK_TIME_NONE)
928 in_surface->surface->Data.TimeStamp = MFX_TIMESTAMP_UNKNOWN;
930 in_surface->surface->Data.TimeStamp =
931 gst_util_uint64_scale_round (inbuf->pts, 90000, GST_SECOND);
933 if (gst_msdk_is_msdk_buffer (outbuf)) {
934 out_surface = g_slice_new0 (GstMsdkSurface);
935 out_surface->surface = gst_msdk_get_surface_from_buffer (outbuf);
938 out_surface = gst_msdk_import_to_msdk_surface (outbuf, thiz->context,
939 &thiz->srcpad_info, 0);
942 gst_msdk_import_sys_mem_to_msdk_surface (outbuf, thiz->srcpad_info);
945 out_surface->buf = gst_buffer_ref (outbuf);
947 GST_ERROR_OBJECT (thiz, "Failed to get msdk outsurface!");
948 free_msdk_surface (in_surface);
949 return GST_FLOW_ERROR;
953 /* update surface crop info (NOTE: msdk min frame size is 2x2) */
954 in_info = &in_surface->surface->Info;
955 if ((thiz->crop_left + thiz->crop_right >= in_info->CropW - 1)
956 || (thiz->crop_top + thiz->crop_bottom >= in_info->CropH - 1)) {
957 GST_WARNING_OBJECT (thiz, "ignoring crop... cropping too much!");
958 } else if (!in_surface->from_qdata) {
959 /* We only fill crop info when it is a new surface.
960 * If the surface is a cached one, it already has crop info,
961 * and we should avoid updating again.
963 in_info->CropX = thiz->crop_left;
964 in_info->CropY = thiz->crop_top;
965 in_info->CropW -= thiz->crop_left + thiz->crop_right;
966 in_info->CropH -= thiz->crop_top + thiz->crop_bottom;
969 session = gst_msdk_context_get_session (thiz->context);
971 /* outer loop is for handling FrameRate Control and deinterlace use cases */
975 MFXVideoVPP_RunFrameVPPAsync (session, in_surface->surface,
976 out_surface->surface, NULL, &sync_point);
977 timestamp = out_surface->surface->Data.TimeStamp;
979 if (status != MFX_WRN_DEVICE_BUSY)
981 /* If device is busy, wait 1ms and retry, as per MSDK's recommendation */
985 if (timestamp == MFX_TIMESTAMP_UNKNOWN)
986 timestamp = GST_CLOCK_TIME_NONE;
988 timestamp = gst_util_uint64_scale_round (timestamp, GST_SECOND, 90000);
990 if (status == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM)
991 GST_WARNING_OBJECT (thiz, "VPP returned: %s",
992 msdk_status_to_string (status));
993 else if (status != MFX_ERR_NONE && status != MFX_ERR_MORE_DATA
994 && status != MFX_ERR_MORE_SURFACE)
997 /* No output generated */
998 if (status == MFX_ERR_MORE_DATA)
999 goto error_more_data;
1001 /* Wait for vpp operation to complete, the magic number 300000 below
1002 * is used in MSDK samples
1003 * #define MSDK_VPP_WAIT_INTERVAL 300000
1006 MFXVideoCORE_SyncOperation (session, sync_point,
1007 300000) != MFX_ERR_NONE)
1008 GST_WARNING_OBJECT (thiz, "failed to do sync operation");
1009 /* push new output buffer forward after sync operation */
1010 if (create_new_surface) {
1011 create_new_surface = FALSE;
1012 ret = gst_pad_push (GST_BASE_TRANSFORM_SRC_PAD (trans), outbuf_new);
1013 if (ret != GST_FLOW_OK)
1014 goto error_push_buffer;
1017 /* More than one output buffers are generated */
1018 if (status == MFX_ERR_MORE_SURFACE) {
1019 outbuf_new = create_output_buffer (thiz);
1020 GST_BUFFER_TIMESTAMP (outbuf_new) = timestamp;
1021 GST_BUFFER_DURATION (outbuf_new) = thiz->buffer_duration;
1023 if (gst_msdk_is_msdk_buffer (outbuf_new)) {
1024 release_out_surface (thiz, out_surface);
1025 out_surface = g_slice_new0 (GstMsdkSurface);
1026 out_surface->surface = gst_msdk_get_surface_from_buffer (outbuf_new);
1027 create_new_surface = TRUE;
1029 release_out_surface (thiz, out_surface);
1032 gst_msdk_import_to_msdk_surface (outbuf_new, thiz->context,
1033 &thiz->srcpad_buffer_pool_info, 0);
1036 gst_msdk_import_sys_mem_to_msdk_surface (outbuf_new,
1037 thiz->srcpad_buffer_pool_info);
1040 out_surface->buf = gst_buffer_ref (outbuf_new);
1041 create_new_surface = TRUE;
1043 GST_ERROR_OBJECT (thiz, "Failed to get msdk outsurface!");
1044 release_in_surface (thiz, in_surface, locked_by_others);
1045 return GST_FLOW_ERROR;
1049 GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1050 GST_BUFFER_DURATION (outbuf) = thiz->buffer_duration;
1052 } while (status == MFX_ERR_MORE_SURFACE);
1057 GST_ERROR_OBJECT (thiz, "MSDK Failed to do VPP");
1058 ret = GST_FLOW_ERROR;
1062 GST_WARNING_OBJECT (thiz,
1063 "MSDK Requires additional input for processing, "
1064 "Retruning FLOW_DROPPED since no output buffer was generated");
1065 ret = GST_BASE_TRANSFORM_FLOW_DROPPED;
1069 GST_DEBUG_OBJECT (thiz, "failed to push output buffer: %s",
1070 gst_flow_get_name (ret));
1073 release_in_surface (thiz, in_surface, locked_by_others);
1074 release_out_surface (thiz, out_surface);
1080 gst_msdkvpp_close (GstMsdkVPP * thiz)
1087 GST_DEBUG_OBJECT (thiz, "Closing VPP 0x%p", thiz->context);
1088 status = MFXVideoVPP_Close (gst_msdk_context_get_session (thiz->context));
1089 if (status != MFX_ERR_NONE && status != MFX_ERR_NOT_INITIALIZED) {
1090 GST_WARNING_OBJECT (thiz, "VPP close failed (%s)",
1091 msdk_status_to_string (status));
1093 free_all_msdk_surfaces (thiz);
1095 gst_clear_object (&thiz->context);
1097 memset (&thiz->param, 0, sizeof (thiz->param));
1099 gst_clear_object (&thiz->sinkpad_buffer_pool);
1100 gst_clear_object (&thiz->srcpad_buffer_pool);
1102 thiz->buffer_duration = GST_CLOCK_TIME_NONE;
1103 gst_video_info_init (&thiz->sinkpad_info);
1104 gst_video_info_init (&thiz->srcpad_info);
1108 ensure_filters (GstMsdkVPP * thiz)
1111 if (thiz->flags & GST_MSDK_FLAG_DENOISE) {
1112 mfxExtVPPDenoise *mfx_denoise = &thiz->mfx_denoise;
1113 mfx_denoise->Header.BufferId = MFX_EXTBUFF_VPP_DENOISE;
1114 mfx_denoise->Header.BufferSz = sizeof (mfxExtVPPDenoise);
1115 mfx_denoise->DenoiseFactor = thiz->denoise_factor;
1116 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_denoise);
1120 if (thiz->rotation != MFX_ANGLE_0) {
1121 mfxExtVPPRotation *mfx_rotation = &thiz->mfx_rotation;
1122 mfx_rotation->Header.BufferId = MFX_EXTBUFF_VPP_ROTATION;
1123 mfx_rotation->Header.BufferSz = sizeof (mfxExtVPPRotation);
1124 mfx_rotation->Angle = thiz->rotation;
1125 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_rotation);
1129 if (thiz->flags & GST_MSDK_FLAG_DEINTERLACE) {
1130 mfxExtVPPDeinterlacing *mfx_deinterlace = &thiz->mfx_deinterlace;
1131 mfx_deinterlace->Header.BufferId = MFX_EXTBUFF_VPP_DEINTERLACING;
1132 mfx_deinterlace->Header.BufferSz = sizeof (mfxExtVPPDeinterlacing);
1133 mfx_deinterlace->Mode = thiz->deinterlace_method;
1134 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_deinterlace);
1137 /* Colorbalance(ProcAmp) */
1138 if (thiz->flags & (GST_MSDK_FLAG_HUE | GST_MSDK_FLAG_SATURATION |
1139 GST_MSDK_FLAG_BRIGHTNESS | GST_MSDK_FLAG_CONTRAST)) {
1140 mfxExtVPPProcAmp *mfx_procamp = &thiz->mfx_procamp;
1141 mfx_procamp->Header.BufferId = MFX_EXTBUFF_VPP_PROCAMP;
1142 mfx_procamp->Header.BufferSz = sizeof (mfxExtVPPProcAmp);
1143 mfx_procamp->Hue = thiz->hue;
1144 mfx_procamp->Saturation = thiz->saturation;
1145 mfx_procamp->Brightness = thiz->brightness;
1146 mfx_procamp->Contrast = thiz->contrast;
1147 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_procamp);
1150 /* Detail/Edge enhancement */
1151 if (thiz->flags & GST_MSDK_FLAG_DETAIL) {
1152 mfxExtVPPDetail *mfx_detail = &thiz->mfx_detail;
1153 mfx_detail->Header.BufferId = MFX_EXTBUFF_VPP_DETAIL;
1154 mfx_detail->Header.BufferSz = sizeof (mfxExtVPPDetail);
1155 mfx_detail->DetailFactor = thiz->detail;
1156 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_detail);
1160 if (thiz->mirroring != MFX_MIRRORING_DISABLED) {
1161 mfxExtVPPMirroring *mfx_mirroring = &thiz->mfx_mirroring;
1162 mfx_mirroring->Header.BufferId = MFX_EXTBUFF_VPP_MIRRORING;
1163 mfx_mirroring->Header.BufferSz = sizeof (mfxExtVPPMirroring);
1164 mfx_mirroring->Type = thiz->mirroring;
1165 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_mirroring);
1169 if (thiz->flags & GST_MSDK_FLAG_SCALING_MODE) {
1170 mfxExtVPPScaling *mfx_scaling = &thiz->mfx_scaling;
1171 mfx_scaling->Header.BufferId = MFX_EXTBUFF_VPP_SCALING;
1172 mfx_scaling->Header.BufferSz = sizeof (mfxExtVPPScaling);
1173 mfx_scaling->ScalingMode = thiz->scaling_mode;
1174 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_scaling);
1178 if (thiz->flags & GST_MSDK_FLAG_FRC) {
1179 mfxExtVPPFrameRateConversion *mfx_frc = &thiz->mfx_frc;
1180 mfx_frc->Header.BufferId = MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION;
1181 mfx_frc->Header.BufferSz = sizeof (mfxExtVPPFrameRateConversion);
1182 mfx_frc->Algorithm = thiz->frc_algm;
1183 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_frc);
1188 gst_msdkvpp_set_passthrough (GstMsdkVPP * thiz)
1190 gboolean passthrough = TRUE;
1192 /* no passthrough if any of the filter algorithm is enabled */
1194 passthrough = FALSE;
1196 /* vpp could be needed in some specific circumstances, for eg:
1197 * input surface is dmabuf and output must be videomemory. So far
1198 * the underline iHD driver doesn't seems to support dmabuf mapping,
1199 * so we could explicitly ask msdkvpp to provide non-dambuf videomemory
1200 * surfaces as output thourgh capsfileters */
1202 passthrough = FALSE;
1204 /* no passthrough if there is change in out width,height or format */
1205 if (GST_VIDEO_INFO_WIDTH (&thiz->sinkpad_info) !=
1206 GST_VIDEO_INFO_WIDTH (&thiz->srcpad_info)
1207 || GST_VIDEO_INFO_HEIGHT (&thiz->sinkpad_info) !=
1208 GST_VIDEO_INFO_HEIGHT (&thiz->srcpad_info)
1209 || GST_VIDEO_INFO_FORMAT (&thiz->sinkpad_info) !=
1210 GST_VIDEO_INFO_FORMAT (&thiz->srcpad_info))
1211 passthrough = FALSE;
1213 gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (thiz), passthrough);
1217 gst_msdkvpp_initialize (GstMsdkVPP * thiz)
1221 mfxFrameAllocRequest *request = &thiz->request[0];
1223 if (!thiz->context) {
1224 GST_WARNING_OBJECT (thiz, "No MSDK Context");
1228 GST_OBJECT_LOCK (thiz);
1229 session = gst_msdk_context_get_session (thiz->context);
1231 /* Close the current session if the session has been initialized,
1232 * otherwise the subsequent function call of MFXVideoVPP_Init() will
1235 if (thiz->initialized) {
1236 MFXVideoVPP_Close (session);
1238 memset (&thiz->param, 0, sizeof (thiz->param));
1239 memset (&thiz->extra_params, 0, sizeof (thiz->extra_params));
1240 thiz->num_extra_params = 0;
1243 if (thiz->use_video_memory) {
1244 gst_msdk_set_frame_allocator (thiz->context);
1245 thiz->param.IOPattern =
1246 MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY;
1248 thiz->param.IOPattern =
1249 MFX_IOPATTERN_IN_SYSTEM_MEMORY | MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
1252 /* update input video attributes */
1253 gst_msdk_set_mfx_frame_info_from_video_info (&thiz->param.vpp.In,
1254 &thiz->sinkpad_info);
1256 /* update output video attributes, only CSC and Scaling are supported for now */
1257 gst_msdk_set_mfx_frame_info_from_video_info (&thiz->param.vpp.Out,
1258 &thiz->srcpad_info);
1260 /* use msdk frame rarte control if there is a mismatch in In & OUt fps */
1261 if (GST_VIDEO_INFO_FPS_N (&thiz->srcpad_info) &&
1262 (GST_VIDEO_INFO_FPS_N (&thiz->sinkpad_info) !=
1263 GST_VIDEO_INFO_FPS_N (&thiz->srcpad_info)
1264 || GST_VIDEO_INFO_FPS_D (&thiz->sinkpad_info) !=
1265 GST_VIDEO_INFO_FPS_D (&thiz->srcpad_info))) {
1266 thiz->flags |= GST_MSDK_FLAG_FRC;
1267 /* manually set distributed timestamp as frc algorithm
1268 * as it is more resonable for framerate conversion
1270 thiz->frc_algm = MFX_FRCALGM_DISTRIBUTED_TIMESTAMP;
1273 /* work-around to avoid zero fps in msdk structure */
1274 if (!thiz->param.vpp.In.FrameRateExtN)
1275 thiz->param.vpp.In.FrameRateExtN = 30;
1276 if (!thiz->param.vpp.Out.FrameRateExtN)
1277 thiz->param.vpp.Out.FrameRateExtN = thiz->param.vpp.In.FrameRateExtN;
1279 /* set vpp out picstruct as progressive if deinterlacing enabled */
1280 if (thiz->flags & GST_MSDK_FLAG_DEINTERLACE)
1281 thiz->param.vpp.Out.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
1283 /* Enable the required filters */
1284 ensure_filters (thiz);
1286 /* Add extended buffers */
1287 if (thiz->num_extra_params) {
1288 thiz->param.NumExtParam = thiz->num_extra_params;
1289 thiz->param.ExtParam = thiz->extra_params;
1292 /* validate parameters and allow MFX to make adjustments */
1293 status = MFXVideoVPP_Query (session, &thiz->param, &thiz->param);
1294 if (status < MFX_ERR_NONE) {
1295 GST_ERROR_OBJECT (thiz, "Video VPP Query failed (%s)",
1296 msdk_status_to_string (status));
1298 } else if (status > MFX_ERR_NONE) {
1299 GST_WARNING_OBJECT (thiz, "Video VPP Query returned: %s",
1300 msdk_status_to_string (status));
1303 status = MFXVideoVPP_QueryIOSurf (session, &thiz->param, request);
1304 if (status < MFX_ERR_NONE) {
1305 GST_ERROR_OBJECT (thiz, "VPP Query IO surfaces failed (%s)",
1306 msdk_status_to_string (status));
1308 } else if (status > MFX_ERR_NONE) {
1309 GST_WARNING_OBJECT (thiz, "VPP Query IO surfaces returned: %s",
1310 msdk_status_to_string (status));
1313 if (thiz->use_video_memory) {
1314 /* Input surface pool pre-allocation */
1315 request[0].Type |= MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
1316 if (thiz->use_sinkpad_dmabuf)
1317 request[0].Type |= MFX_MEMTYPE_EXPORT_FRAME;
1319 /* Output surface pool pre-allocation */
1320 request[1].Type |= MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
1321 if (thiz->use_srcpad_dmabuf)
1322 request[1].Type |= MFX_MEMTYPE_EXPORT_FRAME;
1325 thiz->in_num_surfaces = request[0].NumFrameSuggested;
1327 status = MFXVideoVPP_Init (session, &thiz->param);
1328 if (status < MFX_ERR_NONE) {
1329 GST_ERROR_OBJECT (thiz, "Init failed (%s)", msdk_status_to_string (status));
1331 } else if (status > MFX_ERR_NONE) {
1332 GST_WARNING_OBJECT (thiz, "Init returned: %s",
1333 msdk_status_to_string (status));
1336 thiz->initialized = TRUE;
1337 GST_OBJECT_UNLOCK (thiz);
1341 GST_OBJECT_UNLOCK (thiz);
1342 gst_clear_object (&thiz->context);
1347 gst_msdkvpp_set_caps (GstBaseTransform * trans, GstCaps * caps,
1350 GstMsdkVPP *thiz = GST_MSDKVPP (trans);
1351 GstVideoInfo in_info, out_info;
1352 gboolean sinkpad_info_changed = FALSE;
1353 gboolean srcpad_info_changed = FALSE;
1354 gboolean deinterlace;
1356 if (!gst_caps_features_is_equal (gst_caps_get_features (caps, 0),
1357 gst_caps_get_features (out_caps, 0)))
1360 if (!gst_video_info_from_caps (&in_info, caps))
1361 goto error_no_video_info;
1362 if (!gst_video_info_from_caps (&out_info, out_caps))
1363 goto error_no_video_info;
1365 if (!gst_video_info_is_equal (&in_info, &thiz->sinkpad_info))
1366 sinkpad_info_changed = TRUE;
1367 if (!gst_video_info_is_equal (&out_info, &thiz->srcpad_info))
1368 srcpad_info_changed = TRUE;
1370 if (!sinkpad_info_changed && !srcpad_info_changed && thiz->initialized)
1373 thiz->sinkpad_info = in_info;
1374 thiz->srcpad_info = out_info;
1376 thiz->use_video_memory = TRUE;
1378 /* check for deinterlace requirement */
1379 deinterlace = gst_msdkvpp_is_deinterlace_enabled (thiz, &in_info);
1381 thiz->flags |= GST_MSDK_FLAG_DEINTERLACE;
1383 thiz->buffer_duration = GST_VIDEO_INFO_FPS_N (&out_info) > 0 ?
1384 gst_util_uint64_scale (GST_SECOND, GST_VIDEO_INFO_FPS_D (&out_info),
1385 GST_VIDEO_INFO_FPS_N (&out_info)) : 0;
1387 if (!gst_msdkvpp_initialize (thiz))
1390 /* set passthrough according to filter operation change */
1391 gst_msdkvpp_set_passthrough (thiz);
1393 /* Ensure sinkpad buffer pool */
1394 if (thiz->sinkpad_buffer_pool)
1395 gst_object_unref (thiz->sinkpad_buffer_pool);
1397 thiz->sinkpad_buffer_pool =
1398 gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SINK, caps,
1399 thiz->in_num_surfaces, FALSE);
1400 if (!thiz->sinkpad_buffer_pool) {
1401 GST_ERROR_OBJECT (thiz, "Failed to ensure the sinkpad buffer pool");
1407 error_no_video_info:
1408 GST_ERROR_OBJECT (thiz, "Failed to get video info from caps");
1413 pad_accept_memory (GstMsdkVPP * thiz, const gchar * mem_type,
1414 GstPadDirection direction, GstCaps * filter)
1416 gboolean ret = FALSE;
1417 GstCaps *caps, *out_caps;
1419 GstBaseTransform *trans = GST_BASE_TRANSFORM (thiz);
1421 if (direction == GST_PAD_SRC)
1422 pad = GST_BASE_TRANSFORM_SRC_PAD (trans);
1424 pad = GST_BASE_TRANSFORM_SINK_PAD (trans);
1426 /* make a copy of filter caps since we need to alter the structure
1427 * by adding dmabuf-capsfeatures */
1428 caps = gst_caps_copy (filter);
1429 gst_caps_set_features (caps, 0, gst_caps_features_from_string (mem_type));
1431 out_caps = gst_pad_peer_query_caps (pad, caps);
1435 if (gst_caps_is_any (out_caps) || gst_caps_is_empty (out_caps)
1436 || out_caps == caps)
1439 if (_gst_caps_has_feature (out_caps, mem_type))
1443 gst_caps_unref (caps);
1445 gst_caps_unref (out_caps);
1450 gst_msdkvpp_fixate_caps (GstBaseTransform * trans,
1451 GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
1453 GstMsdkVPP *thiz = GST_MSDKVPP (trans);
1454 GstCaps *result = NULL;
1455 gboolean *use_dmabuf;
1457 if (direction == GST_PAD_SRC) {
1458 result = gst_caps_fixate (result);
1459 use_dmabuf = &thiz->use_sinkpad_dmabuf;
1462 * Override mirroring & rotation properties once video-direction
1465 if (thiz->flags & GST_MSDK_FLAG_VIDEO_DIRECTION)
1466 gst_msdk_get_mfx_video_orientation_from_video_direction
1467 (thiz->video_direction, &thiz->mirroring, &thiz->rotation);
1469 result = gst_msdkvpp_fixate_srccaps (thiz, caps, othercaps);
1470 use_dmabuf = &thiz->use_srcpad_dmabuf;
1473 GST_DEBUG_OBJECT (trans, "fixated to %" GST_PTR_FORMAT, result);
1474 gst_caps_unref (othercaps);
1476 /* We let msdkvpp srcpad first query if downstream has va memory type caps,
1477 * if not, will check the type of dma memory.
1480 if (pad_accept_memory (thiz, GST_CAPS_FEATURE_MEMORY_VA,
1481 direction == GST_PAD_SRC ? GST_PAD_SINK : GST_PAD_SRC, result)) {
1482 gst_caps_set_features (result, 0,
1483 gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_VA, NULL));
1484 } else if (pad_accept_memory (thiz, GST_CAPS_FEATURE_MEMORY_DMABUF,
1485 direction == GST_PAD_SRC ? GST_PAD_SINK : GST_PAD_SRC, result)) {
1486 gst_caps_set_features (result, 0,
1487 gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_DMABUF, NULL));
1491 if (pad_accept_memory (thiz, GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY,
1492 direction == GST_PAD_SRC ? GST_PAD_SINK : GST_PAD_SRC, result)) {
1493 gst_caps_set_features (result, 0,
1494 gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, NULL));
1501 /* Generic code for now, requires changes in future when we
1502 * add hardware query for supported formats, Framerate control etc */
1504 gst_msdkvpp_transform_caps (GstBaseTransform * trans,
1505 GstPadDirection direction, GstCaps * caps, GstCaps * filter)
1509 GST_DEBUG_OBJECT (trans,
1510 "Transforming caps %" GST_PTR_FORMAT " in direction %s", caps,
1511 (direction == GST_PAD_SINK) ? "sink" : "src");
1513 if (direction == GST_PAD_SRC)
1514 out_caps = gst_static_pad_template_get_caps (&gst_msdkvpp_sink_factory);
1516 out_caps = gst_static_pad_template_get_caps (&gst_msdkvpp_src_factory);
1518 if (out_caps && filter) {
1519 GstCaps *intersection;
1521 intersection = gst_caps_intersect_full (out_caps, filter,
1522 GST_CAPS_INTERSECT_FIRST);
1523 gst_caps_unref (out_caps);
1524 out_caps = intersection;
1527 GST_DEBUG_OBJECT (trans, "returning caps: %" GST_PTR_FORMAT, out_caps);
1532 gst_msdkvpp_start (GstBaseTransform * trans)
1534 if (!ensure_context (trans))
1540 gst_msdkvpp_stop (GstBaseTransform * trans)
1542 gst_msdkvpp_close (GST_MSDKVPP (trans));
1547 gst_msdkvpp_query (GstBaseTransform * trans, GstPadDirection direction,
1550 GstMsdkVPP *thiz = GST_MSDKVPP (trans);
1551 gboolean ret = FALSE;
1553 switch (GST_QUERY_TYPE (query)) {
1554 case GST_QUERY_CONTEXT:{
1555 GstMsdkContext *msdk_context = NULL;
1557 gst_object_replace ((GstObject **) & msdk_context,
1558 (GstObject *) thiz->context);
1559 ret = gst_msdk_handle_context_query (GST_ELEMENT_CAST (trans),
1560 query, msdk_context);
1561 gst_clear_object (&msdk_context);
1565 ret = GST_BASE_TRANSFORM_CLASS (parent_class)->query (trans,
1574 gst_msdkvpp_set_property (GObject * object, guint prop_id,
1575 const GValue * value, GParamSpec * pspec)
1577 GstMsdkVPP *thiz = GST_MSDKVPP (object);
1581 thiz->hardware = g_value_get_boolean (value);
1583 case PROP_ASYNC_DEPTH:
1584 thiz->async_depth = g_value_get_uint (value);
1587 thiz->denoise_factor = g_value_get_uint (value);
1588 thiz->flags |= GST_MSDK_FLAG_DENOISE;
1590 #ifndef GST_REMOVE_DEPRECATED
1592 thiz->rotation = g_value_get_enum (value);
1593 thiz->flags |= GST_MSDK_FLAG_ROTATION;
1595 case PROP_MIRRORING:
1596 thiz->mirroring = g_value_get_enum (value);
1597 thiz->flags |= GST_MSDK_FLAG_MIRRORING;
1600 case PROP_DEINTERLACE_MODE:
1601 thiz->deinterlace_mode = g_value_get_enum (value);
1603 case PROP_DEINTERLACE_METHOD:
1604 thiz->deinterlace_method = g_value_get_enum (value);
1607 thiz->hue = g_value_get_float (value);
1608 thiz->flags |= GST_MSDK_FLAG_HUE;
1610 case PROP_SATURATION:
1611 thiz->saturation = g_value_get_float (value);
1612 thiz->flags |= GST_MSDK_FLAG_SATURATION;
1614 case PROP_BRIGHTNESS:
1615 thiz->brightness = g_value_get_float (value);
1616 thiz->flags |= GST_MSDK_FLAG_BRIGHTNESS;
1619 thiz->contrast = g_value_get_float (value);
1620 thiz->flags |= GST_MSDK_FLAG_CONTRAST;
1623 thiz->detail = g_value_get_uint (value);
1624 thiz->flags |= GST_MSDK_FLAG_DETAIL;
1626 case PROP_SCALING_MODE:
1627 thiz->scaling_mode = g_value_get_enum (value);
1628 thiz->flags |= GST_MSDK_FLAG_SCALING_MODE;
1630 case PROP_FORCE_ASPECT_RATIO:
1631 thiz->keep_aspect = g_value_get_boolean (value);
1633 case PROP_FRC_ALGORITHM:
1634 thiz->frc_algm = g_value_get_enum (value);
1636 case PROP_VIDEO_DIRECTION:
1637 thiz->video_direction = g_value_get_enum (value);
1638 thiz->flags |= GST_MSDK_FLAG_VIDEO_DIRECTION;
1640 case PROP_CROP_LEFT:
1641 thiz->crop_left = g_value_get_uint (value);
1643 case PROP_CROP_RIGHT:
1644 thiz->crop_right = g_value_get_uint (value);
1647 thiz->crop_top = g_value_get_uint (value);
1649 case PROP_CROP_BOTTOM:
1650 thiz->crop_bottom = g_value_get_uint (value);
1653 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1659 gst_msdkvpp_get_property (GObject * object, guint prop_id,
1660 GValue * value, GParamSpec * pspec)
1662 GstMsdkVPP *thiz = GST_MSDKVPP (object);
1666 g_value_set_boolean (value, thiz->hardware);
1668 case PROP_ASYNC_DEPTH:
1669 g_value_set_uint (value, thiz->async_depth);
1672 g_value_set_uint (value, thiz->denoise_factor);
1674 #ifndef GST_REMOVE_DEPRECATED
1676 g_value_set_enum (value, thiz->rotation);
1678 case PROP_MIRRORING:
1679 g_value_set_enum (value, thiz->mirroring);
1682 case PROP_DEINTERLACE_MODE:
1683 g_value_set_enum (value, thiz->deinterlace_mode);
1685 case PROP_DEINTERLACE_METHOD:
1686 g_value_set_enum (value, thiz->deinterlace_method);
1689 g_value_set_float (value, thiz->hue);
1691 case PROP_SATURATION:
1692 g_value_set_float (value, thiz->saturation);
1694 case PROP_BRIGHTNESS:
1695 g_value_set_float (value, thiz->brightness);
1698 g_value_set_float (value, thiz->contrast);
1701 g_value_set_uint (value, thiz->detail);
1703 case PROP_SCALING_MODE:
1704 g_value_set_enum (value, thiz->scaling_mode);
1706 case PROP_FORCE_ASPECT_RATIO:
1707 g_value_set_boolean (value, thiz->keep_aspect);
1709 case PROP_FRC_ALGORITHM:
1710 g_value_set_enum (value, thiz->frc_algm);
1712 case PROP_VIDEO_DIRECTION:
1713 g_value_set_enum (value, thiz->video_direction);
1715 case PROP_CROP_LEFT:
1716 g_value_set_uint (value, thiz->crop_left);
1718 case PROP_CROP_RIGHT:
1719 g_value_set_uint (value, thiz->crop_right);
1722 g_value_set_uint (value, thiz->crop_top);
1724 case PROP_CROP_BOTTOM:
1725 g_value_set_uint (value, thiz->crop_bottom);
1728 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1734 gst_msdkvpp_dispose (GObject * object)
1736 GstMsdkVPP *thiz = GST_MSDKVPP (object);
1738 gst_clear_object (&thiz->old_context);
1740 G_OBJECT_CLASS (parent_class)->dispose (object);
1744 gst_msdkvpp_set_context (GstElement * element, GstContext * context)
1746 GstMsdkContext *msdk_context = NULL;
1747 GstMsdkVPP *thiz = GST_MSDKVPP (element);
1749 if (gst_msdk_context_get_context (context, &msdk_context)) {
1750 gst_object_replace ((GstObject **) & thiz->context,
1751 (GstObject *) msdk_context);
1752 gst_object_unref (msdk_context);
1755 if (gst_msdk_context_from_external_va_display (context,
1756 thiz->hardware, 0 /* GST_MSDK_JOB_VPP will be set later */ ,
1758 gst_object_replace ((GstObject **) & thiz->context,
1759 (GstObject *) msdk_context);
1760 gst_object_unref (msdk_context);
1763 if (gst_msdk_context_from_external_d3d11_device (context,
1764 thiz->hardware, 0 /* GST_MSDK_JOB_VPP will be set later */ ,
1766 gst_object_replace ((GstObject **) & thiz->context,
1767 (GstObject *) msdk_context);
1768 gst_object_unref (msdk_context);
1772 GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
1776 gst_msdkvpp_class_init (GstMsdkVPPClass * klass)
1778 GObjectClass *gobject_class;
1779 GstElementClass *element_class;
1780 GstBaseTransformClass *trans_class;
1781 GParamSpec *obj_properties[PROP_N] = { NULL, };
1783 gobject_class = G_OBJECT_CLASS (klass);
1784 element_class = GST_ELEMENT_CLASS (klass);
1785 trans_class = GST_BASE_TRANSFORM_CLASS (klass);
1787 gobject_class->set_property = gst_msdkvpp_set_property;
1788 gobject_class->get_property = gst_msdkvpp_get_property;
1789 gobject_class->dispose = gst_msdkvpp_dispose;
1791 element_class->set_context = gst_msdkvpp_set_context;
1793 gst_element_class_add_static_pad_template (element_class,
1794 &gst_msdkvpp_src_factory);
1795 gst_element_class_add_static_pad_template (element_class,
1796 &gst_msdkvpp_sink_factory);
1798 gst_element_class_set_static_metadata (element_class,
1799 "Intel MSDK Video Postprocessor",
1800 "Filter/Converter/Video;Filter/Converter/Video/Scaler;"
1801 "Filter/Effect/Video;Filter/Effect/Video/Deinterlace",
1802 "Video Postprocessing Filter based on " MFX_API_SDK,
1803 "Sreerenj Balachandrn <sreerenj.balachandran@intel.com>");
1805 trans_class->start = GST_DEBUG_FUNCPTR (gst_msdkvpp_start);
1806 trans_class->stop = GST_DEBUG_FUNCPTR (gst_msdkvpp_stop);
1807 trans_class->transform_caps = GST_DEBUG_FUNCPTR (gst_msdkvpp_transform_caps);
1808 trans_class->fixate_caps = GST_DEBUG_FUNCPTR (gst_msdkvpp_fixate_caps);
1809 trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_msdkvpp_set_caps);
1810 trans_class->transform = GST_DEBUG_FUNCPTR (gst_msdkvpp_transform);
1811 trans_class->propose_allocation =
1812 GST_DEBUG_FUNCPTR (gst_msdkvpp_propose_allocation);
1813 trans_class->decide_allocation =
1814 GST_DEBUG_FUNCPTR (gst_msdkvpp_decide_allocation);
1815 trans_class->prepare_output_buffer =
1816 GST_DEBUG_FUNCPTR (gst_msdkvpp_prepare_output_buffer);
1817 trans_class->query = GST_DEBUG_FUNCPTR (gst_msdkvpp_query);
1819 obj_properties[PROP_HARDWARE] =
1820 g_param_spec_boolean ("hardware", "Hardware", "Enable hardware VPP",
1821 PROP_HARDWARE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1823 obj_properties[PROP_ASYNC_DEPTH] =
1824 g_param_spec_uint ("async-depth", "Async Depth",
1825 "Depth of asynchronous pipeline",
1826 1, 1, PROP_ASYNC_DEPTH_DEFAULT,
1827 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1829 obj_properties[PROP_DENOISE] =
1830 g_param_spec_uint ("denoise", "Denoising factor",
1832 0, 100, PROP_DENOISE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1834 #ifndef GST_REMOVE_DEPRECATED
1835 obj_properties[PROP_ROTATION] =
1836 g_param_spec_enum ("rotation", "Rotation",
1837 "Rotation Angle (DEPRECATED, use video-direction instead)",
1838 gst_msdkvpp_rotation_get_type (), PROP_ROTATION_DEFAULT,
1839 G_PARAM_DEPRECATED | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1841 obj_properties[PROP_MIRRORING] =
1842 g_param_spec_enum ("mirroring", "Mirroring",
1843 "The Mirroring type (DEPRECATED, use video-direction instead)",
1844 gst_msdkvpp_mirroring_get_type (), PROP_MIRRORING_DEFAULT,
1845 G_PARAM_DEPRECATED | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1849 obj_properties[PROP_DEINTERLACE_MODE] =
1850 g_param_spec_enum ("deinterlace-mode", "Deinterlace Mode",
1851 "Deinterlace mode to use", gst_msdkvpp_deinterlace_mode_get_type (),
1852 PROP_DEINTERLACE_MODE_DEFAULT,
1853 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1855 obj_properties[PROP_DEINTERLACE_METHOD] =
1856 g_param_spec_enum ("deinterlace-method", "Deinterlace Method",
1857 "Deinterlace method to use", gst_msdkvpp_deinterlace_method_get_type (),
1858 PROP_DEINTERLACE_METHOD_DEFAULT,
1859 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1861 obj_properties[PROP_HUE] =
1862 g_param_spec_float ("hue", "Hue",
1863 "The hue of the video",
1864 -180, 180, PROP_HUE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1866 obj_properties[PROP_SATURATION] =
1867 g_param_spec_float ("saturation", "Saturation",
1868 "The Saturation of the video",
1869 0, 10, PROP_SATURATION_DEFAULT,
1870 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1872 obj_properties[PROP_BRIGHTNESS] =
1873 g_param_spec_float ("brightness", "Brightness",
1874 "The Brightness of the video",
1875 -100, 100, PROP_BRIGHTNESS_DEFAULT,
1876 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1878 obj_properties[PROP_CONTRAST] =
1879 g_param_spec_float ("contrast", "Contrast",
1880 "The Contrast of the video",
1881 0, 10, PROP_CONTRAST_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1883 obj_properties[PROP_DETAIL] =
1884 g_param_spec_uint ("detail", "Detail",
1885 "The factor of detail/edge enhancement filter algorithm",
1886 0, 100, PROP_DETAIL_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1888 obj_properties[PROP_SCALING_MODE] =
1889 g_param_spec_enum ("scaling-mode", "Scaling Mode",
1890 "The Scaling mode to use", gst_msdkvpp_scaling_mode_get_type (),
1891 PROP_SCALING_MODE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1893 obj_properties[PROP_FORCE_ASPECT_RATIO] =
1894 g_param_spec_boolean ("force-aspect-ratio", "Force Aspect Ratio",
1895 "When enabled, scaling will respect original aspect ratio",
1896 PROP_FORCE_ASPECT_RATIO_DEFAULT,
1897 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1899 obj_properties[PROP_FRC_ALGORITHM] =
1900 g_param_spec_enum ("frc-algorithm", "FrameRateControl Algorithm",
1901 "The Framerate Control Alogorithm to use",
1902 gst_msdkvpp_frc_algorithm_get_type (), PROP_FRC_ALGORITHM_DEFAULT,
1903 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1906 * The video-direction to use, expressed as an enum value. See
1907 * #GstVideoOrientationMethod.
1909 obj_properties[PROP_VIDEO_DIRECTION] = g_param_spec_enum ("video-direction",
1910 "Video Direction", "Video direction: rotation and flipping"
1911 #ifndef GST_REMOVE_DEPRECATED
1912 ", it will override both mirroring & rotation properties if set explicitly"
1915 GST_TYPE_VIDEO_ORIENTATION_METHOD,
1916 PROP_VIDEO_DIRECTION_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1918 obj_properties[PROP_CROP_LEFT] = g_param_spec_uint ("crop-left",
1919 "Crop Left", "Pixels to crop at left",
1920 0, G_MAXUINT16, PROP_CROP_LEFT_DEFAULT,
1921 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1923 obj_properties[PROP_CROP_RIGHT] = g_param_spec_uint ("crop-right",
1924 "Crop Right", "Pixels to crop at right",
1925 0, G_MAXUINT16, PROP_CROP_RIGHT_DEFAULT,
1926 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1928 obj_properties[PROP_CROP_TOP] = g_param_spec_uint ("crop-top",
1929 "Crop Top", "Pixels to crop at top",
1930 0, G_MAXUINT16, PROP_CROP_TOP_DEFAULT,
1931 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1933 obj_properties[PROP_CROP_BOTTOM] = g_param_spec_uint ("crop-bottom",
1934 "Crop Bottom", "Pixels to crop at bottom",
1935 0, G_MAXUINT16, PROP_CROP_BOTTOM_DEFAULT,
1936 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1938 g_object_class_install_properties (gobject_class, PROP_N, obj_properties);
1942 gst_msdkvpp_init (GstMsdkVPP * thiz)
1944 thiz->initialized = FALSE;
1945 thiz->hardware = PROP_HARDWARE_DEFAULT;
1946 thiz->async_depth = PROP_ASYNC_DEPTH_DEFAULT;
1947 thiz->denoise_factor = PROP_DENOISE_DEFAULT;
1948 #ifndef GST_REMOVE_DEPRECATED
1949 thiz->rotation = PROP_ROTATION_DEFAULT;
1950 thiz->mirroring = PROP_MIRRORING_DEFAULT;
1952 thiz->rotation = MFX_ANGLE_0;
1953 thiz->mirroring = MFX_MIRRORING_DISABLED;
1955 thiz->deinterlace_mode = PROP_DEINTERLACE_MODE_DEFAULT;
1956 thiz->deinterlace_method = PROP_DEINTERLACE_METHOD_DEFAULT;
1957 thiz->buffer_duration = GST_CLOCK_TIME_NONE;
1958 thiz->hue = PROP_HUE_DEFAULT;
1959 thiz->saturation = PROP_SATURATION_DEFAULT;
1960 thiz->brightness = PROP_BRIGHTNESS_DEFAULT;
1961 thiz->contrast = PROP_CONTRAST_DEFAULT;
1962 thiz->detail = PROP_DETAIL_DEFAULT;
1963 thiz->scaling_mode = PROP_SCALING_MODE_DEFAULT;
1964 thiz->keep_aspect = PROP_FORCE_ASPECT_RATIO_DEFAULT;
1965 thiz->frc_algm = PROP_FRC_ALGORITHM_DEFAULT;
1966 thiz->video_direction = PROP_VIDEO_DIRECTION_DEFAULT;
1967 thiz->crop_left = PROP_CROP_LEFT_DEFAULT;
1968 thiz->crop_right = PROP_CROP_RIGHT_DEFAULT;
1969 thiz->crop_top = PROP_CROP_TOP_DEFAULT;
1970 thiz->crop_bottom = PROP_CROP_BOTTOM_DEFAULT;
1972 gst_video_info_init (&thiz->sinkpad_info);
1973 gst_video_info_init (&thiz->srcpad_info);