msdk: vpp: Add ProAmp(colorbalance) support
[platform/upstream/gstreamer.git] / sys / msdk / gstmsdkvpp.c
1 /* GStreamer Intel MSDK plugin
2  * Copyright (c) 2018, Intel Corporation
3  * All rights reserved.
4  *
5  * Author: Sreerenj Balachaandran <sreerenj.balachandran@intel.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  *    this list of conditions and the following disclaimer.
12  *
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.
16  *
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.
20  *
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.
32  */
33
34 #ifdef HAVE_CONFIG_H
35 #  include <config.h>
36 #endif
37
38 #include <stdlib.h>
39
40 #include "gstmsdkvpp.h"
41 #include "gstmsdkbufferpool.h"
42 #include "gstmsdkvideomemory.h"
43 #include "gstmsdksystemmemory.h"
44 #include "gstmsdkcontextutil.h"
45 #include "gstmsdkvpputil.h"
46
47 GST_DEBUG_CATEGORY_EXTERN (gst_msdkvpp_debug);
48 #define GST_CAT_DEFAULT gst_msdkvpp_debug
49
50 static GstStaticPadTemplate gst_msdkvpp_sink_factory =
51 GST_STATIC_PAD_TEMPLATE ("sink",
52     GST_PAD_SINK,
53     GST_PAD_ALWAYS,
54     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ NV12, I420, YUY2, UYVY, BGRA }")
55         ", " "interlace-mode = (string){ progressive, interleaved, mixed }"));
56
57 static GstStaticPadTemplate gst_msdkvpp_src_factory =
58 GST_STATIC_PAD_TEMPLATE ("src",
59     GST_PAD_SRC,
60     GST_PAD_ALWAYS,
61     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ NV12, BGRA }") ", "
62         "interlace-mode = (string){ progressive, interleaved, mixed }"));
63
64 enum
65 {
66   PROP_0,
67   PROP_HARDWARE,
68   PROP_ASYNC_DEPTH,
69   PROP_DENOISE,
70   PROP_ROTATION,
71   PROP_DEINTERLACE_MODE,
72   PROP_DEINTERLACE_METHOD,
73   PROP_HUE,
74   PROP_SATURATION,
75   PROP_BRIGHTNESS,
76   PROP_CONTRAST,
77   PROP_N,
78 };
79
80 #define PROP_HARDWARE_DEFAULT            TRUE
81 #define PROP_ASYNC_DEPTH_DEFAULT         1
82 #define PROP_DENOISE_DEFAULT             0
83 #define PROP_ROTATION_DEFAULT            MFX_ANGLE_0
84 #define PROP_DEINTERLACE_MODE_DEFAULT    GST_MSDKVPP_DEINTERLACE_MODE_AUTO
85 #define PROP_DEINTERLACE_METHOD_DEFAULT  MFX_DEINTERLACING_BOB
86 #define PROP_HUE_DEFAULT                 0
87 #define PROP_SATURATION_DEFAULT          1
88 #define PROP_BRIGHTNESS_DEFAULT          0
89 #define PROP_CONTRAST_DEFAULT            1
90
91 #define gst_msdkvpp_parent_class parent_class
92 G_DEFINE_TYPE (GstMsdkVPP, gst_msdkvpp, GST_TYPE_BASE_TRANSFORM);
93
94 typedef struct
95 {
96   mfxFrameSurface1 *surface;
97   GstBuffer *buf;
98 } MsdkSurface;
99
100 static void
101 free_msdk_surface (MsdkSurface * surface)
102 {
103   if (surface->buf)
104     gst_buffer_unref (surface->buf);
105   g_slice_free (MsdkSurface, surface);
106 }
107
108 static void
109 gst_msdkvpp_add_extra_param (GstMsdkVPP * thiz, mfxExtBuffer * param)
110 {
111   if (thiz->num_extra_params < MAX_EXTRA_PARAMS) {
112     thiz->extra_params[thiz->num_extra_params] = param;
113     thiz->num_extra_params++;
114   }
115 }
116
117 static gboolean
118 ensure_context (GstBaseTransform * trans)
119 {
120   GstMsdkVPP *thiz = GST_MSDKVPP (trans);
121
122   if (gst_msdk_context_prepare (GST_ELEMENT_CAST (thiz), &thiz->context)) {
123     GST_INFO_OBJECT (thiz, "Found context from neighbour %" GST_PTR_FORMAT,
124         thiz->context);
125
126     if (gst_msdk_context_get_job_type (thiz->context) & GST_MSDK_JOB_VPP) {
127       GstMsdkContext *parent_context;
128
129       parent_context = thiz->context;
130       thiz->context = gst_msdk_context_new_with_parent (parent_context);
131       gst_object_unref (parent_context);
132
133       GST_INFO_OBJECT (thiz,
134           "Creating new context %" GST_PTR_FORMAT " with joined session",
135           thiz->context);
136     } else {
137       gst_msdk_context_add_job_type (thiz->context, GST_MSDK_JOB_VPP);
138     }
139   } else {
140     if (!gst_msdk_context_ensure_context (GST_ELEMENT_CAST (thiz),
141             thiz->hardware, GST_MSDK_JOB_VPP))
142       return FALSE;
143     GST_INFO_OBJECT (thiz, "Creating new context %" GST_PTR_FORMAT,
144         thiz->context);
145   }
146
147   gst_msdk_context_add_shared_async_depth (thiz->context, thiz->async_depth);
148
149   return TRUE;
150 }
151
152 static GstBuffer *
153 create_output_buffer (GstMsdkVPP * thiz)
154 {
155   GstBuffer *outbuf;
156   GstFlowReturn ret;
157   GstBufferPool *pool = thiz->srcpad_buffer_pool;
158
159   g_return_val_if_fail (pool != NULL, NULL);
160
161   if (!gst_buffer_pool_is_active (pool) &&
162       !gst_buffer_pool_set_active (pool, TRUE))
163     goto error_activate_pool;
164
165   outbuf = NULL;
166   ret = gst_buffer_pool_acquire_buffer (pool, &outbuf, NULL);
167   if (ret != GST_FLOW_OK || !outbuf)
168     goto error_create_buffer;
169
170   return outbuf;
171
172   /* ERRORS */
173 error_activate_pool:
174   {
175     GST_ERROR_OBJECT (thiz, "failed to activate output video buffer pool");
176     return NULL;
177   }
178 error_create_buffer:
179   {
180     GST_ERROR_OBJECT (thiz, "failed to create output video buffer");
181     return NULL;
182   }
183 }
184
185 static GstFlowReturn
186 gst_msdkvpp_prepare_output_buffer (GstBaseTransform * trans,
187     GstBuffer * inbuf, GstBuffer ** outbuf_ptr)
188 {
189   GstMsdkVPP *thiz = GST_MSDKVPP (trans);
190
191   if (gst_base_transform_is_passthrough (trans)) {
192     *outbuf_ptr = inbuf;
193     return GST_FLOW_OK;
194   }
195
196   *outbuf_ptr = create_output_buffer (thiz);
197   return *outbuf_ptr ? GST_FLOW_OK : GST_FLOW_ERROR;
198 }
199
200 static GstBufferPool *
201 gst_msdkvpp_create_buffer_pool (GstMsdkVPP * thiz, GstPadDirection direction,
202     GstCaps * caps, guint min_num_buffers)
203 {
204   GstBufferPool *pool = NULL;
205   GstStructure *config;
206   GstAllocator *allocator = NULL;
207   GstVideoInfo info;
208   GstVideoInfo *pool_info = NULL;
209   GstVideoAlignment align;
210   GstAllocationParams params = { 0, 31, 0, 0, };
211   mfxFrameAllocResponse *alloc_resp = NULL;
212
213   if (direction == GST_PAD_SINK) {
214     alloc_resp = &thiz->in_alloc_resp;
215     pool_info = &thiz->sinkpad_buffer_pool_info;
216   } else if (direction == GST_PAD_SRC) {
217     alloc_resp = &thiz->out_alloc_resp;
218     pool_info = &thiz->srcpad_buffer_pool_info;
219   }
220
221   pool = gst_msdk_buffer_pool_new (thiz->context, alloc_resp);
222   if (!pool)
223     goto error_no_pool;
224
225   if (!gst_video_info_from_caps (&info, caps))
226     goto error_no_video_info;
227
228   gst_msdk_set_video_alignment (&info, &align);
229   gst_video_info_align (&info, &align);
230
231   if (thiz->use_video_memory)
232     allocator = gst_msdk_video_allocator_new (thiz->context, &info, alloc_resp);
233   else
234     allocator = gst_msdk_system_allocator_new (&info);
235
236   if (!allocator)
237     goto error_no_allocator;
238
239   config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
240   gst_buffer_pool_config_set_params (config, caps, info.size, min_num_buffers,
241       0);
242
243   gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
244   gst_buffer_pool_config_add_option (config,
245       GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
246   if (thiz->use_video_memory)
247     gst_buffer_pool_config_add_option (config,
248         GST_BUFFER_POOL_OPTION_MSDK_USE_VIDEO_MEMORY);
249
250   gst_buffer_pool_config_set_video_alignment (config, &align);
251   gst_buffer_pool_config_set_allocator (config, allocator, &params);
252   gst_object_unref (allocator);
253
254   if (!gst_buffer_pool_set_config (pool, config))
255     goto error_pool_config;
256
257   /* Updating pool_info with algined info of allocator */
258   *pool_info = info;
259
260   return pool;
261
262 error_no_pool:
263   {
264     GST_INFO_OBJECT (thiz, "Failed to create bufferpool");
265     return NULL;
266   }
267 error_no_video_info:
268   {
269     GST_INFO_OBJECT (thiz, "Failed to get Video info from caps");
270     return NULL;
271   }
272 error_no_allocator:
273   {
274     GST_INFO_OBJECT (thiz, "Failed to create allocator");
275     if (pool)
276       gst_object_unref (pool);
277     return NULL;
278   }
279 error_pool_config:
280   {
281     GST_INFO_OBJECT (thiz, "Failed to set config");
282     if (pool)
283       gst_object_unref (pool);
284     if (allocator)
285       gst_object_unref (allocator);
286     return NULL;
287   }
288 }
289
290 static gboolean
291 gst_msdkvpp_decide_allocation (GstBaseTransform * trans, GstQuery * query)
292 {
293   GstMsdkVPP *thiz = GST_MSDKVPP (trans);
294   GstVideoInfo info;
295   GstBufferPool *pool = NULL;
296   GstStructure *config = NULL;
297   GstCaps *caps;
298   guint size = 0, min_buffers = 0, max_buffers = 0;
299   GstAllocator *allocator = NULL;
300   GstAllocationParams params;
301   gboolean update_pool = FALSE;
302
303   gst_query_parse_allocation (query, &caps, NULL);
304   if (!caps) {
305     GST_ERROR_OBJECT (thiz, "Failed to parse the decide_allocation caps");
306     return FALSE;
307   }
308   if (!gst_video_info_from_caps (&info, caps)) {
309     GST_ERROR_OBJECT (thiz, "Failed to get video info");
310     return FALSE;
311   }
312
313   if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL))
314     thiz->add_video_meta = TRUE;
315   else
316     thiz->add_video_meta = FALSE;
317
318   if (gst_query_get_n_allocation_pools (query) > 0) {
319     gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min_buffers,
320         &max_buffers);
321     update_pool = TRUE;
322     size = MAX (size, GST_VIDEO_INFO_SIZE (&info));
323
324     if (pool && !GST_IS_MSDK_BUFFER_POOL (pool)) {
325       GST_INFO_OBJECT (thiz, "ignoring non-msdk pool: %" GST_PTR_FORMAT, pool);
326       g_clear_object (&pool);
327     }
328   }
329
330   if (!pool) {
331     gst_object_unref (thiz->srcpad_buffer_pool);
332     pool =
333         gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SRC, caps, min_buffers);
334     thiz->srcpad_buffer_pool = pool;
335
336     /* get the configured pool properties inorder to set in query */
337     config = gst_buffer_pool_get_config (pool);
338     gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers,
339         &max_buffers);
340     if (gst_buffer_pool_config_get_allocator (config, &allocator, &params))
341       gst_query_add_allocation_param (query, allocator, &params);
342     gst_structure_free (config);
343   }
344
345   if (update_pool)
346     gst_query_set_nth_allocation_pool (query, 0, pool, size, min_buffers,
347         max_buffers);
348   else
349     gst_query_add_allocation_pool (query, pool, size, min_buffers, max_buffers);
350
351   gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
352
353   /* Fixme if downstream doesn't have videometa support, msdkvpp should
354    * copy the output buffers */
355
356   return TRUE;
357 }
358
359 static gboolean
360 gst_msdkvpp_propose_allocation (GstBaseTransform * trans,
361     GstQuery * decide_query, GstQuery * query)
362 {
363   GstMsdkVPP *thiz = GST_MSDKVPP (trans);
364   GstVideoInfo info;
365   GstBufferPool *pool = NULL;
366   GstAllocator *allocator = NULL;
367   GstCaps *caps;
368   GstStructure *config;
369   gboolean need_pool;
370   guint size;
371   GstAllocationParams params;
372
373   gst_query_parse_allocation (query, &caps, &need_pool);
374   if (!caps) {
375     GST_ERROR_OBJECT (thiz, "Failed to parse the allocation caps");
376     return FALSE;
377   }
378
379   if (!gst_video_info_from_caps (&info, caps)) {
380     GST_ERROR_OBJECT (thiz, "Failed to get video info");
381     return FALSE;
382   }
383
384   size = MAX (info.size, GST_VIDEO_INFO_SIZE (&thiz->sinkpad_buffer_pool_info));
385
386   /* We already created a pool while setting the caps
387    * just to make sure the pipeline works even if there is
388    * no allocation query from upstream (theoratical ??).Provide the
389    * same pool in query if required/possible */
390   if (!gst_video_info_is_equal (&thiz->sinkpad_buffer_pool_info, &info)) {
391     gst_object_unref (thiz->sinkpad_buffer_pool);
392     thiz->sinkpad_buffer_pool =
393         gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SINK, caps,
394         thiz->in_num_surfaces);
395   }
396
397   pool = thiz->sinkpad_buffer_pool;
398
399   config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
400
401   gst_buffer_pool_config_get_params (config, NULL, &size, NULL, NULL);
402
403   if (gst_buffer_pool_config_get_allocator (config, &allocator, &params))
404     gst_query_add_allocation_param (query, allocator, &params);
405   gst_structure_free (config);
406
407   /* if upstream does't have a pool requirement, set only
408    *  size, min_buffers and max_buffers in query */
409   if (!need_pool)
410     pool = NULL;
411
412   gst_query_add_allocation_pool (query, pool, size, thiz->in_num_surfaces, 0);
413   gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
414
415   return GST_BASE_TRANSFORM_CLASS (parent_class)->propose_allocation (trans,
416       decide_query, query);
417 }
418
419 static MsdkSurface *
420 get_surface_from_pool (GstMsdkVPP * thiz, GstBufferPool * pool,
421     GstBufferPoolAcquireParams * params)
422 {
423   GstBuffer *new_buffer;
424   mfxFrameSurface1 *new_surface;
425   MsdkSurface *msdk_surface;
426
427   if (!gst_buffer_pool_is_active (pool) &&
428       !gst_buffer_pool_set_active (pool, TRUE)) {
429     GST_ERROR_OBJECT (pool, "failed to activate buffer pool");
430     return NULL;
431   }
432
433   if (gst_buffer_pool_acquire_buffer (pool, &new_buffer, params) != GST_FLOW_OK) {
434     GST_ERROR_OBJECT (pool, "failed to acquire a buffer from pool");
435     return NULL;
436   }
437
438   if (gst_msdk_is_msdk_buffer (new_buffer))
439     new_surface = gst_msdk_get_surface_from_buffer (new_buffer);
440   else {
441     GST_ERROR_OBJECT (pool, "the acquired memory is not MSDK memory");
442     return NULL;
443   }
444
445   msdk_surface = g_slice_new0 (MsdkSurface);
446   msdk_surface->surface = new_surface;
447   msdk_surface->buf = new_buffer;
448
449   return msdk_surface;
450 }
451
452 static MsdkSurface *
453 get_msdk_surface_from_input_buffer (GstMsdkVPP * thiz, GstBuffer * inbuf)
454 {
455   GstVideoFrame src_frame, out_frame;
456   MsdkSurface *msdk_surface;
457
458   if (gst_msdk_is_msdk_buffer (inbuf)) {
459     msdk_surface = g_slice_new0 (MsdkSurface);
460     msdk_surface->surface = gst_msdk_get_surface_from_buffer (inbuf);
461     msdk_surface->buf = gst_buffer_ref (inbuf);
462     return msdk_surface;
463   }
464
465   /* If upstream hasn't accpeted the proposed msdk bufferpool,
466    * just copy frame to msdk buffer and take a surface from it.
467    */
468   if (!(msdk_surface =
469           get_surface_from_pool (thiz, thiz->sinkpad_buffer_pool, NULL)))
470     goto error;
471
472   if (!gst_video_frame_map (&src_frame, &thiz->sinkpad_info, inbuf,
473           GST_MAP_READ)) {
474     GST_ERROR_OBJECT (thiz, "failed to map the frame for source");
475     goto error;
476   }
477
478   if (!gst_video_frame_map (&out_frame, &thiz->sinkpad_buffer_pool_info,
479           msdk_surface->buf, GST_MAP_WRITE)) {
480     GST_ERROR_OBJECT (thiz, "failed to map the frame for destination");
481     gst_video_frame_unmap (&src_frame);
482     goto error;
483   }
484
485   if (!gst_video_frame_copy (&out_frame, &src_frame)) {
486     GST_ERROR_OBJECT (thiz, "failed to copy frame");
487     gst_video_frame_unmap (&out_frame);
488     gst_video_frame_unmap (&src_frame);
489     goto error;
490   }
491
492   gst_video_frame_unmap (&out_frame);
493   gst_video_frame_unmap (&src_frame);
494
495   return msdk_surface;
496
497 error:
498   return NULL;
499 }
500
501 static GstFlowReturn
502 gst_msdkvpp_transform (GstBaseTransform * trans, GstBuffer * inbuf,
503     GstBuffer * outbuf)
504 {
505   GstMsdkVPP *thiz = GST_MSDKVPP (trans);
506   mfxSession session;
507   mfxSyncPoint sync_point = NULL;
508   mfxStatus status;
509   MsdkSurface *in_surface = NULL;
510   MsdkSurface *out_surface = NULL;
511
512   in_surface = get_msdk_surface_from_input_buffer (thiz, inbuf);
513   if (!in_surface)
514     return GST_FLOW_ERROR;
515
516   if (gst_msdk_is_msdk_buffer (outbuf)) {
517     out_surface = g_slice_new0 (MsdkSurface);
518     out_surface->surface = gst_msdk_get_surface_from_buffer (outbuf);
519   } else {
520     GST_ERROR ("Failed to get msdk outsurface!");
521     return GST_FLOW_ERROR;
522   }
523
524   session = gst_msdk_context_get_session (thiz->context);
525   for (;;) {
526     status =
527         MFXVideoVPP_RunFrameVPPAsync (session, in_surface->surface,
528         out_surface->surface, NULL, &sync_point);
529     if (status != MFX_WRN_DEVICE_BUSY)
530       break;
531     /* If device is busy, wait 1ms and retry, as per MSDK's recomendation */
532     g_usleep (1000);
533   };
534
535   if (status != MFX_ERR_NONE && status != MFX_ERR_MORE_DATA
536       && status != MFX_ERR_MORE_SURFACE)
537     goto vpp_error;
538
539   /* No output generated */
540   if (status == MFX_ERR_MORE_DATA)
541     goto error_more_data;
542   if (sync_point)
543     MFXVideoCORE_SyncOperation (session, sync_point, 10000);
544
545   /* More than one output buffers are generated */
546   if (status == MFX_ERR_MORE_SURFACE)
547     status = MFX_ERR_NONE;
548
549   gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
550
551   free_msdk_surface (in_surface);
552   return GST_FLOW_OK;
553
554 vpp_error:
555   GST_ERROR_OBJECT (thiz, "MSDK Failed to do VPP");
556   free_msdk_surface (in_surface);
557   free_msdk_surface (out_surface);
558   return GST_FLOW_ERROR;
559
560 error_more_data:
561   GST_WARNING_OBJECT (thiz,
562       "MSDK Requries additional input for processing, "
563       "Retruning FLOW_DROPPED since no output buffer was generated");
564   free_msdk_surface (in_surface);
565   return GST_BASE_TRANSFORM_FLOW_DROPPED;
566 }
567
568 static void
569 gst_msdkvpp_close (GstMsdkVPP * thiz)
570 {
571   mfxStatus status;
572
573   if (!thiz->context)
574     return;
575
576   GST_DEBUG_OBJECT (thiz, "Closing VPP 0x%p", thiz->context);
577   status = MFXVideoVPP_Close (gst_msdk_context_get_session (thiz->context));
578   if (status != MFX_ERR_NONE && status != MFX_ERR_NOT_INITIALIZED) {
579     GST_WARNING_OBJECT (thiz, "Encoder close failed (%s)",
580         msdk_status_to_string (status));
581   }
582
583   if (thiz->context)
584     gst_object_replace ((GstObject **) & thiz->context, NULL);
585
586   memset (&thiz->param, 0, sizeof (thiz->param));
587
588   if (thiz->sinkpad_buffer_pool)
589     gst_object_unref (thiz->sinkpad_buffer_pool);
590   thiz->sinkpad_buffer_pool = NULL;
591   if (thiz->srcpad_buffer_pool)
592     gst_object_unref (thiz->srcpad_buffer_pool);
593   thiz->srcpad_buffer_pool = NULL;
594
595   thiz->field_duration = GST_CLOCK_TIME_NONE;
596   gst_video_info_init (&thiz->sinkpad_info);
597   gst_video_info_init (&thiz->srcpad_info);
598 }
599
600 static void
601 ensure_filters (GstMsdkVPP * thiz)
602 {
603   guint n_filters = 0;
604
605   /* Denoise */
606   if (thiz->flags & GST_MSDK_FLAG_DENOISE) {
607     mfxExtVPPDenoise *mfx_denoise = &thiz->mfx_denoise;
608     mfx_denoise->Header.BufferId = MFX_EXTBUFF_VPP_DENOISE;
609     mfx_denoise->Header.BufferSz = sizeof (mfxExtVPPDenoise);
610     mfx_denoise->DenoiseFactor = thiz->denoise_factor;
611     gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_denoise);
612     thiz->max_filter_algorithms[n_filters] = MFX_EXTBUFF_VPP_DENOISE;
613     n_filters++;
614   }
615
616   /* Rotation */
617   if (thiz->flags & GST_MSDK_FLAG_ROTATION) {
618     mfxExtVPPRotation *mfx_rotation = &thiz->mfx_rotation;
619     mfx_rotation->Header.BufferId = MFX_EXTBUFF_VPP_ROTATION;
620     mfx_rotation->Header.BufferSz = sizeof (mfxExtVPPRotation);
621     mfx_rotation->Angle = thiz->rotation;
622     gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_rotation);
623     thiz->max_filter_algorithms[n_filters] = MFX_EXTBUFF_VPP_ROTATION;
624     n_filters++;
625   }
626
627   /* Deinterlace */
628   if (thiz->flags & GST_MSDK_FLAG_DEINTERLACE) {
629     mfxExtVPPDeinterlacing *mfx_deinterlace = &thiz->mfx_deinterlace;
630     mfx_deinterlace->Header.BufferId = MFX_EXTBUFF_VPP_DEINTERLACING;
631     mfx_deinterlace->Header.BufferSz = sizeof (mfxExtVPPDeinterlacing);
632     mfx_deinterlace->Mode = thiz->deinterlace_method;
633     gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_deinterlace);
634     thiz->max_filter_algorithms[n_filters] = MFX_EXTBUFF_VPP_DEINTERLACING;
635     n_filters++;
636   }
637
638   /* Colorbalance(ProcAmp) */
639   if (thiz->flags & (GST_MSDK_FLAG_HUE | GST_MSDK_FLAG_SATURATION |
640           GST_MSDK_FLAG_BRIGHTNESS | GST_MSDK_FLAG_CONTRAST)) {
641     mfxExtVPPProcAmp *mfx_procamp = &thiz->mfx_procamp;
642     mfx_procamp->Header.BufferId = MFX_EXTBUFF_VPP_PROCAMP;
643     mfx_procamp->Header.BufferSz = sizeof (mfxExtVPPProcAmp);
644     mfx_procamp->Hue = thiz->hue;
645     mfx_procamp->Saturation = thiz->saturation;
646     mfx_procamp->Brightness = thiz->brightness;
647     mfx_procamp->Contrast = thiz->contrast;
648     gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_procamp);
649     thiz->max_filter_algorithms[n_filters] = MFX_EXTBUFF_VPP_PROCAMP;
650     n_filters++;
651   }
652
653   /* mfxExtVPPDoUse */
654   if (n_filters) {
655     mfxExtVPPDoUse *mfx_vpp_douse = &thiz->mfx_vpp_douse;
656     mfx_vpp_douse->Header.BufferId = MFX_EXTBUFF_VPP_DOUSE;
657     mfx_vpp_douse->Header.BufferSz = sizeof (mfxExtVPPDoUse);
658     mfx_vpp_douse->NumAlg = n_filters;
659     mfx_vpp_douse->AlgList = thiz->max_filter_algorithms;
660     gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_vpp_douse);
661   }
662 }
663
664 static void
665 gst_msdkvpp_set_passthrough (GstMsdkVPP * thiz)
666 {
667   gboolean passthrough = TRUE;
668
669   /* no passthrough if any of the filter algorithm is enabled */
670   if (thiz->flags)
671     passthrough = FALSE;
672
673   /* no passthrough if there is change in out width,height or format */
674   if (GST_VIDEO_INFO_WIDTH (&thiz->sinkpad_info) !=
675       GST_VIDEO_INFO_WIDTH (&thiz->srcpad_info)
676       || GST_VIDEO_INFO_HEIGHT (&thiz->sinkpad_info) !=
677       GST_VIDEO_INFO_HEIGHT (&thiz->srcpad_info)
678       || GST_VIDEO_INFO_FORMAT (&thiz->sinkpad_info) !=
679       GST_VIDEO_INFO_FORMAT (&thiz->srcpad_info))
680     passthrough = FALSE;
681
682   GST_OBJECT_UNLOCK (thiz);
683   gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (thiz), passthrough);
684   GST_OBJECT_LOCK (thiz);
685 }
686
687 static gboolean
688 gst_msdkvpp_initialize (GstMsdkVPP * thiz)
689 {
690   mfxSession session;
691   mfxStatus status;
692   mfxFrameAllocRequest request[2];
693
694   if (!thiz->context) {
695     GST_WARNING_OBJECT (thiz, "No MSDK Context");
696     return FALSE;
697   }
698
699   GST_OBJECT_LOCK (thiz);
700   session = gst_msdk_context_get_session (thiz->context);
701
702   if (thiz->use_video_memory) {
703     gst_msdk_set_frame_allocator (thiz->context);
704     thiz->param.IOPattern =
705         MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY;
706   } else {
707     thiz->param.IOPattern =
708         MFX_IOPATTERN_IN_SYSTEM_MEMORY | MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
709   }
710
711   /* update input video attributes */
712   gst_msdk_set_mfx_frame_info_from_video_info (&thiz->param.vpp.In,
713       &thiz->sinkpad_info);
714
715   /* update output video attributes, only CSC and Scaling are supported for now */
716   gst_msdk_set_mfx_frame_info_from_video_info (&thiz->param.vpp.Out,
717       &thiz->srcpad_info);
718   thiz->param.vpp.Out.FrameRateExtN =
719       GST_VIDEO_INFO_FPS_N (&thiz->sinkpad_info);
720   thiz->param.vpp.Out.FrameRateExtD =
721       GST_VIDEO_INFO_FPS_D (&thiz->sinkpad_info);
722
723   /* set vpp out picstruct as progressive if deinterlacing enabled */
724   if (thiz->flags & GST_MSDK_FLAG_DEINTERLACE)
725     thiz->param.vpp.Out.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
726
727   /* validate parameters and allow the Media SDK to make adjustments */
728   status = MFXVideoVPP_Query (session, &thiz->param, &thiz->param);
729   if (status < MFX_ERR_NONE) {
730     GST_ERROR_OBJECT (thiz, "Video VPP Query failed (%s)",
731         msdk_status_to_string (status));
732     goto no_vpp;
733   } else if (status > MFX_ERR_NONE) {
734     GST_WARNING_OBJECT (thiz, "Video VPP Query returned: %s",
735         msdk_status_to_string (status));
736   }
737
738   /* Enable the required filters */
739   ensure_filters (thiz);
740
741   /* set passthrough according to filter operation change */
742   gst_msdkvpp_set_passthrough (thiz);
743
744   /* Add exteneded buffers */
745   if (thiz->num_extra_params) {
746     thiz->param.NumExtParam = thiz->num_extra_params;
747     thiz->param.ExtParam = thiz->extra_params;
748   }
749
750   status = MFXVideoVPP_QueryIOSurf (session, &thiz->param, request);
751   if (status < MFX_ERR_NONE) {
752     GST_ERROR_OBJECT (thiz, "VPP Query IO surfaces failed (%s)",
753         msdk_status_to_string (status));
754     goto no_vpp;
755   } else if (status > MFX_ERR_NONE) {
756     GST_WARNING_OBJECT (thiz, "VPP Query IO surfaces returned: %s",
757         msdk_status_to_string (status));
758   }
759
760   if (thiz->use_video_memory) {
761     /* Input surface pool pre-allocation */
762     gst_msdk_frame_alloc (thiz->context, &(request[0]), &thiz->in_alloc_resp);
763     /* Output surface pool pre-allocation */
764     gst_msdk_frame_alloc (thiz->context, &(request[1]), &thiz->out_alloc_resp);
765   }
766
767   thiz->in_num_surfaces = request[0].NumFrameSuggested;
768   thiz->out_num_surfaces = request[1].NumFrameSuggested;
769
770
771   status = MFXVideoVPP_Init (session, &thiz->param);
772   if (status < MFX_ERR_NONE) {
773     GST_ERROR_OBJECT (thiz, "Init failed (%s)", msdk_status_to_string (status));
774     goto no_vpp;
775   } else if (status > MFX_ERR_NONE) {
776     GST_WARNING_OBJECT (thiz, "Init returned: %s",
777         msdk_status_to_string (status));
778   }
779
780   GST_OBJECT_UNLOCK (thiz);
781   return TRUE;
782
783 no_vpp:
784   GST_OBJECT_UNLOCK (thiz);
785   if (thiz->context)
786     gst_object_replace ((GstObject **) & thiz->context, NULL);
787   return FALSE;
788 }
789
790 static gboolean
791 gst_msdkvpp_set_caps (GstBaseTransform * trans, GstCaps * caps,
792     GstCaps * out_caps)
793 {
794   GstMsdkVPP *thiz = GST_MSDKVPP (trans);
795   GstVideoInfo in_info, out_info;
796   gboolean sinkpad_info_changed = FALSE;
797   gboolean srcpad_info_changed = FALSE;
798   gboolean deinterlace;
799
800   gst_video_info_from_caps (&in_info, caps);
801   gst_video_info_from_caps (&out_info, out_caps);
802
803   if (!gst_video_info_is_equal (&in_info, &thiz->sinkpad_info))
804     sinkpad_info_changed = TRUE;
805   if (!gst_video_info_is_equal (&out_info, &thiz->srcpad_info))
806     srcpad_info_changed = TRUE;
807
808   thiz->sinkpad_info = in_info;
809   thiz->srcpad_info = out_info;
810 #ifndef _WIN32
811   thiz->use_video_memory = TRUE;
812 #else
813   thiz->use_video_memory = FALSE;
814 #endif
815
816   if (!sinkpad_info_changed && !srcpad_info_changed)
817     return TRUE;
818
819   /* check for deinterlace requirement */
820   deinterlace = gst_msdkvpp_is_deinterlace_enabled (thiz, &in_info);
821   if (deinterlace)
822     thiz->flags |= GST_MSDK_FLAG_DEINTERLACE;
823   thiz->field_duration = GST_VIDEO_INFO_FPS_N (&in_info) > 0 ?
824       gst_util_uint64_scale (GST_SECOND, GST_VIDEO_INFO_FPS_D (&in_info),
825       (1 + deinterlace) * GST_VIDEO_INFO_FPS_N (&in_info)) : 0;
826
827   if (!gst_msdkvpp_initialize (thiz))
828     return FALSE;
829
830   /* Ensure sinkpad buffer pool */
831   thiz->sinkpad_buffer_pool =
832       gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SINK, caps,
833       thiz->in_num_surfaces);
834   if (!thiz->sinkpad_buffer_pool) {
835     GST_ERROR_OBJECT (thiz, "Failed to ensure the sinkpad buffer pool");
836     return FALSE;
837   }
838   /* Ensure a srcpad buffer pool */
839   thiz->srcpad_buffer_pool =
840       gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SRC, out_caps,
841       thiz->out_num_surfaces);
842   if (!thiz->srcpad_buffer_pool) {
843     GST_ERROR_OBJECT (thiz, "Failed to ensure the srcpad buffer pool");
844     return FALSE;
845   }
846
847   return TRUE;
848 }
849
850 static GstCaps *
851 gst_msdkvpp_fixate_caps (GstBaseTransform * trans,
852     GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
853 {
854   GstMsdkVPP *thiz = GST_MSDKVPP (trans);
855   GstCaps *result = NULL;
856
857   if (direction == GST_PAD_SRC)
858     result = gst_caps_fixate (result);
859   else {
860     result = gst_msdkvpp_fixate_srccaps (thiz, caps, othercaps);
861   }
862
863   GST_DEBUG_OBJECT (trans, "fixated to %" GST_PTR_FORMAT, result);
864   gst_caps_unref (othercaps);
865   return result;
866 }
867
868 /* Generic code for now, requires changes in future when we
869  * add hardware query for supported formats, Framerate control etc */
870 static GstCaps *
871 gst_msdkvpp_transform_caps (GstBaseTransform * trans,
872     GstPadDirection direction, GstCaps * caps, GstCaps * filter)
873 {
874   GstCaps *out_caps;
875
876   GST_DEBUG_OBJECT (trans,
877       "Transforming caps %" GST_PTR_FORMAT " in direction %s", caps,
878       (direction == GST_PAD_SINK) ? "sink" : "src");
879
880   if (direction == GST_PAD_SRC)
881     out_caps = gst_static_pad_template_get_caps (&gst_msdkvpp_sink_factory);
882   else
883     out_caps = gst_static_pad_template_get_caps (&gst_msdkvpp_src_factory);
884
885   if (out_caps && filter) {
886     GstCaps *intersection;
887
888     intersection = gst_caps_intersect_full (out_caps, filter,
889         GST_CAPS_INTERSECT_FIRST);
890     gst_caps_unref (out_caps);
891     out_caps = intersection;
892   }
893
894   GST_DEBUG_OBJECT (trans, "returning caps: %" GST_PTR_FORMAT, out_caps);
895   return out_caps;
896 }
897
898 static gboolean
899 gst_msdkvpp_start (GstBaseTransform * trans)
900 {
901   if (!ensure_context (trans))
902     return FALSE;
903   return TRUE;
904 }
905
906 static gboolean
907 gst_msdkvpp_stop (GstBaseTransform * trans)
908 {
909   gst_msdkvpp_close (GST_MSDKVPP (trans));
910   return TRUE;
911 }
912
913 static void
914 gst_msdkvpp_set_property (GObject * object, guint prop_id,
915     const GValue * value, GParamSpec * pspec)
916 {
917   GstMsdkVPP *thiz = GST_MSDKVPP (object);
918
919   switch (prop_id) {
920     case PROP_HARDWARE:
921       thiz->hardware = g_value_get_boolean (value);
922       break;
923     case PROP_ASYNC_DEPTH:
924       thiz->async_depth = g_value_get_uint (value);
925       break;
926     case PROP_DENOISE:
927       thiz->denoise_factor = g_value_get_uint (value);
928       thiz->flags |= GST_MSDK_FLAG_DENOISE;
929       break;
930     case PROP_ROTATION:
931       thiz->rotation = g_value_get_enum (value);
932       thiz->flags |= GST_MSDK_FLAG_ROTATION;
933       break;
934     case PROP_DEINTERLACE_MODE:
935       thiz->deinterlace_mode = g_value_get_enum (value);
936       break;
937     case PROP_DEINTERLACE_METHOD:
938       thiz->deinterlace_method = g_value_get_enum (value);
939       break;
940     case PROP_HUE:
941       thiz->hue = g_value_get_float (value);
942       thiz->flags |= GST_MSDK_FLAG_HUE;
943       break;
944     case PROP_SATURATION:
945       thiz->saturation = g_value_get_float (value);
946       thiz->flags |= GST_MSDK_FLAG_SATURATION;
947       break;
948     case PROP_BRIGHTNESS:
949       thiz->brightness = g_value_get_float (value);
950       thiz->flags |= GST_MSDK_FLAG_BRIGHTNESS;
951       break;
952     case PROP_CONTRAST:
953       thiz->contrast = g_value_get_float (value);
954       thiz->flags |= GST_MSDK_FLAG_CONTRAST;
955       break;
956     default:
957       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
958       break;
959   }
960 }
961
962 static void
963 gst_msdkvpp_get_property (GObject * object, guint prop_id,
964     GValue * value, GParamSpec * pspec)
965 {
966   GstMsdkVPP *thiz = GST_MSDKVPP (object);
967
968   switch (prop_id) {
969     case PROP_HARDWARE:
970       g_value_set_boolean (value, thiz->hardware);
971       break;
972     case PROP_ASYNC_DEPTH:
973       g_value_set_uint (value, thiz->async_depth);
974       break;
975     case PROP_DENOISE:
976       g_value_set_uint (value, thiz->denoise_factor);
977       break;
978     case PROP_ROTATION:
979       g_value_set_enum (value, thiz->rotation);
980       break;
981     case PROP_DEINTERLACE_MODE:
982       g_value_set_enum (value, thiz->deinterlace_mode);
983       break;
984     case PROP_DEINTERLACE_METHOD:
985       g_value_set_enum (value, thiz->deinterlace_method);
986       break;
987     case PROP_HUE:
988       g_value_set_float (value, thiz->hue);
989       break;
990     case PROP_SATURATION:
991       g_value_set_float (value, thiz->saturation);
992       break;
993     case PROP_BRIGHTNESS:
994       g_value_set_float (value, thiz->brightness);
995       break;
996     case PROP_CONTRAST:
997       g_value_set_float (value, thiz->contrast);
998       break;
999     default:
1000       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1001       break;
1002   }
1003 }
1004
1005 static void
1006 gst_msdkvpp_finalize (GObject * object)
1007 {
1008   G_OBJECT_CLASS (parent_class)->finalize (object);
1009 }
1010
1011 static void
1012 gst_msdkvpp_set_context (GstElement * element, GstContext * context)
1013 {
1014   GstMsdkContext *msdk_context = NULL;
1015   GstMsdkVPP *thiz = GST_MSDKVPP (element);
1016
1017   if (gst_msdk_context_get_context (context, &msdk_context)) {
1018     gst_object_replace ((GstObject **) & thiz->context,
1019         (GstObject *) msdk_context);
1020     gst_object_unref (msdk_context);
1021   }
1022
1023   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
1024 }
1025
1026 static void
1027 gst_msdkvpp_class_init (GstMsdkVPPClass * klass)
1028 {
1029   GObjectClass *gobject_class;
1030   GstElementClass *element_class;
1031   GstBaseTransformClass *trans_class;
1032   GParamSpec *obj_properties[PROP_N] = { NULL, };
1033
1034   gobject_class = G_OBJECT_CLASS (klass);
1035   element_class = GST_ELEMENT_CLASS (klass);
1036   trans_class = GST_BASE_TRANSFORM_CLASS (klass);
1037
1038   gobject_class->set_property = gst_msdkvpp_set_property;
1039   gobject_class->get_property = gst_msdkvpp_get_property;
1040   gobject_class->finalize = gst_msdkvpp_finalize;
1041
1042   element_class->set_context = gst_msdkvpp_set_context;
1043
1044   gst_element_class_add_static_pad_template (element_class,
1045       &gst_msdkvpp_src_factory);
1046   gst_element_class_add_static_pad_template (element_class,
1047       &gst_msdkvpp_sink_factory);
1048
1049   gst_element_class_set_static_metadata (element_class,
1050       "MSDK Video Postprocessor",
1051       "Filter/Converter/Video;Filter/Converter/Video/Scaler;"
1052       "Filter/Effect/Video;Filter/Effect/Video/Deinterlace",
1053       "A MediaSDK Video Postprocessing Filter",
1054       "Sreerenj Balachandrn <sreerenj.balachandran@intel.com>");
1055
1056   trans_class->start = GST_DEBUG_FUNCPTR (gst_msdkvpp_start);
1057   trans_class->stop = GST_DEBUG_FUNCPTR (gst_msdkvpp_stop);
1058   trans_class->transform_caps = GST_DEBUG_FUNCPTR (gst_msdkvpp_transform_caps);
1059   trans_class->fixate_caps = GST_DEBUG_FUNCPTR (gst_msdkvpp_fixate_caps);
1060   trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_msdkvpp_set_caps);
1061   trans_class->transform = GST_DEBUG_FUNCPTR (gst_msdkvpp_transform);
1062   trans_class->propose_allocation =
1063       GST_DEBUG_FUNCPTR (gst_msdkvpp_propose_allocation);
1064   trans_class->decide_allocation =
1065       GST_DEBUG_FUNCPTR (gst_msdkvpp_decide_allocation);
1066   trans_class->prepare_output_buffer =
1067       GST_DEBUG_FUNCPTR (gst_msdkvpp_prepare_output_buffer);
1068
1069   obj_properties[PROP_HARDWARE] =
1070       g_param_spec_boolean ("hardware", "Hardware", "Enable hardware VPP",
1071       PROP_HARDWARE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1072
1073   obj_properties[PROP_ASYNC_DEPTH] =
1074       g_param_spec_uint ("async-depth", "Async Depth",
1075       "Depth of asynchronous pipeline",
1076       1, 1, PROP_ASYNC_DEPTH_DEFAULT,
1077       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1078
1079   obj_properties[PROP_DENOISE] =
1080       g_param_spec_uint ("denoise", "Denoising factor",
1081       "Denoising Factor",
1082       0, 100, PROP_DENOISE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1083
1084   obj_properties[PROP_ROTATION] =
1085       g_param_spec_enum ("rotation", "Rotation",
1086       "Rotation Angle", gst_msdkvpp_rotation_get_type (),
1087       PROP_ROTATION_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1088
1089   obj_properties[PROP_DEINTERLACE_MODE] =
1090       g_param_spec_enum ("deinterlace-mode", "Deinterlace Mode",
1091       "Deinterlace mode to use", gst_msdkvpp_deinterlace_mode_get_type (),
1092       PROP_DEINTERLACE_MODE_DEFAULT,
1093       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1094
1095   obj_properties[PROP_DEINTERLACE_METHOD] =
1096       g_param_spec_enum ("deinterlace-method", "Deinterlace Method",
1097       "Deinterlace method to use", gst_msdkvpp_deinterlace_method_get_type (),
1098       PROP_DEINTERLACE_METHOD_DEFAULT,
1099       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1100
1101   obj_properties[PROP_HUE] =
1102       g_param_spec_float ("hue", "Hue",
1103       "The hue of the video",
1104       -180, 180, PROP_HUE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1105
1106   obj_properties[PROP_SATURATION] =
1107       g_param_spec_float ("saturation", "Saturation",
1108       "The Saturation of the video",
1109       0, 10, PROP_SATURATION_DEFAULT,
1110       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1111
1112   obj_properties[PROP_BRIGHTNESS] =
1113       g_param_spec_float ("brightness", "Brightness",
1114       "The Brightness of the video",
1115       -100, 100, PROP_BRIGHTNESS_DEFAULT,
1116       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1117
1118   obj_properties[PROP_CONTRAST] =
1119       g_param_spec_float ("contrast", "Contrast",
1120       "The Contrast of the video",
1121       0, 10, PROP_CONTRAST_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1122
1123   g_object_class_install_properties (gobject_class, PROP_N, obj_properties);
1124 }
1125
1126 static void
1127 gst_msdkvpp_init (GstMsdkVPP * thiz)
1128 {
1129   thiz->hardware = PROP_HARDWARE_DEFAULT;
1130   thiz->async_depth = PROP_ASYNC_DEPTH_DEFAULT;
1131   thiz->denoise_factor = PROP_DENOISE_DEFAULT;
1132   thiz->rotation = PROP_ROTATION_DEFAULT;
1133   thiz->deinterlace_mode = PROP_DEINTERLACE_MODE_DEFAULT;
1134   thiz->deinterlace_method = PROP_DEINTERLACE_METHOD_DEFAULT;
1135   thiz->field_duration = GST_CLOCK_TIME_NONE;
1136   thiz->hue = PROP_HUE_DEFAULT;
1137   thiz->saturation = PROP_SATURATION_DEFAULT;
1138   thiz->brightness = PROP_BRIGHTNESS_DEFAULT;
1139   thiz->contrast = PROP_CONTRAST_DEFAULT;
1140   gst_video_info_init (&thiz->sinkpad_info);
1141   gst_video_info_init (&thiz->srcpad_info);
1142 }