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.
26 #include "mm_file_utils.h"
28 //#define ENABLE_ITUNES_META //All itunes metadata extracted by ffmpeg. see mov_read_udta_string()
30 typedef struct _mmfilemp4basicboxheader {
33 long long start_offset; /*huge file*/
34 } MMFILE_MP4_BASIC_BOX_HEADER;
36 typedef struct _mmfilemp4ftpybox {
37 unsigned int major_brand;
38 unsigned short major_version;
39 unsigned short minor_version;
40 unsigned int *compatiable_brands;
44 eMMFILE_3GP_TAG_TITLE = 0x01,
45 eMMFILE_3GP_TAG_CAPTION = 0x02,
46 eMMFILE_3GP_TAG_COPYRIGHT = 0x03,
47 eMMFILE_3GP_TAG_PERFORMER = 0x04,
48 eMMFILE_3GP_TAG_AUTHOR = 0x05,
49 eMMFILE_3GP_TAG_GENRE = 0x06,
50 } eMMFILE_3GP_TEXT_TAG;
52 typedef struct _mmfile3gptagtextbox {
53 unsigned char version;
54 unsigned char flag[3];
55 unsigned char language[2];
57 } MMFILE_3GP_TEXT_TAGBOX;
59 typedef struct _mmfile3gptagyearbox {
60 unsigned char version;
61 unsigned char flag[3];
63 } MMFILE_3GP_YEAR_TAGBOX;
65 typedef struct _mmfile3gptagalbumbox {
66 unsigned char version;
67 unsigned char flag[3];
68 unsigned char language[2];
69 unsigned char *albumtile;
70 unsigned char trackNumber;
71 } MMFILE_3GP_ALBUM_TAGBOX;
73 typedef struct _mmfile3gpratingbox {
74 unsigned char version;
75 unsigned char flag[3];
76 unsigned int ratingEntity;
77 unsigned int ratingCriteria;
78 unsigned char language[2];
79 unsigned char *ratingInfo;
80 } MMFILE_3GP_RATING_TAGBOX;
82 typedef struct _mmfile3gpclsfbox {
83 unsigned char version;
84 unsigned char flag[3];
85 unsigned int classificationEntity;
86 unsigned int classificationTable;
87 unsigned char language[2];
88 unsigned char *classificationInfo;
89 } MMFILE_3GP_CLASSIFICATION_TAGBOX;
91 typedef struct _mmfile3gphdlrbox {
93 unsigned int pre_defined;
94 unsigned int handler_type;
95 unsigned int reserved[3];
96 unsigned char *boxname;
97 } MMFILE_3GP_HANDLER_BOX;
99 typedef struct _mmfileidv2box {
100 unsigned char version;
101 unsigned char flag[3];
102 unsigned char language[2];
103 unsigned char *id3v2Data;
104 } MMFILE_3GP_ID3V2_BOX;
106 typedef struct _mmfilelocibox {
107 unsigned char version;
108 unsigned char flag[3];
109 unsigned char language[2];
115 unsigned char *astronomical_body;
116 unsigned char *additional_notes;
117 } MMFILE_3GP_LOCATION_TAGBOX;
119 #define MMFILE_MP4_BASIC_BOX_HEADER_LEN 8
120 #define MMFILE_MP4_MOVIE_HEADER_BOX_LEN 96
121 #define MMFILE_MP4_HDLR_BOX_LEN 24
122 #define MMFILE_MP4_STSZ_BOX_LEN 20
123 #define MMFILE_MP4_MP4VBOX_LEN 80
124 #define MMFILE_MP4_MP4ABOX_LEN 28
125 #define MMFILE_3GP_TEXT_TAGBOX_LEN 6
126 #define MMFILE_3GP_YEAR_TAGBOX_LEN 6
127 #define MMFILE_3GP_ALBUM_TAGBOX_LEN 6
128 #define MMFILE_3GP_RATING_TAGBOX_LEN 14
129 #define MMFILE_3GP_CLASS_TAGBOX_LEN 14
130 #define MMFILE_3GP_HANDLER_BOX_LEN 24
131 #define MMFILE_3GP_ID3V2_BOX_LEN 6
132 #define MMFILE_SYNC_LYRIC_INFO_MIN_LEN 5
135 #define FOURCC(a,b,c,d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24))
137 #define MIN(a,b) (((a)<(b))?(a):(b))
139 #define GENRE_COUNT 149
141 static char* MpegAudio_Genre[GENRE_COUNT] = {"Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz", "Metal",
142 "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno", "Industrial",
143 "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk",
144 "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise",
145 "AlternRock", "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic",
146 "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta",
147 "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes",
148 "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock",
149 "Folk", "Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass",
150 "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic",
151 "Humour", "Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", "Porn Groove",
152 "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle",
153 "Duet", "Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall", "Goa", "Drum & Bass", "Club-House", "Hardcore",
154 "Terror", "Indie", "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian", "Heavy Metal", "Black Metal", "Crossover",
155 "Contemporary", "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", "Synthpop", "Unknown" };
158 static int GetStringFromTextTagBox (MMFileFormatContext *formatContext, MMFileIOHandle *fp, MMFILE_MP4_BASIC_BOX_HEADER *basic_header, eMMFILE_3GP_TEXT_TAG eTag)
160 int ret = MMFILE_UTIL_FAIL; /*fail*/
161 MMFILE_3GP_TEXT_TAGBOX texttag = {0,};
164 char *temp_text = NULL;
166 if (!formatContext || !fp || !basic_header) {
167 debug_error ("invalid param\n");
168 return MMFILE_UTIL_FAIL;
171 textBytes = basic_header->size - MMFILE_MP4_BASIC_BOX_HEADER_LEN - MMFILE_3GP_TEXT_TAGBOX_LEN;
173 readed = mmfile_read (fp, (unsigned char *)&texttag, MMFILE_3GP_TEXT_TAGBOX_LEN);
174 if (readed != MMFILE_3GP_TEXT_TAGBOX_LEN) {
175 debug_error ("read text tag header fail\n");
176 ret = MMFILE_UTIL_FAIL;
180 if (textBytes <= 1) /* there exist only 00 (null) */
182 debug_error ("Text is NULL\n");
186 texttag.text = mmfile_malloc (textBytes);
188 debug_error ("malloc fail for text box\n");
189 ret = MMFILE_UTIL_FAIL;
193 readed = mmfile_read (fp, (unsigned char *)texttag.text, textBytes);
194 if (readed != textBytes) {
195 debug_error ("read text fail\n");
196 ret = MMFILE_UTIL_FAIL;
201 if ( (texttag.text[0] == 0xFE) && (texttag.text[1] == 0xFF)) {
202 /* this char is UTF-16 */
203 unsigned int bytes_written = 0;
204 temp_text = mmfile_string_convert ((const char *)&texttag.text[2], readed-2, "UTF-8", "UTF-16",NULL, (unsigned int*)&bytes_written);
206 temp_text = mmfile_strdup ((const char *)texttag.text);
210 case eMMFILE_3GP_TAG_TITLE: {
211 if (!formatContext->title) {
212 formatContext->title = temp_text;
216 case eMMFILE_3GP_TAG_CAPTION: {
217 if (!formatContext->description) {
218 formatContext->description = temp_text;
222 case eMMFILE_3GP_TAG_COPYRIGHT: {
223 if (!formatContext->copyright) {
224 formatContext->copyright = temp_text;
228 case eMMFILE_3GP_TAG_PERFORMER: {
229 if (!formatContext->artist) {
230 formatContext->artist = temp_text;
234 case eMMFILE_3GP_TAG_AUTHOR: {
235 if (!formatContext->author) {
236 formatContext->author = temp_text;
240 case eMMFILE_3GP_TAG_GENRE: {
241 if (!formatContext->genre) {
242 formatContext->genre = temp_text;
247 debug_warning("Not supported Text Tag type[%d]\n", eTag);
252 mmfile_free (texttag.text);
254 mmfile_seek (fp, basic_header->start_offset + basic_header->size, SEEK_SET);
256 return MMFILE_UTIL_SUCCESS;
259 mmfile_seek (fp, basic_header->start_offset + basic_header->size, SEEK_SET);
261 mmfile_free(texttag.text);
266 static int GetYearFromYearTagBox (MMFileFormatContext *formatContext, MMFileIOHandle *fp, MMFILE_MP4_BASIC_BOX_HEADER *basic_header)
268 #define MAX_YEAR_BUFFER 10
270 MMFILE_3GP_YEAR_TAGBOX yearbox = {0,};
271 char temp_year[MAX_YEAR_BUFFER] = {0,};
273 if (!formatContext || !fp || !basic_header) {
274 debug_error ("invalid param\n");
275 return MMFILE_UTIL_FAIL;
278 readed = mmfile_read (fp, (unsigned char *)&yearbox, MMFILE_3GP_YEAR_TAGBOX_LEN);
279 if (readed != MMFILE_3GP_YEAR_TAGBOX_LEN) {
280 debug_error ("read yeartag header fail\n");
284 if (!formatContext->year) {
285 yearbox.year = mmfile_io_be_int16 (yearbox.year);
286 snprintf (temp_year, MAX_YEAR_BUFFER, "%d", yearbox.year);
287 temp_year[MAX_YEAR_BUFFER-1] = '\0';
288 formatContext->year = mmfile_strdup ((const char*)temp_year);
291 mmfile_seek (fp, basic_header->start_offset + basic_header->size, SEEK_SET);
292 return MMFILE_UTIL_SUCCESS;
295 mmfile_seek (fp, basic_header->start_offset + basic_header->size, SEEK_SET);
297 return MMFILE_UTIL_FAIL;
300 static int GetAlbumFromAlbumTagBox (MMFileFormatContext *formatContext, MMFileIOHandle *fp, MMFILE_MP4_BASIC_BOX_HEADER *basic_header)
302 int albumTitleLen = 0;
303 char *temp_text = NULL;
306 MMFILE_3GP_ALBUM_TAGBOX albumbox = {0,};
308 if (!formatContext || !fp || !basic_header) {
309 debug_error ("invalid param\n");
310 return MMFILE_UTIL_FAIL;
313 readed = mmfile_read (fp, (unsigned char *)&albumbox, MMFILE_3GP_ALBUM_TAGBOX_LEN);
314 if (readed != MMFILE_3GP_ALBUM_TAGBOX_LEN) {
315 debug_error ("read albumtag header fail\n");
319 albumTitleLen = basic_header->size - MMFILE_MP4_BASIC_BOX_HEADER_LEN - MMFILE_3GP_ALBUM_TAGBOX_LEN - 1; /* 1: track number */
320 if (albumTitleLen > 1) /* there exist only 00 (null) */
322 #ifdef __MMFILE_TEST_MODE__
323 debug_msg ("albumTitleLen=%d\n", albumTitleLen);
326 albumbox.albumtile = mmfile_malloc (albumTitleLen + 1); /* 1: for null char */
327 if (!albumbox.albumtile) {
328 debug_error ("malloc fail for album title text\n");
332 readed = mmfile_read (fp, (unsigned char *)albumbox.albumtile, albumTitleLen);
333 if (readed != albumTitleLen) {
334 debug_error ("read album title fail\n");
338 if (albumbox.albumtile[albumTitleLen-1] == '\0') /* there exist track number */
345 readed = mmfile_read (fp, (unsigned char *)&(albumbox.albumtile[albumTitleLen]), 1);
347 debug_error ("read album title fail\n");
350 albumbox.albumtile[albumTitleLen] = '\0';
354 if ( (albumbox.albumtile[0] == 0xFE) && (albumbox.albumtile[1] == 0xFF)) {
355 /* this char is UTF-16 */
356 unsigned int bytes_written = 0;
357 temp_text = mmfile_string_convert ((const char*)&albumbox.albumtile[2], readed-2, "UTF-8", "UTF-16", NULL, (unsigned int*)&bytes_written);
359 temp_text = mmfile_strdup ((const char*)albumbox.albumtile);
362 if (!formatContext->album) {
363 formatContext->album = temp_text;
366 #ifdef __MMFILE_TEST_MODE__
367 debug_msg ("formatContext->album=%s, strlen=%d\n", formatContext->album, strlen(formatContext->album));
372 readed = mmfile_read (fp, (unsigned char *)&albumbox.trackNumber, 1);
374 debug_error ("read track number fail\n");
378 if (formatContext->tagTrackNum == 0) {
379 char tracknum[10] = {0,};
380 snprintf (tracknum, 10, "%d", albumbox.trackNumber);
382 formatContext->tagTrackNum = mmfile_strdup ((const char*)tracknum);
386 mmfile_free (albumbox.albumtile);
387 mmfile_seek (fp, basic_header->start_offset + basic_header->size, SEEK_SET);
389 return MMFILE_UTIL_SUCCESS;
392 mmfile_seek (fp, basic_header->start_offset + basic_header->size, SEEK_SET);
393 mmfile_free (albumbox.albumtile);
395 return MMFILE_UTIL_FAIL;
398 static int GetRatingFromRatingTagBox (MMFileFormatContext *formatContext, MMFileIOHandle *fp, MMFILE_MP4_BASIC_BOX_HEADER *basic_header)
401 int ratinginfoLen = 0;
402 char *temp_text = NULL;
404 MMFILE_3GP_RATING_TAGBOX ratingTag = {0,};
406 if (!formatContext || !fp || !basic_header) {
407 debug_error ("invalid param\n");
408 return MMFILE_UTIL_FAIL;
411 readed = mmfile_read (fp, (unsigned char *)&ratingTag, MMFILE_3GP_RATING_TAGBOX_LEN);
412 if (readed != MMFILE_3GP_RATING_TAGBOX_LEN) {
413 debug_error ("read rating tag header fail\n");
417 ratinginfoLen = basic_header->size - MMFILE_MP4_BASIC_BOX_HEADER_LEN - MMFILE_3GP_RATING_TAGBOX_LEN;
419 if (ratinginfoLen == 1) {
420 debug_error ("Rating Text is NULL\n");
424 ratingTag.ratingInfo = mmfile_malloc (ratinginfoLen);
425 if (!ratingTag.ratingInfo) {
426 debug_error ("rating info error\n");
430 readed = mmfile_read (fp, (unsigned char *)ratingTag.ratingInfo, ratinginfoLen);
431 if (readed != ratinginfoLen) {
432 debug_error ("read rating info string fail\n");
437 if ( (ratingTag.ratingInfo[0] == 0xFE) && (ratingTag.ratingInfo[1] == 0xFF)) {
438 /* this char is UTF-16 */
439 unsigned int bytes_written = 0;
440 temp_text = mmfile_string_convert ((const char*)&ratingTag.ratingInfo[2], readed-2, "UTF-8", "UTF-16", NULL, (unsigned int*)&bytes_written);
442 temp_text = mmfile_strdup ((const char*)ratingTag.ratingInfo);
445 if (!formatContext->rating) {
446 formatContext->rating = temp_text;
448 mmfile_free (temp_text);
451 mmfile_free (ratingTag.ratingInfo);
452 mmfile_seek (fp, basic_header->start_offset + basic_header->size, SEEK_SET);
454 return MMFILE_UTIL_SUCCESS;
457 mmfile_seek (fp, basic_header->start_offset + basic_header->size, SEEK_SET);
458 mmfile_free (ratingTag.ratingInfo);
460 return MMFILE_UTIL_FAIL;
464 static int GetClassficationFromClsfTagBox (MMFileFormatContext *formatContext, MMFileIOHandle *fp, MMFILE_MP4_BASIC_BOX_HEADER *basic_header)
466 int classinfoLen = 0;
468 char *temp_text = NULL;
469 MMFILE_3GP_CLASSIFICATION_TAGBOX classTag = {0,};
471 if (!formatContext || !fp || !basic_header) {
472 debug_error ("invalid param\n");
473 return MMFILE_UTIL_FAIL;
476 readed = mmfile_read (fp, (unsigned char *)&classTag, MMFILE_3GP_CLASS_TAGBOX_LEN);
477 if (readed != MMFILE_3GP_CLASS_TAGBOX_LEN) {
478 debug_error ("read classification tag header fail\n");
483 classinfoLen = basic_header->size - MMFILE_MP4_BASIC_BOX_HEADER_LEN - MMFILE_3GP_CLASS_TAGBOX_LEN;
484 if (classinfoLen == 1) {
485 debug_error ("Classification Text is NULL\n");
489 classTag.classificationInfo = mmfile_malloc (classinfoLen);
490 if (!classTag.classificationInfo) {
491 debug_error ("class info error\n");
495 readed = mmfile_read (fp, (unsigned char *)classTag.classificationInfo, classinfoLen);
496 if (readed != classinfoLen) {
497 debug_error ("read class info string fail\n");
502 if ( (classTag.classificationInfo[0] == 0xFE) && (classTag.classificationInfo[1] == 0xFF)) {
503 /* this char is UTF-16 */
504 unsigned int bytes_written = 0;
505 temp_text = mmfile_string_convert ((const char*)&classTag.classificationInfo[2], readed-2, "UTF-8", "UTF-16", NULL, (unsigned int*)&bytes_written);
507 temp_text = mmfile_strdup ((const char*)classTag.classificationInfo);
510 if (!formatContext->classification) {
511 formatContext->classification = temp_text;
513 mmfile_free (temp_text);
516 mmfile_free (classTag.classificationInfo);
517 mmfile_seek (fp, basic_header->start_offset + basic_header->size, SEEK_SET);
519 return MMFILE_UTIL_SUCCESS;
522 mmfile_seek (fp, basic_header->start_offset + basic_header->size, SEEK_SET);
523 mmfile_free (classTag.classificationInfo);
525 return MMFILE_UTIL_FAIL;
529 * The Location Information box
530 * --------------------+-------------------+-----------------------------------+------
531 * Field Type Details Value
532 * --------------------+-------------------+-----------------------------------+------
533 * BoxHeader.Size Unsigned int(32)
534 * BoxHeader.Type Unsigned int(32) 'loci'
535 * BoxHeader.Version Unsigned int(8) 0
536 * BoxHeader.Flags Bit(24) 0
538 * Language Unsigned int(5)[3] Packed ISO-639-2/T language code
539 * Name String Text of place name
540 * Role Unsigned int(8) Non-negative value indicating role
542 * Longitude Unsigned int(32) Fixed-point value of the longitude
543 * Latitude Unsigned int(32) Fixed-point value of the latitude
544 * Altitude Unsigned int(32) Fixed-point value of the Altitude
545 * Astronomical_body String Text of astronomical body
546 * Additional_notes String Text of additional location-related
548 * --------------------+-------------------+-----------------------------------+------
550 static int _get_char_position (unsigned char *src, char ch, int max)
553 for (i = 0; i < max; i++) {
554 if ( *(src + i) == ch)
561 static int GetLocationFromLociTagBox (MMFileFormatContext *formatContext, MMFileIOHandle *fp, MMFILE_MP4_BASIC_BOX_HEADER *basic_header)
564 MMFILE_3GP_LOCATION_TAGBOX lociTag = {0,};
567 unsigned char *buffer = NULL;
568 unsigned char *p = NULL;
570 unsigned int bytes_written = 0;
571 unsigned int name_sz = 0;
572 unsigned int astro_sz = 0;
574 int ilong, ilati, ialti;
575 float flong, flati, falti;
578 if (!formatContext || !fp || !basic_header) {
579 debug_error ("invalid param\n");
580 return MMFILE_UTIL_FAIL;
583 readed = mmfile_read (fp, (unsigned char *)&lociTag, 6); /*6 = version + flag + pad + language */
585 debug_error ("read location tag header fail\n");
589 /*buffer len = name + role + ... + additional notes length */
590 bufferLen = basic_header->size - MMFILE_MP4_BASIC_BOX_HEADER_LEN - 6;
592 debug_error ("too small buffer\n");
596 buffer = mmfile_malloc (bufferLen);
598 debug_error ("buffer malloc error\n");
602 readed = mmfile_read (fp, (unsigned char *)buffer, bufferLen);
603 if (readed != bufferLen) {
604 debug_error ("read location tag fail\n");
610 pos = _get_char_position (p, '\0', readed - (1+4+4+4+2));
612 if (p[0] == 0xFE && p[1] == 0xFF) {
613 lociTag.name = (unsigned char*)mmfile_string_convert ((const char*)(p + 2), pos - 2, "UTF-8", "UTF-16", NULL, (unsigned int*)&bytes_written);
615 lociTag.name = (unsigned char*)mmfile_strdup ((const char*)p);
627 #ifdef __MMFILE_TEST_MODE__
628 debug_msg ("long: 0x%02X 0x%02X 0x%02X 0x%02X \n", *(p+0), *(p+1), *(p+2), *(p+3));
629 debug_msg ("lati: 0x%02X 0x%02X 0x%02X 0x%02X \n", *(p+4), *(p+5), *(p+6), *(p+7));
630 debug_msg ("alti: 0x%02X 0x%02X 0x%02X 0x%02X \n", *(p+8), *(p+9), *(p+10), *(p+11));
633 ilong = mmfile_io_be_uint32 (*(unsigned int*)p);
634 ilati = mmfile_io_be_uint32 (*(unsigned int*)(p+4));
635 ialti = mmfile_io_be_uint32 (*(unsigned int*)(p+8));
637 flong = (float)ilong / (1<<16);
638 flati = (float)ilati / (1<<16);
639 falti = (float)ialti / (1<<16);
642 lociTag.longitude = flong;
644 lociTag.latitude = flati;
646 lociTag.altitude = falti;
650 /*astronomical body*/
651 pos = _get_char_position (p, '\0', readed - (name_sz+1+4+4+4+1));
653 if (p[0] == 0xFE && p[1] == 0xFF) {
654 lociTag.astronomical_body = (unsigned char*)mmfile_string_convert ((const char*)(p + 2), pos - 2, "UTF-8", "UTF-16", NULL, (unsigned int*)&bytes_written);
656 lociTag.astronomical_body = (unsigned char*)mmfile_strdup ((const char*)p);
665 pos = _get_char_position (p, '\0', readed - (name_sz+1+4+4+4+astro_sz));
667 if (p[0] == 0xFE && p[1] == 0xFF) {
668 lociTag.additional_notes = (unsigned char*)mmfile_string_convert ((const char*)(p + 2), pos - 2, "UTF-8", "UTF-16", NULL, (unsigned int*)&bytes_written);
670 lociTag.additional_notes = (unsigned char*)mmfile_strdup ((const char*)p);
676 #ifdef __MMFILE_TEST_MODE__
677 debug_msg ("** Location Information **\n");
678 debug_msg ("Name : %s\n", lociTag.name);
679 debug_msg ("Role : %d (0: shooting, 1: real, 2: fictional, other: reserved)\n", lociTag.role);
680 debug_msg ("Longitude : %16.16f\n", lociTag.longitude);
681 debug_msg ("Latitude : %16.16f\n", lociTag.latitude);
682 debug_msg ("Altitude : %16.16f\n", lociTag.altitude);
683 debug_msg ("Astronomical body: %s\n", lociTag.astronomical_body);
684 debug_msg ("Additional notes : %s\n", lociTag.additional_notes);
687 formatContext->longitude = lociTag.longitude;
688 formatContext->latitude = lociTag.latitude;
689 formatContext->altitude = lociTag.altitude;
691 mmfile_free (buffer);
692 mmfile_free (lociTag.name);
693 mmfile_free (lociTag.astronomical_body);
694 mmfile_free (lociTag.additional_notes);
696 mmfile_seek (fp, basic_header->start_offset + basic_header->size, SEEK_SET);
697 return MMFILE_UTIL_SUCCESS;
700 mmfile_seek (fp, basic_header->start_offset + basic_header->size, SEEK_SET);
701 mmfile_free (buffer);
702 mmfile_free (lociTag.name);
703 mmfile_free (lociTag.astronomical_body);
704 mmfile_free (lociTag.additional_notes);
706 return MMFILE_UTIL_FAIL;
709 static int GetTagFromMetaBox (MMFileFormatContext *formatContext, MMFileIOHandle *fp, MMFILE_MP4_BASIC_BOX_HEADER *basic_header)
712 MMFILE_MP4_BASIC_BOX_HEADER hdlrBoxHeader = {0,};
713 MMFILE_MP4_BASIC_BOX_HEADER id3v2BoxHeader = {0,};
714 MMFILE_3GP_ID3V2_BOX id3v2Box = {0,};
715 AvFileContentInfo tagInfo = {0,};
716 unsigned char tagVersion = 0;
717 bool versionCheck = false;
719 unsigned int meta_version = 0;
720 MMFILE_3GP_HANDLER_BOX hdlrBox = {0,};
723 #ifdef ENABLE_ITUNES_META /* We don't support itunes meta now. so this is not defined yet */
728 readed = mmfile_read (fp, (unsigned char *)&meta_version, 4);
730 debug_error ("read meta box version\n");
735 readed = mmfile_read (fp, (unsigned char *)&hdlrBoxHeader, MMFILE_MP4_BASIC_BOX_HEADER_LEN);
736 if (readed != MMFILE_MP4_BASIC_BOX_HEADER_LEN) {
737 debug_error ("read hdlr box header\n");
741 if (hdlrBoxHeader.type != FOURCC ('h', 'd', 'l', 'r')) {
742 debug_warning ("meta type is not hdlr\n");
746 hdlrBoxHeader.size = mmfile_io_be_uint32 (hdlrBoxHeader.size);
747 hdlrBoxHeader.type = mmfile_io_le_uint32 (hdlrBoxHeader.type);
749 readed = mmfile_read (fp, (unsigned char *)&hdlrBox, MMFILE_3GP_HANDLER_BOX_LEN);
750 if (readed != MMFILE_3GP_HANDLER_BOX_LEN) {
751 debug_error ("read hdlr box\n");
755 hdlrBox.handler_type = mmfile_io_le_uint32 (hdlrBox.handler_type);
758 * check tag type (ID3v2 or iTunes)
760 if (hdlrBox.handler_type == FOURCC ('I', 'D', '3', '2')) {
761 #ifdef __MMFILE_TEST_MODE__
762 debug_msg ("ID3v2 tag detected.\n");
766 #ifdef ENABLE_ITUNES_META
769 } else if (hdlrBox.handler_type == FOURCC ('m', 'd', 'i', 'r') &&
770 mmfile_io_le_uint32 (hdlrBox.reserved[0]) == FOURCC ('a', 'p', 'p', 'l')) {
772 #ifdef __MMFILE_TEST_MODE__
773 debug_msg ("Apple iTunes tag detected by mdir.\n");
776 #ifdef ENABLE_ITUNES_META
780 debug_warning ("unknown meta type. 4CC:[%c%c%c%c]\n", ((char*)&hdlrBox.handler_type)[0],
781 ((char*)&hdlrBox.handler_type)[1],
782 ((char*)&hdlrBox.handler_type)[2],
783 ((char*)&hdlrBox.handler_type)[3]);
787 #ifdef ENABLE_ITUNES_META
788 if(!id3_meta && !iTunes_meta) {
790 APPLE meta data for iTunes reader = 'mdir.' so if handler type is 'mdir', this content may has itunes meta.
791 most of contents has 'mdir' + 'appl'. but some contents just has 'mdir'
792 but 'ilst' is meta for iTunes. so find 'ilst' is more correct to check if this contents has iTunes meta or not.*/
794 char *ilst_box = "ilst";
795 int buf_size = strlen(ilst_box);
797 unsigned char read_buf[buf_size+1];
798 memset(read_buf, 0x00, buf_size+1);
801 mmfile_seek (fp, hdlrBoxHeader.size - MMFILE_MP4_BASIC_BOX_HEADER_LEN - MMFILE_3GP_HANDLER_BOX_LEN +4, SEEK_CUR); //+4 is hdlr size field
803 readed = mmfile_read (fp, read_buf, buf_size); // to find 'ilst'
804 if (readed != buf_size) {
805 debug_error ("read fail [%d]\n", readed);
809 if(read_buf[0] == 'i' && read_buf[1] == 'l' && read_buf[2] == 's' && read_buf[3] == 't') {
810 #ifdef __MMFILE_TEST_MODE__
811 debug_msg ("Apple iTunes tag detected by ilst.\n");
819 #ifdef ENABLE_ITUNES_META
822 * iTunes (Cover[?ovr] & Track[trkn] only extract!) + Genre/Artist : Added 2010.10.27,28
830 #define _ITUNES_READ_BUF_SZ 20
831 #define _ITUNES_TRACK_NUM_SZ 4
832 #define _ITUNES_GENRE_NUM_SZ 4
833 #define _ITUNES_COVER_TYPE_JPEG 13
834 #define _ITUNES_COVER_TYPE_PNG 14
836 unsigned char read_buf[_ITUNES_READ_BUF_SZ];
838 int cover_sz = 0, cover_type = 0, cover_found = 0;
839 int track_num = 0, track_found = 0;
840 int genre_index = 0, genre_found = 0;
841 int artist_sz = 0, artist_found = 0;
842 int limit = basic_header->size - hdlrBoxHeader.size;
843 long long cover_offset = 0, track_offset =0 , genre_offset = 0, artist_offset = 0;
845 for (i = 0, cover_found = 0, track_found = 0, genre_found = 0, artist_found = 0; i < limit && (cover_found == 0 || track_found == 0 || genre_found == 0 || artist_found == 0) ; i++) {
846 readed = mmfile_read (fp, read_buf, _ITUNES_READ_BUF_SZ);
847 if (readed != _ITUNES_READ_BUF_SZ)
850 /*ffmpeg extract artist, tracknum, excep cover image. see mov_read_udta_string()*/
853 * Artist : Added 2010.10.28
855 if (artist_found == 0 &&
856 read_buf[0] == 0xa9 && read_buf[1] == 'A' && read_buf[2] == 'R' && read_buf[3] == 'T' &&
857 read_buf[8] == 'd' && read_buf[9] == 'a' && read_buf[10] == 't' && read_buf[11] == 'a') {
860 artist_offset = mmfile_tell (fp);
861 artist_sz = mmfile_io_be_uint32 (*(int*)(read_buf + 4)) - 16; /* atom len(4)+data(4)+atom verion(1)+flag(3)+null(4) = 16 */
863 #ifdef __MMFILE_TEST_MODE__
864 debug_msg ("[%s][%d]----------------------------------- artist found, offset=[%lld], size=[%d]\n", __func__, __LINE__, artist_offset, artist_sz);
871 if (track_found == 0 &&
872 read_buf[0] == 't' && read_buf[1] == 'r' && read_buf[2] == 'k' && read_buf[3] == 'n' &&
873 read_buf[8] == 'd' && read_buf[9] == 'a' && read_buf[10] == 't' && read_buf[11] == 'a') {
876 track_offset = mmfile_tell (fp);
878 #ifdef __MMFILE_TEST_MODE__
879 debug_msg ("[%s][%d]----------------------------------- Track found, offset=[%lld]\n", __func__, __LINE__, track_offset);
884 * Genre : Added 2010.10.27
886 /*ffmpeg extract genre but only (0xa9,'g','e','n'). see mov_read_udta_string()*/
887 if (genre_found == 0 &&
888 read_buf[0] == 'g' && read_buf[1] == 'n' && read_buf[2] == 'r' && read_buf[3] == 'e' &&
889 read_buf[8] == 'd' && read_buf[9] == 'a' && read_buf[10] == 't' && read_buf[11] == 'a') {
892 genre_offset = mmfile_tell (fp);
894 #ifdef __MMFILE_TEST_MODE__
895 debug_msg ("[%s][%d]----------------------------------- genre found, offset=[%lld]\n", __func__, __LINE__, genre_offset);
903 if (cover_found == 0 &&
904 read_buf[0] == 'c' && read_buf[1] == 'o' && read_buf[2] == 'v' && read_buf[3] == 'r' &&
905 read_buf[8] == 'd' && read_buf[9] == 'a' && read_buf[10] == 't' && read_buf[11] == 'a') {
908 cover_sz = mmfile_io_be_uint32 (*(int*)(read_buf + 4)) - 12;
909 cover_type = mmfile_io_be_uint32 (*(int*)(read_buf + 12));
911 cover_offset = mmfile_tell (fp);
913 #ifdef __MMFILE_TEST_MODE__
914 debug_msg ("[%s][%d]----------------------------------- cover_found found, offset=[%lld]\n", __func__, __LINE__, cover_offset);
918 mmfile_seek (fp, -(_ITUNES_READ_BUF_SZ - 1), SEEK_CUR); /*FIXME: poor search*/
921 /*ffmpeg extract artist, tracknum, excep cover image. see mov_read_udta_string()*/
925 mmfile_seek (fp, artist_offset, SEEK_SET);
927 if (formatContext->artist) {
928 #ifdef __MMFILE_TEST_MODE__
929 debug_msg ("[%s][%d]----------------------------------- previous artist was [%s] \n", __func__, __LINE__, formatContext->artist);
931 free (formatContext->artist);
933 #ifdef __MMFILE_TEST_MODE__
934 debug_msg ("[%s][%d]----------------------------------- new artist will be allocated with size (len+1) [%d] \n", __func__, __LINE__, artist_sz+1);
936 formatContext->artist = mmfile_malloc (artist_sz+1);
938 if (formatContext->artist) {
939 readed = mmfile_read (fp, (unsigned char*)formatContext->artist, artist_sz);
940 formatContext->artist[artist_sz] = '\0';
942 #ifdef __MMFILE_TEST_MODE__
943 debug_msg ("[%s][%d]----------------------------------- new artist is [%s] \n", __func__, __LINE__, formatContext->artist);
946 if (readed != artist_sz) {
947 debug_error ("failed to read. ret = %d, in = %d\n", readed, artist_sz);
948 mmfile_free (formatContext->artist);
955 mmfile_seek (fp, track_offset, SEEK_SET);
956 readed = mmfile_read (fp, read_buf, _ITUNES_TRACK_NUM_SZ);
957 if (readed != _ITUNES_TRACK_NUM_SZ) {
958 debug_error ("failed to read. ret = %d, in = %d\n", readed, _ITUNES_TRACK_NUM_SZ);
960 track_num = mmfile_io_be_uint32 (*(int*)read_buf);
961 if (!formatContext->tagTrackNum) {
962 memset (read_buf, 0x00, _ITUNES_READ_BUF_SZ);
963 sprintf ((char*)read_buf, "%d", track_num);
964 formatContext->tagTrackNum = mmfile_strdup ((const char*)read_buf);
970 mmfile_seek (fp, genre_offset, SEEK_SET);
971 readed = mmfile_read (fp, read_buf, _ITUNES_GENRE_NUM_SZ);
972 if (readed != _ITUNES_GENRE_NUM_SZ) {
973 debug_error ("failed to read. ret = %d, in = %d\n", readed, _ITUNES_GENRE_NUM_SZ);
975 genre_index = mmfile_io_be_uint16 (*(int*)read_buf);
976 #ifdef __MMFILE_TEST_MODE__
977 debug_msg ("[%s][%d] genre index=[%d] \n", __func__, __LINE__, genre_index);
979 if (genre_index > 0 && genre_index < GENRE_COUNT) {
980 if (!formatContext->genre) {
981 memset (read_buf, 0x00, _ITUNES_READ_BUF_SZ);
982 snprintf ((char*)read_buf, sizeof(read_buf),"%s", MpegAudio_Genre[genre_index-1]);
983 #ifdef __MMFILE_TEST_MODE__
984 debug_msg ("[%s][%d] genre string=[%s] \n", __func__, __LINE__, read_buf);
986 formatContext->genre = mmfile_strdup ((const char*)read_buf);
992 1) below spec is in "iTunes Package Asset Specification 4.3" published by apple.
993 Music Cover Art Image Profile
994 - TIFF with ".tif" extension (32-bit uncompressed), JPEG with ".jpg" extension (quality unconstrained), or PNG with ".png" extension
995 - RGB (screen standard)
996 - Minimum size of 600 x 600 pixels
997 - Images must be at least 72 dpi
999 2)I found below info from google.
1000 cover image flag : JPEG (13, 0xd), PNG (14, 0xe)
1002 3)So, FIXME when cover image format is tif!
1006 mmfile_seek (fp, cover_offset, SEEK_SET);
1008 formatContext->artwork = mmfile_malloc (cover_sz);
1009 formatContext->artworkSize = cover_sz;
1010 if(cover_type == _ITUNES_COVER_TYPE_JPEG) {
1011 formatContext->artworkMime = mmfile_strdup("image/jpeg");
1012 } else if(cover_type == _ITUNES_COVER_TYPE_PNG) {
1013 formatContext->artworkMime = mmfile_strdup("image/png");
1014 /*} else if(cover_type == _ITUNES_COVER_TYPE_TIF) {
1015 formatContext->artworkMime = mmfile_strdup("image/tif");*/
1017 debug_error("Not proper cover image type, but set to jpeg. cover_type[%d]", cover_type);
1018 formatContext->artworkMime = mmfile_strdup("image/jpeg");
1021 if (formatContext->artwork) {
1022 readed = mmfile_read (fp, formatContext->artwork, cover_sz);
1023 if (readed != cover_sz) {
1024 debug_error ("failed to read. ret = %d, in = %d\n", readed, cover_sz);
1025 mmfile_free (formatContext->artwork);
1026 formatContext->artworkSize = 0;
1027 mmfile_free (formatContext->artworkMime);
1033 /*reset seek position*/
1034 mmfile_seek (fp, basic_header->start_offset + basic_header->size, SEEK_SET);
1036 return MMFILE_UTIL_SUCCESS;
1044 /* skip hdlr box name */
1045 mmfile_seek (fp, hdlrBoxHeader.size - MMFILE_MP4_BASIC_BOX_HEADER_LEN - MMFILE_3GP_HANDLER_BOX_LEN, SEEK_CUR);
1048 readed = mmfile_read (fp, (unsigned char *)&id3v2BoxHeader, MMFILE_MP4_BASIC_BOX_HEADER_LEN);
1049 if (readed != MMFILE_MP4_BASIC_BOX_HEADER_LEN)
1051 debug_error ("read id3v2 box header\n");
1055 id3v2BoxHeader.size = mmfile_io_be_uint32 (id3v2BoxHeader.size);
1056 id3v2BoxHeader.type = mmfile_io_le_uint32 (id3v2BoxHeader.type);
1058 if (id3v2BoxHeader.type != FOURCC ('I', 'D', '3', '2'))
1060 debug_warning ("meta type is not id3v2\n");
1064 readed = mmfile_read (fp, (unsigned char *)&id3v2Box, MMFILE_3GP_ID3V2_BOX_LEN);
1065 if (readed != MMFILE_3GP_ID3V2_BOX_LEN)
1067 debug_error ("read id3v2 box\n");
1071 id3v2Len = id3v2BoxHeader.size - MMFILE_MP4_BASIC_BOX_HEADER_LEN - MMFILE_3GP_ID3V2_BOX_LEN;
1073 id3v2Box.id3v2Data = mmfile_malloc (id3v2Len);
1074 if (!id3v2Box.id3v2Data)
1076 debug_error ("malloc id3tag data error\n");
1080 readed = mmfile_read (fp, (unsigned char *)id3v2Box.id3v2Data, id3v2Len);
1081 if (readed != id3v2Len)
1083 debug_error ("read id3tag data error\n");
1088 if (!IS_ID3V2_TAG(id3v2Box.id3v2Data))
1090 debug_error ("it is not id3tag\n");
1094 if (id3v2Box.id3v2Data[3] == 0xFF || id3v2Box.id3v2Data[4] == 0xFF ||
1095 id3v2Box.id3v2Data[6] >= 0x80 || id3v2Box.id3v2Data[7] >= 0x80 ||
1096 id3v2Box.id3v2Data[8] >= 0x80 || id3v2Box.id3v2Data[9] >= 0x80)
1098 debug_error ("it is not valid id3tag\n");
1102 tagVersion = id3v2Box.id3v2Data[3];
1103 if ( tagVersion > 4)
1105 debug_error ("tag vesion is too high\n");
1109 encSize = mmfile_io_le_uint32(&id3v2Box.id3v2Data[6]);
1110 tagInfo.tagV2Info.tagLen = MP3_TAGv2_HEADER_LEN;
1111 tagInfo.tagV2Info.tagLen += (((encSize & 0x0000007F) >> 0) | ((encSize & 0x00007F00) >> 1) | ((encSize & 0x007F0000) >> 2) | ((encSize & 0x7F000000) >> 3));
1112 tagInfo.tagV2Info.tagVersion = tagVersion;
1113 tagInfo.fileLen = id3v2Len;
1115 /* set id3v2 data to formatContext */
1120 versionCheck = mm_file_id3tag_parse_v222(&tagInfo, id3v2Box.id3v2Data);
1125 versionCheck = mm_file_id3tag_parse_v223(&tagInfo, id3v2Box.id3v2Data);
1130 versionCheck = mm_file_id3tag_parse_v224(&tagInfo, id3v2Box.id3v2Data);
1136 debug_error ("tag vesion is not support\n");
1137 versionCheck = false;
1142 if (versionCheck == false)
1144 debug_error ("tag parsing is fail\n");
1148 if (!formatContext->title) formatContext->title = mmfile_strdup((const char*)tagInfo.pTitle);
1149 if (!formatContext->artist) formatContext->artist = mmfile_strdup((const char*)tagInfo.pArtist);
1150 if (!formatContext->author) formatContext->author = mmfile_strdup((const char*)tagInfo.pAuthor);
1151 if (!formatContext->copyright) formatContext->copyright = mmfile_strdup((const char*)tagInfo.pCopyright);
1152 if (!formatContext->comment) formatContext->comment = mmfile_strdup((const char*)tagInfo.pComment);
1153 if (!formatContext->album) formatContext->album = mmfile_strdup((const char*)tagInfo.pAlbum);
1154 if (!formatContext->album_artist) formatContext->album_artist = mmfile_strdup((const char*)tagInfo.pAlbum_Artist);
1155 if (!formatContext->year) formatContext->year = mmfile_strdup((const char*)tagInfo.pYear);
1156 if (!formatContext->genre) formatContext->genre = mmfile_strdup((const char*)tagInfo.pGenre);
1157 if (!formatContext->tagTrackNum) formatContext->tagTrackNum = mmfile_strdup((const char*)tagInfo.pTrackNum);
1158 if (!formatContext->composer) formatContext->composer = mmfile_strdup((const char*)tagInfo.pComposer);
1159 if (!formatContext->classification) formatContext->classification = mmfile_strdup((const char*)tagInfo.pContentGroup);
1160 if (!formatContext->conductor) formatContext->conductor = mmfile_strdup((const char*)tagInfo.pConductor);
1162 formatContext->artwork = mmfile_malloc (tagInfo.imageInfo.imageLen);
1163 if ((tagInfo.imageInfo.imageLen > 0) && formatContext->artwork)
1165 formatContext->artworkSize = tagInfo.imageInfo.imageLen;
1166 memcpy (formatContext->artwork, tagInfo.imageInfo.pImageBuf, tagInfo.imageInfo.imageLen);
1169 mm_file_free_AvFileContentInfo (&tagInfo);
1170 mmfile_free (id3v2Box.id3v2Data);
1172 /*reset seek position*/
1173 mmfile_seek (fp, basic_header->start_offset + basic_header->size, SEEK_SET);
1175 return MMFILE_UTIL_SUCCESS;
1181 mmfile_seek (fp, basic_header->start_offset + basic_header->size, SEEK_SET);
1182 mmfile_free (id3v2Box.id3v2Data);
1184 return MMFILE_UTIL_FAIL;
1188 EXPORT_API int MMFileUtilGetMetaDataFromMP4 (MMFileFormatContext * formatContext)
1190 MMFileIOHandle *fp = NULL;
1194 ret = mmfile_open (&fp, formatContext->uriFileName, MMFILE_RDONLY);
1195 if(ret == MMFILE_UTIL_FAIL) {
1196 debug_error ("error: mmfile_open\n");
1200 MMFILE_MP4_BASIC_BOX_HEADER basic_header = {0,};
1201 basic_header.start_offset = mmfile_tell (fp);
1203 while ( (ret != MMFILE_UTIL_FAIL) && ((readed = mmfile_read (fp, (unsigned char *)&basic_header, MMFILE_MP4_BASIC_BOX_HEADER_LEN)) > 0 ) ) {
1204 basic_header.size = mmfile_io_be_uint32 (basic_header.size);
1205 basic_header.type = mmfile_io_le_uint32 (basic_header.type);
1207 if (basic_header.size == 0) {
1208 debug_warning ("header is invalid.\n");
1209 basic_header.size = readed;
1210 basic_header.type = 0;
1213 #ifdef __MMFILE_TEST_MODE__
1214 debug_msg ("START_OFFSET:[%lld] SIZE:[%d Byte] 4CC:[%c%c%c%c]\n",
1215 basic_header.start_offset, basic_header.size,
1216 ((char*)&basic_header.type)[0], ((char*)&basic_header.type)[1],
1217 ((char*)&basic_header.type)[2], ((char*)&basic_header.type)[3]);
1220 switch (basic_header.type) {
1221 case FOURCC ('m', 'o', 'o', 'v'): {
1222 #ifdef __MMFILE_TEST_MODE__
1223 debug_msg ("MPEG4: [moov] SIZE: [%d]Byte\n", basic_header.size);
1227 case FOURCC ('u', 'd', 't', 'a'): {
1228 #ifdef __MMFILE_TEST_MODE__
1229 debug_msg ("MPEG4: [udat] SIZE: [%d]Byte\n", basic_header.size);
1233 /////////////////////////////////////////////////////////////////
1234 // Extracting Tag Data //
1235 /////////////////////////////////////////////////////////////////
1236 case FOURCC ('t', 'i', 't', 'l'): {
1237 #ifdef __MMFILE_TEST_MODE__
1238 debug_msg ("MPEG4: [titl] SIZE: [%d]Byte\n", basic_header.size);
1240 GetStringFromTextTagBox (formatContext, fp, &basic_header, eMMFILE_3GP_TAG_TITLE);
1243 case FOURCC ('d', 's', 'c', 'p'): {
1244 #ifdef __MMFILE_TEST_MODE__
1245 debug_msg ("MPEG4: [dscp] SIZE: [%d]Byte\n", basic_header.size);
1247 GetStringFromTextTagBox (formatContext, fp, &basic_header, eMMFILE_3GP_TAG_CAPTION);
1250 case FOURCC ('c', 'p', 'r', 't'): {
1251 #ifdef __MMFILE_TEST_MODE__
1252 debug_msg ("MPEG4: [cprt] SIZE: [%d]Byte\n", basic_header.size);
1254 GetStringFromTextTagBox (formatContext, fp, &basic_header, eMMFILE_3GP_TAG_COPYRIGHT);
1257 case FOURCC ('p', 'e', 'r', 'f'): {
1258 #ifdef __MMFILE_TEST_MODE__
1259 debug_msg ("MPEG4: [perf] SIZE: [%d]Byte\n", basic_header.size);
1261 GetStringFromTextTagBox (formatContext, fp, &basic_header, eMMFILE_3GP_TAG_PERFORMER );
1264 case FOURCC ('a', 'u', 't', 'h'): {
1265 #ifdef __MMFILE_TEST_MODE__
1266 debug_msg ("MPEG4: [auth] SIZE: [%d]Byte\n", basic_header.size);
1268 GetStringFromTextTagBox (formatContext, fp, &basic_header, eMMFILE_3GP_TAG_AUTHOR);
1271 case FOURCC ('g', 'n', 'r', 'e'): {
1272 #ifdef __MMFILE_TEST_MODE__
1273 debug_msg ("MPEG4: [gnre] SIZE: [%d]Byte\n", basic_header.size);
1275 GetStringFromTextTagBox (formatContext, fp, &basic_header, eMMFILE_3GP_TAG_GENRE);
1278 case FOURCC ('a', 'l', 'b', 'm'): {
1279 #ifdef __MMFILE_TEST_MODE__
1280 debug_msg ("MPEG4: [albm] SIZE: [%d]Byte\n", basic_header.size);
1282 GetAlbumFromAlbumTagBox (formatContext, fp, &basic_header);
1285 case FOURCC ('y', 'r', 'r', 'c'): {
1286 #ifdef __MMFILE_TEST_MODE__
1287 debug_msg ("MPEG4: [yrrc] SIZE: [%d]Byte\n", basic_header.size);
1289 GetYearFromYearTagBox (formatContext, fp, &basic_header);
1292 case FOURCC ('r', 't', 'n', 'g'): {
1293 #ifdef __MMFILE_TEST_MODE__
1294 debug_msg ("MPEG4: [rtng] SIZE: [%d]Byte\n", basic_header.size);
1296 GetRatingFromRatingTagBox (formatContext, fp, &basic_header); /* not use */
1299 case FOURCC ('c', 'l', 's', 'f'): {
1300 #ifdef __MMFILE_TEST_MODE__
1301 debug_msg ("MPEG4: [clsf] SIZE: [%d]Byte\n", basic_header.size);
1303 GetClassficationFromClsfTagBox (formatContext, fp, &basic_header);
1306 case FOURCC ('k', 'y', 'w', 'd'): {
1307 #ifdef __MMFILE_TEST_MODE__
1308 debug_msg ("MPEG4: [kywd] SIZE: [%d]Byte\n", basic_header.size);
1310 ret = mmfile_seek (fp, basic_header.start_offset + basic_header.size, SEEK_SET);
1313 case FOURCC ('l', 'o', 'c', 'i'): {
1314 #ifdef __MMFILE_TEST_MODE__
1315 debug_msg ("MPEG4: [loci] SIZE: [%d]Byte\n", basic_header.size);
1317 GetLocationFromLociTagBox (formatContext, fp, &basic_header);
1320 /////////////////////////////////////////////////////////////////
1321 // Extracting ID3 Tag Data //
1322 /////////////////////////////////////////////////////////////////
1323 case FOURCC ('m', 'e', 't', 'a'): {
1324 #ifdef __MMFILE_TEST_MODE__
1325 debug_msg ("MPEG4: [meta] SIZE: [%d]Byte\n", basic_header.size);
1327 GetTagFromMetaBox (formatContext, fp, &basic_header);
1331 #ifdef __MMFILE_TEST_MODE__
1332 debug_msg ("4CC: Not Support.. so skip it\n");
1334 ret = mmfile_seek (fp, basic_header.start_offset + basic_header.size, SEEK_SET);
1339 if (ret == MMFILE_UTIL_FAIL) {
1340 debug_error("mmfile operation is error\n");
1345 basic_header.start_offset = mmfile_tell (fp);
1354 bool mm_file_id3tag_parse_v110(AvFileContentInfo* pInfo, unsigned char *buffer)
1356 const char *locale = MMFileUtilGetLocale (NULL);
1358 #ifdef __MMFILE_TEST_MODE__
1359 debug_msg ("ID3tag v110--------------------------------------------------------------\n");
1362 if(pInfo->tagV2Info.bTitleMarked == false) {
1363 pInfo->pTitle = mmfile_string_convert ((const char*)&buffer[3], MP3_ID3_TITLE_LENGTH, "UTF-8", locale, NULL, (unsigned int*)&pInfo->titleLen);
1364 #ifdef __MMFILE_TEST_MODE__
1365 debug_msg ( "pInfo->pTitle returned =(%s), pInfo->titleLen(%d)\n", pInfo->pTitle, pInfo->titleLen);
1369 if(pInfo->tagV2Info.bArtistMarked == false) {
1370 pInfo->pArtist = mmfile_string_convert ((const char*)&buffer[33], MP3_ID3_ARTIST_LENGTH, "UTF-8", locale, NULL, (unsigned int*)&pInfo->artistLen);
1371 #ifdef __MMFILE_TEST_MODE__
1372 debug_msg ( "pInfo->pArtist returned =(%s), pInfo->artistLen(%d)\n", pInfo->pArtist, pInfo->artistLen);
1375 if(pInfo->tagV2Info.bAlbumMarked == false) {
1376 pInfo->pAlbum = mmfile_string_convert ((const char*)&buffer[63], MP3_ID3_ALBUM_LENGTH, "UTF-8", locale, NULL, (unsigned int*)&pInfo->albumLen);
1377 #ifdef __MMFILE_TEST_MODE__
1378 debug_msg ( "pInfo->pAlbum returned =(%s), pInfo->albumLen(%d)\n", pInfo->pAlbum, pInfo->albumLen);
1381 if(pInfo->tagV2Info.bYearMarked == false) {
1382 pInfo->pYear = mmfile_string_convert ((const char*)&buffer[93], MP3_ID3_YEAR_LENGTH, "UTF-8", locale, NULL, (unsigned int*)&pInfo->yearLen);
1383 #ifdef __MMFILE_TEST_MODE__
1384 debug_msg ( "pInfo->pYear returned =(%s), pInfo->yearLen(%d)\n", pInfo->pYear, pInfo->yearLen);
1387 if(pInfo->tagV2Info.bDescriptionMarked == false) {
1388 pInfo->pComment = mmfile_string_convert ((const char*)&buffer[97], MP3_ID3_DESCRIPTION_LENGTH, "UTF-8", locale, NULL, (unsigned int*)&pInfo->commentLen);
1389 #ifdef __MMFILE_TEST_MODE__
1390 debug_msg ( "pInfo->pComment returned =(%s), pInfo->commentLen(%d)\n", pInfo->pComment, pInfo->commentLen);
1394 if(pInfo->tagV2Info.bTrackNumMarked== false) {
1395 pInfo->pTrackNum = mmfile_malloc (5);
1396 pInfo->pTrackNum[4] = 0;
1397 snprintf(pInfo->pTrackNum, 4, "%04d", (int)buffer[126]);
1398 pInfo->tracknumLen = strlen(pInfo->pTrackNum);
1399 #ifdef __MMFILE_TEST_MODE__
1400 debug_msg ( "pInfo->pTrackNum returned =(%s), pInfo->tracknumLen(%d)\n", pInfo->pTrackNum, pInfo->tracknumLen);
1404 if(pInfo->tagV2Info.bGenreMarked == false) {
1405 pInfo->genre = buffer[127];
1406 #ifdef __MMFILE_TEST_MODE__
1407 debug_msg ( "pInfo->genre returned genre number (%d)\n", pInfo->genre);
1415 bool mm_file_id3tag_parse_v222(AvFileContentInfo* pInfo, unsigned char *buffer)
1417 unsigned long taglen = 0;
1418 unsigned long needToloopv2taglen;
1419 unsigned long oneFrameLen = 0;
1420 unsigned long v2numOfFrames = 0;
1421 unsigned long curPos = 0;
1423 char *pExtContent = NULL;
1424 unsigned long purelyFramelen = 0;
1425 char *tmpConvert2Pcode = NULL;
1426 int inx=0, encodingOffSet=0, realCpyFrameNum=0,
1427 checkImgMimeTypeMax=0, checkImgDescriptionMax=0, checkImgExtMax=0,
1428 imgstartOffset=0, tmp = 0;
1430 int textEncodingType = 0;
1431 const char *locale = NULL;
1433 pInfo->tagV2Info.bTitleMarked = false;
1434 pInfo->tagV2Info.bAlbumMarked= false;
1435 pInfo->tagV2Info.bArtistMarked= false;
1436 pInfo->tagV2Info.bDescriptionMarked= false;
1437 pInfo->tagV2Info.bGenreMarked= false;
1438 pInfo->tagV2Info.bYearMarked= false;
1439 pInfo->tagV2Info.bTrackNumMarked= false;
1440 pInfo->tagV2Info.bEncByMarked= false;
1441 pInfo->tagV2Info.bURLMarked= false;
1442 pInfo->tagV2Info.bCopyRightMarked= false;
1443 pInfo->tagV2Info.bOriginArtistMarked= false;
1444 pInfo->tagV2Info.bComposerMarked= false;
1445 pInfo->tagV2Info.bImageMarked= false;
1446 pInfo->imageInfo.bURLInfo = false;
1447 pInfo->tagV2Info.bGenreUTF16 = false;
1448 pInfo->tagV2Info.bConductorMarked = false;
1450 pInfo->imageInfo.pImageBuf = NULL;
1451 pInfo->imageInfo.imageLen = 0;
1453 locale = MMFileUtilGetLocale (NULL);
1455 taglen = pInfo->tagV2Info.tagLen;
1456 needToloopv2taglen = taglen - MP3_TAGv2_HEADER_LEN;
1457 curPos = MP3_TAGv2_HEADER_LEN;
1459 #ifdef __MMFILE_TEST_MODE__
1460 debug_msg ("ID3tag v222--------------------------------------------------------------\n");
1462 if(needToloopv2taglen -MP3_TAGv2_22_TXT_HEADER_LEN > MP3_TAGv2_22_TXT_HEADER_LEN) {
1464 while(needToloopv2taglen > MP3_TAGv2_22_TXT_HEADER_LEN)
1466 if((buffer[curPos] < '0' || buffer[curPos] > 'Z') || (buffer[curPos+1] < '0' || buffer[curPos+1] > 'Z')
1467 || (buffer[curPos+2] < '0' || buffer[curPos+2] > 'Z'))
1470 memcpy(CompTmp, &buffer[curPos], 3);
1473 oneFrameLen = MP3_TAGv2_22_TXT_HEADER_LEN;
1474 oneFrameLen += (unsigned long)buffer[3+curPos] << 16 | (unsigned long)buffer[4+curPos] << 8
1475 | (unsigned long)buffer[5+curPos];
1476 if(oneFrameLen > taglen-curPos)
1478 purelyFramelen = oneFrameLen - MP3_TAGv2_22_TXT_HEADER_LEN;
1479 curPos +=MP3_TAGv2_22_TXT_HEADER_LEN;
1481 if(oneFrameLen > MP3_TAGv2_22_TXT_HEADER_LEN && purelyFramelen <= taglen-curPos)
1483 curPos += purelyFramelen;
1485 if(buffer[curPos-purelyFramelen] == 0x00)
1488 textEncodingType = AV_ID3V2_ISO_8859;
1490 else if(buffer[curPos-purelyFramelen] == 0x01)
1493 textEncodingType = AV_ID3V2_UTF16;
1496 //in order to deliver valid string to MP
1497 while((buffer[curPos-purelyFramelen+encodingOffSet] < 0x20) && (encodingOffSet < purelyFramelen))
1500 if(encodingOffSet < purelyFramelen)
1502 realCpyFrameNum = purelyFramelen - encodingOffSet;
1503 pExtContent = mmfile_malloc (realCpyFrameNum+3);
1504 memset(pExtContent, '\0', realCpyFrameNum+3);
1505 if(textEncodingType == AV_ID3V2_ISO_8859)
1507 if(strncmp((char *)CompTmp, "PIC", 3) != 0)
1509 tmpConvert2Pcode = mmfile_malloc ((realCpyFrameNum)*2+2);
1510 memset(tmpConvert2Pcode, 0, (realCpyFrameNum)*2+2);
1514 memcpy(pExtContent, &buffer[curPos-purelyFramelen+encodingOffSet], purelyFramelen-encodingOffSet);
1516 if(realCpyFrameNum > 0)
1518 if(strncmp((char *)CompTmp, "TT2", 3) == 0 && pInfo->tagV2Info.bTitleMarked == false)
1520 if(textEncodingType == AV_ID3V2_UTF16)
1522 pInfo->pTitle = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->titleLen);
1526 pInfo->pTitle = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->titleLen);
1529 #ifdef __MMFILE_TEST_MODE__
1530 debug_msg ( "pInfo->pTitle returned = (%s), pInfo->titleLen(%d)\n", pInfo->pTitle, pInfo->titleLen);
1532 pInfo->tagV2Info.bTitleMarked = true;
1534 else if(strncmp((char *)CompTmp, "TP1", 3) == 0 && pInfo->tagV2Info.bArtistMarked == false)
1536 if(textEncodingType == AV_ID3V2_UTF16)
1538 pInfo->pArtist = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->artistLen);
1542 pInfo->pArtist = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->artistLen);
1544 #ifdef __MMFILE_TEST_MODE__
1545 debug_msg ( "pInfo->pArtist returned = (%s), pInfo->artistLen(%d)\n", pInfo->pArtist, pInfo->artistLen);
1547 pInfo->tagV2Info.bArtistMarked = true;
1549 else if(strncmp((char *)CompTmp, "TP3", 3) == 0 && pInfo->tagV2Info.bConductorMarked == false)
1551 if(textEncodingType == AV_ID3V2_UTF16)
1553 pInfo->pConductor = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->conductorLen);
1557 pInfo->pConductor = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->conductorLen);
1559 #ifdef __MMFILE_TEST_MODE__
1560 debug_msg ( "pInfo->pConductor returned = (%s), pInfo->conductorLen(%d)\n", pInfo->pConductor, pInfo->conductorLen);
1562 pInfo->tagV2Info.bConductorMarked = true;
1564 else if(strncmp((char *)CompTmp, "TAL", 3) == 0 && pInfo->tagV2Info.bAlbumMarked == false)
1566 if(textEncodingType == AV_ID3V2_UTF16)
1568 pInfo->pAlbum = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->albumLen);
1572 pInfo->pAlbum = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->albumLen);
1574 #ifdef __MMFILE_TEST_MODE__
1575 debug_msg ( "pInfo->pAlbum returned = (%s), pInfo->albumLen(%d)\n", pInfo->pAlbum, pInfo->albumLen);
1577 pInfo->tagV2Info.bAlbumMarked = true;
1579 else if(strncmp((char *)CompTmp, "TYE", 3) == 0 && pInfo->tagV2Info.bYearMarked == false)
1581 if(textEncodingType == AV_ID3V2_UTF16)
1583 pInfo->pYear = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->yearLen);
1587 pInfo->pYear = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->yearLen);
1589 #ifdef __MMFILE_TEST_MODE__
1590 debug_msg ( "pInfo->pYear returned = (%s), pInfo->yearLen(%d)\n", pInfo->pYear, pInfo->yearLen);
1592 pInfo->tagV2Info.bYearMarked = true;
1594 else if(strncmp((char *)CompTmp, "COM", 3) == 0 && pInfo->tagV2Info.bDescriptionMarked == false)
1596 //skip language data!
1597 if(realCpyFrameNum > 4)
1599 realCpyFrameNum -= 4;
1602 //pExtContent[tmp+1] value should't have encoding value
1603 if(pExtContent[tmp] > 0x20 && (pExtContent[tmp - 1] == 0x00 || pExtContent[tmp - 1] == 0x01))
1605 if(pExtContent[tmp - 1] == 0x00)
1606 textEncodingType = AV_ID3V2_ISO_8859;
1608 textEncodingType = AV_ID3V2_UTF16;
1610 if(textEncodingType == AV_ID3V2_UTF16)
1612 pInfo->pComment = mmfile_string_convert ((char*)&pExtContent[tmp], realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->commentLen);
1616 pInfo->pComment = mmfile_string_convert ((char*)&pExtContent[tmp], realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->commentLen);
1619 #ifdef __MMFILE_TEST_MODE__
1620 debug_msg ( "pInfo->pComment returned = (%s), pInfo->commentLen(%d)\n", pInfo->pComment, pInfo->commentLen);
1622 pInfo->tagV2Info.bDescriptionMarked = true;
1626 #ifdef __MMFILE_TEST_MODE__
1627 debug_msg ( "mmf_file_id3tag_parse_v222: failed to get Comment Info tmp(%d), purelyFramelen - encodingOffSet(%d)\n", tmp, purelyFramelen - encodingOffSet );
1633 #ifdef __MMFILE_TEST_MODE__
1634 debug_msg ( "mmf_file_id3tag_parse_v222: Description info too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum );
1640 else if(strncmp((char *)CompTmp, "TCO", 3) == 0 && pInfo->tagV2Info.bGenreMarked == false)
1642 if(textEncodingType == AV_ID3V2_UTF16)
1644 pInfo->pGenre = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->genreLen);
1648 pInfo->pGenre = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->genreLen);
1651 #ifdef __MMFILE_TEST_MODE__
1652 debug_msg ( "pInfo->pGenre returned = (%s), pInfo->genreLen(%d)\n", pInfo->pGenre, pInfo->genreLen);
1655 if((pInfo->pGenre != NULL) && (pInfo->genreLen > 0)) {
1659 ret = sscanf( pInfo->pGenre, "%d", &int_genre);
1662 #ifdef __MMFILE_TEST_MODE__
1663 debug_msg("genre information is inteager [%d]\n", int_genre);
1666 //Change int to string
1667 if((0 <= int_genre) && (int_genre < GENRE_COUNT-1)) {
1668 /*save genreinfo like "(123)". mm_file_id3tag_restore_content_info convert it to string*/
1669 char tmp_genre[6] = {0,}; /*ex. "(123)+NULL"*/
1670 int tmp_genre_len = 0;
1672 memset (tmp_genre, 0, 6);
1673 snprintf(tmp_genre, sizeof(tmp_genre), "(%d)", int_genre);
1675 tmp_genre_len = strlen(tmp_genre);
1676 if(tmp_genre_len > 0) {
1677 if(pInfo->pGenre) _FREE_EX(pInfo->pGenre);
1678 pInfo->pGenre = mmfile_malloc (sizeof(char) * (tmp_genre_len + 1) );
1681 strncpy(pInfo->pGenre, tmp_genre, tmp_genre_len);
1682 pInfo->pGenre[tmp_genre_len] = 0;
1689 pInfo->tagV2Info.bGenreMarked = true;
1691 else if(strncmp((char *)CompTmp, "TRK", 3) == 0 && pInfo->tagV2Info.bTrackNumMarked == false)
1693 if(textEncodingType == AV_ID3V2_UTF16)
1695 pInfo->pTrackNum = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->tracknumLen);
1699 pInfo->pTrackNum = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->tracknumLen);
1702 #ifdef __MMFILE_TEST_MODE__
1703 debug_msg ( "pInfo->pTrackNum returned = (%s), pInfo->tracknumLen(%d)\n", pInfo->pTrackNum, pInfo->tracknumLen);
1705 pInfo->tagV2Info.bTrackNumMarked = true;
1707 else if(strncmp((char *)CompTmp, "TEN", 3) == 0 && pInfo->tagV2Info.bEncByMarked == false)
1709 if(textEncodingType == AV_ID3V2_UTF16)
1711 pInfo->pEncBy = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->encbyLen);
1715 pInfo->pEncBy = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->encbyLen);
1718 #ifdef __MMFILE_TEST_MODE__
1719 debug_msg ( "pInfo->pEncBy returned = (%s), pInfo->encbyLen(%d)\n", pInfo->pEncBy, pInfo->encbyLen);
1721 pInfo->tagV2Info.bEncByMarked = true;
1723 else if(strncmp((char *)CompTmp, "WXX", 3) == 0 && pInfo->tagV2Info.bURLMarked == false)
1725 if(realCpyFrameNum > 4)
1727 //skip language data!
1728 realCpyFrameNum -= 4;
1731 //pExtContent[tmp+1] value should't have null value
1732 if(pExtContent[tmp] > 0x20 && (pExtContent[tmp - 1] == 0x00 || pExtContent[tmp - 1] == 0x01))
1734 if(pExtContent[tmp - 1] == 0x00)
1735 textEncodingType = AV_ID3V2_ISO_8859;
1737 textEncodingType = AV_ID3V2_UTF16;
1739 if(textEncodingType == AV_ID3V2_UTF16)
1741 pInfo->pURL = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->urlLen);
1745 pInfo->pURL = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->urlLen);
1748 #ifdef __MMFILE_TEST_MODE__
1749 debug_msg ( "pInfo->pURL returned = (%s), pInfo->urlLen(%d)\n", pInfo->pURL, pInfo->urlLen);
1751 pInfo->tagV2Info.bURLMarked = true;
1755 #ifdef __MMFILE_TEST_MODE__
1756 debug_msg ( "mmf_file_id3tag_parse_v222: failed to get URL Info tmp(%d), purelyFramelen - encodingOffSet(%d)\n", tmp, purelyFramelen - encodingOffSet );
1762 #ifdef __MMFILE_TEST_MODE__
1763 debug_msg ( "mmf_file_id3tag_parse_v222: URL info too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum );
1768 else if(strncmp((char *)CompTmp, "TCR", 3) == 0 && pInfo->tagV2Info.bCopyRightMarked == false)
1770 if(textEncodingType == AV_ID3V2_UTF16)
1772 pInfo->pCopyright = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->copyrightLen);
1776 pInfo->pCopyright = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->copyrightLen);
1779 #ifdef __MMFILE_TEST_MODE__
1780 debug_msg ( "pInfo->pCopyright returned = (%s), pInfo->copyrightLen(%d)\n", pInfo->pCopyright, pInfo->copyrightLen);
1782 pInfo->tagV2Info.bCopyRightMarked = true;
1784 else if(strncmp((char *)CompTmp, "TOA", 3) == 0 && pInfo->tagV2Info.bOriginArtistMarked == false)
1786 if(textEncodingType == AV_ID3V2_UTF16)
1788 pInfo->pOriginArtist = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->originartistLen);
1792 pInfo->pOriginArtist = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->originartistLen);
1795 #ifdef __MMFILE_TEST_MODE__
1796 debug_msg ( "pInfo->pOriginArtist returned = (%s), pInfo->originartistLen(%d)\n", pInfo->pOriginArtist, pInfo->originartistLen);
1798 pInfo->tagV2Info.bOriginArtistMarked = true;
1800 else if(strncmp((char *)CompTmp, "TCM", 3) == 0 && pInfo->tagV2Info.bComposerMarked == false)
1802 if(textEncodingType == AV_ID3V2_UTF16)
1804 pInfo->pComposer = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->composerLen);
1808 pInfo->pComposer = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->composerLen);
1810 #ifdef __MMFILE_TEST_MODE__
1811 debug_msg ( "pInfo->pComposer returned = (%s), pInfo->originartistLen(%d)\n", pInfo->pComposer, pInfo->composerLen);
1813 pInfo->tagV2Info.bComposerMarked = true;
1815 else if(strncmp((char *)CompTmp, "TRD", 3) == 0 && pInfo->tagV2Info.bRecDateMarked== false)
1817 if(textEncodingType == AV_ID3V2_UTF16)
1819 pInfo->pRecDate = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->recdateLen);
1823 pInfo->pRecDate = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->recdateLen);
1825 #ifdef __MMFILE_TEST_MODE__
1826 debug_msg ( "pInfo->pRecDate returned = (%s), pInfo->recdateLen(%d)\n", pInfo->pRecDate, pInfo->recdateLen);
1828 pInfo->tagV2Info.bRecDateMarked = true;
1830 else if(strncmp((char *)CompTmp, "PIC", 3) == 0 && pInfo->tagV2Info.bImageMarked == false && realCpyFrameNum <= 2000000)
1832 if(textEncodingType == AV_ID3V2_UTF16)
1834 #ifdef __MMFILE_TEST_MODE__
1835 debug_msg ("mmf_file_id3tag_parse_v222: this is abnormal case!!\n");
1840 if(pExtContent[0] != 0)
1842 for(inx = 0; inx < MP3_ID3_IMAGE_EXT_MAX_LENGTH; inx++)
1843 pInfo->imageInfo.imageExt[inx] = '\0';//ini mimetype variable
1845 while((checkImgExtMax < MP3_ID3_IMAGE_EXT_MAX_LENGTH-1) && pExtContent[checkImgExtMax] != '\0')
1847 pInfo->imageInfo.imageExt[checkImgExtMax] = pExtContent[checkImgExtMax];
1853 #ifdef __MMFILE_TEST_MODE__
1854 debug_msg ( "mmf_file_id3tag_parse_v222: PIC image's not included to image Extention\n");
1858 imgstartOffset += checkImgExtMax;
1860 if(pExtContent[imgstartOffset] < AV_ID3V2_PICTURE_TYPE_MAX)
1862 pInfo->imageInfo.pictureType = pExtContent[imgstartOffset];
1864 imgstartOffset++;//PictureType(1byte)
1866 if(pExtContent[imgstartOffset] != 0x0)
1868 for(inx = 0; inx < MP3_ID3_IMAGE_DESCRIPTION_MAX_LENGTH-1; inx++)
1869 pInfo->imageInfo.imageDescription[inx] = '\0';//ini imgdescripiton variable
1871 while((checkImgDescriptionMax < MP3_ID3_IMAGE_DESCRIPTION_MAX_LENGTH-1) && pExtContent[imgstartOffset+checkImgDescriptionMax] != '\0')
1873 pInfo->imageInfo.imageDescription[checkImgDescriptionMax] = pExtContent[imgstartOffset+checkImgDescriptionMax];
1874 checkImgDescriptionMax++;
1876 pInfo->imageInfo.imgDesLen= checkImgDescriptionMax;
1880 pInfo->imageInfo.imgDesLen= 0;
1883 imgstartOffset += checkImgDescriptionMax;
1885 if((pExtContent[imgstartOffset] == '\0') && (realCpyFrameNum - imgstartOffset > 0))
1887 imgstartOffset ++; // endofDesceriptionType(1byte)
1889 while(pExtContent[imgstartOffset] == '\0') //some content has useless '\0' in front of picture data
1894 #ifdef __MMFILE_TEST_MODE__
1895 debug_msg ( "after scaning imgDescription imgstartOffset(%d) value!\n", imgstartOffset);
1898 if(realCpyFrameNum - imgstartOffset > 0)
1900 pInfo->imageInfo.imageLen = realCpyFrameNum - imgstartOffset;
1901 pInfo->imageInfo.pImageBuf= mmfile_malloc (pInfo->imageInfo.imageLen + 1);
1902 memcpy(pInfo->imageInfo.pImageBuf, pExtContent+ imgstartOffset, pInfo->imageInfo.imageLen);
1903 pInfo->imageInfo.pImageBuf[pInfo->imageInfo.imageLen] = 0;
1905 if(IS_INCLUDE_URL(pInfo->imageInfo.imageMIMEType))
1906 pInfo->imageInfo.bURLInfo = true; //if mimetype is "-->", image date has an URL
1910 #ifdef __MMFILE_TEST_MODE__
1911 debug_msg ( "No APIC image!! realCpyFrameNum(%d) - imgstartOffset(%d)\n", realCpyFrameNum, imgstartOffset);
1918 checkImgMimeTypeMax = 0;
1919 checkImgDescriptionMax = 0;
1923 pInfo->tagV2Info.bImageMarked= true;
1932 curPos += purelyFramelen;
1933 if(purelyFramelen != 0)
1934 needToloopv2taglen = MP3_TAGv2_22_TXT_HEADER_LEN;
1937 if(pExtContent) _FREE_EX(pExtContent);
1938 if(tmpConvert2Pcode) _FREE_EX(tmpConvert2Pcode);
1939 memset(CompTmp, 0, 4);
1942 needToloopv2taglen -= oneFrameLen;
1946 needToloopv2taglen = MP3_TAGv2_22_TXT_HEADER_LEN;
1949 realCpyFrameNum = 0;
1950 textEncodingType = 0;
1966 bool mm_file_id3tag_parse_v223(AvFileContentInfo* pInfo, unsigned char *buffer)
1968 unsigned long taglen = 0;
1969 unsigned long needToloopv2taglen;
1970 unsigned long oneFrameLen = 0;
1971 unsigned long v2numOfFrames = 0;
1972 unsigned long curPos = 0;
1974 unsigned char *pExtContent = NULL;
1975 unsigned long purelyFramelen = 0;
1976 char *tmpConvert2Pcode = NULL;
1977 int inx=0, encodingOffSet=0, realCpyFrameNum=0, checkImgMimeTypeMax=0, checkImgDescriptionMax=0, imgstartOffset=0, tmp = 0;
1978 int textEncodingType = 0;
1979 const char *locale = NULL;
1981 locale = MMFileUtilGetLocale (NULL);
1983 pInfo->tagV2Info.bTitleMarked = false;
1984 pInfo->tagV2Info.bAlbumMarked= false;
1985 pInfo->tagV2Info.bArtistMarked= false;
1986 pInfo->tagV2Info.bDescriptionMarked= false;
1987 pInfo->tagV2Info.bGenreMarked= false;
1988 pInfo->tagV2Info.bYearMarked= false;
1989 pInfo->tagV2Info.bTrackNumMarked= false;
1990 pInfo->tagV2Info.bEncByMarked= false;
1991 pInfo->tagV2Info.bURLMarked= false;
1992 pInfo->tagV2Info.bCopyRightMarked= false;
1993 pInfo->tagV2Info.bOriginArtistMarked= false;
1994 pInfo->tagV2Info.bComposerMarked= false;
1995 pInfo->tagV2Info.bImageMarked= false;
1996 pInfo->imageInfo.bURLInfo = false;
1997 pInfo->tagV2Info.bConductorMarked = false;
1998 pInfo->tagV2Info.bUnsyncLyricsMarked = false;
1999 pInfo->tagV2Info.bSyncLyricsMarked = false;
2001 pInfo->tagV2Info.bGenreUTF16 = false;
2003 pInfo->imageInfo.pImageBuf = NULL;
2004 pInfo->imageInfo.imageLen = 0;
2006 taglen = pInfo->tagV2Info.tagLen;
2007 needToloopv2taglen = taglen - MP3_TAGv2_HEADER_LEN;
2008 curPos = MP3_TAGv2_HEADER_LEN;
2010 #ifdef __MMFILE_TEST_MODE__
2011 debug_msg ("ID3tag v223--------------------------------------------------------------\n");
2014 if(needToloopv2taglen -MP3_TAGv2_23_TXT_HEADER_LEN > MP3_TAGv2_23_TXT_HEADER_LEN)
2017 while(needToloopv2taglen > MP3_TAGv2_23_TXT_HEADER_LEN)
2019 if((buffer[curPos] < '0' || buffer[curPos] > 'Z') || (buffer[curPos+1] < '0' || buffer[curPos+1] > 'Z')
2020 || (buffer[curPos+2] < '0' || buffer[curPos+2] > 'Z')|| (buffer[curPos+3] < '0' || buffer[curPos+3] > 'Z'))
2023 memcpy(CompTmp, &buffer[curPos], 4);
2026 oneFrameLen = MP3_TAGv2_23_TXT_HEADER_LEN;
2027 oneFrameLen += (unsigned long)buffer[4+curPos] << 24 | (unsigned long)buffer[5+curPos] << 16
2028 | (unsigned long)buffer[6+curPos] << 8 | (unsigned long)buffer[7+curPos];
2030 #ifdef __MMFILE_TEST_MODE__
2031 debug_msg ("----------------------------------------------------------------------------------------------------\n");
2034 if(oneFrameLen > taglen-curPos)
2037 purelyFramelen = oneFrameLen - MP3_TAGv2_23_TXT_HEADER_LEN;
2038 curPos +=MP3_TAGv2_23_TXT_HEADER_LEN;
2040 if(oneFrameLen > MP3_TAGv2_23_TXT_HEADER_LEN && purelyFramelen <= taglen-curPos)
2042 curPos += purelyFramelen;
2044 if( IS_ENCODEDBY_UTF16(buffer+(curPos-purelyFramelen)) )
2047 #ifdef __MMFILE_TEST_MODE__
2048 debug_msg ( "this text string(%s) encoded by UTF16 encodingOffSet(%d)\n", CompTmp, encodingOffSet);
2050 textEncodingType = AV_ID3V2_UTF16;
2052 else if ( IS_ENCODEDBY_UTF16_R(buffer+(curPos-purelyFramelen)) )
2055 #ifdef __MMFILE_TEST_MODE__
2056 debug_msg ( "this text string(%s) encoded by UTF16 encodingOffSet(%d)\n", CompTmp, encodingOffSet);
2058 textEncodingType = AV_ID3V2_UTF16_BE;
2060 else if( IS_ENCODEDBY_UTF16(buffer+(curPos-purelyFramelen+1)) )
2063 #ifdef __MMFILE_TEST_MODE__
2064 debug_msg ( "this text string(%s) encoded by UTF16 encodingOffSet(%d)\n", CompTmp, encodingOffSet);
2066 textEncodingType = AV_ID3V2_UTF16;
2068 else if ( IS_ENCODEDBY_UTF16_R(buffer+(curPos-purelyFramelen+1)) )
2071 #ifdef __MMFILE_TEST_MODE__
2072 debug_msg ( "this text string(%s) encoded by UTF16 encodingOffSet(%d)\n", CompTmp, encodingOffSet);
2074 textEncodingType = AV_ID3V2_UTF16_BE;
2078 if (buffer[curPos-purelyFramelen+encodingOffSet] == 0x00)
2080 #ifdef __MMFILE_TEST_MODE__
2081 debug_msg ("encodingOffset will be set to 1\n");
2088 #ifdef __MMFILE_TEST_MODE__
2089 debug_msg ("Finding encodingOffset\n");
2092 while((buffer[curPos-purelyFramelen+encodingOffSet] < 0x20) && (encodingOffSet < purelyFramelen)) // text string encoded by ISO-8859-1
2095 textEncodingType = AV_ID3V2_ISO_8859;
2096 #ifdef __MMFILE_TEST_MODE__
2097 debug_msg ( "this text string(%s) encoded by ISO-8859-1 encodingOffSet(%d)\n", CompTmp, encodingOffSet);
2101 if(encodingOffSet < purelyFramelen)
2103 realCpyFrameNum = purelyFramelen - encodingOffSet;
2104 pExtContent = mmfile_malloc (realCpyFrameNum+3);
2105 memset(pExtContent, '\0', realCpyFrameNum+3);
2106 if(textEncodingType == AV_ID3V2_ISO_8859)
2108 if(strncmp((char *)CompTmp, "APIC", 4) != 0)
2110 tmpConvert2Pcode = mmfile_malloc ((realCpyFrameNum)*2+2);
2111 memset(tmpConvert2Pcode, 0, (realCpyFrameNum)*2+2);
2115 memcpy(pExtContent, &buffer[curPos-purelyFramelen+encodingOffSet], purelyFramelen-encodingOffSet);
2116 if(realCpyFrameNum > 0)
2118 if(strncmp((char *)CompTmp, "TIT2", 4) == 0 && pInfo->tagV2Info.bTitleMarked == false)
2120 if(textEncodingType == AV_ID3V2_UTF16)
2122 pInfo->pTitle = mmfile_string_convert ((char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->titleLen);
2124 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2126 debug_warning ("not implemented\n");
2130 pInfo->pTitle = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->titleLen);
2133 #ifdef __MMFILE_TEST_MODE__
2134 debug_msg ( "pInfo->pTitle returned = (%s), pInfo->titleLen(%d)\n", pInfo->pTitle, pInfo->titleLen);
2136 pInfo->tagV2Info.bTitleMarked = true;
2139 else if(strncmp((char *)CompTmp, "TPE1", 4) == 0 && pInfo->tagV2Info.bArtistMarked == false)
2141 if(textEncodingType == AV_ID3V2_UTF16)
2143 pInfo->pArtist = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->artistLen);
2145 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2147 debug_warning ("not implemented\n");
2151 pInfo->pArtist = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->artistLen);
2154 #ifdef __MMFILE_TEST_MODE__
2155 debug_msg ( "pInfo->pArtist returned = (%s), pInfo->artistLen(%d)\n", pInfo->pArtist, pInfo->artistLen);
2157 pInfo->tagV2Info.bArtistMarked = true;
2159 else if(strncmp((char *)CompTmp, "TPE3", 4) == 0 && pInfo->tagV2Info.bConductorMarked == false)
2161 if(textEncodingType == AV_ID3V2_UTF16)
2163 pInfo->pConductor = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->conductorLen);
2165 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2167 debug_warning ("not implemented\n");
2171 pInfo->pConductor = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->conductorLen);
2174 #ifdef __MMFILE_TEST_MODE__
2175 debug_msg ( "pInfo->pConductor returned = (%s), pInfo->conductorLen(%d)\n", pInfo->pConductor, pInfo->conductorLen);
2177 pInfo->tagV2Info.bConductorMarked = true;
2179 else if(strncmp((char *)CompTmp, "TALB", 4) == 0 && pInfo->tagV2Info.bAlbumMarked == false)
2181 if(textEncodingType == AV_ID3V2_UTF16)
2183 pInfo->pAlbum = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->albumLen);
2185 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2187 debug_warning ("not implemented\n");
2191 pInfo->pAlbum = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->albumLen);
2193 #ifdef __MMFILE_TEST_MODE__
2194 debug_msg ( "pInfo->pAlbum returned = (%s), pInfo->albumLen(%d)\n", pInfo->pAlbum, pInfo->albumLen);
2196 pInfo->tagV2Info.bAlbumMarked = true;
2198 else if(strncmp((char *)CompTmp, "TYER", 4) == 0 && pInfo->tagV2Info.bYearMarked == false)
2200 if(textEncodingType == AV_ID3V2_UTF16)
2202 pInfo->pYear = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->yearLen);
2204 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2206 debug_warning ("not implemented\n");
2210 pInfo->pYear = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->yearLen);
2213 #ifdef __MMFILE_TEST_MODE__
2214 debug_msg ( "pInfo->pYear returned = (%s), pInfo->yearLen(%d)\n", pInfo->pYear, pInfo->yearLen);
2216 pInfo->tagV2Info.bYearMarked = true;
2218 else if(strncmp((char *)CompTmp, "COMM", 4) == 0 && pInfo->tagV2Info.bDescriptionMarked == false)
2220 if(realCpyFrameNum > 3)
2222 realCpyFrameNum -= 3;
2225 //pExtContent[tmp+1] value should't have encoding value
2226 if(pExtContent[tmp] == 0x00 || pExtContent[tmp] == 0xFF|| pExtContent[tmp] == 0xFE)
2228 if((IS_ENCODEDBY_UTF16(pExtContent+tmp) || IS_ENCODEDBY_UTF16_R(pExtContent+tmp)) && realCpyFrameNum > 2)
2230 while((NEWLINE_OF_UTF16(pExtContent + tmp) || NEWLINE_OF_UTF16_R(pExtContent + tmp))&& realCpyFrameNum > 4)
2232 realCpyFrameNum -= 4;
2236 if(IS_ENCODEDBY_UTF16(pExtContent+tmp) && (realCpyFrameNum > 2))
2238 realCpyFrameNum -= 2;
2240 textEncodingType = AV_ID3V2_UTF16;
2242 else if (IS_ENCODEDBY_UTF16_R(pExtContent+tmp) && (realCpyFrameNum > 2))
2244 realCpyFrameNum -= 2;
2246 textEncodingType = AV_ID3V2_UTF16_BE;
2248 else if(IS_ENCODEDBY_UTF16(pExtContent+tmp+1) && (realCpyFrameNum > 3))
2250 realCpyFrameNum -= 3;
2252 textEncodingType = AV_ID3V2_UTF16;
2254 else if (IS_ENCODEDBY_UTF16_R(pExtContent+tmp+1) && (realCpyFrameNum > 3))
2256 realCpyFrameNum -= 3;
2258 textEncodingType = AV_ID3V2_UTF16_BE;
2262 #ifdef __MMFILE_TEST_MODE__
2263 debug_msg ( "pInfo->pComment Never Get Here!!\n");
2269 while((pExtContent[tmp] < 0x20) && (tmp < realCpyFrameNum)) // text string encoded by ISO-8859-1
2274 textEncodingType = AV_ID3V2_ISO_8859;
2277 #ifdef __MMFILE_TEST_MODE__
2278 debug_msg ( "tmp(%d) textEncodingType(%d), realCpyFrameNum(%d)\n", tmp, textEncodingType, realCpyFrameNum);
2281 if(textEncodingType == AV_ID3V2_UTF16)
2283 pInfo->pComment = mmfile_string_convert ((const char*)&pExtContent[tmp], realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->commentLen);
2285 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2287 debug_warning ("not implemented\n");
2291 pInfo->pComment = mmfile_string_convert ((const char*)&pExtContent[tmp], realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->commentLen);
2296 #ifdef __MMFILE_TEST_MODE__
2297 debug_msg ( "failed to get Comment Info tmp(%d), purelyFramelen - encodingOffSet(%d)\n", tmp, purelyFramelen - encodingOffSet);
2299 pInfo->commentLen = 0;
2304 #ifdef __MMFILE_TEST_MODE__
2305 debug_msg ( "Description info too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum);
2307 pInfo->commentLen = 0;
2311 #ifdef __MMFILE_TEST_MODE__
2312 debug_msg ( "pInfo->pComment returned = (%s), pInfo->commentLen(%d)\n", pInfo->pComment, pInfo->commentLen);
2314 pInfo->tagV2Info.bDescriptionMarked = true;
2316 else if(strncmp((char *)CompTmp, "SYLT", 4) == 0 && pInfo->tagV2Info.bSyncLyricsMarked == false)
2320 int copy_start_pos = tmp;
2321 AvSynclyricsInfo *synclyrics_info = NULL;
2322 GList *synclyrics_info_list = NULL;
2324 if(realCpyFrameNum > 5)
2326 realCpyFrameNum -= 5;
2329 //pExtContent[tmp+1] value should't have encoding value
2330 if(pExtContent[tmp] == 0x00 || pExtContent[tmp] == 0xFF|| pExtContent[tmp] == 0xFE)
2332 if((IS_ENCODEDBY_UTF16(pExtContent+tmp) || IS_ENCODEDBY_UTF16_R(pExtContent+tmp)) && realCpyFrameNum > 2)
2334 while((NEWLINE_OF_UTF16(pExtContent + tmp) || NEWLINE_OF_UTF16_R(pExtContent + tmp))&& realCpyFrameNum > 4)
2336 realCpyFrameNum -= 4;
2340 if(IS_ENCODEDBY_UTF16(pExtContent+tmp) && (realCpyFrameNum > 2))
2342 realCpyFrameNum -= 2;
2344 textEncodingType = AV_ID3V2_UTF16;
2346 else if (IS_ENCODEDBY_UTF16_R(pExtContent+tmp) && (realCpyFrameNum > 2))
2348 realCpyFrameNum -= 2;
2350 textEncodingType = AV_ID3V2_UTF16_BE;
2352 else if(IS_ENCODEDBY_UTF16(pExtContent+tmp+1) && (realCpyFrameNum > 3))
2354 realCpyFrameNum -= 3;
2356 textEncodingType = AV_ID3V2_UTF16;
2358 else if (IS_ENCODEDBY_UTF16_R(pExtContent+tmp+1) && (realCpyFrameNum > 3))
2360 realCpyFrameNum -= 3;
2362 textEncodingType = AV_ID3V2_UTF16_BE;
2366 #ifdef __MMFILE_TEST_MODE__
2367 debug_msg ( "pInfo->pSyncLyrics Never Get Here!!\n");
2373 while((pExtContent[tmp] < 0x20) && (tmp < realCpyFrameNum)) // text string encoded by ISO-8859-1
2378 textEncodingType = AV_ID3V2_ISO_8859;
2381 #ifdef __MMFILE_TEST_MODE__
2382 debug_msg ( "tmp(%d) textEncodingType(%d), realCpyFrameNum(%d)\n", tmp, textEncodingType, realCpyFrameNum);
2385 if(realCpyFrameNum < MMFILE_SYNC_LYRIC_INFO_MIN_LEN)
2387 #ifdef __MMFILE_TEST_MODE__
2388 debug_msg ( "failed to get Synchronised lyrics Info realCpyFramNum(%d)\n", realCpyFrameNum);
2390 pInfo->syncLyricsNum = 0;
2394 if(textEncodingType == AV_ID3V2_UTF16)
2396 debug_warning ("[AV_ID3V2_UTF16] not implemented\n");
2398 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2400 debug_warning ("[AV_ID3V2_UTF16_BE] not implemented\n");
2404 for(idx = 0; idx < realCpyFrameNum; idx++)
2406 if(pExtContent[tmp+idx] == 0x00)
2408 synclyrics_info = (AvSynclyricsInfo *)malloc(sizeof(AvSynclyricsInfo));
2410 if(textEncodingType == AV_ID3V2_UTF8) {
2411 synclyrics_info->lyric_info= mmfile_malloc(copy_len+1);
2412 memset(synclyrics_info->lyric_info, 0, copy_len+1);
2413 memcpy(synclyrics_info->lyric_info, pExtContent+copy_start_pos, copy_len);
2414 synclyrics_info->lyric_info[copy_len+1] = '\0';
2417 synclyrics_info->lyric_info = mmfile_string_convert ((const char*)&pExtContent[copy_start_pos], copy_len, "UTF-8", locale, NULL, NULL);
2420 synclyrics_info->time_info= (unsigned long)pExtContent[tmp+idx+1] << 24 | (unsigned long)pExtContent[tmp+idx+2] << 16 | (unsigned long)pExtContent[tmp+idx+3] << 8 | (unsigned long)pExtContent[tmp+idx+4];
2422 copy_start_pos = tmp + idx + 1;
2423 debug_msg("[%d][%s] idx[%d], copy_len[%d] copy_start_pos[%d]", synclyrics_info->time_info, synclyrics_info->lyric_info, idx, copy_len, copy_start_pos);
2425 synclyrics_info_list = g_list_append(synclyrics_info_list, synclyrics_info);
2429 pInfo->pSyncLyrics = synclyrics_info_list;
2430 pInfo->syncLyricsNum = g_list_length(pInfo->pSyncLyrics);
2436 #ifdef __MMFILE_TEST_MODE__
2437 debug_msg ( "failed to get Synchronised lyrics Info tmp(%d), purelyFramelen - encodingOffSet(%d)\n", tmp, purelyFramelen - encodingOffSet);
2439 pInfo->syncLyricsNum = 0;
2444 #ifdef __MMFILE_TEST_MODE__
2445 debug_msg ( "Synchronised lyrics too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum);
2447 pInfo->syncLyricsNum = 0;
2451 #ifdef __MMFILE_TEST_MODE__
2452 debug_msg ( "pInfo->pSyncLyrics returned = (%s), pInfo->syncLyricsNum(%d)\n", pInfo->pSyncLyrics, pInfo->syncLyricsNum);
2454 pInfo->tagV2Info.bSyncLyricsMarked = true;
2456 else if(strncmp((char *)CompTmp, "USLT", 4) == 0 && pInfo->tagV2Info.bUnsyncLyricsMarked == false)
2458 if(realCpyFrameNum > 3)
2460 realCpyFrameNum -= 3;
2463 //pExtContent[tmp+1] value should't have encoding value
2464 if(pExtContent[tmp] == 0x00 || pExtContent[tmp] == 0xFF|| pExtContent[tmp] == 0xFE)
2466 if (pExtContent[tmp] == 0x00) {
2467 realCpyFrameNum -= 2;
2471 if((IS_ENCODEDBY_UTF16(pExtContent+tmp) || IS_ENCODEDBY_UTF16_R(pExtContent+tmp)) && realCpyFrameNum > 2)
2473 while((NEWLINE_OF_UTF16(pExtContent + tmp) || NEWLINE_OF_UTF16_R(pExtContent + tmp))&& realCpyFrameNum > 4)
2475 realCpyFrameNum -= 4;
2479 if(IS_ENCODEDBY_UTF16(pExtContent+tmp) && (realCpyFrameNum > 2))
2481 realCpyFrameNum -= 2;
2483 textEncodingType = AV_ID3V2_UTF16;
2485 else if (IS_ENCODEDBY_UTF16_R(pExtContent+tmp) && (realCpyFrameNum > 2))
2487 realCpyFrameNum -= 2;
2489 textEncodingType = AV_ID3V2_UTF16_BE;
2491 else if(IS_ENCODEDBY_UTF16(pExtContent+tmp+1) && (realCpyFrameNum > 3))
2493 realCpyFrameNum -= 3;
2495 textEncodingType = AV_ID3V2_UTF16;
2497 else if (IS_ENCODEDBY_UTF16_R(pExtContent+tmp+1) && (realCpyFrameNum > 3))
2499 realCpyFrameNum -= 3;
2501 textEncodingType = AV_ID3V2_UTF16_BE;
2505 #ifdef __MMFILE_TEST_MODE__
2506 debug_msg ( "pInfo->pUnsyncLyrics Never Get Here!!\n");
2512 while((pExtContent[tmp] < 0x20) && (tmp < realCpyFrameNum)) // text string encoded by ISO-8859-1
2517 textEncodingType = AV_ID3V2_ISO_8859;
2520 #ifdef __MMFILE_TEST_MODE__
2521 debug_msg ( "tmp(%d) textEncodingType(%d), realCpyFrameNum(%d)\n", tmp, textEncodingType, realCpyFrameNum);
2524 if(textEncodingType == AV_ID3V2_UTF16)
2526 pInfo->pUnsyncLyrics = mmfile_string_convert ((const char*)&pExtContent[tmp], realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->unsynclyricsLen);
2528 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2530 debug_warning ("not implemented\n");
2534 pInfo->pUnsyncLyrics = mmfile_string_convert ((const char*)&pExtContent[tmp], realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->unsynclyricsLen);
2539 #ifdef __MMFILE_TEST_MODE__
2540 debug_msg ( "failed to get Unsynchronised lyrics Info tmp(%d), purelyFramelen - encodingOffSet(%d)\n", tmp, purelyFramelen - encodingOffSet);
2542 pInfo->unsynclyricsLen = 0;
2547 #ifdef __MMFILE_TEST_MODE__
2548 debug_msg ( "Unsynchronised lyrics too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum);
2550 pInfo->unsynclyricsLen = 0;
2554 #ifdef __MMFILE_TEST_MODE__
2555 debug_msg ( "pInfo->pUnsyncLyrics returned = (%s), pInfo->unsynclyricsLen(%d)\n", pInfo->pUnsyncLyrics, pInfo->unsynclyricsLen);
2557 pInfo->tagV2Info.bUnsyncLyricsMarked = true;
2559 else if(strncmp((char *)CompTmp, "TCON", 4) == 0 && pInfo->tagV2Info.bGenreMarked == false)
2561 if(textEncodingType == AV_ID3V2_UTF16)
2563 pInfo->pGenre = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->genreLen);
2565 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2567 debug_warning ("not implemented\n");
2571 pInfo->pGenre = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->genreLen);
2574 #ifdef __MMFILE_TEST_MODE__
2575 debug_msg ( "pInfo->pGenre returned = (%s), pInfo->genreLen(%d)\n", pInfo->pGenre, pInfo->genreLen);
2578 if((pInfo->pGenre != NULL) && (pInfo->genreLen > 0)) {
2582 ret = sscanf( pInfo->pGenre, "%d", &int_genre);
2585 #ifdef __MMFILE_TEST_MODE__
2586 debug_msg("genre information is inteager [%d]\n", int_genre);
2589 //Change int to string
2590 if((0 <= int_genre) && (int_genre < GENRE_COUNT-1)) {
2591 /*save genreinfo like "(123)". mm_file_id3tag_restore_content_info convert it to string*/
2592 char tmp_genre[6] = {0,}; /*ex. "(123)+NULL"*/
2593 int tmp_genre_len = 0;
2595 memset (tmp_genre, 0, 6);
2596 snprintf(tmp_genre, sizeof(tmp_genre), "(%d)", int_genre);
2598 tmp_genre_len = strlen(tmp_genre);
2599 if(tmp_genre_len > 0) {
2600 if(pInfo->pGenre) _FREE_EX(pInfo->pGenre);
2601 pInfo->pGenre = mmfile_malloc (sizeof(char) * (tmp_genre_len + 1) );
2604 strncpy(pInfo->pGenre, tmp_genre, tmp_genre_len);
2605 pInfo->pGenre[tmp_genre_len] = 0;
2612 pInfo->tagV2Info.bGenreMarked = true;
2614 else if(strncmp((char *)CompTmp, "TRCK", 4) == 0 && pInfo->tagV2Info.bTrackNumMarked == false)
2616 if(textEncodingType == AV_ID3V2_UTF16)
2618 pInfo->pTrackNum = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->tracknumLen);
2620 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2622 debug_warning ("not implemented\n");
2626 pInfo->pTrackNum = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->tracknumLen);
2629 #ifdef __MMFILE_TEST_MODE__
2630 debug_msg ( "pInfo->pTrackNum returned = (%s), pInfo->tracknumLen(%d)\n", pInfo->pTrackNum, pInfo->tracknumLen);
2632 pInfo->tagV2Info.bTrackNumMarked = true;
2634 else if(strncmp((char *)CompTmp, "TENC", 4) == 0 && pInfo->tagV2Info.bEncByMarked == false)
2636 if(textEncodingType == AV_ID3V2_UTF16)
2638 pInfo->pEncBy = mmfile_string_convert ((char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->encbyLen);
2640 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2642 debug_warning ("not implemented\n");
2646 pInfo->pEncBy = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->encbyLen);
2648 #ifdef __MMFILE_TEST_MODE__
2649 debug_msg ( "pInfo->pEncBy returned = (%s), pInfo->encbyLen(%d)\n", pInfo->pEncBy, pInfo->encbyLen);
2651 pInfo->tagV2Info.bEncByMarked = true;
2653 else if(strncmp((char *)CompTmp, "WXXX", 4) == 0 && pInfo->tagV2Info.bURLMarked == false)
2655 if(textEncodingType == AV_ID3V2_UTF16)
2657 pInfo->pURL = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->urlLen);
2659 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2661 debug_warning ("not implemented\n");
2665 pInfo->pURL = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->urlLen);
2668 #ifdef __MMFILE_TEST_MODE__
2669 debug_msg ( "pInfo->pURL returned = (%s), pInfo->urlLen(%d)\n", pInfo->pURL, pInfo->urlLen);
2671 pInfo->tagV2Info.bURLMarked = true;
2673 else if(strncmp((char *)CompTmp, "TCOP", 4) == 0 && pInfo->tagV2Info.bCopyRightMarked == false)
2675 if(textEncodingType == AV_ID3V2_UTF16)
2677 pInfo->pCopyright = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->copyrightLen);
2679 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2681 debug_warning ("not implemented\n");
2685 pInfo->pCopyright = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->copyrightLen);
2688 #ifdef __MMFILE_TEST_MODE__
2689 debug_msg ( "pInfo->pCopyright returned = (%s), pInfo->copyrightLen(%d)\n", pInfo->pCopyright, pInfo->copyrightLen);
2691 pInfo->tagV2Info.bCopyRightMarked = true;
2693 else if(strncmp((char *)CompTmp, "TOPE", 4) == 0 && pInfo->tagV2Info.bOriginArtistMarked == false)
2695 if(textEncodingType == AV_ID3V2_UTF16)
2697 pInfo->pOriginArtist = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->originartistLen);
2699 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2701 debug_warning ("not implemented\n");
2705 pInfo->pOriginArtist = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->originartistLen);
2707 #ifdef __MMFILE_TEST_MODE__
2708 debug_msg ( "pInfo->pOriginArtist returned = (%s), pInfo->originartistLen(%d)\n", pInfo->pOriginArtist, pInfo->originartistLen);
2710 pInfo->tagV2Info.bOriginArtistMarked = true;
2712 else if(strncmp((char *)CompTmp, "TCOM", 4) == 0 && pInfo->tagV2Info.bComposerMarked == false)
2714 if(textEncodingType == AV_ID3V2_UTF16)
2716 pInfo->pComposer = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->composerLen);
2718 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2720 debug_warning ("not implemented\n");
2724 pInfo->pComposer = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->composerLen);
2727 #ifdef __MMFILE_TEST_MODE__
2728 debug_msg ( "pInfo->pComposer returned = (%s), pInfo->composerLen(%d)\n", pInfo->pComposer, pInfo->composerLen);
2730 pInfo->tagV2Info.bComposerMarked = true;
2732 else if(strncmp((char *)CompTmp, "TRDA", 4) == 0 && pInfo->tagV2Info.bRecDateMarked== false)
2734 if(textEncodingType == AV_ID3V2_UTF16)
2736 pInfo->pRecDate = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->recdateLen);
2738 else if (textEncodingType == AV_ID3V2_UTF16_BE)
2740 debug_warning ("not implemented\n");
2744 pInfo->pRecDate = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->recdateLen);
2746 #ifdef __MMFILE_TEST_MODE__
2747 debug_msg ( "pInfo->pRecDate returned = (%s), pInfo->recdateLen(%d)\n", pInfo->pRecDate, pInfo->recdateLen);
2749 pInfo->tagV2Info.bRecDateMarked = true;
2751 else if(strncmp((char *)CompTmp, "APIC", 4) == 0 && pInfo->tagV2Info.bImageMarked == false && realCpyFrameNum <= 2000000)
2753 if(textEncodingType == AV_ID3V2_UTF16)
2755 #ifdef __MMFILE_TEST_MODE__
2756 debug_msg ( "mmf_file_id3tag_parse_v223: this is abnormal case!!\n");
2762 if(pExtContent[0] != '\0')
2764 for(inx = 0; inx < MP3_ID3_IMAGE_MIME_TYPE_MAX_LENGTH-1; inx++)
2765 pInfo->imageInfo.imageMIMEType[inx] = '\0';//ini mimetype variable
2767 while((checkImgMimeTypeMax < MP3_ID3_IMAGE_MIME_TYPE_MAX_LENGTH-1) && pExtContent[checkImgMimeTypeMax] != '\0')
2769 pInfo->imageInfo.imageMIMEType[checkImgMimeTypeMax] = pExtContent[checkImgMimeTypeMax];
2770 checkImgMimeTypeMax++;
2772 pInfo->imageInfo.imgMimetypeLen = checkImgMimeTypeMax;
2776 pInfo->imageInfo.imgMimetypeLen = 0;
2777 #ifdef __MMFILE_TEST_MODE__
2778 debug_msg ( "APIC image's not included to MIME type\n");
2782 imgstartOffset += checkImgMimeTypeMax;
2784 if((pExtContent[imgstartOffset] == '\0') && (realCpyFrameNum - imgstartOffset > 0))
2786 imgstartOffset++;//endofMIME(1byte)
2787 #ifdef __MMFILE_TEST_MODE__
2788 debug_msg ( "after scaning Mime type imgstartOffset(%d) value!\n", imgstartOffset);
2791 if(pExtContent[imgstartOffset] < AV_ID3V2_PICTURE_TYPE_MAX)
2793 pInfo->imageInfo.pictureType = pExtContent[imgstartOffset];
2797 #ifdef __MMFILE_TEST_MODE__
2798 debug_msg ( "APIC image has invalid picture type(0x%x)\n", pExtContent[imgstartOffset]);
2801 imgstartOffset++;//PictureType(1byte)
2802 #ifdef __MMFILE_TEST_MODE__
2803 debug_msg ( "after scaning PictureType imgstartOffset(%d) value!\n", imgstartOffset);
2806 if(pExtContent[imgstartOffset] != 0x0)
2808 for(inx = 0; inx < MP3_ID3_IMAGE_DESCRIPTION_MAX_LENGTH-1; inx++)
2809 pInfo->imageInfo.imageDescription[inx] = '\0';//ini imgdescripiton variable
2811 while((checkImgDescriptionMax < MP3_ID3_IMAGE_DESCRIPTION_MAX_LENGTH-1) && pExtContent[imgstartOffset+checkImgDescriptionMax] != '\0')
2813 pInfo->imageInfo.imageDescription[checkImgDescriptionMax] = pExtContent[imgstartOffset+checkImgDescriptionMax];
2814 checkImgDescriptionMax++;
2816 pInfo->imageInfo.imgDesLen= checkImgDescriptionMax;
2820 pInfo->imageInfo.imgDesLen= 0;
2821 #ifdef __MMFILE_TEST_MODE__
2822 debug_msg ( "APIC image's not included to Description!!!\n");
2826 imgstartOffset += checkImgDescriptionMax;
2827 if((pExtContent[imgstartOffset] == '\0') && (realCpyFrameNum - imgstartOffset > 0))
2829 imgstartOffset ++; // endofDesceriptionType(1byte)
2831 while(pExtContent[imgstartOffset] == '\0') //some content has useless '\0' in front of picture data
2836 #ifdef __MMFILE_TEST_MODE__
2837 debug_msg ( "after scaning imgDescription imgstartOffset(%d) value!\n", imgstartOffset);
2840 if(realCpyFrameNum - imgstartOffset > 0)
2842 pInfo->imageInfo.imageLen = realCpyFrameNum - imgstartOffset;
2843 pInfo->imageInfo.pImageBuf = mmfile_malloc (pInfo->imageInfo.imageLen + 1);
2844 memcpy(pInfo->imageInfo.pImageBuf, pExtContent+ imgstartOffset, pInfo->imageInfo.imageLen);
2845 pInfo->imageInfo.pImageBuf[pInfo->imageInfo.imageLen] = 0;
2846 if(IS_INCLUDE_URL(pInfo->imageInfo.imageMIMEType))
2847 pInfo->imageInfo.bURLInfo = true; //if mimetype is "-->", image date has an URL
2851 #ifdef __MMFILE_TEST_MODE__
2852 debug_msg ( "No APIC image!! realCpyFrameNum(%d) - imgstartOffset(%d)\n", realCpyFrameNum, imgstartOffset);
2855 #ifdef __MMFILE_TEST_MODE__
2856 debug_msg ( "pInfo->imageInfo.imageLen(%d), imgstartOffset(%d)!\n", pInfo->imageInfo.imageLen, imgstartOffset);
2861 #ifdef __MMFILE_TEST_MODE__
2862 debug_msg ( "pExtContent[imgstartOffset](%d) value should setted NULL value for end of description! realCpyFrameNum - imgstartOffset(%d)\n",
2863 pExtContent[imgstartOffset], realCpyFrameNum - imgstartOffset);
2869 #ifdef __MMFILE_TEST_MODE__
2870 debug_msg ( "pExtContent[imgstartOffset](%d) value should setted NULL value for end of mimetype! realCpyFrameNum - imgstartOffset(%d)\n",
2871 pExtContent[imgstartOffset], realCpyFrameNum - imgstartOffset);
2877 checkImgMimeTypeMax = 0;
2878 checkImgDescriptionMax = 0;
2881 pInfo->tagV2Info.bImageMarked= true;
2886 #ifdef __MMFILE_TEST_MODE__
2887 debug_msg ( "CompTmp(%s) This Frame ID currently not Supports!!\n", CompTmp);
2895 #ifdef __MMFILE_TEST_MODE__
2896 debug_msg ( "All of the pExtContent Values are NULL\n");
2902 curPos += purelyFramelen;
2903 if(purelyFramelen != 0)
2904 needToloopv2taglen = MP3_TAGv2_23_TXT_HEADER_LEN;
2905 #ifdef __MMFILE_TEST_MODE__
2906 debug_msg ( "This Frame's size is Zero! purelyFramelen(%d)\n", purelyFramelen);
2910 if(pExtContent) _FREE_EX(pExtContent);
2911 if(tmpConvert2Pcode) _FREE_EX(tmpConvert2Pcode);
2912 memset(CompTmp, 0, 4);
2916 needToloopv2taglen -= oneFrameLen;
2920 needToloopv2taglen = MP3_TAGv2_23_TXT_HEADER_LEN;
2923 realCpyFrameNum = 0;
2924 textEncodingType = 0;
2938 bool mm_file_id3tag_parse_v224(AvFileContentInfo* pInfo, unsigned char *buffer)
2940 unsigned long taglen = 0;
2941 unsigned long needToloopv2taglen;
2942 unsigned long oneFrameLen = 0;
2943 unsigned long v2numOfFrames = 0;
2944 unsigned long curPos = 0;
2946 unsigned char *pExtContent = NULL;
2947 unsigned long purelyFramelen = 0;
2948 char *tmpConvert2Pcode = NULL;
2949 int inx=0, encodingOffSet=0, realCpyFrameNum=0, checkImgMimeTypeMax=0, checkImgDescriptionMax=0, imgstartOffset=0, tmp = 0;
2950 int textEncodingType = 0;
2951 const char *locale = NULL;
2953 locale = MMFileUtilGetLocale (NULL);
2955 pInfo->tagV2Info.bTitleMarked = false;
2956 pInfo->tagV2Info.bAlbumMarked= false;
2957 pInfo->tagV2Info.bArtistMarked= false;
2958 pInfo->tagV2Info.bDescriptionMarked= false;
2959 pInfo->tagV2Info.bGenreMarked= false;
2960 pInfo->tagV2Info.bYearMarked= false;
2961 pInfo->tagV2Info.bTrackNumMarked= false;
2962 pInfo->tagV2Info.bEncByMarked= false;
2963 pInfo->tagV2Info.bURLMarked= false;
2964 pInfo->tagV2Info.bCopyRightMarked= false;
2965 pInfo->tagV2Info.bOriginArtistMarked= false;
2966 pInfo->tagV2Info.bComposerMarked= false;
2967 pInfo->tagV2Info.bImageMarked= false;
2968 pInfo->imageInfo.bURLInfo = false;
2969 pInfo->tagV2Info.bConductorMarked = false;
2970 pInfo->tagV2Info.bGenreUTF16 = false;
2971 pInfo->tagV2Info.bUnsyncLyricsMarked = false;
2972 pInfo->tagV2Info.bSyncLyricsMarked = false;
2974 pInfo->imageInfo.pImageBuf = NULL;
2975 pInfo->imageInfo.imageLen = 0;
2977 taglen = pInfo->tagV2Info.tagLen;
2978 needToloopv2taglen = taglen - MP3_TAGv2_HEADER_LEN;
2979 curPos = MP3_TAGv2_HEADER_LEN;
2981 #ifdef __MMFILE_TEST_MODE__
2982 debug_msg ("ID3tag v224--------------------------------------------------------------\n");
2985 /* check Extended Header */
2986 if (buffer[5] & 0x40)
2988 /* if extended header exists, skip it*/
2989 int extendedHeaderLen = (unsigned long)buffer[10] << 21 | (unsigned long)buffer[11] << 14 | (unsigned long)buffer[12] << 7 | (unsigned long)buffer[13];
2991 #ifdef __MMFILE_TEST_MODE__
2992 debug_msg ("[%s][%d]--------------- extendedHeaderLen = %d\n",__func__,__LINE__, extendedHeaderLen);
2995 curPos += extendedHeaderLen;
2998 if(needToloopv2taglen -MP3_TAGv2_23_TXT_HEADER_LEN > MP3_TAGv2_23_TXT_HEADER_LEN)
3001 while(needToloopv2taglen > MP3_TAGv2_23_TXT_HEADER_LEN)
3003 if((buffer[curPos] < '0' || buffer[curPos] > 'Z') || (buffer[curPos+1] < '0' || buffer[curPos+1] > 'Z')
3004 || (buffer[curPos+2] < '0' || buffer[curPos+2] > 'Z')|| (buffer[curPos+3] < '0' || buffer[curPos+3] > 'Z'))
3007 memcpy(CompTmp, &buffer[curPos], 4);
3010 oneFrameLen = MP3_TAGv2_23_TXT_HEADER_LEN;
3011 oneFrameLen += (unsigned long)buffer[4+curPos] << 21 | (unsigned long)buffer[5+curPos] << 14
3012 | (unsigned long)buffer[6+curPos] << 7 | (unsigned long)buffer[7+curPos];
3013 if(oneFrameLen > taglen-curPos)
3016 purelyFramelen = oneFrameLen - MP3_TAGv2_23_TXT_HEADER_LEN;
3017 curPos +=MP3_TAGv2_23_TXT_HEADER_LEN;
3019 #ifdef __MMFILE_TEST_MODE__
3020 debug_msg ("-----------------------------------------------------------------------------------\n");
3023 if(oneFrameLen > MP3_TAGv2_23_TXT_HEADER_LEN && purelyFramelen <= taglen-curPos)
3025 curPos += purelyFramelen;
3027 //in case of UTF 16 encoding
3028 //buffer+(curPos-purelyFramelen) data should '0x01' but in order to expansion, we don't accurately check the value.
3029 if(IS_ENCODEDBY_UTF16(buffer+(curPos-purelyFramelen)))
3032 textEncodingType = AV_ID3V2_UTF16;
3034 else if (IS_ENCODEDBY_UTF16_R(buffer+(curPos-purelyFramelen)))
3037 textEncodingType = AV_ID3V2_UTF16_BE;
3039 else if(IS_ENCODEDBY_UTF16(buffer+(curPos-purelyFramelen+1)))
3042 textEncodingType = AV_ID3V2_UTF16;
3044 else if(IS_ENCODEDBY_UTF16_R(buffer+(curPos-purelyFramelen+1)))
3047 textEncodingType = AV_ID3V2_UTF16_BE;
3051 //in case of UTF-16 BE encoding
3052 if(buffer[curPos-purelyFramelen] == 0x02)
3055 while((buffer[curPos-purelyFramelen+encodingOffSet] == '\0') && (encodingOffSet < purelyFramelen))
3056 encodingOffSet++;//null skip!
3057 textEncodingType = AV_ID3V2_UTF16_BE;
3059 //in case of UTF8 encoding
3060 else if (buffer[curPos-purelyFramelen] == 0x03)
3063 while((buffer[curPos-purelyFramelen+encodingOffSet] == '\0') && (encodingOffSet < purelyFramelen))
3064 encodingOffSet++;//null skip!
3065 textEncodingType = AV_ID3V2_UTF8;
3067 //in case of ISO-8859-1 encoding
3070 //buffer+(curPos-purelyFramelen) data should 0x00 but in order to expansion, we don't accurately check the value.
3072 while((buffer[curPos-purelyFramelen+encodingOffSet] < 0x20) && (encodingOffSet < purelyFramelen))
3073 encodingOffSet++;//less than 0x20 value skip!
3074 textEncodingType = AV_ID3V2_ISO_8859;
3078 if(encodingOffSet < purelyFramelen)
3080 realCpyFrameNum = purelyFramelen - encodingOffSet;
3081 pExtContent = mmfile_malloc (realCpyFrameNum+3);
3082 memset(pExtContent, '\0', realCpyFrameNum+3);
3083 if(textEncodingType == AV_ID3V2_ISO_8859)
3085 if(strncmp((char *)CompTmp, "APIC", 4) != 0)
3087 tmpConvert2Pcode = mmfile_malloc ((realCpyFrameNum)*2+2);
3088 memset(tmpConvert2Pcode, 0, (realCpyFrameNum)*2+2);
3092 memcpy(pExtContent, &buffer[curPos-purelyFramelen+encodingOffSet], purelyFramelen-encodingOffSet);
3094 if(realCpyFrameNum > 0)
3096 if(strncmp((char *)CompTmp, "TIT2", 4) == 0 && pInfo->tagV2Info.bTitleMarked == false)
3098 if(textEncodingType == AV_ID3V2_UTF16)
3100 pInfo->pTitle = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->titleLen);
3102 else if(textEncodingType == AV_ID3V2_UTF16_BE)
3104 debug_warning ("not implemented\n");
3106 else if(textEncodingType == AV_ID3V2_UTF8)
3108 pInfo->pTitle= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3109 memcpy(pInfo->pTitle, pExtContent, realCpyFrameNum);
3110 pInfo->pTitle[realCpyFrameNum] = '\0';
3111 /*string copy with '\0'*/
3112 pInfo->titleLen = realCpyFrameNum;
3113 _STRNCPY_EX (pInfo->pTitle, pExtContent, pInfo->titleLen);
3117 pInfo->pTitle = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->titleLen);
3120 #ifdef __MMFILE_TEST_MODE__
3121 debug_msg ( "pInfo->pTitle returned = (%s), pInfo->titleLen(%d)\n", pInfo->pTitle, pInfo->titleLen);
3123 pInfo->tagV2Info.bTitleMarked = true;
3126 else if(strncmp((char *)CompTmp, "TPE1", 4) == 0 && pInfo->tagV2Info.bArtistMarked == false)
3128 if(textEncodingType == AV_ID3V2_UTF16)
3130 pInfo->pArtist = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->artistLen);
3132 else if(textEncodingType == AV_ID3V2_UTF16_BE)
3134 debug_warning ("not implemented\n");
3136 else if(textEncodingType == AV_ID3V2_UTF8)
3138 pInfo->pArtist= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3139 memcpy(pInfo->pArtist, pExtContent, realCpyFrameNum);
3140 pInfo->pArtist[realCpyFrameNum] = '\0';
3141 /*string copy with '\0'*/
3142 pInfo->artistLen = realCpyFrameNum;
3143 _STRNCPY_EX (pInfo->pArtist, pExtContent, pInfo->artistLen);
3147 pInfo->pArtist = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->artistLen);
3150 #ifdef __MMFILE_TEST_MODE__
3151 debug_msg ( "pInfo->pArtist returned = (%s), pInfo->artistLen(%d)\n", pInfo->pArtist, pInfo->artistLen);
3153 pInfo->tagV2Info.bArtistMarked = true;
3155 else if(strncmp((char *)CompTmp, "TPE3", 4) == 0 && pInfo->tagV2Info.bConductorMarked == false)
3157 if(textEncodingType == AV_ID3V2_UTF16)
3159 pInfo->pConductor = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->conductorLen);
3161 else if(textEncodingType == AV_ID3V2_UTF16_BE)
3163 debug_warning ("not implemented\n");
3165 else if(textEncodingType == AV_ID3V2_UTF8)
3167 pInfo->pConductor= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3168 memcpy(pInfo->pConductor, pExtContent, realCpyFrameNum);
3169 pInfo->pConductor[realCpyFrameNum] = '\0';
3170 /*string copy with '\0'*/
3171 pInfo->conductorLen = realCpyFrameNum;
3172 _STRNCPY_EX (pInfo->pConductor, pExtContent, pInfo->conductorLen);
3176 pInfo->pConductor = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->conductorLen);
3179 #ifdef __MMFILE_TEST_MODE__
3180 debug_msg ( "pInfo->pConductor returned = (%s), pInfo->conductorLen(%d)\n", pInfo->pConductor, pInfo->conductorLen);
3182 pInfo->tagV2Info.bConductorMarked = true;
3184 else if(strncmp((char *)CompTmp, "TALB", 4) == 0 && pInfo->tagV2Info.bAlbumMarked == false)
3186 if(textEncodingType == AV_ID3V2_UTF16)
3188 pInfo->pAlbum = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->albumLen);
3190 else if(textEncodingType == AV_ID3V2_UTF16_BE)
3192 debug_warning ("not implemented\n");
3194 else if(textEncodingType == AV_ID3V2_UTF8)
3196 pInfo->pAlbum= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3197 memcpy(pInfo->pAlbum, pExtContent, realCpyFrameNum);
3198 pInfo->pAlbum[realCpyFrameNum] = '\0';
3199 /*string copy with '\0'*/
3200 pInfo->albumLen = realCpyFrameNum;
3201 _STRNCPY_EX (pInfo->pAlbum, pExtContent, pInfo->albumLen);
3205 pInfo->pAlbum = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->albumLen);
3208 #ifdef __MMFILE_TEST_MODE__
3209 debug_msg ( "pInfo->pAlbum returned = (%s), pInfo->albumLen(%d)\n", pInfo->pAlbum, pInfo->albumLen);
3211 pInfo->tagV2Info.bAlbumMarked = true;
3213 else if(strncmp((char *)CompTmp, "TYER", 4) == 0 && pInfo->tagV2Info.bYearMarked == false) //TODO. TYER is replaced by the TDRC. but many files use TYER in v2.4
3215 if(textEncodingType == AV_ID3V2_UTF16)
3217 pInfo->pYear = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->yearLen);
3219 else if (textEncodingType == AV_ID3V2_UTF16_BE)
3221 debug_warning ("not implemented\n");
3223 else if(textEncodingType == AV_ID3V2_UTF8)
3225 pInfo->pYear= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3226 memcpy(pInfo->pYear, pExtContent, realCpyFrameNum);
3227 pInfo->pYear[realCpyFrameNum] = '\0';
3228 /*string copy with '\0'*/
3229 pInfo->yearLen = realCpyFrameNum;
3230 _STRNCPY_EX (pInfo->pYear, pExtContent, pInfo->yearLen);
3234 pInfo->pYear = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->yearLen);
3237 #ifdef __MMFILE_TEST_MODE__
3238 debug_msg ( "pInfo->pYear returned = (%s), pInfo->yearLen(%d)\n", pInfo->pYear, pInfo->yearLen);
3240 pInfo->tagV2Info.bYearMarked = true;
3242 else if(strncmp((char *)CompTmp, "COMM", 4) == 0 && pInfo->tagV2Info.bDescriptionMarked == false)
3244 if(realCpyFrameNum > 3)
3246 realCpyFrameNum -= 3;
3249 if(textEncodingType == AV_ID3V2_UTF16 || textEncodingType == AV_ID3V2_UTF16_BE)
3251 while((NEWLINE_OF_UTF16(pExtContent + tmp) || NEWLINE_OF_UTF16_R(pExtContent + tmp))&& realCpyFrameNum > 4)
3253 realCpyFrameNum -= 4;
3257 if((IS_ENCODEDBY_UTF16(pExtContent+tmp) || IS_ENCODEDBY_UTF16_R(pExtContent+tmp)) && realCpyFrameNum > 2)
3259 realCpyFrameNum -= 2;
3261 textEncodingType = AV_ID3V2_UTF16;
3265 #ifdef __MMFILE_TEST_MODE__
3266 debug_msg ( "pInfo->pComment Never Get Here!!\n");
3270 else if(textEncodingType == AV_ID3V2_UTF8)
3272 while(pExtContent[tmp] < 0x20 && (tmp < realCpyFrameNum)) // text string encoded by ISO-8859-1
3277 textEncodingType = AV_ID3V2_UTF8;
3281 while(pExtContent[tmp] < 0x20 && (tmp < realCpyFrameNum)) // text string encoded by ISO-8859-1
3286 textEncodingType = AV_ID3V2_ISO_8859;
3289 #ifdef __MMFILE_TEST_MODE__
3290 debug_msg ( "tmp(%d) textEncodingType(%d), realCpyFrameNum(%d)\n", tmp, textEncodingType, realCpyFrameNum);
3293 if(textEncodingType == AV_ID3V2_UTF16)
3295 pInfo->pComment = mmfile_string_convert ((const char*)&pExtContent[tmp], realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->commentLen);
3297 else if(textEncodingType == AV_ID3V2_UTF16_BE)
3299 debug_warning ("not implemented\n");
3301 else if(textEncodingType == AV_ID3V2_UTF8)
3303 pInfo->pComment= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3304 memset(pInfo->pComment, 0, (realCpyFrameNum+2));
3305 memcpy(pInfo->pComment, pExtContent+tmp, realCpyFrameNum);
3306 pInfo->pComment[realCpyFrameNum] = '\0';
3307 /*string copy with '\0'*/
3308 pInfo->commentLen = realCpyFrameNum;
3309 _STRNCPY_EX (pInfo->pComment, pExtContent, pInfo->commentLen);
3313 pInfo->pComment = mmfile_string_convert ((const char*)&pExtContent[tmp], realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->commentLen);
3318 #ifdef __MMFILE_TEST_MODE__
3319 debug_msg ( "Description info too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum);
3325 #ifdef __MMFILE_TEST_MODE__
3326 debug_msg ( "pInfo->pComment returned = (%s), pInfo->commentLen(%d)\n", pInfo->pComment, pInfo->commentLen);
3328 pInfo->tagV2Info.bDescriptionMarked = true;
3330 else if(strncmp((char *)CompTmp, "SYLT", 4) == 0 && pInfo->tagV2Info.bSyncLyricsMarked == false)
3334 int copy_start_pos = tmp;
3335 AvSynclyricsInfo *synclyrics_info = NULL;
3336 GList *synclyrics_info_list = NULL;
3338 if(realCpyFrameNum > 5)
3340 realCpyFrameNum -= 5;
3343 if(textEncodingType == AV_ID3V2_UTF16 || textEncodingType == AV_ID3V2_UTF16_BE)
3345 while((NEWLINE_OF_UTF16(pExtContent + tmp) || NEWLINE_OF_UTF16_R(pExtContent + tmp))&& realCpyFrameNum > 4)
3347 realCpyFrameNum -= 4;
3351 if((IS_ENCODEDBY_UTF16(pExtContent+tmp) || IS_ENCODEDBY_UTF16_R(pExtContent+tmp)) && realCpyFrameNum > 2)
3353 realCpyFrameNum -= 2;
3355 textEncodingType = AV_ID3V2_UTF16;
3359 #ifdef __MMFILE_TEST_MODE__
3360 debug_msg ( "pInfo->pSyncLyrics Never Get Here!!\n");
3364 else if(textEncodingType == AV_ID3V2_UTF8)
3366 while(pExtContent[tmp] < 0x20 && (tmp < realCpyFrameNum)) // text string encoded by ISO-8859-1
3371 textEncodingType = AV_ID3V2_UTF8;
3375 while(pExtContent[tmp] < 0x20 && (tmp < realCpyFrameNum)) // text string encoded by ISO-8859-1
3380 textEncodingType = AV_ID3V2_ISO_8859;
3383 #ifdef __MMFILE_TEST_MODE__
3384 debug_msg ( "tmp(%d) textEncodingType(%d), realCpyFrameNum(%d)\n", tmp, textEncodingType, realCpyFrameNum);
3387 if(realCpyFrameNum < MMFILE_SYNC_LYRIC_INFO_MIN_LEN)
3389 #ifdef __MMFILE_TEST_MODE__
3390 debug_msg ( "failed to get Synchronised lyrics Info realCpyFramNum(%d)\n", realCpyFrameNum);
3392 pInfo->syncLyricsNum = 0;
3396 if(textEncodingType == AV_ID3V2_UTF16)
3398 debug_warning ("[AV_ID3V2_UTF16] not implemented\n");
3400 else if(textEncodingType == AV_ID3V2_UTF16_BE)
3402 debug_warning ("[AV_ID3V2_UTF16_BE] not implemented\n");
3406 for(idx = 0; idx < realCpyFrameNum; idx++)
3408 if(pExtContent[tmp+idx] == 0x00)
3410 synclyrics_info = (AvSynclyricsInfo *)malloc(sizeof(AvSynclyricsInfo));
3412 if(textEncodingType == AV_ID3V2_UTF8) {
3413 synclyrics_info->lyric_info= mmfile_malloc(copy_len+1);
3414 memset(synclyrics_info->lyric_info, 0, copy_len+1);
3415 memcpy(synclyrics_info->lyric_info, pExtContent+copy_start_pos, copy_len);
3416 synclyrics_info->lyric_info[copy_len+1] = '\0';
3419 synclyrics_info->lyric_info = mmfile_string_convert ((const char*)&pExtContent[copy_start_pos], copy_len, "UTF-8", locale, NULL, NULL);
3422 synclyrics_info->time_info= (unsigned long)pExtContent[tmp+idx+1] << 24 | (unsigned long)pExtContent[tmp+idx+2] << 16 | (unsigned long)pExtContent[tmp+idx+3] << 8 | (unsigned long)pExtContent[tmp+idx+4];
3424 copy_start_pos = tmp + idx + 1;
3425 #ifdef __MMFILE_TEST_MODE__
3426 debug_msg("[%d][%s] idx[%d], copy_len[%d] copy_start_pos[%d]", synclyrics_info->time_info, synclyrics_info->lyric_info, idx, copy_len, copy_start_pos);
3429 synclyrics_info_list = g_list_append(synclyrics_info_list, synclyrics_info);
3433 pInfo->pSyncLyrics = synclyrics_info_list;
3434 pInfo->syncLyricsNum = g_list_length(pInfo->pSyncLyrics);
3440 #ifdef __MMFILE_TEST_MODE__
3441 debug_msg ( "SyncLyrics info too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum);
3446 pInfo->tagV2Info.bSyncLyricsMarked = true;
3448 else if(strncmp((char *)CompTmp, "USLT", 4) == 0 && pInfo->tagV2Info.bUnsyncLyricsMarked == false)
3450 if(realCpyFrameNum > 3)
3452 realCpyFrameNum -= 3;
3455 if(textEncodingType == AV_ID3V2_UTF16 || textEncodingType == AV_ID3V2_UTF16_BE)
3457 while((NEWLINE_OF_UTF16(pExtContent + tmp) || NEWLINE_OF_UTF16_R(pExtContent + tmp))&& realCpyFrameNum > 4)
3459 realCpyFrameNum -= 4;
3463 if((IS_ENCODEDBY_UTF16(pExtContent+tmp) || IS_ENCODEDBY_UTF16_R(pExtContent+tmp)) && realCpyFrameNum > 2)
3465 realCpyFrameNum -= 2;
3467 textEncodingType = AV_ID3V2_UTF16;
3471 #ifdef __MMFILE_TEST_MODE__
3472 debug_msg ( "pInfo->pUnsyncLyrics Never Get Here!!\n");
3476 else if(textEncodingType == AV_ID3V2_UTF8)
3478 while(pExtContent[tmp] < 0x20 && (tmp < realCpyFrameNum)) // text string encoded by ISO-8859-1
3483 textEncodingType = AV_ID3V2_UTF8;
3487 while(pExtContent[tmp] < 0x20 && (tmp < realCpyFrameNum)) // text string encoded by ISO-8859-1
3492 textEncodingType = AV_ID3V2_ISO_8859;
3495 #ifdef __MMFILE_TEST_MODE__
3496 debug_msg ( "tmp(%d) textEncodingType(%d), realCpyFrameNum(%d)\n", tmp, textEncodingType, realCpyFrameNum);
3499 if(textEncodingType == AV_ID3V2_UTF16)
3501 pInfo->pUnsyncLyrics = mmfile_string_convert ((const char*)&pExtContent[tmp], realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->unsynclyricsLen);
3503 else if(textEncodingType == AV_ID3V2_UTF16_BE)
3505 debug_warning ("not implemented\n");
3507 else if(textEncodingType == AV_ID3V2_UTF8)
3509 pInfo->pUnsyncLyrics= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3510 memset(pInfo->pUnsyncLyrics, 0, (realCpyFrameNum+2));
3511 memcpy(pInfo->pUnsyncLyrics, pExtContent+tmp, realCpyFrameNum);
3512 pInfo->pUnsyncLyrics[realCpyFrameNum] = '\0';
3513 /*string copy with '\0'*/
3514 pInfo->unsynclyricsLen = realCpyFrameNum;
3515 _STRNCPY_EX (pInfo->pUnsyncLyrics, pExtContent, pInfo->unsynclyricsLen);
3519 pInfo->pUnsyncLyrics = mmfile_string_convert ((const char*)&pExtContent[tmp], realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->unsynclyricsLen);
3524 #ifdef __MMFILE_TEST_MODE__
3525 debug_msg ( "Description info too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum);
3531 #ifdef __MMFILE_TEST_MODE__
3532 debug_msg ( "pInfo->pUnsyncLyrics returned = (%s), pInfo->unsynclyricsLen(%d)\n", pInfo->pUnsyncLyrics, pInfo->unsynclyricsLen);
3534 pInfo->tagV2Info.bDescriptionMarked = true;
3536 else if(strncmp((char *)CompTmp, "TCON", 4) == 0 && pInfo->tagV2Info.bGenreMarked == false)
3538 if(textEncodingType == AV_ID3V2_UTF16)
3540 pInfo->pGenre = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->genreLen);
3542 else if(textEncodingType == AV_ID3V2_UTF16_BE)
3544 debug_warning ("not implemented\n");
3546 else if(textEncodingType == AV_ID3V2_UTF8)
3548 pInfo->pGenre= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3549 memcpy(pInfo->pGenre, pExtContent, realCpyFrameNum);
3550 pInfo->pGenre[realCpyFrameNum] = '\0';
3551 /*string copy with '\0'*/
3552 pInfo->genreLen = realCpyFrameNum;
3553 _STRNCPY_EX (pInfo->pGenre, pExtContent, pInfo->genreLen);
3557 pInfo->pGenre = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->genreLen);
3560 #ifdef __MMFILE_TEST_MODE__
3561 debug_msg ( "pInfo->pGenre returned = (%s), pInfo->genreLen(%d)\n", pInfo->pGenre, pInfo->genreLen);
3564 if((pInfo->pGenre != NULL) && (pInfo->genreLen > 0)) {
3568 ret = sscanf( pInfo->pGenre, "%d", &int_genre);
3571 #ifdef __MMFILE_TEST_MODE__
3572 debug_msg("genre information is inteager [%d]\n", int_genre);
3575 //Change int to string
3576 if((0 <= int_genre) && (int_genre < GENRE_COUNT-1)) {
3577 /*save genreinfo like "(123)". mm_file_id3tag_restore_content_info convert it to string*/
3578 char tmp_genre[6] = {0,}; /*ex. "(123)+NULL"*/
3579 int tmp_genre_len = 0;
3581 memset (tmp_genre, 0, 6);
3582 snprintf(tmp_genre, sizeof(tmp_genre), "(%d)", int_genre);
3584 tmp_genre_len = strlen(tmp_genre);
3585 if(tmp_genre_len > 0) {
3586 if(pInfo->pGenre) _FREE_EX(pInfo->pGenre);
3587 pInfo->pGenre = mmfile_malloc (sizeof(char) * (tmp_genre_len + 1) );
3590 strncpy(pInfo->pGenre, tmp_genre, tmp_genre_len);
3591 pInfo->pGenre[tmp_genre_len] = 0;
3598 pInfo->tagV2Info.bGenreMarked = true;
3600 else if(strncmp((char *)CompTmp, "TRCK", 4) == 0 && pInfo->tagV2Info.bTrackNumMarked == false)
3602 if(textEncodingType == AV_ID3V2_UTF16)
3604 pInfo->pTrackNum = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->tracknumLen);
3606 else if(textEncodingType == AV_ID3V2_UTF16_BE)
3608 debug_warning ("not implemented\n");
3610 else if(textEncodingType == AV_ID3V2_UTF8)
3612 pInfo->pTrackNum= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3613 memcpy(pInfo->pTrackNum, pExtContent, realCpyFrameNum);
3614 pInfo->pTrackNum[realCpyFrameNum] = '\0';
3615 /*string copy with '\0'*/
3616 pInfo->tracknumLen = realCpyFrameNum;
3617 _STRNCPY_EX (pInfo->pTrackNum, pExtContent, pInfo->tracknumLen);
3621 pInfo->pTrackNum = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->tracknumLen);
3625 #ifdef __MMFILE_TEST_MODE__
3626 debug_msg ( "pInfo->pTrackNum returned = (%s), pInfo->tracknumLen(%d)\n", pInfo->pTrackNum, pInfo->tracknumLen);
3628 pInfo->tagV2Info.bTrackNumMarked = true;
3630 else if(strncmp((char *)CompTmp, "TENC", 4) == 0 && pInfo->tagV2Info.bEncByMarked == false)
3632 if(textEncodingType == AV_ID3V2_UTF16)
3634 pInfo->pEncBy = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->encbyLen);
3636 else if(textEncodingType == AV_ID3V2_UTF16_BE)
3638 debug_warning ("not implemented\n");
3640 else if(textEncodingType == AV_ID3V2_UTF8)
3642 pInfo->pEncBy= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3643 memcpy(pInfo->pEncBy, pExtContent, realCpyFrameNum);
3644 pInfo->pEncBy[realCpyFrameNum] = '\0';
3645 /*string copy with '\0'*/
3646 pInfo->encbyLen = realCpyFrameNum;
3647 _STRNCPY_EX (pInfo->pEncBy, pExtContent, pInfo->encbyLen);
3651 pInfo->pEncBy = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->encbyLen);
3654 #ifdef __MMFILE_TEST_MODE__
3655 debug_msg ( "pInfo->pEncBy returned = (%s), pInfo->encbyLen(%d)\n", pInfo->pEncBy, pInfo->encbyLen);
3657 pInfo->tagV2Info.bEncByMarked = true;
3659 else if(strncmp((char *)CompTmp, "WXXX", 4) == 0 && pInfo->tagV2Info.bURLMarked == false)
3661 if(textEncodingType == AV_ID3V2_UTF16)
3663 pInfo->pURL = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->urlLen);
3665 else if (textEncodingType == AV_ID3V2_UTF16_BE)
3667 debug_warning ("not implemented\n");
3669 else if(textEncodingType == AV_ID3V2_UTF8)
3671 pInfo->pURL= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3672 memcpy(pInfo->pURL, pExtContent, realCpyFrameNum);
3673 pInfo->pURL[realCpyFrameNum] = '\0';
3674 /*string copy with '\0'*/
3675 pInfo->urlLen = realCpyFrameNum;
3676 _STRNCPY_EX (pInfo->pURL, pExtContent, pInfo->urlLen);
3680 pInfo->pURL = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->urlLen);
3683 #ifdef __MMFILE_TEST_MODE__
3684 debug_msg ( "pInfo->pURL returned = (%s), pInfo->urlLen(%d)\n", pInfo->pURL, pInfo->urlLen);
3686 pInfo->tagV2Info.bURLMarked = true;
3688 else if(strncmp((char *)CompTmp, "TCOP", 4) == 0 && pInfo->tagV2Info.bCopyRightMarked == false)
3690 if(textEncodingType == AV_ID3V2_UTF16)
3692 pInfo->pCopyright = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->copyrightLen);
3694 else if (textEncodingType == AV_ID3V2_UTF16_BE)
3696 debug_warning ("not implemented\n");
3698 else if(textEncodingType == AV_ID3V2_UTF8)
3700 pInfo->pCopyright= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3701 memcpy(pInfo->pCopyright, pExtContent, realCpyFrameNum);
3702 pInfo->pCopyright[realCpyFrameNum] = '\0';
3703 /*string copy with '\0'*/
3704 pInfo->copyrightLen = realCpyFrameNum;
3705 _STRNCPY_EX (pInfo->pCopyright, pExtContent, pInfo->copyrightLen);
3709 pInfo->pCopyright = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->copyrightLen);
3712 #ifdef __MMFILE_TEST_MODE__
3713 debug_msg ( "pInfo->pCopyright returned = (%s), pInfo->copyrightLen(%d)\n", pInfo->pCopyright, pInfo->copyrightLen);
3715 pInfo->tagV2Info.bCopyRightMarked = true;
3717 else if(strncmp((char *)CompTmp, "TOPE", 4) == 0 && pInfo->tagV2Info.bOriginArtistMarked == false)
3719 if(textEncodingType == AV_ID3V2_UTF16)
3721 pInfo->pOriginArtist = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->originartistLen);
3723 else if(textEncodingType == AV_ID3V2_UTF16_BE)
3725 debug_warning ("not implemented\n");
3727 else if(textEncodingType == AV_ID3V2_UTF8)
3729 pInfo->pOriginArtist= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3730 memcpy(pInfo->pOriginArtist, pExtContent, realCpyFrameNum);
3731 pInfo->pOriginArtist[realCpyFrameNum] = '\0';
3732 /*string copy with '\0'*/
3733 pInfo->originartistLen = realCpyFrameNum;
3734 _STRNCPY_EX (pInfo->pOriginArtist, pExtContent, pInfo->originartistLen);
3738 pInfo->pOriginArtist = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->originartistLen);
3741 #ifdef __MMFILE_TEST_MODE__
3742 debug_msg ( "pInfo->pOriginArtist returned = (%s), pInfo->originartistLen(%d)\n", pInfo->pOriginArtist, pInfo->originartistLen);
3744 pInfo->tagV2Info.bOriginArtistMarked = true;
3746 else if(strncmp((char *)CompTmp, "TCOM", 4) == 0 && pInfo->tagV2Info.bComposerMarked == false)
3748 if(textEncodingType == AV_ID3V2_UTF16)
3750 pInfo->pComposer = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->composerLen);
3752 else if (textEncodingType == AV_ID3V2_UTF16_BE)
3754 debug_warning ("not implemented\n");
3756 else if(textEncodingType == AV_ID3V2_UTF8)
3758 pInfo->pComposer= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3759 memcpy(pInfo->pComposer, pExtContent, realCpyFrameNum);
3760 pInfo->pComposer[realCpyFrameNum] = '\0';
3761 /*string copy with '\0'*/
3762 pInfo->composerLen = realCpyFrameNum;
3763 _STRNCPY_EX (pInfo->pComposer, pExtContent, pInfo->composerLen);
3767 pInfo->pComposer = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->composerLen);
3770 #ifdef __MMFILE_TEST_MODE__
3771 debug_msg ( "pInfo->pComposer returned = (%s), pInfo->originartistLen(%d)\n", pInfo->pComposer, pInfo->composerLen);
3773 pInfo->tagV2Info.bComposerMarked = true;
3775 else if(strncmp((char *)CompTmp, "TDRC", 4) == 0 && pInfo->tagV2Info.bRecDateMarked== false) //TYER(year) and TRDA are replaced by the TDRC
3777 if(textEncodingType == AV_ID3V2_UTF16)
3779 pInfo->pRecDate = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->recdateLen);
3781 else if(textEncodingType == AV_ID3V2_UTF16_BE)
3783 debug_warning ("not implemented\n");
3785 else if(textEncodingType == AV_ID3V2_UTF8)
3787 pInfo->pRecDate= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3788 memcpy(pInfo->pRecDate, pExtContent, realCpyFrameNum);
3789 pInfo->pRecDate[realCpyFrameNum] = '\0';
3790 /*string copy with '\0'*/
3791 pInfo->recdateLen = realCpyFrameNum;
3792 _STRNCPY_EX (pInfo->pRecDate, pExtContent, pInfo->recdateLen);
3796 pInfo->pRecDate = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->recdateLen);
3799 #ifdef __MMFILE_TEST_MODE__
3800 debug_msg ( "pInfo->pRecDate returned = (%s), pInfo->recdateLen(%d)\n", pInfo->pRecDate, pInfo->recdateLen);
3802 pInfo->tagV2Info.bRecDateMarked = true;
3804 else if(strncmp((char *)CompTmp, "TIT1", 4) == 0 && pInfo->tagV2Info.bContentGroupMarked== false)
3806 if(textEncodingType == AV_ID3V2_UTF16)
3808 pInfo->pContentGroup = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", "UCS2", NULL, (unsigned int*)&pInfo->contentGroupLen);
3810 else if(textEncodingType == AV_ID3V2_UTF16_BE)
3812 debug_warning ("not implemented\n");
3814 else if(textEncodingType == AV_ID3V2_UTF8)
3816 pInfo->pContentGroup= mmfile_malloc (realCpyFrameNum+2);//Ignore NULL char for UTF16
3817 memcpy(pInfo->pContentGroup, pExtContent, realCpyFrameNum);
3818 pInfo->pContentGroup[realCpyFrameNum] = '\0';
3819 /*string copy with '\0'*/
3820 pInfo->contentGroupLen = realCpyFrameNum;
3821 _STRNCPY_EX (pInfo->pContentGroup, pExtContent, pInfo->contentGroupLen);
3825 pInfo->pContentGroup = mmfile_string_convert ((const char*)pExtContent, realCpyFrameNum, "UTF-8", locale, NULL, (unsigned int*)&pInfo->contentGroupLen);
3827 #ifdef __MMFILE_TEST_MODE__
3828 debug_msg ( "pInfo->pContentGroup returned = (%s), pInfo->contentGroupLen(%d)\n", pInfo->pContentGroup, pInfo->contentGroupLen);
3830 pInfo->tagV2Info.bContentGroupMarked = true;
3832 else if(strncmp((char *)CompTmp, "APIC", 4) == 0 && pInfo->tagV2Info.bImageMarked == false && realCpyFrameNum <= 2000000)
3834 if(textEncodingType == AV_ID3V2_UTF16 || textEncodingType == AV_ID3V2_UTF16_BE || textEncodingType == AV_ID3V2_UTF8)
3836 #ifdef __MMFILE_TEST_MODE__
3837 debug_msg ( "mmf_file_id3tag_parse_v224: this is abnormal case!!\n");
3842 if(pExtContent[0] != '\0')
3844 for(inx = 0; inx < MP3_ID3_IMAGE_MIME_TYPE_MAX_LENGTH-1; inx++)
3845 pInfo->imageInfo.imageMIMEType[inx] = '\0';//ini mimetype variable
3847 while((checkImgMimeTypeMax < MP3_ID3_IMAGE_MIME_TYPE_MAX_LENGTH-1) && pExtContent[checkImgMimeTypeMax] != '\0')
3849 pInfo->imageInfo.imageMIMEType[checkImgMimeTypeMax] = pExtContent[checkImgMimeTypeMax];
3850 checkImgMimeTypeMax++;
3852 pInfo->imageInfo.imgMimetypeLen = checkImgMimeTypeMax;
3856 pInfo->imageInfo.imgMimetypeLen = 0;
3859 imgstartOffset += checkImgMimeTypeMax;
3861 if((pExtContent[imgstartOffset] == '\0') && (realCpyFrameNum - imgstartOffset > 0))
3863 imgstartOffset++;//endofMIME(1byte)
3865 if(pExtContent[imgstartOffset] < AV_ID3V2_PICTURE_TYPE_MAX)
3867 pInfo->imageInfo.pictureType = pExtContent[imgstartOffset];
3869 imgstartOffset++;//PictureType(1byte)
3871 if(pExtContent[imgstartOffset] != 0x0)
3873 for(inx = 0; inx < MP3_ID3_IMAGE_DESCRIPTION_MAX_LENGTH-1; inx++)
3874 pInfo->imageInfo.imageDescription[inx] = '\0';//ini imgdescripiton variable
3876 while((checkImgDescriptionMax < MP3_ID3_IMAGE_DESCRIPTION_MAX_LENGTH-1) && pExtContent[imgstartOffset+checkImgDescriptionMax] != '\0')
3878 pInfo->imageInfo.imageDescription[checkImgDescriptionMax] = pExtContent[imgstartOffset+checkImgDescriptionMax];
3879 checkImgDescriptionMax++;
3881 pInfo->imageInfo.imgDesLen= checkImgDescriptionMax;
3885 pInfo->imageInfo.imgDesLen= 0;
3888 imgstartOffset += checkImgDescriptionMax;
3889 if((pExtContent[imgstartOffset] == '\0') && (realCpyFrameNum - imgstartOffset > 0))
3891 imgstartOffset ++; // endofDesceriptionType(1byte)
3893 while(pExtContent[imgstartOffset] == '\0') //some content has useless '\0' in front of picture data
3898 #ifdef __MMFILE_TEST_MODE__
3899 debug_msg ( "after scaning imgDescription imgstartOffset(%d) value!\n", imgstartOffset);
3902 if(realCpyFrameNum - imgstartOffset > 0)
3904 pInfo->imageInfo.imageLen = realCpyFrameNum - imgstartOffset;
3905 pInfo->imageInfo.pImageBuf= mmfile_malloc (pInfo->imageInfo.imageLen+1);
3906 memcpy(pInfo->imageInfo.pImageBuf, pExtContent+ imgstartOffset, pInfo->imageInfo.imageLen);
3907 pInfo->imageInfo.pImageBuf[pInfo->imageInfo.imageLen] = 0;
3908 if(IS_INCLUDE_URL(pInfo->imageInfo.imageMIMEType))
3909 pInfo->imageInfo.bURLInfo = true; //if mimetype is "-->", image date has an URL
3913 #ifdef __MMFILE_TEST_MODE__
3914 debug_msg ( "No APIC image!! realCpyFrameNum(%d) - imgstartOffset(%d)\n", realCpyFrameNum, imgstartOffset);
3921 checkImgMimeTypeMax = 0;
3922 checkImgDescriptionMax = 0;
3925 pInfo->tagV2Info.bImageMarked= true;
3929 #ifdef __MMFILE_TEST_MODE__
3930 debug_msg ( "CompTmp(%s) This Frame ID currently not Supports!!\n", CompTmp);
3938 #ifdef __MMFILE_TEST_MODE__
3939 debug_msg ( "mmf_file_id3tag_parse_v224: All of the pExtContent Values are NULL\n");
3946 curPos += purelyFramelen;
3947 if(purelyFramelen != 0)
3948 needToloopv2taglen = MP3_TAGv2_23_TXT_HEADER_LEN;
3951 if(pExtContent) _FREE_EX(pExtContent);
3952 if(tmpConvert2Pcode) _FREE_EX(tmpConvert2Pcode);
3953 memset(CompTmp, 0, 4);
3956 needToloopv2taglen -= oneFrameLen;
3960 needToloopv2taglen = MP3_TAGv2_23_TXT_HEADER_LEN;
3964 realCpyFrameNum = 0;
3965 textEncodingType = 0;
3979 void mm_file_id3tag_restore_content_info(AvFileContentInfo* pInfo)
3981 char *mpegAudioGenre=NULL, *tmpGenreForV1Tag = NULL;
3982 bool bAdditionGenre= false /*, bMpegAudioFrame = false*/;
3983 int mpegAudioFileLen=0, idv2IntGenre=148, tmpinx=0/*, tmpinx2=0*/;
3984 char *pGenreForUTF16;
3987 if(pInfo->tagV2Info.bGenreMarked == false)
3989 if(pInfo->bV1tagFound == true)
3991 #ifdef __MMFILE_TEST_MODE__
3992 debug_msg ( "Genre: %d\n", pInfo->genre);
3994 if(pInfo->genre > 147)
3996 mpegAudioGenre = MpegAudio_Genre[148];
4000 mpegAudioGenre = MpegAudio_Genre[pInfo->genre];
4003 if(mpegAudioGenre!=NULL)
4005 pInfo->genreLen = strlen(mpegAudioGenre);
4006 if (pInfo->genreLen > 0)
4008 // Give space for NULL character. Hence added "+1"
4009 pInfo->pGenre = mmfile_malloc (sizeof(char) * (pInfo->genreLen + 1) );
4012 strncpy(pInfo->pGenre, mpegAudioGenre, pInfo->genreLen);
4013 pInfo->pGenre[pInfo->genreLen] = '\0';
4020 #ifdef __MMFILE_TEST_MODE__
4021 debug_msg ( "Genre was not Found.\n");
4025 else if(pInfo->tagV2Info.bGenreMarked == true)
4027 if(pInfo->genreLen && pInfo->tagV2Info.bGenreUTF16)
4029 pInfo->pGenre[pInfo->genreLen+1] = '\0';
4030 mpegAudioGenre = mmfile_malloc (sizeof(char) * (pInfo->genreLen*AV_WM_LOCALCODE_SIZE_MAX + 1) );
4031 pGenreForUTF16 = (char *)pInfo->pGenre;
4033 if(WmConvert2LCode(mpegAudioGenre, sizeof ( char ) * AV_WM_LOCALCODE_SIZE_MAX * ( pInfo->genreLen + 1 ), pGenreForUTF16))
4035 pInfo->genreLen = strlen(mpegAudioGenre);
4036 mpegAudioGenre[pInfo->genreLen] = '\0';
4042 #ifdef __MMFILE_TEST_MODE__
4043 debug_msg ( "pInfo->genreLen size is Zero Or not UTF16 code! genreLen[%d] genre[%s]\n",pInfo->genreLen,pInfo->pGenre);
4045 if (pInfo->pGenre) {
4046 pInfo->genreLen = strlen(pInfo->pGenre);
4047 mpegAudioGenre = mmfile_malloc (sizeof(char) * (pInfo->genreLen + 1) );
4048 mpegAudioGenre[pInfo->genreLen] = '\0';
4049 strncpy(mpegAudioGenre, pInfo->pGenre, pInfo->genreLen);
4051 pInfo->genreLen = 0;
4055 if(pInfo->pGenre) _FREE_EX(pInfo->pGenre);
4058 if(mpegAudioGenre!=NULL)
4062 * (XXX) XXX is 0 - 148
4064 pInfo->genreLen = strlen (mpegAudioGenre);
4065 if (pInfo->genreLen >= 3 &&
4066 mpegAudioGenre[0] == '(' && mpegAudioGenre[pInfo->genreLen - 1] == ')') {
4067 bAdditionGenre = true;
4068 for (mpegAudioFileLen = 1; mpegAudioFileLen <= pInfo->genreLen - 2; mpegAudioFileLen++) {
4069 if(mpegAudioGenre[mpegAudioFileLen] < '0' || mpegAudioGenre[mpegAudioFileLen] > '9') {
4070 bAdditionGenre = false;
4076 if(bAdditionGenre == true)
4078 idv2IntGenre = atoi(mpegAudioGenre+1);
4079 if(idv2IntGenre > 147 || idv2IntGenre < 0)
4081 tmpGenreForV1Tag = MpegAudio_Genre[148];
4085 tmpGenreForV1Tag = MpegAudio_Genre[idv2IntGenre];
4087 if(tmpGenreForV1Tag!=NULL)
4089 pInfo->genreLen = strlen(tmpGenreForV1Tag);
4090 if (pInfo->genreLen > 0)
4092 // Give space for NULL character. Hence added "+1"
4093 pInfo->pGenre = mmfile_malloc (sizeof(char) * (pInfo->genreLen + 1) );
4096 strncpy(pInfo->pGenre, tmpGenreForV1Tag, pInfo->genreLen);
4097 pInfo->pGenre[pInfo->genreLen] = 0;
4101 #ifdef __MMFILE_TEST_MODE__
4102 debug_msg ( "pInfo->pGenre = %s\n", pInfo->pGenre);
4105 else if (bAdditionGenre == false && pInfo->genreLen > 0)
4111 // Give space for NULL character. Hence added "+1"
4112 pInfo->pGenre = mmfile_malloc (sizeof(char) * (pInfo->genreLen + 1) );
4115 strncpy(pInfo->pGenre, mpegAudioGenre, pInfo->genreLen);
4116 pInfo->pGenre[pInfo->genreLen] = '\0';
4118 #ifdef __MMFILE_TEST_MODE__
4119 debug_msg ( "pInfo->pGenre = %s, pInfo->genreLen = %d\n", pInfo->pGenre, pInfo->genreLen);
4124 #ifdef __MMFILE_TEST_MODE__
4125 debug_msg ( "Failed to \"(...)\" value to genre = %s\n", pInfo->pGenre);
4131 #ifdef __MMFILE_TEST_MODE__
4132 debug_msg ( "mpegAudioGenre = %x\n", mpegAudioGenre);
4136 _FREE_EX(mpegAudioGenre);
4141 #ifdef __MMFILE_TEST_MODE__
4142 debug_msg ( "Neither ID3 v1 nor v2 info doesn't have Genre Info.\n");
4148 void mm_file_free_synclyrics_list(GList * synclyrics_list)
4152 AvSynclyricsInfo *synclyrics_info = NULL;
4154 if (synclyrics_list == NULL) {
4158 list_len = g_list_length(synclyrics_list);
4159 for (idx = 0; idx < list_len; idx++) {
4160 synclyrics_info = g_list_nth_data(synclyrics_list, idx);
4162 free(synclyrics_info->lyric_info);
4163 synclyrics_info->lyric_info = NULL;
4165 free(synclyrics_info);
4166 synclyrics_info = NULL;
4169 if (synclyrics_list != NULL) {
4170 g_list_free(synclyrics_list);
4171 synclyrics_list = NULL;