#include "Ap4BitStream.h"
#include "Ap4Ac3Parser.h"
#include "Ap4Utils.h"
AP4_Ac3Header::AP4_Ac3Header(const AP4_UI08* bytes)
{
AP4_BitReader bits(bytes, AP4_AC3_HEADER_SIZE);
bits.SkipBits(16); bits.SkipBits(16); m_Fscod = bits.ReadBits(2);
m_Frmsizecod = bits.ReadBits(6); m_FrameSize = FRAME_SIZE_CODE_ARY_AC3[m_Fscod][m_Frmsizecod] * 2;
m_Bsid = bits.ReadBits(5);
m_Bsmod = bits.ReadBits(3);
m_Acmod = bits.ReadBits(3);
if((m_Acmod & 0x1) && (m_Acmod != 0x1)){
bits.SkipBits(2); }
if(m_Acmod & 0x4){
bits.SkipBits(2); }
if(m_Acmod == 0x2){
bits.SkipBits(2); }
m_Lfeon = bits.ReadBit();
m_ChannelCount = GLOBAL_CHANNEL_ARY[m_Acmod] + m_Lfeon;
bits.SkipBits(5); if(bits.ReadBit()){ bits.SkipBits(8); }
if(bits.ReadBit()){ bits.SkipBits(8); }
if(bits.ReadBit()){ bits.SkipBits(5); bits.SkipBits(2); }
if (m_Acmod == 0){
bits.SkipBits(5); if(bits.ReadBit()){ bits.SkipBits(8); }
if(bits.ReadBit()){ bits.SkipBits(8); }
if(bits.ReadBit()){ bits.SkipBits(5); bits.SkipBits(2); }
}
bits.SkipBits(1); bits.SkipBits(1); if(bits.ReadBit()){ bits.SkipBits(14); }
if(bits.ReadBit()){ bits.SkipBits(14); }
m_Addbsie = bits.ReadBit();
if (m_Addbsie){
m_Addbsil = bits.ReadBits(6);
for (unsigned int idx = 0 ; idx < (m_Addbsil + 1); idx ++){
m_addbsi[idx] = bits.ReadBits(8);
}
} else {
m_Addbsil = 0;
AP4_SetMemory(m_addbsi, 0, sizeof (m_addbsi));
}
m_HeadSize = (bits.GetBitsRead() / 8) + ((bits.GetBitsRead() % 8 == 0) ? 0: 1);
}
bool
AP4_Ac3Header::MatchFixed(AP4_Ac3Header& frame, AP4_Ac3Header& next_frame)
{
return true;
}
AP4_Result
AP4_Ac3Header::Check()
{
if (m_Bsid > 8) {
return AP4_FAILURE;
}
return AP4_SUCCESS;
}
AP4_Ac3Parser::AP4_Ac3Parser() :
m_FrameCount(0)
{
}
AP4_Ac3Parser::~AP4_Ac3Parser()
{
}
AP4_Result
AP4_Ac3Parser::Reset()
{
m_FrameCount = 0;
return AP4_SUCCESS;
}
AP4_Result
AP4_Ac3Parser::Feed(const AP4_UI08* buffer,
AP4_Size* buffer_size,
AP4_Flags flags)
{
AP4_Size free_space;
m_Bits.m_Flags = flags;
if (buffer == NULL ||
buffer_size == NULL ||
*buffer_size == 0) {
return AP4_SUCCESS;
}
free_space = m_Bits.GetBytesFree();
if (*buffer_size > free_space) *buffer_size = free_space;
if (*buffer_size == 0) return AP4_SUCCESS;
return m_Bits.WriteBytes(buffer, *buffer_size);
}
AP4_Result
AP4_Ac3Parser::FindHeader(AP4_UI08* header)
{
AP4_Size available = m_Bits.GetBytesAvailable();
while (available-- >= AP4_AC3_HEADER_SIZE) {
m_Bits.PeekBytes(header, 2);
if( (((header[0] << 8) | header[1]) == AP4_AC3_SYNC_WORD_BIG_ENDIAN) ||
(((header[0] << 8) | header[1]) == AP4_AC3_SYNC_WORD_LITTLE_ENDIAN) ){
if (((header[0] << 8) | header[1]) == AP4_AC3_SYNC_WORD_LITTLE_ENDIAN) {
m_LittleEndian = true;
} else {
m_LittleEndian = false;
}
m_Bits.PeekBytes(header, AP4_AC3_HEADER_SIZE);
return AP4_SUCCESS;
} else {
m_Bits.SkipBytes(1); }
}
return AP4_ERROR_NOT_ENOUGH_DATA;
}
AP4_Result
AP4_Ac3Parser::FindFrame(AP4_Ac3Frame& frame)
{
unsigned int available;
unsigned char raw_header[AP4_AC3_HEADER_SIZE];
AP4_Result result;
m_Bits.ByteAlign();
result = FindHeader(raw_header);
if (AP4_FAILED(result)) return result;
if (m_LittleEndian) {
AP4_ByteSwap16(raw_header, AP4_AC3_HEADER_SIZE);
}
AP4_Ac3Header ac3_header(raw_header);
result = ac3_header.Check();
if (AP4_FAILED(result)) {
m_Bits.SkipBytes(2);
goto fail;
}
available = m_Bits.GetBytesAvailable();
if (available >= ac3_header.m_FrameSize + AP4_AC3_HEADER_SIZE) {
unsigned char peek_raw_header[AP4_AC3_HEADER_SIZE];
m_Bits.SkipBytes(ac3_header.m_FrameSize);
m_Bits.PeekBytes(peek_raw_header, AP4_AC3_HEADER_SIZE);
m_Bits.SkipBytes(-((int)ac3_header.m_FrameSize));
if (m_LittleEndian) {
AP4_ByteSwap16(peek_raw_header, AP4_AC3_HEADER_SIZE);
}
AP4_Ac3Header peek_ac3_header(peek_raw_header);
result = peek_ac3_header.Check();
if (AP4_FAILED(result)) {
m_Bits.SkipBytes(ac3_header.m_FrameSize + 2);
goto fail;
}
else if (!AP4_Ac3Header::MatchFixed(ac3_header, peek_ac3_header)) {
m_Bits.SkipBytes(ac3_header.m_FrameSize + 2);
goto fail;
}
} else if (available < ac3_header.m_FrameSize || (m_Bits.m_Flags & AP4_BITSTREAM_FLAG_EOS) == 0) {
return AP4_ERROR_NOT_ENOUGH_DATA;
}
frame.m_Info.m_ChannelCount = ac3_header.m_ChannelCount;
frame.m_Info.m_SampleRate = FSCOD_AC3[ac3_header.m_Fscod];
frame.m_Info.m_FrameSize = ac3_header.m_FrameSize;
frame.m_Info.m_Ac3StreamInfo.fscod = ac3_header.m_Fscod;
frame.m_Info.m_Ac3StreamInfo.bsid = ac3_header.m_Bsid;
frame.m_Info.m_Ac3StreamInfo.bsmod = ac3_header.m_Bsmod;
frame.m_Info.m_Ac3StreamInfo.acmod = ac3_header.m_Acmod;
frame.m_Info.m_Ac3StreamInfo.lfeon = ac3_header.m_Lfeon;
frame.m_Info.m_Ac3StreamInfo.bit_rate_code = ac3_header.m_Frmsizecod / 2;
frame.m_LittleEndian = m_LittleEndian;
frame.m_Source = &m_Bits;
return AP4_SUCCESS;
fail:
return AP4_ERROR_CORRUPTED_BITSTREAM;
}
AP4_Size
AP4_Ac3Parser::GetBytesFree()
{
return (m_Bits.GetBytesFree());
}
AP4_Size
AP4_Ac3Parser::GetBytesAvailable()
{
return (m_Bits.GetBytesAvailable());
}