4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Haejeong Kim <backto.kim@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include <string.h> /*memcmp*/
23 #include <sys/types.h>
26 #include "mm_file_debug.h"
27 #include "mm_file_utils.h"
28 #include "mm_file_format_private.h"
29 #include "mm_file_format_audio.h"
30 #include "mm_file_format_mp3.h"
32 static const int mp3BitRateTable[2][3][16] = {
33 { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
34 {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
35 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}
38 { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
39 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
40 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}
44 static const int mp3SamRateTable[3][3] = {
45 {44100, 48000, 32000},
46 {22050, 24000, 16000},
50 /* interface functions */
51 int mmfile_format_read_stream_mp3(MMFileFormatContext *formatContext);
52 int mmfile_format_read_frame_mp3(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
53 int mmfile_format_read_tag_mp3(MMFileFormatContext *formatContext);
54 int mmfile_format_close_mp3(MMFileFormatContext *formatContext);
57 static bool __get_tag_info(char *src, AvFileContentInfo *pInfo, bool extract_artwork);
58 static bool __get_stream_info(char *src, AvFileContentInfo *pInfo);
61 int mmfile_format_open_mp3(MMFileFormatContext *formatContext)
63 AvFileContentInfo *privateData = NULL;;
64 debug_fenter(RELEASE);
66 mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
67 mm_file_retvm_if_fails(DEBUG, MMFileFormatIsValidMP3(NULL, formatContext->uriFileName, 5), MMFILE_FORMAT_FAIL);
69 formatContext->ReadStream = mmfile_format_read_stream_mp3;
70 formatContext->ReadFrame = mmfile_format_read_frame_mp3;
71 formatContext->ReadTag = mmfile_format_read_tag_mp3;
72 formatContext->Close = mmfile_format_close_mp3;
74 formatContext->videoTotalTrackNum = 0;
75 formatContext->audioTotalTrackNum = 1;
77 privateData = g_new0(AvFileContentInfo, 1);
79 formatContext->privateFormatData = privateData;
81 return MMFILE_FORMAT_SUCCESS;
85 int mmfile_format_read_stream_mp3(MMFileFormatContext *formatContext)
87 AvFileContentInfo *privateData = NULL;
89 debug_fenter(RELEASE);
91 mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
92 mm_file_retvm_if_fails(DEBUG, formatContext->privateFormatData, MMFILE_FORMAT_FAIL);
94 if (!__get_stream_info(formatContext->uriFileName, formatContext->privateFormatData)) {
95 debug_error(DEBUG, "getting stream information is failed");
96 return MMFILE_FORMAT_FAIL;
99 privateData = formatContext->privateFormatData;
101 formatContext->duration = privateData->duration;
102 formatContext->videoTotalTrackNum = 0;
103 formatContext->audioTotalTrackNum = 1;
104 formatContext->nbStreams = 1;
105 formatContext->streams[MMFILE_AUDIO_STREAM] = g_new0(MMFileFormatStream, 1);
106 formatContext->streams[MMFILE_AUDIO_STREAM]->streamType = MMFILE_AUDIO_STREAM;
107 formatContext->streams[MMFILE_AUDIO_STREAM]->codecId = MM_AUDIO_CODEC_MP3;
108 formatContext->streams[MMFILE_AUDIO_STREAM]->bitRate = (privateData->bitRate * 1000);
109 formatContext->streams[MMFILE_AUDIO_STREAM]->framePerSec = (privateData->duration == 0 ? 0 : privateData->frameNum / privateData->duration);
110 formatContext->streams[MMFILE_AUDIO_STREAM]->width = 0;
111 formatContext->streams[MMFILE_AUDIO_STREAM]->height = 0;
112 formatContext->streams[MMFILE_AUDIO_STREAM]->nbChannel = privateData->channels;
113 formatContext->streams[MMFILE_AUDIO_STREAM]->samplePerSec = privateData->sampleRate;
115 return MMFILE_FORMAT_SUCCESS;
119 int mmfile_format_read_frame_mp3(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
121 return MMFILE_FORMAT_SUCCESS;
125 int mmfile_format_read_tag_mp3(MMFileFormatContext *formatContext)
127 AvFileContentInfo *privateData = NULL;
129 debug_fenter(RELEASE);
131 mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
132 mm_file_retvm_if_fails(DEBUG, formatContext->privateFormatData, MMFILE_FORMAT_FAIL);
134 if (!__get_tag_info(formatContext->uriFileName, formatContext->privateFormatData, formatContext->extract_artwork)) {
135 debug_error(DEBUG, "getting tag information is failed");
136 return MMFILE_FORMAT_FAIL;
139 privateData = formatContext->privateFormatData;
141 formatContext->title = g_strdup(privateData->tagInfo[AV_ID3TAG_TITLE].value);
142 formatContext->artist = g_strdup(privateData->tagInfo[AV_ID3TAG_ARTIST].value);
143 formatContext->copyright = g_strdup(privateData->tagInfo[AV_ID3TAG_COPYRIGHT].value);
144 formatContext->comment = g_strdup(privateData->tagInfo[AV_ID3TAG_COMMENT].value);
145 formatContext->album = g_strdup(privateData->tagInfo[AV_ID3TAG_ALBUM].value);
146 formatContext->album_artist = g_strdup(privateData->tagInfo[AV_ID3TAG_ALBUM_ARTIST].value);
147 formatContext->year = g_strdup(privateData->tagInfo[AV_ID3TAG_YEAR].value);
148 formatContext->genre = g_strdup(privateData->tagInfo[AV_ID3TAG_GENRE].value);
149 formatContext->tagTrackNum = g_strdup(privateData->tagInfo[AV_ID3TAG_TRACKNUM].value);
150 formatContext->composer = g_strdup(privateData->tagInfo[AV_ID3TAG_COMPOSER].value);
151 formatContext->classification = g_strdup(privateData->tagInfo[AV_ID3TAG_CONTENT_GROUP].value);
152 formatContext->conductor = g_strdup(privateData->tagInfo[AV_ID3TAG_CONDUCTOR].value);
153 formatContext->unsyncLyrics = g_strdup(privateData->tagInfo[AV_ID3TAG_UNSYNCLYRICS].value);
154 formatContext->syncLyrics = privateData->pSyncLyrics;
155 formatContext->syncLyricsNum = g_list_length(formatContext->syncLyrics);
156 formatContext->recDate = g_strdup(privateData->tagInfo[AV_ID3TAG_RECDATE].value);
158 if (privateData->imageInfo.imageLen > 0) {
159 formatContext->artworkSize = privateData->imageInfo.imageLen;
160 formatContext->artwork = g_memdup2(privateData->imageInfo.pImageBuf, privateData->imageInfo.imageLen);
162 if (strlen(privateData->imageInfo.imageMIMEType) > 0)
163 formatContext->artworkMime = g_strdup(privateData->imageInfo.imageMIMEType);
164 else if (strlen(privateData->imageInfo.imageExt) > 0) {
165 debug_msg(RELEASE, "ID3 tag V2 File");
166 formatContext->artworkMime = g_strdup(privateData->imageInfo.imageExt);
168 debug_error(DEBUG, "Album art image exist but there is no type information of album art");
172 return MMFILE_FORMAT_SUCCESS;
176 int mmfile_format_close_mp3(MMFileFormatContext *formatContext)
178 AvFileContentInfo *privateData = NULL;
181 privateData = formatContext->privateFormatData;
183 mm_file_free_AvFileContentInfo(privateData);
184 mmfile_free(privateData);
185 formatContext->privateFormatData = NULL;
189 return MMFILE_FORMAT_SUCCESS;
192 static bool __AvGetXingHeader(AvXHeadData *headData, unsigned char *buf)
195 int hId, hMode, hSrIndex;
196 int mp3SampleRateTable[4] = { 44100, 48000, 32000, 99999 };
198 /* get Xing header data */
201 /* get selected MP3 header data */
202 hId = (buf[1] >> 3) & 1;
203 hSrIndex = (buf[2] >> 2) & 3;
204 hMode = (buf[3] >> 6) & 3;
207 /* determine offset of header */
208 if (hId) { /* mpeg1 */
220 /* There could be 2 attrs in this header : Xing or Info */
222 mm_file_retv_if_fails(buf[1] == 'i', false);
223 mm_file_retv_if_fails(buf[2] == 'n', false);
224 mm_file_retv_if_fails(buf[3] == 'g', false);
225 } else if (buf[0] == 'I') {
226 mm_file_retv_if_fails(buf[1] == 'n', false);
227 mm_file_retv_if_fails(buf[2] == 'f', false);
228 mm_file_retv_if_fails(buf[3] == 'o', false);
236 headData->sampRate = mp3SampleRateTable[hSrIndex];
238 headData->sampRate >>= 1;
240 headFlags = headData->flags = MMFILE_CONVERT_INT(buf); /* get flags */
243 if (headFlags & FRAMES_FLAG) {
244 headData->frames = MMFILE_CONVERT_INT(buf);
247 if (headFlags & BYTES_FLAG) {
248 headData->bytes = MMFILE_CONVERT_INT(buf);
252 if (headFlags & TOC_FLAG)
255 headData->vbrScale = -1;
256 if (headFlags & VBR_SCALE_FLAG)
257 headData->vbrScale = MMFILE_CONVERT_INT(buf);
259 debug_msg(RELEASE, "Xing header: sampling-rate:%d, stream-size:%d, frame-number:%d",
260 headData->sampRate, headData->bytes, headData->frames);
262 return true; /* success */
265 static bool __AvGetVBRIHeader(AvVBRIHeadData *headData, unsigned char *buf)
268 int mp3SampleRateTable[4] = { 44100, 48000, 32000, 99999 };
271 /* get selected MP3 header data */
272 hId = (buf[1] >> 3) & 1;
273 hSrIndex = (buf[2] >> 2) & 3;
277 mm_file_retv_if_fails(buf[0] == 'V', false);
278 mm_file_retv_if_fails(buf[1] == 'B', false);
279 mm_file_retv_if_fails(buf[2] == 'R', false);
280 mm_file_retv_if_fails(buf[3] == 'I', false);
285 headData->sampRate = mp3SampleRateTable[hSrIndex];
287 headData->sampRate >>= 1;
289 headData->vID = MMFILE_CONVERT_SHORT(buf); /* get ver ID */
291 headData->delay = MMFILE_CONVERT_SHORT(buf);
293 headData->qualityIndicator = buf[0];
295 headData->bytes = MMFILE_CONVERT_INT(buf);
297 headData->frames = MMFILE_CONVERT_INT(buf);
299 headData->numOfTOC = MMFILE_CONVERT_SHORT(buf);
301 headData->vbriScale = MMFILE_CONVERT_SHORT(buf);
303 headData->sizePerTable = MMFILE_CONVERT_SHORT(buf);
305 headData->framesPerTable = MMFILE_CONVERT_SHORT(buf);
307 debug_msg(RELEASE, "Vbri header: sampling-rate:%d, stream-size:%d, frame-number:%d", headData->sampRate, headData->bytes, headData->frames);
309 return true; /* success */
312 static bool __AvIsValidHeader(AvFileContentInfo *pInfo, unsigned char *buf)
316 mm_file_retv_if_fails(VALID_SYNC(buf), false);
319 * MPEG Audio Layer I/II/III frame header
320 * from : http://www.mp3-tech.org/programmer/frame_header.html *
322 * AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM
324 * A 11 (31-21) Frame sync (all bits must be set)
325 * B 2 (20,19) MPEG Audio version ID
326 * C 2 (18,17) Layer description
327 * D 1 (16) Protection bit
328 * E 4 (15,12) Bitrate index
329 * F 2 (11,10) Sampling rate frequency index
330 * G 1 (9) Padding bit
331 * H 1 (8) Private bit. This one is only informative.
332 * I 2 (7,6) Channel Mode
333 * J 2 (5,4) Mode extension (Only used in Joint stereo)
340 /* Simple check for version, layer, bitrate, samplerate */
341 if ((buf[1] & 0x18) != 0x08 && /* 000XX000 : MPEG Audio version ID, XX=01 - reserved => 00001000(0x08) */
342 (buf[1] & 0x06) != 0x00 && /* 00000XX0 : Layer description, XX=00 - reserved => 00000000(0x00) */
343 (buf[2] & 0xF0) != 0xF0 && /* XXXX0000 : Bitrate index, XX=1111 - bad => 11110000(0xF0) */
344 (buf[2] & 0x0C) != 0x0C) { /* 0000XX00 : Sampling rate frequency index, XX=11 -reserved => 00001100(0x0C) */
347 debug_msg(RELEASE, "=> %s", bSync ? "Good!" : "Bad...");
352 static bool __AvParseMp3Header(AvFileContentInfo *pInfo, unsigned char *header)
354 unsigned char result;
356 debug_msg(RELEASE, "### [%02x][%02x][%02x][%02x] ###", header[0], header[1], header[2], header[3]);
358 /* 1. Check the version of mp3 */
359 result = header[1] & MASK_MPEG;
362 pInfo->mpegVersion = AV_MPEG_VER_1;
365 pInfo->mpegVersion = AV_MPEG_VER_2;
368 pInfo->mpegVersion = AV_MPEG_VER_25;
375 result = header[1] & MASK_LAYER;
378 pInfo->layer = AV_MP3_LAYER_1;
381 pInfo->layer = AV_MP3_LAYER_2;
384 pInfo->layer = AV_MP3_LAYER_3;
391 result = header[2] >> 4;
392 if (pInfo->mpegVersion == AV_MPEG_VER_1)
393 pInfo->bitRate = mp3BitRateTable[0][pInfo->layer - 1][(int)result] ;
395 pInfo->bitRate = mp3BitRateTable[1][pInfo->layer - 1][(int)result] ;
398 result = (header[2] & MASK_SAMPLERATE) >> 2;
402 pInfo->sampleRate = mp3SamRateTable[pInfo->mpegVersion - 1][(int)result];
405 result = header[3] & MASK_CHANNEL;
407 case MASK_CHANNEL_ST:
408 pInfo->channelIndex = 0;
411 case MASK_CHANNEL_JS:
412 pInfo->channelIndex = 1;
415 case MASK_CHANNEL_DC:
416 pInfo->channelIndex = 2;
419 case MASK_CHANNEL_MN:
420 pInfo->channelIndex = 3;;
428 result = header[2] & MASK_PADDING;
429 if (result == MASK_PADDING)
430 pInfo->bPadding = true;
432 pInfo->bPadding = false;
434 debug_msg(RELEASE, "=> samplerate=%d, bitrate=%d, layer=%d, version=%d, channel=%d, padding=%d", pInfo->sampleRate, pInfo->bitRate, pInfo->layer, pInfo->mpegVersion, pInfo->channels, pInfo->bPadding);
439 static bool __AvParseXingHeader(AvFileContentInfo *pInfo, unsigned char *buf)
441 AvXHeadData data = {0, };
442 unsigned int pos = 0;
445 /* There could be 2 attrs in this header : Xing or Info */
446 if ((pInfo->mpegVersion == AV_MPEG_VER_1) && (pInfo->channels == 2))
448 else if ((pInfo->mpegVersion == AV_MPEG_VER_2 || pInfo->mpegVersion == AV_MPEG_VER_25) && (pInfo->channels == 1))
453 if (buf[pos] == 'X') {
454 mm_file_retv_if_fails(buf[pos + 1] == 'i', false);
455 mm_file_retv_if_fails(buf[pos + 2] == 'n', false);
456 mm_file_retv_if_fails(buf[pos + 3] == 'g', false);
457 } else if (buf[pos] == 'I') {
458 mm_file_retv_if_fails(buf[pos + 1] == 'n', false);
459 mm_file_retv_if_fails(buf[pos + 2] == 'f', false);
460 mm_file_retv_if_fails(buf[pos + 3] == 'o', false);
465 if (__AvGetXingHeader(&data, (unsigned char *)buf)) { /* VBR. */
466 if (data.sampRate == 0 || data.bytes == 0 || data.frames == 0) {
467 debug_error(DEBUG, "invalid Xing header");
471 pInfo->datafileLen = data.bytes;
472 pInfo->frameNum = data.frames;
473 pInfo->frameSize = (int)((float) data.bytes / (float) data.frames);
480 static bool __AvParseVBRIHeader(AvFileContentInfo *pInfo, unsigned char *buf)
482 AvVBRIHeadData data = {0, };
485 mm_file_retv_if_fails(buf[36] == 'V', false);
486 mm_file_retv_if_fails(buf[37] == 'B', false);
487 mm_file_retv_if_fails(buf[38] == 'R', false);
488 mm_file_retv_if_fails(buf[39] == 'I', false);
490 mm_file_retvm_if_fails(DEBUG, __AvGetVBRIHeader(&data, buf), false);
491 mm_file_retvm_if_fails(DEBUG, data.sampRate > 0, false);
492 mm_file_retvm_if_fails(DEBUG, data.bytes > 0, false);
493 mm_file_retvm_if_fails(DEBUG, data.frames > 0, false);
495 pInfo->sampleRate = data.sampRate;
496 pInfo->datafileLen = data.bytes;
497 pInfo->frameNum = data.frames;
498 pInfo->frameSize = (int)((float) data.bytes / (float) data.frames) ;
504 static bool __AvGetMp3FrameSize(AvFileContentInfo *pInfo)
506 unsigned int frameSize = 0;
510 frameSize = pInfo->bPadding;
511 if (pInfo->bitRate == 0) {
512 if (pInfo->layer == 1) {
514 frameSize += 0/* FIXME: possible_free_framelen*/;
515 pInfo->bitRate = frameSize * pInfo->sampleRate / 48000;
517 frameSize += 0/* FIXME: possible_free_framelen*/;
518 pInfo->bitRate = frameSize * pInfo->sampleRate / ((pInfo->layer == AV_MP3_LAYER_3 && pInfo->mpegVersion != AV_MPEG_VER_1) ? 72000 : 144000);
522 if (pInfo->layer == 1) {
523 frameSize = ((12000 * pInfo->bitRate / pInfo->sampleRate) + frameSize) * 4;
525 frameSize += ((pInfo->layer == AV_MP3_LAYER_3 && pInfo->mpegVersion != AV_MPEG_VER_1) ? 72000 : 144000) * pInfo->bitRate / pInfo->sampleRate;
529 pInfo->frameSize = (int)frameSize;
534 static bool __AvGetBitrate(AvFileContentInfo *pInfo)
539 mm_file_retv_if_fails(pInfo, false);
540 mm_file_retv_if_fails(pInfo->bVbr, false);
545 if (pInfo->mpegVersion == AV_MPEG_VER_1) { /* MPEG version 1 */
546 if (pInfo->layer == AV_MP3_LAYER_1) /* Layer 1 */
548 else /* Layer 2, 3 */
550 } else { /* MPEG version 2 */
551 if (pInfo->layer == AV_MP3_LAYER_1) /* Layer 1 */
553 else /* Layer 2, 3 */
557 br = (pInfo->frameSize - padding) * pInfo->sampleRate / factor;
559 pInfo->bitRate = (int) br;
564 static bool __AvGetID3v1Header(unsigned char *buf, size_t buf_size, int *offset)
566 unsigned char TagV1ID[4] = { 0x54, 0x41, 0x47}; /* TAG */
567 int id3v1_offset = 0;
569 mm_file_retvm_if_fails(DEBUG, buf, false);
570 mm_file_retvm_if_fails(DEBUG, buf_size >= 3, false);
572 id3v1_offset = __AvMemstr(buf, TagV1ID, 3, TAGV1_SEEK_GAP + 5);
573 mm_file_retv_if_fails(id3v1_offset >= 0, false);
576 *offset = id3v1_offset;
578 debug_msg(RELEASE, "ID3v1 is existing");
582 static bool __AvGetID3v2Header(unsigned char *buf, size_t buf_size, AvTagVer2AdditionalData *id3v2info)
584 mm_file_retvm_if_fails(DEBUG, buf, false);
585 mm_file_retvm_if_fails(DEBUG, buf_size >= MP3_TAGv2_HEADER_LEN, false);
586 mm_file_retvm_if_fails(DEBUG, id3v2info, false);
587 mm_file_retvm_if_fails(DEBUG, IS_ID3V2_TAG(buf), false);
589 /* weak id3v2 tag check */
590 if (buf[3] == 0xFF || buf[4] == 0xFF || buf[6] >= 0x80 || buf[7] >= 0x80 || buf[8] >= 0x80 || buf[9] >= 0x80) {
591 debug_error(RELEASE, "Invalid ID3v2 base header!");
596 debug_error(RELEASE, "Invalid or not supported ID3v2 version(%d)!", buf[3]);
600 id3v2info->tagVersion = buf[3];
601 id3v2info->tagLen = MP3_TAGv2_HEADER_LEN;
602 id3v2info->tagLen += (unsigned long)buf[6] << 21 | (unsigned long)buf[7] << 14 | (unsigned long)buf[8] << 7 | (unsigned long)buf[9];
603 debug_msg(RELEASE, "ID3v2 version(%d), length (%d)", id3v2info->tagVersion, id3v2info->tagLen);
608 static bool __AvGetMp3HeaderInfo(MMFileIOHandle *hFile, AvFileContentInfo *pInfo)
610 long preHeaderGap = 0;
611 unsigned char header[MP3_FORMAT_HEADER_LEN] = {0, };
613 mm_file_retvm_if_fails(DEBUG, hFile, false);
614 mm_file_retvm_if_fails(DEBUG, pInfo, false);
616 preHeaderGap = pInfo->tagV2Info.tagLen;
618 while (preHeaderGap < pInfo->fileLen - MP3_FORMAT_HEADER_LEN) {
619 if (mmfile_seek(hFile, preHeaderGap, SEEK_SET) < 0)
622 if (mmfile_read(hFile, header, MP3_FORMAT_HEADER_LEN) != MP3_FORMAT_HEADER_LEN)
625 if (!__AvIsValidHeader(pInfo, header)) {
630 if (!__AvParseMp3Header(pInfo, header)) {
631 debug_warning(DEBUG, "Mp3 parse header failed & preHeaderGap(%ld)", preHeaderGap);
636 debug_msg(RELEASE, "This header is valid. preHeaderGap(%ld)", preHeaderGap);
637 pInfo->headerPos = preHeaderGap;
639 if (__AvParseXingHeader(pInfo, header) || __AvParseVBRIHeader(pInfo, header)) {
640 __AvGetBitrate(pInfo);
642 __AvGetMp3FrameSize(pInfo);
643 pInfo->datafileLen = pInfo->fileLen - pInfo->headerPos;
644 debug_msg(RELEASE, "Mp3 File FrameSize (%d) pInfo->headerPos(%ld)", pInfo->frameSize, pInfo->headerPos);
656 * -----------------------------------------------------
657 * | Start Offset: 0 |
659 * | Length: variable |
660 * -----------------------------------------------------
661 * | Start Offset: at the end of Last ID3 |
662 * | MP3(Mpeg audio) |
663 * | Length: variable |
664 * -----------------------------------------------------
665 * | Start Offset: -(128byte + a) at the end of file |
667 * | Length: Fixed 128byte |
668 * -----------------------------------------------------
671 * This function retrieves the ID3 tag information.
672 * Param filename [in] Specifies a mp3 file path.
673 * Param pInfo [out] Specifies a struct pointer for ID3 tag information.
674 * This function returns true on success, or false on failure.
676 static bool __get_tag_info(char *filename, AvFileContentInfo *pInfo, bool extract_artwork)
678 MMFileIOHandle *hFile;
679 unsigned char *buf = NULL;
680 unsigned char tag_v1[MP3TAGINFO_SIZE + TAGV1_SEEK_GAP] = {0, };
681 unsigned char check_tag_v2[MP3_TAGv2_HEADER_LEN] = {0, };
682 int tagHeaderPos = 0;
684 debug_fenter(RELEASE);
686 mm_file_retv_if_fails(pInfo, false);
687 mm_file_retv_if_fails(filename, false);
689 memset(pInfo, 0x00, sizeof(AvFileContentInfo));
691 pInfo->tagV2Info.tagLen = 0;
692 pInfo->headerPos = 0;
696 mm_file_retvm_if_fails(DEBUG, mmfile_open(&hFile, filename, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, false);
698 pInfo->fileLen = mmfile_get_size(hFile);
699 if (pInfo->fileLen <= 0) {
700 debug_error(DEBUG, "file is too small.");
704 /* read file to check ID3v2 header */
705 if (mmfile_read(hFile, check_tag_v2, MP3_TAGv2_HEADER_LEN) != MP3_TAGv2_HEADER_LEN) {
706 debug_error(DEBUG, "ID3v2 check fail!");
710 /* check ID3v2 header */
711 __AvGetID3v2Header(check_tag_v2, MP3_TAGv2_HEADER_LEN, &pInfo->tagV2Info);
713 if (mmfile_seek(hFile, 0L, SEEK_SET) < 0)
716 debug_msg(RELEASE, "pInfo->fileLen(%lld)", pInfo->fileLen);
718 /* read file to get ID3v2 tags from offset 0 */
719 if (pInfo->fileLen <= (long long)pInfo->tagV2Info.tagLen)
720 pInfo->tagV2Info.tagLen = pInfo->fileLen;
722 debug_msg(RELEASE, "buf size(%d)", pInfo->tagV2Info.tagLen);
724 buf = g_malloc0(pInfo->tagV2Info.tagLen);
726 if (mmfile_read(hFile, buf, pInfo->tagV2Info.tagLen) != pInfo->tagV2Info.tagLen) {
731 if (pInfo->tagV2Info.tagVersion == 0x02)
732 mm_file_id3tag_parse_v222(pInfo, buf, extract_artwork);
733 else if (pInfo->tagV2Info.tagVersion == 0x03)
734 mm_file_id3tag_parse_v223(pInfo, buf, extract_artwork);
735 else if (pInfo->tagV2Info.tagVersion == 0x04)
736 mm_file_id3tag_parse_v224(pInfo, buf, extract_artwork); /* currently 2.4 ver parsed by 2.3 routine */
738 debug_msg(RELEASE, "Invalid tag version(%d)", pInfo->tagV2Info.tagVersion);
742 /* locate fp to read TAG(ID3v1) information */
743 if (mmfile_seek(hFile, -(MP3TAGINFO_SIZE + TAGV1_SEEK_GAP), SEEK_END) < 0)
746 pInfo->bV1tagFound = false;
749 if (mmfile_read(hFile, tag_v1, MP3TAGINFO_SIZE + TAGV1_SEEK_GAP) != MP3TAGINFO_SIZE + TAGV1_SEEK_GAP)
752 /* check and get ID3v1 information */
753 if (__AvGetID3v1Header(tag_v1, MP3TAGINFO_SIZE + TAGV1_SEEK_GAP, &tagHeaderPos)) {
754 pInfo->bV1tagFound = true;
755 if (tagHeaderPos == TAGV1_SEEK_GAP) {
756 if (!mm_file_id3tag_parse_v110(pInfo, tag_v1 + tagHeaderPos))
757 debug_msg(RELEASE, "mm_file_id3tag_parse_v110 fails");
761 mm_file_id3tag_restore_content_info(pInfo);
766 debug_msg(RELEASE, "Title : %s", pInfo->tagInfo[AV_ID3TAG_TITLE].value);
767 debug_msg(RELEASE, "Artist : %s", pInfo->tagInfo[AV_ID3TAG_ARTIST].value);
768 debug_msg(RELEASE, "Album : %s", pInfo->tagInfo[AV_ID3TAG_ALBUM].value);
769 debug_msg(RELEASE, "Album_Artist: %s", pInfo->tagInfo[AV_ID3TAG_ALBUM_ARTIST].value);
770 debug_msg(RELEASE, "Year : %s", pInfo->tagInfo[AV_ID3TAG_YEAR].value);
771 debug_msg(RELEASE, "Comment : %s", pInfo->tagInfo[AV_ID3TAG_COMMENT].value);
772 debug_msg(RELEASE, "TrackNum : %s", pInfo->tagInfo[AV_ID3TAG_TRACKNUM].value);
773 debug_msg(RELEASE, "Genre : %s", pInfo->tagInfo[AV_ID3TAG_GENRE].value);
774 debug_msg(RELEASE, "Copyright : %s", pInfo->tagInfo[AV_ID3TAG_COPYRIGHT].value);
775 debug_msg(RELEASE, "RecDate : %s", pInfo->tagInfo[AV_ID3TAG_RECDATE].value);
776 debug_msg(RELEASE, "Composer : %s", pInfo->tagInfo[AV_ID3TAG_COMPOSER].value);
777 debug_msg(RELEASE, "Conductor : %s", pInfo->tagInfo[AV_ID3TAG_CONDUCTOR].value);
778 debug_msg(RELEASE, "Artwork : mime(%s) addr(%p) size(%d)", pInfo->imageInfo.imageMIMEType, pInfo->imageInfo.pImageBuf, pInfo->imageInfo.imageLen);
779 debug_msg(RELEASE, "UnsyncLyrics : %s", pInfo->tagInfo[AV_ID3TAG_UNSYNCLYRICS].value);
784 debug_error(DEBUG, "Error occured!");
790 * This function retrieves the MP3 stream information.
791 * Param filename [in] Specifies a mp3 file path.
792 * Param pInfo [out] Specifies a struct pointer for MP3 stream information.
793 * This function returns true on success, or false on failure.
795 static bool __get_stream_info(char *filename, AvFileContentInfo *pInfo)
797 MMFileIOHandle *hFile;
798 unsigned long frameSamples = 0;
799 AvTagVer2AdditionalData tagInfo = { 0, };
800 unsigned char check_v1[TAGV1_SEEK_GAP + 5] = {0, };
801 unsigned char check_v2[MP3_TAGv2_HEADER_LEN] = {0, };
803 debug_fenter(RELEASE);
805 mm_file_retv_if_fails(pInfo, false);
806 mm_file_retv_if_fails(filename, false);
808 memset(pInfo, 0x00, sizeof(AvFileContentInfo));
810 pInfo->tagV2Info.tagLen = 0;
811 pInfo->headerPos = 0;
814 mm_file_retvm_if_fails(DEBUG, mmfile_open(&hFile, filename, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, false);
816 pInfo->fileLen = mmfile_get_size(hFile);
817 if (pInfo->fileLen <= 0) {
818 debug_error(DEBUG, "file is too small.");
822 /* Find the end of ID3v2 */
823 while (pInfo->tagV2Info.tagLen < pInfo->fileLen - MP3_TAGv2_HEADER_LEN) {
824 mmfile_seek(hFile, pInfo->tagV2Info.tagLen, SEEK_SET);
826 if (mmfile_read(hFile, check_v2, MP3_TAGv2_HEADER_LEN) != MP3_TAGv2_HEADER_LEN)
829 if (!__AvGetID3v2Header(check_v2, MP3_TAGv2_HEADER_LEN, &tagInfo))
832 /* Some contents may have multiple id3 tags */
833 pInfo->tagV2Info.tagLen += tagInfo.tagLen;
834 debug_msg(RELEASE, "ID3 size[%u] Total size[%u]", tagInfo.tagLen, pInfo->tagV2Info.tagLen);
837 debug_msg(RELEASE, "ID3 Len[%u] File Len[%lld]", pInfo->tagV2Info.tagLen, pInfo->fileLen);
839 if (!__AvGetMp3HeaderInfo(hFile, pInfo))
842 if (pInfo->mpegVersion == 1)
843 frameSamples = (pInfo->layer == 1) ? MPEG_1_SIZE_LAYER_1 : MPEG_1_SIZE_LAYER_2_3;
845 frameSamples = (pInfo->layer == 1) ? MPEG_2_SIZE_LAYER_1 : MPEG_2_SIZE_LAYER_2_3;
847 /* check TAG(ID3v1) exist due to duration */
848 if (mmfile_seek(hFile, -(MP3TAGINFO_SIZE + TAGV1_SEEK_GAP), SEEK_END) < 0)
851 pInfo->bV1tagFound = false;
853 if (mmfile_read(hFile, check_v1, TAGV1_SEEK_GAP + 5) != TAGV1_SEEK_GAP + 5)
858 /* Check if id3v1 tag exists for duration calculation. */
859 if (__AvGetID3v1Header(check_v1, TAGV1_SEEK_GAP + 5, NULL))
860 pInfo->bV1tagFound = true;
862 /* get MP3 duration */
864 pInfo->duration = ((double)(frameSamples * 1000) / pInfo->sampleRate) * pInfo->frameNum;
865 debug_msg(DEBUG, "duration for VBR : %lld", pInfo->duration);
867 unsigned long long frame_duration = (((unsigned long long)frameSamples * 1000000000) / pInfo->sampleRate / 1000);
868 int file_size_except_header = pInfo->fileLen - (pInfo->headerPos + (pInfo->bV1tagFound ? MP3TAGINFO_SIZE : 0));
869 pInfo->duration = ((double)file_size_except_header / (double)pInfo->frameSize) * frame_duration / 1000;
870 /*pInfo->duration = ((double)file_size_except_header / (double)pInfo->frameSize) * (frameSamples * 1000 / pInfo->sampleRate); */
871 debug_msg(DEBUG, "duration from new algorithm : %lld", pInfo->duration);
875 debug_msg(RELEASE, "Mp3 File pInfo->duration (%lld) ", pInfo->duration);
876 debug_msg(RELEASE, "** MP3 **");
877 debug_msg(RELEASE, "Version : %u", pInfo->mpegVersion);
878 debug_msg(RELEASE, "Layer : %u", pInfo->layer);
879 debug_msg(RELEASE, "Channel idx: %u", pInfo->channelIndex);
880 debug_msg(RELEASE, "Is VBR : %d", (pInfo->bVbr == true ? 1 : 0));
881 debug_msg(RELEASE, "Bitrate : %u", pInfo->bitRate);
882 debug_msg(RELEASE, "SampleRate : %u", pInfo->sampleRate);
883 debug_msg(RELEASE, "Channels : %u", pInfo->channels);
888 debug_error(DEBUG, "Error occured!");