⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aud_id3_parser.c

📁 最新MTK手机软件源码
💻 C
📖 第 1 页 / 共 4 页
字号:
 * DESCRIPTION
 *  
 * PARAMETERS
 *  data                [?]         
 *  size                [IN]        
 *  frame_header        [?]         
 *  id3_tag             [?]         
 * RETURNS
 *  kal_int8: PARSE_ID3_FRAME_NO_SPACE (-1) -> no space
 *  PARSE_ID3_FRAME_SUCCESS (0) -> success
 *  PARSE_ID3_FRAME_ABORT (1) -> abort
 *****************************************************************************/
kal_int8 id3_tag_parse_v2_frame_header(
            kal_uint8 *data,
            kal_int32 size,
            id3_tag_frame_header_struct *frame_header,
            id3_tag_struct *id3_tag)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    kal_uint8 flags;
    kal_uint32 data_offset;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    switch (id3_tag->v2_major_ver)
    {
        case 4:
            if (size < 10)
            {
                return PARSE_ID3_FRAME_NO_SPACE;
            }
            memcpy(frame_header->id, data, 4);  /* 0, 1, 2, 3 */
            frame_header->size = id3_tag_get_unsync_uint32(data + 4, 4);        /* 4, 5, 6, 7 */
            frame_header->size += 10;
            data_offset = 10;

            /* get status flags */
            flags = data[8];
            if (flags & 0x80)   /* check unset flags */
            {
                return PARSE_ID3_FRAME_ABORT;
            }
            if (flags & 0x60)   /* check file and tag alter perservation flags */
            {
                return PARSE_ID3_FRAME_ABORT;
            }

            /* get format flags */
            flags = data[9];

            if (flags & 0xB0)   /* check unset flags */
            {
                return PARSE_ID3_FRAME_ABORT;
            }

            if (flags & 0x0C)   /* check compress and encrypt flags */
            {
                return PARSE_ID3_FRAME_ABORT;
            }

            if (flags & 0x40)   /* check group id flag */
            {
                data_offset++;
            }

            if (flags & 0x20)   /* check unsyncrhonisation flag */
            {
                frame_header->unsync = KAL_TRUE;
            }
            else
            {
                frame_header->unsync = KAL_FALSE;
            }

            if (flags & 0x01)   /* check data length indicator flag */
            {
                id3_tag_get_unsync_uint32(data + 10, 4);    /* 10, 11, 12, 13 */
                data_offset += 4;
            }
            break;

        case 3:
            if (size < 10)
            {
                return PARSE_ID3_FRAME_NO_SPACE;
            }
            memcpy(frame_header->id, data, 4);  /* 0, 1, 2, 3 */
            frame_header->size = id3_tag_get_uint32(data + 4, 4);       /* 4, 5, 6, 7 */
            frame_header->size += 10;
            data_offset = 10;

            /* get status flags */
            flags = data[8];

            if (flags & 0x1F)   /* check unset flags */
            {
                return PARSE_ID3_FRAME_ABORT;
            }

            if (flags & 0xC0)   /* check file and tag alter perservation flags */
            {
                return PARSE_ID3_FRAME_ABORT;
            }

            /* get format flags */
            flags = data[9];

            if (flags & 0x1F)   /* check unset flags */
            {
                return PARSE_ID3_FRAME_ABORT;
            }

            if (flags & 0xC0)   /* check compress and encrypt flags */
            {
                return PARSE_ID3_FRAME_ABORT;
            }

            if (flags & 0x20)   /* check group id flag */
            {
                data_offset++;
            }
            break;

        case 2:
            if (size < 6)
            {
                return PARSE_ID3_FRAME_NO_SPACE;
            }
            memcpy(frame_header->id, data, 3);  /* 0, 1, 2 */
            frame_header->size = id3_tag_get_uint32(data + 3, 3);       /* 3, 4, 5 */
            frame_header->size += 6;
            data_offset = 6;
            break;

        default:
            data_offset = 0;
            ASSERT(0);
    }

    if (size <= (kal_int32) data_offset)    /* check buffer size */
    {
        return PARSE_ID3_FRAME_NO_SPACE;
    }
    else if (frame_header->size <= data_offset) /* frame size */
    {
        return PARSE_ID3_FRAME_ABORT;
    }

    frame_header->data_offset = data_offset;
    frame_header->data_size = frame_header->size - data_offset;

    return PARSE_ID3_FRAME_SUCCESS;
}


/*****************************************************************************
 * FUNCTION
 *  id3_tag_match_v2_frame_id_from_list
 * DESCRIPTION
 *  
 * PARAMETERS
 *  id          [?]         Const char* id_list[]
 *  id_list     [IN]        
 *  size        [IN]        
 * RETURNS
 *  kal_int8
 *****************************************************************************/
kal_int8 id3_tag_match_v2_frame_id_from_list(kal_uint8 *id, const char *id_list[], kal_uint8 size)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    kal_int8 i;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    for (i = 0; i < NUM_OF_ID3_FRAME; i++)
    {
        if (memcmp(id, id_list[i], size) == 0)
        {
            return i;
        }
    }
    return -1;
}


/*****************************************************************************
 * FUNCTION
 *  id3_tag_parse_v2_frame_data
 * DESCRIPTION
 *  
 * PARAMETERS
 *  data                [?]     
 *  frame_header        [?]     
 *  id3_tag             [?]     
 * RETURNS
 *  kal_bool
 *****************************************************************************/
kal_bool id3_tag_parse_v2_frame_data(
            kal_uint8 *data,
            id3_tag_frame_header_struct *frame_header,
            id3_tag_struct *id3_tag)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    kal_int8 frame_id_index;
    kal_uint8 text_encoding;
    kal_uint8 *ptr, *src;
    kal_uint32 text_size, i, count; /* number of bytes */
    kal_uint32 max_text_size;
    kal_int32 genre_index;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    text_encoding = data[0];
    switch (id3_tag->v2_major_ver)
    {
        case 4:
            if (text_encoding > 3)
            {
                return KAL_FALSE;
            }
            frame_id_index = id3_tag_match_v2_frame_id_from_list((kal_uint8*) frame_header->id, id3_tag_v2_4_frame_id_list, 4);
            break;
        case 3:
            if (text_encoding > 1)
            {
                return KAL_FALSE;
            }
            frame_id_index = id3_tag_match_v2_frame_id_from_list((kal_uint8*) frame_header->id, id3_tag_v2_3_frame_id_list, 4);
            break;
        case 2:
            if (text_encoding > 1)
            {
                return KAL_FALSE;
            }
            frame_id_index = id3_tag_match_v2_frame_id_from_list((kal_uint8*) frame_header->id, id3_tag_v2_2_frame_id_list, 3);
            break;
        default:
            frame_id_index = -1;
            ASSERT(0);
    }

    if (frame_id_index < 0) /* quit if it's not our wanted frame */
    {
        return KAL_FALSE;
    }

    ptr = (kal_uint8*) id3_tag->text_pool.next_p;
    max_text_size = id3_tag->text_pool.available_words << 1;
    if (max_text_size < 4)
    {
        return KAL_FALSE;
    }
    /* limit each text field size */
    if (max_text_size > (ID3_TAG_POOL_SIZE>>3))
        max_text_size = (ID3_TAG_POOL_SIZE>>3);
    text_size = frame_header->data_size - 1;    /* src text size */
    src = data + 1;

    switch (text_encoding)
    {
        case ID3_FRAME_TEXT_ENCODING_ISO_8859_1:
            /* limit our dest text size if there is no null terminator in src */
            count = 2;  /* UCS2 null terminator */
            for (i = 0; src[i] && i < text_size; i++)
            {
                if (src[i] > 0x7F)
                {
                    i++;
                }
                count += 2;
            }
            if (max_text_size > count)
            {
                max_text_size = count;
            }
            text_size = (kal_uint32) mmi_chset_text_to_ucs2(ptr, max_text_size, src);
            break;
        case ID3_FRAME_TEXT_ENCODING_UTF16:
            text_size = id3_tag_utf16_to_ucs2(ID3_UTF16_UNKNOWN_BYTE_ORDER, ptr, max_text_size, src, text_size);
            break;
        case ID3_FRAME_TEXT_ENCODING_UTF16_BE:
            text_size = id3_tag_utf16_to_ucs2(ID3_UTF16_BE, ptr, max_text_size, src, text_size);
            break;
        case ID3_FRAME_TEXT_ENCODING_UTF8:
            text_size = med_util_utf8_to_ucs2(ptr, max_text_size, src, text_size);
            break;
    }

    if (text_size <= 2) /* check if more than null terminator chars */
    {
        return KAL_FALSE;
    }

    if (frame_id_index == ID3_FRAME_GENRE)
    {
        if (kal_wstrcmp((const kal_wchar*)ptr, L"RX") == 0)
        {
            if (id3_tag->text_pool.available_words >= 6)    /* check available space in pool */
            {
                kal_wstrcpy((kal_wchar*) ptr, L"Remix");
                text_size = 12; /* include UCS2 null terminator */
            }
        }
        else if (kal_wstrcmp((const kal_wchar*)ptr, L"CR") == 0)
        {
            if (id3_tag->text_pool.available_words >= 6)    /* check available space in pool */
            {
                kal_wstrcpy((kal_wchar*) ptr, L"Cover");
                text_size = 12; /* include UCS2 null terminator */
            }
        }
        else
        {
            genre_index = id3_tag_parse_number((kal_wchar*) ptr, text_size / 2);       /* get genre number (index) */
            if (genre_index >= 0 && genre_index < ID3_TAG_GENRE_NUM)    /* check if the index is valid */
            {
                ptr = (kal_uint8*) id3_tag_genres[genre_index];        /* get genre string from list */
                max_text_size = (kal_uint32) (strlen((const char*)ptr) + 1) * 2;       /* include UCS2 null terminator */
                if (max_text_size <= (id3_tag->text_pool.available_words << 1)) /* check available space in pool */
                {
                    text_size =
                        (kal_uint32) mmi_chset_text_to_ucs2(
                                        (kal_uint8*) id3_tag->text_pool.next_p,
                                        max_text_size,
                                        ptr);
                }
            }
        }
    }
    id3_tag->frames[frame_id_index].text = id3_tag->text_pool.next_p;
    id3_tag->frames[frame_id_index].size = text_size;
    id3_text_pool_consume(&id3_tag->text_pool, (text_size + 1) >> 1);

    return KAL_TRUE;
}


