MP3.c
上传用户:super_houu
上传日期:2008-09-21
资源大小:4099k
文件大小:29k
- /****************************************************************************************
- * Copyright (c) 2000 ZORAN Corporation, All Rights Reserved
- * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ZORAN CORPORATION
- *
- * File: $Workfile: MP3.c $
- *
- * Description:
- * ============
- * MP3 Clip implementation
- *
- * Log:
- * ====
- ****************************************************************************************
- * Updates:
- ****************************************************************************************
- * $Log: /I76/I76_Common/I76_Reference/Playcore/Nav_Clips/MP3.c $
- *
- ****************************************************************************************/
- #include "Config.h" // Global Configuration - do not remove!
- #ifdef _DEBUG
- #undef IFTRACE
- #define IFTRACE if (gTraceNavigator)
- #include "DebugDbgMain.h"
- #endif
- #include "DecoderDecoder.h"
- #include "DecoderDec_defs.h"
- #include "Decoderlow_levelDEC_LL_Def.h"
- #include "Drivedrv_api.h"
- #include "Drivedrv_defs.h"
- #include "LogoLogo.h"
- #include "PlaycoreCoremainCoreGDef.h"
- #include "PlaycoreAuxCacheAuxCache.h"
- #include "PlaycoreFileSysFileSystem.h"
- #include "PlaycoreNav_ClipsMP3.h"
- #include "PlaycoreNav_ClipsClip_Impl.h"
- #include "PlaycoreNav_ClipsGenericClip.h"
- #include "PlaycoreNav_ClipsNav_Clips.h"
- #include "PlaycoreNav_ClipsPE_Clips.h"
- #include "PlaycoreNav_CDDAPE_CD.h"
- /////////////////////////////////////////////////////////////////////////////
- // General MP3
- /////////////////////////////////////////////////////////////////////////////
- #define m_frameBytes gns.clips.globals.mp3Globals.m_frameBytes
- #define dwUsPerFrame gns.clips.globals.mp3Globals.dwUsPerFrame
- #define aHeaderBuffer gns.clips.globals.mp3Globals.aHeaderBuffer
- #define uiBuffNo gns.clips.globals.mp3Globals.uiBuffNo
- #define dwClipStartAddrForHeadBuffer gns.clips.globals.mp3Globals.dwClipStartAddrForHeadBuffer
- #define m_pXingHeader gns.clips.globals.mp3Globals.m_pXingHeader
- #define ucMP3PlayabckFinishedCounter gns.clips.globals.mp3Globals.ucMP3PlayabckFinishedCounter
- typedef struct
- {
- int sync; /* 1 if valid sync */
- int id;
- int option;
- int prot;
- int br_index;
- int sr_index;
- int pad;
- int private_bit;
- int mode;
- int mode_ext;
- int cr;
- int original;
- int emphasis;
- } MPEG_HEAD;
- static CONST int mp_br_table[2][16] =
- {
- {0, 8 , 16, 24, 32, 40, 48, 56 , 64 , 80 , 96 , 112, 128, 144, 160, 0},
- {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0}
- };
- static CONST int mp_sr20_table[2][4] =
- {
- {441, 480, 320, -999},
- {882, 960, 640, -999}
- };
- static CONST int mp_br_tableL1[2][16] =
- {
- {0, 32, 48, 56, 64 , 80 , 96 , 112, 128, 144, 160, 176, 192, 224, 256, 0}, /* mpeg2 */
- {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0}
- };
- static CONST int mp_br_tableL3[2][16] =
- {
- {0, 8 , 16, 24, 32, 40, 48, 56, 64 , 80 , 96 , 112, 128, 144, 160, 0}, /* mpeg 2 */
- {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}
- };
- static CONST DWORD sample_rate_table[8] =
- {
- 22050L, 24000L, 16000L, 1L, 44100L, 48000L, 32000L, 1L
- };
- static CONST int l[4] = {25, 3, 2, 1};
- static int head_info(DWORD offset, unsigned int n, MPEG_HEAD * h);
- static int head_info3(DWORD offset, unsigned int n, MPEG_HEAD *h, unsigned int *searchForward);
- static int head_info2(DWORD offset, unsigned int n, MPEG_HEAD * h);
- static void GetBitstreamStats(DWORD dwClipStartAddr, int *piTotalSeconds);
- static BOOL GetHeadInfo(DWORD dwClipStartAddr, MPEG_HEAD * pm_sMpegHead, int *pm_frameBytes);
- static void InitHeaderBuff(BYTE * buff, DWORD dwClipStartAddr);
- static BYTE GetCharFromDisc(DWORD n);
- static BOOL GetXingHeader(XHEADDATA *X, DWORD offset);
- ////////////////////////////////////////////////////////////////////////////
- // Forward Declarations of Virtual Methods
- BOOL MP3Clip_getExtendedInfo(const struct Clip_TAG *i_pThis,
- WORD i_pExtInfo_sc_handle);
- void MP3Clip_refresh(Clip *i_pThis);
- enClipStatus MP3_getStatus(const Clip *i_pThis);
- void MP3_scan(Clip *i_pThis, int iScanSpeed);
- void MP3_recordMarker(Clip *i_pThis, ClipMarker *o_pMarker);
- void MP3_pause(Clip *i_pThis, BOOL bEnable);
- BOOL MP3_play(Clip *i_pThis, const ClipMarker *i_pResumeMarker,
- BOOL bCacheOnly);
- UINT16 MP3Clip_GetTime(Clip *i_pThis);
- /////////////////////////////////////////////////////////////////////////////
- // Constants and Enumerations
- #define MAX_FRAME_SIZE 1441L
- #define NUM_OF_SANITY_CHECK 3L
- #define INITIAL_FRAME_SIZE (MAX_FRAME_SIZE * NUM_OF_SANITY_CHECK)
- #define MAX_DECODING_RETRY 32
- #define TEMP_BUFF_SIZE 128
- #define FRAMES_FLAG 0x0001
- #define BYTES_FLAG 0x0002
- #define MPEG_FRAMES_TO_SAMPLE 80
- #define ID3_GENRE_COUNT 116
- #define ID3_GENRE_DEFAULT 255
- #ifdef EXINO2 // ZKR GL041804 : No need to delay fo finishing the playback.
- #define DEFAULT_MP3_PLAYBACK_FINISHED_COUNTER 0
- #else
- #define DEFAULT_MP3_PLAYBACK_FINISHED_COUNTER 10
- #endif
- LPWSTR _str2wcs(LPCSTR pszSource, LPWSTR pszDest, unsigned int cbDestSize);
- /////////////////////////////////////////////////////////////////////////////
- // Globals and Singletons
- // Valid Extenions List
- BEGIN_CLIP_VALID_EXTENSIONS_MAP(MP3)
- CLIP_VALID_EXTENSIONS_ENTRY(L"MP3")
- CLIP_VALID_EXTENSIONS_ENTRY(L"MP2")
- END_CLIP_VALID_EXTENSIONS_MAP()
- // Constant Attributes
- DECLARE_CLIP_CONST_ATTR(MP3,
- DECLARE_CLIP_VTABLE(MP3Clip_getExtendedInfo,
- MP3_play,
- MP3_pause,
- MP3_getStatus,
- GenericClip_abort,
- MP3_recordMarker,
- MP3Clip_refresh,
- MP3Clip_GetTime,
- GenericClip_digest,
- MP3_scan
- ),
- eClipType_MP3,
- DEC_ASID_MP3, 0xFF, DEC_DISC_TYPE_MP3,
- ( eCA_Markable | eCA_Scanable ),
- NULL
- )
- #ifdef MOTOROLA
- #define BE_DWORD(a) a
- #define BE_WORD(a) a
- #else
- #define BE_DWORD(a) (DWORD)((a << 24) | ((a & 0xFF00) << 8) | ((a & 0xFF0000L) >> 8) | ((a & 0xFF000000L) >> 24))
- #define BE_WORD(a) (WORD)((a << 8) | (a >> 8))
- #endif // MOTOROLA
- #if (defined(CLIPS_ACQUIRE_EXTENDED_INFO) && defined(CLIPS_MP3_EXTRACT_ID3V1_TAG))
- BOOL isFailedToReadMP3Head = FALSE;
- static CONST LPSTR g_pszEmptyField= " ";
- static CONST LPWSTR g_aMP3_ID3Genres[ID3_GENRE_COUNT+1] =
- { L"", L"Blues", L"Classic Rock", L"Country", L"Dance", L"Disco", L"Funk", L"Grunge",
- L"Hip-Hop", L"Jazz", L"Metal", L"New Age", L"Oldies", L"Other", L"Pop", L"R&B",
- L"Rap", L"Reggae", L"Rock", L"Techno", L"Industrial", L"Alternative", L"Ska",
- L"Death Metal", L"Pranks", L"Soundtrack", L"Euro-Techno", L"Ambient",
- L"Trip-Hop", L"Vocal", L"Jazz+Funk", L"Fusion", L"Trance", L"Classical",
- L"Instrumental", L"Acid", L"House", L"Game", L"Sound Clip", L"Gospel", L"Noise",
- L"Alt. Rock", L"Bass", L"Soul", L"Punk", L"Space", L"Meditative", L"Instrumental Pop",
- L"Instrumental Rock", L"Ethnic", L"Gothic", L"Darkwave", L"Techno-Industrial",
- L"Electronic", L"Pop-Folk", L"Eurodance", L"Dream", L"Southern Rock", L"Comedy",
- L"Cult", L"Gangsta", L"Top 40", L"Christian Rap", L"Pop/Funk", L"Jungle",
- L"Native American", L"Cabaret", L"New Wave", L"Psychadelic", L"Rave",
- L"Showtunes", L"Trailer", L"Lo-Fi", L"Tribal", L"Acid Punk", L"Acid Jazz",
- L"Polka", L"Retro", L"Musical", L"Rock & Roll", L"Hard Rock", L"Folk",
- L"Folk/Rock", L"National Folk", L"Swing", L"Fast-Fusion", L"Bebob", L"Latin", L"Revival",
- L"Celtic", L"Bluegrass", L"Avantgarde", L"Gothic Rock", L"Progressive Rock",
- L"Psychadelic Rock", L"Symphonic Rock", L"Slow Rock", L"Big Band", L"Chorus",
- L"Easy Listening", L"Acoustic", L"Humour", L"Speech", L"Chanson", L"Opera",
- L"Chamber Music", L"Sonata", L"Symphony", L"Booty Bass", L"Primus",
- L"Porn Groove", L"Satire", L"Slow Jam", L"Club", L"Tango", L"Samba", L"Folklore"
- };
- // The Frame Bitrate according to the MPEG-Layer (MPEG Audio 1.0, Section 2.4.2.3)
- static CONST UINT16 g_aBitrateByMpeg1Layer[15][3] =
- {
- { 0 , 0 , 0 },
- { 32 , 32 , 32 },
- { 64 , 48 , 40 },
- { 96 , 56 , 48 },
- { 128, 64 , 56 },
- { 160, 80 , 64 },
- { 192, 96 , 80 },
- { 224, 112, 96 },
- { 256, 128, 112 },
- { 288, 160, 128 },
- { 320, 192, 160 },
- { 352, 224, 192 },
- { 384, 256, 224 },
- { 416, 320, 256 },
- { 448, 384, 320 }
- };
- static CONST UINT16 g_aBitrateByMpeg2Layer[15][3] =
- {
- { 0 , 0 , 0 },
- { 32 , 32 , 8 },
- { 64 , 48 , 16 },
- { 96 , 56 , 24 },
- { 128, 64 , 32 },
- { 160, 80 , 64 },
- { 192, 96 , 80 },
- { 224, 112, 56 },
- { 256, 128, 64 },
- { 288, 160, 128 },
- { 320, 192, 160 },
- { 352, 224, 112 },
- { 384, 256, 128 },
- { 416, 320, 256 },
- { 448, 384, 320 }
- };
- #endif //(CLIPS_ACQUIRE_EXTENDED_INFO) && (CLIPS_MP3_EXTRACT_ID3V1_TAG)
- /////////////////////////////////////////////////////////////////////////////
- // Private Services
- #pragma argsused
- void MP3_setPresentationTime(UINT8 uPresentationTime)
- {
- dbg_printf(("WARNING: MP3_setPresentationTime() Failed: MP3 Clips cannot have a presentation time.n"));
- }
- #if (defined(CLIPS_ACQUIRE_EXTENDED_INFO) && defined(CLIPS_MP3_EXTRACT_ID3V1_TAG))
- BOOL MP3_getID3v1Tag(DWORD dwClipStartAddr, DWORD cbClipSize,
- WORD i_pExtInfo_sc_handle)
- {
- INT32 iOffset;
- BYTE aTagBuffer[ID3V1_SIZE];
- UINT16 uBlocksCnt;
- DWORD dwStartLBA;
- //Angie_0810_2004:Move the MP3 and WMA extend info from gns to SCPAD for I86 memory reducing.
- MP3_ID3v1Tag o_pID3v1Tag;
- // Reset the result
- memset(&o_pID3v1Tag, 0, sizeof(MP3_ID3v1Tag));
- o_pID3v1Tag.pszGenre= g_aMP3_ID3Genres[0];
- // First of all, calculate the LBA to fetch, and the offset within that LBA
- // in which the ID3v1-Tag should reside (the last 128 Bytes of the Clip).
- uBlocksCnt= (UINT16)(cbClipSize / LOGICAL_BLOCK_SIZE);
- dwStartLBA= (dwClipStartAddr + uBlocksCnt);
- iOffset= (cbClipSize - (LOGICAL_BLOCK_SIZE * (ULONG)uBlocksCnt) - ID3V1_SIZE);
- if (iOffset < 0)
- {
- UINT32 uPortionOfLastSector= (cbClipSize - (LOGICAL_BLOCK_SIZE * (ULONG)uBlocksCnt));
- iOffset= (LOGICAL_BLOCK_SIZE - (ID3V1_SIZE - uPortionOfLastSector));
- dwStartLBA--;
- }
- // Now fetch the last 128 Bytes of the Clip
- if (! AuxCache_GetBytes(dwStartLBA, (DWORD)iOffset, ID3V1_SIZE, aTagBuffer))
- {
- dbg_printf(("Failed to extract an MP3-ID3v1 Tag.n"));
- isFailedToReadMP3Head = TRUE;
- drv_abort_play();
- return FALSE;
- }
- // Examine the Buffer, and search for the "TAG" identifier
- if (0 != strncmp((LPCSTR)aTagBuffer, "TAG", 3))
- {
- // The Clip doesn't have an ID3v1 Tag
- return FALSE;
- }
- // Copy the various fields into the destination Tag, converted into UNICODE-CS0
- if (0 != memcmp((LPCSTR)&aTagBuffer[3], g_pszEmptyField, ID3V1_TEXT_LENGTH));
- _str2wcs((LPCSTR)&aTagBuffer[3], o_pID3v1Tag.szSongName, sizeof(o_pID3v1Tag.szSongName));
- if (0 != memcmp((LPCSTR)&aTagBuffer[33], g_pszEmptyField, ID3V1_TEXT_LENGTH))
- _str2wcs((LPCSTR)&aTagBuffer[33], o_pID3v1Tag.szArtist, sizeof(o_pID3v1Tag.szArtist));
- if (0 != memcmp((LPCSTR)&aTagBuffer[63], g_pszEmptyField, ID3V1_TEXT_LENGTH))
- _str2wcs((LPCSTR)&aTagBuffer[63], o_pID3v1Tag.szAlbum, sizeof(o_pID3v1Tag.szAlbum));
- if (0 != memcmp((LPCSTR)&aTagBuffer[93], g_pszEmptyField, 4))
- _str2wcs((LPCSTR)&aTagBuffer[93], o_pID3v1Tag.szYear, sizeof(o_pID3v1Tag.szYear));
- if (0 != memcmp((LPCSTR)&aTagBuffer[97], g_pszEmptyField, ID3V1_TEXT_LENGTH))
- _str2wcs((LPCSTR)&aTagBuffer[97], o_pID3v1Tag.szComment, sizeof(o_pID3v1Tag.szComment));
- // Extrapulate the Track-Number field: if the Comment field's next-to-last char
- // is NULL, then the last char is the Track-Number.
- if (0 == o_pID3v1Tag.szComment[ID3V1_TEXT_LENGTH-2])
- o_pID3v1Tag.uTrackNum= o_pID3v1Tag.szComment[ID3V1_TEXT_LENGTH-1];
- else
- o_pID3v1Tag.uTrackNum= 0;
- // Assign the Genre-name
- if ((ID3_GENRE_DEFAULT == aTagBuffer[127]) || (ID3_GENRE_COUNT <= aTagBuffer[127]))
- o_pID3v1Tag.pszGenre= g_aMP3_ID3Genres[0]; // The Default Genre, or an Undefined one
- else
- o_pID3v1Tag.pszGenre= g_aMP3_ID3Genres[aTagBuffer[127] + 1];
- sc_SetBytes(i_pExtInfo_sc_handle,0,sizeof(MP3_ID3v1Tag),(BYTE *)&o_pID3v1Tag);
-
- drv_abort_play();
- return TRUE;
- }
- #endif //(CLIPS_ACQUIRE_EXTENDED_INFO) && (CLIPS_MP3_EXTRACT_ID3V1_TAG)
- /////////////////////////////////////////////////////////////////////////////
- // Public Services
- BOOL MP3Clip_isKindOf(LPCWSTR i_pszFilename)
- {
- return GenericClip_isKindOf(i_pszFilename, CLIP_VALID_EXTENSIONS(MP3));
- }
- void MP3Clip_construct(Clip *o_pThis, const FindData *i_pFileInfo)
- {
- GenericClip_construct(o_pThis, i_pFileInfo);
- o_pThis->m_pConstAttr= &CLIP_CONST_ATTR(MP3);
- }
- /////////////////////////////////////////////////////////////////////////////
- // Virtual Methods
- BOOL MP3Clip_getExtendedInfo(const struct Clip_TAG *i_pThis,
- WORD i_pExtInfo_sc_handle)
- {
- BOOL bSuccess= FALSE;
- int iTotalSeconds;
- dbg_printf(("MP3Clip_getExtendedInfo()n"));
- #ifdef CLIPS_MP3_EXTRACT_ID3V1_TAG
- ASSERT(NULL != i_pExtInfo_sc_handle)
-
- bSuccess= MP3_getID3v1Tag(i_pThis->m_cfiInfo.dwFileLocation,
- i_pThis->m_cfiInfo.cbFileSize,
- i_pExtInfo_sc_handle);
- #endif //CLIPS_MP3_EXTRACT_ID3V1_TAG
- GetBitstreamStats(i_pThis->m_cfiInfo.dwFileLocation, &iTotalSeconds);
- gns.clips.uTotalPlaybackTime = iTotalSeconds;
- return bSuccess;
- }
- #pragma argsused
- void MP3Clip_refresh(Clip *i_pThis)
- {
- UINT32 dwBufferLevel;
- if (PST_PLAY == gcs.pstate)
- {
- BOOL bEnableClock;
- dwBufferLevel = DEC_ReadCodeBufferFullness(DEC_AUDIO_CODE_BUFFER, DEC_FULLNESS_IN_BYTES);
- if (dwBufferLevel == 0)
- {
- bEnableClock = FALSE;
- }
- else
- {
- bEnableClock = TRUE;
- }
- if ( (0 == dwBufferLevel) && drv_is_play_done())
- {
- PE_Clips_EnableClock(bEnableClock, TRUE, 0);
- }
- else
- {
- PE_Clips_EnableClock(bEnableClock, FALSE, 0);
- }
- }
- else
- {
- if ( (PST_SCAN == gcs.pstate) && (eCS_Finished == MP3_getStatus(i_pThis)) )
- {
- PE_Clips_EnableClock(FALSE, TRUE, 0);
- }
- }
- }
- enClipStatus MP3_getStatus(const Clip *i_pThis)
- {
- static UINT16 uiWatchDog = 100; // 10s, called on 100ms tick.
- static UINT16 uLastReadTime;
- if (PST_PLAY == gcs.pstate)
- {
- if (PE_Clips_GetClock() == uLastReadTime)
- {
- // either decoder got stuck or drive is trying to bring data.
- uiWatchDog--;
- }
- else
- {
- uiWatchDog = 100;
- uLastReadTime = PE_Clips_GetClock();
- }
- if (0 == uiWatchDog)
- {
- uiWatchDog = 100;
- return eCS_Finished;
- }
- }
- else
- {
- uiWatchDog = 100;
- }
- if (PST_SCAN != gcs.pstate)
- {
- if (drv_is_play_done() && DEC_IsPlaybackFinished(FALSE))
- {
- if (0 == ucMP3PlayabckFinishedCounter)
- {
- return eCS_Finished;
- }
- else
- {
- ucMP3PlayabckFinishedCounter--;
- return eCS_Busy;
- }
- }
-
- ucMP3PlayabckFinishedCounter = DEFAULT_MP3_PLAYBACK_FINISHED_COUNTER;
- return eCS_Busy;
- }
- else
- {
- UINT16 uCurrTime = PE_Clips_GetClock();
- // Check if Scan in current Clip is finished
- if ( (uCurrTime >= gns.clips.uTotalPlaybackTime) ||
- (0 == uCurrTime) )
- {
- return eCS_Finished;
- }
- else
- {
- return eCS_Busy;
- }
- }
- }
- void MP3_pause(Clip *i_pThis, BOOL bEnable)
- {
- if ( (PST_SCAN == gcs.pstate) || (0 != gns.clips.iScanSpeed) )
- {
- if (bEnable)
- {
- PE_Clips_EnableClock(FALSE, FALSE, 0);
- }
- else
- {
- if (PST_PLAY == gcs.pstate)
- {
- gns.clips.iScanSpeed = 0;
- }
-
- MP3_scan(i_pThis, gns.clips.iScanSpeed);
- }
- }
- else
- {
- GenericClip_pause(i_pThis, bEnable);
- }
- }
- BOOL MP3_play(Clip *i_pThis, const ClipMarker *i_pResumeMarker,
- BOOL bCacheOnly)
- {
- DWORD dwStartLBA;
- ULONG ulBlocksCnt, cbPlaybackLength;
- dbg_printf(("MP3_play()n"));
- ucMP3PlayabckFinishedCounter = DEFAULT_MP3_PLAYBACK_FINISHED_COUNTER;
- // Cached-playback is unsupported by default
- if (bCacheOnly)
- return FALSE;
- drv_abort_play();
-
- // Kill any existing Zoom
- DEC_SetZoomScale(NO_ZOOM);
- // Configure the Decoder to the appropriate Bitstream Type
- DEC_SetDiskType((i_pThis->m_pConstAttr)->m_eBitstreamType);
- // Prepare for decoding
- DEC_prepare_to_decode();
- #ifdef CLIPS_MP3_EXTRACT_ID3V1_TAG
- if (gns.clips.cieCurrClip.mpeginfo.uLayer == IS_LAYER_II)
- {
- DEC_SetSID(DEC_SID_TYPE_AUDIO, MPEG_SID0);
- }
- else
- #endif
- {
- DEC_SetSID(DEC_SID_TYPE_AUDIO, MP3_SID);
- }
-
- DEC_SetSID(DEC_SID_TYPE_VIDEO, (i_pThis->m_pConstAttr)->m_eVideoSID);
- // Set audio ID for MP2 again.
- #ifdef CLIPS_MP3_EXTRACT_ID3V1_TAG
- if (gns.clips.cieCurrClip.mpeginfo.uLayer == IS_LAYER_II)
- {
- DEC_SetSID(DEC_SID_TYPE_AUDIO, MPEG_SID0);
- }
- #endif
- // Select the appropriate Clock
- PE_Clips_SelectClock(eCT_Internal);
- // Calculate the Playback Start-Address
- if (NULL == i_pResumeMarker)
- {
- // Start at the beginning
- dwStartLBA= (i_pThis->m_cfiInfo).dwFileLocation;
-
- }
- else
- {
- // Playback is being resumed
- dwStartLBA= i_pResumeMarker->dwAddress;
- }
- // Calculate the Playback Length (in Bytes)
- cbPlaybackLength= ( (i_pThis->m_cfiInfo).cbFileSize -
- (LOGICAL_BLOCK_SIZE * (dwStartLBA - (i_pThis->m_cfiInfo).dwFileLocation)) );
-
- ulBlocksCnt= ((cbPlaybackLength + LOGICAL_BLOCK_SIZE - 1) / LOGICAL_BLOCK_SIZE);
- // Inform the Decoder of the Playback-Range
- PE_Clips_SetPlaybackRange(dwStartLBA, ulBlocksCnt, cbPlaybackLength/2);
- // Invoke playback of the Decoder & Drive
- // NOTE: The order of invocation is important, and must not be changed!
- DEC_PlaybackCommand(DEC_PLAYBACK_CMD_PLAY, NULL);
- if (!PE_Clips_Playback_Sectors(DRVCF_CDSPEED_1X | DRVF_PLAY_CD_AV_DATA, dwStartLBA, ulBlocksCnt))
- {
- tr_printf(("WARNING: MP3_play() Failed [1]n"));
- return FALSE;
- }
- // Restart the Clock
- PE_Clips_EnableClock(TRUE, TRUE,
- (NULL != i_pResumeMarker) ? i_pResumeMarker->uTime : 0);
- return TRUE;
- }
- void MP3_scan(Clip *i_pThis, int iScanSpeed)
- {
- UINT16 ulCurrTime = PE_Clips_GetClock();
- dbg_printf(("MP3 Scan(%d)n", iScanSpeed));
- if (iScanSpeed != 0)
- {
- if (0 < iScanSpeed && 0 == ulCurrTime)
- {
- ulCurrTime = 1;
- }
-
- PE_Clips_SelectClock(eCT_Internal);
- PE_Clips_EnableClock(TRUE, TRUE, ulCurrTime); // Reset curent clock
- if (PST_PLAY == gcs.pstate)
- {
- PE_CD_AbortPlayback(TRUE);
- }
- gcs.pstate = PST_SCAN;
- gns.clips.iScanSpeed = iScanSpeed;
- }
- else
- {
- ClipMarker mClipMarker;
- PE_Clips_SelectClock(eCT_Decoder);
- // Cancel Scan during Scan mode
- mClipMarker.dwAddress = MP3_Time_To_Address(ulCurrTime);
- mClipMarker.uTime = ulCurrTime;
- gns.clips.iScanSpeed = 0;
- gcs.pstate = PST_PLAY;
- dbg_printf(("Resume from %lx, file start address is %lxn", mClipMarker.dwAddress, i_pThis->m_cfiInfo.dwFileLocation));
- (i_pThis->m_pConstAttr->m_vtable.m_pfPlay)(i_pThis, &mClipMarker, FALSE);
- }
- return;
- }
- void MP3_recordMarker(Clip *i_pThis, ClipMarker *o_pMarker)
- {
- if (NULL != o_pMarker)
- {
- DWORD dwStartAddress, dwJumpOffset;
- UINT16 uiTime;
-
- // Record the current position
- uiTime = PE_Clips_GetClock();
-
- o_pMarker->uTime = uiTime;
-
- dwStartAddress = MP3_Time_To_Address(uiTime);
-
- o_pMarker->dwAddress = dwStartAddress;
-
- o_pMarker->uClipNumer = gns.clips.uCurrentClipNumber;
- }
- return;
- }
- UINT16 MP3Clip_GetTime(Clip *i_pThis)
- {
- UINT16 iCurrentTime;
- // Update Current Elapsed Time
- iCurrentTime = PE_Clips_GetClock();
- return iCurrentTime;
- }
- DWORD MP3_Time_To_Address(WORD uTime)
- {
- DWORD dwJumpOffset;
-
- if (dwUsPerFrame)
- {
- dwJumpOffset = ((DWORD)(uTime)*1000000/dwUsPerFrame *m_frameBytes)>>11;
- }
- else
- {
- dwJumpOffset = 0;
- }
- return (gns.clips.cieCurrClip.ciInfo.dwFileLocation) + dwJumpOffset;
- }
- /*--------------------------------------------------------------*/
- static int head_info(DWORD offset, unsigned int n, MPEG_HEAD * h)
- {
- int framebytes;
- int mpeg25_flag;
- if (n > 10000)
- n = 10000; /* limit scan for free format */
- h->sync = 0;
- //if ((GetCharFromDisc(0] == 0xFF) && ((GetCharFromDisc(1] & 0xF0) == 0xF0))
- if ((GetCharFromDisc(offset + 0) == 0xFF) && ((GetCharFromDisc(offset +0+1) & 0xF0) == 0xF0))
- {
- mpeg25_flag = 0; // mpeg 1 & 2
- }
- else if ((GetCharFromDisc(offset +0) == 0xFF) && ((GetCharFromDisc(offset +0+1) & 0xF0) == 0xE0))
- {
- mpeg25_flag = 1; // mpeg 2.5
- }
- else
- return 0; // sync fail
- h->sync = 1;
- if (mpeg25_flag)
- h->sync = 2; //low bit clear signals mpeg25 (as in 0xFFE)
- h->id = (GetCharFromDisc(offset +0+1) & 0x08) >> 3;
- h->option = (GetCharFromDisc(offset +0+1) & 0x06) >> 1;
- h->prot = (GetCharFromDisc(offset +0+1) & 0x01);
- h->br_index = (GetCharFromDisc(offset +0+2) & 0xf0) >> 4;
- h->sr_index = (GetCharFromDisc(offset +0+2) & 0x0c) >> 2;
- h->pad = (GetCharFromDisc(offset +0+2) & 0x02) >> 1;
- h->private_bit = (GetCharFromDisc(offset +0+2) & 0x01);
- h->mode = (GetCharFromDisc(offset +0+3) & 0xc0) >> 6;
- h->mode_ext = (GetCharFromDisc(offset +0+3) & 0x30) >> 4;
- h->cr = (GetCharFromDisc(offset +0+3) & 0x08) >> 3;
- h->original = (GetCharFromDisc(offset +0+3) & 0x04) >> 2;
- h->emphasis = (GetCharFromDisc(offset +0+3) & 0x03);
- // if( mpeg25_flag ) {
- // if( h->sr_index == 2 ) return 0; // fail 8khz
- //}
- /* compute framebytes for Layer I, II, III */
- if (h->option < 1)
- return 0;
- if (h->option > 3)
- return 0;
- framebytes = 0;
- #ifdef CLIPS_MP3_EXTRACT_ID3V1_TAG
- if (h->br_index > 0)
- {
- if (h->option == 3)
- { /* layer I */
- gns.clips.cieCurrClip.mpeginfo.uLayer = 1;
- framebytes =
- (ULONG)240 * mp_br_tableL1[h->id][h->br_index]
- / mp_sr20_table[h->id][h->sr_index];
- framebytes = 4 * framebytes;
- }
- else if (h->option == 2)
- { /* layer II */
- gns.clips.cieCurrClip.mpeginfo.uLayer = 2;
- framebytes =
- (ULONG)2880 * mp_br_table[h->id][h->br_index]
- / mp_sr20_table[h->id][h->sr_index];
- }
- else if (h->option == 1)
- { /* layer III */
- gns.clips.cieCurrClip.mpeginfo.uLayer = 3;
- if (h->id)
- { // mpeg1
- framebytes =
- (ULONG)2880 * mp_br_tableL3[h->id][h->br_index]
- / mp_sr20_table[h->id][h->sr_index];
- }
- else
- { // mpeg2
- if (mpeg25_flag)
- { // mpeg2.2
- framebytes =
- (ULONG)2880 * mp_br_tableL3[h->id][h->br_index]
- / mp_sr20_table[h->id][h->sr_index];
- }
- else
- {
- framebytes =
- (ULONG)1440 * mp_br_tableL3[h->id][h->br_index]
- / mp_sr20_table[h->id][h->sr_index];
- }
- }
- }
- }
- else
- framebytes = -1; /* free format */
- #endif
- return framebytes;
- }
- static int head_info3(DWORD offset, unsigned int n, MPEG_HEAD *h, unsigned int *searchForward) {
- unsigned int pBuf = 0;
- BYTE c0,c1;
- c0 = GetCharFromDisc(offset + pBuf);
- c1 = GetCharFromDisc(offset + pBuf+1);
- // jdw insertion...
- while ((pBuf < n) && !((c0 == 0xFF) &&
- ((c1 & 0xF0) == 0xF0 ||
- (c1 & 0xF0) == 0xE0)))
- {
- pBuf++;
- c0 = GetCharFromDisc(offset + pBuf);
- c1 = GetCharFromDisc(offset + pBuf+1);
- }
- if (pBuf == n) return 0;
- *searchForward = pBuf;
- return head_info2(offset + pBuf, n - pBuf,h);
- }
- /*--------------------------------------------------------------*/
- static int head_info2(DWORD offset, unsigned int n, MPEG_HEAD * h)
- {
- int framebytes;
- framebytes = head_info(offset, n, h);
- if (framebytes == 0)
- return 0;
- return framebytes;
- }
- static void GetBitstreamStats(DWORD dwClipStartAddr, int *piTotalSeconds)
- {
- int sampRateIndex;
- MPEG_HEAD m_sMpegHead;
- DWORD dwTotalFrames, dwSampleRate;
- int iLayer;
- //<<Leon.He_1001_05: Prevent the total time caculating overflow
- DWORD dwTempTotalFrames;
- WORD wShift = 0;
- //>>Leon.He_1001_05
- *piTotalSeconds = 0;
- dwUsPerFrame = 0;
- dwTotalFrames = dwSampleRate = 0;
- if (FALSE == GetHeadInfo(dwClipStartAddr, &m_sMpegHead, &m_frameBytes))
- {
- dwTotalFrames = -1;
- *piTotalSeconds = -1;
- return;
- }
- sampRateIndex = 4 * m_sMpegHead.id + m_sMpegHead.sr_index;
- dwSampleRate = sample_rate_table[sampRateIndex];
- if ((m_sMpegHead.sync & 1) == 0)
- dwSampleRate = dwSampleRate / 2; // mpeg25
- gns.clips.iClipSamplingRate = dwSampleRate;
- iLayer = l[m_sMpegHead.option];
- if (m_sMpegHead.id == 1)
- dwUsPerFrame = (ULONG)(1152 * 1000000) / (ULONG)dwSampleRate;
- else
- dwUsPerFrame = (ULONG)(576 * 1000000) / (ULONG)dwSampleRate;
- #ifdef CLIPS_MP3_EXTRACT_ID3V1_TAG
- if (gns.clips.cieCurrClip.ciInfo.cbFileSize > 0 && 0 != m_frameBytes)
- {
- //<<Leon.He_1001_05: Prevent the total time caculating overflow
- // MP3 VBR total time
- if (gns.clips.cieCurrClip.mpeginfo.isXingHeaderOn)
- dwTotalFrames = m_pXingHeader.frames;
- else
- dwTotalFrames = gns.clips.cieCurrClip.ciInfo.cbFileSize / m_frameBytes;
- dwTempTotalFrames = dwTotalFrames;
- wShift = 0;
- while ((DWORD_MAX/dwUsPerFrame)< dwTempTotalFrames)
- {
- wShift++;
- dwTempTotalFrames = dwTotalFrames>>wShift;
- }
- *piTotalSeconds = ((ULONG) dwTempTotalFrames *
- (ULONG) dwUsPerFrame)/ (1000000>>wShift);
- //>>Leon.He_1001_05
- }
- else
- {
- dwTotalFrames = -1;
- *piTotalSeconds = -1;
- }
- #endif
- return ;
- }
- static void InitHeaderBuff(BYTE * buff, DWORD dwClipStartAddr)
- {
- aHeaderBuffer = buff;
- uiBuffNo = -1;
- dwClipStartAddrForHeadBuffer = dwClipStartAddr;
- }
- static BYTE GetCharFromDisc(DWORD n)
- {
- //LeonHe_2005_0519: Jump out directly when Failed to read the MP3 Head.
- if(isFailedToReadMP3Head)
- return NULL;
- if((n/TEMP_BUFF_SIZE) != uiBuffNo)
- {
- uiBuffNo = n/TEMP_BUFF_SIZE;
- //AngieHe_1111_2004: Add (DOWRD) to avoid the offset overflow.
- if (!AuxCache_GetBytes(dwClipStartAddrForHeadBuffer, (DWORD)uiBuffNo*TEMP_BUFF_SIZE, TEMP_BUFF_SIZE, aHeaderBuffer))
- {
- memset(aHeaderBuffer, 0, TEMP_BUFF_SIZE);
- //>>LeonHe_2005_0519: Set a Flag when Failed to read the MP3 Head.
- isFailedToReadMP3Head = TRUE;
- drv_abort_play();
- //<<LeonHe_2005_0519
- }
- }
- return (aHeaderBuffer[n%TEMP_BUFF_SIZE]);
- }
- static BOOL GetHeadInfo(DWORD dwClipStartAddr, MPEG_HEAD * pm_sMpegHead, int *pm_frameBytes)
- {
- int iLoop, iFrame, iOffset;
- int iLastSRIndex = -1, iLastOption = -1;
- int iLastId = -1, iLastMode = -1;
- unsigned int iForward;
- BYTE abTempBuffer[TEMP_BUFF_SIZE];
- MPEG_HEAD m_sMpegHead;
- #ifdef CLIPS_MP3_EXTRACT_ID3V1_TAG
- InitHeaderBuff(abTempBuffer, dwClipStartAddr);
- for (iLoop = 0; iLoop < MAX_DECODING_RETRY; iLoop++)
- {
- for(iFrame = 0, iOffset = 0; iFrame < NUM_OF_SANITY_CHECK; iFrame++)
- {
- m_frameBytes = head_info3((DWORD)iLoop*INITIAL_FRAME_SIZE + iOffset,INITIAL_FRAME_SIZE - iOffset, &m_sMpegHead,&iForward);
- if (m_frameBytes > 0 && iFrame == 0)
- {
- iOffset += m_frameBytes + iForward + m_sMpegHead.pad;
- iLastSRIndex = m_sMpegHead.sr_index;
- iLastOption = m_sMpegHead.option;
- iLastId = m_sMpegHead.id;
- iLastMode = m_sMpegHead.mode;
- continue;
- }
- if (m_frameBytes > 0 && m_frameBytes < MAX_FRAME_SIZE &&
- (m_sMpegHead.option == 1 || m_sMpegHead.option == 2) &&
- iLastSRIndex == m_sMpegHead.sr_index &&
- iLastOption == m_sMpegHead.option &&
- iLastId == m_sMpegHead.id &&
- iLastMode == m_sMpegHead.mode)
- {
- iOffset += m_frameBytes + iForward + m_sMpegHead.pad;
- iLastSRIndex = m_sMpegHead.sr_index;
- iLastOption = m_sMpegHead.option;
- iLastId = m_sMpegHead.id;
- iLastMode = m_sMpegHead.mode;
- //<<<LeonH_0818_2003_A :For Get mp3 VBR total time
- if (iFrame < NUM_OF_SANITY_CHECK - 1)
- continue;
- if (gns.clips.cieCurrClip.mpeginfo.isXingHeaderOn)
- gns.clips.cieCurrClip.mpeginfo.isXingHeaderOn = FALSE;
- if (!GetXingHeader(&m_pXingHeader, 0))
- gns.clips.cieCurrClip.mpeginfo.isXingHeaderOn = FALSE;
- else
- gns.clips.cieCurrClip.mpeginfo.isXingHeaderOn = TRUE;
- //<<<Leonh_0818_2003_A
- continue;
- }
- break;
- }
- if (iFrame == NUM_OF_SANITY_CHECK)
- {
- memcpy(pm_sMpegHead, &m_sMpegHead, sizeof(m_sMpegHead));
- *pm_frameBytes = m_frameBytes;
- return TRUE;
- }
- }
- #endif
- return FALSE;
- }
- //<<<LeonH_0818_2003_A :For Get mp3 VBR total time
- int ExtractI4(DWORD offset)
- {
- int x;
- // big endian extract
-
- x = GetCharFromDisc(offset++);
- x <<= 8;
- x |= GetCharFromDisc(offset++);
- x <<= 8;
- x |= GetCharFromDisc(offset++);
- x <<= 8;
- x |= GetCharFromDisc(offset);
-
- return x;
- }
- static BOOL GetXingHeader(XHEADDATA *X, DWORD offset)
- {
- int i, head_flags;
- int h_id, h_mode, h_sr_index;
- // get Xing header data
- X->flags = 0; // clear to null incase fail
- // get selected MPEG header data
- h_id= (GetCharFromDisc(offset +0+1) & 0x08) >> 3;
- h_mode = (GetCharFromDisc(offset +0+3) & 0xc0) >> 6;
- // determine offset of header
- if( h_id )
- { // mpeg1
- if( h_mode != 3 )
- offset+=(32+4);
- else
- offset+=(17+4);
- }
- else
- { // mpeg2
- if( h_mode != 3 )
- offset+=(17+4);
- else
- offset+=(9+4);
- }
- if(GetCharFromDisc(offset++) !='X') return FALSE;
- if(GetCharFromDisc(offset++) !='i') return FALSE;
- if(GetCharFromDisc(offset++) !='n') return FALSE;
- if(GetCharFromDisc(offset++) !='g') return FALSE;
-
- X->h_id = h_id;
- head_flags = X->flags = ExtractI4(offset); offset+=4; // get flags
- if( head_flags & FRAMES_FLAG ) {X->frames = ExtractI4(offset); offset+=4;}
- if( head_flags & BYTES_FLAG ) {X->bytes = ExtractI4(offset); offset+=4;}
- return TRUE; // success
- }
- //<<<Leonh_0818_2003_A