Merge pull request #5101 from FernetMenta/ffmpeg-threads
[vuplus_xbmc] / xbmc / cores / dvdplayer / DVDOverlayContainer.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "DVDOverlayContainer.h"
22 #include "DVDInputStreams/DVDInputStreamNavigator.h"
23 #include "threads/SingleLock.h"
24
25 CDVDOverlayContainer::CDVDOverlayContainer()
26 {
27   m_overlays.clear();
28 }
29
30 CDVDOverlayContainer::~CDVDOverlayContainer()
31 {
32   Clear();
33 }
34
35 void CDVDOverlayContainer::Add(CDVDOverlay* pOverlay)
36 {
37   pOverlay->Acquire();
38
39   CSingleLock lock(*this);
40
41   // markup any non ending overlays, to finish
42   // when this new one starts, there can be
43   // multiple overlays queued at same start
44   // point so only stop them when we get a
45   // new startpoint
46   for(int i = m_overlays.size();i>0;)
47   {
48     i--;
49     if(m_overlays[i]->iPTSStopTime)
50     {
51       if(!m_overlays[i]->replace)
52         break;
53       if(m_overlays[i]->iPTSStopTime <= pOverlay->iPTSStartTime)
54         break;
55     }
56     if(m_overlays[i]->iPTSStartTime != pOverlay->iPTSStartTime)
57       m_overlays[i]->iPTSStopTime = pOverlay->iPTSStartTime;
58   }
59
60   m_overlays.push_back(pOverlay);
61
62 }
63
64 VecOverlays* CDVDOverlayContainer::GetOverlays()
65 {
66   return &m_overlays;
67 }
68
69 VecOverlaysIter CDVDOverlayContainer::Remove(VecOverlaysIter itOverlay)
70 {
71   VecOverlaysIter itNext;
72   CDVDOverlay* pOverlay = *itOverlay;
73
74   {
75     CSingleLock lock(*this);
76     itNext = m_overlays.erase(itOverlay);
77   }
78
79   pOverlay->Release();
80
81   return itNext;
82 }
83
84 void CDVDOverlayContainer::CleanUp(double pts)
85 {
86   CSingleLock lock(*this);
87
88   VecOverlaysIter it = m_overlays.begin();
89   while (it != m_overlays.end())
90   {
91     CDVDOverlay* pOverlay = *it;
92
93     // never delete forced overlays, they are used in menu's
94     // clear takes care of removing them
95     // also if stoptime = 0, it means the next subtitles will use its starttime as the stoptime
96     // which means we cannot delete overlays with stoptime 0
97     if (!pOverlay->bForced && pOverlay->iPTSStopTime <= pts && pOverlay->iPTSStopTime != 0)
98     {
99       //CLog::Log(LOGDEBUG,"CDVDOverlay::CleanUp, removing %d", (int)(pts / 1000));
100       //CLog::Log(LOGDEBUG,"CDVDOverlay::CleanUp, remove, start : %d, stop : %d", (int)(pOverlay->iPTSStartTime / 1000), (int)(pOverlay->iPTSStopTime / 1000));
101       it = Remove(it);
102       continue;
103     }
104     else if (pOverlay->bForced)
105     {
106       //Check for newer replacements
107       VecOverlaysIter it2 = it;
108       bool bNewer = false;
109       while (!bNewer && ++it2 != m_overlays.end())
110       {
111         CDVDOverlay* pOverlay2 = *it2;
112         if (pOverlay2->bForced && pOverlay2->iPTSStartTime <= pts) bNewer = true;
113       }
114
115       if (bNewer)
116       {
117         it = Remove(it);
118         continue;
119       }
120     }
121     ++it;
122   }
123
124 }
125
126 void CDVDOverlayContainer::Remove()
127 {
128   if (!m_overlays.empty())
129   {
130     CDVDOverlay* pOverlay;
131
132     {
133       CSingleLock lock(*this);
134
135       pOverlay = m_overlays.front();
136       m_overlays.erase(m_overlays.begin());
137     }
138     pOverlay->Release();
139   }
140 }
141
142 void CDVDOverlayContainer::Clear()
143 {
144   while (!m_overlays.empty()) Remove();
145 }
146
147 int CDVDOverlayContainer::GetSize()
148 {
149   return m_overlays.size();
150 }
151
152 bool CDVDOverlayContainer::ContainsOverlayType(DVDOverlayType type)
153 {
154   bool result = false;
155
156   CSingleLock lock(*this);
157
158   VecOverlaysIter it = m_overlays.begin();
159   while (!result && it != m_overlays.end())
160   {
161     if (((CDVDOverlay*)*it)->IsOverlayType(type)) result = true;
162     ++it;
163   }
164
165   return result;
166 }
167
168 /*
169  * iAction should be LIBDVDNAV_BUTTON_NORMAL or LIBDVDNAV_BUTTON_CLICKED
170  */
171 void CDVDOverlayContainer::UpdateOverlayInfo(CDVDInputStreamNavigator* pStream, CDVDDemuxSPU *pSpu, int iAction)
172 {
173   CSingleLock lock(*this);
174
175   //Update any forced overlays.
176   for(VecOverlays::iterator it = m_overlays.begin(); it != m_overlays.end(); ++it )
177   {
178     if ((*it)->IsOverlayType(DVDOVERLAY_TYPE_SPU))
179     {
180       CDVDOverlaySpu* pOverlaySpu = (CDVDOverlaySpu*)(*it);
181
182       // make sure its a forced (menu) overlay
183       // set menu spu color and alpha data if there is a valid menu overlay
184       if (pOverlaySpu->bForced)
185       {
186         if(pOverlaySpu->Acquire()->Release() > 1)
187         {
188           pOverlaySpu = new CDVDOverlaySpu(*pOverlaySpu);
189           (*it)->Release();
190           (*it) = pOverlaySpu;
191         }
192
193         if(pStream->GetCurrentButtonInfo(pOverlaySpu, pSpu, iAction))
194         {
195           if(pOverlaySpu->m_overlay)
196             pOverlaySpu->m_overlay->Release();
197           pOverlaySpu->m_overlay = NULL;
198         }
199
200       }
201     }
202   }
203 }