00001
00002
00003
00004
00005
00006 #include <streams.h>
00007
00008 CSource::CSource(TCHAR *pName, LPUNKNOWN lpunk, CLSID clsid)
00009 : CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
00010 m_iPins(0),
00011 m_paStreams(NULL)
00012 {
00013 }
00014
00015 CSource::CSource(TCHAR *pName, LPUNKNOWN lpunk, CLSID clsid, HRESULT *phr)
00016 : CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
00017 m_iPins(0),
00018 m_paStreams(NULL)
00019 {
00020 UNREFERENCED_PARAMETER(phr);
00021 }
00022
00023 #ifdef UNICODE
00024 CSource::CSource(CHAR *pName, LPUNKNOWN lpunk, CLSID clsid)
00025 : CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
00026 m_iPins(0),
00027 m_paStreams(NULL)
00028 {
00029 }
00030
00031 CSource::CSource(CHAR *pName, LPUNKNOWN lpunk, CLSID clsid, HRESULT *phr)
00032 : CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
00033 m_iPins(0),
00034 m_paStreams(NULL)
00035 {
00036 UNREFERENCED_PARAMETER(phr);
00037 }
00038 #endif
00039
00040 CSource::~CSource()
00041 {
00042
00043 while (m_iPins != 0) {
00044
00045 delete m_paStreams[m_iPins - 1];
00046 }
00047
00048 ASSERT(m_paStreams == NULL);
00049 }
00050
00051 HRESULT CSource::AddPin(CSourceStream *pStream)
00052 {
00053 CAutoLock lock(&m_cStateLock);
00054
00055
00056 CSourceStream **paStreams = new CSourceStream *[m_iPins + 1];
00057 if (paStreams == NULL) {
00058 return E_OUTOFMEMORY;
00059 }
00060 if (m_paStreams != NULL) {
00061 CopyMemory((PVOID)paStreams, (PVOID)m_paStreams,
00062 m_iPins * sizeof(m_paStreams[0]));
00063 paStreams[m_iPins] = pStream;
00064 delete [] m_paStreams;
00065 }
00066 m_paStreams = paStreams;
00067 m_paStreams[m_iPins] = pStream;
00068 m_iPins++;
00069 return S_OK;
00070 }
00071
00072 HRESULT CSource::RemovePin(CSourceStream *pStream)
00073 {
00074 int i;
00075 for (i = 0; i < m_iPins; i++) {
00076 if (m_paStreams[i] == pStream) {
00077 if (m_iPins == 1) {
00078 delete [] m_paStreams;
00079 m_paStreams = NULL;
00080 } else {
00081
00082 while (++i < m_iPins)
00083 m_paStreams[i - 1] = m_paStreams[i];
00084 }
00085 m_iPins--;
00086 return S_OK;
00087 }
00088 }
00089 return S_FALSE;
00090 }
00091
00092 STDMETHODIMP CSource::FindPin(LPCWSTR Id, IPin **ppPin)
00093 {
00094 CheckPointer(ppPin,E_POINTER);
00095 ValidateReadWritePtr(ppPin,sizeof(IPin *));
00096
00097
00098 int i = WstrToInt(Id) -1;
00099 *ppPin = GetPin(i);
00100 if (*ppPin!=NULL){
00101 (*ppPin)->AddRef();
00102 return NOERROR;
00103 } else {
00104 return VFW_E_NOT_FOUND;
00105 }
00106 }
00107
00108 int CSource::FindPinNumber(IPin *iPin) {
00109 int i;
00110 for (i=0; i<m_iPins; ++i) {
00111 if ((IPin *)(m_paStreams[i])==iPin) {
00112 return i;
00113 }
00114 }
00115 return -1;
00116 }
00117
00118 int CSource::GetPinCount(void) {
00119
00120 CAutoLock lock(&m_cStateLock);
00121 return m_iPins;
00122 }
00123
00124 CBasePin *CSource::GetPin(int n) {
00125
00126 CAutoLock lock(&m_cStateLock);
00127
00128
00129
00130
00131 if ((n >= 0) && (n < m_iPins)) {
00132
00133 ASSERT(m_paStreams[n]);
00134 return m_paStreams[n];
00135 }
00136 return NULL;
00137 }
00138
00139 STDMETHODIMP CSourceStream::QueryId(LPWSTR *Id) {
00140 CheckPointer(Id,E_POINTER);
00141 ValidateReadWritePtr(Id,sizeof(LPWSTR));
00142
00143
00144
00145 int i = 1+ m_pFilter->FindPinNumber(this);
00146 if (i<1) return VFW_E_NOT_FOUND;
00147 *Id = (LPWSTR)CoTaskMemAlloc(8);
00148 if (*Id==NULL) {
00149 return E_OUTOFMEMORY;
00150 }
00151 IntToWstr(i, *Id);
00152 return NOERROR;
00153 }
00154
00155 CSourceStream::CSourceStream(
00156 TCHAR *pObjectName,
00157 HRESULT *phr,
00158 CSource *ps,
00159 LPCWSTR pPinName)
00160 : CBaseOutputPin(pObjectName, ps, ps->pStateLock(), phr, pPinName),
00161 m_pFilter(ps) {
00162
00163 *phr = m_pFilter->AddPin(this);
00164 }
00165
00166 #ifdef UNICODE
00167 CSourceStream::CSourceStream(
00168 char *pObjectName,
00169 HRESULT *phr,
00170 CSource *ps,
00171 LPCWSTR pPinName)
00172 : CBaseOutputPin(pObjectName, ps, ps->pStateLock(), phr, pPinName),
00173 m_pFilter(ps) {
00174
00175 *phr = m_pFilter->AddPin(this);
00176 }
00177 #endif
00178
00179 CSourceStream::~CSourceStream(void) {
00180
00181 m_pFilter->RemovePin(this);
00182 }
00183
00184 HRESULT CSourceStream::CheckMediaType(const CMediaType *pMediaType) {
00185
00186 CAutoLock lock(m_pFilter->pStateLock());
00187
00188 CMediaType mt;
00189 GetMediaType(&mt);
00190
00191 if (mt == *pMediaType) {
00192 return NOERROR;
00193 }
00194
00195 return E_FAIL;
00196 }
00197
00198 HRESULT CSourceStream::GetMediaType(int iPosition, CMediaType *pMediaType) {
00199
00200 CAutoLock lock(m_pFilter->pStateLock());
00201
00202 if (iPosition<0) {
00203 return E_INVALIDARG;
00204 }
00205 if (iPosition>0) {
00206 return VFW_S_NO_MORE_ITEMS;
00207 }
00208 return GetMediaType(pMediaType);
00209 }
00210
00211 HRESULT CSourceStream::Active(void) {
00212
00213 CAutoLock lock(m_pFilter->pStateLock());
00214
00215 HRESULT hr;
00216
00217 if (m_pFilter->IsActive()) {
00218 return S_FALSE;
00219 }
00220
00221
00222
00223 if (!IsConnected()) {
00224 return NOERROR;
00225 }
00226
00227 hr = CBaseOutputPin::Active();
00228 if (FAILED(hr)) {
00229 return hr;
00230 }
00231
00232 ASSERT(!ThreadExists());
00233
00234
00235 if (!Create()) {
00236 return E_FAIL;
00237 }
00238
00239
00240 hr = Init();
00241 if (FAILED(hr))
00242 return hr;
00243
00244 return Pause();
00245 }
00246
00247 HRESULT CSourceStream::Inactive(void) {
00248
00249 CAutoLock lock(m_pFilter->pStateLock());
00250
00251 HRESULT hr;
00252
00253
00254
00255 if (!IsConnected()) {
00256 return NOERROR;
00257 }
00258
00259
00260
00261
00262 hr = CBaseOutputPin::Inactive();
00263 if (FAILED(hr)) {
00264 return hr;
00265 }
00266
00267 if (ThreadExists()) {
00268 hr = Stop();
00269
00270 if (FAILED(hr)) {
00271 return hr;
00272 }
00273
00274 hr = Exit();
00275 if (FAILED(hr)) {
00276 return hr;
00277 }
00278
00279 Close();
00280 }
00281
00282
00283
00284
00285
00286
00287 return NOERROR;
00288 }
00289
00290 DWORD CSourceStream::ThreadProc(void) {
00291
00292 HRESULT hr;
00293 Command com;
00294
00295 do {
00296 com = GetRequest();
00297 if (com != CMD_INIT) {
00298 DbgLog((LOG_ERROR, 1, TEXT("Thread expected init command")));
00299 Reply((DWORD) E_UNEXPECTED);
00300 }
00301 } while (com != CMD_INIT);
00302
00303 DbgLog((LOG_TRACE, 1, TEXT("CSourceStream worker thread initializing")));
00304
00305 hr = OnThreadCreate();
00306 if (FAILED(hr)) {
00307 DbgLog((LOG_ERROR, 1, TEXT("CSourceStream::OnThreadCreate failed. Aborting thread.")));
00308 OnThreadDestroy();
00309 Reply(hr);
00310 return 1;
00311 }
00312
00313
00314 Reply(NOERROR);
00315
00316 Command cmd;
00317 do {
00318 cmd = GetRequest();
00319
00320 switch (cmd) {
00321
00322 case CMD_EXIT:
00323 Reply(NOERROR);
00324 break;
00325
00326 case CMD_RUN:
00327 DbgLog((LOG_ERROR, 1, TEXT("CMD_RUN received before a CMD_PAUSE???")));
00328
00329
00330 case CMD_PAUSE:
00331 Reply(NOERROR);
00332 DoBufferProcessingLoop();
00333 break;
00334
00335 case CMD_STOP:
00336 Reply(NOERROR);
00337 break;
00338
00339 default:
00340 DbgLog((LOG_ERROR, 1, TEXT("Unknown command %d received!"), cmd));
00341 Reply((DWORD) E_NOTIMPL);
00342 break;
00343 }
00344 } while (cmd != CMD_EXIT);
00345
00346 hr = OnThreadDestroy();
00347 if (FAILED(hr)) {
00348 DbgLog((LOG_ERROR, 1, TEXT("CSourceStream::OnThreadDestroy failed. Exiting thread.")));
00349 return 1;
00350 }
00351
00352 DbgLog((LOG_TRACE, 1, TEXT("CSourceStream worker thread exiting")));
00353 return 0;
00354 }
00355
00356 HRESULT CSourceStream::DoBufferProcessingLoop(void) {
00357
00358 Command com;
00359
00360 OnThreadStartPlay();
00361
00362 do {
00363 while (!CheckRequest(&com)) {
00364
00365 IMediaSample *pSample;
00366
00367 HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0);
00368 if (FAILED(hr)) {
00369 Sleep(1);
00370 continue;
00371
00372
00373 }
00374
00375
00376 hr = FillBuffer(pSample);
00377
00378 if (hr == S_OK) {
00379 hr = Deliver(pSample);
00380 pSample->Release();
00381
00382
00383
00384 if(hr != S_OK)
00385 {
00386 DbgLog((LOG_TRACE, 2, TEXT("Deliver() returned %08x; stopping"), hr));
00387 return S_OK;
00388 }
00389
00390 } else if (hr == S_FALSE) {
00391
00392 pSample->Release();
00393 DeliverEndOfStream();
00394 return S_OK;
00395 } else {
00396
00397 pSample->Release();
00398 DbgLog((LOG_ERROR, 1, TEXT("Error %08lX from FillBuffer!!!"), hr));
00399 DeliverEndOfStream();
00400 m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0);
00401 return hr;
00402 }
00403
00404
00405 }
00406
00407
00408
00409 if (com == CMD_RUN || com == CMD_PAUSE) {
00410 Reply(NOERROR);
00411 } else if (com != CMD_STOP) {
00412 Reply((DWORD) E_UNEXPECTED);
00413 DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!")));
00414 }
00415 } while (com != CMD_STOP);
00416
00417 return S_FALSE;
00418 }
00419