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

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