📄 cra2ihxaenc.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 ***** */
#include "hxcom.h"
#include "hxtypes.h"
#include "hxresult.h"
#include "hlxclib/string.h"
/* heap, memory debugging */
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
#include "dunitprvt.h"
#include "gcd.h"
#include "racodec.h"
#include "hxacodec.h"
#include "cra2ihxaenc.h"
#ifdef _M_IX86 /* Asm versions */
__inline short
RoundFtoS(float f) {
long l;
__asm fld f
__asm fistp l
if (l < -32768)
l = -32768;
else if (l > 32767)
l = 32767;
return (short)l;
}
#else /* C versions */
__inline short
RoundFtoS(float f) {
long l = (long)(f < 0.0f ? f - 0.5f : f + 0.5f);
if (l < -32768)
l = -32768;
else if (l > 32767)
l = 32767;
return (short)l;
}
#endif /* _M_IX86 */
/****************************************************************************
* IUnknown methods
*/
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::QueryInterface
//
STDMETHODIMP HXAudioEncoder::QueryInterface(REFIID riid, void** ppvObj)
{
if (IsEqualIID(riid, IID_IHXAudioEncoder))
{
AddRef();
*ppvObj = (IHXAudioEncoder*) this;
return HXR_OK;
}
else if (IsEqualIID(riid, IID_IHXAudioEncoderConfigurator))
{
AddRef();
*ppvObj = (IHXAudioEncoderConfigurator*)this;
return HXR_OK;
}
else if (IsEqualIID(riid, IID_IHXCodecOldStyleAuthenticate))
{
// runtime check if password function is present
if (RAHaveSetPassword())
{
AddRef();
*ppvObj = (IHXCodecOldStyleAuthenticate*)this;
return HXR_OK;
}
}
else if (IsEqualIID(riid, IID_IUnknown))
{
AddRef();
*ppvObj = this;
return HXR_OK;
}
*ppvObj = NULL;
return HXR_NOINTERFACE;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::AddRef
//
STDMETHODIMP_(ULONG32) HXAudioEncoder::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::Release
//
STDMETHODIMP_(ULONG32) HXAudioEncoder::Release()
{
if (InterlockedDecrement(&m_lRefCount) > 0)
{
return m_lRefCount;
}
delete this;
return 0;
}
HXAudioEncoder::HXAudioEncoder()
: m_lRefCount(0)
, mpCodecRef(0)
, mnSamplesIn(0)
, mnBytesOut(0)
, mCurrentFlavorIndex(-1)
, mpDataIn(0)
, mpDataOut(0)
, mDataOffset(0)
, mpPropTable(0)
{
}
HXAudioEncoder::~HXAudioEncoder()
{
if (mpCodecRef)
{
ENTRYPOINT(RACloseCodec)(mpCodecRef) ;
}
if (mpPropTable)
delete[] mpPropTable ;
}
HX_RESULT HXAudioEncoder::Init()
{
HX_RESULT res ;
res = ENTRYPOINT(RAOpenCodec2)(&mpCodecRef, 0) ;
if (SUCCEEDED(res)) res = retrieveProperties() ;
return res ;
}
HX_RESULT HXEXPORT ENTRYPOINT(RACreateEncoderInstance) (const CLSID &clsid, IUnknown** ppUnknown)
{
HX_RESULT res = HXR_OUTOFMEMORY ;
HXAudioEncoder* pObj = new HXAudioEncoder() ;
if (pObj)
res = pObj->Init() ;
if (SUCCEEDED(res))
res = pObj->QueryInterface(clsid, (void**)ppUnknown) ;
return res ;
}
STDMETHODIMP HXAudioEncoder::SetOption(OPTION_LONG option, INT32 arg)
{
return HXR_NOTIMPL ;
}
STDMETHODIMP HXAudioEncoder::OpenEncoder()
{
HX_RESULT res ;
RAENCODER_INIT_PARAMS initParams ;
HX_AUDIO_FORMAT *p ;
unsigned short pSize ;
/* stupid. Some encoders (notably tokyo) check for consistency among initParams and its
internal parameters, failing if inconsistent. This is why we have to fill this structure
out */
p = (HX_AUDIO_FORMAT*)ENTRYPOINT(RAGetFlavorProperty)(mpCodecRef, mCurrentFlavorIndex, ::FLV_PROP_INPUT_AUDIO_FORMAT, &pSize) ;
if (p && pSize == sizeof(*p))
{
initParams.sampleRate = p->SamplesPerSec ;
initParams.bitsPerSample = p->BitsPerSample ;
initParams.channels = p->Channels ;
if (p->BitsPerSample != 16)
return HXR_NOTIMPL ;
}
res = ENTRYPOINT(RAInitEncoder)(mpCodecRef, &initParams) ;
if (SUCCEEDED(res))
{
mnSamplesIn = initParams.numSamplesIn ;
mnBytesOut = initParams.numBytesOut ;
mDataOffset = mpPropTable[mCurrentFlavorIndex].bytesPerEncode ;
mpDataIn = new short[mnSamplesIn] ;
mpDataOut = new unsigned char[mnBytesOut] ;
}
return res ;
}
STDMETHODIMP_(void) HXAudioEncoder::CloseEncoder()
{
if (mpCodecRef) ENTRYPOINT(RAFreeEncoder)(mpCodecRef) ;
if (mpDataIn) delete[] mpDataIn ;
if (mpDataOut) delete[] mpDataOut ;
}
STDMETHODIMP
HXAudioEncoder::EncodeData(void *pvDataIn, UINT32 nSamplesIn,
UINT32& nSamplesConsumed,
IQueryDecoderUnit* dataOut[], UINT32& nDecoderUnits,
INT32 eof)
{
float *pfDataIn = (float*)pvDataIn ;
UINT32 maxDecoderUnits = nDecoderUnits ;
UINT32 samplesLeft = nSamplesIn ;
nDecoderUnits = 0 ;
nSamplesConsumed = 0 ;
while (1)
{
if (samplesLeft > (eof ? 0 : mnSamplesIn-1) &&
mDataOffset == mpPropTable[mCurrentFlavorIndex].bytesPerEncode) // can produce output
{
unsigned short *input ;
if (samplesLeft >= mnSamplesIn)
input = (unsigned short *)pvDataIn + nSamplesConsumed ;
else
{
// apparently, eof is on. Copy remaining samples into temp buffer and fill with zeros.
input = new unsigned short[mnSamplesIn] ;
memcpy(input, (unsigned short*)pvDataIn + nSamplesConsumed, samplesLeft * sizeof(signed short)) ; /* Flawfinder: ignore */
memset(input + samplesLeft, 0, (mnSamplesIn - samplesLeft) * sizeof(short)) ;
}
ENTRYPOINT(RAEncode)(mpCodecRef, input, mpDataOut) ;
mDataOffset = 0 ;
// delete the temp buffer if this was the last time around.
if (samplesLeft < mnSamplesIn)
delete[] input ;
nSamplesConsumed += mnSamplesIn ;
if (nSamplesConsumed > nSamplesIn)
nSamplesConsumed = nSamplesIn ;
}
samplesLeft = nSamplesIn - nSamplesConsumed ;
if (mDataOffset == mpPropTable[mCurrentFlavorIndex].bytesPerEncode)
{
// did not produce any samples, and none are pending
break ;
}
// pack output into data units
while (nDecoderUnits < maxDecoderUnits && mDataOffset < mpPropTable[mCurrentFlavorIndex].bytesPerEncode)
{
/* we have data pending from a previous Encode() call
that are not yet shipped in decoder units. */
/* since we always allocate these, we know they are really PrepareDecoderUnits,
and the cast is harmless */
IPrepareDecoderUnit* du = (IPrepareDecoderUnit*)dataOut[nDecoderUnits] ;
if (du == 0) /* need to instantiate a new unit */
{
HX_RESULT hr = CreateIPrepareDecoderUnit(du) ;
if (FAILED(hr))
return hr ;
dataOut[nDecoderUnits] = du ;
}
du->putData((const char*)mpDataOut + mDataOffset, mpPropTable[mCurrentFlavorIndex].bytesPerFrame, mpPropTable[mCurrentFlavorIndex].samplesPerFrame) ;
du->setBufferFullness(0) ; // we are CBR
if (eof && samplesLeft <= 0 &&
mDataOffset == mpPropTable[mCurrentFlavorIndex].bytesPerEncode - mpPropTable[mCurrentFlavorIndex].bytesPerFrame )
{
// this is the very last decoder unit.
du->setFlags(IQueryDecoderUnit::ENDOFSTREAM) ;
}
mDataOffset += mpPropTable[mCurrentFlavorIndex].bytesPerFrame ;
nDecoderUnits++;
if (nDecoderUnits == maxDecoderUnits)
{
return HXR_OK ;
}
}
}
return HXR_OK ;
}
HX_RESULT HXAudioEncoder::CreateIPrepareDecoderUnit(IPrepareDecoderUnit*& ppi)
{
CDecoderUnit *du = new CDecoderUnit() ;
return du->QueryInterface(IID_IPrepareDecoderUnit, (void**)&ppi) ;
}
HX_RESULT HXAudioEncoder::SetPassword(const char* password)
{
if (mpCodecRef && password) ENTRYPOINT(RASetPwd)(mpCodecRef, password) ;
return HXR_OK ; // we always smile, no matter what
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -