Fix coverity issue (INTEGER_OVERFLOW)
[platform/core/multimedia/libmm-fileinfo.git] / utils / mm_file_util_tag.c
old mode 100755 (executable)
new mode 100644 (file)
index 4e52dd1..42844c6
 #include <ctype.h>
 #include <vconf.h>
 #include <glib.h>
+#include <stdint.h>
 
+#include "mm_file.h"
 #include "mm_file_debug.h"
 #include "mm_file_utils.h"
 
 #define ENABLE_ITUNES_META             /*All itunes metadata extracted by ffmpeg. see mov_read_udta_string() but Some cover art not support. */
+#define INVALID_UINT_VALUE     0xFFFFFFFF
+#define INVALID_UINT8_VALUE    0xFF
+
+#define ID3TAG_V110_TRACK_NUM_DIGIT    5
 
 typedef struct _mmfilemp4basicboxheader {
        unsigned int size;
@@ -127,6 +133,70 @@ typedef struct _mmfilesmtabox {
        unsigned int value;
 } MMFILE_M4A_SMTA_TAGBOX;
 
+typedef struct _mmfilesa3dbox {
+       uint8_t version;
+       uint8_t ambisonic_type;
+       uint32_t ambisonic_order;
+       uint8_t ambisonic_channel_ordering;
+       uint8_t ambisonic_normalization;
+       uint32_t num_channels;
+       uint32_t channel_map[49]; /* Up to 6th order */
+} __attribute__((aligned(1), packed)) MMFILE_MP4A_SA3D_TAGBOX;
+
+typedef struct _mmfile_proj_v2_box {
+       uint16_t proj_box_id;
+       uint8_t proj_box_size;
+       uint16_t proj_type_box_id;
+       uint8_t proj_type_box_size;
+       uint8_t proj_type_box_value; /* only equi (=1) or cubemap (=2) currently */
+       uint16_t proj_priv_box_id;
+       uint8_t proj_priv_box_size;
+} __attribute__((aligned(1), packed)) MMFILE_WEBM_PROJ_V2_BOX;
+
+typedef struct _mmfile_equi_proj_v2_box {
+       unsigned char proj_priv_box_name[4]; /* "equi" */
+       uint32_t equi_projection_bounds_top;
+       uint32_t equi_projection_bounds_bottom;
+       uint32_t equi_projection_bounds_left;
+       uint32_t equi_projection_bounds_right;
+} __attribute__((aligned(1), packed)) MMFILE_WEBM_EQUI_PROJ_V2_BOX;
+
+typedef struct _mmfile_cbmp_proj_v2_box {
+       unsigned char proj_priv_box_name[4]; /* "cbmp" */
+       uint32_t cbmp_projection_layout;
+       uint32_t cbmp_projection_padding;
+} __attribute__((aligned(1), packed)) MMFILE_WEBM_CBMP_PROJ_V2_BOX;
+
+typedef struct _mmfile_pose_element_v2_box {
+       uint16_t pose_yaw_element_id;
+       uint8_t pose_yaw_element_size;
+       float pose_yaw_element_value;
+       uint16_t pose_pitch_element_id;
+       uint8_t pose_pitch_element_size;
+       float  pose_pitch_element_value;
+       uint16_t pose_roll_element_id;
+       uint8_t pose_roll_element_size;
+       float  pose_roll_element_value;
+} __attribute__((aligned(1), packed)) MMFILE_WEBM_POSE_ELEMENT_V2_BOX;
+
+
+typedef enum {
+       PROJECTION_TYPE_RECT = 0, /* Rectangular, Google's RFC value */
+       PROJECTION_TYPE_EQUI = 1, /* Equirectangular, Google's RFC value */
+       PROJECTION_TYPE_CBMP = 2, /* Cubemap, Google's RFC value */
+       PROJECTION_TYPE_MESH = 3, /* Mesh, Google's RFC value, unsupported */
+       PROJECTION_TYPE_UNKNOWN = INVALID_UINT_VALUE,
+} SPHERICAL_VIDEO2_PROJECTION_TYPE;
+
+enum spherical_video_metadata_elements_ids_le {
+       PROJ_BOX_ID           = 0x7076,
+       PROJ_TYPE_BOX_ID      = 0x7176,
+       PROJ_PRIV_BOX_ID      = 0x7276,
+       POSE_YAW_ELEMENT_ID   = 0x7376,
+       POSE_PITCH_ELEMENT_ID = 0x7476,
+       POSE_ROLL_ELEMENT_ID  = 0x7576
+};
+
 #define MMFILE_MP4_BASIC_BOX_HEADER_LEN 8
 #define MMFILE_MP4_MOVIE_HEADER_BOX_LEN 96
 #define MMFILE_MP4_HDLR_BOX_LEN         24
@@ -145,11 +215,9 @@ typedef struct _mmfilesmtabox {
 
 #define FOURCC(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24))
 
-/*#define      MIN(a, b) (((a) < (b)) ? (a):(b))*/
-
 #define GENRE_COUNT    149
 
-static const char *MpegAudio_Genre[GENRE_COUNT] = {"Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz", "Metal",
+static const char * const MpegAudio_Genre[GENRE_COUNT] = {"Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz", "Metal",
                                                                                                "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno", "Industrial",
                                                                                                "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk",
                                                                                                "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise",
@@ -169,6 +237,53 @@ static const char *MpegAudio_Genre[GENRE_COUNT] = {"Blues", "Classic Rock", "Cou
 static unsigned char gTagJPEGHeader[] = {0xff, 0xd8, 0xff };
 static unsigned char gTagPNGHeader[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a };
 
+typedef struct _mmfileid3taginfo {
+       char name[4];
+       unsigned int int_name;
+       AvID3TagList tag;
+} MMFILE_ID3TAG_INFO;
+
+#define ID3TAG_NUM_V22 16
+#define ID3TAG_NUM_V23 21
+
+static MMFILE_ID3TAG_INFO tag_info_v22[ID3TAG_NUM_V22] = {
+       {"TT2", 21170, AV_ID3TAG_TITLE},
+       {"TP1", 21041, AV_ID3TAG_ARTIST},
+       {"TP2", 21042, AV_ID3TAG_ALBUM_ARTIST},
+       {"TP3", 21043, AV_ID3TAG_CONDUCTOR},
+       {"TAL", 20588, AV_ID3TAG_ALBUM},
+       {"TYE", 21349, AV_ID3TAG_YEAR},
+       {"COM", 3629, AV_ID3TAG_COMMENT},
+       {"TCO", 20655, AV_ID3TAG_GENRE},
+       {"TRK", 21131, AV_ID3TAG_TRACKNUM},
+       {"PIC", 16739, AV_ID3TAG_PICTURE},
+       {"TCR", 20658, AV_ID3TAG_COPYRIGHT},
+       {"TCM", 20653, AV_ID3TAG_COMPOSER},
+       {"TRD", 21124, AV_ID3TAG_RECDATE},
+};
+
+static MMFILE_ID3TAG_INFO tag_info_v23[ID3TAG_NUM_V23] = {
+       {"TIT2", 665266, AV_ID3TAG_TITLE},
+       {"TPE1", 671953, AV_ID3TAG_ARTIST},
+       {"TPE2", 671954, AV_ID3TAG_ALBUM_ARTIST},
+       {"TPE3", 671955, AV_ID3TAG_CONDUCTOR},
+       {"TALB", 656834, AV_ID3TAG_ALBUM},
+       {"TYER", 681202, AV_ID3TAG_YEAR},
+       {"COMM", 114157, AV_ID3TAG_COMMENT},
+       {"TCON", 658990, AV_ID3TAG_GENRE},
+       {"TRCK", 673963, AV_ID3TAG_TRACKNUM},
+       {"APIC", 49507, AV_ID3TAG_PICTURE},
+       {"TCOP", 658992, AV_ID3TAG_COPYRIGHT},
+       {"TCOM", 658989, AV_ID3TAG_COMPOSER},
+       {"TRDA", 660097, AV_ID3TAG_RECDATE},                    /*Recdate for 2.3*/
+       {"USLT", 708052, AV_ID3TAG_UNSYNCLYRICS},
+       {"SYLT", 648660, AV_ID3TAG_SYNCLYRICS},
+       {"TIT1", 665265, AV_ID3TAG_CONTENT_GROUP},      /*Content Group for 2.4*/
+       {"TDRC", 660099, AV_ID3TAG_RECDATE},                    /*Recdate for 2.4*/
+};
+
+static int g_junk_counter_limit = 0;
+
 static int GetStringFromTextTagBox(MMFileFormatContext *formatContext, MMFileIOHandle *fp, MMFILE_MP4_BASIC_BOX_HEADER *basic_header, eMMFILE_3GP_TEXT_TAG eTag)
 {
        int ret = MMFILE_UTIL_FAIL;    /*fail*/
@@ -178,7 +293,7 @@ static int GetStringFromTextTagBox(MMFileFormatContext *formatContext, MMFileIOH
        char *temp_text = NULL;
 
        if (!formatContext || !fp || !basic_header) {
-               debug_error("invalid param\n");
+               debug_error(DEBUG, "invalid param");
                return MMFILE_UTIL_FAIL;
        }
 
@@ -186,26 +301,21 @@ static int GetStringFromTextTagBox(MMFileFormatContext *formatContext, MMFileIOH
 
        readed = mmfile_read(fp, (unsigned char *)&texttag, MMFILE_3GP_TEXT_TAGBOX_LEN);
        if (readed != MMFILE_3GP_TEXT_TAGBOX_LEN) {
-               debug_error("read text tag header fail\n");
+               debug_error(DEBUG, "read text tag header fail");
                ret = MMFILE_UTIL_FAIL;
                goto exception;
        }
 
        if (textBytes <= 1) { /* there exist only 00(null) */
-               debug_error("Text is NULL\n");
+               debug_error(DEBUG, "Text is NULL");
                goto exception;
        }
 
-       texttag.text = mmfile_malloc(textBytes);
-       if (!texttag.text) {
-               debug_error("malloc fail for text box\n");
-               ret = MMFILE_UTIL_FAIL;
-               goto exception;
-       }
+       texttag.text = g_malloc0(textBytes);
 
        readed = mmfile_read(fp, (unsigned char *)texttag.text, textBytes);
        if (readed != textBytes) {
-               debug_error("read text fail\n");
+               debug_error(DEBUG, "read text fail");
                ret = MMFILE_UTIL_FAIL;
                goto exception;
        }
@@ -213,51 +323,50 @@ static int GetStringFromTextTagBox(MMFileFormatContext *formatContext, MMFileIOH
        /* check BOM char */
        if ((texttag.text[0] == 0xFE) && (texttag.text[1] == 0xFF)) {
                /* this char is UTF-16 */
-               unsigned int bytes_written = 0;
-               temp_text = mmfile_string_convert((const char *)&texttag.text[2], readed - 2, "UTF-8", "UTF-16", NULL, (unsigned int *)&bytes_written);
+               temp_text = mmfile_convert_to_utf8((const char *)&texttag.text[2], readed - 2, MMFILE_CODESET_UTF16);
        } else {
-               temp_text = mmfile_strdup((const char *)texttag.text);
+               temp_text = g_strdup((const char *)texttag.text);
        }
 
        switch (eTag) {
                case eMMFILE_3GP_TAG_TITLE: {
                                if (!formatContext->title) {
-                                       formatContext->title = temp_text;
+                                       formatContext->title = g_strdup(temp_text);
                                }
                                break;
                        }
                case eMMFILE_3GP_TAG_CAPTION: {
                                if (!formatContext->description) {
-                                       formatContext->description = temp_text;
+                                       formatContext->description = g_strdup(temp_text);
                                }
                                break;
                        }
                case eMMFILE_3GP_TAG_COPYRIGHT: {
                                if (!formatContext->copyright) {
-                                       formatContext->copyright = temp_text;
+                                       formatContext->copyright = g_strdup(temp_text);
                                }
                                break;
                        }
                case eMMFILE_3GP_TAG_PERFORMER: {
                                if (!formatContext->artist) {
-                                       formatContext->artist = temp_text;
+                                       formatContext->artist = g_strdup(temp_text);
                                }
                                break;
                        }
                case eMMFILE_3GP_TAG_AUTHOR: {
                                if (!formatContext->author) {
-                                       formatContext->author = temp_text;
+                                       formatContext->author = g_strdup(temp_text);
                                }
                                break;
                        }
                case eMMFILE_3GP_TAG_GENRE: {
                                if (!formatContext->genre) {
-                                       formatContext->genre = temp_text;
+                                       formatContext->genre = g_strdup(temp_text);
                                }
                                break;
                        }
                default: {
-                               debug_warning("Not supported Text Tag type[%d]\n", eTag);
+                               debug_warning(DEBUG, "Not supported Text Tag type[%d]", eTag);
                                break;
                        }
        }
@@ -266,13 +375,14 @@ static int GetStringFromTextTagBox(MMFileFormatContext *formatContext, MMFileIOH
        texttag.text = NULL;
        mmfile_seek(fp, basic_header->start_offset + basic_header->size, SEEK_SET);
 
+       mmfile_free(temp_text);
+
        return MMFILE_UTIL_SUCCESS;
 
 exception:
        mmfile_seek(fp, basic_header->start_offset + basic_header->size, SEEK_SET);
-       if (texttag.text) {
-               mmfile_free(texttag.text);
-       }
+       mmfile_free(texttag.text);
+
        return ret;
 }
 
@@ -284,13 +394,13 @@ static int GetYearFromYearTagBox(MMFileFormatContext *formatContext, MMFileIOHan
        char temp_year[MAX_YEAR_BUFFER] = {0, };
 
        if (!formatContext || !fp || !basic_header) {
-               debug_error("invalid param\n");
+               debug_error(DEBUG, "invalid param");
                return MMFILE_UTIL_FAIL;
        }
 
        readed = mmfile_read(fp, (unsigned char *)&yearbox, MMFILE_3GP_YEAR_TAGBOX_LEN);
        if (readed != MMFILE_3GP_YEAR_TAGBOX_LEN) {
-               debug_error("read yeartag header fail\n");
+               debug_error(DEBUG, "read yeartag header fail");
                goto exception;
        }
 
@@ -298,7 +408,7 @@ static int GetYearFromYearTagBox(MMFileFormatContext *formatContext, MMFileIOHan
                yearbox.year = mmfile_io_be_int16(yearbox.year);
                snprintf(temp_year, MAX_YEAR_BUFFER, "%d", yearbox.year);
                temp_year[MAX_YEAR_BUFFER - 1] = '\0';
-               formatContext->year = mmfile_strdup((const char *)temp_year);
+               formatContext->year = g_strdup((const char *)temp_year);
        }
 
        mmfile_seek(fp, basic_header->start_offset + basic_header->size, SEEK_SET);
@@ -319,31 +429,25 @@ static int GetAlbumFromAlbumTagBox(MMFileFormatContext *formatContext, MMFileIOH
        MMFILE_3GP_ALBUM_TAGBOX albumbox = {0, };
 
        if (!formatContext || !fp || !basic_header) {
-               debug_error("invalid param\n");
+               debug_error(DEBUG, "invalid param");
                return MMFILE_UTIL_FAIL;
        }
 
        readed = mmfile_read(fp, (unsigned char *)&albumbox, MMFILE_3GP_ALBUM_TAGBOX_LEN);
        if (readed != MMFILE_3GP_ALBUM_TAGBOX_LEN) {
-               debug_error("read albumtag header fail\n");
+               debug_error(DEBUG, "read albumtag header fail");
                goto exception;
        }
 
        albumTitleLen = basic_header->size - MMFILE_MP4_BASIC_BOX_HEADER_LEN - MMFILE_3GP_ALBUM_TAGBOX_LEN - 1; /* 1: track number */
        if (albumTitleLen > 1) { /* there exist only 00(null) */
-#ifdef __MMFILE_TEST_MODE__
-               debug_msg("albumTitleLen=%d\n", albumTitleLen);
-#endif
+               debug_msg(RELEASE, "albumTitleLen=%d", albumTitleLen);
 
-               albumbox.albumtile = mmfile_malloc(albumTitleLen + 1);  /* 1: for null char */
-               if (!albumbox.albumtile) {
-                       debug_error("malloc fail for album title text\n");
-                       goto exception;
-               }
+               albumbox.albumtile = g_malloc0(albumTitleLen + 1);  /* 1: for null char */
 
                readed = mmfile_read(fp, (unsigned char *)albumbox.albumtile, albumTitleLen);
                if (readed != albumTitleLen) {
-                       debug_error("read album title fail\n");
+                       debug_error(DEBUG, "read album title fail");
                        goto exception;
                }
 
@@ -353,7 +457,7 @@ static int GetAlbumFromAlbumTagBox(MMFileFormatContext *formatContext, MMFileIOH
                        trackFlags = 0;
                        readed = mmfile_read(fp, (unsigned char *)&(albumbox.albumtile[albumTitleLen]), 1);
                        if (readed != 1) {
-                               debug_error("read album title fail\n");
+                               debug_error(DEBUG, "read album title fail");
                                goto exception;
                        }
                        albumbox.albumtile[albumTitleLen] = '\0';
@@ -362,25 +466,23 @@ static int GetAlbumFromAlbumTagBox(MMFileFormatContext *formatContext, MMFileIOH
                /* check BOM char */
                if ((albumbox.albumtile[0] == 0xFE) && (albumbox.albumtile[1] == 0xFF)) {
                        /* this char is UTF-16 */
-                       unsigned int bytes_written = 0;
-                       temp_text = mmfile_string_convert((const char *)&albumbox.albumtile[2], readed - 2, "UTF-8", "UTF-16", NULL, (unsigned int *)&bytes_written);
+                       temp_text = mmfile_convert_to_utf8((const char *)&albumbox.albumtile[2], readed - 2, MMFILE_CODESET_UTF16);
                } else {
-                       temp_text = mmfile_strdup((const char *)albumbox.albumtile);
+                       temp_text = g_strdup((const char *)albumbox.albumtile);
                }
 
-               if (!formatContext->album) {
+               if (!formatContext->album)
                        formatContext->album = temp_text;
-               }
+               else
+                       mmfile_free(temp_text);
 
-#ifdef __MMFILE_TEST_MODE__
-               debug_msg("formatContext->album=%s, strlen=%d\n", formatContext->album, strlen(formatContext->album));
-#endif
+               debug_msg(RELEASE, "formatContext->album=%s, strlen=%zu", formatContext->album, strlen(formatContext->album));
        }
 
        if (trackFlags) {
                readed = mmfile_read(fp, (unsigned char *)&albumbox.trackNumber, 1);
                if (readed != 1) {
-                       debug_error("read track number fail\n");
+                       debug_error(DEBUG, "read track number fail");
                        goto exception;
                }
 
@@ -388,7 +490,7 @@ static int GetAlbumFromAlbumTagBox(MMFileFormatContext *formatContext, MMFileIOH
                        char tracknum[10] = {0, };
                        snprintf(tracknum, 10, "%d", albumbox.trackNumber);
                        tracknum[9] = '\0';
-                       formatContext->tagTrackNum = mmfile_strdup((const char *)tracknum);
+                       formatContext->tagTrackNum = g_strdup((const char *)tracknum);
                }
        }
 
@@ -413,42 +515,37 @@ static int GetRatingFromRatingTagBox(MMFileFormatContext *formatContext, MMFileI
        MMFILE_3GP_RATING_TAGBOX ratingTag = {0, };
 
        if (!formatContext || !fp || !basic_header) {
-               debug_error("invalid param\n");
+               debug_error(DEBUG, "invalid param");
                return MMFILE_UTIL_FAIL;
        }
 
        readed = mmfile_read(fp, (unsigned char *)&ratingTag, MMFILE_3GP_RATING_TAGBOX_LEN);
        if (readed != MMFILE_3GP_RATING_TAGBOX_LEN) {
-               debug_error("read rating tag header fail\n");
+               debug_error(DEBUG, "read rating tag header fail");
                goto exception;
        }
 
        ratinginfoLen = basic_header->size - MMFILE_MP4_BASIC_BOX_HEADER_LEN - MMFILE_3GP_RATING_TAGBOX_LEN;
 
        if (ratinginfoLen == 1) {
-               debug_error("Rating Text is NULL\n");
+               debug_error(DEBUG, "Rating Text is NULL");
                goto exception;
        }
 
-       ratingTag.ratingInfo = mmfile_malloc(ratinginfoLen);
-       if (!ratingTag.ratingInfo) {
-               debug_error("rating info error\n");
-               goto exception;
-       }
+       ratingTag.ratingInfo = g_malloc0(ratinginfoLen);
 
        readed = mmfile_read(fp, (unsigned char *)ratingTag.ratingInfo, ratinginfoLen);
        if (readed != ratinginfoLen) {
-               debug_error("read rating info string fail\n");
+               debug_error(DEBUG, "read rating info string fail");
                goto exception;
        }
 
        /* check BOM char */
        if ((ratingTag.ratingInfo[0] == 0xFE) && (ratingTag.ratingInfo[1] == 0xFF)) {
                /* this char is UTF-16 */
-               unsigned int bytes_written = 0;
-               temp_text = mmfile_string_convert((const char *)&ratingTag.ratingInfo[2], readed - 2, "UTF-8", "UTF-16", NULL, (unsigned int *)&bytes_written);
+               temp_text = mmfile_convert_to_utf8((const char *)&ratingTag.ratingInfo[2], readed - 2, MMFILE_CODESET_UTF16);
        } else {
-               temp_text = mmfile_strdup((const char *)ratingTag.ratingInfo);
+               temp_text = g_strdup((const char *)ratingTag.ratingInfo);
        }
 
        if (!formatContext->rating) {
@@ -478,42 +575,37 @@ static int GetClassficationFromClsfTagBox(MMFileFormatContext *formatContext, MM
        MMFILE_3GP_CLASSIFICATION_TAGBOX classTag = {0, };
 
        if (!formatContext || !fp || !basic_header) {
-               debug_error("invalid param\n");
+               debug_error(DEBUG, "invalid param");
                return MMFILE_UTIL_FAIL;
        }
 
        readed = mmfile_read(fp, (unsigned char *)&classTag, MMFILE_3GP_CLASS_TAGBOX_LEN);
        if (readed != MMFILE_3GP_CLASS_TAGBOX_LEN) {
-               debug_error("read classification tag header fail\n");
+               debug_error(DEBUG, "read classification tag header fail");
                goto exception;
        }
 
 
        classinfoLen = basic_header->size - MMFILE_MP4_BASIC_BOX_HEADER_LEN - MMFILE_3GP_CLASS_TAGBOX_LEN;
        if (classinfoLen == 1) {
-               debug_error("Classification Text is NULL\n");
+               debug_error(DEBUG, "Classification Text is NULL");
                goto exception;
        }
 
-       classTag.classificationInfo = mmfile_malloc(classinfoLen);
-       if (!classTag.classificationInfo) {
-               debug_error("class info error\n");
-               goto exception;
-       }
+       classTag.classificationInfo = g_malloc0(classinfoLen);
 
        readed = mmfile_read(fp, (unsigned char *)classTag.classificationInfo, classinfoLen);
        if (readed != classinfoLen) {
-               debug_error("read class info string fail\n");
+               debug_error(DEBUG, "read class info string fail");
                goto exception;
        }
 
        /* check BOM char */
        if ((classTag.classificationInfo[0] == 0xFE) && (classTag.classificationInfo[1] == 0xFF)) {
                /* this char is UTF-16 */
-               unsigned int bytes_written = 0;
-               temp_text = mmfile_string_convert((const char *)&classTag.classificationInfo[2], readed - 2, "UTF-8", "UTF-16", NULL, (unsigned int *)&bytes_written);
+               temp_text = mmfile_convert_to_utf8((const char *)&classTag.classificationInfo[2], readed - 2, MMFILE_CODESET_UTF16);
        } else {
-               temp_text = mmfile_strdup((const char *)classTag.classificationInfo);
+               temp_text = g_strdup((const char *)classTag.classificationInfo);
        }
 
        if (!formatContext->classification) {
@@ -576,7 +668,6 @@ static int GetLocationFromLociTagBox(MMFileFormatContext *formatContext, MMFileI
        unsigned char *buffer = NULL;
        unsigned char *p = NULL;
        int pos = 0;
-       unsigned int bytes_written = 0;
        unsigned int name_sz = 0;
        unsigned int astro_sz = 0;
 
@@ -585,32 +676,28 @@ static int GetLocationFromLociTagBox(MMFileFormatContext *formatContext, MMFileI
 
 
        if (!formatContext || !fp || !basic_header) {
-               debug_error("invalid param\n");
+               debug_error(DEBUG, "invalid param");
                return MMFILE_UTIL_FAIL;
        }
 
        readed = mmfile_read(fp, (unsigned char *)&lociTag, 6);  /*6 = version + flag + pad + language */
        if (readed != 6) {
-               debug_error("read location tag header fail\n");
+               debug_error(DEBUG, "read location tag header fail");
                goto exception;
        }
 
        /*buffer len = name + role + ... + additional notes length */
        bufferLen = basic_header->size - MMFILE_MP4_BASIC_BOX_HEADER_LEN - 6;
        if (bufferLen < 1) {
-               debug_error("too small buffer\n");
+               debug_error(DEBUG, "too small buffer");
                goto exception;
        }
 
-       buffer = mmfile_malloc(bufferLen);
-       if (!buffer) {
-               debug_error("buffer malloc error\n");
-               goto exception;
-       }
+       buffer = g_malloc0(bufferLen);
 
        readed = mmfile_read(fp, (unsigned char *)buffer, bufferLen);
        if (readed != bufferLen) {
-               debug_error("read location tag fail\n");
+               debug_error(DEBUG, "read location tag fail");
                goto exception;
        }
        p = buffer;
@@ -619,9 +706,9 @@ static int GetLocationFromLociTagBox(MMFileFormatContext *formatContext, MMFileI
        pos = _get_char_position(p, '\0', readed - (1 + 4 + 4 + 4 + 2));
        if (pos >= 0) {
                if (p[0] == 0xFE && p[1] == 0xFF) {
-                       lociTag.name = (unsigned char *)mmfile_string_convert((const char *)(p + 2), pos - 2, "UTF-8", "UTF-16", NULL, (unsigned int *)&bytes_written);
+                       lociTag.name = (unsigned char *)mmfile_convert_to_utf8((const char *)(p + 2), pos - 2, MMFILE_CODESET_UTF16);
                } else {
-                       lociTag.name = (unsigned char *)mmfile_strdup((const char *)p);
+                       lociTag.name = (unsigned char *)g_strdup((const char *)p);
                }
        } else {
                goto exception;
@@ -633,11 +720,9 @@ static int GetLocationFromLociTagBox(MMFileFormatContext *formatContext, MMFileI
        lociTag.role = *p;
        p++;
 
-#ifdef __MMFILE_TEST_MODE__
-       debug_msg("long: 0x%02X 0x%02X 0x%02X 0x%02X \n", *(p + 0), *(p + 1), *(p + 2), *(p + 3));
-       debug_msg("lati: 0x%02X 0x%02X 0x%02X 0x%02X \n", *(p + 4), *(p + 5), *(p + 6), *(p + 7));
-       debug_msg("alti: 0x%02X 0x%02X 0x%02X 0x%02X \n", *(p + 8), *(p + 9), *(p + 10), *(p + 11));
-#endif
+       debug_msg(RELEASE, "long: 0x%02X 0x%02X 0x%02X 0x%02X ", *(p + 0), *(p + 1), *(p + 2), *(p + 3));
+       debug_msg(RELEASE, "lati: 0x%02X 0x%02X 0x%02X 0x%02X ", *(p + 4), *(p + 5), *(p + 6), *(p + 7));
+       debug_msg(RELEASE, "alti: 0x%02X 0x%02X 0x%02X 0x%02X ", *(p + 8), *(p + 9), *(p + 10), *(p + 11));
 
        ilong = mmfile_io_be_uint32(*(unsigned int *)p);
        ilati = mmfile_io_be_uint32(*(unsigned int *)(p + 4));
@@ -660,9 +745,9 @@ static int GetLocationFromLociTagBox(MMFileFormatContext *formatContext, MMFileI
        pos = _get_char_position(p, '\0', readed - (name_sz + 1 + 4 + 4 + 4 + 1));
        if (pos >= 0) {
                if (p[0] == 0xFE && p[1] == 0xFF) {
-                       lociTag.astronomical_body = (unsigned char *)mmfile_string_convert((const char *)(p + 2), pos - 2, "UTF-8", "UTF-16", NULL, (unsigned int *)&bytes_written);
+                       lociTag.astronomical_body = (unsigned char *)mmfile_convert_to_utf8((const char *)(p + 2), pos - 2, MMFILE_CODESET_UTF16);
                } else {
-                       lociTag.astronomical_body = (unsigned char *)mmfile_strdup((const char *)p);
+                       lociTag.astronomical_body = (unsigned char *)g_strdup((const char *)p);
                }
        } else {
                goto exception;
@@ -674,24 +759,22 @@ static int GetLocationFromLociTagBox(MMFileFormatContext *formatContext, MMFileI
        pos = _get_char_position(p, '\0', readed - (name_sz + 1 + 4 + 4 + 4 + astro_sz));
        if (pos >= 0) {
                if (p[0] == 0xFE && p[1] == 0xFF) {
-                       lociTag.additional_notes = (unsigned char *)mmfile_string_convert((const char *)(p + 2), pos - 2, "UTF-8", "UTF-16", NULL, (unsigned int *)&bytes_written);
+                       lociTag.additional_notes = (unsigned char *)mmfile_convert_to_utf8((const char *)(p + 2), pos - 2, MMFILE_CODESET_UTF16);
                } else {
-                       lociTag.additional_notes = (unsigned char *)mmfile_strdup((const char *)p);
+                       lociTag.additional_notes = (unsigned char *)g_strdup((const char *)p);
                }
        } else {
                goto exception;
        }
 
-#ifdef __MMFILE_TEST_MODE__
-       debug_msg("** Location Information **\n");
-       debug_msg("Name             : %s\n", lociTag.name);
-       debug_msg("Role             : %d (0: shooting, 1: real, 2: fictional, other: reserved)\n", lociTag.role);
-       debug_msg("Longitude        : %16.16f\n", lociTag.longitude);
-       debug_msg("Latitude         : %16.16f\n", lociTag.latitude);
-       debug_msg("Altitude         : %16.16f\n", lociTag.altitude);
-       debug_msg("Astronomical body: %s\n", lociTag.astronomical_body);
-       debug_msg("Additional notes : %s\n", lociTag.additional_notes);
-#endif
+       debug_msg(RELEASE, "** Location Information **");
+       debug_msg(RELEASE, "Name             : %s", lociTag.name);
+       debug_msg(RELEASE, "Role             : %d (0: shooting, 1: real, 2: fictional, other: reserved)", lociTag.role);
+       debug_msg(RELEASE, "Longitude        : %16.16f", lociTag.longitude);
+       debug_msg(RELEASE, "Latitude         : %16.16f", lociTag.latitude);
+       debug_msg(RELEASE, "Altitude         : %16.16f", lociTag.altitude);
+       debug_msg(RELEASE, "Astronomical body: %s", lociTag.astronomical_body);
+       debug_msg(RELEASE, "Additional notes : %s", lociTag.additional_notes);
 
        formatContext->longitude = lociTag.longitude;
        formatContext->latitude = lociTag.latitude;
@@ -721,42 +804,486 @@ static int GetSAUTInfoFromSMTATagBox(MMFileFormatContext *formatContext, MMFileI
        int readed = 0;
 
        if (!formatContext || !fp || !basic_header) {
-               debug_error("invalid param\n");
+               debug_error(DEBUG, "invalid param");
                return MMFILE_UTIL_FAIL;
        }
 
        readed = mmfile_read(fp, (unsigned char *)&smtaTag, sizeof(MMFILE_M4A_SMTA_TAGBOX));
        if (readed != sizeof(MMFILE_M4A_SMTA_TAGBOX)) {
-               debug_error("read smta tag header fail\n");
+               debug_error(DEBUG, "read smta tag header fail");
                goto exception;
        }
 
        smtaTag.length = mmfile_io_be_uint32(smtaTag.length);
        smtaTag.value = mmfile_io_be_uint32(smtaTag.value);
-#ifdef __MMFILE_TEST_MODE__
-       debug_msg("Len : 0x%x", smtaTag.length);
-       debug_msg("Saut : 0x%x 0x%x 0x%x 0x%x", smtaTag.saut[0], smtaTag.saut[1], smtaTag.saut[2], smtaTag.saut[3]);
-       debug_msg("Value : 0x%x", smtaTag.value);
-#endif
 
+       debug_msg(RELEASE, "Len : 0x%x", smtaTag.length);
+       debug_msg(RELEASE, "Saut : 0x%x 0x%x 0x%x 0x%x", smtaTag.saut[0], smtaTag.saut[1], smtaTag.saut[2], smtaTag.saut[3]);
+       debug_msg(RELEASE, "Value : 0x%x", smtaTag.value);
+
+/*
+       Samsung Metadata
+       0: None-mode
+       1: 360 normal
+       2: 360 timelapse
+       3: 180 normal
+       4: 180 timelapse
+       5: 360 looping mode
+       6: 180 looping mode
+       7: 360 slowmotion mode
+       8: 180 slowmotion mode
+*/
        if (smtaTag.saut[0] == 's'
            && smtaTag.saut[1] == 'a'
            && smtaTag.saut[2] == 'u'
            && smtaTag.saut[3] == 't') {
                if (smtaTag.value == 0x01) {
-#ifdef __MMFILE_TEST_MODE__
-                       debug_msg("This has saut tag and valid value");
-#endif
+                       debug_msg(RELEASE, "This has saut tag and valid value");
                        formatContext->smta = 1;
+               } else if (smtaTag.value == 0x02) {
+                       debug_msg(RELEASE, "This has saut tag and valid value");
+                       formatContext->smta = 2;
                } else {
-                       debug_error("This has saut tag and but invalid value");
+                       debug_error(DEBUG, "This has saut tag but invalid value");
                        goto exception;
                }
        } else {
-               debug_error("This hasn't saut tag and valid value");
+               debug_error(DEBUG, "This hasn't saut tag and valid value");
+               goto exception;
+       }
+
+       return MMFILE_UTIL_SUCCESS;
+
+exception:
+       mmfile_seek(fp, basic_header->start_offset + basic_header->size, SEEK_SET);
+
+       return MMFILE_UTIL_FAIL;
+}
+
+static int GetSA3DInfoFromMP4ATagBox(MMFileFormatContext *formatContext, MMFileIOHandle *fp, MMFILE_MP4_BASIC_BOX_HEADER *basic_header)
+{
+       if (!formatContext || !fp || !basic_header) {
+               debug_error(DEBUG, "invalid param");
+               return MMFILE_UTIL_FAIL;
+       }
+
+       unsigned char *buffer;
+       int readed = 0;
+       bool is_SA3D_present = false;
+       unsigned int i = 0;
+       MMFILE_MP4A_SA3D_TAGBOX sa3dTag = {0, };
+
+       formatContext->ambisonicType = MMFILE_AMBISONIC_TYPE_UNKNOWN;
+       formatContext->ambisonicOrder = MMFILE_AMBISONIC_ORDER_UNKNOWN;
+       formatContext->ambisonicFormat = MMFILE_AMBISONIC_FORMAT_UNKNOWN;
+
+       mmfile_seek(fp, basic_header->start_offset, SEEK_SET);
+
+       buffer = calloc(basic_header->size + 1, sizeof(unsigned char));
+       if (!buffer) {
+               debug_error(DEBUG, "calloc failed ");
+               goto exception;
+       }
+
+       readed = mmfile_read(fp, buffer, basic_header->size);
+       if (readed != (int)basic_header->size) {
+               debug_error(DEBUG, "read mp4a box failed");
+               goto exception;
+       }
+
+       for (i = 0; i + 3 < basic_header->size; ++i)
+               if (buffer[i] == 'S' && buffer[i + 1] == 'A' && buffer[i + 2] == '3' && buffer[i + 3] == 'D') {
+                       debug_warning(DEBUG, "SA3D data found at offset %d bytes", i);
+                       is_SA3D_present = true;
+                       break;
+               }
+
+       if (!is_SA3D_present) {
+               debug_warning(DEBUG, "No SA3D box found");
+               goto exception;
+       }
+
+       mmfile_seek(fp, basic_header->start_offset + i + 4, SEEK_SET);
+
+       readed = mmfile_read(fp, (unsigned char *)&sa3dTag, sizeof(MMFILE_MP4A_SA3D_TAGBOX));
+       if (readed != sizeof(MMFILE_MP4A_SA3D_TAGBOX)) {
+               debug_error(DEBUG, "read SA3D tag header fail");
+               goto exception;
+       }
+
+       sa3dTag.ambisonic_order = mmfile_io_be_uint32(sa3dTag.ambisonic_order);
+       sa3dTag.num_channels = mmfile_io_be_uint32(sa3dTag.num_channels);
+       for (i = 0; i < sa3dTag.num_channels; ++i)
+               sa3dTag.channel_map[i] = mmfile_io_be_uint32(sa3dTag.channel_map[i]);
+
+       debug_msg(RELEASE, "sa3dTag.version = %d", sa3dTag.version);
+       debug_msg(RELEASE, "sa3dTag.ambisonic_type = %d", sa3dTag.ambisonic_type);
+       debug_msg(RELEASE, "sa3dTag.ambisonic_order = %d", sa3dTag.ambisonic_order);
+       debug_msg(RELEASE, "sa3dTag.ambisonic_channel_ordering = %d", sa3dTag.ambisonic_channel_ordering);
+       debug_msg(RELEASE, "sa3dTag.ambisonic_normalization = %d", sa3dTag.ambisonic_normalization);
+       debug_msg(RELEASE, "sa3dTag.num_channels = %d", sa3dTag.num_channels);
+       for (i = 0; i < sa3dTag.num_channels; ++i)
+               debug_msg(RELEASE, "sa3dTag.channel_map[%d] = %d", i, sa3dTag.channel_map[i]);
+
+       if (sa3dTag.version != RFC_AMBISONIC_SA3DBOX_VERSION_SUPPORTED) {
+               debug_error(DEBUG, "SA3D tag box version is unsupported");
+               goto exception;
+       } else {
+               if (sa3dTag.ambisonic_type == RFC_AMBISONIC_TYPE_PERIPHONIC)
+                       formatContext->ambisonicType = MMFILE_AMBISONIC_TYPE_PERIPHONIC;
+
+               switch (sa3dTag.ambisonic_order) {
+                       case MMFILE_AMBISONIC_ORDER_FOA: {
+                                       if (sa3dTag.num_channels == 4) {
+                                               formatContext->ambisonicOrder = MMFILE_AMBISONIC_ORDER_FOA;
+
+                                               if ((sa3dTag.ambisonic_channel_ordering == RFC_AMBISONIC_CHANNEL_ORDERING_ACN) &&
+                                                               (sa3dTag.ambisonic_normalization == RFC_AMBISONIC_NORMALIZATION_SN3D) &&
+                                                               (sa3dTag.channel_map[0] == 0) &&
+                                                               (sa3dTag.channel_map[1] == 1) &&
+                                                               (sa3dTag.channel_map[2] == 2) &&
+                                                               (sa3dTag.channel_map[3] == 3))
+                                                       formatContext->ambisonicFormat = MMFILE_AMBISONIC_FORMAT_AMBIX;
+
+                                               if ((sa3dTag.ambisonic_channel_ordering == RFC_AMBISONIC_CHANNEL_ORDERING_FUMA) &&
+                                                               (sa3dTag.ambisonic_normalization == RFC_AMBISONIC_NORMALIZATION_FUMA) &&
+                                                               (sa3dTag.channel_map[0] == 0) &&
+                                                               (sa3dTag.channel_map[1] == 3) &&
+                                                               (sa3dTag.channel_map[2] == 1) &&
+                                                               (sa3dTag.channel_map[3] == 2))
+                                                       formatContext->ambisonicFormat = MMFILE_AMBISONIC_FORMAT_AMB;
+                                       } else {
+                                               debug_error(DEBUG, "Incorrect metadata: ambisonic order and channels number do not correspond");
+                                               goto exception;
+                                       }
+
+                                       break;
+                               }
+                       case MMFILE_AMBISONIC_ORDER_SOA: {
+                                       if (sa3dTag.num_channels == 9) {
+                                               formatContext->ambisonicOrder = MMFILE_AMBISONIC_ORDER_SOA;
+
+                                               if ((sa3dTag.ambisonic_channel_ordering == RFC_AMBISONIC_CHANNEL_ORDERING_ACN) &&
+                                                               (sa3dTag.ambisonic_normalization == RFC_AMBISONIC_NORMALIZATION_SN3D) &&
+                                                               (sa3dTag.channel_map[0] == 0) &&
+                                                               (sa3dTag.channel_map[1] == 1) &&
+                                                               (sa3dTag.channel_map[2] == 2) &&
+                                                               (sa3dTag.channel_map[3] == 3) &&
+                                                               (sa3dTag.channel_map[4] == 4) &&
+                                                               (sa3dTag.channel_map[5] == 5) &&
+                                                               (sa3dTag.channel_map[6] == 6) &&
+                                                               (sa3dTag.channel_map[7] == 7) &&
+                                                               (sa3dTag.channel_map[8] == 8))
+                                                       formatContext->ambisonicFormat = MMFILE_AMBISONIC_FORMAT_AMBIX;
+
+                                               if ((sa3dTag.ambisonic_channel_ordering == RFC_AMBISONIC_CHANNEL_ORDERING_FUMA) &&
+                                                               (sa3dTag.ambisonic_normalization == RFC_AMBISONIC_NORMALIZATION_FUMA) &&
+                                                               (sa3dTag.channel_map[0] == 0) &&
+                                                               (sa3dTag.channel_map[1] == 3) &&
+                                                               (sa3dTag.channel_map[2] == 1) &&
+                                                               (sa3dTag.channel_map[3] == 2) &&
+                                                               (sa3dTag.channel_map[4] == 6) &&
+                                                               (sa3dTag.channel_map[5] == 7) &&
+                                                               (sa3dTag.channel_map[6] == 5) &&
+                                                               (sa3dTag.channel_map[7] == 8) &&
+                                                               (sa3dTag.channel_map[8] == 4))
+                                                       formatContext->ambisonicFormat = MMFILE_AMBISONIC_FORMAT_AMB;
+                                       } else {
+                                               debug_error(DEBUG, "Incorrect metadata: ambisonic order and channels number do not correspond");
+                                               goto exception;
+                                       }
+
+                                       break;
+                               }
+
+                       case MMFILE_AMBISONIC_ORDER_TOA: {
+                                       if (sa3dTag.num_channels == 16) {
+                                               formatContext->ambisonicOrder = MMFILE_AMBISONIC_ORDER_TOA;
+
+                                               if ((sa3dTag.ambisonic_channel_ordering == RFC_AMBISONIC_CHANNEL_ORDERING_ACN) &&
+                                                               (sa3dTag.ambisonic_normalization == RFC_AMBISONIC_NORMALIZATION_SN3D) &&
+                                                               (sa3dTag.channel_map[0] == 0) &&
+                                                               (sa3dTag.channel_map[1] == 1) &&
+                                                               (sa3dTag.channel_map[2] == 2) &&
+                                                               (sa3dTag.channel_map[3] == 3) &&
+                                                               (sa3dTag.channel_map[4] == 4) &&
+                                                               (sa3dTag.channel_map[5] == 5) &&
+                                                               (sa3dTag.channel_map[6] == 6) &&
+                                                               (sa3dTag.channel_map[7] == 7) &&
+                                                               (sa3dTag.channel_map[8] == 8) &&
+                                                               (sa3dTag.channel_map[9] == 9) &&
+                                                               (sa3dTag.channel_map[10] == 10) &&
+                                                               (sa3dTag.channel_map[11] == 11) &&
+                                                               (sa3dTag.channel_map[12] == 12) &&
+                                                               (sa3dTag.channel_map[13] == 13) &&
+                                                               (sa3dTag.channel_map[14] == 14) &&
+                                                               (sa3dTag.channel_map[15] == 15))
+                                                       formatContext->ambisonicFormat = MMFILE_AMBISONIC_FORMAT_AMBIX;
+
+                                               if ((sa3dTag.ambisonic_channel_ordering == RFC_AMBISONIC_CHANNEL_ORDERING_FUMA) &&
+                                                               (sa3dTag.ambisonic_normalization == RFC_AMBISONIC_NORMALIZATION_FUMA) &&
+                                                               (sa3dTag.channel_map[0] == 0) &&
+                                                               (sa3dTag.channel_map[1] == 3) &&
+                                                               (sa3dTag.channel_map[2] == 1) &&
+                                                               (sa3dTag.channel_map[3] == 2) &&
+                                                               (sa3dTag.channel_map[4] == 6) &&
+                                                               (sa3dTag.channel_map[5] == 7) &&
+                                                               (sa3dTag.channel_map[6] == 5) &&
+                                                               (sa3dTag.channel_map[7] == 8) &&
+                                                               (sa3dTag.channel_map[8] == 4) &&
+                                                               (sa3dTag.channel_map[9] == 12) &&
+                                                               (sa3dTag.channel_map[10] == 13) &&
+                                                               (sa3dTag.channel_map[11] == 11) &&
+                                                               (sa3dTag.channel_map[12] == 14) &&
+                                                               (sa3dTag.channel_map[13] == 10) &&
+                                                               (sa3dTag.channel_map[14] == 15) &&
+                                                               (sa3dTag.channel_map[15] == 9))
+                                                       formatContext->ambisonicFormat = MMFILE_AMBISONIC_FORMAT_AMB;
+                                       } else {
+                                               debug_error(DEBUG, "Incorrect metadata: ambisonic order and channels number do not correspond");
+                                               goto exception;
+                                       }
+
+                                       break;
+                               }
+
+                       default: {
+                                       debug_warning(DEBUG, "Ambisonic order or format is not supported: ambix or amb formats up to 3rd order were expected.");
+                                       goto exception;
+                                       break;
+                               }
+               }
+
+               debug_msg(RELEASE, "formatContext->ambisonic_type = %d", formatContext->ambisonicType);
+               debug_msg(RELEASE, "formatContext->ambisonic_order = %d", formatContext->ambisonicOrder);
+               debug_msg(RELEASE, "formatContext->ambisonic_format = %d", formatContext->ambisonicFormat);
+       }
+
+       return MMFILE_UTIL_SUCCESS;
+
+exception:
+       mmfile_seek(fp, basic_header->start_offset + basic_header->size, SEEK_SET);
+
+       return MMFILE_UTIL_FAIL;
+}
+
+static int ParseSt3dData(MMFileFormatContext *formatContext, MMFileIOHandle *fp, long long start_offset)
+{
+       uint8_t stereo_mode = INVALID_UINT8_VALUE;
+       unsigned int readed = 0;
+
+       mmfile_seek(fp, start_offset, SEEK_SET);
+
+       readed = mmfile_read(fp, (unsigned char *)&stereo_mode, sizeof(uint8_t));
+       if (readed != sizeof(uint8_t)) {
+               debug_error(DEBUG, "read st3d tag header fail");
+               return MMFILE_UTIL_FAIL;
+       }
+
+       formatContext->stereoModeV2 = stereo_mode;
+
+       return MMFILE_UTIL_SUCCESS;
+}
+
+static int ParseSvhdData(MMFileFormatContext *formatContext, MMFileIOHandle *fp, long long start_offset, unsigned int box_size)
+{
+       unsigned int readed = 0;
+
+       formatContext->metadataSourceV2 = (char *)calloc(1, box_size);
+       if (!formatContext->metadataSourceV2) {
+               debug_error(DEBUG, "Calloc failed");
+               return MMFILE_UTIL_FAIL;
+       }
+
+       mmfile_seek(fp, start_offset, SEEK_SET);
+       readed = mmfile_read(fp, (unsigned char *)formatContext->metadataSourceV2, box_size);
+       if (readed != box_size) {
+               debug_error(DEBUG, "read svhd tag header fail");
+               if (formatContext->metadataSourceV2)
+                       free(formatContext->metadataSourceV2);
+               return MMFILE_UTIL_FAIL;
+       }
+
+       return MMFILE_UTIL_SUCCESS;
+}
+
+static int ParseProjData(MMFileFormatContext *formatContext, MMFileIOHandle *fp, long long start_offset)
+{
+       unsigned int readed = 0;
+       typedef struct proj_box_data_s {
+               uint32_t proj_type;
+               uint8_t version;
+               uint8_t flags[3];
+       } __attribute__((aligned(1), packed)) proj_box_data;
+
+       typedef struct prhd_box_data_s {
+               uint32_t projection_pose_yaw;
+               uint32_t projection_pose_pitch;
+               uint32_t projection_pose_roll;
+       } prhd_box_data;
+
+       typedef struct equi_box_data_s {
+               uint32_t projection_bounds_top;
+               uint32_t projection_bounds_bottom;
+               uint32_t projection_bounds_left;
+               uint32_t projection_bounds_right;
+       } equi_box_data;
+
+       typedef struct cbmp_box_data_s {
+               uint32_t layout;
+               uint32_t padding;
+       } cbmp_box_data;
+
+
+       proj_box_data proj_data;
+       proj_data.proj_type = INVALID_UINT_VALUE;
+
+       prhd_box_data prhd_data;
+       prhd_data.projection_pose_yaw = INVALID_UINT_VALUE;
+       prhd_data.projection_pose_pitch = INVALID_UINT_VALUE;
+       prhd_data.projection_pose_roll = INVALID_UINT_VALUE;
+
+       equi_box_data equi_data;
+       equi_data.projection_bounds_top = INVALID_UINT_VALUE;
+       equi_data.projection_bounds_bottom = INVALID_UINT_VALUE;
+       equi_data.projection_bounds_left = INVALID_UINT_VALUE;
+       equi_data.projection_bounds_right = INVALID_UINT_VALUE;
+
+       cbmp_box_data cbmp_data;
+       cbmp_data.layout = INVALID_UINT_VALUE;
+       cbmp_data.padding = INVALID_UINT_VALUE;
+
+       mmfile_seek(fp, start_offset, SEEK_SET);
+
+       readed = mmfile_read(fp, (unsigned char *)&proj_data, sizeof(proj_box_data));
+       if (readed != sizeof(proj_box_data)) {
+               debug_error(DEBUG, "read of proj box failed");
+               return MMFILE_UTIL_FAIL;
+       }
+
+       formatContext->projTypeV2 = mmfile_io_be_uint32(proj_data.proj_type);
+
+       debug_error(DEBUG, "formatContext->projTypeV2 = %d", formatContext->projTypeV2);
+       debug_error(DEBUG, "proj_data.version = %d", proj_data.version);
+       debug_error(DEBUG, "proj_data.flags = %d", ((uint32_t)proj_data.flags[0] << 16) +
+                       ((uint32_t)proj_data.flags[1] << 8) + (uint32_t)proj_data.flags[2]);
+
+       mmfile_seek(fp, sizeof(proj_box_data), SEEK_CUR);
+       readed = mmfile_read(fp, (unsigned char *)&prhd_data, sizeof(prhd_box_data));
+       if (readed != sizeof(prhd_box_data)) {
+               debug_error(DEBUG, "read of prhd box failed");
+               return MMFILE_UTIL_FAIL;
+       }
+
+       formatContext->poseYawV2 = mmfile_io_be_uint32(prhd_data.projection_pose_yaw);
+       formatContext->posePitchV2 = mmfile_io_be_uint32(prhd_data.projection_pose_pitch);
+       formatContext->poseRollV2 = mmfile_io_be_uint32(prhd_data.projection_pose_roll);
+
+       debug_error(DEBUG, "formatContext->poseYawV2 = %d", formatContext->poseYawV2);
+       debug_error(DEBUG, "formatContext->posePitchV2 = %d", formatContext->posePitchV2);
+       debug_error(DEBUG, "formatContext->poseRollV2 = %d", formatContext->poseRollV2);
+
+       if (formatContext->projTypeV2 == PROJECTION_TYPE_EQUI) {
+               debug_msg(RELEASE, "Projection type is Equirectangular");
+               mmfile_seek(fp, 8, SEEK_CUR); /* 8 = 4 (for size) + 4 (fourcc) */
+               readed = mmfile_read(fp, (unsigned char *)&equi_data, sizeof(equi_box_data));
+               if (readed != sizeof(equi_box_data)) {
+                       debug_error(DEBUG, "read of equi box failed");
+                       return MMFILE_UTIL_FAIL;
+               }
+
+               formatContext->equiBoundsTopV2 = mmfile_io_be_uint32(equi_data.projection_bounds_top);
+               formatContext->equiBoundsBottomV2 = mmfile_io_be_uint32(equi_data.projection_bounds_bottom);
+               formatContext->equiBoundsLeftV2 = mmfile_io_be_uint32(equi_data.projection_bounds_left);
+               formatContext->equiBoundsRightV2 = mmfile_io_be_uint32(equi_data.projection_bounds_right);
+
+               debug_error(DEBUG, "formatContext->equiBoundsTopV2 = %d", formatContext->equiBoundsTopV2);
+               debug_error(DEBUG, "formatContext->equiBoundsBottomV2 = %d", formatContext->equiBoundsBottomV2);
+               debug_error(DEBUG, "formatContext->equiBoundsLeftV2 = %d", formatContext->equiBoundsLeftV2);
+               debug_error(DEBUG, "formatContext->equiBoundsRightV2 = %d", formatContext->equiBoundsRightV2);
+
+       } else if (formatContext->projTypeV2 == PROJECTION_TYPE_CBMP) {
+               debug_msg(RELEASE, "Projection type is Cubemap");
+               mmfile_seek(fp, 8, SEEK_CUR); /* 8 = 4 (for size) + 4 (fourcc) */
+               readed = mmfile_read(fp, (unsigned char *)&cbmp_data, sizeof(cbmp_box_data));
+               if (readed != sizeof(cbmp_box_data)) {
+                       debug_error(DEBUG, "read of cbmp box failed");
+                       return MMFILE_UTIL_FAIL;
+               }
+
+               formatContext->cbmpLayoutV2 = mmfile_io_be_uint32(cbmp_data.layout);
+               formatContext->cbmpPaddingV2 = mmfile_io_be_uint32(cbmp_data.padding);
+
+               debug_error(DEBUG, "formatContext->cbmpLayoutV2 = %d", formatContext->cbmpLayoutV2);
+               debug_error(DEBUG, "formatContext->cbmpPaddingV2 = %d", formatContext->cbmpPaddingV2);
+
+       } else {
+               debug_msg(RELEASE, "Projection type is %d (unknown)", proj_data.proj_type);
+               return MMFILE_UTIL_FAIL;
+       }
+
+       return MMFILE_UTIL_SUCCESS;
+}
+
+static int GetVideoV2MetadataFromAvc1TagBox(MMFileFormatContext *formatContext, MMFileIOHandle *fp, MMFILE_MP4_BASIC_BOX_HEADER *basic_header)
+{
+       if (!formatContext || !fp || !basic_header) {
+               debug_error(DEBUG, "invalid param");
+               return MMFILE_UTIL_FAIL;
+       }
+
+       unsigned char *buffer;
+       int readed = 0;
+       unsigned int i = 0;
+
+       formatContext->stereoModeV2 = INVALID_UINT_VALUE;
+       formatContext->metadataSourceV2 = NULL;
+       formatContext->projTypeV2 = INVALID_UINT_VALUE;
+       formatContext->poseYawV2 = INVALID_UINT_VALUE;
+       formatContext->posePitchV2 = INVALID_UINT_VALUE;
+       formatContext->poseRollV2 = INVALID_UINT_VALUE;
+       formatContext->cbmpLayoutV2 = INVALID_UINT_VALUE;
+       formatContext->cbmpPaddingV2 = INVALID_UINT_VALUE;
+       formatContext->equiBoundsTopV2 = INVALID_UINT_VALUE;
+       formatContext->equiBoundsBottomV2 = INVALID_UINT_VALUE;
+       formatContext->equiBoundsLeftV2 = INVALID_UINT_VALUE;
+       formatContext->equiBoundsRightV2 = INVALID_UINT_VALUE;
+
+       mmfile_seek(fp, basic_header->start_offset, SEEK_SET);
+
+       buffer = calloc(basic_header->size + 1, sizeof(unsigned char));
+       if (!buffer) {
+               debug_error(DEBUG, "calloc failed ");
+               goto exception;
+       }
+
+       readed = mmfile_read(fp, buffer, basic_header->size);
+       if (readed != (int)basic_header->size) {
+               debug_error(DEBUG, "read st3d box failed");
                goto exception;
        }
 
+       for (i = 0; i + 3 < basic_header->size; ++i) {
+               if ((buffer[i] == 's' && buffer[i + 1] == 't' && buffer[i + 2] == '3' && buffer[i + 3] == 'd') && (formatContext->stereoModeV2 == INVALID_UINT_VALUE)) {
+                       debug_warning(DEBUG, "st3d data found at offset %lld", basic_header->start_offset + i);
+                       ParseSt3dData(formatContext, fp, basic_header->start_offset + i + 4);
+                       debug_msg(RELEASE, "formatContext->stereoModeV2 = %d", formatContext->stereoModeV2);
+               }
+               if (buffer[i] == 's' && buffer[i + 1] == 'v' && buffer[i + 2] == '3' && buffer[i + 3] == 'd') {
+                       debug_warning(DEBUG, "sv3d data found at offset %lld", basic_header->start_offset + i);
+                       formatContext->isSpherical = true;
+               }
+               if (buffer[i] == 's' && buffer[i + 1] == 'v' && buffer[i + 2] == 'h' && buffer[i + 3] == 'd') {
+                       debug_warning(DEBUG, "svhd data found at offset %lld", basic_header->start_offset + i);
+                       ParseSvhdData(formatContext, fp, basic_header->start_offset + i + 4, mmfile_io_be_uint32(*((uint32_t*)(buffer - 4 + i))));
+                       debug_msg(RELEASE, "formatContext->metadataSourceV2 = %s (length = %zu)", formatContext->metadataSourceV2, strlen(formatContext->metadataSourceV2));
+               }
+               if (buffer[i] == 'p' && buffer[i + 1] == 'r' && buffer[i + 2] == 'o' && buffer[i + 3] == 'j') {
+                       debug_warning(DEBUG, "proj data found at offset %lld", basic_header->start_offset + i);
+                       ParseProjData(formatContext, fp, basic_header->start_offset + i + 4);
+               }
+       }
+
        return MMFILE_UTIL_SUCCESS;
 
 exception:
@@ -771,29 +1298,25 @@ static int GetValueFromCDISTagBox(MMFileFormatContext *formatContext, MMFileIOHa
        int readed = 0;
 
        if (!formatContext || !fp || !basic_header) {
-               debug_error("invalid param\n");
+               debug_error(DEBUG, "invalid param");
                return MMFILE_UTIL_FAIL;
        }
 
        readed = mmfile_read(fp, (unsigned char *)&value, sizeof(unsigned int));
        if (readed != sizeof(unsigned int)) {
-               debug_error("read cdis tag header fail\n");
+               debug_error(DEBUG, "read cdis tag header fail");
                goto exception;
        }
 
        value = mmfile_io_be_uint32(value);
 
-#ifdef __MMFILE_TEST_MODE__
-       debug_msg("Value : 0x%x", value);
-#endif
+       debug_msg(RELEASE, "Value : 0x%x", value);
 
        if (value == 0x01) {
-#ifdef __MMFILE_TEST_MODE__
-               debug_msg("This has cdis tag and valid value");
-#endif
+               debug_msg(RELEASE, "This has cdis tag and valid value");
                formatContext->cdis = 1;
        } else {
-               debug_error("This has cdis tag and but invalid value");
+               debug_error(DEBUG, "This has cdis tag and but invalid value");
                goto exception;
        }
 
@@ -817,7 +1340,6 @@ static int GetTagFromMetaBox(MMFileFormatContext *formatContext, MMFileIOHandle
        int id3v2Len = 0;
        unsigned int meta_version = 0;
        MMFILE_3GP_HANDLER_BOX hdlrBox = {0, };
-       unsigned int encSize = 0;
        int id3_meta = 0;
 #ifdef ENABLE_ITUNES_META /* We don't support itunes meta now. so this is not defined yet */
        int iTunes_meta = 0;
@@ -826,19 +1348,19 @@ static int GetTagFromMetaBox(MMFileFormatContext *formatContext, MMFileIOHandle
        /* meta box */
        readed = mmfile_read(fp, (unsigned char *)&meta_version, 4);
        if (readed != 4) {
-               debug_error("read meta box version\n");
+               debug_error(DEBUG, "read meta box version");
                goto exception;
        }
 
        /* hdlr box */
        readed = mmfile_read(fp, (unsigned char *)&hdlrBoxHeader, MMFILE_MP4_BASIC_BOX_HEADER_LEN);
        if (readed != MMFILE_MP4_BASIC_BOX_HEADER_LEN) {
-               debug_error("read hdlr box header\n");
+               debug_error(DEBUG, "read hdlr box header");
                goto exception;
        }
 
        if (hdlrBoxHeader.type != FOURCC('h', 'd', 'l', 'r')) {
-               debug_warning("meta type is not hdlr\n");
+               debug_warning(DEBUG, "meta type is not hdlr");
                goto exception;
        }
 
@@ -847,7 +1369,7 @@ static int GetTagFromMetaBox(MMFileFormatContext *formatContext, MMFileIOHandle
 
        readed = mmfile_read(fp, (unsigned char *)&hdlrBox, MMFILE_3GP_HANDLER_BOX_LEN);
        if (readed != MMFILE_3GP_HANDLER_BOX_LEN) {
-               debug_error("read hdlr box\n");
+               debug_error(DEBUG, "read hdlr box");
                goto exception;
        }
 
@@ -857,9 +1379,7 @@ static int GetTagFromMetaBox(MMFileFormatContext *formatContext, MMFileIOHandle
         * check tag type (ID3v2 or iTunes)
         */
        if (hdlrBox.handler_type == FOURCC('I', 'D', '3', '2')) {
-#ifdef __MMFILE_TEST_MODE__
-               debug_msg("ID3v2 tag detected.\n");
-#endif
+               debug_msg(RELEASE, "ID3v2 tag detected.");
 
                id3_meta = 1;
 #ifdef ENABLE_ITUNES_META
@@ -868,15 +1388,13 @@ static int GetTagFromMetaBox(MMFileFormatContext *formatContext, MMFileIOHandle
        } else if (hdlrBox.handler_type == FOURCC('m', 'd', 'i', 'r') &&
                                mmfile_io_le_uint32(hdlrBox.reserved[0]) == FOURCC('a', 'p', 'p', 'l')) {
 
-#ifdef __MMFILE_TEST_MODE__
-               debug_msg("Apple iTunes tag detected by mdir.\n");
-#endif
+               debug_msg(RELEASE, "Apple iTunes tag detected by mdir.");
 
 #ifdef ENABLE_ITUNES_META
                iTunes_meta = 1;
 #endif
        } else {
-               debug_warning("unknown meta type. 4CC:[%c%c%c%c]\n", ((char *)&hdlrBox.handler_type)[0],
+               debug_warning(DEBUG, "unknown meta type. 4CC:[%c%c%c%c]", ((char *)&hdlrBox.handler_type)[0],
                                        ((char *)&hdlrBox.handler_type)[1],
                                        ((char *)&hdlrBox.handler_type)[2],
                                        ((char *)&hdlrBox.handler_type)[3]);
@@ -901,15 +1419,12 @@ static int GetTagFromMetaBox(MMFileFormatContext *formatContext, MMFileIOHandle
 
                readed = mmfile_read(fp, read_buf, buf_size);   /* to find 'ilst' */
                if (readed != buf_size) {
-                       debug_error("read fail [%d]\n", readed);
+                       debug_error(DEBUG, "read fail [%d]", readed);
                        goto exception;
                }
 
                if (read_buf[0] == 'i' && read_buf[1] == 'l' && read_buf[2] == 's' && read_buf[3] == 't') {
-#ifdef __MMFILE_TEST_MODE__
-                       debug_msg("Apple iTunes tag detected by ilst.\n");
-#endif
-
+                       debug_msg(RELEASE, "Apple iTunes tag detected by ilst.");
                        iTunes_meta = 1;
                }
        }
@@ -962,9 +1477,7 @@ static int GetTagFromMetaBox(MMFileFormatContext *formatContext, MMFileIOHandle
                                artist_offset = mmfile_tell(fp);
                                artist_sz = mmfile_io_be_uint32(*(int *)(read_buf + 4)) - 16; /* atom len(4)+data(4)+atom verion(1)+flag(3)+null(4) = 16 */
 
-#ifdef __MMFILE_TEST_MODE__
-                               debug_msg("----------------------------------- artist found, offset=[%lld], size=[%d]\n", artist_offset, artist_sz);
-#endif
+                               debug_msg(RELEASE, "----------------------------------- artist found, offset=[%lld], size=[%d]", artist_offset, artist_sz);
                        }
 
                        /**
@@ -977,9 +1490,7 @@ static int GetTagFromMetaBox(MMFileFormatContext *formatContext, MMFileIOHandle
                                track_found = 1;
                                track_offset = mmfile_tell(fp);
 
-#ifdef __MMFILE_TEST_MODE__
-                               debug_msg("----------------------------------- Track found, offset=[%lld]\n", track_offset);
-#endif
+                               debug_msg(RELEASE, "----------------------------------- Track found, offset=[%lld]", track_offset);
                        }
 
                        /**
@@ -993,9 +1504,7 @@ static int GetTagFromMetaBox(MMFileFormatContext *formatContext, MMFileIOHandle
                                genre_found = 1;
                                genre_offset = mmfile_tell(fp);
 
-#ifdef __MMFILE_TEST_MODE__
-                               debug_msg("----------------------------------- genre found, offset=[%lld]\n", genre_offset);
-#endif
+                               debug_msg(RELEASE, "----------------------------------- genre found, offset=[%lld]", genre_offset);
                        }
 #endif
 
@@ -1013,41 +1522,34 @@ static int GetTagFromMetaBox(MMFileFormatContext *formatContext, MMFileIOHandle
 
                                cover_offset = mmfile_tell(fp);
 
-#ifdef __MMFILE_TEST_MODE__
-                               debug_msg("----------------------------------- cover_found found,  offset=[%lld]\n", cover_offset);
-#endif
+                               debug_msg(RELEASE, "----------------------------------- cover_found found,  offset=[%lld]", cover_offset);
                        }
 
                        mmfile_seek(fp, -(_ITUNES_READ_BUF_SZ - 1), SEEK_CUR);  /*FIXME: poor search*/
                } /*loop*/
 
-               /*ffmpeg extract artist, tracknum, excep cover image. see mov_read_udta_string()*/
+               /*ffmpeg extract artist, tracknum, except cover image. see mov_read_udta_string()*/
 #if 0
                if (artist_found) {
                        if (artist_sz > 0) {
                                mmfile_seek(fp, artist_offset, SEEK_SET);
 
                                if (formatContext->artist) {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("----------------------------------- previous artist was [%s] \n", formatContext->artist);
-#endif
+                                       debug_msg(RELEASE, "----------------------------------- previous artist was [%s] ", formatContext->artist);
                                        free(formatContext->artist);
                                }
-#ifdef __MMFILE_TEST_MODE__
-                               debug_msg("----------------------------------- new artist will be allocated with size (len+1) [%d] \n", artist_sz + 1);
-#endif
-                               formatContext->artist = mmfile_malloc(artist_sz + 1);
+
+                               debug_msg(RELEASE, "----------------------------------- new artist will be allocated with size (len+1) [%d] ", artist_sz + 1);
+                               formatContext->artist = g_malloc0(artist_sz + 1);
 
                                if (formatContext->artist) {
                                        readed = mmfile_read(fp, (unsigned char *)formatContext->artist, artist_sz);
                                        formatContext->artist[artist_sz] = '\0';
 
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("----------------------------------- new artist is [%s] \n", formatContext->artist);
-#endif
+                                       debug_msg(RELEASE, "----------------------------------- new artist is [%s] ", formatContext->artist);
 
                                        if (readed != artist_sz) {
-                                               debug_error("failed to read. ret = %d, in = %d\n", readed, artist_sz);
+                                               debug_error(DEBUG, "failed to read. ret = %d, in = %d", readed, artist_sz);
                                                mmfile_free(formatContext->artist);
                                        }
                                }
@@ -1058,13 +1560,13 @@ static int GetTagFromMetaBox(MMFileFormatContext *formatContext, MMFileIOHandle
                        mmfile_seek(fp, track_offset, SEEK_SET);
                        readed = mmfile_read(fp, read_buf, _ITUNES_TRACK_NUM_SZ);
                        if (readed != _ITUNES_TRACK_NUM_SZ) {
-                               debug_error("failed to read. ret = %d, in = %d\n", readed, _ITUNES_TRACK_NUM_SZ);
+                               debug_error(DEBUG, "failed to read. ret = %d, in = %d", readed, _ITUNES_TRACK_NUM_SZ);
                        } else {
                                track_num = mmfile_io_be_uint32(*(int *)read_buf);
                                if (!formatContext->tagTrackNum) {
                                        memset(read_buf, 0x00, _ITUNES_READ_BUF_SZ);
                                        snprintf((char *)read_buf, sizeof(read_buf), "%d", track_num);
-                                       formatContext->tagTrackNum = mmfile_strdup((const char *)read_buf);
+                                       formatContext->tagTrackNum = g_strdup((const char *)read_buf);
                                }
                        }
                }
@@ -1073,20 +1575,17 @@ static int GetTagFromMetaBox(MMFileFormatContext *formatContext, MMFileIOHandle
                        mmfile_seek(fp, genre_offset, SEEK_SET);
                        readed = mmfile_read(fp, read_buf, _ITUNES_GENRE_NUM_SZ);
                        if (readed != _ITUNES_GENRE_NUM_SZ) {
-                               debug_error("failed to read. ret = %d, in = %d\n", readed, _ITUNES_GENRE_NUM_SZ);
+                               debug_error(DEBUG, "failed to read. ret = %d, in = %d", readed, _ITUNES_GENRE_NUM_SZ);
                        } else {
                                genre_index = mmfile_io_be_uint16(*(int *)read_buf);
-#ifdef __MMFILE_TEST_MODE__
-                               debug_msg("genre index=[%d] \n", genre_index);
-#endif
+                               debug_msg(RELEASE, "genre index=[%d] ", genre_index);
+
                                if (genre_index > 0 && genre_index < GENRE_COUNT)       {
                                        if (!formatContext->genre) {
                                                memset(read_buf, 0x00, _ITUNES_READ_BUF_SZ);
                                                snprintf((char *)read_buf, sizeof(read_buf), "%s", MpegAudio_Genre[genre_index - 1]);
-#ifdef __MMFILE_TEST_MODE__
-                                               debug_msg("genre string=[%s] \n", read_buf);
-#endif
-                                               formatContext->genre = mmfile_strdup((const char *)read_buf);
+                                               debug_msg(RELEASE, "genre string=[%s] ", read_buf);
+                                               formatContext->genre = g_strdup((const char *)read_buf);
                                        }
                                }
                        }
@@ -1110,23 +1609,23 @@ static int GetTagFromMetaBox(MMFileFormatContext *formatContext, MMFileIOHandle
                        if (cover_sz > 0) {
                                mmfile_seek(fp, cover_offset, SEEK_SET);
 
-                               formatContext->artwork = mmfile_malloc(cover_sz);
+                               formatContext->artwork = g_malloc0(cover_sz);
                                formatContext->artworkSize = cover_sz;
                                if (cover_type == _ITUNES_COVER_TYPE_JPEG) {
-                                       formatContext->artworkMime = mmfile_strdup("image/jpeg");
+                                       formatContext->artworkMime = g_strdup("image/jpeg");
                                } else if (cover_type == _ITUNES_COVER_TYPE_PNG) {
-                                       formatContext->artworkMime = mmfile_strdup("image/png");
-                                       /*} else if(cover_type == _ITUNES_COVER_TYPE_TIF) {
-                                               formatContext->artworkMime = mmfile_strdup("image/tif");*/
+                                       formatContext->artworkMime = g_strdup("image/png");
+                                       /*} else if (cover_type == _ITUNES_COVER_TYPE_TIF) {
+                                               formatContext->artworkMime = g_strdup("image/tif");*/
                                } else {
-                                       debug_warning("Not proper cover image type, but set to jpeg. cover_type[%d]", cover_type);
-                                       formatContext->artworkMime = mmfile_strdup("image/jpeg");
+                                       debug_warning(DEBUG, "Not proper cover image type, but set to jpeg. cover_type[%d]", cover_type);
+                                       formatContext->artworkMime = g_strdup("image/jpeg");
                                }
 
                                if (formatContext->artwork) {
                                        readed = mmfile_read(fp, formatContext->artwork, cover_sz);
                                        if (readed != cover_sz) {
-                                               debug_error("failed to read. ret = %d, in = %d\n", readed, cover_sz);
+                                               debug_error(DEBUG, "failed to read. ret = %d, in = %d", readed, cover_sz);
                                                mmfile_free(formatContext->artwork);
                                                formatContext->artworkSize = 0;
                                                mmfile_free(formatContext->artworkMime);
@@ -1152,7 +1651,7 @@ static int GetTagFromMetaBox(MMFileFormatContext *formatContext, MMFileIOHandle
                        /* id3 tag box */
                        readed = mmfile_read(fp, (unsigned char *)&id3v2BoxHeader, MMFILE_MP4_BASIC_BOX_HEADER_LEN);
                        if (readed != MMFILE_MP4_BASIC_BOX_HEADER_LEN) {
-                               debug_error("read id3v2 box header\n");
+                               debug_error(DEBUG, "read id3v2 box header");
                                goto exception;
                        }
 
@@ -1160,100 +1659,89 @@ static int GetTagFromMetaBox(MMFileFormatContext *formatContext, MMFileIOHandle
                        id3v2BoxHeader.type = mmfile_io_le_uint32(id3v2BoxHeader.type);
 
                        if (id3v2BoxHeader.type != FOURCC('I', 'D', '3', '2')) {
-                               debug_warning("meta type is not id3v2\n");
+                               debug_warning(DEBUG, "meta type is not id3v2");
                                goto exception;
                        }
 
                        readed = mmfile_read(fp, (unsigned char *)&id3v2Box, MMFILE_3GP_ID3V2_BOX_LEN);
                        if (readed != MMFILE_3GP_ID3V2_BOX_LEN) {
-                               debug_error("read id3v2 box\n");
+                               debug_error(DEBUG, "read id3v2 box");
                                goto exception;
                        }
 
                        id3v2Len = id3v2BoxHeader.size - MMFILE_MP4_BASIC_BOX_HEADER_LEN - MMFILE_3GP_ID3V2_BOX_LEN;
 
-                       id3v2Box.id3v2Data = mmfile_malloc(id3v2Len);
-                       if (!id3v2Box.id3v2Data) {
-                               debug_error("malloc id3tag data error\n");
-                               goto exception;
-                       }
+                       id3v2Box.id3v2Data = g_malloc0(id3v2Len);
 
                        readed = mmfile_read(fp, (unsigned char *)id3v2Box.id3v2Data, id3v2Len);
                        if (readed != id3v2Len) {
-                               debug_error("read id3tag data error\n");
+                               debug_error(DEBUG, "read id3tag data error");
                                goto exception;
                        }
 
                        /* check id3v2 */
                        if (!IS_ID3V2_TAG(id3v2Box.id3v2Data)) {
-                               debug_error("it is not id3tag\n");
+                               debug_error(DEBUG, "it is not id3tag");
                                goto exception;
                        }
 
                        if (id3v2Box.id3v2Data[3] == 0xFF ||  id3v2Box.id3v2Data[4] == 0xFF ||
                            id3v2Box.id3v2Data[6] >= 0x80 ||  id3v2Box.id3v2Data[7] >= 0x80 ||
                            id3v2Box.id3v2Data[8] >= 0x80 ||  id3v2Box.id3v2Data[9] >= 0x80) {
-                               debug_error("it is not valid id3tag\n");
+                               debug_error(DEBUG, "it is not valid id3tag");
                                goto exception;
                        }
 
                        tagVersion = id3v2Box.id3v2Data[3];
                        if (tagVersion > 4) {
-                               debug_error("tag vesion is too high\n");
+                               debug_error(DEBUG, "tag version is too high");
                                goto exception;
                        }
 
-                       encSize = mmfile_io_le_uint32((unsigned int)&id3v2Box.id3v2Data[6]);
                        tagInfo.tagV2Info.tagLen = MP3_TAGv2_HEADER_LEN;
-                       tagInfo.tagV2Info.tagLen += (((encSize & 0x0000007F) >> 0) | ((encSize & 0x00007F00) >> 1) | ((encSize & 0x007F0000) >> 2) | ((encSize & 0x7F000000) >> 3));
+                       tagInfo.tagV2Info.tagLen += (((id3v2Box.id3v2Data[6] & 0x7F) << 21) | ((id3v2Box.id3v2Data[7] & 0x7F) << 14) | ((id3v2Box.id3v2Data[8] & 0x7F) << 7) | ((id3v2Box.id3v2Data[9] & 0x7F)));
                        tagInfo.tagV2Info.tagVersion = tagVersion;
                        tagInfo.fileLen = id3v2Len;
 
                        /* set id3v2 data to formatContext */
                        switch (tagVersion) {
-                               case 2: {
-                                               versionCheck = mm_file_id3tag_parse_v222(&tagInfo, id3v2Box.id3v2Data);
-                                               break;
-                                       }
-                               case 3: {
-                                               versionCheck = mm_file_id3tag_parse_v223(&tagInfo, id3v2Box.id3v2Data);
-                                               break;
-                                       }
-                               case 4: {
-                                               versionCheck = mm_file_id3tag_parse_v224(&tagInfo, id3v2Box.id3v2Data);
-                                               break;
-                                       }
-                               case 1:
-                               default: {
-                                               debug_error("tag vesion is not support\n");
-                                               versionCheck = false;
-                                               break;
-                                       }
+                       case 2:
+                               versionCheck = mm_file_id3tag_parse_v222(&tagInfo, id3v2Box.id3v2Data, formatContext->extract_artwork);
+                               break;
+                       case 3:
+                               versionCheck = mm_file_id3tag_parse_v223(&tagInfo, id3v2Box.id3v2Data, formatContext->extract_artwork);
+                               break;
+                       case 4:
+                               versionCheck = mm_file_id3tag_parse_v224(&tagInfo, id3v2Box.id3v2Data, formatContext->extract_artwork);
+                               break;
+                       case 1:
+                       default:
+                               debug_error(DEBUG, "tag vesion is not support");
+                               versionCheck = false;
+                               break;
                        }
 
                        if (versionCheck == false) {
-                               debug_error("tag parsing is fail\n");
+                               debug_error(DEBUG, "tag parsing is fail");
                                goto exception;
                        }
 
-                       if (!formatContext->title)          formatContext->title = mmfile_strdup((const char *)tagInfo.pTitle);
-                       if (!formatContext->artist)         formatContext->artist = mmfile_strdup((const char *)tagInfo.pArtist);
-                       if (!formatContext->author)         formatContext->author = mmfile_strdup((const char *)tagInfo.pAuthor);
-                       if (!formatContext->copyright)      formatContext->copyright = mmfile_strdup((const char *)tagInfo.pCopyright);
-                       if (!formatContext->comment)        formatContext->comment = mmfile_strdup((const char *)tagInfo.pComment);
-                       if (!formatContext->album)          formatContext->album = mmfile_strdup((const char *)tagInfo.pAlbum);
-                       if (!formatContext->album_artist)   formatContext->album_artist = mmfile_strdup((const char *)tagInfo.pAlbum_Artist);
-                       if (!formatContext->year)           formatContext->year = mmfile_strdup((const char *)tagInfo.pYear);
-                       if (!formatContext->genre)          formatContext->genre = mmfile_strdup((const char *)tagInfo.pGenre);
-                       if (!formatContext->tagTrackNum)    formatContext->tagTrackNum = mmfile_strdup((const char *)tagInfo.pTrackNum);
-                       if (!formatContext->composer)       formatContext->composer = mmfile_strdup((const char *)tagInfo.pComposer);
-                       if (!formatContext->classification) formatContext->classification = mmfile_strdup((const char *)tagInfo.pContentGroup);
-                       if (!formatContext->conductor)      formatContext->conductor = mmfile_strdup((const char *)tagInfo.pConductor);
-
-                       formatContext->artwork = mmfile_malloc(tagInfo.imageInfo.imageLen);
-                       if ((tagInfo.imageInfo.imageLen > 0) && formatContext->artwork) {
+                       formatContext->title = g_strdup((const char *)tagInfo.tagInfo[AV_ID3TAG_TITLE].value);
+                       formatContext->artist = g_strdup((const char *)tagInfo.tagInfo[AV_ID3TAG_ARTIST].value);
+                       formatContext->copyright = g_strdup((const char *)tagInfo.tagInfo[AV_ID3TAG_COPYRIGHT].value);
+                       formatContext->comment = g_strdup((const char *)tagInfo.tagInfo[AV_ID3TAG_COMMENT].value);
+                       formatContext->album = g_strdup((const char *)tagInfo.tagInfo[AV_ID3TAG_ALBUM].value);
+                       formatContext->album_artist = g_strdup((const char *)tagInfo.tagInfo[AV_ID3TAG_ALBUM_ARTIST].value);
+                       formatContext->year = g_strdup((const char *)tagInfo.tagInfo[AV_ID3TAG_YEAR].value);
+                       formatContext->genre = g_strdup((const char *)tagInfo.tagInfo[AV_ID3TAG_GENRE].value);
+                       formatContext->tagTrackNum = g_strdup((const char *)tagInfo.tagInfo[AV_ID3TAG_TRACKNUM].value);
+                       formatContext->composer = g_strdup((const char *)tagInfo.tagInfo[AV_ID3TAG_COMPOSER].value);
+                       formatContext->classification = g_strdup((const char *)tagInfo.tagInfo[AV_ID3TAG_CONTENT_GROUP].value);
+                       formatContext->conductor = g_strdup((const char *)tagInfo.tagInfo[AV_ID3TAG_CONDUCTOR].value);
+
+                       if (tagInfo.imageInfo.pImageBuf && tagInfo.imageInfo.imageLen > 0) {
                                formatContext->artworkSize = tagInfo.imageInfo.imageLen;
-                               memcpy(formatContext->artwork, tagInfo.imageInfo.pImageBuf, tagInfo.imageInfo.imageLen);
+                               formatContext->artwork = g_memdup2(tagInfo.imageInfo.pImageBuf, tagInfo.imageInfo.imageLen);
                        }
 
                        mm_file_free_AvFileContentInfo(&tagInfo);
@@ -1275,167 +1763,497 @@ exception:
        return MMFILE_UTIL_FAIL;
 }
 
+int mm_file_get_int_value_from_xml_string(const char* xml_str, const char* param_name, int* value)
+{
+       char *value_start, *value_end, *endptr;
+       const short value_length_max = 12;
+       char init_view_ret[value_length_max];
+       int value_length = 0;
 
-#define BIG_CONTENT_BOX_SIZE_LEN 8
-EXPORT_API int MMFileUtilGetMetaDataFromMP4(MMFileFormatContext *formatContext)
+       if (!xml_str || !param_name || !strstr(xml_str, param_name)) {
+               debug_error(DEBUG, "error: incorrect or non-existing parameter");
+               return MMFILE_UTIL_FAIL;
+       }
+
+       value_start = strstr(xml_str, param_name) + strlen(param_name);
+       while ((value_start[0] == ' ') || (value_start[0] == '\t'))
+               value_start++;
+
+       value_end = strchr(value_start, '<');
+       if (!value_end) {
+               debug_error(DEBUG, "error: incorrect XML");
+               return MMFILE_UTIL_FAIL;
+       }
+
+       value_length = value_end - value_start;
+       while ((value_length >= 1) && ((value_start[value_length - 1] == ' ') || (value_start[value_length - 1] == '\t')))
+               value_length--;
+
+       int i = 0;
+       if (value_start[i] == '+' || value_start[i] == '-')
+                       i++;
+       while (i < value_length) {
+               if (value_start[i] < '0' || value_start[i] > '9') {
+                       debug_error(DEBUG, "error: incorrect value, integer was expected");
+                       return MMFILE_UTIL_FAIL;
+               }
+               i++;
+       }
+
+       if (value_length >= value_length_max || value_length < 1) {
+               debug_error(DEBUG, "error: empty XML value or incorrect range");
+               return MMFILE_UTIL_FAIL;
+       }
+
+       memset(init_view_ret, 0x00, value_length_max);
+       if (g_strlcpy(init_view_ret, value_start, value_length_max) >= value_length_max) {
+               debug_error(DEBUG, "error: truncation occurred");
+               return MMFILE_UTIL_FAIL;
+       }
+
+
+       *value = strtol(init_view_ret, &endptr, 10);
+       if (endptr == init_view_ret) {
+               debug_error(DEBUG, "error: no digits were found");
+               return MMFILE_UTIL_FAIL;
+       }
+
+       return MMFILE_UTIL_SUCCESS;
+}
+
+int mm_file_get_string_value_from_xml_string(const char* xml_str, const char* param_name, char** value)
 {
-       MMFileIOHandle *fp = NULL;
-       int ret = 0;
-       int readed;
-       unsigned long long chunk_size = 0;
+       char *value_start, *value_end;
+       const short value_length_max = 256;
+       int value_length = 0;
 
-       ret = mmfile_open(&fp, formatContext->uriFileName, MMFILE_RDONLY);
-       if (ret == MMFILE_UTIL_FAIL) {
-               debug_error("error: mmfile_open\n");
-               goto exit;
+       if (!xml_str || !param_name || !strstr(xml_str, param_name)) {
+               debug_error(DEBUG, "error: incorrect or non-existing parameter");
+               return MMFILE_UTIL_FAIL;
        }
 
-       MMFILE_MP4_BASIC_BOX_HEADER basic_header = {0, };
-       basic_header.start_offset = mmfile_tell(fp);
+       value_start = strstr(xml_str, param_name) + strlen(param_name);
+       while ((value_start[0] == ' ') || (value_start[0] == '\t'))
+               value_start++;
 
-       while ((ret != MMFILE_UTIL_FAIL) && ((readed = mmfile_read(fp, (unsigned char *)&basic_header, MMFILE_MP4_BASIC_BOX_HEADER_LEN)) > 0)) {
-               basic_header.size = mmfile_io_be_uint32(basic_header.size);
-               basic_header.type = mmfile_io_le_uint32(basic_header.type);
+       value_end = strchr(value_start, '<');
+       if (!value_end) {
+               debug_error(DEBUG, "error: incorrect XML");
+               return MMFILE_UTIL_FAIL;
+       }
 
-               if (basic_header.size == 0) {
-                       debug_warning("header is invalid.\n");
-                       basic_header.size = readed;
-                       basic_header.type = 0;
-                       chunk_size = basic_header.size;
-               } else if (basic_header.size == 1) {
-                       int i = 0;
-                       unsigned char temp[BIG_CONTENT_BOX_SIZE_LEN] = {0, };
-                       unsigned long long size = 0;
+       value_length = value_end - value_start;
+       while ((value_length >= 1) && ((value_start[value_length - 1] == ' ') || (value_start[value_length - 1] == '\t')))
+               value_length--;
 
-                       mmfile_read(fp, (unsigned char *)&temp, BIG_CONTENT_BOX_SIZE_LEN);
+       if (value_length >= value_length_max || value_length < 1) {
+               debug_error(DEBUG, "error: empty XML value or incorrect range");
+               return MMFILE_UTIL_FAIL;
+       }
 
-                       for(i = 0; i < BIG_CONTENT_BOX_SIZE_LEN; i++)
-                               size |= (unsigned long long)temp[i] << (BIG_CONTENT_BOX_SIZE_LEN - 1 - i) * BIG_CONTENT_BOX_SIZE_LEN;
-                       chunk_size = size;
-               } else {
-                       chunk_size = basic_header.size;
-               }
+       *value = (char*)calloc(value_length, sizeof(char));
+       if (*value == NULL) {
+               debug_error(DEBUG, "error: calloc failed");
+               return MMFILE_UTIL_FAIL;
+       }
+       strncpy(*value, value_start, value_length);
 
-#ifdef __MMFILE_TEST_MODE__
-               debug_msg("START_OFFSET:[%lld] SIZE:[%d Byte] 4CC:[%c%c%c%c]\n",
-                               basic_header.start_offset, basic_header.size,
-                               ((char *)&basic_header.type)[0], ((char *)&basic_header.type)[1],
-                               ((char *)&basic_header.type)[2], ((char *)&basic_header.type)[3]);
-#endif
+       return MMFILE_UTIL_SUCCESS;
+}
 
-               switch (basic_header.type) {
+int mm_file_get_bool_value_from_xml_string(const char* xml_str, const char* param_name, bool* value)
+{
+       char *value_start = NULL;
+       char *value_end = NULL;
+       int value_length = 0;
+
+       if (!xml_str || !param_name || !strstr(xml_str, param_name)) {
+               debug_error(DEBUG, "error: incorrect or non-existing parameter");
+               return MMFILE_UTIL_FAIL;
+       }
+
+       value_start = strstr(xml_str, param_name) + strlen(param_name);
+       while ((value_start != NULL) && ((value_start[0] == ' ') || (value_start[0] == '\t')))
+               value_start++;
+
+       value_end = strchr(value_start, '<');
+       if (value_end == NULL) {
+               debug_error(DEBUG, "error: incorrect XML.");
+               return MMFILE_UTIL_FAIL;
+       }
+
+       value_length = value_end - value_start;
+       while ((value_length >= 1) && ((value_start[value_length - 1] == ' ') || (value_start[value_length - 1] == '\t')))
+               value_length--;
+
+       if (value_length < 1) {
+               debug_error(DEBUG, "error: empty XML value or incorrect range");
+               return MMFILE_UTIL_FAIL;
+       }
+
+       *value = strstr(value_start, "true") ? true : false;
+
+       return MMFILE_UTIL_SUCCESS;
+}
+
+int ParseSpatialVideoMetadataFromXMLString(const char *xmlStr, MMFileFormatContext *formatContext)
+{
+       const char is_spherical_str[] = "<GSpherical:Spherical>";
+       const char is_stitched_str[] = "<GSpherical:Stitched>";
+       const char stitching_software_str[] = "<GSpherical:StitchingSoftware>";
+       const char projection_type_str[] = "<GSpherical:ProjectionType>";
+       const char stereo_mode_str[] = "<GSpherical:StereoMode>";
+       const char source_count_str[] = "<GSpherical:SourceCount>";
+       const char init_view_heading_str[] = "<GSpherical:InitialViewHeadingDegrees>";
+       const char init_view_pitch_str[] = "<GSpherical:InitialViewPitchDegrees>";
+       const char init_view_roll_str[] = "<GSpherical:InitialViewRollDegrees>";
+       const char timestamp_str[] = "<GSpherical:Timestamp>";
+       const char full_pano_width_str[] = "<GSpherical:FullPanoWidthPixels>";
+       const char full_pano_height_str[] = "<GSpherical:FullPanoHeightPixels>";
+       const char cropped_area_image_width_str[] = "<GSpherical:CroppedAreaImageWidthPixels>";
+       const char cropped_area_image_height_str[] = "<GSpherical:CroppedAreaImageHeightPixels>";
+       const char cropped_area_left_str[] = "<GSpherical:CroppedAreaLeftPixels>";
+       const char cropped_area_top_str[] = "<GSpherical:CroppedAreaTopPixels>";
+
+       mm_file_get_bool_value_from_xml_string(xmlStr, is_spherical_str, (bool*)&formatContext->isSpherical);
+       mm_file_get_bool_value_from_xml_string(xmlStr, is_stitched_str, (bool*)&formatContext->isStitched);
+
+       debug_msg(RELEASE, "isSpherical = %d", formatContext->isSpherical);
+       debug_msg(RELEASE, "isStitched = %d", formatContext->isStitched);
+
+       if (formatContext->isSpherical && formatContext->isStitched) {
+               mm_file_get_string_value_from_xml_string(xmlStr, stitching_software_str, &formatContext->stitchingSoftware);
+               mm_file_get_string_value_from_xml_string(xmlStr, projection_type_str, &formatContext->projectionType);
+               mm_file_get_string_value_from_xml_string(xmlStr, stereo_mode_str, &formatContext->stereoMode);
+               mm_file_get_int_value_from_xml_string(xmlStr, source_count_str, &formatContext->sourceCount);
+               mm_file_get_int_value_from_xml_string(xmlStr, init_view_heading_str, &formatContext->initViewHeading);
+               mm_file_get_int_value_from_xml_string(xmlStr, init_view_pitch_str, &formatContext->initViewPitch);
+               mm_file_get_int_value_from_xml_string(xmlStr, init_view_roll_str, &formatContext->initViewRoll);
+               mm_file_get_int_value_from_xml_string(xmlStr, timestamp_str, &formatContext->timestamp);
+               mm_file_get_int_value_from_xml_string(xmlStr, full_pano_width_str, &formatContext->fullPanoWidth);
+               mm_file_get_int_value_from_xml_string(xmlStr, full_pano_height_str, &formatContext->fullPanoHeight);
+               mm_file_get_int_value_from_xml_string(xmlStr, cropped_area_image_width_str, &formatContext->croppedAreaImageWidth);
+               mm_file_get_int_value_from_xml_string(xmlStr, cropped_area_image_height_str, &formatContext->croppedAreaImageHeight);
+               mm_file_get_int_value_from_xml_string(xmlStr, cropped_area_left_str, &formatContext->croppedAreaLeft);
+               mm_file_get_int_value_from_xml_string(xmlStr, cropped_area_top_str, &formatContext->croppedAreaTop);
+
+               debug_msg(RELEASE, "stitchingSoftware = %s", formatContext->stitchingSoftware);
+               debug_msg(RELEASE, "projectionType = %s", formatContext->projectionType);
+               debug_msg(RELEASE, "stereoMode = %s", formatContext->stereoMode);
+               debug_msg(RELEASE, "sourceCount %d", formatContext->sourceCount);
+               debug_msg(RELEASE, "initViewHeading = %d", formatContext->initViewHeading);
+               debug_msg(RELEASE, "initViewPitch = %d", formatContext->initViewPitch);
+               debug_msg(RELEASE, "initViewRoll = %d", formatContext->initViewRoll);
+               debug_msg(RELEASE, "timestamp = %d", formatContext->timestamp);
+               debug_msg(RELEASE, "fullPanoWidthPixels = %d", formatContext->fullPanoWidth);
+               debug_msg(RELEASE, "fullPanoHeightPixels = %d", formatContext->fullPanoHeight);
+               debug_msg(RELEASE, "croppedAreaImageWidth = %d", formatContext->croppedAreaImageWidth);
+               debug_msg(RELEASE, "croppedAreaImageHeight = %d", formatContext->croppedAreaImageHeight);
+               debug_msg(RELEASE, "croppedAreaLeft = %d", formatContext->croppedAreaLeft);
+               debug_msg(RELEASE, "croppedAreaTop = %d", formatContext->croppedAreaTop);
+       }
+
+       return MMFILE_UTIL_SUCCESS;
+}
+
+#define BIG_CONTENT_BOX_SIZE_LEN 8
+
+int MMFileUtilGetMetaDataFromMKV(MMFileFormatContext *formatContext)
+{
+       MMFileIOHandle *fp = NULL;
+       long long probe_size = 10000;
+       unsigned char *buffer = NULL;
+       int ret = 0;
+       long long i;
+       long long file_size = 0;
+
+       MMFILE_WEBM_PROJ_V2_BOX v2box = { 0, };
+       MMFILE_WEBM_EQUI_PROJ_V2_BOX equi = { 0, };
+       MMFILE_WEBM_CBMP_PROJ_V2_BOX cbmp = { 0, };
+       MMFILE_WEBM_POSE_ELEMENT_V2_BOX pose = { 0, };
+
+       ret = mmfile_open(&fp, formatContext->uriFileName, MMFILE_RDONLY);
+       if (ret == MMFILE_UTIL_FAIL) {
+               debug_error(DEBUG, "error: mmfile_open");
+               goto exit;
+       }
+
+       file_size = mmfile_seek(fp, 0, SEEK_END);
+       if (file_size == MMFILE_UTIL_FAIL) {
+               debug_error(DEBUG, "mmfile operation failed");
+               goto exit;
+       }
+
+       probe_size = (file_size > probe_size) ? probe_size : file_size;
+       buffer = (unsigned char *)malloc(probe_size * sizeof(unsigned char));
+       if (!buffer) {
+               debug_error(DEBUG, "malloc failed");
+               goto exit;
+       }
+
+       ret = mmfile_seek(fp, 0, SEEK_SET);
+       if (ret == MMFILE_UTIL_FAIL) {
+               debug_error(DEBUG, "mmfile operation failed");
+               goto exit;
+       }
+
+       ret = mmfile_read(fp, buffer, probe_size * sizeof(unsigned char));
+       if (ret == MMFILE_UTIL_FAIL) {
+               debug_error(DEBUG, "mmfile operation failed");
+               goto exit;
+       }
+
+       /* FIXME (m.alieksieie): It's better to use some EBML parser here*/
+       for (i = 0; i + 3 < probe_size; ++i) {
+               if (*(unsigned int *)(buffer + i) == FOURCC('e', 'q', 'u', 'i') ||
+                               *(unsigned int *)(buffer + i) == FOURCC('c', 'b', 'm', 'p')) {
+                       debug_msg(DEBUG, "projection data found at offset %lld bytes", i);
+                       break;
+               }
+       }
+
+       if (i + 3 == probe_size) {
+               debug_msg(DEBUG, "projection info wasn't found");
+               ret = MMFILE_UTIL_SUCCESS;
+               goto exit;
+       }
+
+       if ((i - sizeof(MMFILE_WEBM_PROJ_V2_BOX)) < 0) {
+               debug_error(DEBUG, "error: invalid supposed projection info location");
+               ret = MMFILE_UTIL_FAIL;
+               goto exit;
+       }
+
+       ret = mmfile_seek(fp, i - sizeof(MMFILE_WEBM_PROJ_V2_BOX), SEEK_SET);
+       if (ret == MMFILE_UTIL_FAIL) {
+               debug_error(DEBUG, "error: failed to seek to the supposed projection info location");
+               goto exit;
+       }
+
+       ret = mmfile_read(fp, (unsigned char *)&v2box, sizeof(MMFILE_WEBM_PROJ_V2_BOX));
+       if (ret == MMFILE_UTIL_FAIL) {
+               debug_error(DEBUG, "mmfile operation failed");
+               goto exit;
+       }
+
+       if (v2box.proj_type_box_value == PROJECTION_TYPE_EQUI) {
+               debug_msg(DEBUG, "Equirectangular projection is used");
+
+               ret = mmfile_read(fp, (unsigned char *)&equi, sizeof(MMFILE_WEBM_EQUI_PROJ_V2_BOX));
+               if (ret == MMFILE_UTIL_FAIL) {
+                       debug_error(DEBUG, "error: failed to read equirectangular element");
+                       goto exit;
+               }
+               if (strncmp((char *)equi.proj_priv_box_name, "equi", 4) == 0) {
+                       formatContext->equiBoundsTopV2 = mmfile_io_be_uint32(equi.equi_projection_bounds_top);
+                       formatContext->equiBoundsBottomV2 = mmfile_io_be_uint32(equi.equi_projection_bounds_bottom);
+                       formatContext->equiBoundsLeftV2 = mmfile_io_be_uint32(equi.equi_projection_bounds_left);
+                       formatContext->equiBoundsRightV2 = mmfile_io_be_uint32(equi.equi_projection_bounds_right);
+               } else {
+                       debug_error(DEBUG, "error: failed to read equirectangular element");
+                       ret = MMFILE_UTIL_SUCCESS;
+                       goto exit;
+               }
+       }
+       if (v2box.proj_type_box_value == PROJECTION_TYPE_CBMP) {
+               debug_msg(DEBUG, "Cubemap projection is used");
+
+               ret = mmfile_read(fp, (unsigned char *)&cbmp, sizeof(MMFILE_WEBM_CBMP_PROJ_V2_BOX));
+               if (ret == MMFILE_UTIL_FAIL) {
+                       debug_error(DEBUG, "error: failed to read cubemap element");
+                       goto exit;
+               }
+               if (strncmp((char *)cbmp.proj_priv_box_name, "cbmp", 4) == 0) {
+                       formatContext->cbmpLayoutV2 = mmfile_io_be_uint32(cbmp.cbmp_projection_layout);
+                       formatContext->cbmpPaddingV2 = mmfile_io_be_uint32(cbmp.cbmp_projection_padding);
+               } else {
+                       debug_error(DEBUG, "error: failed to read cubemap element");
+                       ret = MMFILE_UTIL_FAIL;
+                       goto exit;
+               }
+       }
+
+       ret = mmfile_read(fp, (unsigned char *)&pose, sizeof(MMFILE_WEBM_POSE_ELEMENT_V2_BOX));
+       if (ret == MMFILE_UTIL_FAIL) {
+               debug_error(DEBUG, "error: failed to read pose info");
+               goto exit;
+       }
+
+       if (pose.pose_yaw_element_id == POSE_YAW_ELEMENT_ID) {
+               formatContext->poseYawV2 = (uint)mmfile_io_be_float32(pose.pose_yaw_element_value);
+       } else {
+               debug_error(DEBUG, "error: failed to pose yaw element");
+               ret = MMFILE_UTIL_FAIL;
+               goto exit;
+       }
+       if (pose.pose_pitch_element_id == POSE_PITCH_ELEMENT_ID) {
+               formatContext->posePitchV2 = (uint)mmfile_io_be_float32(pose.pose_pitch_element_value);
+       } else {
+               debug_error(DEBUG, "error: failed to pose pitch element");
+               ret = MMFILE_UTIL_FAIL;
+               goto exit;
+       }
+       if (pose.pose_roll_element_id == POSE_ROLL_ELEMENT_ID) {
+               formatContext->poseRollV2 = (uint)mmfile_io_be_float32(pose.pose_roll_element_value);
+       } else {
+               debug_error(DEBUG, "error: failed to pose roll element");
+               ret = MMFILE_UTIL_FAIL;
+               goto exit;
+       }
+
+exit:
+       mmfile_close(fp);
+
+       if (buffer)
+               free(buffer);
+
+       return ret;
+}
+
+int MMFileUtilGetMetaDataFromMP4(MMFileFormatContext *formatContext)
+{
+       MMFileIOHandle *fp = NULL;
+       int ret = 0;
+       int readed;
+       unsigned long long chunk_size = 0;
+       long long moov_end = 0;
+       MMFILE_MP4_BASIC_BOX_HEADER basic_header = {0, };
+       int junk_counter = 0;
+
+       ret = mmfile_open(&fp, formatContext->uriFileName, MMFILE_RDONLY);
+       if (ret == MMFILE_UTIL_FAIL) {
+               debug_error(DEBUG, "error: mmfile_open");
+               goto exit;
+       }
+
+       basic_header.start_offset = mmfile_tell(fp);
+       if (basic_header.start_offset < 0) {
+               debug_error(DEBUG, "error: mmfile_tell");
+               goto exit;
+       }
+
+       if (g_junk_counter_limit == 0)
+               g_junk_counter_limit = mmfile_get_int_from_ini(MMFILE_INI_JUNKCNTLIMIT, MMFILE_DEFAULT_JUNKCNTLIMIT);
+
+       while ((ret != MMFILE_UTIL_FAIL) && ((readed = mmfile_read(fp, (unsigned char *)&basic_header, MMFILE_MP4_BASIC_BOX_HEADER_LEN)) == MMFILE_MP4_BASIC_BOX_HEADER_LEN)) {
+               basic_header.size = mmfile_io_be_uint32(basic_header.size);
+               basic_header.type = mmfile_io_le_uint32(basic_header.type);
+
+               if (basic_header.size == 0) {
+                       debug_warning(DEBUG, "header is invalid.");
+                       basic_header.size = readed;
+                       basic_header.type = 0;
+                       chunk_size = basic_header.size;
+
+                       if ((moov_end != 0) && (moov_end < basic_header.start_offset)) {
+                               debug_msg(DEBUG, "found junk data but moov data already was extracted, so junk counter will be increase: %d", junk_counter);
+                               junk_counter++;
+
+                               /* stop the loop for junk case. */
+                               if ((g_junk_counter_limit > 0) && (junk_counter > g_junk_counter_limit)) {
+                                       debug_msg(DEBUG, "stop the loop by junk-data checker");
+                                       ret = MMFILE_UTIL_FAIL;
+                                       continue;
+                               }
+                       }
+               } else if (basic_header.size == 1) {
+                       int i = 0;
+                       unsigned char temp[BIG_CONTENT_BOX_SIZE_LEN] = {0, };
+                       unsigned long long size = 0;
+
+                       mmfile_read(fp, (unsigned char *)&temp, BIG_CONTENT_BOX_SIZE_LEN);
+
+                       for (i = 0; i < BIG_CONTENT_BOX_SIZE_LEN; i++)
+                               size |= (unsigned long long)temp[i] << (BIG_CONTENT_BOX_SIZE_LEN - 1 - i) * BIG_CONTENT_BOX_SIZE_LEN;
+                       chunk_size = size;
+                       junk_counter = 0;
+               } else {
+                       chunk_size = basic_header.size;
+                       junk_counter = 0;
+               }
+
+               switch (basic_header.type) {
                        case FOURCC('m', 'o', 'o', 'v'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [moov] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [moov] SIZE: [%lld]Byte", chunk_size);
+                                       moov_end = basic_header.start_offset + chunk_size;
                                        break;
                                }
                        case FOURCC('u', 'd', 't', 'a'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [udat] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [udat] SIZE: [%lld]Byte", chunk_size);
                                        break;
                                }
                                /*/////////////////////////////////////////////////////////////// */
                                /*                  Extracting Tag Data                        // */
                                /*/////////////////////////////////////////////////////////////// */
                        case FOURCC('t', 'i', 't', 'l'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [titl] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [titl] SIZE: [%lld]Byte", chunk_size);
                                        GetStringFromTextTagBox(formatContext, fp, &basic_header, eMMFILE_3GP_TAG_TITLE);
                                        break;
                                }
                        case FOURCC('d', 's', 'c', 'p'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [dscp] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [dscp] SIZE: [%lld]Byte", chunk_size);
                                        GetStringFromTextTagBox(formatContext, fp, &basic_header, eMMFILE_3GP_TAG_CAPTION);
                                        break;
                                }
                        case FOURCC('c', 'p', 'r', 't'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [cprt] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [cprt] SIZE: [%lld]Byte", chunk_size);
                                        GetStringFromTextTagBox(formatContext, fp, &basic_header, eMMFILE_3GP_TAG_COPYRIGHT);
                                        break;
                                }
                        case FOURCC('p', 'e', 'r', 'f'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [perf] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [perf] SIZE: [%lld]Byte", chunk_size);
                                        GetStringFromTextTagBox(formatContext, fp, &basic_header, eMMFILE_3GP_TAG_PERFORMER);
                                        break;
                                }
                        case FOURCC('a', 'u', 't', 'h'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [auth] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [auth] SIZE: [%lld]Byte", chunk_size);
                                        GetStringFromTextTagBox(formatContext, fp, &basic_header, eMMFILE_3GP_TAG_AUTHOR);
                                        break;
                                }
                        case FOURCC('g', 'n', 'r', 'e'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [gnre] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [gnre] SIZE: [%lld]Byte", chunk_size);
                                        GetStringFromTextTagBox(formatContext, fp, &basic_header, eMMFILE_3GP_TAG_GENRE);
                                        break;
                                }
                        case FOURCC('a', 'l', 'b', 'm'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [albm] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [albm] SIZE: [%lld]Byte", chunk_size);
                                        GetAlbumFromAlbumTagBox(formatContext, fp, &basic_header);
                                        break;
                                }
                        case FOURCC('y', 'r', 'r', 'c'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [yrrc] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [yrrc] SIZE: [%lld]Byte", chunk_size);
                                        GetYearFromYearTagBox(formatContext, fp, &basic_header);
                                        break;
                                }
                        case FOURCC('r', 't', 'n', 'g'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [rtng] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [rtng] SIZE: [%lld]Byte", chunk_size);
                                        GetRatingFromRatingTagBox(formatContext, fp, &basic_header);  /* not use */
                                        break;
                                }
                        case FOURCC('c', 'l', 's', 'f'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [clsf] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [clsf] SIZE: [%lld]Byte", chunk_size);
                                        GetClassficationFromClsfTagBox(formatContext, fp, &basic_header);
                                        break;
                                }
                        case FOURCC('k', 'y', 'w', 'd'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [kywd] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [kywd] SIZE: [%lld]Byte", chunk_size);
                                        ret = mmfile_seek(fp, basic_header.start_offset + chunk_size, SEEK_SET);
                                        break;
                                }
                        case FOURCC('l', 'o', 'c', 'i'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [loci] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [loci] SIZE: [%lld]Byte", chunk_size);
                                        GetLocationFromLociTagBox(formatContext, fp, &basic_header);
                                        break;
                                }
-                               /* Check smta in user data field to be compatible with android */
+                               /* Check smta in user data field (moov) to be compatible with android */
                        case FOURCC('s', 'm', 't', 'a'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [smta] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [smta] SIZE: [%lld]Byte", chunk_size);
                                        GetSAUTInfoFromSMTATagBox(formatContext, fp, &basic_header);
                                        break;
                                }
-                               /* Check smta in user data field to be compatible with android */
+                               /* Check cdis in user data field (moov) to be compatible with android */
                        case FOURCC('c', 'd', 'i', 's'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [smta] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [smta] SIZE: [%lld]Byte", chunk_size);
                                        GetValueFromCDISTagBox(formatContext, fp, &basic_header);
                                        break;
                                }
@@ -1443,58 +2261,110 @@ EXPORT_API int MMFileUtilGetMetaDataFromMP4(MMFileFormatContext *formatContext)
                                /*                  Extracting ID3 Tag Data                    // */
                                /*/////////////////////////////////////////////////////////////// */
                        case FOURCC('m', 'e', 't', 'a'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [meta] SIZE: [%lld]Byte\n", chunk_size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [meta] SIZE: [%lld]Byte", chunk_size);
                                        GetTagFromMetaBox(formatContext, fp, &basic_header);
                                        break;
                                }
 
                        case FOURCC('t', 'r', 'a', 'k'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [trak] SIZE: [%d]Byte\n", basic_header.size);
-#endif
+                                       debug_msg(RELEASE, "MPEG4: [trak] SIZE: [%lld]Byte", chunk_size);
                                        break;
                                }
                        case FOURCC('u', 'u', 'i', 'd'): {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("MPEG4: [uuid] SIZE: [%d]Byte\n", basic_header.size);
+                                       unsigned long uuid[4] = {0, };
+
+                                       debug_msg(RELEASE, "MPEG4: [uuid] SIZE: [%lld]Byte", chunk_size);
+
+                                       mmfile_read(fp, (unsigned char *)uuid, sizeof(uuid));
+
+                                       if (mmfile_io_be_uint32(uuid[0]) == 0xffcc8263
+                                               && mmfile_io_be_uint32(uuid[1]) == 0xf8554a93
+                                               && mmfile_io_be_uint32(uuid[2]) == 0x8814587a
+                                               && mmfile_io_be_uint32(uuid[3]) == 0x02521fdd) {
+                                               char *str = NULL;
+                                               str = (char *)malloc(basic_header.size);
+
+                                               if (str != NULL) {
+                                                       memset(str, 0, basic_header.size);
+                                                       mmfile_read(fp, (unsigned char *)str, basic_header.size);
+#if 0
+/* The block is superseded */
+                                                       if (strstr(str, "<GSpherical:Spherical>true</GSpherical:Spherical>"))
+                                                               formatContext->is_360 = 1;
+                                                       else
+                                                               formatContext->is_360 = 0;
+/* Image can be stitched even if it is not spherical */
+                                                       if (formatContext->is_360 == 1) {
+                                                               if (strstr(str, "<GSpherical:Stitched>true</GSpherical:Stitched>"))
+                                                                       formatContext->stitched = MMFILE_360_STITCHED;
+                                                               else
+                                                                       formatContext->stitched = MMFILE_360_NON_STITCHED;
+                                                       } else {
+/* Image can be stitched or non-stitched. Usage of some 3rd value is superfluous */
+                                                               formatContext->stitched = MMFILE_360_NONE;
+                                                       }
 #endif
-                                       if (!formatContext->is_360) {
-                                               unsigned long uuid[4] = {0, };
 
-                                               mmfile_read(fp, (unsigned char *)uuid, sizeof(uuid));
+                                                       debug_msg(RELEASE, "Extracting tags from UUID XML string %s", str);
 
-                                               if (mmfile_io_be_uint32(uuid[0]) == 0xffcc8263
-                                                       && mmfile_io_be_uint32(uuid[1]) == 0xf8554a93
-                                                       && mmfile_io_be_uint32(uuid[2]) == 0x8814587a
-                                                       && mmfile_io_be_uint32(uuid[3]) == 0x02521fdd) {
-                                                       formatContext->is_360 = 1;
+                                                       ParseSpatialVideoMetadataFromXMLString(str, formatContext);
                                                }
-                                               ret = mmfile_seek(fp, basic_header.start_offset + basic_header.size, SEEK_SET);
                                        }
+                                       ret = mmfile_seek(fp, basic_header.start_offset + chunk_size, SEEK_SET);
 
                                        break;
                                }
-
+                       case FOURCC('m', 'd', 'i', 'a'): {
+                                       debug_msg(RELEASE, "MPEG4: [mdia] SIZE: [%lld]Byte", chunk_size);
+                                       break;
+                               }
+                       case FOURCC('m', 'i', 'n', 'f'): {
+                                       debug_msg(RELEASE, "MPEG4: [minf] SIZE: [%lld]Byte", chunk_size);
+                                       break;
+                               }
+                       case FOURCC('s', 't', 'b', 'l'): {
+                                       debug_msg(RELEASE, "MPEG4: [stbl] SIZE: [%lld]Byte", chunk_size);
+                                       break;
+                               }
+                       case FOURCC('s', 't', 's', 'd'): {
+                                       debug_msg(RELEASE, "MPEG4: [stsd] SIZE: [%lld]Byte", chunk_size);
+                                       break;
+                               }
+                       case FOURCC('m', 'p', '4', 'a'): {
+                                       debug_msg(RELEASE, "MPEG4: [mp4a] SIZE: [%lld]Byte", chunk_size);
+                                       GetSA3DInfoFromMP4ATagBox(formatContext, fp, &basic_header);
+                                       ret = mmfile_seek(fp, basic_header.start_offset + chunk_size, SEEK_SET);
+                                       break;
+                               }
+                       case FOURCC('a', 'v', 'c', '1'): {
+                                       debug_msg(RELEASE, "MPEG4: [avc1] SIZE: [%lld]Byte (offset: %lld)", chunk_size, basic_header.start_offset);
+                                       GetVideoV2MetadataFromAvc1TagBox(formatContext, fp, &basic_header);
+                                       break;
+                               }
                        default: {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("4CC: Not Support [%c%c%c%c]. So skip it. Size [%lld Byte]\n",
+                                       debug_msg(RELEASE, "4CC: Not Support [%c%c%c%c]. So skip it. Size [%lld Byte]",
                                                                ((char *)&basic_header.type)[0], ((char *)&basic_header.type)[1],
                                                                ((char *)&basic_header.type)[2], ((char *)&basic_header.type)[3], chunk_size);
-#endif
                                        ret = mmfile_seek(fp, basic_header.start_offset + chunk_size, SEEK_SET);
                                        break;
                                }
                }
 
                if (ret == MMFILE_UTIL_FAIL) {
-                       debug_error("mmfile operation is error\n");
+                       debug_error(DEBUG, "mmfile operation is error");
                        ret = -1;
                        goto exit;
                }
 
-               basic_header.start_offset = mmfile_tell(fp);
+               long long new_pos = mmfile_tell(fp);
+
+               if ((moov_end == 0) && (new_pos <= basic_header.start_offset)) {
+                       debug_error(DEBUG, "Wrong position");
+                       ret = MMFILE_UTIL_FAIL;
+                       continue;
+               }
+               basic_header.start_offset = new_pos;
+
        }
 
 exit:
@@ -1502,72 +2372,43 @@ exit:
        return ret;
 }
 
-static char *get_string(const char *buf, int buf_size, int *bytes_written)
+static bool __get_genre_num(const char *buffer, int *si)
 {
-       int i = 0, c = 0;
-       char *q = NULL;
-       char str[512] = {0, };
-
-       q = str;
-       for (i = 0; i < buf_size; i++) {
-               c = buf[i];
-               if (c == '\0')
-                       break;
-               if ((q - str) >= (int)sizeof(str) - 1)
-                       break;
-               *q++ = c;
-       }
-       *q = '\0';
-
-       if (strlen(str) > 0) {
-               *bytes_written = strlen(str);
-               return strdup(str);
-       } else {
-               *bytes_written = 0;
-               return NULL;
-       }
-}
+       int len = strlen(buffer);
+       char *tmp_genre = NULL;
 
-static bool is_numeric(const char *buf, int buf_size)
-{
-       int idx = 0;
-       bool is_num = true;
+       /* Genre format: (###), ### */
+       if (len > 6 || len == 0)
+               return false;
 
-       for (idx = 0; idx < buf_size; idx++) {
-               if (isdigit((int)buf[idx])) {
-                       continue;
-               } else {
-                       is_num = false;
-                       break;
-               }
+       /* Check first c */
+       if (len == 1) {
+               if (!g_ascii_isdigit(buffer[0]))
+                       return false;
+       } else {
+               if (!g_ascii_isdigit(buffer[1]))
+                       return false;
        }
 
-       return is_num;
-}
+       /* Remove bind () if exist */
+       tmp_genre = g_strdup(buffer);
+       if (g_str_has_prefix(tmp_genre, "(") && g_str_has_suffix(tmp_genre, ")"))
+               tmp_genre[0] = '0';
 
-char *rtrimN(char *pStr)
-{
-       int pos = 0;
-       pos = strlen(pStr) - 1;
-       for (; pos >= 0; pos--) {
-               if (pStr[pos] == 0x20) {
-                       pStr[pos] = 0x00;
-               } else {
-                       break;
-               }
-       }
+       *si = atoi(tmp_genre);
+       g_free(tmp_genre);
 
-       return strdup(pStr);
+       return true;
 }
 
 static bool make_characterset_array(char ***charset_array)
 {
-       char *locale = MMFileUtilGetLocale(NULL);
+       char *locale = MMFileUtilGetLocale();
 
        *charset_array = calloc(AV_ID3V2_MAX, sizeof(char *));
 
        if (*charset_array == NULL) {
-               debug_error("calloc failed ");
+               debug_error(DEBUG, "calloc failed ");
                if (locale != NULL)
                        free(locale);
                return false;
@@ -1576,13 +2417,13 @@ static bool make_characterset_array(char ***charset_array)
        if (locale != NULL) {
                (*charset_array)[AV_ID3V2_ISO_8859] = strdup(locale);
        } else {
-               debug_error("get locale failed");
+               debug_error(DEBUG, "get locale failed");
                (*charset_array)[AV_ID3V2_ISO_8859] = NULL;
        }
 
        (*charset_array)[AV_ID3V2_UTF16] = strdup("UCS2");
        (*charset_array)[AV_ID3V2_UTF16_BE] = strdup("UTF16-BE");
-       (*charset_array)[AV_ID3V2_UTF8] = strdup("UTF-8");
+       (*charset_array)[AV_ID3V2_UTF8] = strdup(MMFILE_CODESET_UTF8);
 
        return true;
 }
@@ -1591,6 +2432,9 @@ static bool release_characterset_array(char **charset_array)
 {
        int i = 0;
 
+       if (!charset_array)
+               return false;
+
        for (i = 0; i < AV_ID3V2_MAX; i++) {
                if (charset_array[i] != NULL) {
                        free(charset_array[i]);
@@ -1598,2273 +2442,997 @@ static bool release_characterset_array(char **charset_array)
                }
        }
 
-       if (charset_array != NULL) {
-               free(charset_array);
-               charset_array = NULL;
-       }
+       free(charset_array);
+       charset_array = NULL;
 
        return true;
 }
 
 static void init_content_info(AvFileContentInfo *pInfo)
 {
-       pInfo->tagV2Info.bTitleMarked = false;
-       pInfo->tagV2Info.bArtistMarked = false;
-       pInfo->tagV2Info.bAlbumMarked = false;
-       pInfo->tagV2Info.bAlbum_ArtistMarked = false;
-       pInfo->tagV2Info.bYearMarked = false;
-       pInfo->tagV2Info.bDescriptionMarked = false;
-       pInfo->tagV2Info.bGenreMarked = false;
-       pInfo->tagV2Info.bTrackNumMarked = false;
-       pInfo->tagV2Info.bEncByMarked = false;
-       pInfo->tagV2Info.bURLMarked = false;
-       pInfo->tagV2Info.bCopyRightMarked = false;
-       pInfo->tagV2Info.bOriginArtistMarked = false;
-       pInfo->tagV2Info.bComposerMarked = false;
-       pInfo->tagV2Info.bImageMarked = false;
-
-       pInfo->tagV2Info.bRecDateMarked = false;
-       pInfo->tagV2Info.bContentGroupMarked = false;
-
-       pInfo->tagV2Info.bUnsyncLyricsMarked = false;
-       pInfo->tagV2Info.bSyncLyricsMarked = false;
-       pInfo->tagV2Info.bConductorMarked = false;
-       pInfo->tagV2Info.bGenreUTF16 = false;
+       int i=0;
+
+       for(i = 0; i < AV_ID3TAG_MAX; i++)
+               pInfo->tagInfo[i].value = NULL;
 
        pInfo->imageInfo.bURLInfo = false;
        pInfo->imageInfo.pImageBuf = NULL;
        pInfo->imageInfo.imageLen = 0;
 }
 
-EXPORT_API
-bool mm_file_id3tag_parse_v110(AvFileContentInfo *pInfo,  unsigned char *buffer)
+static void __id3tag_skip_newline(unsigned char *pTagVal, int *nTagLen, int *offset)
 {
-       const char *locale = MMFileUtilGetLocale(NULL);
-       char *pFullStr = NULL;
+       /* skip newline in text encoding of ID3 tag frame */
+       while ((NEWLINE_OF_UTF16(pTagVal + *offset) || NEWLINE_OF_UTF16_R(pTagVal + *offset)) && *nTagLen > 4) {
+               *nTagLen -= 4;
+               *offset += 4;
+       }
+}
 
-#ifdef __MMFILE_TEST_MODE__
-       debug_msg("ID3tag v110--------------------------------------------------------------\n");
-#endif
+static int __id3tag_get_text_encoding_v222(unsigned char *pTagVal, int offset)
+{
+       if (pTagVal[offset - 1] == 0x00)
+               return AV_ID3V2_ISO_8859;
 
-       if (pInfo->tagV2Info.bTitleMarked == false) {
-               pFullStr = mmfile_string_convert((const char *)&buffer[3], MP3_ID3_TITLE_LENGTH, "UTF-8", locale, NULL, (unsigned int *)&pInfo->titleLen);
-               if (pFullStr != NULL) {
-                       pInfo->pTitle = rtrimN(pFullStr);
-                       free(pFullStr);
-               }
+       return AV_ID3V2_UTF16;
+}
 
-#ifdef __MMFILE_TEST_MODE__
-               debug_msg("pInfo->pTitle returned =(%s), pInfo->titleLen(%d)\n", pInfo->pTitle, pInfo->titleLen);
-#endif
+static int __id3tag_get_text_encoding_v223(unsigned char *pTagVal, int *npTagLen, int nTextEnc, int *offset)
+{
+       if ((IS_ENCODEDBY_UTF16(pTagVal + *offset) || IS_ENCODEDBY_UTF16_R(pTagVal + *offset)) && *npTagLen > 2) {
+               __id3tag_skip_newline(pTagVal, npTagLen, offset);
+
+               if (IS_ENCODEDBY_UTF16(pTagVal + *offset) && (*npTagLen > 2)) {
+                       *npTagLen -= 2;
+                       *offset += 2;
+                       return AV_ID3V2_UTF16;
+               } else if (IS_ENCODEDBY_UTF16_R(pTagVal + *offset) && (*npTagLen > 2)) {
+                       *npTagLen -= 2;
+                       *offset += 2;
+                       return AV_ID3V2_UTF16_BE;
+               } else if (IS_ENCODEDBY_UTF16(pTagVal + *offset + 1) && (*npTagLen > 3)) {
+                       *npTagLen -= 3;
+                       *offset += 3;
+                       return AV_ID3V2_UTF16;
+               } else if (IS_ENCODEDBY_UTF16_R(pTagVal + *offset + 1)  && (*npTagLen > 3)) {
+                       *npTagLen -= 3;
+                       *offset += 3;
+                       return AV_ID3V2_UTF16_BE;
+               } else {
+                       debug_msg(RELEASE, "id3tag never get here!!");
+                       return nTextEnc;        /* default bypass */
+               }
+       } else {
+               while ((pTagVal[*offset] < 0x20) && (*offset < *npTagLen)) { /* text string encoded by ISO-8859-1 */
+                       (*npTagLen)--;
+                       (*offset)++;
+               }
+               return AV_ID3V2_ISO_8859;
        }
+}
 
-       if (pInfo->tagV2Info.bArtistMarked == false) {
-               pFullStr = mmfile_string_convert((const char *)&buffer[33], MP3_ID3_ARTIST_LENGTH, "UTF-8", locale, NULL, (unsigned int *)&pInfo->artistLen);
-               if (pFullStr != NULL) {
-                       pInfo->pArtist = rtrimN(pFullStr);
-                       free(pFullStr);
-               }
+static int __id3tag_get_text_encoding_v224(unsigned char *pTagVal, int *npTagLen, int nTextEnc, int *offset)
+{
+       if (nTextEnc == AV_ID3V2_UTF16 || nTextEnc == AV_ID3V2_UTF16_BE) {
+               __id3tag_skip_newline(pTagVal, npTagLen, offset);
 
-#ifdef __MMFILE_TEST_MODE__
-               debug_msg("pInfo->pArtist returned =(%s), pInfo->artistLen(%d)\n", pInfo->pArtist, pInfo->artistLen);
-#endif
+               if ((IS_ENCODEDBY_UTF16(pTagVal + *offset) || IS_ENCODEDBY_UTF16_R(pTagVal + *offset)) && *npTagLen > 2) {
+                       *npTagLen -= 2;
+                       *offset += 2;
+                       return AV_ID3V2_UTF16;
+               } else {
+                       debug_msg(RELEASE, "id3tag never get here!!");
+                       return nTextEnc;        /* default bypass */
+               }
+       } else if (nTextEnc == AV_ID3V2_UTF8) {
+               while (pTagVal[*offset] < 0x20 && (*offset < *npTagLen)) { /* text string encoded by UTF-8 */
+                       (*npTagLen)--;
+                       (*offset)++;
+               }
+               return AV_ID3V2_UTF8;
+       } else {
+               while (pTagVal[*offset] < 0x20 && (*offset < *npTagLen)) { /* text string encoded by ISO-8859-1 */
+                       (*npTagLen)--;
+                       (*offset)++;
+               }
+               return AV_ID3V2_ISO_8859;
        }
+}
 
-       if (pInfo->tagV2Info.bAlbumMarked == false) {
-               pFullStr = mmfile_string_convert((const char *)&buffer[63], MP3_ID3_ALBUM_LENGTH, "UTF-8", locale, NULL, (unsigned int *)&pInfo->albumLen);
-               if (pFullStr != NULL) {
-                       pInfo->pAlbum = rtrimN(pFullStr);
-                       free(pFullStr);
-               }
+static void __id3tag_parse_SYLT(AvFileContentInfo *pInfo, unsigned char *pTagVal, int nTagLen, const char *pCharSet, int textEncodingType, int offset)
+{
+       int idx = 0;
+       int copy_len = 0;
+       int copy_start_pos = offset;
+       AvSynclyricsInfo *synclyrics_info = NULL;
+       GList *synclyrics_info_list = NULL;
 
-#ifdef __MMFILE_TEST_MODE__
-               debug_msg("pInfo->pAlbum returned =(%s), pInfo->albumLen(%d)\n", pInfo->pAlbum, pInfo->albumLen);
-#endif
+       if (nTagLen < MMFILE_SYNC_LYRIC_INFO_MIN_LEN) {
+               debug_msg(RELEASE, "failed to get Synchronised lyrics Info realCpyFramNum(%d)", nTagLen);
+               return;
        }
 
-       if (pInfo->tagV2Info.bYearMarked == false) {
+       if ((textEncodingType == AV_ID3V2_UTF16) || (textEncodingType == AV_ID3V2_UTF16_BE)) {
+               debug_warning(DEBUG, "[%d] not implemented", textEncodingType);
+               return;
+       }
 
-               pInfo->pYear = mmfile_string_convert((const char *)&buffer[93], MP3_ID3_YEAR_LENGTH, "UTF-8", locale, NULL, (unsigned int *)&pInfo->yearLen);
-#ifdef __MMFILE_TEST_MODE__
-               debug_msg("pInfo->pYear returned =(%s), pInfo->yearLen(%d)\n", pInfo->pYear, pInfo->yearLen);
-#endif
-
-               if (pInfo->pYear == NULL) {     /*Use same logic with ffmpeg*/
-                       pInfo->pYear = get_string((const char *)&buffer[93], MP3_ID3_YEAR_LENGTH, (int *)&pInfo->yearLen);
-#ifdef __MMFILE_TEST_MODE__
-                       debug_msg("pInfo->pYear returned =(%s), pInfo->yearLen(%d)\n", pInfo->pYear, pInfo->yearLen);
-#endif
+       for (idx = 0; idx < nTagLen; idx++) {
+               if (pTagVal[offset + idx] == 0x00) {
+                       synclyrics_info = g_new0(AvSynclyricsInfo, 1);
+                       if (textEncodingType == AV_ID3V2_UTF8)
+                               synclyrics_info->lyric_info = g_memdup2(pTagVal + copy_start_pos, copy_len + 1);
+                       else
+                               synclyrics_info->lyric_info = mmfile_convert_to_utf8((const char *)&pTagVal[copy_start_pos], copy_len, pCharSet);
+
+                       synclyrics_info->time_info = (unsigned long)pTagVal[offset + idx + 1] << 24 | (unsigned long)pTagVal[offset + idx + 2] << 16 | (unsigned long)pTagVal[offset + idx + 3] << 8  | (unsigned long)pTagVal[offset + idx + 4];
+                       idx += 4;
+                       copy_start_pos = offset + idx + 1;
+                       debug_msg(RELEASE, "[%lu][%s] idx[%d], copy_len[%d] copy_start_pos[%d]", synclyrics_info->time_info, synclyrics_info->lyric_info, idx, copy_len, copy_start_pos);
+                       copy_len = 0;
+                       synclyrics_info_list = g_list_append(synclyrics_info_list, synclyrics_info);
                }
+               copy_len++;
        }
 
-       if (pInfo->tagV2Info.bDescriptionMarked == false) {
-               pInfo->pComment = mmfile_string_convert((const char *)&buffer[97], MP3_ID3_DESCRIPTION_LENGTH, "UTF-8", locale, NULL, (unsigned int *)&pInfo->commentLen);
-#ifdef __MMFILE_TEST_MODE__
-               debug_msg("pInfo->pComment returned =(%s), pInfo->commentLen(%d)\n", pInfo->pComment, pInfo->commentLen);
-#endif
+       pInfo->pSyncLyrics = synclyrics_info_list;
+}
 
-               if (pInfo->pComment == NULL) {  /*Use same logic with ffmpeg*/
-                       pInfo->pComment = get_string((const char *)&buffer[97], MP3_ID3_DESCRIPTION_LENGTH, (int *)&pInfo->commentLen);
-#ifdef __MMFILE_TEST_MODE__
-                       debug_msg("pInfo->pComment returned =(%s), pInfo->commentLen(%d)\n", pInfo->pComment, pInfo->commentLen);
-#endif
-               }
-       }
+static bool __id3tag_parse_PIC_format(AvFileContentInfo *pInfo, unsigned char *pTagVal, int *offset)
+{
+       unsigned int idx = 0;
 
-       if (pInfo->tagV2Info.bTrackNumMarked == false) {
-               pInfo->pTrackNum = mmfile_malloc(5);
-               if (pInfo->pTrackNum != NULL) {
-                       pInfo->pTrackNum[4] = 0;
-                       snprintf(pInfo->pTrackNum, 4, "%04d", (int)buffer[126]);
-                       pInfo->tracknumLen = strlen(pInfo->pTrackNum);
-#ifdef __MMFILE_TEST_MODE__
-                       debug_msg("pInfo->pTrackNum returned =(%s), pInfo->tracknumLen(%d)\n", pInfo->pTrackNum, pInfo->tracknumLen);
-#endif
-               }
+       /* get the mime type of Attached PICture, it is text string */
+
+       if (pTagVal[*offset] == '\0') {
+               debug_msg(RELEASE, "The picture format of PIC is not included");
+               return false;
        }
 
-       if (pInfo->tagV2Info.bGenreMarked == false) {
-               pInfo->genre = buffer[127];
-#ifdef __MMFILE_TEST_MODE__
-               debug_msg("pInfo->genre returned genre number (%d)\n", pInfo->genre);
-#endif
+       /* init ext variable */
+       memset(pInfo->imageInfo.imageExt, 0, sizeof(pInfo->imageInfo.imageExt));
+       /* get ext */
+       while ((idx < MP3_ID3_IMAGE_EXT_MAX_LENGTH - 1) && (pTagVal[idx] != '\0')) {
+               pInfo->imageInfo.imageExt[idx] = pTagVal[idx];
+               idx++;
        }
 
+       *offset += idx;
+
        return true;
 }
 
-EXPORT_API
-bool mm_file_id3tag_parse_v222(AvFileContentInfo *pInfo, unsigned char *buffer)
+static bool __id3tag_parse_APIC_mimetype(AvFileContentInfo *pInfo, unsigned char *pTagVal, int nTagLen, int *offset)
 {
-       unsigned long taglen = 0;
-       unsigned long needToloopv2taglen;
-       unsigned long oneFrameLen = 0;
-       unsigned long v2numOfFrames = 0;
-       unsigned long curPos = 0;
-       char CompTmp[4];
-       unsigned char *pExtContent = NULL;
-       unsigned long purelyFramelen = 0;
-       unsigned int encodingOffSet = 0;
-       int inx = 0, realCpyFrameNum = 0,
-           /*checkImgMimeTypeMax = 0, */checkImgExtMax = 0,
-           imgstartOffset = 0, tmp = 0;
-
-       int textEncodingType = 0;
+       unsigned int idx = 0;
+       const char *MIME_PRFIX = "image/";
 
-       char **charset_array = NULL;
+       /* get the mime type of Attached PICture, it is text string */
 
-       make_characterset_array(&charset_array);
+       if (pTagVal[*offset] == '\0') {
+               pInfo->imageInfo.imgMimetypeLen = 0;
+               debug_msg(RELEASE, "The MIME type of APIC is not included");
+               return false;
+       }
 
-       init_content_info(pInfo);
+       /* init mimetype variable */
+       memset(pInfo->imageInfo.imageMIMEType, 0, sizeof(pInfo->imageInfo.imageMIMEType));
+       /* get mimetype */
+       while ((idx < MP3_ID3_IMAGE_MIME_TYPE_MAX_LENGTH - 1) && (pTagVal[idx] != '\0')) {
+               pInfo->imageInfo.imageMIMEType[idx] = pTagVal[idx];
+               idx++;
+       }
+       pInfo->imageInfo.imgMimetypeLen = idx;
 
-       taglen = pInfo->tagV2Info.tagLen;
-       needToloopv2taglen = taglen - MP3_TAGv2_HEADER_LEN;
-       curPos = MP3_TAGv2_HEADER_LEN;
+       *offset += idx;
 
-#ifdef __MMFILE_TEST_MODE__
-       debug_msg("ID3tag v222--------------------------------------------------------------\n");
-#endif
-       if (needToloopv2taglen - MP3_TAGv2_22_TXT_HEADER_LEN > MP3_TAGv2_22_TXT_HEADER_LEN) {
-               v2numOfFrames = 1;
-               while (needToloopv2taglen > MP3_TAGv2_22_TXT_HEADER_LEN) {
-                       if ((buffer[curPos] < '0' || buffer[curPos] > 'Z') || (buffer[curPos + 1] < '0' || buffer[curPos + 1] > 'Z')
-                           || (buffer[curPos + 2] < '0' || buffer[curPos + 2] > 'Z'))
-                               break;
+       if (strncmp(pInfo->imageInfo.imageMIMEType, MIME_PRFIX, strlen(MIME_PRFIX)) != 0) {
+               pInfo->imageInfo.imgMimetypeLen = 0;
+               debug_error(DEBUG, "MIME type(%s) is not image", pInfo->imageInfo.imageMIMEType);
+               return false;
+       }
 
-                       memcpy(CompTmp, &buffer[curPos], 3);
+       if ((pTagVal[*offset] != '\0') || (nTagLen <= *offset)) {
+               debug_msg(RELEASE, "pTagVal[offset](%d) mimetype is not NULL terminated! realCpyFrameNum - offset(%d)",
+                                       pTagVal[*offset], nTagLen - *offset);
+               return true;
+       }
 
-                       CompTmp[3] = 0;
-                       oneFrameLen = MP3_TAGv2_22_TXT_HEADER_LEN;
-                       oneFrameLen += (unsigned long)buffer[3 + curPos] << 16 | (unsigned long)buffer[4 + curPos] << 8
-                                               | (unsigned long)buffer[5 + curPos];
-                       if (oneFrameLen > taglen - curPos)
-                               break;
-                       purelyFramelen = oneFrameLen - MP3_TAGv2_22_TXT_HEADER_LEN;
-                       curPos += MP3_TAGv2_22_TXT_HEADER_LEN;
-
-                       if (oneFrameLen > MP3_TAGv2_22_TXT_HEADER_LEN && purelyFramelen <= taglen - curPos) {
-                               curPos += purelyFramelen;
-
-                               if (buffer[curPos - purelyFramelen] == 0x00) {
-                                       encodingOffSet = 1;
-                                       textEncodingType = AV_ID3V2_ISO_8859;
-                               } else if (buffer[curPos - purelyFramelen] == 0x01) {
-                                       encodingOffSet = 1;
-                                       textEncodingType = AV_ID3V2_UTF16;
-                               }
+       (*offset)++;/* end of MIME('\0', 1byte) */
+       debug_msg(RELEASE, "after scaning Mime type offset(%d) value!", *offset);
+
+       return true;
+}
 
-                               /*in order to deliver valid string to MP */
-                               while ((buffer[curPos - purelyFramelen + encodingOffSet] < 0x20) && (encodingOffSet < purelyFramelen))
-                                       encodingOffSet++;
+static void __id3tag_parse_APIC_pictype(AvFileContentInfo *pInfo, unsigned char *pTagVal, int *offset)
+{
+       /* get the picture type of Attached PICture, it is 1byte(0xff) */
 
-                               if (encodingOffSet < purelyFramelen) {
-                                       realCpyFrameNum = purelyFramelen - encodingOffSet;
-                                       pExtContent = mmfile_malloc(realCpyFrameNum + 3);
+       if (pTagVal[*offset] < MP3_ID3V2_PICTURE_TYPE_MAX)
+               pInfo->imageInfo.pictureType = pTagVal[*offset];
+       else
+               debug_msg(RELEASE, "APIC image has invalid picture type(0x%x)", pTagVal[*offset]);
 
-                                       if (pExtContent == NULL) {
-                                               debug_error("out of memory for pExtContent\n");
-                                               continue;
-                                       }
+       (*offset)++;/* PictureType(1byte) */
+       debug_msg(RELEASE, "after scaning PictureType(%d) offset(%d) value!", pInfo->imageInfo.pictureType, *offset);
+}
 
-                                       memset(pExtContent, '\0', realCpyFrameNum + 3);
+static void __id3tag_parse_APIC_desc(AvFileContentInfo *pInfo, unsigned char *pTagVal, int nTagLen, const char *pCharSet, int *offset)
+{
+       /* get the description of Attached PICture, it is text string */
 
-                                       memcpy(pExtContent, &buffer[curPos - purelyFramelen + encodingOffSet], purelyFramelen - encodingOffSet);
+       int idx = 0;
+       unsigned int tag_len = 0;
+       char *tmp_desc = NULL;
 
-                                       if (realCpyFrameNum > 0) {
-                                               if (strncmp((char *)CompTmp, "TT2", 3) == 0 && pInfo->tagV2Info.bTitleMarked == false) {
-                                                       pInfo->pTitle = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->titleLen);
+       if (pTagVal[*offset] == 0x0) {
+               debug_msg(RELEASE, "The description of APIC is not included!!!");
+               return;
+       }
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pTitle returned = (%s), pInfo->titleLen(%d)\n", pInfo->pTitle, pInfo->titleLen);
-#endif
-                                                       pInfo->tagV2Info.bTitleMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TP1", 3) == 0 && pInfo->tagV2Info.bArtistMarked == false) {
-                                                       pInfo->pArtist = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->artistLen);
+       while (1) {
+               if (pTagVal[*offset + idx] == '\0') {
+                       if (nTagLen < (*offset + idx)) {
+                               debug_error(DEBUG, "End of APIC Tag %d %d %d", nTagLen, *offset, idx);
+                               break;
+                       }
+                       /* check end of image description */
+                       if ((pTagVal[*offset + idx + 1] == gTagJPEGHeader[0]) ||
+                               (pTagVal[*offset + idx + 1] == gTagPNGHeader[0])) {
+                               debug_msg(RELEASE, "length of description (%d)", idx);
+                               break;
+                       }
+               }
+               idx++;
+       }
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pArtist returned = (%s), pInfo->artistLen(%d)\n", pInfo->pArtist, pInfo->artistLen);
-#endif
-                                                       pInfo->tagV2Info.bArtistMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TP2", 3) == 0 && pInfo->tagV2Info.bAlbum_ArtistMarked == false) {
-                                                       pInfo->pAlbum_Artist = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->album_artistLen);
+       tag_len = idx + 1;      /* length of description + '\0' */
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pAlbum_Artist returned = (%s), pInfo->album_artistLen(%d)\n", pInfo->pAlbum_Artist, pInfo->album_artistLen);
-#endif
-                                                       pInfo->tagV2Info.bAlbum_ArtistMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TP3", 3) == 0 && pInfo->tagV2Info.bConductorMarked == false) {
-                                                       pInfo->pConductor = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->conductorLen);
+       tmp_desc = g_memdup2(pTagVal + *offset, tag_len);
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pConductor returned = (%s), pInfo->conductorLen(%d)\n", pInfo->pConductor, pInfo->conductorLen);
-#endif
-                                                       pInfo->tagV2Info.bConductorMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TAL", 3) == 0 && pInfo->tagV2Info.bAlbumMarked == false) {
-                                                       pInfo->pAlbum = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->albumLen);
+       /* convert description */
+       pInfo->imageInfo.imageDescription = mmfile_convert_to_utf8(tmp_desc, tag_len, pCharSet);
+       mmfile_free(tmp_desc);
+       debug_msg(RELEASE, "new_desc %s", pInfo->imageInfo.imageDescription);
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pAlbum returned = (%s), pInfo->albumLen(%d)\n", pInfo->pAlbum, pInfo->albumLen);
-#endif
-                                                       pInfo->tagV2Info.bAlbumMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TYE", 3) == 0 && pInfo->tagV2Info.bYearMarked == false) {
-                                                       pInfo->pYear = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->yearLen);
+       *offset += idx;
+       if ((pTagVal[*offset] != '\0') || (nTagLen <= *offset)) {
+               debug_msg(RELEASE, "pTagVal[offset](%d) description is not NULL terminated! realCpyFrameNum - offset(%d)",
+                                       pTagVal[*offset], nTagLen - *offset);
+               return;
+       }
+       (*offset)++; /* end of desceription(1byte) */
+}
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pYear returned = (%s), pInfo->yearLen(%d)\n", pInfo->pYear, pInfo->yearLen);
-#endif
-                                                       pInfo->tagV2Info.bYearMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "COM", 3) == 0 && pInfo->tagV2Info.bDescriptionMarked == false) {
-                                                       /*skip language data! */
-                                                       if (realCpyFrameNum > 4) {
-                                                               realCpyFrameNum -= 4;
-                                                               tmp = 4;
-
-                                                               /*pExtContent[tmp+1] value should't have encoding value */
-                                                               if (pExtContent[tmp] > 0x20 && (pExtContent[tmp - 1] == 0x00 || pExtContent[tmp - 1] == 0x01)) {
-                                                                       if (pExtContent[tmp - 1] == 0x00)
-                                                                               textEncodingType = AV_ID3V2_ISO_8859;
-                                                                       else
-                                                                               textEncodingType = AV_ID3V2_UTF16;
-
-                                                                       pInfo->pComment = mmfile_string_convert((char *)&pExtContent[tmp], realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->commentLen);
-
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("pInfo->pComment returned = (%s), pInfo->commentLen(%d)\n", pInfo->pComment, pInfo->commentLen);
-#endif
-                                                                       pInfo->tagV2Info.bDescriptionMarked = true;
-                                                               } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("mmf_file_id3tag_parse_v222: failed to get Comment Info tmp(%d), purelyFramelen - encodingOffSet(%d)\n", tmp, purelyFramelen - encodingOffSet);
-#endif
-                                                               }
-                                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("mmf_file_id3tag_parse_v222: Description info too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum);
-#endif
-                                                       }
-                                                       tmp = 0;
+static void __id3tag_parse_APIC_picture(AvFileContentInfo *pInfo, unsigned char *pTagVal, int nTagLen, int *offset)
+{
+       /* get the picture of Attached PICture, it is binary data */
+
+       /* some content has useless '\0' in front of picture data */
+       while (pTagVal[*offset] == '\0') {
+               (*offset)++;
+       }
 
-                                               } else if (strncmp((char *)CompTmp, "TCO", 3) == 0 && pInfo->tagV2Info.bGenreMarked == false) {
-                                                       pInfo->pGenre = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->genreLen);
+       debug_msg(RELEASE, "after scaning APIC description offset(%d) value!", *offset);
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pGenre returned = (%s), pInfo->genreLen(%d)\n", pInfo->pGenre, pInfo->genreLen);
-#endif
+       if (nTagLen <= *offset) {
+               debug_msg(RELEASE, "No APIC image!! realCpyFrameNum(%d) - offset(%d)", nTagLen, *offset);
+               return;
+       }
 
-                                                       if ((pInfo->pGenre != NULL) && (pInfo->genreLen > 0)) {
-                                                               bool ret = FALSE;
-                                                               int int_genre = -1;
+       pInfo->imageInfo.imageLen = nTagLen - *offset;
+       pInfo->imageInfo.pImageBuf = g_memdup2(pTagVal + *offset, pInfo->imageInfo.imageLen);
 
-                                                               ret = is_numeric(pInfo->pGenre, pInfo->genreLen);
+       /* if mimetype is "-->", image date has an URL */
+       if (IS_INCLUDE_URL(pInfo->imageInfo.imageMIMEType))
+               pInfo->imageInfo.bURLInfo = true;
+}
 
-                                                               if (ret == TRUE) {
-                                                                       sscanf(pInfo->pGenre, "%d", &int_genre);
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("genre information is inteager [%d]\n", int_genre);
-#endif
+static bool _mm_file_id3tag_parse_PIC(AvFileContentInfo *pInfo, unsigned char *pTagVal, int nTagLen, const char *pCharSet)
+{
+       /* current position to read pTagVal */
+       int offset = 0;
 
-                                                                       /*Change int to string */
-                                                                       if ((0 <= int_genre) && (int_genre < GENRE_COUNT - 1)) {
-                                                                               /*save genreinfo like "(123)". mm_file_id3tag_restore_content_info convert it to string*/
-                                                                               char tmp_genre[6] = {0, };      /*ex. "(123)+NULL"*/
-                                                                               int tmp_genre_len = 0;
-
-                                                                               memset(tmp_genre, 0, 6);
-                                                                               snprintf(tmp_genre, sizeof(tmp_genre), "(%d)", int_genre);
-
-                                                                               tmp_genre_len = strlen(tmp_genre);
-                                                                               if (tmp_genre_len > 0) {
-                                                                                       if (pInfo->pGenre) _FREE_EX(pInfo->pGenre);
-                                                                                       pInfo->pGenre = mmfile_malloc(sizeof(char) * (tmp_genre_len + 1));
-                                                                                       if (pInfo->pGenre) {
-                                                                                               strncpy(pInfo->pGenre, tmp_genre, tmp_genre_len);
-                                                                                               pInfo->pGenre[tmp_genre_len] = 0;
-                                                                                       }
-                                                                               }
-                                                                       }
-                                                               }
-                                                       }
+       debug_fenter(RELEASE);
 
-                                                       pInfo->tagV2Info.bGenreMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TRK", 3) == 0 && pInfo->tagV2Info.bTrackNumMarked == false) {
-                                                       pInfo->pTrackNum = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->tracknumLen);
+       if (!__id3tag_parse_PIC_format(pInfo, pTagVal, &offset)) {
+               debug_msg(RELEASE, "PIC is not valid");
+               return false;
+       }
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pTrackNum returned = (%s), pInfo->tracknumLen(%d)\n", pInfo->pTrackNum, pInfo->tracknumLen);
-#endif
-                                                       pInfo->tagV2Info.bTrackNumMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TEN", 3) == 0 && pInfo->tagV2Info.bEncByMarked == false) {
-                                                       pInfo->pEncBy = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->encbyLen);
+       __id3tag_parse_APIC_pictype(pInfo, pTagVal, &offset);
+       __id3tag_parse_APIC_desc(pInfo, pTagVal, nTagLen, pCharSet, &offset);
+       __id3tag_parse_APIC_picture(pInfo, pTagVal, nTagLen, &offset);
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pEncBy returned = (%s), pInfo->encbyLen(%d)\n", pInfo->pEncBy, pInfo->encbyLen);
-#endif
-                                                       pInfo->tagV2Info.bEncByMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "WXX", 3) == 0 && pInfo->tagV2Info.bURLMarked == false) {
-                                                       if (realCpyFrameNum > 4) {
-                                                               /*skip language data! */
-                                                               realCpyFrameNum -= 4;
-                                                               tmp = 4;
-
-                                                               /*pExtContent[tmp+1] value should't have null value */
-                                                               if (pExtContent[tmp] > 0x20 && (pExtContent[tmp - 1] == 0x00 || pExtContent[tmp - 1] == 0x01)) {
-                                                                       if (pExtContent[tmp - 1] == 0x00)
-                                                                               textEncodingType = AV_ID3V2_ISO_8859;
-                                                                       else
-                                                                               textEncodingType = AV_ID3V2_UTF16;
-
-                                                                       pInfo->pURL = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->urlLen);
-
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("pInfo->pURL returned = (%s), pInfo->urlLen(%d)\n", pInfo->pURL, pInfo->urlLen);
-#endif
-                                                                       pInfo->tagV2Info.bURLMarked = true;
-                                                               } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("mmf_file_id3tag_parse_v222: failed to get URL Info tmp(%d), purelyFramelen - encodingOffSet(%d)\n", tmp, purelyFramelen - encodingOffSet);
-#endif
-                                                               }
-                                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("mmf_file_id3tag_parse_v222: URL info too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum);
-#endif
-                                                       }
-                                                       tmp = 0;
-                                               } else if (strncmp((char *)CompTmp, "TCR", 3) == 0 && pInfo->tagV2Info.bCopyRightMarked == false) {
-                                                       pInfo->pCopyright = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->copyrightLen);
+       debug_fleave(RELEASE);
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pCopyright returned = (%s), pInfo->copyrightLen(%d)\n", pInfo->pCopyright, pInfo->copyrightLen);
-#endif
-                                                       pInfo->tagV2Info.bCopyRightMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TOA", 3) == 0 && pInfo->tagV2Info.bOriginArtistMarked == false) {
-                                                       pInfo->pOriginArtist = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->originartistLen);
+       return true;
+}
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pOriginArtist returned = (%s), pInfo->originartistLen(%d)\n", pInfo->pOriginArtist, pInfo->originartistLen);
-#endif
-                                                       pInfo->tagV2Info.bOriginArtistMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TCM", 3) == 0 && pInfo->tagV2Info.bComposerMarked == false) {
-                                                       pInfo->pComposer = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->composerLen);
+static bool _mm_file_id3tag_parse_APIC(AvFileContentInfo *pInfo, unsigned char *pTagVal, int nTagLen, const char *pCharSet)
+{
+       int offset = 0;
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pComposer returned = (%s), pInfo->originartistLen(%d)\n", pInfo->pComposer, pInfo->composerLen);
-#endif
-                                                       pInfo->tagV2Info.bComposerMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TRD", 3) == 0 && pInfo->tagV2Info.bRecDateMarked == false) {
-                                                       pInfo->pRecDate = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->recdateLen);
+       debug_fenter(RELEASE);
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pRecDate returned = (%s), pInfo->recdateLen(%d)\n", pInfo->pRecDate, pInfo->recdateLen);
-#endif
-                                                       pInfo->tagV2Info.bRecDateMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "PIC", 3) == 0 && pInfo->tagV2Info.bImageMarked == false && realCpyFrameNum <= 2000000) {
-                                                       if (pExtContent[0] != 0) {
-                                                               for (inx = 0; inx < MP3_ID3_IMAGE_EXT_MAX_LENGTH; inx++)
-                                                                       pInfo->imageInfo.imageExt[inx] = '\0';/*ini mimetype variable */
-
-                                                               while ((checkImgExtMax < MP3_ID3_IMAGE_EXT_MAX_LENGTH - 1) && pExtContent[checkImgExtMax] != '\0') {
-                                                                       pInfo->imageInfo.imageExt[checkImgExtMax] = pExtContent[checkImgExtMax];
-                                                                       checkImgExtMax++;
-                                                               }
-                                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("mmf_file_id3tag_parse_v222: PIC image's not included to image Extention\n");
-#endif
-                                                       }
+       if (!__id3tag_parse_APIC_mimetype(pInfo, pTagVal, nTagLen, &offset)) {
+               debug_msg(RELEASE, "APIC is not valid");
+               return false;
+       }
 
-                                                       imgstartOffset += checkImgExtMax;
+       __id3tag_parse_APIC_pictype(pInfo, pTagVal, &offset);
+       __id3tag_parse_APIC_desc(pInfo, pTagVal, nTagLen, pCharSet, &offset);
+       __id3tag_parse_APIC_picture(pInfo, pTagVal, nTagLen, &offset);
 
-                                                       if (pExtContent[imgstartOffset] < AV_ID3V2_PICTURE_TYPE_MAX) {
-                                                               pInfo->imageInfo.pictureType = pExtContent[imgstartOffset];
-                                                       }
-                                                       imgstartOffset++;/*PictureType(1byte) */
-
-                                                       if (pExtContent[imgstartOffset] != 0x0) {
-                                                               int cur_pos = 0;
-                                                               int dis_len = 0;
-                                                               int new_dis_len = 0;
-                                                               char *tmp_desc = NULL;
-
-                                                               while (1) {
-                                                                       if (pExtContent[imgstartOffset + cur_pos] == '\0') {
-                                                                               if (realCpyFrameNum < imgstartOffset + cur_pos) {
-                                                                                       debug_error("End of APIC Tag %d %d %d\n", realCpyFrameNum, imgstartOffset, cur_pos);
-                                                                                       break;
-                                                                               }
-                                                                               /*check end of image description*/
-                                                                               if ((pExtContent[imgstartOffset + cur_pos + 1] == gTagJPEGHeader[0]) ||
-                                                                                   (pExtContent[imgstartOffset + cur_pos + 1] == gTagPNGHeader[0])) {
-#ifdef __MMFILE_TEST_MODE__
-                                                                                       debug_msg("length of description (%d)", cur_pos);
-#endif
+       debug_fleave(RELEASE);
 
-                                                                                       break;
-                                                                               }
-                                                                       }
-                                                                       cur_pos++;
-                                                               }
+       return true;
+}
 
-                                                               dis_len = cur_pos + 1;
+static char * __id3tag_get_v110(const char *buf, ssize_t len, const char *locale)
+{
+       char *tmp_str = NULL;
 
-                                                               tmp_desc = mmfile_malloc(sizeof(char) * dis_len);
+       mm_file_retv_if_fails(buf, NULL);
+       mm_file_retv_if_fails(locale, NULL);
 
-                                                               if (tmp_desc != NULL) {
-                                                                       memcpy(tmp_desc, pExtContent + imgstartOffset, dis_len);
+       tmp_str = mmfile_convert_to_utf8(buf, len, locale);
 
-                                                                       /*convert description*/
-                                                                       pInfo->imageInfo.imageDescription = mmfile_string_convert(tmp_desc, dis_len, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&new_dis_len);
-                                                                       mmfile_free(tmp_desc);
+       /* ID3v1 tag need check length or space. */
+       if (tmp_str && (strlen(tmp_str) == 0 || g_ascii_isspace(tmp_str[0])))
+               mmfile_free(tmp_str);
 
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("new_desc %s(%d)\n", pInfo->imageInfo.imageDescription, new_dis_len);
-#endif
-                                                                       pInfo->imageInfo.imgDesLen = new_dis_len; /**/
-                                                               }
+       return tmp_str;
+}
 
-                                                               imgstartOffset += cur_pos;
-                                                       } else {
-                                                               pInfo->imageInfo.imgDesLen = 0;
-                                                       }
+bool mm_file_id3tag_parse_v110(AvFileContentInfo *pInfo, unsigned char *buffer)
+{
+       const char *locale = MMFileUtilGetLocale();
 
-                                                       if ((pExtContent[imgstartOffset] == '\0') && (realCpyFrameNum - imgstartOffset > 0)) {
-                                                               imgstartOffset++; /* endofDesceriptionType(1byte) */
+       debug_msg(RELEASE, "ID3tag v110--------------------------------------------------------------");
 
-                                                               while (pExtContent[imgstartOffset] == '\0') {   /*some content has useless '\0' in front of picture data */
-                                                                       imgstartOffset++;
-                                                               }
+       if (!pInfo->tagInfo[AV_ID3TAG_TITLE].value) {
+               pInfo->tagInfo[AV_ID3TAG_TITLE].value = __id3tag_get_v110((const char *)&buffer[3], MP3_ID3_TITLE_LENGTH, locale);
 
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("after scaning imgDescription imgstartOffset(%d) value!\n", imgstartOffset);
-#endif
+               debug_msg(RELEASE, "pInfo->pTitle returned =(%s)", pInfo->tagInfo[AV_ID3TAG_TITLE].value);
+       }
 
-                                                               if (realCpyFrameNum - imgstartOffset > 0) {
-                                                                       pInfo->imageInfo.imageLen = realCpyFrameNum - imgstartOffset;
-                                                                       pInfo->imageInfo.pImageBuf = mmfile_malloc(pInfo->imageInfo.imageLen + 1);
+       if (!pInfo->tagInfo[AV_ID3TAG_ARTIST].value) {
+               pInfo->tagInfo[AV_ID3TAG_ARTIST].value = __id3tag_get_v110((const char *)&buffer[33], MP3_ID3_ARTIST_LENGTH, locale);
 
-                                                                       if (pInfo->imageInfo.pImageBuf != NULL) {
-                                                                               memcpy(pInfo->imageInfo.pImageBuf, pExtContent + imgstartOffset, pInfo->imageInfo.imageLen);
-                                                                               pInfo->imageInfo.pImageBuf[pInfo->imageInfo.imageLen] = 0;
-                                                                       }
+               debug_msg(RELEASE, "pInfo->pArtist returned =(%s)", pInfo->tagInfo[AV_ID3TAG_ARTIST].value);
+       }
 
-                                                                       if (IS_INCLUDE_URL(pInfo->imageInfo.imageMIMEType))
-                                                                               pInfo->imageInfo.bURLInfo = true; /*if mimetype is "-->", image date has an URL */
-                                                               } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("No APIC image!! realCpyFrameNum(%d) - imgstartOffset(%d)\n", realCpyFrameNum, imgstartOffset);
-#endif
-                                                               }
-                                                       }
+       if (!pInfo->tagInfo[AV_ID3TAG_ALBUM].value) {
+               pInfo->tagInfo[AV_ID3TAG_ALBUM].value = __id3tag_get_v110((const char *)&buffer[63], MP3_ID3_ALBUM_LENGTH, locale);
 
-                                                       /*checkImgMimeTypeMax = 0;*/
-                                                       checkImgExtMax = 0;
-                                                       inx = 0;
-                                                       imgstartOffset = 0;
-                                                       pInfo->tagV2Info.bImageMarked = true;
+               debug_msg(RELEASE, "pInfo->pAlbum returned =(%s)", pInfo->tagInfo[AV_ID3TAG_ALBUM].value);
+       }
 
-                                               }
-                                       }
+       if (!pInfo->tagInfo[AV_ID3TAG_YEAR].value) {
+               pInfo->tagInfo[AV_ID3TAG_YEAR].value = __id3tag_get_v110((const char *)&buffer[93], MP3_ID3_YEAR_LENGTH, locale);
 
-                               }
-                       } else {
-                               curPos += purelyFramelen;
-                               if (purelyFramelen != 0)
-                                       needToloopv2taglen = MP3_TAGv2_22_TXT_HEADER_LEN;
-                       }
+               debug_msg(RELEASE, "pInfo->pYear returned =(%s)", pInfo->tagInfo[AV_ID3TAG_YEAR].value);
+       }
 
-                       if (pExtContent)        _FREE_EX(pExtContent);
-                       memset(CompTmp, 0, 4);
-                       if (curPos < taglen) {
-                               needToloopv2taglen -= oneFrameLen;
-                               v2numOfFrames++;
-                       } else
-                               needToloopv2taglen = MP3_TAGv2_22_TXT_HEADER_LEN;
-                       oneFrameLen = 0;
-                       encodingOffSet = 0;
-                       realCpyFrameNum = 0;
-                       textEncodingType = 0;
-                       purelyFramelen = 0;
+       if (!pInfo->tagInfo[AV_ID3TAG_COMMENT].value) {
+               pInfo->tagInfo[AV_ID3TAG_COMMENT].value = __id3tag_get_v110((const char *)&buffer[97], MP3_ID3_DESCRIPTION_LENGTH, locale);
 
-               }
+               debug_msg(RELEASE, "pInfo->pComment returned =(%s)", pInfo->tagInfo[AV_ID3TAG_COMMENT].value);
        }
 
-       release_characterset_array(charset_array);
+       if (!pInfo->tagInfo[AV_ID3TAG_TRACKNUM].value) {
+               pInfo->tagInfo[AV_ID3TAG_TRACKNUM].value = g_malloc0(ID3TAG_V110_TRACK_NUM_DIGIT);
+               pInfo->tagInfo[AV_ID3TAG_TRACKNUM].value[ID3TAG_V110_TRACK_NUM_DIGIT - 1] = 0;
+               snprintf(pInfo->tagInfo[AV_ID3TAG_TRACKNUM].value, ID3TAG_V110_TRACK_NUM_DIGIT, "%04d", (int)buffer[126]);
 
-       if (taglen) {
-               return true;
-       } else {
-               return false;
+               debug_msg(RELEASE, "pInfo->pTrackNum returned =(%s)", pInfo->tagInfo[AV_ID3TAG_TRACKNUM].value);
        }
+
+       /*ID3V2 genre is stored in pInfo->tagInfo[AV_ID3TAG_GENRE].value */
+       /*pInfo->genre is used when ID3V2 genre is invalid, or empty. */
+       pInfo->genre = buffer[127];
+       debug_msg(RELEASE, "pInfo->genre returned genre number (%d)", pInfo->genre);
+
+       return true;
 }
 
-EXPORT_API
-bool mm_file_id3tag_parse_v223(AvFileContentInfo *pInfo, unsigned char *buffer)
+static AvID3TagList __get_tag_info_v222(const unsigned char *tag)
 {
-       unsigned long taglen = 0;
-       unsigned long needToloopv2taglen;
-       unsigned long oneFrameLen = 0;
-       unsigned long v2numOfFrames = 0;
-       unsigned long curPos = 0;
-       char CompTmp[5];
-       unsigned char *pExtContent = NULL;
-       unsigned long purelyFramelen = 0;
-       unsigned int encodingOffSet = 0;
-       int inx = 0, realCpyFrameNum = 0, checkImgMimeTypeMax = 0, imgstartOffset = 0,  tmp = 0;
-       int textEncodingType = 0;
-       char **charset_array = NULL;
-       const char *MIME_PRFIX = "image/";
+       unsigned int n = 0;
+       int i = 0;
 
-       make_characterset_array(&charset_array);
+       while (i < 2) {
+               n  += tag[i++] - 'A' + 1;
+               n  <<= 5;
+       }
+       n  += tag[2];   //num, char mixted
 
-       init_content_info(pInfo);
+       for (i = 0; i < ID3TAG_NUM_V22; i++) {
+               if (n == tag_info_v22[i].int_name) {
+                       return tag_info_v22[i].tag;
+               }
+       }
 
-       taglen = pInfo->tagV2Info.tagLen;
-       needToloopv2taglen = taglen - MP3_TAGv2_HEADER_LEN;
-       curPos = MP3_TAGv2_HEADER_LEN;
+       debug_msg(RELEASE, "(%s) This Frame ID currently not Supports!!", tag);
 
-#ifdef __MMFILE_TEST_MODE__
-       debug_msg("ID3tag v223--------------------------------------------------------------\n");
-#endif
+       return AV_ID3TAG_MAX;
+}
 
-       /* check Extended Header */
-       if (buffer[5] & 0x40) {
-               /* if extended header exists, skip it*/
-               int extendedHeaderLen = (unsigned long)buffer[10] << 21 | (unsigned long)buffer[11] << 14 | (unsigned long)buffer[12] << 7  | (unsigned long)buffer[13];
+static AvID3TagList __get_tag_info_v223(const unsigned char *tag)
+{
+       unsigned int n = 0;
+       int i = 0;
 
-#ifdef __MMFILE_TEST_MODE__
-               debug_msg("--------------- extendedHeaderLen = %d\n", extendedHeaderLen);
-#endif
+       while (i < 3) {
+               n  += tag[i++] - 'A' + 1;
+               n  <<= 5;
+       }
+       n  += tag[3];   //num, char mixted
 
-               if (extendedHeaderLen > (int)(taglen - curPos)) {
-                       debug_error("extended header too long.\n");
-               } else {
-                       curPos += extendedHeaderLen;
-                       curPos += 4;
+       for (i = 0; i < ID3TAG_NUM_V23; i++) {
+               if (n == tag_info_v23[i].int_name) {
+                       return tag_info_v23[i].tag;
                }
        }
 
-       if (needToloopv2taglen - MP3_TAGv2_23_TXT_HEADER_LEN > MP3_TAGv2_23_TXT_HEADER_LEN) {
-               v2numOfFrames = 1;
-               while (needToloopv2taglen > MP3_TAGv2_23_TXT_HEADER_LEN) {
-                       if ((buffer[curPos] < '0' || buffer[curPos] > 'Z') || (buffer[curPos + 1] < '0' || buffer[curPos + 1] > 'Z')
-                           || (buffer[curPos + 2] < '0' || buffer[curPos + 2] > 'Z') || (buffer[curPos + 3] < '0' || buffer[curPos + 3] > 'Z'))
-                               break;
+       debug_msg(RELEASE, "(%s) This Frame ID currently not Supports!!", tag);
 
-                       memcpy(CompTmp, &buffer[curPos], 4);
+       return AV_ID3TAG_MAX;
+}
 
-                       CompTmp[4] = 0;
-                       oneFrameLen = MP3_TAGv2_23_TXT_HEADER_LEN;
-                       oneFrameLen += (unsigned long)buffer[4 + curPos] << 24 | (unsigned long)buffer[5 + curPos] << 16
-                                               | (unsigned long)buffer[6 + curPos] << 8 | (unsigned long)buffer[7 + curPos];
 
-#ifdef __MMFILE_TEST_MODE__
-                       debug_msg("----------------------------------------------------------------------------------------------------\n");
-#endif
+bool mm_file_id3tag_parse_v222(AvFileContentInfo *pInfo, unsigned char *buffer, bool extract_artwork)
+{
+       int curPos = MP3_TAGv2_HEADER_LEN;
+       int frameLen = 0;
+       int encOffset = 0;
+       int encType = 0;
+       char **charset_array = NULL;
+       AvID3TagList tag_id = AV_ID3TAG_MAX;
 
-                       if (oneFrameLen > taglen - curPos)
-                               break;
+       if (pInfo->tagV2Info.tagLen <= 0)
+               return false;
 
-                       purelyFramelen = oneFrameLen - MP3_TAGv2_23_TXT_HEADER_LEN;
-                       curPos += MP3_TAGv2_23_TXT_HEADER_LEN;
+       make_characterset_array(&charset_array);
+       init_content_info(pInfo);
 
-                       if (oneFrameLen > MP3_TAGv2_23_TXT_HEADER_LEN && purelyFramelen <= taglen - curPos) {
-                               curPos += purelyFramelen;
+       debug_msg(RELEASE, "ID3tag v222--------------------------------------------------------------");
 
-                               if (IS_ENCODEDBY_UTF16(buffer + (curPos - purelyFramelen))) {
-                                       encodingOffSet = 2;
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("this text string(%s) encoded by UTF16 encodingOffSet(%d)\n", CompTmp, encodingOffSet);
-#endif
-                                       textEncodingType = AV_ID3V2_UTF16;
-                               } else if (IS_ENCODEDBY_UTF16_R(buffer + (curPos - purelyFramelen))) {
-                                       encodingOffSet = 2;
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("this text string(%s) encoded by UTF16 encodingOffSet(%d)\n", CompTmp, encodingOffSet);
-#endif
-                                       textEncodingType = AV_ID3V2_UTF16_BE;
-                               } else if (IS_ENCODEDBY_UTF16(buffer + (curPos - purelyFramelen + 1))) {
-                                       encodingOffSet = 3;
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("this text string(%s) encoded by UTF16 encodingOffSet(%d)\n", CompTmp, encodingOffSet);
-#endif
-                                       textEncodingType = AV_ID3V2_UTF16;
-                               } else if (IS_ENCODEDBY_UTF16_R(buffer + (curPos - purelyFramelen + 1))) {
-                                       encodingOffSet = 3;
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("this text string(%s) encoded by UTF16 encodingOffSet(%d)\n", CompTmp, encodingOffSet);
-#endif
-                                       textEncodingType = AV_ID3V2_UTF16_BE;
-                               } else {
-                                       if (buffer[curPos - purelyFramelen + encodingOffSet] == 0x00) {
-#ifdef __MMFILE_TEST_MODE__
-                                               debug_msg("encodingOffset will be set to 1\n");
-#endif
+       while (curPos + MP3_TAGv2_22_TXT_HEADER_LEN < pInfo->tagV2Info.tagLen) {
+               if (!g_ascii_isalnum(buffer[curPos]) || !g_ascii_isalnum(buffer[curPos + 1]) || !g_ascii_isalnum(buffer[curPos + 2]))
+                       break;
 
-                                               encodingOffSet = 1;
-                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                               debug_msg("Finding encodingOffset\n");
-#endif
+               tag_id = __get_tag_info_v222(&buffer[curPos]);
+               frameLen = buffer[curPos + 3] << 16 | buffer[curPos + 4] << 8 | buffer[curPos + 5];
+               curPos += MP3_TAGv2_22_TXT_HEADER_LEN;
+               if (curPos + frameLen > pInfo->tagV2Info.tagLen)
+                       break;
 
-                                               while ((buffer[curPos - purelyFramelen + encodingOffSet] < 0x20) && (encodingOffSet < purelyFramelen)) /* text string encoded by ISO-8859-1 */
-                                                       encodingOffSet++;
-                                       }
-                                       textEncodingType = AV_ID3V2_ISO_8859;
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("this text string(%s) encoded by ISO-8859-1 encodingOffSet(%d)\n", CompTmp, encodingOffSet);
-#endif
-                               }
+               if (frameLen <= 0)
+                       continue;
 
-                               if (encodingOffSet < purelyFramelen) {
-                                       realCpyFrameNum = purelyFramelen - encodingOffSet;
-                                       pExtContent = mmfile_malloc(realCpyFrameNum + 3);
+               if (tag_id == AV_ID3TAG_MAX || pInfo->tagInfo[tag_id].value)
+                       goto NEXT;
 
-                                       if (pExtContent == NULL) {
-                                               debug_msg("pExtContent malloc failed\n");
-                                               continue;
-                                       }
+               if (buffer[curPos] == 0x00) {
+                       encOffset = 1;
+                       encType = AV_ID3V2_ISO_8859;
+               } else if (buffer[curPos] == 0x01) {
+                       encOffset = 1;
+                       encType = AV_ID3V2_UTF16;
+               }
 
-                                       memset(pExtContent, '\0', realCpyFrameNum + 3);
+               /*in order to deliver valid string to MP */
+               while ((buffer[curPos + encOffset] < 0x20) && (encOffset < frameLen))
+                       encOffset++;
 
-                                       if (textEncodingType != AV_ID3V2_UTF16 && textEncodingType != AV_ID3V2_UTF16_BE) {
-                                               if (CompTmp[0] == 'T' || (strcmp(CompTmp, "APIC") == 0)) {
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("get the new text ecoding type\n");
-#endif
-                                                       textEncodingType = buffer[curPos - purelyFramelen + encodingOffSet - 1];
-                                               }
-                                       }
+               if (frameLen == encOffset) {
+                       debug_warning(DEBUG, "warning: invalid frame length %d %d", frameLen, encOffset);
+                       goto NEXT;
+               }
 
-                                       if (textEncodingType > AV_ID3V2_MAX) {
-                                               debug_msg("WRONG ENCOIDNG TYPE [%d], FRAME[%s]\n", textEncodingType, (char *)CompTmp);
-                                               continue;
-                                       }
+               curPos += encOffset;
+               frameLen -= encOffset;
+
+               switch (tag_id) {
+               case AV_ID3TAG_COMMENT:
+                       /*
+                       https://id3.org/id3v2-00
+                       Comment                   "COM"
+                       Frame size                $xx xx xx
+                       Text encoding             $xx
+                       Language                  $xx xx xx
+                       Short content description <textstring> $00 (00)
+                       The actual text           <textstring>
+                       */
+                       if (frameLen <= 4) {
+                               debug_msg(RELEASE, "Too small to parse frameLen(%d)", frameLen);
+                               break;
+                       }
 
-                                       memcpy(pExtContent, &buffer[curPos - purelyFramelen + encodingOffSet], purelyFramelen - encodingOffSet);
-                                       if (realCpyFrameNum > 0) {
-                                               if (strncmp((char *)CompTmp, "TIT2", 4) == 0 && pInfo->tagV2Info.bTitleMarked == false) {
-                                                       pInfo->pTitle = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->titleLen);
+                       if (buffer[curPos + 4] > 0x20 && (buffer[curPos + 3] == 0x00 || buffer[curPos + 3] == 0x01)) {
+                               encType = __id3tag_get_text_encoding_v222(&buffer[curPos], 4);
+                               /*skip language data! */
+                               curPos += 4;
+                               frameLen -= 4;
+                               pInfo->tagInfo[tag_id].value = mmfile_convert_to_utf8((const char *)&buffer[curPos], frameLen, charset_array[encType]);
+                       } else {
+                               debug_msg(RELEASE, "Failed to get tag: frameLen(%d)", frameLen);
+                       }
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pTitle returned = (%s), pInfo->titleLen(%d)\n", pInfo->pTitle, pInfo->titleLen);
-#endif
-                                                       pInfo->tagV2Info.bTitleMarked = true;
+                       break;
 
-                                               } else if (strncmp((char *)CompTmp, "TPE1", 4) == 0 && pInfo->tagV2Info.bArtistMarked == false) {
-                                                       pInfo->pArtist = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->artistLen);
+               case AV_ID3TAG_PICTURE:
+                       if (extract_artwork)
+                               _mm_file_id3tag_parse_PIC(pInfo, &buffer[curPos], frameLen, charset_array[encType]);
+                       break;
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pArtist returned = (%s), pInfo->artistLen(%d)\n", pInfo->pArtist, pInfo->artistLen);
-#endif
-                                                       pInfo->tagV2Info.bArtistMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TPE2", 4) == 0 && pInfo->tagV2Info.bAlbum_ArtistMarked == false) {
-                                                       pInfo->pAlbum_Artist = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->album_artistLen);
+               default:
+                       pInfo->tagInfo[tag_id].value = mmfile_convert_to_utf8((const char *)&buffer[curPos], frameLen, charset_array[encType]);
+                       break;
+               }
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pAlbum_Artist returned = (%s), pInfo->album_artistLen(%d)\n", pInfo->pAlbum_Artist, pInfo->album_artistLen);
-#endif
-                                                       pInfo->tagV2Info.bAlbum_ArtistMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TPE3", 4) == 0 && pInfo->tagV2Info.bConductorMarked == false) {
-                                                       pInfo->pConductor = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->conductorLen);
+               if (pInfo->tagInfo[tag_id].value)
+                       debug_msg(RELEASE, "[%d] returned = (%s)", tag_id, pInfo->tagInfo[tag_id].value);
+NEXT:
+               curPos += frameLen;
+               encOffset = 0;
+               encType = 0;
+       }
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pConductor returned = (%s), pInfo->conductorLen(%d)\n", pInfo->pConductor, pInfo->conductorLen);
-#endif
-                                                       pInfo->tagV2Info.bConductorMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TALB", 4) == 0 && pInfo->tagV2Info.bAlbumMarked == false) {
-                                                       pInfo->pAlbum = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->albumLen);
+       release_characterset_array(charset_array);
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pAlbum returned = (%s), pInfo->albumLen(%d)\n", pInfo->pAlbum, pInfo->albumLen);
-#endif
-                                                       pInfo->tagV2Info.bAlbumMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TYER", 4) == 0 && pInfo->tagV2Info.bYearMarked == false) {
-                                                       pInfo->pYear = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->yearLen);
+       return true;
+}
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pYear returned = (%s), pInfo->yearLen(%d)\n", pInfo->pYear, pInfo->yearLen);
-#endif
-                                                       pInfo->tagV2Info.bYearMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "COMM", 4) == 0 && pInfo->tagV2Info.bDescriptionMarked == false) {
-                                                       if (realCpyFrameNum > 3) {
-                                                               realCpyFrameNum -= 3;
-                                                               tmp = 3;
-
-                                                               /*pExtContent[tmp+1] value should't have encoding value */
-                                                               if (pExtContent[tmp] == 0x00 || pExtContent[tmp] == 0xFF || pExtContent[tmp] == 0xFE) {
-                                                                       if ((IS_ENCODEDBY_UTF16(pExtContent + tmp) || IS_ENCODEDBY_UTF16_R(pExtContent + tmp)) && realCpyFrameNum > 2) {
-                                                                               while ((NEWLINE_OF_UTF16(pExtContent + tmp) || NEWLINE_OF_UTF16_R(pExtContent + tmp)) && realCpyFrameNum > 4) {
-                                                                                       realCpyFrameNum -= 4;
-                                                                                       tmp += 4;
-                                                                               }
-
-                                                                               if (IS_ENCODEDBY_UTF16(pExtContent + tmp) && (realCpyFrameNum > 2)) {
-                                                                                       realCpyFrameNum -= 2;
-                                                                                       tmp += 2;
-                                                                                       textEncodingType = AV_ID3V2_UTF16;
-                                                                               } else if (IS_ENCODEDBY_UTF16_R(pExtContent + tmp) && (realCpyFrameNum > 2)) {
-                                                                                       realCpyFrameNum -= 2;
-                                                                                       tmp += 2;
-                                                                                       textEncodingType = AV_ID3V2_UTF16_BE;
-                                                                               } else if (IS_ENCODEDBY_UTF16(pExtContent + tmp + 1) && (realCpyFrameNum > 3)) {
-                                                                                       realCpyFrameNum -= 3;
-                                                                                       tmp += 3;
-                                                                                       textEncodingType = AV_ID3V2_UTF16;
-                                                                               } else if (IS_ENCODEDBY_UTF16_R(pExtContent + tmp + 1)  && (realCpyFrameNum > 3)) {
-                                                                                       realCpyFrameNum -= 3;
-                                                                                       tmp += 3;
-                                                                                       textEncodingType = AV_ID3V2_UTF16_BE;
-                                                                               } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                                       debug_msg("pInfo->pComment Never Get Here!!\n");
-#endif
-                                                                               }
-                                                                       } else {
-                                                                               while ((pExtContent[tmp] < 0x20) && (tmp < realCpyFrameNum)) { /* text string encoded by ISO-8859-1 */
-                                                                                       realCpyFrameNum--;
-                                                                                       tmp++;
-                                                                               }
-                                                                               textEncodingType = AV_ID3V2_ISO_8859;
-                                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("tmp(%d) textEncodingType(%d), realCpyFrameNum(%d)\n", tmp, textEncodingType, realCpyFrameNum);
-#endif
+static void __get_v223_encoding_info(const unsigned char *buffer,
+                                                                       int length,
+                                                                       int *offset,
+                                                                       unsigned int *type)
+{
+       int _offset = 0;
 
-                                                                       pInfo->pComment = mmfile_string_convert((const char *)&pExtContent[tmp], realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->commentLen);
-                                                               } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("failed to get Comment Info tmp(%d), purelyFramelen - encodingOffSet(%d)\n", tmp, purelyFramelen - encodingOffSet);
-#endif
-                                                                       pInfo->commentLen = 0;
-                                                               }
-                                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("Description info too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum);
-#endif
-                                                               pInfo->commentLen = 0;
-                                                       }
-                                                       tmp = 0;
+       if (!buffer || !offset || !type)
+               return;
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pComment returned = (%s), pInfo->commentLen(%d)\n", pInfo->pComment, pInfo->commentLen);
-#endif
-                                                       pInfo->tagV2Info.bDescriptionMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "SYLT", 4) == 0 && pInfo->tagV2Info.bSyncLyricsMarked == false) {
-                                                       int idx = 0;
-                                                       int copy_len = 0;
-                                                       int copy_start_pos = tmp;
-                                                       AvSynclyricsInfo *synclyrics_info = NULL;
-                                                       GList *synclyrics_info_list = NULL;
-
-                                                       if (realCpyFrameNum > 5) {
-                                                               realCpyFrameNum -= 5;
-                                                               tmp = 5;
-
-                                                               /*pExtContent[tmp+1] value should't have encoding value */
-                                                               if (pExtContent[tmp] == 0x00 || pExtContent[tmp] == 0xFF || pExtContent[tmp] == 0xFE) {
-                                                                       if ((IS_ENCODEDBY_UTF16(pExtContent + tmp) || IS_ENCODEDBY_UTF16_R(pExtContent + tmp)) && realCpyFrameNum > 2) {
-                                                                               while ((NEWLINE_OF_UTF16(pExtContent + tmp) || NEWLINE_OF_UTF16_R(pExtContent + tmp)) && realCpyFrameNum > 4) {
-                                                                                       realCpyFrameNum -= 4;
-                                                                                       tmp += 4;
-                                                                               }
-
-                                                                               if (IS_ENCODEDBY_UTF16(pExtContent + tmp) && (realCpyFrameNum > 2)) {
-                                                                                       realCpyFrameNum -= 2;
-                                                                                       tmp += 2;
-                                                                                       textEncodingType = AV_ID3V2_UTF16;
-                                                                               } else if (IS_ENCODEDBY_UTF16_R(pExtContent + tmp) && (realCpyFrameNum > 2)) {
-                                                                                       realCpyFrameNum -= 2;
-                                                                                       tmp += 2;
-                                                                                       textEncodingType = AV_ID3V2_UTF16_BE;
-                                                                               } else if (IS_ENCODEDBY_UTF16(pExtContent + tmp + 1) && (realCpyFrameNum > 3)) {
-                                                                                       realCpyFrameNum -= 3;
-                                                                                       tmp += 3;
-                                                                                       textEncodingType = AV_ID3V2_UTF16;
-                                                                               } else if (IS_ENCODEDBY_UTF16_R(pExtContent + tmp + 1)  && (realCpyFrameNum > 3)) {
-                                                                                       realCpyFrameNum -= 3;
-                                                                                       tmp += 3;
-                                                                                       textEncodingType = AV_ID3V2_UTF16_BE;
-                                                                               } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                                       debug_msg("pInfo->pSyncLyrics Never Get Here!!\n");
-#endif
-                                                                               }
-                                                                       } else {
-                                                                               while ((pExtContent[tmp] < 0x20) && (tmp < realCpyFrameNum)) { /* text string encoded by ISO-8859-1 */
-                                                                                       realCpyFrameNum--;
-                                                                                       tmp++;
-                                                                               }
-                                                                               textEncodingType = AV_ID3V2_ISO_8859;
-                                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("tmp(%d) textEncodingType(%d), realCpyFrameNum(%d)\n", tmp, textEncodingType, realCpyFrameNum);
-#endif
+       if (IS_ENCODEDBY_UTF16(buffer)) {
+               *offset = 2;
+               *type = AV_ID3V2_UTF16;
+               return;
+       }
+       if (IS_ENCODEDBY_UTF16_R(buffer)) {
+               *offset = 2;
+               *type = AV_ID3V2_UTF16_BE;
+               return;
+       }
+       if (IS_ENCODEDBY_UTF16(buffer + 1)) {
+               *offset = 3;
+               *type = AV_ID3V2_UTF16;
+               return;
+       }
+       if (IS_ENCODEDBY_UTF16_R(buffer + 1)) {
+               *offset = 3;
+               *type = AV_ID3V2_UTF16_BE;
+               return;
+       }
 
-                                                                       if (realCpyFrameNum < MMFILE_SYNC_LYRIC_INFO_MIN_LEN) {
-#ifdef __MMFILE_TEST_MODE__
-                                                                               debug_msg("failed to get Synchronised lyrics Info realCpyFramNum(%d)\n", realCpyFrameNum);
-#endif
-                                                                               pInfo->syncLyricsNum = 0;
-                                                                       } else {
-                                                                               if (textEncodingType == AV_ID3V2_UTF16) {
-                                                                                       debug_warning("[AV_ID3V2_UTF16] not implemented\n");
-                                                                               } else if (textEncodingType == AV_ID3V2_UTF16_BE) {
-                                                                                       debug_warning("[AV_ID3V2_UTF16_BE] not implemented\n");
-                                                                               } else {
-                                                                                       for (idx = 0; idx < realCpyFrameNum; idx++) {
-                                                                                               if (pExtContent[tmp + idx] == 0x00) {
-                                                                                                       synclyrics_info = (AvSynclyricsInfo *)malloc(sizeof(AvSynclyricsInfo));
-
-                                                                                                       if (synclyrics_info != NULL) {
-                                                                                                               if (textEncodingType == AV_ID3V2_UTF8) {
-                                                                                                                       synclyrics_info->lyric_info = mmfile_malloc(copy_len + 1);
-                                                                                                                       if (synclyrics_info->lyric_info != NULL) {
-                                                                                                                               memset(synclyrics_info->lyric_info, 0, copy_len + 1);
-                                                                                                                               memcpy(synclyrics_info->lyric_info, pExtContent + copy_start_pos, copy_len);
-                                                                                                                               synclyrics_info->lyric_info[copy_len] = '\0';
-                                                                                                                       }
-                                                                                                               } else {
-                                                                                                                       synclyrics_info->lyric_info = mmfile_string_convert((const char *)&pExtContent[copy_start_pos], copy_len, "UTF-8", charset_array[AV_ID3V2_ISO_8859], NULL, NULL);
-                                                                                                               }
-
-                                                                                                               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];
-                                                                                                               idx += 4;
-                                                                                                               copy_start_pos = tmp + idx + 1;
-#ifdef __MMFILE_TEST_MODE__
-                                                                                                               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);
-#endif
-                                                                                                               copy_len = 0;
-                                                                                                               synclyrics_info_list = g_list_append(synclyrics_info_list, synclyrics_info);
-                                                                                                       }
-                                                                                               }
-                                                                                               copy_len++;
-                                                                                       }
-                                                                                       pInfo->pSyncLyrics = synclyrics_info_list;
-                                                                                       pInfo->syncLyricsNum = g_list_length(pInfo->pSyncLyrics);
-                                                                               }
-                                                                       }
-                                                               } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("failed to get Synchronised lyrics Info tmp(%d), purelyFramelen - encodingOffSet(%d)\n", tmp, purelyFramelen - encodingOffSet);
-#endif
-                                                                       pInfo->syncLyricsNum = 0;
-                                                               }
-                                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("Synchronised lyrics too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum);
-#endif
-                                                               pInfo->syncLyricsNum = 0;
-                                                       }
-                                                       tmp = 0;
+       if (buffer[0] == 0x00) {
+               *offset = 1;
+       } else {
+               while ((buffer[_offset] < 0x20) && (_offset < length))
+                       _offset++;
+               *offset = _offset;
+       }
+       *type = AV_ID3V2_ISO_8859;
+}
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pSyncLyrics returned = (%s), pInfo->syncLyricsNum(%d)\n", pInfo->pSyncLyrics, pInfo->syncLyricsNum);
-#endif
-                                                       pInfo->tagV2Info.bSyncLyricsMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "USLT", 4) == 0 && pInfo->tagV2Info.bUnsyncLyricsMarked == false) {
-                                                       char *lang_info = strndup((char *)pExtContent, 3);
-
-                                                       if (realCpyFrameNum > 3) {
-                                                               realCpyFrameNum -= 3;
-                                                               tmp = 3;
-
-                                                               /*find start of lyrics */
-                                                               while (1) {
-                                                                       if (pExtContent[tmp] == 0x00) {
-                                                                               if (pExtContent[tmp + 1] == 0x00) {
-                                                                                       realCpyFrameNum -= 2;
-                                                                                       tmp += 2;
-                                                                               }
-                                                                               break;
-                                                                       } else {
-                                                                               realCpyFrameNum--;
-                                                                               tmp++;
-                                                                       }
-                                                               }
-
-                                                               /*pExtContent[tmp+1] value should't have encoding value */
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("tpExtContent[%d] %x\n", tmp, pExtContent[tmp]);
-#endif
-                                                               if (pExtContent[tmp] == 0x00 || pExtContent[tmp] == 0xFF || pExtContent[tmp] == 0xFE) {
-                                                                       if ((IS_ENCODEDBY_UTF16(pExtContent + tmp) || IS_ENCODEDBY_UTF16_R(pExtContent + tmp)) && realCpyFrameNum > 2) {
-                                                                               while ((NEWLINE_OF_UTF16(pExtContent + tmp) || NEWLINE_OF_UTF16_R(pExtContent + tmp)) && realCpyFrameNum > 4) {
-                                                                                       realCpyFrameNum -= 4;
-                                                                                       tmp += 4;
-                                                                               }
-
-                                                                               if (IS_ENCODEDBY_UTF16(pExtContent + tmp) && (realCpyFrameNum > 2)) {
-                                                                                       realCpyFrameNum -= 2;
-                                                                                       tmp += 2;
-                                                                                       textEncodingType = AV_ID3V2_UTF16;
-                                                                               } else if (IS_ENCODEDBY_UTF16_R(pExtContent + tmp) && (realCpyFrameNum > 2)) {
-                                                                                       realCpyFrameNum -= 2;
-                                                                                       tmp += 2;
-                                                                                       textEncodingType = AV_ID3V2_UTF16_BE;
-                                                                               } else if (IS_ENCODEDBY_UTF16(pExtContent + tmp + 1) && (realCpyFrameNum > 3)) {
-                                                                                       realCpyFrameNum -= 3;
-                                                                                       tmp += 3;
-                                                                                       textEncodingType = AV_ID3V2_UTF16;
-                                                                               } else if (IS_ENCODEDBY_UTF16_R(pExtContent + tmp + 1)  && (realCpyFrameNum > 3)) {
-                                                                                       realCpyFrameNum -= 3;
-                                                                                       tmp += 3;
-                                                                                       textEncodingType = AV_ID3V2_UTF16_BE;
-                                                                               } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                                       debug_msg("pInfo->pUnsyncLyrics Never Get Here!!\n");
-#endif
-                                                                               }
-                                                                       } else {
-                                                                               while ((pExtContent[tmp] < 0x20) && (tmp < realCpyFrameNum)) { /* text string encoded by ISO-8859-1 */
-                                                                                       realCpyFrameNum--;
-                                                                                       tmp++;
-                                                                               }
-                                                                               textEncodingType = AV_ID3V2_ISO_8859;
-                                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("tmp(%d) textEncodingType(%d), realCpyFrameNum(%d)\n", tmp, textEncodingType, realCpyFrameNum);
-#endif
+bool mm_file_id3tag_parse_v223(AvFileContentInfo *pInfo, unsigned char *buffer, bool extract_artwork)
+{
+       int extendedHeaderLen = 0;
+       int frameLen = 0;
+       int curPos = MP3_TAGv2_HEADER_LEN;
+       int encOffset = 0;
+       unsigned int encType = 0;
+       char **charset_array = NULL;
+       AvID3TagList tag_id = AV_ID3TAG_MAX;
+       char *lang_info = NULL;
 
-                                                                       char *char_set = NULL;
-                                                                       if (textEncodingType == AV_ID3V2_ISO_8859) {
-                                                                               if (lang_info != NULL && !strcasecmp(lang_info, "KOR")) {
-                                                                                       char_set = strdup("EUC-KR");
-                                                                               } else {
-                                                                                       char_set = mmfile_get_charset((const char *)&pExtContent[tmp]);
-                                                                               }
-                                                                               _FREE_EX(lang_info);
-                                                                       }
-
-                                                                       if (char_set == NULL) {
-                                                                               pInfo->pUnsyncLyrics = mmfile_string_convert((const char *)&pExtContent[tmp], realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->unsynclyricsLen);
-                                                                       } else {
-                                                                               pInfo->pUnsyncLyrics = mmfile_string_convert((const char *)&pExtContent[tmp], realCpyFrameNum, "UTF-8", char_set, NULL, (unsigned int *)&pInfo->unsynclyricsLen);
-                                                                               _FREE_EX(char_set);
-                                                                       }
-                                                               } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("failed to get Unsynchronised lyrics Info tmp(%d), purelyFramelen - encodingOffSet(%d)\n", tmp, purelyFramelen - encodingOffSet);
-#endif
-                                                                       pInfo->unsynclyricsLen = 0;
-                                                               }
-                                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("Unsynchronised lyrics too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum);
-#endif
-                                                               pInfo->unsynclyricsLen = 0;
-                                                       }
-                                                       tmp = 0;
+       if (pInfo->tagV2Info.tagLen <= 0)
+               return false;
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pUnsyncLyrics returned = (%s), pInfo->unsynclyricsLen(%d)\n", pInfo->pUnsyncLyrics, pInfo->unsynclyricsLen);
-#endif
-                                                       pInfo->tagV2Info.bUnsyncLyricsMarked = true;
-                                                       mmfile_free(lang_info);
-                                               } else if (strncmp((char *)CompTmp, "TCON", 4) == 0 && pInfo->tagV2Info.bGenreMarked == false) {
-                                                       pInfo->pGenre = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->genreLen);
+       make_characterset_array(&charset_array);
+       init_content_info(pInfo);
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pGenre returned = (%s), pInfo->genreLen(%d)\n", pInfo->pGenre, pInfo->genreLen);
-#endif
+       debug_msg(RELEASE, "ID3tag v223--------------------------------------------------------------");
+       if (buffer[5] & 0x40) {
+               /* if extended header exists, skip it*/
+               extendedHeaderLen = buffer[10] << 21 | buffer[11] << 14 | buffer[12] << 7 | buffer[13];
+               debug_msg(RELEASE, "--------------- extendedHeaderLen = %d", extendedHeaderLen);
+               if (extendedHeaderLen > pInfo->tagV2Info.tagLen - MP3_TAGv2_HEADER_LEN) {
+                       debug_error(DEBUG, "extended header too long.");
+               } else {
+                       curPos += extendedHeaderLen;
+                       curPos += 4;
+               }
+       }
 
-                                                       if ((pInfo->pGenre != NULL) && (pInfo->genreLen > 0)) {
-                                                               bool ret = FALSE;
-                                                               int int_genre = -1;
+       while (curPos + MP3_TAGv2_23_TXT_HEADER_LEN < pInfo->tagV2Info.tagLen) {
+               if (!g_ascii_isalnum(buffer[curPos]) || !g_ascii_isalnum(buffer[curPos + 1]) ||
+                       !g_ascii_isalnum(buffer[curPos + 2]) || !g_ascii_isalnum(buffer[curPos + 3]))
+                       break;
 
-                                                               ret = is_numeric(pInfo->pGenre, pInfo->genreLen);
+               tag_id = __get_tag_info_v223(&buffer[curPos]);
+               frameLen = buffer[curPos + 4] << 24 | buffer[curPos + 5] << 16 | buffer[curPos + 6] << 8 | buffer[curPos + 7];
+               curPos += MP3_TAGv2_23_TXT_HEADER_LEN;
+               if (curPos + frameLen > pInfo->tagV2Info.tagLen)
+                       break;
 
-                                                               if (ret == TRUE) {
-                                                                       sscanf(pInfo->pGenre, "%d", &int_genre);
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("genre information is inteager [%d]\n", int_genre);
-#endif
+               if (frameLen <= 0)
+                       continue;
 
-                                                                       /*Change int to string */
-                                                                       if ((0 <= int_genre) && (int_genre < GENRE_COUNT - 1)) {
-                                                                               /*save genreinfo like "(123)". mm_file_id3tag_restore_content_info convert it to string*/
-                                                                               char tmp_genre[6] = {0, };      /*ex. "(123)+NULL"*/
-                                                                               int tmp_genre_len = 0;
-
-                                                                               memset(tmp_genre, 0, 6);
-                                                                               snprintf(tmp_genre, sizeof(tmp_genre), "(%d)", int_genre);
-
-                                                                               tmp_genre_len = strlen(tmp_genre);
-                                                                               if (tmp_genre_len > 0) {
-                                                                                       if (pInfo->pGenre) _FREE_EX(pInfo->pGenre);
-                                                                                       pInfo->pGenre = mmfile_malloc(sizeof(char) * (tmp_genre_len + 1));
-                                                                                       if (pInfo->pGenre) {
-                                                                                               strncpy(pInfo->pGenre, tmp_genre, tmp_genre_len);
-                                                                                               pInfo->pGenre[tmp_genre_len] = 0;
-                                                                                       }
-                                                                               }
-                                                                       }
-                                                               }
-                                                       }
+               if (tag_id == AV_ID3TAG_MAX || pInfo->tagInfo[tag_id].value)
+                       goto NEXT;
 
-                                                       pInfo->tagV2Info.bGenreMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TRCK", 4) == 0 && pInfo->tagV2Info.bTrackNumMarked == false) {
-                                                       pInfo->pTrackNum = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->tracknumLen);
+               __get_v223_encoding_info(buffer + curPos, frameLen, &encOffset, &encType);
+               if (frameLen <= encOffset) {
+                       debug_warning(DEBUG, "warning: invalid frame length %d %d", frameLen, encOffset);
+                       goto NEXT;
+               }
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pTrackNum returned = (%s), pInfo->tracknumLen(%d)\n", pInfo->pTrackNum, pInfo->tracknumLen);
-#endif
-                                                       pInfo->tagV2Info.bTrackNumMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TENC", 4) == 0 && pInfo->tagV2Info.bEncByMarked == false) {
-                                                       pInfo->pEncBy = mmfile_string_convert((char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->encbyLen);
+               curPos += encOffset;
+               frameLen -= encOffset;
+               encOffset = 0;
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pEncBy returned = (%s), pInfo->encbyLen(%d)\n", pInfo->pEncBy, pInfo->encbyLen);
-#endif
-                                                       pInfo->tagV2Info.bEncByMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "WXXX", 4) == 0 && pInfo->tagV2Info.bURLMarked == false) {
-                                                       pInfo->pURL = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->urlLen);
+               if (encType != AV_ID3V2_UTF16 && encType != AV_ID3V2_UTF16_BE) {
+                       if (tag_id != AV_ID3TAG_COMMENT && tag_id != AV_ID3TAG_UNSYNCLYRICS && tag_id != AV_ID3TAG_SYNCLYRICS) {
+                               debug_msg(RELEASE, "get the new text encoding type");
+                               encType = buffer[curPos - 1];
+                       }
+               }
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pURL returned = (%s), pInfo->urlLen(%d)\n", pInfo->pURL, pInfo->urlLen);
-#endif
-                                                       pInfo->tagV2Info.bURLMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TCOP", 4) == 0 && pInfo->tagV2Info.bCopyRightMarked == false) {
-                                                       pInfo->pCopyright = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->copyrightLen);
+               if (encType > AV_ID3V2_MAX) {
+                       debug_msg(DEBUG, "WRONG ENCOIDNG TYPE [%u], TAG ID[%d]", encType, tag_id);
+                       goto NEXT;
+               }
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pCopyright returned = (%s), pInfo->copyrightLen(%d)\n", pInfo->pCopyright, pInfo->copyrightLen);
-#endif
-                                                       pInfo->tagV2Info.bCopyRightMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TOPE", 4) == 0 && pInfo->tagV2Info.bOriginArtistMarked == false) {
-                                                       pInfo->pOriginArtist = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->originartistLen);
+               switch (tag_id) {
+               case AV_ID3TAG_COMMENT:
+                       if (frameLen <= 3) {
+                               debug_msg(RELEASE, "Description info too small to parse frameLen(%d)", frameLen);
+                               break;
+                       }
+                       frameLen -= 3;
+                       encOffset = 3;
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pOriginArtist returned = (%s), pInfo->originartistLen(%d)\n", pInfo->pOriginArtist, pInfo->originartistLen);
-#endif
-                                                       pInfo->tagV2Info.bOriginArtistMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TCOM", 4) == 0 && pInfo->tagV2Info.bComposerMarked == false) {
-                                                       pInfo->pComposer = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->composerLen);
+                       if (buffer[curPos] != 0x00 && buffer[curPos] != 0xFF && buffer[curPos] != 0xFE) {
+                               debug_msg(RELEASE, "failed to get Comment: frameLen(%d)", frameLen);
+                       }
 
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pComposer returned = (%s), pInfo->composerLen(%d)\n", pInfo->pComposer, pInfo->composerLen);
-#endif
-                                                       pInfo->tagV2Info.bComposerMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TRDA", 4) == 0 && pInfo->tagV2Info.bRecDateMarked == false) {
-                                                       pInfo->pRecDate = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->recdateLen);
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pRecDate returned = (%s), pInfo->recdateLen(%d)\n", pInfo->pRecDate, pInfo->recdateLen);
-#endif
-                                                       pInfo->tagV2Info.bRecDateMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "APIC", 4) == 0 && pInfo->tagV2Info.bImageMarked == false && realCpyFrameNum <= 2000000) {
-                                                       debug_msg("text encoding %d \n", textEncodingType);
-
-                                                       if (pExtContent[0] != '\0') {
-                                                               for (inx = 0; inx < MP3_ID3_IMAGE_MIME_TYPE_MAX_LENGTH - 1; inx++)
-                                                                       pInfo->imageInfo.imageMIMEType[inx] = '\0';/*ini mimetype variable */
-
-                                                               while ((checkImgMimeTypeMax < MP3_ID3_IMAGE_MIME_TYPE_MAX_LENGTH - 1) && pExtContent[checkImgMimeTypeMax] != '\0') {
-                                                                       pInfo->imageInfo.imageMIMEType[checkImgMimeTypeMax] = pExtContent[checkImgMimeTypeMax];
-                                                                       checkImgMimeTypeMax++;
-                                                               }
-                                                               pInfo->imageInfo.imgMimetypeLen = checkImgMimeTypeMax;
-                                                       } else {
-                                                               pInfo->imageInfo.imgMimetypeLen = 0;
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("APIC image's not included to MIME type\n");
-#endif
-                                                       }
-
-                                                       imgstartOffset += checkImgMimeTypeMax;
-
-                                                       if (strncmp(pInfo->imageInfo.imageMIMEType, MIME_PRFIX, strlen(MIME_PRFIX)) != 0) {
-                                                               pInfo->imageInfo.imgMimetypeLen = 0;
-                                                               debug_error("APIC NOT VALID");
-                                                               continue;
-                                                       }
+                       encType = __id3tag_get_text_encoding_v223(&buffer[curPos], &frameLen, encType, &encOffset);
+                       debug_msg(RELEASE, "encOffset(%d) encType(%u), frameLen(%d)", encOffset, encType, frameLen);
+                       curPos += encOffset;
+                       pInfo->tagInfo[tag_id].value = mmfile_convert_to_utf8((const char *)&buffer[curPos], frameLen, charset_array[encType]);
+                       break;
 
-                                                       if ((pExtContent[imgstartOffset] == '\0') && (realCpyFrameNum - imgstartOffset > 0)) {
-                                                               imgstartOffset++;/*endofMIME(1byte) */
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("after scaning Mime type imgstartOffset(%d) value!\n", imgstartOffset);
-#endif
+               case AV_ID3TAG_SYNCLYRICS:
+                       if (frameLen <= 5) {
+                               debug_msg(RELEASE, "Synchronised lyrics too small to parse frameLen(%d)", frameLen);
+                               break;
+                       }
+                       frameLen -= 5;
+                       encOffset = 5;
 
-                                                               if (pExtContent[imgstartOffset] < AV_ID3V2_PICTURE_TYPE_MAX) {
-                                                                       pInfo->imageInfo.pictureType = pExtContent[imgstartOffset];
-                                                               } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("APIC image has invalid picture type(0x%x)\n", pExtContent[imgstartOffset]);
-#endif
-                                                               }
-                                                               imgstartOffset++;/*PictureType(1byte) */
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("after scaning PictureType imgstartOffset(%d) value!\n", imgstartOffset);
-#endif
+                       if (buffer[curPos] != 0x00 && buffer[curPos] != 0xFF && buffer[curPos] != 0xFE) {
+                               debug_msg(RELEASE, "failed to get Synchronised lyrics Info curPos(%d), frameLen(%d)", curPos, frameLen);
+                       }
+                       encType = __id3tag_get_text_encoding_v223(&buffer[curPos], &frameLen, encType, &encOffset);
+                       debug_msg(RELEASE, "encOffset(%d) encType(%u), frameLen(%d)", encOffset, encType, frameLen);
+                       curPos += encOffset;
+                       __id3tag_parse_SYLT(pInfo, buffer, frameLen, charset_array[encType], encType, curPos);
+                       break;
 
-                                                               if (pExtContent[imgstartOffset] != 0x0) {
-                                                                       int cur_pos = 0;
-                                                                       int dis_len = 0;
-                                                                       int new_dis_len = 0;
-                                                                       char *tmp_desc = NULL;
-
-                                                                       while (1) {
-                                                                               if (pExtContent[imgstartOffset + cur_pos] == '\0') {
-                                                                                       if (realCpyFrameNum < imgstartOffset + cur_pos) {
-                                                                                               debug_error("End of APIC Tag %d %d %d\n", realCpyFrameNum, imgstartOffset, cur_pos);
-                                                                                               break;
-                                                                                       }
-                                                                                       /*check end of image description*/
-                                                                                       if ((pExtContent[imgstartOffset + cur_pos + 1] == gTagJPEGHeader[0]) ||
-                                                                                           (pExtContent[imgstartOffset + cur_pos + 1] == gTagPNGHeader[0])) {
-#ifdef __MMFILE_TEST_MODE__
-                                                                                               debug_msg("length of description (%d)", cur_pos);
-#endif
+               case AV_ID3TAG_UNSYNCLYRICS:
+                       lang_info = strndup((const char *)&buffer[curPos], 3);
 
-                                                                                               break;
-                                                                                       }
-                                                                               }
-                                                                               cur_pos++;
-                                                                       }
+                       if (frameLen <= 3) {
+                               debug_msg(RELEASE, "Unsynchronised lyrics too small to parse frameLen(%d)", frameLen);
+                               mmfile_free(lang_info);
+                               break;
+                       }
+                       frameLen -= 3;
+                       encOffset = 3;
 
-                                                                       dis_len = cur_pos + 1;
+                       if (buffer[curPos] != 0x00 && buffer[curPos] != 0xFF && buffer[curPos] != 0xFE) {
+                               debug_msg(RELEASE, "failed to get Unsynchronised lyrics Info curPos(%d), frameLen(%d)", curPos, frameLen);
+                       }
+                       encType = __id3tag_get_text_encoding_v223(&buffer[curPos], &frameLen, encType, &encOffset);
 
-                                                                       tmp_desc = mmfile_malloc(sizeof(char) * dis_len);
-                                                                       memcpy(tmp_desc, pExtContent + imgstartOffset, dis_len);
+                       char *char_set = NULL;
 
-                                                                       /*convert description*/
-                                                                       pInfo->imageInfo.imageDescription = mmfile_string_convert(tmp_desc, dis_len, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&new_dis_len);
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("new_desc %s(%d)\n", pInfo->imageInfo.imageDescription, new_dis_len);
-#endif
-                                                                       mmfile_free(tmp_desc);
-
-                                                                       pInfo->imageInfo.imgDesLen = new_dis_len; /**/
-                                                                       imgstartOffset += cur_pos;
-                                                               } else {
-                                                                       pInfo->imageInfo.imgDesLen = 0;
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("APIC image's not included to Description!!!\n");
-#endif
-                                                               }
+                       debug_msg(RELEASE, "encOffset(%d) encType(%u), frameLen(%d)", encOffset, encType, frameLen);
 
-                                                               if ((pExtContent[imgstartOffset] == '\0') && (realCpyFrameNum - imgstartOffset > 0)) {
-                                                                       imgstartOffset++; /* endofDesceriptionType(1byte) */
+                       if (encType == AV_ID3V2_ISO_8859) {
+                               if (lang_info != NULL && !g_ascii_strcasecmp(lang_info, "KOR")) {
+                                       char_set = strdup("EUC-KR");
+                               } else {
+                                       char_set = mmfile_get_charset((const char *)&buffer[curPos]);
+                               }
+                               mmfile_free(lang_info);
+                       }
 
-                                                                       while (pExtContent[imgstartOffset] == '\0') {   /*some content has useless '\0' in front of picture data */
-                                                                               imgstartOffset++;
-                                                                       }
+                       curPos += encOffset;
 
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("after scaning imgDescription imgstartOffset(%d) value!\n", imgstartOffset);
-#endif
+                       if (!char_set) {
+                               pInfo->tagInfo[tag_id].value = mmfile_convert_to_utf8((const char *)&buffer[curPos], frameLen, charset_array[encType]);
+                       } else {
+                               pInfo->tagInfo[tag_id].value = mmfile_convert_to_utf8((const char *)&buffer[curPos], frameLen, char_set);
+                               mmfile_free(char_set);
+                       }
+                       mmfile_free(lang_info);
+                       break;
 
-                                                                       if (realCpyFrameNum - imgstartOffset > 0) {
-                                                                               pInfo->imageInfo.imageLen = realCpyFrameNum - imgstartOffset;
-                                                                               pInfo->imageInfo.pImageBuf = mmfile_malloc(pInfo->imageInfo.imageLen + 1);
+               case AV_ID3TAG_PICTURE:
+                       if (extract_artwork)
+                               _mm_file_id3tag_parse_APIC(pInfo, &buffer[curPos], frameLen, charset_array[encType]);
+                       break;
 
-                                                                               if (pInfo->imageInfo.pImageBuf != NULL) {
-                                                                                       memcpy(pInfo->imageInfo.pImageBuf, pExtContent + imgstartOffset, pInfo->imageInfo.imageLen);
-                                                                                       pInfo->imageInfo.pImageBuf[pInfo->imageInfo.imageLen] = 0;
-                                                                               }
+               default:
+                       pInfo->tagInfo[tag_id].value = mmfile_convert_to_utf8((const char *)&buffer[curPos], frameLen, charset_array[encType]);
+                       break;
+               }
 
-                                                                               if (IS_INCLUDE_URL(pInfo->imageInfo.imageMIMEType))
-                                                                                       pInfo->imageInfo.bURLInfo = true; /*if mimetype is "-->", image date has an URL */
-                                                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                               debug_msg("No APIC image!! realCpyFrameNum(%d) - imgstartOffset(%d)\n", realCpyFrameNum, imgstartOffset);
-#endif
-                                                                       }
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("pInfo->imageInfo.imageLen(%d), imgstartOffset(%d)!\n", pInfo->imageInfo.imageLen, imgstartOffset);
-#endif
-                                                               } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("pExtContent[imgstartOffset](%d) value should setted NULL value for end of description! realCpyFrameNum - imgstartOffset(%d)\n",
-                                                                                       pExtContent[imgstartOffset], realCpyFrameNum - imgstartOffset);
-#endif
-                                                               }
-                                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("pExtContent[imgstartOffset](%d) value should setted NULL value for end of mimetype! realCpyFrameNum - imgstartOffset(%d)\n",
-                                                                                       pExtContent[imgstartOffset], realCpyFrameNum - imgstartOffset);
-#endif
-                                                       }
+               if (pInfo->tagInfo[tag_id].value)
+                       debug_msg(RELEASE, "[%d] returned = (%s)", tag_id, pInfo->tagInfo[tag_id].value);
+NEXT:
+               curPos += frameLen;
+               encOffset = 0;
+               encType = 0;
+       }
 
-                                                       checkImgMimeTypeMax = 0;
-                                                       inx = 0;
-                                                       imgstartOffset = 0;
-                                                       pInfo->tagV2Info.bImageMarked = true;
+       release_characterset_array(charset_array);
 
-                                               } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("CompTmp(%s) This Frame ID currently not Supports!!\n", CompTmp);
-#endif
-                                               }
-                                       }
+       return true;
+}
 
-                               } else {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("All of the pExtContent Values are NULL\n");
-#endif
-                               }
-                       } else {
-                               curPos += purelyFramelen;
-                               if (purelyFramelen != 0)
-                                       needToloopv2taglen = MP3_TAGv2_23_TXT_HEADER_LEN;
-#ifdef __MMFILE_TEST_MODE__
-                               debug_msg("This Frame's size is Zero! purelyFramelen(%d)\n", purelyFramelen);
-#endif
-                       }
+static void __get_v224_encoding_info(const unsigned char *buffer,
+                                                                       int length,
+                                                                       int *offset,
+                                                                       unsigned int *type)
+{
+       int _offset = 0;
 
-                       if (pExtContent)        _FREE_EX(pExtContent);
-                       memset(CompTmp, 0, 4);
+       if (!buffer || !offset || !type)
+               return;
 
-                       if (curPos < taglen) {
-                               needToloopv2taglen -= oneFrameLen;
-                               v2numOfFrames++;
-                       } else
-                               needToloopv2taglen = MP3_TAGv2_23_TXT_HEADER_LEN;
-                       oneFrameLen = 0;
-                       encodingOffSet = 0;
-                       realCpyFrameNum = 0;
-                       textEncodingType = 0;
-                       purelyFramelen = 0;
+       /*in case of UTF 16 encoding */
+       /*buffer+(position-length) data should '0x01' but in order to expansion, we don't accurately check the value. */
+       if (IS_ENCODEDBY_UTF16(buffer)) {
+               *offset = 2;
+               *type = AV_ID3V2_UTF16;
+               return;
+       }
 
-               }
+       if (IS_ENCODEDBY_UTF16_R(buffer)) {
+               *offset = 2;
+               *type = AV_ID3V2_UTF16_BE;
+               return;
        }
 
-       release_characterset_array(charset_array);
+       if (IS_ENCODEDBY_UTF16(buffer + 1)) {
+               *offset = 3;
+               *type = AV_ID3V2_UTF16;
+               return;
+       }
+       if (IS_ENCODEDBY_UTF16_R(buffer + 1)) {
+               *offset = 3;
+               *type = AV_ID3V2_UTF16_BE;
+               return;
+       }
 
-       if (taglen)
-               return true;
-       else
-               return false;
+       /*in case of UTF-16 BE encoding */
+       if (buffer[0] == 0x02) {
+               _offset = 1;
+               while ((buffer[_offset] == '\0') && (_offset < length))
+                       _offset++;/*null skip! */
+               *offset = _offset;
+               *type = AV_ID3V2_UTF16_BE;
+               return;
+       }
 
+       /*in case of UTF8 encoding */
+       if (buffer[0] == 0x03) {
+               _offset = 1;
+               while ((buffer[_offset] == '\0') && (_offset < length))
+                       _offset++;/*null skip! */
+               *offset = _offset;
+               *type = AV_ID3V2_UTF8;
+               return;
+       }
+       /*in case of ISO-8859-1 encoding */
+       /*buffer+(position-length) data should 0x00 but in order to expansion, we don't accurately check the value. */
+       _offset = 1;
+       while ((buffer[_offset] < 0x20) && (_offset < length))
+               _offset++;/*less than 0x20 value skip! */
+       *offset = _offset;
+       *type = AV_ID3V2_ISO_8859;
 }
 
-EXPORT_API
-bool mm_file_id3tag_parse_v224(AvFileContentInfo *pInfo, unsigned char *buffer)
+bool mm_file_id3tag_parse_v224(AvFileContentInfo *pInfo, unsigned char *buffer, bool extract_artwork)
 {
-       unsigned long taglen = 0;
-       unsigned long needToloopv2taglen;
-       unsigned long oneFrameLen = 0;
-       unsigned long v2numOfFrames = 0;
-       unsigned long curPos = 0;
-       char CompTmp[5];
-       unsigned char *pExtContent = NULL;
-       unsigned long purelyFramelen = 0;
-       unsigned int encodingOffSet = 0;
-       int inx = 0, realCpyFrameNum = 0, checkImgMimeTypeMax = 0, imgstartOffset = 0,  tmp = 0;
-       int textEncodingType = 0;
+       int extendedHeaderLen = 0;
+       int frameLen = 0;
+       int curPos = MP3_TAGv2_HEADER_LEN;
+       int encOffset = 0;
+       unsigned int encType = 0;
        char **charset_array = NULL;
-       const char *MIME_PRFIX = "image/";
+       AvID3TagList tag_id = AV_ID3TAG_MAX;
 
-       make_characterset_array(&charset_array);
+       if (pInfo->tagV2Info.tagLen <= 0)
+               return false;
 
+       make_characterset_array(&charset_array);
        init_content_info(pInfo);
 
-       taglen = pInfo->tagV2Info.tagLen;
-       needToloopv2taglen = taglen - MP3_TAGv2_HEADER_LEN;
-       curPos = MP3_TAGv2_HEADER_LEN;
-
-#ifdef __MMFILE_TEST_MODE__
-       debug_msg("ID3tag v224--------------------------------------------------------------\n");
-#endif
-
-       /* check Extended Header */
+       debug_msg(RELEASE, "ID3tag v224--------------------------------------------------------------");
        if (buffer[5] & 0x40) {
                /* if extended header exists, skip it*/
-               int extendedHeaderLen = (unsigned long)buffer[10] << 21 | (unsigned long)buffer[11] << 14 | (unsigned long)buffer[12] << 7  | (unsigned long)buffer[13];
-
-#ifdef __MMFILE_TEST_MODE__
-               debug_msg("--------------- extendedHeaderLen = %d\n", extendedHeaderLen);
-#endif
-
-               if (extendedHeaderLen > (int)(taglen - curPos)) {
-                       debug_error("extended header too long.\n");
+               extendedHeaderLen = buffer[10] << 21 | buffer[11] << 14 | buffer[12] << 7 | buffer[13];
+               debug_msg(RELEASE, "--------------- extendedHeaderLen = %d", extendedHeaderLen);
+               if (extendedHeaderLen > pInfo->tagV2Info.tagLen - MP3_TAGv2_HEADER_LEN) {
+                       debug_error(DEBUG, "extended header too long.");
                } else {
                        curPos += extendedHeaderLen;
                }
        }
 
-       if (needToloopv2taglen - MP3_TAGv2_23_TXT_HEADER_LEN > MP3_TAGv2_23_TXT_HEADER_LEN) {
-               v2numOfFrames = 1;
-               while (needToloopv2taglen > MP3_TAGv2_23_TXT_HEADER_LEN) {
-                       if ((buffer[curPos] < '0' || buffer[curPos] > 'Z') || (buffer[curPos + 1] < '0' || buffer[curPos + 1] > 'Z')
-                           || (buffer[curPos + 2] < '0' || buffer[curPos + 2] > 'Z') || (buffer[curPos + 3] < '0' || buffer[curPos + 3] > 'Z'))
-                               break;
-
-                       memcpy(CompTmp, &buffer[curPos], 4);
-
-                       CompTmp[4] = 0;
-                       oneFrameLen = MP3_TAGv2_23_TXT_HEADER_LEN;
-                       oneFrameLen += (unsigned long)buffer[4 + curPos] << 21 | (unsigned long)buffer[5 + curPos] << 14
-                                               | (unsigned long)buffer[6 + curPos] << 7 | (unsigned long)buffer[7 + curPos];
-                       if (oneFrameLen > taglen - curPos)
-                               break;
-
-                       purelyFramelen = oneFrameLen - MP3_TAGv2_23_TXT_HEADER_LEN;
-                       curPos += MP3_TAGv2_23_TXT_HEADER_LEN;
-
-#ifdef __MMFILE_TEST_MODE__
-                       debug_msg("-----------------------------------------------------------------------------------\n");
-#endif
-
-                       if (oneFrameLen > MP3_TAGv2_23_TXT_HEADER_LEN && purelyFramelen <= taglen - curPos) {
-                               curPos += purelyFramelen;
-
-                               /*in case of UTF 16 encoding */
-                               /*buffer+(curPos-purelyFramelen) data should '0x01' but in order to expansion, we don't accurately check the value. */
-                               if (IS_ENCODEDBY_UTF16(buffer + (curPos - purelyFramelen))) {
-                                       encodingOffSet = 2;
-                                       textEncodingType = AV_ID3V2_UTF16;
-                               } else if (IS_ENCODEDBY_UTF16_R(buffer + (curPos - purelyFramelen))) {
-                                       encodingOffSet = 2;
-                                       textEncodingType = AV_ID3V2_UTF16_BE;
-                               } else if (IS_ENCODEDBY_UTF16(buffer + (curPos - purelyFramelen + 1))) {
-                                       encodingOffSet = 3;
-                                       textEncodingType = AV_ID3V2_UTF16;
-                               } else if (IS_ENCODEDBY_UTF16_R(buffer + (curPos - purelyFramelen + 1))) {
-                                       encodingOffSet = 3;
-                                       textEncodingType = AV_ID3V2_UTF16_BE;
-                               } else {
-                                       /*in case of UTF-16 BE encoding */
-                                       if (buffer[curPos - purelyFramelen] == 0x02) {
-                                               encodingOffSet = 1;
-                                               while ((buffer[curPos - purelyFramelen + encodingOffSet] == '\0') && (encodingOffSet < purelyFramelen))
-                                                       encodingOffSet++;/*null skip! */
-                                               textEncodingType = AV_ID3V2_UTF16_BE;
-                                       }
-                                       /*in case of UTF8 encoding */
-                                       else if (buffer[curPos - purelyFramelen] == 0x03) {
-                                               encodingOffSet = 1;
-                                               while ((buffer[curPos - purelyFramelen + encodingOffSet] == '\0') && (encodingOffSet < purelyFramelen))
-                                                       encodingOffSet++;/*null skip! */
-                                               textEncodingType = AV_ID3V2_UTF8;
-                                       }
-                                       /*in case of ISO-8859-1 encoding */
-                                       else {
-                                               /*buffer+(curPos-purelyFramelen) data should 0x00 but in order to expansion, we don't accurately check the value. */
-                                               encodingOffSet = 1;
-                                               while ((buffer[curPos - purelyFramelen + encodingOffSet] < 0x20) && (encodingOffSet < purelyFramelen))
-                                                       encodingOffSet++;/*less than 0x20 value skip! */
-                                               textEncodingType = AV_ID3V2_ISO_8859;
-                                       }
-                               }
-
-                               if (encodingOffSet < purelyFramelen) {
-                                       realCpyFrameNum = purelyFramelen - encodingOffSet;
-                                       pExtContent = mmfile_malloc(realCpyFrameNum + 3);
-
-                                       if (pExtContent == NULL) {
-                                               debug_error("out of memoryu for id3tag parse\n");
-                                               continue;
-                                       }
-
-                                       memset(pExtContent, '\0', realCpyFrameNum + 3);
-
-                                       if (textEncodingType != AV_ID3V2_UTF16 && textEncodingType != AV_ID3V2_UTF16_BE) {
-                                               if (CompTmp[0] == 'T' || (strcmp(CompTmp, "APIC") == 0)) {
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("get the new text ecoding type\n");
-#endif
-                                                       textEncodingType = buffer[curPos - purelyFramelen + encodingOffSet - 1];
-                                               }
-                                       }
-
-                                       if (textEncodingType > AV_ID3V2_MAX) {
-                                               debug_msg("WRONG ENCOIDNG TYPE [%d], FRAME[%s]\n", textEncodingType, (char *)CompTmp);
-                                               continue;
-                                       }
-
-                                       memcpy(pExtContent, &buffer[curPos - purelyFramelen + encodingOffSet], purelyFramelen - encodingOffSet);
-
-                                       if (realCpyFrameNum > 0) {
-                                               if (strncmp((char *)CompTmp, "TIT2", 4) == 0 && pInfo->tagV2Info.bTitleMarked == false) {
-                                                       if (textEncodingType == AV_ID3V2_UTF8) {
-                                                               pInfo->pTitle = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                               if (pInfo->pTitle) {
-                                                                       memcpy(pInfo->pTitle, pExtContent, realCpyFrameNum);
-                                                                       pInfo->pTitle[realCpyFrameNum] = '\0';
-                                                                       /*string copy with '\0'*/
-                                                                       pInfo->titleLen = realCpyFrameNum;
-                                                                       _STRNCPY_EX(pInfo->pTitle, pExtContent, pInfo->titleLen);
-                                                               }
-                                                       } else {
-                                                               pInfo->pTitle = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->titleLen);
-                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pTitle returned = (%s), pInfo->titleLen(%d)\n", pInfo->pTitle, pInfo->titleLen);
-#endif
-                                                       pInfo->tagV2Info.bTitleMarked = true;
-
-                                               } else if (strncmp((char *)CompTmp, "TPE1", 4) == 0 && pInfo->tagV2Info.bArtistMarked == false) {
-                                                       if (textEncodingType == AV_ID3V2_UTF8) {
-                                                               pInfo->pArtist = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                               if (pInfo->pArtist) {
-                                                                       memcpy(pInfo->pArtist, pExtContent, realCpyFrameNum);
-                                                                       pInfo->pArtist[realCpyFrameNum] = '\0';
-                                                                       /*string copy with '\0'*/
-                                                                       pInfo->artistLen = realCpyFrameNum;
-                                                                       _STRNCPY_EX(pInfo->pArtist, pExtContent, pInfo->artistLen);
-                                                               }
-                                                       } else {
-                                                               pInfo->pArtist = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->artistLen);
-                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pArtist returned = (%s), pInfo->artistLen(%d)\n", pInfo->pArtist, pInfo->artistLen);
-#endif
-                                                       pInfo->tagV2Info.bArtistMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TPE2", 4) == 0 && pInfo->tagV2Info.bAlbum_ArtistMarked == false) {
-                                                       if (textEncodingType == AV_ID3V2_UTF8) {
-                                                               pInfo->pAlbum_Artist = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                               if (pInfo->pAlbum_Artist) {
-                                                                       memcpy(pInfo->pAlbum_Artist, pExtContent, realCpyFrameNum);
-                                                                       pInfo->pAlbum_Artist[realCpyFrameNum] = '\0';
-                                                                       /*string copy with '\0'*/
-                                                                       pInfo->album_artistLen = realCpyFrameNum;
-                                                                       _STRNCPY_EX(pInfo->pAlbum_Artist, pExtContent, pInfo->album_artistLen);
-                                                               }
-                                                       } else {
-                                                               pInfo->pAlbum_Artist = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->album_artistLen);
-                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pAlbum_Artist returned = (%s), pInfo->album_artistLen(%d)\n", pInfo->pAlbum_Artist, pInfo->album_artistLen);
-#endif
-                                                       pInfo->tagV2Info.bAlbum_ArtistMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TPE3", 4) == 0 && pInfo->tagV2Info.bConductorMarked == false) {
-                                                       if (textEncodingType == AV_ID3V2_UTF8) {
-                                                               pInfo->pConductor = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                               if (pInfo->pConductor) {
-                                                                       memcpy(pInfo->pConductor, pExtContent, realCpyFrameNum);
-                                                                       pInfo->pConductor[realCpyFrameNum] = '\0';
-                                                                       /*string copy with '\0'*/
-                                                                       pInfo->conductorLen = realCpyFrameNum;
-                                                                       _STRNCPY_EX(pInfo->pConductor, pExtContent, pInfo->conductorLen);
-                                                               }
-                                                       } else {
-                                                               pInfo->pConductor = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->conductorLen);
-                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pConductor returned = (%s), pInfo->conductorLen(%d)\n", pInfo->pConductor, pInfo->conductorLen);
-#endif
-                                                       pInfo->tagV2Info.bConductorMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TALB", 4) == 0 && pInfo->tagV2Info.bAlbumMarked == false) {
-                                                       if (textEncodingType == AV_ID3V2_UTF8) {
-                                                               pInfo->pAlbum = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                               if (pInfo->pAlbum) {
-                                                                       memcpy(pInfo->pAlbum, pExtContent, realCpyFrameNum);
-                                                                       pInfo->pAlbum[realCpyFrameNum] = '\0';
-                                                                       /*string copy with '\0'*/
-                                                                       pInfo->albumLen = realCpyFrameNum;
-                                                                       _STRNCPY_EX(pInfo->pAlbum, pExtContent, pInfo->albumLen);
-                                                               }
-                                                       } else {
-                                                               pInfo->pAlbum = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->albumLen);
-                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pAlbum returned = (%s), pInfo->albumLen(%d)\n", pInfo->pAlbum, pInfo->albumLen);
-#endif
-                                                       pInfo->tagV2Info.bAlbumMarked = true;
-                                               } 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 */
-                                                       if (textEncodingType == AV_ID3V2_UTF8) {
-                                                               pInfo->pYear = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                               if (pInfo->pYear) {
-                                                                       memcpy(pInfo->pYear, pExtContent, realCpyFrameNum);
-                                                                       pInfo->pYear[realCpyFrameNum] = '\0';
-                                                                       /*string copy with '\0'*/
-                                                                       pInfo->yearLen = realCpyFrameNum;
-                                                                       _STRNCPY_EX(pInfo->pYear, pExtContent, pInfo->yearLen);
-                                                               }
-                                                       } else {
-                                                               pInfo->pYear = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->yearLen);
-                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pYear returned = (%s), pInfo->yearLen(%d)\n", pInfo->pYear, pInfo->yearLen);
-#endif
-                                                       pInfo->tagV2Info.bYearMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "COMM", 4) == 0 && pInfo->tagV2Info.bDescriptionMarked == false) {
-                                                       if (realCpyFrameNum > 3) {
-                                                               realCpyFrameNum -= 3;
-                                                               tmp = 3;
-
-                                                               if (textEncodingType == AV_ID3V2_UTF16 || textEncodingType == AV_ID3V2_UTF16_BE) {
-                                                                       while ((NEWLINE_OF_UTF16(pExtContent + tmp) || NEWLINE_OF_UTF16_R(pExtContent + tmp)) && realCpyFrameNum > 4) {
-                                                                               realCpyFrameNum -= 4;
-                                                                               tmp += 4;
-                                                                       }
-
-                                                                       if ((IS_ENCODEDBY_UTF16(pExtContent + tmp) || IS_ENCODEDBY_UTF16_R(pExtContent + tmp)) && realCpyFrameNum > 2) {
-                                                                               realCpyFrameNum -= 2;
-                                                                               tmp += 2;
-                                                                               textEncodingType = AV_ID3V2_UTF16;
-                                                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                               debug_msg("pInfo->pComment Never Get Here!!\n");
-#endif
-                                                                       }
-                                                               } else if (textEncodingType == AV_ID3V2_UTF8) {
-                                                                       while (pExtContent[tmp] < 0x20 && (tmp < realCpyFrameNum)) { /* text string encoded by ISO-8859-1 */
-                                                                               realCpyFrameNum--;
-                                                                               tmp++;
-                                                                       }
-                                                                       textEncodingType = AV_ID3V2_UTF8;
-                                                               } else {
-                                                                       while (pExtContent[tmp] < 0x20 && (tmp < realCpyFrameNum)) { /* text string encoded by ISO-8859-1 */
-                                                                               realCpyFrameNum--;
-                                                                               tmp++;
-                                                                       }
-                                                                       textEncodingType = AV_ID3V2_ISO_8859;
-                                                               }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("tmp(%d) textEncodingType(%d), realCpyFrameNum(%d)\n", tmp, textEncodingType, realCpyFrameNum);
-#endif
-
-                                                               if (textEncodingType == AV_ID3V2_UTF8) {
-                                                                       pInfo->pComment = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                                       if (pInfo->pComment) {
-                                                                               memset(pInfo->pComment, 0, (realCpyFrameNum + 2));
-                                                                               memcpy(pInfo->pComment, pExtContent + tmp, realCpyFrameNum);
-                                                                               pInfo->pComment[realCpyFrameNum] = '\0';
-                                                                               /*string copy with '\0'*/
-                                                                               pInfo->commentLen = realCpyFrameNum;
-                                                                               _STRNCPY_EX(pInfo->pComment, pExtContent, pInfo->commentLen);
-                                                                       }
-                                                               } else {
-                                                                       pInfo->pComment = mmfile_string_convert((const char *)&pExtContent[tmp], realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->commentLen);
-                                                               }
-                                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("Description info too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum);
-#endif
-                                                       }
-
-                                                       tmp = 0;
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pComment returned = (%s), pInfo->commentLen(%d)\n", pInfo->pComment, pInfo->commentLen);
-#endif
-                                                       pInfo->tagV2Info.bDescriptionMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "SYLT", 4) == 0 && pInfo->tagV2Info.bSyncLyricsMarked == false) {
-                                                       int idx = 0;
-                                                       int copy_len = 0;
-                                                       int copy_start_pos = tmp;
-                                                       AvSynclyricsInfo *synclyrics_info = NULL;
-                                                       GList *synclyrics_info_list = NULL;
-
-                                                       if (realCpyFrameNum > 5) {
-                                                               realCpyFrameNum -= 5;
-                                                               tmp = 5;
-
-                                                               if (textEncodingType == AV_ID3V2_UTF16 || textEncodingType == AV_ID3V2_UTF16_BE) {
-                                                                       while ((NEWLINE_OF_UTF16(pExtContent + tmp) || NEWLINE_OF_UTF16_R(pExtContent + tmp)) && realCpyFrameNum > 4) {
-                                                                               realCpyFrameNum -= 4;
-                                                                               tmp += 4;
-                                                                       }
-
-                                                                       if ((IS_ENCODEDBY_UTF16(pExtContent + tmp) || IS_ENCODEDBY_UTF16_R(pExtContent + tmp)) && realCpyFrameNum > 2) {
-                                                                               realCpyFrameNum -= 2;
-                                                                               tmp += 2;
-                                                                               textEncodingType = AV_ID3V2_UTF16;
-                                                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                               debug_msg("pInfo->pSyncLyrics Never Get Here!!\n");
-#endif
-                                                                       }
-                                                               } else if (textEncodingType == AV_ID3V2_UTF8) {
-                                                                       while (pExtContent[tmp] < 0x20 && (tmp < realCpyFrameNum)) { /* text string encoded by ISO-8859-1 */
-                                                                               realCpyFrameNum--;
-                                                                               tmp++;
-                                                                       }
-                                                                       textEncodingType = AV_ID3V2_UTF8;
-                                                               } else {
-                                                                       while (pExtContent[tmp] < 0x20 && (tmp < realCpyFrameNum)) { /* text string encoded by ISO-8859-1 */
-                                                                               realCpyFrameNum--;
-                                                                               tmp++;
-                                                                       }
-                                                                       textEncodingType = AV_ID3V2_ISO_8859;
-                                                               }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("tmp(%d) textEncodingType(%d), realCpyFrameNum(%d)\n", tmp, textEncodingType, realCpyFrameNum);
-#endif
-
-                                                               if (realCpyFrameNum < MMFILE_SYNC_LYRIC_INFO_MIN_LEN) {
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("failed to get Synchronised lyrics Info realCpyFramNum(%d)\n", realCpyFrameNum);
-#endif
-                                                                       pInfo->syncLyricsNum = 0;
-                                                               } else {
-                                                                       if (textEncodingType == AV_ID3V2_UTF16) {
-                                                                               debug_warning("[AV_ID3V2_UTF16] not implemented\n");
-                                                                       } else if (textEncodingType == AV_ID3V2_UTF16_BE) {
-                                                                               debug_warning("[AV_ID3V2_UTF16_BE] not implemented\n");
-                                                                       } else {
-                                                                               for (idx = 0; idx < realCpyFrameNum; idx++) {
-                                                                                       if (pExtContent[tmp + idx] == 0x00) {
-                                                                                               synclyrics_info = (AvSynclyricsInfo *)malloc(sizeof(AvSynclyricsInfo));
-
-                                                                                               if (textEncodingType == AV_ID3V2_UTF8) {
-                                                                                                       synclyrics_info->lyric_info = mmfile_malloc(copy_len + 1);
-                                                                                                       if (synclyrics_info->lyric_info) {
-                                                                                                               memset(synclyrics_info->lyric_info, 0, copy_len + 1);
-                                                                                                               memcpy(synclyrics_info->lyric_info, pExtContent + copy_start_pos, copy_len);
-                                                                                                               synclyrics_info->lyric_info[copy_len] = '\0';
-                                                                                                       }
-                                                                                               } else {
-                                                                                                       synclyrics_info->lyric_info = mmfile_string_convert((const char *)&pExtContent[copy_start_pos], copy_len, "UTF-8", charset_array[textEncodingType], NULL, NULL);
-                                                                                               }
-
-                                                                                               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];
-                                                                                               idx += 4;
-                                                                                               copy_start_pos = tmp + idx + 1;
-#ifdef __MMFILE_TEST_MODE__
-                                                                                               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);
-#endif
-                                                                                               copy_len = 0;
-                                                                                               synclyrics_info_list = g_list_append(synclyrics_info_list, synclyrics_info);
-                                                                                       }
-                                                                                       copy_len++;
-                                                                               }
-                                                                               pInfo->pSyncLyrics = synclyrics_info_list;
-                                                                               pInfo->syncLyricsNum = g_list_length(pInfo->pSyncLyrics);
-                                                                       }
-                                                               }
-                                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("SyncLyrics info too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum);
-#endif
-                                                       }
-
-                                                       tmp = 0;
-                                                       pInfo->tagV2Info.bSyncLyricsMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "USLT", 4) == 0 && pInfo->tagV2Info.bUnsyncLyricsMarked == false) {
-                                                       if (realCpyFrameNum > 3) {
-                                                               realCpyFrameNum -= 3;
-                                                               tmp = 3;
-
-                                                               if (textEncodingType == AV_ID3V2_UTF16 || textEncodingType == AV_ID3V2_UTF16_BE) {
-                                                                       while ((NEWLINE_OF_UTF16(pExtContent + tmp) || NEWLINE_OF_UTF16_R(pExtContent + tmp)) && realCpyFrameNum > 4) {
-                                                                               realCpyFrameNum -= 4;
-                                                                               tmp += 4;
-                                                                       }
-
-                                                                       if ((IS_ENCODEDBY_UTF16(pExtContent + tmp) || IS_ENCODEDBY_UTF16_R(pExtContent + tmp)) && realCpyFrameNum > 2) {
-                                                                               realCpyFrameNum -= 2;
-                                                                               tmp += 2;
-                                                                               textEncodingType = AV_ID3V2_UTF16;
-                                                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                               debug_msg("pInfo->pUnsyncLyrics Never Get Here!!\n");
-#endif
-                                                                       }
-                                                               } else if (textEncodingType == AV_ID3V2_UTF8) {
-                                                                       while (pExtContent[tmp] < 0x20 && (tmp < realCpyFrameNum)) { /* text string encoded by ISO-8859-1 */
-                                                                               realCpyFrameNum--;
-                                                                               tmp++;
-                                                                       }
-                                                                       textEncodingType = AV_ID3V2_UTF8;
-                                                               } else {
-                                                                       while (pExtContent[tmp] < 0x20 && (tmp < realCpyFrameNum)) { /* text string encoded by ISO-8859-1 */
-                                                                               realCpyFrameNum--;
-                                                                               tmp++;
-                                                                       }
-                                                                       textEncodingType = AV_ID3V2_ISO_8859;
-                                                               }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("tmp(%d) textEncodingType(%d), realCpyFrameNum(%d)\n", tmp, textEncodingType, realCpyFrameNum);
-#endif
-
-                                                               if (textEncodingType == AV_ID3V2_UTF8) {
-                                                                       pInfo->pUnsyncLyrics = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-
-                                                                       if (pInfo->pUnsyncLyrics != NULL) {
-                                                                               memset(pInfo->pUnsyncLyrics, 0, (realCpyFrameNum + 2));
-                                                                               memcpy(pInfo->pUnsyncLyrics, pExtContent + tmp, realCpyFrameNum);
-                                                                               pInfo->pUnsyncLyrics[realCpyFrameNum] = '\0';
-                                                                               /*string copy with '\0'*/
-                                                                               pInfo->unsynclyricsLen = realCpyFrameNum;
-                                                                               _STRNCPY_EX(pInfo->pUnsyncLyrics, pExtContent, pInfo->unsynclyricsLen);
-                                                                       } else {
-                                                                               debug_error("out of memoryu for SyncLyrics\n");
-                                                                       }
-                                                               } else {
-                                                                       pInfo->pUnsyncLyrics = mmfile_string_convert((const char *)&pExtContent[tmp], realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->unsynclyricsLen);
-                                                               }
-                                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                               debug_msg("Description info too small to parse realCpyFrameNum(%d)\n", realCpyFrameNum);
-#endif
-                                                       }
-
-                                                       tmp = 0;
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pUnsyncLyrics returned = (%s), pInfo->unsynclyricsLen(%d)\n", pInfo->pUnsyncLyrics, pInfo->unsynclyricsLen);
-#endif
-                                                       pInfo->tagV2Info.bDescriptionMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TCON", 4) == 0 && pInfo->tagV2Info.bGenreMarked == false) {
-                                                       if (textEncodingType == AV_ID3V2_UTF8) {
-                                                               pInfo->pGenre = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                               if (pInfo->pGenre) {
-                                                                       memcpy(pInfo->pGenre, pExtContent, realCpyFrameNum);
-                                                                       pInfo->pGenre[realCpyFrameNum] = '\0';
-                                                                       /*string copy with '\0'*/
-                                                                       pInfo->genreLen = realCpyFrameNum;
-                                                                       _STRNCPY_EX(pInfo->pGenre, pExtContent, pInfo->genreLen);
-                                                               }
-                                                       } else {
-                                                               pInfo->pGenre = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->genreLen);
-                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pGenre returned = (%s), pInfo->genreLen(%d)\n", pInfo->pGenre, pInfo->genreLen);
-#endif
-
-                                                       if ((pInfo->pGenre != NULL) && (pInfo->genreLen > 0)) {
-                                                               bool ret = FALSE;
-                                                               int int_genre = -1;
-
-                                                               ret = is_numeric(pInfo->pGenre, pInfo->genreLen);
-
-                                                               if (ret == TRUE) {
-                                                                       sscanf(pInfo->pGenre, "%d", &int_genre);
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("genre information is inteager [%d]\n", int_genre);
-#endif
-
-                                                                       /*Change int to string */
-                                                                       if ((0 <= int_genre) && (int_genre < GENRE_COUNT - 1)) {
-                                                                               /*save genreinfo like "(123)". mm_file_id3tag_restore_content_info convert it to string*/
-                                                                               char tmp_genre[6] = {0, };      /*ex. "(123)+NULL"*/
-                                                                               int tmp_genre_len = 0;
-
-                                                                               memset(tmp_genre, 0, 6);
-                                                                               snprintf(tmp_genre, sizeof(tmp_genre), "(%d)", int_genre);
-
-                                                                               tmp_genre_len = strlen(tmp_genre);
-                                                                               if (tmp_genre_len > 0) {
-                                                                                       if (pInfo->pGenre) _FREE_EX(pInfo->pGenre);
-                                                                                       pInfo->pGenre = mmfile_malloc(sizeof(char) * (tmp_genre_len + 1));
-                                                                                       if (pInfo->pGenre) {
-                                                                                               strncpy(pInfo->pGenre, tmp_genre, tmp_genre_len);
-                                                                                               pInfo->pGenre[tmp_genre_len] = 0;
-                                                                                       }
-                                                                               }
-                                                                       }
-                                                               }
-                                                       }
-
-                                                       pInfo->tagV2Info.bGenreMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TRCK", 4) == 0 && pInfo->tagV2Info.bTrackNumMarked == false) {
-                                                       if (textEncodingType == AV_ID3V2_UTF8) {
-                                                               pInfo->pTrackNum = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                               if (pInfo->pTrackNum != NULL) {
-                                                                       memcpy(pInfo->pTrackNum, pExtContent, realCpyFrameNum);
-                                                                       pInfo->pTrackNum[realCpyFrameNum] = '\0';
-                                                                       /*string copy with '\0'*/
-                                                                       pInfo->tracknumLen = realCpyFrameNum;
-                                                                       _STRNCPY_EX(pInfo->pTrackNum, pExtContent, pInfo->tracknumLen);
-                                                               }
-                                                       } else {
-                                                               pInfo->pTrackNum = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->tracknumLen);
-                                                       }
-
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pTrackNum returned = (%s), pInfo->tracknumLen(%d)\n", pInfo->pTrackNum, pInfo->tracknumLen);
-#endif
-                                                       pInfo->tagV2Info.bTrackNumMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TENC", 4) == 0 && pInfo->tagV2Info.bEncByMarked == false) {
-                                                       if (textEncodingType == AV_ID3V2_UTF8) {
-                                                               pInfo->pEncBy = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                               if (pInfo->pEncBy != NULL) {
-                                                                       memcpy(pInfo->pEncBy, pExtContent, realCpyFrameNum);
-                                                                       pInfo->pEncBy[realCpyFrameNum] = '\0';
-                                                                       /*string copy with '\0'*/
-                                                                       pInfo->encbyLen = realCpyFrameNum;
-                                                                       _STRNCPY_EX(pInfo->pEncBy, pExtContent, pInfo->encbyLen);
-                                                               }
-                                                       } else {
-                                                               pInfo->pEncBy = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->encbyLen);
-                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pEncBy returned = (%s), pInfo->encbyLen(%d)\n", pInfo->pEncBy, pInfo->encbyLen);
-#endif
-                                                       pInfo->tagV2Info.bEncByMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "WXXX", 4) == 0 && pInfo->tagV2Info.bURLMarked == false) {
-                                                       if (textEncodingType == AV_ID3V2_UTF8) {
-                                                               pInfo->pURL = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                               if (pInfo->pURL != NULL) {
-                                                                       memcpy(pInfo->pURL, pExtContent, realCpyFrameNum);
-                                                                       pInfo->pURL[realCpyFrameNum] = '\0';
-                                                                       /*string copy with '\0'*/
-                                                                       pInfo->urlLen = realCpyFrameNum;
-                                                                       _STRNCPY_EX(pInfo->pURL, pExtContent, pInfo->urlLen);
-                                                               }
-                                                       } else {
-                                                               pInfo->pURL = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->urlLen);
-                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pURL returned = (%s), pInfo->urlLen(%d)\n", pInfo->pURL, pInfo->urlLen);
-#endif
-                                                       pInfo->tagV2Info.bURLMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TCOP", 4) == 0 && pInfo->tagV2Info.bCopyRightMarked == false) {
-                                                       if (textEncodingType == AV_ID3V2_UTF8) {
-                                                               pInfo->pCopyright = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                               if (pInfo->pCopyright != NULL) {
-                                                                       memcpy(pInfo->pCopyright, pExtContent, realCpyFrameNum);
-                                                                       pInfo->pCopyright[realCpyFrameNum] = '\0';
-                                                                       /*string copy with '\0'*/
-                                                                       pInfo->copyrightLen = realCpyFrameNum;
-                                                                       _STRNCPY_EX(pInfo->pCopyright, pExtContent, pInfo->copyrightLen);
-                                                               }
-                                                       } else {
-                                                               pInfo->pCopyright = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->copyrightLen);
-                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pCopyright returned = (%s), pInfo->copyrightLen(%d)\n", pInfo->pCopyright, pInfo->copyrightLen);
-#endif
-                                                       pInfo->tagV2Info.bCopyRightMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TOPE", 4) == 0 && pInfo->tagV2Info.bOriginArtistMarked == false) {
-                                                       if (textEncodingType == AV_ID3V2_UTF8) {
-                                                               pInfo->pOriginArtist = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                               if (pInfo->pOriginArtist != NULL) {
-                                                                       memcpy(pInfo->pOriginArtist, pExtContent, realCpyFrameNum);
-                                                                       pInfo->pOriginArtist[realCpyFrameNum] = '\0';
-                                                                       /*string copy with '\0'*/
-                                                                       pInfo->originartistLen = realCpyFrameNum;
-                                                                       _STRNCPY_EX(pInfo->pOriginArtist, pExtContent, pInfo->originartistLen);
-                                                               }
-                                                       } else {
-                                                               pInfo->pOriginArtist = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->originartistLen);
-                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pOriginArtist returned = (%s), pInfo->originartistLen(%d)\n", pInfo->pOriginArtist, pInfo->originartistLen);
-#endif
-                                                       pInfo->tagV2Info.bOriginArtistMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TCOM", 4) == 0 && pInfo->tagV2Info.bComposerMarked == false) {
-                                                       if (textEncodingType == AV_ID3V2_UTF8) {
-                                                               pInfo->pComposer = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                               if (pInfo->pComposer != NULL) {
-                                                                       memcpy(pInfo->pComposer, pExtContent, realCpyFrameNum);
-                                                                       pInfo->pComposer[realCpyFrameNum] = '\0';
-                                                                       /*string copy with '\0'*/
-                                                                       pInfo->composerLen = realCpyFrameNum;
-                                                                       _STRNCPY_EX(pInfo->pComposer, pExtContent, pInfo->composerLen);
-                                                               }
-                                                       } else {
-                                                               pInfo->pComposer = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->composerLen);
-                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pComposer returned = (%s), pInfo->originartistLen(%d)\n", pInfo->pComposer, pInfo->composerLen);
-#endif
-                                                       pInfo->tagV2Info.bComposerMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TDRC", 4) == 0 && pInfo->tagV2Info.bRecDateMarked == false) {      /*TYER(year) and TRDA are replaced by the TDRC */
-                                                       if (textEncodingType == AV_ID3V2_UTF8) {
-                                                               pInfo->pRecDate = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                               if (pInfo->pRecDate != NULL) {
-                                                                       memcpy(pInfo->pRecDate, pExtContent, realCpyFrameNum);
-                                                                       pInfo->pRecDate[realCpyFrameNum] = '\0';
-                                                                       /*string copy with '\0'*/
-                                                                       pInfo->recdateLen = realCpyFrameNum;
-                                                                       _STRNCPY_EX(pInfo->pRecDate, pExtContent, pInfo->recdateLen);
-                                                               }
-                                                       } else {
-                                                               pInfo->pRecDate = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->recdateLen);
-                                                       }
-
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pRecDate returned = (%s), pInfo->recdateLen(%d)\n", pInfo->pRecDate, pInfo->recdateLen);
-#endif
-                                                       pInfo->tagV2Info.bRecDateMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "TIT1", 4) == 0 && pInfo->tagV2Info.bContentGroupMarked == false) {
-                                                       if (textEncodingType == AV_ID3V2_UTF8) {
-                                                               pInfo->pContentGroup = mmfile_malloc(realCpyFrameNum + 2); /*Ignore NULL char for UTF16 */
-                                                               if (pInfo->pContentGroup != NULL) {
-                                                                       memcpy(pInfo->pContentGroup, pExtContent, realCpyFrameNum);
-                                                                       pInfo->pContentGroup[realCpyFrameNum] = '\0';
-                                                                       /*string copy with '\0'*/
-                                                                       pInfo->contentGroupLen = realCpyFrameNum;
-                                                                       _STRNCPY_EX(pInfo->pContentGroup, pExtContent, pInfo->contentGroupLen);
-                                                               }
-                                                       } else {
-                                                               pInfo->pContentGroup = mmfile_string_convert((const char *)pExtContent, realCpyFrameNum, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&pInfo->contentGroupLen);
-                                                       }
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("pInfo->pContentGroup returned = (%s), pInfo->contentGroupLen(%d)\n", pInfo->pContentGroup, pInfo->contentGroupLen);
-#endif
-                                                       pInfo->tagV2Info.bContentGroupMarked = true;
-                                               } else if (strncmp((char *)CompTmp, "APIC", 4) == 0 && pInfo->tagV2Info.bImageMarked == false && realCpyFrameNum <= 2000000) {
-                                                       if (pExtContent[0] != '\0') {
-                                                               for (inx = 0; inx < MP3_ID3_IMAGE_MIME_TYPE_MAX_LENGTH - 1; inx++)
-                                                                       pInfo->imageInfo.imageMIMEType[inx] = '\0';/*ini mimetype variable */
-
-                                                               while ((checkImgMimeTypeMax < MP3_ID3_IMAGE_MIME_TYPE_MAX_LENGTH - 1) && pExtContent[checkImgMimeTypeMax] != '\0') {
-                                                                       pInfo->imageInfo.imageMIMEType[checkImgMimeTypeMax] = pExtContent[checkImgMimeTypeMax];
-                                                                       checkImgMimeTypeMax++;
-                                                               }
-                                                               pInfo->imageInfo.imgMimetypeLen = checkImgMimeTypeMax;
-                                                       } else {
-                                                               pInfo->imageInfo.imgMimetypeLen = 0;
-                                                       }
-
-                                                       imgstartOffset += checkImgMimeTypeMax;
-
-                                                       if (strncmp(pInfo->imageInfo.imageMIMEType, MIME_PRFIX, strlen(MIME_PRFIX)) != 0) {
-                                                               pInfo->imageInfo.imgMimetypeLen = 0;
-                                                               debug_error("APIC NOT VALID");
-                                                               continue;
-                                                       }
-
-                                                       if ((pExtContent[imgstartOffset] == '\0') && (realCpyFrameNum - imgstartOffset > 0)) {
-                                                               imgstartOffset++;/*endofMIME(1byte) */
-
-                                                               if (pExtContent[imgstartOffset] < AV_ID3V2_PICTURE_TYPE_MAX) {
-                                                                       pInfo->imageInfo.pictureType = pExtContent[imgstartOffset];
-                                                               }
-                                                               imgstartOffset++;/*PictureType(1byte) */
-
-                                                               if (pExtContent[imgstartOffset] != 0x0) {
-                                                                       int cur_pos = 0;
-                                                                       int dis_len = 0;
-                                                                       int new_dis_len = 0;
-                                                                       char *tmp_desc = NULL;
-
-                                                                       while (1) {
-                                                                               if (pExtContent[imgstartOffset + cur_pos] == '\0') {
-                                                                                       if (realCpyFrameNum < imgstartOffset + cur_pos) {
-                                                                                               debug_error("End of APIC Tag %d %d %d\n", realCpyFrameNum, imgstartOffset, cur_pos);
-                                                                                               break;
-                                                                                       }
-                                                                                       /*check end of image description*/
-                                                                                       if ((pExtContent[imgstartOffset + cur_pos + 1] == gTagJPEGHeader[0]) ||
-                                                                                           (pExtContent[imgstartOffset + cur_pos + 1] == gTagPNGHeader[0])) {
-#ifdef __MMFILE_TEST_MODE__
-                                                                                               debug_msg("length of description (%d)", cur_pos);
-#endif
-
-                                                                                               break;
-                                                                                       }
-                                                                               }
-                                                                               cur_pos++;
-                                                                       }
-
-                                                                       dis_len = cur_pos + 1;
-
-                                                                       tmp_desc = mmfile_malloc(sizeof(char) * dis_len);
-
-                                                                       if (tmp_desc != NULL) {
-                                                                               memcpy(tmp_desc, pExtContent + imgstartOffset, dis_len);
-                                                                               debug_msg("tmp_desc %s\n", tmp_desc);
-
-                                                                               /*convert description*/
-                                                                               pInfo->imageInfo.imageDescription = mmfile_string_convert(tmp_desc, dis_len, "UTF-8", charset_array[textEncodingType], NULL, (unsigned int *)&new_dis_len);
-                                                                               debug_msg("new_desc %s(%d)\n", pInfo->imageInfo.imageDescription, new_dis_len);
-                                                                               mmfile_free(tmp_desc);
-
-                                                                               pInfo->imageInfo.imgDesLen = new_dis_len; /**/
-                                                                       }
+       while (curPos + MP3_TAGv2_23_TXT_HEADER_LEN < pInfo->tagV2Info.tagLen) {
+               if (!g_ascii_isalnum(buffer[curPos]) || !g_ascii_isalnum(buffer[curPos + 1]) ||
+                       !g_ascii_isalnum(buffer[curPos + 2]) || !g_ascii_isalnum(buffer[curPos + 3]))
+                       break;
 
-                                                                       imgstartOffset += cur_pos;
-                                                               } else {
-                                                                       pInfo->imageInfo.imgDesLen = 0;
-                                                               }
+               tag_id = __get_tag_info_v223(&buffer[curPos]);
+               frameLen = buffer[curPos + 4] << 21 | buffer[curPos + 5] << 14 | buffer[curPos + 6] << 7 | buffer[curPos + 7];
+               curPos += MP3_TAGv2_23_TXT_HEADER_LEN;
+               if (curPos + frameLen > pInfo->tagV2Info.tagLen)
+                       break;
 
-                                                               if ((pExtContent[imgstartOffset] == '\0') && (realCpyFrameNum - imgstartOffset > 0)) {
-                                                                       imgstartOffset++; /* endofDesceriptionType(1byte) */
+               if (frameLen <= 0)
+                       continue;
 
-                                                                       while (pExtContent[imgstartOffset] == '\0') {   /*some content has useless '\0' in front of picture data */
-                                                                               imgstartOffset++;
-                                                                       }
+               if (tag_id == AV_ID3TAG_MAX || pInfo->tagInfo[tag_id].value)
+                       goto NEXT;
 
-#ifdef __MMFILE_TEST_MODE__
-                                                                       debug_msg("after scaning imgDescription imgstartOffset(%d) value!\n", imgstartOffset);
-#endif
+               __get_v224_encoding_info(buffer + curPos, frameLen, &encOffset, &encType);
+               if (frameLen <= encOffset) {
+                       debug_warning(DEBUG, "warning: invalid frame length %d %d", frameLen, encOffset);
+                       goto NEXT;
+               }
 
-                                                                       if (realCpyFrameNum - imgstartOffset > 0) {
-                                                                               pInfo->imageInfo.imageLen = realCpyFrameNum - imgstartOffset;
-                                                                               pInfo->imageInfo.pImageBuf = mmfile_malloc(pInfo->imageInfo.imageLen + 1);
+               curPos += encOffset;
+               frameLen -= encOffset;
+               encOffset = 0;
 
-                                                                               if (pInfo->imageInfo.pImageBuf != NULL) {
-                                                                                       memcpy(pInfo->imageInfo.pImageBuf, pExtContent + imgstartOffset, pInfo->imageInfo.imageLen);
-                                                                                       pInfo->imageInfo.pImageBuf[pInfo->imageInfo.imageLen] = 0;
-                                                                               }
+               if (encType != AV_ID3V2_UTF16 && encType != AV_ID3V2_UTF16_BE) {
+                       if (tag_id != AV_ID3TAG_COMMENT && tag_id != AV_ID3TAG_UNSYNCLYRICS && tag_id != AV_ID3TAG_SYNCLYRICS) {
+                               debug_msg(RELEASE, "get the new text encoding type");
+                               encType = buffer[curPos - 1];
+                       }
+               }
 
-                                                                               if (IS_INCLUDE_URL(pInfo->imageInfo.imageMIMEType))
-                                                                                       pInfo->imageInfo.bURLInfo = true; /*if mimetype is "-->", image date has an URL */
-                                                                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                                               debug_msg("No APIC image!! realCpyFrameNum(%d) - imgstartOffset(%d)\n", realCpyFrameNum, imgstartOffset);
-#endif
-                                                                       }
-                                                               }
-                                                       }
+               if (encType > AV_ID3V2_MAX) {
+                       debug_msg(DEBUG, "WRONG ENCOIDNG TYPE [%u], TAG ID[%d]", encType, tag_id);
+                       goto NEXT;
+               }
 
-                                                       checkImgMimeTypeMax = 0;
-                                                       inx = 0;
-                                                       imgstartOffset = 0;
-                                                       pInfo->tagV2Info.bImageMarked = true;
-                                               } else {
-#ifdef __MMFILE_TEST_MODE__
-                                                       debug_msg("CompTmp(%s) This Frame ID currently not Supports!!\n", CompTmp);
-#endif
-                                               }
-                                       }
+               switch (tag_id) {
+               case AV_ID3TAG_COMMENT:
+                       /* fall through */
+               case AV_ID3TAG_UNSYNCLYRICS:
+                       if (frameLen <= 3) {
+                               debug_msg(RELEASE, "Description info too small to parse frameLen(%d)", frameLen);
+                               break;
+                       }
+                       frameLen -= 3;
+                       encOffset = 3;
 
-                               } else {
-#ifdef __MMFILE_TEST_MODE__
-                                       debug_msg("mmf_file_id3tag_parse_v224: All of the pExtContent Values are NULL\n");
-#endif
-                               }
+                       encType = __id3tag_get_text_encoding_v224(&buffer[curPos], &frameLen, encType, &encOffset);
+                       debug_msg(RELEASE, "encOffset(%d) encType(%u), frameLen(%d)", encOffset, encType, frameLen);
+                       curPos += encOffset;
+                       pInfo->tagInfo[tag_id].value = mmfile_convert_to_utf8((const char *)&buffer[curPos], frameLen, charset_array[encType]);
+                       break;
 
-                       } else {
-                               curPos += purelyFramelen;
-                               if (purelyFramelen != 0)
-                                       needToloopv2taglen = MP3_TAGv2_23_TXT_HEADER_LEN;
+               case AV_ID3TAG_SYNCLYRICS:
+                       if (frameLen <= 5) {
+                               debug_msg(RELEASE, "Synchronised lyrics too small to parse frameLen(%d)", frameLen);
+                               break;
                        }
+                       frameLen -= 5;
+                       encOffset = 5;
 
-                       if (pExtContent)        _FREE_EX(pExtContent);
-                       memset(CompTmp, 0, 4);
-                       if (curPos < taglen) {
-                               needToloopv2taglen -= oneFrameLen;
-                               v2numOfFrames++;
-                       } else
-                               needToloopv2taglen = MP3_TAGv2_23_TXT_HEADER_LEN;
+                       encType = __id3tag_get_text_encoding_v224(&buffer[curPos], &frameLen, encType, &encOffset);
+                       debug_msg(RELEASE, "encOffset(%d) encType(%u), frameLen(%d)", encOffset, encType, frameLen);
+                       curPos += encOffset;
+                       __id3tag_parse_SYLT(pInfo, buffer, frameLen, charset_array[encType], encType, curPos);
+                       break;
 
-                       oneFrameLen = 0;
-                       encodingOffSet = 0;
-                       realCpyFrameNum = 0;
-                       textEncodingType = 0;
-                       purelyFramelen = 0;
+               case AV_ID3TAG_PICTURE:
+                       if (extract_artwork)
+                               _mm_file_id3tag_parse_APIC(pInfo, &buffer[curPos], frameLen, charset_array[encType]);
+                       break;
 
+               default:
+                       pInfo->tagInfo[tag_id].value = mmfile_convert_to_utf8((const char *)&buffer[curPos], frameLen, charset_array[encType]);
+                       break;
                }
+
+               if (pInfo->tagInfo[tag_id].value)
+                       debug_msg(RELEASE, "[%d] returned = (%s)", tag_id, pInfo->tagInfo[tag_id].value);
+NEXT:
+               curPos += frameLen;
+               encOffset = 0;
+               encType = 0;
        }
 
        release_characterset_array(charset_array);
 
-       if (taglen)
-               return true;
-       else
-               return false;
-
+       return true;
 }
 
-EXPORT_API
+
 void mm_file_id3tag_restore_content_info(AvFileContentInfo *pInfo)
 {
-       char    *mpegAudioGenre = NULL/*, *tmpGenreForV1Tag = NULL*/;
-       bool    bAdditionGenre = false /*, bMpegAudioFrame = false*/;
-       int mpegAudioFileLen = 0, idv2IntGenre = 148/*, tmpinx = 0, tmpinx2=0*/;
-#ifdef _SM_ONLY
-       char    *pGenreForUTF16;
-#endif
-       unsigned char genre = pInfo->genre;
+       int genre_id = 0;
 
        /* for Genre Info */
-       if (pInfo->tagV2Info.bGenreMarked == false) {
-               if (pInfo->bV1tagFound == true) {
-#ifdef __MMFILE_TEST_MODE__
-                       debug_msg("Genre: %d\n", genre);
-#endif
-                       if (genre > 147)
-                               genre = 148;
-
-                       if (MpegAudio_Genre[genre] != NULL) {
-                               pInfo->genreLen = strlen(MpegAudio_Genre[genre]);
-                               if (pInfo->genreLen > 0) {
-                                       /* Give space for NULL character. Hence added "+1" */
-                                       pInfo->pGenre = mmfile_malloc(sizeof(char) * (pInfo->genreLen + 1));
-                                       if (pInfo->pGenre) {
-                                               strncpy(pInfo->pGenre, MpegAudio_Genre[genre], pInfo->genreLen);
-                                               pInfo->pGenre[pInfo->genreLen] = '\0';
-                                       }
-                               }
-                       }
-               } else {
-#ifdef __MMFILE_TEST_MODE__
-                       debug_msg("Genre was not Found.\n");
-#endif
-               }
-       } else if (pInfo->tagV2Info.bGenreMarked == true) {
-               if (pInfo->genreLen && pInfo->tagV2Info.bGenreUTF16) {
-                       pInfo->pGenre[pInfo->genreLen + 1] = '\0';
-                       mpegAudioGenre = mmfile_malloc(sizeof(char) * (pInfo->genreLen * AV_WM_LOCALCODE_SIZE_MAX + 1));
-#ifdef _SM_ONLY
-                       pGenreForUTF16 = (char *)pInfo->pGenre;
-
-                       if (WmConvert2LCode(mpegAudioGenre, sizeof(char) * AV_WM_LOCALCODE_SIZE_MAX * (pInfo->genreLen + 1), pGenreForUTF16)) {
-                               pInfo->genreLen = strlen(mpegAudioGenre);
-                               mpegAudioGenre[pInfo->genreLen] = '\0';
-                       }
-#endif
-               } else {
-#ifdef __MMFILE_TEST_MODE__
-                       debug_msg("pInfo->genreLen size is Zero Or not UTF16 code! genreLen[%d] genre[%s]\n", pInfo->genreLen, pInfo->pGenre);
-#endif
-                       if (pInfo->pGenre) {
-                               pInfo->genreLen = strlen(pInfo->pGenre);
-                               mpegAudioGenre = mmfile_malloc(sizeof(char) * (pInfo->genreLen + 1));
-                               if (mpegAudioGenre != NULL) {
-                                       mpegAudioGenre[pInfo->genreLen] = '\0';
-                                       strncpy(mpegAudioGenre, pInfo->pGenre, pInfo->genreLen);
-                               }
-                       } else {
-                               pInfo->genreLen = 0;
-                       }
+       if (pInfo->tagInfo[AV_ID3TAG_GENRE].value) {
+               /* Check integer */
+               if (!__get_genre_num(pInfo->tagInfo[AV_ID3TAG_GENRE].value, &genre_id)) {
+                       debug_msg(RELEASE, "genre information is not integer [%s]", pInfo->tagInfo[AV_ID3TAG_GENRE].value);
+                       return;
                }
 
-               if (pInfo->pGenre) _FREE_EX(pInfo->pGenre);
+               /* If integer, check genre code. */
+               /* If out of range, set UNKNOWN */
+               if (genre_id < 0 || genre_id >= GENRE_COUNT)
+                       genre_id = GENRE_COUNT - 1;
 
-               /*tmpinx = 0;*/
-               if (mpegAudioGenre != NULL) {
-                       /**
-                        *Genre number
-                        * (XXX)        XXX is 0 - 148
-                        */
-                       pInfo->genreLen = strlen(mpegAudioGenre);
-                       if (pInfo->genreLen >= 3 &&
-                           mpegAudioGenre[0] == '(' && mpegAudioGenre[pInfo->genreLen - 1] == ')') {
-                               bAdditionGenre = true;
-                               for (mpegAudioFileLen = 1; mpegAudioFileLen <= pInfo->genreLen - 2; mpegAudioFileLen++) {
-                                       if (mpegAudioGenre[mpegAudioFileLen] < '0' || mpegAudioGenre[mpegAudioFileLen] > '9') {
-                                               bAdditionGenre = false;
-                                               break;
-                                       }
-                               }
-                       }
+               debug_msg(RELEASE, "genre information is integer [%d]", genre_id);
 
-                       if (bAdditionGenre == true) {
-                               idv2IntGenre = atoi(mpegAudioGenre + 1);
+               g_free(pInfo->tagInfo[AV_ID3TAG_GENRE].value);
+               pInfo->tagInfo[AV_ID3TAG_GENRE].value = g_strdup(MpegAudio_Genre[genre_id]);
+       } else {
+               /* No genre in ID3V2.. So check V1 */
+               if (pInfo->bV1tagFound == true) {
+                       debug_msg(RELEASE, "Genre: %d", pInfo->genre);
 
-                               if (idv2IntGenre > 147 || idv2IntGenre < 0)
-                                       idv2IntGenre = 148;
+                       /* If out of range, set UNKNOWN */
+                       if (pInfo->genre > GENRE_COUNT - 1)
+                               pInfo->genre = GENRE_COUNT - 1;
 
-                               if (MpegAudio_Genre[idv2IntGenre] != NULL) {
-                                       pInfo->genreLen = strlen(MpegAudio_Genre[idv2IntGenre]);
-                                       if (pInfo->genreLen > 0) {
-                                               /* Give space for NULL character. Hence added "+1" */
-                                               pInfo->pGenre = mmfile_malloc(sizeof(char) * (pInfo->genreLen + 1));
-                                               if (pInfo->pGenre) {
-                                                       strncpy(pInfo->pGenre, MpegAudio_Genre[idv2IntGenre], pInfo->genreLen);
-                                                       pInfo->pGenre[pInfo->genreLen] = 0;
-                                               }
-                                       }
-                               }
-#ifdef __MMFILE_TEST_MODE__
-                               debug_msg("pInfo->pGenre = %s\n", pInfo->pGenre);
-#endif
-                       } else if (bAdditionGenre == false && pInfo->genreLen > 0) {
-                               /**
-                                * Genre string.
-                                */
-
-                               /* Give space for NULL character. Hence added "+1" */
-                               pInfo->pGenre = mmfile_malloc(sizeof(char) * (pInfo->genreLen + 1));
-                               if (pInfo->pGenre) {
-                                       strncpy(pInfo->pGenre, mpegAudioGenre, pInfo->genreLen);
-                                       pInfo->pGenre[pInfo->genreLen] = '\0';
-                               }
-#ifdef __MMFILE_TEST_MODE__
-                               debug_msg("pInfo->pGenre = %s, pInfo->genreLen = %d\n", pInfo->pGenre, pInfo->genreLen);
-#endif
-                       } else {
-#ifdef __MMFILE_TEST_MODE__
-                               debug_msg("Failed to \"(...)\" value to genre = %s\n", pInfo->pGenre);
-#endif
-                       }
+                       pInfo->tagInfo[AV_ID3TAG_GENRE].value = g_strdup(MpegAudio_Genre[pInfo->genre]);
                } else {
-#ifdef __MMFILE_TEST_MODE__
-                       debug_msg("mpegAudioGenre = %x\n", mpegAudioGenre);
-#endif
+                       debug_msg(RELEASE, "Genre was not Found.");
                }
-               if (mpegAudioGenre)
-                       _FREE_EX(mpegAudioGenre);
-
-       } else {
-#ifdef __MMFILE_TEST_MODE__
-               debug_msg("Neither ID3 v1 nor v2 info doesn't have Genre Info.\n");
-#endif
        }
-
 }
 
-void mm_file_free_synclyrics_list(GList *synclyrics_list)
+static void __free_synclyrics(gpointer data)
 {
-       int list_len = 0;
-       int idx = 0;
-       AvSynclyricsInfo *synclyrics_info = NULL;
+       AvSynclyricsInfo *info = (AvSynclyricsInfo *) data;
 
-       if (synclyrics_list == NULL) {
+       if (!info)
                return;
-       }
 
-       list_len = g_list_length(synclyrics_list);
-       for (idx = 0; idx < list_len; idx++) {
-               synclyrics_info = g_list_nth_data(synclyrics_list, idx);
+       mmfile_free(info->lyric_info);
+       mmfile_free(info);
+}
 
-               if (synclyrics_info != NULL) {
-                       mmfile_free(synclyrics_info->lyric_info);
-                       mmfile_free(synclyrics_info);
-               }
-       }
 
-       if (synclyrics_list != NULL) {
-               g_list_free(synclyrics_list);
-               synclyrics_list = NULL;
-       }
+void mm_file_free_synclyrics_list(GList *synclyrics_list)
+{
+       if (!synclyrics_list)
+               return;
 
-       return;
+       g_list_free_full(synclyrics_list, __free_synclyrics);
 }
-