/*****************************************************************************
 * FUNCTION
 *  id3_tag_parse_v2_tag
 * DESCRIPTION
 *  
 * PARAMETERS
 *  input_stream        [?]     
 *  id3_tag             [?]     
 * RETURNS
 *  kal_bool
 *****************************************************************************/
kal_bool id3_tag_parse_v2_tag(audio_input_stream_struct *input_stream, id3_tag_struct *id3_tag)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    kal_bool data_full_load;
    kal_uint8 parse_result;
    kal_uint8 *frame_data_ptr, *ptr;
    kal_uint32 frame_size, frame_data_size;
    kal_int32 target_size, buf_size;
    kal_int32 v2_tag_size, offset;
    id3_tag_frame_header_struct frame_header;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    if (audio_input_stream_read(input_stream, 10) != 10)
    {
        return KAL_FALSE;
    }
    offset = (kal_int32) input_stream->total_load;
    buf_size = (kal_int32) input_stream->buf_size;
    ptr = input_stream->buf;

    /*
     * check id3v2 magic word -- "ID3"
     * and parse header and set the following 4 fields in id3_tag:
     * (1) v2_size // not include header & footer size
     * (2) v2_unsync
     * (3) v2_exthdr
     * (4) v2_footer
     */
    if (id3_tag_parse_v2_tag_header(ptr, id3_tag))
    {
        /* check if tag size <= our read buffer size */
        if ((v2_tag_size = (kal_int32) id3_tag->v2_size) > buf_size)
        {
            data_full_load = KAL_FALSE;
            /* read partial data of the tag to read buffer */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -