📄 shoutcaststream.cpp
字号:
TAudioFrameInfo frameInfo;
if ( iDataType.FourCC() == KMMFFourCCCodeMP3 )
{
seekOffset = Mp3SeekSync(aBuf, aLength);
seekLen = readLen - seekOffset;
seekPtr = aBuf + seekOffset;
length = GetMp3FrameInfo(seekPtr, seekLen, frameInfo);
}
else if ( iDataType.FourCC() == KMMFFourCCCodeAAC )
{
seekOffset = AacSeekSync(aBuf, aLength);
seekLen = readLen - seekOffset;
seekPtr = aBuf + seekOffset;
length = GetAacFrameInfo(seekPtr, seekLen, frameInfo);
}
if ( length > 0 && frameInfo.iBitRate > 0 )
{
iSamplingRate = frameInfo.iSamplingRate;
iBitRate = frameInfo.iBitRate;
iChannels = frameInfo.iChannels;
return ETrue;
}
else
{
return EFalse;
}
}
// -----------------------------------------------------------------------------
// CShoutcastStream::Mp3SeekSync
// -----------------------------------------------------------------------------
//
TInt CShoutcastStream::Mp3SeekSync(
TUint8 *aBuf,
TInt aLength )
{
const TUint8* buf = aBuf;
const TInt KMaxFrames = 3; // number of frames to check
const TInt KNotFound = aLength; // sync not found position
TAudioFrameInfo frameInfo; // frame parameters
TInt i = 0;
TInt syncPos = KNotFound;
TInt maxSeek = KMaxFrames;
const TUint8* endPtr = buf + aLength;
// Seek a valid frame candidate byte by byte until a valid frame
// is found or all bytes have been checked.
while ( buf < endPtr && syncPos == KNotFound )
{
TInt seekCount = 0;
const TUint8* framePtr = buf;
TInt frameBufLen = aLength;
syncPos = i;
// Check the validity of this frame candidate and the nearest next
// frames. If they are not OK, syncPos will be set to KNotFound.
while ( framePtr < endPtr && syncPos != KNotFound && seekCount < maxSeek )
{
TInt length = GetMp3FrameInfo(framePtr, frameBufLen, frameInfo);
if ( length == 0 )
{
syncPos = KNotFound;
}
if ( (length > 0) && (frameInfo.iBitRate < 0 ) )
{
maxSeek = 1; // free formatcase
}
framePtr += length;
frameBufLen -= length;
seekCount++;
// consider SYNC not found if we reach end of buffer before finding 3 SYNC frames
if ((framePtr >= endPtr) && (seekCount < maxSeek))
{
syncPos = KNotFound;
aBuf += (aLength - 1); // force an exit from while loop
}
}
buf++; aLength--; i++;
}
return syncPos;
}
// -----------------------------------------------------------------------------
// CShoutcastStream::GetMp3FrameInfo
// -----------------------------------------------------------------------------
//
TInt CShoutcastStream::GetMp3FrameInfo(
const TUint8* aBuf,
TInt aBufLen,
TAudioFrameInfo& aInfo )
{
TInt length = 0;
TUint temp;
TUint lTempVal;
if ( aBufLen >= KMp3FrameHeaderSize )
{
// Extract header fields to aInfo and check their bit syntax
// (including the sync word!). If the syntax is not OK the length
// is set to zero.
temp = 0;
temp = aBuf[0] << 24;
temp |= (aBuf[1] << 16);
temp |= (aBuf[2] << 8);
temp |= aBuf[3];
if ( ((temp >> 21) & 0x7FF) != 0x7FF )
{
return length;
}
lTempVal = (temp >> 19) & 0x03;
switch ( lTempVal )
{
case 0:
aInfo.iId = 2; // MPEG2.5
aInfo.iFrameSamples = 576;
break;
case 1:
return length;
case 2:
aInfo.iId = 0; // MPEG 2
aInfo.iFrameSamples = 576;
break;
case 3:
aInfo.iId = 1; // MPEG 1
aInfo.iFrameSamples = 1152;
break;
}
lTempVal = (temp >> 17) & 0x03;
if ( lTempVal != 1 )
{
return length;
}
lTempVal = (temp >> 12) & 0x0F;
aInfo.iBitRate = KMp3BitRateTable[aInfo.iId][lTempVal] * 1000;
if ( aInfo.iBitRate == 0 )
{
return length;
}
lTempVal = (temp >> 10) & 0x03;
if ( lTempVal == 3 )
{
return length;
}
else
{
aInfo.iSamplingRate = KMp3SamplingFrequencyTable[aInfo.iId][lTempVal];
}
aInfo.iPadding = (temp >> 9) & 0x01;
lTempVal = (temp >> 6) & 0x03;
aInfo.iMode = lTempVal;
if ( lTempVal == 3 )
{
aInfo.iChannels = 1;
}
else
{
aInfo.iChannels = 2;
}
aInfo.iSamplingRateOut = aInfo.iSamplingRate;
aInfo.iChannelsOut = 2; /* always set to stereo output */
aInfo.iFrameSamplesOut = aInfo.iFrameSamples;
if ( aInfo.iBitRate == -1 )
{
// For free mode operation
length = KMp3MaxFrameSize;
}
if ( aInfo.iSamplingRate > 0 && aInfo.iBitRate > 0 )
{
length = (144 * aInfo.iBitRate) / aInfo.iSamplingRate;
if ( aInfo.iId != 1 )
{
length >>= 1; /*for MPEG2 and MPEG2.5 */
}
if ( aInfo.iPadding )
{
length++;
}
}
aInfo.iFrameSize = length;
}
return length;
}
// -----------------------------------------------------------------------------
// CShoutcastStream::AacSeekSync
// -----------------------------------------------------------------------------
//
TInt CShoutcastStream::AacSeekSync(
TUint8 *aBuf,
TInt aLength )
{
TInt seekLen = 0;
while ( seekLen < (aLength - 4) )
{
if ( IsValidAacFrame(aBuf + seekLen, aLength - seekLen) )
{
return seekLen;
}
seekLen++;
}
return aLength;
}
// -----------------------------------------------------------------------------
// CShoutcastStream::IsValidAacFrame
// -----------------------------------------------------------------------------
//
TBool CShoutcastStream::IsValidAacFrame(
const TUint8* aPtr,
TInt aBufLen )
{
if ( (aPtr[0] == 'A') && (aPtr[1] == 'D') &&
(aPtr[2] == 'I') && (aPtr[3] == 'F') )
{
return ETrue;
}
if ( (aPtr[0] == 0xFF) && ((aPtr[1] >> 4) == 0xF) && // Check syncword FFF
((aPtr[1] >> 1) & 0x3) == 0 // Check layer == 0
)
{
TInt frameLen = 0;
frameLen = (aPtr[3] & 0x3) << 11;
frameLen |= aPtr[4] << 3;
frameLen |= ((aPtr[5] >> 5) & 0x7);
if ( !frameLen || frameLen > (aBufLen-4) )
{
return EFalse;
}
// Check next frame
const TUint8* nextFramePtr = aPtr + frameLen;
if ( ((nextFramePtr[0] == 0xFF) && ((nextFramePtr[1] >> 4) == 0xF)) && // Check syncword FFF
((nextFramePtr[1] >> 1) & 0x3) == 0 // Check layer == 0
)
{
return ETrue;
}
}
return EFalse;
}
// -----------------------------------------------------------------------------
// CShoutcastStream::GetAacFrameInfo
// -----------------------------------------------------------------------------
//
TInt CShoutcastStream::GetAacFrameInfo(
const TUint8* aBuf,
TInt aBufLen,
TAudioFrameInfo& aInfo )
{
TInt length = 0;
TUint temp;
TUint lTempVal;
TUint lTemp1;
TUint lUnSupported = 0;
if ( aBufLen >= KAacFrameHeaderSize )
{
// Extract header fields to aInfo and check their bit syntax
// (including the sync word!). If the syntax is not OK the length
// is set to zero.
lTemp1 = aBuf[0] << 24;
lTemp1 |= (aBuf[1] << 16);
lTemp1 |= (aBuf[2] << 8);
lTemp1 |= aBuf[3];
temp = (lTemp1 >> 20) & 0xFFF;
if((temp & 0xFFF) == 0xFFF)
{
// ADTS Frame
temp = (lTemp1 >> 19) & 0x01;
aInfo.iId = temp; // 0 for MPEG 4 and 1 for MPEG 2
// Sampling Frequency Index
temp = (lTemp1 >> 10) & 0x0F;
if(temp > 11)
{
lUnSupported = 1;
}
else
{
aInfo.iSamplingRate = KAacSamplingFrequencyTable[temp];
}
// The header doesn't tell us about bitrate so use the bitrate from the server
aInfo.iBitRate = iBitRate;
// Channel Configuration
lTempVal = (lTemp1 >> 6) & 0x07;
if(lTempVal > 2)
{
lUnSupported = 1;
aInfo.iChannels = lTempVal;
}
else if (lTempVal == 0 )
{
aInfo.iChannels = 2;
}
else
{
aInfo.iChannels = lTempVal;
}
// frame_length
length = (lTemp1 & 0x03) << 11;
lTemp1 = 0;
lTemp1 = aBuf[4] << 24;
lTemp1 |= (aBuf[5] << 16);
lTemp1 |= (aBuf[6] << 8);
/* adts_buffer_fullness */
temp = temp | ((lTemp1 >> 21) & 0x7FF);
/*Number of raw data blocks*/
TInt numberOfRawDataBlks = ((lTemp1 >> 8) &0x03) + 1;
if(temp > (1536 * numberOfRawDataBlks))
{
/* 1536 bytes per raw datablock in the ADTS frame */
lUnSupported = 1;
}
/* Update Framesize only if the bit stream is supported */
if(!lUnSupported)
{
aInfo.iFrameSize = temp;
length = temp;
}
}
}
return length;
}
// -----------------------------------------------------------------------------
// CShoutcastStream::GetIPFromURL
// Get the IP address from the URL
// -----------------------------------------------------------------------------
//
void CShoutcastStream::GetIPFromURL()
{
//parse the iURL and get the IP:port
//the URL is iURL. The target IP:port is *addr
//we must keep the iURL constant
TUint32 ip=0;
TUint port=80;//the default port
TInt length,start,end,i;
TBuf8<URL_SIZE> url;
//assume the http:// in front of the string
ASSERT(iURL.Find(_L8("http://"))==0);
start=7;
//get the length of the url
length=iURL.Length();
//get the url without the http://
url=iURL.Right(length-start);
length = url.Find(_L8(":"));
// get the ip addr from the url
if ( length == KErrNotFound )
{
iIp = url;
}
else
{
iIp = url.Left(length);
}
if ( url[0] >= 48 && url[0] <=57)
{
//the IP starts with a number, so we have a numeric IP
for( i = 3; i>=0; i-- )
{
ip = ip*256+(unsigned)atoi((const char *)url.PtrZ());
LOG1("GetIPFromURL: ip: %u",(unsigned)atoi((const char *)url.PtrZ()));
//get the next dot/:
if ( i )
{
end=url.Locate('.');
url.Delete(0,end+1);
}
}
}
else
{
//the IP does not start with a number!
ASSERT(0);//### not handled yet
};
//get the port, if any
end=url.Locate(':');
if ( end != KErrNotFound )
{
//we found a port!
url.Delete(0,end+1);
port = (unsigned)atoi((const char *)url.PtrZ());
}
//get the iPath, this is what remains
end = url.Locate('/');
if ( end != KErrNotFound )
{
//we have a path
url.Delete(0,end);//we do not delete the /
iPath.Copy(url);
}
else
{
//there is no path! we make it /
iPath.Copy(_L8("/"));
}
iAddr = new TInetAddr(ip,port);
}
// -----------------------------------------------------------------------------
// CShoutcastStream::Disconnect
// Send disconnect event to client.
// -----------------------------------------------------------------------------
//
void CShoutcastStream::Disconnect(
TInt aError)
{
LOG1("In Disconnect (status: %d)", aError);
iDispatcher->SendEvent(TUid::Uid(KShoutcastStreamUid),KShoutcastEvent_Disconnected);
}
// -----------------------------------------------------------------------------
// CShoutcastStream::SetVolume
// Sets the volume level
// -----------------------------------------------------------------------------
//
void CShoutcastStream::SetVolume(
TInt aVolume )
{
iVolume = aVolume;
if ( iStreamOutput )
{
iStreamOutput->SetVolume(aVolume);
}
}
// -----------------------------------------------------------------------------
// CShoutcastStream::Volume
// Get the volume level
// -----------------------------------------------------------------------------
//
TInt CShoutcastStream::Volume()
{
if ( iStreamOutput )
{
return iStreamOutput->Volume();
}
else
{
return iVolume;
}
}
// -----------------------------------------------------------------------------
// CShoutcastStream::MaxVolume
// Get the maximum volume level
// -----------------------------------------------------------------------------
//
TInt CShoutcastStream::MaxVolume()
{
if ( iStreamOutput )
{
return iStreamOutput->MaxVolume();
}
else
{
return 10;
}
}
// End of File
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -