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

📄 raformat.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/* ***** 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 ***** */ 

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

#include "raformat.h"
#include "smppkfdr.h"
#include "raparser.h"
#include "raibufs.h"
#include "rafactry.h"
#include "hxstrutl.h"
#include "hxmime.h"
#include "adjtime.h"

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


/****************************************************************************
 *  Defines
 */
//#define RAFORMAT_LOGING_ON
#ifdef RAFORMAT_LOGING_ON
#define LOG_PATH	    "c:\\log\\rarender\\raformat\\"
#define SPLICE_FILE	    LOG_PATH##"splice.txt"
#define TIMERANGE_FILE	    LOG_PATH##"timerange.txt"
#define PLACE_FILE	    LOG_PATH##"place.txt"
#define XFADE_FILE	    LOG_PATH##"xfade.txt"
#define DISCARDUNTIL_FILE   LOG_PATH##"discarduntil.txt"
#define TREND_FILE	    LOG_PATH##"trend.txt"
#define TR_FILE		    LOG_PATH##"timerange.txt"
#define ONPACKET_FILE	    LOG_PATH##"packet.txt"
#define TIME_FILE	    LOG_PATH##"time.txt"
#define DOAUDIO_FILE	    LOG_PATH##"doaudio.txt"
#else
#define SPLICE_FILE	    0
#define TIMERANGE_FILE	    0
#define PLACE_FILE	    0
#define XFADE_FILE	    0
#define DISCARDUNTIL_FILE   0
#define TREND_FILE	    0
#define TR_FILE		    0
#define ONPACKET_FILE	    0
#define TIME_FILE	    0
#define DOAUDIO_FILE	    0
#endif

#define MINMAX_BLOCK_GAP			1	// in ms
#define MAXMAX_BLOCK_GAP			30	// in ms
#define MIN_CODEC_BLOCK_DELAY			3	// in ms
#define MAX_TOLERABLE_BLOCK_YIELD_DEFICIENCY	4	// in bytes

#define MAX_AUDIO_DATA_ATTEMPTS			30

#define DFLT_AUDIO_BUF_SIZE			32768


/****************************************************************************
 *  CRaFormat
 */
/****************************************************************************
 *  Constructor & Destructor
 */
CRaFormat::CRaFormat (IUnknown*			pContext,
		      IHXCommonClassFactory*	pCommonClassFactory,
		      IHXErrorMessages*	pErrorMessages,
		      UINT16*			pRuleToFlagMap,
		      UINT16			uStreamNumber)
    : m_IBufs(m_StreamParam, uStreamNumber)
    , m_pContext(pContext)
    , m_pPacketFeeder(NULL)
    , m_pCodec(NULL)
    , m_ulAudioBufSize(0)
    , m_pUpgradeCollection(NULL)
    , m_ulCrossFadeEndTime(NO_TIME_SET)
    , m_ulForceDiscardUntilTime(NO_TIME_SET)
    , m_ulLastPacketTime(NO_TIME_SET)
    , m_ulBytesWrite(0)
    , m_pAudioSync(NULL)
    , m_bRegistered(FALSE)
    , m_lTimeOffset(0)
    , m_ulTrackStartTime(0)
    , m_ulTrackEndTime(0)
    , m_bForceInterleaved(FALSE)
    , m_bFirstPacket(TRUE)
    , m_bDeterminedAdjustment(FALSE)
    , m_bForceStartTrackTime(FALSE)
    , m_bForceEndTrackTime(FALSE)
    , m_bAdjustTimestamps(FALSE)
    , m_bEndOfPackets(FALSE)
    , m_ulNextAudioTime(NO_TIME_SET)
    , m_ulNextActualAudioTime(NO_TIME_SET)
    , m_bSecure(FALSE)
    , m_bIsVBR(FALSE)
    , m_uStreamNumber(uStreamNumber)
    , m_ulMaxBlockGap(MAXMAX_BLOCK_GAP)
    , m_ulMinExpectedDecodedBlockSize(0)
    , m_ulCodecDelay(0)
    , m_fCodecDelay(0.0)
    , m_bPCMStreamStart(TRUE)
    , m_pRuleToFlagMap(pRuleToFlagMap)
    , m_pCachingClassFactory(NULL)
{
    if (m_pContext)
    {
	m_pContext->AddRef();
    }

    m_pCommonClassFactory = pCommonClassFactory;
    if (m_pCommonClassFactory)
    {
	m_pCommonClassFactory->AddRef();
    }

    if (m_pContext)
    {
	m_pContext->QueryInterface(IID_IHXUpgradeCollection, 
				   (void**) &m_pUpgradeCollection);
    }

    if (pErrorMessages)
    {
	m_pErrorMessages = pErrorMessages;
	m_pErrorMessages->AddRef();
    }
}

CRaFormat::~CRaFormat()
{
    if (m_pCodec)
    {
	m_pCodec->FreeDecoder();
	HX_DELETE(m_pCodec);
    }

    HX_DELETE(m_pPacketFeeder);

    HX_RELEASE(m_pUpgradeCollection);
    if( m_pCachingClassFactory )
    {
       HX_RELEASE(m_pCachingClassFactory);
    }
    HX_RELEASE(m_pCommonClassFactory);
    HX_RELEASE(m_pErrorMessages);
    HX_RELEASE(m_pContext);
}

// Read Header
HX_RESULT
CRaFormat::NewReadRAHeader (Byte*	buffer, 
			    UINT32	bLength, 
			    BOOL	bForceStartTrackTime,
			    BOOL	bForceEndTrackTime,
			    UINT32	ulTrackStartTime,
			    UINT32	ulTrackEndTime,
			    UINT32*	pBytesRead, 
			    char*	pAllCodecs,
                            UINT32      ulAllCodecsBufLen)
{
    HX_RESULT	theError = HXR_INVALID_FILE;
    
    m_bForceStartTrackTime = bForceStartTrackTime;
    m_bForceEndTrackTime = bForceEndTrackTime;

    m_ulTrackStartTime = ulTrackStartTime;
    m_ulTrackEndTime = ulTrackEndTime;

    theError = m_StreamParam.ReadOneRAHeader(buffer, bLength, pBytesRead);

    // add this codec to the AllCodecs list (if its not already in there)
    if (m_StreamParam.codecID && pAllCodecs && (strstr(pAllCodecs, m_StreamParam.codecID) == 0))
    {
	char szBuffer[64]; /* Flawfinder: ignore */
	if (*pAllCodecs == '\0')
	{
	    SafeStrCpy(szBuffer,  m_StreamParam.codecID, 64);
	}
	else
	{
	    SafeSprintf(szBuffer, 64, ", %s", m_StreamParam.codecID);
	}

	SafeStrCat(pAllCodecs, szBuffer, ulAllCodecsBufLen);
    }
   
#if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC)
    // If we are RAAC and VBRS then we need to
    // tell the interleave bufs class to use the
    // SamplesIn property to compute the ms per block
    if ((theError == HXR_OK) &&
	m_StreamParam.interleaverID &&
        (!strcmp(m_StreamParam.interleaverID, RA_INTERLEAVER_VBRS_ID) ||
         !strcmp(m_StreamParam.interleaverID, RA_INTERLEAVER_VBRF_ID)))
    {
	m_bIsVBR = TRUE;
    }
#endif /* #if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC) */

    // initialize codecs
    if (theError == HXR_OK)
    {
        theError = LoadDecoderAndInitDeInterleaver();
    }
#if defined(HELIX_FEATURE_AUTOUPGRADE)
    else if (theError == HXR_INVALID_VERSION ||
             theError == HXR_INVALID_REVISION)
    {
        // We parsed out an invalid RAformat version
        // or revision, a condition on which we should AU.
        ThrowUpgrade(REALAUDIO_MIME_TYPE);
    }
#endif /* #if defined(HELIX_FEATURE_AUTOUPGRADE) */

    if (m_StreamParam.uInterleaveFactor == 1)
    {
	// if the data isn't interleaved then we know 
	// we don't have to adjust the timestamps
	m_bDeterminedAdjustment = TRUE;
    }

    if (m_bIsVBR)
    {
	m_IBufs.SetReliableSamplesIn(TRUE);

    }

    // initialize interleavers
    if (theError == HXR_OK)
    {
        theError = m_IBufs.InitDeinterleaver();
        if (theError == HXR_INVALID_INTERLEAVER)
        {
            // We had an unknown interleaver type, a condition
            // for which we should AU.
            ThrowUpgrade(REALAUDIO_MIME_TYPE);
        }
    }

    // create superblock allocation
    if (theError == HXR_OK)
    {
	theError = m_IBufs.AllocIBufs();
    }
    
    // create packet interleave puffer packet feeder
    if (theError == HXR_OK)
    {
	m_pPacketFeeder = CreatePacketFeeder();
	theError = HXR_OUTOFMEMORY;
	if (m_pPacketFeeder)
	{
	    theError = HXR_OK;
	}
    }
    if (theError == HXR_OK)
    {
	if (GetMSPerBlock() >= 1.0)
	{
	    m_ulMaxBlockGap = (UINT32) (GetMSPerBlock() / 4.0 + 0.5);
	    // Assume max time stamp drift of 1 ms per block of superblock
	    if (m_ulMaxBlockGap < GetInterleaveFactor())
	    {
		m_ulMaxBlockGap = GetInterleaveFactor();
	    }
	}
	if (m_ulMaxBlockGap < MINMAX_BLOCK_GAP)
	{
	    m_ulMaxBlockGap = MINMAX_BLOCK_GAP;
	}
	if (m_ulMaxBlockGap > MAXMAX_BLOCK_GAP)
	{
	    m_ulMaxBlockGap = MAXMAX_BLOCK_GAP;
	}

	m_ulMinExpectedDecodedBlockSize = m_IBufs.CalcBytes(GetMSPerBlock());
	if (m_ulMinExpectedDecodedBlockSize > MAX_TOLERABLE_BLOCK_YIELD_DEFICIENCY)
	{
	    m_ulMinExpectedDecodedBlockSize -= MAX_TOLERABLE_BLOCK_YIELD_DEFICIENCY;
	}
    }

    DEBUG_OUTF_IDX(m_uStreamNumber, RA_FLOW_FILE, (s, "Init(%d): BlockMS=%.2f, SuperMS=%d, IBlocks=%hd\n",
						m_uStreamNumber,
						GetMSPerBlock(),
						GetSuperBlockTime(),
						GetInterleaveFactor()));
    return theError;
}

