qtatmmgs.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 2,238 行 · 第 1/4 页
CPP
2,238 行
/* ***** 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 _IGNORE_MP4_AUDIO
#define TRACK_SDP_CHUNK_SIZE 512
/****************************************************************************
* Includes
*/
#include "qtatmmgs.h"
#include "qttrkmgr.h"
#include "mp4desc.h"
#include "hxstrutl.h"
#include "rtptypes.h"
#include "rtsputil.h"
#ifndef QTCONFIG_SPEED_OVER_SIZE
#include "qtatmmgs_inline.h"
#endif // QTCONFIG_SPEED_OVER_SIZE
/****************************************************************************
* Track Edit Manager
*/
#define QT_MAX_MOVIE_DURATION 0xFFFFFFFF
/****************************************************************************
* Constructor/Destructor
*/
CQT_TrackEdit_Manager::CQT_TrackEdit_Manager(void)
: m_pEditListAtom(NULL)
, m_ulMovieTimeScale(1)
, m_ulMediaTimeScale(1)
, m_ulNumEdits(0)
, m_ulCurrentEditIdx(0)
, m_ulCurrentEditTime(0)
, m_ulCurrentInEditTime(0)
, m_ulCurrentEditDuration(QT_MAX_MOVIE_DURATION)
, m_ulCurrentMediaStartTime(0)
{
;
}
CQT_TrackEdit_Manager::~CQT_TrackEdit_Manager(void)
{
HX_RELEASE(m_pEditListAtom);
}
/****************************************************************************
* Main Interface
*/
/****************************************************************************
* Init
*/
HX_RESULT CQT_TrackEdit_Manager::Init(CQTAtom* pAtom,
ULONG32 ulMovieTimeScale,
ULONG32 ulMediaTimeScale)
{
HX_RESULT retVal = HXR_OK;
HX_ASSERT(ulMovieTimeScale);
HX_ASSERT(ulMediaTimeScale);
m_ulMovieTimeScale = ulMovieTimeScale;
m_ulMediaTimeScale = ulMediaTimeScale;
m_ulNumEdits = 0;
HX_RELEASE(m_pEditListAtom);
if (pAtom)
{
if (pAtom->GetType() == QT_elst)
{
m_pEditListAtom = (CQT_elst_Atom*) pAtom;
}
else
{
m_pEditListAtom = (CQT_elst_Atom*) pAtom->FindPresentChild(QT_elst);
}
if (m_pEditListAtom)
{
m_pEditListAtom->AddRef();
m_ulNumEdits = m_pEditListAtom->Get_NumEntries();
}
}
if (!EstablishByTime(0))
{
retVal = HXR_FAIL;
// Reset State
HX_RELEASE(m_pEditListAtom);
m_ulNumEdits = 0;
EstablishByTime(0);
}
return retVal;
}
/****************************************************************************
* EstablishByMovieTime
*/
BOOL CQT_TrackEdit_Manager::EstablishByTime(ULONG32 ulTime)
{
m_ulCurrentEditIdx = 0;
m_ulCurrentEditTime = 0;
m_ulCurrentInEditTime = (ULONG32) (ulTime / 1000.0 *
m_ulMediaTimeScale +
0.5);
if (m_ulNumEdits > 0)
{
m_ulCurrentEditDuration = MovieToMediaUnits(
m_pEditListAtom->Get_TrackDuration(0));
m_ulCurrentMediaStartTime = m_pEditListAtom->Get_MediaTime(0);
return SequenceToEdit();
}
else
{
m_ulCurrentEditDuration = QT_MAX_MOVIE_DURATION;
m_ulCurrentMediaStartTime = 0;
}
return TRUE;
}
/****************************************************************************
* Private Methods
*/
/****************************************************************************
* SequenceToEdit
*/
BOOL CQT_TrackEdit_Manager::SequenceToEdit(void)
{
while ((m_ulCurrentMediaStartTime == QT_EMPTY_EDIT) ||
(m_ulCurrentInEditTime >= m_ulCurrentEditDuration))
{
m_ulCurrentEditIdx++;
if (m_ulCurrentEditIdx < m_ulNumEdits)
{
if (m_ulCurrentMediaStartTime != QT_EMPTY_EDIT)
{
m_ulCurrentInEditTime -= m_ulCurrentEditDuration;
}
m_ulCurrentEditTime += m_ulCurrentEditDuration;
m_ulCurrentEditDuration = MovieToMediaUnits(
m_pEditListAtom->Get_TrackDuration(
m_ulCurrentEditIdx));
m_ulCurrentMediaStartTime = m_pEditListAtom->Get_MediaTime(
m_ulCurrentEditIdx);
}
else
{
m_ulCurrentEditIdx--;
return FALSE;
}
}
return TRUE;
}
/****************************************************************************
* Sample To Chunk Manager
*/
#define QT_MAX_SAMPLES_PER_CHUNK 0xFFFFFFFF
#define QT_NULL_CHUNK_NUM 0
/****************************************************************************
* Constructor/Destructor
*/
CQT_SampleToChunk_Manager::CQT_SampleToChunk_Manager(void)
: m_ulNumEntries(0)
, m_pSampleToChunkAtom(NULL)
, m_ulSampleInChunkNum(0)
, m_ulCurrentChunk(0)
, m_ulNextEntryChunk(QT_NULL_CHUNK_NUM)
, m_ulCurrentEntryIdx(0)
, m_ulSamplesPerChunk(QT_MAX_SAMPLES_PER_CHUNK)
, m_ulSampleNumber(0)
, m_ulSampleDescIdx(QT_BAD_IDX)
#ifdef _STCO_ZERO_BASED_IQ
, m_ulChunkNumOffset(0)
#endif // _STCO_ZERO_BASED_IQ
{
;
}
CQT_SampleToChunk_Manager::~CQT_SampleToChunk_Manager()
{
HX_RELEASE(m_pSampleToChunkAtom);
}
/****************************************************************************
* Init
*/
HX_RESULT CQT_SampleToChunk_Manager::Init(CQTAtom* pAtom)
{
HX_RESULT retVal = HXR_OK;
HX_RELEASE(m_pSampleToChunkAtom);
m_ulNumEntries = 0;
m_ulSampleNumber = 0;
if (pAtom)
{
if (pAtom->GetType() == QT_stsc)
{
m_pSampleToChunkAtom = (CQT_stsc_Atom*) pAtom;
}
else
{
m_pSampleToChunkAtom = (CQT_stsc_Atom*) pAtom->FindPresentChild(QT_stsc);
}
if (m_pSampleToChunkAtom)
{
m_pSampleToChunkAtom->AddRef();
m_ulNumEntries = m_pSampleToChunkAtom->Get_NumEntries();
}
}
if (m_ulNumEntries == 0)
{
EstablishBySample(0);
retVal = HXR_NO_DATA;
}
else
{
m_ulSampleNumber = 2; // Force full initialization
retVal = EstablishBySample(1) ? HXR_OK : HXR_FAIL;
#ifdef _STCO_ZERO_BASED_IQ
m_ulChunkNumOffset = 0;
if (retVal == HXR_OK)
{
if ((m_ulCurrentChunk == 0) ||
(m_ulSampleDescIdx == ((ULONG32) -1)))
{
m_ulCurrentChunk = 1;
m_ulNextEntryChunk++;
m_ulSampleDescIdx++;
m_ulChunkNumOffset = 1;
}
}
#endif // _STCO_ZERO_BASED_IQ
}
return retVal;
}
/****************************************************************************
* EstablishBySample
*/
BOOL CQT_SampleToChunk_Manager::EstablishBySample(ULONG32 ulSampleNum)
{
if (m_ulNumEntries > 0)
{
HX_ASSERT(ulSampleNum);
if (ulSampleNum >= m_ulSampleNumber)
{
// Search Forward
m_ulSampleInChunkNum += (ulSampleNum - m_ulSampleNumber);
m_ulSampleNumber = ulSampleNum;
return SequenceToChunk();
}
else if (ulSampleNum > (m_ulSampleNumber >> 1))
{
// Search in Reverse
m_ulSampleInChunkNum = m_ulSamplesPerChunk -
m_ulSampleInChunkNum +
m_ulSampleNumber -
ulSampleNum +
1;
m_ulSampleNumber = ulSampleNum;
if (SequenceReverseToChunk())
{
m_ulSampleInChunkNum = m_ulSamplesPerChunk -
m_ulSampleInChunkNum +
1;
return TRUE;
}
}
else
{
// Search Forward from the beginning
m_ulSampleInChunkNum = ulSampleNum;
m_ulCurrentEntryIdx = 0;
m_ulCurrentChunk = m_pSampleToChunkAtom->Get_FirstChunk(0)
#ifdef _STCO_ZERO_BASED_IQ
+ m_ulChunkNumOffset
#endif // _STCO_ZERO_BASED_IQ
;
m_ulSamplesPerChunk = m_pSampleToChunkAtom->Get_SamplesPerChunk(0);
m_ulSampleDescIdx = m_pSampleToChunkAtom->Get_SampleDescID(0) - 1
#ifdef _STCO_ZERO_BASED_IQ
+ m_ulChunkNumOffset
#endif // _STCO_ZERO_BASED_IQ
;
if (m_ulNumEntries > 1)
{
m_ulNextEntryChunk = m_pSampleToChunkAtom->
Get_FirstChunk(1)
#ifdef _STCO_ZERO_BASED_IQ
+ m_ulChunkNumOffset
#endif // _STCO_ZERO_BASED_IQ
;
}
else
{
// No more chunk entries
m_ulNextEntryChunk = QT_NULL_CHUNK_NUM;
}
m_ulSampleNumber = ulSampleNum;
return SequenceToChunk();
}
}
else
{
m_ulSampleNumber = 0;
m_ulSampleInChunkNum = 0;
m_ulCurrentChunk = 0;
m_ulSamplesPerChunk = QT_MAX_SAMPLES_PER_CHUNK;
m_ulSampleDescIdx = QT_BAD_IDX;
#ifdef _STCO_ZERO_BASED_IQ
m_ulChunkNumOffset = 0;
#endif // _STCO_ZERO_BASED_IQ
}
return FALSE;
}
/****************************************************************************
* Private Methods
*/
/****************************************************************************
* SequenceToChunk
*/
#ifdef STCMGR_USE_MODULUS_SEQUENCING
// This sequencing algorithm has better efficiency (than non-modulus
// sequencing) on files containing many chunks per table entry and/or those
// whose progression through the table is irratic (has skipps).
BOOL CQT_SampleToChunk_Manager::SequenceToChunk(void)
{
ULONG32 ulTargetChunk;
BOOL bEntryIdxChanged;
if (m_ulSampleInChunkNum > m_ulSamplesPerChunk)
{
bEntryIdxChanged = FALSE;
do
{
if (m_ulSamplesPerChunk == 0)
{
ulTargetChunk = m_ulCurrentChunk + 1;
}
else
{
ulTargetChunk = m_ulCurrentChunk +
(m_ulSampleInChunkNum - 1) /
m_ulSamplesPerChunk;
}
if ((ulTargetChunk >= m_ulNextEntryChunk) &&
(m_ulNextEntryChunk != QT_NULL_CHUNK_NUM))
{
m_ulSampleInChunkNum -= (m_ulNextEntryChunk -
m_ulCurrentChunk) *
m_ulSamplesPerChunk;
m_ulCurrentChunk = m_ulNextEntryChunk;
m_ulCurrentEntryIdx++;
bEntryIdxChanged = TRUE;
m_ulSamplesPerChunk = m_pSampleToChunkAtom->
Get_SamplesPerChunk(m_ulCurrentEntryIdx);
if ((m_ulCurrentEntryIdx + 1) < m_ulNumEntries)
{
m_ulNextEntryChunk = m_pSampleToChunkAtom->
Get_FirstChunk(m_ulCurrentEntryIdx + 1);
}
else
{
// No more chunk entries
m_ulNextEntryChunk = QT_NULL_CHUNK_NUM;
}
}
else
{
m_ulCurrentChunk = ulTargetChunk;
if (m_ulSamplesPerChunk != 0)
{
m_ulSampleInChunkNum = (m_ulSampleInChunkNum - 1) %
m_ulSamplesPerChunk +
1;
}
else
{
// encountered empty chunk at the end of table
return FALSE;
}
}
} while (m_ulSampleInChunkNum > m_ulSamplesPerChunk);
if (bEntryIdxChanged)
{
m_ulSampleDescIdx = m_pSampleToChunkAtom->
Get_SampleDescID(m_ulCurrentEntryIdx) - 1
#ifdef _STCO_ZERO_BASED_IQ
+ m_ulChunkNumOffset
#endif // _STCO_ZERO_BASED_IQ
;
}
}
return TRUE;
}
#else // STCMGR_USE_MODULUS_SEQUENCING
// This sequencing algorithm is more efficient for files
// containing fewer chunks per table entry and/or those
// whose progression through the chunks involves fewer
// skipps.
BOOL CQT_SampleToChunk_Manager::SequenceToChunk(void)
{
BOOL bEntryIdxChanged;
if (m_ulSampleInChunkNum > m_ulSamplesPerChunk)
{
bEntryIdxChanged = FALSE;
do
{
m_ulSampleInChunkNum = m_ulSampleInChunkNum - m_ulSamplesPerChunk;
m_ulCurrentChunk++;
if (m_ulCurrentChunk == m_ulNextEntryChunk)
{
m_ulCurrentEntryIdx++;
bEntryIdxChanged = TRUE;
m_ulSamplesPerChunk = m_pSampleToChunkAtom->
Get_SamplesPerChunk(m_ulCurrentEntryIdx);
if ((m_ulCurrentEntryIdx + 1) < m_ulNumEntries)
{
m_ulNextEntryChunk = m_pSampleToChunkAtom->
Get_FirstChunk(m_ulCurrentEntryIdx + 1)
#ifdef _STCO_ZERO_BASED_IQ
+ m_ulChunkNumOffset
#endif // _STCO_ZERO_BASED_IQ
;
}
else
{
// No more chunk entries
m_ulNextEntryChunk = QT_NULL_CHUNK_NUM;
}
}
else if ((m_ulSamplesPerChunk == 0) &&
(m_ulNextEntryChunk == QT_NULL_CHUNK_NUM))
{
return FALSE;
}
} while (m_ulSampleInChunkNum > m_ulSamplesPerChunk);
if (bEntryIdxChanged)
{
m_ulSampleDescIdx = m_pSampleToChunkAtom->
Get_SampleDescID(m_ulCurrentEntryIdx) - 1
#ifdef _STCO_ZERO_BASED_IQ
+ m_ulChunkNumOffset
#endif // _STCO_ZERO_BASED_IQ
;
}
}
return TRUE;
}
#endif // STCMGR_USE_MODULUS_SEQUENCING
/****************************************************************************
* SequenceReverseToChunk
*/
BOOL CQT_SampleToChunk_Manager::SequenceReverseToChunk(void)
{
ULONG32 ulEntryFirstChunk;
BOOL bEntryIdxChanged;
if (m_ulSampleInChunkNum > m_ulSamplesPerChunk)
{
bEntryIdxChanged = FALSE;
ulEntryFirstChunk = m_pSampleToChunkAtom->
Get_FirstChunk(m_ulCurrentEntryIdx);
do
{
m_ulSampleInChunkNum = m_ulSampleInChunkNum - m_ulSamplesPerChunk;
m_ulCurrentChunk--;
if (m_ulCurrentChunk < ulEntryFirstChunk)
{
if (m_ulCurrentEntryIdx == 0)
{
return FALSE;
}
m_ulCurrentEntryIdx--;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?