home *** CD-ROM | disk | FTP | other *** search
- /*
- * Audio.cpp
- *
- * Copyright (C) Alberto Vigata - January 2000 - ultraflask@yahoo.com
- *
- * This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
- *
- * FlasKMPEG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * FlasKMPEG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Make; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
- #include <stdio.h>
- #include "Audio.h"
- #include "debug.h"
-
-
-
- //char *sAC3SampleFreq[4]={"48 Khz","44.1 Khz", "32 Khz","Unexpected"};
- int AC3Acmod[]={ 2, 1, 2, 3, 3, 4, 4, 5 };
- int AC3SampleFreq[4]={48000,44100,32000,0};
-
- struct TFrameSize framesize_table[] = {
- { 32 ,{64 ,69 ,96 } },
- { 32 ,{64 ,70 ,96 } },
- { 40 ,{80 ,87 ,120 } },
- { 40 ,{80 ,88 ,120 } },
- { 48 ,{96 ,104 ,144 } },
- { 48 ,{96 ,105 ,144 } },
- { 56 ,{112 ,121 ,168 } },
- { 56 ,{112 ,122 ,168 } },
- { 64 ,{128 ,139 ,192 } },
- { 64 ,{128 ,140 ,192 } },
- { 80 ,{160 ,174 ,240 } },
- { 80 ,{160 ,175 ,240 } },
- { 96 ,{192 ,208 ,288 } },
- { 96 ,{192 ,209 ,288 } },
- { 112 ,{224 ,243 ,336 } },
- { 112 ,{224 ,244 ,336 } },
- { 128 ,{256 ,278 ,384 } },
- { 128 ,{256 ,279 ,384 } },
- { 160 ,{320 ,348 ,480 } },
- { 160 ,{320 ,349 ,480 } },
- { 192 ,{384 ,417 ,576 } },
- { 192 ,{384 ,418 ,576 } },
- { 224 ,{448 ,487 ,672 } },
- { 224 ,{448 ,488 ,672 } },
- { 256 ,{512 ,557 ,768 } },
- { 256 ,{512 ,558 ,768 } },
- { 320 ,{640 ,696 ,960 } },
- { 320 ,{640 ,697 ,960 } },
- { 384 ,{768 ,835 ,1152 } },
- { 384 ,{768 ,836 ,1152 } },
- { 448 ,{896 ,975 ,1344 } },
- { 448 ,{896 ,976 ,1344 } },
- { 512 ,{1024 ,1114 ,1536 } },
- { 512 ,{1024 ,1115 ,1536 } },
- { 576 ,{1152 ,1253 ,1728 } },
- { 576 ,{1152 ,1254 ,1728 } },
- { 640 ,{1280 ,1393 ,1920 } },
- { 640 ,{1280 ,1394 ,1920 } }};
-
- static const int mpeg1_bitrate_table[3][15] = {
- { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 },
- { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 },
- { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 }
- };
-
- static const int mpeg1_sampling_frequency[4] = { 44100, 48000, 32000 , 0 };
-
- static const int mpeg2_bitrate_table[3][15] = {
- {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, },
- {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, },
- {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, },
- };
-
- #define IsAc3Track(streamId, subStreamId) ( (subStreamId>= 0x80 && subStreamId <= 0x87 && streamId==0xBD) )
- #define IsMpegTrack(streamId, subStreamId ) ((streamId >= 0xC0) && (streamId <= 0xDF))
-
- #define IsAudioTrack(streamId, subStreamId) ( IsAc3Track(streamId, subStreamId) || IsMpegTrack(streamId, subStreamId) )
-
- #define safedelete(x){delete (x); (x)=NULL;}
-
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- Audio::Audio()
- {
-
- m_nStreamID = 0;
- m_nSubStreamID = 0;
- m_bAudioInfoIsValid = false;
-
- resampler = NULL;
- decoded_samples_buffer = NULL;
- ResamplerBuffer = NULL;
- frameFIFO = NULL;
-
- sampleRate = 0;
-
- }
-
- Audio::~Audio()
- {
- }
-
- bool Audio::Init(LPTWorkingMism pMismInfo)
- {
-
- //Start demuxer
- if(!SetInput(pMismInfo))
- return false;
-
- resampler = NULL;
- decoded_samples_buffer = NULL;
- ResamplerBuffer = NULL;
- frameFIFO = NULL;
-
-
- //file opened
- CDemux::SetStreamPos(0);
-
- ReadSpanInit();
-
- bool bSuccess = true;
- bool bFoundStream = false;
- ui8 nStreamId, nSubStreamId;
- ui32 nFramesFound=0;
-
- // Create frame FIFO
- frameFIFO = new CAudFrameBuffer();
- // Grab the first audio frame that flies around
-
- while(nFramesFound < 10)
- {
- while(frameFIFO->firstFrame==NULL && bSuccess)
- {
- bSuccess =ReadLPES((unsigned char **)&read_state.PES.data, &read_state.PES.pInfo);
- nStreamId = read_state.PES.pInfo.streamID;
- nSubStreamId = read_state.PES.pInfo.subStreamID;
-
- // Find first track to know the sample rate
- if( IsAudioTrack( nStreamId, nSubStreamId ) && !bFoundStream )
- {
- // This is the first audio track that passes
- if(IsAc3Track(nStreamId, nSubStreamId))
- m_nFormat = Ac3;
- if( IsMpegTrack(nStreamId, nSubStreamId) )
- m_nFormat = MpegAudio;
-
- bSuccess = true;
- bFoundStream = true;
- m_nStreamID = nStreamId;
- m_nSubStreamID = nSubStreamId;
- }
-
- if(bFoundStream)
- {
- if( m_nStreamID == read_state.PES.pInfo.streamID &&
- m_nSubStreamID == read_state.PES.pInfo.subStreamID )
- ParseFrameData();
- }
- }
-
- if(bSuccess)
- {
- // We have a frame.
- // Retrieve the info for it
- while(frameFIFO->firstFrame)
- {
- GetPropertiesFromFrame(m_nFormat,frameFIFO->firstFrame->data, &m_sAudioInfo );
-
- if( m_sAudioInfo.sample_rate!=sampleRate )
- nFramesFound = 0;
- else
- nFramesFound++;
-
- sampleRate = m_sAudioInfo.sample_rate;
- m_bAudioInfoIsValid = true;
- frameFIFO->RemoveFirstFrame();
-
- }
- }
- }
- safedelete(frameFIFO);
-
- return bSuccess;
- }
-
- TAudioInfo * Audio::GetAudioInfo()
- {
- if(m_bAudioInfoIsValid)
- return &m_sAudioInfo;
- else
- return NULL;
- }
-
- bool Audio::GetPropertiesFromFrame(AudioFormat nFormat, ui8* pFrame, TAudioInfo *pTrackInfo)
- {
- if(!pFrame)
- return false;
-
- ui8 *data;
- ui8 fscod, frmsizecode, acmod;
-
- // Mask to determine the position of the lfe bit
- // depending on acmod
- static ui8 lfeon[8] = {0x10, 0x10, 0x04, 0x04, 0x04, 0x01, 0x04, 0x01};
-
- switch( nFormat )
- {
- case Ac3:
- data = pFrame;
- fscod = (data[4] & 0xC0) >> 6;
- frmsizecode = (data[4] & 0x3F);
-
- pTrackInfo->sample_rate = AC3SampleFreq[fscod];
- pTrackInfo->bit_rate = framesize_table[frmsizecode].bit_rate;
-
- //Update channels info
- acmod = data[6] >> 5;
-
- // retrieve more info
- pTrackInfo->subwoofer = data[6] & lfeon[acmod];
-
- pTrackInfo->channels = AC3Acmod[acmod];
-
- pTrackInfo->format = Ac3;
- break;
- case MpegAudio:
- data = pFrame;
- long hdr;
- // Yay! A valid MPEG header! Parse it!
-
- // 0000F0FF 12 bits sync mark
- //
- // 00000800 1 bit version
- // 00000600 2 bits layer (3 = layer I, 2 = layer II, 1 = layer III)
- // 00000100 1 bit error protection (0 = enabled)
- //
- // 00F00000 4 bits bitrate_index
- // 000C0000 2 bits sampling_freq
- // 00020000 1 bit padding
- // 00010000 1 bit extension
- //
- // C0000000 2 bits mode (0=stereo, 1=joint stereo, 2=dual channel, 3=mono)
- // 30000000 2 bits mode_ext
- // 08000000 1 bit copyright
- // 04000000 1 bit original
- // 03000000 2 bits emphasis
- int is_mpeg2, layer, is_errorprotected, br_index, bitrate, sr_index, frequency;
-
- memcpy(&hdr, data, 4);
- //hdr = ((hdr&0xFF000000)>>24) | ((hdr&0x00FF0000)>>8) |
- // ((hdr&0x0000FF00)<< 8) | ((hdr&0x000000FF)<<24);
-
- is_mpeg2 = !(hdr & 0x00000800);
- layer = 4 - (hdr>>9)&3;
- is_errorprotected = !(hdr & 0x00000100);
- br_index = (hdr>>20)&15;
- bitrate = (is_mpeg2 ? mpeg2_bitrate_table : mpeg1_bitrate_table)[layer-1][br_index];
- sr_index = (hdr>>18)&3;
- frequency = mpeg1_sampling_frequency[sr_index];
- mode = (hdr>>30)&3;
-
- if (is_mpeg2)
- frequency>>=1;
-
- pTrackInfo->sample_rate = frequency;
- pTrackInfo->bit_rate = bitrate;
- pTrackInfo->channels = (mode <= 2) ? 2 : 1;
- pTrackInfo->format = MpegAudio;
- break;
- case Lpcm:
- break;
- default:
- return false;
- }
- return true;
- }
-
- #if 0
- bool Audio::GetTrackProperties(TAudioTrack *pTrack)
- {
- TTimeSpan span;
- span.start=0;
- span.end = 0;
-
-
- // Create frame FIFO
- frameFIFO = new CAudFrameBuffer();
- ReadSpanInit();
-
- while(ReadSpan(&span, 1*MPEG2_CLK_REF) )
- {
- if(frameFIFO->firstFrame==NULL)
- return false;
- else
- {
- GetPropertiesFromFrame(pTrack->nFormat, frameFIFO->firstFrame->data, pTrack);
- return true;
- break;
- }
- }
-
- safedelete(frameFIFO);
- return true;
- }
-
- #endif
-
- bool Audio::SetTrackIdsAndFormat(TAudioTrack *pTrack)
- {
- if(IsAc3Track(pTrack->nStreamId, pTrack->nSubStreamId))
- m_nFormat = Ac3;
- else if (IsMpegTrack(pTrack->nStreamId, pTrack->nSubStreamId))
- m_nFormat = MpegAudio;
- else
- return false;
-
- m_nStreamID = pTrack->nStreamId;
- m_nSubStreamID = pTrack->nSubStreamId;
-
- return true;
- }
-
- //DO_AUDIO start
- bool Audio::Start(int out_sFreq, int audioMode, TAudioProperties *pAudProps ){
-
- if(!pAudProps)
- return false;
-
- m_sAudioProperties = *pAudProps;
-
-
- // Set some other stuff.
- m_bIsPreview = (audioMode & AUDIO_PREVIEW)>0;
- m_bDontNormalize = (audioMode & AUDIO_DONT_NORMALIZE)>0;
-
- // From the track told set the format
- if(!SetTrackIdsAndFormat(&pAudProps->sAudioTrack))
- return false;
-
- // read init
- frame_in_progress = false;
- eof_flag = 0;
- aud_clk = 0;
- tot_n_samples = 0;
- StartReadLPES();
-
- if(audioMode&DO_AUDIO)
- {
- ReadSpanInit();
- justStarted = true;
-
- // Create decoders
- m_pA52Dec = new CA52Dec;
- m_pA52Dec->Init();
- MPEGDec = new CMPEGDec;
- MPEGDec->Start();
-
- // Set m_pA52Dec properties
- m_pA52Dec->SetProperties(m_sAudioProperties.dolby_surround_downmix,
- m_sAudioProperties.multichannel_volume,
- TAUDIOPROPERTIES_MCHANNEL_MAX_RANGE,
- m_sAudioProperties.center,
- m_sAudioProperties.front,
- m_sAudioProperties.rear);
-
- // Create the frame FIFO queue
- frameFIFO = new CAudFrameBuffer();
-
- // Connect all the pieces together
- if(out_sFreq!=sampleRate)
- {
- // Input and Output sample frecuencies don't match
- // Calculate relationship between them
- double factor= (double)out_sFreq/(double)sampleRate;
-
- // Create buffer for the decoded samples. Tell him the audio class
- // is its source of data
- decoded_samples_buffer = new CAsyncBuffer(this, PCM_1SECOND_SIZE, 1);
-
- // Create a resampler object, and tell him where he has to extract the data from
- resampler= new CResampler(factor, 2/*stereo*/,(CAsyncBuffer *)decoded_samples_buffer);
- resampler->ResampleFastStart();
-
- // Create the buffer where resampled samples are going to go
- ResamplerBuffer= new CAsyncBuffer(resampler, 4096, 10);
-
- // Create audio compressor
- AC.CreateCompressor( ResamplerBuffer );
- compressed_samples_buffer = new CAsyncBuffer( (CDataSource *)&AC , RMS_WINDOW*4, 20 );
-
- destination_buffer = compressed_samples_buffer;
-
- }
- else
- {
- decoded_samples_buffer= new CAsyncBuffer((CDataSource *)this, PCM_1SECOND_SIZE,1);
-
- AC.CreateCompressor( decoded_samples_buffer );
- compressed_samples_buffer = new CAsyncBuffer( (CDataSource *)&AC , RMS_WINDOW*4, 20 );
-
- destination_buffer = compressed_samples_buffer;
- }
- // Set the compressor properties
- AC.SetProperties(m_sAudioProperties.drc, m_sAudioProperties.drc_value);
-
- return true;
- }
- return false;
- }
-
-
- int Audio::SetAudioMode(int audioMode)
-
- {
-
- Audio::audioMode=audioMode;
-
-
-
- return 1;
-
- }
-
-
-
-
- //DSC start
- int Audio::Start(char *inputFileName, int audioMode)
- {
- StartReadLPES();
- //eos
- resampler=NULL;
- decoded_samples_buffer=NULL;
- ResamplerBuffer=NULL;
- frameFIFO=NULL;
-
- frameFIFO = new CAudFrameBuffer();
- ReadSpanInit();
- char szTemp[1024];
-
- if(audioMode&DSC){
- justStarted=true;
- if(m_nFormat==Ac3){
-
- strcpy(szTemp, inputFileName);
- strcat(szTemp, ".AC3");
- if((hOutputFile=fopen(szTemp,"wb"))==NULL)
- return 0;
- }
- else{
- strcpy(szTemp, inputFileName);
- strcat(szTemp, ".mp2");
- if((hOutputFile=fopen(szTemp,"wb"))==NULL)
- return 0;
- }
-
- //AlignFrame();
- justStarted=true;
- firstPTSfound=false;
- }
-
-
- return 1;
- }
-
- int Audio::Stop()
- {
- stopDecoder=true;
- justStarted=false;
-
- if(audioMode==DSC){
- //EndWritingFrame();
- //close file
- fclose(hOutputFile);
- }
- else if(audioMode==DO_AUDIO)
- {
- if(resampler)
- {
- resampler->ResampleFastStop();
- safedelete(resampler);
- }
- if(decoded_samples_buffer)
- safedelete(decoded_samples_buffer);
-
- if(ResamplerBuffer)
- safedelete(ResamplerBuffer);
-
- if(m_pA52Dec)
- safedelete(m_pA52Dec);
-
- if(MPEGDec)
- safedelete(MPEGDec) ;
- }
- if(frameFIFO)
- safedelete(frameFIFO);
-
- return 1;
- }
- /*
- int Audio::GetAudio()
- {
- int bytesRead;
- if( (bytesRead=ReadStream( buffer, AUDIO_BUFFER_SIZE)) == AUDIO_BUFFER_SIZE){
- fwrite( buffer, 1, bytesRead, hOutputFile);
- return 1;
- }
- else{
- fwrite( buffer, 1, bytesRead, hOutputFile);
- goto end;
- }
-
- end:
- // decoderStopped=true;
- return 0;
-
- }
- */
- //GetAudio Direct Stream Copy
- int Audio::GetAudioDSC(i64 PTS, i64 videoStreamPos)
- {
- TTimeSpan span;
-
- //Parse packets up to videoStreamPos
-
- while( CDemux::GetStreamPos() < (ui64)videoStreamPos){
- ReadSpan(&span, MPEG2_CLK_REF);
- while( frameFIFO->firstFrame ){
- fwrite( frameFIFO->firstFrame->data, frameFIFO->firstFrame->datasize , 1, hOutputFile);
- frameFIFO->RemoveFrame( frameFIFO->firstFrame );
- }
- }
- return 1;
- }
-
- int Audio::GetSamples(int frame, short **buffer, int nSamples)
- {
- // React to some real time changes
- if(m_bIsPreview)
- {
- AC.SetProperties(m_sAudioProperties.drc, m_sAudioProperties.drc_value);
-
- if(m_pA52Dec)
- m_pA52Dec->SetProperties(m_sAudioProperties.dolby_surround_downmix,
- m_sAudioProperties.multichannel_volume,
- TAUDIOPROPERTIES_MCHANNEL_MAX_RANGE,
- m_sAudioProperties.center,
- m_sAudioProperties.front,
- m_sAudioProperties.rear);
- }
-
- // try
- // {
- destination_buffer->ReadBuffer((char **)buffer, nSamples*4);
-
- if(m_sAudioProperties.normalize && !m_bDontNormalize)
- Normalize((i16*)*buffer, nSamples, (float)m_sAudioProperties.normalize_value/100.0f);
- // }
- // catch( ... )
- // {
- // DBG_STR((str, "Audio::GetSamples - Exception thrown!\n"))
- // eof_flag = 1;
- // }
-
- return !eof_flag;
- }
-
- void Audio::Normalize(i16 *pData, ui32 nSamples, float gain)
- {
- #define saturate(x) (((x)>32767) ? 32767 : (x) < -32768 ? -32768 : (x) )
- ui32 i;
- for(i=0; i<nSamples; i++)
- {
- pData[2*i] = (i16)saturate((float)pData[2*i] * gain);
- pData[2*i+1] = (i16)saturate((float)pData[2*i+1] * gain);
- }
- }
-
- //-----------------------------------------------------------------------------
- #define ROUND(x) ( ((x-floor(x)) > 0.5) ? ceil(x) : floor(x) )
- int Audio::read(char *buffer){
-
- TTimeSpan span;
- span.start=0;
- span.end = 0;
-
- CAudioFrame *frame, *nextframe = NULL;
-
- eof_flag = !ReadSpan(&span, 1*MPEG2_CLK_REF);
-
- if( (span.end - span.start)> (3*MPEG2_CLK_REF)/2 ) {
- DBG_STR(( str, "Audio::read - span: %I64d, %I64d ms !!\n", span.end - span.start, (span.end - span.start)/27000 ))
- span.end = span.start + (3*MPEG2_CLK_REF)/2;
- eof_flag = 1;
- }
-
- // Initialize local variables
- i32 diff;
- ui32 span_samples_offset =0;
- ui32 frame_pcm_samples;
- ui32 span_ptr = 0;
-
- // Update local audio clock, number of samples for this span,
- // and total number of samples.
- aud_clk += span.end - span.start;
- ui32 n_samples = (ui32)ROUND((double)(aud_clk*(i64)sampleRate)/(double)MPEG2_CLK_REF) - tot_n_samples;
- tot_n_samples += n_samples;
-
-
- frame_pcm_samples = m_nFormat==Ac3 ? 1536 : (m_nFormat==MpegAudio ? 1152 : 0) ;
- ui32 frame_duration = (ui32)(((double)frame_pcm_samples/(double)sampleRate) * (double)MPEG2_CLK_REF);
-
- short *samples = (short *)buffer;
- memset(samples, 0, n_samples*4);
-
-
-
- // If there was a frame in progress from the previous
- // call, copy the remaining data
- if(frame_in_progress)
- {
- memcpy( &samples[span_ptr*2], &temp_decoded_frame[temp_decoded_ptr*2], fip_remaining_bytes);
- span_ptr += (fip_remaining_bytes>>2);
- frame_in_progress = false;
- }
-
- // Loop through the frame buffer
- // and parse the frames
-
- // If there are any frames
- if(frameFIFO->firstFrame)
- {
- if(!m_bAudioInfoIsValid)
- {
- GetPropertiesFromFrame(m_nFormat, frameFIFO->firstFrame->data, &m_sAudioInfo);
- m_bAudioInfoIsValid = true;
- }
- // Take first frame
- frame = frameFIFO->firstFrame;
- while( span_ptr < n_samples )
- {
- // we update nextframe here because it's likely to remove the
- // present frame during this iteration
- nextframe = frame->next;
- // If the frame doesn't fit in this span
- if( (span_ptr + frame_pcm_samples ) > n_samples)
- {
- frame_in_progress=true;
- decodeFrame( frame, temp_decoded_frame );
- temp_decoded_ptr = n_samples - span_ptr;
- memcpy( &samples[span_ptr*2], temp_decoded_frame, temp_decoded_ptr*4);
-
- fip_remaining_bytes = (frame_pcm_samples*4) - (temp_decoded_ptr*4);
- frameFIFO->RemoveFrame(frame);
- span_ptr += temp_decoded_ptr;
- goto end;
- }
- if(frame->pInfo.hasPTS)
- {
- if( (frame->pInfo.PTS >= span.start) )
- {
- if(frame->pInfo.PTS > span.end)
- //frame out of the span
- goto end;
- // The frame starts inside this span
- /* if( (span.end - frame->pInfo.PTS) < frame_duration ){
- if(frame_in_progress){ //Oddly there is already a frame in progress. Remove it
- frameFIFO->RemoveFrame(frame);
- goto end;
- }
- //The frame doesn't completely fit into this span
- frame_in_progress=true;
-
- decodeFrame(frame, temp_decoded_frame);
-
- temp_decoded_ptr = n_samples - span_ptr;
- memcpy( &samples[span_ptr*2], temp_decoded_frame, temp_decoded_ptr*4);
-
- fip_remaining_bytes = (frame_pcm_samples*4) - (temp_decoded_ptr*4);
- frameFIFO->RemoveFrame(frame);
- span_ptr += temp_decoded_ptr;
-
- }
- else{*/
- span_samples_offset = (ui32)ROUND((double)((frame->pInfo.PTS - span.start)*sampleRate)/(double)MPEG2_CLK_REF);
- /*if(span_samples_offset < span_ptr){
- //Something went wrong with this PTS. Put this frame
- // behind the decoded data if there is room for it
- if( (span_ptr+1536) <= n_samples ){
- m_pA52Dec->decodeFrame((short *)frame->data, &samples[span_ptr*2]);
- frameFIFO->RemoveFrame(frame);
- span_ptr+= 1536;
- }
- goto end;
- }*/
- //Handle small clock jitter
- diff=span_samples_offset-span_ptr;
- if( diff < 0 )
- span_samples_offset = span_ptr;
- else
- {
- diff = (diff>0) ? diff : -diff;
- if( diff < CLK_THRESHOLD )
- span_samples_offset = span_ptr;
- }
-
- decodeFrame(frame, &samples[span_samples_offset*2]);
-
- span_ptr = span_samples_offset + frame_pcm_samples;
- frameFIFO->RemoveFrame(frame);
- /*}*/
- }
- else
- {
- //The frame has a PTS previous to this span. ┐┐??
- //HACK
- // Decode the frame if the PTS from the current time
- // is just a little bit behind
- int clk_span = (int)(((double)span_ptr/(double)sampleRate) * (double)MPEG2_CLK_REF);
- if( ((span.start+clk_span) - frame->pInfo.PTS) < CLK_THRESHOLD_SPAN)
- {
- decodeFrame( frame, &samples[span_ptr*2] );
- span_ptr += frame_pcm_samples;
- }
- frameFIFO->RemoveFrame(frame);
- }
-
- }
- else
- {
- // decode frame right away
- decodeFrame( frame, &samples[span_ptr*2] );
- span_ptr += frame_pcm_samples;
- frameFIFO->RemoveFrame(frame);
- }
-
- end:
- if( nextframe==NULL )
- break;
- else
- frame = nextframe;
- }
- }
- //else There are no frames to be decoded in this span
-
- return n_samples*4;
- }
-
- //-----------------------------------------------------------------------------
- // SetTrack() resets the audio format
- void Audio::SetTrack(TAudioTrack *pAudioTrack)
- {
- // From the track told set the format
- if(!SetTrackIdsAndFormat(pAudioTrack))
- return;
-
- if(frameFIFO)
- frameFIFO->RemoveAllFrames();
-
- //Reset the state of all frames being grabbed
- read_state.frame_in_course = false;
- read_state.header_in_course = false;
- read_state.frame_size = 0;
- read_state.frame_remaining_bytes = 0;
- header_pos = 0;
-
- // Invalidate info
- m_bAudioInfoIsValid = false;
- }
- //-----------------------------------------------------------------------------
- int inline Audio::ReadSpan(TTimeSpan *span, i64 time)
- {
- int not_eof;
-
- not_eof=1;
- span->start = read_state.lastSCR;
- span->end = span->start;
- while( ((span->end - span->start) < time) && not_eof)
- {
- if( m_nStreamID == read_state.PES.pInfo.streamID &&
- m_nSubStreamID == read_state.PES.pInfo.subStreamID )
- ParseFrameData();
-
- not_eof=ReadLPES((unsigned char **)&read_state.PES.data, &read_state.PES.pInfo);
- if(!not_eof)
- break;
-
- span->end = read_state.PES.pInfo.SCR;
-
- // Update variables for next loop
- read_state.lastSCR = read_state.PES.pInfo.SCR;
- }
- return not_eof;
- }
-
-
- //-----------------------------------------------------------------------------
- int inline Audio::RetrieveFrameData()
- {
- ui32 PES_bytes_left = read_state.PES.pInfo.payloadSize - read_state.in_ptr;
- ui8 *optr = &read_state.frame_data[read_state.out_ptr];
- ui8 *iptr = read_state.PES.data + read_state.in_ptr;
-
- if(read_state.frame_remaining_bytes <= PES_bytes_left){
- memcpy(optr, iptr, read_state.frame_remaining_bytes);
- // Add frame to the FIFO
- frameFIFO->AddFrame( read_state.frame_data,
- read_state.frame_size,
- &read_state.frame_pInfo);
- read_state.frame_in_course = false;
- read_state.in_ptr += read_state.frame_remaining_bytes;
- return 1;
- }
- else{
- memcpy(optr, iptr, PES_bytes_left);
- read_state.frame_in_course = true;
- read_state.out_ptr += PES_bytes_left;
- read_state.frame_remaining_bytes -= PES_bytes_left;
- return 0;
- }
- }
-
-
- //-----------------------------------------------------------------------------
- void inline Audio::ParseFrameData()
- {
- ui32 headers_found = 0;
-
- read_state.in_ptr = 0;
-
- // take any possible audio frame and put it in the audio frame FIFO
- // we enter in this function when a PES of our ID was found
-
- // parse the frame in course
- if(read_state.frame_in_course){
- if(!RetrieveFrameData())
- return;
- }
- // wh
- while( read_state.in_ptr < read_state.PES.pInfo.payloadSize ){
- if(FindHeader(headers_found)){
- //An audio header was found
- headers_found++;
- if(!RetrieveFrameData())
- return;
- }
- else
- break;
- }
-
- }
-
- //-----------------------------------------------------------------------------
- int inline Audio::ParseHeader(ui32 headers_found)
- {
-
-
- ui8 *data = read_state.PES.data;
- ui8 fscod;
- ui8 frmsizecode;
-
-
-
- if(m_nFormat==Ac3){
- if( data[read_state.in_ptr]==0x0B && header_pos==0){
- read_state.header_in_course = true;
- header_pos = 1;
- //Handle presentation info
- if( (read_state.PES.pInfo.PTS != 0) && (headers_found==0) )
- {
- read_state.frame_pInfo.hasPTS = true;
- read_state.frame_pInfo.PTS = read_state.PES.pInfo.PTS;
- // Now reset the PTS so its not used again
- read_state.PES.pInfo.PTS = 0;
- }
- else
- {
- read_state.frame_pInfo.hasPTS = false;
- read_state.frame_pInfo.PTS = 0;
- }
- return 0;
- }
-
- if( data[read_state.in_ptr]==0x77 && header_pos==1){
- read_state.header_in_course = true;
- header_pos = 2;
- return 0;
- }
- if( header_pos==2 ){
- read_state.header_in_course = true;
- hdr2 = data[read_state.in_ptr];
- header_pos = 3;
- return 0;
- }
- if( header_pos==3 ){
- read_state.header_in_course = true;
- hdr3 = data[read_state.in_ptr];
- header_pos = 4;
- return 0;
- }
- if( header_pos==4 ){
- read_state.header_in_course = true;
- fscod = (data[read_state.in_ptr] & 0xC0) >> 6;
- frmsizecode = (data[read_state.in_ptr] & 0x3F);
-
- // Check fscod and frmsizecode for valid parameters
- if( (fscod!=3) && (frmsizecode<38) ){
- read_state.frame_size = framesize_table[frmsizecode].frm_size[fscod]*2;
-
- //Reconstruct frame header
- read_state.frame_data[0] = 0x0B;
- read_state.frame_data[1] = 0x77;
- read_state.frame_data[2] = hdr2;
- read_state.frame_data[3] = hdr3;
- read_state.frame_data[4] = data[read_state.in_ptr];
-
-
-
- read_state.frame_remaining_bytes = read_state.frame_size - 5;
- read_state.out_ptr = 5;
- header_pos = 0;
- return 1;
- }
- }
- }
-
- if(m_nFormat==MpegAudio)
- {
- if( data[read_state.in_ptr]==0xFF && header_pos==0)
- {
- // MPEG audio header 0xFFF-
- read_state.header_in_course = true;
- header_pos = 1;
- //Handle presentation info
- if( (read_state.PES.pInfo.PTS != 0) && (headers_found==0) )
- {
- read_state.frame_pInfo.hasPTS = true;
- read_state.frame_pInfo.PTS = read_state.PES.pInfo.PTS;
- // Now reset the PTS so its not used again
- read_state.PES.pInfo.PTS = 0;
- }
- else
- {
- read_state.frame_pInfo.hasPTS = false;
- read_state.frame_pInfo.PTS = 0;
- }
- mpeg_header[0] = data[read_state.in_ptr];
- return 0;
- }
- if( (data[read_state.in_ptr]&0xF8)==0xF8 && header_pos==1)
- {
- // MPEG audio header
-
- mpeg_layer = (data[read_state.in_ptr]&0x06)>>1;
- if( mpeg_layer==3 ) //If the frame is Layer I
- mpeg_layer=1;
- else
- if( mpeg_layer==1 ) //If the frame is Layer III
- mpeg_layer=3;
- if( !mpeg_layer )
- header_pos = 0;
- else
- header_pos = 2;
-
- mpeg_header[1] = data[read_state.in_ptr];
-
- read_state.header_in_course = true;
- header_pos = 2;
- return 0;
- }
- if( header_pos==2 )
- {
- read_state.header_in_course = true;
-
- bit_rate_index = (data[read_state.in_ptr]&0xF0)>>4;
- if( bit_rate_index == 16 || bit_rate_index == 0 )
- {
- header_pos = 0;
- return 0;
- }
- bitrate = mpeg1_bitrate_table[mpeg_layer-1][bit_rate_index]*1000;
- sampling_frequency = (data[read_state.in_ptr]&0x0C)>>2;
- if( sampling_frequency == 3 )
- {
- header_pos = 0;
- return 0;
- }
- padding_bit = (data[read_state.in_ptr]&0x02)>>1;
- //Find number of slots and frame size
- if(mpeg_layer == 1)
- {
- N = (i32)floor( (12 *(double)bitrate)/(double)mpeg1_sampling_frequency[sampling_frequency] );
- N = padding_bit ? (N+1) : N;
- read_state.frame_size = N*4;
- }
- else
- {
- N = (i32)floor( (144*(double)bitrate)/(double)mpeg1_sampling_frequency[sampling_frequency] );
- N = padding_bit ? (N+1) : N;
- read_state.frame_size = N;
- }
-
- mpeg_header[2] = data[read_state.in_ptr];
- memcpy( read_state.frame_data, mpeg_header, 3);
-
- read_state.frame_remaining_bytes = read_state.frame_size - 3;
- read_state.out_ptr = 3;
- header_pos = 0;
- return 1;
- }
- }
- header_pos = 0;
- read_state.header_in_course = false;
- return 0;
- }
-
- int inline Audio::FindHeader(ui32 headers_found)
- {
- int header_found = false;
-
-
- //Search for an audio header from the current position
- while( read_state.in_ptr < read_state.PES.pInfo.payloadSize ){
- header_found = ParseHeader(headers_found);
- read_state.in_ptr++;
- if(header_found)
- break;
- }
-
- return header_found;
-
- }
- int Audio::ReadSpanInit()
- {
-
- //Force first time
- read_state.frame_in_course = false;
- read_state.header_in_course = false;
- read_state.frame_size = 0;
- read_state.frame_remaining_bytes = 0;
- read_state.lastSCR = 0;
- read_state.delta = 0;
- header_pos = 0;
- ReadLPES((unsigned char **)&read_state.PES.data, &read_state.PES.pInfo);
-
- return 1;
- }
-
- int inline Audio::decodeFrame(CAudioFrame *frame, short *pcm_samples)
- {
- if(m_nFormat==Ac3)
- {
- if(m_pA52Dec)
- m_pA52Dec->decodeFrame((ui8 *)pcm_samples, frame->data, frame->datasize );
- return 1536;
- }
- if(m_nFormat==MpegAudio)
- {
- MPEGDec->decodeFrame( (ui8 *)pcm_samples, frame->data, frame->datasize );
- return 1152;
- }
- return 0;
- }
-
-