1 /*
2  * gstxcamfilter.cpp -gst xcamfilter plugin
3  *
4  *  Copyright (c) 2016 Intel Corporation
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Author: Yinhang Liu <yinhangx.liu@intel.com>
19  */
20 
21 #include "gstxcamfilter.h"
22 #include "gstxcambuffermeta.h"
23 
24 #include <gst/gstmeta.h>
25 #include <gst/allocators/gstdmabuf.h>
26 
27 using namespace XCam;
28 using namespace GstXCam;
29 
30 #define DEFAULT_SMART_ANALYSIS_LIB_DIR      "/usr/lib/xcam/plugins/smart"
31 #define DEFAULT_DELAY_BUFFER_NUM            2
32 
33 #define DEFAULT_PROP_BUFFERCOUNT            8
34 #define DEFAULT_PROP_COPY_MODE              COPY_MODE_CPU
35 #define DEFAULT_PROP_DEFOG_MODE             DEFOG_NONE
36 #define DEFAULT_PROP_WAVELET_MODE           NONE_WAVELET
37 #define DEFAULT_PROP_3D_DENOISE_MODE        DENOISE_3D_NONE
38 #define DEFAULT_PROP_ENABLE_WIREFRAME       FALSE
39 #define DEFAULT_PROP_ENABLE_IMAGE_WARP      FALSE
40 #define DEFAULT_PROP_ENABLE_IMAGE_STITCH    FALSE
41 #define DEFAULT_PROP_STITCH_ENABLE_SEAM     FALSE
42 #define DEFAULT_PROP_STITCH_SCALE_MODE      CLBlenderScaleLocal
43 #define DEFAULT_PROP_STITCH_FISHEYE_MAP     FALSE
44 #define DEFAULT_PROP_STITCH_LSC             FALSE
45 #define DEFAULT_PROP_STITCH_FM_OCL          FALSE
46 #define DEFAULT_PROP_STITCH_RES_MODE        StitchRes1080P
47 
48 XCAM_BEGIN_DECLARE
49 
50 enum {
51     PROP_0,
52     PROP_BUFFERCOUNT,
53     PROP_COPY_MODE,
54     PROP_DEFOG_MODE,
55     PROP_WAVELET_MODE,
56     PROP_DENOISE_3D_MODE,
57     PROP_ENABLE_WIREFRAME,
58     PROP_ENABLE_IMAGE_WARP,
59     PROP_ENABLE_IMAGE_STITCH,
60     PROP_STITCH_ENABLE_SEAM,
61     PROP_STITCH_SCALE_MODE,
62     PROP_STITCH_FISHEYE_MAP,
63     PROP_STITCH_LSC,
64     PROP_STITCH_FM_OCL,
65     PROP_STITCH_RES_MODE
66 };
67 
68 #define GST_TYPE_XCAM_FILTER_COPY_MODE (gst_xcam_filter_copy_mode_get_type ())
69 static GType
gst_xcam_filter_copy_mode_get_type(void)70 gst_xcam_filter_copy_mode_get_type (void)
71 {
72     static GType g_type = 0;
73     static const GEnumValue copy_mode_types[] = {
74         {COPY_MODE_CPU, "Copy buffer with CPU", "cpu"},
75         {COPY_MODE_DMA, "Copy buffer with DMA", "dma"},
76         {0, NULL, NULL}
77     };
78 
79     if (g_once_init_enter (&g_type)) {
80         const GType type =
81             g_enum_register_static ("GstXCamFilterCopyModeType", copy_mode_types);
82         g_once_init_leave (&g_type, type);
83     }
84 
85     return g_type;
86 }
87 
88 #define GST_TYPE_XCAM_FILTER_DEFOG_MODE (gst_xcam_filter_defog_mode_get_type ())
89 static GType
gst_xcam_filter_defog_mode_get_type(void)90 gst_xcam_filter_defog_mode_get_type (void)
91 {
92     static GType g_type = 0;
93     static const GEnumValue defog_mode_types [] = {
94         {DEFOG_NONE, "Defog disabled", "none"},
95         {DEFOG_RETINEX, "Defog retinex", "retinex"},
96         {DEFOG_DCP, "Defog dark channel prior", "dcp"},
97         {0, NULL, NULL}
98     };
99 
100     if (g_once_init_enter (&g_type)) {
101         const GType type =
102             g_enum_register_static ("GstXCamFilterDefogModeType", defog_mode_types);
103         g_once_init_leave (&g_type, type);
104     }
105 
106     return g_type;
107 }
108 
109 #define GST_TYPE_XCAM_FILTER_WAVELET_MODE (gst_xcam_filter_wavelet_mode_get_type ())
110 static GType
gst_xcam_filter_wavelet_mode_get_type(void)111 gst_xcam_filter_wavelet_mode_get_type (void)
112 {
113     static GType g_type = 0;
114     static const GEnumValue wavelet_mode_types[] = {
115         {NONE_WAVELET, "Wavelet disabled", "none"},
116         {HAT_WAVELET_Y, "Hat wavelet Y", "hat Y"},
117         {HAT_WAVELET_UV, "Hat wavelet UV", "hat UV"},
118         {HARR_WAVELET_Y, "Haar wavelet Y", "haar Y"},
119         {HARR_WAVELET_UV, "Haar wavelet UV", "haar UV"},
120         {HARR_WAVELET_YUV, "Haar wavelet YUV", "haar YUV"},
121         {HARR_WAVELET_BAYES, "Haar wavelet bayes shrink", "haar Bayes"},
122         {0, NULL, NULL},
123     };
124 
125     if (g_once_init_enter (&g_type)) {
126         const GType type =
127             g_enum_register_static ("GstXCamFilterWaveletModeType", wavelet_mode_types);
128         g_once_init_leave (&g_type, type);
129     }
130 
131     return g_type;
132 }
133 
134 #define GST_TYPE_XCAM_FILTER_3D_DENOISE_MODE (gst_xcam_filter_3d_denoise_mode_get_type ())
135 static GType
gst_xcam_filter_3d_denoise_mode_get_type(void)136 gst_xcam_filter_3d_denoise_mode_get_type (void)
137 {
138     static GType g_type = 0;
139     static const GEnumValue denoise_3d_mode_types [] = {
140         {DENOISE_3D_NONE, "3D Denoise disabled", "none"},
141         {DENOISE_3D_YUV, "3D Denoise yuv", "yuv"},
142         {DENOISE_3D_UV, "3D Denoise uv", "uv"},
143         {0, NULL, NULL}
144     };
145 
146     if (g_once_init_enter (&g_type)) {
147         const GType type =
148             g_enum_register_static ("GstXCamFilter3DDenoiseModeType", denoise_3d_mode_types);
149         g_once_init_leave (&g_type, type);
150     }
151 
152     return g_type;
153 }
154 
155 #define GST_TYPE_XCAM_FILTER_STITCH_SCALE_MODE (gst_xcam_filter_stitch_scale_mode_get_type ())
156 static GType
gst_xcam_filter_stitch_scale_mode_get_type(void)157 gst_xcam_filter_stitch_scale_mode_get_type (void)
158 {
159     static GType g_type = 0;
160     static const GEnumValue stitch_scale_mode_types [] = {
161         {CLBlenderScaleLocal, "Image stitch local scale", "local"},
162         {CLBlenderScaleGlobal, "Image stitch glocal scale", "global"},
163         {0, NULL, NULL}
164     };
165 
166     if (g_once_init_enter (&g_type)) {
167         const GType type =
168             g_enum_register_static ("GstXCamFilterStitchScaleModeType", stitch_scale_mode_types);
169         g_once_init_leave (&g_type, type);
170     }
171 
172     return g_type;
173 }
174 
175 #define GST_TYPE_XCAM_FILTER_STITCH_RES_MODE (gst_xcam_filter_stitch_res_mode_get_type ())
176 static GType
gst_xcam_filter_stitch_res_mode_get_type(void)177 gst_xcam_filter_stitch_res_mode_get_type (void)
178 {
179     static GType g_type = 0;
180     static const GEnumValue stitch_res_mode_types [] = {
181         {StitchRes1080P, "Image stitch 1080P mode", "1080p"},
182         {StitchRes4K, "Image stitch 4K mode", "4k"},
183         {0, NULL, NULL}
184     };
185 
186     if (g_once_init_enter (&g_type)) {
187         const GType type =
188             g_enum_register_static ("GstXCamFilterStitchResModeType", stitch_res_mode_types);
189         g_once_init_leave (&g_type, type);
190     }
191 
192     return g_type;
193 }
194 
195 static GstStaticPadTemplate gst_xcam_sink_factory =
196     GST_STATIC_PAD_TEMPLATE ("sink",
197                              GST_PAD_SINK,
198                              GST_PAD_ALWAYS,
199                              GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ NV12 }")));
200 
201 static GstStaticPadTemplate gst_xcam_src_factory =
202     GST_STATIC_PAD_TEMPLATE ("src",
203                              GST_PAD_SRC,
204                              GST_PAD_ALWAYS,
205                              GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ NV12 }")));
206 
207 GST_DEBUG_CATEGORY (gst_xcam_filter_debug);
208 #define GST_CAT_DEFAULT gst_xcam_filter_debug
209 
210 #define gst_xcam_filter_parent_class parent_class
211 G_DEFINE_TYPE (GstXCamFilter, gst_xcam_filter, GST_TYPE_BASE_TRANSFORM);
212 
213 static void gst_xcam_filter_finalize (GObject * object);
214 static void gst_xcam_filter_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
215 static void gst_xcam_filter_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
216 static gboolean gst_xcam_filter_start (GstBaseTransform *trans);
217 static GstCaps *gst_xcam_filter_transform_caps (
218     GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, GstCaps *filter);
219 static gboolean gst_xcam_filter_set_caps (GstBaseTransform *trans, GstCaps *incaps, GstCaps *outcaps);
220 static gboolean gst_xcam_filter_stop (GstBaseTransform *trans);
221 static void gst_xcam_filter_before_transform (GstBaseTransform *trans, GstBuffer *buffer);
222 static GstFlowReturn gst_xcam_filter_prepare_output_buffer (GstBaseTransform * trans, GstBuffer *input, GstBuffer **outbuf);
223 static GstFlowReturn gst_xcam_filter_transform (GstBaseTransform *trans, GstBuffer *inbuf, GstBuffer *outbuf);
224 
225 XCAM_END_DECLARE
226 
227 static void
gst_xcam_filter_class_init(GstXCamFilterClass * class_self)228 gst_xcam_filter_class_init (GstXCamFilterClass *class_self)
229 {
230     GObjectClass *gobject_class;
231     GstElementClass *element_class;
232     GstBaseTransformClass *basetrans_class;
233 
234     gobject_class = (GObjectClass *) class_self;
235     element_class = (GstElementClass *) class_self;
236     basetrans_class = (GstBaseTransformClass *) class_self;
237 
238     GST_DEBUG_CATEGORY_INIT (gst_xcam_filter_debug, "xcamfilter", 0, "LibXCam filter plugin");
239 
240     gobject_class->finalize = gst_xcam_filter_finalize;
241     gobject_class->set_property = gst_xcam_filter_set_property;
242     gobject_class->get_property = gst_xcam_filter_get_property;
243 
244     g_object_class_install_property (
245         gobject_class, PROP_BUFFERCOUNT,
246         g_param_spec_int ("buffercount", "buffer count", "Buffer count",
247                           0, G_MAXINT, DEFAULT_PROP_BUFFERCOUNT,
248                           (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
249 
250     g_object_class_install_property (
251         gobject_class, PROP_COPY_MODE,
252         g_param_spec_enum ("copy-mode", "copy mode", "Copy Mode",
253                            GST_TYPE_XCAM_FILTER_COPY_MODE, DEFAULT_PROP_COPY_MODE,
254                            (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
255 
256     g_object_class_install_property (
257         gobject_class, PROP_DEFOG_MODE,
258         g_param_spec_enum ("defog-mode", "defog mode", "Defog mode",
259                            GST_TYPE_XCAM_FILTER_DEFOG_MODE, DEFAULT_PROP_DEFOG_MODE,
260                            (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
261 
262     g_object_class_install_property (
263         gobject_class, PROP_WAVELET_MODE,
264         g_param_spec_enum ("wavelet-mode", "wavelet mode", "Wavelet Mode",
265                            GST_TYPE_XCAM_FILTER_WAVELET_MODE, DEFAULT_PROP_WAVELET_MODE,
266                            (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
267 
268     g_object_class_install_property (
269         gobject_class, PROP_DENOISE_3D_MODE,
270         g_param_spec_enum ("denoise-3d", "3D Denoise mode", "3D Denoise mode",
271                            GST_TYPE_XCAM_FILTER_3D_DENOISE_MODE, DEFAULT_PROP_3D_DENOISE_MODE,
272                            (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
273 
274     g_object_class_install_property (
275         gobject_class, PROP_ENABLE_WIREFRAME,
276         g_param_spec_boolean ("enable-wireframe", "enable wire frame", "Enable wire frame",
277                               DEFAULT_PROP_ENABLE_WIREFRAME, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
278 
279     g_object_class_install_property (
280         gobject_class, PROP_ENABLE_IMAGE_WARP,
281         g_param_spec_boolean ("enable-warp", "enable image warp", "Enable Image Warp",
282                               DEFAULT_PROP_ENABLE_IMAGE_WARP, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
283 
284     g_object_class_install_property (
285         gobject_class, PROP_ENABLE_IMAGE_STITCH,
286         g_param_spec_boolean ("enable-stitch", "enable image stitch", "Enable Image Stitch",
287                               DEFAULT_PROP_ENABLE_IMAGE_STITCH, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
288 
289     g_object_class_install_property (
290         gobject_class, PROP_STITCH_ENABLE_SEAM,
291         g_param_spec_boolean ("stitch-seam", "enable seam just for stitch", "Enable Seam Just For Stitch",
292                               DEFAULT_PROP_STITCH_ENABLE_SEAM, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
293 
294     g_object_class_install_property (
295         gobject_class, PROP_STITCH_SCALE_MODE,
296         g_param_spec_enum ("stitch-scale", "stitch scale mode", "Stitch Scale Mode",
297                            GST_TYPE_XCAM_FILTER_STITCH_SCALE_MODE, DEFAULT_PROP_STITCH_SCALE_MODE,
298                            (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
299 
300     g_object_class_install_property (
301         gobject_class, PROP_STITCH_FISHEYE_MAP,
302         g_param_spec_boolean ("stitch-fisheye-map", "stitch fisheye map", "Enable fisheye map for stitch",
303                               DEFAULT_PROP_STITCH_FISHEYE_MAP, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
304 
305     g_object_class_install_property (
306         gobject_class, PROP_STITCH_LSC,
307         g_param_spec_boolean ("stitch-lsc", "stitch enable lens shading correction", "Enable Lens Shading Correction",
308                               DEFAULT_PROP_STITCH_LSC, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
309 
310 #if HAVE_OPENCV
311     g_object_class_install_property (
312         gobject_class, PROP_STITCH_FM_OCL,
313         g_param_spec_boolean ("stitch-fm-ocl", "stitch enable ocl for feature match", "Enable ocl for feature match",
314                               DEFAULT_PROP_STITCH_FM_OCL, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
315 #endif
316 
317     g_object_class_install_property (
318         gobject_class, PROP_STITCH_RES_MODE,
319         g_param_spec_enum ("stitch-res-mode", "stitch resolution mode", "Stitch Resolution Mode",
320                            GST_TYPE_XCAM_FILTER_STITCH_RES_MODE, DEFAULT_PROP_STITCH_RES_MODE,
321                            (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
322 
323     gst_element_class_set_details_simple (element_class,
324                                           "Libxcam Filter",
325                                           "Filter/Effect/Video",
326                                           "Process NV12 stream using xcam library",
327                                           "Wind Yuan <feng.yuan@intel.com> & Yinhang Liu <yinhangx.liu@intel.com>");
328 
329     gst_element_class_add_pad_template (element_class,
330                                         gst_static_pad_template_get (&gst_xcam_src_factory));
331     gst_element_class_add_pad_template (element_class,
332                                         gst_static_pad_template_get (&gst_xcam_sink_factory));
333 
334     basetrans_class->start = GST_DEBUG_FUNCPTR (gst_xcam_filter_start);
335     basetrans_class->stop = GST_DEBUG_FUNCPTR (gst_xcam_filter_stop);
336     basetrans_class->transform_caps = GST_DEBUG_FUNCPTR (gst_xcam_filter_transform_caps);
337     basetrans_class->set_caps = GST_DEBUG_FUNCPTR (gst_xcam_filter_set_caps);
338     basetrans_class->before_transform = GST_DEBUG_FUNCPTR (gst_xcam_filter_before_transform);
339     basetrans_class->prepare_output_buffer = GST_DEBUG_FUNCPTR (gst_xcam_filter_prepare_output_buffer);
340     basetrans_class->transform = GST_DEBUG_FUNCPTR (gst_xcam_filter_transform);
341 }
342 
343 static void
gst_xcam_filter_init(GstXCamFilter * xcamfilter)344 gst_xcam_filter_init (GstXCamFilter *xcamfilter)
345 {
346     xcamfilter->buf_count = DEFAULT_PROP_BUFFERCOUNT;
347     xcamfilter->copy_mode = DEFAULT_PROP_COPY_MODE;
348     xcamfilter->defog_mode = DEFAULT_PROP_DEFOG_MODE;
349     xcamfilter->wavelet_mode = DEFAULT_PROP_WAVELET_MODE;
350     xcamfilter->denoise_3d_mode = DEFAULT_PROP_3D_DENOISE_MODE;
351     xcamfilter->denoise_3d_ref_count = 2;
352     xcamfilter->enable_wireframe = DEFAULT_PROP_ENABLE_WIREFRAME;
353     xcamfilter->enable_image_warp = DEFAULT_PROP_ENABLE_IMAGE_WARP;
354     xcamfilter->enable_stitch = DEFAULT_PROP_ENABLE_IMAGE_STITCH;
355     xcamfilter->stitch_enable_seam = DEFAULT_PROP_STITCH_ENABLE_SEAM;
356     xcamfilter->stitch_fisheye_map = DEFAULT_PROP_STITCH_FISHEYE_MAP;
357     xcamfilter->stitch_lsc = DEFAULT_PROP_STITCH_LSC;
358     xcamfilter->stitch_fm_ocl = DEFAULT_PROP_STITCH_FM_OCL;
359     xcamfilter->stitch_scale_mode = DEFAULT_PROP_STITCH_SCALE_MODE;
360     xcamfilter->stitch_res_mode = DEFAULT_PROP_STITCH_RES_MODE;
361 
362     xcamfilter->delay_buf_num = DEFAULT_DELAY_BUFFER_NUM;
363     xcamfilter->cached_buf_num = 0;
364 
365     XCAM_CONSTRUCTOR (xcamfilter->pipe_manager, SmartPtr<MainPipeManager>);
366     xcamfilter->pipe_manager = new MainPipeManager;
367     XCAM_ASSERT (xcamfilter->pipe_manager.ptr ());
368 }
369 
370 static void
gst_xcam_filter_finalize(GObject * object)371 gst_xcam_filter_finalize (GObject *object)
372 {
373     GstXCamFilter *xcamfilter = GST_XCAM_FILTER (object);
374 
375     if (xcamfilter->allocator)
376         gst_object_unref (xcamfilter->allocator);
377 
378     xcamfilter->pipe_manager.release ();
379     XCAM_DESTRUCTOR (xcamfilter->pipe_manager, SmartPtr<MainPipeManager>);
380 
381     G_OBJECT_CLASS (parent_class)->finalize (object);
382 }
383 
384 static void
gst_xcam_filter_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)385 gst_xcam_filter_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
386 {
387     GstXCamFilter *xcamfilter = GST_XCAM_FILTER (object);
388 
389     switch (prop_id) {
390     case PROP_BUFFERCOUNT:
391         xcamfilter->buf_count = g_value_get_int (value);
392         break;
393     case PROP_COPY_MODE:
394         xcamfilter->copy_mode = (CopyMode) g_value_get_enum (value);
395         break;
396     case PROP_DEFOG_MODE:
397         xcamfilter->defog_mode = (DefogModeType) g_value_get_enum (value);
398         break;
399     case PROP_WAVELET_MODE:
400         xcamfilter->wavelet_mode = (WaveletModeType) g_value_get_enum (value);
401         break;
402     case PROP_DENOISE_3D_MODE:
403         xcamfilter->denoise_3d_mode = (Denoise3DModeType) g_value_get_enum (value);
404         break;
405     case PROP_ENABLE_WIREFRAME:
406         xcamfilter->enable_wireframe = g_value_get_boolean (value);
407         break;
408     case PROP_ENABLE_IMAGE_WARP:
409         xcamfilter->enable_image_warp = g_value_get_boolean (value);
410         break;
411     case PROP_ENABLE_IMAGE_STITCH:
412         xcamfilter->enable_stitch = g_value_get_boolean (value);
413         break;
414     case PROP_STITCH_ENABLE_SEAM:
415         xcamfilter->stitch_enable_seam = g_value_get_boolean (value);
416         break;
417     case PROP_STITCH_SCALE_MODE:
418         xcamfilter->stitch_scale_mode = (CLBlenderScaleMode) g_value_get_enum (value);
419         break;
420     case PROP_STITCH_FISHEYE_MAP:
421         xcamfilter->stitch_fisheye_map = g_value_get_boolean (value);
422         break;
423     case PROP_STITCH_LSC:
424         xcamfilter->stitch_lsc = g_value_get_boolean (value);
425         break;
426 #if HAVE_OPENCV
427     case PROP_STITCH_FM_OCL:
428         xcamfilter->stitch_fm_ocl = g_value_get_boolean (value);
429         break;
430 #endif
431     case PROP_STITCH_RES_MODE:
432         xcamfilter->stitch_res_mode = (StitchResMode) g_value_get_enum (value);
433         break;
434     default:
435         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
436         break;
437     }
438 }
439 
440 static void
gst_xcam_filter_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)441 gst_xcam_filter_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
442 {
443     GstXCamFilter *xcamfilter = GST_XCAM_FILTER (object);
444 
445     switch (prop_id) {
446     case PROP_BUFFERCOUNT:
447         g_value_set_int (value, xcamfilter->buf_count);
448         break;
449     case PROP_COPY_MODE:
450         g_value_set_enum (value, xcamfilter->copy_mode);
451         break;
452     case PROP_DEFOG_MODE:
453         g_value_set_enum (value, xcamfilter->defog_mode);
454         break;
455     case PROP_WAVELET_MODE:
456         g_value_set_enum (value, xcamfilter->wavelet_mode);
457         break;
458     case PROP_DENOISE_3D_MODE:
459         g_value_set_enum (value, xcamfilter->denoise_3d_mode);
460         break;
461     case PROP_ENABLE_WIREFRAME:
462         g_value_set_boolean (value, xcamfilter->enable_wireframe);
463         break;
464     case PROP_ENABLE_IMAGE_WARP:
465         g_value_set_boolean (value, xcamfilter->enable_image_warp);
466         break;
467     case PROP_ENABLE_IMAGE_STITCH:
468         g_value_set_boolean (value, xcamfilter->enable_stitch);
469         break;
470     case PROP_STITCH_ENABLE_SEAM:
471         g_value_set_boolean (value, xcamfilter->stitch_enable_seam);
472         break;
473     case PROP_STITCH_SCALE_MODE:
474         g_value_set_enum (value, xcamfilter->stitch_scale_mode);
475         break;
476     case PROP_STITCH_FISHEYE_MAP:
477         g_value_set_boolean (value, xcamfilter->stitch_fisheye_map);
478         break;
479     case PROP_STITCH_LSC:
480         g_value_set_boolean (value, xcamfilter->stitch_lsc);
481         break;
482 #if HAVE_OPENCV
483     case PROP_STITCH_FM_OCL:
484         g_value_set_boolean (value, xcamfilter->stitch_fm_ocl);
485         break;
486 #endif
487     case PROP_STITCH_RES_MODE:
488         g_value_set_enum (value, xcamfilter->stitch_res_mode);
489         break;
490     default:
491         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
492         break;
493     }
494 }
495 
496 static gboolean
gst_xcam_filter_start(GstBaseTransform * trans)497 gst_xcam_filter_start (GstBaseTransform *trans)
498 {
499     GstXCamFilter *xcamfilter = GST_XCAM_FILTER (trans);
500 
501     if (xcamfilter->buf_count <= xcamfilter->delay_buf_num) {
502         XCAM_LOG_ERROR (
503             "buffer count (%d) should be greater than delayed buffer number (%d)",
504             xcamfilter->buf_count,
505             xcamfilter->delay_buf_num);
506         return false;
507     }
508 
509     SmartPtr<MainPipeManager> pipe_manager = xcamfilter->pipe_manager;
510     SmartPtr<SmartAnalyzer> smart_analyzer;
511     SmartPtr<CLPostImageProcessor> image_processor;
512 
513     SmartHandlerList smart_handlers = SmartAnalyzerLoader::load_smart_handlers (DEFAULT_SMART_ANALYSIS_LIB_DIR);
514     if (!smart_handlers.empty ()) {
515         smart_analyzer = new SmartAnalyzer ();
516         if (smart_analyzer.ptr ()) {
517             SmartHandlerList::iterator i_handler = smart_handlers.begin ();
518             for (; i_handler != smart_handlers.end ();  ++i_handler)
519             {
520                 XCAM_ASSERT ((*i_handler).ptr ());
521                 smart_analyzer->add_handler (*i_handler);
522             }
523             if (smart_analyzer->prepare_handlers () != XCAM_RETURN_NO_ERROR) {
524                 XCAM_LOG_WARNING ("analyzer(%s) prepare handlers failed", smart_analyzer->get_name ());
525                 return false;
526             }
527             pipe_manager->set_smart_analyzer (smart_analyzer);
528         } else {
529             XCAM_LOG_WARNING ("load smart analyzer(%s) failed, please check.", DEFAULT_SMART_ANALYSIS_LIB_DIR);
530         }
531     }
532 
533     image_processor = new CLPostImageProcessor ();
534     XCAM_ASSERT (image_processor.ptr ());
535     image_processor->set_stats_callback (pipe_manager);
536     image_processor->set_defog_mode ((CLPostImageProcessor::CLDefogMode) xcamfilter->defog_mode);
537 
538     if (NONE_WAVELET != xcamfilter->wavelet_mode) {
539         if (HAT_WAVELET_Y == xcamfilter->wavelet_mode) {
540             image_processor->set_wavelet (CL_WAVELET_HAT, CL_IMAGE_CHANNEL_Y, false);
541         } else if (HAT_WAVELET_UV == xcamfilter->wavelet_mode) {
542             image_processor->set_wavelet (CL_WAVELET_HAT, CL_IMAGE_CHANNEL_UV, false);
543         } else if (HARR_WAVELET_Y == xcamfilter->wavelet_mode) {
544             image_processor->set_wavelet (CL_WAVELET_HAAR, CL_IMAGE_CHANNEL_Y, false);
545         } else if (HARR_WAVELET_UV == xcamfilter->wavelet_mode) {
546             image_processor->set_wavelet (CL_WAVELET_HAAR, CL_IMAGE_CHANNEL_UV, false);
547         } else if (HARR_WAVELET_YUV == xcamfilter->wavelet_mode) {
548             image_processor->set_wavelet (CL_WAVELET_HAAR, CL_IMAGE_CHANNEL_UV | CL_IMAGE_CHANNEL_Y, false);
549         } else if (HARR_WAVELET_BAYES == xcamfilter->wavelet_mode) {
550             image_processor->set_wavelet (CL_WAVELET_HAAR, CL_IMAGE_CHANNEL_UV | CL_IMAGE_CHANNEL_Y, true);
551         } else {
552             image_processor->set_wavelet (CL_WAVELET_DISABLED, CL_IMAGE_CHANNEL_UV, false);
553         }
554     }
555 
556     image_processor->set_3ddenoise_mode (
557         (CLPostImageProcessor::CL3DDenoiseMode) xcamfilter->denoise_3d_mode, xcamfilter->denoise_3d_ref_count);
558 
559     image_processor->set_wireframe (xcamfilter->enable_wireframe);
560     image_processor->set_image_warp (xcamfilter->enable_image_warp);
561     if (smart_analyzer.ptr ()) {
562         if (xcamfilter->enable_wireframe)
563             image_processor->set_scaler (true);
564 
565         if (xcamfilter->enable_image_warp) {
566             image_processor->set_scaler (true);
567             xcamfilter->delay_buf_num = DEFAULT_DELAY_BUFFER_NUM + 16;
568         }
569     }
570 
571     pipe_manager->add_image_processor (image_processor);
572     pipe_manager->set_image_processor (image_processor);
573 
574     xcamfilter->buf_pool = new CLVideoBufferPool ();
575     XCAM_ASSERT (xcamfilter->buf_pool.ptr ());
576     if (xcamfilter->copy_mode == COPY_MODE_DMA) {
577         XCAM_LOG_WARNING ("CLVideoBuffer doesn't support DMA copy mode, switch to CPU copy mode");
578         xcamfilter->copy_mode = COPY_MODE_CPU;
579     }
580 
581     if (xcamfilter->copy_mode == COPY_MODE_DMA) {
582         xcamfilter->allocator = gst_dmabuf_allocator_new ();
583         if (!xcamfilter->allocator) {
584             GST_WARNING ("xcamfilter get allocator failed");
585             return false;
586         }
587     }
588 
589     return true;
590 }
591 
592 static gboolean
gst_xcam_filter_stop(GstBaseTransform * trans)593 gst_xcam_filter_stop (GstBaseTransform *trans)
594 {
595     GstXCamFilter *xcamfilter = GST_XCAM_FILTER (trans);
596 
597     SmartPtr<BufferPool> buf_pool = xcamfilter->buf_pool;
598     if (buf_pool.ptr ())
599         buf_pool->stop ();
600 
601     SmartPtr<MainPipeManager> pipe_manager = xcamfilter->pipe_manager;
602     if (pipe_manager.ptr ())
603         pipe_manager->stop ();
604 
605     return true;
606 }
607 
608 static GstCaps *
gst_xcam_filter_transform_caps(GstBaseTransform * trans,GstPadDirection direction,GstCaps * caps,GstCaps * filter)609 gst_xcam_filter_transform_caps (
610     GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, GstCaps *filter)
611 {
612     GstXCamFilter *xcamfilter = GST_XCAM_FILTER (trans);
613 
614     GstCaps *src_caps, *peer_caps, *intersect_caps;
615     GstStructure *sink_struct, *src_struct;
616     GstPad *peer_pad;
617     gint sink_width, sink_height, src_width, src_height;
618 
619     gboolean is_sink_width = false;
620     gboolean is_sink_height = false;
621 
622     src_caps = gst_pad_get_pad_template_caps (trans->srcpad);
623 
624     if (direction == GST_PAD_SRC || !gst_caps_is_fixed (caps))
625         goto filtering;
626 
627     sink_struct = gst_caps_get_structure (caps, 0);
628     if (!gst_structure_get_int (sink_struct, "width", &sink_width) ||
629             !gst_structure_get_int (sink_struct, "height", &sink_height))
630         goto filtering;
631 
632     peer_pad = gst_pad_get_peer (trans->srcpad);
633     peer_caps = gst_pad_query_caps (peer_pad, src_caps);
634     if (!peer_pad || gst_caps_is_empty (peer_caps)) {
635         if (xcamfilter->enable_stitch) {
636             src_height = XCAM_ALIGN_UP (sink_width / 2, 16);
637             if (src_height * 2 != sink_width) {
638                 gst_caps_unref (src_caps);
639                 gst_caps_unref (peer_caps);
640                 XCAM_LOG_ERROR ("xcamfilter stitch incorrect size, sink-width(%d) / 2 should be aligned with 16",
641                                 sink_width);
642                 return NULL;
643             }
644             src_width = sink_width;
645 
646             gst_caps_unref (src_caps);
647             src_caps = gst_caps_copy (caps);
648             src_struct = gst_caps_get_structure (src_caps, 0);
649 
650             gst_structure_set (src_struct, "width", G_TYPE_INT, src_width,
651                                "height", G_TYPE_INT, src_height, NULL);
652         }
653 
654         gst_caps_unref (peer_caps);
655         goto filtering;
656     }
657 
658     intersect_caps = gst_caps_intersect_full (peer_caps, src_caps, GST_CAPS_INTERSECT_FIRST);
659     gst_caps_unref (src_caps);
660     src_caps = intersect_caps;
661 
662     src_struct = gst_caps_get_structure (src_caps, 0);
663     if (!gst_structure_get_int (src_struct, "width", &src_width)) {
664         is_sink_width = true;
665         src_width = sink_width;
666     }
667     if (!gst_structure_get_int (src_struct, "height", &src_height)) {
668         is_sink_height = true;
669         src_height = sink_height;
670     }
671 
672     if (xcamfilter->enable_stitch) {
673         if (is_sink_width && is_sink_height)
674             src_height = XCAM_ALIGN_UP (src_width / 2, 16);
675 
676         if (src_width != src_height * 2) {
677             XCAM_LOG_ERROR ("xcamfilter incorrect stitch size width:%d height:%d", src_width, src_height);
678             gst_caps_unref (src_caps);
679             return NULL;
680         }
681     }
682 
683     gint fps_n, fps_d;
684     if (!gst_structure_get_fraction (src_struct, "framerate", &fps_n, &fps_d) &&
685             !gst_structure_get_fraction (sink_struct, "framerate", &fps_n, &fps_d)) {
686         fps_n = 25;
687         fps_d = 1;
688     }
689 
690     gst_structure_set (src_struct, "width", G_TYPE_INT, src_width,
691                        "height", G_TYPE_INT, src_height,
692                        "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
693 
694 filtering:
695     if (filter) {
696         intersect_caps = gst_caps_intersect_full (filter, src_caps, GST_CAPS_INTERSECT_FIRST);
697         gst_caps_unref (src_caps);
698         src_caps = intersect_caps;
699     }
700 
701     return src_caps;
702 }
703 
704 static gboolean
gst_xcam_filter_set_caps(GstBaseTransform * trans,GstCaps * incaps,GstCaps * outcaps)705 gst_xcam_filter_set_caps (GstBaseTransform *trans, GstCaps *incaps, GstCaps *outcaps)
706 {
707     GstXCamFilter *xcamfilter = GST_XCAM_FILTER (trans);
708     GstVideoInfo in_info, out_info;
709 
710     if (!gst_video_info_from_caps (&in_info, incaps) ||
711             !gst_video_info_from_caps (&out_info, outcaps)) {
712         XCAM_LOG_WARNING ("fail to parse incaps or outcaps");
713         return false;
714     }
715 
716     XCAM_FAIL_RETURN (
717         ERROR,
718         GST_VIDEO_INFO_FORMAT (&in_info) == GST_VIDEO_FORMAT_NV12 ||
719         GST_VIDEO_INFO_FORMAT (&out_info) == GST_VIDEO_FORMAT_NV12,
720         false,
721         "xcamfilter only support NV12 stream");
722     xcamfilter->gst_sink_video_info = in_info;
723     xcamfilter->gst_src_video_info = out_info;
724 
725     SmartPtr<MainPipeManager> pipe_manager = xcamfilter->pipe_manager;
726     SmartPtr<CLPostImageProcessor> processor = pipe_manager->get_image_processor();
727     XCAM_ASSERT (pipe_manager.ptr () && processor.ptr ());
728     if (!processor->set_output_format (V4L2_PIX_FMT_NV12))
729         return false;
730 
731     if (processor->is_scaled ())
732         processor->set_scaler_factor (640.0 / GST_VIDEO_INFO_WIDTH (&in_info));
733     //processor->set_scaler_factor (0.5f);
734 
735     if (xcamfilter->enable_stitch) {
736         processor->set_image_stitch (
737             xcamfilter->enable_stitch, xcamfilter->stitch_enable_seam, xcamfilter->stitch_scale_mode,
738             xcamfilter->stitch_fisheye_map, xcamfilter->stitch_lsc, xcamfilter->stitch_fm_ocl,
739             GST_VIDEO_INFO_WIDTH (&out_info), GST_VIDEO_INFO_HEIGHT (&out_info), (uint32_t) xcamfilter->stitch_res_mode);
740         XCAM_LOG_INFO ("xcamfilter stitch output size width:%d height:%d",
741                        GST_VIDEO_INFO_WIDTH (&out_info), GST_VIDEO_INFO_HEIGHT (&out_info));
742     }
743 
744     if (pipe_manager->start () != XCAM_RETURN_NO_ERROR) {
745         XCAM_LOG_ERROR ("pipe manager start failed");
746         return false;
747     }
748 
749     VideoBufferInfo buf_info;
750     buf_info.init (
751         V4L2_PIX_FMT_NV12,
752         GST_VIDEO_INFO_WIDTH (&in_info),
753         GST_VIDEO_INFO_HEIGHT (&in_info),
754         XCAM_ALIGN_UP (GST_VIDEO_INFO_WIDTH (&in_info), 16),
755         XCAM_ALIGN_UP (GST_VIDEO_INFO_HEIGHT (&in_info), 16));
756 
757     SmartPtr<BufferPool> buf_pool = xcamfilter->buf_pool;
758     XCAM_ASSERT (buf_pool.ptr ());
759     if (!buf_pool->set_video_info (buf_info) ||
760             !buf_pool->reserve (xcamfilter->buf_count)) {
761         XCAM_LOG_ERROR ("init buffer pool failed");
762         return false;
763     }
764 
765     return true;
766 }
767 
768 static GstFlowReturn
copy_gstbuf_to_xcambuf(GstVideoInfo gstinfo,GstBuffer * gstbuf,SmartPtr<VideoBuffer> xcambuf)769 copy_gstbuf_to_xcambuf (GstVideoInfo gstinfo, GstBuffer *gstbuf, SmartPtr<VideoBuffer> xcambuf)
770 {
771     GstMapInfo mapinfo;
772     VideoBufferPlanarInfo planar;
773     const VideoBufferInfo xcaminfo = xcambuf->get_video_info ();
774 
775     uint8_t *memory = xcambuf->map ();
776     gboolean ret = gst_buffer_map (gstbuf, &mapinfo, GST_MAP_READ);
777     if (!memory || !ret) {
778         XCAM_LOG_WARNING ("xcamfilter map buffer failed");
779         return GST_FLOW_ERROR;
780     }
781 
782     uint8_t *src = NULL;
783     uint8_t *dest = NULL;
784     for (uint32_t index = 0; index < xcaminfo.components; index++) {
785         xcaminfo.get_planar_info (planar, index);
786 
787         src = mapinfo.data + GST_VIDEO_INFO_PLANE_OFFSET (&gstinfo, index);
788         dest = memory + xcaminfo.offsets [index];
789         for (uint32_t i = 0; i < planar.height; i++) {
790             memcpy (dest, src, GST_VIDEO_INFO_WIDTH (&gstinfo));
791             src += GST_VIDEO_INFO_PLANE_STRIDE (&gstinfo, index);
792             dest += xcaminfo.strides [index];
793         }
794     }
795 
796     gst_buffer_unmap (gstbuf, &mapinfo);
797     xcambuf->unmap ();
798 
799     return GST_FLOW_OK;
800 }
801 
802 static GstFlowReturn
copy_xcambuf_to_gstbuf(GstVideoInfo gstinfo,SmartPtr<VideoBuffer> xcambuf,GstBuffer ** gstbuf)803 copy_xcambuf_to_gstbuf (GstVideoInfo gstinfo, SmartPtr<VideoBuffer> xcambuf, GstBuffer **gstbuf)
804 {
805     GstMapInfo mapinfo;
806     VideoBufferPlanarInfo planar;
807     const VideoBufferInfo xcaminfo = xcambuf->get_video_info ();
808 
809     GstBuffer *tmpbuf = gst_buffer_new_allocate (NULL, GST_VIDEO_INFO_SIZE (&gstinfo), NULL);
810     if (!tmpbuf) {
811         XCAM_LOG_ERROR ("xcamfilter allocate buffer failed");
812         return GST_FLOW_ERROR;
813     }
814 
815     uint8_t *memory = xcambuf->map ();
816     gboolean ret = gst_buffer_map (tmpbuf, &mapinfo, GST_MAP_WRITE);
817     if (!memory || !ret) {
818         XCAM_LOG_WARNING ("xcamfilter map buffer failed");
819         return GST_FLOW_ERROR;
820     }
821 
822     uint8_t *src = NULL;
823     uint8_t *dest = NULL;
824     for (uint32_t index = 0; index < GST_VIDEO_INFO_N_PLANES (&gstinfo); index++) {
825         xcaminfo.get_planar_info (planar, index);
826 
827         src = memory + xcaminfo.offsets [index];
828         dest = mapinfo.data + GST_VIDEO_INFO_PLANE_OFFSET (&gstinfo, index);
829         for (uint32_t i = 0; i < planar.height; i++) {
830             memcpy (dest, src, planar.width);
831             src += xcaminfo.strides [index];
832             dest += GST_VIDEO_INFO_PLANE_STRIDE (&gstinfo, index);
833         }
834     }
835 
836     gst_buffer_unmap (tmpbuf, &mapinfo);
837     xcambuf->unmap ();
838 
839     *gstbuf = tmpbuf;
840 
841     return GST_FLOW_OK;
842 }
843 
844 static GstFlowReturn
append_xcambuf_to_gstbuf(GstAllocator * allocator,SmartPtr<VideoBuffer> xcambuf,GstBuffer ** gstbuf)845 append_xcambuf_to_gstbuf (GstAllocator *allocator, SmartPtr<VideoBuffer> xcambuf, GstBuffer **gstbuf)
846 {
847     gsize offsets [XCAM_VIDEO_MAX_COMPONENTS];
848 
849     VideoBufferInfo xcaminfo = xcambuf->get_video_info ();
850     for (int i = 0; i < XCAM_VIDEO_MAX_COMPONENTS; i++) {
851         offsets [i] = xcaminfo.offsets [i];
852     }
853 
854     GstBuffer *tmpbuf = gst_buffer_new ();
855     GstMemory *mem = gst_dmabuf_allocator_alloc (allocator, dup (xcambuf->get_fd ()), xcambuf->get_size ());
856     XCAM_ASSERT (mem);
857 
858     gst_buffer_append_memory (tmpbuf, mem);
859 
860     gst_buffer_add_video_meta_full (
861         tmpbuf,
862         GST_VIDEO_FRAME_FLAG_NONE,
863         GST_VIDEO_FORMAT_NV12,
864         xcaminfo.width,
865         xcaminfo.height,
866         xcaminfo.components,
867         offsets,
868         (gint *) (xcaminfo.strides));
869 
870     *gstbuf = tmpbuf;
871 
872     return GST_FLOW_OK;
873 }
874 
875 static gint
get_dmabuf_fd(GstBuffer * buffer)876 get_dmabuf_fd (GstBuffer *buffer)
877 {
878     GstMemory *mem = gst_buffer_peek_memory (buffer, 0);
879     if (!gst_is_dmabuf_memory (mem)) {
880         return -1;
881     }
882 
883     return gst_dmabuf_memory_get_fd (mem);
884 }
885 
886 static void
gst_xcam_filter_before_transform(GstBaseTransform * trans,GstBuffer * buffer)887 gst_xcam_filter_before_transform (GstBaseTransform *trans, GstBuffer *buffer)
888 {
889     GstXCamFilter *xcamfilter = GST_XCAM_FILTER (trans);
890 
891     SmartPtr<BufferPool> buf_pool = xcamfilter->buf_pool;
892     SmartPtr<MainPipeManager> pipe_manager = xcamfilter->pipe_manager;
893     XCAM_ASSERT (buf_pool.ptr () && pipe_manager.ptr ());
894 
895     if (xcamfilter->cached_buf_num > xcamfilter->delay_buf_num)
896         return;
897 
898     SmartPtr<VideoBuffer> video_buf;
899     gint dma_fd = get_dmabuf_fd (buffer);
900     if (dma_fd >= 0) {
901 #if HAVE_LIBDRM
902         SmartPtr<DrmBoBufferPool> bo_buf_pool = buf_pool.dynamic_cast_ptr<DrmBoBufferPool> ();
903         SmartPtr<DrmDisplay> display = bo_buf_pool->get_drm_display ();
904         VideoBufferInfo info = bo_buf_pool->get_video_info ();
905 
906         SmartPtr<VideoBuffer> dma_buf = new DmaGstBuffer (info, dma_fd, buffer);
907         video_buf = display->convert_to_drm_bo_buf (display, dma_buf);
908 #endif
909         if (!video_buf.ptr ()) {
910             XCAM_LOG_ERROR ("xcamfilter convert to drm bo buffer failed");
911             return;
912         }
913     } else {
914         video_buf = buf_pool->get_buffer (buf_pool);
915         if (!buf_pool.ptr ()) {
916             XCAM_LOG_ERROR ("xcamfilter sink-pad get buffer failed");
917             return;
918         }
919 
920         copy_gstbuf_to_xcambuf (xcamfilter->gst_sink_video_info, buffer, video_buf);
921     }
922 
923     if (pipe_manager->push_buffer (video_buf) != XCAM_RETURN_NO_ERROR) {
924         XCAM_LOG_ERROR ("xcamfilter push buffer failed");
925         return;
926     }
927 
928     xcamfilter->cached_buf_num++;
929 }
930 
931 static GstFlowReturn
gst_xcam_filter_prepare_output_buffer(GstBaseTransform * trans,GstBuffer * input,GstBuffer ** outbuf)932 gst_xcam_filter_prepare_output_buffer (GstBaseTransform *trans, GstBuffer *input, GstBuffer **outbuf)
933 {
934     GstXCamFilter *xcamfilter = GST_XCAM_FILTER (trans);
935     GstFlowReturn ret = GST_FLOW_OK;
936 
937     SmartPtr<MainPipeManager> pipe_manager = xcamfilter->pipe_manager;
938     SmartPtr<VideoBuffer> video_buf;
939 
940     if (xcamfilter->cached_buf_num > xcamfilter->buf_count)
941         return GST_FLOW_ERROR;
942 
943     int32_t timeout = -1;
944     if (xcamfilter->cached_buf_num <= xcamfilter->delay_buf_num)
945         timeout = 0;
946 
947     video_buf = pipe_manager->dequeue_buffer (timeout);
948     if (!video_buf.ptr ()) {
949         XCAM_LOG_WARNING ("xcamfilter dequeue buffer failed");
950         *outbuf = NULL;
951         return GST_FLOW_OK;
952     }
953 
954     if (xcamfilter->copy_mode == COPY_MODE_CPU) {
955         ret = copy_xcambuf_to_gstbuf (xcamfilter->gst_src_video_info, video_buf, outbuf);
956     } else if (xcamfilter->copy_mode == COPY_MODE_DMA) {
957         GstAllocator *allocator = xcamfilter->allocator;
958         ret = append_xcambuf_to_gstbuf (allocator, video_buf, outbuf);
959     }
960 
961     if (ret == GST_FLOW_OK) {
962         xcamfilter->cached_buf_num--;
963         GST_BUFFER_TIMESTAMP (*outbuf) = GST_BUFFER_TIMESTAMP (input);
964     }
965 
966     return ret;
967 }
968 
969 static GstFlowReturn
gst_xcam_filter_transform(GstBaseTransform * trans,GstBuffer * inbuf,GstBuffer * outbuf)970 gst_xcam_filter_transform (GstBaseTransform *trans, GstBuffer *inbuf, GstBuffer *outbuf)
971 {
972     XCAM_UNUSED (trans);
973     XCAM_UNUSED (inbuf);
974 
975     if (!outbuf) {
976         XCAM_LOG_ERROR ("transform failed with null outbufer");
977         return GST_FLOW_ERROR;
978     }
979 
980     XCAM_STATIC_FPS_CALCULATION (gstxcamfilter, XCAM_OBJ_DUR_FRAME_NUM);
981     return GST_FLOW_OK;
982 }
983 
984 static gboolean
gst_xcam_filter_plugin_init(GstPlugin * xcamfilter)985 gst_xcam_filter_plugin_init (GstPlugin *xcamfilter)
986 {
987     return gst_element_register (xcamfilter, "xcamfilter", GST_RANK_NONE,
988                                  GST_TYPE_XCAM_FILTER);
989 }
990 
991 #ifndef PACKAGE
992 #define PACKAGE "libxam"
993 #endif
994 
995 GST_PLUGIN_DEFINE (
996     GST_VERSION_MAJOR,
997     GST_VERSION_MINOR,
998     xcamfilter,
999     "Libxcam filter plugin",
1000     gst_xcam_filter_plugin_init,
1001     VERSION,
1002     GST_LICENSE_UNKNOWN,
1003     "libxcamfilter",
1004     "https://github.com/01org/libxcam"
1005 )
1006