Unify duplicated codes regarding getting file size
[platform/core/multimedia/libmm-fileinfo.git] / formats / ffmpeg / mm_file_format_aac.c
1 /*
2  * libmm-fileinfo
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Haejeong Kim <backto.kim@samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 #include <stdio.h>
23 #include <string.h>     /*memcmp*/
24 #include <stdlib.h>     /*malloc*/
25
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"
30
31
32 /* Internal Error Type */
33 #define MMFILE_AAC_PARSER_FILE_END 2
34
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
40
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))
43
44
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) | \
49                                                         (((int)(buff)[3])))
50
51 #define GET_SHORT_NUMBER(buff) (short)(((short)(buff)[0] << 8) | \
52                                                         ((short)(buff)[1]))
53
54
55
56 typedef enum _mmfile_aac_format_type {
57         AAC_FORMAT_ADIF,
58         AAC_FORMAT_ADTS,
59         AAC_FORMAT_UNKNOWN
60 } TAacFormatType;
61
62 typedef enum _mmfile_aac_bitstream_type {
63         AAC_STREAM_CONSTANT,
64         AAC_STREAM_VARIABLE
65 } TAacStreamType;
66
67 typedef enum _mmfile_aac_mpeg_type {
68         AAC_MPEG_4,
69         AAC_MPEG_2
70 } TAacMpegType;
71
72 typedef struct _mmfile_aac_handle {
73         MMFileIOHandle         *hFile;
74         AvFileContentInfo       id3Handle;
75         unsigned int            streamOffset;
76         unsigned int            tagOffset;
77         char                    isTagPresent;
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;
85 } tMMFILE_AAC_HANDLE;
86
87
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,
92                                                                 0,     0,      0,     0
93                                                                 };
94
95 /* internal APIs */
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);
103
104
105 void _aac_init_handle(tMMFILE_AAC_HANDLE *privateData)
106 {
107         /* Default Initializations */
108         privateData->streamOffset = 0;
109         privateData->isTagPresent = FALSE;
110         privateData->streamOffset = 0;
111         privateData->tagOffset = 0;
112
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;
121
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;
139 }
140
141
142 int _search_id3tag(tMMFILE_AAC_HANDLE *pData)
143 {
144         unsigned char tagHeader[MP3_TAGv2_HEADER_LEN] = {0, };
145         int encSize = 0;
146         int readed = 0;
147
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;
153         }
154
155         if (!IS_ID3V2_TAG(tagHeader)) {
156                 debug_msg(RELEASE, "No ID3 Tag");
157                 goto search_end;
158         }
159
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;
165         }
166
167         pData->tagVersion = tagHeader[3];
168
169         if (pData->tagVersion > 4) {
170                 debug_msg(RELEASE, "\nTag version not supported");
171                 return MMFILE_AAC_PARSER_FAIL;
172         }
173
174         encSize = GET_INT_NUMBER(&tagHeader[6]);
175         pData->tagInfoSize = MP3_TAGv2_HEADER_LEN;
176
177         pData->tagInfoSize += (((encSize & 0x0000007F) >> 0) | ((encSize & 0x00007F00) >> 1) |  \
178                                                 ((encSize & 0x007F0000) >> 2) | ((encSize & 0x7F000000) >> 3));
179
180         if (pData->tagInfoSize > pData->streamInfo.fileSize) {
181                 debug_msg(RELEASE, "Invalid size");
182                 return MMFILE_AAC_PARSER_FAIL;
183         }
184
185         pData->isTagPresent = TRUE;
186         pData->tagOffset = 0;
187         pData->streamOffset = pData->tagInfoSize;
188
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;
194
195 search_end:
196         return MMFILE_AAC_PARSER_SUCCESS;
197 }
198
199
200 int _parse_id3_tag(tMMFILE_AAC_HANDLE *pData)
201 {
202         unsigned char *tagBuff = NULL;
203         AvFileContentInfo *hTag = &pData->id3Handle;
204         int ret = FALSE;
205         int readed = 0;
206
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);
212                 goto failure;
213         }
214
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);
218                 goto failure;
219         }
220
221         switch (hTag->tagV2Info.tagVersion) {
222         case 1:
223                 ret = mm_file_id3tag_parse_v110(hTag, tagBuff);
224                 break;
225         case 2:
226                 ret = mm_file_id3tag_parse_v222(hTag, tagBuff);
227                 break;
228         case 3:
229                 ret = mm_file_id3tag_parse_v223(hTag, tagBuff);
230                 break;
231         case 4:
232                 ret = mm_file_id3tag_parse_v224(hTag, tagBuff);
233                 break;
234         default:
235                 debug_error(DEBUG, "Invalid Tag version [%d]\n", hTag->tagV2Info.tagVersion);
236                 break;
237         }
238
239         if (ret == FALSE) {
240                 ret = MMFILE_AAC_PARSER_FAIL;
241                 debug_warning(DEBUG, "failed to parse\n");
242                 goto failure;
243         }
244
245         mm_file_id3tag_restore_content_info(hTag);
246
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;
263
264         ret = MMFILE_AAC_PARSER_SUCCESS;
265
266
267 failure:
268         mmfile_free(tagBuff);
269
270         return ret;
271 }
272
273
274 int _get_range_bits_value(unsigned char *buff, int fieldOffset, int fieldSize)
275 {
276         int pos = 0;
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;
287
288
289         srcByteStartOff = (fieldOffset / 8);
290         srcBitStartOff = (fieldOffset % 8);
291
292         srcByteEndOff = ((fieldOffset + fieldSize - 1) / 8);
293         srcBitEndOff = ((fieldOffset + fieldSize - 1) % 8);
294
295         occupiedBytes = srcByteEndOff - srcByteStartOff + 1;
296
297         for (i = srcByteStartOff, j = 0; i <= srcByteEndOff && j <= 3; i++, j++) {
298                 dest[j] = buff[i];
299         }
300
301         for (pos = 7; pos >= (char)srcBitStartOff; pos--) {
302                 mask = mask | maskBit;
303                 maskBit <<= 1;
304         }
305
306         dest[0] = dest[0] & mask;
307
308         if (i <= srcByteEndOff) {
309                 extraByteFlag = 1;
310         }
311
312         res = GET_INT_NUMBER(dest);
313
314         if (!extraByteFlag) {
315                 temp = (4 - occupiedBytes) * 8 + (7 - srcBitEndOff);
316                 res >>= temp;
317         }
318
319         if (extraByteFlag) {
320                 res <<= srcBitStartOff;
321                 temp = buff[srcByteEndOff] >> (7 - srcBitEndOff);
322                 res = res | (unsigned int)temp;
323         }
324
325         return res;
326 }
327
328
329 int _parse_aac_adif_header(tMMFILE_AAC_HANDLE *pData)
330 {
331         unsigned char adifHeader[MMFILE_AAC_ADIF_HEADER_MAX_SIZE] = {0, };
332         int currentBitOffset = 0;
333         unsigned int fieldValue = 0;
334         int copyRightStatus = 0;
335         int readed = 0;
336
337         mmfile_seek(pData->hFile, pData->streamOffset, MMFILE_SEEK_SET);
338         readed = mmfile_read(pData->hFile, adifHeader, MMFILE_AAC_ADIF_HEADER_MAX_SIZE);
339         if (readed < 0) {
340                 return MMFILE_AAC_PARSER_FAIL;
341         }
342
343         if (memcmp(adifHeader, "ADIF", 4) != 0) {
344                 return MMFILE_AAC_PARSER_FAIL;
345         }
346         currentBitOffset += 32;
347
348         copyRightStatus = _get_range_bits_value(adifHeader, currentBitOffset, 1);
349         currentBitOffset += 1;
350
351         if (copyRightStatus) {
352                 /*skipping Copyright info */
353                 currentBitOffset += 72;
354         }
355
356         /*Original/copy */
357         fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 1);
358         currentBitOffset += 1;
359
360         /*skipping Home status */
361         currentBitOffset += 1;
362
363         /*Bit stream type */
364         fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 1);
365         currentBitOffset += 1;
366         if (!fieldValue) {
367                 pData->streamType = AAC_STREAM_CONSTANT;
368         } else {
369                 pData->streamType = AAC_STREAM_VARIABLE;
370         }
371
372         /*Bit-rate */
373         pData->streamInfo.bitRate = _get_range_bits_value(adifHeader, currentBitOffset, 23);
374         currentBitOffset += 23;
375
376         /*Num of program config elements */
377         fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 4);
378         currentBitOffset += 4;
379
380         /*skipping adif buffer fullness */
381         currentBitOffset += 20;
382
383         /*skipping element instance tag */
384         currentBitOffset += 4;
385
386         /*Profile */
387         pData->streamInfo.profileType = _get_range_bits_value(adifHeader, currentBitOffset, 2);
388         currentBitOffset += 2;
389
390         /*sampling freq index */
391         fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 4);
392         currentBitOffset += 4;
393         pData->streamInfo.samplingRate = Sampling_freq_table[fieldValue];
394
395         /*num_front_channel_elements */
396         pData->streamInfo.numAudioChannels = _get_range_bits_value(adifHeader, currentBitOffset, 4);
397         currentBitOffset += 4;
398
399         /*num_side_channel_elements */
400         pData->streamInfo.numAudioChannels += _get_range_bits_value(adifHeader, currentBitOffset, 4);
401         currentBitOffset += 4;
402
403         /*num_back_channel_elements */
404         pData->streamInfo.numAudioChannels += _get_range_bits_value(adifHeader, currentBitOffset, 4);
405         currentBitOffset += 4;
406
407         /*num_lfe_channel_elements */
408         pData->streamInfo.numAudioChannels += _get_range_bits_value(adifHeader, currentBitOffset, 2);
409
410         return MMFILE_AAC_PARSER_SUCCESS;
411
412 }
413
414
415 int _parse_aac_adts_header(tMMFILE_AAC_HANDLE *pData)
416 {
417         unsigned char adtsHeader[MMFILE_AAC_ADTS_HEADER_MAX_SIZE] = {0, };
418         int currentBitOffset = 0;
419         unsigned int fieldValue = 0;
420         int readed = 0;
421
422         mmfile_seek(pData->hFile, pData->streamOffset, MMFILE_SEEK_SET);
423         readed = mmfile_read(pData->hFile, adtsHeader, MMFILE_AAC_ADTS_HEADER_MAX_SIZE);
424         if (readed < 0) {
425                 return MMFILE_AAC_PARSER_FAIL;
426         }
427
428         if (!IS_AAC_ADTS_HEADER(adtsHeader)) {
429                 return MMFILE_AAC_PARSER_FAIL;
430         }
431         currentBitOffset += 12;
432
433         /*adtsId */
434         fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 1);
435         currentBitOffset += 1;
436         pData->mpegType = (fieldValue != 0);
437
438         /*LayerType */
439         fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 2);
440         currentBitOffset += 2;
441
442         /*skipping Protection Absent */
443         currentBitOffset += 1;
444
445         /*ProfileType */
446         fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 2);
447         currentBitOffset += 2;
448         pData->streamInfo.profileType = fieldValue;
449
450         /*SamplingrateIndex */
451         fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 4);
452         currentBitOffset += 4;
453         pData->streamInfo.samplingRate = Sampling_freq_table[fieldValue];
454
455         /*skipping PrivateBit */
456         currentBitOffset += 1;
457
458         /*ChannelConfig */
459         pData->streamInfo.numAudioChannels = _get_range_bits_value(adtsHeader, currentBitOffset, 3);
460         currentBitOffset += 3;
461
462         /*Original/copy status */
463         fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 1);
464         currentBitOffset += 1;
465
466         /*skipping Home status */
467         fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 1);
468
469         return MMFILE_AAC_PARSER_SUCCESS;
470 }
471
472
473 int _get_next_adts_frame_length(tMMFILE_AAC_HANDLE *pData, int *frameLen)
474 {
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);
478         int readed = 0;
479
480         readed = mmfile_read(pData->hFile, adtsHeader, MMFILE_AAC_ADTS_HEADER_MAX_SIZE);
481         if (readed < 0)
482                 return MMFILE_AAC_PARSER_FAIL;
483
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]);
487
488         if (mmfile_tell(pData->hFile) >= pData->streamInfo.fileSize) {
489                 *frameLen = 0;
490                 ret = MMFILE_AAC_PARSER_FILE_END;
491                 goto function_end;
492         }
493
494         if (!IS_AAC_ADTS_HEADER(adtsHeader)) {
495                 *frameLen = 0;
496                 ret = MMFILE_AAC_PARSER_FAIL;
497                 goto function_end;
498         }
499
500         *frameLen = _get_range_bits_value(adtsHeader, AAC_ADTS_FRAME_LEN_OFFSET, 13);
501
502         if (*frameLen == 0 || *frameLen > (pData->streamInfo.fileSize - filePosBefore)) {
503                 *frameLen = 0;
504                 ret = MMFILE_AAC_PARSER_FAIL;
505                 goto function_end;
506         }
507
508 function_end:
509
510         mmfile_seek(pData->hFile, filePosBefore + *frameLen, MMFILE_SEEK_SET);
511
512         return ret;
513 }
514
515
516 int mmfile_aacparser_open(MMFileAACHandle *handle, const char *filenamec)
517 {
518         tMMFILE_AAC_HANDLE *privateData = NULL;
519         int ret = 0;
520         unsigned char header[4] = {0, };
521         int firstFrameLen = 0;
522         int readed = 0;
523
524         if (NULL == filenamec) {
525                 debug_error(DEBUG, "file source is NULL\n");
526                 return MMFILE_AAC_PARSER_FAIL;
527         }
528
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;
533         }
534
535         ret = mmfile_open(&privateData->hFile, filenamec, MMFILE_RDONLY);
536         if (ret == MMFILE_UTIL_FAIL) {
537                 debug_error(DEBUG, "error: mmfile_open\n");
538                 goto exception;
539         }
540
541         /* Initialize the members of handle */
542         _aac_init_handle(privateData);
543
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");
547                 goto exception;
548         }
549
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");
554                 goto exception;
555         }
556
557         mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
558         readed = mmfile_read(privateData->hFile, header, 4);
559         if (readed != 4)
560                 goto exception;
561
562         if (IS_AAC_ADIF_HEADER(header)) {
563                 privateData->formatType = AAC_FORMAT_ADIF;
564
565                 debug_msg(RELEASE, "AAC Format: ADIF\n");
566
567         } else if (IS_AAC_ADTS_HEADER(header)) {
568                 privateData->formatType = AAC_FORMAT_ADTS;
569
570                 debug_msg(RELEASE, "AAC Format: ADTS\n");
571
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");
577                         goto exception;
578                 }
579         } else {
580                 privateData->formatType = AAC_FORMAT_UNKNOWN;
581                 debug_error(DEBUG, "AAC Format: UNKNOWN\n");
582                 goto exception;
583         }
584
585         *handle = privateData;
586
587         return MMFILE_AAC_PARSER_SUCCESS;
588
589 exception:
590         if (privateData) {
591                 mmfile_close(privateData->hFile);
592                 mmfile_free(privateData);
593                 *handle = NULL;
594         }
595         return MMFILE_AAC_PARSER_FAIL;
596
597 }
598
599
600 int mmfile_aacparser_get_stream_info(MMFileAACHandle handle, tMMFILE_AAC_STREAM_INFO *aacinfo)
601 {
602         tMMFILE_AAC_HANDLE *privateData = NULL;
603         int frameLen = 0;
604         long long totalFrames = 0, totalFrameLength = 0;
605         unsigned long long streamDataSize = 0;
606         int ret = MMFILE_AAC_PARSER_SUCCESS;
607
608         if (NULL == handle || NULL == aacinfo) {
609                 debug_error(DEBUG, "handle is NULL\n");
610                 return MMFILE_AAC_PARSER_FAIL;
611         }
612
613         privateData = (tMMFILE_AAC_HANDLE *) handle;
614
615         if (privateData->formatType == AAC_FORMAT_ADIF) {
616                 ret = _parse_aac_adif_header(privateData);
617                 aacinfo->iseekable = 0;
618         } else {
619                 ret = _parse_aac_adts_header(privateData);
620                 aacinfo->iseekable = 1;
621         }
622
623         if (ret == MMFILE_AAC_PARSER_FAIL) {
624                 debug_error(DEBUG, "Error in parsing the stream header\n");
625                 return ret;
626         }
627
628         mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
629
630         if (privateData->formatType == AAC_FORMAT_ADTS) {
631
632                 while (TRUE) {
633                         ret = _get_next_adts_frame_length(privateData, &frameLen);
634                         if (ret != MMFILE_AAC_PARSER_SUCCESS) {
635                                 break;
636                         }
637                         totalFrameLength += frameLen - MMFILE_AAC_ADTS_HEADER_MAX_SIZE;
638                         totalFrames++;
639                 }
640
641                 if (ret == MMFILE_AAC_PARSER_FAIL) {
642                         debug_error(DEBUG, "Found corrupted frames!!! Ignoring\n");
643                 }
644
645                 debug_msg(RELEASE, "No of ADTS frames: %lld\n", totalFrames);
646
647                 privateData->streamInfo.frameRate = privateData->streamInfo.samplingRate / AAC_ADTS_SAMPLES_PER_FRAME;
648
649                 if (privateData->streamInfo.frameRate)
650                         privateData->streamInfo.duration = (totalFrames * 1000) / privateData->streamInfo.frameRate;
651                 else privateData->streamInfo.duration = 0;
652
653                 if (privateData->streamInfo.duration)
654                         privateData->streamInfo.bitRate = (totalFrameLength * 8 * 1000) / (privateData->streamInfo.duration);
655                 else privateData->streamInfo.bitRate = 0;
656
657         } else {
658                 streamDataSize = (unsigned long long)privateData->streamInfo.fileSize - privateData->tagInfoSize;
659                 privateData->streamInfo.duration = streamDataSize * 8 * 1000 / privateData->streamInfo.bitRate;
660         }
661
662         /* Return the stream info structure */
663         memcpy(aacinfo, &(privateData->streamInfo), sizeof(tMMFILE_AAC_STREAM_INFO));
664
665         return MMFILE_AAC_PARSER_SUCCESS;
666 }
667
668
669 int mmfile_aacparser_get_tag_info(MMFileAACHandle handle, tMMFILE_AAC_TAG_INFO *tagInfo)
670 {
671         tMMFILE_AAC_HANDLE *privateData = NULL;
672         int ret = 0;
673
674         if (NULL == handle || NULL == tagInfo) {
675                 debug_error(DEBUG, "handle is NULL\n");
676                 return MMFILE_AAC_PARSER_FAIL;
677         }
678
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;
683         }
684
685         ret = _parse_id3_tag(privateData);
686         if (ret == MMFILE_AAC_PARSER_FAIL) {
687                 debug_warning(DEBUG, "Error in parsing the Tag info\n");
688                 return ret;
689         }
690
691         /* Return the tag info structure */
692         memcpy(tagInfo, &(privateData->tagInfo), sizeof(tMMFILE_AAC_TAG_INFO));
693
694         return MMFILE_AAC_PARSER_SUCCESS;
695 }
696
697
698 int mmfile_aacparser_close(MMFileAACHandle handle)
699 {
700         tMMFILE_AAC_HANDLE *privateData = NULL;
701
702         if (NULL == handle) {
703                 debug_error(DEBUG, "handle is NULL\n");
704                 return MMFILE_AAC_PARSER_FAIL;
705         }
706
707         privateData = (tMMFILE_AAC_HANDLE *) handle;
708         mm_file_free_AvFileContentInfo(&privateData->id3Handle);
709
710         mmfile_close(privateData->hFile);
711
712         return MMFILE_AAC_PARSER_SUCCESS;
713 }
714
715
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);
721
722
723 EXPORT_API
724 int mmfile_format_open_aac(MMFileFormatContext *formatContext)
725 {
726         MMFileAACHandle handle = NULL;
727         int res = MMFILE_FORMAT_FAIL;
728
729         if (NULL == formatContext || NULL == formatContext->uriFileName) {
730                 debug_error(DEBUG, "error: mmfile_format_open_aac\n");
731                 return MMFILE_FORMAT_FAIL;
732         }
733
734         res = MMFileFormatIsValidAAC(NULL, formatContext->uriFileName, 0);
735         if (res == 0) {
736                 debug_error(DEBUG, "It is not AAC file\n");
737                 return MMFILE_FORMAT_FAIL;
738         }
739
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;
744
745         formatContext->videoTotalTrackNum = 0;
746         formatContext->audioTotalTrackNum = 1;
747
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;
752         }
753
754         formatContext->privateFormatData = handle;
755
756         return MMFILE_FORMAT_SUCCESS;
757 }
758
759 EXPORT_API
760 int mmfile_format_read_stream_aac(MMFileFormatContext *formatContext)
761 {
762         MMFileAACHandle     handle = NULL;
763         tMMFILE_AAC_STREAM_INFO  aacinfo = {0, };
764         MMFileFormatStream  *audioStream = NULL;
765
766         int ret = MMFILE_FORMAT_FAIL;
767
768         if (NULL == formatContext) {
769                 debug_error(DEBUG, "error: invalid params\n");
770                 ret = MMFILE_FORMAT_FAIL;
771                 goto exception;
772         }
773
774         handle = formatContext->privateFormatData;
775
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;
780                 goto exception;
781         }
782
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;
789
790         audioStream = mmfile_malloc(sizeof(MMFileFormatStream));
791         if (NULL == audioStream) {
792                 debug_error(DEBUG, "error: calloc_audiostream\n");
793                 ret = MMFILE_FORMAT_FAIL;
794                 goto exception;
795         }
796
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;
806
807 #ifdef  __MMFILE_TEST_MODE__
808         mmfile_format_print_contents(formatContext);
809 #endif
810
811         return MMFILE_FORMAT_SUCCESS;
812
813 exception:
814         return ret;
815 }
816
817 EXPORT_API
818 int mmfile_format_read_tag_aac(MMFileFormatContext *formatContext)
819 {
820         MMFileAACHandle     handle = NULL;
821         tMMFILE_AAC_TAG_INFO  aacinfo = {0, };
822         int ret = MMFILE_FORMAT_FAIL;
823
824         if (NULL == formatContext) {
825                 debug_error(DEBUG, "error: invalid params\n");
826                 ret = MMFILE_FORMAT_FAIL;
827                 goto exception;
828         }
829
830         handle = formatContext->privateFormatData;
831
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;
836                 goto exception;
837         }
838
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;
859                         goto exception;
860                 }
861                 memcpy(formatContext->artwork, aacinfo.artwork, aacinfo.artworkSize);
862         }
863
864 #ifdef  __MMFILE_TEST_MODE__
865         mmfile_format_print_contents(formatContext);
866 #endif
867
868         return MMFILE_FORMAT_SUCCESS;
869
870 exception:
871         return ret;
872 }
873
874
875 EXPORT_API
876 int mmfile_format_read_frame_aac(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
877 {
878         debug_error(DEBUG, "error: mmfile_format_read_frame_aac, no handling\n");
879
880         return MMFILE_FORMAT_FAIL;
881 }
882
883
884 EXPORT_API
885 int mmfile_format_close_aac(MMFileFormatContext *formatContext)
886 {
887         MMFileAACHandle  handle = NULL;
888         int ret = MMFILE_FORMAT_FAIL;
889
890         if (NULL == formatContext) {
891                 debug_error(DEBUG, "error: invalid params\n");
892                 return MMFILE_FORMAT_FAIL;
893         }
894
895         handle = formatContext->privateFormatData;
896
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");
901                 }
902         }
903
904         mmfile_free(formatContext->streams[MMFILE_AUDIO_STREAM]);
905
906         formatContext->ReadStream   = NULL;
907         formatContext->ReadFrame    = NULL;
908         formatContext->ReadTag      = NULL;
909         formatContext->Close        = NULL;
910
911         return MMFILE_FORMAT_SUCCESS;
912 }
913
914