?? cdecodedstream.cpp
字號:
//
// CDecodedStream.cpp
//
#include <streams.h>
#include <stdio.h>
#include "CFilterMpeg2Dec.h"
#include "CDecodedStream.h"
#include "CFilterMpeg2DecInputPin.h"
/////////////////////////////////////////////////////////////////////////////
CDecodedStream::CDecodedStream(TCHAR * inObjectName,
HRESULT * outResult,
CFilterMpeg2Dec * inFilter) :
CSourceStream(inObjectName, outResult, inFilter, L"Output")
{
mDecodeFilter = inFilter;
mPosition = NULL;
mFlushing = FALSE;
mMpeg2Controller = NULL;
mSamplesSent = 0;
}
CDecodedStream::~CDecodedStream()
{
if (mPosition)
{
mPosition->Release();
mPosition = NULL;
}
}
void CDecodedStream::SetController(CMpeg2Controller * inController)
{
mMpeg2Controller = 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;
mMpeg2Controller->BeginFlush();
{
CAutoLock lck(&mDataAccess);
mSamplesSent = 0;
}
return NOERROR;
}
STDMETHODIMP CDecodedStream::EndFlush(void)
{
mMpeg2Controller->EndFlush();
mFlushing = FALSE;
return NOERROR;
}
HRESULT CDecodedStream::EndOfStream(void)
{
return NOERROR;
}
HRESULT CDecodedStream::DoBufferProcessingLoop(void)
{
Command com;
OnThreadStartPlay();
BOOL pass;
int test_number = 0;
BOOL EOS_Flag = FALSE;
do
{
while (!CheckRequest(&com))
{
// If no data, never enter blocking reading
if (mFlushing || mMpeg2Controller->IsCacheEmpty() || EOS_Flag)
{
if (mDecodeFilter->mEOSReceived)
{
EOS_Flag = TRUE;
mMpeg2Controller->EndEndOfStream();
if (!mDecodeFilter->mEOSDelivered)
{
mDecodeFilter->mEOSDelivered = TRUE;
DeliverEndOfStream();
}
}
Sleep(1);
continue;
}
/*if(!init_header_flag)
{
SetCacheChecking();
Initialize_Buffer();
init_header_flag = 1;
}*/
test_number++; // calculate the times of GetBytes() before real decoding
mMpeg2Controller->GetBytes();
// mMpeg2Controller->SequenceHeaderChecking();
// BOOL pass = mMpeg2Controller->LocatePictureHeader();
// if (pass)
// {
// pass = mMpeg2Controller->DecodeOnePicture();
// }
do
{
pass = mMpeg2Controller->Decode_Mpeg2();
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;
mMpeg2Controller->EndEndOfStream();
if (!mDecodeFilter->mEOSDelivered)
{
mDecodeFilter->mEOSDelivered = TRUE;
DeliverEndOfStream();
}
}
}
}while(pass);
}
// 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);
mMpeg2Controller->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;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -