CDecodedStream.cpp
上传用户:hhs829
上传日期:2022-06-17
资源大小:586k
文件大小:9k
- //
- // CDecodedStream.cpp
- //
- #include <streams.h>
- #include <stdio.h>
- #include "CFilterMpeg2VD.h"
- #include "CDecodedStream.h"
- #include "CMpegInputPin.h"
- /////////////////////////////////////////////////////////////////////////////
- CDecodedStream::CDecodedStream(TCHAR * inObjectName,
- HRESULT * outResult,
- CFilterMpeg2VD * inFilter) :
- CSourceStream(inObjectName, outResult, inFilter, L"Output")
- {
- mDecodeFilter = inFilter;
- mPosition = NULL;
- mFlushing = FALSE;
- mMpegController = NULL;
- mSamplesSent = 0;
- }
- CDecodedStream::~CDecodedStream()
- {
- if (mPosition)
- {
- mPosition->Release();
- mPosition = NULL;
- }
- }
- void CDecodedStream::SetController(CMpegController * inController)
- {
- mMpegController = inController;
- }
- HRESULT CDecodedStream::FillBuffer(IMediaSample *pSample)
- {
- return NOERROR;
- }
- HRESULT CDecodedStream::CompleteConnect(IPin *pReceivePin)
- {
- HRESULT hr = mDecodeFilter->CompleteConnect(PINDIR_OUTPUT, pReceivePin);
- if (FAILED(hr))
- {
- return hr;
- }
- return CBaseOutputPin::CompleteConnect(pReceivePin);
- }
- //
- // DecideBufferSize
- //
- // Tell the output pin's allocator what size buffers we
- // require. Can only do this when the input is connected
- //
- HRESULT CDecodedStream::DecideBufferSize(IMemAllocator * pAllocator,
- ALLOCATOR_PROPERTIES *pprop)
- {
- // Is the input pin connected
- if (!mDecodeFilter->mMpegInputPin->IsConnected())
- {
- return E_UNEXPECTED;
- }
- ASSERT(pAllocator);
- ASSERT(pprop);
- HRESULT hr = NOERROR;
- pprop->cbBuffer = mDecodeFilter->mOutputImageSize;
- pprop->cBuffers = 1;
- pprop->cbAlign = 1;
- ASSERT(pprop->cbBuffer);
- // Ask the allocator to reserve us some sample memory, NOTE the function
- // can succeed (that is return NOERROR) but still not have allocated the
- // memory that we requested, so we must check we got whatever we wanted
- ALLOCATOR_PROPERTIES Actual;
- hr = pAllocator->SetProperties(pprop, &Actual);
- if (FAILED(hr)) {
- return hr;
- }
- ASSERT( Actual.cBuffers == 1 );
- if (pprop->cBuffers > Actual.cBuffers ||
- pprop->cbBuffer > Actual.cbBuffer) {
- return E_FAIL;
- }
- return NOERROR;
- }
- HRESULT CDecodedStream::CheckMediaType(const CMediaType *mtOut)
- {
- if (mDecodeFilter->mMpegInputPin->IsConnected())
- {
- if ((mtOut->subtype == MEDIASUBTYPE_YUY2 ||
- mtOut->subtype == MEDIASUBTYPE_RGB24) &&
- mtOut->formattype == FORMAT_VideoInfo)
- {
- VIDEOINFOHEADER * pFormat = (VIDEOINFOHEADER *) mtOut->pbFormat;
- if (pFormat->bmiHeader.biHeight == mDecodeFilter->mImageHeight &&
- pFormat->bmiHeader.biWidth == mDecodeFilter->mImageWidth)
- {
- return S_OK;
- }
- }
- }
- return E_FAIL;
- }
- // ---------------------------------------------------------
- // Currently we only support YUY2 and RGB24 decoded out
- // ---------------------------------------------------------
- HRESULT CDecodedStream::GetMediaType(int iPosition, CMediaType *pMediaType)
- {
- if (!mDecodeFilter->mMpegInputPin->IsConnected() ||
- iPosition < 0 || iPosition > 1)
- {
- return E_FAIL;
- }
- VIDEOINFOHEADER format;
- ZeroMemory(&format, sizeof(VIDEOINFOHEADER));
- pMediaType->SetType(&MEDIATYPE_Video);
- switch (iPosition)
- {
- case 0: // YUY2
- pMediaType->SetSubtype(&MEDIASUBTYPE_YUY2);
- format.bmiHeader.biBitCount = 16;
- format.bmiHeader.biCompression = mmioFOURCC('Y','U','Y','2');
- break;
- case 1: // RGB24
- pMediaType->SetSubtype(&MEDIASUBTYPE_RGB24);
- format.bmiHeader.biBitCount = 24;
- format.bmiHeader.biCompression = BI_RGB;
- break;
- }
- pMediaType->SetFormatType(&FORMAT_VideoInfo);
- format.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- format.bmiHeader.biPlanes = 1;
- format.AvgTimePerFrame = mDecodeFilter->mSampleDuration;
- format.bmiHeader.biWidth = mDecodeFilter->mImageWidth;
- format.bmiHeader.biHeight = mDecodeFilter->mImageHeight;
- format.bmiHeader.biSizeImage = mDecodeFilter->mImageWidth * mDecodeFilter->mImageHeight * format.bmiHeader.biBitCount / 8;
- pMediaType->SetFormat(PBYTE(&format), sizeof(VIDEOINFOHEADER));
- return S_OK;
- } // GetMediaType
- STDMETHODIMP CDecodedStream::QueryId(LPWSTR * Id)
- {
- return CBaseOutputPin::QueryId(Id);
- }
- // overriden to expose IMediaPosition and IMediaSeeking control interfaces
- STDMETHODIMP CDecodedStream::NonDelegatingQueryInterface(REFIID riid, void **ppv)
- {
- CheckPointer(ppv,E_POINTER);
- ValidateReadWritePtr(ppv,sizeof(PVOID));
- *ppv = NULL;
- if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking)
- {
- // we should have an input pin by now
- ASSERT(mDecodeFilter->mMpegInputPin != NULL);
- if (mPosition == NULL)
- {
- HRESULT hr = CreatePosPassThru(GetOwner(),
- FALSE,
- (IPin *)mDecodeFilter->mMpegInputPin,
- &mPosition);
- if (FAILED(hr))
- {
- return hr;
- }
- }
- return mPosition->QueryInterface(riid, ppv);
- }
- else
- {
- return CSourceStream::NonDelegatingQueryInterface(riid, ppv);
- }
- }
- // Override this if you can do something constructive to act on the
- // quality message. Consider passing it upstream as well
- // Pass the quality mesage on upstream.
- STDMETHODIMP CDecodedStream::Notify(IBaseFilter * pSender, Quality q)
- {
- UNREFERENCED_PARAMETER(pSender);
- ValidateReadPtr(pSender, sizeof(IBaseFilter));
- return mDecodeFilter->mMpegInputPin->PassNotify(q);
- } // Notify
- STDMETHODIMP CDecodedStream::BeginFlush(void)
- {
- mFlushing = TRUE;
- mMpegController->BeginFlush();
- {
- CAutoLock lck(&mDataAccess);
- mSamplesSent = 0;
- }
- return NOERROR;
- }
- STDMETHODIMP CDecodedStream::EndFlush(void)
- {
- mMpegController->EndFlush();
- mFlushing = FALSE;
- return NOERROR;
- }
- HRESULT CDecodedStream::EndOfStream(void)
- {
- return NOERROR;
- }
- HRESULT CDecodedStream::DoBufferProcessingLoop(void)
- {
- Command com;
- OnThreadStartPlay();
- BOOL EOS_Flag = FALSE;
- do
- {
- while (!CheckRequest(&com))
- {
- // If no data, never enter blocking reading
- if (mFlushing || mMpegController->IsCacheEmpty() || EOS_Flag)
- {
- if (mDecodeFilter->mEOSReceived)
- {
- EOS_Flag = TRUE;
- mMpegController->EndEndOfStream();
- if (!mDecodeFilter->mEOSDelivered)
- {
- mDecodeFilter->mEOSDelivered = TRUE;
- DeliverEndOfStream();
- }
- }
-
- Sleep(1);
- continue;
- }
- mMpegController->SequenceHeaderChecking();
- BOOL pass = mMpegController->LocatePictureHeader();
- if (pass)
- {
- pass = mMpegController->DecodeOnePicture();
- }
- if (pass)
- {
- IMediaSample *pSample;
- HRESULT hr = GetDeliveryBuffer(&pSample, NULL, NULL, 0);
- if (FAILED(hr))
- {
- Sleep(1);
- continue; // go round again. Perhaps the error will go away
- // or the allocator is decommited & we will be asked to
- // exit soon.
- }
- hr = DeliverCurrentPicture(pSample);
- if (FAILED(hr) && mDecodeFilter->mEOSReceived)
- {
- EOS_Flag = TRUE;
- mMpegController->EndEndOfStream();
- if (!mDecodeFilter->mEOSDelivered)
- {
- mDecodeFilter->mEOSDelivered = TRUE;
- DeliverEndOfStream();
- }
- }
- }
- }
- // For all commands sent to us there must be a Reply call!
- if (com == CMD_RUN || com == CMD_PAUSE)
- {
- Reply(NOERROR);
- }
- else if (com != CMD_STOP)
- {
- Reply((DWORD) E_UNEXPECTED);
- DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!")));
- }
- } while (com != CMD_STOP);
- // If EOS not delivered at the moment, just do it here!
- // mMpegController->EndEndOfStream();
- // if (!mDecodeFilter->mEOSDelivered)
- // {
- // mDecodeFilter->mEOSDelivered = TRUE;
- // DeliverEndOfStream();
- // }
- return S_FALSE;
- }
- HRESULT CDecodedStream::OnThreadStartPlay(void)
- {
- mSamplesSent = 0;
- return NOERROR;
- }
- HRESULT CDecodedStream::OnThreadDestroy(void)
- {
- return NOERROR;
- }
- HRESULT CDecodedStream::DeliverCurrentPicture(IMediaSample * pSample)
- {
- PBYTE pOut;
- pSample->GetPointer(&pOut);
- mMpegController->GetDecoded(pOut);
- pSample->SetActualDataLength(mDecodeFilter->mOutputImageSize);
- ULONG alreadySent = 0;
- {
- CAutoLock lck(&mDataAccess);
- alreadySent = mSamplesSent;
- mSamplesSent++;
- }
- LONGLONG llStart = alreadySent;
- LONGLONG llEnd = alreadySent + 1;
- pSample->SetMediaTime(&llStart, &llEnd);
- REFERENCE_TIME rtStart = alreadySent * mDecodeFilter->mSampleDuration;
- REFERENCE_TIME rtEnd = (alreadySent + 1) * mDecodeFilter->mSampleDuration;
- pSample->SetTime(&rtStart, &rtEnd);
- pSample->SetDiscontinuity(FALSE);
- pSample->SetPreroll(FALSE);
- pSample->SetSyncPoint(TRUE);
- HRESULT hr = Deliver(pSample);
- pSample->Release();
- return hr;
- }
- HRESULT CDecodedStream::StopThreadSafely(void)
- {
- if (ThreadExists())
- {
- Stop();
- }
- return NOERROR;
- }
- HRESULT CDecodedStream::RunThreadSafely(void)
- {
- if (ThreadExists())
- {
- Run();
- }
- return NOERROR;
- }