atomizer.cpp
字号:
BOOL bLoop = FALSE;
if (SUCCEEDED(status) && (m_State != ATMZR_Offline))
{
HX_ASSERT(pBuffer);
pBuffer->Get(pData, ulDataLen);
ulNormalizedLen = ulDataLen;
do
{
bLoop = FALSE;
switch (m_State)
{
case ATMZR_ProcNewHeader:
ulNormalizedLen -= (QT_NEW_HEADER_SIZE - QT_HEADER_SIZE);
{
QTNewHeader *pHeader = (QTNewHeader *) (pData);
ulAtomID = CQTAtom::GetUL32(pHeader->pAtomID);
uChildCount = CQTAtom::GetUI16(pHeader->pChildCount);
}
// drop to case below
case ATMZR_ProcHeader:
if (ulNormalizedLen == QT_HEADER_SIZE)
{
QTHeader *pHeader = (QTHeader *) (pData);
AtomType = CQTAtom::GetUL32(pHeader->pType);
ulAtomSize = CQTAtom::GetUL32(pHeader->pSize);
if (AtomType == 0)
{
if (m_State == ATMZR_ProcHeader)
{
// Try to interpret this as CQTNewAtom
m_State = ATMZR_ProcNewHeader;
SeekDataCB(QT_NEW_HEADER_GAP, ATMZR_SEEK_RELATIVE);
return retVal;
}
status = HXR_PARSE_ERROR;
}
else if (ulAtomSize == 1)
{
// This must be the Atom with extended size
m_State = ATMZR_ProcExtendedSize;
m_AtomType = AtomType;
ReadDataCB(QT_EXTENDED_SIZE);
return retVal;
}
else if (ulAtomSize == 0)
{
// This Atom extends to the of enclosing container
ulAtomSize = ATOMIZE_ALL;
}
// drop to case below;
m_State = ATMZR_MakeAtom;
}
else
{
break;
}
case ATMZR_MakeAtom:
{
QTAtomizerCmd AtomCmd;
HX_ASSERT(!m_pNewAtom);
AtomCmd = m_pCommander->GetAtomCommand( AtomType,
m_pCurrentRoot);
if (ulAtomSize == ATOMIZE_ALL)
{
if (m_pCurrentRoot->GetSize() != ATOMIZE_ALL)
{
ulAtomSize = m_pCurrentRoot->GetOffset() +
m_pCurrentRoot->GetSize() -
m_ulNewAtomOffset;
HX_ASSERT(ulAtomSize != 0);
if (ulAtomSize == 0)
{
status = HXR_PARSE_ERROR;
break;
}
}
}
switch (AtomCmd)
{
case ATMZR_CMD_LOAD:
case ATMZR_CMD_OUTLINE:
m_pNewAtom = CreateQTAtom( AtomType,
m_ulNewAtomOffset,
ulAtomSize,
NULL, // no parent
ulAtomID,
uChildCount);
if (m_pNewAtom != NULL)
{
if (m_pNewAtom->IsLeafType())
{
// A Leaf Atom
if (AtomCmd == ATMZR_CMD_LOAD)
{
m_ulNewAtomDataSize = 0;
if (ulAtomSize != ATOMIZE_ALL)
{
m_ulNewAtomDataSize = ulAtomSize - ulDataLen;
}
#ifndef QTCONFIG_NO_PAGING
if ((m_ulNewAtomDataSize > ATMZR_PAGING_THRESHOLD)
&& m_pNewAtom->IsPagingAtom()
#ifdef QTCONFIG_NO_ASYNC_PAGING
&& m_bSyncAccessEnabled
#endif // QTCONFIG_NO_ASYNC_PAGING
&& (m_ulNewAtomDataSize != ATOMIZE_ALL)
)
{
CMemPager* pMemPager = new CMemPager;
status = HXR_OUTOFMEMORY;
if (pMemPager)
{
pMemPager->AddRef();
status = pMemPager->Init(m_pFileSwitcher,
m_ulCurrentOffset,
m_ulNewAtomDataSize);
if (SUCCEEDED(status))
{
m_pNewAtom->AddRef();
m_State = ATMZR_ProcBody;
m_pNewAtom->SetMemPager(pMemPager);
status = pMemPager->LoadPage((IHXFileResponse*) this);
}
pMemPager->Release();
if (SUCCEEDED(status))
{
return retVal;
}
}
// Failure
HX_ASSERT(status != HXR_OK);
break;
}
else
#endif // QTCONFIG_NO_PAGING
if ((m_ulNewAtomDataSize != 0) ||
(ulAtomSize == ATOMIZE_ALL))
{
// Leaf atom with data
m_pNewAtom->AddRef();
m_State = ATMZR_ProcBody;
if (m_ulNewAtomDataSize != 0)
{
ReadDataCB(m_ulNewAtomDataSize);
return retVal;
}
else
{
ReadDataCB(ATMZR_MAX_FILE_SIZE - m_ulCurrentOffset);
return retVal;
}
}
else
{
// Leaf atom with no data
m_pCurrentRoot->AddPresentChild(m_pNewAtom);
m_ulNewAtomOffset = m_ulCurrentOffset;
m_pNewAtom = NULL;
m_State = ATMZR_ProcHeader;
ReadDataCB(QT_HEADER_SIZE);
}
}
else
{
// We are not to load the data
// so we are ready to attach the atom shell
// to the atom tree.
m_pCurrentRoot->AddPresentChild(m_pNewAtom);
m_pNewAtom = NULL;
if (ulAtomSize != ATOMIZE_ALL)
{
m_ulNewAtomOffset = m_ulCurrentOffset +
ulAtomSize -
ulDataLen;
m_State = ATMZR_ProcHeader;
SeekDataCB(m_ulNewAtomOffset);
return retVal;
}
// Location of the end of file - unknown
m_ulNewAtomOffset = ATOMIZE_ALL;
}
}
else
{
// A Non Leaf Atom - has no direct data
m_pCurrentRoot->AddPresentChild(m_pNewAtom);
m_pCurrentRoot = m_pNewAtom;
m_ulNewAtomOffset = m_ulCurrentOffset;
m_pNewAtom = NULL;
m_State = ATMZR_ProcHeader;
ReadDataCB(QT_HEADER_SIZE);
return retVal;
}
break;
}
// If we couldn't create the atom, skip it.
// Drop down to case below.
case ATMZR_CMD_SKIP:
if (ulAtomSize != ATOMIZE_ALL)
{
m_ulNewAtomOffset = m_ulCurrentOffset +
ulAtomSize -
ulDataLen;
m_State = ATMZR_ProcHeader;
/* Check to see if we are trying to skip
* an mdat atom while using a file object
* that prefers linear access (ie. HTTP/1.0)
*/
if (m_bPreferLinearAccess && (QT_mdat == AtomType))
{
HX_RESULT completionRes = HXR_INVALID_FILE;
if ((m_pCurrentRoot) &&
(m_pCurrentRoot->FindPresentChild(QT_moov)))
{
/* We have the moov atom already so
* this file is likely formatted for
* progressive download
*/
completionRes = HXR_OK;
}
CompleteAtomization(completionRes);
}
else
{
SeekDataCB(m_ulNewAtomOffset);
}
return retVal;
}
else
{
m_ulNewAtomOffset = ATOMIZE_ALL;
break;
}
// If we couldn't skip the atom, stop.
// Drop to case below
case ATMZR_CMD_STOP:
break;
default:
status = HXR_INVALID_PARAMETER;
break;
}
}
break;
case ATMZR_ProcExtendedSize:
if (ulNormalizedLen == QT_EXTENDED_SIZE)
{
AtomType = m_AtomType;
ulAtomSize = CQTAtom::GetUL32(pData);
HX_ASSERT(ulAtomSize == 0);
if (ulAtomSize == 0)
{
ulAtomSize = CQTAtom::GetUL32(pData + 4);
m_State = ATMZR_MakeAtom;
bLoop = TRUE;
}
else
{
// can't handle atom size beyond 4GB
status = HXR_ABORT;
}
}
break;
case ATMZR_ProcBody:
HX_ASSERT(m_pNewAtom);
if (m_ulNewAtomDataSize != ATOMIZE_ALL)
{
if ((!m_pNewAtom->IsPagingEnabled()) &&
(ulDataLen == m_ulNewAtomDataSize))
{
HX_ASSERT(pBuffer);
m_pNewAtom->SetBuffer(pBuffer);
m_pCurrentRoot->AddPresentChild(m_pNewAtom);
m_ulNewAtomOffset = m_ulCurrentOffset;
m_pNewAtom->Release();
m_pNewAtom = NULL;
m_State = ATMZR_ProcHeader;
ReadDataCB(QT_HEADER_SIZE);
return retVal;
}
else if (m_pNewAtom->IsPagingEnabled() &&
(ulDataLen != 0))
{
m_ulCurrentOffset += ulDataLen;
m_pCurrentRoot->AddPresentChild(m_pNewAtom);
HX_ASSERT(m_ulNewAtomDataSize >= ulDataLen);
m_ulNewAtomOffset = m_ulCurrentOffset +
m_ulNewAtomDataSize -
ulDataLen;
m_pNewAtom->Release();
m_pNewAtom = NULL;
m_State = ATMZR_ProcHeader;
if (m_ulNewAtomOffset != m_ulCurrentOffset)
{
SeekDataCB(m_ulNewAtomOffset);
}
else
{
ReadDataCB(QT_HEADER_SIZE);
}
return retVal;
}
}
else if (ulDataLen > 0)
{
// Body extended to the end of file - stop here
HX_ASSERT(pBuffer);
m_ulNewAtomDataSize = ulDataLen;
m_pNewAtom->SetBuffer(pBuffer);
m_pNewAtom->SetSize(m_ulNewAtomDataSize);
m_ulNewAtomOffset = m_ulCurrentOffset;
m_pNewAtom->Release();
m_pNewAtom = NULL;
}
break;
default:
status = HXR_FAIL;
retVal = HXR_UNEXPECTED;
break;
}
} while (bLoop);
}
else
{
// Did not clear for processing
if (m_State == ATMZR_Offline)
{
return HXR_UNEXPECTED;
}
else
{
// The read must have failed - complete atomization as is
status = HXR_OK;
}
}
CompleteAtomization(status);
return retVal;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXFileResponse::SeekDone
// Purpose:
// Notification interface provided by users of the IHXFileObject
// interface. This method is called by the IHXFileObject when the
// last seek in the file is complete.
//
STDMETHODIMP CAtomizer::SeekDone(HX_RESULT status)
{
HX_RESULT retVal = HXR_OK;
if (SUCCEEDED(status) && (m_State != ATMZR_Offline))
{
// We seek headers only, so start the read of a header
switch(m_State)
{
case ATMZR_ProcHeader:
ReadDataCB(QT_HEADER_SIZE);
return retVal;
case ATMZR_ProcNewHeader:
ReadDataCB(QT_NEW_HEADER_SIZE);
return retVal;
default:
status = HXR_FAIL;
retVal = HXR_UNEXPECTED;
break;
}
}
else
{
// Did not clear for processing
if (m_State == ATMZR_Offline)
{
return HXR_UNEXPECTED;
}
else
{
// The seek must have failed - complete atomization as is
status = HXR_OK;
}
}
CompleteAtomization(status);
return retVal;
}
/****************************************************************************
* IUnknown methods
*/
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::QueryInterface
//
STDMETHODIMP CAtomizer::QueryInterface(REFIID riid, void** ppvObj)
{
if (IsEqualIID(riid, IID_IHXFileResponse))
{
AddRef();
*ppvObj = (IHXFileResponse*) this;
return HXR_OK;
}
else if (IsEqualIID(riid, IID_IHXAtomizationCommander))
{
AddRef();
*ppvObj = (IHXAtomizationCommander*) this;
return HXR_OK;
}
else if (IsEqualIID(riid, IID_IHXThreadSafeMethods))
{
AddRef();
*ppvObj = (IHXThreadSafeMethods*) this;
return HXR_OK;
}
else if (IsEqualIID(riid, IID_IUnknown))
{
AddRef();
*ppvObj = this;
return HXR_OK;
}
*ppvObj = NULL;
return HXR_NOINTERFACE;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::AddRef
//
STDMETHODIMP_(ULONG32) CAtomizer::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::Release
//
STDMETHODIMP_(ULONG32) CAtomizer::Release()
{
if (InterlockedDecrement(&m_lRefCount) > 0)
{
return m_lRefCount;
}
delete this;
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// Method:
// IHXThreadSafeMethods::IsThreadsafe
//
// Purpose:
// This routine returns threadsafeness information about the file object
// which is used by the server for improved performance.
//
STDMETHODIMP_(UINT32)
CAtomizer::IsThreadSafe()
{
return HX_THREADSAFE_METHOD_FF_GETPACKET | HX_THREADSAFE_METHOD_FSR_READDONE;
}
/****************************************************************************
* Class CAtomizer::RecursionCallback
*/
#ifdef QTCONFIG_RECURSION_PROTECTION
/****************************************************************************
* Constructor/Destructor
*/
CAtomizer::CRecursionCallback::CRecursionCallback(CAtomizer *pAtomizer)
: m_pAtomizer(pAtomizer)
, m_lRefCount(0)
{
HX_ASSERT(m_pAtomizer);
m_pAtomizer->AddRef();
}
CAtomizer::CRecursionCallback::~CRecursionCallback(void)
{
HX_RELEASE(m_pAtomizer);
}
/****************************************************************************
* IHXCallback methods
*/
/****************************************************************************
* Func
*/
STDMETHODIMP CAtomizer::CRecursionCallback::Func(void)
{
switch (m_pAtomizer->m_CallbackStep)
{
case ATMZR_CBSTEP_Read:
m_pAtomizer->ReadData(m_pAtomizer->m_ulSize);
return HXR_OK;
case ATMZR_CBSTEP_Seek:
m_pAtomizer->SeekData(m_pAtomizer->m_ulSize,
m_pAtomizer->m_bRelative);
return HXR_OK;
default:
// nothing to do
break;
}
return HXR_UNEXPECTED;
}
/****************************************************************************
* IUnknown methods
*/
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::QueryInterface
//
STDMETHODIMP CAtomizer::CRecursionCallback::QueryInterface(
REFIID riid,
void** ppvObj)
{
if (IsEqualIID(riid, IID_IUnknown))
{
AddRef();
*ppvObj = this;
return HXR_OK;
}
else if (IsEqualIID(riid, IID_IHXCallback))
{
AddRef();
*ppvObj = (IHXCallback*)this;
return HXR_OK;
}
*ppvObj = NULL;
return HXR_NOINTERFACE;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::AddRef
//
STDMETHODIMP_(ULONG32) CAtomizer::CRecursionCallback::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::Release
//
STDMETHODIMP_(ULONG32) CAtomizer::CRecursionCallback::Release()
{
if (InterlockedDecrement(&m_lRefCount) > 0)
{
return m_lRefCount;
}
delete this;
return 0;
}
#endif // QTCONFIG_RECURSION_PROTECTION
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -