PageRenderTime 26ms CodeModel.GetById 2ms app.highlight 20ms RepoModel.GetById 2ms app.codeStats 0ms

/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxVobsub.cpp

http://github.com/xbmc/xbmc
C++ | 246 lines | 188 code | 39 blank | 19 comment | 73 complexity | 4e5823bfa2331cbc8ab9cecb5c203286 MD5 | raw file
  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  auto_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  auto_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
218  state.id = stream->iId;
219  m_Streams.push_back(stream.release());
220  return true;
221}
222
223bool CDVDDemuxVobsub::ParseExtra(SState& state, char* line)
224{
225  state.extra += line;
226  state.extra += '\n';
227  return true;
228}
229
230bool CDVDDemuxVobsub::ParseTimestamp(SState& state, char* line)
231{
232  if(state.id < 0)
233    return false;
234
235  int h,m,s,ms;
236  STimestamp timestamp;
237
238  while(*line == ' ') line++;
239  if(sscanf(line, "%d:%d:%d:%d, filepos:%"PRIx64, &h, &m, &s, &ms, &timestamp.pos) != 5)
240    return false;
241
242  timestamp.id  = state.id;
243  timestamp.pts = DVD_SEC_TO_TIME(state.delay + h*3600.0 + m*60.0 + s + ms*0.001);
244  m_Timestamps.push_back(timestamp);
245  return true;
246}