📄 aud_id3_parser.c
字号:
* 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 + -