1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "DVDMessage.h"
12 #include "threads/CriticalSection.h"
13 #include "threads/Event.h"
14 
15 #include <algorithm>
16 #include <atomic>
17 #include <list>
18 #include <string>
19 
20 struct DVDMessageListItem
21 {
DVDMessageListItemDVDMessageListItem22   DVDMessageListItem(CDVDMsg* msg, int prio)
23   {
24     message = msg->Acquire();
25     priority = prio;
26   }
DVDMessageListItemDVDMessageListItem27   DVDMessageListItem()
28   {
29     message = NULL;
30     priority = 0;
31   }
32   DVDMessageListItem(const DVDMessageListItem&) = delete;
~DVDMessageListItemDVDMessageListItem33  ~DVDMessageListItem()
34   {
35     if(message)
36       message->Release();
37   }
38 
39   DVDMessageListItem& operator=(const DVDMessageListItem&) = delete;
40 
41   CDVDMsg* message;
42   int priority;
43 };
44 
45 enum MsgQueueReturnCode
46 {
47   MSGQ_OK = 1,
48   MSGQ_TIMEOUT = 0,
49   MSGQ_ABORT = -1, // negative for legacy, not an error actually
50   MSGQ_NOT_INITIALIZED = -2,
51   MSGQ_INVALID_MSG = -3,
52   MSGQ_OUT_OF_MEMORY = -4
53 };
54 
55 #define MSGQ_IS_ERROR(c)    (c < 0)
56 
57 class CDVDMessageQueue
58 {
59 public:
60   explicit CDVDMessageQueue(const std::string &owner);
61   virtual ~CDVDMessageQueue();
62 
63   void Init();
64   void Flush(CDVDMsg::Message message = CDVDMsg::DEMUXER_PACKET);
65   void Abort();
66   void End();
67 
68   MsgQueueReturnCode Put(CDVDMsg* pMsg, int priority = 0);
69   MsgQueueReturnCode PutBack(CDVDMsg* pMsg, int priority = 0);
70 
71   /**
72    * msg,       message type from DVDMessage.h
73    * timeout,   timeout in msec
74    * priority,  minimum priority to get, outputs returned packets priority
75    */
76   MsgQueueReturnCode Get(CDVDMsg** pMsg, unsigned int iTimeoutInMilliSeconds, int &priority);
Get(CDVDMsg ** pMsg,unsigned int iTimeoutInMilliSeconds)77   MsgQueueReturnCode Get(CDVDMsg** pMsg, unsigned int iTimeoutInMilliSeconds)
78   {
79     int priority = 0;
80     return Get(pMsg, iTimeoutInMilliSeconds, priority);
81   }
82 
GetDataSize()83   int GetDataSize() const { return m_iDataSize; }
84   int GetTimeSize() const;
85   unsigned GetPacketCount(CDVDMsg::Message type);
ReceivedAbortRequest()86   bool ReceivedAbortRequest() { return m_bAbortRequest; }
87   void WaitUntilEmpty();
88 
89   // non messagequeue related functions
IsFull()90   bool IsFull() const { return GetLevel() == 100; }
91   int GetLevel() const;
92 
SetMaxDataSize(int iMaxDataSize)93   void SetMaxDataSize(int iMaxDataSize) { m_iMaxDataSize = iMaxDataSize; }
SetMaxTimeSize(double sec)94   void SetMaxTimeSize(double sec) { m_TimeSize  = 1.0 / std::max(1.0, sec); }
GetMaxDataSize()95   int GetMaxDataSize() const { return m_iMaxDataSize; }
GetMaxTimeSize()96   double GetMaxTimeSize() const { return m_TimeSize; }
IsInited()97   bool IsInited() const { return m_bInitialized; }
98   bool IsDataBased() const;
99 
100 private:
101 
102   MsgQueueReturnCode Put(CDVDMsg* pMsg, int priority, bool front);
103   void UpdateTimeFront();
104   void UpdateTimeBack();
105 
106   CEvent m_hEvent;
107   mutable CCriticalSection m_section;
108 
109   std::atomic<bool> m_bAbortRequest;
110   bool m_bInitialized;
111   bool m_drain = false;
112 
113   int m_iDataSize;
114   double m_TimeFront;
115   double m_TimeBack;
116   double m_TimeSize;
117 
118   int m_iMaxDataSize;
119   std::string m_owner;
120 
121   std::list<DVDMessageListItem> m_messages;
122   std::list<DVDMessageListItem> m_prioMessages;
123 };
124 
125