summaryrefslogtreecommitdiffstats
path: root/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxVobsub.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxVobsub.cpp')
-rw-r--r--xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxVobsub.cpp247
1 files changed, 247 insertions, 0 deletions
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxVobsub.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxVobsub.cpp
new file mode 100644
index 0000000..9625a19
--- /dev/null
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxVobsub.cpp
@@ -0,0 +1,247 @@
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 "DVDDemuxVobsub.h"
22#include "DVDInputStreams/DVDFactoryInputStream.h"
23#include "DVDInputStreams/DVDInputStream.h"
24#include "DVDStreamInfo.h"
25#include "DVDCodecs/DVDCodecs.h"
26#include "DVDDemuxers/DVDDemuxFFmpeg.h"
27#include "DVDDemuxers/DVDDemuxUtils.h"
28#include "DVDClock.h"
29#include "DVDSubtitles/DVDSubtitleStream.h"
30
31#include <string.h>
32
33using namespace std;
34
35CDVDDemuxVobsub::CDVDDemuxVobsub()
36{
37}
38
39CDVDDemuxVobsub::~CDVDDemuxVobsub()
40{
41 for(unsigned i=0;i<m_Streams.size();i++)
42 {
43 delete m_Streams[i];
44 }
45 m_Streams.clear();
46}
47
48bool CDVDDemuxVobsub::Open(const string& filename, const string& subfilename)
49{
50 m_Filename = filename;
51
52 unique_ptr<CDVDSubtitleStream> pStream(new CDVDSubtitleStream());
53 if(!pStream->Open(filename))
54 return false;
55
56 string vobsub = subfilename;
57 if ( vobsub == "")
58 {
59 vobsub = filename;
60 vobsub.erase(vobsub.rfind('.'), vobsub.size());
61 vobsub += ".sub";
62 }
63
64 m_Input.reset(CDVDFactoryInputStream::CreateInputStream(NULL, vobsub, ""));
65 if(!m_Input.get() || !m_Input->Open(vobsub.c_str(), "video/x-vobsub"))
66 return false;
67
68 m_Demuxer.reset(new CDVDDemuxFFmpeg());
69 if(!m_Demuxer->Open(m_Input.get()))
70 return false;
71
72 CDVDStreamInfo hints;
73 CDVDCodecOptions options;
74 hints.codec = AV_CODEC_ID_DVD_SUBTITLE;
75
76 char line[2048];
77 DECLARE_UNUSED(bool,res)
78
79 SState state;
80 state.delay = 0;
81 state.id = -1;
82
83 while( pStream->ReadLine(line, sizeof(line)) )
84 {
85 if (*line == 0 || *line == '\r' || *line == '\n' || *line == '#')
86 continue;
87 else if (strncmp("langidx:", line, 8) == 0)
88 res = ParseLangIdx(state, line + 8);
89 else if (strncmp("delay:", line, 6) == 0)
90 res = ParseDelay(state, line + 6);
91 else if (strncmp("id:", line, 3) == 0)
92 res = ParseId(state, line + 3);
93 else if (strncmp("timestamp:", line, 10) == 0)
94 res = ParseTimestamp(state, line + 10);
95 else if (strncmp("palette:", line, 8) == 0
96 || strncmp("size:", line, 5) == 0
97 || strncmp("org:", line, 4) == 0
98 || strncmp("custom colors:", line, 14) == 0
99 || strncmp("scale:", line, 6) == 0
100 || strncmp("alpha:", line, 6) == 0
101 || strncmp("fadein/out:", line, 11) == 0
102 || strncmp("forced subs:", line, 12) == 0)
103 res = ParseExtra(state, line);
104 else
105 continue;
106 }
107
108 struct sorter s;
109 sort(m_Timestamps.begin(), m_Timestamps.end(), s);
110 m_Timestamp = m_Timestamps.begin();
111
112 for(unsigned i=0;i<m_Streams.size();i++)
113 {
114 m_Streams[i]->ExtraSize = state.extra.length()+1;
115 m_Streams[i]->ExtraData = new uint8_t[m_Streams[i]->ExtraSize];
116 strcpy((char*)m_Streams[i]->ExtraData, state.extra.c_str());
117 }
118
119 return true;
120}
121
122void CDVDDemuxVobsub::Reset()
123{
124 Flush();
125}
126
127void CDVDDemuxVobsub::Flush()
128{
129 m_Demuxer->Flush();
130}
131
132bool CDVDDemuxVobsub::SeekTime(int time, bool backwords, double* startpts)
133{
134 double pts = DVD_MSEC_TO_TIME(time);
135 m_Timestamp = m_Timestamps.begin();
136 for(;m_Timestamp != m_Timestamps.end();++m_Timestamp)
137 {
138 if(m_Timestamp->pts > pts)
139 break;
140 }
141 for(unsigned i=0;i<m_Streams.size() && m_Timestamps.begin() != m_Timestamp;i++)
142 {
143 --m_Timestamp;
144 }
145 return true;
146}
147
148DemuxPacket* CDVDDemuxVobsub::Read()
149{
150 vector<STimestamp>::iterator current;
151 do {
152 if(m_Timestamp == m_Timestamps.end())
153 return NULL;
154
155 current = m_Timestamp++;
156 } while(m_Streams[current->id]->m_discard == AVDISCARD_ALL);
157
158 if(!m_Demuxer->SeekByte(current->pos))
159 return NULL;
160
161 DemuxPacket *packet = m_Demuxer->Read();
162 if(!packet)
163 return NULL;
164
165 packet->iStreamId = current->id;
166 packet->pts = current->pts;
167 packet->dts = current->pts;
168
169 return packet;
170}
171
172bool CDVDDemuxVobsub::ParseLangIdx(SState& state, char* line)
173{
174 return true;
175}
176
177bool CDVDDemuxVobsub::ParseDelay(SState& state, char* line)
178{
179 int h,m,s,ms;
180 bool negative = false;
181
182 while(*line == ' ') line++;
183 if(*line == '-')
184 {
185 line++;
186 negative = true;
187 }
188 if(sscanf(line, "%d:%d:%d:%d", &h, &m, &s, &ms) != 4)
189 return false;
190 state.delay = h*3600.0 + m*60.0 + s + ms*0.001;
191 if(negative)
192 state.delay *= -1;
193 return true;
194}
195
196bool CDVDDemuxVobsub::ParseId(SState& state, char* line)
197{
198 unique_ptr<CStream> stream(new CStream(this));
199
200 while(*line == ' ') line++;
201 strncpy(stream->language, line, 2);
202 stream->language[2] = '\0';
203 line+=2;
204
205 while(*line == ' ' || *line == ',') line++;
206 if (strncmp("index:", line, 6) == 0)
207 {
208 line+=6;
209 while(*line == ' ') line++;
210 stream->iPhysicalId = atoi(line);
211 }
212 else
213 stream->iPhysicalId = -1;
214
215 stream->codec = AV_CODEC_ID_DVD_SUBTITLE;
216 stream->iId = m_Streams.size();
217 stream->source = STREAM_SOURCE_DEMUX_SUB;
218
219 state.id = stream->iId;
220 m_Streams.push_back(stream.release());
221 return true;
222}
223
224bool CDVDDemuxVobsub::ParseExtra(SState& state, char* line)
225{
226 state.extra += line;
227 state.extra += '\n';
228 return true;
229}
230
231bool CDVDDemuxVobsub::ParseTimestamp(SState& state, char* line)
232{
233 if(state.id < 0)
234 return false;
235
236 int h,m,s,ms;
237 STimestamp timestamp;
238
239 while(*line == ' ') line++;
240 if(sscanf(line, "%d:%d:%d:%d, filepos:%" PRIx64, &h, &m, &s, &ms, &timestamp.pos) != 5)
241 return false;
242
243 timestamp.id = state.id;
244 timestamp.pts = DVD_SEC_TO_TIME(state.delay + h*3600.0 + m*60.0 + s + ms*0.001);
245 m_Timestamps.push_back(timestamp);
246 return true;
247}