欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

atomizer.cpp

symbian 下的helix player源代码
CPP
第 1 页 / 共 2 页
字号:
/* ***** BEGIN LICENSE BLOCK *****
 * Version: RCSL 1.0/RPSL 1.0
 *
 * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
 *
 * The contents of this file, and the files included with this file, are
 * subject to the current version of the RealNetworks Public Source License
 * Version 1.0 (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the RealNetworks Community Source License Version 1.0
 * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
 * in which case the RCSL will apply. You may also obtain the license terms
 * directly from RealNetworks.  You may not use this file except in
 * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
 * applicable to this file, the RCSL.  Please see the applicable RPSL or
 * RCSL for the rights, obligations and limitations governing use of the
 * contents of the file.
 *
 * This file is part of the Helix DNA Technology. RealNetworks is the
 * developer of the Original Code and owns the copyrights in the portions
 * it created.
 *
 * This file, and the files included with this file, is distributed and made
 * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 *
 * Technology Compatibility Kit Test Suite(s) Location:
 *    http://www.helixcommunity.org/content/tck
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

/****************************************************************************
 *  Defines
 */
#define ATMZR_SEEK_RELATIVE  TRUE
#define ATMZR_SEEK_ABSOLUTE  FALSE

#define ATMZR_MAX_RECURSION_LEVEL   20
#ifdef HELIX_FEATURE_MIN_HEAP
#define ATMZR_PAGING_THRESHOLD	    0x00000400	// 1K
#else	// HELIX_FEATURE_MIN_HEAP
#define ATMZR_PAGING_THRESHOLD	    0x0000FFFF	// 64K
#endif	// HELIX_FEATURE_MIN_HEAP

#define ATMZR_MAX_FILE_SIZE	    0xFFFFFFFF


/****************************************************************************
 *  Includes
 */
#include "atomizer.h"
#include "qtatoms.h"
#include "mempager.h"
#include "qtffrefcounter.h"


/****************************************************************************
 *  Data Types
 */
struct QTHeader
{
    UINT8 pSize[4];
    UINT8 pType[4];
};

struct QTNewHeader
{
    UINT8 pSize[4];
    UINT8 pType[4];
    UINT8 pAtomID[4];
    UINT8 pRsvd1[2];
    UINT8 pChildCount[2];
    UINT8 pRsvd2[4];
};


/****************************************************************************
 *  Class CAtomizer
 */
/****************************************************************************
 *  Constructor/Destructor
 */
CAtomizer::CAtomizer(void)
    : m_pFileSwitcher(NULL)
    , m_pResponse(NULL)
    , m_pCommander(NULL)
    , m_pScheduler(NULL)
    , m_pRoot(NULL)
    , m_pCurrentRoot(NULL)
    , m_pNewAtom(NULL)
    , m_ulStartOffset(0)
    , m_ulFinalOffset(0)
    , m_ulCurrentOffset(0)
    , m_ulNewAtomOffset(0)
    , m_ulNewAtomDataSize(0)
    , m_AtomType(0)
    , m_ulTotalSize(0)
    , m_State(ATMZR_Offline)
    , m_bSyncAccessEnabled(FALSE)
    , m_bPreferLinearAccess(FALSE)
    , m_pRecursionCallback(NULL)
    , m_ulRecursionCount(0)
    , m_lRefCount(0)
{
    g_nRefCount_qtff++;
}


CAtomizer::~CAtomizer()
{
    Close();
    g_nRefCount_qtff--;
}


/****************************************************************************
 *  Main Interface
 */
/****************************************************************************
 *  Init
 */
