// Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef MEDIAFRAMEINPUTQUEUE_H #define MEDIAFRAMEINPUTQUEUE_H #include #include #include #include #include #include struct AudioBufferInputQueueTraits { using MediaFrame = QAudioBuffer; using MediaFrameInput = QAudioBufferInput; static constexpr auto sendMediaFrame = &QAudioBufferInput::sendAudioBuffer; static constexpr auto readyToSend = &QAudioBufferInput::readyToSendAudioBuffer; static constexpr char name[] = "audio"; }; struct VideoFrameInputQueueTraits { using MediaFrame = QVideoFrame; using MediaFrameInput = QVideoFrameInput; static constexpr auto sendMediaFrame = &QVideoFrameInput::sendVideoFrame; static constexpr auto readyToSend = &QVideoFrameInput::readyToSendVideoFrame; static constexpr char name[] = "video"; }; template class MediaFrameInputQueue { public: MediaFrameInputQueue(size_t maxQueueSize = 5) : m_maxQueueSize(maxQueueSize) { QObject::connect(&m_input, Traits::readyToSend, &m_input, [this]() { while (!m_queue.empty() && (m_input.*Traits::sendMediaFrame)(m_queue.front())) m_queue.pop(); }); } auto *mediaFrameInput() { return &m_input; } void pushMediaFrame(const typename Traits::MediaFrame &mediaFrame) { const bool sent = m_queue.empty() && (m_input.*Traits::sendMediaFrame)(mediaFrame); if (!sent) { if (m_queue.size() < m_maxQueueSize) m_queue.push(mediaFrame); else qWarning() << "Drop" << Traits::name << "frame with startTime" << mediaFrame.startTime() / 1000 << "ms"; } } private: typename Traits::MediaFrameInput m_input; std::queue m_queue; size_t m_maxQueueSize; }; #endif // MEDIAFRAMEINPUTQUEUE_H