Separate some classes from mv_depthstream_test_suite 40/294440/2 accepted/tizen/7.0/unified/20230620.164244
authorTae-Young Chung <ty83.chung@samsung.com>
Mon, 19 Jun 2023 08:23:30 +0000 (17:23 +0900)
committerTae-Young Chung <ty83.chung@samsung.com>
Tue, 20 Jun 2023 02:29:16 +0000 (11:29 +0900)
[Version] 0.23.49-2
[Issue type] update

Change-Id: I2fa91ff20369609406fb4e7250ad83213f42dfe1
Signed-off-by: Tae-Young Chung <ty83.chung@samsung.com>
packaging/capi-media-vision.spec
test/testsuites/mv3d/CameraSourceFeeder.h [new file with mode: 0644]
test/testsuites/mv3d/DfsUtil.h [new file with mode: 0644]
test/testsuites/mv3d/FeederFactory.h [new file with mode: 0644]
test/testsuites/mv3d/IFeeder.h [new file with mode: 0644]
test/testsuites/mv3d/Mv3d.h [new file with mode: 0644]
test/testsuites/mv3d/VisionSourceFeeder.h [new file with mode: 0644]
test/testsuites/mv3d/depthstream_test_suite.cpp

index 231832fc486657d7bae8a252b4fd3e4263f2dbe3..6b67301b0b6a0b26b6c1b85fa112f40142160072 100644 (file)
@@ -1,7 +1,7 @@
 Name:        capi-media-vision
 Summary:     Media Vision library for Tizen Native API
 Version:     0.23.49
-Release:     1
+Release:     2
 Group:       Multimedia/Framework
 License:     Apache-2.0 and BSD-3-Clause
 Source0:     %{name}-%{version}.tar.gz
diff --git a/test/testsuites/mv3d/CameraSourceFeeder.h b/test/testsuites/mv3d/CameraSourceFeeder.h
new file mode 100644 (file)
index 0000000..8099bd2
--- /dev/null
@@ -0,0 +1,99 @@
+/**
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __MV_DEPTHSTREAM_TESTSUITE_CAMERA_SOURCE_FEEDER_H__
+#define __MV_DEPTHSTREAM_TESTSUITE_CAMERA_SOURCE_FEEDER_H__
+
+#include "IFeeder.h"
+#include <camera_internal.h>
+
+class CameraSourceFeeder : public IFeeder
+{
+private:
+       Mv3d* _mv3d;
+       const camera_device_e _deviceId;
+
+       camera_h _handle;
+       camera_frame_meta_s _frameMeta;
+
+       static void _camera_preview_cb(media_packet_h pkt, void *user_data);
+       static bool _supported_preview_fps_cb(camera_attr_fps_e fps, void *user_data);
+public:
+       CameraSourceFeeder();
+       ~CameraSourceFeeder();
+
+       void start(std::shared_ptr<Mv3d> mv3d) override;
+       void stop() override;
+};
+
+CameraSourceFeeder::CameraSourceFeeder()
+               : _mv3d(nullptr)
+               , _deviceId(CAMERA_DEVICE_CAMERA3)
+               , _handle(nullptr)
+{
+       camera_create(_deviceId, &_handle);
+       camera_attr_foreach_supported_fps(_handle, _supported_preview_fps_cb, this);
+       if (!camera_is_supported_media_packet_preview_cb(_handle))
+               throw std::runtime_error("not supported media packet preview cb");
+}
+
+CameraSourceFeeder::~CameraSourceFeeder()
+{
+       stop();
+
+       camera_destroy(_handle);
+       _handle = nullptr;
+};
+
+void CameraSourceFeeder::start(std::shared_ptr<Mv3d> mv3d)
+{
+       _mv3d = mv3d.get();
+       camera_set_media_packet_preview_cb(_handle, _camera_preview_cb, this);
+
+       mv3d->resetTime();
+       camera_start_preview(_handle);
+}
+
+void CameraSourceFeeder::stop()
+{
+       camera_state_e state;
+       camera_get_state(_handle, &state);
+       if (state == CAMERA_STATE_PREVIEW)
+               camera_stop_preview(_handle);
+}
+
+void CameraSourceFeeder::_camera_preview_cb(media_packet_h pkt, void *user_data)
+{
+       CameraSourceFeeder* cameraSource = static_cast<CameraSourceFeeder*>(user_data);
+       std::cout << "_camera_preview_cb: " << cameraSource->_mv3d->checkElapsedTime()  << " ms" << std::endl;
+
+       unsigned long timestamp;
+       camera_attr_get_preview_frame_timestamp(cameraSource->_handle, &timestamp);
+       camera_attr_get_preview_frame_meta(cameraSource->_handle, &cameraSource->_frameMeta);
+       cameraSource->_mv3d->run(pkt, timestamp, cameraSource->_frameMeta);
+       media_packet_unref(pkt);
+}
+
+bool CameraSourceFeeder::_supported_preview_fps_cb(camera_attr_fps_e fps, void *user_data)
+{
+       CameraSourceFeeder* cameraSource = static_cast<CameraSourceFeeder*>(user_data);
+       if (fps == 10) {
+               std::cout << "Set desired camera preview fps: "  << fps << std::endl;
+               camera_attr_set_preview_fps(cameraSource->_handle, fps);
+               return false;
+       }
+       return true;
+}
+#endif
\ No newline at end of file
diff --git a/test/testsuites/mv3d/DfsUtil.h b/test/testsuites/mv3d/DfsUtil.h
new file mode 100644 (file)
index 0000000..2c36feb
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __MV_DEPTHSTREAM_TESTSUITE_DFS_UTIL_H__
+#define __MV_DEPTHSTREAM_TESTSUITE_DFS_UTIL_H__
+
+#include <chrono>
+
+enum { STEREO_FORMAT_NONE, STEREO_FORMAT_SIDE_BY_SIDE, STEREO_FORMAT_TOP_AND_BOTTOM };
+enum { VISION_SOURCE, CAMERA_SOURCE };
+enum { NONE, OKAY };
+
+class StopWatch
+{
+private:
+       std::chrono::steady_clock::time_point start;
+public:
+       StopWatch() = default;
+       ~StopWatch() = default;
+
+       void resetTime();
+
+       std::chrono::milliseconds elapsedTime();
+};
+
+void StopWatch::resetTime()
+{
+       start = std::chrono::steady_clock::now();
+}
+
+std::chrono::milliseconds StopWatch::elapsedTime()
+{
+    return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start);
+}
+#endif
diff --git a/test/testsuites/mv3d/FeederFactory.h b/test/testsuites/mv3d/FeederFactory.h
new file mode 100644 (file)
index 0000000..c016959
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __MV_DEPTHSTREAM_TESTSUITE_FEEDER_FACTORY_H__
+#define __MV_DEPTHSTREAM_TESTSUITE_FEEDER_FACTORY_H__
+
+#include "IFeeder.h"
+#include "VisionSourceFeeder.h"
+#include "CameraSourceFeeder.h"
+
+class FeederFactory
+{
+private:
+       FeederFactory() = delete;
+       FeederFactory(const FeederFactory&) = delete;
+public:
+       static std::unique_ptr<IFeeder> createVisionSourceFeeder(int width=640, int height=400, int fps=10, int stereoFormat=STEREO_FORMAT_TOP_AND_BOTTOM)
+       {
+               return std::make_unique<VisionSourceFeeder>(width, height, fps, stereoFormat);
+       }
+
+       static std::unique_ptr<IFeeder> createCameraSourceFeeder()
+       {
+               return std::make_unique<CameraSourceFeeder>();
+       }
+};
+#endif
diff --git a/test/testsuites/mv3d/IFeeder.h b/test/testsuites/mv3d/IFeeder.h
new file mode 100644 (file)
index 0000000..c08393c
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __MV_DEPTHSTREAM_TESTSUITE_IFEEDER_H__
+#define __MV_DEPTHSTREAM_TESTSUITE_IFEEDER_H__
+
+#include <memory>
+#include "Mv3d.h"
+#include "DfsUtil.h"
+
+class IFeeder
+{
+public:
+       virtual ~IFeeder(){};
+       virtual void start(std::shared_ptr<Mv3d> mv3d) = 0;
+       virtual void stop() = 0;
+};
+#endif
diff --git a/test/testsuites/mv3d/Mv3d.h b/test/testsuites/mv3d/Mv3d.h
new file mode 100644 (file)
index 0000000..2fa6986
--- /dev/null
@@ -0,0 +1,224 @@
+/**
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __MV_DEPTHSTREAM_TESTSUITE_MV3D_H__
+#define __MV_DEPTHSTREAM_TESTSUITE_MV3D_H__
+
+#include <vision_source.h>
+#include <camera_internal.h>
+
+#include "mv_3d.h"
+#include "mv_common.h"
+#include "DfsUtil.h"
+
+#ifdef WITH_DA_PROFILE
+#include <mv_common_internal.h>
+#endif
+
+class Mv3d
+{
+private:
+       bool _isAsync;
+       int _sourceWidth;
+       int _sourceHeight;
+       unsigned char *_rawBuffer;
+
+       mv_3d_h _3dHandle;
+       mv_source_h _source;
+       mv_engine_config_h _engineConfig;
+
+       int _state;
+       std::string _calibFilePath;
+       std::string _depthFilePath;
+       StopWatch _timer;
+
+       static void _depth_stereo_cb(mv_source_h source, unsigned short *depth, unsigned int width, unsigned int height,
+                                                               void *user_data);
+public:
+       Mv3d(int minDisparity, int maxDisparity, bool isAsync, std::string calibFilePath, int depthWidth, int depthHeight, int stereoFormat, std::string depthFilePath);
+       ~Mv3d();
+
+       void prepare();
+       void run(vision_source_buffer_s *buffer);
+       void run(media_packet_h pkt, unsigned long& timestamp, camera_frame_meta_s& meta);
+
+       void stop();
+
+       void resetTime();
+
+       long long int checkElapsedTime();
+};
+
+Mv3d::Mv3d(int minDisparity, int maxDisparity, bool isAsync, std::string calibFilePath, int depthWidth, int depthHeight, int stereoFormat, std::string depthFilePath)
+       :_isAsync(isAsync)
+    , _sourceWidth(depthWidth)
+    , _sourceHeight(depthHeight)
+    , _rawBuffer(nullptr)
+    , _3dHandle(nullptr)
+    , _source(nullptr)
+    , _engineConfig(nullptr)
+    , _state(NONE)
+    , _calibFilePath("/usr/share/dfs-qcmv/stereoCalibDA.yaml")
+    , _depthFilePath("/tmp/depthDump.png")
+{
+    // MediaVision mv_engine_config_h
+    mv_create_engine_config(&_engineConfig);
+    mv_engine_config_set_int_attribute(_engineConfig, MV_3D_DEPTH_WIDTH, depthWidth);
+    mv_engine_config_set_int_attribute(_engineConfig, MV_3D_DEPTH_HEIGHT, depthHeight);
+    mv_engine_config_set_int_attribute(_engineConfig, MV_3D_DEPTH_MIN_DISPARITY, minDisparity);
+    mv_engine_config_set_int_attribute(_engineConfig, MV_3D_DEPTH_MAX_DISPARITY, maxDisparity);
+
+    if (!calibFilePath.empty())
+        _calibFilePath = calibFilePath;
+    mv_engine_config_set_string_attribute(_engineConfig, MV_3D_DEPTH_STEREO_CONFIG_FILE_PATH, _calibFilePath.c_str());
+
+    if (!depthFilePath.empty())
+        _depthFilePath = depthFilePath;
+
+    // MediaVision mv_3d_h
+    mv_3d_create(&_3dHandle);
+    mv_3d_configure(_3dHandle, _engineConfig);
+    mv_3d_set_depth_cb(_3dHandle, _depth_stereo_cb, this);
+
+    mv_create_source(&_source);
+
+    switch (stereoFormat) {
+    case STEREO_FORMAT_SIDE_BY_SIDE:
+        _sourceWidth <<= 1;
+        break;
+    case STEREO_FORMAT_TOP_AND_BOTTOM:
+        _sourceHeight <<= 1;
+        break;
+    default:
+        break;
+    }
+
+    _rawBuffer = new unsigned char [_sourceWidth * _sourceHeight];
+}
+
+Mv3d::~Mv3d()
+{
+    if (_engineConfig || _3dHandle || _source)
+        stop();
+}
+
+
+void Mv3d::prepare()
+{
+    mv_3d_prepare(_3dHandle);
+    _state = OKAY;
+}
+
+void Mv3d::run(vision_source_buffer_s *buffer)
+{
+    if (_state != OKAY)
+        return;
+
+    for (unsigned int h = 0; h < buffer->resolution.height; h++) {
+        memcpy(_rawBuffer + buffer->resolution.width * h, buffer->planes[0].data + (buffer->planes[0].align_width * h),
+            buffer->resolution.width);
+    }
+
+    mv_source_fill_by_buffer(_source, _rawBuffer, _sourceWidth * _sourceHeight,
+                    _sourceWidth, _sourceHeight, MEDIA_VISION_COLORSPACE_Y800);
+
+#ifdef WITH_DA_PROFILE
+    mv_source_set_timestamp(_source, static_cast<da_timestamp_s *>(buffer->priv));
+#endif
+
+if (_isAsync)
+    mv_3d_run_async(_3dHandle, _source, nullptr, nullptr);
+else
+    mv_3d_run(_3dHandle, _source, nullptr, nullptr);
+
+    mv_source_clear(_source);
+}
+
+void Mv3d::run(media_packet_h pkt, unsigned long& timestamp, camera_frame_meta_s& meta)
+{
+    mv_source_fill_by_media_packet(_source, pkt);
+
+#ifdef WITH_DA_PROFILE
+    da_timestamp_s daTimestamp = {timestamp,
+                                meta.ts_soe,
+                                meta.ts_eoe,
+                                meta.ts_sof,
+                                meta.ts_eof,
+                                meta.ts_hal,
+                                meta.ts_qmf,
+                                meta.td_exp,
+                                meta.ts_aux,
+                                meta.td_aux,
+                                meta.seqnum,
+                                meta.flags };
+
+    mv_source_set_timestamp(_source, &daTimestamp);
+#endif
+    mv_3d_run_async(_3dHandle, _source, nullptr, nullptr);
+
+    mv_source_clear(_source);
+}
+
+void Mv3d::stop()
+{
+    _state = NONE;
+    delete [] _rawBuffer;
+
+    if (_source) {
+        mv_destroy_source(_source);
+        _source = nullptr;
+    }
+
+    if (_3dHandle) {
+        mv_3d_destroy(_3dHandle);
+        _3dHandle = nullptr;
+    }
+
+    if (_engineConfig) {
+        mv_destroy_engine_config(_engineConfig);
+        _engineConfig = nullptr;
+    }
+}
+
+void Mv3d::resetTime()
+{
+    _timer.resetTime();
+}
+
+long long int Mv3d::checkElapsedTime()
+{
+    return static_cast<long long int>(_timer.elapsedTime().count());
+}
+
+
+void Mv3d::_depth_stereo_cb(mv_source_h source, unsigned short *depth, unsigned int width, unsigned int height,
+                            void *user_data)
+{
+#ifdef WITH_DA_PROFILE
+    std::cout << "_depth_stereo_cb: " << std::endl;
+    da_timestamp_s timestamp;
+    mv_source_get_timestamp(source, &timestamp);
+    std::cout << "timestamp [" << timestamp.timestamp << "], ";
+    std::cout << "ts_sof [" << timestamp.ts_sof << "], ";
+    std::cout << "ts_aux [" << timestamp.ts_aux << "], ";
+    std::cout << "ts_eof [" << timestamp.ts_eof << "], " << std::endl;
+#endif
+    cv::Mat dump(cv::Size(width, height), CV_16U, depth);
+    dump.setTo(0, dump==65535);
+
+    Mv3d* mv3d = static_cast<Mv3d *>(user_data);
+    cv::imwrite(mv3d->_depthFilePath, dump);
+}
+#endif
\ No newline at end of file
diff --git a/test/testsuites/mv3d/VisionSourceFeeder.h b/test/testsuites/mv3d/VisionSourceFeeder.h
new file mode 100644 (file)
index 0000000..dc0bc13
--- /dev/null
@@ -0,0 +1,105 @@
+/**
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __MV_DEPTHSTREAM_TESTSUITE_VISION_SOURCE_FEEDER_H__
+#define __MV_DEPTHSTREAM_TESTSUITE_VISION_SOURCE_FEEDER_H__
+
+#include "IFeeder.h"
+#include <vision_source.h>
+
+class VisionSourceFeeder : public IFeeder
+{
+private:
+       Mv3d * _mv3d;
+       int _state;
+       const int _deviceId;
+
+       vision_source_h _handle;
+       vision_source_format_s _format;
+
+       static int _vision_source_cb(vision_source_buffer_s *buffer, void *user_data);
+public:
+       VisionSourceFeeder(int width, int height, int fps, int stereoFormat);
+       ~VisionSourceFeeder();
+
+       void start(std::shared_ptr<Mv3d> mv3d) override;
+       void stop() override;
+};
+
+VisionSourceFeeder::VisionSourceFeeder(int width, int height, int fps, int stereoFormat)
+               : _mv3d(nullptr)
+               , _state(NONE)
+               , _deviceId(3)
+               , _handle(nullptr)
+{
+       vision_source_init(&_handle);
+       vision_source_open_device(_handle, _deviceId);
+
+       _format.pixel_format = VISION_SOURCE_PIXEL_FORMAT_NV12;
+       _format.resolution = { width, height },
+       _format.fps = fps;
+       _format.quality = 0;
+       _format.bitrate = 0;
+
+       switch (stereoFormat) {
+       case STEREO_FORMAT_SIDE_BY_SIDE:
+               _format.resolution.width <<= 1;
+               break;
+       case STEREO_FORMAT_TOP_AND_BOTTOM:
+               _format.resolution.height <<= 1;
+               break;
+       default:
+               break;
+       }
+
+       vision_source_set_stream_format(_handle, &_format);
+};
+
+VisionSourceFeeder::~VisionSourceFeeder()
+{
+       if (_handle) {
+               stop();
+       }
+};
+
+void VisionSourceFeeder::start(std::shared_ptr<Mv3d> mv3d)
+{
+       _mv3d = mv3d.get();
+       _mv3d->resetTime();
+       _state = OKAY;
+       vision_source_start_stream(_handle, _vision_source_cb, this);
+}
+
+void VisionSourceFeeder::stop()
+{
+       _state = NONE;
+       vision_source_stop_stream(_handle);
+       vision_source_close_device(_handle);
+       vision_source_exit(_handle);
+       _handle = nullptr;
+}
+
+
+int VisionSourceFeeder::_vision_source_cb(vision_source_buffer_s *buffer, void *user_data)
+{
+       VisionSourceFeeder* visionSource = static_cast<VisionSourceFeeder*>(user_data);
+       std::cout << "_vision_source_cb: " << visionSource->_mv3d->checkElapsedTime() << " ms" << std::endl;
+       if (visionSource->_state != OKAY)
+               return 0;
+
+       visionSource->_mv3d->run(buffer);
+       return 0;
+}
+#endif
\ No newline at end of file
index 5cf5421263649f5426adb56aba2959f477978eff..e38a98e40a10bff25bc8526f4971ad4b74c3cb26 100644 (file)
 
 #include <mv_log_cfg.h>
 #include <mv_common.h>
-#include "mv_3d.h"
+#include "Mv3d.h"
+
 #include <mv_testsuite_common.h>
-#include <vision_source.h>
-#include <camera_internal.h>
-#ifdef WITH_DA_PROFILE
-#include <mv_common_internal.h>
-#endif
+#include "FeederFactory.h"
 
 #include <glib-2.0/glib.h>
 
 using namespace open3d;
 #endif
 
-#define VISION_SOURCE_DEVICE_ID 3
-
-class StopWatch
-{
-private:
-       std::chrono::steady_clock::time_point start;
-public:
-       StopWatch() = default;
-       ~StopWatch() = default;
-
-       void resetTime()
-       {
-               start = std::chrono::steady_clock::now();
-       }
-       std::chrono::milliseconds elapsedTime()
-       {
-               return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start);
-       }
-};
-
-enum { STEREO_FORMAT_NONE, STEREO_FORMAT_SIDE_BY_SIDE, STEREO_FORMAT_TOP_AND_BOTTOM };
-enum { VISION_SOURCE, CAMERA_SOURCE };
-enum { NONE, OKAY };
-
-class Mv3d
+class DfsApp
 {
 private:
-       bool _isAsync;
-       int _sourceWidth;
-       int _sourceHeight;
-       unsigned char *_rawBuffer;
-
-       mv_3d_h _3dHandle;
-       mv_source_h _source;
-       mv_engine_config_h _engineConfig;
-
-       int _state;
-       std::string _calibFilePath;
-       std::string _depthFilePath;
-       StopWatch _timer;
-
-       static void _depth_stereo_cb(mv_source_h source, unsigned short *depth, unsigned int width, unsigned int height,
-                                                               void *user_data)
-       {
-#ifdef WITH_DA_PROFILE
-               std::cout << "_depth_stereo_cb: " << std::endl;
-               da_timestamp_s timestamp;
-               mv_source_get_timestamp(source, &timestamp);
-               std::cout << "timestamp [" << timestamp.timestamp << "], ";
-               std::cout << "ts_sof [" << timestamp.ts_sof << "], ";
-               std::cout << "ts_aux [" << timestamp.ts_aux << "], ";
-               std::cout << "ts_eof [" << timestamp.ts_eof << "], " << std::endl;
-#endif
-               cv::Mat dump(cv::Size(width, height), CV_16U, depth);
-               dump.setTo(0, dump==65535);
-
-               Mv3d* mv3d = static_cast<Mv3d *>(user_data);
-               cv::imwrite(mv3d->_depthFilePath, dump);
-       }
+       GMainLoop *_loop;
+       std::unique_ptr<IFeeder> _feeder;
+       std::shared_ptr<Mv3d> _mv3d;
 public:
-       Mv3d(int minDisparity, int maxDisparity, bool isAsync, std::string calibFilePath, int depthWidth, int depthHeight, int stereoFormat, std::string depthFilePath)
-               :_isAsync(isAsync)
-               , _sourceWidth(depthWidth)
-               , _sourceHeight(depthHeight)
-               , _rawBuffer(nullptr)
-               , _3dHandle(nullptr)
-               , _source(nullptr)
-               , _engineConfig(nullptr)
-               , _state(NONE)
-               , _calibFilePath("/usr/share/dfs-qcmv/stereoCalibDA.yaml")
-               , _depthFilePath("/tmp/depthDump.png")
-       {
-               // MediaVision mv_engine_config_h
-               mv_create_engine_config(&_engineConfig);
-               mv_engine_config_set_int_attribute(_engineConfig, MV_3D_DEPTH_WIDTH, depthWidth);
-               mv_engine_config_set_int_attribute(_engineConfig, MV_3D_DEPTH_HEIGHT, depthHeight);
-               mv_engine_config_set_int_attribute(_engineConfig, MV_3D_DEPTH_MIN_DISPARITY, minDisparity);
-               mv_engine_config_set_int_attribute(_engineConfig, MV_3D_DEPTH_MAX_DISPARITY, maxDisparity);
-
-               if (!calibFilePath.empty())
-                       _calibFilePath = calibFilePath;
-               mv_engine_config_set_string_attribute(_engineConfig, MV_3D_DEPTH_STEREO_CONFIG_FILE_PATH, _calibFilePath.c_str());
-
-               if (!depthFilePath.empty())
-                       _depthFilePath = depthFilePath;
-
-               // MediaVision mv_3d_h
-               mv_3d_create(&_3dHandle);
-               mv_3d_configure(_3dHandle, _engineConfig);
-               mv_3d_set_depth_cb(_3dHandle, _depth_stereo_cb, this);
-
-               mv_create_source(&_source);
-
-               switch (stereoFormat) {
-               case STEREO_FORMAT_SIDE_BY_SIDE:
-                       _sourceWidth <<= 1;
-                       break;
-               case STEREO_FORMAT_TOP_AND_BOTTOM:
-                       _sourceHeight <<= 1;
-                       break;
-               default:
-                       break;
-               }
-
-               _rawBuffer = new unsigned char [_sourceWidth * _sourceHeight];
-       }
-
-       ~Mv3d()
-       {
-               if (_engineConfig || _3dHandle || _source)
-                       stop();
-       }
-
-       void prepare()
-       {
-               mv_3d_prepare(_3dHandle);
-               _state = OKAY;
-       }
-
-       void run(vision_source_buffer_s *buffer)
-       {
-               if (_state != OKAY)
-                       return;
-
-               for (unsigned int h = 0; h < buffer->resolution.height; h++) {
-                       memcpy(_rawBuffer + buffer->resolution.width * h, buffer->planes[0].data + (buffer->planes[0].align_width * h),
-                               buffer->resolution.width);
-               }
-
-               mv_source_fill_by_buffer(_source, _rawBuffer, _sourceWidth * _sourceHeight,
-                                               _sourceWidth, _sourceHeight, MEDIA_VISION_COLORSPACE_Y800);
-
-#ifdef WITH_DA_PROFILE
-               mv_source_set_timestamp(_source, static_cast<da_timestamp_s *>(buffer->priv));
-#endif
+       DfsApp();
+       ~DfsApp();
 
-       if (_isAsync)
-               mv_3d_run_async(_3dHandle, _source, nullptr, nullptr);
-       else
-               mv_3d_run(_3dHandle, _source, nullptr, nullptr);
-
-               mv_source_clear(_source);
-       }
-
-       void run(media_packet_h pkt, unsigned long& timestamp, camera_frame_meta_s& meta)
-       {
-               mv_source_fill_by_media_packet(_source, pkt);
-
-#ifdef WITH_DA_PROFILE
-               da_timestamp_s daTimestamp = {timestamp,
-                                                                meta.ts_soe,
-                                                                meta.ts_eoe,
-                                                                meta.ts_sof,
-                                                                meta.ts_eof,
-                                                                meta.ts_hal,
-                                                                meta.ts_qmf,
-                                                                meta.td_exp,
-                                                                meta.ts_aux,
-                                                                meta.td_aux,
-                                                                meta.seqnum,
-                                                                meta.flags };
-
-               mv_source_set_timestamp(_source, &daTimestamp);
-#endif
-               mv_3d_run_async(_3dHandle, _source, nullptr, nullptr);
-
-               mv_source_clear(_source);
-       }
-
-       void stop()
-       {
-               _state = NONE;
-               delete [] _rawBuffer;
-
-               if (_source) {
-                       mv_destroy_source(_source);
-                       _source = nullptr;
-               }
-
-               if (_3dHandle) {
-                       mv_3d_destroy(_3dHandle);
-                       _3dHandle = nullptr;
-               }
-
-               if (_engineConfig) {
-                       mv_destroy_engine_config(_engineConfig);
-                       _engineConfig = nullptr;
-               }
-       }
-
-       void resetTime()
-       {
-               _timer.resetTime();
-       }
-
-       long long int checkElapsedTime()
-       {
-               return static_cast<long long int>(_timer.elapsedTime().count());
-       }
+       void createDfs(std::shared_ptr<Mv3d> mv3d, std::unique_ptr<IFeeder> feeder);
+       void start();
+       void stop();
+       static void helper();
 };
 
-class IFeeder
+DfsApp::DfsApp()
+       : _loop(nullptr)
 {
-public:
-       virtual ~IFeeder(){};
-       virtual void start(std::shared_ptr<Mv3d> mv3d) = 0;
-       virtual void stop() = 0;
-};
-
-class VisionSourceFeeder : public IFeeder
-{
-private:
-       Mv3d * _mv3d;
-       int _state;
-       const int _deviceId;
-
-       vision_source_h _handle;
-       vision_source_format_s _format;
-
-       static int _vision_source_cb(vision_source_buffer_s *buffer, void *user_data)
-       {
-               VisionSourceFeeder* visionSource = static_cast<VisionSourceFeeder*>(user_data);
-               std::cout << "_vision_source_cb: " << visionSource->_mv3d->checkElapsedTime() << " ms" << std::endl;
-               if (visionSource->_state != OKAY)
-                       return 0;
-
-               visionSource->_mv3d->run(buffer);
-               return 0;
-       }
-public:
-       VisionSourceFeeder(int width, int height, int fps, int stereoFormat)
-                       : _mv3d(nullptr)
-                       , _state(NONE)
-                       , _deviceId(3)
-                       , _handle(nullptr)
-       {
-               vision_source_init(&_handle);
-               vision_source_open_device(_handle, _deviceId);
-
-               _format.pixel_format = VISION_SOURCE_PIXEL_FORMAT_NV12;
-               _format.resolution = { width, height },
-               _format.fps = fps;
-               _format.quality = 0;
-               _format.bitrate = 0;
-
-               switch (stereoFormat) {
-               case STEREO_FORMAT_SIDE_BY_SIDE:
-                       _format.resolution.width <<= 1;
-                       break;
-               case STEREO_FORMAT_TOP_AND_BOTTOM:
-                       _format.resolution.height <<= 1;
-                       break;
-               default:
-                       break;
-               }
-
-               vision_source_set_stream_format(_handle, &_format);
-       };
-
-       ~VisionSourceFeeder()
-       {
-               if (_handle) {
-                       stop();
-               }
-       };
-
-       void start(std::shared_ptr<Mv3d> mv3d) override
-       {
-               _mv3d = mv3d.get();
-               _mv3d->resetTime();
-               _state = OKAY;
-               vision_source_start_stream(_handle, _vision_source_cb, this);
-       }
-
-       void stop() override
-       {
-               _state = NONE;
-               vision_source_stop_stream(_handle);
-               vision_source_close_device(_handle);
-               vision_source_exit(_handle);
-               _handle = nullptr;
-       }
-};
+}
 
-class CameraSourceFeeder : public IFeeder
+DfsApp::~DfsApp()
 {
-private:
-       Mv3d* _mv3d;
-       const camera_device_e _deviceId;
-
-       camera_h _handle;
-       camera_frame_meta_s _frameMeta;
-
-       static void _camera_preview_cb(media_packet_h pkt, void *user_data)
-       {
-               CameraSourceFeeder* cameraSource = static_cast<CameraSourceFeeder*>(user_data);
-               std::cout << "_camera_preview_cb: " << cameraSource->_mv3d->checkElapsedTime()  << " ms" << std::endl;
-
-               unsigned long timestamp;
-               camera_attr_get_preview_frame_timestamp(cameraSource->_handle, &timestamp);
-               camera_attr_get_preview_frame_meta(cameraSource->_handle, &cameraSource->_frameMeta);
-               cameraSource->_mv3d->run(pkt, timestamp, cameraSource->_frameMeta);
-               media_packet_unref(pkt);
-       }
-
-       static bool _supported_preview_fps_cb(camera_attr_fps_e fps, void *user_data)
-       {
-               CameraSourceFeeder* cameraSource = static_cast<CameraSourceFeeder*>(user_data);
-               if (fps == 10) {
-                       std::cout << "Set desired camera preview fps: "  << fps << std::endl;
-                       camera_attr_set_preview_fps(cameraSource->_handle, fps);
-                       return false;
-               }
-               return true;
-       }
-public:
-       CameraSourceFeeder()
-                       : _mv3d(nullptr)
-                       , _deviceId(CAMERA_DEVICE_CAMERA3)
-                       , _handle(nullptr)
-       {
-               camera_create(_deviceId, &_handle);
-               camera_attr_foreach_supported_fps(_handle, _supported_preview_fps_cb, this);
-               if (!camera_is_supported_media_packet_preview_cb(_handle))
-                       throw std::runtime_error("not supported media packet preview cb");
-       }
-
-       ~CameraSourceFeeder()
-       {
+       if (_loop)
                stop();
+}
 
-               camera_destroy(_handle);
-               _handle = nullptr;
-       };
-
-       void start(std::shared_ptr<Mv3d> mv3d) override
-       {
-               _mv3d = mv3d.get();
-               camera_set_media_packet_preview_cb(_handle, _camera_preview_cb, this);
+void DfsApp::createDfs(std::shared_ptr<Mv3d> mv3d, std::unique_ptr<IFeeder> feeder)
+{
+       // Mv3d - mediavision dfs
+       _mv3d = mv3d;
+       _mv3d->prepare();
 
-               mv3d->resetTime();
-               camera_start_preview(_handle);
-       }
+       // loop
+       _loop = g_main_loop_new(nullptr, false);
 
-       void stop() override
-       {
-               camera_state_e state;
-               camera_get_state(_handle, &state);
-               if (state == CAMERA_STATE_PREVIEW)
-                       camera_stop_preview(_handle);
-       }
-};
+       // SourceFeeder
+       _feeder = std::move(feeder);
+}
 
-class FeederFactory
+void DfsApp::start()
 {
-private:
-       FeederFactory() = delete;
-       FeederFactory(const FeederFactory&) = delete;
-public:
-       static std::unique_ptr<IFeeder> createVisionSourceFeeder(int width=640, int height=400, int fps=10, int stereoFormat=STEREO_FORMAT_TOP_AND_BOTTOM)
-       {
-               return std::make_unique<VisionSourceFeeder>(width, height, fps, stereoFormat);
-       }
-
-       static std::unique_ptr<IFeeder> createCameraSourceFeeder()
-       {
-               return std::make_unique<CameraSourceFeeder>();
-       }
-};
+       _feeder->start(_mv3d);
+       g_main_loop_run(_loop);
+}
 
-class DfsApp
+void DfsApp::stop()
 {
-private:
-       GMainLoop *_loop;
-       std::unique_ptr<IFeeder> _feeder;
-       std::shared_ptr<Mv3d> _mv3d;
-public:
-       DfsApp() : _loop(nullptr) {}
+       g_main_loop_quit(_loop);
 
-       ~DfsApp()
-       {
-               if (_loop)
-                       stop();
+       if (_loop) {
+               g_main_loop_unref(_loop);
+               _loop = nullptr;
        }
 
-       void createDfs(int minDisparity, int maxDisparity, bool isAsync, std::string calibFilePath = "",
-                       int sourceSelection = VISION_SOURCE, int stereoFormat = STEREO_FORMAT_TOP_AND_BOTTOM,
-                       int sourceWidth = 640, int sourceHeight = 400, std::string depthFilePath = "")
-       {
-               // Mv3d - mediavision dfs
-               _mv3d = std::make_shared<Mv3d>(minDisparity, maxDisparity, isAsync, calibFilePath, sourceWidth, sourceHeight, stereoFormat, depthFilePath);
-               _mv3d->prepare();
+       _feeder->stop();
 
-               // loop
-               _loop = g_main_loop_new(nullptr, false);
-
-               // SourceFeeder
-               switch (sourceSelection) {
-               case VISION_SOURCE:
-                       _feeder = FeederFactory::createVisionSourceFeeder(sourceWidth, sourceHeight, 10, stereoFormat);
-                       break;
-               case CAMERA_SOURCE:
-                       _feeder = FeederFactory::createCameraSourceFeeder();
-                       break;
-               default:
-                       throw std::runtime_error("invalid source");
-               }
-       }
-
-       void start()
-       {
-               _feeder->start(_mv3d);
-               g_main_loop_run(_loop);
-       }
-
-       void stop()
-       {
-               g_main_loop_quit(_loop);
-
-               if (_loop) {
-                       g_main_loop_unref(_loop);
-                       _loop = nullptr;
-               }
-
-               _feeder->stop();
-
-               _mv3d->stop();
-       }
-
-       static void helper()
-       {
-               std::cout << "Usage:" << std::endl;
-               std::cout << "mv_depthstream_test_suite <isAsync> <minimum disparity search range> <maximum disparity search range>" << std::endl;
-               std::cout << "\t\t\t <width> <height> <stereo format> <source> <stereo calibration file path> <depth file path>" << std::endl;
-               std::cout << "\t isAsync: 0: mv_3d_run(), 1: mv_3d_run_async()" << std::endl;
-               std::cout << "\t stereo format: 1: side-by-side, 2: top-and-bottom" << std::endl;
-               std::cout << "\t source: 0: vision-source, 2: camera" << std::endl;
-               std::cout << "\t ex: mv_depthstream_test_suite 1 8 96 640 400 2 1 /usr/share/dfs-qcmv/stereoCalibDA.yaml /tmp/camerasource.png" << std::endl;
-               std::cout << "or simply run:" << std::endl;
-               std::cout << "mv_depthstream_test_suite <isAsync> <minimum disparity search range> <maximun disparity search range>" << std::endl;
-               std::cout << "\tex: mv_depthstream_test_suite 1 8 96" << std::endl;
-       }
+       _mv3d->stop();
+}
 
-};
+void DfsApp::helper()
+{
+       std::cout << "Usage:" << std::endl;
+       std::cout << "mv_depthstream_test_suite <isAsync> <minimum disparity search range> <maximum disparity search range>" << std::endl;
+       std::cout << "\t\t\t <width> <height> <stereo format> <source> <stereo calibration file path> <depth file path>" << std::endl;
+       std::cout << "\t isAsync: 0: mv_3d_run(), 1: mv_3d_run_async()" << std::endl;
+       std::cout << "\t stereo format: 1: side-by-side, 2: top-and-bottom" << std::endl;
+       std::cout << "\t source: 0: vision-source, 1: camera" << std::endl;
+       std::cout << "\t ex: mv_depthstream_test_suite 1 8 96 640 400 2 1 /usr/share/dfs-qcmv/stereoCalibDA.yaml /tmp/camerasource.png" << std::endl;
+       std::cout << "or simply run:" << std::endl;
+       std::cout << "mv_depthstream_test_suite <isAsync> <minimum disparity search range> <maximun disparity search range>" << std::endl;
+       std::cout << "\tex: mv_depthstream_test_suite 1 8 96" << std::endl;
+}
 
 static DfsApp gApp;
 
@@ -530,28 +156,46 @@ int main(int argc, char *argv[])
                bool isAsync = false;
                int minDisp = 8;
                int maxDisp = 96;
-
-               if (argc >= 4) {
+               int camWidth = 640;
+               int camHeight = 400;
+               int stereoFormat = STEREO_FORMAT_TOP_AND_BOTTOM;
+               int sourceSelection = VISION_SOURCE;
+               std::string stereoConfigFile;
+               std::string dispResultFile;
+
+               if (argc == 4) {
                        isAsync = (atoi(argv[1]) != 0); // 0: mv_3d_run(), 1: mv_3d_run_async()
                        minDisp = atoi(argv[2]); // 8
                        maxDisp = atoi(argv[3]); // 96
-               }
-
-               if (argc == 10) {
-                       int camWidth = atoi(argv[4]); // 640
-                       int camHeight = atoi(argv[5]); // 400
-                       int stereoFormat = atoi(argv[6]); // 1: SIDE_BY_SIDE, 2: STEREO_FORMAT_TOP_AND_BOTTOM
-                       int sourceSelection = (atoi(argv[7]) != 0); // 0: vision-source, 1: camera
-                       std::string stereoConfigFile = argv[8];
-                       std::string dispResultFile = argv[9];
-
-                       gApp.createDfs(minDisp, maxDisp, isAsync, stereoConfigFile, sourceSelection, stereoFormat, camWidth, camHeight, dispResultFile);
-               } else if (argc == 4) {
-                       gApp.createDfs(minDisp, maxDisp, isAsync);
+               } else if (argc == 10) {
+                       camWidth = atoi(argv[4]); // 640
+                       camHeight = atoi(argv[5]); // 400
+                       stereoFormat = atoi(argv[6]); // 1: SIDE_BY_SIDE, 2: STEREO_FORMAT_TOP_AND_BOTTOM
+                       sourceSelection = (atoi(argv[7]) != 0); // 0: vision-source, 1: camera
+                       stereoConfigFile = argv[8];
+                       dispResultFile = argv[9];
                } else {
                        gApp.helper();
                        return 0;
                }
+
+               std::unique_ptr<IFeeder> feeder;
+               switch (sourceSelection) {
+               case VISION_SOURCE:
+                       feeder = FeederFactory::createVisionSourceFeeder(camWidth, camHeight, 10, stereoFormat);
+                       break;
+               case CAMERA_SOURCE:
+                       feeder = FeederFactory::createCameraSourceFeeder();
+                       break;
+               default:
+                       throw std::runtime_error("invalid source");
+               }
+
+               std::shared_ptr<Mv3d> mv3d = std::make_shared<Mv3d>(minDisp, maxDisp, isAsync, stereoConfigFile, camWidth, camHeight, stereoFormat, dispResultFile);
+
+               // gApp.createDfs(mv3d, feeder);
+               gApp.createDfs(mv3d, std::move(feeder));
+
                signal(SIGINT, gSigHandler);
                gApp.start();
        } catch (const std::exception& e) {