From 49eb34a186a193d09ab044047ceffe4c64d6a4a3 Mon Sep 17 00:00:00 2001 From: rjhowell44 Date: Tue, 30 Jul 2024 08:24:09 -0700 Subject: [PATCH] Support/test new method to EOS pipeline on stop --- src/DslNodetr.h | 99 ++++++++++++++++++++++++++++++++- src/DslPipelineBintr.cpp | 9 ++- src/DslPipelineSourcesBintr.cpp | 7 ++- src/DslSourceBintr.cpp | 1 - 4 files changed, 109 insertions(+), 7 deletions(-) diff --git a/src/DslNodetr.h b/src/DslNodetr.h index 21fd512d..4c07943c 100644 --- a/src/DslNodetr.h +++ b/src/DslNodetr.h @@ -671,6 +671,101 @@ namespace DSL // call the parent class to complete the link-to-sink return Nodetr::LinkToSink(pMuxer); } + + /** + * @brief Sets the state of the Src to NULL and then sends flush-start, + * flush-stop, EOS events to the muxers Sink Pad connected to this GstNoder. + * @return true if able to successfully EOS the Sink Pad + */ + virtual bool NullSrcEosSinkMuxer() + { + LOG_FUNC(); + + if (!IsLinkedToSink()) + { + return false; + } + + GstState currState, nextState; + GstStateChangeReturn result = gst_element_get_state(GetGstElement(), + &currState, &nextState, 1); + + if (currState < GST_STATE_PLAYING) + { + LOG_ERROR("GstNodetr '" << GetName() + << "' is not in a PLAYING state"); + return false; + } + + // Get a reference to this GstNodetr's source pad + GstPad* pStaticSrcPad = gst_element_get_static_pad(GetGstElement(), "src"); + if (!pStaticSrcPad) + { + LOG_ERROR("Failed to get static source pad for GstNodetr '" + << GetName() << "'"); + return false; + } + + // Get a reference to the Muxer's sink pad that is connected + // to this GstNodetr's source pad + GstPad* pRequestedSinkPad = gst_pad_get_peer(pStaticSrcPad); + if (!pRequestedSinkPad) + { + LOG_ERROR("Failed to get requested sink pad peer for GstNodetr '" + << GetName() << "'"); + return false; + } + + GstStateChangeReturn changeResult = gst_element_set_state( + GetGstElement(), GST_STATE_NULL); + + switch (changeResult) + { + case GST_STATE_CHANGE_FAILURE: + LOG_ERROR("GstNodetr '" << GetName() + << "' failed to set state to NULL"); + return false; + + case GST_STATE_CHANGE_ASYNC: + LOG_INFO("GstNodetr '" << GetName() + << "' changing state to NULL async"); + + // block on get state until change completes. + if (gst_element_get_state(GetGstElement(), + NULL, NULL, GST_CLOCK_TIME_NONE) == GST_STATE_CHANGE_FAILURE) + { + LOG_ERROR("GstNodetr '" << GetName() + << "' failed to set state to NULL"); + return false; + } + // drop through on success - DO NOT BREAK + + case GST_STATE_CHANGE_SUCCESS: + LOG_INFO("GstNodetr '" << GetName() + << "' changed state to NULL successfully"); + + // Send flush-start and flush-stop events downstream to the muxer + // followed by an end-of-stream for this GstNodetr's stream + gst_pad_send_event(pRequestedSinkPad, + gst_event_new_flush_start()); + gst_pad_send_event(pRequestedSinkPad, + gst_event_new_flush_stop(TRUE)); + gst_pad_send_event(pRequestedSinkPad, + gst_event_new_eos()); + + break; + default: + LOG_ERROR("Unknown state change for Bintr '" << GetName() << "'"); + return false; + } + + // unreference both the static source pad and requested sink + gst_object_unref(pStaticSrcPad); + gst_object_unref(pRequestedSinkPad); + + // Call the parent class to complete the unlink from sink + return true; + } /** * @brief unlinks this Nodetr from a previously linked Muxer Sink Pad @@ -773,7 +868,7 @@ namespace DSL gst_object_unref(pRequestedSinkPad); // Call the parent class to complete the unlink from sink - return Nodetr::UnlinkFromSink(); + return Nodetr::UnlinkFromSink(); } /** @@ -947,7 +1042,7 @@ namespace DSL bool SendEos() { LOG_FUNC(); - + return gst_element_send_event(GetGstElement(), gst_event_new_eos()); } diff --git a/src/DslPipelineBintr.cpp b/src/DslPipelineBintr.cpp index 7b07a0ec..23212647 100644 --- a/src/DslPipelineBintr.cpp +++ b/src/DslPipelineBintr.cpp @@ -516,8 +516,15 @@ namespace DSL { m_eosFlag = true; - // Send an EOS event to the Pipline bin. + // IMPORTANT! There are two methods to send the EOS event. + // The best method is still under investigation. Only call one. + + // 1. Send the event to the Pipeline bin SendEos(); + + // 2. Send the event to each Streammuxer sink pads connected + // to a Source component. + // m_pPipelineSourcesBintr->EosAll(); // once the EOS event has been received on all sink pads of all // elements, an EOS message will be posted on the bus. We need to diff --git a/src/DslPipelineSourcesBintr.cpp b/src/DslPipelineSourcesBintr.cpp index 1698d693..b6c8912a 100644 --- a/src/DslPipelineSourcesBintr.cpp +++ b/src/DslPipelineSourcesBintr.cpp @@ -405,9 +405,10 @@ namespace DSL // Send EOS message to each source object. for (auto const& imap: m_pChildSources) { - LOG_INFO("Sending EOS message to Source " << imap.second->GetName()); - gst_element_send_event(imap.second->GetGstElement(), - gst_event_new_eos()); + LOG_INFO("Sending EOS for Source " << imap.second->GetName()); + imap.second->NullSrcEosSinkMuxer(); + // gst_element_send_event(imap.second->GetGstElement(), + // gst_event_new_eos()); } } diff --git a/src/DslSourceBintr.cpp b/src/DslSourceBintr.cpp index 52950387..75fcb7f4 100644 --- a/src/DslSourceBintr.cpp +++ b/src/DslSourceBintr.cpp @@ -3520,7 +3520,6 @@ namespace DSL } m_pDepay->UnlinkFromSink(); m_pParser->UnlinkFromSink(); - m_pDecoder->UnlinkFromSink(); UnlinkCommon(); } m_isLinked = false;