#include "mm_file_format_audio.h"
#include "mm_file_format_mp3.h"
-#define MMFILE_MIN(a, b) ((a) < (b) ? (a) : (b))
-
-static const unsigned char mp3FrameMasking[4] = {0xFF, 0xFE, 0x0C, 0x00};
-static unsigned char mp3FrameDataValid[4];
-
static const int mp3BitRateTable[2][3][16] = {
{ {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,},
{11025, 12000, 8000}
};
-#define IS_VALID_FRAME_MP3(x) \
- ((((x)[0] & mp3FrameMasking[0]) == mp3FrameDataValid[0]) && \
- (((x)[1] & mp3FrameMasking[1]) == mp3FrameDataValid[1]) && \
- (((x)[2] & mp3FrameMasking[2]) == mp3FrameDataValid[2]) && \
- (((x)[3] & mp3FrameMasking[3]) == mp3FrameDataValid[3]))
-
-
-
/* interface functions */
int mmfile_format_read_stream_mp3(MMFileFormatContext *formatContext);
int mmfile_format_read_frame_mp3(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
mm_file_retv_if_fails(VALID_SYNC(buf), false);
- mp3FrameDataValid[0] = (0xFF) & (mp3FrameMasking[0]);
- mp3FrameDataValid[1] = (0xE0 | (buf[AV_MP3HDR_VERSION_OFS] & AV_MP3HDR_VERSION_M) | (buf[AV_MP3HDR_LAYER_OFS] & AV_MP3HDR_LAYER_M)) & (mp3FrameMasking[1]);
- mp3FrameDataValid[2] = (buf[AV_MP3HDR_SAMPLERATE_OFS] & AV_MP3HDR_SAMPLERATE_M) & (mp3FrameMasking[2]);
- mp3FrameDataValid[3] = (buf[AV_MP3HDR_CHANNEL_OFS] & AV_MP3HDR_CHANNEL_M) & (mp3FrameMasking[3]);
-
- debug_msg(RELEASE, "*** [%02x][%02x][%02x][%02x] : [%02x][%02x][%02x][%02x]", buf[0], buf[1], buf[2], buf[3], mp3FrameDataValid[0], mp3FrameDataValid[1], mp3FrameDataValid[2], mp3FrameDataValid[3]);
-
/*
* MPEG Audio Layer I/II/III frame header
* from : http://www.mp3-tech.org/programmer/frame_header.html *
return true;
}
-/*
- * This fuction retrieves the start position of header.
- * Param _pFile [in] Specifies the file pointer of mp3 file.
- * This function returns the start position of header.
- */
-static int __AvFindStartOfMp3Header(unsigned char *buf, unsigned long bufLen, AvFileContentInfo *pInfo)
+static bool __AvGetMp3HeaderInfo(MMFileIOHandle *hFile, AvFileContentInfo *pInfo)
{
- unsigned int index = 0;
- unsigned long id3v2TagLen = 0;
- unsigned char *pHeader = NULL;
- unsigned long preHeaderGap = 0;
- unsigned long frameLen = 0;
- unsigned long nextFrameOff = 0; /* Offset to the start of the next frame */
- unsigned long nextFrameOffEnd = 0;
- bool bFoundSync = false;
- unsigned long minLen;
+ unsigned long preHeaderGap = 0;
+ unsigned char header[MP3_FORMAT_HEADER_LEN] = {0, };
- mm_file_retvm_if_fails(DEBUG, buf, -1);
- mm_file_retvm_if_fails(DEBUG, pInfo, -1);
+ mm_file_retvm_if_fails(DEBUG, hFile, false);
+ mm_file_retvm_if_fails(DEBUG, pInfo, false);
- id3v2TagLen = pInfo->tagV2Info.tagLen;
+ preHeaderGap = pInfo->tagV2Info.tagLen;
- debug_msg(RELEASE, "id3v2TagLen(%lu)", id3v2TagLen);
+ while (preHeaderGap < pInfo->fileLen - MP3_FORMAT_HEADER_LEN) {
+ if (mmfile_seek(hFile, preHeaderGap, SEEK_SET) < 0)
+ return false;
- while (1) {
- if (preHeaderGap == bufLen - 2)
- break;
- if (__AvIsValidHeader(pInfo, buf + preHeaderGap))
- break;
- preHeaderGap++;
- }
+ if (mmfile_read(hFile, header, MP3_FORMAT_HEADER_LEN) != MP3_FORMAT_HEADER_LEN)
+ return false;
- minLen = 4;
-
- buf += preHeaderGap;
- index += preHeaderGap;
- while (index <= (bufLen - minLen)) {
- if (buf[0] == 0xff) {
- if (VALID_SYNC(buf)) {
- if (bufLen - index > 256) {
- pHeader = g_malloc0(256);
- strncpy((char *)pHeader, (char *)buf, 256);
- } else {
- debug_error(DEBUG, "Header field is not exist");
- return -1;
- }
- if (!__AvParseMp3Header(pInfo, pHeader)) {
- /*return -1; */
- mmfile_free(pHeader);
- debug_warning(DEBUG, "Mp3 parse header failed & index(%d)", index);
- buf++;
- index++;
- continue;
- } else {
- debug_msg(RELEASE, "This header is valid. index(%d)", index);
- }
-
- if (__AvParseXingHeader(pInfo, pHeader) || __AvParseVBRIHeader(pInfo, pHeader))
- __AvGetBitrate(pInfo);
-
- if (pInfo->bVbr) {
- mmfile_free(pHeader);
- bFoundSync = true;
- break;
- } else {
- if (__AvIsValidHeader(pInfo, pHeader)) {
- mmfile_free(pHeader);
-
- __AvGetMp3FrameSize(pInfo);
- pInfo->datafileLen = pInfo->fileLen - pInfo->headerPos;
- frameLen = pInfo->frameSize;
- if (frameLen) {
- debug_msg(RELEASE, "<<< frameLen=[%lu] >>> ", frameLen);
- /* Check if the remaining buffer size is large enough to
- * look for another sync */
- if ((index + frameLen) < (bufLen - (minLen - 1))) {
- nextFrameOff = frameLen;
- nextFrameOffEnd = nextFrameOff + MMFILE_MIN(6, bufLen - (index + frameLen) - (minLen - 1));
-
- /* Search the next few bytes for the next sync */
- while (nextFrameOff < nextFrameOffEnd) {
- if (VALID_SYNC(buf + nextFrameOff)) {
- if (IS_VALID_FRAME_MP3(buf + nextFrameOff)) {
- bFoundSync = true;
- break;
- }
- }
- nextFrameOff++;
- }
- if (bFoundSync == true)
- break;
- } else {
- /* Assume that the first sync is valid, since there is not
- * enough data in the buffer to look for the next sync */
- bFoundSync = true;
- break;
- }
- }
-
- } else {
- debug_warning(DEBUG, "Is not vaild header pHeader");
- }
- }
- mmfile_free(pHeader);
- } else {
- debug_warning(RELEASE, "Mp3 file first byte is 0xff, but not header sync");
- }
+ if (!__AvIsValidHeader(pInfo, header)) {
+ preHeaderGap++;
+ continue;
}
- buf++;
- index++;
- }
- mmfile_free(pHeader);
+ if (!__AvParseMp3Header(pInfo, header)) {
+ debug_warning(DEBUG, "Mp3 parse header failed & preHeaderGap(%ld)", preHeaderGap);
+ preHeaderGap++;
+ continue;
+ }
- if (index > (bufLen - minLen)) {
- debug_warning(DEBUG, "Mp3 file sync is not found : index(%u) bufLen(%lu), minLen(%lu)", index, bufLen, minLen);
- return -1;
- }
+ debug_msg(RELEASE, "This header is valid. preHeaderGap(%ld)", preHeaderGap);
+ pInfo->headerPos = preHeaderGap;
- if (bFoundSync == true) {
- debug_msg(RELEASE, "Mp3 file found a sync Success!");
- } else {
- debug_msg(RELEASE, "Mp3 file found a sync Failed!");
- return -1;
+ if (__AvParseXingHeader(pInfo, header) || __AvParseVBRIHeader(pInfo, header)) {
+ __AvGetBitrate(pInfo);
+ } else {
+ __AvGetMp3FrameSize(pInfo);
+ pInfo->datafileLen = pInfo->fileLen - pInfo->headerPos;
+ debug_msg(RELEASE, "Mp3 File FrameSize (%d) pInfo->headerPos(%ld)", pInfo->frameSize, pInfo->headerPos);
+ }
+
+ return true;
}
- return index + id3v2TagLen;
+ return false;
}
/*
MMFileIOHandle *hFile;
unsigned long frameSamples = 0;
AvTagVer2AdditionalData tagInfo = { 0, };
- unsigned char header[256] = {0, };
- unsigned char *buf = NULL;
- unsigned long bufLen = 0;
+ unsigned char header[MP3_FORMAT_HEADER_LEN] = {0, };
debug_fenter(RELEASE);
debug_msg(RELEASE, "ID3 Len[%u] File Len[%lld]", pInfo->tagV2Info.tagLen, pInfo->fileLen);
- /* read file to find MP3 header */
- if (pInfo->fileLen - (long long)pInfo->tagV2Info.tagLen > (long long)_AV_MP3_HEADER_POSITION_MAX) {
- /* set offset at the end of ID3v2 */
- if (mmfile_seek(hFile, pInfo->tagV2Info.tagLen, SEEK_SET) < 0)
- goto EXCEPTION;
-
- bufLen = _AV_MP3_HEADER_POSITION_MAX;
- } else if (pInfo->fileLen - (long long)pInfo->tagV2Info.tagLen > 0) {
- /* set offset at the end of ID3v2 */
- if (mmfile_seek(hFile, pInfo->tagV2Info.tagLen, SEEK_SET) < 0)
- goto EXCEPTION;
-
- bufLen = pInfo->fileLen - (long long)pInfo->tagV2Info.tagLen;
- } else {
- /* if taglen is invalid, check whole file to get MP3 info */
- if (mmfile_seek(hFile, 0L, SEEK_SET) < 0)
- goto EXCEPTION;
-
- pInfo->tagV2Info.tagLen = 0;
- bufLen = pInfo->fileLen;
- }
-
- debug_msg(RELEASE, "buf size(%lu)", bufLen);
-
- buf = g_malloc0(bufLen);
-
- if (mmfile_read(hFile, buf, bufLen) != (int)bufLen) {
- mmfile_free(buf);
+ if (!__AvGetMp3HeaderInfo(hFile, pInfo) || pInfo->headerPos <= 0)
goto EXCEPTION;
- }
-
- /* get offset of MP3 header */
- pInfo->headerPos = (long) __AvFindStartOfMp3Header(buf, bufLen, pInfo);
-
- debug_msg(RELEASE, "Header Pos: %ld", pInfo->headerPos);
-
- mmfile_free(buf);
-
- /* get MP3 stream information from MP3 header */
- if (pInfo->headerPos == -1)
- goto EXCEPTION;
-
- if (mmfile_seek(hFile, pInfo->headerPos, SEEK_SET) < 0)
- goto EXCEPTION;
-
- if (mmfile_read(hFile, header, 256) != 256)
- goto EXCEPTION;
-
- if (!__AvParseMp3Header(pInfo, header))
- goto EXCEPTION;
-
- if (__AvParseXingHeader(pInfo, header) || __AvParseVBRIHeader(pInfo, header)) {
- __AvGetBitrate(pInfo);
- } else {
- __AvGetMp3FrameSize(pInfo);
- pInfo->datafileLen = pInfo->fileLen - pInfo->headerPos;
- debug_msg(RELEASE, "Mp3 File FrameSize (%d) pInfo->headerPos(%ld)", pInfo->frameSize, pInfo->headerPos);
- }
if (pInfo->mpegVersion == 1)
frameSamples = (pInfo->layer == 1) ? MPEG_1_SIZE_LAYER_1 : MPEG_1_SIZE_LAYER_2_3;
pInfo->bV1tagFound = false;
/* Reuse header for check if ID3v1 tag exists */
- memset(header, 0x00, 256);
+ memset(header, 0x00, TAGV1_SEEK_GAP + 5);
if (mmfile_read(hFile, header, TAGV1_SEEK_GAP + 5) != TAGV1_SEEK_GAP + 5)
goto EXCEPTION;