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.
23 #include <string.h> /*memcmp*/
24 #include <stdlib.h> /*malloc*/
28 #include "mm_file_debug.h"
29 #include "mm_file_utils.h"
30 #include "mm_file_format_private.h"
31 #include "mm_file_format_aac.h"
34 /* Internal Error Type */
35 #define MMFILE_AAC_PARSER_FILE_END 2
37 /* Media specific definations */
38 #define MMFILE_AAC_ADIF_HEADER_MAX_SIZE 30
39 #define MMFILE_AAC_ADTS_HEADER_MAX_SIZE 7
40 #define AAC_ADTS_FRAME_LEN_OFFSET 30
41 #define AAC_ADTS_SAMPLES_PER_FRAME 1024
43 #define IS_AAC_ADIF_HEADER(buff) (!(memcmp((buff), "ADIF", 4)))
44 #define IS_AAC_ADTS_HEADER(buff) (((buff)[0] == 0xff) && (((buff)[1] & 0xf0) == 0xf0))
47 /* Array to Number conversions */
48 #define GET_INT_NUMBER(buff) (int)((((int)(buff)[0]) << 24) | \
49 (((int)(buff)[1]) << 16) | \
50 (((int)(buff)[2]) << 8) | \
53 #define GET_SHORT_NUMBER(buff) (short)(((short)(buff)[0] << 8) | \
58 typedef enum _mmfile_aac_format_type {
64 typedef enum _mmfile_aac_bitstream_type {
69 typedef enum _mmfile_aac_mpeg_type {
74 typedef struct _mmfile_aac_handle {
75 MMFileIOHandle *hFile;
76 AvFileContentInfo id3Handle;
77 unsigned int streamOffset;
78 unsigned int tagOffset;
80 unsigned int tagInfoSize;
81 unsigned char tagVersion;
82 TAacFormatType formatType;
83 TAacStreamType streamType;
84 TAacMpegType mpegType;
85 tMMFILE_AAC_STREAM_INFO streamInfo;
86 tMMFILE_AAC_TAG_INFO tagInfo;
90 /*Index table for Sampling frequency */
91 const int Sampling_freq_table[16] = { 96000, 88200, 64000, 48000,
92 44100, 32000, 24000, 22050,
93 16000, 12000, 11025, 8000,
98 void _aac_init_handle(tMMFILE_AAC_HANDLE *privateData);
99 int _search_id3tag(tMMFILE_AAC_HANDLE *pData);
100 int _parse_id3_tag(tMMFILE_AAC_HANDLE *pData);
101 int _get_range_bits_value(unsigned char *buff, int fieldOffset, int fieldSize);
102 int _parse_aac_adif_header(tMMFILE_AAC_HANDLE *pData);
103 int _get_next_adts_frame_length(tMMFILE_AAC_HANDLE *pData, int *frameLen);
104 int _parse_aac_adts_header(tMMFILE_AAC_HANDLE *pData);
107 void _aac_init_handle(tMMFILE_AAC_HANDLE *privateData)
109 /* Default Initializations */
110 privateData->streamOffset = 0;
111 privateData->isTagPresent = FALSE;
112 privateData->streamOffset = 0;
113 privateData->tagOffset = 0;
115 privateData->streamInfo.fileSize = 0;
116 privateData->streamInfo.duration = 0;
117 privateData->streamInfo.bitRate = 0;
118 privateData->streamInfo.samplingRate = 0;
119 privateData->streamInfo.frameRate = 0;
120 privateData->streamInfo.numAudioChannels = 0;
121 privateData->streamInfo.numTracks = 1;
122 privateData->streamInfo.profileType = 0;
124 privateData->tagInfo.title = NULL;
125 privateData->tagInfo.author = NULL;
126 privateData->tagInfo.artist = NULL;
127 privateData->tagInfo.album = NULL;
128 privateData->tagInfo.album_artist = NULL;
129 privateData->tagInfo.year = NULL;
130 privateData->tagInfo.copyright = NULL;
131 privateData->tagInfo.comment = NULL;
132 privateData->tagInfo.genre = NULL;
133 privateData->tagInfo.composer = NULL;
134 privateData->tagInfo.classification = NULL;
135 privateData->tagInfo.rating = NULL;
136 privateData->tagInfo.recordDate = NULL;
137 privateData->tagInfo.conductor = NULL;
138 privateData->tagInfo.artwork = NULL;
139 privateData->tagInfo.artworkSize = 0;
140 privateData->tagInfo.artworkMime = NULL;
144 int _search_id3tag(tMMFILE_AAC_HANDLE *pData)
146 unsigned char tagHeader[MP3_TAGv2_HEADER_LEN] = {0, };
150 mmfile_seek(pData->hFile, 0, MMFILE_SEEK_SET);
151 readed = mmfile_read(pData->hFile, tagHeader, MP3_TAGv2_HEADER_LEN);
152 if (MP3_TAGv2_HEADER_LEN != readed) {
153 #ifdef __MMFILE_TEST_MODE__
154 debug_msg("Read Fail");
156 return MMFILE_AAC_PARSER_FAIL;
159 if (!IS_ID3V2_TAG(tagHeader)) {
160 #ifdef __MMFILE_TEST_MODE__
161 debug_msg("No ID3 Tag");
166 if (tagHeader[3] == 0xFF || tagHeader[4] == 0xFF ||
167 tagHeader[6] >= 0x80 || tagHeader[7] >= 0x80 ||
168 tagHeader[8] >= 0x80 || tagHeader[9] >= 0x80) {
169 #ifdef __MMFILE_TEST_MODE__
170 debug_msg("Read Fail");
172 return MMFILE_AAC_PARSER_FAIL;
175 pData->tagVersion = tagHeader[3];
177 if (pData->tagVersion > 4) {
178 #ifdef __MMFILE_TEST_MODE__
179 debug_msg("\nTag version not supported");
181 return MMFILE_AAC_PARSER_FAIL;
184 encSize = GET_INT_NUMBER(&tagHeader[6]);
185 pData->tagInfoSize = MP3_TAGv2_HEADER_LEN;
187 pData->tagInfoSize += (((encSize & 0x0000007F) >> 0) | ((encSize & 0x00007F00) >> 1) | \
188 ((encSize & 0x007F0000) >> 2) | ((encSize & 0x7F000000) >> 3));
190 if (pData->tagInfoSize > pData->streamInfo.fileSize) {
191 #ifdef __MMFILE_TEST_MODE__
192 debug_msg("Invalid size");
194 return MMFILE_AAC_PARSER_FAIL;
197 pData->isTagPresent = TRUE;
198 pData->tagOffset = 0;
199 pData->streamOffset = pData->tagInfoSize;
201 /* Filling the information in id3Handle for tag parsing */
202 pData->id3Handle.fileLen = pData->streamInfo.fileSize;
203 pData->id3Handle.tagV2Info.tagLen = pData->tagInfoSize;
204 pData->id3Handle.tagV2Info.tagVersion = pData->tagVersion;
205 pData->id3Handle.tagV2Info.tagLen = pData->tagInfoSize;
208 return MMFILE_AAC_PARSER_SUCCESS;
212 int _parse_id3_tag(tMMFILE_AAC_HANDLE *pData)
214 unsigned char *tagBuff = NULL;
215 AvFileContentInfo *hTag = &pData->id3Handle;
219 mmfile_seek(pData->hFile, pData->tagOffset, MMFILE_SEEK_SET);
220 tagBuff = (unsigned char *) mmfile_malloc(hTag->fileLen);
221 if (tagBuff == NULL) {
222 ret = MMFILE_AAC_PARSER_FAIL;
223 debug_error("failed to memory allocation. %d\n", hTag->fileLen);
227 readed = mmfile_read(pData->hFile, tagBuff, hTag->fileLen);
228 if (readed != hTag->fileLen) {
229 debug_error("failed to read. %d, %lld\n", readed, hTag->fileLen);
233 switch (hTag->tagV2Info.tagVersion) {
235 ret = mm_file_id3tag_parse_v110(hTag, tagBuff);
238 ret = mm_file_id3tag_parse_v222(hTag, tagBuff);
241 ret = mm_file_id3tag_parse_v223(hTag, tagBuff);
244 ret = mm_file_id3tag_parse_v224(hTag, tagBuff);
247 debug_error("Invalid Tag version [%d]\n", hTag->tagV2Info.tagVersion);
252 ret = MMFILE_AAC_PARSER_FAIL;
253 debug_warning("failed to parse\n");
257 mm_file_id3tag_restore_content_info(hTag);
259 pData->tagInfo.title = hTag->pTitle;
260 pData->tagInfo.author = hTag->pAuthor;
261 pData->tagInfo.artist = hTag->pArtist;
262 pData->tagInfo.album = hTag->pAlbum;
263 pData->tagInfo.album_artist = hTag->pAlbum_Artist;
264 pData->tagInfo.year = hTag->pYear;
265 pData->tagInfo.copyright = hTag->pCopyright;
266 pData->tagInfo.comment = hTag->pComment;
267 pData->tagInfo.genre = hTag->pGenre;
268 pData->tagInfo.tracknum = hTag->pTrackNum;
269 pData->tagInfo.composer = hTag->pComposer;
270 pData->tagInfo.classification = hTag->pContentGroup;
271 pData->tagInfo.rating = hTag->pRating;
272 pData->tagInfo.recordDate = hTag->pRecDate;
273 pData->tagInfo.conductor = hTag->pConductor;
274 pData->tagInfo.artworkMime = hTag->imageInfo.imageMIMEType;
275 pData->tagInfo.artworkSize = hTag->imageInfo.imageLen;
276 pData->tagInfo.artwork = hTag->imageInfo.pImageBuf;
278 ret = MMFILE_AAC_PARSER_SUCCESS;
283 mmfile_free(tagBuff);
292 int _get_range_bits_value(unsigned char *buff, int fieldOffset, int fieldSize)
295 unsigned int srcByteStartOff = 0;
296 unsigned int srcByteEndOff = 0;
297 unsigned int srcBitStartOff = 0;
298 unsigned int srcBitEndOff = 0;
299 unsigned char dest[4] = {0, };
300 unsigned int res = 0;
301 unsigned int i, j, temp;
302 unsigned char extraByteFlag = 0;
303 unsigned int occupiedBytes = 0;
304 unsigned char mask = 0, maskBit = 0x01;
307 srcByteStartOff = (fieldOffset / 8);
308 srcBitStartOff = (fieldOffset % 8);
310 srcByteEndOff = ((fieldOffset + fieldSize - 1) / 8);
311 srcBitEndOff = ((fieldOffset + fieldSize - 1) % 8);
313 occupiedBytes = srcByteEndOff - srcByteStartOff + 1;
315 for (i = srcByteStartOff, j = 0; i <= srcByteEndOff && j <= 3; i++, j++) {
319 for (pos = 7; pos >= (char)srcBitStartOff; pos--) {
320 mask = mask | maskBit;
324 dest[0] = dest[0] & mask;
326 if (i <= srcByteEndOff) {
330 res = GET_INT_NUMBER(dest);
332 if (!extraByteFlag) {
333 temp = (4 - occupiedBytes) * 8 + (7 - srcBitEndOff);
338 res <<= srcBitStartOff;
339 temp = buff[srcByteEndOff] >> (7 - srcBitEndOff);
340 res = res | (unsigned int)temp;
347 int _parse_aac_adif_header(tMMFILE_AAC_HANDLE *pData)
349 unsigned char adifHeader[MMFILE_AAC_ADIF_HEADER_MAX_SIZE] = {0, };
350 int currentBitOffset = 0;
351 unsigned int fieldValue = 0;
352 int copyRightStatus = 0;
355 mmfile_seek(pData->hFile, pData->streamOffset, MMFILE_SEEK_SET);
356 readed = mmfile_read(pData->hFile, adifHeader, MMFILE_AAC_ADIF_HEADER_MAX_SIZE);
358 return MMFILE_AAC_PARSER_FAIL;
361 if (memcmp(adifHeader, "ADIF", 4) != 0) {
362 return MMFILE_AAC_PARSER_FAIL;
364 currentBitOffset += 32;
366 copyRightStatus = _get_range_bits_value(adifHeader, currentBitOffset, 1);
367 currentBitOffset += 1;
369 if (copyRightStatus) {
370 /*skipping Copyright info */
371 currentBitOffset += 72;
375 fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 1);
376 currentBitOffset += 1;
378 /*skipping Home status */
379 currentBitOffset += 1;
382 fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 1);
383 currentBitOffset += 1;
385 pData->streamType = AAC_STREAM_CONSTANT;
387 pData->streamType = AAC_STREAM_VARIABLE;
391 pData->streamInfo.bitRate = _get_range_bits_value(adifHeader, currentBitOffset, 23);
392 currentBitOffset += 23;
394 /*Num of program config elements */
395 fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 4);
396 currentBitOffset += 4;
398 /*skipping adif buffer fullness */
399 currentBitOffset += 20;
401 /*skipping element instance tag */
402 currentBitOffset += 4;
405 pData->streamInfo.profileType = _get_range_bits_value(adifHeader, currentBitOffset, 2);
406 currentBitOffset += 2;
408 /*sampling freq index */
409 fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 4);
410 currentBitOffset += 4;
411 pData->streamInfo.samplingRate = Sampling_freq_table[fieldValue];
413 /*num_front_channel_elements */
414 pData->streamInfo.numAudioChannels = _get_range_bits_value(adifHeader, currentBitOffset, 4);
415 currentBitOffset += 4;
417 /*num_side_channel_elements */
418 pData->streamInfo.numAudioChannels += _get_range_bits_value(adifHeader, currentBitOffset, 4);
419 currentBitOffset += 4;
421 /*num_back_channel_elements */
422 pData->streamInfo.numAudioChannels += _get_range_bits_value(adifHeader, currentBitOffset, 4);
423 currentBitOffset += 4;
425 /*num_lfe_channel_elements */
426 pData->streamInfo.numAudioChannels += _get_range_bits_value(adifHeader, currentBitOffset, 2);
428 return MMFILE_AAC_PARSER_SUCCESS;
433 int _parse_aac_adts_header(tMMFILE_AAC_HANDLE *pData)
435 unsigned char adtsHeader[MMFILE_AAC_ADTS_HEADER_MAX_SIZE] = {0, };
436 int currentBitOffset = 0;
437 unsigned int fieldValue = 0;
440 mmfile_seek(pData->hFile, pData->streamOffset, MMFILE_SEEK_SET);
441 readed = mmfile_read(pData->hFile, adtsHeader, MMFILE_AAC_ADTS_HEADER_MAX_SIZE);
443 return MMFILE_AAC_PARSER_FAIL;
446 if (!IS_AAC_ADTS_HEADER(adtsHeader)) {
447 return MMFILE_AAC_PARSER_FAIL;
449 currentBitOffset += 12;
452 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 1);
453 currentBitOffset += 1;
454 pData->mpegType = (fieldValue != 0);
457 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 2);
458 currentBitOffset += 2;
460 /*skipping Protection Absent */
461 currentBitOffset += 1;
464 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 2);
465 currentBitOffset += 2;
466 pData->streamInfo.profileType = fieldValue;
468 /*SamplingrateIndex */
469 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 4);
470 currentBitOffset += 4;
471 pData->streamInfo.samplingRate = Sampling_freq_table[fieldValue];
473 /*skipping PrivateBit */
474 currentBitOffset += 1;
477 pData->streamInfo.numAudioChannels = _get_range_bits_value(adtsHeader, currentBitOffset, 3);
478 currentBitOffset += 3;
480 /*Original/copy status */
481 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 1);
482 currentBitOffset += 1;
484 /*skipping Home status */
485 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 1);
487 return MMFILE_AAC_PARSER_SUCCESS;
491 int _get_next_adts_frame_length(tMMFILE_AAC_HANDLE *pData, int *frameLen)
493 unsigned char adtsHeader[MMFILE_AAC_ADTS_HEADER_MAX_SIZE] = {0, };
494 int ret = MMFILE_AAC_PARSER_SUCCESS;
495 long long filePosBefore = mmfile_tell(pData->hFile);
498 readed = mmfile_read(pData->hFile, adtsHeader, MMFILE_AAC_ADTS_HEADER_MAX_SIZE);
500 return MMFILE_AAC_PARSER_FAIL;
502 #ifdef __MMFILE_TEST_MODE__
503 debug_msg("\nFILE POS: %lld\n", filePosBefore);
504 debug_msg("\nADTS HEADER: [%2x] [%2x] [%2x] [%2x] [%2x] [%2x]\n",
505 adtsHeader[0], adtsHeader[1], adtsHeader[2], adtsHeader[3], adtsHeader[4], adtsHeader[5]);
508 if (mmfile_tell(pData->hFile) >= pData->streamInfo.fileSize) {
510 ret = MMFILE_AAC_PARSER_FILE_END;
514 if (!IS_AAC_ADTS_HEADER(adtsHeader)) {
516 ret = MMFILE_AAC_PARSER_FAIL;
520 *frameLen = _get_range_bits_value(adtsHeader, AAC_ADTS_FRAME_LEN_OFFSET, 13);
522 if (*frameLen == 0 || *frameLen > (pData->streamInfo.fileSize - filePosBefore)) {
524 ret = MMFILE_AAC_PARSER_FAIL;
530 mmfile_seek(pData->hFile, filePosBefore + *frameLen, MMFILE_SEEK_SET);
536 int mmfile_aacparser_open(MMFileAACHandle *handle, const char *filenamec)
538 tMMFILE_AAC_HANDLE *privateData = NULL;
540 unsigned char header[4] = {0, };
541 int firstFrameLen = 0;
544 if (NULL == filenamec) {
545 debug_error("file source is NULL\n");
546 return MMFILE_AAC_PARSER_FAIL;
549 privateData = mmfile_malloc(sizeof(tMMFILE_AAC_HANDLE));
550 if (NULL == privateData) {
551 debug_error("file source is NULL\n");
552 return MMFILE_AAC_PARSER_FAIL;
555 ret = mmfile_open(&privateData->hFile, filenamec, MMFILE_RDONLY);
556 if (ret == MMFILE_UTIL_FAIL) {
557 debug_error("error: mmfile_open\n");
561 /* Initialize the members of handle */
562 _aac_init_handle(privateData);
564 mmfile_seek(privateData->hFile, 0, MMFILE_SEEK_END);
565 privateData->streamInfo.fileSize = mmfile_tell(privateData->hFile);
567 mmfile_seek(privateData->hFile, 0, MMFILE_SEEK_SET);
569 /* Search the existance of ID3 tag */
570 ret = _search_id3tag(privateData);
571 if (ret == MMFILE_AAC_PARSER_FAIL) {
572 debug_error("Error in searching the ID3 tag\n");
576 mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
577 readed = mmfile_read(privateData->hFile, header, 4);
581 if (IS_AAC_ADIF_HEADER(header)) {
582 privateData->formatType = AAC_FORMAT_ADIF;
584 #ifdef __MMFILE_TEST_MODE__
585 debug_msg("AAC Format: ADIF\n");
588 } else if (IS_AAC_ADTS_HEADER(header)) {
589 privateData->formatType = AAC_FORMAT_ADTS;
591 #ifdef __MMFILE_TEST_MODE__
592 debug_msg("AAC Format: ADTS\n");
595 /* Verify whether the first frame size is proper */
596 mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
597 ret = _get_next_adts_frame_length(privateData, &firstFrameLen);
598 if (ret == MMFILE_AAC_PARSER_FAIL) {
599 debug_error("Invalid Frame length in ADTS header\n");
603 privateData->formatType = AAC_FORMAT_UNKNOWN;
604 debug_error("AAC Format: UNKNOWN\n");
608 *handle = privateData;
610 return MMFILE_AAC_PARSER_SUCCESS;
614 mmfile_close(privateData->hFile);
615 mmfile_free(privateData);
618 return MMFILE_AAC_PARSER_FAIL;
623 int mmfile_aacparser_get_stream_info(MMFileAACHandle handle, tMMFILE_AAC_STREAM_INFO *aacinfo)
625 tMMFILE_AAC_HANDLE *privateData = NULL;
627 long long totalFrames = 0, totalFrameLength = 0;
628 unsigned long long streamDataSize = 0;
629 int ret = MMFILE_AAC_PARSER_SUCCESS;
631 if (NULL == handle || NULL == aacinfo) {
632 debug_error("handle is NULL\n");
633 return MMFILE_AAC_PARSER_FAIL;
636 privateData = (tMMFILE_AAC_HANDLE *) handle;
638 if (privateData->formatType == AAC_FORMAT_ADIF) {
639 ret = _parse_aac_adif_header(privateData);
640 aacinfo->iseekable = 0;
642 ret = _parse_aac_adts_header(privateData);
643 aacinfo->iseekable = 1;
646 if (ret == MMFILE_AAC_PARSER_FAIL) {
647 debug_error("Error in parsing the stream header\n");
651 mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
653 if (privateData->formatType == AAC_FORMAT_ADTS) {
656 ret = _get_next_adts_frame_length(privateData, &frameLen);
657 if (ret != MMFILE_AAC_PARSER_SUCCESS) {
660 totalFrameLength += frameLen - MMFILE_AAC_ADTS_HEADER_MAX_SIZE;
664 if (ret == MMFILE_AAC_PARSER_FAIL) {
665 debug_error("Found corrupted frames!!! Ignoring\n");
668 #ifdef __MMFILE_TEST_MODE__
669 debug_msg("No of ADTS frames: %d\n", totalFrames);
671 privateData->streamInfo.frameRate = privateData->streamInfo.samplingRate / AAC_ADTS_SAMPLES_PER_FRAME;
673 if (privateData->streamInfo.frameRate)
674 privateData->streamInfo.duration = (totalFrames * 1000) / privateData->streamInfo.frameRate;
675 else privateData->streamInfo.duration = 0;
677 if (privateData->streamInfo.duration)
678 privateData->streamInfo.bitRate = (totalFrameLength * 8 * 1000) / (privateData->streamInfo.duration);
679 else privateData->streamInfo.bitRate = 0;
682 streamDataSize = (unsigned long long)privateData->streamInfo.fileSize - privateData->tagInfoSize;
683 privateData->streamInfo.duration = streamDataSize * 8 * 1000 / privateData->streamInfo.bitRate;
686 /* Return the stream info structure */
687 memcpy(aacinfo, &(privateData->streamInfo), sizeof(tMMFILE_AAC_STREAM_INFO));
689 return MMFILE_AAC_PARSER_SUCCESS;
693 int mmfile_aacparser_get_tag_info(MMFileAACHandle handle, tMMFILE_AAC_TAG_INFO *tagInfo)
695 tMMFILE_AAC_HANDLE *privateData = NULL;
698 if (NULL == handle || NULL == tagInfo) {
699 debug_error("handle is NULL\n");
700 return MMFILE_AAC_PARSER_FAIL;
703 privateData = (tMMFILE_AAC_HANDLE *) handle;
704 if (privateData->id3Handle.tagV2Info.tagVersion == 0) {
705 debug_warning("There is no Tag info\n");
706 return MMFILE_AAC_PARSER_SUCCESS;
709 ret = _parse_id3_tag(privateData);
710 if (ret == MMFILE_AAC_PARSER_FAIL) {
711 debug_warning("Error in parsing the Tag info\n");
715 /* Return the tag info structure */
716 memcpy(tagInfo, &(privateData->tagInfo), sizeof(tMMFILE_AAC_TAG_INFO));
718 return MMFILE_AAC_PARSER_SUCCESS;
722 int mmfile_aacparser_close(MMFileAACHandle handle)
724 tMMFILE_AAC_HANDLE *privateData = NULL;
726 if (NULL == handle) {
727 debug_error("handle is NULL\n");
728 return MMFILE_AAC_PARSER_FAIL;
731 privateData = (tMMFILE_AAC_HANDLE *) handle;
732 mm_file_free_AvFileContentInfo(&privateData->id3Handle);
734 mmfile_close(privateData->hFile);
736 return MMFILE_AAC_PARSER_SUCCESS;
740 /* mm plugin interface */
741 int mmfile_format_read_stream_aac(MMFileFormatContext *formatContext);
742 int mmfile_format_read_frame_aac(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
743 int mmfile_format_read_tag_aac(MMFileFormatContext *formatContext);
744 int mmfile_format_close_aac(MMFileFormatContext *formatContext);
748 int mmfile_format_open_aac(MMFileFormatContext *formatContext)
750 MMFileAACHandle handle = NULL;
751 int res = MMFILE_FORMAT_FAIL;
753 if (NULL == formatContext || NULL == formatContext->uriFileName) {
754 debug_error("error: mmfile_format_open_aac\n");
755 return MMFILE_FORMAT_FAIL;
758 if (formatContext->pre_checked == 0) {
759 res = MMFileFormatIsValidAAC(NULL, formatContext->uriFileName);
761 debug_error("It is not AAC file\n");
762 return MMFILE_FORMAT_FAIL;
766 formatContext->ReadStream = mmfile_format_read_stream_aac;
767 formatContext->ReadFrame = mmfile_format_read_frame_aac;
768 formatContext->ReadTag = mmfile_format_read_tag_aac;
769 formatContext->Close = mmfile_format_close_aac;
771 formatContext->videoTotalTrackNum = 0;
772 formatContext->audioTotalTrackNum = 1;
774 res = mmfile_aacparser_open(&handle, formatContext->uriFileName);
775 if (MMFILE_AAC_PARSER_FAIL == res) {
776 debug_error("mmfile_aacparser_open\n");
777 return MMFILE_FORMAT_FAIL;
780 formatContext->privateFormatData = handle;
782 return MMFILE_FORMAT_SUCCESS;
786 int mmfile_format_read_stream_aac(MMFileFormatContext *formatContext)
788 MMFileAACHandle handle = NULL;
789 tMMFILE_AAC_STREAM_INFO aacinfo = {0, };
790 MMFileFormatStream *audioStream = NULL;
792 int ret = MMFILE_FORMAT_FAIL;
794 if (NULL == formatContext) {
795 debug_error("error: invalid params\n");
796 ret = MMFILE_FORMAT_FAIL;
800 handle = formatContext->privateFormatData;
802 ret = mmfile_aacparser_get_stream_info(handle, &aacinfo);
803 if (MMFILE_FORMAT_SUCCESS != ret) {
804 debug_error("error: mmfile_aacparser_get_stream_info\n");
805 ret = MMFILE_FORMAT_FAIL;
809 formatContext->isseekable = aacinfo.iseekable;
810 formatContext->duration = aacinfo.duration;
811 formatContext->videoStreamId = -1;
812 formatContext->videoTotalTrackNum = 0;
813 formatContext->audioTotalTrackNum = aacinfo.numTracks;
814 formatContext->nbStreams = 1;
816 audioStream = mmfile_malloc(sizeof(MMFileFormatStream));
817 if (NULL == audioStream) {
818 debug_error("error: calloc_audiostream\n");
819 ret = MMFILE_FORMAT_FAIL;
823 audioStream->streamType = MMFILE_AUDIO_STREAM;
824 audioStream->codecId = MM_AUDIO_CODEC_AAC;
825 audioStream->bitRate = aacinfo.bitRate;
826 audioStream->framePerSec = aacinfo.frameRate;
827 audioStream->width = 0;
828 audioStream->height = 0;
829 audioStream->nbChannel = aacinfo.numAudioChannels;
830 audioStream->samplePerSec = aacinfo.samplingRate;
831 formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream;
833 #ifdef __MMFILE_TEST_MODE__
834 mmfile_format_print_contents(formatContext);
837 return MMFILE_FORMAT_SUCCESS;
844 int mmfile_format_read_tag_aac(MMFileFormatContext *formatContext)
846 MMFileAACHandle handle = NULL;
847 tMMFILE_AAC_TAG_INFO aacinfo = {0, };
848 int ret = MMFILE_FORMAT_FAIL;
850 if (NULL == formatContext) {
851 debug_error("error: invalid params\n");
852 ret = MMFILE_FORMAT_FAIL;
856 handle = formatContext->privateFormatData;
858 ret = mmfile_aacparser_get_tag_info(handle, &aacinfo);
859 if (MMFILE_FORMAT_SUCCESS != ret) {
860 debug_warning("error: mmfile_aacparser_get_tag_info\n");
861 ret = MMFILE_FORMAT_FAIL;
866 formatContext->title = mmfile_strdup(aacinfo.title);
868 formatContext->author = mmfile_strdup(aacinfo.author);
870 formatContext->artist = mmfile_strdup(aacinfo.artist);
872 formatContext->album = mmfile_strdup(aacinfo.album);
873 if (aacinfo.album_artist)
874 formatContext->album_artist = mmfile_strdup(aacinfo.album_artist);
876 formatContext->year = mmfile_strdup(aacinfo.year);
877 if (aacinfo.copyright)
878 formatContext->copyright = mmfile_strdup(aacinfo.copyright);
880 formatContext->comment = mmfile_strdup(aacinfo.comment);
882 formatContext->genre = mmfile_strdup(aacinfo.genre);
883 if (aacinfo.tracknum)
884 formatContext->tagTrackNum = mmfile_strdup(aacinfo.tracknum);
885 if (aacinfo.composer)
886 formatContext->composer = mmfile_strdup(aacinfo.composer);
887 if (aacinfo.classification)
888 formatContext->classification = mmfile_strdup(aacinfo.classification);
890 formatContext->rating = mmfile_strdup(aacinfo.rating); /*not exist rating tag in id3*/
891 if (aacinfo.conductor)
892 formatContext->conductor = mmfile_strdup(aacinfo.conductor);
893 if (aacinfo.artworkMime)
894 formatContext->artworkMime = mmfile_strdup(aacinfo.artworkMime);
895 if (aacinfo.artwork) {
896 formatContext->artworkSize = aacinfo.artworkSize;
897 formatContext->artwork = mmfile_malloc(aacinfo.artworkSize);
898 if (formatContext->artwork == NULL) {
899 ret = MMFILE_FORMAT_FAIL;
902 memcpy(formatContext->artwork, aacinfo.artwork, aacinfo.artworkSize);
905 #ifdef __MMFILE_TEST_MODE__
906 mmfile_format_print_contents(formatContext);
909 return MMFILE_FORMAT_SUCCESS;
917 int mmfile_format_read_frame_aac(MMFileFormatContext *formatContext,
918 unsigned int timestamp, MMFileFormatFrame *frame)
920 debug_error("error: mmfile_format_read_frame_aac, no handling\n");
922 return MMFILE_FORMAT_FAIL;
927 int mmfile_format_close_aac(MMFileFormatContext *formatContext)
929 MMFileAACHandle handle = NULL;
930 int ret = MMFILE_FORMAT_FAIL;
932 if (NULL == formatContext) {
933 debug_error("error: invalid params\n");
934 return MMFILE_FORMAT_FAIL;
937 handle = formatContext->privateFormatData;
939 if (NULL != handle) {
940 ret = mmfile_aacparser_close(handle);
941 if (ret == MMFILE_AAC_PARSER_FAIL) {
942 debug_error("error: mmfile_format_close_aac\n");
946 if (formatContext->streams[MMFILE_AUDIO_STREAM]) {
947 mmfile_free(formatContext->streams[MMFILE_AUDIO_STREAM]);
948 formatContext->streams[MMFILE_AUDIO_STREAM] = NULL;
951 formatContext->ReadStream = NULL;
952 formatContext->ReadFrame = NULL;
953 formatContext->ReadTag = NULL;
954 formatContext->Close = NULL;
956 return MMFILE_FORMAT_SUCCESS;