📄 amr_pin.cpp
字号:
//-----------------------------------------------------------------------------
//
// AMR Demuxer
//
// Author : Igor Janos
//
//-----------------------------------------------------------------------------
#include "stdafx.h"
//-----------------------------------------------------------------------------
//
// CAMRInputPin class
//
//-----------------------------------------------------------------------------
CAMRInputPin::CAMRInputPin(TCHAR *pObjectName, CAMRDemux *pDemux, HRESULT *phr, LPCWSTR pName) :
CBaseInputPin(pObjectName, pDemux, &pDemux->lock_filter, phr, pName),
reader(NULL)
{
// assign the splitter filter
demux = pDemux;
}
CAMRInputPin::~CAMRInputPin()
{
if (reader) { reader->Release(); reader = NULL; }
}
// this is a pull mode pin - these can not happen
STDMETHODIMP CAMRInputPin::EndOfStream() { return E_UNEXPECTED; }
STDMETHODIMP CAMRInputPin::BeginFlush() { return E_UNEXPECTED; }
STDMETHODIMP CAMRInputPin::EndFlush() { return E_UNEXPECTED; }
STDMETHODIMP CAMRInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double rate) { return E_UNEXPECTED; }
// we don't support this kind of transport
STDMETHODIMP CAMRInputPin::Receive(IMediaSample * pSample) { return E_UNEXPECTED; }
// check for input type
HRESULT CAMRInputPin::CheckConnect(IPin *pPin)
{
HRESULT hr = demux->CheckConnect(PINDIR_INPUT, pPin);
if (FAILED(hr)) return hr;
return CBaseInputPin::CheckConnect(pPin);
}
HRESULT CAMRInputPin::BreakConnect()
{
// Can't disconnect unless stopped
ASSERT(IsStopped());
demux->BreakConnect(PINDIR_INPUT, this);
// release the reader
if (reader) reader->Release(); reader = NULL;
return CBaseInputPin::BreakConnect();
}
HRESULT CAMRInputPin::CompleteConnect(IPin *pReceivePin)
{
// make sure there is a pin
ASSERT(pReceivePin);
if (reader) reader->Release(); reader = NULL;
// and make sure it supports IAsyncReader
HRESULT hr = pReceivePin->QueryInterface(IID_IAsyncReader, (void **)&reader);
if (FAILED(hr)) return hr;
// we're done here
hr = demux->CompleteConnect(PINDIR_INPUT, this, pReceivePin);
if (FAILED(hr)) return hr;
return CBaseInputPin::CompleteConnect(pReceivePin);
}
HRESULT CAMRInputPin::CheckMediaType(const CMediaType* pmt)
{
// make sure we have a type
ASSERT(pmt);
// ask the splitter
return demux->CheckInputType(pmt);
}
HRESULT CAMRInputPin::SetMediaType(const CMediaType* pmt)
{
// let the baseclass know
if (FAILED(CheckMediaType(pmt))) return E_FAIL;
HRESULT hr = CBasePin::SetMediaType(pmt);
if (FAILED(hr)) return hr;
return NOERROR;
}
HRESULT CAMRInputPin::Inactive()
{
HRESULT hr = CBaseInputPin::Inactive();
if (hr == VFW_E_NO_ALLOCATOR) hr = NOERROR;
if (FAILED(hr)) return hr;
return hr;
}
//-----------------------------------------------------------------------------
//
// CAMROutputPin class
//
//-----------------------------------------------------------------------------
CAMROutputPin::CAMROutputPin(TCHAR *pObjectName, CAMRDemux *pDemux, HRESULT *phr, LPCWSTR pName, int iBuffers) :
CBaseOutputPin(pObjectName, pDemux, &pDemux->lock_filter, phr, pName),
CAMThread(),
demux(pDemux),
buffers(iBuffers),
active(false),
rtStart(0),
rtStop(0xffffffffffff),
rate(1.0),
ev_can_read(TRUE),
ev_can_write(TRUE),
ev_abort(TRUE)
{
discontinuity = true;
eos_delivered = false;
ev_can_read.Reset();
ev_can_write.Set();
ev_abort.Reset();
// up to 5 seconds
buffer_time_ms = 5000;
}
CAMROutputPin::~CAMROutputPin()
{
// nothing yet
}
STDMETHODIMP CAMROutputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
CheckPointer(ppv, E_POINTER);
if (riid == IID_IMediaSeeking) {
return GetInterface((IMediaSeeking*)this, ppv);
} else {
return CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv);
}
}
HRESULT CAMROutputPin::CheckMediaType(const CMediaType *mtOut)
{
for (int i=0; i<mt_types.GetCount(); i++) {
if (mt_types[i] == *mtOut) return NOERROR;
}
// reject type if it's not among ours
return E_FAIL;
}
HRESULT CAMROutputPin::SetMediaType(const CMediaType *pmt)
{
// just set internal media type
if (FAILED(CheckMediaType(pmt))) return E_FAIL;
return CBaseOutputPin::SetMediaType(pmt);
}
HRESULT CAMROutputPin::GetMediaType(int iPosition, CMediaType *pmt)
{
// enumerate the list
if (iPosition < 0) return E_INVALIDARG;
if (iPosition >= mt_types.GetCount()) return VFW_S_NO_MORE_ITEMS;
*pmt = mt_types[iPosition];
return NOERROR;
}
HRESULT CAMROutputPin::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp)
{
ASSERT(pAlloc);
ASSERT(pProp);
HRESULT hr = NOERROR;
pProp->cBuffers = max(buffers, 1);
pProp->cbBuffer = max(m_mt.lSampleSize, 1);
ALLOCATOR_PROPERTIES Actual;
hr = pAlloc->SetProperties(pProp, &Actual);
if (FAILED(hr)) return hr;
ASSERT(Actual.cBuffers >= pProp->cBuffers);
return NOERROR;
}
HRESULT CAMROutputPin::BreakConnect()
{
ASSERT(IsStopped());
demux->BreakConnect(PINDIR_OUTPUT, this);
discontinuity = true;
return CBaseOutputPin::BreakConnect();
}
HRESULT CAMROutputPin::CompleteConnect(IPin *pReceivePin)
{
// let the parent know
HRESULT hr = demux->CompleteConnect(PINDIR_OUTPUT, this, pReceivePin);
if (FAILED(hr)) return hr;
discontinuity = true;
// okey
return CBaseOutputPin::CompleteConnect(pReceivePin);
}
STDMETHODIMP CAMROutputPin::Notify(IBaseFilter *pSender, Quality q)
{
return S_FALSE;
}
HRESULT CAMROutputPin::Inactive()
{
if (!active) return NOERROR;
active = FALSE;
// destroy everything
ev_abort.Set();
HRESULT hr = CBaseOutputPin::Inactive();
ASSERT(SUCCEEDED(hr));
if (ThreadExists()) {
CallWorker(CMD_EXIT);
Close();
}
FlushQueue();
ev_abort.Reset();
return NOERROR;
}
HRESULT CAMROutputPin::Active()
{
if (active) return NOERROR;
FlushQueue();
if (!IsConnected()) return VFW_E_NOT_CONNECTED;
ev_abort.Reset();
HRESULT hr = CBaseOutputPin::Active();
if (FAILED(hr)) {
active = FALSE;
return hr;
}
// new segment
DoNewSegment(rtStart, rtStop, rate);
// vytvorime novu queue
if (!ThreadExists()) {
Create();
CallWorker(CMD_RUN);
}
active = TRUE;
return hr;
}
HRESULT CAMROutputPin::DoNewSegment(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double dRate)
{
// queue the EOS packet
this->rtStart = rtStart;
this->rtStop = rtStop;
this->rate = dRate;
eos_delivered = false;
if (1) {
discontinuity = true;
return DeliverNewSegment(rtStart, rtStop, rate);
} else {
DataPacket *packet = new DataPacket();
{
CAutoLock lck(&lock_queue);
packet->type = DataPacket::PACKET_TYPE_NEW_SEGMENT;
packet->rtStart = rtStart;
packet->rtStop = rtStop;
packet->rate = rate;
queue.AddTail(packet);
ev_can_read.Set();
discontinuity = true;
}
}
return NOERROR;
}
// IMediaSeeking
STDMETHODIMP CAMROutputPin::GetCapabilities(DWORD* pCapabilities) { return demux->GetCapabilities(pCapabilities); }
STDMETHODIMP CAMROutputPin::CheckCapabilities(DWORD* pCapabilities) { return demux->CheckCapabilities(pCapabilities); }
STDMETHODIMP CAMROutputPin::IsFormatSupported(const GUID* pFormat) { return demux->IsFormatSupported(pFormat); }
STDMETHODIMP CAMROutputPin::QueryPreferredFormat(GUID* pFormat) { return demux->QueryPreferredFormat(pFormat); }
STDMETHODIMP CAMROutputPin::GetTimeFormat(GUID* pFormat) { return demux->GetTimeFormat(pFormat); }
STDMETHODIMP CAMROutputPin::IsUsingTimeFormat(const GUID* pFormat) { return demux->IsUsingTimeFormat(pFormat); }
STDMETHODIMP CAMROutputPin::SetTimeFormat(const GUID* pFormat) { return demux->SetTimeFormat(pFormat); }
STDMETHODIMP CAMROutputPin::GetDuration(LONGLONG* pDuration) { return demux->GetDuration(pDuration); }
STDMETHODIMP CAMROutputPin::GetStopPosition(LONGLONG* pStop) { return demux->GetStopPosition(pStop); }
STDMETHODIMP CAMROutputPin::GetCurrentPosition(LONGLONG* pCurrent) { return demux->GetCurrentPosition(pCurrent); }
STDMETHODIMP CAMROutputPin::GetPositions(LONGLONG* pCurrent, LONGLONG* pStop) { return demux->GetPositions(pCurrent, pStop); }
STDMETHODIMP CAMROutputPin::GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest) { return demux->GetAvailable(pEarliest, pLatest); }
STDMETHODIMP CAMROutputPin::SetRate(double dRate) { return demux->SetRate(dRate); }
STDMETHODIMP CAMROutputPin::GetRate(double* pdRate) { return demux->GetRate(pdRate); }
STDMETHODIMP CAMROutputPin::GetPreroll(LONGLONG* pllPreroll) { return demux->GetPreroll(pllPreroll); }
STDMETHODIMP CAMROutputPin::ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat)
{
return demux->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat);
}
STDMETHODIMP CAMROutputPin::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
{
return demux->SetPositionsInternal(0, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
}
int CAMROutputPin::GetDataPacket(DataPacket **packet)
{
// this method may blokc
HANDLE events[] = { ev_can_write, ev_abort };
DWORD ret;
do {
// if the abort event is set, quit
if (ev_abort.Check()) return -1;
ret = WaitForMultipleObjects(2, events, FALSE, 10);
if (ret == WAIT_OBJECT_0) {
// return new packet
*packet = new DataPacket();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -