解析TS流的包头,含源代码
Demux::Demux(PidParser *pPidParser, IBaseFilter *pFilter) :
m_bAuto(TRUE),
m_bMPEG2AudioMediaType(TRUE),
m_bMPEG2Audio2Mode(FALSE),
m_bNPControl(FALSE),
m_bNPSlave(FALSE),
m_bConnectBusyFlag(FALSE),
m_WasPlaying(FALSE),
m_WasPaused(FALSE),
m_bAC3Mode(FALSE),//(TRUE),
m_StreamH264(FALSE),
m_StreamMpeg4(FALSE),
m_StreamVid(FALSE),
m_StreamAC3(FALSE),
m_StreamMP2(FALSE),
m_StreamAud2(FALSE),
m_StreamAAC(FALSE),
m_ClockMode(1),
m_SelTelexPid(0),
m_SelAudioPid(0),
m_SelVideoPid(0),
m_bFixedAR(FALSE),
m_bCreateTSPinOnDemux(FALSE),
m_bCreateTxtPinOnDemux(FALSE)
{
m_pTSFileSourceFilter = pFilter;
m_pPidParser = pPidParser;
}
Demux::~Demux()
{
}
// Find all the immediate upstream or downstream peers of a filter.
HRESULT Demux::GetPeerFilters(
IBaseFilter *pFilter, // Pointer to the starting filter
PIN_DIRECTION Dir, // Direction to search (upstream or downstream)
CFilterList &FilterList) // Collect the results in this list.
{
if (!pFilter) return E_POINTER;
IEnumPins *pEnum = 0;
IPin *pPin = 0;
HRESULT hr = pFilter->EnumPins(&pEnum);
if (FAILED(hr)) return hr;
while (S_OK == pEnum->Next(1, &pPin, 0))
{
// See if this pin matches the specified direction.
PIN_DIRECTION thisPinDir;
hr = pPin->QueryDirection(&thisPinDir);
if (FAILED(hr))
{
// Something strange happened.
hr = E_UNEXPECTED;
pPin->Release();
break;
}
if (thisPinDir == Dir)
{
// Check if the pin is connected to another pin.
IPin *pPinNext = 0;
hr = pPin->ConnectedTo(&pPinNext);
if (SUCCEEDED(hr))
{
// Get the filter that owns that pin.
PIN_INFO PinInfo;
hr = pPinNext->QueryPinInfo(&PinInfo);
pPinNext->Release();
if (FAILED(hr) || (PinInfo.pFilter == NULL))
{
// Something strange happened.
pPin->Release();
pEnum->Release();
return E_UNEXPECTED;
}
// Insert the filter into the list.
AddFilterUnique(FilterList, PinInfo.pFilter);
PinInfo.pFilter->Release();
}
}
pPin->Release();
}
pEnum->Release();
return S_OK;
}
void Demux::AddFilterUnique(CFilterList &FilterList, IBaseFilter *pNew)
{
if (pNew == NULL) return;
POSITION pos = FilterList.GetHeadPosition();
while (pos)
{
IBaseFilter *pF = FilterList.GetNext(pos);
if (IsEqualObject(pF, pNew))
{
return;
}
}
pNew->AddRef(); // The caller must release everything in the list.
FilterList.AddTail(pNew);
}
// Get the first upstream or downstream filter
HRESULT Demux::GetNextFilter(
IBaseFilter *pFilter, // Pointer to the starting filter
PIN_DIRECTION Dir, // Direction to search (upstream or downstream)
IBaseFilter **ppNext) // Receives a pointer to the next filter.
{
if (!pFilter || !ppNext) return E_POINTER;
IEnumPins *pEnum = 0;
IPin *pPin = 0;
HRESULT hr = pFilter->EnumPins(&pEnum);
if (FAILED(hr)) return hr;
while (S_OK == pEnum->Next(1, &pPin, 0))
{
// See if this pin matches the specified direction.
PIN_DIRECTION thisPinDir;
hr = pPin->QueryDirection(&thisPinDir);
if (FAILED(hr))
{
// Something strange happened.
hr = E_UNEXPECTED;
pPin->Release();
break;
}
if (thisPinDir == Dir)
{
// Check if the pin is connected to another pin.
IPin *pPinNext = 0;
hr = pPin->ConnectedTo(&pPinNext);
if (SUCCEEDED(hr))
{
// Get the filter that owns that pin.
PIN_INFO PinInfo;
hr = pPinNext->QueryPinInfo(&PinInfo);
pPinNext->Release();
pPin->Release();
pEnum->Release();
if (FAILED(hr) || (PinInfo.pFilter == NULL))
{
// Something strange happened.
return E_UNEXPECTED;
}
// This is the filter we're looking for.
*ppNext = PinInfo.pFilter; // Client must release.
return S_OK;
}
}
pPin->Release();
}
pEnum->Release();
// Did not find a matching filter.
return E_FAIL;
}
HRESULT Demux::AOnConnect()
{
if (m_bConnectBusyFlag || m_pPidParser->m_ParsingLock)
return S_FALSE;
// Check if Enabled
if (!m_bAuto && !m_bNPControl && !m_bNPSlave)
return S_FALSE;
CAutoLock demuxlock(&m_DemuxLock);
m_bConnectBusyFlag = TRUE;
m_WasPlaying = FALSE;
m_WasPaused = FALSE;
m_TimeOut[0] = 0;
m_TimeOut[1] = 0;
// if (IsStopped() != S_FALSE)
// DoStop();
if (IsPaused() != S_FALSE)
{
m_TimeOut[0] = 10000;
if (DoStop() == S_OK){while(IsStopped() == S_FALSE){if (Sleeps(100,m_TimeOut) != S_OK) break;}}
m_WasPaused = TRUE;
}
else if (IsPlaying() == S_OK)
{
m_TimeOut[0] = 10000;
m_WasPlaying = TRUE;
}
// Parse only the existing Network Provider Filter
// in the filter graph, we do this by looking for filters
// that implement the ITuner interface while
// the count is still active.
FILTER_INFO Info;
if (SUCCEEDED(m_pTSFileSourceFilter->QueryFilterInfo(&Info)))
{
IEnumFilters* EnumFilters;
if(SUCCEEDED(Info.pGraph->EnumFilters(&EnumFilters)))
{
IBaseFilter* pFilter;
ULONG Fetched(0);
while(EnumFilters->Next(1, &pFilter, &Fetched) == S_OK)
{
if(pFilter != NULL)
{
UpdateNetworkProvider(pFilter);
pFilter->Release();
pFilter = NULL;
}
}
EnumFilters->Release();
}
Info.pGraph->Release();
}
// Parse only the existing Mpeg2 Demultiplexer Filter
// in the filter graph, we do this by looking for filters
// that implement the IMpeg2Demultiplexer interface while
// the count is still active.
CFilterList FList(NAME("MyList")); // List to hold the downstream peers.
if (SUCCEEDED(GetPeerFilters(m_pTSFileSourceFilter, PINDIR_OUTPUT, FList))
&& FList.GetHeadPosition())
{
IBaseFilter* pFilter = NULL;
POSITION pos = FList.GetHeadPosition();
pFilter = FList.Get(pos);
while (SUCCEEDED(GetPeerFilters(pFilter, PINDIR_OUTPUT, FList)) && pos)
{
pFilter = FList.GetNext(pos);
}
pos = FList.GetHeadPosition();
while (pos)
{
pFilter = FList.GetNext(pos);
if(pFilter != NULL)
{
UpdateDemuxPins(pFilter);
pFilter->Release();
pFilter = NULL;
}
}
}