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

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

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

#include "netbyte.h"
#include "hxtypes.h"
#include "hxresult.h"
#include "hxcom.h"
#include "hxcomm.h"
#include "hxbuffer.h"
#include "hxausvc.h"
#include "ihxpckts.h"
#include "hxcodec.h"
#include "raparser.h"
#include "hxengin.h"

#include "cinterl.h"
#include "codec.h"
#include "hxcore.h"
#include "hxupgrd.h"
#include "hxslist.h"
#include "raformat.h"
#include "rmfftype.h"

#include "hxassert.h"
#include "errdbg.h"
#include "hxtick.h"

#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE		
static const char HX_THIS_FILE[] = __FILE__;
#endif

#include "hxstat.h"
#define LOG_INFO 0
// Add this back and make it work if you turn on LOG_VIDEO_INFO

//#define RAIBUFS_LOGING_ON
#ifdef RAIBUFS_LOGING_ON
#define LOG_PATH	    "D:\\Temp\\"
#define SPLICE_FILE	    LOG_PATH##"splice.txt"
#define XFADEREADY_FILE	    LOG_PATH##"xfadeready.txt"
#define TIMERANGE_FILE	    LOG_PATH##"timerange.txt"
#define GETBLOCK_FILE	    LOG_PATH##"getblock.txt"
#else
#define SPLICE_FILE	    0
#define XFADEREADY_FILE	    0
#define TIMERANGE_FILE	    0
#define GETBLOCK_FILE	    0
#endif

// this value is the approximate maximum overlap of superblocks caused by math
// error when calculating block times.  If the error is .5 ms and the superblock
// had 20 blocks it could be as much as 10 ms off.  Currently the max superblock
// size is 14 blocks so we have some room to grow.
#define SUPERBLOCK_OVERLAP_FUDGE    10
#define SUPERBLOCK_VALUE_FACTOR	    2

// Constructors & Destructors
CInterleaveBufs::CInterleaveBufs (CStreamParam& param, UINT16 uStreamNumber)
    : m_Param(param)
    , m_uStreamNumber(uStreamNumber)
    , m_Interleaver(NULL)
    , m_ulSuperBlockSize(0)
    , m_fmsPerBlock(0.0)
    , m_pIDataBuf(NULL)
    , m_pDDataBuf(NULL)
    , m_pIPresent(NULL)
    , m_pDPresent(NULL)
    , m_pIActualTimestamps(NULL)
    , m_pDActualTimestamps(NULL)
    , m_bISuperBlockEmpty(TRUE)
    , m_bISuperBlockDone(FALSE)
    , m_uNumIBlocks(0)
    , m_ulFirstSequenceNum(0)
    , m_fActualTimestamp(0.0)
    , m_bFirstPacketReceived(FALSE)
    , m_bDSuperBlockEmpty(TRUE)
    , m_uBlockToDecode(0)
    , m_bEndOfPackets(FALSE)
    , m_fMsPerByte((double) 0.)
    , m_bTimeStampsInTenths(FALSE)
    , m_ulSamplesIn(0)
    , m_fLastDecodedTime(0.0)
    , m_bLastDecodedTimeSet(FALSE)
    , m_bDeinterleaveInPlace(FALSE)
    , m_bReliableSamplesIn(FALSE)
    , m_bIsVBRS(FALSE)
    , m_ulVBRSMaxBufSize(INITIAL_VBR_MAXBUFSIZE)
    , m_ulVBRSDBufBytes(0)
{
    DEBUG_OUTF(SPLICE_FILE, (s, "Start Stream\t%p\t*******\n", this));
}

CInterleaveBufs::~CInterleaveBufs()
{
    DeallocIBufs();
    HX_DELETE(m_Interleaver);
}

