- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# 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