18 #ifndef NVDS3D_GST_NVDS3D_PIPELINE_CONTEXT_H
19 #define NVDS3D_GST_NVDS3D_PIPELINE_CONTEXT_H
21 #include "gstnvdsmeta.h"
24 #include <ds3d/common/hpp/dataloader.hpp>
25 #include <ds3d/common/hpp/datamap.hpp>
26 #include <ds3d/common/hpp/frame.hpp>
27 #include <ds3d/common/hpp/yaml_config.hpp>
30 #include <ds3d/gst/nvds3d_gst_plugin.h>
31 #include <ds3d/gst/nvds3d_gst_ptr.h>
32 #include <ds3d/gst/nvds3d_meta.h>
35 namespace ds3d {
namespace gst {
46 GstPad* peer = gst_pad_get_peer(pad);
49 "send EOS downstream [elem:%s] skipped; not linked\n",
50 GST_ELEMENT_NAME(GST_ELEMENT(gst_pad_get_parent(pad))));
54 "sending EOS downstream [elem:%s->%s]\n", GST_ELEMENT_NAME(GST_ELEMENT(gst_pad_get_parent(pad))),
55 GST_ELEMENT_NAME(GST_ELEMENT(gst_pad_get_parent(peer))));
56 if (gst_pad_send_event(peer, gst_event_new_eos()) == FALSE) {
58 "send EOS downstream [elem:%s->%s] failed\n", GST_ELEMENT_NAME(GST_ELEMENT(gst_pad_get_parent(pad))),
59 GST_ELEMENT_NAME(GST_ELEMENT(gst_pad_get_parent(peer))));
61 gst_object_unref(peer);
101 runMainLoop(std::move(loopQuitCb)),
"failed to run main loop on the pipeline");
111 std::unique_lock<std::mutex> lock(
mutex());
112 if (!
_StatusCond.wait_for(lock, std::chrono::seconds(3), [
this]() {
113 return _mainStopped || _eosReceived;
115 LOG_DEBUG(
"waiting for EOS timed out, force to stop");
128 gst_bus_remove_watch(
bus());
140 std::unique_lock<std::mutex> locker(
mutex());
144 if (!g_main_loop_is_running(
mainLoop())) {
149 GstState state = GST_STATE_NULL;
150 GstState pending = GST_STATE_NULL;
151 GstStateChangeReturn ret = gst_element_get_state(
152 GST_ELEMENT(
pipeline()), &state, &pending,
153 (timeout ? timeout * 1000000 : GST_CLOCK_TIME_NONE));
157 while (ret == GST_STATE_CHANGE_FAILURE && times++ < 3) {
158 ret = gst_element_get_state(GST_ELEMENT(
pipeline()), &state, &pending, 0);
160 if (ret == GST_STATE_CHANGE_FAILURE) {
163 if (state == GST_STATE_PLAYING || pending == GST_STATE_PLAYING) {
171 std::unique_lock<std::mutex> locker(
mutex());
180 std::unique_lock<std::mutex> locker(
mutex());
182 if (
_StatusCond.wait_for(locker, std::chrono::milliseconds(3000)) ==
183 std::cv_status::timeout) {
184 LOG_DEBUG(
"waiting loop timed out, force loop to stop");
200 std::unique_lock<std::mutex> locker(
mutex());
214 LOG_WARNING(
"set pipeline state to GST_STATE_NULL failed");
216 GstState end = GST_STATE_NULL;
218 if (!
isGood(c) || end != GST_STATE_NULL) {
219 LOG_WARNING(
"waiting for pipeline state to null failed, force to quit");
223 c =
setState(each.get(), GST_STATE_NULL);
231 std::function<bool()>* f = (std::function<bool()>*)(user_data);
238 std::unique_lock<std::mutex> locker(
mutex());
241 "failed to run main loop due to loop might not set or thread already running.");
244 auto loopThread = std::make_unique<std::thread>([
this, quitCb = std::move(loopQuitCb)]() {
247 std::unique_lock<std::mutex> locker(
mutex());
254 std::atomic_bool loopStarted{
false};
255 std::function<bool()> loopCheck = [&loopStarted,
this]() ->
bool {
256 std::unique_lock<std::mutex> locker(
mutex());
265 if (!
_StatusCond.wait_for(locker, std::chrono::milliseconds(20000), [
this, &loopStarted]() {
266 return loopStarted || _mainStopped;
277 LOG_ERROR(
"Run main loop stopped too fast, please check.");
290 GstIterator* itr =
nullptr;
294 for (itr = gst_bin_iterate_sources(GST_BIN(
pipeline())); gst_iterator_next(itr, &data) == GST_ITERATOR_OK;) {
295 GstElement* elem = GST_ELEMENT_CAST(g_value_get_object(&data));
296 LOG_DEBUG(
"sending EOS downstream from src element %s\n", GST_ELEMENT_NAME(elem));
300 g_value_reset(&data);
302 g_value_unset(&data);
303 gst_iterator_free(itr);
314 virtual bool busCall(GstMessage* msg)
317 switch (GST_MESSAGE_TYPE(msg)) {
318 case GST_MESSAGE_EOS:
321 std::unique_lock<std::mutex> locker(
mutex());
329 case GST_MESSAGE_ERROR: {
330 gchar* debug =
nullptr;
331 GError* error =
nullptr;
332 gst_message_parse_error(msg, &error, &debug);
334 "ERROR from element %s: %s, details: %s", GST_OBJECT_NAME(msg->src), error->message,
335 (debug ? debug :
""));
342 case GST_MESSAGE_STATE_CHANGED: {
343 GstState oldState, newState, pendingState;
345 gst_message_parse_state_changed(msg, &oldState, &newState, &pendingState);
347 "Element %s changed state from %s to %s, pending: %s.", GST_OBJECT_NAME(msg->src),
348 gst_element_state_get_name(oldState), gst_element_state_get_name(newState),
349 gst_element_state_get_name(pendingState));
368 GstStateChangeReturn ret = gst_element_set_state(ele, state);
370 ret != GST_STATE_CHANGE_FAILURE,
ErrCode::kGst,
"element set state: %d failed", state);
377 GstElement* ele, GstState* state, GstState* pending =
nullptr,
size_t timeout = 0)
380 GstStateChangeReturn ret = gst_element_get_state(
381 ele, state, pending, (timeout ? timeout * 1000000 : GST_CLOCK_TIME_NONE));
383 case GST_STATE_CHANGE_FAILURE:
385 case GST_STATE_CHANGE_SUCCESS:
386 case GST_STATE_CHANGE_NO_PREROLL:
394 static gboolean
sBusCall(GstBus*
bus, GstMessage* msg, gpointer data)
398 return ctx->busCall(msg);
420 #endif // NVDS3D_GST_NVDS3D_PIPELINE_CONTEXT_H