Improve function to get stream info 95/246295/9
authorMinje Ahn <minje.ahn@samsung.com>
Wed, 28 Oct 2020 00:05:00 +0000 (09:05 +0900)
committerMinje Ahn <minje.ahn@samsung.com>
Wed, 28 Oct 2020 05:12:16 +0000 (14:12 +0900)
The patch contents are as follows:
1. Instead of reading the first 50KB, it finds only normal header. (For reduce memory usage)
2. If the header information found is normal, it no longer searches for other headers.
3. Code optimization for readability.
4. Remove values that are no longer used.

Change-Id: Ic0be9eec1ba1902558be0a5150a00fd41bcbb924
Signed-off-by: Minje Ahn <minje.ahn@samsung.com>
formats/ffmpeg/mm_file_format_mp3.c
utils/include/mm_file_utils.h

index 5f6f049..c820330 100644 (file)
 #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,},
@@ -52,14 +47,6 @@ static const int mp3SamRateTable[3][3] = {
        {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);
@@ -329,13 +316,6 @@ static bool __AvIsValidHeader(AvFileContentInfo *pInfo, unsigned char *buf)
 
        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           *
@@ -626,133 +606,49 @@ static bool __AvGetID3v2Header(unsigned char *buf, size_t buf_size, AvTagVer2Add
        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;
 }
 
 /*
@@ -906,9 +802,7 @@ static bool __get_stream_info(char *filename, AvFileContentInfo *pInfo)
        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);
 
@@ -946,64 +840,8 @@ static bool __get_stream_info(char *filename, AvFileContentInfo *pInfo)
 
        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;
@@ -1016,7 +854,7 @@ static bool __get_stream_info(char *filename, AvFileContentInfo *pInfo)
 
        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;
index ee73d1e..daf6832 100755 (executable)
@@ -215,6 +215,7 @@ inline static int __AvMemstr(unsigned char *mem, unsigned char *str, int str_len
 #define NEWLINE_OF_UTF16_R(x)  (((x))[0] == 0xFE && ((x))[1] == 0xFF && ((x))[2] == 0x00 && ((x))[3] == 0x00)
 
 
+#define MP3_FORMAT_HEADER_LEN 256
 #define MP3_TAGv2_HEADER_LEN 10
 #define MP3_TAGv2_23_TXT_HEADER_LEN 10
 #define MP3_TAGv2_22_TXT_HEADER_LEN 6