mpa_frame_header.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 208 行

CPP
208
字号
/*============================================================================*
 *
 * (c) 1995-2002 RealNetworks, Inc. Patents pending. All rights reserved.
 *
 *============================================================================*/
 

#include "mpa_frame_header.h"
#include "hxassert.h"
//#include "debug.h"

#define MPA_VERSION_MASK 0x18
#define MPA_VERSION_SHIFT 3

#define MPA_LAYER_MASK 0x06
#define MPA_LAYER_SHIFT 1

#define MPA_CRC_MASK 0x01

#define MPA_BITRATE_MASK 0xf0
#define MPA_BITRATE_SHIFT 4

#define MPA_SMPLRATE_MASK 0x0c
#define MPA_SMPLRATE_SHIFT 2

#define MPA_PAD_MASK 0x02
#define MPA_PAD_SHIFT 1

#define MPA_CHNLMODE_MASK 0xc0
#define MPA_CHNLMODE_SHIFT 6

#define MPA_CHNLMODEEX_MASK 0x30
#define MPA_CHNLMODEEX_SHIFT 4


static const short k_bitRateTable[][16] = 
{
    // MPEG 1 Layer 1
    { -1, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1},
    // MPEG 1 Layer 2
    { -1, 32, 48, 56, 64,  80,  96,  112, 128, 160, 192, 224, 256, 320, 384, -1},
    // MPEG 1 Layer 3
    { -1, 32, 40, 48, 56,  64,  80,  96,  112, 128, 160, 192, 224, 256, 320, -1},
    // MPEG 2 and 2.5 Layer 1
    { -1, 32, 48, 56, 64,  80,  96,  112, 128, 144, 160, 176, 192, 224, 256, -1},
    // MPEG 2 and 2.5 Layer 2 & 3
    { -1, 8,  16, 24, 32,  40,  48,  56,  64,  80,  96,  112, 128, 144, 160, -1}
};

//
// for finding vertical row from k_bitRateTable to use
// for determining bitrate for given version/layer combo
//
static const signed char k_brIndexTable[4][4] = 
{
    // Reserved, Layer III, Layer II, Layer I
    {  -1      , 4        , 4       , 3 },       // MPEG2.5
    {  -1      , -1       , -1      , -1},       // Reserved
    {  -1      , 4        , 4       , 3 },       // MPEG2
    {  -1      , 2        , 1       , 0 }        // MPEG1
};      
  
//
// sample rates for MPEG1; values for MPEG2 and 2.5 are derived from 
// these using shift table (i.e., we divide by 2 once for MPEG2 and twice
// for MPEG2.5)
//
static const int k_smplRateTable[4] = 
{ 
    44100, 48000, 32000, -1 
};

static const char k_srShiftTable[4] = 
{
 // MPEG2.5 , Reserved, MPEG2, MPEG1
    2       , 0       , 1    , 0
};       


bool MPAFrameHeader::IsSync(const unsigned char* p)
{
    // frame sync = 11 bits all set to 1
    return (0xff == *p && 0xe0 == (*(p+1) & 0xe0) );
}

template<typename T>
inline bool IndexInRange(int i, T& array)
{         
    return (i >= 0 && i < sizeof(array)/sizeof(array[0]));
}

template<typename T>
inline bool IndexInRange( int x, int y, T& array ){
    return (IndexInRange( x, array) && IndexInRange(y,array[0]));
}

bool MPAFrameHeader::Unpack(const unsigned char* p)
{
    if (!IsSync(p))
    {
	return false;
    }

    // version and layer
    m_version = (p[1] & MPA_VERSION_MASK) >> MPA_VERSION_SHIFT;
    m_layer   = (p[1] & MPA_LAYER_MASK)   >> MPA_LAYER_SHIFT;
    if( m_version == MPA_VERSION_RESERVED || m_layer == MPA_LAYER_RESERVED)
    {
        return false;
    }

    // does 16 bit CRC follow this header
    m_hasCRC     = !(p[1] & MPA_CRC_MASK);

    // find bitrate for this frame
    HX_ASSERT( IndexInRange(m_version, m_layer, k_brIndexTable) ); // version and layer are 2 bits (max 3)
    int brVertIndex = k_brIndexTable[m_version][m_layer];
    int brHorIndex = (p[2] & MPA_BITRATE_MASK) >> MPA_BITRATE_SHIFT;
    if(-1 == brVertIndex || -1 == brHorIndex)
    {
        return false;
    }
    HX_ASSERT(IndexInRange( brVertIndex, brHorIndex, k_bitRateTable ) );
    
    // bitrate
    m_bitRate = k_bitRateTable[brVertIndex][brHorIndex];
    if(-1 == m_bitRate)
    {
        return false;
    }
    m_bitRate *= 1000;
    
    // find sample rate for this frame
    TInt sampleRateIndex = (p[2] & MPA_SMPLRATE_MASK) >> MPA_SMPLRATE_SHIFT;
    HX_ASSERT(IndexInRange( sampleRateIndex, k_smplRateTable )); // sampleRateIndex is 2 bits (max 3)
    
    // sample rate
    m_sampleRate = k_smplRateTable[sampleRateIndex];
    if( -1 == m_sampleRate)
    {
        return false;
    }
    
    HX_ASSERT(IndexInRange(m_version, k_srShiftTable)); // version is 2 bits (max 3)
  
    m_sampleRate >>= k_srShiftTable[m_version];
    
    // is this frame padded
    m_pad = (p[2] & MPA_PAD_MASK) >> MPA_PAD_SHIFT;

    // stereo, joint stereo, dual channel, single channel
    m_chnlMode   = (p[3] & MPA_CHNLMODE_MASK) >> MPA_CHNLMODE_SHIFT;

    // joint stereo extension
    m_chnlModeEx = (p[3] & MPA_CHNLMODEEX_MASK) >> MPA_CHNLMODEEX_SHIFT;    
    
    // now we can determine frame size
    ComputeFrameSize();

    m_channels = (m_chnlMode == 3) ? 1 : 2;

    m_samplesPerFrame = MPA_SAMPLES_PER_FRAME;
    if(m_version != MPA_VERSION1)
    {
        m_samplesPerFrame /= 2;
    }
    m_samplesPerFrame *= m_channels;
    
    return true;
} 

#if(0)
// output frame stats in format similar to mpg123
void MPAFrameHeader::DumpFrameInfo() const
{
    //
    char* version[] = {"2.5", "undefined", "2", "1"};
    char* layer[] = {"undefined", "III", "II", "I"};
    char* channel_mode[] = {"stereo", "joint-stereo", "dual-channel", "single-channel"};
    char* channel_ex[] = {"", "intensity", "ms", "intensity ms"};

    DPRINTF(D_INFO, (" MPEG %s layer %s, %d kbits/s %d Hz %s %s %d bytes\n",
		     version[m_version], layer[m_layer],
		     m_bitRate/1000, m_sampleRate, 
		     channel_mode[m_chnlMode], 
		     channel_ex[m_chnlModeEx],
		     m_frameSize));
}
#endif

void MPAFrameHeader::ComputeFrameSize()
{
    if (m_layer == MPA_LAYER1)
    {
	m_frameSize = (12 * m_bitRate / m_sampleRate + m_pad) * 4;
    }
    else
    {
	int mult = 144;
	if (m_version == MPA_VERSION2 || m_version == MPA_VERSION25)
        {
	    mult /= 2;
        }

	m_frameSize = (mult * m_bitRate) / m_sampleRate + m_pad;
    }
}

⌨️ 快捷键说明

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