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 (at) 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 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 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 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 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 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 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 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 (at) intel.com> & Yinhang Liu <yinhangx.liu (at) 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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