📄 pmpeg4audio.c
字号:
/*
MPEG4 Audio Decoding Module
Base source is pMP3.c
*/
//****************************************************************************
//
// MP3InitBitstream initializes the stream to the given byte offset in the
// file.
//
//****************************************************************************
#include "include/main.h"
#include "kernel/Telechips.h"
#include "Lib76x.h"
#include "include/commoncmd.h"
#include "resource/tccresource.h"
#include "include/TCC760.h" //dddxxx
#include "include/globals.h"
#include "MP3Dec/MP3DEC_TCC76xMP3Dec_ADS_V101.h"
#include "MP3Dec/MP3DEC_pMP3_Dec_ADS.h"
#include "MP3Dec/MP3DEC_MpgData.h"
#include "buffer/buffer.h"
#include "FS/utils.h"
//----------------------
#include "Myfifo.h"
#include "Pixfileformat.h"
#ifdef MP4_INCLUDE
//static unsigned int KeyIn; // content of MessageQ
extern long gTotalSizeOfMPEG4Audio;
extern int gVideoFrameNum, gAudioFrameNum;
extern int gVideoTotalFrame, gAudioTotalFrame;
extern ELEMENTSTREAM AStreamBuf;
extern unsigned char gPlugInSkip;
extern unsigned char gMpegMode;
extern unsigned short usSRMap[];
extern unsigned short usBRMap[];
extern unsigned short usFLMap[][];
extern unsigned short usFLMap2[][];
extern char gLongPusgFFRR;
unsigned char ISFirst;
static int bitstreamDataToProcess = -1;
static int MPEG4_buffer_size;
int MPEG4_sp;
int MPEG4FirstHeaderDecoded = 0;
int MPEG4_BR;
#ifndef SWAP32
#define SWAP32(x) ( \
(((unsigned long int)(x) & 0x000000ffL) << 24) | \
(((unsigned long int)(x) & 0x0000ff00L) << 8) | \
(((unsigned long int)(x) & 0x00ff0000L) >> 8) | \
(((unsigned long int)(x) & 0xff000000L) >> 24) \
)
#endif
extern int GetOneFrameAudio(PELEMENTSTREAM pIdxStream,char* pFrameFiFo, unsigned int uiFrameNum);
//========================================================
// Decripton : Check Valid Frame Header by Input String
// Parameter : header -> Expected data to a Frame Header.
// Return : 0 -> Invalid Frame Header
// 1 -> Valid Frame Header
//========================================================
extern unsigned char CheckValidHeader(unsigned char *header);
//=============================================================================
// Decripton : Determines if the current frame is VBR header frame
// and decodes it if it is. (Xing and VBRI)
// Parameter : buffer -> the first pointer position of the MP3 file
// Return : 0 -> Fail to read the number of frame in Header
// Other -> The Number of Frame in Header
//========================================================
extern unsigned long DecodeVBRHeader(unsigned char *buffer, unsigned int *framesize);
extern unsigned short GetFrameSize(unsigned char* pucBuffer);
extern unsigned short GetSamplingRate(unsigned char* pucBuffer);
extern unsigned short GetBitrate(unsigned char* pucBuffer);
extern unsigned long GetHeaderInfo(unsigned char* pucBuffer);
extern unsigned char GetChannels(unsigned char* pucBuffer);
extern unsigned char GetLayerDescription(unsigned char* pucBuffer);
//****************************************************************************
//
// MP3DecodeVBRHeader determines if the current frame is a Xing VBR header
// frame and decodes it if it is.
//
//****************************************************************************
//========================================================
// Decripton : Search MP3 Header position
// Parameter : MP3Data -> String pointer of working data
// Return : -1 -> Invalid MP3 file
// signed digit -> Positoin of first frame header
//========================================================
int MPEG4_GetHeaderPosition(tMP3 *pMP3)//unsigned char* MP3Data)
{
unsigned char* MP3Data;
unsigned int firstheaderposition = 0;
unsigned int searchcount = 70*1024;//1000;
unsigned long ulFramesize;
unsigned long ulTotalframes;
unsigned char returnvalue;
int result;
MP3Data = pMP3->pcEncodedData;
result = GetOneFrameAudio(&AStreamBuf, MP3Data, gAudioFrameNum);
firstheaderposition = 0;
// If valid header, check 20 times
// else, check 1000 times. exept all 0xFF, 0x00
while(searchcount)
{
returnvalue = CheckValidHeader(MP3Data);
if(returnvalue){
// check Xing & VBRI ==========================================================
ulTotalframes = DecodeVBRHeader(MP3Data, &ulFramesize);
if(!ulTotalframes){
// get header information
pMP3->ucIsVBR = 0;
pMP3->ucChannels = GetChannels(MP3Data);
pMP3->usSampleRate = GetSamplingRate(MP3Data);
pMP3->ulFirstFrame = firstheaderposition;
ulTotalframes = ulFramesize * gAudioTotalFrame;
pMP3->ulLength = ulTotalframes - pMP3->ulFirstFrame;
pMP3->ulBitRate = ((pMP3->ulLength / ulTotalframes) *
pMP3->usSampleRate) / (ulFramesize / 8);
if(pMP3->ulBitRate == 0)
{
return 0;
}
return 1;
}
}
searchcount--;
firstheaderposition++;
MP3Data++;
}
return 0;
}
void MPEG4FillBitstream(tMP3 *pMP3, int mtest)
{
int bytesCurrent;
int bytesNeeded;
char *bsdata;
int result_fread = 0;
bytesCurrent = pMP3->bitstream.dataLength - pMP3->bitstream.dataOffset;
bytesNeeded = pMP3->bitstream.dataRequired - bytesCurrent;
/* Update bitstream structure values */
pMP3->bitstream.data += pMP3->bitstream.dataOffset;
pMP3->bitstream.dataOffset = 0;
pMP3->bitstream.dataLength = bytesCurrent;
/* bsdata is the address at which to start writing new data */
bsdata = pMP3->bitstream.data + bytesCurrent;
if (bytesNeeded > 0)
{
// Will we run off the end of the bitstream buffer?
if ( ((pMP3->bitstream.data - pMP3->pcEncodedData) + pMP3->bitstream.dataRequired) > 1152 )
{
// YES: We need to move the existing data to the start of the buffer to make room at the end
mem_cpy(pMP3->pcEncodedData, pMP3->bitstream.data, bytesCurrent);
pMP3->bitstream.data = pMP3->pcEncodedData; // Move data pointer back to start of buffer
bsdata = pMP3->pcEncodedData + bytesCurrent;
}
RETRY_GETAUDIO :
if(gAudioFrameNum <= gAudioTotalFrame)
{
result_fread = GetOneFrameAudio(&AStreamBuf, bsdata, gAudioFrameNum);
if(!gLongPusgFFRR)
{
gAudioFrameNum += 1;
if( gAudioFrameNum >= gAudioTotalFrame - 1 )
gAudioTotalFrame = gAudioTotalFrame - 1;
}
if(result_fread == -1)
{
#ifdef AGING_TEST
SerialWriteString("GetOneFrameAudio Fail");
#endif
goto RETRY_GETAUDIO;
}
}
else{
// If there is insufficient data, signal end of file
bitstreamDataToProcess = 0;
}
bsdata = bsdata + result_fread;
if(result_fread < bytesNeeded){
bitstreamDataToProcess = 0;
}
pMP3->bitstream.dataLength = bsdata - pMP3->bitstream.data;
// If there is insufficient data, signal end of file
if (pMP3->bitstream.dataLength < pMP3->bitstream.dataRequired)
{
bitstreamDataToProcess = 0;
}
}
}
//****************************************************************************
//
// The codec plug-in entry point for the MP4 Audio.
//
//****************************************************************************
unsigned long
MPEG4AudioFunction(unsigned long ulSubFn, unsigned long ulParam1, unsigned long ulParam2,
unsigned long ulParam3, unsigned long ulParam4)
{
// Decode a frame of data.
if( ulSubFn == SUBFN_CODEC_DECODE)
{
unsigned char Cmd=0;
short *psLeft=0, *psRight=0;
long lLength=0;
// The first parameter is a pointer to the MP3 persistent state.
tMP3 *pMP3;
int MP4_Timer, MP4_Timer2;
// The first parameter is a pointer to the MP3 persistent state.
pMP3 = (tMP3 *)ulParam1;
if( ISFirst == 0 ) // Start DeMux task for Video Decoding
{
Cmd = STATE_PLAY;
OSQPost(TCC_DEMUX_Q, (void *)&Cmd); // pend DEmux Task
OSSemPend(MPEG_DEMUX_SEM, 0, &Cmd);
ISFirst = 1;
while( gVideoFrameNum < 8 && !gLongPusgFFRR )
{
OSTimeDly(1);
}
}
pMP3->status = 0;
if(MPEG4FirstHeaderDecoded != 1){
MP4_Timer = 1024;
bitstreamDataToProcess = -1;
do
{
MPEG4FillBitstream(pMP3, 0);
if (!bitstreamDataToProcess) break;
pMP3->status = pMP3->workspace->Decoder->DecodeHeader( pMP3->workspace->handle,
pMP3->workspace->scratch,
&(pMP3->bitstream) );
if(pMP3->bitstream.sampleRate != MPEG4_sp)
{
pMP3->status = kDecoderStatus_ReservedSamplingFrequency;
}
if ( --MP4_Timer < 0 )
break;
}
while ( (pMP3->status != kDecoderStatus_NoError) && bitstreamDataToProcess);
if(pMP3->status != kDecoderStatus_NoError)
{
OSTimeDly(5);
return 1;
// return(0);
}
}
//decode header
MPEG4FirstHeaderDecoded = 0;
if(!bitstreamDataToProcess) return(0);
pMP3->bitstream.formats.outputFormats = OUTPUT_FORMAT_16BIT;
// Wait until there is space in the output buffer. This tells us
// when it is OK to write more data into the output buffer.
MP4_Timer = 10000;
while( BufferSpaceAvailable(pMP3->pOutput,gPlugInSkip) < MP3_MAX_PCM_LENGTH )
{
if ( --MP4_Timer < 0 )
break;
OSTimeDly(2);
Halt();
}
// Get a pointer to the available space in the output buffer.
BufferGetWritePointer(pMP3->pOutput, &psLeft, &psRight, &lLength,gPlugInSkip);
pMP3->output.channels[0] = psLeft;
pMP3->output.channels[1] = psRight;
bitstreamDataToProcess = -1;
MP4_Timer = 1024;
do{
if(pMP3->status == kDecoderStatus_FrameDiscarded || pMP3->status == kDecoderStatus_BrokenFrame)
{
bitstreamDataToProcess = -1;
MP4_Timer2 = 1024;
do
{
MPEG4FillBitstream(pMP3, 0);
if (!bitstreamDataToProcess) break;
pMP3->status = pMP3->workspace->Decoder->DecodeHeader( pMP3->workspace->handle,
pMP3->workspace->scratch,
&(pMP3->bitstream) );
if(pMP3->bitstream.sampleRate != MPEG4_sp)
{
pMP3->status = kDecoderStatus_ReservedSamplingFrequency;
}
#if 0
if(pMP3->bitstream.bitRate!= MPEG4_BR)
{
pMP3->status = kDecoderStatus_ReservedBitRate;
}
#endif
if ( --MP4_Timer2 < 0 )
break;
}
while ( (pMP3->status != kDecoderStatus_NoError && bitstreamDataToProcess) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -