[cstdstring] removal of Trim/TrimLeft/TrimRight
[vuplus_xbmc] / xbmc / cores / dvdplayer / DVDCodecs / Overlay / DVDOverlayCodecSSA.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 "DVDOverlayCodecSSA.h"
22 #include "DVDOverlaySSA.h"
23 #include "DVDStreamInfo.h"
24 #include "DVDCodecs/DVDCodecs.h"
25 #include "DVDClock.h"
26 #include "Util.h"
27 #include "utils/AutoPtrHandle.h"
28 #include "utils/StringUtils.h"
29
30 using namespace AUTOPTR;
31 using namespace std;
32
33 CDVDOverlayCodecSSA::CDVDOverlayCodecSSA() : CDVDOverlayCodec("SSA Subtitle Decoder")
34 {
35   m_pOverlay = NULL;
36   m_libass   = NULL;
37   m_order    = 0;
38   m_output   = false;
39 }
40
41 CDVDOverlayCodecSSA::~CDVDOverlayCodecSSA()
42 {
43   Dispose();
44 }
45
46 bool CDVDOverlayCodecSSA::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
47 {
48   if(hints.codec != AV_CODEC_ID_SSA)
49     return false;
50
51   Dispose();
52
53   m_hints  = hints;
54   m_libass = new CDVDSubtitlesLibass();
55   return m_libass->DecodeHeader((char *)hints.extradata, hints.extrasize);
56 }
57
58 void CDVDOverlayCodecSSA::Dispose()
59 {
60   if(m_libass)
61     SAFE_RELEASE(m_libass);
62
63   if(m_pOverlay)
64     SAFE_RELEASE(m_pOverlay);
65 }
66
67 int CDVDOverlayCodecSSA::Decode(DemuxPacket *pPacket)
68 {
69   if(!pPacket)
70     return OC_ERROR;
71   
72   double pts = pPacket->dts != DVD_NOPTS_VALUE ? pPacket->dts : pPacket->pts;
73   uint8_t *data = pPacket->pData;
74   int size = pPacket->iSize;
75   double duration = pPacket->duration;
76   if(duration == DVD_NOPTS_VALUE)
77     duration = 0.0;
78
79   if(strncmp((const char*)data, "Dialogue:", 9) == 0)
80   {
81     int    sh, sm, ss, sc, eh, em, es, ec;
82     double beg, end;
83     size_t pos;
84     CStdString      line, line2;
85     std::vector<std::string> lines;
86     StringUtils::Tokenize((const char*)data, lines, "\r\n");
87     for(size_t i=0; i<lines.size(); i++)
88     {
89       line = lines[i];
90       StringUtils::Trim(line);
91       auto_aptr<char> layer(new char[line.length()+1]);
92
93       if(sscanf(line.c_str(), "%*[^:]:%[^,],%d:%d:%d%*c%d,%d:%d:%d%*c%d"
94                             , layer.get(), &sh, &sm, &ss, &sc, &eh,&em, &es, &ec) != 9)
95         continue;
96
97       end = 10000 * ((eh*360000.0)+(em*6000.0)+(es*100.0)+ec);
98       beg = 10000 * ((sh*360000.0)+(sm*6000.0)+(ss*100.0)+sc);
99
100       pos = line.find_first_of(",", 0);
101       pos = line.find_first_of(",", pos+1);
102       pos = line.find_first_of(",", pos+1);
103       if(pos == CStdString::npos)
104         continue;
105
106       line2 = StringUtils::Format("%d,%s,%s", m_order++, layer.get(), line.Mid(pos+1).c_str());
107
108       m_libass->DecodeDemuxPkt((char*)line2.c_str(), line2.length(), beg, end - beg);
109
110       /* setup time spanning all dialogs */
111       if(pts == DVD_NOPTS_VALUE || beg < pts)
112         pts = beg;
113       if(end - pts > duration)
114         duration = end - pts;
115     }
116   }
117   else
118     m_libass->DecodeDemuxPkt((char*)data, size, pts, duration);
119
120   if(m_pOverlay)
121   {
122     /* there will only ever be one active, so we 
123      * must always make sure any new one overlap
124      * include the full duration of the old one */
125     if(m_pOverlay->iPTSStopTime > pts + duration)
126       duration = m_pOverlay->iPTSStopTime - pts;
127     SAFE_RELEASE(m_pOverlay);
128   }
129
130   m_pOverlay = new CDVDOverlaySSA(m_libass);
131   m_pOverlay->iPTSStartTime = pts;
132   m_pOverlay->iPTSStopTime  = pts + duration;
133   m_output = true;
134   return OC_OVERLAY;
135 }
136 void CDVDOverlayCodecSSA::Reset()
137 {
138   Dispose();
139   m_order  = 0;
140   m_output = false;
141   m_libass = new CDVDSubtitlesLibass();
142   m_libass->DecodeHeader((char *)m_hints.extradata, m_hints.extrasize);
143 }
144
145 void CDVDOverlayCodecSSA::Flush()
146 {
147   Reset();
148 }
149
150 CDVDOverlay* CDVDOverlayCodecSSA::GetOverlay()
151 {
152   if(m_output)
153   {
154     m_output = false;
155     return m_pOverlay->Acquire();
156   }
157   return NULL;
158 }
159
160