void
CRaFormat::GetAudioFormat (HXAudioFormat& audioFmt)
{
    audioFmt.uChannels = m_StreamParam.uChannels;                
    audioFmt.uBitsPerSample = m_StreamParam.uSampleSize;
    audioFmt.ulSamplesPerSec = m_StreamParam.ulSampleRate;
    audioFmt.uMaxBlockSize = (UINT16) m_ulAudioBufSize;
}

CCodec*
CRaFormat::CreateDecoder(char* pCodecID)
{
    if (!strcmp(pCodecID, "racp"))
    {
        // The racp 4cc is also handled 
        // by the raac codec
        pCodecID = "raac";
    }

    return new CCodec(pCodecID, m_pContext);
}

CRealAudioPacketFeeder*
CRaFormat::CreatePacketFeeder(void)
{
#if defined(HELIX_FEATURE_RAREND_ADV_PACKET_FEEDER)
    // The RealAudio advanced packet feeder is distributed
    // as a binary statically-linked library and therefore must
    // be created from this factory class that resides in the libary.
    return CRealAudioRendererFactory::CreateRealAudioAdvancedPacketFeeder(m_StreamParam, 
                                                                          m_IBufs, 
                                                                          m_pRuleToFlagMap,
                                                                          m_uStreamNumber);
#else	// HELIX_FEATURE_RAREND_ADV_PACKET_FEEDER
    //otherwise we just create it directly.
    return new CRealAudioSimplePacketFeeder(m_StreamParam, 
                                            m_IBufs,
                                            m_pRuleToFlagMap,
                                            m_uStreamNumber);
#endif	// HELIX_FEATURE_RAREND_ADV_PACKET_FEEDER
}

