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

📄 mp4afmt.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 ***** */ 

/****************************************************************************
 *  Defines
 */
// #define _BYPASS_DECODER
// #define _SILENT_PLAY
// #define ENABLE_FRAME_TRACE
#define _IGNORE_UNSUPPORTED // must be defined if _BYPASS_DECODER is defined

#define MIN_ACCEPTBALE_DATA_REMAINDER	1	// in bytes
#define MP4_DEFAULT_AUDIO_PREROLL	2000	// in milliseconds
#define MAX_TOLERABLE_TIME_GAP		5	// in milliseconds


/****************************************************************************
 *  Includes
 */
#include "mp4afmt.h"
#include "mp4adec.h"

#include "hxtick.h"
#include "hxassert.h"
#include "hxstrutl.h"

#include "mp4audio.h"
#include "mp4apyld.h"
#include "mp4gpyld.h"
#include "amrpyld.h"
#include "hxamrpyld.h"
#if defined(HELIX_FEATURE_AUDIO_CODEC_MP3)
#include "mp3draft.h"
#endif /* #if defined(HELIX_FEATURE_AUDIO_CODEC_MP3) */


/****************************************************************************
 *  Debug
 */
#ifdef ENABLE_FRAME_TRACE
#define MAX_FRAME_TRACE_ENTRIES	100000
ULONG32 ulFrameTraceIdx = 0;
LONG32 frameTraceArray[MAX_FRAME_TRACE_ENTRIES][4];

void DumpFrameEntries(void)
{
    FILE* pFile = NULL;
    ULONG32 ulIdx;

    if (ulFrameTraceIdx > 0)
    {
	pFile = fopen("c:\\mp4a.txt", "wb");
    }

    if (pFile)
    {
	for (ulIdx = 0; ulIdx < ulFrameTraceIdx; ulIdx++)
	{
	    fprintf(pFile, "%c(%d=%d) = %d\n", (char) frameTraceArray[ulIdx][1], 
					   frameTraceArray[ulIdx][2],
					   frameTraceArray[ulIdx][3],
					   frameTraceArray[ulIdx][0]);
	}

	fclose(pFile);
    }

    ulFrameTraceIdx = 0;
}
#endif	// ENABLE_FRAME_TRACE


/****************************************************************************
 *  Locals
 */


/****************************************************************************
 *  Method:
 *    CMP4AudioFormat::CMP4AudioFormat
 *
 */
CMP4AudioFormat::CMP4AudioFormat(IHXCommonClassFactory* pCommonClassFactory,
				 CMP4AudioRenderer* pMP4AudioRenderer)
    : CAudioFormat(pCommonClassFactory, pMP4AudioRenderer)
    , m_pRssm(NULL)
    , m_bNewAssembledFrame(TRUE)
    , m_ulAUDuration(0)
    , m_ulLastDecodedEndTime(0)
    , m_ulLastFrameTime(0)
    , m_ulCodecDelayMs(0)
    , m_bCanChangeAudioStream(FALSE)
    , m_ulMaxDecoderOutputBytes(0)
    , m_ulMaxDecoderOutputSamples(0)
    , m_pDecoderBuffer(NULL)
    , m_ulDecoderBufferSize(0)
    , m_pDecoderModule(NULL)
    , m_pDecoderInstance(NULL)
    , m_pMP4AudioRenderer(pMP4AudioRenderer)
{
    // Register the payload format builders with m_fmtFactory
    RegisterPayloadFormats();

    HX_ASSERT(m_pCommonClassFactory);
}


/****************************************************************************
 *  Method:
 *    CMP4AudioFormat::~CMP4AudioFormat
 *
 */
CMP4AudioFormat::~CMP4AudioFormat()
{
    _Reset();

    HX_RELEASE(m_pDecoderInstance);
    HX_DELETE(m_pDecoderModule);
    HX_VECTOR_DELETE(m_pDecoderBuffer);
    HX_RELEASE(m_pRssm);

#ifdef ENABLE_FRAME_TRACE
    DumpFrameEntries();
#endif	// ENABLE_FRAME_TRACE
}


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

    // Open the Decoder Module
    if (SUCCEEDED(retVal))
    {
	m_pDecoderModule = CreateDecoder();

	retVal = HXR_OUTOFMEMORY;
	if (m_pDecoderModule)
	{
	    retVal = HXR_OK;
	}
    }

    if (SUCCEEDED(retVal))
    {
	retVal = m_pDecoderModule->Open(pHeader, 
					&m_pDecoderInstance,
					m_pContext);
#if defined(HELIX_FEATURE_AUTOUPGRADE)
        if (FAILED(retVal) && retVal == HXR_REQUEST_UPGRADE)
        {
            // If we returned a HXR_REQUEST_UPGRADE, then we 
            // failed to load the decoder binary. Therefore, we
            // will copy the decoder's AU string into our
            // own AU String
            SafeStrCpy(m_szAUStr, // m_szAUStr is from our parent class
                       m_pDecoderModule->GetAutoUpgradeString(),
                       MAX_AUSTR_SIZE);
        }
#endif /* #if defined(HELIX_FEATURE_AUTOUPGRADE) */
    }

#if defined(HELIX_FEATURE_STATS)
    if (SUCCEEDED(retVal))
    {
	char* pVal = (char*) m_pDecoderModule->GetCodecName();

	if (pVal)
	{
	    m_pMP4AudioRenderer->ReportStat(AS_CODEC_NAME, pVal);
	}

	pVal = (char*) m_pDecoderModule->GetCodecFourCC();

	if (pVal)
	{
	    m_pMP4AudioRenderer->ReportStat(AS_CODEC_4CC, pVal);
	}
    }
#endif /* #if defined(HELIX_FEATURE_STATS) */

    // Create Packet Assembler
    if (SUCCEEDED(retVal))
    {
        retVal = m_fmtFactory.BuildFormat(m_pCommonClassFactory, FALSE, 
                                          pHeader, m_pRssm);
#if defined(HELIX_FEATURE_AUTOUPGRADE)
        if (FAILED(retVal) && retVal == HXR_REQUEST_UPGRADE)
        {
            // If BuildFormat returns HXR_REQUEST_UPGRADE, then
            // it means that no depacketizer had successful calls
            // to Init() and SetStreamHeader(), but at least one
            // of the depacketizers returned HXR_REQUEST_UPGRADE.
            //
            // Copy our own mime type into the AU string
            IHXBuffer* pMimeTypeStr = NULL;
            pHeader->GetPropertyCString("MimeType", pMimeTypeStr);
            if (pMimeTypeStr)
            {
                SafeStrCpy(m_szAUStr, // m_szAUStr is from our parent class
                           (const char*) pMimeTypeStr->GetBuffer(),
                           MAX_AUSTR_SIZE);
            }
            HX_RELEASE(pMimeTypeStr);
        }
#endif /* #if defined(HELIX_FEATURE_AUTOUPGRADE) */

#ifdef _IGNORE_UNSUPPORTED
	if (FAILED(retVal))
	{
	    HX_RELEASE(m_pDecoderInstance);
	    retVal = HXR_OK;
	}
#endif	// _IGNORE_UNSUPPORTED
    }
    
    // Open Codec Instance
    if (SUCCEEDED(retVal) && m_pDecoderInstance)
    {
	HX_ASSERT(m_pDecoderModule);

	ULONG32 ulBitstreamHeaderSize;
	const UINT8* pBitstreamHeader;
        UINT8 unBitstreamType;

	ulBitstreamHeaderSize = m_pRssm->GetBitstreamHeaderSize();
	pBitstreamHeader = m_pRssm->GetBitstreamHeader();
	unBitstreamType = m_pRssm->GetBitstreamType();

	retVal = HXR_FAIL;
	if (pBitstreamHeader && (ulBitstreamHeaderSize > 0))
	{
	    retVal = HXR_OK;
	}

	if (SUCCEEDED(retVal))
	{
	    retVal = m_pDecoderInstance->OpenDecoder(unBitstreamType,	// eCfgDesc
						     pBitstreamHeader,
						     ulBitstreamHeaderSize);
            if (FAILED(retVal))
            {
#if defined(HELIX_FEATURE_AUTOUPGRADE)
                // If we failed in our OpenDecoder() call, then the
                // decoder must be a version which does not support the
                // particular profile which we passed in. Therefore,
                // we will AU with the "qtplayer" string to instruct
                // the TLC to attempt to play this file other means.
                //
                // Copy into our parent class's AU string buffer
                SafeStrCpy(m_szAUStr, // m_szAUStr is from our parent class
                           "qtplayer",
                           MAX_AUSTR_SIZE);
#endif /* #if defined(HELIX_FEATURE_AUTOUPGRADE) */
                // When CAudioFormat::Init() returns to where it was called
                // from CAudioRenderer::OnHeader(), then if the return code
                // is HXR_REQUEST_UPGRADE, then it will assume it needs
                // to AU, and will look for an AU string from CAudioFormat.
                // So we need to return HXR_REQUEST_UPGRADE.
                retVal = HXR_REQUEST_UPGRADE;
            }
	}

#ifdef _IGNORE_UNSUPPORTED
	if (FAILED(retVal) && retVal != HXR_REQUEST_UPGRADE)
	{
	    HX_RELEASE(m_pDecoderInstance);
	    retVal = HXR_OK;
	}
#endif	// _IGNORE_UNSUPPORTED
    }

    // Inquire and set Audio data parameters
    if (SUCCEEDED(retVal) && m_pDecoderInstance)
    {
        retVal = UpdateAudioFormat(m_ulLastDecodedEndTime, TRUE);
    }

    if (SUCCEEDED(retVal))
    {
	m_bCanChangeAudioStream = CanChangeAudioStream();
    }