HX_RESULT CAtomizer::Init(IUnknown *pSource,
			  IUnknown *pResponse,
			  IUnknown *pCommander)
{
    HX_RESULT retVal;

    if ((m_State != ATMZR_Offline) &&
	(m_State != ATMZR_Ready))
    {
	return HXR_UNEXPECTED;
    }

    HX_ASSERT(pSource);
    HX_ASSERT(pResponse);

    // Reset
    HX_RELEASE(m_pFileSwitcher);
    HX_RELEASE(m_pResponse);
    HX_RELEASE(m_pCommander);
    HX_RELEASE(m_pRoot);
    HX_RELEASE(m_pNewAtom);
    HX_RELEASE(m_pRecursionCallback);
    m_ulCurrentOffset = 0;
    m_ulRecursionCount = 0;

    // Find Input Interface
    retVal = pSource->QueryInterface(IID_IHXFileSwitcher, (void**) &m_pFileSwitcher);

    // Find out if syncrhonous use of input is possible
    if (SUCCEEDED(retVal))
    {
	if (SUCCEEDED(m_pFileSwitcher->Advise(HX_FILEADVISE_SYNCACCESS)))
	{
	    m_bSyncAccessEnabled = TRUE;
	    m_pFileSwitcher->Advise(HX_FILEADVISE_ASYNCACCESS);
	}
	
	HX_RESULT adviseRes = 
	    m_pFileSwitcher->Advise(HX_FILEADVISE_RANDOMACCESS);

	if (HXR_ADVISE_PREFER_LINEAR == adviseRes)
	{
	    m_bPreferLinearAccess = TRUE;
	}
    }

    // Find Output Interface
    if (SUCCEEDED(retVal))
    {
	retVal = pResponse->QueryInterface(IID_IHXAtomizerResponse, (void**) &m_pResponse);
    }

    // Find Scheduler Interface
    if (SUCCEEDED(retVal))
    {
	retVal = pResponse->QueryInterface(IID_IHXScheduler, (void **) &m_pScheduler);

	if (FAILED(retVal))
	{
	    retVal = pSource->QueryInterface(IID_IHXScheduler, (void **) &m_pScheduler);
	}
    }

    // See if the Atomization Commander is given
    if (SUCCEEDED(retVal))
    {
	if (pCommander)
	{
	    pCommander->QueryInterface(IID_IHXAtomizationCommander, (void**) &m_pCommander);
	}

	if (!m_pCommander)
	{
	    // No commander given, Atomizer will command itself
	    m_pCommander = (IHXAtomizationCommander *) this;
	    m_pCommander->AddRef();
	}

	m_State = ATMZR_Ready;
    }

    // Allocate Recursion breaker callback
#ifdef QTCONFIG_RECURSION_PROTECTION
    if (SUCCEEDED(retVal))
    {
	m_pRecursionCallback = new CRecursionCallback(this);
	if (m_pRecursionCallback)
	{
	    m_pRecursionCallback->AddRef();
	}
	else
	{
	    retVal = HXR_OUTOFMEMORY;
	}
    }
#endif	// QTCONFIG_RECURSION_PROTECTION

    return retVal;
}


/****************************************************************************
 *  Close
 */
void CAtomizer::Close(void)
{
    m_State = ATMZR_Offline;

    HX_RELEASE(m_pFileSwitcher);
    HX_RELEASE(m_pResponse);
    HX_RELEASE(m_pCommander);
    HX_RELEASE(m_pScheduler);
    HX_RELEASE(m_pRoot);
    HX_RELEASE(m_pNewAtom);
    HX_RELEASE(m_pRecursionCallback);
}


/****************************************************************************
 *  Atomize
 */
HX_RESULT CAtomizer::Atomize(ULONG32 ulOffset, ULONG32 ulSize)
{
    if (m_State != ATMZR_Ready)
    {
	return HXR_UNEXPECTED;
    }

    if ((m_pFileSwitcher == NULL) ||
	(m_pResponse == NULL) ||
	(m_pCommander == NULL))
    {
	return HXR_FAIL;
    }

    // Reset
    HX_RELEASE(m_pRoot);
    HX_RELEASE(m_pNewAtom);
    m_ulCurrentOffset = 0;

    // Take on parameters
    m_ulStartOffset = ulOffset;
    m_ulNewAtomOffset = ulOffset;
    m_ulTotalSize = ulSize;
    m_ulFinalOffset = (m_ulTotalSize == ATOMIZE_ALL) ? ATOMIZE_ALL : m_ulStartOffset + m_ulTotalSize;

    // Prepare the root
    m_pRoot = new CQTRootAtom();
    if (m_pRoot == NULL)
    {
	return HXR_OUTOFMEMORY;
    }
    m_pRoot->AddRef();

    m_pRoot->SetSize(m_ulTotalSize);
    m_pRoot->SetOffset(m_ulStartOffset);
    m_pCurrentRoot = m_pRoot;

    // Start of the atomization process
    m_State = ATMZR_ProcHeader;
    SeekDataCB(m_ulStartOffset);

    return HXR_OK;
}


/****************************************************************************
 *  Private Methods
 */
/****************************************************************************
 *  SeekData
 */
HX_RESULT CAtomizer::SeekData(ULONG32 ulOffset, BOOL bRelative)
{
    if (m_State == ATMZR_Offline)
    {
	return HXR_UNEXPECTED;
    }

    if (bRelative)
    {
	m_ulCurrentOffset += ulOffset;
    }
    else
    {
	m_ulCurrentOffset = ulOffset;
    }

    if (IsOffsetInRange(m_ulCurrentOffset))
    {
	HX_RESULT retVal;

	// Initiate the Seek
	retVal = m_pFileSwitcher->Seek(	ulOffset,
					bRelative,
					(IHXFileResponse *) this);

	if (FAILED(retVal))
	{
	    CompleteAtomization(retVal);
	}
    }
    else
    {
	CompleteAtomization(HXR_OK);
    }

    return HXR_ABORT;
}


/****************************************************************************
 *  ReadData
 */
HX_RESULT CAtomizer::ReadData(ULONG32 ulSize)
{
    HX_RESULT retVal = HXR_OK;

    if (m_State == ATMZR_Offline)
    {
	return HXR_UNEXPECTED;
    }

    if (m_State == ATMZR_ProcHeader)
    {
	retVal = AdjustCurrentRoot();

	if (FAILED(retVal))
	{
	    if (retVal == HXR_CHUNK_MISSING)
	    {
		// udta Atom terminator encountered, must skip over the
		// terminator chunk
		m_ulNewAtomOffset = m_ulCurrentOffset +
				    QT_UDTA_TERMINATOR_LENGTH;
		return SeekDataCB(m_ulNewAtomOffset);
	    }
	    else
	    {
		CompleteAtomization(retVal);

		return HXR_ABORT;
	    }
	}
    }

    m_ulCurrentOffset += ulSize;

    if (IsOffsetInRange(m_ulCurrentOffset - 1))
    {
	HX_RESULT retVal;

	// Initiate the Read
	retVal = m_pFileSwitcher->Read(	ulSize,
					(IHXFileResponse *) this);

	if (SUCCEEDED(retVal))
	{
	    return retVal;
	}
    }

    CompleteAtomization(retVal);

    return HXR_ABORT;
}


/****************************************************************************
 *  ReadDataCB
 */
HX_RESULT CAtomizer::ReadDataCB(ULONG32 ulSize)
{
#ifdef QTCONFIG_RECURSION_PROTECTION
    if (m_ulRecursionCount < ATMZR_MAX_RECURSION_LEVEL)
    {
	m_ulRecursionCount++;
	return ReadData(ulSize);
    }
    else
    {
	CallbackHandle retVal;

	m_ulRecursionCount = 0;
	m_ulSize = ulSize;
	m_CallbackStep = ATMZR_CBSTEP_Read;
	retVal = m_pScheduler->RelativeEnter(m_pRecursionCallback, 0);
	if (!retVal)
	{
	    CompleteAtomization(HXR_FAIL);
	}

	return HXR_OK;
    }
#else	// QTCONFIG_RECURSION_PROTECTION
    return ReadData(ulSize);
#endif	// QTCONFIG_RECURSION_PROTECTION
}


/****************************************************************************
 *  SeekDataCB
 */
HX_RESULT CAtomizer::SeekDataCB(ULONG32 ulOffset, BOOL bRelative)
{
#ifdef QTCONFIG_RECURSION_PROTECTION
    if (m_ulRecursionCount < ATMZR_MAX_RECURSION_LEVEL)
    {
	m_ulRecursionCount++;
	return SeekData(ulOffset, bRelative);
    }
    else
    {
	CallbackHandle retVal;

	m_ulRecursionCount = 0;
	m_ulSize = ulOffset;
	m_bRelative = bRelative;
	m_CallbackStep = ATMZR_CBSTEP_Seek;
	retVal = m_pScheduler->RelativeEnter(m_pRecursionCallback, 0);
	if (!retVal)
	{
	    CompleteAtomization(HXR_FAIL);
	}

	return HXR_OK;
    }
#else	// QTCONFIG_RECURSION_PROTECTION
    return SeekData(ulOffset, bRelative);
#endif	// QTCONFIG_RECURSION_PROTECTION
}