// decoding
HX_RESULT
CRaFormat::InitDecoder(CStreamParam& param, CCodec** hCodec)
{
    HX_RESULT	theError = HXR_OK;
    CCodec*	pCodec = NULL;
    CHXBuffer*	pBuffer = NULL;

    pCodec = CreateDecoder(param.codecID);
    if (!pCodec)
    {
	theError = HXR_OUTOFMEMORY;
    }
    else
    {
	// first load with codec w/o versioning
	theError = pCodec->InitCodec(FALSE);
	if (HXR_OK != theError)
	{
	    // try to load with codec w/ versioning(xxxx3260)
	    theError = pCodec->InitCodec(TRUE);
	}
    }

    if (theError == HXR_OK)
    {
	RADECODER_INIT_PARAMS   initParams;

	// set up initialization parameters

	initParams.sampleRate = param.ulSampleRate;
	initParams.bitsPerSample = param.uSampleSize;
	initParams.channels = param.uChannels;
	initParams.audioQuality = 100;
	initParams.bitsPerFrame = param.uCodecFrameSize;
	initParams.granularity = param.ulGranularity;
	initParams.opaqueDataLength = param.ulOpaqueDataSize;
	initParams.opaqueData = param.opaqueData;

	theError = pCodec->InitDecoder(&initParams, FALSE);

        // Sometimes the uChannels parameter may be passed
        // in with a 0, and the decoder will update the
        // value. Therefore, we need to copy the decoder
        // value back.
        param.uChannels = initParams.channels;
        // If for some reason the channels parameter is
        // still 0, then we have a problem worthy of failure
        if (param.uChannels == 0)
        {
            theError = HXR_FAIL;
        }
        // The param.ulSampleRate parameter may be different
        // coming out of InitDecoder() than it was going in.
        // This indicates that the codec has initialized itself
        // at a sample rate which is different the sample rate
        // in param.ulSampleRate. This can happen in the
        // case of the High-Efficiency AAC profile.
        param.ulSampleRate = initParams.sampleRate;
        // If for some reason the sample rate is 0, then
        // we have a problem
        if (param.ulSampleRate == 0)
        {
            theError = HXR_FAIL;
        }

	if (theError == HXR_OK)
	    theError = pCodec->SetFlavor(param.uFlavorIndex);
    }

#if defined(HELIX_FEATURE_AUTOUPGRADE)
    if (HXR_DEC_NOT_FOUND == theError || HXR_INVALID_VERSION == theError)
    {
        ThrowUpgrade((const char*) param.codecID);
    }
#endif /* #if defined(HELIX_FEATURE_AUTOUPGRADE) */

    if (theError == HXR_OK)
    {
	*hCodec = pCodec;
    }
    else
    {
	*hCodec = NULL;
	HX_DELETE(pCodec);
    }

    // Ask the codec for the number of samples per block, and use this to 
    // figure out exactly how big our decoded data buffer needs to be.
    ULONG32 * pulSamplesPerBlock;
    UINT16  uPropSize = 0;
    ULONG32 ulBytesPerMinute = m_StreamParam.ulBytesPerMin;
    if (pCodec)
    {
        pulSamplesPerBlock = (ULONG32*) pCodec->GetFlavorProperty(
            param.uFlavorIndex,
            FLV_PROP_SAMPLES_IN,
            &uPropSize);
    }

    if (m_bIsVBR)
    {
	// For VBR Streams, do not use bytes per minute to compute decoder
	// buffer size since bytes per minute are variable
	ulBytesPerMinute = 0;
    }

#if defined(HELIX_FEATURE_MIN_HEAP)
    // In case of min_heap - always use codec reported block size when avaialable
    // This however does not work correctly for some non-deafult encoder setting.
    // It needs to be corrected on MIN-HEAP utilizing platforms.
    if (uPropSize != 0)
    {
	ulBytesPerMinute = 0;
    }
#endif	// HELIX_FEATURE_MIN_HEAP

    if (ulBytesPerMinute != 0)
    {
	// Resort to backup plan: this is very non-optimal for heap usage!
	UINT32 uMaxSecPerBlock = (m_StreamParam.uInterleaveBlockSize * 60/ulBytesPerMinute) + 1;
	m_ulAudioBufSize = uMaxSecPerBlock * m_StreamParam.ulSampleRate * m_StreamParam.uSampleSize / 8 * m_StreamParam.uChannels;
    }
    else
    {

⌨️ 快捷键说明

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