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);
427 currentBitOffset += 2;
429 return MMFILE_AAC_PARSER_SUCCESS;
434 int _parse_aac_adts_header(tMMFILE_AAC_HANDLE *pData)
436 unsigned char adtsHeader[MMFILE_AAC_ADTS_HEADER_MAX_SIZE] = {0, };
437 int currentBitOffset = 0;
438 unsigned int fieldValue = 0;
441 mmfile_seek(pData->hFile, pData->streamOffset, MMFILE_SEEK_SET);
442 readed = mmfile_read(pData->hFile, adtsHeader, MMFILE_AAC_ADTS_HEADER_MAX_SIZE);
444 return MMFILE_AAC_PARSER_FAIL;
447 if (!IS_AAC_ADTS_HEADER(adtsHeader)) {
448 return MMFILE_AAC_PARSER_FAIL;
450 currentBitOffset += 12;
453 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 1);
454 currentBitOffset += 1;
455 pData->mpegType = (fieldValue != 0);
458 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 2);
459 currentBitOffset += 2;
461 /*skipping Protection Absent */
462 currentBitOffset += 1;
465 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 2);
466 currentBitOffset += 2;
467 pData->streamInfo.profileType = fieldValue;
469 /*SamplingrateIndex */
470 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 4);
471 currentBitOffset += 4;
472 pData->streamInfo.samplingRate = Sampling_freq_table[fieldValue];
474 /*skipping PrivateBit */
475 currentBitOffset += 1;
478 pData->streamInfo.numAudioChannels = _get_range_bits_value(adtsHeader, currentBitOffset, 3);
479 currentBitOffset += 3;
481 /*Original/copy status */
482 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 1);
483 currentBitOffset += 1;
485 /*skipping Home status */
486 fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 1);
487 currentBitOffset += 1;
489 /*copy right Id status bit */
490 currentBitOffset += 1;
492 return MMFILE_AAC_PARSER_SUCCESS;
496 int _get_next_adts_frame_length(tMMFILE_AAC_HANDLE *pData, int *frameLen)
498 unsigned char adtsHeader[MMFILE_AAC_ADTS_HEADER_MAX_SIZE] = {0, };
499 int ret = MMFILE_AAC_PARSER_SUCCESS;
500 long long filePosBefore = mmfile_tell(pData->hFile);
503 readed = mmfile_read(pData->hFile, adtsHeader, MMFILE_AAC_ADTS_HEADER_MAX_SIZE);
505 return MMFILE_AAC_PARSER_FAIL;
507 #ifdef __MMFILE_TEST_MODE__
508 debug_msg("\nFILE POS: %lld\n", filePosBefore);
509 debug_msg("\nADTS HEADER: [%2x] [%2x] [%2x] [%2x] [%2x] [%2x]\n",
510 adtsHeader[0], adtsHeader[1], adtsHeader[2], adtsHeader[3], adtsHeader[4], adtsHeader[5]);
513 if (mmfile_tell(pData->hFile) >= pData->streamInfo.fileSize) {
515 ret = MMFILE_AAC_PARSER_FILE_END;
519 if (!IS_AAC_ADTS_HEADER(adtsHeader)) {
521 ret = MMFILE_AAC_PARSER_FAIL;
525 *frameLen = _get_range_bits_value(adtsHeader, AAC_ADTS_FRAME_LEN_OFFSET, 13);
527 if (*frameLen == 0 || *frameLen > (pData->streamInfo.fileSize - filePosBefore)) {
529 ret = MMFILE_AAC_PARSER_FAIL;
535 mmfile_seek(pData->hFile, filePosBefore + *frameLen, MMFILE_SEEK_SET);
541 int mmfile_aacparser_open(MMFileAACHandle *handle, const char *filenamec)
543 tMMFILE_AAC_HANDLE *privateData = NULL;
545 unsigned char header[4] = {0, };
546 int firstFrameLen = 0;
549 if (NULL == filenamec) {
550 debug_error("file source is NULL\n");
551 return MMFILE_AAC_PARSER_FAIL;
554 privateData = mmfile_malloc(sizeof(tMMFILE_AAC_HANDLE));
555 if (NULL == privateData) {
556 debug_error("file source is NULL\n");
557 return MMFILE_AAC_PARSER_FAIL;
560 ret = mmfile_open(&privateData->hFile, filenamec, MMFILE_RDONLY);
561 if (ret == MMFILE_UTIL_FAIL) {
562 debug_error("error: mmfile_open\n");
566 /* Initialize the members of handle */
567 _aac_init_handle(privateData);
569 mmfile_seek(privateData->hFile, 0, MMFILE_SEEK_END);
570 privateData->streamInfo.fileSize = mmfile_tell(privateData->hFile);
572 mmfile_seek(privateData->hFile, 0, MMFILE_SEEK_SET);
574 /* Search the existance of ID3 tag */
575 ret = _search_id3tag(privateData);
576 if (ret == MMFILE_AAC_PARSER_FAIL) {
577 debug_error("Error in searching the ID3 tag\n");
581 mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
582 readed = mmfile_read(privateData->hFile, header, 4);
586 if (IS_AAC_ADIF_HEADER(header)) {
587 privateData->formatType = AAC_FORMAT_ADIF;
589 #ifdef __MMFILE_TEST_MODE__
590 debug_msg("AAC Format: ADIF\n");
593 } else if (IS_AAC_ADTS_HEADER(header)) {
594 privateData->formatType = AAC_FORMAT_ADTS;
596 #ifdef __MMFILE_TEST_MODE__
597 debug_msg("AAC Format: ADTS\n");
600 /* Verify whether the first frame size is proper */
601 mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
602 ret = _get_next_adts_frame_length(privateData, &firstFrameLen);
603 if (ret == MMFILE_AAC_PARSER_FAIL) {
604 debug_error("Invalid Frame length in ADTS header\n");
608 privateData->formatType = AAC_FORMAT_UNKNOWN;
609 debug_error("AAC Format: UNKNOWN\n");
613 *handle = privateData;
615 return MMFILE_AAC_PARSER_SUCCESS;
619 mmfile_close(privateData->hFile);
620 mmfile_free(privateData);
623 return MMFILE_AAC_PARSER_FAIL;
628 int mmfile_aacparser_get_stream_info(MMFileAACHandle handle, tMMFILE_AAC_STREAM_INFO *aacinfo)
630 tMMFILE_AAC_HANDLE *privateData = NULL;
632 long long totalFrames = 0, totalFrameLength = 0;
633 unsigned long long streamDataSize = 0;
634 int ret = MMFILE_AAC_PARSER_SUCCESS;
636 if (NULL == handle || NULL == aacinfo) {
637 debug_error("handle is NULL\n");
638 return MMFILE_AAC_PARSER_FAIL;
641 privateData = (tMMFILE_AAC_HANDLE *) handle;
643 if (privateData->formatType == AAC_FORMAT_ADIF) {
644 ret = _parse_aac_adif_header(privateData);
645 aacinfo->iseekable = 0;
647 ret = _parse_aac_adts_header(privateData);
648 aacinfo->iseekable = 1;
651 if (ret == MMFILE_AAC_PARSER_FAIL) {
652 debug_error("Error in parsing the stream header\n");
656 mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
658 if (privateData->formatType == AAC_FORMAT_ADTS) {
661 ret = _get_next_adts_frame_length(privateData, &frameLen);
662 if (ret != MMFILE_AAC_PARSER_SUCCESS) {
665 totalFrameLength += frameLen - MMFILE_AAC_ADTS_HEADER_MAX_SIZE;
669 if (ret == MMFILE_AAC_PARSER_FAIL) {
670 debug_error("Found corrupted frames!!! Ignoring\n");
673 #ifdef __MMFILE_TEST_MODE__
674 debug_msg("No of ADTS frames: %d\n", totalFrames);
676 privateData->streamInfo.frameRate = privateData->streamInfo.samplingRate / AAC_ADTS_SAMPLES_PER_FRAME;
678 if (privateData->streamInfo.frameRate)
679 privateData->streamInfo.duration = (totalFrames * 1000) / privateData->streamInfo.frameRate;
680 else privateData->streamInfo.duration = 0;
682 if (privateData->streamInfo.duration)
683 privateData->streamInfo.bitRate = (totalFrameLength * 8 * 1000) / (privateData->streamInfo.duration);
684 else privateData->streamInfo.bitRate = 0;
687 streamDataSize = (unsigned long long)privateData->streamInfo.fileSize - privateData->tagInfoSize;
688 privateData->streamInfo.duration = streamDataSize * 8 * 1000 / privateData->streamInfo.bitRate;
691 /* Return the stream info structure */
692 memcpy(aacinfo, &(privateData->streamInfo), sizeof(tMMFILE_AAC_STREAM_INFO));
694 return MMFILE_AAC_PARSER_SUCCESS;
698 int mmfile_aacparser_get_tag_info(MMFileAACHandle handle, tMMFILE_AAC_TAG_INFO *tagInfo)
700 tMMFILE_AAC_HANDLE *privateData = NULL;
703 if (NULL == handle || NULL == tagInfo) {
704 debug_error("handle is NULL\n");
705 return MMFILE_AAC_PARSER_FAIL;
708 privateData = (tMMFILE_AAC_HANDLE *) handle;
709 if (privateData->id3Handle.tagV2Info.tagVersion == 0) {
710 debug_warning("There is no Tag info\n");
711 return MMFILE_AAC_PARSER_SUCCESS;
714 ret = _parse_id3_tag(privateData);
715 if (ret == MMFILE_AAC_PARSER_FAIL) {
716 debug_warning("Error in parsing the Tag info\n");
720 /* Return the tag info structure */
721 memcpy(tagInfo, &(privateData->tagInfo), sizeof(tMMFILE_AAC_TAG_INFO));
723 return MMFILE_AAC_PARSER_SUCCESS;
727 int mmfile_aacparser_close(MMFileAACHandle handle)
729 tMMFILE_AAC_HANDLE *privateData = NULL;
731 if (NULL == handle) {
732 debug_error("handle is NULL\n");
733 return MMFILE_AAC_PARSER_FAIL;
736 privateData = (tMMFILE_AAC_HANDLE *) handle;
737 mm_file_free_AvFileContentInfo(&privateData->id3Handle);
739 mmfile_close(privateData->hFile);
741 return MMFILE_AAC_PARSER_SUCCESS;
745 /* mm plugin interface */
746 int mmfile_format_read_stream_aac(MMFileFormatContext *formatContext);
747 int mmfile_format_read_frame_aac(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
748 int mmfile_format_read_tag_aac(MMFileFormatContext *formatContext);
749 int mmfile_format_close_aac(MMFileFormatContext *formatContext);
753 int mmfile_format_open_aac(MMFileFormatContext *formatContext)
755 MMFileAACHandle handle = NULL;
756 int res = MMFILE_FORMAT_FAIL;
758 if (NULL == formatContext || NULL == formatContext->uriFileName) {
759 debug_error("error: mmfile_format_open_aac\n");
760 return MMFILE_FORMAT_FAIL;
763 if (formatContext->pre_checked == 0) {
764 res = MMFileFormatIsValidAAC(NULL, formatContext->uriFileName);
766 debug_error("It is not AAC file\n");
767 return MMFILE_FORMAT_FAIL;
771 formatContext->ReadStream = mmfile_format_read_stream_aac;
772 formatContext->ReadFrame = mmfile_format_read_frame_aac;
773 formatContext->ReadTag = mmfile_format_read_tag_aac;
774 formatContext->Close = mmfile_format_close_aac;
776 formatContext->videoTotalTrackNum = 0;
777 formatContext->audioTotalTrackNum = 1;
779 res = mmfile_aacparser_open(&handle, formatContext->uriFileName);
780 if (MMFILE_AAC_PARSER_FAIL == res) {
781 debug_error("mmfile_aacparser_open\n");
782 return MMFILE_FORMAT_FAIL;
785 formatContext->privateFormatData = handle;
787 return MMFILE_FORMAT_SUCCESS;
791 int mmfile_format_read_stream_aac(MMFileFormatContext *formatContext)
793 MMFileAACHandle handle = NULL;
794 tMMFILE_AAC_STREAM_INFO aacinfo = {0, };
795 MMFileFormatStream *audioStream = NULL;
797 int ret = MMFILE_FORMAT_FAIL;
799 if (NULL == formatContext) {
800 debug_error("error: invalid params\n");
801 ret = MMFILE_FORMAT_FAIL;
805 handle = formatContext->privateFormatData;
807 ret = mmfile_aacparser_get_stream_info(handle, &aacinfo);
808 if (MMFILE_FORMAT_SUCCESS != ret) {
809 debug_error("error: mmfile_aacparser_get_stream_info\n");
810 ret = MMFILE_FORMAT_FAIL;
814 formatContext->isseekable = aacinfo.iseekable;
815 formatContext->duration = aacinfo.duration;
816 formatContext->videoStreamId = -1;
817 formatContext->videoTotalTrackNum = 0;
818 formatContext->audioTotalTrackNum = aacinfo.numTracks;
819 formatContext->nbStreams = 1;
821 audioStream = mmfile_malloc(sizeof(MMFileFormatStream));
822 if (NULL == audioStream) {
823 debug_error("error: calloc_audiostream\n");
824 ret = MMFILE_FORMAT_FAIL;
828 audioStream->streamType = MMFILE_AUDIO_STREAM;
829 audioStream->codecId = MM_AUDIO_CODEC_AAC;
830 audioStream->bitRate = aacinfo.bitRate;
831 audioStream->framePerSec = aacinfo.frameRate;
832 audioStream->width = 0;
833 audioStream->height = 0;
834 audioStream->nbChannel = aacinfo.numAudioChannels;
835 audioStream->samplePerSec = aacinfo.samplingRate;
836 formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream;
838 #ifdef __MMFILE_TEST_MODE__
839 mmfile_format_print_contents(formatContext);
842 return MMFILE_FORMAT_SUCCESS;
849 int mmfile_format_read_tag_aac(MMFileFormatContext *formatContext)
851 MMFileAACHandle handle = NULL;
852 tMMFILE_AAC_TAG_INFO aacinfo = {0, };
853 int ret = MMFILE_FORMAT_FAIL;
855 if (NULL == formatContext) {
856 debug_error("error: invalid params\n");
857 ret = MMFILE_FORMAT_FAIL;
861 handle = formatContext->privateFormatData;
863 ret = mmfile_aacparser_get_tag_info(handle, &aacinfo);
864 if (MMFILE_FORMAT_SUCCESS != ret) {
865 debug_warning("error: mmfile_aacparser_get_tag_info\n");
866 ret = MMFILE_FORMAT_FAIL;
871 formatContext->title = mmfile_strdup(aacinfo.title);
873 formatContext->author = mmfile_strdup(aacinfo.author);
875 formatContext->artist = mmfile_strdup(aacinfo.artist);
877 formatContext->album = mmfile_strdup(aacinfo.album);
878 if (aacinfo.album_artist)
879 formatContext->album_artist = mmfile_strdup(aacinfo.album_artist);
881 formatContext->year = mmfile_strdup(aacinfo.year);
882 if (aacinfo.copyright)
883 formatContext->copyright = mmfile_strdup(aacinfo.copyright);
885 formatContext->comment = mmfile_strdup(aacinfo.comment);
887 formatContext->genre = mmfile_strdup(aacinfo.genre);
888 if (aacinfo.tracknum)
889 formatContext->tagTrackNum = mmfile_strdup(aacinfo.tracknum);
890 if (aacinfo.composer)
891 formatContext->composer = mmfile_strdup(aacinfo.composer);
892 if (aacinfo.classification)
893 formatContext->classification = mmfile_strdup(aacinfo.classification);
895 formatContext->rating = mmfile_strdup(aacinfo.rating); /*not exist rating tag in id3*/
896 if (aacinfo.conductor)
897 formatContext->conductor = mmfile_strdup(aacinfo.conductor);
898 if (aacinfo.artworkMime)
899 formatContext->artworkMime = mmfile_strdup(aacinfo.artworkMime);
900 if (aacinfo.artwork) {
901 formatContext->artworkSize = aacinfo.artworkSize;
902 formatContext->artwork = mmfile_malloc(aacinfo.artworkSize);
903 if (formatContext->artwork == NULL) {
904 ret = MMFILE_FORMAT_FAIL;
907 memcpy(formatContext->artwork, aacinfo.artwork, aacinfo.artworkSize);
910 #ifdef __MMFILE_TEST_MODE__
911 mmfile_format_print_contents(formatContext);
914 return MMFILE_FORMAT_SUCCESS;
922 int mmfile_format_read_frame_aac(MMFileFormatContext *formatContext,
923 unsigned int timestamp, MMFileFormatFrame *frame)
925 debug_error("error: mmfile_format_read_frame_aac, no handling\n");
927 return MMFILE_FORMAT_FAIL;
932 int mmfile_format_close_aac(MMFileFormatContext *formatContext)
934 MMFileAACHandle handle = NULL;
935 int ret = MMFILE_FORMAT_FAIL;
937 if (NULL == formatContext) {
938 debug_error("error: invalid params\n");
939 return MMFILE_FORMAT_FAIL;
942 handle = formatContext->privateFormatData;
944 if (NULL != handle) {
945 ret = mmfile_aacparser_close(handle);
946 if (ret == MMFILE_AAC_PARSER_FAIL) {
947 debug_error("error: mmfile_format_close_aac\n");
951 if (formatContext->streams[MMFILE_AUDIO_STREAM]) {
952 mmfile_free(formatContext->streams[MMFILE_AUDIO_STREAM]);
953 formatContext->streams[MMFILE_AUDIO_STREAM] = NULL;
956 formatContext->ReadStream = NULL;
957 formatContext->ReadFrame = NULL;
958 formatContext->ReadTag = NULL;
959 formatContext->Close = NULL;
961 return MMFILE_FORMAT_SUCCESS;