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