?? mpeg.c
字號:
/*
* $Copyright:
* ----------------------------------------------------------------
* This confidential and proprietary software may be used only as
* authorised by a licensing agreement from Optomech, Co., Ltd.
* (C) COPYRIGHT 2006 Optomech, Co., Ltd.
* ALL RIGHTS RESERVED
* The entire notice above must be reproduced on all authorised
* copies and copies may only be made to the extent permitted
* by a licensing agreement from Optomech, Co., Ltd..
* ----------------------------------------------------------------
* File: mpeg.c,v
* Revision: 1.0
* ----------------------------------------------------------------
* $
*
* Implementation of mpeg demuxer
*/
#include "gendef.h"
#if (0 != HAVE_AAC)
#include "xfile.h"
#include "constants.h"
#include "storage.h"
#include "mpeg.h"
#define MP4_INVALID_AUDIO_TYPE 0x00
#define MP4_MPEG4_AUDIO_TYPE 0x40
#define MP4_MPEG2_AAC_MAIN_AUDIO_TYPE 0x66
#define MP4_MPEG2_AAC_LC_AUDIO_TYPE 0x67
#define MP4_MPEG2_AAC_SSR_AUDIO_TYPE 0x68
#define MP4_MPEG2_AAC_AUDIO_TYPE MP4_MPEG2_AAC_MAIN_AUDIO_TYPE
#define AAC_Decoder ((tAAC_Decoder *) handle)
#define MP4_IS_MPEG2_AAC_AUDIO_TYPE(type) \
(((type) >= MP4_MPEG2_AAC_MAIN_AUDIO_TYPE \
&& (type) <= MP4_MPEG2_AAC_SSR_AUDIO_TYPE))
#define MP4_GET_UINT(p) (((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3])
#define MP4_INDEX ((tMpegIndex*)buf)
#define AAC_CHANNEL_BUFFER_SIZE (6144>>3) // 6144 bits per channel
static const char iDemux_DefaultSpeakers[9][4] =
{
{ 0,0,0,0 },
{ 1,0,0,0 },
{ 2,0,0,0 },
{ 3,0,0,0 },
{ 3,0,1,0 },
{ 3,0,2,0 },
{ 3,0,2,1 },
{ 5,0,2,0 },
{ 5,0,2,1 }
}; // from demux.c
static void iDemux_AssignDefaultPositions(oDecoderHandle handle, int nChans)
{
if (0 == nChans) // if CC == 0
{
nChans = 2; // suppose!
}
AAC_Decoder->Hdr_NumberOfChannels = (char) nChans;
if (nChans<=8)
{
const char *speakers = iDemux_DefaultSpeakers[nChans];
AAC_Decoder->Hdr_NumberOfFrontChannels = speakers[0];
AAC_Decoder->Hdr_NumberOfSideChannels = speakers[1];
AAC_Decoder->Hdr_NumberOfBackChannels = speakers[2];
AAC_Decoder->Hdr_NumberOfLFEChannels = speakers[3];
}
else
{
AAC_Decoder->Hdr_NumberOfFrontChannels = (char) nChans;
AAC_Decoder->Hdr_NumberOfSideChannels = 0;
AAC_Decoder->Hdr_NumberOfBackChannels = 0;
AAC_Decoder->Hdr_NumberOfLFEChannels = 0;
}
}
eDecoderStatus mpeg_find_tag(unsigned int tag, char** ppos, unsigned int* psize)
{
char target;
char* pos;
char* max;
if(*psize < sizeof(unsigned int))
{
return kDecoderStatus_Error;
}
target = (char)(0xFF & (tag >> 24));
pos = *ppos;
max = pos + (*psize - 3);
while(pos < max)
{
if(*pos == target)
{
if(tag == MPEG_GET_TAG(pos))
{
pos -= 4;
*ppos = pos;
*psize = MPEG_MAKE_SIZE(pos);
if((max + 3) < (pos + (*psize)))
{
return kDecoderStatus_MoreData;
}
return kDecoderStatus_NoError;
}
}
pos ++;
}
return kDecoderStatus_Error;
}
eDecoderStatus mpeg_decode_esds(char* pos, unsigned int size, sMpegEsds* pesds)
{
unsigned char value;
unsigned char len;
if(0x2C > size)
{
return kDecoderStatus_Fatal_BadBitstream;
}
value = (unsigned char)pos[0x19];
len = (unsigned char)pos[0x2A];
if(MP4_IS_MPEG2_AAC_AUDIO_TYPE(value))
{
pesds->Profile = value - MP4_MPEG2_AAC_MAIN_AUDIO_TYPE;
}
else if(MP4_MPEG4_AUDIO_TYPE == value)
{
if(1 > len)
{
return kDecoderStatus_Fatal_BadBitstream;
}
pesds->Profile = (pos[0x2B] >> 3) - 1;
}
else
{
return kDecoderStatus_Fatal_BadBitstream;
}
if(0x01 != pesds->Profile)
{
return kDecoderStatus_Fatal_UnsupportedFeature;
}
if(2 > len)
{
/* Ignore case for a while */
return kDecoderStatus_Fatal_BadBitstream;
}
else
{
value = ((pos[0x2B] << 1) | (pos[0x2C] >> 7)) & 0x0F;
/* Ignore 0x0F case for a while */
if(eAAC_InvalidFrequency <= value)
{
return kDecoderStatus_Fatal_BadBitstream;
}
else
{
pesds->Frequency = (tAAC_Frequency)value;
pesds->Channel = 0x0F & (pos[0x2C] >> 3);
if(7 == pesds->Channel)
{
pesds->Channel = 8;
}
}
}
pesds->BitRate = MP4_GET_UINT(pos + 0x22);
return kDecoderStatus_NoError;
}
eDecoderStatus mpeg_decode_stsc(char* pos, unsigned int size, void* buf)
{
if(0x1C > size)
{
return kDecoderStatus_Fatal_BadBitstream;
}
// if(1 != MP4_GET_UINT(pos + 0x0C)) // entry count
// {
// return kDecoderStatus_Fatal_BadBitstream;
// }
if(1 != MP4_GET_UINT(pos + 0x10)) // 1st chuck
{
return kDecoderStatus_Fatal_BadBitstream;
}
// if(1 != MP4_GET_UINT(pos + 0x18)) // 1st sample
// {
// return kDecoderStatus_Fatal_BadBitstream;
// }
MP4_INDEX->framePerChunk = MP4_GET_UINT(pos + 0x14);
if(0 == MP4_INDEX->framePerChunk)
{
return kDecoderStatus_Fatal_BadBitstream;
}
MP4_INDEX->chunkMax = (MP4_INDEX->size - sizeof(tMpegIndex) - sizeof(tFrame) - sizeof(tChunk))
/ ((MP4_INDEX->framePerChunk * sizeof(tFrame)) + sizeof(tChunk));
MP4_INDEX->frameMax = MP4_INDEX->framePerChunk * MP4_INDEX->chunkMax;
MP4_INDEX->chunkCount = 0;
MP4_INDEX->frameCount = 0;
MP4_INDEX->chunk = (tChunk*)(MP4_INDEX + 1);
MP4_INDEX->frame = (tFrame*)(MP4_INDEX->chunk + MP4_INDEX->chunkMax + 1);
return kDecoderStatus_NoError;
}
eDecoderStatus mpeg_decode_stsz(char** ppos, unsigned int* psize, void* buf)
{
unsigned int count;
if(0x14 > *psize)
{
return kDecoderStatus_MoreData;
}
count = MP4_GET_UINT(*ppos + 0x10);
if(count < MP4_INDEX->frameMax)
{
MP4_INDEX->frameMax = count;
}
*ppos += 0x14;
*psize -= 0x14;
return kDecoderStatus_NoError;
}
eDecoderStatus mpeg_read_stsz(char** ppos, unsigned int size, void* buf)
{
tFrame* out;
char* read;
char* end;
size >>= 2;
if((MP4_INDEX->frameCount + size) > MP4_INDEX->frameMax)
{
size = MP4_INDEX->frameMax - MP4_INDEX->frameCount;
}
read = *ppos;
end = read + (size << 2);
out = MP4_INDEX->frame + MP4_INDEX->frameCount;
while(read < end)
{
*out ++ = ((read[2] << 8) | read[3]);
read += 4;
}
*out = 0;
MP4_INDEX->frameCount += size;
*ppos = read;
return (MP4_INDEX->frameMax > MP4_INDEX->frameCount) ? kDecoderStatus_MoreData
: kDecoderStatus_NoError;
}
eDecoderStatus mpeg_decode_stco(char** ppos, unsigned int* psize, void* buf)
{
unsigned int count;
if(0x10 > *psize)
{
return kDecoderStatus_MoreData;
}
count = MP4_GET_UINT(*ppos + 0x0C);
if(count < MP4_INDEX->chunkMax)
{
MP4_INDEX->chunkMax = count;
}
*ppos += 0x10;
*psize -= 0x10;
return kDecoderStatus_NoError;
}
eDecoderStatus mpeg_read_stco(char** ppos, unsigned int size, void* buf)
{
tChunk* out;
char* read;
char* end;
size >>= 2;
if((MP4_INDEX->chunkCount + size) > MP4_INDEX->chunkMax)
{
size = MP4_INDEX->chunkMax - MP4_INDEX->chunkCount;
}
read = *ppos;
end = read + (size << 2);
out = MP4_INDEX->chunk + MP4_INDEX->chunkCount;
while(read < end)
{
*out ++ = MPEG_MAKE_SIZE(read);
read += 4;
}
*out = 0;
MP4_INDEX->chunkCount += size;
*ppos = read;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -