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.
40 #include "gstmsdkvpp.h"
41 #include "gstmsdkbufferpool.h"
42 #include "gstmsdkvideomemory.h"
43 #include "gstmsdksystemmemory.h"
44 #include "gstmsdkcontextutil.h"
45 #include "gstmsdkvpputil.h"
47 GST_DEBUG_CATEGORY_EXTERN (gst_msdkvpp_debug);
48 #define GST_CAT_DEFAULT gst_msdkvpp_debug
50 static GstStaticPadTemplate gst_msdkvpp_sink_factory =
51 GST_STATIC_PAD_TEMPLATE ("sink",
54 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
55 ("{ NV12, YV12, I420, YUY2, UYVY, BGRA, BGRx }")
56 ", " "interlace-mode = (string){ progressive, interleaved, mixed }"));
58 static GstStaticPadTemplate gst_msdkvpp_src_factory =
59 GST_STATIC_PAD_TEMPLATE ("src",
62 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ NV12, YUY2, BGRA, BGRx }") ", "
63 "interlace-mode = (string){ progressive, interleaved, mixed }"));
72 PROP_DEINTERLACE_MODE,
73 PROP_DEINTERLACE_METHOD,
81 PROP_FORCE_ASPECT_RATIO,
86 #define PROP_HARDWARE_DEFAULT TRUE
87 #define PROP_ASYNC_DEPTH_DEFAULT 1
88 #define PROP_DENOISE_DEFAULT 0
89 #define PROP_ROTATION_DEFAULT MFX_ANGLE_0
90 #define PROP_DEINTERLACE_MODE_DEFAULT GST_MSDKVPP_DEINTERLACE_MODE_AUTO
91 #define PROP_DEINTERLACE_METHOD_DEFAULT MFX_DEINTERLACING_BOB
92 #define PROP_HUE_DEFAULT 0
93 #define PROP_SATURATION_DEFAULT 1
94 #define PROP_BRIGHTNESS_DEFAULT 0
95 #define PROP_CONTRAST_DEFAULT 1
96 #define PROP_DETAIL_DEFAULT 0
97 #define PROP_MIRRORING_DEFAULT MFX_MIRRORING_DISABLED
98 #define PROP_SCALING_MODE_DEFAULT MFX_SCALING_MODE_DEFAULT
99 #define PROP_FORCE_ASPECT_RATIO_DEFAULT TRUE
100 #define PROP_FRC_ALGORITHM_DEFAULT _MFX_FRC_ALGORITHM_NONE
102 #define gst_msdkvpp_parent_class parent_class
103 G_DEFINE_TYPE (GstMsdkVPP, gst_msdkvpp, GST_TYPE_BASE_TRANSFORM);
107 mfxFrameSurface1 *surface;
112 free_msdk_surface (MsdkSurface * surface)
115 gst_buffer_unref (surface->buf);
116 g_slice_free (MsdkSurface, surface);
120 gst_msdkvpp_add_extra_param (GstMsdkVPP * thiz, mfxExtBuffer * param)
122 if (thiz->num_extra_params < MAX_EXTRA_PARAMS) {
123 thiz->extra_params[thiz->num_extra_params] = param;
124 thiz->num_extra_params++;
129 ensure_context (GstBaseTransform * trans)
131 GstMsdkVPP *thiz = GST_MSDKVPP (trans);
133 if (gst_msdk_context_prepare (GST_ELEMENT_CAST (thiz), &thiz->context)) {
134 GST_INFO_OBJECT (thiz, "Found context from neighbour %" GST_PTR_FORMAT,
137 if (gst_msdk_context_get_job_type (thiz->context) & GST_MSDK_JOB_VPP) {
138 GstMsdkContext *parent_context;
140 parent_context = thiz->context;
141 thiz->context = gst_msdk_context_new_with_parent (parent_context);
142 gst_object_unref (parent_context);
144 GST_INFO_OBJECT (thiz,
145 "Creating new context %" GST_PTR_FORMAT " with joined session",
148 gst_msdk_context_add_job_type (thiz->context, GST_MSDK_JOB_VPP);
151 if (!gst_msdk_context_ensure_context (GST_ELEMENT_CAST (thiz),
152 thiz->hardware, GST_MSDK_JOB_VPP))
154 GST_INFO_OBJECT (thiz, "Creating new context %" GST_PTR_FORMAT,
158 gst_msdk_context_add_shared_async_depth (thiz->context, thiz->async_depth);
164 create_output_buffer (GstMsdkVPP * thiz)
168 GstBufferPool *pool = thiz->srcpad_buffer_pool;
170 g_return_val_if_fail (pool != NULL, NULL);
172 if (!gst_buffer_pool_is_active (pool) &&
173 !gst_buffer_pool_set_active (pool, TRUE))
174 goto error_activate_pool;
177 ret = gst_buffer_pool_acquire_buffer (pool, &outbuf, NULL);
178 if (ret != GST_FLOW_OK || !outbuf)
179 goto error_create_buffer;
186 GST_ERROR_OBJECT (thiz, "failed to activate output video buffer pool");
191 GST_ERROR_OBJECT (thiz, "failed to create output video buffer");
197 gst_msdkvpp_prepare_output_buffer (GstBaseTransform * trans,
198 GstBuffer * inbuf, GstBuffer ** outbuf_ptr)
200 GstMsdkVPP *thiz = GST_MSDKVPP (trans);
202 if (gst_base_transform_is_passthrough (trans)) {
207 *outbuf_ptr = create_output_buffer (thiz);
208 return *outbuf_ptr ? GST_FLOW_OK : GST_FLOW_ERROR;
211 static GstBufferPool *
212 gst_msdkvpp_create_buffer_pool (GstMsdkVPP * thiz, GstPadDirection direction,
213 GstCaps * caps, guint min_num_buffers)
215 GstBufferPool *pool = NULL;
216 GstStructure *config;
217 GstAllocator *allocator = NULL;
219 GstVideoInfo *pool_info = NULL;
220 GstVideoAlignment align;
221 GstAllocationParams params = { 0, 31, 0, 0, };
222 mfxFrameAllocResponse *alloc_resp = NULL;
224 if (direction == GST_PAD_SINK) {
225 alloc_resp = &thiz->in_alloc_resp;
226 pool_info = &thiz->sinkpad_buffer_pool_info;
227 } else if (direction == GST_PAD_SRC) {
228 alloc_resp = &thiz->out_alloc_resp;
229 pool_info = &thiz->srcpad_buffer_pool_info;
232 pool = gst_msdk_buffer_pool_new (thiz->context, alloc_resp);
236 if (!gst_video_info_from_caps (&info, caps))
237 goto error_no_video_info;
239 gst_msdk_set_video_alignment (&info, &align);
240 gst_video_info_align (&info, &align);
242 if (thiz->use_video_memory)
243 allocator = gst_msdk_video_allocator_new (thiz->context, &info, alloc_resp);
245 allocator = gst_msdk_system_allocator_new (&info);
248 goto error_no_allocator;
250 config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
251 gst_buffer_pool_config_set_params (config, caps, info.size, min_num_buffers,
254 gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
255 gst_buffer_pool_config_add_option (config,
256 GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
257 if (thiz->use_video_memory)
258 gst_buffer_pool_config_add_option (config,
259 GST_BUFFER_POOL_OPTION_MSDK_USE_VIDEO_MEMORY);
261 gst_buffer_pool_config_set_video_alignment (config, &align);
262 gst_buffer_pool_config_set_allocator (config, allocator, ¶ms);
263 gst_object_unref (allocator);
265 if (!gst_buffer_pool_set_config (pool, config))
266 goto error_pool_config;
268 /* Updating pool_info with algined info of allocator */
275 GST_INFO_OBJECT (thiz, "Failed to create bufferpool");
280 GST_INFO_OBJECT (thiz, "Failed to get Video info from caps");
285 GST_INFO_OBJECT (thiz, "Failed to create allocator");
287 gst_object_unref (pool);
292 GST_INFO_OBJECT (thiz, "Failed to set config");
294 gst_object_unref (pool);
296 gst_object_unref (allocator);
302 gst_msdkvpp_decide_allocation (GstBaseTransform * trans, GstQuery * query)
304 GstMsdkVPP *thiz = GST_MSDKVPP (trans);
306 GstBufferPool *pool = NULL;
307 GstStructure *config = NULL;
309 guint size = 0, min_buffers = 0, max_buffers = 0;
310 GstAllocator *allocator = NULL;
311 GstAllocationParams params;
312 gboolean update_pool = FALSE;
314 gst_query_parse_allocation (query, &caps, NULL);
316 GST_ERROR_OBJECT (thiz, "Failed to parse the decide_allocation caps");
319 if (!gst_video_info_from_caps (&info, caps)) {
320 GST_ERROR_OBJECT (thiz, "Failed to get video info");
324 if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL))
325 thiz->add_video_meta = TRUE;
327 thiz->add_video_meta = FALSE;
329 /* Check whether the query has pool */
330 if (gst_query_get_n_allocation_pools (query) > 0)
333 /* increase the min_buffers with number of concurrent vpp operations */
334 min_buffers += thiz->async_depth;
336 /* invalidate the cached pool if there is an allocation_query */
337 if (thiz->srcpad_buffer_pool)
338 gst_object_unref (thiz->srcpad_buffer_pool);
340 /* Always create a pool for vpp out buffers. Each of the msdk element
341 * has to create it's own mfxsurfacepool which is an msdk contraint.
342 * For eg: Each Msdk component (vpp, dec and enc) will invoke the external
343 * Frame allocator for video-memory usage.So sharing the pool between
344 * gst-msdk elements might not be a good idea, rather each element
345 * can check the buffer type (whether it is from msdk-buffer pool)
346 * to make sure there is no copy. Since we share the context between
347 * msdk elements, using buffers from one sdk's framealloator in another
348 * sdk-components is perfectly fine */
349 pool = gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SRC, caps, min_buffers);
350 thiz->srcpad_buffer_pool = pool;
352 /* get the configured pool properties inorder to set in query */
353 config = gst_buffer_pool_get_config (pool);
354 gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers,
356 if (gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms))
357 gst_query_add_allocation_param (query, allocator, ¶ms);
358 gst_structure_free (config);
361 gst_query_set_nth_allocation_pool (query, 0, pool, size, min_buffers,
364 gst_query_add_allocation_pool (query, pool, size, min_buffers, max_buffers);
366 gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
368 /* Fixme if downstream doesn't have videometa support, msdkvpp should
369 * copy the output buffers */
375 gst_msdkvpp_propose_allocation (GstBaseTransform * trans,
376 GstQuery * decide_query, GstQuery * query)
378 GstMsdkVPP *thiz = GST_MSDKVPP (trans);
380 GstBufferPool *pool = NULL;
381 GstAllocator *allocator = NULL;
383 GstStructure *config;
385 GstAllocationParams params;
387 guint min_buffers = thiz->async_depth + 1;
389 gst_query_parse_allocation (query, &caps, &need_pool);
391 GST_ERROR_OBJECT (thiz, "Failed to parse the allocation caps");
395 if (!gst_video_info_from_caps (&info, caps)) {
396 GST_ERROR_OBJECT (thiz, "Failed to get video info");
401 /* alwys provide a new pool for upstream to help re-negotiation
402 * more info here: https://bugzilla.gnome.org/show_bug.cgi?id=748344 */
403 pool = gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SINK, caps,
407 /* Update the internal pool if any allocation attribute changed */
408 if (!gst_video_info_is_equal (&thiz->sinkpad_buffer_pool_info, &info)) {
409 gst_object_unref (thiz->sinkpad_buffer_pool);
410 thiz->sinkpad_buffer_pool = gst_msdkvpp_create_buffer_pool (thiz,
411 GST_PAD_SINK, caps, min_buffers);
414 /* get the size and allocator params from configured pool and set it in query */
416 pool = gst_object_ref (thiz->sinkpad_buffer_pool);
417 config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
418 gst_buffer_pool_config_get_params (config, NULL, &size, NULL, NULL);
419 if (gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms))
420 gst_query_add_allocation_param (query, allocator, ¶ms);
421 gst_structure_free (config);
423 /* if upstream does't have a pool requirement, set only
424 * size, min_buffers and max_buffers in query */
425 gst_query_add_allocation_pool (query, need_pool ? pool : NULL, size,
427 gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
429 gst_object_unref (pool);
431 return GST_BASE_TRANSFORM_CLASS (parent_class)->propose_allocation (trans,
432 decide_query, query);
436 get_surface_from_pool (GstMsdkVPP * thiz, GstBufferPool * pool,
437 GstBufferPoolAcquireParams * params)
439 GstBuffer *new_buffer;
440 mfxFrameSurface1 *new_surface;
441 MsdkSurface *msdk_surface;
443 if (!gst_buffer_pool_is_active (pool) &&
444 !gst_buffer_pool_set_active (pool, TRUE)) {
445 GST_ERROR_OBJECT (pool, "failed to activate buffer pool");
449 if (gst_buffer_pool_acquire_buffer (pool, &new_buffer, params) != GST_FLOW_OK) {
450 GST_ERROR_OBJECT (pool, "failed to acquire a buffer from pool");
454 if (gst_msdk_is_msdk_buffer (new_buffer))
455 new_surface = gst_msdk_get_surface_from_buffer (new_buffer);
457 GST_ERROR_OBJECT (pool, "the acquired memory is not MSDK memory");
461 msdk_surface = g_slice_new0 (MsdkSurface);
462 msdk_surface->surface = new_surface;
463 msdk_surface->buf = new_buffer;
469 get_msdk_surface_from_input_buffer (GstMsdkVPP * thiz, GstBuffer * inbuf)
471 GstVideoFrame src_frame, out_frame;
472 MsdkSurface *msdk_surface;
474 if (gst_msdk_is_msdk_buffer (inbuf)) {
475 msdk_surface = g_slice_new0 (MsdkSurface);
476 msdk_surface->surface = gst_msdk_get_surface_from_buffer (inbuf);
477 msdk_surface->buf = gst_buffer_ref (inbuf);
481 /* If upstream hasn't accpeted the proposed msdk bufferpool,
482 * just copy frame to msdk buffer and take a surface from it.
485 get_surface_from_pool (thiz, thiz->sinkpad_buffer_pool, NULL)))
488 if (!gst_video_frame_map (&src_frame, &thiz->sinkpad_info, inbuf,
490 GST_ERROR_OBJECT (thiz, "failed to map the frame for source");
494 if (!gst_video_frame_map (&out_frame, &thiz->sinkpad_buffer_pool_info,
495 msdk_surface->buf, GST_MAP_WRITE)) {
496 GST_ERROR_OBJECT (thiz, "failed to map the frame for destination");
497 gst_video_frame_unmap (&src_frame);
501 if (!gst_video_frame_copy (&out_frame, &src_frame)) {
502 GST_ERROR_OBJECT (thiz, "failed to copy frame");
503 gst_video_frame_unmap (&out_frame);
504 gst_video_frame_unmap (&src_frame);
508 gst_video_frame_unmap (&out_frame);
509 gst_video_frame_unmap (&src_frame);
518 gst_msdkvpp_transform (GstBaseTransform * trans, GstBuffer * inbuf,
521 GstMsdkVPP *thiz = GST_MSDKVPP (trans);
522 GstClockTime timestamp;
523 GstFlowReturn ret = GST_FLOW_OK;
525 mfxSyncPoint sync_point = NULL;
527 MsdkSurface *in_surface = NULL;
528 MsdkSurface *out_surface = NULL;
530 timestamp = GST_BUFFER_TIMESTAMP (inbuf);
532 in_surface = get_msdk_surface_from_input_buffer (thiz, inbuf);
534 return GST_FLOW_ERROR;
536 if (gst_msdk_is_msdk_buffer (outbuf)) {
537 out_surface = g_slice_new0 (MsdkSurface);
538 out_surface->surface = gst_msdk_get_surface_from_buffer (outbuf);
540 GST_ERROR ("Failed to get msdk outsurface!");
541 return GST_FLOW_ERROR;
544 session = gst_msdk_context_get_session (thiz->context);
546 /* outer loop is for handling FrameRate Control and deinterlace use cases */
550 MFXVideoVPP_RunFrameVPPAsync (session, in_surface->surface,
551 out_surface->surface, NULL, &sync_point);
552 if (status != MFX_WRN_DEVICE_BUSY)
554 /* If device is busy, wait 1ms and retry, as per MSDK's recommendation */
558 if (status != MFX_ERR_NONE && status != MFX_ERR_MORE_DATA
559 && status != MFX_ERR_MORE_SURFACE)
562 /* No output generated */
563 if (status == MFX_ERR_MORE_DATA)
564 goto error_more_data;
567 MFXVideoCORE_SyncOperation (session, sync_point, 10000);
569 /* More than one output buffers are generated */
570 if (status == MFX_ERR_MORE_SURFACE) {
571 GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
572 GST_BUFFER_DURATION (outbuf) = thiz->buffer_duration;
573 timestamp += thiz->buffer_duration;
574 ret = gst_pad_push (GST_BASE_TRANSFORM_SRC_PAD (trans), outbuf);
575 if (ret != GST_FLOW_OK)
576 goto error_push_buffer;
577 outbuf = create_output_buffer (thiz);
579 GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
580 GST_BUFFER_DURATION (outbuf) = thiz->buffer_duration;
582 } while (status == MFX_ERR_MORE_SURFACE);
584 free_msdk_surface (in_surface);
588 GST_ERROR_OBJECT (thiz, "MSDK Failed to do VPP");
589 free_msdk_surface (in_surface);
590 free_msdk_surface (out_surface);
591 return GST_FLOW_ERROR;
594 GST_WARNING_OBJECT (thiz,
595 "MSDK Requries additional input for processing, "
596 "Retruning FLOW_DROPPED since no output buffer was generated");
597 free_msdk_surface (in_surface);
598 return GST_BASE_TRANSFORM_FLOW_DROPPED;
602 free_msdk_surface (in_surface);
603 free_msdk_surface (out_surface);
604 GST_DEBUG_OBJECT (thiz, "failed to push output buffer: %s",
605 gst_flow_get_name (ret));
611 gst_msdkvpp_close (GstMsdkVPP * thiz)
618 GST_DEBUG_OBJECT (thiz, "Closing VPP 0x%p", thiz->context);
619 status = MFXVideoVPP_Close (gst_msdk_context_get_session (thiz->context));
620 if (status != MFX_ERR_NONE && status != MFX_ERR_NOT_INITIALIZED) {
621 GST_WARNING_OBJECT (thiz, "Encoder close failed (%s)",
622 msdk_status_to_string (status));
626 gst_object_replace ((GstObject **) & thiz->context, NULL);
628 memset (&thiz->param, 0, sizeof (thiz->param));
630 if (thiz->sinkpad_buffer_pool)
631 gst_object_unref (thiz->sinkpad_buffer_pool);
632 thiz->sinkpad_buffer_pool = NULL;
633 if (thiz->srcpad_buffer_pool)
634 gst_object_unref (thiz->srcpad_buffer_pool);
635 thiz->srcpad_buffer_pool = NULL;
637 thiz->buffer_duration = GST_CLOCK_TIME_NONE;
638 gst_video_info_init (&thiz->sinkpad_info);
639 gst_video_info_init (&thiz->srcpad_info);
643 ensure_filters (GstMsdkVPP * thiz)
648 if (thiz->flags & GST_MSDK_FLAG_DENOISE) {
649 mfxExtVPPDenoise *mfx_denoise = &thiz->mfx_denoise;
650 mfx_denoise->Header.BufferId = MFX_EXTBUFF_VPP_DENOISE;
651 mfx_denoise->Header.BufferSz = sizeof (mfxExtVPPDenoise);
652 mfx_denoise->DenoiseFactor = thiz->denoise_factor;
653 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_denoise);
654 thiz->max_filter_algorithms[n_filters] = MFX_EXTBUFF_VPP_DENOISE;
659 if (thiz->flags & GST_MSDK_FLAG_ROTATION) {
660 mfxExtVPPRotation *mfx_rotation = &thiz->mfx_rotation;
661 mfx_rotation->Header.BufferId = MFX_EXTBUFF_VPP_ROTATION;
662 mfx_rotation->Header.BufferSz = sizeof (mfxExtVPPRotation);
663 mfx_rotation->Angle = thiz->rotation;
664 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_rotation);
665 thiz->max_filter_algorithms[n_filters] = MFX_EXTBUFF_VPP_ROTATION;
670 if (thiz->flags & GST_MSDK_FLAG_DEINTERLACE) {
671 mfxExtVPPDeinterlacing *mfx_deinterlace = &thiz->mfx_deinterlace;
672 mfx_deinterlace->Header.BufferId = MFX_EXTBUFF_VPP_DEINTERLACING;
673 mfx_deinterlace->Header.BufferSz = sizeof (mfxExtVPPDeinterlacing);
674 mfx_deinterlace->Mode = thiz->deinterlace_method;
675 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_deinterlace);
676 thiz->max_filter_algorithms[n_filters] = MFX_EXTBUFF_VPP_DEINTERLACING;
680 /* Colorbalance(ProcAmp) */
681 if (thiz->flags & (GST_MSDK_FLAG_HUE | GST_MSDK_FLAG_SATURATION |
682 GST_MSDK_FLAG_BRIGHTNESS | GST_MSDK_FLAG_CONTRAST)) {
683 mfxExtVPPProcAmp *mfx_procamp = &thiz->mfx_procamp;
684 mfx_procamp->Header.BufferId = MFX_EXTBUFF_VPP_PROCAMP;
685 mfx_procamp->Header.BufferSz = sizeof (mfxExtVPPProcAmp);
686 mfx_procamp->Hue = thiz->hue;
687 mfx_procamp->Saturation = thiz->saturation;
688 mfx_procamp->Brightness = thiz->brightness;
689 mfx_procamp->Contrast = thiz->contrast;
690 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_procamp);
691 thiz->max_filter_algorithms[n_filters] = MFX_EXTBUFF_VPP_PROCAMP;
695 /* Detail/Edge enhancement */
696 if (thiz->flags & GST_MSDK_FLAG_DETAIL) {
697 mfxExtVPPDetail *mfx_detail = &thiz->mfx_detail;
698 mfx_detail->Header.BufferId = MFX_EXTBUFF_VPP_DETAIL;
699 mfx_detail->Header.BufferSz = sizeof (mfxExtVPPDetail);
700 mfx_detail->DetailFactor = thiz->detail;
701 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_detail);
702 thiz->max_filter_algorithms[n_filters] = MFX_EXTBUFF_VPP_DETAIL;
708 mfxExtVPPDoUse *mfx_vpp_douse = &thiz->mfx_vpp_douse;
709 mfx_vpp_douse->Header.BufferId = MFX_EXTBUFF_VPP_DOUSE;
710 mfx_vpp_douse->Header.BufferSz = sizeof (mfxExtVPPDoUse);
711 mfx_vpp_douse->NumAlg = n_filters;
712 mfx_vpp_douse->AlgList = thiz->max_filter_algorithms;
713 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_vpp_douse);
717 if (thiz->flags & GST_MSDK_FLAG_MIRRORING) {
718 mfxExtVPPMirroring *mfx_mirroring = &thiz->mfx_mirroring;
719 mfx_mirroring->Header.BufferId = MFX_EXTBUFF_VPP_MIRRORING;
720 mfx_mirroring->Header.BufferSz = sizeof (mfxExtVPPMirroring);
721 mfx_mirroring->Type = thiz->mirroring;
722 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_mirroring);
723 thiz->max_filter_algorithms[n_filters] = MFX_EXTBUFF_VPP_MIRRORING;
728 if (thiz->flags & GST_MSDK_FLAG_SCALING_MODE) {
729 mfxExtVPPScaling *mfx_scaling = &thiz->mfx_scaling;
730 mfx_scaling->Header.BufferId = MFX_EXTBUFF_VPP_SCALING;
731 mfx_scaling->Header.BufferSz = sizeof (mfxExtVPPScaling);
732 mfx_scaling->ScalingMode = thiz->scaling_mode;
733 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_scaling);
734 thiz->max_filter_algorithms[n_filters] = MFX_EXTBUFF_VPP_SCALING;
739 if (thiz->flags & GST_MSDK_FLAG_FRC) {
740 mfxExtVPPFrameRateConversion *mfx_frc = &thiz->mfx_frc;
741 mfx_frc->Header.BufferId = MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION;
742 mfx_frc->Header.BufferSz = sizeof (mfxExtVPPFrameRateConversion);
743 mfx_frc->Algorithm = thiz->frc_algm;
744 gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_frc);
745 thiz->max_filter_algorithms[n_filters] =
746 MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION;
752 gst_msdkvpp_set_passthrough (GstMsdkVPP * thiz)
754 gboolean passthrough = TRUE;
756 /* no passthrough if any of the filter algorithm is enabled */
760 /* no passthrough if there is change in out width,height or format */
761 if (GST_VIDEO_INFO_WIDTH (&thiz->sinkpad_info) !=
762 GST_VIDEO_INFO_WIDTH (&thiz->srcpad_info)
763 || GST_VIDEO_INFO_HEIGHT (&thiz->sinkpad_info) !=
764 GST_VIDEO_INFO_HEIGHT (&thiz->srcpad_info)
765 || GST_VIDEO_INFO_FORMAT (&thiz->sinkpad_info) !=
766 GST_VIDEO_INFO_FORMAT (&thiz->srcpad_info))
769 GST_OBJECT_UNLOCK (thiz);
770 gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (thiz), passthrough);
771 GST_OBJECT_LOCK (thiz);
775 gst_msdkvpp_initialize (GstMsdkVPP * thiz)
779 mfxFrameAllocRequest request[2];
781 if (!thiz->context) {
782 GST_WARNING_OBJECT (thiz, "No MSDK Context");
786 GST_OBJECT_LOCK (thiz);
787 session = gst_msdk_context_get_session (thiz->context);
789 if (thiz->use_video_memory) {
790 gst_msdk_set_frame_allocator (thiz->context);
791 thiz->param.IOPattern =
792 MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY;
794 thiz->param.IOPattern =
795 MFX_IOPATTERN_IN_SYSTEM_MEMORY | MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
798 /* update input video attributes */
799 gst_msdk_set_mfx_frame_info_from_video_info (&thiz->param.vpp.In,
800 &thiz->sinkpad_info);
802 /* update output video attributes, only CSC and Scaling are supported for now */
803 gst_msdk_set_mfx_frame_info_from_video_info (&thiz->param.vpp.Out,
806 /* use msdk frame rarte control if there is a mismatch in In & OUt fps */
807 if (GST_VIDEO_INFO_FPS_N (&thiz->srcpad_info) &&
808 (GST_VIDEO_INFO_FPS_N (&thiz->sinkpad_info) !=
809 GST_VIDEO_INFO_FPS_N (&thiz->srcpad_info)
810 || GST_VIDEO_INFO_FPS_D (&thiz->sinkpad_info) !=
811 GST_VIDEO_INFO_FPS_D (&thiz->srcpad_info))) {
812 thiz->flags |= GST_MSDK_FLAG_FRC;
813 /* So far this is the only algorithm which is working somewhat good */
814 thiz->frc_algm = MFX_FRCALGM_PRESERVE_TIMESTAMP;
817 /* work-around to avoid zero fps in msdk structure */
818 if (!thiz->param.vpp.In.FrameRateExtN)
819 thiz->param.vpp.In.FrameRateExtN = 30;
820 if (!thiz->param.vpp.Out.FrameRateExtN)
821 thiz->param.vpp.Out.FrameRateExtN = thiz->param.vpp.In.FrameRateExtN;
823 /* set vpp out picstruct as progressive if deinterlacing enabled */
824 if (thiz->flags & GST_MSDK_FLAG_DEINTERLACE)
825 thiz->param.vpp.Out.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
827 /* validate parameters and allow the Media SDK to make adjustments */
828 status = MFXVideoVPP_Query (session, &thiz->param, &thiz->param);
829 if (status < MFX_ERR_NONE) {
830 GST_ERROR_OBJECT (thiz, "Video VPP Query failed (%s)",
831 msdk_status_to_string (status));
833 } else if (status > MFX_ERR_NONE) {
834 GST_WARNING_OBJECT (thiz, "Video VPP Query returned: %s",
835 msdk_status_to_string (status));
838 /* Enable the required filters */
839 ensure_filters (thiz);
841 /* set passthrough according to filter operation change */
842 gst_msdkvpp_set_passthrough (thiz);
844 /* Add exteneded buffers */
845 if (thiz->num_extra_params) {
846 thiz->param.NumExtParam = thiz->num_extra_params;
847 thiz->param.ExtParam = thiz->extra_params;
850 status = MFXVideoVPP_QueryIOSurf (session, &thiz->param, request);
851 if (status < MFX_ERR_NONE) {
852 GST_ERROR_OBJECT (thiz, "VPP Query IO surfaces failed (%s)",
853 msdk_status_to_string (status));
855 } else if (status > MFX_ERR_NONE) {
856 GST_WARNING_OBJECT (thiz, "VPP Query IO surfaces returned: %s",
857 msdk_status_to_string (status));
860 if (thiz->use_video_memory) {
861 /* Input surface pool pre-allocation */
862 gst_msdk_frame_alloc (thiz->context, &(request[0]), &thiz->in_alloc_resp);
863 /* Output surface pool pre-allocation */
864 gst_msdk_frame_alloc (thiz->context, &(request[1]), &thiz->out_alloc_resp);
867 thiz->in_num_surfaces = request[0].NumFrameSuggested;
868 thiz->out_num_surfaces = request[1].NumFrameSuggested;
871 status = MFXVideoVPP_Init (session, &thiz->param);
872 if (status < MFX_ERR_NONE) {
873 GST_ERROR_OBJECT (thiz, "Init failed (%s)", msdk_status_to_string (status));
875 } else if (status > MFX_ERR_NONE) {
876 GST_WARNING_OBJECT (thiz, "Init returned: %s",
877 msdk_status_to_string (status));
880 GST_OBJECT_UNLOCK (thiz);
884 GST_OBJECT_UNLOCK (thiz);
886 gst_object_replace ((GstObject **) & thiz->context, NULL);
891 gst_msdkvpp_set_caps (GstBaseTransform * trans, GstCaps * caps,
894 GstMsdkVPP *thiz = GST_MSDKVPP (trans);
895 GstVideoInfo in_info, out_info;
896 gboolean sinkpad_info_changed = FALSE;
897 gboolean srcpad_info_changed = FALSE;
898 gboolean deinterlace;
900 gst_video_info_from_caps (&in_info, caps);
901 gst_video_info_from_caps (&out_info, out_caps);
903 if (!gst_video_info_is_equal (&in_info, &thiz->sinkpad_info))
904 sinkpad_info_changed = TRUE;
905 if (!gst_video_info_is_equal (&out_info, &thiz->srcpad_info))
906 srcpad_info_changed = TRUE;
908 thiz->sinkpad_info = in_info;
909 thiz->srcpad_info = out_info;
911 thiz->use_video_memory = TRUE;
913 thiz->use_video_memory = FALSE;
916 if (!sinkpad_info_changed && !srcpad_info_changed)
919 /* check for deinterlace requirement */
920 deinterlace = gst_msdkvpp_is_deinterlace_enabled (thiz, &in_info);
922 thiz->flags |= GST_MSDK_FLAG_DEINTERLACE;
924 thiz->buffer_duration = GST_VIDEO_INFO_FPS_N (&out_info) > 0 ?
925 gst_util_uint64_scale (GST_SECOND, GST_VIDEO_INFO_FPS_D (&out_info),
926 GST_VIDEO_INFO_FPS_N (&out_info)) : 0;
928 if (!gst_msdkvpp_initialize (thiz))
931 /* Ensure sinkpad buffer pool */
932 thiz->sinkpad_buffer_pool =
933 gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SINK, caps,
934 thiz->in_num_surfaces);
935 if (!thiz->sinkpad_buffer_pool) {
936 GST_ERROR_OBJECT (thiz, "Failed to ensure the sinkpad buffer pool");
939 /* Ensure a srcpad buffer pool */
940 thiz->srcpad_buffer_pool =
941 gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SRC, out_caps,
942 thiz->out_num_surfaces);
943 if (!thiz->srcpad_buffer_pool) {
944 GST_ERROR_OBJECT (thiz, "Failed to ensure the srcpad buffer pool");
952 gst_msdkvpp_fixate_caps (GstBaseTransform * trans,
953 GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
955 GstMsdkVPP *thiz = GST_MSDKVPP (trans);
956 GstCaps *result = NULL;
958 if (direction == GST_PAD_SRC)
959 result = gst_caps_fixate (result);
961 result = gst_msdkvpp_fixate_srccaps (thiz, caps, othercaps);
964 GST_DEBUG_OBJECT (trans, "fixated to %" GST_PTR_FORMAT, result);
965 gst_caps_unref (othercaps);
969 /* Generic code for now, requires changes in future when we
970 * add hardware query for supported formats, Framerate control etc */
972 gst_msdkvpp_transform_caps (GstBaseTransform * trans,
973 GstPadDirection direction, GstCaps * caps, GstCaps * filter)
977 GST_DEBUG_OBJECT (trans,
978 "Transforming caps %" GST_PTR_FORMAT " in direction %s", caps,
979 (direction == GST_PAD_SINK) ? "sink" : "src");
981 if (direction == GST_PAD_SRC)
982 out_caps = gst_static_pad_template_get_caps (&gst_msdkvpp_sink_factory);
984 out_caps = gst_static_pad_template_get_caps (&gst_msdkvpp_src_factory);
986 if (out_caps && filter) {
987 GstCaps *intersection;
989 intersection = gst_caps_intersect_full (out_caps, filter,
990 GST_CAPS_INTERSECT_FIRST);
991 gst_caps_unref (out_caps);
992 out_caps = intersection;
995 GST_DEBUG_OBJECT (trans, "returning caps: %" GST_PTR_FORMAT, out_caps);
1000 gst_msdkvpp_start (GstBaseTransform * trans)
1002 if (!ensure_context (trans))
1008 gst_msdkvpp_stop (GstBaseTransform * trans)
1010 gst_msdkvpp_close (GST_MSDKVPP (trans));
1015 gst_msdkvpp_set_property (GObject * object, guint prop_id,
1016 const GValue * value, GParamSpec * pspec)
1018 GstMsdkVPP *thiz = GST_MSDKVPP (object);
1022 thiz->hardware = g_value_get_boolean (value);
1024 case PROP_ASYNC_DEPTH:
1025 thiz->async_depth = g_value_get_uint (value);
1028 thiz->denoise_factor = g_value_get_uint (value);
1029 thiz->flags |= GST_MSDK_FLAG_DENOISE;
1032 thiz->rotation = g_value_get_enum (value);
1033 thiz->flags |= GST_MSDK_FLAG_ROTATION;
1035 case PROP_DEINTERLACE_MODE:
1036 thiz->deinterlace_mode = g_value_get_enum (value);
1038 case PROP_DEINTERLACE_METHOD:
1039 thiz->deinterlace_method = g_value_get_enum (value);
1042 thiz->hue = g_value_get_float (value);
1043 thiz->flags |= GST_MSDK_FLAG_HUE;
1045 case PROP_SATURATION:
1046 thiz->saturation = g_value_get_float (value);
1047 thiz->flags |= GST_MSDK_FLAG_SATURATION;
1049 case PROP_BRIGHTNESS:
1050 thiz->brightness = g_value_get_float (value);
1051 thiz->flags |= GST_MSDK_FLAG_BRIGHTNESS;
1054 thiz->contrast = g_value_get_float (value);
1055 thiz->flags |= GST_MSDK_FLAG_CONTRAST;
1058 thiz->detail = g_value_get_uint (value);
1059 thiz->flags |= GST_MSDK_FLAG_DETAIL;
1061 case PROP_MIRRORING:
1062 thiz->mirroring = g_value_get_enum (value);
1063 thiz->flags |= GST_MSDK_FLAG_MIRRORING;
1065 case PROP_SCALING_MODE:
1066 thiz->scaling_mode = g_value_get_enum (value);
1067 thiz->flags |= GST_MSDK_FLAG_SCALING_MODE;
1069 case PROP_FORCE_ASPECT_RATIO:
1070 thiz->keep_aspect = g_value_get_boolean (value);
1072 case PROP_FRC_ALGORITHM:
1073 thiz->frc_algm = g_value_get_enum (value);
1076 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1082 gst_msdkvpp_get_property (GObject * object, guint prop_id,
1083 GValue * value, GParamSpec * pspec)
1085 GstMsdkVPP *thiz = GST_MSDKVPP (object);
1089 g_value_set_boolean (value, thiz->hardware);
1091 case PROP_ASYNC_DEPTH:
1092 g_value_set_uint (value, thiz->async_depth);
1095 g_value_set_uint (value, thiz->denoise_factor);
1098 g_value_set_enum (value, thiz->rotation);
1100 case PROP_DEINTERLACE_MODE:
1101 g_value_set_enum (value, thiz->deinterlace_mode);
1103 case PROP_DEINTERLACE_METHOD:
1104 g_value_set_enum (value, thiz->deinterlace_method);
1107 g_value_set_float (value, thiz->hue);
1109 case PROP_SATURATION:
1110 g_value_set_float (value, thiz->saturation);
1112 case PROP_BRIGHTNESS:
1113 g_value_set_float (value, thiz->brightness);
1116 g_value_set_float (value, thiz->contrast);
1119 g_value_set_uint (value, thiz->detail);
1121 case PROP_MIRRORING:
1122 g_value_set_enum (value, thiz->mirroring);
1124 case PROP_SCALING_MODE:
1125 g_value_set_enum (value, thiz->scaling_mode);
1127 case PROP_FORCE_ASPECT_RATIO:
1128 g_value_set_boolean (value, thiz->keep_aspect);
1130 case PROP_FRC_ALGORITHM:
1131 g_value_set_enum (value, thiz->frc_algm);
1134 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1140 gst_msdkvpp_finalize (GObject * object)
1142 G_OBJECT_CLASS (parent_class)->finalize (object);
1146 gst_msdkvpp_set_context (GstElement * element, GstContext * context)
1148 GstMsdkContext *msdk_context = NULL;
1149 GstMsdkVPP *thiz = GST_MSDKVPP (element);
1151 if (gst_msdk_context_get_context (context, &msdk_context)) {
1152 gst_object_replace ((GstObject **) & thiz->context,
1153 (GstObject *) msdk_context);
1154 gst_object_unref (msdk_context);
1157 GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
1161 gst_msdkvpp_class_init (GstMsdkVPPClass * klass)
1163 GObjectClass *gobject_class;
1164 GstElementClass *element_class;
1165 GstBaseTransformClass *trans_class;
1166 GParamSpec *obj_properties[PROP_N] = { NULL, };
1168 gobject_class = G_OBJECT_CLASS (klass);
1169 element_class = GST_ELEMENT_CLASS (klass);
1170 trans_class = GST_BASE_TRANSFORM_CLASS (klass);
1172 gobject_class->set_property = gst_msdkvpp_set_property;
1173 gobject_class->get_property = gst_msdkvpp_get_property;
1174 gobject_class->finalize = gst_msdkvpp_finalize;
1176 element_class->set_context = gst_msdkvpp_set_context;
1178 gst_element_class_add_static_pad_template (element_class,
1179 &gst_msdkvpp_src_factory);
1180 gst_element_class_add_static_pad_template (element_class,
1181 &gst_msdkvpp_sink_factory);
1183 gst_element_class_set_static_metadata (element_class,
1184 "MSDK Video Postprocessor",
1185 "Filter/Converter/Video;Filter/Converter/Video/Scaler;"
1186 "Filter/Effect/Video;Filter/Effect/Video/Deinterlace",
1187 "A MediaSDK Video Postprocessing Filter",
1188 "Sreerenj Balachandrn <sreerenj.balachandran@intel.com>");
1190 trans_class->start = GST_DEBUG_FUNCPTR (gst_msdkvpp_start);
1191 trans_class->stop = GST_DEBUG_FUNCPTR (gst_msdkvpp_stop);
1192 trans_class->transform_caps = GST_DEBUG_FUNCPTR (gst_msdkvpp_transform_caps);
1193 trans_class->fixate_caps = GST_DEBUG_FUNCPTR (gst_msdkvpp_fixate_caps);
1194 trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_msdkvpp_set_caps);
1195 trans_class->transform = GST_DEBUG_FUNCPTR (gst_msdkvpp_transform);
1196 trans_class->propose_allocation =
1197 GST_DEBUG_FUNCPTR (gst_msdkvpp_propose_allocation);
1198 trans_class->decide_allocation =
1199 GST_DEBUG_FUNCPTR (gst_msdkvpp_decide_allocation);
1200 trans_class->prepare_output_buffer =
1201 GST_DEBUG_FUNCPTR (gst_msdkvpp_prepare_output_buffer);
1203 obj_properties[PROP_HARDWARE] =
1204 g_param_spec_boolean ("hardware", "Hardware", "Enable hardware VPP",
1205 PROP_HARDWARE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1207 obj_properties[PROP_ASYNC_DEPTH] =
1208 g_param_spec_uint ("async-depth", "Async Depth",
1209 "Depth of asynchronous pipeline",
1210 1, 1, PROP_ASYNC_DEPTH_DEFAULT,
1211 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1213 obj_properties[PROP_DENOISE] =
1214 g_param_spec_uint ("denoise", "Denoising factor",
1216 0, 100, PROP_DENOISE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1218 obj_properties[PROP_ROTATION] =
1219 g_param_spec_enum ("rotation", "Rotation",
1220 "Rotation Angle", gst_msdkvpp_rotation_get_type (),
1221 PROP_ROTATION_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1223 obj_properties[PROP_DEINTERLACE_MODE] =
1224 g_param_spec_enum ("deinterlace-mode", "Deinterlace Mode",
1225 "Deinterlace mode to use", gst_msdkvpp_deinterlace_mode_get_type (),
1226 PROP_DEINTERLACE_MODE_DEFAULT,
1227 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1229 obj_properties[PROP_DEINTERLACE_METHOD] =
1230 g_param_spec_enum ("deinterlace-method", "Deinterlace Method",
1231 "Deinterlace method to use", gst_msdkvpp_deinterlace_method_get_type (),
1232 PROP_DEINTERLACE_METHOD_DEFAULT,
1233 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1235 obj_properties[PROP_HUE] =
1236 g_param_spec_float ("hue", "Hue",
1237 "The hue of the video",
1238 -180, 180, PROP_HUE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1240 obj_properties[PROP_SATURATION] =
1241 g_param_spec_float ("saturation", "Saturation",
1242 "The Saturation of the video",
1243 0, 10, PROP_SATURATION_DEFAULT,
1244 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1246 obj_properties[PROP_BRIGHTNESS] =
1247 g_param_spec_float ("brightness", "Brightness",
1248 "The Brightness of the video",
1249 -100, 100, PROP_BRIGHTNESS_DEFAULT,
1250 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1252 obj_properties[PROP_CONTRAST] =
1253 g_param_spec_float ("contrast", "Contrast",
1254 "The Contrast of the video",
1255 0, 10, PROP_CONTRAST_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1257 obj_properties[PROP_DETAIL] =
1258 g_param_spec_uint ("detail", "Detail",
1259 "The factor of detail/edge enhancement filter algorithm",
1260 0, 100, PROP_DETAIL_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1262 obj_properties[PROP_MIRRORING] =
1263 g_param_spec_enum ("mirroring", "Mirroring",
1264 "The Mirroring type", gst_msdkvpp_mirroring_get_type (),
1265 PROP_MIRRORING_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1267 obj_properties[PROP_SCALING_MODE] =
1268 g_param_spec_enum ("scaling-mode", "Scaling Mode",
1269 "The Scaling mode to use", gst_msdkvpp_scaling_mode_get_type (),
1270 PROP_SCALING_MODE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1272 obj_properties[PROP_FORCE_ASPECT_RATIO] =
1273 g_param_spec_boolean ("force-aspect-ratio", "Force Aspect Ratio",
1274 "When enabled, scaling will respect original aspect ratio",
1275 PROP_FORCE_ASPECT_RATIO_DEFAULT,
1276 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1278 obj_properties[PROP_FRC_ALGORITHM] =
1279 g_param_spec_enum ("frc-algorithm", "FrameRateControl Algorithm",
1280 "The Framerate Control Alogorithm to use",
1281 gst_msdkvpp_frc_algorithm_get_type (), PROP_FRC_ALGORITHM_DEFAULT,
1282 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1284 g_object_class_install_properties (gobject_class, PROP_N, obj_properties);
1288 gst_msdkvpp_init (GstMsdkVPP * thiz)
1290 thiz->hardware = PROP_HARDWARE_DEFAULT;
1291 thiz->async_depth = PROP_ASYNC_DEPTH_DEFAULT;
1292 thiz->denoise_factor = PROP_DENOISE_DEFAULT;
1293 thiz->rotation = PROP_ROTATION_DEFAULT;
1294 thiz->deinterlace_mode = PROP_DEINTERLACE_MODE_DEFAULT;
1295 thiz->deinterlace_method = PROP_DEINTERLACE_METHOD_DEFAULT;
1296 thiz->buffer_duration = GST_CLOCK_TIME_NONE;
1297 thiz->hue = PROP_HUE_DEFAULT;
1298 thiz->saturation = PROP_SATURATION_DEFAULT;
1299 thiz->brightness = PROP_BRIGHTNESS_DEFAULT;
1300 thiz->contrast = PROP_CONTRAST_DEFAULT;
1301 thiz->detail = PROP_DETAIL_DEFAULT;
1302 thiz->mirroring = PROP_MIRRORING_DEFAULT;
1303 thiz->scaling_mode = PROP_SCALING_MODE_DEFAULT;
1304 thiz->keep_aspect = PROP_FORCE_ASPECT_RATIO_DEFAULT;
1305 thiz->frc_algm = PROP_FRC_ALGORITHM_DEFAULT;
1306 gst_video_info_init (&thiz->sinkpad_info);
1307 gst_video_info_init (&thiz->srcpad_info);