File indexing completed on 2025-01-19 03:57:05

0001 /*********************************************************
0002  * Copyright (C) 2020, Val Doroshchuk <valbok@gmail.com> *
0003  *                                                       *
0004  * This file is part of QtAVPlayer.                      *
0005  * Free Qt Media Player based on FFmpeg.                 *
0006  *********************************************************/
0007 
0008 #ifndef QAVPACKETQUEUE_H
0009 #define QAVPACKETQUEUE_H
0010 
0011 //
0012 //  W A R N I N G
0013 //  -------------
0014 //
0015 // This file is not part of the Qt API. It exists purely as an
0016 // implementation detail. This header file may change from version to
0017 // version without notice, or even be removed.
0018 //
0019 // We mean it.
0020 //
0021 
0022 #include "qavpacket_p.h"
0023 #include "qavfilter_p.h"
0024 #include "qavfiltergraph_p.h"
0025 #include "qavframe.h"
0026 #include "qavsubtitleframe.h"
0027 #include "qavstreamframe.h"
0028 #include "qavdemuxer_p.h"
0029 #include <QMutex>
0030 #include <QWaitCondition>
0031 #include <QList>
0032 #include <math.h>
0033 #include <memory>
0034 
0035 extern "C" {
0036 #include <libavutil/time.h>
0037 #include <libavcodec/avcodec.h>
0038 }
0039 
0040 QT_BEGIN_NAMESPACE
0041 
0042 class QAVQueueClock
0043 {
0044 public:
0045     QAVQueueClock(double v = 0.0)
0046         : frameRate(v)
0047     {
0048     }
0049 
0050     bool wait(bool shouldSync, double pts, double speed = 1.0, double master = -1)
0051     {
0052         QMutexLocker locker(&m_mutex);
0053         double delay = pts - prevPts;
0054         if (isnan(delay) || delay <= 0 || delay > maxFrameDuration)
0055             delay = frameRate;
0056 
0057         if (master > 0) {
0058             double diff = pts - master;
0059             double sync_threshold = qMax(minThreshold, qMin(maxThreshold, delay));
0060             if (!isnan(diff) && fabs(diff) < maxFrameDuration) {
0061                 if (diff <= -sync_threshold)
0062                     delay = qMax(0.0, delay + diff);
0063                 else if (diff >= sync_threshold && delay > frameDuplicationThreshold)
0064                     delay = delay + diff;
0065                 else if (diff >= sync_threshold)
0066                     delay = 2 * delay;
0067             }
0068         }
0069 
0070         delay /= speed;
0071         const double time = av_gettime_relative() / 1000000.0;
0072         if (shouldSync) {
0073             if (time < frameTimer + delay) {
0074                 double remaining_time = qMin(frameTimer + delay - time, refreshRate);
0075                 locker.unlock();
0076                 av_usleep((int64_t)(remaining_time * 1000000.0));
0077                 return false;
0078             }
0079         }
0080 
0081         prevPts = pts;
0082         frameTimer += delay;
0083         if ((delay > 0 && time - frameTimer > maxThreshold) || !shouldSync)
0084             frameTimer = time;
0085 
0086         return true;
0087     }
0088 
0089     double pts() const
0090     {
0091         QMutexLocker locker(&m_mutex);
0092         return prevPts;
0093     }
0094 
0095     void clear()
0096     {
0097         QMutexLocker locker(&m_mutex);
0098         prevPts = 0;
0099         frameTimer = 0;
0100     }
0101 
0102     void setFrameRate(double v)
0103     {
0104         QMutexLocker locker(&m_mutex);
0105         frameRate = v;
0106     }
0107 
0108 private:
0109     double frameRate = 0;
0110     double frameTimer = 0;
0111     double prevPts = 0;
0112     mutable QMutex m_mutex;
0113     const double maxFrameDuration = 10.0;
0114     const double minThreshold = 0.04;
0115     const double maxThreshold = 0.1;
0116     const double frameDuplicationThreshold = 0.1;
0117     const double refreshRate = 0.01;
0118 };
0119 
0120 template<class T>
0121 class QAVPacketQueue
0122 {
0123 public:
0124     QAVPacketQueue(AVMediaType mediaType, QAVDemuxer &demuxer)
0125         : m_mediaType(mediaType)
0126         , m_demuxer(demuxer)
0127     {
0128     }
0129 
0130     ~QAVPacketQueue()
0131     {
0132         abort();
0133     }
0134 
0135     AVMediaType mediaType() const
0136     {
0137         return m_mediaType;
0138     }
0139 
0140     bool isEmpty() const
0141     {
0142         QMutexLocker locker(&m_mutex);
0143         return m_packets.isEmpty() && m_decodedFrames.isEmpty();
0144     }
0145 
0146     void enqueue(const QAVPacket &packet)
0147     {
0148         QMutexLocker locker(&m_mutex);
0149         m_packets.append(packet);
0150         m_bytes += packet.packet()->size + sizeof(packet);
0151         m_duration += packet.duration();
0152         m_consumerWaiter.wakeAll();
0153         m_abort = false;
0154         m_waitingForPackets = false;
0155     }
0156 
0157     bool frontFrame(T &frame)
0158     {
0159         QMutexLocker locker(&m_mutex);
0160         if (m_decodedFrames.isEmpty())
0161             m_demuxer.decode(dequeue(), m_decodedFrames);
0162         if (m_decodedFrames.isEmpty())
0163             return false;
0164         frame = m_decodedFrames.front();
0165         return true;
0166     }
0167 
0168     void popFrame()
0169     {
0170         QMutexLocker locker(&m_mutex);
0171         if (!m_decodedFrames.isEmpty())
0172             m_decodedFrames.pop_front();
0173     }
0174 
0175     void waitForEmpty()
0176     {
0177         QMutexLocker locker(&m_mutex);
0178         clearPackets();
0179         if (!m_abort && !m_waitingForPackets)
0180             m_producerWaiter.wait(&m_mutex);
0181     }
0182 
0183     void abort()
0184     {
0185         QMutexLocker locker(&m_mutex);
0186         m_abort = true;
0187         m_waitingForPackets = true;
0188         m_consumerWaiter.wakeAll();
0189         m_producerWaiter.wakeAll();
0190     }
0191 
0192     bool enough() const
0193     {
0194         QMutexLocker locker(&m_mutex);
0195         const int minFrames = 15;
0196         return m_packets.size() > minFrames && (!m_duration || m_duration > 1.0);
0197     }
0198 
0199     int bytes() const
0200     {
0201         QMutexLocker locker(&m_mutex);
0202         return m_bytes;
0203     }
0204 
0205     void clear()
0206     {
0207         QMutexLocker locker(&m_mutex);
0208         clearPackets();
0209     }
0210 
0211     void clearFrames()
0212     {
0213         QMutexLocker locker(&m_mutex);
0214         m_decodedFrames.clear();
0215     }
0216 
0217     void wake(bool wake)
0218     {
0219         QMutexLocker locker(&m_mutex);
0220         if (wake)
0221             m_consumerWaiter.wakeAll();
0222         m_wake = wake;
0223     }
0224 
0225 private:
0226     QAVPacket dequeue()
0227     {
0228         if (m_packets.isEmpty()) {
0229             m_producerWaiter.wakeAll();
0230             if (!m_abort && !m_wake) {
0231                 m_waitingForPackets = true;
0232                 m_consumerWaiter.wait(&m_mutex);
0233                 m_waitingForPackets = false;
0234             }
0235         }
0236         if (m_packets.isEmpty())
0237             return {};
0238 
0239         auto packet = m_packets.takeFirst();
0240         m_bytes -= packet.packet()->size + sizeof(packet);
0241         m_duration -= packet.duration();
0242         return packet;
0243     }
0244 
0245     void clearPackets()
0246     {
0247         m_packets.clear();
0248         m_decodedFrames.clear();
0249         m_bytes = 0;
0250         m_duration = 0;
0251     }
0252 
0253     const AVMediaType m_mediaType = AVMEDIA_TYPE_UNKNOWN;
0254     QAVDemuxer &m_demuxer;
0255     QList<QAVPacket> m_packets;
0256     // Tracks decoded frames to prevent EOF if not all frames are landed
0257     QList<T> m_decodedFrames;
0258     mutable QMutex m_mutex;
0259     QWaitCondition m_consumerWaiter;
0260     QWaitCondition m_producerWaiter;
0261     bool m_abort = false;
0262     bool m_waitingForPackets = true;
0263     bool m_wake = false;
0264 
0265     int m_bytes = 0;
0266     int m_duration = 0;
0267 
0268 private:
0269     Q_DISABLE_COPY(QAVPacketQueue)
0270 };
0271 
0272 
0273 QT_END_NAMESPACE
0274 
0275 #endif