#ifdef _BYPASS_DECODER
    HX_RELEASE(m_pDecoderInstance);
#endif	// _BYPASS_DECODER

    return retVal;
}


/****************************************************************************
 *    CMP4AudioFormat::GetDefaultPreroll
 */
ULONG32 CMP4AudioFormat::GetDefaultPreroll(IHXValues* pValues)
{
    return MP4_DEFAULT_AUDIO_PREROLL;
}

HX_RESULT CMP4AudioFormat::UpdateAudioFormat(ULONG32& ulAnchorTime, 
					     BOOL bForceUpdate)
{
    HX_RESULT retVal = HXR_FAIL;

    if (m_pDecoderInstance && m_pAudioFmt && m_pRssm)
    {
	UINT32 ulChannels = 0;
	BOOL bFormatChanged = FALSE;

        // Set the bits per sample (always 16 bits per sample)
        m_pAudioFmt->uBitsPerSample = 16;                 
        // Set number of channels
        retVal = m_pDecoderInstance->GetNChannels(ulChannels);
        if (SUCCEEDED(retVal))
        {
            retVal = HXR_FAIL;
	    if (ulChannels)
	    {
		retVal = HXR_OK;

		if ((ulChannels != m_pAudioFmt->uChannels) || bForceUpdate)
		{
		    bFormatChanged = TRUE;
		}
	    }
        }
        // Set the sample rate
        if (SUCCEEDED(retVal))
        {
            UINT32 ulSampleRate = 0;
            retVal = m_pDecoderInstance->GetSampleRate(ulSampleRate);
            if (SUCCEEDED(retVal))
            {
                retVal = HXR_FAIL;
                if (ulSampleRate)
                {
		    retVal = HXR_OK;

		    if ((m_pAudioFmt->ulSamplesPerSec != ulSampleRate) || 
			bForceUpdate)
		    {
			ULONG32 ulAnchorInMs = m_TSConverter.Convert(ulAnchorTime);

			m_pAudioFmt->uChannels = (UINT16) ulChannels;
			m_pAudioFmt->ulSamplesPerSec = ulSampleRate;

			ulAnchorTime = 	ConvertMsToTime(ulAnchorInMs);

			ConfigureRssm(ulAnchorInMs);

			m_TSConverter.SetBase(ulSampleRate, 1000);
			m_TSConverter.SetOffset(ulAnchorInMs);

			bFormatChanged = TRUE;
		    }
		    else
		    {
			m_pAudioFmt->uChannels = (UINT16) ulChannels;
		    }  
                }
            }
        }
        // Set the max samples out
        if (SUCCEEDED(retVal))
        {
            UINT32 ulMaxSamplesOut = 0;
            retVal = m_pDecoderInstance->GetMaxSamplesOut(ulMaxSamplesOut);
            if (SUCCEEDED(retVal))
            {
                retVal = HXR_FAIL;
                if (ulMaxSamplesOut)
                {
                    retVal = HXR_OK;

		    if ((ulMaxSamplesOut != m_ulMaxDecoderOutputSamples) || 
			bForceUpdate)
		    {
			// Save the max samples out
			m_ulMaxDecoderOutputSamples = ulMaxSamplesOut;
			// Compute and set the AU duration
			m_ulAUDuration = m_ulMaxDecoderOutputSamples / m_pAudioFmt->uChannels;
			m_pRssm->SetAUDuration(m_ulAUDuration);
			// Compute the max output in bytes
			m_ulMaxDecoderOutputBytes = CAudioFormat::ConvertSamplesToBytes(m_ulMaxDecoderOutputSamples);
			// Save the max block size
			m_pAudioFmt->uMaxBlockSize = (UINT16) m_ulMaxDecoderOutputBytes;

			bFormatChanged = TRUE;
		    }
                }
            }
        }
        // Set the codec delay in samples
        if (bFormatChanged && SUCCEEDED(retVal))
        {
            UINT32 ulCodecDelaySamples = 0;
            retVal = m_pDecoderInstance->GetDelay(ulCodecDelaySamples);

⌨️ 快捷键说明

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