raformat.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:55k
- /* ***** 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 == ' ')
- {
- 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=%hdn",
- 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
- {
- if (uPropSize)
- {
- // The original comment in here suggested that for G2 stereo content,
- // param.uChannels would wrongly indicate "1" as the number of channels.
- // This cannot be reproduced anymore, but to be sure, we never allocate
- // memory for less than 2 channels. The downside is that
- // if we're playing a mono stream we could waste as much as ~10kb. Until
- // the codec interface is changed to allow us to get the exact size of
- // the output buffer, however, this will have to suffice.
- int nchannels = param.uChannels < 2 ? 2 : param.uChannels ;
- // /Fixes PR 114676: also multiply by bytes-per-sample, as is done
- // in the other calculation of m_ulAudioBufSize, above, to fix
- // overflow of buffer in RAAC codec's Decode() when there are
- // samples to conceal. m_ulAudioBufSize should be in total bytes
- // per block (total meaning for all channels):
- // (samples / block)*(bytes / sample) * channels => total bytes per block. :
- m_ulAudioBufSize = (*pulSamplesPerBlock) * m_StreamParam.uSampleSize / 8 * nchannels;
- }
- else
- {
- // There is no information on how large the decode buffer should be
- m_ulAudioBufSize = DFLT_AUDIO_BUF_SIZE;
- }
- }
- return theError;
- }
- BOOL
- CRaFormat::IsActive()
- {
- BOOL bRetVal = FALSE;
- if ((!m_IBufs.IsDSuperBlockEmpty()) ||
- (!m_IBufs.IsISuperBlockEmpty()))
- {
- bRetVal = TRUE;
- }
- else
- {
- if( m_pPacketFeeder )
- {
- bRetVal = m_pPacketFeeder->IsActive();
- }
- }
- return bRetVal;
- }
- void
- CRaFormat::LossOccured()
- {
- if( m_pPacketFeeder )
- {
- m_pPacketFeeder->LossOccured();
- }
- }
- HX_RESULT
- CRaFormat::OnPacket(IHXPacket* pPacket, LONG32 lTimeOffset, UINT16* rule_to_flag_map)
- {
- HX_RESULT retVal = HXR_OK;
- m_lTimeOffset = lTimeOffset;
- /*
- DEBUG_OUTF_IDX(m_uStreamNumber, RA_FLOW_FILE, (s, "PKT: TS=%d, Rule=%d L=%sn",
- pPacket->GetTime() % MAX_TS_DBG_RANGE,
- pPacket->GetASMRuleNumber(),
- pPacket->IsLost() ? "YES" : "NO"));
- */
- retVal = m_pPacketFeeder->OnPacket(pPacket,
- lTimeOffset,
- rule_to_flag_map);
- // we only deinterleave data when the input buffer
- // is filled and output buffer is empty
- if (m_IBufs.IsISuperBlockFilled() && m_IBufs.IsDSuperBlockEmpty())
- {
- // deinterleave the data and fill up the interleave buffer from
- // the packet queue
- m_IBufs.DeInterleaveData();
- }
- return retVal;
- }
- HX_RESULT
- CRaFormat::GetAudioData(HXAudioData& audioData,
- UINT32& ulActualTimestamp,
- AUDIO_STATE audioState,
- UINT32 ulSpliceToActualTime,
- UINT32 ulSpliceToStreamTime)
- {
- UINT32 ulIterationCounter = 0;
- HX_RESULT pnr = HXR_NO_DATA;
- if (ulSpliceToActualTime != NO_TIME_SET)
- {
- ulSpliceToActualTime = UnAdjustTimestamp(ulSpliceToActualTime, m_lTimeOffset);
- ulSpliceToStreamTime = UnAdjustTimestamp(ulSpliceToStreamTime, m_lTimeOffset);
- }
- // if we've not determined the if we need to adjust the timestamps
- // the we don't have any data available.
- do
- {
- HX_RELEASE(audioData.pData);
- audioData.ulAudioTime = 0;
- // move any data from the time range queue into the IBufs
- m_pPacketFeeder->FillISuperBlock();
- switch (audioState)
- {
- case AUDIO_CROSSFADE:
- case AUDIO_DRYNOTIFICATION:
- case AUDIO_END_OF_PACKETS:
- if (!m_IBufs.DataAvailable(audioState))
- {
- // this is an "emergency" state so do this even
- // if the IBlock isn't quite full
- m_IBufs.DeInterleaveData();
- }
- break;
- default:
- break;
- }
- if (m_IBufs.DataAvailable(audioState))
- {
- pnr = DecodeAudioData(audioData,
- ulActualTimestamp,
- ulSpliceToActualTime,
- ulSpliceToStreamTime);
- if (HXR_OK == pnr)
- {
- // if we've fulfilled the discard, reset state
- if (m_ulForceDiscardUntilTime != NO_TIME_SET &&
- IsTimeGreater(audioData.ulAudioTime + (UINT32)GetMSPerBlock(),
- m_ulForceDiscardUntilTime))
- {
- m_ulForceDiscardUntilTime = NO_TIME_SET;
- }
- break;
- }
- else if (FAILED(pnr))
- {
- DEBUG_OUTF(DOAUDIO_FILE, (s, "GetAudioDatat%lut0x%Xn",
- (UINT32)GetMSPerBlock(), pnr));
- if( pnr == HXR_OUTOFMEMORY )
- {
- return pnr;
- }
- break;
- }
- DEBUG_OUTF(DOAUDIO_FILE, (s, "DataAvailable - no decodet%lut0x%Xn",
- (UINT32)GetMSPerBlock(), pnr));
- }
- else
- {
- BOOL bTimeRangeEnded = m_pPacketFeeder->IsCurrentTimeRangeEnded();
- BOOL bDataInTimeRange = !m_pPacketFeeder->IsCurrentTimeRangeEmpty();
- // if the D superblock is empty and there's more data to decode
- // we give it a try to move the data into the D superblock to
- // decode it.
- if (m_IBufs.IsDSuperBlockEmpty() &&
- (!m_IBufs.IsISuperBlockEmpty() || bDataInTimeRange))
- {
- if (m_IBufs.IsISuperBlockFilled())
- {
- m_IBufs.DeInterleaveData();
- }
- // if we don't have any data in the De-interleaved superblock
- // and we failed to fill the Interleaved superblock, we
- // must be out of data and we should break out of the while loop
- if (m_IBufs.IsDSuperBlockEmpty() &&
- (!m_pPacketFeeder->FillISuperBlock()))
- {
- DEBUG_OUTF(DOAUDIO_FILE, (s, "GetAudioDatat%dt%dt%dt%dt%lun",
- m_IBufs.IsDSuperBlockEmpty(), m_IBufs.IsISuperBlockEmpty(), m_IBufs.IsISuperBlockFilled(), bTimeRangeEnded, (UINT32)GetMSPerBlock()));
- break;
- }
- }
- else
- {
- HX_ASSERT(!bDataInTimeRange);
- // we've drained the IBufs of data from the previous TR, now
- // we can start the next TR if there is one.
- if (bTimeRangeEnded)
- {
- if (HXR_OK == DecodeAudioData(audioData,
- ulActualTimestamp,
- ulSpliceToActualTime,
- ulSpliceToStreamTime,
- TRUE))
- {
- // if we've fulfilled the discard, reset state
- if (m_ulForceDiscardUntilTime != NO_TIME_SET &&
- IsTimeGreater(audioData.ulAudioTime + (UINT32)GetMSPerBlock(),
- m_ulForceDiscardUntilTime))
- {
- m_ulForceDiscardUntilTime = NO_TIME_SET;
- }
- pnr = HXR_OK;
- }
- else
- {
- // stream done result here tells the renderer not to expect
- // any more data on this format for this particular time range
- // so it can give up on a cross fade if it is pending one here
- pnr = HXR_STREAM_DONE;
- }
- SetupForNextTimeRange();
- }
- else
- {
- DEBUG_OUTF(DOAUDIO_FILE, (s, "GetNextAudioDataTimet%dt%dt%dt%dt%lun",
- m_IBufs.IsDSuperBlockEmpty(), m_IBufs.IsISuperBlockEmpty(), m_IBufs.IsISuperBlockFilled(), bTimeRangeEnded, (UINT32)GetMSPerBlock()));
- }
- break;
- }
- }
- ulIterationCounter++;
- } while (ulIterationCounter < MAX_AUDIO_DATA_ATTEMPTS);
- return pnr;
- }
- HX_RESULT
- CRaFormat::GenerateLostAudioData (UINT32 ulForceEndTime,
- HXAudioData& audioData,
- UINT32& ulActualTimestamp,
- UINT32 ulSpliceToActualTime,
- UINT32 ulSpliceToStreamTime)
- {
- HX_RESULT theError = HXR_FAILED;
- Byte* pData = new UCHAR[m_StreamParam.uInterleaveBlockSize];
- UINT32 ulInSize = m_StreamParam.uInterleaveBlockSize;
- UINT32 ulDataFlags = 0;
- UINT32 ulOutSize;
-
- ulForceEndTime = UnAdjustTimestamp(ulForceEndTime, m_lTimeOffset);
- if( !m_pCodec )
- {
- theError = LoadDecoderAndInitDeInterleaver();
- }
- if (m_pCodec != NULL)
- {
- theError = m_pCachingClassFactory->CreateInstance(CLSID_IHXBuffer,
- (void**) &audioData.pData);
- // These buffers will initially be size 0, but since we're using
- // the caching class factory, they will generally be the right size
- // on reuse. We can't assume this, but let's not call SetSize
- // unnecessarily.
- if( audioData.pData && audioData.pData->GetSize() != m_ulAudioBufSize )
- {
- theError = audioData.pData->SetSize( m_ulAudioBufSize );
- }
- if( theError != HXR_OK )
- {
- return theError;
- }
- theError = m_pCodec->Decode(pData,
- ulInSize,
- audioData.pData->GetBuffer(),
- &ulOutSize,
- ulDataFlags);
- // Make the buffer size smaller if necessary, since we don't always
- // pass the decoder the max size of encoded data. Note that this does
- // not alter the heap (based on current buffer implementation).
- if( ulOutSize < m_ulAudioBufSize )
- {
- theError = audioData.pData->SetSize( ulOutSize );
- }
- }
- HX_VECTOR_DELETE(pData);
-
- if (theError == HXR_OK && ulOutSize == 0)
- {
- theError = HXR_NO_DATA;
- }
- if (theError == HXR_OK)
- {
- audioData.ulAudioTime = ulSpliceToStreamTime;
- audioData.uAudioStreamType = STREAMING_AUDIO;
- ulActualTimestamp = ulSpliceToActualTime;
- // don't forget to adjust...
- if (!AdjustAudioData(audioData, ulActualTimestamp, ulForceEndTime))
- {
- HX_RELEASE(audioData.pData);
- audioData.ulAudioTime = 0;
- theError = HXR_FAILED;
- }
- }
- else
- {
- HX_RELEASE( audioData.pData );
- audioData.pData = NULL;
- audioData.ulAudioTime = 0;
- }
- return (HXR_OK == theError) ? (HXR_OK) : (HXR_NO_DATA);
- }
- HX_RESULT CRaFormat::DecodeAudioBlock(Byte* pData,
- UINT32 ulInSize,
- Byte* pAudioBuf,
- UINT32* pOutSize,
- UINT32 ulDataFlags)
- {
- HX_RESULT retVal = HXR_OK;
- retVal = m_pCodec->Decode(pData, ulInSize,
- pAudioBuf, pOutSize,
- ulDataFlags);
- return retVal;
- }
- HX_RESULT
- CRaFormat::DecodeAudioData (HXAudioData& audioData,
- UINT32& ulActualTimestamp,
- ULONG32 ulSpliceToActualTime,
- ULONG32 ulSpliceToStreamTime,
- BOOL bFlushCodec)
- {
- HX_RESULT theError = HXR_FAILED;
- Byte* pData;
- UINT32 ulInSize;
- UINT32 ulOutSize;
- UINT32 ulDataFlags;
- UINT32 ulTimestamp;
- // To optimize heap, we don't use the m_pAudioBuf as a
- // temporary pcm buffer; we just decode straight into the buffer
- // that we're going to dump it in anyway.
- theError = m_pCachingClassFactory->CreateInstance(CLSID_IHXBuffer,
- (void**) &audioData.pData);
- if( theError != HXR_OK )
- {
- HX_RELEASE(audioData.pData);
- theError = HXR_OUTOFMEMORY;
- }
- if (theError == HXR_OK && m_pCodec != NULL)
- {
- theError = m_IBufs.GetBlock(&pData,
- &ulInSize,
- &ulDataFlags,
- &ulTimestamp,
- &ulActualTimestamp);
- }
- if (theError == HXR_OK)
- {
- // increment the IBuf for next block
- m_IBufs.NextBlock();
- if (!GetDropBlock(ulTimestamp))
- {
- // These buffers will initially be size 0, but since we're using
- // the caching class factory, they will generally be the right
- // on reuse. We can't assume this, but let's not call SetSize
- // unnecessarily.
- if( audioData.pData->GetSize() != m_ulAudioBufSize )
- {
- theError = audioData.pData->SetSize( m_ulAudioBufSize );
- }
- if( theError == HXR_OUTOFMEMORY )
- {
- return theError;
- }
- theError = DecodeAudioBlock(pData, ulInSize, audioData.pData->GetBuffer(),
- &ulOutSize, ulDataFlags);
- }
- else
- {
- DEBUG_OUTF(DOAUDIO_FILE, (s, "DropBlockt%lut%lun",
- ulTimestamp, (UINT32)GetMSPerBlock()));
- // assume entire block decoded?
- m_IBufs.NumDecodedBytes(ConvertMsToBytes((UINT32)GetMSPerBlock()));
- m_bPCMStreamStart = TRUE;
- HX_RELEASE( audioData.pData );
- theError = HXR_NO_DATA;
- }
- }
- else if (theError == HXR_OK && bFlushCodec && m_pCodec != NULL)
- {
- ulOutSize = m_ulAudioBufSize;
- theError = m_pCodec->Flush(audioData.pData->GetBuffer(), &ulOutSize);
- HX_RELEASE( audioData.pData );
- }
- if (theError == HXR_OK && ulOutSize == 0)
- {
- m_fCodecDelay += GetMSPerBlock();
- m_ulCodecDelay = (UINT32) m_fCodecDelay;
- theError = HXR_NO_DATA;
- HX_RELEASE( audioData.pData );
- }
- if (theError == HXR_OK)
- {
- // Make the buffer size smaller if necessary, since we don't always
- // pass the decoder the max size of encoded data. Note that this does
- // not alter the heap (based on current buffer implementation).
- if( audioData.pData->GetSize() > ulOutSize )
- {
- theError = audioData.pData->SetSize( ulOutSize );
- if( theError == HXR_OUTOFMEMORY )
- {
- return theError;
- }
- }
- audioData.ulAudioTime = ulTimestamp;
- if (ulOutSize < m_ulMinExpectedDecodedBlockSize)
- {
- double fCodecDelay = (GetMSPerBlock() - m_IBufs.CalcMs(ulOutSize));
- if (fCodecDelay >= MIN_CODEC_BLOCK_DELAY)
- {
- LONG32 lCodecDelay = (UINT32) fCodecDelay;
- audioData.ulAudioTime += lCodecDelay;
- m_ulCodecDelay += lCodecDelay;
- m_fCodecDelay += fCodecDelay;
- }
- }
- audioData.ulAudioTime -= m_ulCodecDelay;
- m_IBufs.NumDecodedBytes(audioData.ulAudioTime, ulOutSize);
- SpliceAudioData(audioData,
- ulActualTimestamp,
- ulSpliceToActualTime,
- ulSpliceToStreamTime);
- m_bPCMStreamStart = FALSE;
- if (AdjustAudioData(audioData, ulActualTimestamp))
- {
- m_ulNextAudioTime = audioData.ulAudioTime +
- (UINT32) m_IBufs.CalcMs(audioData.pData->GetSize());
- m_ulNextActualAudioTime = ulActualTimestamp +
- (UINT32) m_IBufs.CalcMs(audioData.pData->GetSize());
- }
- else
- {
- m_bPCMStreamStart = TRUE;
- HX_RELEASE(audioData.pData);
- audioData.ulAudioTime = 0;
- theError = HXR_NO_DATA;
- }
- }
- else
- {
- HX_RELEASE( audioData.pData );
- audioData.pData = NULL;
- audioData.ulAudioTime = 0;
- }
- return theError;
- }
- void
- CRaFormat::SetCrossFadeEndTime(UINT32 ulTimestamp)
- {
- DEBUG_OUTF(XFADE_FILE, (s, "SetXFadeEndTimet%lut%lun", ulTimestamp, (UINT32)GetMSPerBlock()));
- /*
- * The ulTimestamp can be in one of these 5 positions.
- * We start from 4 and go to 0 looking for some data that's
- * less than the ulTimestamp time.
- *
- * [DDD][III] {_,_,_,} {_,_,_,_,}
- * ^ ^ ^ ^ ^
- * | | | | |
- * 0 1 2 3 4
- *
- */
- BOOL bDone = FALSE;
- ulTimestamp = UnAdjustTimestamp(ulTimestamp, m_lTimeOffset);
- m_ulCrossFadeEndTime = ulTimestamp;
- // see if it's at #3
- bDone = m_pPacketFeeder->SetCrossFadeEndTime(ulTimestamp);
- // see if it's at #2
- if (!bDone)
- {
- if (!m_IBufs.m_IBlockTimeRange.IsEmpty())
- {
- if (m_IBufs.m_IBlockTimeRange.TimeInRange(ulTimestamp))
- {
- DEBUG_OUTF(XFADE_FILE, (s, "SetXFadeEndTime Pos(2)t%lut%lun", ulTimestamp, (UINT32)GetMSPerBlock()));
- bDone = TRUE;
- }
- else
- {
- // check for the #4 position
- if (IsTimeGreater(ulTimestamp, m_IBufs.m_IBlockTimeRange.m_ulEnd))
- {
- // position #4 and we're done
- bDone = TRUE;
- DEBUG_OUTF(XFADE_FILE, (s, "SetXFadeEndTime Pos(4 after 2)t%lut%lun", ulTimestamp, (UINT32)GetMSPerBlock()));
- }
- else
- {
- // either 1 or 0 so flush 2
- m_IBufs.FlushIBlock();
- }
- }
- }
- }
- // see if it's #1
- if (!bDone)
- {
- if (!m_IBufs.m_DBlockTimeRange.IsEmpty())
- {
- if (m_IBufs.m_DBlockTimeRange.TimeInRange(ulTimestamp))
- {
- DEBUG_OUTF(XFADE_FILE, (s, "SetXFadeEndTime Pos(1)t%lut%lun", ulTimestamp, (UINT32)GetMSPerBlock()));
- bDone = TRUE;
- }
- else
- {
- // check for the #4 position
- if (IsTimeGreater(ulTimestamp, m_IBufs.m_DBlockTimeRange.m_ulEnd))
- {
- // position #4 and we're done
- DEBUG_OUTF(XFADE_FILE, (s, "SetXFadeEndTime Pos(4 after 1)t%lut%lun", ulTimestamp, (UINT32)GetMSPerBlock()));
- bDone = TRUE;
- }
- else
- {
- //it's 0, flush the I bufs now
- DEBUG_OUTF(XFADE_FILE, (s, "SetXFadeEndTime Pos(0), flushing formatt%lut%lun", ulTimestamp, (UINT32)GetMSPerBlock()));
- SetupForNextTimeRange();
- }
- }
- }
- else
- {
- //it's 0, flush the I bufs now
- DEBUG_OUTF(XFADE_FILE, (s, "SetXFadeEndTime Pos(0), flushing formatt%lut%lun", ulTimestamp, (UINT32)GetMSPerBlock()));
- SetupForNextTimeRange();
- }
- }
- }
- void
- CRaFormat::DiscardTillEndOfCrossFade(UINT32 ulTimestamp)
- {
- /*
- * The ulTimestamp can be in one of these 5 positions.
- * We start from 0 and go to 4 looking for some data that's
- * greater than the ulTimestamp time.
- *
- * [DDD][III] {_,_,_,_,_,_,_,}
- * ^ ^ ^ ^ ^
- * | | | | |
- * 0 1 2 3 4
- *
- */
- BOOL bDone = FALSE;
- ulTimestamp = UnAdjustTimestamp(ulTimestamp, m_lTimeOffset);
- // cannot equal NO_TIME_SET so we bump it up one
- if (ulTimestamp == NO_TIME_SET)
- {
- ulTimestamp += 1;
- }
- m_ulForceDiscardUntilTime = ulTimestamp;
- // start looking to see if it's #0 or #1
- if (!m_IBufs.m_DBlockTimeRange.IsEmpty())
- {
- if (IsTimeGreater(m_IBufs.m_DBlockTimeRange.m_ulStart, ulTimestamp))
- {
- DEBUG_OUTF(DISCARDUNTIL_FILE, (s, "DiscardUntil Pos(0),t%lut%lun", ulTimestamp, (UINT32)GetMSPerBlock()));
- // time is in past and we're done, reset state variables
- m_ulForceDiscardUntilTime = NO_TIME_SET;
- bDone = TRUE;
- }
- else if (m_IBufs.m_DBlockTimeRange.TimeInRange(ulTimestamp))
- {
- DEBUG_OUTF(DISCARDUNTIL_FILE, (s, "DiscardUntil Pos(1),t%lut%lun", ulTimestamp, (UINT32)GetMSPerBlock()));
- bDone = TRUE;
- }
- else
- {
- DEBUG_OUTF(DISCARDUNTIL_FILE, (s, "FlushDBlockt%lut%lut%lun", ulTimestamp, (UINT32)GetMSPerBlock(), m_IBufs.m_DBlockTimeRange.m_ulStart));
- m_IBufs.FlushDBlock();
- }
- }
-
- // see if it's at #2
- if (!bDone)
- {
- // fill the IBlock if we can
- if (!m_IBufs.IsISuperBlockFilled())
- {
- m_pPacketFeeder->FillISuperBlock();
- }
-
- if (!m_IBufs.m_IBlockTimeRange.IsEmpty())
- {
- if (IsTimeGreater(m_IBufs.m_IBlockTimeRange.m_ulStart, ulTimestamp))
- {
- DEBUG_OUTF(DISCARDUNTIL_FILE, (s, "DiscardUntil Pos(0),t%lut%lun", ulTimestamp, (UINT32)GetMSPerBlock()));
- // time is in past and we're done, reset state variables
- m_ulForceDiscardUntilTime = NO_TIME_SET;
- bDone = TRUE;
- }
- else if (m_IBufs.m_IBlockTimeRange.TimeInRange(ulTimestamp))
- {
- bDone = TRUE;
- DEBUG_OUTF(DISCARDUNTIL_FILE, (s, "DiscardUntil Pos(2),t%lut%lun", ulTimestamp, (UINT32)GetMSPerBlock()));
- }
- else
- {
- DEBUG_OUTF(DISCARDUNTIL_FILE, (s, "FlushIBlockt%lut%lut%lun", ulTimestamp, (UINT32)GetMSPerBlock(), m_IBufs.m_IBlockTimeRange.m_ulStart));
- m_IBufs.FlushIBlock();
- }
- }
- }
- bDone = m_pPacketFeeder->DiscardTillEndOfCrossFade(ulTimestamp, bDone);
- // if still not done, it's at #4, else we found it before #4
- if (!bDone)
- {
- m_ulForceDiscardUntilTime = NO_TIME_SET;
- }
- }
- HX_RESULT
- CRaFormat::GetNextAudioDataTime(UINT32& ulStart, UINT32& ulEnd)
- {
- UINT32 ulIterationCounter = 0;
- HX_RESULT theError = HXR_OK;
- BOOL bSuccess = FALSE;
-
- ulStart = ulEnd = 0;
- // move any data from the time range queue into the IBufs
- m_pPacketFeeder->FillISuperBlock();
-
- if (m_bEndOfPackets)
- {
- if (!m_IBufs.DataAvailable(AUDIO_END_OF_PACKETS))
- {
- // this is an "emergency" state so do this even
- // if the IBlock isn't quite full
- m_IBufs.DeInterleaveData();
- }
- }
- do
- {
- // move any data from the time range queue into the IBufs
- m_pPacketFeeder->FillISuperBlock();
- // Here we always want to know the full time range of available
- // time so we always ask for the crossfade time
- if (m_IBufs.DataAvailable(AUDIO_CROSSFADE))
- {
- if (m_ulForceDiscardUntilTime != NO_TIME_SET)
- {
- // this will be the actual start time of
- // the data returned from GetAudioData
- ulStart = m_ulForceDiscardUntilTime;
- DEBUG_OUTF(TIME_FILE, (s, "Force Discard Time Reportedt%lut%lun",
- ulStart, (UINT32)GetMSPerBlock()));
- }
- else
- {
- ulStart = m_IBufs.m_DBlockTimeRange.m_ulStart;
-
- // we may have data before the track start time but we will
- // not return audio data prior to the track start time
- if (m_bForceStartTrackTime && IsTimeLess(ulStart, m_ulTrackStartTime))
- {
- ulStart = m_ulTrackStartTime;
- }
- DEBUG_OUTF(TIME_FILE, (s, "DBlock start Time Reportedt%lut%lun",
- ulStart, (UINT32)GetMSPerBlock()));
- HX_ASSERT(ulStart != NO_TIME_SET);
- }
- ulEnd = ulStart + (UINT32)GetMSPerBlock();
- if (m_bForceEndTrackTime && ulEnd > m_ulTrackEndTime)
- {
- ulEnd = m_ulTrackEndTime;
- HX_ASSERT(ulEnd >= ulStart);
- }
- ulStart = AdjustTimestamp(ulStart, m_lTimeOffset);
- ulEnd = AdjustTimestamp(ulEnd, m_lTimeOffset);
- bSuccess = TRUE;
- break;
- }
- else
- {
- // if there is a current time range, ask it if it's
- // ended. We assume it's not ended.
- BOOL bTimeRangeEnded = m_pPacketFeeder->IsCurrentTimeRangeEnded();
- BOOL bDataInTimeRange = !m_pPacketFeeder->IsCurrentTimeRangeEmpty();
- // If the D superblock is empty and there's more data to decode
- // we give it a try to move the data into the D superblock to
- // decode it.
- if (m_IBufs.IsDSuperBlockEmpty() &&
- (!m_IBufs.IsISuperBlockEmpty() || bDataInTimeRange))
- {
- if (m_IBufs.IsISuperBlockFilled())
- {
- m_IBufs.DeInterleaveData();
- }
- // if we don't have any data in the De-interleaved superblock
- // and we failed to fill the Interleaved superblock, we
- // must be out of data and we should break out of the while loop
- if (m_IBufs.IsDSuperBlockEmpty() &&
- (!m_pPacketFeeder->FillISuperBlock()))
- {
- DEBUG_OUTF(DOAUDIO_FILE, (s, "GetNextAudioDataTimet%dt%dt%dt%dt%lun",
- m_IBufs.IsDSuperBlockEmpty(), m_IBufs.IsISuperBlockEmpty(), m_IBufs.IsISuperBlockFilled(), bTimeRangeEnded, (UINT32)GetMSPerBlock()));
- break;
- }
- }
- else
- {
- // if we get here, there's no in the IBuf or the
- // current time range.
- HX_ASSERT(!bDataInTimeRange);
- if (bTimeRangeEnded)
- {
- // the Time range has ended and the data from it is
- // gone from the IBufs so setup the next time range
- // now
- SetupForNextTimeRange();
- }
- else
- {
- DEBUG_OUTF(DOAUDIO_FILE, (s, "GetNextAudioDataTimet%dt%dt%dt%dt%lun",
- m_IBufs.IsDSuperBlockEmpty(), m_IBufs.IsISuperBlockEmpty(), m_IBufs.IsISuperBlockFilled(), bTimeRangeEnded, (UINT32)GetMSPerBlock()));
- break;
- }
- }
- }
-
- ulIterationCounter++;
- } while (ulIterationCounter < MAX_AUDIO_DATA_ATTEMPTS);
- if (bSuccess)
- {
- return HXR_OK;
- }
- else
- {
- return HXR_NO_DATA;
- }
- }
- UINT32
- CRaFormat::GetCurrentTimeRangeEnd()
- {
- UINT32 ulRet = m_pPacketFeeder->GetCurrentTimeRangeEnd();
- if (ulRet == NO_TIME_SET)
- {
- if (!m_IBufs.m_IBlockTimeRange.IsEmpty())
- {
- // it will be in the IBufs
- ulRet = m_IBufs.m_IBlockTimeRange.m_ulEnd;
- }
- else
- {
- ulRet = m_IBufs.m_DBlockTimeRange.m_ulEnd;
- }
- }
- DEBUG_OUTF(TREND_FILE, (s, "%lut%lun", (UINT32)GetMSPerBlock(), ulRet));
- ulRet = AdjustTimestamp(ulRet, m_lTimeOffset);
- return ulRet;
- }
- void CRaFormat::ThrowUpgrade(const char* pszStr)
- {
- if (m_pCommonClassFactory && pszStr)
- {
- IHXBuffer* pBuffer = NULL;
- m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**) &pBuffer);
- if (pBuffer)
- {
- pBuffer->Set((BYTE*) pszStr, strlen(pszStr) + 1);
- if (m_pUpgradeCollection)
- {
- m_pUpgradeCollection->Add(eUT_Required, pBuffer, 0, 0);
- }
- }
- HX_RELEASE(pBuffer);
- }
- }
- HX_RESULT
- CRaFormat::OnSeek (UINT32 ulOldTime, UINT32 ulNewTime)
- {
- m_IBufs.OnSeek();
- m_bFirstPacket = TRUE;
- m_bEndOfPackets = FALSE;
- m_ulCodecDelay = 0;
- m_fCodecDelay = 0.0;
- m_bPCMStreamStart = TRUE;
-
- SetupForNextTimeRange();
- m_pPacketFeeder->Reset();
- return HXR_OK;
- }
- BOOL
- CRaFormat::IsStreamDone()
- {
- if( !m_pPacketFeeder )
- {
- return TRUE;
- }
- return ((!m_pPacketFeeder->IsActive()) && m_IBufs.IsStreamDone());
- }
- void
- CRaFormat::SetupForNextTimeRange()
- {
- m_pPacketFeeder->SetupForNextTimeRange();
- if (m_pCodec != NULL)
- {
- UINT32 ulOutSize = m_ulAudioBufSize;
- IHXBuffer * pBuffer = NULL;
- m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**) &pBuffer);
- if( pBuffer )
- {
- if( pBuffer->GetSize() != m_ulAudioBufSize )
- {
- // Yikes! This can fail if heap is low: no check!
- pBuffer->SetSize( ulOutSize );
- }
- m_pCodec->Flush( pBuffer->GetBuffer(), &ulOutSize );
- HX_RELEASE( pBuffer );
- }
- }
- m_ulCodecDelay = 0;
- m_fCodecDelay = 0.0;
- m_bPCMStreamStart = TRUE;
- m_ulCrossFadeEndTime = NO_TIME_SET;
- m_ulForceDiscardUntilTime = NO_TIME_SET;
- m_IBufs.SwitchOff();
- }
- void
- CRaFormat::OnEndofPackets(void)
- {
- if( !m_pPacketFeeder )
- {
- m_bEndOfPackets = TRUE;
- return;
- }
- m_pPacketFeeder->OnEndOfPackets();
- m_bEndOfPackets = TRUE;
-
- // if we've already given all of the packets to the ibufs,
- // we can tell them we are done now, otherwise wait till
- // we do finish the packets
- if (!m_pPacketFeeder->IsActive())
- {
- m_IBufs.OnEndofPackets();
- }
- }
- HX_RESULT
- CRaFormat::UpdatePacketTimeOffset(INT32 lTimeOffset)
- {
- m_lTimeOffset -= lTimeOffset;
- return HXR_OK;
- }
- HX_RESULT
- CRaFormat::UpdatePlayTimes(IHXValues* pProps)
- {
- UINT32 ulStart = 0;
- UINT32 ulEnd = 0;
- if (HXR_OK == pProps->GetPropertyULONG32("Start", ulStart))
- {
- m_ulTrackStartTime = ulStart;
- m_bForceStartTrackTime = TRUE;
- }
- if (HXR_OK == pProps->GetPropertyULONG32("End", ulEnd))
- {
- m_ulTrackEndTime = ulEnd;
- m_bForceEndTrackTime = TRUE;
- }
- return HXR_OK;
- }
- // statistics
- #if defined(HELIX_FEATURE_STATS)
- HX_RESULT CRaFormat::UpdateStatistics (IHXRegistry* pRegistry, UINT32 ulRegistryID,
- UINT32& ulCodecRegID, UINT32& ulCodecTextRegID,
- UINT32& ulCodec4CCRegID, UINT32& ulRateRegID,
- UINT32& ulChannelsRegID, UINT32& ulSurroundRegID)
- {
- char szRegistryEntry[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
- IHXBuffer* pszRegistryName = NULL;
- IHXBuffer* pValue = NULL;
- CStreamParam* pParam;
- HX_RESULT retVal = HXR_OK;
- if (!pRegistry || !ulRegistryID || m_pCodec == NULL)
- {
- return HXR_FAILED;
- }
- pParam = &m_StreamParam;
- if (!ulCodecRegID)
- {
- // Get the current registry key name
- if (!ulCodecRegID && (HXR_OK == pRegistry->GetPropName(ulRegistryID, pszRegistryName)))
- {
- SafeSprintf (szRegistryEntry, MAX_DISPLAY_NAME, "%s.Codec", pszRegistryName->GetBuffer());
- if (pParam->codecID)
- {
- m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
- (void**) &pValue);
- //
- UINT16 uPropSize = 0;
- void* pProp = m_pCodec->GetFlavorProperty(m_StreamParam.uFlavorIndex, FLV_PROP_NAME, &uPropSize);
- if (uPropSize)
- {
- pValue->Set((const UCHAR*)pProp, uPropSize);
- ulCodecRegID = pRegistry->AddStr(szRegistryEntry, pValue);
- }
- pValue->Release();
- }
- pszRegistryName->Release();
- pszRegistryName = NULL;
- }
- }
- else
- {
- if (pParam->codecID)
- {
- m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
- (void**) &pValue);
- UINT16 uPropSize = 0;
- void* pProp = m_pCodec->GetFlavorProperty(m_StreamParam.uFlavorIndex, FLV_PROP_NAME, &uPropSize);
- if (uPropSize)
- {
- pValue->Set((const UCHAR*)pProp, uPropSize);
- pRegistry->SetStrById(ulCodecRegID, pValue);
- }
- pValue->Release();
- }
- }
- if (!ulCodecTextRegID)
- {
- // Get the current registry key name
- if (!ulCodecTextRegID && (HXR_OK == pRegistry->GetPropName(ulRegistryID, pszRegistryName)))
- {
- SafeSprintf (szRegistryEntry, MAX_DISPLAY_NAME, "%s.CodecText", pszRegistryName->GetBuffer());
- if (pParam->codecID)
- {
- m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
- (void**) &pValue);
- //
- UINT16 uPropSize = 0;
- void* pProp = m_pCodec->GetFlavorProperty(m_StreamParam.uFlavorIndex, FLV_PROP_STATUS_TEXT, &uPropSize);
- if (uPropSize)
- {
- pValue->Set((const UCHAR*)pProp, uPropSize);
- ulCodecTextRegID = pRegistry->AddStr(szRegistryEntry, pValue);
- }
- pValue->Release();
- }
- pszRegistryName->Release();
- pszRegistryName = NULL;
- }
- }
- else
- {
- if (pParam->codecID)
- {
- m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
- (void**) &pValue);
- //
- UINT16 uPropSize = 0;
- void* pProp = m_pCodec->GetFlavorProperty(m_StreamParam.uFlavorIndex, FLV_PROP_STATUS_TEXT, &uPropSize);
- if (uPropSize)
- {
- pValue->Set((const UCHAR*)pProp, uPropSize);
- pRegistry->SetStrById(ulCodecTextRegID, pValue);
- }
- pValue->Release();
- }
- }
- if (!ulCodec4CCRegID)
- {
- // Get the current registry key name
- if (!ulCodec4CCRegID && (HXR_OK == pRegistry->GetPropName(ulRegistryID, pszRegistryName)))
- {
- SafeSprintf (szRegistryEntry, MAX_DISPLAY_NAME, "%s.CodecFourCC", pszRegistryName->GetBuffer());
- if (pParam->codecID)
- {
- m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
- (void**) &pValue);
- pValue->Set((const UCHAR*)pParam->codecID, strlen(pParam->codecID)+1);
- ulCodec4CCRegID = pRegistry->AddStr(szRegistryEntry, pValue);
- pValue->Release();
- }
- pszRegistryName->Release();
- pszRegistryName = NULL;
- }
- }
- else
- {
- if (pParam->codecID)
- {
- m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
- (void**) &pValue);
- pValue->Set((const UCHAR*)pParam->codecID, strlen(pParam->codecID)+1);
- pRegistry->SetStrById(ulCodec4CCRegID, pValue);
- pValue->Release();
- }
- }
- if (!ulRateRegID || !ulChannelsRegID)
- {
- if (!ulRateRegID && (HXR_OK == pRegistry->GetPropName (ulRegistryID, pszRegistryName)))
- {
- SafeSprintf (szRegistryEntry, MAX_DISPLAY_NAME, "%s.Rate", pszRegistryName->GetBuffer());
- ulRateRegID = pRegistry->AddInt (szRegistryEntry, m_IBufs.RateInBytesPerSec());
- pszRegistryName->Release();
- pszRegistryName = NULL;
- }
- if (!ulChannelsRegID && (HXR_OK == pRegistry->GetPropName (ulRegistryID, pszRegistryName)))
- {
- SafeSprintf (szRegistryEntry, MAX_DISPLAY_NAME, "%s.Channels", pszRegistryName->GetBuffer());
- ulChannelsRegID = pRegistry->AddInt (szRegistryEntry, pParam->uChannels);
- pszRegistryName->Release();
- pszRegistryName = NULL;
- }
- }
- else
- {
- pRegistry->SetIntById(ulRateRegID, m_IBufs.RateInBytesPerSec());
- pRegistry->SetIntById(ulChannelsRegID, pParam->uChannels);
- }
- if (pParam->ulUserData)
- {
- // Get the current registry key name
- if ((!ulSurroundRegID) &&
- (HXR_OK == pRegistry->GetPropName(ulRegistryID, pszRegistryName)))
- {
- if ((pParam->ulUserData & USER_DATA_REALAUDIO_SURROUND) != 0)
- {
- SafeSprintf (szRegistryEntry, MAX_DISPLAY_NAME, "%s.Surround", pszRegistryName->GetBuffer());
-
- retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
- (void**) &pValue);
-
- if (SUCCEEDED(retVal))
- {
- retVal = pValue->Set((UINT8*) "TRUE", sizeof("TRUE"));
- }
- if (SUCCEEDED(retVal))
- {
- if (ulSurroundRegID)
- {
- pRegistry->SetStrById(ulSurroundRegID, pValue);
- }
- else
- {
- ulSurroundRegID = pRegistry->AddStr(szRegistryEntry, pValue);
- }
- }
- HX_RELEASE(pValue);
- }
-
- HX_RELEASE(pszRegistryName);
- }
- }
- return retVal;
- }
- #endif // HELIX_FEATURE_STATS
- UINT32
- CRaFormat::ConvertMsToBytes(UINT32 ulMs)
- {
- /*
- * ms # Channels * Sample size in Bits * # samples per second
- * ____ * _________________________________________________________
- *
- * 1000 ms per second 8 bits per byte
- */
-
- return (UINT32)(((double)(ulMs * m_StreamParam.uChannels *
- m_StreamParam.uSampleSize * m_StreamParam.ulSampleRate) / 8000.0) + .5);
- }
- double
- CRaFormat::ConvertBytesToMs(UINT32 ulBytes)
- {
- return (ulBytes * 8000.0) /
- (m_StreamParam.uChannels *
- m_StreamParam.uSampleSize *
- m_StreamParam.ulSampleRate);
- }
- BOOL
- CRaFormat::ClipAudioBuffer(HXAudioData* pAudioData,
- UINT32& ulActualTime,
- UINT32 ulAudioStreamTime,
- BOOL bFromStart)
- {
- BOOL bResult = TRUE;
- UINT32 ulDuration = 0;
- UINT32 ulSize = 0;
- INT32 lExtraInMs = 0;
- UINT32 ulExtraInBytes = 0;
- IHXBuffer* pBuffer = NULL;
- ulSize = (pAudioData->pData)->GetSize();
- // caculate the worth of this data in ms
- ulDuration = (UINT32) ConvertBytesToMs(ulSize);
-
- // trim off any extra bytes
- if (bFromStart)
- {
- if (IsTimeGreater(pAudioData->ulAudioTime + ulDuration, ulAudioStreamTime))
- {
- lExtraInMs = ulAudioStreamTime - pAudioData->ulAudioTime;
- }
- }
- else
- {
- if (IsTimeLess(pAudioData->ulAudioTime, ulAudioStreamTime))
- {
- lExtraInMs = pAudioData->ulAudioTime + ulDuration - ulAudioStreamTime;
- }
- }
- if (lExtraInMs > 0)
- {
- bResult = ClipAudioData(*pAudioData,
- ulActualTime,
- (ULONG32) lExtraInMs,
- bFromStart);
- }
- else if (lExtraInMs < 0)
- {
- // Nothing to clip
- bResult = TRUE;
- }
- return bResult;
- }
- void
- CRaFormat::OverrideFactory(IHXCommonClassFactory* pCommonClassFactory)
- {
- // Actually, we no longer override, we just add this one.
- m_pCachingClassFactory = pCommonClassFactory;
- m_pCachingClassFactory->AddRef();
- }
- BOOL
- CRaFormat::GetDropBlock(UINT32 ulAudioTime)
- {
- BOOL bRetVal = FALSE;
- if (m_bForceStartTrackTime && IsTimeLess(ulAudioTime, m_ulTrackStartTime) ||
- m_ulForceDiscardUntilTime != NO_TIME_SET && IsTimeLess(ulAudioTime, m_ulForceDiscardUntilTime))
- {
- // since the crossfade end time is going to happen in the middle of a stream
- // it has "precidence" over the track start time here
- UINT32 ulStartTimeToUse = (m_ulForceDiscardUntilTime != NO_TIME_SET)?(m_ulForceDiscardUntilTime):
- (m_ulTrackStartTime);
- bRetVal = IsTimeLessOrEqual(ulAudioTime + (UINT32)GetMSPerBlock(), ulStartTimeToUse);
- }
-
- //XXXJEFFA add code for droping entire block clipping at end
- return bRetVal;
- }
- void CRaFormat::SpliceAudioData(HXAudioData &audioData,
- UINT32 &ulActualTimestamp,
- UINT32 ulSpliceToActualTime,
- UINT32 ulSpliceToStreamTime)
- {
- LONG32 lActualTimeDiff = 0;
- ULONG32 ulAbsActualTimeDiff = 0;
- audioData.uAudioStreamType = TIMED_AUDIO;
- ulActualTimestamp = audioData.ulAudioTime;
- if (ulSpliceToActualTime != NO_TIME_SET)
- {
- lActualTimeDiff = ulActualTimestamp - ulSpliceToActualTime;
- ulAbsActualTimeDiff = (ULONG32) lActualTimeDiff;
- if (lActualTimeDiff < 0)
- {
- ulAbsActualTimeDiff = (ULONG32) (-lActualTimeDiff);
- }
- if (ulAbsActualTimeDiff <= m_ulMaxBlockGap)
- {
- audioData.ulAudioTime = ulSpliceToStreamTime;
- if (!m_bPCMStreamStart)
- {
- audioData.uAudioStreamType = STREAMING_AUDIO;
- }
- }
- else
- {
- audioData.ulAudioTime = ulSpliceToStreamTime + lActualTimeDiff;
- }
- }
- }
- BOOL
- CRaFormat::AdjustAudioData(HXAudioData& audioData,
- UINT32& ulActualTimestamp,
- UINT32 ulTrackEndTime)
- {
- BOOL bResult = TRUE;
- UINT32 ulDuration = 0;
- UINT32 ulSize = 0;
- INT32 lExtraInMs = 0;
- IHXBuffer* pBuffer = NULL;
- if (m_bForceStartTrackTime ||
- m_bForceEndTrackTime ||
- (m_ulForceDiscardUntilTime != NO_TIME_SET) ||
- (m_ulCrossFadeEndTime != NO_TIME_SET) ||
- (ulTrackEndTime != NO_TIME_SET))
- {
- ulSize = (audioData.pData)->GetSize();
- // caculate the worth of this data in ms
- ulDuration = (UINT32) ConvertBytesToMs(ulSize);
-
- // Trim based on start time
- if (m_bForceStartTrackTime || (m_ulForceDiscardUntilTime != NO_TIME_SET))
- {
- // since the crossfade end time is going to happen in the middle of a stream
- // it has "precidence" over the track start time here
- UINT32 ulStartTimeToUse =
- (m_ulForceDiscardUntilTime != NO_TIME_SET) ? m_ulForceDiscardUntilTime :
- m_ulTrackStartTime;
- lExtraInMs = ulStartTimeToUse - ulActualTimestamp;
- bResult = ClipAndAdjust(lExtraInMs, audioData, ulActualTimestamp, TRUE, ulDuration, ulSize);
- }
- // Trim based on track end time
- if (bResult &&
- m_bForceEndTrackTime)
- {
- lExtraInMs = ulActualTimestamp + ulDuration - m_ulTrackEndTime;
- bResult = ClipAndAdjust(lExtraInMs, audioData, ulActualTimestamp, FALSE, ulDuration, ulSize);
- if (lExtraInMs > 0)
- {
- // if we are ending the stream here because this block goes over the forced end time
- // we want to flush the IBuf etc. cause we are done.
- SetupForNextTimeRange();
- }
- }
- // Trim based on X-fade end time
- if (bResult &&
- (m_ulCrossFadeEndTime != NO_TIME_SET))
- {
- lExtraInMs = ulActualTimestamp + ulDuration - m_ulCrossFadeEndTime;
- bResult = ClipAndAdjust(lExtraInMs, audioData, ulActualTimestamp, FALSE, ulDuration, ulSize);
- if (lExtraInMs > 0)
- {
- SetupForNextTimeRange();
- }
- }
- // Trim based on forced end time
- if (bResult &&
- (ulTrackEndTime != NO_TIME_SET))
- {
- lExtraInMs = ulActualTimestamp + ulDuration - ulTrackEndTime;
- bResult = ClipAndAdjust(lExtraInMs, audioData, ulActualTimestamp, FALSE, ulDuration, ulSize);
- }
- }
- audioData.ulAudioTime = AdjustTimestamp(audioData.ulAudioTime, m_lTimeOffset);
- ulActualTimestamp = AdjustTimestamp(ulActualTimestamp, m_lTimeOffset);
- return bResult;
- }
- BOOL
- CRaFormat::ClipAudioData(HXAudioData &audioData,
- UINT32 &ulActualTimestamp,
- UINT32 ulDurationToClip,
- BOOL bFromFront)
- {
- UINT32 ulExtraInBytes;
- UINT32 ulSize;
- BOOL bResult = FALSE; // completely elimninated = FALSE
- // Get data size
- ulSize = audioData.pData->GetSize();
- // convert to bytes
- ulExtraInBytes = ConvertMsToBytes(ulDurationToClip);
-
- // align in sample boundary
- ulExtraInBytes -= (ulExtraInBytes % (m_StreamParam.uSampleSize *
- m_StreamParam.uChannels / 8));
-
- if (ulExtraInBytes < ulSize)
- {
- IHXBuffer* pBuffer = NULL;
- m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
- (void**) &pBuffer);
- if (pBuffer)
- {
- if (bFromFront)
- {
- if (SUCCEEDED(pBuffer->Set(audioData.pData->GetBuffer() +
- ulExtraInBytes,
- ulSize - ulExtraInBytes)))
- {
- audioData.pData->Release();
- audioData.pData = pBuffer;
- pBuffer = NULL;
- audioData.ulAudioTime += ulDurationToClip;
- ulActualTimestamp += ulDurationToClip;
- bResult = TRUE;
- }
- }
- else
- {
- if (SUCCEEDED(pBuffer->Set(audioData.pData->GetBuffer(),
- ulSize - ulExtraInBytes)))
- {
- audioData.pData->Release();
- audioData.pData = pBuffer;
- pBuffer = NULL;
- bResult = TRUE;
- }
- }
- HX_RELEASE(pBuffer);
- }
- }
-
- return bResult;
- }
- HX_RESULT
- CRaFormat::LoadDecoderAndInitDeInterleaver()
- {
- HX_RESULT theError = HXR_OK;
- // initialize codecs
- theError = InitDecoder (m_StreamParam, &m_pCodec);
- if (theError == HXR_OK)
- {
- // Get SAMPLES_IN from codec and give it to the IBufs
- UINT16 uPropSize = 0;
- void* pProp =
- m_pCodec->GetFlavorProperty(m_StreamParam.uFlavorIndex,
- FLV_PROP_SAMPLES_IN, &uPropSize);
- if (uPropSize != 0)
- {
- HX_ASSERT(uPropSize == sizeof(UINT32));
- m_IBufs.SetSamplesIn(*(UINT32*)pProp);
- }
- }
- return theError;
- }
- BOOL CRaFormat::ClipAndAdjust(INT32 lExtraInMs,
- HXAudioData& audioData,
- UINT32& ulActualTimestamp,
- BOOL bFromFront,
- UINT32& ulDuration,
- UINT32& ulSize)
- {
- BOOL bResult = TRUE;
- if (lExtraInMs > 0)
- {
- bResult = ClipAudioData(audioData,
- ulActualTimestamp,
- (ULONG32) lExtraInMs,
- bFromFront);
- if (bResult)
- {
- ulDuration -= lExtraInMs;
- ulSize = audioData.pData->GetSize();
- }
- else
- {
- ulDuration = 0;
- ulSize = 0;
- }
- }
- return bResult;
- }