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 "framequeue.h"
0009 
0010 #include <QMutex>
0011 #include <QWaitCondition>
0012 
0013 #include "packetqueue.h"
0014 
0015 using namespace SubtitleComposer;
0016 
0017 FrameQueue::FrameQueue()
0018     : m_rIndex(0),
0019       m_wIndex(0),
0020       m_size(0),
0021       m_maxSize(0),
0022       m_keepLast(0),
0023       m_rIndexShown(0),
0024       m_mutex(nullptr),
0025       m_cond(nullptr),
0026       m_pktQ(nullptr)
0027 {
0028     memset(m_queue, 0, sizeof(m_queue));
0029 }
0030 
0031 void
0032 FrameQueue::unrefItem(Frame *vp)
0033 {
0034     av_frame_unref(vp->frame);
0035     avsubtitle_free(&vp->sub);
0036 }
0037 
0038 int
0039 FrameQueue::init(PacketQueue *pktq, int maxSize, int keepLast)
0040 {
0041     m_rIndex = m_wIndex = m_size = m_rIndexShown = 0;
0042     m_mutex = new QMutex();
0043     m_cond = new QWaitCondition();
0044     m_pktQ = pktq;
0045     m_maxSize = FFMIN(maxSize, FRAME_QUEUE_SIZE);
0046     m_keepLast = !!keepLast;
0047     for(int i = 0; i < m_maxSize; i++)
0048         if((m_queue[i].frame = av_frame_alloc()) == nullptr)
0049             return AVERROR(ENOMEM);
0050     return 0;
0051 }
0052 
0053 void
0054 FrameQueue::destory()
0055 {
0056     for(int i = 0; i < m_maxSize; i++) {
0057         Frame *vp = &m_queue[i];
0058         FrameQueue::unrefItem(vp);
0059         av_frame_free(&vp->frame);
0060     }
0061     delete m_mutex;
0062     delete m_cond;
0063 }
0064 
0065 void
0066 FrameQueue::signal()
0067 {
0068     m_mutex->lock();
0069     m_cond->wakeOne();
0070     m_mutex->unlock();
0071 }
0072 
0073 Frame *
0074 FrameQueue::peek()
0075 {
0076     return &m_queue[(m_rIndex + m_rIndexShown) % m_maxSize];
0077 }
0078 
0079 Frame *
0080 FrameQueue::peekNext()
0081 {
0082     return &m_queue[(m_rIndex + m_rIndexShown + 1) % m_maxSize];
0083 }
0084 
0085 Frame *
0086 FrameQueue::peekLast()
0087 {
0088     return &m_queue[m_rIndex];
0089 }
0090 
0091 Frame *
0092 FrameQueue::peekWritable()
0093 {
0094     // wait until we have space to put a new frame
0095     m_mutex->lock();
0096     while(m_size >= m_maxSize && !m_pktQ->m_abortRequest)
0097         m_cond->wait(m_mutex);
0098     m_mutex->unlock();
0099 
0100     if(m_pktQ->m_abortRequest)
0101         return nullptr;
0102 
0103     return &m_queue[m_wIndex];
0104 }
0105 
0106 Frame *
0107 FrameQueue::peekReadable()
0108 {
0109     // wait until we have a new readable frame
0110     m_mutex->lock();
0111     while(m_size - m_rIndexShown <= 0 && !m_pktQ->m_abortRequest)
0112         m_cond->wait(m_mutex);
0113     m_mutex->unlock();
0114 
0115     if(m_pktQ->m_abortRequest)
0116         return nullptr;
0117 
0118     return &m_queue[(m_rIndex + m_rIndexShown) % m_maxSize];
0119 }
0120 
0121 void
0122 FrameQueue::push()
0123 {
0124     if(++m_wIndex == m_maxSize)
0125         m_wIndex = 0;
0126     m_mutex->lock();
0127     m_size++;
0128     m_cond->wakeOne();
0129     m_mutex->unlock();
0130 }
0131 
0132 void
0133 FrameQueue::next()
0134 {
0135     if(m_keepLast && !m_rIndexShown) {
0136         m_rIndexShown = 1;
0137         return;
0138     }
0139     FrameQueue::unrefItem(&m_queue[m_rIndex]);
0140     if(++m_rIndex == m_maxSize)
0141         m_rIndex = 0;
0142     m_mutex->lock();
0143     m_size--;
0144     m_cond->wakeOne();
0145     m_mutex->unlock();
0146 }
0147 
0148 /* return the number of undisplayed frames in the queue */
0149 int
0150 FrameQueue::nbRemaining()
0151 {
0152     return m_size - m_rIndexShown;
0153 }
0154 
0155 /* return last shown position */
0156 int64_t
0157 FrameQueue::lastPos()
0158 {
0159     Frame *fp = &m_queue[m_rIndex];
0160     if(m_rIndexShown && fp->serial == m_pktQ->m_serial)
0161         return fp->pos;
0162     else
0163         return -1;
0164 }
0165