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