// de-interleaving
HX_RESULT 
CInterleaveBufs::InitDeinterleaver (void)
{
    HX_RESULT	theError = HXR_OK;

    if (strcmp(m_Param.interleaverID, RA_NO_INTERLEAVER) != 0)
    {
	m_Interleaver = CInterleave::Construct(m_Param.interleaverID, &theError, (void*) &m_Param.uFlavorIndex);
	if ((m_Interleaver == NULL) && (SUCCEEDED(theError)))
	{
	    theError = HXR_OUTOFMEMORY;
	}
        else if (m_Interleaver)
        {
            ULONG32 bitProperties = m_Interleaver->GetProperties();
            if( bitProperties && INTERPROP_INPLACE )
            {
                m_bDeinterleaveInPlace = TRUE;
            }
        }
    }

#if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC)
    if (m_Param.interleaverID &&
        (!strcmp(m_Param.interleaverID, RA_INTERLEAVER_VBRS_ID) ||
         !strcmp(m_Param.interleaverID, RA_INTERLEAVER_VBRF_ID)))
    {
        m_bIsVBRS = TRUE;
    }
#endif /* #if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC) */

    if (theError == HXR_OK)
    {
	if (m_Interleaver) 
	{
	    theError = m_Interleaver->Init(&m_Param.uCodecFrameSize,
					   &m_Param.uInterleaveBlockSize,
					   &m_Param.uInterleaveFactor,
					   m_Param.interleavePattern);
	}
	
	m_ulSuperBlockSize = m_Param.uInterleaveBlockSize * m_Param.uInterleaveFactor;

	if (theError == HXR_OK)
	{
	    m_fMsPerByte = (double) (1./(m_Param.uChannels * 
				(m_Param.uSampleSize/8) * 
				(double) m_Param.ulSampleRate/1000.));

	    // Compute the less accurate msPerBlock - but more reliable
	    if (m_Param.ulBytesPerMin != 0.0)
	    {
		m_fmsPerBlock = 
		    ((double)(m_Param.uInterleaveBlockSize * 60000)) / m_Param.ulBytesPerMin;
	    }

	    if (m_ulSamplesIn != 0)
	    {
		/* Compute more accurate msPerBlock - 
		   however some codecs report samplesIn incorrectly 
		   (by an integer factor).  Thus, apply the more accurate
		   computation only if it is in the ballpark of the
		   less accurate one to filter out any rogue reports. */
		double fRatio = 1.0;
		double fmsPerBlock = ((double) (1000 * m_ulSamplesIn)) /
				     ((double) (m_Param.ulSampleRate * m_Param.uChannels));

                if (m_bReliableSamplesIn)
                {
                    // If the m_bReliableSamplesIn flag is set to TRUE,
                    // then this indicates that the fmsPerBlock value computed
                    // from the codec's SamplesIn property should be
                    // used in computing the fmsPerBlock UNCONDITIONALLY
                    m_fmsPerBlock = fmsPerBlock;
                }
                else
                {
		    if (m_fmsPerBlock != 0.0)
		    {
		        fRatio = fmsPerBlock / m_fmsPerBlock;
		    }

		    if ((fRatio > 0.94) && (fRatio < 1.06))
		    {
		        m_fmsPerBlock = fmsPerBlock;
		    }
                }
	    }
	}

	HX_ASSERT(m_fmsPerBlock != 0.0);
    }

    return theError;
}

HX_RESULT
CInterleaveBufs::AllocIBufs (void)
{
    DeallocIBufs();

    UINT32 ulAllocSize = m_ulSuperBlockSize;
#if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC)
    if (m_bIsVBRS)
    {
        ulAllocSize = m_ulVBRSMaxBufSize;
    }
#endif /* #if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC) */
    m_pIDataBuf = new Byte[ulAllocSize];
    if( m_bDeinterleaveInPlace == TRUE )
    {
       m_pDDataBuf = m_pIDataBuf;
    }
    else
    {
       m_pDDataBuf = new Byte [ulAllocSize];
    }
    m_pIPresent = new UINT32[m_Param.uInterleaveFactor];
    // set the present flags for the interleaved buffer
    memset(m_pIPresent, 0, m_Param.uInterleaveFactor * sizeof(UINT32));

    m_pDPresent = new UINT32[m_Param.uInterleaveFactor];

    m_pIActualTimestamps = new double[m_Param.uInterleaveFactor];
    m_pDActualTimestamps = new double[m_Param.uInterleaveFactor];
    
    if (!m_pIDataBuf || !m_pDDataBuf || 
	!m_pIPresent || !m_pDPresent || 
	!m_pIActualTimestamps || !m_pDActualTimestamps)
    {
	DeallocIBufs();
	return HXR_OUTOFMEMORY;
    }

    return HXR_OK;
}

void
CInterleaveBufs::DeallocIBufs (void)
{
    HX_VECTOR_DELETE(m_pIDataBuf);
    if( m_bDeinterleaveInPlace == FALSE )
    {
       HX_VECTOR_DELETE(m_pDDataBuf);
    }

    HX_VECTOR_DELETE(m_pIPresent);
    HX_VECTOR_DELETE(m_pDPresent);

    HX_VECTOR_DELETE(m_pIActualTimestamps);
    HX_VECTOR_DELETE(m_pDActualTimestamps);
}

