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 + -
显示快捷键?