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