GstEnginePipeline: Make sure all set states are finished before finishing pipeline

This commit is contained in:
Jonas Kvinge
2025-01-05 18:58:03 +01:00
parent be8097919b
commit 7afae70bb0
2 changed files with 24 additions and 4 deletions

View File

@@ -174,7 +174,9 @@ GstEnginePipeline::GstEnginePipeline(QObject *parent)
logged_unsupported_analyzer_format_(false), logged_unsupported_analyzer_format_(false),
about_to_finish_(false), about_to_finish_(false),
finish_requested_(false), finish_requested_(false),
finished_(false) { finished_(false),
set_state_in_progress_(0),
set_state_async_in_progress_(0) {
eq_band_gains_.reserve(kEqBandCount); eq_band_gains_.reserve(kEqBandCount);
for (int i = 0; i < kEqBandCount; ++i) eq_band_gains_ << 0; for (int i = 0; i < kEqBandCount; ++i) eq_band_gains_ << 0;
@@ -419,7 +421,7 @@ bool GstEnginePipeline::Finish() {
Disconnect(); Disconnect();
if (IsStateNull()) { if (IsStateNull() && set_state_async_in_progress_ == 0 && set_state_in_progress_ == 0) {
finished_ = true; finished_ = true;
} }
else { else {
@@ -1792,7 +1794,17 @@ bool GstEnginePipeline::IsStateNull() const {
void GstEnginePipeline::SetStateAsync(const GstState state) { void GstEnginePipeline::SetStateAsync(const GstState state) {
QMetaObject::invokeMethod(this, "SetState", Qt::QueuedConnection, Q_ARG(GstState, state)); ++set_state_async_in_progress_;
QMetaObject::invokeMethod(this, "SetStateAsyncSlot", Qt::QueuedConnection, Q_ARG(GstState, state));
}
void GstEnginePipeline::SetStateAsyncSlot(const GstState state) {
--set_state_async_in_progress_;
SetState(state);
} }
@@ -1800,6 +1812,8 @@ QFuture<GstStateChangeReturn> GstEnginePipeline::SetState(const GstState state)
qLog(Debug) << "Setting pipeline" << id() << "state to" << GstStateText(state); qLog(Debug) << "Setting pipeline" << id() << "state to" << GstStateText(state);
++set_state_in_progress_;
QFutureWatcher<GstStateChangeReturn> *watcher = new QFutureWatcher<GstStateChangeReturn>(); QFutureWatcher<GstStateChangeReturn> *watcher = new QFutureWatcher<GstStateChangeReturn>();
QObject::connect(watcher, &QFutureWatcher<GstStateChangeReturn>::finished, this, [this, watcher, state]() { QObject::connect(watcher, &QFutureWatcher<GstStateChangeReturn>::finished, this, [this, watcher, state]() {
const GstStateChangeReturn state_change_return = watcher->result(); const GstStateChangeReturn state_change_return = watcher->result();
@@ -1815,13 +1829,15 @@ QFuture<GstStateChangeReturn> GstEnginePipeline::SetState(const GstState state)
void GstEnginePipeline::SetStateFinishedSlot(const GstState state, const GstStateChangeReturn state_change_return) { void GstEnginePipeline::SetStateFinishedSlot(const GstState state, const GstStateChangeReturn state_change_return) {
--set_state_in_progress_;
switch (state_change_return) { switch (state_change_return) {
case GST_STATE_CHANGE_SUCCESS: case GST_STATE_CHANGE_SUCCESS:
case GST_STATE_CHANGE_ASYNC: case GST_STATE_CHANGE_ASYNC:
case GST_STATE_CHANGE_NO_PREROLL: case GST_STATE_CHANGE_NO_PREROLL:
qLog(Debug) << "Pipeline" << id() << "state successfully set to" << GstStateText(state); qLog(Debug) << "Pipeline" << id() << "state successfully set to" << GstStateText(state);
Q_EMIT SetStateFinished(state_change_return); Q_EMIT SetStateFinished(state_change_return);
if (!finished_.value() && finish_requested_.value()) { if (!finished_.value() && finish_requested_.value() && set_state_async_in_progress_ == 0 && set_state_in_progress_ == 0) {
finished_ = true; finished_ = true;
Q_EMIT Finished(); Q_EMIT Finished();
} }

View File

@@ -197,6 +197,7 @@ class GstEnginePipeline : public QObject {
void ProcessPendingSeek(const GstState state); void ProcessPendingSeek(const GstState state);
private Q_SLOTS: private Q_SLOTS:
void SetStateAsyncSlot(const GstState state);
void SetStateFinishedSlot(const GstState state, const GstStateChangeReturn state_change_return); void SetStateFinishedSlot(const GstState state, const GstStateChangeReturn state_change_return);
void SetFaderVolume(const qreal volume); void SetFaderVolume(const qreal volume);
void FaderTimelineStateChanged(const QTimeLine::State state); void FaderTimelineStateChanged(const QTimeLine::State state);
@@ -368,6 +369,9 @@ class GstEnginePipeline : public QObject {
mutex_protected<bool> about_to_finish_; mutex_protected<bool> about_to_finish_;
mutex_protected<bool> finish_requested_; mutex_protected<bool> finish_requested_;
mutex_protected<bool> finished_; mutex_protected<bool> finished_;
mutex_protected<int> set_state_in_progress_;
mutex_protected<int> set_state_async_in_progress_;
}; };
using GstEnginePipelinePtr = SharedPtr<GstEnginePipeline>; using GstEnginePipelinePtr = SharedPtr<GstEnginePipeline>;