📄 manager.cpp
字号:
/***********************************************************************/
/* manager.cpp : Implementation of Memory Manager
* REALmagic Quasar Hardware Library
* Created by Kevin Vo
* Copyright Sigma Designs Inc
* Sigma Designs Proprietary and confidential
* Created on 3/20/01
* Description: It will maintain the FreeBuffer and MediaSample lists.
/************************************************************************/
/****h* MMDemux/MemManager
* NAME
* MemManager
* DESCRIPTION
* Memory Manager implementation.
* COPYRIGHT
* Copyright 2000 Sigma Designs Inc.
* 355 Fairview Way, Milpitas, CA 95035-3024 USA. All Rights Reserved.
* Sigma Designs Proprietary and Confidential
/*************************************************************************/
#include "pch.h"
#include "manager.h"
#include "mmutils.h"
#define TSBUFFER_SIZE 0x800 // Do not change this value
#define TSBUFFER_NUMBER 100 // Number of buffers in transport stream buffer list
////////////////////////////////////////////////////////////////////
/****f* MMDemux/MemManager::MemManager
* USAGE
* MemManager (int uiNumOfBuffer, int uiNumOfMediaSample, DWORD dwBufferSize)
* DESCRIPTION
* Constructor of the Memory Manager. It allocates memory of the buffer list
* and media sample list.
* PARAMETERS
* int uiNumOfBuffer - Number of buffers to be allocated.
* int uiNumOfMediaSample - Number of MediaSamples to be allocated.
* DWORD dwBufferSize - The size of each buffer (32KB).
* RETURN VALUE
* None
/**********************************************************************/
MemManager::MemManager(int iNumOfBuffer, int iNumOfMediaSample,
unsigned long dwBufferSize)
{
int i = 0;
CBuffer *pBuffer = 0;
CIMediaSample *pMedia = 0;
if (dwBufferSize == TSBUFFER_SIZE)
dwBufferSize = TSBUFFER_SIZE + 1;
m_iNumOfBuffer = iNumOfBuffer;
m_iNumOfMediaSample = iNumOfMediaSample;
m_iCurrentNumOfBuffer = iNumOfBuffer;
m_iCurrentNumOfMediaSample = iNumOfMediaSample;
m_dwDemuxBufferSize = dwBufferSize;
m_dwTSBufferSize = TSBUFFER_SIZE;
m_iNumOfTSBuffer = TSBUFFER_NUMBER;
m_pDemuxBuffer = new BYTE[(iNumOfBuffer * dwBufferSize) + (TSBUFFER_NUMBER * TSBUFFER_SIZE)];
if (m_pDemuxBuffer == 0)
return;
m_pCBufferList = new CBufferList();
m_pTSCBufferList = new CBufferList();
m_pCIMediaSampleList = new CIMediaSampleList();
unsigned char* pTempPtr = m_pDemuxBuffer;
// Buffers for demux
for (i = 0; i < iNumOfBuffer; i++)
{
pBuffer = new CBuffer(this, m_dwDemuxBufferSize, pTempPtr);
m_pCBufferList->SetBuffer(pBuffer);
pTempPtr += m_dwDemuxBufferSize;
}
// Transport stream buffers
for (i = 0; i < m_iNumOfTSBuffer; i++)
{
pBuffer = new CBuffer (this, m_dwTSBufferSize, pTempPtr);
m_pTSCBufferList->SetBuffer(pBuffer);
pTempPtr += m_dwTSBufferSize;
}
for (i = 0; i < iNumOfMediaSample; i++)
{
pMedia = new CIMediaSample(this);
m_pCIMediaSampleList->SetMediaSample(pMedia);
}
OSInitializeCriticalSection(&crBuffer);
OSInitializeCriticalSection(&crTSBuffer);
OSInitializeCriticalSection(&crMediaSample);
m_hBufferSemaphore = CreateSemaphore(NULL, m_iNumOfBuffer, m_iNumOfBuffer, NULL);
m_hTSBufferSemaphore = CreateSemaphore(NULL, m_iNumOfTSBuffer, m_iNumOfTSBuffer, NULL);
m_hMediaSampleSemaphore = CreateSemaphore(NULL, m_iNumOfMediaSample, m_iNumOfMediaSample, NULL);
if (m_hBufferSemaphore == NULL)
MmDebugLogfile((MmDebugLevelLog, "CreateSemaphore - BufferSemaphore Error %ld", GetLastError()));
if (m_hTSBufferSemaphore == NULL)
MmDebugLogfile((MmDebugLevelLog, "CreateSemaphore - TSBufferSemaphore Error %ld", GetLastError()));
if (m_hMediaSampleSemaphore == NULL)
MmDebugLogfile((MmDebugLevelLog, "CreateSemaphore - m_hMediaSampleSemaphore Error %ld", GetLastError()));
}
////////////////////////////////////////////////////////////////////
/****f* MMDemux/MemManager::MemManager
* USAGE
* MemManager (unsigned char* buffer, unsigned long dwBufferSize)
* DESCRIPTION
* Constructor of the Memory Manager. It allocates memory of the buffer list
* and media sample list. The demux will use 1/3 of the buffer for
* Transport stream and 2/3 for demux.
* PARAMETERS
* unsigned char* buffer - A pointer to the pre-allocated buffer.
* unsigned long dwBufferSize - Size of the buffer.
* RETURN VALUE
* None
/**********************************************************************/
MemManager::MemManager(unsigned char* buffer, unsigned long dwBufferSize)
{
int i = 0;
CBuffer *pBuffer = 0;
CIMediaSample *pMedia = 0;
if (dwBufferSize < 0x8000)
{
MmDebugLogfile((MmDebugLevelTrace|MmDebugLevelLog, "Buffer is too small!!!"));
return;
}
else
{
// Reserve 1/3 of the buffer for Transport Stream.
m_iNumOfTSBuffer = (dwBufferSize / 3) / TSBUFFER_SIZE;
m_dwTSBufferSize = (dwBufferSize / 3) / m_iNumOfTSBuffer;
// Make 2/3 of the buffer as the demux buffer and devide it into 10 separate small buffers.
m_iNumOfBuffer = 8;
m_iNumOfMediaSample = (dwBufferSize / 2048) * 2;
m_dwDemuxBufferSize = (dwBufferSize / 3 * 2) / m_iNumOfBuffer;
if (m_dwTSBufferSize == m_dwDemuxBufferSize)
m_dwTSBufferSize--;
}
m_iCurrentNumOfBuffer = m_iNumOfBuffer;
m_iCurrentNumOfMediaSample = m_iNumOfMediaSample;
m_pDemuxBuffer = 0;
m_pCBufferList = new CBufferList();
m_pTSCBufferList = new CBufferList();
m_pCIMediaSampleList = new CIMediaSampleList();
unsigned char* pTempPtr = buffer;
// Buffer for demux
for (i = 0; i < m_iNumOfBuffer; i++)
{
pBuffer = new CBuffer(this, m_dwDemuxBufferSize, pTempPtr);
m_pCBufferList->SetBuffer(pBuffer);
pTempPtr += m_dwDemuxBufferSize;
}
// Transport stream buffer
for (i = 0; i < m_iNumOfTSBuffer; i++)
{
pBuffer = new CBuffer (this, m_dwTSBufferSize, pTempPtr);
m_pTSCBufferList->SetBuffer(pBuffer);
pTempPtr += m_dwTSBufferSize;
}
for (i = 0; i < m_iNumOfMediaSample; i++)
{
pMedia = new CIMediaSample(this);
m_pCIMediaSampleList->SetMediaSample(pMedia);
}
OSInitializeCriticalSection(&crBuffer);
OSInitializeCriticalSection(&crTSBuffer);
OSInitializeCriticalSection(&crMediaSample);
m_hBufferSemaphore = CreateSemaphore(NULL, m_iNumOfBuffer, m_iNumOfBuffer, NULL);
m_hTSBufferSemaphore = CreateSemaphore(NULL, m_iNumOfTSBuffer, m_iNumOfTSBuffer, NULL);
m_hMediaSampleSemaphore = CreateSemaphore(NULL, m_iNumOfMediaSample, m_iNumOfMediaSample, NULL);
if (m_hBufferSemaphore == NULL)
MmDebugLogfile((MmDebugLevelLog, "CreateSemaphore - BufferSemaphore Error %ld", GetLastError()));
if (m_hTSBufferSemaphore == NULL)
MmDebugLogfile((MmDebugLevelLog, "CreateSemaphore - TSBufferSemaphore Error %ld", GetLastError()));
if (m_hMediaSampleSemaphore == NULL)
MmDebugLogfile((MmDebugLevelLog, "CreateSemaphore - m_hMediaSampleSemaphore Error %ld", GetLastError()));
}
////////////////////////////////////////////////////////////////////
MemManager::~MemManager()
{
delete m_pCBufferList;
delete m_pTSCBufferList;
delete m_pCIMediaSampleList;
if (m_pDemuxBuffer != 0)
delete m_pDemuxBuffer;
#ifdef _LINUXAPPS_
LinuxCloseSemaphore(m_hBufferSemaphore);
LinuxCloseSemaphore(m_hTSBufferSemaphore);
LinuxCloseSemaphore(m_hMediaSampleSemaphore);
#else // _LINUXAPPS_
CloseHandle(m_hBufferSemaphore);
CloseHandle(m_hTSBufferSemaphore);
CloseHandle(m_hMediaSampleSemaphore);
#endif // _LINUXAPPS_
OSDeleteCriticalSection(&crBuffer);
OSDeleteCriticalSection(&crTSBuffer);
OSDeleteCriticalSection(&crMediaSample);
}
////////////////////////////////////////////////////////////////////
/****f* MMDemux/MemManager::GetBuffer
* USAGE
* CBuffer *GetBuffer()
* DESCRIPTION
* Get an empty buffer from the buffer list. Only the main thread is
* calling this function.
* PARAMETERS
* None.
* RETURN VALUE
* A pointer to CBuffer.
* NULL if there isn't any buffer in the list.
/**********************************************************************/
CBuffer *MemManager::GetBuffer(void)
{
if (WaitForSingleObject(m_hBufferSemaphore, INFINITE) == WAIT_FAILED)
{
MmDebugLogfile((MmDebugLevelLog, "GetBuffer - WaitForSingleObject Error %d", GetLastError()));
return NULL;
}
CBuffer *pCBuffer = 0;
OSEnterCriticalSection(&crBuffer);
// Returns the top buffer from FreeBuffer list
pCBuffer = m_pCBufferList->GetBuffer();
pCBuffer->AddRef();
OSLeaveCriticalSection(&crBuffer);
return pCBuffer;
}
////////////////////////////////////////////////////////////////////
/****f* MMDemux/MemManager::GetMediaSample
* USAGE
* void GetMediaSample (CBuffer *pBuffer, CIMediaSample **pMedia)
* DESCRIPTION
* Get a MediaSample from the media sample list and sets a pointer to the
* buffer that this media sample will point to. Only the main thread is
* calling this function.
* PARAMETERS
* CBuffer *pBuffer - A pointer to the CBuffer that this MediaSample will point to.
* CIMediaSample **pMedia - A pointer to the pointer to MediaSample. It's NULL
* initially.
* RETURN VALUE
* None
/**********************************************************************/
void MemManager::GetMediaSample(CBuffer *pBuffer, CIMediaSample **pMedia)
{
if (WaitForSingleObject(m_hMediaSampleSemaphore, INFINITE) == WAIT_FAILED)
{
MmDebugLogfile((MmDebugLevelLog, "GetMediaSample - WaitForSingleObject Error %d", GetLastError()));
return;
}
OSEnterCriticalSection(&crMediaSample);
if ((*pMedia = m_pCIMediaSampleList->GetMediaSample()) != NULL)
{
(*pMedia)->SetCBuffer(pBuffer);
pBuffer->AddRef();
(*pMedia)->AddRef();
}
OSLeaveCriticalSection(&crMediaSample);
}
///////////////////////////////////////////////////////////////////
/****f* MMDemux/MemManager::GetTSBuffer
* USAGE
* CBuffer *GetTSBuffer()
* DESCRIPTION
* Get an empty buffer from the buffer list. Splitter will call this
* function if the file is of Transport Stream type.
* PARAMETERS
* None.
* RETURN VALUE
* A pointer to CBuffer.
* NULL if there isn't any buffer in the list.
/**********************************************************************/
CBuffer *MemManager::GetTSBuffer(void)
{
if (WaitForSingleObject(m_hTSBufferSemaphore, INFINITE) == WAIT_FAILED)
{
MmDebugLogfile((MmDebugLevelLog, "GetTBuffer - WaitForSingleObject Error %d", GetLastError()));
return NULL;
}
CBuffer *pCBuffer = 0;
OSEnterCriticalSection(&crTSBuffer);
// Returns the top buffer from FreeBuffer list
pCBuffer = m_pTSCBufferList->GetBuffer();
pCBuffer->AddRef();
OSLeaveCriticalSection(&crTSBuffer);
return pCBuffer;
}
////////////////////////////////////////////////////////////////////
/****f* MMDemux/MemManager::ReleaseMediaSample
* USAGE
* void ReleaseMediaSample (CIMediaSample *pMedia)
* DESCRIPTION
* Put the MediaSample back to MediaSample list. The COM thread will call
* this function if the application is using COM; otherwise, the SendToHardware
* function will call it.
* PARAMETERS
* CIMediaSample *pMedia - A pointer to the CIMediaSample that will be inserted
* to the MediaSample list.
* RETURN VALUE
* None
/**********************************************************************/
void MemManager::ReleaseMediaSample(CIMediaSample *pMedia)
{
if (pMedia != NULL)
{
OSEnterCriticalSection(&crMediaSample);
CBuffer *pBuffer = pMedia->GetCBuffer();
pBuffer->Release();
m_pCIMediaSampleList->SetMediaSample(pMedia);
if (ReleaseSemaphore(m_hMediaSampleSemaphore, 1, NULL) == 0)
MmDebugLogfile((MmDebugLevelLog, "ReleaseMediaSample - ReleaseSemaphore Error %ld", GetLastError()));
OSLeaveCriticalSection(&crMediaSample);
}
}
////////////////////////////////////////////////////////////////////
/****f* MMDemux/MemManager::ReleaseBuffer
* USAGE
* void ReleaseBuffer (CBuffer *pBuffer)
* DESCRIPTION
* Put the buffer back to the buffer list. The COM thread will call this function.
* PARAMETERS
* CBuffer *pBuffer - A pointer to the CBuffer that will be inserted into
* the buffer list.
* RETURN VALUE
* None
/**********************************************************************/
void MemManager::ReleaseBuffer(CBuffer *pBuffer)
{
if (pBuffer != NULL)
{
// Transport stream buffer. The other buffer is 32Kb by default. This's 2Kb.
if (pBuffer->GetSize() == m_dwTSBufferSize)
{
OSEnterCriticalSection(&crTSBuffer);
m_pTSCBufferList->SetBuffer(pBuffer);
if (ReleaseSemaphore(m_hTSBufferSemaphore, 1, 0) == 0)
MmDebugLogfile((MmDebugLevelLog, "ReleaseTBuffer - ReleaseSemaphore Error %ld", GetLastError()));
OSLeaveCriticalSection(&crTSBuffer);
// MmDebugLogfile((MmDebugLevelTrace, "Rel %X", pBuffer));
}
else
{
OSEnterCriticalSection(&crBuffer);
m_pCBufferList->SetBuffer(pBuffer);
if (ReleaseSemaphore(m_hBufferSemaphore, 1, (long*)&m_iCurrentNumOfBuffer) == 0)
MmDebugLogfile((MmDebugLevelLog, "ReleaseBuffer - ReleaseSemaphore Error %ld", GetLastError()));
OSLeaveCriticalSection(&crBuffer);
// MmDebugLogfile((MmDebugLevelTrace, "Rel %X %d", pBuffer, m_iCurrentNumOfBuffer + 1));
}
}
}
///////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -