qttrkmgr.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,072 行 · 第 1/2 页

CPP
1,072
字号
/* ***** 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_HINTS

#define INV_HINT_TRACK_IDX  0xFFFFFFFF
#define INV_STREAM_NUM	    0xFFFF


/****************************************************************************
 *  Includes
 */
#include "qttrkmgr.h"
#include "qttrack.h"


/****************************************************************************
 *  Class CTrackManager
 */
/****************************************************************************
 *  Constructor/Destructor
 */
CQTTrackManager::CQTTrackManager(void)
    : m_uNumTracks(0)
    , m_uNumStreams(0)
    , m_pTrackTable(NULL)
    , m_pStreamToTrackMap(NULL)
    , m_pTrackAtomList(new CHXSimpleList)
    , m_pHintTrackIdxList(new CHXSimpleList)
    , m_bSubscriptionWindowClosed(FALSE)
    , m_bHintTracksActive(FALSE)
    , m_bHinted(FALSE)
    , m_pIodsAtom(NULL)
    , m_pFtypAtom(NULL)
    , m_FType(QT_FTYPE_UNKNOWN)
    , m_EType(QT_ETYPE_UNKNOWN)
{
    HX_ASSERT(m_pTrackAtomList);
    HX_ASSERT(m_pHintTrackIdxList);
}


CQTTrackManager::~CQTTrackManager()
{
    Clear();
}


/****************************************************************************
 *  Main Interface
 */
/****************************************************************************
 *  ManageTracks
 */
HX_RESULT CQTTrackManager::ManageTracks(CQTAtom *pRootAtom)
{
    if ((m_pTrackAtomList == NULL) ||
	(m_pHintTrackIdxList == NULL))
    {
	HX_ASSERT(!"shouldn't happen");
	return HXR_UNEXPECTED;
    }

    AddTracks(pRootAtom);

    if (m_FType == QT_FTYPE_UNKNOWN)
    {
	m_FType = QT_FTYPE_QT;
    }

    return HXR_OK;
}

/****************************************************************************
 *  ReadyTracks
 */
HX_RESULT CQTTrackManager::ReadyTracks(BOOL bIgnoreHintTracks,
				       BOOL bFallbackToTracks)
{
    HX_RESULT retVal = HXR_OK;

#ifdef _IGNORE_HINTS
    bIgnoreHintTracks = TRUE;
#endif	// _IGNORE_HINTS

    if ((m_pTrackAtomList == NULL) ||
	(m_pHintTrackIdxList == NULL) ||
	(m_pTrackAtomList->GetCount() == 0))
    {
	HX_ASSERT(!"shouldn't happen");
	retVal = HXR_CORRUPT_FILE;
    }

    if (SUCCEEDED(retVal))
    {
	m_uNumStreams = 0;
	m_uNumTracks = m_pTrackAtomList->GetCount();

	if (!bIgnoreHintTracks)
	{
	    m_uNumStreams = m_pHintTrackIdxList->GetCount();
	}

	m_bHinted = (m_uNumStreams != 0);
	m_bHintTracksActive = m_bHinted;

	DecideHintTrackActivation(bFallbackToTracks);

	if (m_uNumStreams <= 0)
	{
	    retVal = HXR_FAIL;	// No Streamable Tracks
	}
    }

    // Allocate Tables
    if (SUCCEEDED(retVal))
    {
	HX_ASSERT(!m_pTrackTable);
	HX_ASSERT(!m_pStreamToTrackMap);

	m_pStreamToTrackMap = new CQTStream [m_uNumStreams];
	m_pTrackTable = new CQTTrackTable [m_uNumTracks];

	if ((m_pStreamToTrackMap == NULL) ||
	    (m_pTrackTable == NULL))
	{
	    retVal = HXR_OUTOFMEMORY;
	}
    }

    // Fill Tables with info.
    if (SUCCEEDED(retVal))
    {
	LISTPOSITION HintTrackIdxListPosition;
	LISTPOSITION TrackAtomListPosition;
	ULONG32 ulHintTrackIdx = INV_HINT_TRACK_IDX;
	UINT16 uStreamTrackCount = 0;
	UINT16 uHintTrackCount = 0;
	CQTAtom* pTrackAtom;
	UINT16 uTrackIdx = 0;

	HintTrackIdxListPosition = m_pHintTrackIdxList->GetHeadPosition();
	TrackAtomListPosition = m_pTrackAtomList->GetHeadPosition();

	if (HintTrackIdxListPosition)
	{
	    ulHintTrackIdx = (UINT32) m_pHintTrackIdxList->GetNext(
						HintTrackIdxListPosition);
	}

	do
	{
	    pTrackAtom = (CQTAtom*) m_pTrackAtomList->GetNext(
					TrackAtomListPosition);

	    HX_ASSERT(pTrackAtom);

	    if (uTrackIdx == ulHintTrackIdx)
	    {
		// This is a hint track
		if (m_bHintTracksActive)
		{
		    retVal = CreateHintTrack(pTrackAtom,
					     uTrackIdx,
					     uStreamTrackCount);
		    if (retVal != HXR_OK)
		    {
			break;
		    }
		}

		uHintTrackCount++;

		if (uHintTrackCount < m_pHintTrackIdxList->GetCount())
		{
		    ulHintTrackIdx = (UINT32) m_pHintTrackIdxList->GetNext(
						    HintTrackIdxListPosition);
		}
	    }
	    else
	    {
		// This a standard track
		m_pTrackTable[uTrackIdx].m_pTrack = new CQTTrack(pTrackAtom);
		if (m_pTrackTable[uTrackIdx].m_pTrack == NULL)
		{
		    retVal = HXR_OUTOFMEMORY;
		    break;
		}

    		m_pTrackTable[uTrackIdx].m_pTrackAtom = pTrackAtom;
		pTrackAtom->AddRef();

		if (!m_bHintTracksActive)
		{
		    HX_ASSERT(uStreamTrackCount < m_uNumStreams);

		    if (uStreamTrackCount < m_uNumStreams)
		    {
			m_pStreamToTrackMap[uStreamTrackCount].m_pQTTrack =
			    m_pTrackTable[uTrackIdx].m_pTrack;

			uStreamTrackCount++;
		    }
		}

		// For now keep references to all "standard" tracks.
		// To do : reference only "standard" tracks referenced
		//         by hint tracks - when hint tracks are active
		m_pTrackTable[uTrackIdx].m_uRefCount++;
	    }

	    if (m_pTrackTable[uTrackIdx].m_pTrack)
	    {
		m_pTrackTable[uTrackIdx].m_pTrack->AddRef();
	    }

	    uTrackIdx++;
	} while (uTrackIdx < m_uNumTracks);
    }

    // Free Unreferenced Standard Tracks
    if (SUCCEEDED(retVal))
    {
	UINT16 uTrackIdx;

	for (uTrackIdx = 0; uTrackIdx < m_uNumTracks; uTrackIdx++)
	{
	    if (m_pTrackTable[uTrackIdx].m_uRefCount == 0)
	    {
		HX_RELEASE(m_pTrackTable[uTrackIdx].m_pTrack);
		HX_RELEASE(m_pTrackTable[uTrackIdx].m_pTrackAtom);
	    }
	}
    }

    if (FAILED(retVal))
    {
	Clear();
    }

    return retVal;
}

/****************************************************************************
 *  CloseTracks
 */
void CQTTrackManager::CloseTracks(void)
{
    UINT16 uTrackIdx;

    if (m_pTrackTable)
    {
	for (uTrackIdx = 0; uTrackIdx < m_uNumTracks; uTrackIdx++)
	{
	    if (m_pTrackTable[uTrackIdx].m_pTrack)
	    {
		m_pTrackTable[uTrackIdx].m_pTrack->Close();
		m_pTrackTable[uTrackIdx].m_pTrack->Release();
		m_pTrackTable[uTrackIdx].m_pTrack = NULL;
	    }
	    HX_RELEASE(m_pTrackTable[uTrackIdx].m_pTrackAtom);
	}
    }

    Clear();
}

/****************************************************************************
 *  ResetTracks - reset what's done in ReadyTracks()
 */
void CQTTrackManager::ResetTracks(void)
{
    if (m_pTrackTable)
    {
	for (UINT16 uTrackIdx = 0; uTrackIdx < m_uNumTracks; uTrackIdx++)
	{
	    if (m_pTrackTable[uTrackIdx].m_pTrack)
	    {
		m_pTrackTable[uTrackIdx].m_pTrack->Close();
		m_pTrackTable[uTrackIdx].m_pTrack->Release();
		m_pTrackTable[uTrackIdx].m_pTrack = NULL;
	    }

	    HX_RELEASE(m_pTrackTable[uTrackIdx].m_pTrackAtom);
	}
    }

    HX_VECTOR_DELETE(m_pTrackTable);
    HX_VECTOR_DELETE(m_pStreamToTrackMap);

    m_uNumTracks = 0;
    m_uNumStreams = 0;
}

/****************************************************************************
 *  InitTracks
 */
HX_RESULT CQTTrackManager::InitTracks(CQTFileFormat *pFileFormat,
				      CQTPacketAssembler *pPacketAssembler,
				      CQTPacketizerFactory* pPacketizerFactory,
				      const char* pProtocol)
{
    UINT16 uTrackIdx;
    HX_RESULT retVal = HXR_OK;

    if (m_pTrackTable)
    {
	UINT16 uStreamNum;
	BOOL bSomeStreamsDeactivated = FALSE;

	for (uTrackIdx = 0;
	     SUCCEEDED(retVal) && (uTrackIdx < m_uNumTracks);
	     uTrackIdx++)
	{
	    if (m_pTrackTable[uTrackIdx].m_pTrack)
	    {
		retVal = m_pTrackTable[uTrackIdx].m_pTrack->Init(pFileFormat,
								 pPacketAssembler,
								 pPacketizerFactory,
								 pProtocol);

		uStreamNum = GetTrackStreamNum(m_pTrackTable[uTrackIdx].m_pTrack);

		if (uStreamNum < m_uNumStreams)
		{
		    m_pStreamToTrackMap[uStreamNum].m_bActive = (retVal == HXR_OK);
		    bSomeStreamsDeactivated = bSomeStreamsDeactivated ||
					      (!m_pStreamToTrackMap[uStreamNum].m_bActive);

		    if ((retVal == HXR_IGNORE) ||
			(retVal == HXR_NO_DATA))
		    {
			retVal = HXR_OK;
		    }
		}
	    }
	}

	// Some streams could have been
        // disabled during initialization - remove the inactive ones
	if (SUCCEEDED(retVal) && bSomeStreamsDeactivated)
	{
	    retVal = RemoveInactiveStreams();

#ifdef QTCONFIG_ALTERNATE_STREAMS
	    // Return remaining streams to inactive (unsubscribed) state
	    if (SUCCEEDED(retVal))
	    {
		for (uTrackIdx = 0; uTrackIdx < m_uNumStreams; uTrackIdx++)
		{
		    m_pStreamToTrackMap[uTrackIdx].m_bActive = FALSE;
		}

		m_bSubscriptionWindowClosed = FALSE;
	    }
#endif	// QTCONFIG_ALTERNATE_STREAMS
	}

	// After track initialization, release all Track Atoms from
	// the track manager
	for (uTrackIdx = 0;
	     uTrackIdx < m_uNumTracks;
	     uTrackIdx++)
	{
	    HX_RELEASE(m_pTrackTable[uTrackIdx].m_pTrackAtom);
	}
    }
    else
    {
	retVal = HXR_UNEXPECTED;
    }

    if (SUCCEEDED(retVal))
    {
        // Release Lists
	DeleteTrackAtomList();
	HX_DELETE(m_pHintTrackIdxList);
    }

    return retVal;
}

#ifdef QTCONFIG_ALTERNATE_STREAMS
/****************************************************************************
 *  AddStreamToGroup
 */
HX_RESULT CQTTrackManager::AddStreamToGroup(UINT16 uStreamNumber,
					    UINT16 uGroup,
					    ULONG32 ulBitrate)
{
    HX_RESULT retVal = HXR_FAIL;

    HX_ASSERT(m_pStreamToTrackMap);
    HX_ASSERT(uStreamNumber < m_uNumStreams);

    if (uStreamNumber < m_uNumStreams)
    {
	m_pStreamToTrackMap[uStreamNumber].m_uGroup = uGroup;
	m_pStreamToTrackMap[uStreamNumber].m_ulBitrate = ulBitrate;
	m_pStreamToTrackMap[uStreamNumber].m_bGroupped = TRUE;

	retVal = HXR_OK;
    }

    return retVal;
}

/****************************************************************************
 *  SubscribeDefault
 */
HX_RESULT CQTTrackManager::SubscribeDefault(void)
{
    UINT16 uStrmIdx;
    HX_RESULT retVal = HXR_OUTOFMEMORY;
    BOOL* pVisitedArray = new BOOL [m_uNumStreams];

    HX_ASSERT(m_pStreamToTrackMap);
    HX_ASSERT(pVisitedArray);

    if (pVisitedArray)
    {
	for (uStrmIdx = 0; uStrmIdx < m_uNumStreams; uStrmIdx++)
	{
	    pVisitedArray[uStrmIdx] = FALSE;
	}

	retVal = HXR_OK;
    }

    if (SUCCEEDED(retVal))
    {
	for (uStrmIdx = 0; uStrmIdx < m_uNumStreams; uStrmIdx++)
	{
	    if (!pVisitedArray[uStrmIdx])
	    {
		if (m_pStreamToTrackMap[uStrmIdx].m_bGroupped)
		{
		    // Activate the highest bitrate stream in the group
		    UINT16 uSubIdx;
		    UINT16 uGroup = m_pStreamToTrackMap[uStrmIdx].m_uGroup;
		    ULONG32 ulHighBitrate = m_pStreamToTrackMap[uStrmIdx].m_ulBitrate;
		    UINT16 uHighIdx = uStrmIdx;

		    m_pStreamToTrackMap[uStrmIdx].m_bActive = FALSE;

		    for (uSubIdx = uStrmIdx + 1; uSubIdx < m_uNumStreams; uSubIdx++)
		    {
			if (m_pStreamToTrackMap[uStrmIdx].m_uGroup == uGroup)
			{
			    m_pStreamToTrackMap[uSubIdx].m_bActive = FALSE;

			    if (m_pStreamToTrackMap[uSubIdx].m_ulBitrate > ulHighBitrate)
			    {
				ulHighBitrate = m_pStreamToTrackMap[uSubIdx].m_ulBitrate;
				uHighIdx = uSubIdx;
			    }

			    pVisitedArray[uSubIdx] = TRUE;
			}
		    }

		    m_pStreamToTrackMap[uHighIdx].m_bActive = TRUE;
		}
		else
		{
		    m_pStreamToTrackMap[uStrmIdx].m_bActive = TRUE;
		}

		pVisitedArray[uStrmIdx] = TRUE;
	    }
	}
    }

    HX_VECTOR_DELETE(pVisitedArray);

    return retVal;
}

/****************************************************************************
 *  Subscribe
 */
HX_RESULT CQTTrackManager::Subscribe(UINT16 uStreamNum)
{
    HX_RESULT retVal = HXR_UNEXPECTED;

    if (!m_bSubscriptionWindowClosed)
    {
	HX_ASSERT(m_pStreamToTrackMap);
	HX_ASSERT(uStreamNum < m_uNumStreams);

	retVal = HXR_FAIL;

	if (uStreamNum < m_uNumStreams)
	{
	    if (m_pStreamToTrackMap[uStreamNum].m_bGroupped)
	    {
		UINT16 uStrmIdx;
		UINT16 uGroup = m_pStreamToTrackMap[uStreamNum].m_uGroup;

		// There can be only one stream subscribed in a group
		for (uStrmIdx = 0; uStrmIdx < m_uNumStreams; uStrmIdx++)

⌨️ 快捷键说明

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