00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "stdafx.h"
00023 #include "SubtitleInputPin.h"
00024 #include "VobSubFile.h"
00025 #include "RTS.h"
00026
00027 #include <initguid.h>
00028 #include "..\..\include\matroska\matroska.h"
00029
00030
00031 #define __GAB1__ "GAB1"
00032
00033
00034
00035
00036 #define __GAB1_LANGUAGE__ 0
00037
00038 #define __GAB1_ENTRY__ 1
00039
00040 #define __GAB1_LANGUAGE_UNICODE__ 2
00041
00042 #define __GAB1_ENTRY_UNICODE__ 3
00043
00044
00045 #define __GAB2__ "GAB2"
00046
00047
00048 #define __GAB1_RAWTEXTSUBTITLE__ 4
00049
00050 CSubtitleInputPin::CSubtitleInputPin(CBaseFilter* pFilter, CCritSec* pLock, CCritSec* pSubLock, HRESULT* phr)
00051 : CBaseInputPin(NAME("CSubtitleInputPin"), pFilter, pLock, phr, L"Input")
00052 , m_pSubLock(pSubLock)
00053 {
00054 m_bCanReconnectWhenActive = TRUE;
00055 }
00056
00057 HRESULT CSubtitleInputPin::CheckMediaType(const CMediaType* pmt)
00058 {
00059 return pmt->majortype == MEDIATYPE_Text && (pmt->subtype == MEDIASUBTYPE_NULL || pmt->subtype == FOURCCMap((DWORD)0))
00060 || pmt->majortype == MEDIATYPE_Subtitle && pmt->subtype == MEDIASUBTYPE_UTF8
00061 || pmt->majortype == MEDIATYPE_Subtitle && (pmt->subtype == MEDIASUBTYPE_SSA || pmt->subtype == MEDIASUBTYPE_ASS)
00062 || pmt->majortype == MEDIATYPE_Subtitle && (pmt->subtype == MEDIASUBTYPE_VOBSUB)
00063 ? S_OK
00064 : E_FAIL;
00065 }
00066
00067 HRESULT CSubtitleInputPin::CompleteConnect(IPin* pReceivePin)
00068 {
00069 if(m_mt.majortype == MEDIATYPE_Text)
00070 {
00071 if(!(m_pSubStream = new CRenderedTextSubtitle(m_pSubLock))) return E_FAIL;
00072 CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
00073 pRTS->m_name = CString(GetPinName(pReceivePin)) + _T(" (embeded)");
00074 pRTS->m_dstScreenSize = CSize(384, 288);
00075 pRTS->CreateDefaultStyle(DEFAULT_CHARSET);
00076 }
00077 else if(m_mt.majortype == MEDIATYPE_Subtitle)
00078 {
00079 SUBTITLEINFO* psi = (SUBTITLEINFO*)m_mt.pbFormat;
00080 DWORD dwOffset = psi->dwOffset;
00081
00082 CString name = ISO6392ToLanguage(psi->IsoLang);
00083 if(name.IsEmpty()) name = _T("English");
00084 if(wcslen(psi->TrackName) > 0) name += _T(" (") + CString(psi->TrackName) + _T(")");
00085
00086 if(m_mt.subtype == MEDIASUBTYPE_UTF8
00087 || m_mt.subtype == MEDIASUBTYPE_SSA || m_mt.subtype == MEDIASUBTYPE_ASS)
00088 {
00089 if(!(m_pSubStream = new CRenderedTextSubtitle(m_pSubLock))) return E_FAIL;
00090 CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
00091 pRTS->m_name = name;
00092 pRTS->m_dstScreenSize = CSize(384, 288);
00093 pRTS->CreateDefaultStyle(DEFAULT_CHARSET);
00094
00095 if(dwOffset > 0 && m_mt.cbFormat - dwOffset > 0)
00096 {
00097 CMediaType mt = m_mt;
00098 if(mt.pbFormat[dwOffset+0] != 0xef
00099 && mt.pbFormat[dwOffset+1] != 0xbb
00100 && mt.pbFormat[dwOffset+2] != 0xfb)
00101 {
00102 dwOffset -= 3;
00103 mt.pbFormat[dwOffset+0] = 0xef;
00104 mt.pbFormat[dwOffset+1] = 0xbb;
00105 mt.pbFormat[dwOffset+2] = 0xbf;
00106 }
00107
00108 pRTS->Open(mt.pbFormat + dwOffset, mt.cbFormat - dwOffset, DEFAULT_CHARSET, pRTS->m_name);
00109 }
00110
00111 }
00112 else if(m_mt.subtype == MEDIASUBTYPE_VOBSUB)
00113 {
00114 if(!(m_pSubStream = new CVobSubStream(m_pSubLock))) return E_FAIL;
00115 CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)m_pSubStream;
00116 pVSS->Open(name, m_mt.pbFormat + dwOffset, m_mt.cbFormat - dwOffset);
00117 }
00118 }
00119
00120 AddSubStream(m_pSubStream);
00121
00122 return __super::CompleteConnect(pReceivePin);
00123 }
00124
00125 HRESULT CSubtitleInputPin::BreakConnect()
00126 {
00127 RemoveSubStream(m_pSubStream);
00128 m_pSubStream = NULL;
00129
00130 ASSERT(IsStopped());
00131
00132 return __super::BreakConnect();
00133 }
00134
00135 STDMETHODIMP CSubtitleInputPin::ReceiveConnection(IPin* pConnector, const AM_MEDIA_TYPE* pmt)
00136 {
00137 if(m_Connected)
00138 {
00139 RemoveSubStream(m_pSubStream);
00140 m_pSubStream = NULL;
00141
00142 m_Connected->Release();
00143 m_Connected = NULL;
00144 }
00145
00146 return __super::ReceiveConnection(pConnector, pmt);
00147 }
00148
00149 STDMETHODIMP CSubtitleInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
00150 {
00151 CAutoLock cAutoLock(&m_csReceive);
00152
00153 if(m_mt.majortype == MEDIATYPE_Text
00154 || m_mt.majortype == MEDIATYPE_Subtitle
00155 && (m_mt.subtype == MEDIASUBTYPE_UTF8
00156 || m_mt.subtype == MEDIASUBTYPE_SSA || m_mt.subtype == MEDIASUBTYPE_ASS))
00157 {
00158 CAutoLock cAutoLock(m_pSubLock);
00159 CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
00160 pRTS->RemoveAll();
00161 pRTS->CreateSegments();
00162 }
00163 else if(m_mt.majortype == MEDIATYPE_Subtitle
00164 && (m_mt.subtype == MEDIASUBTYPE_VOBSUB))
00165 {
00166 CAutoLock cAutoLock(m_pSubLock);
00167 CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)m_pSubStream;
00168 pVSS->RemoveAll();
00169 }
00170
00171 return __super::NewSegment(tStart, tStop, dRate);
00172 }
00173
00174 STDMETHODIMP CSubtitleInputPin::Receive(IMediaSample* pSample)
00175 {
00176 HRESULT hr;
00177
00178 hr = __super::Receive(pSample);
00179 if(FAILED(hr)) return hr;
00180
00181 CAutoLock cAutoLock(&m_csReceive);
00182
00183 REFERENCE_TIME tStart, tStop;
00184 pSample->GetTime(&tStart, &tStop);
00185 tStart += m_tStart;
00186 tStop += m_tStart;
00187
00188 BYTE* pData = NULL;
00189 hr = pSample->GetPointer(&pData);
00190 if(FAILED(hr) || pData == NULL) return hr;
00191
00192 int len = pSample->GetActualDataLength();
00193
00194 bool fInvalidate = false;
00195
00196 if(m_mt.majortype == MEDIATYPE_Text)
00197 {
00198 CAutoLock cAutoLock(m_pSubLock);
00199 CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
00200
00201 if(!strncmp((char*)pData, __GAB1__, strlen(__GAB1__)))
00202 {
00203 char* ptr = (char*)&pData[strlen(__GAB1__)+1];
00204 char* end = (char*)&pData[len];
00205
00206 while(ptr < end)
00207 {
00208 WORD tag = *((WORD*)(ptr)); ptr += 2;
00209 WORD size = *((WORD*)(ptr)); ptr += 2;
00210
00211 if(tag == __GAB1_LANGUAGE__)
00212 {
00213 pRTS->m_name = CString(ptr);
00214 }
00215 else if(tag == __GAB1_ENTRY__)
00216 {
00217 pRTS->Add(AToW(&ptr[8]), false, *(int*)ptr, *(int*)(ptr+4));
00218 fInvalidate = true;
00219 }
00220 else if(tag == __GAB1_LANGUAGE_UNICODE__)
00221 {
00222 pRTS->m_name = (WCHAR*)ptr;
00223 }
00224 else if(tag == __GAB1_ENTRY_UNICODE__)
00225 {
00226 pRTS->Add((WCHAR*)(ptr+8), true, *(int*)ptr, *(int*)(ptr+4));
00227 fInvalidate = true;
00228 }
00229
00230 ptr += size;
00231 }
00232 }
00233 else if(!strncmp((char*)pData, __GAB2__, strlen(__GAB2__)))
00234 {
00235 char* ptr = (char*)&pData[strlen(__GAB2__)+1];
00236 char* end = (char*)&pData[len];
00237
00238 while(ptr < end)
00239 {
00240 WORD tag = *((WORD*)(ptr)); ptr += 2;
00241 DWORD size = *((DWORD*)(ptr)); ptr += 4;
00242
00243 if(tag == __GAB1_LANGUAGE_UNICODE__)
00244 {
00245 pRTS->m_name = (WCHAR*)ptr;
00246 }
00247 else if(tag == __GAB1_RAWTEXTSUBTITLE__)
00248 {
00249 pRTS->Open((BYTE*)ptr, size, DEFAULT_CHARSET, pRTS->m_name);
00250 fInvalidate = true;
00251 }
00252
00253 ptr += size;
00254 }
00255 }
00256 else if(pData != 0 && len > 1 && *pData != 0)
00257 {
00258 CStringA str((char*)pData, len);
00259
00260 str.Replace("\r\n", "\n");
00261 str.Trim();
00262
00263 if(!str.IsEmpty())
00264 {
00265 pRTS->Add(AToW(str), false, (int)(tStart / 10000), (int)(tStop / 10000));
00266 fInvalidate = true;
00267 }
00268 }
00269 }
00270 else if(m_mt.majortype == MEDIATYPE_Subtitle)
00271 {
00272 CAutoLock cAutoLock(m_pSubLock);
00273
00274 if(m_mt.subtype == MEDIASUBTYPE_UTF8)
00275 {
00276 CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
00277
00278 CStringW str = UTF8To16(CStringA((LPCSTR)pData, len)).Trim();
00279 if(!str.IsEmpty())
00280 {
00281 pRTS->Add(str, true, (int)(tStart / 10000), (int)(tStop / 10000));
00282 fInvalidate = true;
00283 }
00284 }
00285 else if(m_mt.subtype == MEDIASUBTYPE_SSA || m_mt.subtype == MEDIASUBTYPE_ASS)
00286 {
00287 CRenderedTextSubtitle* pRTS = (CRenderedTextSubtitle*)(ISubStream*)m_pSubStream;
00288
00289 CStringW str = UTF8To16(CStringA((LPCSTR)pData, len)).Trim();
00290 if(!str.IsEmpty())
00291 {
00292 STSEntry stse;
00293
00294 CList<CStringW> sl;
00295 Explode(str, sl, ',', 9);
00296 if(sl.GetCount() == 9)
00297 {
00298 stse.readorder = wcstol(sl.RemoveHead(), NULL, 10);
00299 stse.layer = wcstol(sl.RemoveHead(), NULL, 10);
00300 stse.style = sl.RemoveHead();
00301 stse.actor = sl.RemoveHead();
00302 stse.marginRect.left = wcstol(sl.RemoveHead(), NULL, 10);
00303 stse.marginRect.right = wcstol(sl.RemoveHead(), NULL, 10);
00304 stse.marginRect.top = stse.marginRect.bottom = wcstol(sl.RemoveHead(), NULL, 10);
00305 stse.effect = sl.RemoveHead();
00306 stse.str = sl.RemoveHead();
00307 }
00308
00309 if(!stse.str.IsEmpty())
00310 {
00311 pRTS->Add(stse.str, true, (int)(tStart / 10000), (int)(tStop / 10000),
00312 stse.style, stse.actor, stse.effect, stse.marginRect, stse.layer, stse.readorder);
00313 fInvalidate = true;
00314 }
00315 }
00316 }
00317 else if(m_mt.subtype == MEDIASUBTYPE_VOBSUB)
00318 {
00319 CVobSubStream* pVSS = (CVobSubStream*)(ISubStream*)m_pSubStream;
00320 pVSS->Add(tStart, tStop, pData, len);
00321 }
00322 }
00323
00324 if(fInvalidate)
00325 {
00326 TRACE(_T("InvalidateSubtitle(%I64d, ..)\n"), tStart);
00327
00328 InvalidateSubtitle(tStart, m_pSubStream);
00329 }
00330
00331 hr = S_OK;
00332
00333 return hr;
00334 }
00335