Removed instructions which were not required.
[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_error.h>
27
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"
32
33
34 /* Internal Error Type */
35 #define MMFILE_AAC_PARSER_FILE_END 2
36
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
42
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))
45
46
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) | \
51                                     (((int)(buff)[3])))
52
53 #define GET_SHORT_NUMBER(buff) (short)(((short)(buff)[0] << 8) | \
54                                         ((short)(buff)[1]))
55
56
57
58 typedef enum _mmfile_aac_format_type {
59         AAC_FORMAT_ADIF,
60         AAC_FORMAT_ADTS,
61         AAC_FORMAT_UNKNOWN
62 } TAacFormatType;
63
64 typedef enum _mmfile_aac_bitstream_type {
65         AAC_STREAM_CONSTANT,
66         AAC_STREAM_VARIABLE
67 } TAacStreamType;
68
69 typedef enum _mmfile_aac_mpeg_type {
70         AAC_MPEG_4,
71         AAC_MPEG_2
72 } TAacMpegType;
73
74 typedef struct _mmfile_aac_handle {
75         MMFileIOHandle         *hFile;
76         AvFileContentInfo       id3Handle;
77         unsigned int            streamOffset;
78         unsigned int            tagOffset;
79         char                    isTagPresent;
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;
87 } tMMFILE_AAC_HANDLE;
88
89
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,
94                                       0,     0,      0,     0
95                                     };
96
97 /* internal APIs */
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);
105
106
107 void _aac_init_handle(tMMFILE_AAC_HANDLE *privateData)
108 {
109         /* Default Initializations */
110         privateData->streamOffset = 0;
111         privateData->isTagPresent = FALSE;
112         privateData->streamOffset = 0;
113         privateData->tagOffset = 0;
114
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;
123
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;
141 }
142
143
144 int _search_id3tag(tMMFILE_AAC_HANDLE *pData)
145 {
146         unsigned char tagHeader[MP3_TAGv2_HEADER_LEN] = {0, };
147         int encSize = 0;
148         int readed = 0;
149
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");
155 #endif
156                 return MMFILE_AAC_PARSER_FAIL;
157         }
158
159         if (!IS_ID3V2_TAG(tagHeader)) {
160 #ifdef __MMFILE_TEST_MODE__
161                 debug_msg("No ID3 Tag");
162 #endif
163                 goto search_end;
164         }
165
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");
171 #endif
172                 return MMFILE_AAC_PARSER_FAIL;
173         }
174
175         pData->tagVersion = tagHeader[3];
176
177         if (pData->tagVersion > 4) {
178 #ifdef __MMFILE_TEST_MODE__
179                 debug_msg("\nTag version not supported");
180 #endif
181                 return MMFILE_AAC_PARSER_FAIL;
182         }
183
184         encSize = GET_INT_NUMBER(&tagHeader[6]);
185         pData->tagInfoSize = MP3_TAGv2_HEADER_LEN;
186
187         pData->tagInfoSize += (((encSize & 0x0000007F) >> 0) | ((encSize & 0x00007F00) >> 1) |  \
188                                ((encSize & 0x007F0000) >> 2) | ((encSize & 0x7F000000) >> 3));
189
190         if (pData->tagInfoSize > pData->streamInfo.fileSize) {
191 #ifdef __MMFILE_TEST_MODE__
192                 debug_msg("Invalid size");
193 #endif
194                 return MMFILE_AAC_PARSER_FAIL;
195         }
196
197         pData->isTagPresent = TRUE;
198         pData->tagOffset = 0;
199         pData->streamOffset = pData->tagInfoSize;
200
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;
206
207 search_end:
208         return MMFILE_AAC_PARSER_SUCCESS;
209 }
210
211
212 int _parse_id3_tag(tMMFILE_AAC_HANDLE *pData)
213 {
214         unsigned char *tagBuff = NULL;
215         AvFileContentInfo *hTag = &pData->id3Handle;
216         int ret = FALSE;
217         int readed = 0;
218
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);
224                 goto failure;
225         }
226
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);
230                 goto failure;
231         }
232
233         switch (hTag->tagV2Info.tagVersion) {
234                 case 1:
235                         ret = mm_file_id3tag_parse_v110(hTag, tagBuff);
236                         break;
237                 case 2:
238                         ret = mm_file_id3tag_parse_v222(hTag, tagBuff);
239                         break;
240                 case 3:
241                         ret = mm_file_id3tag_parse_v223(hTag, tagBuff);
242                         break;
243                 case 4:
244                         ret = mm_file_id3tag_parse_v224(hTag, tagBuff);
245                         break;
246                 default:
247                         debug_error("Invalid Tag version [%d]\n", hTag->tagV2Info.tagVersion);
248                         break;
249         }
250
251         if (ret == FALSE) {
252                 ret = MMFILE_AAC_PARSER_FAIL;
253                 debug_warning("failed to parse\n");
254                 goto failure;
255         }
256
257         mm_file_id3tag_restore_content_info(hTag);
258
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;
277
278         ret = MMFILE_AAC_PARSER_SUCCESS;
279
280
281 failure:
282         if (tagBuff) {
283                 mmfile_free(tagBuff);
284                 tagBuff = NULL;
285         }
286
287         return ret;
288
289 }
290
291
292 int _get_range_bits_value(unsigned char *buff, int fieldOffset, int fieldSize)
293 {
294         int pos = 0;
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;
305
306
307         srcByteStartOff = (fieldOffset / 8);
308         srcBitStartOff = (fieldOffset % 8);
309
310         srcByteEndOff = ((fieldOffset + fieldSize - 1) / 8);
311         srcBitEndOff = ((fieldOffset + fieldSize - 1) % 8);
312
313         occupiedBytes = srcByteEndOff - srcByteStartOff + 1;
314
315         for (i = srcByteStartOff, j = 0; i <= srcByteEndOff && j <= 3; i++, j++) {
316                 dest[j] = buff[i];
317         }
318
319         for (pos = 7; pos >= (char)srcBitStartOff; pos--) {
320                 mask = mask | maskBit;
321                 maskBit <<= 1;
322         }
323
324         dest[0] = dest[0] & mask;
325
326         if (i <= srcByteEndOff) {
327                 extraByteFlag = 1;
328         }
329
330         res = GET_INT_NUMBER(dest);
331
332         if (!extraByteFlag) {
333                 temp = (4 - occupiedBytes) * 8 + (7 - srcBitEndOff);
334                 res >>= temp;
335         }
336
337         if (extraByteFlag) {
338                 res <<= srcBitStartOff;
339                 temp = buff[srcByteEndOff] >> (7 - srcBitEndOff);
340                 res = res | (unsigned int)temp;
341         }
342
343         return res;
344 }
345
346
347 int _parse_aac_adif_header(tMMFILE_AAC_HANDLE *pData)
348 {
349         unsigned char adifHeader[MMFILE_AAC_ADIF_HEADER_MAX_SIZE] = {0, };
350         int currentBitOffset = 0;
351         unsigned int fieldValue = 0;
352         int copyRightStatus = 0;
353         int readed = 0;
354
355         mmfile_seek(pData->hFile, pData->streamOffset, MMFILE_SEEK_SET);
356         readed = mmfile_read(pData->hFile, adifHeader, MMFILE_AAC_ADIF_HEADER_MAX_SIZE);
357         if (readed < 0) {
358                 return MMFILE_AAC_PARSER_FAIL;
359         }
360
361         if (memcmp(adifHeader, "ADIF", 4) != 0) {
362                 return MMFILE_AAC_PARSER_FAIL;
363         }
364         currentBitOffset += 32;
365
366         copyRightStatus = _get_range_bits_value(adifHeader, currentBitOffset, 1);
367         currentBitOffset += 1;
368
369         if (copyRightStatus) {
370                 /*skipping Copyright info */
371                 currentBitOffset += 72;
372         }
373
374         /*Original/copy */
375         fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 1);
376         currentBitOffset += 1;
377
378         /*skipping Home status */
379         currentBitOffset += 1;
380
381         /*Bit stream type */
382         fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 1);
383         currentBitOffset += 1;
384         if (!fieldValue) {
385                 pData->streamType = AAC_STREAM_CONSTANT;
386         } else {
387                 pData->streamType = AAC_STREAM_VARIABLE;
388         }
389
390         /*Bit-rate */
391         pData->streamInfo.bitRate = _get_range_bits_value(adifHeader, currentBitOffset, 23);
392         currentBitOffset += 23;
393
394         /*Num of program config elements */
395         fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 4);
396         currentBitOffset += 4;
397
398         /*skipping adif buffer fullness */
399         currentBitOffset += 20;
400
401         /*skipping element instance tag */
402         currentBitOffset += 4;
403
404         /*Profile */
405         pData->streamInfo.profileType = _get_range_bits_value(adifHeader, currentBitOffset, 2);
406         currentBitOffset += 2;
407
408         /*sampling freq index */
409         fieldValue = _get_range_bits_value(adifHeader, currentBitOffset, 4);
410         currentBitOffset += 4;
411         pData->streamInfo.samplingRate = Sampling_freq_table[fieldValue];
412
413         /*num_front_channel_elements */
414         pData->streamInfo.numAudioChannels = _get_range_bits_value(adifHeader, currentBitOffset, 4);
415         currentBitOffset += 4;
416
417         /*num_side_channel_elements */
418         pData->streamInfo.numAudioChannels += _get_range_bits_value(adifHeader, currentBitOffset, 4);
419         currentBitOffset += 4;
420
421         /*num_back_channel_elements */
422         pData->streamInfo.numAudioChannels += _get_range_bits_value(adifHeader, currentBitOffset, 4);
423         currentBitOffset += 4;
424
425         /*num_lfe_channel_elements */
426         pData->streamInfo.numAudioChannels += _get_range_bits_value(adifHeader, currentBitOffset, 2);
427
428         return MMFILE_AAC_PARSER_SUCCESS;
429
430 }
431
432
433 int _parse_aac_adts_header(tMMFILE_AAC_HANDLE *pData)
434 {
435         unsigned char adtsHeader[MMFILE_AAC_ADTS_HEADER_MAX_SIZE] = {0, };
436         int currentBitOffset = 0;
437         unsigned int fieldValue = 0;
438         int readed = 0;
439
440         mmfile_seek(pData->hFile, pData->streamOffset, MMFILE_SEEK_SET);
441         readed = mmfile_read(pData->hFile, adtsHeader, MMFILE_AAC_ADTS_HEADER_MAX_SIZE);
442         if (readed < 0) {
443                 return MMFILE_AAC_PARSER_FAIL;
444         }
445
446         if (!IS_AAC_ADTS_HEADER(adtsHeader)) {
447                 return MMFILE_AAC_PARSER_FAIL;
448         }
449         currentBitOffset += 12;
450
451         /*adtsId */
452         fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 1);
453         currentBitOffset += 1;
454         pData->mpegType = (fieldValue != 0);
455
456         /*LayerType */
457         fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 2);
458         currentBitOffset += 2;
459
460         /*skipping Protection Absent */
461         currentBitOffset += 1;
462
463         /*ProfileType */
464         fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 2);
465         currentBitOffset += 2;
466         pData->streamInfo.profileType = fieldValue;
467
468         /*SamplingrateIndex */
469         fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 4);
470         currentBitOffset += 4;
471         pData->streamInfo.samplingRate = Sampling_freq_table[fieldValue];
472
473         /*skipping PrivateBit */
474         currentBitOffset += 1;
475
476         /*ChannelConfig */
477         pData->streamInfo.numAudioChannels = _get_range_bits_value(adtsHeader, currentBitOffset, 3);
478         currentBitOffset += 3;
479
480         /*Original/copy status */
481         fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 1);
482         currentBitOffset += 1;
483
484         /*skipping Home status */
485         fieldValue = _get_range_bits_value(adtsHeader, currentBitOffset, 1);
486
487         return MMFILE_AAC_PARSER_SUCCESS;
488 }
489
490
491 int _get_next_adts_frame_length(tMMFILE_AAC_HANDLE *pData, int *frameLen)
492 {
493         unsigned char adtsHeader[MMFILE_AAC_ADTS_HEADER_MAX_SIZE] = {0, };
494         int ret = MMFILE_AAC_PARSER_SUCCESS;
495         long long filePosBefore = mmfile_tell(pData->hFile);
496         int readed = 0;
497
498         readed = mmfile_read(pData->hFile, adtsHeader, MMFILE_AAC_ADTS_HEADER_MAX_SIZE);
499         if (readed < 0)
500                 return MMFILE_AAC_PARSER_FAIL;
501
502 #ifdef __MMFILE_TEST_MODE__
503         debug_msg("\nFILE POS: %lld\n", filePosBefore);
504         debug_msg("\nADTS HEADER: [%2x] [%2x] [%2x] [%2x] [%2x] [%2x]\n",
505                   adtsHeader[0], adtsHeader[1], adtsHeader[2], adtsHeader[3], adtsHeader[4], adtsHeader[5]);
506 #endif
507
508         if (mmfile_tell(pData->hFile) >= pData->streamInfo.fileSize) {
509                 *frameLen = 0;
510                 ret = MMFILE_AAC_PARSER_FILE_END;
511                 goto function_end;
512         }
513
514         if (!IS_AAC_ADTS_HEADER(adtsHeader)) {
515                 *frameLen = 0;
516                 ret = MMFILE_AAC_PARSER_FAIL;
517                 goto function_end;
518         }
519
520         *frameLen = _get_range_bits_value(adtsHeader, AAC_ADTS_FRAME_LEN_OFFSET, 13);
521
522         if (*frameLen == 0 || *frameLen > (pData->streamInfo.fileSize - filePosBefore)) {
523                 *frameLen = 0;
524                 ret = MMFILE_AAC_PARSER_FAIL;
525                 goto function_end;
526         }
527
528 function_end:
529
530         mmfile_seek(pData->hFile, filePosBefore + *frameLen, MMFILE_SEEK_SET);
531
532         return ret;
533 }
534
535
536 int mmfile_aacparser_open(MMFileAACHandle *handle, const char *filenamec)
537 {
538         tMMFILE_AAC_HANDLE *privateData = NULL;
539         int ret = 0;
540         unsigned char header[4] = {0, };
541         int firstFrameLen = 0;
542         int readed = 0;
543
544         if (NULL == filenamec) {
545                 debug_error("file source is NULL\n");
546                 return MMFILE_AAC_PARSER_FAIL;
547         }
548
549         privateData = mmfile_malloc(sizeof(tMMFILE_AAC_HANDLE));
550         if (NULL == privateData) {
551                 debug_error("file source is NULL\n");
552                 return MMFILE_AAC_PARSER_FAIL;
553         }
554
555         ret = mmfile_open(&privateData->hFile, filenamec, MMFILE_RDONLY);
556         if (ret == MMFILE_UTIL_FAIL) {
557                 debug_error("error: mmfile_open\n");
558                 goto exception;
559         }
560
561         /* Initialize the members of handle */
562         _aac_init_handle(privateData);
563
564         mmfile_seek(privateData->hFile, 0, MMFILE_SEEK_END);
565         privateData->streamInfo.fileSize = mmfile_tell(privateData->hFile);
566
567         mmfile_seek(privateData->hFile, 0, MMFILE_SEEK_SET);
568
569         /* Search the existance of ID3 tag */
570         ret = _search_id3tag(privateData);
571         if (ret == MMFILE_AAC_PARSER_FAIL) {
572                 debug_error("Error in searching the ID3 tag\n");
573                 goto exception;
574         }
575
576         mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
577         readed = mmfile_read(privateData->hFile, header, 4);
578         if (readed != 4)
579                 goto exception;
580
581         if (IS_AAC_ADIF_HEADER(header)) {
582                 privateData->formatType = AAC_FORMAT_ADIF;
583
584 #ifdef __MMFILE_TEST_MODE__
585                 debug_msg("AAC Format: ADIF\n");
586 #endif
587
588         } else if (IS_AAC_ADTS_HEADER(header)) {
589                 privateData->formatType = AAC_FORMAT_ADTS;
590
591 #ifdef __MMFILE_TEST_MODE__
592                 debug_msg("AAC Format: ADTS\n");
593 #endif
594
595                 /* Verify whether the first frame size is proper */
596                 mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
597                 ret = _get_next_adts_frame_length(privateData, &firstFrameLen);
598                 if (ret == MMFILE_AAC_PARSER_FAIL) {
599                         debug_error("Invalid Frame length in ADTS header\n");
600                         goto exception;
601                 }
602         } else {
603                 privateData->formatType = AAC_FORMAT_UNKNOWN;
604                 debug_error("AAC Format: UNKNOWN\n");
605                 goto exception;
606         }
607
608         *handle = privateData;
609
610         return MMFILE_AAC_PARSER_SUCCESS;
611
612 exception:
613         if (privateData) {
614                 mmfile_close(privateData->hFile);
615                 mmfile_free(privateData);
616                 *handle = NULL;
617         }
618         return MMFILE_AAC_PARSER_FAIL;
619
620 }
621
622
623 int mmfile_aacparser_get_stream_info(MMFileAACHandle handle, tMMFILE_AAC_STREAM_INFO *aacinfo)
624 {
625         tMMFILE_AAC_HANDLE *privateData = NULL;
626         int frameLen = 0;
627         long long totalFrames = 0, totalFrameLength = 0;
628         unsigned long long streamDataSize = 0;
629         int ret = MMFILE_AAC_PARSER_SUCCESS;
630
631         if (NULL == handle || NULL == aacinfo) {
632                 debug_error("handle is NULL\n");
633                 return MMFILE_AAC_PARSER_FAIL;
634         }
635
636         privateData = (tMMFILE_AAC_HANDLE *) handle;
637
638         if (privateData->formatType == AAC_FORMAT_ADIF) {
639                 ret = _parse_aac_adif_header(privateData);
640                 aacinfo->iseekable = 0;
641         } else {
642                 ret = _parse_aac_adts_header(privateData);
643                 aacinfo->iseekable = 1;
644         }
645
646         if (ret == MMFILE_AAC_PARSER_FAIL) {
647                 debug_error("Error in parsing the stream header\n");
648                 return ret;
649         }
650
651         mmfile_seek(privateData->hFile, privateData->streamOffset, MMFILE_SEEK_SET);
652
653         if (privateData->formatType == AAC_FORMAT_ADTS) {
654
655                 while (TRUE) {
656                         ret = _get_next_adts_frame_length(privateData, &frameLen);
657                         if (ret != MMFILE_AAC_PARSER_SUCCESS) {
658                                 break;
659                         }
660                         totalFrameLength += frameLen - MMFILE_AAC_ADTS_HEADER_MAX_SIZE;
661                         totalFrames++;
662                 }
663
664                 if (ret == MMFILE_AAC_PARSER_FAIL) {
665                         debug_error("Found corrupted frames!!! Ignoring\n");
666                 }
667
668 #ifdef __MMFILE_TEST_MODE__
669                 debug_msg("No of ADTS frames: %d\n", totalFrames);
670 #endif
671                 privateData->streamInfo.frameRate = privateData->streamInfo.samplingRate / AAC_ADTS_SAMPLES_PER_FRAME;
672
673                 if (privateData->streamInfo.frameRate)
674                         privateData->streamInfo.duration = (totalFrames * 1000) / privateData->streamInfo.frameRate;
675                 else privateData->streamInfo.duration = 0;
676
677                 if (privateData->streamInfo.duration)
678                         privateData->streamInfo.bitRate = (totalFrameLength * 8 * 1000) / (privateData->streamInfo.duration);
679                 else privateData->streamInfo.bitRate = 0;
680
681         } else {
682                 streamDataSize = (unsigned long long)privateData->streamInfo.fileSize - privateData->tagInfoSize;
683                 privateData->streamInfo.duration = streamDataSize * 8 * 1000 / privateData->streamInfo.bitRate;
684         }
685
686         /* Return the stream info structure */
687         memcpy(aacinfo, &(privateData->streamInfo), sizeof(tMMFILE_AAC_STREAM_INFO));
688
689         return MMFILE_AAC_PARSER_SUCCESS;
690 }
691
692
693 int mmfile_aacparser_get_tag_info(MMFileAACHandle handle, tMMFILE_AAC_TAG_INFO *tagInfo)
694 {
695         tMMFILE_AAC_HANDLE *privateData = NULL;
696         int ret = 0;
697
698         if (NULL == handle || NULL == tagInfo) {
699                 debug_error("handle is NULL\n");
700                 return MMFILE_AAC_PARSER_FAIL;
701         }
702
703         privateData = (tMMFILE_AAC_HANDLE *) handle;
704         if (privateData->id3Handle.tagV2Info.tagVersion == 0) {
705                 debug_warning("There is no Tag info\n");
706                 return MMFILE_AAC_PARSER_SUCCESS;
707         }
708
709         ret = _parse_id3_tag(privateData);
710         if (ret == MMFILE_AAC_PARSER_FAIL) {
711                 debug_warning("Error in parsing the Tag info\n");
712                 return ret;
713         }
714
715         /* Return the tag info structure */
716         memcpy(tagInfo, &(privateData->tagInfo), sizeof(tMMFILE_AAC_TAG_INFO));
717
718         return MMFILE_AAC_PARSER_SUCCESS;
719 }
720
721
722 int mmfile_aacparser_close(MMFileAACHandle handle)
723 {
724         tMMFILE_AAC_HANDLE *privateData = NULL;
725
726         if (NULL == handle) {
727                 debug_error("handle is NULL\n");
728                 return MMFILE_AAC_PARSER_FAIL;
729         }
730
731         privateData = (tMMFILE_AAC_HANDLE *) handle;
732         mm_file_free_AvFileContentInfo(&privateData->id3Handle);
733
734         mmfile_close(privateData->hFile);
735
736         return MMFILE_AAC_PARSER_SUCCESS;
737 }
738
739
740 /* mm plugin interface */
741 int mmfile_format_read_stream_aac(MMFileFormatContext *formatContext);
742 int mmfile_format_read_frame_aac(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
743 int mmfile_format_read_tag_aac(MMFileFormatContext *formatContext);
744 int mmfile_format_close_aac(MMFileFormatContext *formatContext);
745
746
747 EXPORT_API
748 int mmfile_format_open_aac(MMFileFormatContext *formatContext)
749 {
750         MMFileAACHandle handle = NULL;
751         int res = MMFILE_FORMAT_FAIL;
752
753         if (NULL == formatContext || NULL == formatContext->uriFileName) {
754                 debug_error("error: mmfile_format_open_aac\n");
755                 return MMFILE_FORMAT_FAIL;
756         }
757
758         if (formatContext->pre_checked == 0) {
759                 res = MMFileFormatIsValidAAC(NULL, formatContext->uriFileName);
760                 if (res == 0) {
761                         debug_error("It is not AAC file\n");
762                         return MMFILE_FORMAT_FAIL;
763                 }
764         }
765
766         formatContext->ReadStream   = mmfile_format_read_stream_aac;
767         formatContext->ReadFrame    = mmfile_format_read_frame_aac;
768         formatContext->ReadTag      = mmfile_format_read_tag_aac;
769         formatContext->Close        = mmfile_format_close_aac;
770
771         formatContext->videoTotalTrackNum = 0;
772         formatContext->audioTotalTrackNum = 1;
773
774         res = mmfile_aacparser_open(&handle, formatContext->uriFileName);
775         if (MMFILE_AAC_PARSER_FAIL == res) {
776                 debug_error("mmfile_aacparser_open\n");
777                 return MMFILE_FORMAT_FAIL;
778         }
779
780         formatContext->privateFormatData = handle;
781
782         return MMFILE_FORMAT_SUCCESS;
783 }
784
785 EXPORT_API
786 int mmfile_format_read_stream_aac(MMFileFormatContext *formatContext)
787 {
788         MMFileAACHandle     handle = NULL;
789         tMMFILE_AAC_STREAM_INFO  aacinfo = {0, };
790         MMFileFormatStream  *audioStream = NULL;
791
792         int ret = MMFILE_FORMAT_FAIL;
793
794         if (NULL == formatContext) {
795                 debug_error("error: invalid params\n");
796                 ret = MMFILE_FORMAT_FAIL;
797                 goto exception;
798         }
799
800         handle = formatContext->privateFormatData;
801
802         ret = mmfile_aacparser_get_stream_info(handle, &aacinfo);
803         if (MMFILE_FORMAT_SUCCESS != ret) {
804                 debug_error("error: mmfile_aacparser_get_stream_info\n");
805                 ret = MMFILE_FORMAT_FAIL;
806                 goto exception;
807         }
808
809         formatContext->isseekable = aacinfo.iseekable;
810         formatContext->duration = aacinfo.duration;
811         formatContext->videoStreamId = -1;
812         formatContext->videoTotalTrackNum = 0;
813         formatContext->audioTotalTrackNum = aacinfo.numTracks;
814         formatContext->nbStreams = 1;
815
816         audioStream = mmfile_malloc(sizeof(MMFileFormatStream));
817         if (NULL == audioStream) {
818                 debug_error("error: calloc_audiostream\n");
819                 ret = MMFILE_FORMAT_FAIL;
820                 goto exception;
821         }
822
823         audioStream->streamType = MMFILE_AUDIO_STREAM;
824         audioStream->codecId = MM_AUDIO_CODEC_AAC;
825         audioStream->bitRate = aacinfo.bitRate;
826         audioStream->framePerSec = aacinfo.frameRate;
827         audioStream->width = 0;
828         audioStream->height = 0;
829         audioStream->nbChannel = aacinfo.numAudioChannels;
830         audioStream->samplePerSec = aacinfo.samplingRate;
831         formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream;
832
833 #ifdef  __MMFILE_TEST_MODE__
834         mmfile_format_print_contents(formatContext);
835 #endif
836
837         return MMFILE_FORMAT_SUCCESS;
838
839 exception:
840         return ret;
841 }
842
843 EXPORT_API
844 int mmfile_format_read_tag_aac(MMFileFormatContext *formatContext)
845 {
846         MMFileAACHandle     handle = NULL;
847         tMMFILE_AAC_TAG_INFO  aacinfo = {0, };
848         int ret = MMFILE_FORMAT_FAIL;
849
850         if (NULL == formatContext) {
851                 debug_error("error: invalid params\n");
852                 ret = MMFILE_FORMAT_FAIL;
853                 goto exception;
854         }
855
856         handle = formatContext->privateFormatData;
857
858         ret = mmfile_aacparser_get_tag_info(handle, &aacinfo);
859         if (MMFILE_FORMAT_SUCCESS != ret) {
860                 debug_warning("error: mmfile_aacparser_get_tag_info\n");
861                 ret = MMFILE_FORMAT_FAIL;
862                 goto exception;
863         }
864
865         if (aacinfo.title)
866                 formatContext->title = mmfile_strdup(aacinfo.title);
867         if (aacinfo.author)
868                 formatContext->author = mmfile_strdup(aacinfo.author);
869         if (aacinfo.artist)
870                 formatContext->artist = mmfile_strdup(aacinfo.artist);
871         if (aacinfo.album)
872                 formatContext->album = mmfile_strdup(aacinfo.album);
873         if (aacinfo.album_artist)
874                 formatContext->album_artist = mmfile_strdup(aacinfo.album_artist);
875         if (aacinfo.year)
876                 formatContext->year = mmfile_strdup(aacinfo.year);
877         if (aacinfo.copyright)
878                 formatContext->copyright = mmfile_strdup(aacinfo.copyright);
879         if (aacinfo.comment)
880                 formatContext->comment = mmfile_strdup(aacinfo.comment);
881         if (aacinfo.genre)
882                 formatContext->genre = mmfile_strdup(aacinfo.genre);
883         if (aacinfo.tracknum)
884                 formatContext->tagTrackNum = mmfile_strdup(aacinfo.tracknum);
885         if (aacinfo.composer)
886                 formatContext->composer = mmfile_strdup(aacinfo.composer);
887         if (aacinfo.classification)
888                 formatContext->classification = mmfile_strdup(aacinfo.classification);
889         if (aacinfo.rating)
890                 formatContext->rating = mmfile_strdup(aacinfo.rating);  /*not exist rating tag in id3*/
891         if (aacinfo.conductor)
892                 formatContext->conductor = mmfile_strdup(aacinfo.conductor);
893         if (aacinfo.artworkMime)
894                 formatContext->artworkMime = mmfile_strdup(aacinfo.artworkMime);
895         if (aacinfo.artwork) {
896                 formatContext->artworkSize = aacinfo.artworkSize;
897                 formatContext->artwork = mmfile_malloc(aacinfo.artworkSize);
898                 if (formatContext->artwork == NULL) {
899                         ret = MMFILE_FORMAT_FAIL;
900                         goto exception;
901                 }
902                 memcpy(formatContext->artwork, aacinfo.artwork, aacinfo.artworkSize);
903         }
904
905 #ifdef  __MMFILE_TEST_MODE__
906         mmfile_format_print_contents(formatContext);
907 #endif
908
909         return MMFILE_FORMAT_SUCCESS;
910
911 exception:
912         return ret;
913 }
914
915
916 EXPORT_API
917 int mmfile_format_read_frame_aac(MMFileFormatContext *formatContext,
918                                  unsigned int timestamp, MMFileFormatFrame *frame)
919 {
920         debug_error("error: mmfile_format_read_frame_aac, no handling\n");
921
922         return MMFILE_FORMAT_FAIL;
923 }
924
925
926 EXPORT_API
927 int mmfile_format_close_aac(MMFileFormatContext *formatContext)
928 {
929         MMFileAACHandle  handle = NULL;
930         int ret = MMFILE_FORMAT_FAIL;
931
932         if (NULL == formatContext) {
933                 debug_error("error: invalid params\n");
934                 return MMFILE_FORMAT_FAIL;
935         }
936
937         handle = formatContext->privateFormatData;
938
939         if (NULL != handle) {
940                 ret = mmfile_aacparser_close(handle);
941                 if (ret == MMFILE_AAC_PARSER_FAIL) {
942                         debug_error("error: mmfile_format_close_aac\n");
943                 }
944         }
945
946         if (formatContext->streams[MMFILE_AUDIO_STREAM]) {
947                 mmfile_free(formatContext->streams[MMFILE_AUDIO_STREAM]);
948                 formatContext->streams[MMFILE_AUDIO_STREAM] = NULL;
949         }
950
951         formatContext->ReadStream   = NULL;
952         formatContext->ReadFrame    = NULL;
953         formatContext->ReadTag      = NULL;
954         formatContext->Close        = NULL;
955
956         return MMFILE_FORMAT_SUCCESS;
957 }
958
959