00001
00034 #include "stdafx.h"
00035
00036
00037 #include <iostream>
00038
00039
00040 #include "RtspSourceFilter.h"
00041 #include "RtspSourceOutputPin.h"
00042
00043
00044 #include <liveMedia.hh>
00045 #include <BasicUsageEnvironment.hh>
00046 #include <GroupsockHelper.hh>
00047 #include <RTSPClient.hh>
00048
00049 #include "RtspDataSession.h"
00050 #include "RtspSnifferSession.h"
00051
00052 #include <Shared/StringUtil.h>
00053
00054 RtspSourceFilter::RtspSourceFilter( IUnknown* pUnk, HRESULT* phr )
00055 : CSource(NAME("RTVC Live Media RTSP Source Filter"), pUnk, CLSID_RTVC_RtspAudioSourceFilter),
00056 m_tStreamTimeOffset(0),
00057 m_dStreamTimeOffset(0.0),
00058 m_pRtspDataSession(NULL)
00059
00060 {
00061
00062 initParameters();
00063 m_bStreaming = false;
00064 }
00065
00066 RtspSourceFilter::~RtspSourceFilter(void)
00067 {
00068 for (int i = 0; i < m_vOutputPins.size();i++)
00069 {
00070 delete m_vOutputPins[i];
00071 m_vOutputPins[i] = NULL;
00072 }
00073 }
00074
00075 CUnknown *WINAPI RtspSourceFilter::CreateInstance( IUnknown* pUnk, HRESULT* phr )
00076 {
00077 RtspSourceFilter* pAdvertSource = new RtspSourceFilter(pUnk, phr);
00078 if (!pAdvertSource)
00079 {
00080 *phr = E_OUTOFMEMORY;
00081 }
00082 return pAdvertSource;
00083 }
00084
00085 STDMETHODIMP RtspSourceFilter::NonDelegatingQueryInterface( REFIID riid, void **ppv )
00086 {
00087 if(riid == (IID_ISettingsInterface))
00088 {
00089 return GetInterface((ISettingsInterface*) this, ppv);
00090 }
00091 else if (riid == IID_IStatusInterface)
00092 {
00093 return GetInterface((IStatusInterface*) this, ppv);
00094 }
00095 else if (riid == IID_IFileSourceFilter)
00096 {
00097 return GetInterface((IFileSourceFilter*) this, ppv);
00098 }
00099 else if (riid == IID_ISpecifyPropertyPages)
00100 {
00101 return GetInterface(static_cast<ISpecifyPropertyPages*>(this), ppv);
00102 }
00103 else
00104 {
00105 return CSource::NonDelegatingQueryInterface(riid, ppv);
00106 }
00107 }
00108
00109
00110 STDMETHODIMP RtspSourceFilter::Load( LPCOLESTR lpwszFileName, const AM_MEDIA_TYPE *pmt )
00111 {
00112
00113
00114 m_sUrl = StringUtil::wideToStl(lpwszFileName);
00115
00116
00117 RtspSnifferSession rtspSnifferSession;
00118
00119 bool bSuccess = rtspSnifferSession.getMediaSessionInformation(m_sUrl);
00120 if (bSuccess)
00121 {
00122 HRESULT hr = S_OK;
00123 std::vector<MediaSubsession*> vSubsessions = rtspSnifferSession.getMediaSubsessions();
00124
00125 for (std::vector<MediaSubsession*>::iterator it = vSubsessions.begin(); it!= vSubsessions.end(); ++it)
00126 {
00127 createOutputPin(*it, &hr);
00128 if (FAILED(hr))
00129 {
00130 break;
00131 }
00132 }
00133 return hr;
00134 }
00135 else
00136 {
00137 std::string sError = rtspSnifferSession.getLastError();
00138 SetLastError(sError.c_str(), true);
00139 return E_FAIL;
00140 }
00141 }
00142
00143 STDMETHODIMP RtspSourceFilter::GetCurFile( LPOLESTR * ppszFileName, AM_MEDIA_TYPE *pmt )
00144 {
00145
00146
00147 if (pmt != NULL)
00148 {
00149
00150 if (m_vOutputPins.size() > 0)
00151 {
00152
00153 CMediaType* pMediaType = m_vOutputPins[0]->m_pMediaType;
00154 if (pMediaType == NULL)
00155 {
00156
00157 return E_FAIL;
00158 }
00159 else
00160 {
00161
00162 HRESULT hr = CopyMediaType(pmt, (AM_MEDIA_TYPE*) pMediaType);
00163 if (hr = E_UNEXPECTED)
00164 {
00165 return E_FAIL;
00166 }
00167 }
00168 }
00169 else
00170 {
00171 return E_FAIL;
00172 }
00173 }
00174
00175 *ppszFileName = NULL;
00176
00177 if (m_sUrl.length()!=0)
00178 {
00179 WCHAR* pFileName = (StringUtil::stlToWide(m_sUrl));
00180
00181 DWORD n = sizeof(WCHAR)*(1+lstrlenW(pFileName));
00182
00183 *ppszFileName = (LPOLESTR) CoTaskMemAlloc( n );
00184 if (*ppszFileName!=NULL) {
00185 CopyMemory(*ppszFileName, pFileName, n);
00186 }
00187 delete[] pFileName;
00188 }
00189
00190 return NOERROR;
00191 }
00192
00193 void RtspSourceFilter::createOutputPin(MediaSubsession *pSubsession, HRESULT* pHr)
00194 {
00195
00196
00197 RtspSourceOutputPin* pPin = new RtspSourceOutputPin(pHr, this, pSubsession, m_vOutputPins.size());
00198
00199 m_vOutputPins.push_back(pPin);
00200
00201 IncrementPinVersion();
00202 }
00203
00204 int RtspSourceFilter::GetPinCount()
00205 {
00206 return (int)(m_vOutputPins.size());
00207 }
00208
00209 CBasePin * RtspSourceFilter::GetPin( int n )
00210 {
00211 if ((n >= GetPinCount()) || (n < 0))
00212 return NULL;
00213
00214 return m_vOutputPins[n];
00215 }
00216
00217 STDMETHODIMP RtspSourceFilter::FindPin( LPCWSTR Id, IPin **ppPin )
00218 {
00219
00220 CheckPointer(ppPin,E_POINTER);
00221 ValidateReadWritePtr(ppPin,sizeof(IPin *));
00222
00223
00224 const char* szInput = StringUtil::wideToStl(Id).c_str();
00225
00226 char szTemp[10];
00227 ZeroMemory(szTemp, 10);
00228 memcpy(szTemp, szInput, 6);
00229 szTemp[6] = '\0';
00230 if (0==strcmp(szTemp, "Output"))
00231 {
00232 const char* szID = szInput + 7;
00233 int nId = atoi(szID);
00234 *ppPin = GetPin(nId);
00235 }
00236 else
00237 {
00238 *ppPin = NULL;
00239 return VFW_E_NOT_FOUND;
00240 }
00241
00242 HRESULT hr = NOERROR;
00243
00244 if (*ppPin)
00245 {
00246 (*ppPin)->AddRef();
00247 }
00248 else
00249 {
00250 hr = E_OUTOFMEMORY;
00251 }
00252 return hr;
00253 }
00254
00255 STDMETHODIMP RtspSourceFilter::Stop()
00256 {
00257 CAutoLock cAutoLock(&m_stateLock);
00258
00259 m_bStreaming = false;
00260
00261 m_pRtspDataSession->setWatchVariable();
00262
00263
00264 DWORD result = WaitForSingleObject(m_hLiveMediaStopEvent, INFINITE);
00265 return CSource::Stop();
00266 }
00267
00268 STDMETHODIMP RtspSourceFilter::Pause()
00269 {
00270 CAutoLock cAutoLock(&m_stateLock);
00271 StartRtspServerThreadIfNotStarted();
00272 return CSource::Pause();
00273 }
00274
00276 static DWORD WINAPI LiveRTSPServerThreadFunc(LPVOID pvParam);
00277
00278
00279 void RtspSourceFilter::StartRtspServerThreadIfNotStarted()
00280 {
00281 CAutoLock cAutoLock(&m_stateLock);
00282 if (!m_bStreaming)
00283 {
00284 m_bStreaming = true;
00285
00286 m_hLiveMediaStopEvent = CreateEvent(
00287 NULL,
00288 FALSE,
00289 FALSE,
00290 TEXT("LiveMediaEventLoop")
00291 );
00292
00293 DWORD dwThreadID = 0;
00294
00295 HANDLE hThread = CreateThread(0, 0, LiveRTSPServerThreadFunc, (void*)this, 0, &dwThreadID);
00296 }
00297 }
00298
00299 static DWORD WINAPI LiveRTSPServerThreadFunc(LPVOID pvParam)
00300 {
00301 RtspSourceFilter* pSourceFilter = (RtspSourceFilter*)pvParam;
00302 pSourceFilter->StartRtspSession();
00303 return S_OK;
00304 }
00305
00306 void RtspSourceFilter::StartRtspSession()
00307 {
00308 ASSERT(m_pRtspDataSession == NULL);
00309
00310
00311 m_pRtspDataSession = new RtspDataSession(&m_rtpPacketManager);
00312 m_pRtspDataSession->streamUsingTCP(m_bStreamUsingTCP);
00313
00314 m_pRtspDataSession->startRetrievingData(m_sUrl);
00315 delete m_pRtspDataSession;
00316 m_pRtspDataSession = NULL;
00317
00318 SetEvent(m_hLiveMediaStopEvent);
00319 }
00320
00321 STDMETHODIMP RtspSourceFilter::GetState( DWORD dwMilliSecsTimeout, FILTER_STATE *pState )
00322 {
00323
00324
00325 CheckPointer(pState, E_POINTER);
00326 *pState = m_State;
00327 if (m_State == State_Paused)
00328 return VFW_S_CANT_CUE;
00329 else
00330 return S_OK;
00331 }
00332
00333 void RtspSourceFilter::notifyFilterAboutOffset( double dOffset)
00334 {
00335 CAutoLock cAutoLock(&m_stateLock);
00336
00337
00338
00339
00340
00341
00342 CRefTime streamTime;
00343 StreamTime(streamTime);
00344
00345 m_tStreamTimeOffset = streamTime.GetUnits() + 500000;
00346
00347 m_dStreamTimeOffset = m_tStreamTimeOffset / 10000000.0;
00348
00349
00350
00351 for (int i = 0; i < m_vOutputPins.size(); i++)
00352 {
00353 m_vOutputPins[i]->setOffset(dOffset);
00354 }
00355 }