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

📄 chunkres.cpp

📁 linux下的一款播放器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
HX_RESULT CChunkyResChunk::AddValidRange(ULONG32 offset, ULONG32 length, BOOL bValid /* = TRUE */){	HX_RESULT theErr = HXR_OK;	    int nCount = m_ValidRanges.GetCount();    LISTPOSITION pos = m_ValidRanges.GetHeadPosition();	    if (bValid)	{		// I don't think we need to ensure that the chunk is in		// memory, although it always probably will be if this is		// called from SetData.				// Ensure that it's saying that a legal range is valid.				HX_ASSERT(offset+length <= GetSize());				// Create a new range element.				ValidRange* pNewRange = new ValidRange;		pNewRange->offset = offset;		pNewRange->length = length;				// Iterate through the valid ranges to ensure that		// none of them overlap the range we're adding now.		        for (int i=0; i<nCount; i++)		{            ValidRange* pRange = (ValidRange*)m_ValidRanges.GetAt(pos);			            BOOL bNeedToMerge = FALSE;            // See if this range element overlaps the front end of the            // new range element.            if (pRange->offset <= pNewRange->offset	            && pRange->offset + pRange->length >= pNewRange->offset)            {	            bNeedToMerge = TRUE;            }            // see if this range element overlaps the back end of the            // new range element.            if (pRange->offset <= pNewRange->offset + pNewRange->length	            && pRange->offset + pRange->length >= pNewRange->offset + pNewRange->length)            {	            bNeedToMerge = TRUE;            }			// if an overlap happened, make the new range element hold			// the union of both ranges.            if (bNeedToMerge)            {                ULONG32 ulStartOfRange = min(pNewRange->offset, pRange->offset);                ULONG32 ulEndOfRange = max(pNewRange->offset+pNewRange->length,                pRange->offset+pRange->length);                HX_ASSERT(ulEndOfRange >= ulStartOfRange);                pNewRange->offset = ulStartOfRange;                pNewRange->length = ulEndOfRange-ulStartOfRange;				                // delete the one we overlap with since we've ensured                // that pNewRange's range covers both.                pos = m_ValidRanges.RemoveAt(pos);                delete pRange;			}            else                m_ValidRanges.GetAtNext(pos);		}				// Now that we're sure that nobody overlaps us, we can		// add this range.				m_ValidRanges.AddTail((void*)pNewRange);	}    else    {        // bValid is false, so we're INVALIDATING a range.        // iterate through the list of valid ranges, and for each of them        // that overlaps the incoming range, either trim it appropriately        // or delete it entirely.        for (int i=0; i<nCount; i++)        {            ValidRange* pRange = (ValidRange*)m_ValidRanges.GetAt(pos);            HX_ASSERT(pRange);            // see if it's totally covered by the incoming range            if (offset <= pRange->offset && offset+length >= pRange->offset + pRange->length)            {                pos = m_ValidRanges.RemoveAt(pos);                delete pRange;            }            else            {                // see if it needs to be trimmed                ULONG32 ulCurrentRangeEnd = pRange->offset + pRange->length;                ULONG32 ulRangeEnd = offset + length;                BOOL bNeedToTrimOffBackEnd = pRange->offset < offset && ulCurrentRangeEnd >= offset;                BOOL bNeedToTrimOffFrontEnd = pRange->offset < ulRangeEnd                && ulCurrentRangeEnd > ulRangeEnd;                if (bNeedToTrimOffBackEnd)                {                    pRange->length = offset - pRange->offset;                }                if (bNeedToTrimOffFrontEnd)                {                    // if we've also trimmed off the back end                    // then we need to create a new range element                    // to hold this sans-front-end element.                    if (bNeedToTrimOffBackEnd)                    {                        pRange = new ValidRange;                        m_ValidRanges.AddHead(pRange);                    }                    pRange->offset = ulRangeEnd;                    pRange->length = ulCurrentRangeEnd - pRange->offset;                }                m_ValidRanges.GetAtNext(pos);            }		}    }	    return theErr;}/////////////////////////////////////////////////////////////////////////////////	Method:////		CChunkyResChunk::SetData()////	Purpose:////		Set a portion of the data for a chunk.////	Parameters:////		ULONG32 offset//		const char* buf//		ULONG32 count////	Return:////		HX_RESULT//		Possible errors include: TBD.//HX_RESULT CChunkyResChunk::SetData(ULONG32 offset, const char* buf, ULONG32 count){	// First, make sure this chunk is in memory!	HX_RESULT 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());	// The call to MakeSureChunkIsInMemory() should have handled this!	HX_ASSERT_VALID_PTR(m_pChunkData);	HX_ASSERT(count < UINT_MAX);        memcpy(m_pChunkData+offset,buf,(int)(offset+count <= GetSize() ? count : GetSize() - offset));	m_bModified = TRUE;		// Make sure that it remembers that this is now a valid	// range.		AddValidRange(offset, count);exit:	return theErr;}/////////////////////////////////////////////////////////////////////////////////	Method:////		CChunkyResChunk::SpillToDisk()////	Purpose:////		Spills to disk the data of a chunk.////	Parameters:////		None.////	Return:////		HX_RESULT//		Possible errors include: TBD.//HX_RESULT CChunkyResChunk::SpillToDisk(){	Lock();		HX_RESULT	theErr		= HXR_OK;	CHXDataFile*	pFile		= NULL;	ULONG32		actualCount	= 0;	// Don't waste any time unless we are actually modified.	// And only actually spill, if there is something to spill	if (!m_bModified || !m_pChunkData)	{		goto exit;	}	// If we have never spilled to disk, then ask the ChunkyRes	// for the temp file name and a slot to spill to.	if (!m_bPreviouslySpilled)	{		theErr = m_pChunkRes->GetTempFileChunk(pFile,m_ulTempFileOffset);	}	// Otherwise, just get the temp file name.	else	{		theErr = m_pChunkRes->GetTempFile(pFile);	}	// If we failed to open the file, then set the valid	// size to 0. If the user wants to use the data, they	// will need to handle the case of not having the data!	if (theErr != HXR_OK)	{		HX_ASSERT(pFile == NULL);		theErr = HXR_TEMP_FILE;		goto exit;	}	theErr = pFile->Seek(m_ulTempFileOffset,SEEK_SET);	if (theErr != HXR_OK)	{		theErr = HXR_TEMP_FILE;		goto exit;	}	HX_ASSERT(m_pChunkData);	actualCount = pFile->Write((char *)m_pChunkData, m_pChunkRes->m_ChunkSize);	m_bPreviouslySpilled = TRUE;	if (actualCount != m_pChunkRes->m_ChunkSize)	{		theErr = HXR_TEMP_FILE;	}exit:	// If we created a file, then clean it up!	if (pFile)	{		delete pFile;	}	// If we had an error then record that our size is now invalid.	if (theErr != HXR_OK)	{		AddValidRange(0, m_pChunkRes->m_ChunkSize, FALSE);		m_bPreviouslySpilled = FALSE;	}	// Never the less, we do get rid of the data!	if (m_pChunkData)	{		delete[] m_pChunkData;		m_pChunkData = NULL;	}	Unlock();	return theErr;}/////////////////////////////////////////////////////////////////////////////////	Method:////		CChunkyResChunk::LoadFromDisk()////	Purpose:////		Loads into memory the data from the chunk previously spilled to//		disk.////	Parameters:////		None.////	Return:////		HX_RESULT//		Possible errors include: TBD.//HX_RESULT CChunkyResChunk::LoadFromDisk(){	Lock();		HX_RESULT	theErr		= HXR_OK;	CHXDataFile*	pFile		= NULL;	ULONG32		amountRead	= 0;	// We shouldn't be here if we have memory already allocated!	HX_ASSERT(m_pChunkData == NULL);	// If we have never spilled to disk, then there is nothing to	// load from disk!	if (!m_bPreviouslySpilled)	{		// Even if we've never been spilled, we need to make		// sure we have memory available...		m_pChunkData = new UCHAR[m_pChunkRes->m_ChunkSize];		if(!m_pChunkData)		{			theErr = HXR_OUTOFMEMORY;			goto exit;		}		goto exit;	}	// Get the temp file name.	theErr = m_pChunkRes->GetTempFile(pFile);	// If we failed to open the file, then set the valid	// size to 0. If the user wants to use the data, they	// will need to handle the case of not having the data!	if (theErr != HXR_OK)	{		HX_ASSERT(pFile == NULL);		theErr = HXR_TEMP_FILE;		goto exit;	}	theErr = pFile->Seek(m_ulTempFileOffset,SEEK_SET);	if (theErr != HXR_OK)	{		theErr = HXR_TEMP_FILE;		goto exit;	}	m_pChunkData = new UCHAR[m_pChunkRes->m_ChunkSize];	if(!m_pChunkData)	{		theErr = HXR_OUTOFMEMORY;		goto exit;	}	amountRead = pFile->Read((char *)m_pChunkData, m_pChunkRes->m_ChunkSize);	if(amountRead != m_pChunkRes->m_ChunkSize)	{		theErr = HXR_TEMP_FILE;		delete[] m_pChunkData;		m_pChunkData = NULL;		goto exit;	}exit:	// If we actually, loaded the data from disk, then	// we are not modified!	if (theErr == HXR_OK)	{		m_bModified = FALSE;	}	// If we created a file, then clean it up!	if (pFile)	{		delete pFile;	}	// If we had an error then record that our size is now invalid.	if (theErr != HXR_OK)	{		AddValidRange(0, m_pChunkRes->m_ChunkSize, FALSE);		m_bPreviouslySpilled = FALSE;	}	Unlock();	return theErr;}/////////////////////////////////////////////////////////////////////////////////	Method:////		CChunkyResChunk::CChunkyResChunk()////	Purpose:////		Constructor for CChunkyResChunk.////	Parameters:////		None.////	Return:////		N/A//CChunkyResChunk::CChunkyResChunk(CChunkyRes* pChunkyRes)	: m_ChunkOffset(0)	, m_pChunkData(NULL)	, m_ulTempFileOffset(0)	, m_bPreviouslySpilled(FALSE)	, m_bModified(FALSE)	, m_pChunkRes(pChunkyRes)	, m_bDisableDiskIO(FALSE){    HX_ASSERT(m_pChunkRes);}/////////////////////////////////////////////////////////////////////////////////	Method:////		CChunkyResChunk::~CChunkyResChunk()////	Purpose:////		Destructor for CChunkyResChunk.////	Parameters:////		N/A////	Return:////		N/A//CChunkyResChunk::~CChunkyResChunk(){	HX_RESULT theErr = DiscardDiskData();	HX_ASSERT(theErr == HXR_OK);	if (m_pChunkData)	{		delete[] m_pChunkData;		m_pChunkData = NULL;	}		while (!m_ValidRanges.IsEmpty())	{		ValidRange* pRange = (ValidRange*)m_ValidRanges.RemoveHead();		delete pRange;	}}HX_RESULT CChunkyRes::GetTempFileChunk(CHXDataFile*& pFile,ULONG32& ulTempFileOffset){	// You should set this to NULL on input.	HX_ASSERT(pFile == NULL);	// Get the temporary file...	HX_RESULT theErr = GetTempFile(pFile);	if (theErr == HXR_OK)	{		// If there are free chunk spaces in the file, use those first		if (!m_FreeDiskOffsets.IsEmpty())		{			ulTempFileOffset = (UINT32)(PTR_INT)m_FreeDiskOffsets.GetTail();			m_FreeDiskOffsets.RemoveTail();		}		else		{		    // return the previous next chunk offset...		    ulTempFileOffset = m_ulNextTempFileChunk;		    // bump the next chunk offset		    m_ulNextTempFileChunk += m_ChunkSize;		}	}	return theErr;}/////////////////////////////////////////////////////////////////////////////////	Method:////		CChunkyResChunk::DiscardDiskData()////	Purpose:////		Discard the disk data for a chunk. This is normally done on//		destruction of the chunk when the resource associated with this//		chunk is discarded from disk, but can also be done when we//		are downloading a live stream and want to discard chunks that//		have already been served up to the user.////	Parameters:////		None.////	Return:////		HX_RESULT//		Possible errors include: TBD.//HX_RESULT CChunkyResChunk::DiscardDiskData(){	HX_RESULT theErr = HXR_OK;	// Remove ourselves from the Memory MRU list...	LISTPOSITION posMem = m_pChunkRes->m_ChunksMemoryMRU->Find(this);	if (posMem)	{		m_pChunkRes->m_ChunksMemoryMRU->RemoveAt(posMem);		m_pChunkRes->m_CurMemUsage -= GetSize();	}	// Remove ourselves from the Disks MRU list...	LISTPOSITION posDisk = m_pChunkRes->m_ChunksDiskMRU->Find(this);	if (posDisk)	{		m_pChunkRes->m_ChunksDiskMRU->RemoveAt(posDisk);	}	// Reset a bunch of our members in case someone tries	// to access this chunk after its data has been discarded	m_ChunkOffset		= 0;	AddValidRange(0, m_pChunkRes->m_ChunkSize, FALSE);	HX_VECTOR_DELETE(m_pChunkData);	m_ulTempFileOffset	= 0;	m_bPreviouslySpilled	= FALSE;	m_bModified		= FALSE;	m_bDisableDiskIO	= TRUE;	return theErr;}/////////////////////////////////////////////////////////////////////////////////	Method:////		CChunkyRes::DiscardDiskData()////	Purpose:////		Discard the disk data for a chunk. This is normally done on//		destruction of the chunk when the resource associated with this//		chunk is discarded from disk.////	Parameters:////		None.////	Return:////		HX_RESULT//		Possible errors include: TBD.//HX_RESULT CChunkyRes::DiscardDiskData(){	HX_RESULT theErr = HXR_OK;	const char* pFileName = m_strTempFileName;	if (pFileName && *pFileName)	{#if defined (_MACINTOSH) || defined (_UNIX) || defined(_SYMBIAN) || defined(_OPENWAVE)		int nRet = unlink(pFileName);#else		int nRet = -1;				if (DeleteFile(OS_STRING(pFileName)))		    nRet = 0;#endif		HX_ASSERT(nRet == 0);		m_strTempFileName = "";	}	return theErr;}HX_RESULT CChunkyRes::GetTempFile(CHXDataFile*& pFile){	// You should set this to NULL on input.	HX_ASSERT(pFile == NULL);	HX_RESULT		theErr			= HXR_OK;	const char*		pFileName		= m_strTempFileName;	char			szTempFileName[_MAX_PATH]; /* Flawfinder: ignore */	// Create the OS Specific File object...	pFile = CHXDataFile::Construct();	if (!pFile)	{		theErr = HXR_TEMP_FILE;		goto exit;	}	// If we don't have a filename, then we need to	// get a temp filename, and we know we are creating	// a file.	if (!pFileName || !*pFileName)	{#if defined(_MAC_MACHO) || defined(_MAC_CFM) // GR 7/15/03 other platforms may want a clearer name here too, since 8.3 restrictions don't apply 		if(!pFile->GetTemporaryFileName("Helix", szTempFileName, _MAX_PATH))#else		if(!pFile->GetTemporaryFileName("PNX",szTempFileName, _MAX_PATH))#endif		{			goto exit;		}		m_strTempFileName = szTempFileName;		pFileName = m_strTempFileName;	}	// Open the file...	if (!pFileName)	{		theErr = HXR_TEMP_FILE;		goto exit;	}	if (!m_bHasBeenOpened)	{		// Note: _O_RDWR does not work on the mac. O_RDWR is standard ANSI.		theErr = pFile->Open(pFileName,O_CREAT + O_RDWR);				if (!theErr)		{			m_bHasBeenOpened = TRUE;		}	}	else	{		// Note: _O_RDWR does not work on the mac. O_RDWR is standard ANSI.		theErr = pFile->Open(pFileName, O_RDWR);				}exit:	return theErr;}

⌨️ 快捷键说明

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