NVIDIA DeepStream SDK API Reference

6.4 Release
deepstream_can_context_priv.hpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #ifndef DS_APP_DEEPSTREAM_CAN_CONTEXT_PRIV_H
25 #define DS_APP_DEEPSTREAM_CAN_CONTEXT_PRIV_H
26 
28 #include <future>
29 
30 #include <cuda_runtime_api.h>
31 
32 #undef DS_CAN_FPS_INTERVAL
33 #define DS_CAN_FPS_INTERVAL 30
34 
36 public:
38  virtual ~Ds3dAppContext() { deinit(); }
39 
40  void setMainloop(GMainLoop* loop) { _mainLoop.reset(loop); }
41 
42  ErrCode init(const std::string& name)
43  {
44  int curDev = -1;
45  cudaGetDevice(&curDev);
46  struct cudaDeviceProp gpuProp;
47  cudaGetDeviceProperties(&gpuProp, curDev);
48  _isdGPU = (gpuProp.integrated ? false : true);
49 
52  _pipeline.reset(gst_pipeline_new(name.c_str()));
53  DS3D_FAILED_RETURN(pipeline(), ErrCode::kGst, "create pipeline: %s failed", name.c_str());
54  _pipeline.setName(name);
55  _bus.reset(gst_pipeline_get_bus(pipeline()));
56  DS3D_FAILED_RETURN(bus(), ErrCode::kGst, "get bus from pipeline: %s failed", name.c_str());
57  _busWatchId = gst_bus_add_watch(bus(), sBusCall, this);
58  return ErrCode::kGood;
59  }
60 
62  {
65  gst_bin_add(GST_BIN(pipeline()), ele.copy()), ErrCode::kGst, "add element failed");
66  _elementList.emplace_back(ele);
67  return *this;
68  }
69 
71  {
73  {
74  std::unique_lock<std::mutex> locker(mutex());
75  _eosReceived = false;
76  }
77  auto c = setPipelineState(GST_STATE_PLAYING);
78  return c;
79  }
80 
81  virtual ErrCode stop()
82  {
84  ErrCode c = setPipelineState(GST_STATE_NULL);
85  if (!isGood(c)) {
86  LOG_WARNING("set pipeline state to GST_STATE_NULL failed");
87  }
88  if (!isGood(c)) {
89  LOG_WARNING("set pipeline state to GST_STATE_NULL failed");
90  }
91  GstState end = GST_STATE_NULL;
92  c = getState(_pipeline.get(), &end, nullptr, 3000);
93  if (!isGood(c) || end != GST_STATE_NULL) {
94  LOG_WARNING("waiting for pipeline state to null failed, force to quit");
95  }
96  for (auto& each : _elementList) {
97  if (each) {
98  c = setState(each.get(), GST_STATE_NULL);
99  }
100  }
101  return c;
102  }
103 
104  /* timeout: milliseconds, 0 means never timeout */
105  bool isRunning(size_t timeout = 0)
106  {
107  std::unique_lock<std::mutex> locker(mutex());
108  if (!mainLoop() || !pipeline() || _mainStopped || _eosReceived) {
109  return false;
110  }
111  locker.unlock();
112 
113  GstState state = GST_STATE_NULL;
114  GstState pending = GST_STATE_NULL;
115  GstStateChangeReturn ret = gst_element_get_state(
116  GST_ELEMENT(pipeline()), &state, &pending,
117  (timeout ? timeout * 1000000 : GST_CLOCK_TIME_NONE));
118 
119  // basler camera has change state issue, try multi-times
120  uint32_t times = 1;
121  while (ret == GST_STATE_CHANGE_FAILURE && times++ < 3) {
122  ret = gst_element_get_state(GST_ELEMENT(pipeline()), &state, &pending, 0);
123  }
124  if (ret == GST_STATE_CHANGE_FAILURE) {
125  return false;
126  }
127  if (state == GST_STATE_PLAYING || pending == GST_STATE_PLAYING) {
128  return true;
129  }
130  return false;
131  }
132 
134  {
135  std::unique_lock<std::mutex> locker(mutex());
136  if (mainLoop()) {
137  g_main_loop_quit(mainLoop());
138  }
139  }
140 
142  {
143  std::unique_lock<std::mutex> locker(mutex());
144  if (mainLoop() && !_mainStopped && _mainLoopThread) {
145  _stoppedCond.wait_for(
146  locker, std::chrono::milliseconds(100), [this]() { return _mainStopped; });
147  }
148  _mainStopped = true;
149  if (_mainLoopThread) {
150  auto swapThread = std::move(_mainLoopThread);
151  _mainLoopThread.reset();
152  locker.unlock();
153  swapThread->join();
154  }
155  }
156 
157  void runMainLoop(std::function<void()> loopQuitCb)
158  {
159  std::unique_lock<std::mutex> locker(mutex());
160  if (mainLoop() && !_mainLoopThread) {
161  _mainStopped = false;
162  _mainLoopThread = std::make_unique<std::thread>([this, cb = std::move(loopQuitCb)]() {
163  g_main_loop_run(mainLoop());
164  cb();
165  std::unique_lock<std::mutex> locker(mutex());
166  _mainStopped = true;
167  _stoppedCond.notify_all();
168  });
170  }
171  }
172 
173  virtual void deinit()
174  {
175  if (bus()) {
176  gst_bus_remove_watch(bus());
177  }
178  _bus.reset();
179  _pipeline.reset();
180  _elementList.clear();
181  _mainLoop.reset();
182  }
183 
185  {
187  gst_element_send_event(GST_ELEMENT(pipeline()), gst_event_new_eos()), ErrCode::kGst,
188  "send EOS failed");
189  return ErrCode::kGood;
190  }
191 
192  GstPipeline* pipeline() const { return GST_PIPELINE_CAST(_pipeline.get()); }
193  GstBus* bus() const { return _bus.get(); }
194  GMainLoop* mainLoop() const { return _mainLoop.get(); }
195 
196 private:
197  // no need to free msg
198  virtual bool busCall(GstMessage* msg) = 0;
199 
200 protected:
201  ErrCode setPipelineState(GstState state)
202  {
204  return setState(_pipeline.get(), state);
205  }
206 
207  ErrCode setState(GstElement* ele, GstState state)
208  {
209  DS_ASSERT(ele);
210  GstStateChangeReturn ret = gst_element_set_state(ele, state);
212  ret != GST_STATE_CHANGE_FAILURE, ErrCode::kGst, "element set state: %d failed", state);
213  return ErrCode::kGood;
214  }
215  /* get element states. timeout in milliseconds.
216  */
218  GstElement* ele, GstState* state, GstState* pending = nullptr, size_t timeout = 0)
219  {
220  DS_ASSERT(ele);
221  GstStateChangeReturn ret = gst_element_get_state(
222  ele, state, pending, (timeout ? timeout * 1000000 : GST_CLOCK_TIME_NONE));
223  switch (ret) {
224  case GST_STATE_CHANGE_FAILURE:
225  return ErrCode::kGst;
226  case GST_STATE_CHANGE_SUCCESS:
227  case GST_STATE_CHANGE_NO_PREROLL:
228  return ErrCode::kGood;
229  default:
230  return ErrCode::kUnknown;
231  }
232  return ErrCode::kGood;
233  }
234 
235  static gboolean sBusCall(GstBus* bus, GstMessage* msg, gpointer data)
236  {
237  Ds3dAppContext* ctx = static_cast<Ds3dAppContext*>(data);
238  DS_ASSERT(ctx->bus() == bus);
239  return ctx->busCall(msg);
240  }
241 
242  std::mutex& mutex() const { return _streamMutex; }
243 
244  // members
247  uint32_t _busWatchId = 0;
248  std::vector<gst::ElePtr> _elementList;
249  ds3d::UniqPtr<GMainLoop> _mainLoop{nullptr, g_main_loop_unref};
250  bool _eosAutoQuit = false;
251  std::unique_ptr<std::thread> _mainLoopThread;
252  bool _mainStopped = false;
253  bool _eosReceived = false;
254  mutable std::mutex _streamMutex;
255  std::condition_variable _stoppedCond;
256  bool _isdGPU = true;
258 };
259 
260 class CameraCanApp : public Ds3dAppContext {
261 public:
262  CameraCanApp() = default;
264 
265  void setConfig(const NvDsCanContextConfig& config) { _config = config; }
266  const NvDsCanContextConfig& config() const { return _config; }
267 
269 
270  ErrCode stop() override;
271 
272  void deinit() override
273  {
275  _src.reset();
276  _appsrcFrameIdx = 0;
277  }
278 
280  const NvDsCanContextFrame* frame, std::function<void(GstBuffer*)> callback);
281 
282  NvDsCanSrcType srcType() const { return _config.srcType; }
283 
284  static GstPadProbeReturn lastSinkBufferProbe(
285  GstPad* pad, GstPadProbeInfo* info, gpointer udata);
286  static GstPadProbeReturn processedBufferProbe(
287  GstPad* pad, GstPadProbeInfo* info, gpointer udata);
288 
289 private:
290  bool busCall(GstMessage* msg) final;
291  void outputBuffer(GstBuffer* buf);
292  void visualMetaUpdate(GstBuffer* buf);
293  void printOutputResult(GstBuffer* buf);
294 
295  gst::ElePtr createAppSrc(const NvDsCanFrameInfo& info);
296  gst::ElePtr createSourceBin(const std::string& uri);
297  gst::ElePtr createCameraSrc(const NvDsCanCameraInfo& conf);
298  gst::ElePtr createSink();
299 
300 private:
301  NvDsCanContextConfig _config;
302  gst::ElePtr _src;
303  std::function<void(GstBuffer* buf)> _outputCallback = nullptr;
304  uint64_t _appsrcFrameIdx = 0;
306  uint64_t _bufId = 0;
307 };
308 
309 #endif // DS_APP_DEEPSTREAM_CAN_CONTEXT_PRIV_H
ds3d::isGood
bool isGood(ErrCode c)
Definition: func_utils.h:28
Ds3dAppContext::quitMainLoop
void quitMainLoop()
Definition: deepstream_can_context_priv.hpp:133
Ds3dAppContext::_mainLoop
ds3d::UniqPtr< GMainLoop > _mainLoop
Definition: deepstream_can_context_priv.hpp:249
Ds3dAppContext::mainLoop
GMainLoop * mainLoop() const
Definition: deepstream_can_context_priv.hpp:194
CameraCanApp::setConfig
void setConfig(const NvDsCanContextConfig &config)
Definition: deepstream_can_context_priv.hpp:265
CameraCanApp::config
const NvDsCanContextConfig & config() const
Definition: deepstream_can_context_priv.hpp:266
Ds3dAppContext::bus
GstBus * bus() const
Definition: deepstream_can_context_priv.hpp:193
CameraCanApp::~CameraCanApp
~CameraCanApp()
Definition: deepstream_can_context_priv.hpp:263
NvDsCanContextFrame
Definition: deepstream_can_context.hpp:53
Ds3dAppContext
Definition: deepstream_can_context_priv.hpp:35
ds3d::UniqPtr
std::unique_ptr< T, std::function< void(T *)> > UniqPtr
Definition: obj.hpp:31
DS_ASSERT
#define DS_ASSERT(...)
Definition: defines.h:31
Ds3dAppContext::setState
ErrCode setState(GstElement *ele, GstState state)
Definition: deepstream_can_context_priv.hpp:207
Ds3dAppContext::runMainLoop
void runMainLoop(std::function< void()> loopQuitCb)
Definition: deepstream_can_context_priv.hpp:157
DS_CAN_FPS_INTERVAL
#define DS_CAN_FPS_INTERVAL
Definition: deepstream_can_context_priv.hpp:33
LOG_WARNING
#define LOG_WARNING
Definition: logging.h:18
Ds3dAppContext::mutex
std::mutex & mutex() const
Definition: deepstream_can_context_priv.hpp:242
Ds3dAppContext::_elementList
std::vector< gst::ElePtr > _elementList
Definition: deepstream_can_context_priv.hpp:248
ds3d::gst::GstPtr
Definition: nvds3d_gst_ptr.h:54
NvDsCanFrameInfo
Definition: deepstream_can_context.hpp:71
Ds3dAppContext::waitLoopQuit
void waitLoopQuit()
Definition: deepstream_can_context_priv.hpp:141
Ds3dAppContext::~Ds3dAppContext
virtual ~Ds3dAppContext()
Definition: deepstream_can_context_priv.hpp:38
Ds3dAppContext::_eosReceived
bool _eosReceived
Definition: deepstream_can_context_priv.hpp:253
Ds3dAppContext::_isdGPU
bool _isdGPU
Definition: deepstream_can_context_priv.hpp:256
ds3d::gst::ElePtr
Definition: nvds3d_gst_ptr.h:150
Ds3dAppContext::play
ErrCode play()
Definition: deepstream_can_context_priv.hpp:70
CameraCanApp::processFrame
ErrCode processFrame(const NvDsCanContextFrame *frame, std::function< void(GstBuffer *)> callback)
Ds3dAppContext::isRunning
bool isRunning(size_t timeout=0)
Definition: deepstream_can_context_priv.hpp:105
Ds3dAppContext::_pipeline
gst::ElePtr _pipeline
Definition: deepstream_can_context_priv.hpp:245
Ds3dAppContext::add
Ds3dAppContext & add(const gst::ElePtr &ele)
Definition: deepstream_can_context_priv.hpp:61
ds3d::ErrCode
ErrCode
Definition: common.h:43
ds3d::gst::GstPtr::setName
void setName(const std::string &name)
Definition: nvds3d_gst_ptr.h:68
Ds3dAppContext::_bus
gst::BusPtr _bus
Definition: deepstream_can_context_priv.hpp:246
deepstream_can_context.hpp
Ds3dAppContext::_stoppedCond
std::condition_variable _stoppedCond
Definition: deepstream_can_context_priv.hpp:255
CameraCanApp::deinit
void deinit() override
Definition: deepstream_can_context_priv.hpp:272
ds3d::gst::GstPtr::copy
GstObjT * copy() const
Definition: nvds3d_gst_ptr.h:98
Ds3dAppContext::_mainStopped
bool _mainStopped
Definition: deepstream_can_context_priv.hpp:252
ds3d::gst::GstPtr::get
GstObjT * get() const
Definition: nvds3d_gst_ptr.h:110
Ds3dAppContext::deinit
virtual void deinit()
Definition: deepstream_can_context_priv.hpp:173
CameraCanApp::buildPipeline
ErrCode buildPipeline()
NvDsCanCameraInfo
Definition: deepstream_can_context.hpp:77
CameraCanApp::srcType
NvDsCanSrcType srcType() const
Definition: deepstream_can_context_priv.hpp:282
CameraCanApp::stop
ErrCode stop() override
Ds3dAppContext::_eosAutoQuit
bool _eosAutoQuit
Definition: deepstream_can_context_priv.hpp:250
DS3D_THROW_ERROR
#define DS3D_THROW_ERROR(statement, code, msg)
Definition: defines.h:78
CameraCanApp::processedBufferProbe
static GstPadProbeReturn processedBufferProbe(GstPad *pad, GstPadProbeInfo *info, gpointer udata)
Ds3dAppContext::sendEOS
ErrCode sendEOS()
Definition: deepstream_can_context_priv.hpp:184
ds3d::profiling::FpsCalculation
Definition: profiling.hpp:23
CameraCanApp
Definition: deepstream_can_context_priv.hpp:260
NvDsCanSrcType
NvDsCanSrcType
Definition: deepstream_can_context.hpp:64
Ds3dAppContext::pipeline
GstPipeline * pipeline() const
Definition: deepstream_can_context_priv.hpp:192
Ds3dAppContext::sBusCall
static gboolean sBusCall(GstBus *bus, GstMessage *msg, gpointer data)
Definition: deepstream_can_context_priv.hpp:235
CameraCanApp::lastSinkBufferProbe
static GstPadProbeReturn lastSinkBufferProbe(GstPad *pad, GstPadProbeInfo *info, gpointer udata)
GstBuffer
struct _GstBuffer GstBuffer
Definition: idatatype.h:19
Ds3dAppContext::setPipelineState
ErrCode setPipelineState(GstState state)
Definition: deepstream_can_context_priv.hpp:201
Ds3dAppContext::_mainLoopThread
std::unique_ptr< std::thread > _mainLoopThread
Definition: deepstream_can_context_priv.hpp:251
DS3D_FAILED_RETURN
#define DS3D_FAILED_RETURN(condition, ret, fmt,...)
Definition: defines.h:64
NvDsCanContextConfig
Definition: deepstream_can_context.hpp:85
Ds3dAppContext::getState
ErrCode getState(GstElement *ele, GstState *state, GstState *pending=nullptr, size_t timeout=0)
Definition: deepstream_can_context_priv.hpp:217
CameraCanApp::CameraCanApp
CameraCanApp()=default
Ds3dAppContext::DS3D_DISABLE_CLASS_COPY
DS3D_DISABLE_CLASS_COPY(Ds3dAppContext)
NvDsCanContextConfig::srcType
NvDsCanSrcType srcType
Definition: deepstream_can_context.hpp:86
Ds3dAppContext::Ds3dAppContext
Ds3dAppContext()
Definition: deepstream_can_context_priv.hpp:37
ds3d::gst::GstPtr::reset
void reset(GstObjT *obj=nullptr, bool takeOwner=true)
Definition: nvds3d_gst_ptr.h:89
Ds3dAppContext::_streamMutex
std::mutex _streamMutex
Definition: deepstream_can_context_priv.hpp:254
Ds3dAppContext::_busWatchId
uint32_t _busWatchId
Definition: deepstream_can_context_priv.hpp:247
Ds3dAppContext::stop
virtual ErrCode stop()
Definition: deepstream_can_context_priv.hpp:81
Ds3dAppContext::init
ErrCode init(const std::string &name)
Definition: deepstream_can_context_priv.hpp:42
Ds3dAppContext::setMainloop
void setMainloop(GMainLoop *loop)
Definition: deepstream_can_context_priv.hpp:40