Skip to content

Commit

Permalink
Prettify logic of stopping and deleting encoding threads
Browse files Browse the repository at this point in the history
Let's use unique_ptr with a custom deleter instead of
manual invoking.
No functional changes.

Pick-to: 6.8
Change-Id: I6ce9e496afe6a5f2a890ce78fbc260fb6a6cc443
Reviewed-by: Tim Blechmann <[email protected]>
Reviewed-by: Artem Dyomin <[email protected]>
  • Loading branch information
Artemiy-d committed Oct 5, 2024
1 parent dd3338c commit 62022d5
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 17 deletions.
10 changes: 8 additions & 2 deletions src/plugins/multimedia/ffmpeg/qffmpegthread_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,17 @@ namespace QFFmpeg
class ConsumerThread : public QThread
{
public:
struct Deleter
{
void operator()(ConsumerThread *thread) const { thread->stopAndDelete(); }
};

protected:
/*!
Stops the thread and deletes this object
*/
void stopAndDelete();

protected:

/*!
Called on this thread when thread starts
*/
Expand Down Expand Up @@ -89,6 +93,8 @@ class ConsumerThread : public QThread
bool m_exit = false;
};

template <typename T>
using ConsumerThreadUPtr = std::unique_ptr<T, ConsumerThread::Deleter>;
}

QT_END_NAMESPACE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ AudioEncoder *RecordingEngine::createAudioEncoder(const QAudioFormat &format)

auto audioEncoder = new AudioEncoder(*this, format, m_settings);

m_audioEncoders.push_back(audioEncoder);
m_audioEncoders.emplace_back(audioEncoder);
connect(audioEncoder, &EncoderThread::endOfSourceStream, this,
&RecordingEngine::handleSourceEndOfStream);
connect(audioEncoder, &EncoderThread::initialized, this,
Expand Down Expand Up @@ -125,7 +125,7 @@ void RecordingEngine::addVideoSource(QPlatformVideoSource *source, const QVideoF
<< "ffmpegHWPixelFormat=" << (hwPixelFormat ? *hwPixelFormat : AV_PIX_FMT_NONE);

auto videoEncoder = new VideoEncoder(*this, m_settings, frameFormat, hwPixelFormat);
m_videoEncoders.append(videoEncoder);
m_videoEncoders.emplace_back(videoEncoder);
if (m_autoStop)
videoEncoder->setAutoStop(true);

Expand Down Expand Up @@ -181,8 +181,9 @@ RecordingEngine::EncodingFinalizer::EncodingFinalizer(RecordingEngine &recording

void RecordingEngine::EncodingFinalizer::run()
{
m_recordingEngine.forEachEncoder(&EncoderThread::stopAndDelete);
m_recordingEngine.m_muxer->stopAndDelete();
Q_ASSERT(m_recordingEngine.m_state == State::Finalization);

m_recordingEngine.stopAndDeleteThreads();

const bool headerWritten = m_previousState == State::Encoding;
if (headerWritten) {
Expand Down Expand Up @@ -298,19 +299,26 @@ void RecordingEngine::handleEncoderInitialization()
forEachEncoder(&EncoderThread::startEncoding, true);
}

void RecordingEngine::stopAndDeleteThreads()
{
m_audioEncoders.clear();
m_videoEncoders.clear();
m_muxer.reset();
}

template <typename F, typename... Args>
void RecordingEngine::forEachEncoder(F &&f, Args &&...args)
{
for (AudioEncoder *audioEncoder : m_audioEncoders)
std::invoke(f, audioEncoder, args...);
for (VideoEncoder *videoEncoder : m_videoEncoders)
std::invoke(f, videoEncoder, args...);
for (auto &audioEncoder : m_audioEncoders)
std::invoke(f, audioEncoder.get(), args...);
for (auto &videoEncoder : m_videoEncoders)
std::invoke(f, videoEncoder.get(), args...);
}

template <typename F>
bool RecordingEngine::allOfEncoders(F &&f) const
{
auto predicate = [&f](const EncoderThread *encoder) { return std::invoke(f, encoder); };
auto predicate = [&f](const auto &encoder) { return std::invoke(f, encoder.get()); };

return std::all_of(m_audioEncoders.cbegin(), m_audioEncoders.cend(), predicate)
&& std::all_of(m_videoEncoders.cbegin(), m_videoEncoders.cend(), predicate);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class RecordingEngine : public QObject

void setMetaData(const QMediaMetaData &metaData);
AVFormatContext *avFormatContext() { return m_formatContext->avFormatContext(); }
Muxer *getMuxer() { return m_muxer; }
Muxer *getMuxer() { return m_muxer.get(); }

bool isEndOfSourceStreams() const;

Expand Down Expand Up @@ -104,7 +104,9 @@ public Q_SLOTS:

void handleFormatsInitialization();

qsizetype encodersCount() const { return m_audioEncoders.size() + m_videoEncoders.size(); }
size_t encodersCount() const { return m_audioEncoders.size() + m_videoEncoders.size(); }

void stopAndDeleteThreads();

template <typename F, typename... Args>
void forEachEncoder(F &&f, Args &&...args);
Expand All @@ -116,17 +118,17 @@ public Q_SLOTS:
QMediaEncoderSettings m_settings;
QMediaMetaData m_metaData;
std::unique_ptr<EncodingFormatContext> m_formatContext;
Muxer *m_muxer = nullptr;
ConsumerThreadUPtr<Muxer> m_muxer;

QList<AudioEncoder *> m_audioEncoders;
QList<VideoEncoder *> m_videoEncoders;
std::vector<ConsumerThreadUPtr<AudioEncoder>> m_audioEncoders;
std::vector<ConsumerThreadUPtr<VideoEncoder>> m_videoEncoders;
std::unique_ptr<EncodingInitializer> m_formatsInitializer;

QMutex m_timeMutex;
qint64 m_timeRecorded = 0;

bool m_autoStop = false;
qsizetype m_initializedEncodersCount = 0;
size_t m_initializedEncodersCount = 0;
State m_state = State::None;
};

Expand Down

0 comments on commit 62022d5

Please sign in to comment.