www.pudn.com > src.rar > SubtitleSource.cpp
#include "stdafx.h" #include#include "DirectVobSubUIDs.h" #include "IDirectVobSub.h" #include "SubtitleSource.h" ///////////////////////////////////////////////////////////////////////////////////// CUnknown* WINAPI CSubtitleSource::CreateInstance(LPUNKNOWN lpunk, HRESULT* phr) { CUnknown* punk = new CSubtitleSource(lpunk, phr); if(punk == NULL) *phr = E_OUTOFMEMORY; return punk; } CSubtitleSource::CSubtitleSource(LPUNKNOWN lpunk, HRESULT* phr) : CSource(NAME("Subtitle Source"), lpunk, CLSID_SubtitleSource), CPersistStream(lpunk, phr) { CAutoLock cAutoLock(&m_cStateLock); m_paStreams = (CSourceStream**) new CSubtitleStream*[1]; if(m_paStreams == NULL) { *phr = E_OUTOFMEMORY; return; } m_paStreams[0] = new CSubtitleStream("Subtitle Source", phr, this, L"Output"); if(m_paStreams[0] == NULL) { *phr = E_OUTOFMEMORY; return; } } STDMETHODIMP CSubtitleSource::NonDelegatingQueryInterface(REFIID riid, void** ppv) { CheckPointer(ppv, E_POINTER); return (riid == IID_IPersistStream) ? GetInterface((IPersistStream *)this, ppv) : (riid == IID_IFileSourceFilter) ? GetInterface((IFileSourceFilter *)this, ppv) : CSource::NonDelegatingQueryInterface(riid, ppv); } DWORD CSubtitleSource::GetSoftwareVersion() { return(0x0223); } HRESULT CSubtitleSource::WriteToStream(IStream* pStream) { CAutoLock cAutolock(&m_propsLock); int len = m_fn.GetLength(); HRESULT hr = pStream->Write(&len, sizeof(len), NULL); if(FAILED(hr)) return hr; return NOERROR; } HRESULT CSubtitleSource::ReadFromStream(IStream* pStream) { CAutoLock cAutolock(&m_propsLock); int len; HRESULT hr = pStream->Read(&len, sizeof(len), NULL); if(FAILED(hr) || len <= 0) return hr; char* buff = new char[len+1]; hr = pStream->Read(buff, len+1, NULL); if(FAILED(hr)) {delete [] buff; return hr;} m_fn = buff; delete [] buff; if(m_paStreams[0]) ((CSubtitleStream*)m_paStreams[0])->Open(m_fn); return NOERROR; } STDMETHODIMP CSubtitleSource::GetClassID(CLSID* pClsid) { if(pClsid == NULL) return E_POINTER; *pClsid = CLSID_SubtitleSource; return NOERROR; } STDMETHODIMP CSubtitleSource::GetCurFile(LPOLESTR* ppszFileName, AM_MEDIA_TYPE* pmt) { ASSERT(ppszFileName); if(m_fn.IsEmpty()) return(E_FAIL); *ppszFileName = (unsigned short*)CoTaskMemAlloc((m_fn.GetLength()+1)*sizeof(unsigned short)); if(*ppszFileName == NULL) return S_FALSE; #ifdef UNICODE wcscpy(*ppszFileName, m_fn); #else mbstowcs(*ppszFileName, m_fn, MAX_PATH); #endif CMediaType mt; ((CSubtitleStream*)m_paStreams[0])->GetMediaType(0, &mt); *pmt = mt; return(S_OK); } STDMETHODIMP CSubtitleSource::Load(LPCOLESTR pszFileName, const AM_MEDIA_TYPE* pmt) { if(m_paStreams[0]) { if(!((CSubtitleStream*)m_paStreams[0])->Open(CString(pszFileName))) { return(E_INVALIDARG); } } else { return(E_FAIL); } return(S_OK); } ///////////////////////////////////////////////////////////////////////////////////////////////////////// CSubtitleStream::CSubtitleStream(char* fn, HRESULT* phr, CSubtitleSource* pParent, LPCWSTR pPinName) : CSourceStream(NAME("Subtitle Stream"), phr, pParent, pPinName) { m_duration = 0; m_filesize = 0; m_data = NULL; } CSubtitleStream::~CSubtitleStream() { if(m_data) {delete [] m_data; m_data = NULL;} } bool CSubtitleStream::Open(CString fn) { if(m_data) {delete [] m_data; m_data = NULL;} if(!m_sts.Open(fn, DEFAULT_CHARSET) || m_sts.GetSize() <= 0) return(false); m_duration = m_sts.TranslateEnd(m_sts.GetSize()-1, 23.976); // 23.976 will give us the worst case if we have a FRAME based sub (well, for ordenary dvd rips) m_name = m_sts.m_name; CFileStatus status; if(!CFile::GetStatus(fn, status)) return(false); m_filesize = status.m_size; CFile f; if(!f.Open(fn, CFile::modeRead|CFile::typeBinary)) return(false); m_data = new BYTE[m_filesize]; if(!m_data) return(false); if(f.Read(m_data, m_filesize) != m_filesize) { delete [] m_data; m_data = NULL; return(false); }; return(true); } HRESULT CSubtitleStream::FillBuffer(IMediaSample* pms) { BYTE* pData; long lDataLen; pms->GetPointer(&pData); lDataLen = pms->GetSize(); if(m_fRAWOutput) { CAutoLock cAutoLockShared(&m_cSharedState); if(!pData || !m_data || !m_filesize || m_fOutputDone) return(S_FALSE); BYTE* ptr = pData; { // Format ID strcpy((char*)ptr, __GAB2__); ptr += strlen(__GAB2__)+1; } { int len = (m_name.GetLength()+1)*sizeof(WCHAR); *((ushort*)ptr) = __GAB1_LANGUAGE_UNICODE__; ptr += 2; *((uint*)ptr) = len; ptr += 4; #ifdef UNICODE wcscpy((WCHAR*)ptr, m_name); ptr += len; #else mbstowcs((WCHAR*)ptr, m_name, m_name.GetLength()+1); ptr += len; #endif } { int len = m_filesize; *((ushort*)ptr) = __GAB1_RAWTEXTSUBTITLE__; ptr += 2; *((uint*)ptr) = len; ptr += 4; memcpy(ptr, m_data, len); ptr += len; } REFERENCE_TIME start = __int64(0)*10000, stop = __int64(m_duration)*10000; pms->SetTime(&start, &stop); pms->SetActualDataLength(ptr - pData); m_fOutputDone = true; } else { CAutoLock cAutoLockShared(&m_cSharedState); REFERENCE_TIME start, stop; start = m_sts.TranslateSegmentStart(m_currentidx, 23.976), stop = m_sts.TranslateSegmentEnd(m_currentidx, 23.976); if(start == -1 && stop == -1) return S_FALSE; const STSSegment* stss = m_sts.SearchSubs((int)start, 23.976); start = __int64(start)*10000; stop = __int64(stop)*10000; pms->SetTime(&start, &stop); BYTE* ptr = pData; *ptr = 0; for(int i = 0; stss && i < stss->subs.GetSize(); i++, ptr++) { if(ptr != pData) ptr[-1] = '\n'; m_sts.GetMBCSStr(stss->subs[i], (char*)ptr, 10240); ptr += strlen((char*)ptr); } pms->SetActualDataLength(ptr - pData); m_currentidx++; } pms->SetSyncPoint(TRUE); /* int len = m_sts.GetSize(); if(len < 0 || m_currentidx >= len) return S_FALSE; REFERENCE_TIME start = __int64(m_start)*10000, stop = start + __int64(SUBALIGN)*10000; pms->SetTime(&start, &stop); m_start += SUBALIGN; BYTE* ptr = pData; // Format ID strcpy((char*)ptr, __GAB1__); ptr += strlen(__GAB1__)+1; // if(m_start == SUBALIGN) { if(m_sts.IsEntryUnicode(0)) // m_fUnicode) { int size = (m_sts.m_name.GetLength()+1)*sizeof(WCHAR); *((ushort*)ptr) = __GAB1_LANGUAGE_UNICODE__; ptr += 2; *((ushort*)ptr) = size; ptr += 2; #ifdef UNICODE wcscpy((WCHAR*)ptr, m_sts.m_name); ptr += size; #else mbstowcs((WCHAR*)ptr, m_sts.m_name, m_sts.m_name.GetLength()+1); ptr += size; // TODO: Use user specified charset #endif } else { int size = (m_sts.m_name.GetLength()+1)*sizeof(char); *((ushort*)ptr) = __GAB1_LANGUAGE__; ptr += 2; *((ushort*)ptr) = size; ptr += 2; #ifdef UNICODE wcstombs((char*)ptr, m_sts.m_name, m_sts.m_name.GetLength()+1); ptr += size; #else strcpy((char*)ptr, m_sts.m_name); ptr += size; #endif } } for(int i = m_currentidx; i < len && m_sts[i].start < m_start; i++) { STSEntry& stse = m_sts[i]; int start = m_sts.TranslateStart(i, 25); int end = m_sts.TranslateEnd(i, 25); bool fUnicode = m_sts.IsEntryUnicode(i); CString str = #ifdef UNICODE fUnicode ? m_sts.GetUnicodeStr(i) : #endif m_sts.GetMBCSStr(i); int len = str.GetLength()+1; #ifdef UNICODE if(fUnicode) { int size = 4+4+len*sizeof(WCHAR); *((ushort*)ptr) = __GAB1_ENTRY_UNICODE__; ptr += 2; *((ushort*)ptr) = size; ptr += 2; memcpy(ptr, &start, 4); ptr += 4; memcpy(ptr, &end, 4); ptr += 4; wcscpy((WCHAR*)ptr, str); ptr += len*sizeof(WCHAR); } else #endif { int size = 4+4+len*sizeof(char); *((ushort*)ptr) = __GAB1_ENTRY__; ptr += 2; *((ushort*)ptr) = size; ptr += 2; memcpy(ptr, &start, 4); ptr += 4; memcpy(ptr, &end, 4); ptr += 4; #ifdef UNICODE wcstombs((char*)ptr, str, len+1); ptr += len*sizeof(char); #else strcpy((char*)ptr, str); ptr += len*sizeof(char); #endif } } m_currentidx = i; pms->SetActualDataLength(ptr - pData); } */ // pms->SetSyncPoint(TRUE); return NOERROR; } HRESULT CSubtitleStream::GetMediaType(int iPosition, CMediaType *pmt) { CAutoLock cAutoLock(m_pFilter->pStateLock()); if(iPosition < 0) return E_INVALIDARG; if(iPosition > 0) return VFW_S_NO_MORE_ITEMS; pmt->SetType(&MEDIATYPE_Text); pmt->SetSubtype(&MEDIASUBTYPE_None); pmt->SetFormatType(&FORMAT_None); pmt->SetTemporalCompression(FALSE); pmt->SetVariableSize(); return NOERROR; } HRESULT CSubtitleStream::CheckConnect(IPin* pPin) { bool fAccept = true; PIN_INFO pi; pPin->QueryPinInfo(&pi); if(pi.pFilter) { FILTER_INFO fi; pi.pFilter->QueryFilterInfo(&fi); if(fi.pGraph) { fAccept = (wcsstr(fi.achName, L"Internal Script Command Renderer") == NULL); // sorry, but no! m_fRAWOutput = (CComQIPtr (pi.pFilter) || CComQIPtr (pi.pFilter)); fi.pGraph->Release(); } pi.pFilter->Release(); return(fAccept ? CBaseOutputPin::CheckConnect(pPin) : E_FAIL); } return E_FAIL; } HRESULT CSubtitleStream::CheckMediaType(const CMediaType* pMediaType) { CAutoLock cAutoLock(m_pFilter->pStateLock()); return IsEqualGUID(*pMediaType->Type(), MEDIATYPE_Text) ? S_OK : E_INVALIDARG; } HRESULT CSubtitleStream::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties) { CAutoLock cAutoLock(m_pFilter->pStateLock()); ASSERT(pAlloc); ASSERT(pProperties); HRESULT hr = NOERROR; pProperties->cBuffers = 1; pProperties->cbBuffer = 100 + m_filesize; ASSERT(pProperties->cbBuffer); ALLOCATOR_PROPERTIES Actual; hr = pAlloc->SetProperties(pProperties, &Actual); if(FAILED(hr)) return hr; if(Actual.cbBuffer < pProperties->cbBuffer) return E_FAIL; ASSERT(Actual.cBuffers == 1); return NOERROR; } HRESULT CSubtitleStream::OnThreadCreate() { CAutoLock cAutoLockShared(&m_cSharedState); m_fOutputDone = false; m_currentidx = 0; return NOERROR; }