Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

232 lines
4.6 KiB

//
// queue.cpp
//
// Copyright (C) Microsoft Corporation, 1996 - 1999 All rights reserved.
//
#include <stdafx.h>
#include "queue.h"
///////////////////////////////////////////////////////////////////////////////
//=============================================================================
// CBufferQueue Implementation
//=============================================================================
///////////////////////////////////////////////////////////////////////////////
CBufferQueue::CBufferQueue()
: m_fEOS(FALSE),
m_fActive(FALSE),
m_lCount(0),
m_lTail(0),
m_lHead(0),
m_lDepth(0),
m_dwStartTime(0),
m_dwSampleTime(0),
m_ppBuffers(NULL)
{
InitializeCriticalSection(&m_CritSec);
}
BOOL CBufferQueue::Initialize(long lDepth)
{
EnterCriticalSection(&m_CritSec);
m_ppBuffers = new IMediaSample * [lDepth];
if (m_ppBuffers == NULL)
{
LeaveCriticalSection(&m_CritSec);
return FALSE;
}
ZeroMemory(m_ppBuffers, sizeof(IMediaSample*) * lDepth);
m_lDepth = lDepth;
LeaveCriticalSection(&m_CritSec);
return TRUE;
}
//
// CBufferQueue::~CBufferQueue - delete allocated memory
//
CBufferQueue::~CBufferQueue()
{
EnterCriticalSection(&m_CritSec);
Flush();
delete [] m_ppBuffers;
DeleteCriticalSection(&m_CritSec);
}
void CBufferQueue::EnQ(
IMediaSample * pMS,
DWORD dwStartTime,
DWORD dwSampleTime
)
/*++
Routine Description:
Store a new sample in the queue.
Arguments:
pMS - a pointer to the media sample.
dwStartTime - The schduled start time for this queue.
dwSampleTime - The length of the sample measured in ms.
Return Value:
HRESULT.
--*/
{
EnterCriticalSection(&m_CritSec);
//
// Validity checks
//
ASSERT(m_ppBuffers != NULL);
ASSERT(pMS);
//
// Release a buffer if one is in the way.
//
if (m_ppBuffers[m_lTail] != NULL)
{
m_ppBuffers[m_lTail]->Release();
// addjust the scheduled play time for the first sample in the queue.
m_dwStartTime += m_dwSampleTime;
}
//
// Put the data in the queue.
//
m_ppBuffers[m_lTail] = pMS;
pMS->AddRef(); // Resease assumed!!!
if (!m_fActive)
{
m_dwStartTime = dwStartTime;
m_dwSampleTime = dwSampleTime;
m_fActive = TRUE;
}
//
// Adjust internal data
//
m_lTail = (m_lTail + 1) % m_lDepth;
//
// Head follows the tail if the Q is full
//
if (m_lCount == m_lDepth)
{
m_lHead = (m_lHead + 1) % m_lDepth;
}
else
{
m_lCount++;
}
DbgLog((LOG_TRACE, 0x3ff, TEXT("EnQ, Start: %d, Samples: %d"),
m_dwStartTime, m_lCount));
LeaveCriticalSection(&m_CritSec);
}
IMediaSample *CBufferQueue::DeQ(BOOL fAlways, DWORD dwCurrentTime)
/*++
Routine Description:
Remove the first sample from the queue.
Arguments:
fAlways - If true, deq immediately, ignoring the time.
dwCurrentTime - The current time.
Return Value:
HRESULT.
--*/
{
EnterCriticalSection(&m_CritSec);
//
// Validity checks
//
ASSERT(m_ppBuffers != NULL);
DbgLog((LOG_TRACE, 0x3ff, TEXT("DeQ, Current: %d, Start: %d, Samples: %d"),
dwCurrentTime, m_dwStartTime, m_lCount));
if (m_lCount == 0)
{
ASSERT(m_lHead == m_lTail);
m_fActive = FALSE; // We don't have continous samples.
LeaveCriticalSection(&m_CritSec);
return NULL;
}
if (!fAlways
&& m_dwStartTime != dwCurrentTime
&& m_dwStartTime - dwCurrentTime < (ULONG_MAX >> 2)) //handle wrapping.
{
// The time has not come for this queue to deliver.
LeaveCriticalSection(&m_CritSec);
return NULL;
}
//
// Remove Buffer
//
IMediaSample *pMS = m_ppBuffers[m_lHead];
ASSERT(pMS);
m_ppBuffers[m_lHead] = NULL;
// addjust the start time after we removed the buffer.
m_dwStartTime += m_dwSampleTime;
//
// Adjust internal data
//
m_lCount --;
m_lHead = (m_lHead + 1) % m_lDepth;
LeaveCriticalSection(&m_CritSec);
return pMS;
}
//
// Flush all the samples out of the queue.
//
void CBufferQueue::Flush()
{
EnterCriticalSection(&m_CritSec);
for (int i = 0; i < m_lCount; i ++)
{
m_ppBuffers[m_lHead]->Release();
m_ppBuffers[m_lHead] = NULL;
m_lHead = (m_lHead + 1) % m_lDepth;
}
m_lHead = m_lTail = m_lCount = 0;
m_dwStartTime = m_dwSampleTime = 0;
m_fActive = FALSE;
LeaveCriticalSection(&m_CritSec);
}