File indexing completed on 2024-06-16 04:38:29
0001 /* 0002 SPDX-FileCopyrightText: 2003 Fabrice Bellard 0003 SPDX-FileCopyrightText: 2020-2022 Mladen Milinkovic <max@smoothware.net> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "packetqueue.h" 0009 0010 #include <QMutex> 0011 #include <QWaitCondition> 0012 0013 #include "ffplayer.h" 0014 0015 using namespace SubtitleComposer; 0016 0017 PacketQueue::PacketQueue() 0018 : m_firstPkt(nullptr), 0019 m_lastPkt(nullptr), 0020 m_nbPackets(0), 0021 m_size(0), 0022 m_duration(0), 0023 m_abortRequest(false), 0024 m_serial(0), 0025 m_mutex(nullptr), 0026 m_cond(nullptr) 0027 { 0028 } 0029 0030 int 0031 PacketQueue::put_private(AVPacket **pkt) 0032 { 0033 if(m_abortRequest) { 0034 if((*pkt)->data == FFPlayer::flushPkt()) 0035 (*pkt)->data = nullptr; 0036 av_packet_free(pkt); 0037 return -1; 0038 } 0039 0040 PacketList *pkt1 = new PacketList(); 0041 pkt1->pkt = *pkt; 0042 *pkt = nullptr; 0043 0044 pkt1->next = nullptr; 0045 if(pkt1->pkt->data == FFPlayer::flushPkt()) 0046 m_serial++; 0047 pkt1->serial = m_serial; 0048 0049 if(!m_lastPkt) 0050 m_firstPkt = pkt1; 0051 else 0052 m_lastPkt->next = pkt1; 0053 m_lastPkt = pkt1; 0054 m_nbPackets++; 0055 m_size += pkt1->pkt->size + sizeof(*pkt1); 0056 m_duration += pkt1->pkt->duration; 0057 // XXX: should duplicate packet data in DV case 0058 m_cond->wakeOne(); 0059 return 0; 0060 } 0061 0062 int 0063 PacketQueue::putFlushPacket() 0064 { 0065 QMutexLocker l(m_mutex); 0066 AVPacket *pkt = av_packet_alloc(); 0067 Q_ASSERT(pkt != nullptr); 0068 pkt->data = FFPlayer::flushPkt(); 0069 return put_private(&pkt); 0070 } 0071 0072 int 0073 PacketQueue::put(AVPacket **pkt) 0074 { 0075 QMutexLocker l(m_mutex); 0076 return put_private(pkt); 0077 } 0078 0079 int 0080 PacketQueue::putNullPacket(int streamIndex) 0081 { 0082 AVPacket *pkt = av_packet_alloc(); 0083 Q_ASSERT(pkt != nullptr); 0084 pkt->stream_index = streamIndex; 0085 return put(&pkt); 0086 } 0087 0088 int 0089 PacketQueue::init() 0090 { 0091 m_firstPkt = m_lastPkt = nullptr; 0092 m_nbPackets = m_size = m_serial = 0; 0093 m_duration = 0; 0094 m_mutex = new QMutex(); 0095 m_cond = new QWaitCondition(); 0096 m_abortRequest = true; 0097 return 0; 0098 } 0099 0100 void 0101 PacketQueue::flush() 0102 { 0103 QMutexLocker l(m_mutex); 0104 PacketList *pkt, *pkt1; 0105 for(pkt = m_firstPkt; pkt; pkt = pkt1) { 0106 pkt1 = pkt->next; 0107 av_packet_free(&pkt->pkt); 0108 delete pkt; 0109 } 0110 m_lastPkt = nullptr; 0111 m_firstPkt = nullptr; 0112 m_nbPackets = 0; 0113 m_size = 0; 0114 m_duration = 0; 0115 } 0116 0117 void 0118 PacketQueue::destroy() 0119 { 0120 flush(); 0121 delete m_mutex; 0122 delete m_cond; 0123 } 0124 0125 void 0126 PacketQueue::abort() 0127 { 0128 QMutexLocker l(m_mutex); 0129 m_abortRequest = true; 0130 m_cond->wakeOne(); 0131 } 0132 0133 void 0134 PacketQueue::start() 0135 { 0136 QMutexLocker l(m_mutex); 0137 m_abortRequest = false; 0138 AVPacket *pkt = av_packet_alloc(); 0139 Q_ASSERT(pkt != nullptr); 0140 pkt->data = FFPlayer::flushPkt(); 0141 put_private(&pkt); 0142 } 0143 0144 int 0145 PacketQueue::get(AVPacket **pkt, int block, int *serial) 0146 { 0147 QMutexLocker l(m_mutex); 0148 0149 for(;;) { 0150 if(m_abortRequest) 0151 return -1; 0152 0153 PacketList *pkt1 = m_firstPkt; 0154 if(pkt1) { 0155 m_firstPkt = pkt1->next; 0156 if(!m_firstPkt) 0157 m_lastPkt = nullptr; 0158 m_nbPackets--; 0159 m_size -= pkt1->pkt->size + sizeof(*pkt1); 0160 m_duration -= pkt1->pkt->duration; 0161 *pkt = pkt1->pkt; 0162 if(serial) 0163 *serial = pkt1->serial; 0164 delete pkt1; 0165 return 1; 0166 } 0167 0168 if(!block) 0169 return 0; 0170 0171 m_cond->wait(m_mutex); 0172 } 0173 } 0174