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->pTitle;
248 pData->tagInfo.artist = hTag->pArtist;
249 pData->tagInfo.album = hTag->pAlbum;
250 pData->tagInfo.album_artist = hTag->pAlbum_Artist;
251 pData->tagInfo.year = hTag->pYear;
252 pData->tagInfo.copyright = hTag->pCopyright;
253 pData->tagInfo.comment = hTag->pComment;
254 pData->tagInfo.genre = hTag->pGenre;
255 pData->tagInfo.tracknum = hTag->pTrackNum;
256 pData->tagInfo.composer = hTag->pComposer;
257 pData->tagInfo.classification = hTag->pContentGroup;
258 pData->tagInfo.recordDate = hTag->pRecDate;
259 pData->tagInfo.conductor = hTag->pConductor;
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 mmfile_seek(privateData->hFile, 0, MMFILE_SEEK_END);
545 privateData->streamInfo.fileSize = mmfile_tell(privateData->hFile);
547 mmfile_seek(privateData->hFile, 0, MMFILE_SEEK_SET);
549 /* Search the existance of ID3 tag */
550 ret = _search_id3tag(privateData);
551 if (ret == MMFILE_AAC_PARSER_FAIL) {
552 debug_error(RELEASE, "Error in searching the ID3 tag\n");
556 mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
557 readed = mmfile_read(privateData->hFile, header, 4);
561 if (IS_AAC_ADIF_HEADER(header)) {
562 privateData->formatType = AAC_FORMAT_ADIF;
564 debug_msg(RELEASE, "AAC Format: ADIF\n");
566 } else if (IS_AAC_ADTS_HEADER(header)) {
567 privateData->formatType = AAC_FORMAT_ADTS;
569 debug_msg(RELEASE, "AAC Format: ADTS\n");
571 /* Verify whether the first frame size is proper */
572 mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
573 ret = _get_next_adts_frame_length(privateData, &firstFrameLen);
574 if (ret == MMFILE_AAC_PARSER_FAIL) {
575 debug_error(DEBUG, "Invalid Frame length in ADTS header\n");
579 privateData->formatType = AAC_FORMAT_UNKNOWN;
580 debug_error(DEBUG, "AAC Format: UNKNOWN\n");
584 *handle = privateData;
586 return MMFILE_AAC_PARSER_SUCCESS;
590 mmfile_close(privateData->hFile);
591 mmfile_free(privateData);
594 return MMFILE_AAC_PARSER_FAIL;
599 int mmfile_aacparser_get_stream_info(MMFileAACHandle handle, tMMFILE_AAC_STREAM_INFO *aacinfo)
601 tMMFILE_AAC_HANDLE *privateData = NULL;
603 long long totalFrames = 0, totalFrameLength = 0;
604 unsigned long long streamDataSize = 0;
605 int ret = MMFILE_AAC_PARSER_SUCCESS;
607 if (NULL == handle || NULL == aacinfo) {
608 debug_error(DEBUG, "handle is NULL\n");
609 return MMFILE_AAC_PARSER_FAIL;
612 privateData = (tMMFILE_AAC_HANDLE *) handle;
614 if (privateData->formatType == AAC_FORMAT_ADIF) {
615 ret = _parse_aac_adif_header(privateData);
616 aacinfo->iseekable = 0;
618 ret = _parse_aac_adts_header(privateData);
619 aacinfo->iseekable = 1;
622 if (ret == MMFILE_AAC_PARSER_FAIL) {
623 debug_error(DEBUG, "Error in parsing the stream header\n");
627 mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
629 if (privateData->formatType == AAC_FORMAT_ADTS) {
632 ret = _get_next_adts_frame_length(privateData, &frameLen);
633 if (ret != MMFILE_AAC_PARSER_SUCCESS) {
636 totalFrameLength += frameLen - MMFILE_AAC_ADTS_HEADER_MAX_SIZE;
640 if (ret == MMFILE_AAC_PARSER_FAIL) {
641 debug_error(DEBUG, "Found corrupted frames!!! Ignoring\n");
644 debug_msg(RELEASE, "No of ADTS frames: %lld\n", totalFrames);
646 privateData->streamInfo.frameRate = privateData->streamInfo.samplingRate / AAC_ADTS_SAMPLES_PER_FRAME;
648 if (privateData->streamInfo.frameRate)
649 privateData->streamInfo.duration = (totalFrames * 1000) / privateData->streamInfo.frameRate;
650 else privateData->streamInfo.duration = 0;
652 if (privateData->streamInfo.duration)
653 privateData->streamInfo.bitRate = (totalFrameLength * 8 * 1000) / (privateData->streamInfo.duration);
654 else privateData->streamInfo.bitRate = 0;
657 streamDataSize = (unsigned long long)privateData->streamInfo.fileSize - privateData->tagInfoSize;
658 privateData->streamInfo.duration = streamDataSize * 8 * 1000 / privateData->streamInfo.bitRate;
661 /* Return the stream info structure */
662 memcpy(aacinfo, &(privateData->streamInfo), sizeof(tMMFILE_AAC_STREAM_INFO));
664 return MMFILE_AAC_PARSER_SUCCESS;
668 int mmfile_aacparser_get_tag_info(MMFileAACHandle handle, tMMFILE_AAC_TAG_INFO *tagInfo)
670 tMMFILE_AAC_HANDLE *privateData = NULL;
673 if (NULL == handle || NULL == tagInfo) {
674 debug_error(DEBUG, "handle is NULL\n");
675 return MMFILE_AAC_PARSER_FAIL;
678 privateData = (tMMFILE_AAC_HANDLE *) handle;
679 if (privateData->id3Handle.tagV2Info.tagVersion == 0) {
680 debug_warning(DEBUG, "There is no Tag info\n");
681 return MMFILE_AAC_PARSER_SUCCESS;
684 ret = _parse_id3_tag(privateData);
685 if (ret == MMFILE_AAC_PARSER_FAIL) {
686 debug_warning(DEBUG, "Error in parsing the Tag info\n");
690 /* Return the tag info structure */
691 memcpy(tagInfo, &(privateData->tagInfo), sizeof(tMMFILE_AAC_TAG_INFO));
693 return MMFILE_AAC_PARSER_SUCCESS;
697 int mmfile_aacparser_close(MMFileAACHandle handle)
699 tMMFILE_AAC_HANDLE *privateData = NULL;
701 if (NULL == handle) {
702 debug_error(DEBUG, "handle is NULL\n");
703 return MMFILE_AAC_PARSER_FAIL;
706 privateData = (tMMFILE_AAC_HANDLE *) handle;
707 mm_file_free_AvFileContentInfo(&privateData->id3Handle);
709 mmfile_close(privateData->hFile);
711 return MMFILE_AAC_PARSER_SUCCESS;
715 /* mm plugin interface */
716 int mmfile_format_read_stream_aac(MMFileFormatContext *formatContext);
717 int mmfile_format_read_frame_aac(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
718 int mmfile_format_read_tag_aac(MMFileFormatContext *formatContext);
719 int mmfile_format_close_aac(MMFileFormatContext *formatContext);
723 int mmfile_format_open_aac(MMFileFormatContext *formatContext)
725 MMFileAACHandle handle = NULL;
726 int res = MMFILE_FORMAT_FAIL;
728 if (NULL == formatContext || NULL == formatContext->uriFileName) {
729 debug_error(DEBUG, "error: mmfile_format_open_aac\n");
730 return MMFILE_FORMAT_FAIL;
733 if (formatContext->pre_checked == 0) {
734 res = MMFileFormatIsValidAAC(NULL, formatContext->uriFileName, 0);
736 debug_error(DEBUG, "It is not AAC file\n");
737 return MMFILE_FORMAT_FAIL;
741 formatContext->ReadStream = mmfile_format_read_stream_aac;
742 formatContext->ReadFrame = mmfile_format_read_frame_aac;
743 formatContext->ReadTag = mmfile_format_read_tag_aac;
744 formatContext->Close = mmfile_format_close_aac;
746 formatContext->videoTotalTrackNum = 0;
747 formatContext->audioTotalTrackNum = 1;
749 res = mmfile_aacparser_open(&handle, formatContext->uriFileName);
750 if (MMFILE_AAC_PARSER_FAIL == res) {
751 debug_error(DEBUG, "mmfile_aacparser_open\n");
752 return MMFILE_FORMAT_FAIL;
755 formatContext->privateFormatData = handle;
757 return MMFILE_FORMAT_SUCCESS;
761 int mmfile_format_read_stream_aac(MMFileFormatContext *formatContext)
763 MMFileAACHandle handle = NULL;
764 tMMFILE_AAC_STREAM_INFO aacinfo = {0, };
765 MMFileFormatStream *audioStream = NULL;
767 int ret = MMFILE_FORMAT_FAIL;
769 if (NULL == formatContext) {
770 debug_error(DEBUG, "error: invalid params\n");
771 ret = MMFILE_FORMAT_FAIL;
775 handle = formatContext->privateFormatData;
777 ret = mmfile_aacparser_get_stream_info(handle, &aacinfo);
778 if (MMFILE_FORMAT_SUCCESS != ret) {
779 debug_error(DEBUG, "error: mmfile_aacparser_get_stream_info\n");
780 ret = MMFILE_FORMAT_FAIL;
784 formatContext->isseekable = aacinfo.iseekable;
785 formatContext->duration = aacinfo.duration;
786 formatContext->videoStreamId = -1;
787 formatContext->videoTotalTrackNum = 0;
788 formatContext->audioTotalTrackNum = aacinfo.numTracks;
789 formatContext->nbStreams = 1;
791 audioStream = mmfile_malloc(sizeof(MMFileFormatStream));
792 if (NULL == audioStream) {
793 debug_error(DEBUG, "error: calloc_audiostream\n");
794 ret = MMFILE_FORMAT_FAIL;
798 audioStream->streamType = MMFILE_AUDIO_STREAM;
799 audioStream->codecId = MM_AUDIO_CODEC_AAC;
800 audioStream->bitRate = aacinfo.bitRate;
801 audioStream->framePerSec = aacinfo.frameRate;
802 audioStream->width = 0;
803 audioStream->height = 0;
804 audioStream->nbChannel = aacinfo.numAudioChannels;
805 audioStream->samplePerSec = aacinfo.samplingRate;
806 formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream;
808 #ifdef __MMFILE_TEST_MODE__
809 mmfile_format_print_contents(formatContext);
812 return MMFILE_FORMAT_SUCCESS;
819 int mmfile_format_read_tag_aac(MMFileFormatContext *formatContext)
821 MMFileAACHandle handle = NULL;
822 tMMFILE_AAC_TAG_INFO aacinfo = {0, };
823 int ret = MMFILE_FORMAT_FAIL;
825 if (NULL == formatContext) {
826 debug_error(DEBUG, "error: invalid params\n");
827 ret = MMFILE_FORMAT_FAIL;
831 handle = formatContext->privateFormatData;
833 ret = mmfile_aacparser_get_tag_info(handle, &aacinfo);
834 if (MMFILE_FORMAT_SUCCESS != ret) {
835 debug_warning(DEBUG, "error: mmfile_aacparser_get_tag_info\n");
836 ret = MMFILE_FORMAT_FAIL;
840 formatContext->title = mmfile_strdup(aacinfo.title);
841 formatContext->author = mmfile_strdup(aacinfo.author);
842 formatContext->artist = mmfile_strdup(aacinfo.artist);
843 formatContext->album = mmfile_strdup(aacinfo.album);
844 formatContext->album_artist = mmfile_strdup(aacinfo.album_artist);
845 formatContext->year = mmfile_strdup(aacinfo.year);
846 formatContext->copyright = mmfile_strdup(aacinfo.copyright);
847 formatContext->comment = mmfile_strdup(aacinfo.comment);
848 formatContext->genre = mmfile_strdup(aacinfo.genre);
849 formatContext->tagTrackNum = mmfile_strdup(aacinfo.tracknum);
850 formatContext->composer = mmfile_strdup(aacinfo.composer);
851 formatContext->classification = mmfile_strdup(aacinfo.classification);
852 formatContext->rating = mmfile_strdup(aacinfo.rating); /*not exist rating tag in id3*/
853 formatContext->conductor = mmfile_strdup(aacinfo.conductor);
854 formatContext->artworkMime = mmfile_strdup(aacinfo.artworkMime);
855 if (aacinfo.artwork) {
856 formatContext->artworkSize = aacinfo.artworkSize;
857 formatContext->artwork = mmfile_malloc(aacinfo.artworkSize);
858 if (!formatContext->artwork) {
859 ret = MMFILE_FORMAT_FAIL;
862 memcpy(formatContext->artwork, aacinfo.artwork, aacinfo.artworkSize);
865 #ifdef __MMFILE_TEST_MODE__
866 mmfile_format_print_contents(formatContext);
869 return MMFILE_FORMAT_SUCCESS;
877 int mmfile_format_read_frame_aac(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
879 debug_error(DEBUG, "error: mmfile_format_read_frame_aac, no handling\n");
881 return MMFILE_FORMAT_FAIL;
886 int mmfile_format_close_aac(MMFileFormatContext *formatContext)
888 MMFileAACHandle handle = NULL;
889 int ret = MMFILE_FORMAT_FAIL;
891 if (NULL == formatContext) {
892 debug_error(DEBUG, "error: invalid params\n");
893 return MMFILE_FORMAT_FAIL;
896 handle = formatContext->privateFormatData;
898 if (NULL != handle) {
899 ret = mmfile_aacparser_close(handle);
900 if (ret == MMFILE_AAC_PARSER_FAIL) {
901 debug_error(DEBUG, "error: mmfile_format_close_aac\n");
905 mmfile_free(formatContext->streams[MMFILE_AUDIO_STREAM]);
907 formatContext->ReadStream = NULL;
908 formatContext->ReadFrame = NULL;
909 formatContext->ReadTag = NULL;
910 formatContext->Close = NULL;
912 return MMFILE_FORMAT_SUCCESS;