HX_RESULT 
CInterleaveBufs::DeInterleaveData()
{
    // if the interleave buffer isn't full, we cannot deinterleave
    if (!m_bISuperBlockDone)
	return HXR_NO_DATA;

    // XXXJEFFA this assert was commented out, why?
    // Why do we need this if statement?  If we aren't
    // paying attention to the state flag, why have it?
    HX_ASSERT (m_bDSuperBlockEmpty);
    m_bDSuperBlockEmpty = TRUE;

    if (m_Interleaver)
    {
	HX_RESULT   theError;
	UINT16	    outSize;

	theError = m_Interleaver->ErrorCorrection2(m_pIDataBuf, 
						   (UINT16) m_ulSuperBlockSize, 
						   m_pDDataBuf, 
						   &outSize, 
						   m_pIPresent, 
						   m_Param.ulGranularity);
	if (theError != HXR_OK)
	{
	   goto cleanup;
	}

#if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC)
        if (m_bIsVBRS)
        {
            m_ulVBRSDBufBytes = outSize;
        }
        else
#endif /* #if defined(HELIX_FEATURE_AUDIO_CODEC_RAAC) */
        {
            HX_ASSERT (outSize == m_ulSuperBlockSize);
        }
    }
    else
    {
	// XXXJEFFA we should just swap pointers here instead
	// of memcpying
	memcpy(m_pDDataBuf, m_pIDataBuf, m_ulSuperBlockSize); /* Flawfinder: ignore */
    }

    /* This should happen ONLY if we have received endofpackets() */
    HX_ASSERT(m_bEndOfPackets || m_uNumIBlocks >= m_Param.uInterleaveFactor);

    // if the number of interleave blocks recieved is less than the interleave
    // factor then we assume we didn't fill in the whole superblock because
    // we were either stopped during playback or the encoding didn't fill
    // up the entire superblock.  We fill in the remaining timestamp vector
    // values for the rest of the blocks in the superblock for book keeping
    // purposes
    if (m_uNumIBlocks < m_Param.uInterleaveFactor)
    {
	/* Fill in the right timestamps for the missing packets */
	for (UINT16 i=m_uNumIBlocks; i < m_Param.uInterleaveFactor; i++)
	{
	    m_pIActualTimestamps[i]   = m_fActualTimestamp;

	    INCREMENT_FLOAT_TS(m_fActualTimestamp, m_fmsPerBlock);
	}
    }

    // XXXJEFFA we could swap pointers here instead of memcpying
    //
    // we've moved the data, now move the present flags and timestamps from the
    // interleave blocks to the de-interleave blocks
    memcpy(m_pDPresent, m_pIPresent, m_Param.uInterleaveFactor * sizeof(UINT32)); /* Flawfinder: ignore */
    memcpy(m_pDActualTimestamps, m_pIActualTimestamps, m_Param.uInterleaveFactor * sizeof(double)); /* Flawfinder: ignore */

    // reset the present flags for the interleaved buffer
    memset(m_pIPresent, 0, m_Param.uInterleaveFactor * sizeof(UINT32));

    // if we go here we have a full deinterleaved super block
    m_bDSuperBlockEmpty = FALSE;

cleanup:

    if( m_bDeinterleaveInPlace == FALSE )
    {
       m_bISuperBlockEmpty = TRUE;
       m_bISuperBlockDone = FALSE;
       m_uNumIBlocks = 0;
       m_uBlockToDecode = 0;
    }

    // fix up the time ranges
    if (!m_bDSuperBlockEmpty)
    {
	double fEndTS = m_pDActualTimestamps[m_Param.uInterleaveFactor - 1];
	INCREMENT_FLOAT_TS(fEndTS, m_fmsPerBlock);
	if (m_DBlockTimeRange.m_ulStart == NO_TIME_SET)
	{
	    if (m_bLastDecodedTimeSet)
	    {
		m_DBlockTimeRange.m_ulStart = (UINT32) m_fLastDecodedTime;
	    }
	    else
	    {
		m_fLastDecodedTime = m_pDActualTimestamps[0];
		m_DBlockTimeRange.m_ulStart = (UINT32) m_fLastDecodedTime;
		m_bLastDecodedTimeSet = TRUE;
	    }
	}
	m_DBlockTimeRange.m_ulEnd = (UINT32)(fEndTS);

	DEBUG_OUTF_IDX(m_uStreamNumber, RA_FLOW_FILE, 
	    (s, "DBufDone: Start=%d, End=%d\n",
	     m_DBlockTimeRange.m_ulStart % MAX_TS_DBG_RANGE,
	     m_DBlockTimeRange.m_ulEnd % MAX_TS_DBG_RANGE));

⌨️ 快捷键说明

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