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*/
26 #include "mm_file_debug.h"
27 #include "mm_file_utils.h"
28 #include "mm_file_format_private.h"
29 #include "mm_file_format_aac.h"
32 /* Internal Error Type */
33 #define MMFILE_AAC_PARSER_FILE_END 2
35 /* Media specific definations */
36 #define MMFILE_AAC_ADIF_HEADER_MAX_SIZE 30
37 #define MMFILE_AAC_ADTS_HEADER_MAX_SIZE 7
38 #define AAC_ADTS_FRAME_LEN_OFFSET 30
39 #define AAC_ADTS_SAMPLES_PER_FRAME 1024
41 #define IS_AAC_ADIF_HEADER(buff) (!(memcmp((buff), "ADIF", 4)))
42 #define IS_AAC_ADTS_HEADER(buff) (((buff)[0] == 0xff) && (((buff)[1] & 0xf0) == 0xf0))
45 /* Array to Number conversions */
46 #define GET_INT_NUMBER(buff) (int)((((int)(buff)[0]) << 24) | \
47 (((int)(buff)[1]) << 16) | \
48 (((int)(buff)[2]) << 8) | \
51 #define GET_SHORT_NUMBER(buff) (short)(((short)(buff)[0] << 8) | \
56 typedef enum _mmfile_aac_format_type {
62 typedef enum _mmfile_aac_bitstream_type {
67 typedef enum _mmfile_aac_mpeg_type {
72 typedef struct _mmfile_aac_handle {
73 MMFileIOHandle *hFile;
74 AvFileContentInfo id3Handle;
75 unsigned int streamOffset;
76 unsigned int tagOffset;
78 unsigned int tagInfoSize;
79 unsigned char tagVersion;
80 TAacFormatType formatType;
81 TAacStreamType streamType;
82 TAacMpegType mpegType;
83 tMMFILE_AAC_STREAM_INFO streamInfo;
84 tMMFILE_AAC_TAG_INFO tagInfo;
88 /*Index table for Sampling frequency */
89 static const int Sampling_freq_table[16] = { 96000, 88200, 64000, 48000,
90 44100, 32000, 24000, 22050,
91 16000, 12000, 11025, 8000,
96 void _aac_init_handle(tMMFILE_AAC_HANDLE *privateData);
97 int _search_id3tag(tMMFILE_AAC_HANDLE *pData);
98 int _parse_id3_tag(tMMFILE_AAC_HANDLE *pData);
99 int _get_range_bits_value(unsigned char *buff, int fieldOffset, int fieldSize);
100 int _parse_aac_adif_header(tMMFILE_AAC_HANDLE *pData);
101 int _get_next_adts_frame_length(tMMFILE_AAC_HANDLE *pData, int *frameLen);
102 int _parse_aac_adts_header(tMMFILE_AAC_HANDLE *pData);
105 void _aac_init_handle(tMMFILE_AAC_HANDLE *privateData)
107 /* Default Initializations */
108 privateData->streamOffset = 0;
109 privateData->isTagPresent = FALSE;
110 privateData->streamOffset = 0;
111 privateData->tagOffset = 0;
113 privateData->streamInfo.fileSize = 0;
114 privateData->streamInfo.duration = 0;
115 privateData->streamInfo.bitRate = 0;
116 privateData->streamInfo.samplingRate = 0;
117 privateData->streamInfo.frameRate = 0;
118 privateData->streamInfo.numAudioChannels = 0;
119 privateData->streamInfo.numTracks = 1;
120 privateData->streamInfo.profileType = 0;
122 privateData->tagInfo.title = NULL;
123 privateData->tagInfo.author = NULL;
124 privateData->tagInfo.artist = NULL;
125 privateData->tagInfo.album = NULL;
126 privateData->tagInfo.album_artist = NULL;
127 privateData->tagInfo.year = NULL;
128 privateData->tagInfo.copyright = NULL;
129 privateData->tagInfo.comment = NULL;
130 privateData->tagInfo.genre = NULL;
131 privateData->tagInfo.composer = NULL;
132 privateData->tagInfo.classification = NULL;
133 privateData->tagInfo.rating = NULL;
134 privateData->tagInfo.recordDate = NULL;
135 privateData->tagInfo.conductor = NULL;
136 privateData->tagInfo.artwork = NULL;
137 privateData->tagInfo.artworkSize = 0;
138 privateData->tagInfo.artworkMime = NULL;
142 int _search_id3tag(tMMFILE_AAC_HANDLE *pData)
144 unsigned char tagHeader[MP3_TAGv2_HEADER_LEN] = {0, };
148 mmfile_seek(pData->hFile, 0, MMFILE_SEEK_SET);
149 readed = mmfile_read(pData->hFile, tagHeader, MP3_TAGv2_HEADER_LEN);
150 if (MP3_TAGv2_HEADER_LEN != readed) {
151 debug_msg(RELEASE, "Read Fail");
152 return MMFILE_AAC_PARSER_FAIL;
155 if (!IS_ID3V2_TAG(tagHeader)) {
156 debug_msg(RELEASE, "No ID3 Tag");
160 if (tagHeader[3] == 0xFF || tagHeader[4] == 0xFF ||
161 tagHeader[6] >= 0x80 || tagHeader[7] >= 0x80 ||
162 tagHeader[8] >= 0x80 || tagHeader[9] >= 0x80) {
163 debug_msg(RELEASE, "Read Fail");
164 return MMFILE_AAC_PARSER_FAIL;
167 pData->tagVersion = tagHeader[3];
169 if (pData->tagVersion > 4) {
170 debug_msg(RELEASE, "\nTag version not supported");
171 return MMFILE_AAC_PARSER_FAIL;
174 encSize = GET_INT_NUMBER(&tagHeader[6]);
175 pData->tagInfoSize = MP3_TAGv2_HEADER_LEN;
177 pData->tagInfoSize += (((encSize & 0x0000007F) >> 0) | ((encSize & 0x00007F00) >> 1) | \
178 ((encSize & 0x007F0000) >> 2) | ((encSize & 0x7F000000) >> 3));
180 if (pData->tagInfoSize > pData->streamInfo.fileSize) {
181 debug_msg(RELEASE, "Invalid size");
182 return MMFILE_AAC_PARSER_FAIL;
185 pData->isTagPresent = TRUE;
186 pData->tagOffset = 0;
187 pData->streamOffset = pData->tagInfoSize;
189 /* Filling the information in id3Handle for tag parsing */
190 pData->id3Handle.fileLen = pData->streamInfo.fileSize;
191 pData->id3Handle.tagV2Info.tagLen = pData->tagInfoSize;
192 pData->id3Handle.tagV2Info.tagVersion = pData->tagVersion;
193 pData->id3Handle.tagV2Info.tagLen = pData->tagInfoSize;
196 return MMFILE_AAC_PARSER_SUCCESS;
200 int _parse_id3_tag(tMMFILE_AAC_HANDLE *pData)
202 unsigned char *tagBuff = NULL;
203 AvFileContentInfo *hTag = &pData->id3Handle;
207 mmfile_seek(pData->hFile, pData->tagOffset, MMFILE_SEEK_SET);
208 tagBuff = (unsigned char *) mmfile_malloc(hTag->fileLen);
209 if (tagBuff == NULL) {
210 ret = MMFILE_AAC_PARSER_FAIL;
211 debug_error(DEBUG, "failed to memory allocation. %lld\n", hTag->fileLen);
215 readed = mmfile_read(pData->hFile, tagBuff, hTag->fileLen);
216 if (readed != hTag->fileLen) {
217 debug_error(DEBUG, "failed to read. %d, %lld\n", readed, hTag->fileLen);
221 switch (hTag->tagV2Info.tagVersion) {
223 ret = mm_file_id3tag_parse_v110(hTag, tagBuff);
226 ret = mm_file_id3tag_parse_v222(hTag, tagBuff);
229 ret = mm_file_id3tag_parse_v223(hTag, tagBuff);
232 ret = mm_file_id3tag_parse_v224(hTag, tagBuff);
235 debug_error(DEBUG, "Invalid Tag version [%d]\n", hTag->tagV2Info.tagVersion);
240 ret = MMFILE_AAC_PARSER_FAIL;
241 debug_warning(DEBUG, "failed to parse\n");
245 mm_file_id3tag_restore_content_info(hTag);
247 pData->tagInfo.title = hTag->tagInfo[AV_ID3TAG_TITLE].value;
248 pData->tagInfo.artist = hTag->tagInfo[AV_ID3TAG_ARTIST].value;
249 pData->tagInfo.album = hTag->tagInfo[AV_ID3TAG_ALBUM].value;
250 pData->tagInfo.album_artist = hTag->tagInfo[AV_ID3TAG_ALBUM_ARTIST].value;
251 pData->tagInfo.year = hTag->tagInfo[AV_ID3TAG_YEAR].value;
252 pData->tagInfo.copyright = hTag->tagInfo[AV_ID3TAG_COPYRIGHT].value;
253 pData->tagInfo.comment = hTag->tagInfo[AV_ID3TAG_COMMENT].value;
254 pData->tagInfo.genre = hTag->tagInfo[AV_ID3TAG_GENRE].value;
255 pData->tagInfo.tracknum = hTag->tagInfo[AV_ID3TAG_TRACKNUM].value;
256 pData->tagInfo.composer = hTag->tagInfo[AV_ID3TAG_COMPOSER].value;
257 pData->tagInfo.classification = hTag->tagInfo[AV_ID3TAG_CONTENT_GROUP].value;
258 pData->tagInfo.recordDate = hTag->tagInfo[AV_ID3TAG_RECDATE].value;
259 pData->tagInfo.conductor = hTag->tagInfo[AV_ID3TAG_CONDUCTOR].value;
260 pData->tagInfo.artworkMime = hTag->imageInfo.imageMIMEType;
261 pData->tagInfo.artworkSize = hTag->imageInfo.imageLen;
262 pData->tagInfo.artwork = hTag->imageInfo.pImageBuf;
264 ret = MMFILE_AAC_PARSER_SUCCESS;
268 mmfile_free(tagBuff);
274 int _get_range_bits_value(unsigned char *buff, int fieldOffset, int fieldSize)
277 unsigned int srcByteStartOff = 0;
278 unsigned int srcByteEndOff = 0;
279 unsigned int srcBitStartOff = 0;
280 unsigned int srcBitEndOff = 0;
281 unsigned char dest[4] = {0, };
282 unsigned int res = 0;
283 unsigned int i, j, temp;
284 unsigned char extraByteFlag = 0;
285 unsigned int occupiedBytes = 0;
286 unsigned char mask = 0, maskBit = 0x01;
289 srcByteStartOff = (fieldOffset / 8);
290 srcBitStartOff = (fieldOffset % 8);
292 srcByteEndOff = ((fieldOffset + fieldSize - 1) / 8);
293 srcBitEndOff = ((fieldOffset + fieldSize - 1) % 8);
295 occupiedBytes = srcByteEndOff - srcByteStartOff + 1;
297 for (i = srcByteStartOff, j = 0; i <= srcByteEndOff && j <= 3; i++, j++) {
301 for (pos = 7; pos >= (char)srcBitStartOff; pos--) {
302 mask = mask | maskBit;
306 dest[0] = dest[0] & mask;
308 if (i <= srcByteEndOff) {
312 res = GET_INT_NUMBER(dest);
314 if (!extraByteFlag) {
315 temp = (4 - occupiedBytes) * 8 + (7 - srcBitEndOff);
320 res <<= srcBitStartOff;
321 temp = buff[srcByteEndOff] >> (7 - srcBitEndOff);
322 res = res | (unsigned int)temp;
329 int _parse_aac_adif_header(tMMFILE_AAC_HANDLE *pData)
331 unsigned char adifHeader[MMFILE_AAC_ADIF_HEADER_MAX_SIZE] = {0, };
332 int currentBitOffset = 0;
333 unsigned int fieldValue = 0;
334 int copyRightStatus = 0;
337 mmfile_seek(pData->hFile, pData->streamOffset, MMFILE_SEEK_SET);
338 readed = mmfile_read(pData->hFile, adifHeader, MMFILE_AAC_ADIF_HEADER_MAX_SIZE);
340 return MMFILE_AAC_PARSER_FAIL;
343 if (memcmp(adifHeader, "ADIF", 4) != 0) {
344 return MMFILE_AAC_PARSER_FAIL;
346 currentBitOffset += 32;
348 copyRightStatus = _get_range_bits_value(adifHeader, currentBitOffset, 1);
349 currentBitOffset += 1;
351 if (copyRightStatus) {
352 /*skipping Copyright info */
353 currentBitOffset += 72;
357 fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 1);
358 currentBitOffset += 1;
360 /*skipping Home status */
361 currentBitOffset += 1;
364 fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 1);
365 currentBitOffset += 1;
367 pData->streamType = AAC_STREAM_CONSTANT;
369 pData->streamType = AAC_STREAM_VARIABLE;
373 pData->streamInfo.bitRate = _get_range_bits_value(adifHeader, currentBitOffset, 23);
374 currentBitOffset += 23;
376 /*Num of program config elements */
377 fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 4);
378 currentBitOffset += 4;
380 /*skipping adif buffer fullness */
381 currentBitOffset += 20;
383 /*skipping element instance tag */
384 currentBitOffset += 4;
387 pData->streamInfo.profileType = _get_range_bits_value(adifHeader, currentBitOffset, 2);
388 currentBitOffset += 2;
390 /*sampling freq index */
391 fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 4);
392 currentBitOffset += 4;
393 pData->streamInfo.samplingRate = Sampling_freq_table[fieldValue];
395 /*num_front_channel_elements */
396 pData->streamInfo.numAudioChannels = _get_range_bits_value(adifHeader, currentBitOffset, 4);
397 currentBitOffset += 4;
399 /*num_side_channel_elements */
400 pData->streamInfo.numAudioChannels += _get_range_bits_value(adifHeader, currentBitOffset, 4);
401 currentBitOffset += 4;
403 /*num_back_channel_elements */
404 pData->streamInfo.numAudioChannels += _get_range_bits_value(adifHeader, currentBitOffset, 4);
405 currentBitOffset += 4;
407 /*num_lfe_channel_elements */
408 pData->streamInfo.numAudioChannels += _get_range_bits_value(adifHeader, currentBitOffset, 2);
410 return MMFILE_AAC_PARSER_SUCCESS;
415 int _parse_aac_adts_header(tMMFILE_AAC_HANDLE *pData)
417 unsigned char adtsHeader[MMFILE_AAC_ADTS_HEADER_MAX_SIZE] = {0, };
418 int currentBitOffset = 0;
419 unsigned int fieldValue = 0;
422 mmfile_seek(pData->hFile, pData->streamOffset, MMFILE_SEEK_SET);
423 readed = mmfile_read(pData->hFile, adtsHeader, MMFILE_AAC_ADTS_HEADER_MAX_SIZE);
425 return MMFILE_AAC_PARSER_FAIL;
428 if (!IS_AAC_ADTS_HEADER(adtsHeader)) {
429 return MMFILE_AAC_PARSER_FAIL;
431 currentBitOffset += 12;
434 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 1);
435 currentBitOffset += 1;
436 pData->mpegType = (fieldValue != 0);
439 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 2);
440 currentBitOffset += 2;
442 /*skipping Protection Absent */
443 currentBitOffset += 1;
446 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 2);
447 currentBitOffset += 2;
448 pData->streamInfo.profileType = fieldValue;
450 /*SamplingrateIndex */
451 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 4);
452 currentBitOffset += 4;
453 pData->streamInfo.samplingRate = Sampling_freq_table[fieldValue];
455 /*skipping PrivateBit */
456 currentBitOffset += 1;
459 pData->streamInfo.numAudioChannels = _get_range_bits_value(adtsHeader, currentBitOffset, 3);
460 currentBitOffset += 3;
462 /*Original/copy status */
463 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 1);
464 currentBitOffset += 1;
466 /*skipping Home status */
467 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 1);
469 return MMFILE_AAC_PARSER_SUCCESS;
473 int _get_next_adts_frame_length(tMMFILE_AAC_HANDLE *pData, int *frameLen)
475 unsigned char adtsHeader[MMFILE_AAC_ADTS_HEADER_MAX_SIZE] = {0, };
476 int ret = MMFILE_AAC_PARSER_SUCCESS;
477 long long filePosBefore = mmfile_tell(pData->hFile);
480 readed = mmfile_read(pData->hFile, adtsHeader, MMFILE_AAC_ADTS_HEADER_MAX_SIZE);
482 return MMFILE_AAC_PARSER_FAIL;
484 debug_msg(RELEASE, "\nFILE POS: %lld\n", filePosBefore);
485 debug_msg(RELEASE, "\nADTS HEADER: [%2x] [%2x] [%2x] [%2x] [%2x] [%2x]\n",
486 adtsHeader[0], adtsHeader[1], adtsHeader[2], adtsHeader[3], adtsHeader[4], adtsHeader[5]);
488 if (mmfile_tell(pData->hFile) >= pData->streamInfo.fileSize) {
490 ret = MMFILE_AAC_PARSER_FILE_END;
494 if (!IS_AAC_ADTS_HEADER(adtsHeader)) {
496 ret = MMFILE_AAC_PARSER_FAIL;
500 *frameLen = _get_range_bits_value(adtsHeader, AAC_ADTS_FRAME_LEN_OFFSET, 13);
502 if (*frameLen == 0 || *frameLen > (pData->streamInfo.fileSize - filePosBefore)) {
504 ret = MMFILE_AAC_PARSER_FAIL;
510 mmfile_seek(pData->hFile, filePosBefore + *frameLen, MMFILE_SEEK_SET);
516 int mmfile_aacparser_open(MMFileAACHandle *handle, const char *filenamec)
518 tMMFILE_AAC_HANDLE *privateData = NULL;
520 unsigned char header[4] = {0, };
521 int firstFrameLen = 0;
524 if (NULL == filenamec) {
525 debug_error(DEBUG, "file source is NULL\n");
526 return MMFILE_AAC_PARSER_FAIL;
529 privateData = mmfile_malloc(sizeof(tMMFILE_AAC_HANDLE));
530 if (NULL == privateData) {
531 debug_error(DEBUG, "file source is NULL\n");
532 return MMFILE_AAC_PARSER_FAIL;
535 ret = mmfile_open(&privateData->hFile, filenamec, MMFILE_RDONLY);
536 if (ret == MMFILE_UTIL_FAIL) {
537 debug_error(DEBUG, "error: mmfile_open\n");
541 /* Initialize the members of handle */
542 _aac_init_handle(privateData);
544 privateData->streamInfo.fileSize = mmfile_get_size(privateData->hFile);
545 if (privateData->streamInfo.fileSize <= 0) {
546 debug_error(RELEASE, "file source is too small\n");
550 /* Search the existance of ID3 tag */
551 ret = _search_id3tag(privateData);
552 if (ret == MMFILE_AAC_PARSER_FAIL) {
553 debug_error(RELEASE, "Error in searching the ID3 tag\n");
557 mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
558 readed = mmfile_read(privateData->hFile, header, 4);
562 if (IS_AAC_ADIF_HEADER(header)) {
563 privateData->formatType = AAC_FORMAT_ADIF;
565 debug_msg(RELEASE, "AAC Format: ADIF\n");
567 } else if (IS_AAC_ADTS_HEADER(header)) {
568 privateData->formatType = AAC_FORMAT_ADTS;
570 debug_msg(RELEASE, "AAC Format: ADTS\n");
572 /* Verify whether the first frame size is proper */
573 mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
574 ret = _get_next_adts_frame_length(privateData, &firstFrameLen);
575 if (ret == MMFILE_AAC_PARSER_FAIL) {
576 debug_error(DEBUG, "Invalid Frame length in ADTS header\n");
580 privateData->formatType = AAC_FORMAT_UNKNOWN;
581 debug_error(DEBUG, "AAC Format: UNKNOWN\n");
585 *handle = privateData;
587 return MMFILE_AAC_PARSER_SUCCESS;
591 mmfile_close(privateData->hFile);
592 mmfile_free(privateData);
595 return MMFILE_AAC_PARSER_FAIL;
600 int mmfile_aacparser_get_stream_info(MMFileAACHandle handle, tMMFILE_AAC_STREAM_INFO *aacinfo)
602 tMMFILE_AAC_HANDLE *privateData = NULL;
604 long long totalFrames = 0, totalFrameLength = 0;
605 unsigned long long streamDataSize = 0;
606 int ret = MMFILE_AAC_PARSER_SUCCESS;
608 if (NULL == handle || NULL == aacinfo) {
609 debug_error(DEBUG, "handle is NULL\n");
610 return MMFILE_AAC_PARSER_FAIL;
613 privateData = (tMMFILE_AAC_HANDLE *) handle;
615 if (privateData->formatType == AAC_FORMAT_ADIF) {
616 ret = _parse_aac_adif_header(privateData);
617 aacinfo->iseekable = 0;
619 ret = _parse_aac_adts_header(privateData);
620 aacinfo->iseekable = 1;
623 if (ret == MMFILE_AAC_PARSER_FAIL) {
624 debug_error(DEBUG, "Error in parsing the stream header\n");
628 mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
630 if (privateData->formatType == AAC_FORMAT_ADTS) {
633 ret = _get_next_adts_frame_length(privateData, &frameLen);
634 if (ret != MMFILE_AAC_PARSER_SUCCESS) {
637 totalFrameLength += frameLen - MMFILE_AAC_ADTS_HEADER_MAX_SIZE;
641 if (ret == MMFILE_AAC_PARSER_FAIL) {
642 debug_error(DEBUG, "Found corrupted frames!!! Ignoring\n");
645 debug_msg(RELEASE, "No of ADTS frames: %lld\n", totalFrames);
647 privateData->streamInfo.frameRate = privateData->streamInfo.samplingRate / AAC_ADTS_SAMPLES_PER_FRAME;
649 if (privateData->streamInfo.frameRate)
650 privateData->streamInfo.duration = (totalFrames * 1000) / privateData->streamInfo.frameRate;
651 else privateData->streamInfo.duration = 0;
653 if (privateData->streamInfo.duration)
654 privateData->streamInfo.bitRate = (totalFrameLength * 8 * 1000) / (privateData->streamInfo.duration);
655 else privateData->streamInfo.bitRate = 0;
658 streamDataSize = (unsigned long long)privateData->streamInfo.fileSize - privateData->tagInfoSize;
659 privateData->streamInfo.duration = streamDataSize * 8 * 1000 / privateData->streamInfo.bitRate;
662 /* Return the stream info structure */
663 memcpy(aacinfo, &(privateData->streamInfo), sizeof(tMMFILE_AAC_STREAM_INFO));
665 return MMFILE_AAC_PARSER_SUCCESS;
669 int mmfile_aacparser_get_tag_info(MMFileAACHandle handle, tMMFILE_AAC_TAG_INFO *tagInfo)
671 tMMFILE_AAC_HANDLE *privateData = NULL;
674 if (NULL == handle || NULL == tagInfo) {
675 debug_error(DEBUG, "handle is NULL\n");
676 return MMFILE_AAC_PARSER_FAIL;
679 privateData = (tMMFILE_AAC_HANDLE *) handle;
680 if (privateData->id3Handle.tagV2Info.tagVersion == 0) {
681 debug_warning(DEBUG, "There is no Tag info\n");
682 return MMFILE_AAC_PARSER_SUCCESS;
685 ret = _parse_id3_tag(privateData);
686 if (ret == MMFILE_AAC_PARSER_FAIL) {
687 debug_warning(DEBUG, "Error in parsing the Tag info\n");
691 /* Return the tag info structure */
692 memcpy(tagInfo, &(privateData->tagInfo), sizeof(tMMFILE_AAC_TAG_INFO));
694 return MMFILE_AAC_PARSER_SUCCESS;
698 int mmfile_aacparser_close(MMFileAACHandle handle)
700 tMMFILE_AAC_HANDLE *privateData = NULL;
702 if (NULL == handle) {
703 debug_error(DEBUG, "handle is NULL\n");
704 return MMFILE_AAC_PARSER_FAIL;
707 privateData = (tMMFILE_AAC_HANDLE *) handle;
708 mm_file_free_AvFileContentInfo(&privateData->id3Handle);
710 mmfile_close(privateData->hFile);
712 return MMFILE_AAC_PARSER_SUCCESS;
716 /* mm plugin interface */
717 int mmfile_format_read_stream_aac(MMFileFormatContext *formatContext);
718 int mmfile_format_read_frame_aac(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
719 int mmfile_format_read_tag_aac(MMFileFormatContext *formatContext);
720 int mmfile_format_close_aac(MMFileFormatContext *formatContext);
724 int mmfile_format_open_aac(MMFileFormatContext *formatContext)
726 MMFileAACHandle handle = NULL;
727 int res = MMFILE_FORMAT_FAIL;
729 if (NULL == formatContext || NULL == formatContext->uriFileName) {
730 debug_error(DEBUG, "error: mmfile_format_open_aac\n");
731 return MMFILE_FORMAT_FAIL;
734 res = MMFileFormatIsValidAAC(NULL, formatContext->uriFileName, 0);
736 debug_error(DEBUG, "It is not AAC file\n");
737 return MMFILE_FORMAT_FAIL;
740 formatContext->ReadStream = mmfile_format_read_stream_aac;
741 formatContext->ReadFrame = mmfile_format_read_frame_aac;
742 formatContext->ReadTag = mmfile_format_read_tag_aac;
743 formatContext->Close = mmfile_format_close_aac;
745 formatContext->videoTotalTrackNum = 0;
746 formatContext->audioTotalTrackNum = 1;
748 res = mmfile_aacparser_open(&handle, formatContext->uriFileName);
749 if (MMFILE_AAC_PARSER_FAIL == res) {
750 debug_error(DEBUG, "mmfile_aacparser_open\n");
751 return MMFILE_FORMAT_FAIL;
754 formatContext->privateFormatData = handle;
756 return MMFILE_FORMAT_SUCCESS;
760 int mmfile_format_read_stream_aac(MMFileFormatContext *formatContext)
762 MMFileAACHandle handle = NULL;
763 tMMFILE_AAC_STREAM_INFO aacinfo = {0, };
764 MMFileFormatStream *audioStream = NULL;
766 int ret = MMFILE_FORMAT_FAIL;
768 if (NULL == formatContext) {
769 debug_error(DEBUG, "error: invalid params\n");
770 ret = MMFILE_FORMAT_FAIL;
774 handle = formatContext->privateFormatData;
776 ret = mmfile_aacparser_get_stream_info(handle, &aacinfo);
777 if (MMFILE_FORMAT_SUCCESS != ret) {
778 debug_error(DEBUG, "error: mmfile_aacparser_get_stream_info\n");
779 ret = MMFILE_FORMAT_FAIL;
783 formatContext->isseekable = aacinfo.iseekable;
784 formatContext->duration = aacinfo.duration;
785 formatContext->videoStreamId = -1;
786 formatContext->videoTotalTrackNum = 0;
787 formatContext->audioTotalTrackNum = aacinfo.numTracks;
788 formatContext->nbStreams = 1;
790 audioStream = mmfile_malloc(sizeof(MMFileFormatStream));
791 if (NULL == audioStream) {
792 debug_error(DEBUG, "error: calloc_audiostream\n");
793 ret = MMFILE_FORMAT_FAIL;
797 audioStream->streamType = MMFILE_AUDIO_STREAM;
798 audioStream->codecId = MM_AUDIO_CODEC_AAC;
799 audioStream->bitRate = aacinfo.bitRate;
800 audioStream->framePerSec = aacinfo.frameRate;
801 audioStream->width = 0;
802 audioStream->height = 0;
803 audioStream->nbChannel = aacinfo.numAudioChannels;
804 audioStream->samplePerSec = aacinfo.samplingRate;
805 formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream;
807 #ifdef __MMFILE_TEST_MODE__
808 mmfile_format_print_contents(formatContext);
811 return MMFILE_FORMAT_SUCCESS;
818 int mmfile_format_read_tag_aac(MMFileFormatContext *formatContext)
820 MMFileAACHandle handle = NULL;
821 tMMFILE_AAC_TAG_INFO aacinfo = {0, };
822 int ret = MMFILE_FORMAT_FAIL;
824 if (NULL == formatContext) {
825 debug_error(DEBUG, "error: invalid params\n");
826 ret = MMFILE_FORMAT_FAIL;
830 handle = formatContext->privateFormatData;
832 ret = mmfile_aacparser_get_tag_info(handle, &aacinfo);
833 if (MMFILE_FORMAT_SUCCESS != ret) {
834 debug_warning(DEBUG, "error: mmfile_aacparser_get_tag_info\n");
835 ret = MMFILE_FORMAT_FAIL;
839 formatContext->title = mmfile_strdup(aacinfo.title);
840 formatContext->author = mmfile_strdup(aacinfo.author);
841 formatContext->artist = mmfile_strdup(aacinfo.artist);
842 formatContext->album = mmfile_strdup(aacinfo.album);
843 formatContext->album_artist = mmfile_strdup(aacinfo.album_artist);
844 formatContext->year = mmfile_strdup(aacinfo.year);
845 formatContext->copyright = mmfile_strdup(aacinfo.copyright);
846 formatContext->comment = mmfile_strdup(aacinfo.comment);
847 formatContext->genre = mmfile_strdup(aacinfo.genre);
848 formatContext->tagTrackNum = mmfile_strdup(aacinfo.tracknum);
849 formatContext->composer = mmfile_strdup(aacinfo.composer);
850 formatContext->classification = mmfile_strdup(aacinfo.classification);
851 formatContext->rating = mmfile_strdup(aacinfo.rating); /*not exist rating tag in id3*/
852 formatContext->conductor = mmfile_strdup(aacinfo.conductor);
853 formatContext->artworkMime = mmfile_strdup(aacinfo.artworkMime);
854 if (aacinfo.artwork) {
855 formatContext->artworkSize = aacinfo.artworkSize;
856 formatContext->artwork = mmfile_malloc(aacinfo.artworkSize);
857 if (!formatContext->artwork) {
858 ret = MMFILE_FORMAT_FAIL;
861 memcpy(formatContext->artwork, aacinfo.artwork, aacinfo.artworkSize);
864 #ifdef __MMFILE_TEST_MODE__
865 mmfile_format_print_contents(formatContext);
868 return MMFILE_FORMAT_SUCCESS;
876 int mmfile_format_read_frame_aac(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
878 debug_error(DEBUG, "error: mmfile_format_read_frame_aac, no handling\n");
880 return MMFILE_FORMAT_FAIL;
885 int mmfile_format_close_aac(MMFileFormatContext *formatContext)
887 MMFileAACHandle handle = NULL;
888 int ret = MMFILE_FORMAT_FAIL;
890 if (NULL == formatContext) {
891 debug_error(DEBUG, "error: invalid params\n");
892 return MMFILE_FORMAT_FAIL;
895 handle = formatContext->privateFormatData;
897 if (NULL != handle) {
898 ret = mmfile_aacparser_close(handle);
899 if (ret == MMFILE_AAC_PARSER_FAIL) {
900 debug_error(DEBUG, "error: mmfile_format_close_aac\n");
904 mmfile_free(formatContext->streams[MMFILE_AUDIO_STREAM]);
906 formatContext->ReadStream = NULL;
907 formatContext->ReadFrame = NULL;
908 formatContext->ReadTag = NULL;
909 formatContext->Close = NULL;
911 return MMFILE_FORMAT_SUCCESS;