📄 rarender.cpp
字号:
/* ***** 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" // needed for memcpy, needed by hxmarsh.h
#include "rarender.ver"
#include "rarender.h"
#if defined(HELIX_FEATURE_PREFERENCES)
#include "hxprefs.h"
#include "hxprefutil.h"
#endif /* HELIX_FEATURE_PREFERENCES */
#ifdef _WINCE
#include <winbase.h>
#endif
#include "hxtypes.h"
#include "hxver.h"
/****************************************************************************
* Defines
*/
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
#define MAXIMUM_GRANULARITY 100
#define MINIMUM_GRANULARITY 20
#define DEFAULT_DRY_NOTIFICATION 0
#define MAX_TRANSPORT_BUFFER_DURATION 20000
//#define RA_TEST_LOSS
#if !defined(HELIX_FEATURE_DLLACCESS_CLIENT)
ENABLE_DLLACCESS_PATHS(RACodec);
#endif // HELIX_FEATURE_DLLACCESS_CLIENT
//#define RARENDER_LOGING_ON
#ifdef RARENDER_LOGING_ON
#define LOG_PATH "C:\\Log\\rarender\\"
#define RASYNC_FILE LOG_PATH##"sync.txt"
#define ONPACKET_FILE LOG_PATH##"packet.txt"
#define AUDIOSERVICES_FILE LOG_PATH##"write.txt"
#define SWITCH_FILE LOG_PATH##"switch.txt"
#define DOAUDIO_FILE LOG_PATH##"doaudio.txt"
#define PREREDSTONE_FILE LOG_PATH##"hack.txt"
#define LATESTPACKET_FILE LOG_PATH##"latest.txt"
#define LOSS_FILE LOG_PATH##"loss.txt"
#else
#define RASYNC_FILE 0
#define ONPACKET_FILE 0
#define AUDIOSERVICES_FILE 0
#define SWITCH_FILE 0
#define DOAUDIO_FILE 0
#define PREREDSTONE_FILE 0
#define LATESTPACKET_FILE 0
#define LOSS_FILE 0
#endif
#ifdef LOG_BUFFERING_ENABLED
#define BUF_LOG_FILE "C:\\buffer.txt"
#define LOG_BUFFERING(x, y) { \
char* s = NULL; \
FILE* f1; \
s = new char[2048]; \
if(s){ \
sprintf y; /* Flawfinder: ignore */ \
f1 = (x)?(::fopen(x, "a+")):(NULL); \
(f1)?(::fprintf(f1, s), ::fclose(f1)):(0); \
delete [] s; \
} \
}
#else // LOG_BUFFERING_ENABLED
#define LOG_BUFFERING(x, y)
#endif // LOG_BUFFERING_ENABLED
// The value of 120 for audio pushdown presumes an AUDIO_GRANULARITY of 40:
// 120 = 3 blocks. Note that this value is too small for general use and
// may need to be tweaked depending on the cpu and hardware being used. A
// slower system than the one tested on may not be able to keep pnaudio from
// starving with buffers this small.
#define OPTIMAL_HEAP_MIN_AUDIO_PUSHDOWN 480 // ms
const char* const CRealAudioRenderer::zm_pName = "RealAudio";
const char* const CRealAudioRenderer::zm_pDescription = "RealNetworks RealAudio Renderer Plugin";
const char* const CRealAudioRenderer::zm_pCopyright = "(c) 1995-2002 RealNetworks, Inc. All rights reserved.\r\n\r\n"
"RealNetworks RealAudio 8 Audio Codec:\r\n"
"Copyright (c) 1995-2002 RealNetworks, Inc. All rights reserved.\r\n\r\n"
"ATRAC3\r\n"
"Copyright (c) 2000 Sony Corporation. All rights reserved.\r\n\r\n"
"aacPlus\r\n"
"aacPlus developed by Coding Technologies. All rights reserved.\r\n\r\n"
"DolbyNet(tm) audio system manufactured under license from Dolby Laboratories Licensing Corporation.\r\n"
"Copyright (c) 1996-1997, Dolby Laboratories Licensing Corporation. All rights reserved.\r\n\r\n"
"ACELP(r) is either registered trademark or trademark of VoiceAge Corporation in the United States and/or other countries and used under license from VoiceAge Corporation\r\n"
"The ACELP(r).net codec in this product is used under license from VoiceAge Corporation\r\n"
"Copyright (c) 1998,1999, 2000 VoiceAge Corporation. All rights reserved.\r\n";
const char* const CRealAudioRenderer::zm_pMoreInfoURL = HXVER_MOREINFO;
const char* const CRealAudioRenderer::zm_pStreamMimeTypes[] =
{REALAUDIO_MIME_TYPE, REALAUDIO_MULTIRATE_MIME_TYPE, REALAUDIO_MULTIRATE_LIVE_MIME_TYPE, NULL};
const char* const CRealAudioRenderer::zm_pAdditionalAutoUpgradeInfo[] =
{"", "#unk_c"};
/// These two constants are consistent with those defined in
/// HXWatermarkBufferControl
#define REBUFFERING_SKIP
#define MAX_TRANSPORT_BUFFER_DURATION 20000
#define MAX_TRASPORT_BUFFER_BYTES 3000000
/************************************************************************
* Method:
* IHXPlugin::InitPlugin
* Purpose:
* Initializes the plugin for use. This interface must always be
* called before any other method is called. This is primarily needed
* so that the plugin can have access to the context for creation of
* IHXBuffers and IMalloc.
*/
STDMETHODIMP CRealAudioRenderer::InitPlugin(IUnknown* /*IN*/ pContext)
{
m_pContext = pContext;
m_pContext->AddRef();
if (HXR_OK != m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void **)&m_pCommonClassFactory))
{
return HXR_FAILED;
}
#if defined(HELIX_FEATURE_STATS)
m_pContext->QueryInterface(IID_IHXRegistry, (void**)&m_pRegistry);
#endif // HELIX_FEATURE_STATS
return HXR_OK;
}
/************************************************************************
* Method:
* IHXPlugin::GetPluginInfo
* Purpose:
* Returns the basic information about this plugin. Including:
*
* bLoadMultiple whether or not this plugin DLL can be loaded
* multiple times. All File Formats must set
* this value to TRUE.
* pDescription which is used in about UIs (can be NULL)
* pCopyright which is used in about UIs (can be NULL)
* pMoreInfoURL which is used in about UIs (can be NULL)
*/
STDMETHODIMP CRealAudioRenderer::GetPluginInfo
(
REF(BOOL) /*OUT*/ bLoadMultiple,
REF(const char*) /*OUT*/ pDescription,
REF(const char*) /*OUT*/ pCopyright,
REF(const char*) /*OUT*/ pMoreInfoURL,
REF(ULONG32) /*OUT*/ ulVersionNumber
)
{
bLoadMultiple = TRUE; // Must be true for file formats.
pDescription = zm_pDescription;
pCopyright = zm_pCopyright;
pMoreInfoURL = zm_pMoreInfoURL;
ulVersionNumber = TARVER_ULONG32_VERSION;
return HXR_OK;
}
/************************************************************************
* Method:
* IHXPlugin::GetRendererInfo
* Purpose:
* If this object is a file format object this method returns
* information vital to the instantiation of file format plugins.
* If this object is not a file format object, it should return
* HXR_UNEXPECTED.
*/
STDMETHODIMP CRealAudioRenderer::GetRendererInfo
(
REF(const char**) /*OUT*/ pStreamMimeTypes,
REF(UINT32) /*OUT*/ unInitialGranularity
)
{
pStreamMimeTypes = (const char**)zm_pStreamMimeTypes;
unInitialGranularity = m_ulCurrentGranularity; // OnTimeSync() every 100ms
return HXR_OK;
}
// *** IUnknown methods ***
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::QueryInterface
// Purpose:
// Implement this to export the interfaces supported by your
// object.
//
STDMETHODIMP CRealAudioRenderer::QueryInterface(REFIID riid, void** ppvObj)
{
QInterfaceList qiList[] =
{
{ GET_IIDHANDLE(IID_IUnknown), (IUnknown*) (IHXPlugin*) this},
{ GET_IIDHANDLE(IID_IHXPlugin), (IHXPlugin*) this},
{ GET_IIDHANDLE(IID_IHXRenderer), (IHXRenderer*) this},
{ GET_IIDHANDLE(IID_IHXInterruptSafe), (IHXInterruptSafe*) this},
{ GET_IIDHANDLE(IID_IHXASMStreamSink), (IHXASMStreamSink*) this},
{ GET_IIDHANDLE(IID_IHXDryNotification), (IHXDryNotification*) this},
#if defined(HELIX_FEATURE_RAREND_BANDWIDTH_LISTER)
{ GET_IIDHANDLE(IID_IHXBandwidthLister), (IHXBandwidthLister*) this},
#endif // HELIX_FEATURE_RAREND_BANDWIDTH_LISTER
#if defined(HELIX_FEATURE_STATS)
{ GET_IIDHANDLE(IID_IHXStatistics), (IHXStatistics*) this},
#endif // HELIX_FEATURE_STATS
#if defined(HELIX_FEATURE_SETSRCPROPS)
{ GET_IIDHANDLE(IID_IHXValues), (IHXValues*) this},
#endif /* #if defined(HELIX_FEATURE_SETSRCPROPS) */
{ GET_IIDHANDLE(IID_IHXUpdateProperties), (IHXUpdateProperties*) this}
};
return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::AddRef
// Purpose:
// Everyone usually implements this the same... feel free to use
// this implementation.
//
STDMETHODIMP_(ULONG32) CRealAudioRenderer::AddRef()
{
return _AddRef();
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::Release
// Purpose:
// Everyone usually implements this the same... feel free to use
// this implementation.
//
STDMETHODIMP_(ULONG32) CRealAudioRenderer::Release()
{
return _Release();
}
CRealAudioRenderer::CRealAudioRenderer()
: m_lRefCount(0)
, m_pContext(NULL)
, m_pStream(NULL)
, m_pBufferingStats(NULL)
, m_ulPreroll(0)
, m_bReportOKStatus(FALSE)
, m_ulCurrentTimelineTime(0)
, m_pAudioPlayer(NULL)
, m_pAudioPushdown2(NULL)
, m_pCommonClassFactory(NULL)
, m_ulRegistryID(0)
, m_pRegistry(NULL)
, m_ulSmartStreamRegID(0)
, m_ulNameRegID(0)
, m_ulCodecRegID(0)
, m_ulRateRegID(0)
, m_ulChannelsRegID(0)
, m_ulSurroundRegID(0)
, m_bEndOfPackets(FALSE)
, m_bDoneWritingPackets(FALSE)
, m_bInSeekMode(FALSE)
, m_ulCurrentGranularity(MAXIMUM_GRANULARITY)
, m_bStreamSwitchable(FALSE)
, m_uNumOfSubStreams(0)
, m_uNumOfRules(0)
, m_ulDuration(0)
, m_bFirstPacket(TRUE)
, m_bDelayOffsetSet(FALSE)
, m_bAllStreamsToBeUnregistered(FALSE)
, m_ulLatestStreamTime(NO_TIME_SET)
, m_fLatestStreamTime(0.0)
, m_ulLatestActualTime(NO_TIME_SET)
, m_ulDelay(0)
, m_lTimeLineOffset(0)
, m_usCurrentDryNotificationStream(NO_STREAM_SET)
, m_usPreviousDryNotificationStream(NO_STREAM_SET)
, m_usThisSourceStream(NO_STREAM_SET)
, m_pErrorMessages(0)
, m_pRuleToFlagMap(NULL)
, m_pMutex(NULL)
#ifdef _MACINTOSH
, m_bProcessingPacket(FALSE)
, m_pDryCallback(NULL)
#endif
, m_pRuleMap(NULL)
, m_pRaFormats(NULL)
, m_pAudioStreams(NULL)
, m_PlayState(stopped)
, m_bPreRedstonePlayer(TRUE)
, m_uSyncUnregisterStream(NO_STREAM_SET)
, m_ulSyncUnregisterTime(NO_TIME_SET)
#if defined(HELIX_CONFIG_SLUGGISHAUTOUPGRADE)
, m_pASMStream(NULL)
#endif
, m_pValues(NULL)
, m_ulSrcPropertySubStream(NO_STREAM_SET)
, m_ppVBRDepack(NULL)
{
}
CRealAudioRenderer::~CRealAudioRenderer()
{
EndStream();
HX_DELETE(m_pMutex);
}
// *** IHXRenderer methods ***
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXRenderer::StartStream
// Purpose:
// Called by client engine to inform the renderer of the stream it
// will be rendering. The stream interface can provide access to
// its source or player. This method also provides access to the
// primary client controller interface.
//
STDMETHODIMP
CRealAudioRenderer::StartStream
(
IHXStream* pStream,
IHXPlayer* pPlayer
)
{
HX_RESULT hr = HXR_OK;
// Save for later use!
m_pStream = pStream;
if (m_pStream)
{
m_pStream->AddRef();
}
// get interface to report errors
if (HXR_OK != pPlayer->QueryInterface(IID_IHXErrorMessages, (void **)&m_pErrorMessages))
{
hr = HXR_FAILED;
goto cleanup;
}
// get interface to audio player
if (HXR_OK != pPlayer->QueryInterface(IID_IHXAudioPlayer, (void**) &m_pAudioPlayer))
{
hr = HXR_FAILED;
goto cleanup;
}
#ifdef REBUFFERING__SKIP
if (m_pStream)
{
IHXStreamSource* pSource = 0;
if (m_pStream->GetSource(pSource) == HXR_OK)
{
if (pSource)
{
pSource->QueryInterface(IID_IHXSourceBufferingStats,
(void**) &m_pBufferingStats);
HX_RELEASE(pSource);
}
}
}
#endif // #ifdef REBUFFERING__SKIP
pPlayer->QueryInterface(IID_IHXAudioPushdown2, (void**) &m_pAudioPushdown2);
#ifdef HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES
m_pAudioPushdown2->SetAudioPushdown( OPTIMAL_HEAP_MIN_AUDIO_PUSHDOWN );
#endif // HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -