⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chunkres.cpp

📁 linux下的一款播放器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
////		ULONG32 offset//		char* buf//		ULONG32 count//		ULONG32* actual////	Return:////		HX_RESULT//		Possible errors include: TBD.//HX_RESULT CChunkyRes::GetData(ULONG32 offset, char* buf, ULONG32 count, ULONG32* actual){	HX_RESULT theErr = HXR_OK;	int ndx;	ULONG32 ulFirstChunk = offset/DEF_CHUNKYRES_CHUNK_SIZE;	ULONG32 ulLastChunk  = (offset+count)/DEF_CHUNKYRES_CHUNK_SIZE;	HX_ASSERT(ulFirstChunk < INT_MAX);	HX_ASSERT(ulLastChunk < INT_MAX);	int		nFirstChunk  = (int)ulFirstChunk;	int		nLastChunk   = (int)ulLastChunk;	HX_ASSERT(m_Chunks.GetSize() >= nLastChunk+1);	ULONG32 chunkOffset = offset - (ulFirstChunk*DEF_CHUNKYRES_CHUNK_SIZE);	ULONG32 chunkCount  = count;	ULONG32 baseOffset  = 0;	*actual = 0;	// -fst	for (ndx = nFirstChunk; (ndx <= nLastChunk) && chunkCount; ndx++)	{		CChunkyResChunk* pChunk = (CChunkyResChunk*)m_Chunks[ndx];		if (!pChunk)		{		    // with random access, it's feasible that there's a null chunk.		    		    theErr = HXR_CHUNK_MISSING;		    goto exit;		}				HX_ASSERT_VALID_PTR(pChunk);		ULONG32 chunkActual = 0;		// Actually get the data from the chunk!		ULONG32 chunkAmount = min(DEF_CHUNKYRES_CHUNK_SIZE-chunkOffset,chunkCount);		theErr = pChunk->GetData(chunkOffset,buf+baseOffset,chunkAmount,&chunkActual);		if (theErr != HXR_OK)		{			goto exit;		}		// What?!?!		HX_ASSERT(chunkActual == chunkAmount);		*actual += chunkActual;		// -fst		// reduce the chunk count...		chunkCount -= chunkAmount;		baseOffset += chunkAmount;		// only the first chunk has an offset!		chunkOffset = 0;	}	// Remember how many bytes have been served to the user,	// in case they want us to discard used data	m_ulUsedBytes = offset + *actual;	// Discard chunks that have been fully served to the user	if (m_bDiscardUsedData)	{		nLastChunk = (int)(m_ulUsedBytes/DEF_CHUNKYRES_CHUNK_SIZE);		for (ndx = m_ulFirstChunkIdx; ndx < nLastChunk - 1; ndx++)		{			CChunkyResChunk* pChunk = (CChunkyResChunk*)m_Chunks[ndx];			HX_ASSERT_VALID_PTR(pChunk);			UINT32 ulTempOffset = pChunk->GetTempFileOffset();			pChunk->DiscardDiskData();			// Increment the first valid chunk index			m_ulFirstChunkIdx++;			if (ulTempOffset)			{			    // Add the disk space to the free space list			    m_FreeDiskOffsets.AddHead((void*)ulTempOffset);			}		}	}exit:	return theErr;}HX_RESULT CChunkyRes::GetContiguousDataPointer(ULONG32 offset, char*& buf, ULONG32 count){    HX_RESULT theErr = HXR_OK;    HX_ASSERT(m_bDiscardUsedData == FALSE && m_bDisableDiskIO == FALSE);    ULONG32 ulFirstChunk = offset/DEF_CHUNKYRES_CHUNK_SIZE;    ULONG32 ulLastChunk  = (offset+count)/DEF_CHUNKYRES_CHUNK_SIZE;    HX_ASSERT(ulFirstChunk < INT_MAX);    HX_ASSERT(ulLastChunk < INT_MAX);    // if the required data length spans two chunks, we cannot have     // contiguous memory    if (ulFirstChunk != ulLastChunk)    {	return HXR_FAIL;    }    int nFirstChunk  = (int)ulFirstChunk;    if (m_Chunks.GetSize() < nFirstChunk+1)    {	m_Chunks.SetSize(nFirstChunk+1);    }        CChunkyResChunk* pChunk = (CChunkyResChunk*)m_Chunks[nFirstChunk];    if (!pChunk)    {	pChunk = new CChunkyResChunk(this);	if (m_bDisableDiskIO)	{	    pChunk->DisableDiskIO();	}	m_Chunks[nFirstChunk] = pChunk;    }    HX_ASSERT(m_Chunks.GetSize() >= nFirstChunk+1);    HX_ASSERT_VALID_PTR(pChunk);    ULONG32 chunkOffset = offset - (ulFirstChunk*DEF_CHUNKYRES_CHUNK_SIZE);    // Actually get the data from the chunk!    ULONG32 chunkAmount = min(DEF_CHUNKYRES_CHUNK_SIZE-chunkOffset, count);    theErr = pChunk->GetContiguousDataPointer(chunkOffset,buf,chunkAmount);    return theErr;}/////////////////////////////////////////////////////////////////////////////////	Method:////		CChunkyRes::SetData()////	Purpose:////		Sets a block of data in a resource.////	Parameters:////		ULONG32 offset//		const char* buf//		ULONG32 count////	Return:////		HX_RESULT//		Possible errors include: TBD.//HX_RESULT CChunkyRes::SetData(ULONG32 offset, const char* buf, ULONG32 count){	HX_RESULT theErr = HXR_OK;	ULONG32 ulFirstChunk = offset/DEF_CHUNKYRES_CHUNK_SIZE;	ULONG32 ulLastChunk  = (offset+count)/DEF_CHUNKYRES_CHUNK_SIZE;	HX_ASSERT(ulFirstChunk < INT_MAX);	HX_ASSERT(ulLastChunk < INT_MAX);	int		nFirstChunk  = (int)ulFirstChunk;	int		nLastChunk   = (int)ulLastChunk;	if (m_Chunks.GetSize() < nLastChunk+1)	{		m_Chunks.SetSize(nLastChunk+1);	}	ULONG32 chunkOffset = offset - (ulFirstChunk*DEF_CHUNKYRES_CHUNK_SIZE);	ULONG32 chunkCount  = count;	ULONG32 baseOffset  = 0;	for (int ndx = nFirstChunk; ndx <= nLastChunk; ndx++)	{		CChunkyResChunk* pChunk = (CChunkyResChunk*)m_Chunks[ndx];		if (!pChunk)		{			pChunk = new CChunkyResChunk(this);			if (m_bDisableDiskIO)			{			    pChunk->DisableDiskIO();			}			m_Chunks[ndx] = pChunk;		}		// Actually set the data for the chunk!		theErr = pChunk->SetData(chunkOffset,buf+baseOffset,min(DEF_CHUNKYRES_CHUNK_SIZE-chunkOffset,chunkCount));		if (theErr != HXR_OK)		{			goto exit;		}		// reduce the chunk count...		chunkCount -= (DEF_CHUNKYRES_CHUNK_SIZE-chunkOffset);		baseOffset += (DEF_CHUNKYRES_CHUNK_SIZE-chunkOffset);		// only the first chunk has an offset!		chunkOffset = 0;	}exit:	return theErr;}void CChunkyRes::TrimDownMemoryMRU(){	// If we have just reduced our allowed memory usage, then	// discard the least recently used chunks till we are under	// the ne threshold...	if (m_CurMemUsage > m_MemUsageThreshold)	{		while (!m_ChunksMemoryMRU->IsEmpty() && (m_CurMemUsage > m_MemUsageThreshold))		{			// Get the least recently used chunk.			CChunkyResChunk* pChunk = (CChunkyResChunk*)m_ChunksMemoryMRU->GetTail();			HX_ASSERT_VALID_PTR(pChunk);			// Discount its usage.			m_CurMemUsage -= pChunk->GetSize();			// Spill this chunk to disk...			pChunk->SpillToDisk();			// Remove the chunk from the end of the Memory MRU			m_ChunksMemoryMRU->RemoveTail();			// And add the chunk to the front of the Disk MRU			m_ChunksDiskMRU->AddHead(pChunk);		}		// How can this be?!?! Did you really mean to set the memory usage such		// that there are no chunks in memory?!?		HX_ASSERT(!m_ChunksMemoryMRU->IsEmpty());	}}/////////////////////////////////////////////////////////////////////////////////	Method:////		CChunkyResChunk::SetMemUsageThreshold()////	Purpose:////		Sets the memory usage threshold for the chunky resource chunks.//		If if chunk sizes amount to more than the threshold, then the//		least recently used ones will be spilled to disk.////	Parameters:////		ULONG32 memUsage//		Memory usage in bytes which will be allowed for all chunks before//		least recently used chunks will be spilled to disk.////	Return:////		None.//void CChunkyRes::SetMemUsageThreshold(ULONG32 memUsage){	m_MemUsageThreshold = memUsage;	TrimDownMemoryMRU();}/////////////////////////////////////////////////////////////////////////////////	Method:////		CChunkyRes::CChunkyRes()////	Purpose:////		Constructor for a chunky resource.////	Parameters:////		None.////	Return:////		N/A//CChunkyRes::CChunkyRes()	: m_Chunks()	, m_strTempFileName()	, m_ulNextTempFileChunk(DEF_START_CHUNK_OFFSET)	, m_bHasBeenOpened(FALSE)	, m_bDisableDiskIO(FALSE)	, m_bDiscardUsedData(FALSE)	, m_ulFirstChunkIdx(0)	, m_ulUsedBytes(0)	, m_pMutex(0)	, m_MemUsageThreshold(DEF_CHUNKYRES_MEM_THRESHOLD)	, m_CurMemUsage(0)	, m_ChunksMemoryMRU(NULL)	, m_ChunksDiskMRU(NULL)	, m_ChunkSize(DEF_CHUNKYRES_CHUNK_SIZE){#if defined(THREADS_SUPPORTED)    HXMutex::MakeMutex(m_pMutex);#else    HXMutex::MakeStubMutex(m_pMutex);#endif    HX_ASSERT(m_pMutex);    m_ChunksMemoryMRU = new CHXSimpleList;    m_ChunksDiskMRU = new CHXSimpleList;    HX_ASSERT(m_ChunksMemoryMRU);    HX_ASSERT(m_ChunksDiskMRU);}/////////////////////////////////////////////////////////////////////////////////	Method:////		CChunkyRes::~CChunkyRes()////	Purpose:////		Destructor for a chunky resource.////	Parameters:////		None.////	Return:////		N/A//CChunkyRes::~CChunkyRes(){	// If we are getting rid of the resource, then	// we should discard all of the chunks...	for (int ndx = 0; ndx < m_Chunks.GetSize(); ndx++)	{		CChunkyResChunk* pChunk = (CChunkyResChunk*)m_Chunks[ndx];		if (pChunk)		{			delete pChunk;		}	}	HX_RESULT theErr = DiscardDiskData();	HX_ASSERT(theErr == HXR_OK);	if(m_ChunksMemoryMRU)	{	    HX_ASSERT(m_ChunksMemoryMRU->GetCount() == 0);	    delete m_ChunksMemoryMRU;	    m_ChunksMemoryMRU = NULL;	}		if(m_ChunksDiskMRU)	{	    HX_ASSERT(m_ChunksDiskMRU->GetCount() == 0);	    delete m_ChunksDiskMRU;	    m_ChunksDiskMRU = NULL;	}	HX_DELETE(m_pMutex);}/////////////////////////////////////////////////////////////////////////////////	Method:////		CChunkyResChunk::MakeSureChunkIsInMemory()////	Purpose:////		Get a portion of the data for a chunk.////	Parameters:////		ULONG32 offset//		char* buf//		ULONG32 count//		ULONG32* actual////	Return:////		HX_RESULT//		Possible errors include: TBD.//HX_RESULT CChunkyResChunk::MakeSureChunkIsInMemory(){	HX_RESULT theErr = HXR_OK;	// If we don't have a chunk pointer, then we aren't in	// memory...	if (!m_pChunkData)	{		// Find ourselves in the MRU list for Disk chunks...		LISTPOSITION pos = m_pChunkRes->m_ChunksDiskMRU->Find(this);		// If were found in the disk MRU list, then we have		// some work to do...		if (pos)		{			// First, remove ourselves from the disk list...			m_pChunkRes->m_ChunksDiskMRU->RemoveAt(pos);			// Load from disk...			theErr = LoadFromDisk();			if (theErr != HXR_OK)			{				goto exit;			}		}		else		{			#ifdef _DEBUG			{				// We shouldn't find ourselves in the MRU list				// for memory chunks... but we want to check!				LISTPOSITION pos = m_pChunkRes->m_ChunksMemoryMRU->Find(this);				// We shouldn't be in this list!!!!				HX_ASSERT(pos == NULL);			}			#endif // end _DEBUG section			m_pChunkData = new UCHAR[m_pChunkRes->m_ChunkSize];			if (!m_pChunkData) theErr = HXR_OUTOFMEMORY;			if (theErr != HXR_OK)			{				goto exit;			} 			HX_ASSERT(GetValidLength() == 0);		}		// Add to the front of the Memory list...		m_pChunkRes->m_ChunksMemoryMRU->AddHead(this);		m_pChunkRes->m_CurMemUsage += GetSize();		// Make sure we don't have to much info in memory...		if (!m_bDisableDiskIO)		{		    m_pChunkRes->TrimDownMemoryMRU();		    HX_ASSERT(m_pChunkData);		}	}	// If we are already in memory, then make sure we are at the	// top of the Memory MRU list!!!	else	{		// We should find ourselves in the MRU list		// for memory chunks... but we want to check!		LISTPOSITION pos = m_pChunkRes->m_ChunksMemoryMRU->Find(this);		// XXXNH: If we aren't in this list it means we were paged out,		// so we only need to put ourselves at the top of the MRU list		if (pos)		{		    // First, remove ourselves from wherever we are in the		    // Memory MRU list...		    m_pChunkRes->m_ChunksMemoryMRU->RemoveAt(pos);		}		// And add ourselves to the top of the list!		m_pChunkRes->m_ChunksMemoryMRU->AddHead(this);	}exit:	return theErr;}/////////////////////////////////////////////////////////////////////////////////	Method:////		CChunkyResChunk::GetValidLength()////	Purpose:////		Determines how much of a chunk is valid////	Parameters:////		ULONG32 offset////	Return:////		HX_RESULT//		Possible errors include: TBD.//ULONG32 CChunkyResChunk::GetValidLength(ULONG32 offset /* = 0 */) const{        HX_ASSERT(offset < GetSize());        ULONG32 ulValidLength = 0;    	LISTPOSITION rangePos = m_ValidRanges.GetHeadPosition();		if (rangePos)	{		do		{			ValidRange* pRange = (ValidRange*)m_ValidRanges.GetNext(rangePos);			HX_ASSERT(pRange);			// see if the offset points into this particular range			if (offset >= pRange->offset				&& offset <= pRange->offset + pRange->length)			{			    ulValidLength = pRange->offset + pRange->length - offset;			}		}		while (rangePos);	}	    return ulValidLength;}/////////////////////////////////////////////////////////////////////////////////	Method:////		CChunkyResChunk::GetData()////	Purpose:////		Get a portion of the data for a chunk.////	Parameters:////		ULONG32 offset//		char* buf//		ULONG32 count//		ULONG32* actual////	Return:////		HX_RESULT//		Possible errors include: TBD.//HX_RESULT CChunkyResChunk::GetData(ULONG32 offset, char* buf, ULONG32 count, ULONG32* actual){	HX_RESULT theErr;	if(!count)	{		*actual = count;		return HXR_OK;	}	// We should have a non-zero valid size	if (!GetValidLength(offset))	{		// This chunk must have been discarded		theErr = HXR_CHUNK_MISSING;		goto exit;	}	// Make sure this chunk is in memory!	theErr = MakeSureChunkIsInMemory();	if (theErr != HXR_OK)	{		goto exit;	}	// You can't read more than there is room in this chunk.	// CChunkyRes should prevent this case...	HX_ASSERT(offset+count <= GetSize());	// The call to MakeSureChunkIsInMemory() should have handled this!	HX_ASSERT_VALID_PTR(m_pChunkData);	*actual = min(count,GetValidLength(offset));	HX_ASSERT(*actual < UINT_MAX);	memcpy(buf,m_pChunkData+offset,(int)(*actual)); /* Flawfinder: ignore */exit:	return theErr;}HX_RESULT CChunkyResChunk::GetContiguousDataPointer(ULONG32 offset, char*& buf, ULONG32 count){    HX_RESULT theErr = HXR_OK;    if(!count)    {	theErr = HXR_FAIL;	goto exit;    }    // First, make sure this chunk is in memory!    theErr = MakeSureChunkIsInMemory();    if (theErr != HXR_OK)    {	goto exit;    }    // You can't write more than there is room in this chunk.    // CChunkyRes should prevent this case...    HX_ASSERT(offset+count <= GetSize());    // Currently, you must write to chunks in order from the    // start of the chunk first. Random access may come in the    // future...    HX_ASSERT(GetValidLength(offset) > 0); // needed still at all?    // The call to MakeSureChunkIsInMemory() should have handled this!    HX_ASSERT_VALID_PTR(m_pChunkData);    AddValidRange(offset, count);        HX_ASSERT(count < UINT_MAX);    buf = (char*) (m_pChunkData+offset);    m_bModified = TRUE;exit:    return theErr;}/////////////////////////////////////////////////////////////////////////////////	Method:////		CChunkyResChunk::AddValidRange()////	Purpose:////		Mark a part of this CChunkyResChunk as valid//		Called from SetData.////	Parameters:////		ULONG32 offset//		ULONG32 length//		BOOL	bValid////	Return:////		HX_RESULT//		Possible errors include: TBD.//

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -