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

📄 audrendf.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 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 ***** */ 

//////////////////////////////////////////////////////////////////////////////
// 
//  audio format for QuickTime renderer for RealMedia Architecture.
//
// Notes:
// This class puts together the audio packets and decodes the audio data.
// There are still unresolved problems with this code - audio data gets
// dropped. This only occurs when there is more than one frame of audio
// data per packet - like MP3. Also, audio services doesn't seem to be 
// releasing the audio buffers. This is a huge problem when trying to 
// listen to CD quality audio for any amount of time. Another problem - 
// the current implementation will not work when one audio frame spans 
// multiple rtp packets. The code from the video renderer will need to be 
// adapted to work with audio. The class CQTPacket does all the QuickTime
// header parsing. See the notes in that file for more info on the QT header
// structure.
// 

/****************************************************************************
 *  Defines
 */
#define MAX_DECODE_GRANULARITY	    200	    // in milliseconds
#define DEFAULT_AUDIO_PREROLL	    2000    // in milliseconds
#if defined(HELIX_FEATURE_MIN_HEAP)
#define MAXIMUM_AUDIO_PREROLL	    3000    // in milliseconds
#else
#define MAXIMUM_AUDIO_PREROLL	    15000    // in milliseconds
#endif


/****************************************************************************
 *  Includes
 */
#include "hlxclib/stdio.h"
#include "hlxclib/string.h"

// #include "netbyte.h"
#include "hxtypes.h"
#include "hxresult.h"
#include "hxcom.h"
#include "hxcomm.h"
#include "hxausvc.h"
#include "ihxpckts.h"
#include "hxerror.h"

#include "hxcore.h"
#include "hxupgrd.h"
#include "hxslist.h"
#include "hxassert.h"

#include "hxstrutl.h"

#include "hxheap.h"

#ifdef _DEBUG
#undef HX_THIS_FILE		
static const char HX_THIS_FILE[] = __FILE__;
#endif

#include "hxtick.h"

#include "audrend.h"
#include "audrendf.h"


/****************************************************************************
 *  CAudioFormat
 */
/****************************************************************************
 *  Constructor/Destructor
 */
CAudioFormat::CAudioFormat(IHXCommonClassFactory* pCommonClassFactory,
			   CAudioRenderer* pAudioRenderer)
    : m_pCommonClassFactory(pCommonClassFactory)
    , m_pContext(NULL)
    , m_pPendingPacketQueue(NULL)
    , m_ulForceDiscardUntilTime(NO_TIME_SET)
    , m_bPostStartTime(FALSE)
    , m_ulTrackStartTime(0)
    , m_ulTrackEndTime(NO_TIME_SET)
    , m_pAudioFmt(NULL)
    , m_fCompressionRatio(1.0)
    , m_ulStartTime(0)
    , m_lRefCount(0)
{
    if (m_pCommonClassFactory)
    {
	m_pCommonClassFactory->AddRef();
    }

    m_pContext = pAudioRenderer->GetContext();
    if (m_pContext)
    {
	m_pContext->AddRef();
    }

    // NULL out the AU String
    memset(&m_szAUStr[0], 0, MAX_AUSTR_SIZE);
}

CAudioFormat::~CAudioFormat()
{
    HX_DELETE(m_pAudioFmt);

    FlushQueues();    
    HX_DELETE(m_pPendingPacketQueue);

    HX_RELEASE(m_pCommonClassFactory);
    HX_RELEASE(m_pContext);
}


/****************************************************************************
 *  CAudioFormat::Init
 */
HX_RESULT CAudioFormat::Init(IHXValues* pHeader)
{
    HX_RESULT retVal = HXR_FAIL;

    if (pHeader)
    {
        m_pAudioFmt = new HXAudioFormat;
        if (m_pAudioFmt)
        {
            m_pPendingPacketQueue = new CHXSimpleList;
            if (m_pPendingPacketQueue)
            {
                m_pAudioFmt->uChannels       = (UINT16) GetULONG32Property(pHeader, "Channels", 1);
                m_pAudioFmt->uBitsPerSample  = (UINT16) GetULONG32Property(pHeader, "BitsPerSample", 16);
                m_pAudioFmt->ulSamplesPerSec = GetULONG32Property(pHeader, "SamplesPerSecond", 8000);
                // MaxBlockSize - default to 200ms of data
#ifdef HELIX_FEATURE_FLP_AUDREND
                m_pAudioFmt->uMaxBlockSize = (UINT16)
                    (((double) (m_pAudioFmt->ulSamplesPerSec)) * 
                     ((double) (m_pAudioFmt->uBitsPerSample)) * 
                     ((double) (m_pAudioFmt->uChannels)) *
                     MAX_DECODE_GRANULARITY /
                     8000.0 +
                     ((double) (m_pAudioFmt->uBitsPerSample)) * // Compensate for possible round off
                     ((double) (m_pAudioFmt->uChannels)) /
                     8.0);
#else   // HELIX_FEATURE_FLP_AUDREND
                HX_ASSERT((((UINT32) (m_pAudioFmt->ulSamplesPerSec)) * 
                           ((UINT32) (m_pAudioFmt->uBitsPerSample)) * 
                           ((UINT32) (m_pAudioFmt->uChannels))) < 
                          (((ULONG32) 0xFFFFFFFF) / MAX_DECODE_GRANULARITY));

                m_pAudioFmt->uMaxBlockSize = (UINT16)
                    (((UINT32) (m_pAudioFmt->ulSamplesPerSec)) * 
                     ((UINT32) (m_pAudioFmt->uBitsPerSample)) * 
                     ((UINT32) (m_pAudioFmt->uChannels)) *
                     MAX_DECODE_GRANULARITY /
                     8000 +
                     ((UINT32) (m_pAudioFmt->uBitsPerSample)) * // Compensate for possible round off
                     ((UINT32) (m_pAudioFmt->uChannels)) /
                     8);
#endif  // HELIX_FEATURE_FLP_AUDREND
                // Clear return value
                retVal = HXR_OK;
            }
        }
    }

    return retVal;
}


/****************************************************************************
 *    CAudioFormat::GetDefaultPreroll
 */
ULONG32 CAudioFormat::GetDefaultPreroll(IHXValues* pValues)
{
    return DEFAULT_AUDIO_PREROLL;
}

ULONG32 CAudioFormat::GetMaximumPreroll(IHXValues* pValues)
{
    return MAXIMUM_AUDIO_PREROLL;
}

void CAudioFormat::FlushQueues(void)
{
    if (m_pPendingPacketQueue != NULL)
    {
	CMediaPacket* pQTPkt;
	while (!m_pPendingPacketQueue->IsEmpty())
	{
	    // empty all of the pending packets
	    // and delete them
	    pQTPkt = (CMediaPacket*) m_pPendingPacketQueue->RemoveHead();
	    CMediaPacket::DeletePacket(pQTPkt);
	}
    }
}


HX_RESULT CAudioFormat::GetAudioFormat(HXAudioFormat& audioFmt)
{
    audioFmt.uChannels = m_pAudioFmt->uChannels;
    audioFmt.uBitsPerSample = m_pAudioFmt->uBitsPerSample;
    audioFmt.ulSamplesPerSec = m_pAudioFmt->ulSamplesPerSec;
    audioFmt.uMaxBlockSize = m_pAudioFmt->uMaxBlockSize;

    return HXR_OK;
}


/****************************************************************************
 *  CAudioFormat::Enqueue
 */
BOOL CAudioFormat::Enqueue(IHXPacket* pPacket)
{
    CMediaPacket* pFramePacket = NULL;
    HX_RESULT retVal = HXR_OK;

    HX_ASSERT(m_pPendingPacketQueue);

    pFramePacket = CreateAssembledPacket(pPacket);

    if (pFramePacket)
    {
	m_pPendingPacketQueue->AddTail(pFramePacket);
    }
    
    return retVal;
}


HX_RESULT CAudioFormat::CreateAudioFrame(HXAudioData& audioData, 
					 AUDIO_STATE audioState)
{
    HX_RESULT retVal = HXR_NO_DATA;
    BOOL bTryAgain;

    do
    {
	bTryAgain = FALSE;

	HX_RELEASE(audioData.pData);
	audioData.ulAudioTime = 0;

	retVal = DecodeAudioData(audioData, audioState == AUDIO_END_OF_PACKETS);

	if (retVal == HXR_OK)
	{
	    if (AdjustAudioData(audioData))
	    {
		// once we are passed the start time, disable it as a
		// a requirement to prevent clipping on wrap-around
		m_bPostStartTime = TRUE;
		
		// if we've fulfilled the discard, reset state
		if ((m_ulForceDiscardUntilTime != NO_TIME_SET) && 
		    IsTimeGreater(audioData.ulAudioTime + 
		    ConvertBytesToMs(audioData.pData->GetSize()),
		    m_ulForceDiscardUntilTime))
		{
		    m_ulForceDiscardUntilTime = NO_TIME_SET;
		}
	    }
	    else
	    {
		retVal = HXR_NO_DATA;
		HX_RELEASE(audioData.pData);
		bTryAgain = TRUE;
	    }
	}
    } while (bTryAgain);

    return retVal;
}


CMediaPacket* CAudioFormat::PeekAudioPacket(void)
{
    CMediaPacket* pAudioPacket = NULL;

    if (m_pPendingPacketQueue && (!m_pPendingPacketQueue->IsEmpty()))
    {
	pAudioPacket = (CMediaPacket*) m_pPendingPacketQueue->GetHead();
    }

    return pAudioPacket;
}


CMediaPacket* CAudioFormat::GetAudioPacket(void)
{
    CMediaPacket* pAudioPacket = NULL;

    if (m_pPendingPacketQueue && (!m_pPendingPacketQueue->IsEmpty()))
    {
	pAudioPacket = (CMediaPacket*) m_pPendingPacketQueue->RemoveHead();
    }

    return pAudioPacket;
}


HX_RESULT CAudioFormat::PutAudioPacket(CMediaPacket* pMediaPacket)
{
    HX_RESULT retVal = HXR_FAIL;

    HX_ASSERT(m_pPendingPacketQueue);

    if (m_pPendingPacketQueue && pMediaPacket)
    {
	m_pPendingPacketQueue->AddTail(pMediaPacket);
	retVal = HXR_OK;
    }

    return retVal;
}

CMediaPacket* CAudioFormat::CreateAssembledPacket(IHXPacket* pPayloadPacket)
{
    return NULL;
}


HX_RESULT CAudioFormat::DecodeAudioData(HXAudioData& audioData,
					BOOL bFlushCodec)
{
    return HXR_NOTIMPL;
}

    
void CAudioFormat::DiscardAudioUntil(UINT32 ulTimestamp)
{
    BOOL bDone = FALSE;

    // cannot equal NO_TIME_SET so we bump it up one
    if (ulTimestamp == NO_TIME_SET)
    {
	ulTimestamp += 1;
    }

    m_ulForceDiscardUntilTime = ulTimestamp;

    // look through the re-assembled packet queue and delete data
    // from there that's earlier than the discard until time
    CMediaPacket* pQTPkt;
    while (!m_pPendingPacketQueue->IsEmpty())
    {
	pQTPkt = (CMediaPacket*) m_pPendingPacketQueue->GetHead();
	if (pQTPkt->m_ulTime >= ulTimestamp)
	{
	    break;
	}

	m_pPendingPacketQueue->RemoveHead();
	CMediaPacket::DeletePacket(pQTPkt);
    }
}

void CAudioFormat::Reset(void)
{
    m_bPostStartTime = FALSE;
    m_ulForceDiscardUntilTime = NO_TIME_SET;

    FlushQueues();
}

void CAudioFormat::OverrideFactory(IHXCommonClassFactory* pCommonClassFactory)
{
    HX_ASSERT(pCommonClassFactory);

    if (pCommonClassFactory)
    {
	HX_RELEASE(m_pCommonClassFactory);

⌨️ 快捷键说明

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