- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# SubtitleSource.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 "subtitlesource.h"
    00024 #include "..\..\..\DSUtil\DSUtil.h"
    00025
    00026 #include <initguid.h>
    00027 #include "..\..\..\..\include\matroska\matroska.h"
    00028
    00029 static int _WIDTH = 640;
    00030 static int _HEIGHT = 480;
    00031 static int _ATPF = 400000;
    00032
    00033 #ifdef REGISTER_FILTER
    00034
    00035 const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
    00036 {
    00037         {&MEDIATYPE_Subtitle, &MEDIASUBTYPE_NULL},
    00038         {&MEDIATYPE_Text, &MEDIASUBTYPE_NULL},
    00039         {&MEDIATYPE_Video, &MEDIASUBTYPE_RGB32},
    00040 };
    00041
    00042 const AMOVIESETUP_PIN sudOpPin[] =
    00043 {
    00044         {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut},
    00045 };
    00046
    00047 const AMOVIESETUP_FILTER sudFilter[] =
    00048 {
    00049         {&__uuidof(CSubtitleSourceASCII), L"SubtitleSource (S_TEXT/ASCII)", MERIT_UNLIKELY, countof(sudOpPin), sudOpPin},
    00050         {&__uuidof(CSubtitleSourceUTF8), L"SubtitleSource (S_TEXT/UTF8)", MERIT_UNLIKELY, countof(sudOpPin), sudOpPin},
    00051         {&__uuidof(CSubtitleSourceSSA), L"SubtitleSource (S_TEXT/SSA)", MERIT_UNLIKELY, countof(sudOpPin), sudOpPin},
    00052         {&__uuidof(CSubtitleSourceASS), L"SubtitleSource (S_TEXT/ASS)", MERIT_UNLIKELY, countof(sudOpPin), sudOpPin},
    00053         {&__uuidof(CSubtitleSourceUSF), L"SubtitleSource (S_TEXT/USF)", MERIT_UNLIKELY, countof(sudOpPin), sudOpPin},
    00054         {&__uuidof(CSubtitleSourcePreview), L"SubtitleSource (Preview)", MERIT_UNLIKELY, countof(sudOpPin), sudOpPin},
    00055         {&__uuidof(CSubtitleSourceARGB), L"SubtitleSource (ARGB)", MERIT_UNLIKELY, countof(sudOpPin), sudOpPin},
    00056 };
    00057
    00058 CFactoryTemplate g_Templates[] =
    00059 {
    00060         {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CSubtitleSourceASCII>, NULL, &sudFilter[0]},
    00061         {sudFilter[1].strName, sudFilter[1].clsID, CreateInstance<CSubtitleSourceUTF8>, NULL, &sudFilter[1]},
    00062         {sudFilter[2].strName, sudFilter[2].clsID, CreateInstance<CSubtitleSourceSSA>, NULL, &sudFilter[2]},
    00063         {sudFilter[3].strName, sudFilter[3].clsID, CreateInstance<CSubtitleSourceASS>, NULL, &sudFilter[3]},
    00064 //      {sudFilter[4].strName, sudFilter[4].clsID, CreateInstance<CSubtitleSourceUSF>, NULL, &sudFilter[4]},
    00065         {sudFilter[5].strName, sudFilter[5].clsID, CreateInstance<CSubtitleSourcePreview>, NULL, &sudFilter[5]},
    00066         {sudFilter[6].strName, sudFilter[6].clsID, CreateInstance<CSubtitleSourceARGB>, NULL, &sudFilter[6]},
    00067 };
    00068
    00069 int g_cTemplates = countof(g_Templates);
    00070
    00071 #include "..\..\registry.cpp"
    00072
    00073 STDAPI DllRegisterServer()
    00074 {
    00075 /*
    00076         CString clsid = CStringFromGUID(__uuidof(CSubtitleSourcePreview));
    00077
    00078         SetRegKeyValue(
    00079                 _T("Media Type\\Extensions"), _T(".sub"),
    00080                 _T("Source Filter"), clsid);
    00081
    00082         SetRegKeyValue(
    00083                 _T("Media Type\\Extensions"), _T(".srt"),
    00084                 _T("Source Filter"), clsid);
    00085
    00086         SetRegKeyValue(
    00087                 _T("Media Type\\Extensions"), _T(".smi"),
    00088                 _T("Source Filter"), clsid);
    00089
    00090         SetRegKeyValue(
    00091                 _T("Media Type\\Extensions"), _T(".ssa"),
    00092                 _T("Source Filter"), clsid);
    00093
    00094         SetRegKeyValue(
    00095                 _T("Media Type\\Extensions"), _T(".ass"),
    00096                 _T("Source Filter"), clsid);
    00097
    00098         SetRegKeyValue(
    00099                 _T("Media Type\\Extensions"), _T(".xss"),
    00100                 _T("Source Filter"), clsid);
    00101
    00102         SetRegKeyValue(
    00103                 _T("Media Type\\Extensions"), _T(".usf"),
    00104                 _T("Source Filter"), clsid);
    00105 */
    00106         return AMovieDllRegisterServer2(TRUE);
    00107 }
    00108
    00109 STDAPI DllUnregisterServer()
    00110 {
    00111         DeleteRegKey(_T("Media Type\\Extensions"), _T(".sub"));
    00112         DeleteRegKey(_T("Media Type\\Extensions"), _T(".srt"));
    00113         DeleteRegKey(_T("Media Type\\Extensions"), _T(".smi"));
    00114         DeleteRegKey(_T("Media Type\\Extensions"), _T(".ssa"));
    00115         DeleteRegKey(_T("Media Type\\Extensions"), _T(".ass"));
    00116         DeleteRegKey(_T("Media Type\\Extensions"), _T(".xss"));
    00117         DeleteRegKey(_T("Media Type\\Extensions"), _T(".usf"));
    00118
    00119         return AMovieDllRegisterServer2(FALSE);
    00120 }
    00121
    00122 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
    00123
    00124 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
    00125 {
    00126         if(dwReason == DLL_PROCESS_ATTACH)
    00127         {
    00128                 _WIDTH = GetProfileInt(_T("SubtitleSource"), _T("w"), 640);
    00129                 _HEIGHT = GetProfileInt(_T("SubtitleSource"), _T("h"), 480);
    00130                 _ATPF = GetProfileInt(_T("SubtitleSource"), _T("atpf"), 400000);
    00131                 if(_ATPF <= 0) _ATPF = 400000;
    00132                 CString str;
    00133                 str.Format(_T("%d"), _WIDTH);
    00134                 WriteProfileString(_T("SubtitleSource"), _T("w"), str);
    00135                 str.Format(_T("%d"), _HEIGHT);
    00136                 WriteProfileString(_T("SubtitleSource"), _T("h"), str);
    00137                 str.Format(_T("%d"), _ATPF);
    00138                 WriteProfileString(_T("SubtitleSource"), _T("atpf"), str);
    00139         }
    00140
    00141     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
    00142 }
    00143
    00144 #endif
    00145
    00146 //
    00147 // CSubtitleSource
    00148 //
    00149
    00150 CSubtitleSource::CSubtitleSource(LPUNKNOWN lpunk, HRESULT* phr, const CLSID& clsid)
    00151         : CSource(NAME("CSubtitleSource"), lpunk, clsid)
    00152 {
    00153 }
    00154
    00155 CSubtitleSource::~CSubtitleSource()
    00156 {
    00157 }
    00158
    00159 STDMETHODIMP CSubtitleSource::NonDelegatingQueryInterface(REFIID riid, void** ppv)
    00160 {
    00161     CheckPointer(ppv, E_POINTER);
    00162
    00163         return
    00164                 QI(IFileSourceFilter)
    00165                 QI(IAMFilterMiscFlags)
    00166                 __super::NonDelegatingQueryInterface(riid, ppv);
    00167 }
    00168
    00169 // IFileSourceFilter
    00170
    00171 STDMETHODIMP CSubtitleSource::Load(LPCOLESTR pszFileName, const AM_MEDIA_TYPE* pmt)
    00172 {
    00173         if(GetPinCount() > 0)
    00174                 return VFW_E_ALREADY_CONNECTED;
    00175
    00176         HRESULT hr = S_OK;
    00177         if(!(new CSubtitleStream(pszFileName, this, &hr)))
    00178                 return E_OUTOFMEMORY;
    00179
    00180         if(FAILED(hr))
    00181                 return hr;
    00182
    00183         m_fn = pszFileName;
    00184
    00185         return S_OK;
    00186 }
    00187
    00188 STDMETHODIMP CSubtitleSource::GetCurFile(LPOLESTR* ppszFileName, AM_MEDIA_TYPE* pmt)
    00189 {
    00190         if(!ppszFileName) return E_POINTER;
    00191
    00192         if(!(*ppszFileName = (LPOLESTR)CoTaskMemAlloc((m_fn.GetLength()+1)*sizeof(WCHAR))))
    00193                 return E_OUTOFMEMORY;
    00194
    00195         wcscpy(*ppszFileName, m_fn);
    00196
    00197         return S_OK;
    00198 }
    00199
    00200 // IAMFilterMiscFlags
    00201
    00202 ULONG CSubtitleSource::GetMiscFlags()
    00203 {
    00204         return AM_FILTER_MISC_FLAGS_IS_SOURCE;
    00205 }
    00206
    00207 //
    00208 // CSubtitleStream
    00209 //
    00210
    00211 CSubtitleStream::CSubtitleStream(const WCHAR* wfn, CSubtitleSource* pParent, HRESULT* phr)
    00212         : CSourceStream(NAME("SubtitleStream"), phr, pParent, L"Output")
    00213         , CSourceSeeking(NAME("SubtitleStream"), (IPin*)this, phr, &m_cSharedState)
    00214         , m_bDiscontinuity(FALSE), m_bFlushing(FALSE)
    00215         , m_nPosition(0)
    00216         , m_rts(NULL)
    00217 {
    00218         CAutoLock cAutoLock(&m_cSharedState);
    00219
    00220         CString fn(wfn);
    00221
    00222         if(!m_rts.Open(fn, DEFAULT_CHARSET))
    00223         {
    00224                 if(phr) *phr = E_FAIL;
    00225                 return;
    00226         }
    00227
    00228         m_rts.CreateDefaultStyle(DEFAULT_CHARSET);
    00229         m_rts.ConvertToTimeBased(25);
    00230         m_rts.Sort();
    00231
    00232         m_rtDuration = 0;
    00233         for(int i = 0, cnt = m_rts.GetCount(); i < cnt; i++)
    00234                 m_rtDuration = max(m_rtDuration, 10000i64*m_rts[i].end);
    00235
    00236         m_rtStop = m_rtDuration;
    00237
    00238         if(phr) *phr = m_rtDuration > 0 ? S_OK : E_FAIL;
    00239 }
    00240
    00241 CSubtitleStream::~CSubtitleStream()
    00242 {
    00243         CAutoLock cAutoLock(&m_cSharedState);
    00244 }
    00245
    00246 STDMETHODIMP CSubtitleStream::NonDelegatingQueryInterface(REFIID riid, void** ppv)
    00247 {
    00248     CheckPointer(ppv, E_POINTER);
    00249
    00250         return (riid == IID_IMediaSeeking) ? CSourceSeeking::NonDelegatingQueryInterface(riid, ppv) //GetInterface((IMediaSeeking*)this, ppv)
    00251                 : CSourceStream::NonDelegatingQueryInterface(riid, ppv);
    00252 }
    00253
    00254 void CSubtitleStream::UpdateFromSeek()
    00255 {
    00256         if(ThreadExists())
    00257         {
    00258                 // next time around the loop, the worker thread will
    00259                 // pick up the position change.
    00260                 // We need to flush all the existing data - we must do that here
    00261                 // as our thread will probably be blocked in GetBuffer otherwise
    00262
    00263                 m_bFlushing = TRUE;
    00264
    00265                 DeliverBeginFlush();
    00266                 // make sure we have stopped pushing
    00267                 Stop();
    00268                 // complete the flush
    00269                 DeliverEndFlush();
    00270
    00271         m_bFlushing = FALSE;
    00272
    00273                 // restart
    00274                 Run();
    00275         }
    00276 }
    00277
    00278 HRESULT CSubtitleStream::SetRate(double dRate)
    00279 {
    00280         if(dRate <= 0)
    00281                 return E_INVALIDARG;
    00282
    00283         {
    00284                 CAutoLock lock(CSourceSeeking::m_pLock);
    00285                 m_dRateSeeking = dRate;
    00286         }
    00287
    00288         UpdateFromSeek();
    00289
    00290         return S_OK;
    00291 }
    00292
    00293 HRESULT CSubtitleStream::OnThreadStartPlay()
    00294 {
    00295     m_bDiscontinuity = TRUE;
    00296     return DeliverNewSegment(m_rtStart, m_rtStop, m_dRateSeeking);
    00297 }
    00298
    00299 HRESULT CSubtitleStream::ChangeStart()
    00300 {
    00301     {
    00302         CAutoLock lock(CSourceSeeking::m_pLock);
    00303
    00304                 OnThreadCreate();
    00305 /*
    00306                 if(m_mt.majortype == MEDIATYPE_Video && m_mt.subtype == MEDIASUBTYPE_ARGB32)
    00307                 {
    00308                         m_nPosition = (int)(m_rtStart/10000)*1/1000;
    00309                 }
    00310                 else if(m_mt.majortype == MEDIATYPE_Video && m_mt.subtype == MEDIASUBTYPE_RGB32)
    00311                 {
    00312                         int m_nSegments = 0;
    00313                         if(!m_rts.SearchSubs((int)(m_rtStart/10000), 25, &m_nPosition, &m_nSegments))
    00314                                 m_nPosition = m_nSegments;
    00315                 }
    00316                 else
    00317                 {
    00318                         m_nPosition = m_rts.SearchSub((int)(m_rtStart/10000), 25);
    00319                         if(m_nPosition < 0) m_nPosition = 0;
    00320                         else if(m_rts[m_nPosition].end <= (int)(m_rtStart/10000)) m_nPosition++;
    00321                 }
    00322 */    }
    00323
    00324     UpdateFromSeek();
    00325
    00326     return S_OK;
    00327 }
    00328
    00329 HRESULT CSubtitleStream::ChangeStop()
    00330 {
    00331 /*
    00332     {
    00333         CAutoLock lock(CSourceSeeking::m_pLock);
    00334         if(m_rtPosition < m_rtStop)
    00335                         return S_OK;
    00336     }
    00337 */
    00338     // We're already past the new stop time -- better flush the graph.
    00339     UpdateFromSeek();
    00340
    00341     return S_OK;
    00342 }
    00343
    00344 HRESULT CSubtitleStream::OnThreadCreate()
    00345 {
    00346     CAutoLock cAutoLockShared(&m_cSharedState);
    00347
    00348         if(m_mt.majortype == MEDIATYPE_Video && m_mt.subtype == MEDIASUBTYPE_ARGB32)
    00349         {
    00350                 m_nPosition = m_rtStart/_ATPF;
    00351         }
    00352         else if(m_mt.majortype == MEDIATYPE_Video && m_mt.subtype == MEDIASUBTYPE_RGB32)
    00353         {
    00354                 int m_nSegments = 0;
    00355                 if(!m_rts.SearchSubs((int)(m_rtStart/10000), 10000000/_ATPF, &m_nPosition, &m_nSegments))
    00356                         m_nPosition = m_nSegments;
    00357         }
    00358         else
    00359         {
    00360                 m_nPosition = m_rts.SearchSub((int)(m_rtStart/10000), 25);
    00361                 if(m_nPosition < 0) m_nPosition = 0;
    00362                 else if(m_rts[m_nPosition].end <= (int)(m_rtStart/10000)) m_nPosition++;
    00363         }
    00364
    00365     return CSourceStream::OnThreadCreate();
    00366 }
    00367
    00368 HRESULT CSubtitleStream::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties)
    00369 {
    00370 //    CAutoLock cAutoLock(m_pFilter->pStateLock());
    00371
    00372     ASSERT(pAlloc);
    00373     ASSERT(pProperties);
    00374
    00375     HRESULT hr = NOERROR;
    00376
    00377         if(m_mt.majortype == MEDIATYPE_Video)
    00378         {
    00379                 pProperties->cBuffers = 2;
    00380                 pProperties->cbBuffer = ((VIDEOINFOHEADER*)m_mt.pbFormat)->bmiHeader.biSizeImage;
    00381         }
    00382         else
    00383         {
    00384                 pProperties->cBuffers = 1;
    00385                 pProperties->cbBuffer = 0x10000;
    00386         }
    00387
    00388     ALLOCATOR_PROPERTIES Actual;
    00389     if(FAILED(hr = pAlloc->SetProperties(pProperties, &Actual))) return hr;
    00390
    00391     if(Actual.cbBuffer < pProperties->cbBuffer) return E_FAIL;
    00392     ASSERT(Actual.cBuffers == pProperties->cBuffers);
    00393
    00394     return NOERROR;
    00395 }
    00396
    00397 HRESULT CSubtitleStream::FillBuffer(IMediaSample* pSample)
    00398 {
    00399         HRESULT hr;
    00400
    00401         {
    00402                 CAutoLock cAutoLockShared(&m_cSharedState);
    00403
    00404                 BYTE* pData = NULL;
    00405                 if(FAILED(hr = pSample->GetPointer(&pData)) || !pData)
    00406                         return S_FALSE;
    00407
    00408                 AM_MEDIA_TYPE* pmt;
    00409                 if(SUCCEEDED(pSample->GetMediaType(&pmt)) && pmt)
    00410                 {
    00411                         CMediaType mt(*pmt);
    00412                         SetMediaType(&mt);
    00413                         DeleteMediaType(pmt);
    00414                 }
    00415
    00416                 int len = 0;
    00417                 REFERENCE_TIME rtStart, rtStop;
    00418
    00419                 if(m_mt.majortype == MEDIATYPE_Video && m_mt.subtype == MEDIASUBTYPE_ARGB32)
    00420                 {
    00421                         rtStart = (REFERENCE_TIME)((m_nPosition*_ATPF - m_rtStart) / m_dRateSeeking);
    00422                         rtStop = (REFERENCE_TIME)(((m_nPosition+1)*_ATPF - m_rtStart) / m_dRateSeeking);
    00423                         if(m_rtStart+rtStart >= m_rtDuration)
    00424                                 return S_FALSE;
    00425
    00426                         BITMAPINFOHEADER& bmi = ((VIDEOINFOHEADER*)m_mt.pbFormat)->bmiHeader;
    00427
    00428                         SubPicDesc spd;
    00429                         spd.w = _WIDTH;
    00430                         spd.h = _HEIGHT;
    00431                         spd.bpp = 32;
    00432                         spd.pitch = bmi.biWidth*4;
    00433                         spd.bits = pData;
    00434
    00435                         len = spd.h*spd.pitch;
    00436
    00437                         for(int y = 0; y < spd.h; y++)
    00438                                 memsetd((DWORD*)(pData + spd.pitch*y), 0xff000000, spd.w*4);
    00439
    00440                         RECT bbox;
    00441                         m_rts.Render(spd, m_nPosition*_ATPF, 10000000.0/_ATPF, bbox);
    00442
    00443                         for(int y = 0; y < spd.h; y++)
    00444                         {
    00445                                 DWORD* p = (DWORD*)(pData + spd.pitch*y);
    00446                                 for(int x = 0; x < spd.w; x++, p++)
    00447                                         *p = (0xff000000-(*p&0xff000000))|(*p&0xffffff);
    00448                         }
    00449                 }
    00450                 else if(m_mt.majortype == MEDIATYPE_Video && m_mt.subtype == MEDIASUBTYPE_RGB32)
    00451                 {
    00452                         const STSSegment* stss = m_rts.GetSegment(m_nPosition);
    00453                         if(!stss) return S_FALSE;
    00454
    00455                         BITMAPINFOHEADER& bmi = ((VIDEOINFOHEADER*)m_mt.pbFormat)->bmiHeader;
    00456
    00457                         SubPicDesc spd;
    00458                         spd.w = _WIDTH;
    00459                         spd.h = _HEIGHT;
    00460                         spd.bpp = 32;
    00461                         spd.pitch = bmi.biWidth*4;
    00462                         spd.bits = pData;
    00463
    00464                         len = spd.h*spd.pitch;
    00465
    00466                         for(int y = 0; y < spd.h; y++)
    00467                         {
    00468                                 DWORD c1 = 0xff606060, c2 = 0xffa0a0a0;
    00469                                 if(y&32) c1 ^= c2, c2 ^= c1, c1 ^= c2;
    00470                                 DWORD* p = (DWORD*)(pData + spd.pitch*y);
    00471                                 for(int x = 0; x < spd.w; x+=32, p+=32)
    00472                                         memsetd(p, (x&32) ? c1 : c2, min(spd.w-x,32)*4);
    00473                         }
    00474
    00475                         RECT bbox;
    00476                         m_rts.Render(spd, 10000i64*(stss->start+stss->end)/2, 10000000.0/_ATPF, bbox);
    00477
    00478                         rtStart = (REFERENCE_TIME)((10000i64*stss->start - m_rtStart) / m_dRateSeeking);
    00479                         rtStop = (REFERENCE_TIME)((10000i64*stss->end - m_rtStart) / m_dRateSeeking);
    00480                 }
    00481                 else
    00482                 {
    00483                         if(m_nPosition >= m_rts.GetCount())
    00484                                 return S_FALSE;
    00485
    00486                         STSEntry& stse = m_rts[m_nPosition];
    00487
    00488                         if(stse.start >= m_rtStop/10000)
    00489                                 return S_FALSE;
    00490
    00491                         if(m_mt.majortype == MEDIATYPE_Subtitle && m_mt.subtype == MEDIASUBTYPE_UTF8)
    00492                         {
    00493                                 CStringA str = UTF16To8(m_rts.GetStrW(m_nPosition, false));
    00494                                 memcpy((char*)pData, str, len = str.GetLength());
    00495                         }
    00496                         else if(m_mt.majortype == MEDIATYPE_Subtitle && (m_mt.subtype == MEDIASUBTYPE_SSA || m_mt.subtype == MEDIASUBTYPE_ASS))
    00497                         {
    00498                                 CStringW line;
    00499                                 line.Format(L"%d,%d,%s,%s,%d,%d,%d,%s,%s",
    00500                                         stse.readorder, stse.layer, CStringW(stse.style), CStringW(stse.actor),
    00501                                         stse.marginRect.left, stse.marginRect.right, (stse.marginRect.top+stse.marginRect.bottom)/2,
    00502                                         CStringW(stse.effect), m_rts.GetStrW(m_nPosition, true));
    00503
    00504                                 CStringA str = UTF16To8(line);
    00505                                 memcpy((char*)pData, str, len = str.GetLength());
    00506                         }
    00507                         else if(m_mt.majortype == MEDIATYPE_Text && m_mt.subtype == MEDIASUBTYPE_NULL)
    00508                         {
    00509                                 CStringA str = m_rts.GetStrA(m_nPosition, false);
    00510                                 memcpy((char*)pData, str, len = str.GetLength());
    00511                         }
    00512                         else
    00513                         {
    00514                                 return S_FALSE;
    00515                         }
    00516
    00517                         rtStart = (REFERENCE_TIME)((10000i64*stse.start - m_rtStart) / m_dRateSeeking);
    00518                         rtStop = (REFERENCE_TIME)((10000i64*stse.end - m_rtStart) / m_dRateSeeking);
    00519                 }
    00520
    00521                 pSample->SetTime(&rtStart, &rtStop);
    00522                 pSample->SetActualDataLength(len);
    00523
    00524                 m_nPosition++;
    00525         }
    00526
    00527         pSample->SetSyncPoint(TRUE);
    00528
    00529         if(m_bDiscontinuity)
    00530     {
    00531                 pSample->SetDiscontinuity(TRUE);
    00532                 m_bDiscontinuity = FALSE;
    00533         }
    00534
    00535         return S_OK;
    00536 }
    00537
    00538 HRESULT CSubtitleStream::GetMediaType(CMediaType* pmt)
    00539 {
    00540         return ((CSubtitleSource*)m_pFilter)->GetMediaType(pmt);
    00541 }
    00542
    00543 HRESULT CSubtitleStream::CheckMediaType(const CMediaType* pmt)
    00544 {
    00545     CAutoLock lock(m_pFilter->pStateLock());
    00546
    00547     CMediaType mt;
    00548     GetMediaType(&mt);
    00549
    00550         if(mt.majortype == pmt->majortype && mt.subtype == pmt->subtype)
    00551         {
    00552         return NOERROR;
    00553     }
    00554
    00555     return E_FAIL;
    00556 }
    00557
    00558 STDMETHODIMP CSubtitleStream::Notify(IBaseFilter* pSender, Quality q)
    00559 {
    00560         return E_NOTIMPL;
    00561 }
    00562
    00563 //
    00564 // CSubtitleSourceASCII
    00565 //
    00566
    00567 CSubtitleSourceASCII::CSubtitleSourceASCII(LPUNKNOWN lpunk, HRESULT* phr)
    00568         : CSubtitleSource(lpunk, phr, __uuidof(this))
    00569 {
    00570 }
    00571
    00572 HRESULT CSubtitleSourceASCII::GetMediaType(CMediaType* pmt)
    00573 {
    00574     CAutoLock cAutoLock(pStateLock());
    00575
    00576         pmt->InitMediaType();
    00577         pmt->SetType(&MEDIATYPE_Text);
    00578         pmt->SetSubtype(&MEDIASUBTYPE_NULL);
    00579         pmt->SetFormatType(&FORMAT_None);
    00580         pmt->ResetFormatBuffer();
    00581
    00582     return NOERROR;
    00583 }
    00584
    00585 //
    00586 // CSubtitleSourceUTF8
    00587 //
    00588
    00589 CSubtitleSourceUTF8::CSubtitleSourceUTF8(LPUNKNOWN lpunk, HRESULT* phr)
    00590         : CSubtitleSource(lpunk, phr, __uuidof(this))
    00591 {
    00592 }
    00593
    00594 HRESULT CSubtitleSourceUTF8::GetMediaType(CMediaType* pmt)
    00595 {
    00596     CAutoLock cAutoLock(pStateLock());
    00597
    00598         pmt->InitMediaType();
    00599         pmt->SetType(&MEDIATYPE_Subtitle);
    00600         pmt->SetSubtype(&MEDIASUBTYPE_UTF8);
    00601         pmt->SetFormatType(&FORMAT_SubtitleInfo);
    00602         SUBTITLEINFO* psi = (SUBTITLEINFO*)pmt->AllocFormatBuffer(sizeof(SUBTITLEINFO));
    00603         memset(psi, 0, pmt->FormatLength());
    00604         strcpy(psi->IsoLang, "eng");
    00605
    00606     return NOERROR;
    00607 }
    00608
    00609 //
    00610 // CSubtitleSourceSSA
    00611 //
    00612
    00613 CSubtitleSourceSSA::CSubtitleSourceSSA(LPUNKNOWN lpunk, HRESULT* phr)
    00614         : CSubtitleSource(lpunk, phr, __uuidof(this))
    00615 {
    00616 }
    00617
    00618 HRESULT CSubtitleSourceSSA::GetMediaType(CMediaType* pmt)
    00619 {
    00620     CAutoLock cAutoLock(pStateLock());
    00621
    00622         pmt->InitMediaType();
    00623         pmt->SetType(&MEDIATYPE_Subtitle);
    00624         pmt->SetSubtype(&MEDIASUBTYPE_SSA);
    00625         pmt->SetFormatType(&FORMAT_SubtitleInfo);
    00626
    00627         CSimpleTextSubtitle sts;
    00628         sts.Open(CString(m_fn), DEFAULT_CHARSET);
    00629         sts.RemoveAll();
    00630
    00631         CFile f;
    00632         TCHAR path[MAX_PATH], fn[MAX_PATH];
    00633         if(!GetTempPath(MAX_PATH, path) || !GetTempFileName(path, _T("mpc_sts"), 0, fn))
    00634                 return E_FAIL;
    00635
    00636         _tcscat(fn, _T(".ssa"));
    00637
    00638         if(!sts.SaveAs(fn, EXTSSA, -1, CTextFile::UTF8) || !f.Open(fn, CFile::modeRead))
    00639                 return E_FAIL;
    00640
    00641         int len = (int)f.GetLength()-3;
    00642         f.Seek(3, CFile::begin);
    00643
    00644         SUBTITLEINFO* psi = (SUBTITLEINFO*)pmt->AllocFormatBuffer(sizeof(SUBTITLEINFO) + len);
    00645         memset(psi, 0, pmt->FormatLength());
    00646         psi->dwOffset = sizeof(SUBTITLEINFO);
    00647         strcpy(psi->IsoLang, "eng");
    00648         f.Read(pmt->pbFormat + psi->dwOffset, len);
    00649         f.Close();
    00650
    00651         _tremove(fn);
    00652
    00653     return NOERROR;
    00654 }
    00655
    00656 //
    00657 // CSubtitleSourceASS
    00658 //
    00659
    00660 CSubtitleSourceASS::CSubtitleSourceASS(LPUNKNOWN lpunk, HRESULT* phr)
    00661         : CSubtitleSource(lpunk, phr, __uuidof(this))
    00662 {
    00663 }
    00664
    00665 HRESULT CSubtitleSourceASS::GetMediaType(CMediaType* pmt)
    00666 {
    00667     CAutoLock cAutoLock(pStateLock());
    00668
    00669         pmt->InitMediaType();
    00670         pmt->SetType(&MEDIATYPE_Subtitle);
    00671         pmt->SetSubtype(&MEDIASUBTYPE_ASS);
    00672         pmt->SetFormatType(&FORMAT_SubtitleInfo);
    00673
    00674         CSimpleTextSubtitle sts;
    00675         sts.Open(CString(m_fn), DEFAULT_CHARSET);
    00676         sts.RemoveAll();
    00677
    00678         CFile f;
    00679         TCHAR path[MAX_PATH], fn[MAX_PATH];
    00680         if(!GetTempPath(MAX_PATH, path) || !GetTempFileName(path, _T("mpc_sts"), 0, fn))
    00681                 return E_FAIL;
    00682
    00683         _tcscat(fn, _T(".ass"));
    00684
    00685         if(!sts.SaveAs(fn, EXTASS, -1, CTextFile::UTF8) || !f.Open(fn, CFile::modeRead))
    00686                 return E_FAIL;
    00687
    00688         int len = (int)f.GetLength();
    00689
    00690         SUBTITLEINFO* psi = (SUBTITLEINFO*)pmt->AllocFormatBuffer(sizeof(SUBTITLEINFO) + len);
    00691         memset(psi, 0, pmt->FormatLength());
    00692         psi->dwOffset = sizeof(SUBTITLEINFO);
    00693         strcpy(psi->IsoLang, "eng");
    00694         f.Read(pmt->pbFormat + psi->dwOffset, len);
    00695         f.Close();
    00696
    00697         _tremove(fn);
    00698
    00699     return NOERROR;
    00700 }
    00701
    00702 //
    00703 // CSubtitleSourceUSF
    00704 //
    00705
    00706 CSubtitleSourceUSF::CSubtitleSourceUSF(LPUNKNOWN lpunk, HRESULT* phr)
    00707         : CSubtitleSource(lpunk, phr, __uuidof(this))
    00708 {
    00709 }
    00710
    00711 HRESULT CSubtitleSourceUSF::GetMediaType(CMediaType* pmt)
    00712 {
    00713     CAutoLock cAutoLock(pStateLock());
    00714
    00715         pmt->InitMediaType();
    00716         pmt->SetType(&MEDIATYPE_Subtitle);
    00717         pmt->SetSubtype(&MEDIASUBTYPE_USF);
    00718         pmt->SetFormatType(&FORMAT_SubtitleInfo);
    00719         SUBTITLEINFO* psi = (SUBTITLEINFO*)pmt->AllocFormatBuffer(sizeof(SUBTITLEINFO));
    00720         memset(psi, 0, pmt->FormatLength());
    00721         strcpy(psi->IsoLang, "eng");
    00722         // TODO: ...
    00723
    00724     return NOERROR;
    00725 }
    00726
    00727 //
    00728 // CSubtitleSourcePreview
    00729 //
    00730
    00731 CSubtitleSourcePreview::CSubtitleSourcePreview(LPUNKNOWN lpunk, HRESULT* phr)
    00732         : CSubtitleSource(lpunk, phr, __uuidof(this))
    00733 {
    00734 }
    00735
    00736 HRESULT CSubtitleSourcePreview::GetMediaType(CMediaType* pmt)
    00737 {
    00738     CAutoLock cAutoLock(pStateLock());
    00739
    00740         pmt->InitMediaType();
    00741         pmt->SetType(&MEDIATYPE_Video);
    00742         pmt->SetSubtype(&MEDIASUBTYPE_RGB32);
    00743         pmt->SetFormatType(&FORMAT_VideoInfo);
    00744         VIDEOINFOHEADER* pvih = (VIDEOINFOHEADER*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
    00745         memset(pvih, 0, pmt->FormatLength());
    00746         pvih->bmiHeader.biSize = sizeof(pvih->bmiHeader);
    00747         pvih->bmiHeader.biWidth = _WIDTH;
    00748         pvih->bmiHeader.biHeight = _HEIGHT;
    00749         pvih->bmiHeader.biBitCount = 32;
    00750         pvih->bmiHeader.biCompression = BI_RGB;
    00751         pvih->bmiHeader.biPlanes = 1;
    00752         pvih->bmiHeader.biSizeImage = pvih->bmiHeader.biWidth*abs(pvih->bmiHeader.biHeight)*pvih->bmiHeader.biBitCount>>3;
    00753
    00754     return NOERROR;
    00755 }
    00756
    00757 //
    00758 // CSubtitleSourceARGB
    00759 //
    00760
    00761 CSubtitleSourceARGB::CSubtitleSourceARGB(LPUNKNOWN lpunk, HRESULT* phr)
    00762         : CSubtitleSource(lpunk, phr, __uuidof(this))
    00763 {
    00764 }
    00765
    00766 HRESULT CSubtitleSourceARGB::GetMediaType(CMediaType* pmt)
    00767 {
    00768     CAutoLock cAutoLock(pStateLock());
    00769
    00770         pmt->InitMediaType();
    00771         pmt->SetType(&MEDIATYPE_Video);
    00772         pmt->SetSubtype(&MEDIASUBTYPE_ARGB32);
    00773         pmt->SetFormatType(&FORMAT_VideoInfo);
    00774         VIDEOINFOHEADER* pvih = (VIDEOINFOHEADER*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
    00775         memset(pvih, 0, pmt->FormatLength());
    00776         pvih->bmiHeader.biSize = sizeof(pvih->bmiHeader);
    00777         // TODO: read w,h,fps from a config file or registry
    00778         pvih->bmiHeader.biWidth = _WIDTH;
    00779         pvih->bmiHeader.biHeight = _HEIGHT;
    00780         pvih->bmiHeader.biBitCount = 32;
    00781         pvih->bmiHeader.biCompression = BI_RGB;
    00782         pvih->bmiHeader.biPlanes = 1;
    00783         pvih->bmiHeader.biSizeImage = pvih->bmiHeader.biWidth*abs(pvih->bmiHeader.biHeight)*pvih->bmiHeader.biBitCount>>3;
    00784
    00785     return NOERROR;
    00786 }