/****************************************************************************
 *  AdjustCurrentRoot
 */
HX_RESULT CAtomizer::AdjustCurrentRoot(void)
{
    CQTAtom *pRootParent;

    HX_ASSERT(m_pCurrentRoot);

    while ((m_pCurrentRoot->GetSize() != ATOMIZE_ALL) &&
	   ((m_pCurrentRoot->GetOffset() +
	     m_pCurrentRoot->GetSize() -
	     m_ulNewAtomOffset) <
	    QT_HEADER_SIZE))
    {
	if (m_ulNewAtomOffset ==
	    (m_pCurrentRoot->GetOffset() + m_pCurrentRoot->GetSize()))
	{
	    // Current Atom is completed, move to the parent
	    pRootParent = m_pCurrentRoot->GetParent();

	    if (pRootParent)
	    {
		m_pCurrentRoot = pRootParent;
		continue;
	    }
	    else
	    {
		// We are at the absolute root
		break;
	    }
	}
	else
	{
	    // Not enough room in current parent to read a header, but
	    // still some data left over
	    if ((m_pCurrentRoot->GetType() == QT_udta) &&
		((m_ulNewAtomOffset + QT_UDTA_TERMINATOR_LENGTH) ==
		(m_pCurrentRoot->GetOffset() + m_pCurrentRoot->GetSize())))
	    {
		// Legacy udta Atom termination - need to skip over the
		// terminator
		return HXR_CHUNK_MISSING;
	    }
	    else
	    {
		// Data is corrupted
		return HXR_PARSE_ERROR;
	    }
	}
    }

    return HXR_OK;
}


/****************************************************************************
 *  CompleteAtomization
 */
void CAtomizer::CompleteAtomization(HX_RESULT status)
{
    CQTAtom* pRoot;

    if (!m_pRoot)
    {
	return;
    }

    if (SUCCEEDED(status))
    {
	// Record the amount of data atomized
	CQTAtom *pRoot = m_pCurrentRoot;

	HX_ASSERT(pRoot);

	// If we have the position of where next atom would be,
	// compute unspecified atom sizes
	if (m_ulNewAtomOffset != ATOMIZE_ALL)
	{
	    while (pRoot)
	    {
		if (pRoot->GetSize() == ATOMIZE_ALL)
		{
		    pRoot->SetSize(m_ulNewAtomOffset - m_ulStartOffset);
		}

		// Move to the parent
		pRoot = pRoot->GetParent();
	    }

	    m_pRoot->SetSize(m_ulNewAtomOffset - m_ulStartOffset);
	}

	status = AdjustCurrentRoot();
    }

    if (SUCCEEDED(status))
    {
	// See if parsing fully completed
	if (((m_ulFinalOffset != ATOMIZE_ALL) &&
	     (m_ulFinalOffset != m_ulCurrentOffset)) ||
	    (m_pRoot != m_pCurrentRoot))
	{
	    status = HXR_CORRUPT_FILE;
	}
    }
    else
    {
	// Data compromizing failure occured during atomization
	HX_RELEASE(m_pRoot);
    }

    HX_RELEASE(m_pNewAtom);

    m_State = ATMZR_Ready;

    pRoot = m_pRoot;
    m_pRoot = NULL;
    m_pCurrentRoot = NULL;

    m_pResponse->AtomReady(status, pRoot);

    if (pRoot)
    {
	pRoot->Release();
    }
}


/****************************************************************************
 *  IHXFileResponse methods
 */
/////////////////////////////////////////////////////////////////////////
//  Method:
//	IHXFileResponse::ReadDone
//  Purpose:
//	Notification interface provided by users of the IHXFileObject
//	interface. This method is called by the IHXFileObject when the
//	last read from the file is complete and a buffer is available.
//
STDMETHODIMP CAtomizer::ReadDone
(
    HX_RESULT		status,
    IHXBuffer*		pBuffer
)
{
    HX_RESULT retVal = HXR_OK;
    QTAtomType AtomType = 0;
    ULONG32 ulAtomSize = 0;
    UINT8* pData = NULL;
    ULONG32 ulDataLen = 0;
    ULONG32 ulNormalizedLen = 0;
    ULONG32 ulAtomID = 0;
    UINT16 uChildCount = 0;

⌨️ 快捷键说明

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