📄 aud_id3_parser.c
字号:
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
if (size > 4) /* size should never exceed 5 */
{
num = *data++;
size--;
}
for (; size > 0; size--)
{
num = (num << 7) | (*data++);
}
return num;
}
/*****************************************************************************
* FUNCTION
* id3_tag_get_uint32
* DESCRIPTION
*
* PARAMETERS
* data [?]
* size [IN]
* RETURNS
* kal_uint32
*****************************************************************************/
kal_uint32 id3_tag_get_uint32(kal_uint8 *data, kal_uint8 size)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_uint32 num;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
for (num = 0; size > 0; size--) /* size should never exceed 4 */
{
num = (num << 8) | (*data++);
}
return num;
}
/*****************************************************************************
* FUNCTION
* id3_text_pool_init
* DESCRIPTION
*
* PARAMETERS
* id3_text_pool [?]
* RETURNS
* void
*****************************************************************************/
void id3_text_pool_init(id3_tag_text_pool_struct *id3_text_pool)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
id3_text_pool->next_p = id3_text_pool->text;
id3_text_pool->available_words = ID3_TAG_POOL_SIZE/2;
}
/*****************************************************************************
* FUNCTION
* id3_text_pool_consume
* DESCRIPTION
*
* PARAMETERS
* id3_text_pool [?]
* num_of_words [IN]
* RETURNS
* void
*****************************************************************************/
void id3_text_pool_consume(id3_tag_text_pool_struct *id3_text_pool, kal_uint32 num_of_words)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
id3_text_pool->next_p += num_of_words;
id3_text_pool->available_words -= num_of_words;
}
/*****************************************************************************
* FUNCTION
* id3_frame_init
* DESCRIPTION
*
* PARAMETERS
* id3_frame [?]
* RETURNS
* void
*****************************************************************************/
void id3_frame_init(id3_tag_frame_struct *id3_frame)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
id3_frame->text = NULL;
id3_frame->size = 0;
}
/*****************************************************************************
* FUNCTION
* id3_tag_init
* DESCRIPTION
*
* PARAMETERS
* id3_tag [?]
* RETURNS
* void
*****************************************************************************/
void id3_tag_init(id3_tag_struct *id3_tag)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_int32 i;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
/* init frames */
for (i = 0; i < NUM_OF_ID3_FRAME; i++)
{
id3_frame_init(&id3_tag->frames[i]);
}
/* init text_pool */
id3_text_pool_init(&id3_tag->text_pool);
}
/*****************************************************************************
* FUNCTION
* id3_tag_parse_v2_tag_header
* DESCRIPTION
*
* PARAMETERS
* data [?]
* id3_tag [?]
* RETURNS
* kal_bool
*****************************************************************************/
kal_bool id3_tag_parse_v2_tag_header(kal_uint8 *data, id3_tag_struct *id3_tag)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_uint8 flags, version;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
/* check id3v2 magic word -- "ID3" */
if (!(data[0] == 'I' && data[1] == 'D' && data[2] == '3'))
{
return KAL_FALSE;
}
version = data[3];
if (data[4] != 0)
{
return KAL_FALSE;
}
flags = data[5];
/* init flags */
id3_tag->v2_major_ver = version;
id3_tag->v2_unsync = KAL_FALSE;
id3_tag->v2_exthdr = KAL_FALSE;
id3_tag->v2_footer = KAL_FALSE;
switch (version)
{
case 4:
if (flags & 0x0F)
{
return KAL_FALSE;
}
if (flags & 0x10) /* check footer flag */
{
id3_tag->v2_footer = KAL_TRUE;
}
case 3:
if (flags & 0x1F)
{
return KAL_FALSE;
}
if (flags & 0x20) /* check extended header flag */
{
id3_tag->v2_exthdr = KAL_TRUE;
}
break;
case 2:
if (flags & 0x3F)
{
return KAL_FALSE;
}
if (flags & 0x40) /* check compression flag, if it is set, ignore this tag */
{
return KAL_FALSE;
}
break;
default:
return KAL_FALSE;
}
if (flags & 0x80) /* check unsynchronisation flag */
{
id3_tag->v2_unsync = KAL_TRUE;
}
/* get tag size */
id3_tag->v2_size = id3_tag_get_unsync_uint32(data + 6, 4); /* 6, 7, 8, 9 */
return KAL_TRUE;
}
/*****************************************************************************
* FUNCTION
* id3_tag_reverse_unsync_process
* DESCRIPTION
*
* PARAMETERS
* data [?]
* size [IN]
* RETURNS
* kal_uint32
*****************************************************************************/
kal_uint32 id3_tag_reverse_unsync_process(kal_uint8 *data, kal_uint32 size)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_uint8 *output = data + 1;
kal_uint8 *ptr = data;
kal_uint8 prev_value;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
if (size == 0)
{
return 0;
}
for (prev_value = *ptr++, size--; size != 0; size--)
{
if (!(prev_value == 0xFF && *ptr == 0x00))
{
*output++ = *ptr;
}
prev_value = *ptr++;
}
return (kal_uint32) output - (kal_uint32) data;
}
/*****************************************************************************
* FUNCTION
* id3_tag_parse_v2_tag_extended_header
* DESCRIPTION
*
* IMPACT
* we assume id3 tag read buffer >= 14 bytes
* PARAMETERS
* data [?]
* id3_tag [?] Kal_bool data_full_load;
* data_full_load [IN]
* RETURNS
* kal_bool
*****************************************************************************/
kal_bool id3_tag_parse_v2_tag_extended_header(kal_uint8 *data, id3_tag_struct *id3_tag, kal_bool data_full_load)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_uint32 extended_header_size;
kal_uint32 tag_size;
kal_uint32 padding_size;
kal_uint32 crc_data_size;
kal_uint32 crc_data;
kal_uint8 *crc_data_start;
kal_uint8 flags;
kal_bool crc_data_present;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
if (id3_tag->v2_unsync)
{
tag_size = id3_tag->v2_reverse_unsync_size;
}
else
{
tag_size = id3_tag->v2_size;
}
switch (id3_tag->v2_major_ver)
{
case 4:
extended_header_size = id3_tag_get_unsync_uint32(data, 4); /* 0, 1, 2, 3 */
/* check size */
if (extended_header_size >= tag_size)
{
return KAL_FALSE;
}
if (data[4] != 0x01) /* flag bytes must be 1 */
{
return KAL_FALSE;
}
flags = data[5];
if (flags & 0x8F) /* check unset flags */
{
return KAL_FALSE;
}
if (flags & 0x20) /* check CRC data present flag */
{
crc_data_present = KAL_TRUE;
if (data[6] != 0x05) /* flag data length must be 5 */
{
return KAL_FALSE;
}
crc_data = id3_tag_get_unsync_uint32(data + 7, 5); /* 7, 8, 9, 10, 11 */
crc_data_start = data + 12;
crc_data_size = tag_size - extended_header_size;
}
else
{
crc_data_present = KAL_FALSE;
}
break;
case 3:
extended_header_size = id3_tag_get_uint32(data, 4); /* 0, 1, 2, 3 */
if (data[5] != 0) /* 2nd flag must be all unset */
{
return KAL_FALSE;
}
padding_size = id3_tag_get_uint32(data + 6, 4); /* 6, 7, 8, 9 */
/* check size */
if (extended_header_size + padding_size >= tag_size)
{
return KAL_FALSE;
}
flags = data[4];
if (flags & 0x80) /* check CRC data present flag */
{
crc_data_present = KAL_TRUE;
crc_data = id3_tag_get_uint32(data + 10, 4); /* 10, 11, 12, 13 */
crc_data_start = data + 14;
crc_data_size = tag_size - extended_header_size - padding_size;
}
else
{
crc_data_present = KAL_FALSE;
}
break;
default:
return KAL_FALSE;
}
if (crc_data_present && data_full_load) /* if tag is larger than our buffer size, we skip CRC check process */
{
if (med_crc_calculate((kal_uint8 const*)crc_data_start, crc_data_size) != crc_data)
{
return KAL_FALSE;
}
}
/* get extended header size */
id3_tag->v2_exthdr_size = extended_header_size;
id3_tag->v2_crc = crc_data_present;
return KAL_TRUE;
}
/*****************************************************************************
* FUNCTION
* id3_tag_parse_v2_frame_header
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -