[videodb] remove unused seasons table from episode_view
[xbmc.git] / xbmc / cores / VideoPlayer / DVDMessageQueue.cpp
blob20d1caece6ab047141304ea05123633b467231e4
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "DVDMessageQueue.h"
11 #include "cores/VideoPlayer/Interface/DemuxPacket.h"
12 #include "cores/VideoPlayer/Interface/TimingConstants.h"
13 #include "utils/log.h"
15 #include <math.h>
16 #include <mutex>
18 using namespace std::chrono_literals;
20 CDVDMessageQueue::CDVDMessageQueue(const std::string &owner) : m_hEvent(true), m_owner(owner)
22 m_iDataSize = 0;
23 m_bInitialized = false;
25 m_TimeBack = DVD_NOPTS_VALUE;
26 m_TimeFront = DVD_NOPTS_VALUE;
27 m_TimeSize = 1.0 / 4.0; /* 4 seconds */
28 m_iMaxDataSize = 0;
31 CDVDMessageQueue::~CDVDMessageQueue()
33 // remove all remaining messages
34 Flush(CDVDMsg::NONE);
37 void CDVDMessageQueue::Init()
39 m_iDataSize = 0;
40 m_bAbortRequest = false;
41 m_bInitialized = true;
42 m_TimeBack = DVD_NOPTS_VALUE;
43 m_TimeFront = DVD_NOPTS_VALUE;
44 m_drain = false;
47 void CDVDMessageQueue::Flush(CDVDMsg::Message type)
49 std::unique_lock<CCriticalSection> lock(m_section);
51 m_messages.remove_if([type](const DVDMessageListItem &item){
52 return type == CDVDMsg::NONE || item.message->IsType(type);
53 });
55 m_prioMessages.remove_if([type](const DVDMessageListItem &item){
56 return type == CDVDMsg::NONE || item.message->IsType(type);
57 });
59 if (type == CDVDMsg::DEMUXER_PACKET || type == CDVDMsg::NONE)
61 m_iDataSize = 0;
62 m_TimeBack = DVD_NOPTS_VALUE;
63 m_TimeFront = DVD_NOPTS_VALUE;
67 void CDVDMessageQueue::Abort()
69 std::unique_lock<CCriticalSection> lock(m_section);
71 m_bAbortRequest = true;
73 // inform waiter for abort action
74 m_hEvent.Set();
77 void CDVDMessageQueue::End()
79 std::unique_lock<CCriticalSection> lock(m_section);
81 Flush(CDVDMsg::NONE);
83 m_bInitialized = false;
84 m_iDataSize = 0;
85 m_bAbortRequest = false;
88 MsgQueueReturnCode CDVDMessageQueue::Put(const std::shared_ptr<CDVDMsg>& pMsg, int priority)
90 return Put(pMsg, priority, true);
93 MsgQueueReturnCode CDVDMessageQueue::PutBack(const std::shared_ptr<CDVDMsg>& pMsg, int priority)
95 return Put(pMsg, priority, false);
98 MsgQueueReturnCode CDVDMessageQueue::Put(const std::shared_ptr<CDVDMsg>& pMsg,
99 int priority,
100 bool front)
102 std::unique_lock<CCriticalSection> lock(m_section);
104 if (!m_bInitialized)
106 CLog::Log(LOGWARNING, "CDVDMessageQueue({})::Put MSGQ_NOT_INITIALIZED", m_owner);
107 return MSGQ_NOT_INITIALIZED;
109 if (!pMsg)
111 CLog::Log(LOGFATAL, "CDVDMessageQueue({})::Put MSGQ_INVALID_MSG", m_owner);
112 return MSGQ_INVALID_MSG;
115 if (priority > 0)
117 int prio = priority;
118 if (!front)
119 prio++;
121 auto it = std::find_if(m_prioMessages.begin(), m_prioMessages.end(),
122 [prio](const DVDMessageListItem &item){
123 return prio <= item.priority;
125 m_prioMessages.emplace(it, pMsg, priority);
127 else
129 if (m_messages.empty())
131 m_iDataSize = 0;
132 m_TimeBack = DVD_NOPTS_VALUE;
133 m_TimeFront = DVD_NOPTS_VALUE;
136 if (front)
137 m_messages.emplace_front(pMsg, priority);
138 else
139 m_messages.emplace_back(pMsg, priority);
142 if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET) && priority == 0)
144 DemuxPacket* packet = static_cast<CDVDMsgDemuxerPacket*>(pMsg.get())->GetPacket();
145 if (packet)
147 m_iDataSize += packet->iSize;
148 if (front)
149 UpdateTimeFront();
150 else
151 UpdateTimeBack();
155 // inform waiter for new packet
156 m_hEvent.Set();
158 return MSGQ_OK;
161 MsgQueueReturnCode CDVDMessageQueue::Get(std::shared_ptr<CDVDMsg>& pMsg,
162 std::chrono::milliseconds timeout,
163 int& priority)
165 std::unique_lock<CCriticalSection> lock(m_section);
167 int ret = 0;
169 if (!m_bInitialized)
171 CLog::Log(LOGFATAL, "CDVDMessageQueue({})::Get MSGQ_NOT_INITIALIZED", m_owner);
172 return MSGQ_NOT_INITIALIZED;
175 while (!m_bAbortRequest)
177 std::list<DVDMessageListItem> &msgs = (priority > 0 || !m_prioMessages.empty()) ? m_prioMessages : m_messages;
179 if (!msgs.empty() && (msgs.back().priority >= priority || m_drain))
181 DVDMessageListItem& item(msgs.back());
182 priority = item.priority;
184 if (item.message->IsType(CDVDMsg::DEMUXER_PACKET) && item.priority == 0)
186 DemuxPacket* packet =
187 std::static_pointer_cast<CDVDMsgDemuxerPacket>(item.message)->GetPacket();
188 if (packet)
190 m_iDataSize -= packet->iSize;
194 pMsg = std::move(item.message);
195 msgs.pop_back();
196 UpdateTimeBack();
197 ret = MSGQ_OK;
198 break;
200 else if (timeout == 0ms)
202 ret = MSGQ_TIMEOUT;
203 break;
205 else
207 m_hEvent.Reset();
208 lock.unlock();
210 // wait for a new message
211 if (!m_hEvent.Wait(timeout))
212 return MSGQ_TIMEOUT;
214 lock.lock();
218 if (m_bAbortRequest)
219 return MSGQ_ABORT;
221 return (MsgQueueReturnCode)ret;
224 void CDVDMessageQueue::UpdateTimeFront()
226 if (!m_messages.empty())
228 auto &item = m_messages.front();
229 if (item.message->IsType(CDVDMsg::DEMUXER_PACKET))
231 DemuxPacket* packet =
232 std::static_pointer_cast<CDVDMsgDemuxerPacket>(item.message)->GetPacket();
233 if (packet)
235 if (packet->dts != DVD_NOPTS_VALUE)
236 m_TimeFront = packet->dts;
237 else if (packet->pts != DVD_NOPTS_VALUE)
238 m_TimeFront = packet->pts;
240 if (m_TimeBack == DVD_NOPTS_VALUE)
241 m_TimeBack = m_TimeFront;
247 void CDVDMessageQueue::UpdateTimeBack()
249 if (!m_messages.empty())
251 auto &item = m_messages.back();
252 if (item.message->IsType(CDVDMsg::DEMUXER_PACKET))
254 DemuxPacket* packet =
255 std::static_pointer_cast<CDVDMsgDemuxerPacket>(item.message)->GetPacket();
256 if (packet)
258 if (packet->dts != DVD_NOPTS_VALUE)
259 m_TimeBack = packet->dts;
260 else if (packet->pts != DVD_NOPTS_VALUE)
261 m_TimeBack = packet->pts;
263 if (m_TimeFront == DVD_NOPTS_VALUE)
264 m_TimeFront = m_TimeBack;
270 unsigned CDVDMessageQueue::GetPacketCount(CDVDMsg::Message type)
272 std::unique_lock<CCriticalSection> lock(m_section);
274 if (!m_bInitialized)
275 return 0;
277 unsigned count = 0;
278 for (const auto &item : m_messages)
280 if(item.message->IsType(type))
281 count++;
283 for (const auto &item : m_prioMessages)
285 if(item.message->IsType(type))
286 count++;
289 return count;
292 void CDVDMessageQueue::WaitUntilEmpty()
295 std::unique_lock<CCriticalSection> lock(m_section);
296 m_drain = true;
299 CLog::Log(LOGINFO, "CDVDMessageQueue({})::WaitUntilEmpty", m_owner);
300 auto msg = std::make_shared<CDVDMsgGeneralSynchronize>(40s, SYNCSOURCE_ANY);
301 Put(msg);
302 msg->Wait(m_bAbortRequest, 0);
305 std::unique_lock<CCriticalSection> lock(m_section);
306 m_drain = false;
310 int CDVDMessageQueue::GetLevel() const
312 std::unique_lock<CCriticalSection> lock(m_section);
314 if (m_iDataSize > m_iMaxDataSize)
315 return 100;
316 if (m_iDataSize == 0)
317 return 0;
319 if (IsDataBased())
321 return std::min(100, 100 * m_iDataSize / m_iMaxDataSize);
324 int level = std::min(100.0, ceil(100.0 * m_TimeSize * (m_TimeFront - m_TimeBack) / DVD_TIME_BASE ));
326 // if we added lots of packets with NOPTS, make sure that the queue is not signalled empty
327 if (level == 0 && m_iDataSize != 0)
329 CLog::Log(LOGDEBUG, "CDVDMessageQueue::GetLevel() - can't determine level");
330 return 1;
333 return level;
336 double CDVDMessageQueue::GetTimeSize() const
338 std::unique_lock<CCriticalSection> lock(m_section);
340 if (IsDataBased())
341 return 0.0;
342 else
343 return (m_TimeFront - m_TimeBack) / DVD_TIME_BASE;
346 bool CDVDMessageQueue::IsDataBased() const
348 return (m_TimeBack == DVD_NOPTS_VALUE ||
349 m_TimeFront == DVD_NOPTS_VALUE ||
350 m_TimeFront <= m_TimeBack);