SubtitleInputPin.cpp

00001 /* 
00002  *      Copyright (C) 2003-2005 Gabest
00003  *      http://www.gabest.org
00004  *
00005  *  This Program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2, or (at your option)
00008  *  any later version.
00009  *   
00010  *  This Program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  *  GNU General Public License for more details.
00014  *   
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with GNU Make; see the file COPYING.  If not, write to
00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
00018  *  http://www.gnu.org/copyleft/gpl.html
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 // our first format id
00031 #define __GAB1__ "GAB1"
00032 
00033 // our tags for __GAB1__ (ushort) + size (ushort)
00034 
00035 // "lang" + '0'
00036 #define __GAB1_LANGUAGE__ 0
00037 // (int)start+(int)stop+(char*)line+'0'
00038 #define __GAB1_ENTRY__ 1
00039 // L"lang" + '0'
00040 #define __GAB1_LANGUAGE_UNICODE__ 2
00041 // (int)start+(int)stop+(WCHAR*)line+'0'
00042 #define __GAB1_ENTRY_UNICODE__ 3
00043 
00044 // same as __GAB1__, but the size is (uint) and only __GAB1_LANGUAGE_UNICODE__ is valid
00045 #define __GAB2__ "GAB2"
00046 
00047 // (BYTE*)
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 /*|| m_mt.subtype == MEDIASUBTYPE_USF*/
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 /*|| m_mt.subtype == MEDIASUBTYPE_USF*/
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                 // IMPORTANT: m_pSubLock must not be locked when calling this
00328                 InvalidateSubtitle(tStart, m_pSubStream);
00329         }
00330 
00331         hr = S_OK;
00332 
00333     return hr;
00334 }
00335 

Generated on Tue Dec 13 14:47:55 2005 for guliverkli by  doxygen 1.4.5