SubtitleInputPin.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:10k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.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 GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "stdafx.h"
  22. #include "SubtitleInputPin.h"
  23. #include "VobSubFile.h"
  24. #include "RTS.h"
  25. #include <initguid.h>
  26. #include "....includematroskamatroska.h"
  27. // our first format id
  28. #define __GAB1__ "GAB1"
  29. // our tags for __GAB1__ (ushort) + size (ushort)
  30. // "lang" + '0'
  31. #define __GAB1_LANGUAGE__ 0
  32. // (int)start+(int)stop+(char*)line+'0'
  33. #define __GAB1_ENTRY__ 1
  34. // L"lang" + '0'
  35. #define __GAB1_LANGUAGE_UNICODE__ 2
  36. // (int)start+(int)stop+(WCHAR*)line+'0'
  37. #define __GAB1_ENTRY_UNICODE__ 3
  38. // same as __GAB1__, but the size is (uint) and only __GAB1_LANGUAGE_UNICODE__ is valid
  39. #define __GAB2__ "GAB2"
  40. // (BYTE*)
  41. #define __GAB1_RAWTEXTSUBTITLE__ 4
  42. CSubtitleInputPin::CSubtitleInputPin(CBaseFilter* pFilter, CCritSec* pLock, CCritSec* pSubLock, HRESULT* phr)
  43. : CBaseInputPin(NAME("CSubtitleInputPin"), pFilter, pLock, phr, L"Input")
  44. , m_pSubLock(pSubLock)
  45. {
  46. m_bCanReconnectWhenActive = TRUE;
  47. }
  48. HRESULT CSubtitleInputPin::CheckMediaType(const CMediaType* pmt)
  49. {
  50. return pmt->majortype == MEDIATYPE_Text && (pmt->subtype == MEDIASUBTYPE_NULL || pmt->subtype == FOURCCMap((DWORD)0))
  51. || pmt->majortype == MEDIATYPE_Subtitle && pmt->subtype == MEDIASUBTYPE_UTF8
  52. || pmt->majortype == MEDIATYPE_Subtitle && (pmt->subtype == MEDIASUBTYPE_SSA || pmt->subtype == MEDIASUBTYPE_ASS)
  53. || pmt->majortype == MEDIATYPE_Subtitle && (pmt->subtype == MEDIASUBTYPE_VOBSUB)
  54. ? S_OK 
  55. : E_FAIL;
  56. }
  57. HRESULT CSubtitleInputPin::CompleteConnect(IPin* pReceivePin)
  58. {
  59. if(m_mt.majortype == MEDIATYPE_Text)
  60. {
  61. if(!(m_pSubStream = new CRenderedTextSubtitle(m_pSubLock))) return E_FAIL;
  62. CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
  63. pRTS->m_name = CString(GetPinName(pReceivePin)) + _T(" (embeded)");
  64. pRTS->m_dstScreenSize = CSize(384, 288);
  65. pRTS->CreateDefaultStyle(DEFAULT_CHARSET);
  66. }
  67. else if(m_mt.majortype == MEDIATYPE_Subtitle)
  68. {
  69. SUBTITLEINFO* psi = (SUBTITLEINFO*)m_mt.pbFormat;
  70. DWORD dwOffset = psi->dwOffset;
  71. CString name = ISO6392ToLanguage(psi->IsoLang);
  72. if(name.IsEmpty()) name = _T("English");
  73. if(wcslen(psi->TrackName) > 0) name += _T(" (") + CString(psi->TrackName) + _T(")");
  74. if(m_mt.subtype == MEDIASUBTYPE_UTF8 /*|| m_mt.subtype == MEDIASUBTYPE_USF*/
  75. || m_mt.subtype == MEDIASUBTYPE_SSA || m_mt.subtype == MEDIASUBTYPE_ASS)
  76. {
  77. if(!(m_pSubStream = new CRenderedTextSubtitle(m_pSubLock))) return E_FAIL;
  78. CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
  79. pRTS->m_name = name;
  80. pRTS->m_dstScreenSize = CSize(384, 288);
  81. pRTS->CreateDefaultStyle(DEFAULT_CHARSET);
  82. if(dwOffset > 0 && m_mt.cbFormat - dwOffset > 0)
  83. {
  84. CMediaType mt = m_mt;
  85. if(mt.pbFormat[dwOffset+0] != 0xef
  86. && mt.pbFormat[dwOffset+1] != 0xbb
  87. && mt.pbFormat[dwOffset+2] != 0xfb)
  88. {
  89. dwOffset -= 3;
  90. mt.pbFormat[dwOffset+0] = 0xef;
  91. mt.pbFormat[dwOffset+1] = 0xbb;
  92. mt.pbFormat[dwOffset+2] = 0xbf;
  93. }
  94. pRTS->Open(mt.pbFormat + dwOffset, mt.cbFormat - dwOffset, DEFAULT_CHARSET, pRTS->m_name);
  95. }
  96. }
  97. else if(m_mt.subtype == MEDIASUBTYPE_VOBSUB)
  98. {
  99. if(!(m_pSubStream = new CVobSubStream(m_pSubLock))) return E_FAIL;
  100. CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)m_pSubStream;
  101. pVSS->Open(name, m_mt.pbFormat + dwOffset, m_mt.cbFormat - dwOffset);
  102. }
  103. }
  104. AddSubStream(m_pSubStream);
  105.     return __super::CompleteConnect(pReceivePin);
  106. }
  107. HRESULT CSubtitleInputPin::BreakConnect()
  108. {
  109. RemoveSubStream(m_pSubStream);
  110. m_pSubStream = NULL;
  111. ASSERT(IsStopped());
  112.     return __super::BreakConnect();
  113. }
  114. STDMETHODIMP CSubtitleInputPin::ReceiveConnection(IPin* pConnector, const AM_MEDIA_TYPE* pmt)
  115. {
  116. if(m_Connected)
  117. {
  118. RemoveSubStream(m_pSubStream);
  119. m_pSubStream = NULL;
  120.         m_Connected->Release();
  121.         m_Connected = NULL;
  122. }
  123. return __super::ReceiveConnection(pConnector, pmt);
  124. }
  125. STDMETHODIMP CSubtitleInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
  126. {
  127. CAutoLock cAutoLock(&m_csReceive);
  128. if(m_mt.majortype == MEDIATYPE_Text
  129. || m_mt.majortype == MEDIATYPE_Subtitle 
  130. && (m_mt.subtype == MEDIASUBTYPE_UTF8 /*|| m_mt.subtype == MEDIASUBTYPE_USF*/
  131. || m_mt.subtype == MEDIASUBTYPE_SSA || m_mt.subtype == MEDIASUBTYPE_ASS))
  132. {
  133. CAutoLock cAutoLock(m_pSubLock);
  134. CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
  135. pRTS->RemoveAll();
  136. pRTS->CreateSegments();
  137. }
  138. else if(m_mt.majortype == MEDIATYPE_Subtitle 
  139. && (m_mt.subtype == MEDIASUBTYPE_VOBSUB))
  140. {
  141. CAutoLock cAutoLock(m_pSubLock);
  142. CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)m_pSubStream;
  143. pVSS->RemoveAll();
  144. }
  145. return __super::NewSegment(tStart, tStop, dRate);
  146. }
  147. STDMETHODIMP CSubtitleInputPin::Receive(IMediaSample* pSample)
  148. {
  149. HRESULT hr;
  150. hr = __super::Receive(pSample);
  151.     if(FAILED(hr)) return hr;
  152. CAutoLock cAutoLock(&m_csReceive);
  153. REFERENCE_TIME tStart, tStop;
  154.     pSample->GetTime(&tStart, &tStop);
  155. tStart += m_tStart; 
  156. tStop += m_tStart;
  157. BYTE* pData = NULL;
  158.     hr = pSample->GetPointer(&pData);
  159.     if(FAILED(hr) || pData == NULL) return hr;
  160. int len = pSample->GetActualDataLength();
  161. bool fInvalidate = false;
  162. if(m_mt.majortype == MEDIATYPE_Text)
  163. {
  164. CAutoLock cAutoLock(m_pSubLock);
  165. CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
  166. if(!strncmp((char*)pData, __GAB1__, strlen(__GAB1__)))
  167. {
  168. char* ptr = (char*)&pData[strlen(__GAB1__)+1];
  169. char* end = (char*)&pData[len];
  170. while(ptr < end)
  171. {
  172. WORD tag = *((WORD*)(ptr)); ptr += 2;
  173. WORD size = *((WORD*)(ptr)); ptr += 2;
  174. if(tag == __GAB1_LANGUAGE__)
  175. {
  176. pRTS->m_name = CString(ptr);
  177. }
  178. else if(tag == __GAB1_ENTRY__)
  179. {
  180. pRTS->Add(AToW(&ptr[8]), false, *(int*)ptr, *(int*)(ptr+4));
  181. fInvalidate = true;
  182. }
  183. else if(tag == __GAB1_LANGUAGE_UNICODE__)
  184. {
  185. pRTS->m_name = (WCHAR*)ptr;
  186. }
  187. else if(tag == __GAB1_ENTRY_UNICODE__)
  188. {
  189. pRTS->Add((WCHAR*)(ptr+8), true, *(int*)ptr, *(int*)(ptr+4));
  190. fInvalidate = true;
  191. }
  192. ptr += size;
  193. }
  194. }
  195. else if(!strncmp((char*)pData, __GAB2__, strlen(__GAB2__)))
  196. {
  197. char* ptr = (char*)&pData[strlen(__GAB2__)+1];
  198. char* end = (char*)&pData[len];
  199. while(ptr < end)
  200. {
  201. WORD tag = *((WORD*)(ptr)); ptr += 2;
  202. DWORD size = *((DWORD*)(ptr)); ptr += 4;
  203. if(tag == __GAB1_LANGUAGE_UNICODE__)
  204. {
  205. pRTS->m_name = (WCHAR*)ptr;
  206. }
  207. else if(tag == __GAB1_RAWTEXTSUBTITLE__)
  208. {
  209. pRTS->Open((BYTE*)ptr, size, DEFAULT_CHARSET, pRTS->m_name);
  210. fInvalidate = true;
  211. }
  212. ptr += size;
  213. }
  214. }
  215. else if(pData != 0 && len > 1 && *pData != 0)
  216. {
  217. CStringA str((char*)pData, len);
  218. str.Replace("rn", "n");
  219. str.Trim();
  220. if(!str.IsEmpty())
  221. {
  222. pRTS->Add(AToW(str), false, (int)(tStart / 10000), (int)(tStop / 10000));
  223. fInvalidate = true;
  224. }
  225. }
  226. }
  227. else if(m_mt.majortype == MEDIATYPE_Subtitle)
  228. {
  229. CAutoLock cAutoLock(m_pSubLock);
  230. if(m_mt.subtype == MEDIASUBTYPE_UTF8)
  231. {
  232. CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
  233. CStringW str = UTF8To16(CStringA((LPCSTR)pData, len)).Trim();
  234. if(!str.IsEmpty())
  235. {
  236. pRTS->Add(str, true, (int)(tStart / 10000), (int)(tStop / 10000));
  237. fInvalidate = true;
  238. }
  239. }
  240. else if(m_mt.subtype == MEDIASUBTYPE_SSA || m_mt.subtype == MEDIASUBTYPE_ASS)
  241. {
  242. CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
  243. CStringW str = UTF8To16(CStringA((LPCSTR)pData, len)).Trim();
  244. if(!str.IsEmpty())
  245. {
  246. STSEntry stse;
  247. CList<CStringW> sl;
  248. Explode(str, sl, ',', 9);
  249. if(sl.GetCount() == 9)
  250. {
  251. stse.readorder = wcstol(sl.RemoveHead(), NULL, 10);
  252. stse.layer = wcstol(sl.RemoveHead(), NULL, 10);
  253. stse.style = sl.RemoveHead();
  254. stse.actor = sl.RemoveHead();
  255. stse.marginRect.left = wcstol(sl.RemoveHead(), NULL, 10);
  256. stse.marginRect.right = wcstol(sl.RemoveHead(), NULL, 10);
  257. stse.marginRect.top = stse.marginRect.bottom = wcstol(sl.RemoveHead(), NULL, 10);
  258. stse.effect = sl.RemoveHead();
  259. stse.str = sl.RemoveHead();
  260. }
  261. if(!stse.str.IsEmpty())
  262. {
  263. pRTS->Add(stse.str, true, (int)(tStart / 10000), (int)(tStop / 10000), 
  264. stse.style, stse.actor, stse.effect, stse.marginRect, stse.layer, stse.readorder);
  265. fInvalidate = true;
  266. }
  267. }
  268. }
  269. else if(m_mt.subtype == MEDIASUBTYPE_VOBSUB)
  270. {
  271. CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)m_pSubStream;
  272. pVSS->Add(tStart, tStop, pData, len);
  273. }
  274. }
  275. if(fInvalidate)
  276. {
  277. TRACE(_T("InvalidateSubtitle(%I64d, ..)n"), tStart);
  278. // IMPORTANT: m_pSubLock must not be locked when calling this
  279. InvalidateSubtitle(tStart, m_pSubStream);
  280. }
  281. hr = S_OK;
  282.     return hr;
  283. }