📄 aud_id3_parser.c
字号:
if (audio_input_stream_read(input_stream, buf_size) != buf_size)
{
return KAL_FALSE;
}
}
else
{
data_full_load = KAL_TRUE;
/* read the whole tag header to read buffer (not include footer) */
if (audio_input_stream_read(input_stream, v2_tag_size) != v2_tag_size)
{
return KAL_FALSE;
}
}
/* reverse unsynchronisation process */
if (id3_tag->v2_unsync)
{
if (!data_full_load) /* if the tag is larger than our buffer size, we can't do reverse unsync process */
{
return KAL_TRUE; /* but we still return TRUE */
}
v2_tag_size = id3_tag->v2_reverse_unsync_size =
(kal_int32) id3_tag_reverse_unsync_process(ptr, v2_tag_size);
}
/* target size (v2_tag_size) not including 10 bytes v2 tag header */
target_size = v2_tag_size;
if (id3_tag->v2_exthdr)
{
/*
* parse extended header and set the following 2 fields in id3_tag:
* (1) v2_exthdr_size
* (2) v2_crc
*/
if (!id3_tag_parse_v2_tag_extended_header(ptr, id3_tag, data_full_load))
{
return KAL_FALSE;
}
/* point to frame start position */
offset += id3_tag->v2_exthdr_size;
ptr += id3_tag->v2_exthdr_size;
target_size -= id3_tag->v2_exthdr_size;
}
/* parse frames */
for (frame_size = 0; target_size > 0 && ptr + 15 <= input_stream->tail && /* 15 is the maximal frame header size */
(parse_result = id3_tag_parse_v2_frame_header(ptr, target_size, &frame_header, id3_tag)) != PARSE_ID3_FRAME_NO_SPACE;
ptr += frame_size, target_size -= frame_size)
{
/* check if frame id is invalid or frame size too large */
if (frame_header.id[0] == 0 || frame_header.size > (kal_uint32) target_size)
{
break;
}
offset += frame_size; /* offset always point to frame start position */
frame_size = frame_header.size;
if (parse_result != PARSE_ID3_FRAME_ABORT)
{
// we need to check if the frame boundary is within buffer
// otherwise, we need to skip processing the frame data & move to next frame
if (ptr + frame_size <= input_stream->tail)
{
frame_data_ptr = ptr + frame_header.data_offset;
/* check unsync flag & reverse unsynchronisation process in a frame */
if (!id3_tag->v2_unsync && frame_header.unsync)
{
frame_header.data_size = id3_tag_reverse_unsync_process(frame_data_ptr, frame_header.data_size);
}
/* parse frame data */
if (frame_header.data_size > 1)
{
id3_tag_parse_v2_frame_data(frame_data_ptr, &frame_header, id3_tag);
}
}
}
}
// when data_full_load is FALSE, we can't finish parsing it in buffer in last step
// so we keep loading data & parse frames
if (!data_full_load)
{
target_size += frame_size;
ptr = input_stream->buf;
do
{
/* seek to the frame header start position */
audio_input_stream_seek(input_stream, offset);
/* we assume buf is >= 15 bytes, and read 15 bytes for parsing header */
if (audio_input_stream_read(input_stream, 15) != 15) /* 15 is the maximal frame header size */
{
break;
}
parse_result = id3_tag_parse_v2_frame_header(ptr, target_size, &frame_header, id3_tag);
if (parse_result == PARSE_ID3_FRAME_NO_SPACE)
{
break;
}
/* check if frame id is invalid or frame size too large */
if (frame_header.id[0] == 0 || frame_header.size > (kal_uint32) target_size)
{
break;
}
frame_data_size = frame_header.data_size;
// if it's our wanted frame, we need to check if the frame data size <= buf_size
// otherwise, we need to skip processing the frame data & seek to next frame
if (parse_result != PARSE_ID3_FRAME_ABORT && (kal_int32) frame_data_size <= buf_size)
{
/* seek to the frame data start position */
audio_input_stream_seek(input_stream, offset + frame_header.data_offset);
/* read data bytes */
if ((kal_uint32) audio_input_stream_read(input_stream, frame_data_size) != frame_data_size)
{
break;
}
/* check unsync flag & reverse unsynchronisation process in a frame */
if (!id3_tag->v2_unsync && frame_header.unsync)
{
frame_data_size = frame_header.data_size = id3_tag_reverse_unsync_process(ptr, frame_data_size);
}
/* parse frame data */
if (frame_header.data_size > 1)
{
id3_tag_parse_v2_frame_data(ptr, &frame_header, id3_tag);
}
}
frame_size = frame_header.size;
target_size -= frame_size;
offset += frame_size;
} while (target_size > 0);
}
return KAL_TRUE;
}
return KAL_FALSE;
}
/*****************************************************************************
* FUNCTION
* id3_tag_parse_v1_tag
* DESCRIPTION
*
* PARAMETERS
* input_stream [?]
* id3_tag [?]
* RETURNS
* kal_bool
*****************************************************************************/
kal_bool id3_tag_parse_v1_tag(audio_input_stream_struct *input_stream, id3_tag_struct *id3_tag)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_bool need_alloc_pool;
kal_uint8 i;
kal_uint8 *data, *ptr;
id3_tag_frame_struct *frame_p;
kal_uint32 len, j, size;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
if (audio_input_stream_read(input_stream, 128) != 128)
{
return KAL_FALSE;
}
data = input_stream->buf;
/*
* check id3v1 magic word -- "TAG"
* and parse header and set the following 5 frames in id3_tag:
* (1) title
* (2) artist
* (3) album
* (4) year
* (5) genre
*/
if (!(data[0] == 'T' && data[1] == 'A' && data[2] == 'G'))
{
return KAL_FALSE;
}
for (i = 0; i < NUM_OF_ID3_FRAME; i++)
{
frame_p = &id3_tag->frames[i];
if (frame_p->text != NULL) /* check if the same frame in v2 exist */
{
continue;
}
ptr = data + id3_tag_v1_field_list[i].offset;
size = (kal_uint32) id3_tag_v1_field_list[i].size;
if (i == ID3_FRAME_GENRE)
{
if (*ptr < ID3_TAG_GENRE_NUM)
{
ptr = (kal_uint8*) id3_tag_genres[*ptr];
size = 0xFFFF; /* we know none string length in id3_tag_genres exceed this number */
}
else
{
continue;
}
}
/* measure the string len with limited size boundary */
len = 2; /* UCS2 null terminator */
for (j = 0; ptr[j] && j < size; j++)
{
if (ptr[j] > 0x7F)
{
j++;
if (j == size) /* if it's not ASCII and it's the last char, we discard it */
{
break;
}
}
len += 2;
}
/* check previous frame data from pool. we would like to reuse memory in pool as many as possible */
if (frame_p->text == NULL || frame_p->size < len)
{
/* check available space in pool */
if (id3_tag->text_pool.available_words << 1 >= len)
{
/* alloc space from pool */
frame_p->text = id3_tag->text_pool.next_p;
need_alloc_pool = KAL_TRUE;
}
else
{
continue;
}
}
else
{
need_alloc_pool = KAL_FALSE;
}
/* transalte text to UCS2 and copy to dest space */
len = (kal_uint32) mmi_chset_text_to_ucs2((kal_uint8*) frame_p->text, len, ptr);
frame_p->size = len;
if (need_alloc_pool)
{
id3_text_pool_consume(&id3_tag->text_pool, (len + 1) >> 1);
}
}
return KAL_TRUE;
}
/*****************************************************************************
* FUNCTION
* id3_tag_parse
* DESCRIPTION
*
* PARAMETERS
* input_stream [?]
* id3_tag [?]
* RETURNS
* kal_bool
*****************************************************************************/
kal_bool id3_tag_parse(audio_input_stream_struct *input_stream, id3_tag_struct *id3_tag)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_int32 data_size;
kal_bool v2_result = KAL_FALSE;
kal_bool v1_result = KAL_FALSE;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
/* init id3 tag data structure */
id3_tag_init(id3_tag);
audio_input_stream_seek(input_stream, 0);
/*
* check id3v2 magic word -- "ID3"
* and parse & save data to frames
*/
v2_result = id3_tag_parse_v2_tag(input_stream, id3_tag);
if ((data_size = audio_input_stream_get_data_size(input_stream)) >= 128)
{
/* move to last 128 bytes before file end for checking id3v1 tag */
audio_input_stream_seek(input_stream, data_size - 128);
/*
* check id3v1 magic word -- "TAG"
* and parse & save data to frames
*/
v1_result = id3_tag_parse_v1_tag(input_stream, id3_tag);
}
else
{
v1_result = KAL_FALSE;
}
return v1_result || v2_result;
}
/*****************************************************************************
* FUNCTION
* id3_tag_parse_v2_tag_size
* DESCRIPTION
*
* PARAMETERS
* data [?]
* RETURNS
* kal_int32
*****************************************************************************/
kal_int32 id3_tag_parse_v2_tag_size(kal_uint8 *data)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_uint8 flags, version;
kal_bool footer = KAL_FALSE;
kal_int32 tag_size;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
/* check id3v2 magic word -- "ID3" */
if (!(data[0] == 'I' && data[1] == 'D' && data[2] == '3'))
{
return -1;
}
version = data[3];
if (data[4] != 0)
{
return -1;
}
flags = data[5];
switch (version)
{
case 4:
if (flags & 0x0F) /* check unset bits */
{
return -1;
}
if (flags & 0x10) /* check footer flag */
{
footer = KAL_TRUE;
}
case 3:
if (flags & 0x1F) /* check unset bits */
{
return -1;
}
break;
case 2:
if (flags & 0x3F) /* check unset bits */
{
return -1;
}
break;
default:
return -1;
}
/* get tag size */
tag_size = (kal_int32) id3_tag_get_unsync_uint32(data + 6, 4) + 10; /* 6, 7, 8, 9 */
if (footer)
{
tag_size += 10;
}
return tag_size;
}
#endif /* __RICH_AUDIO_PROFILE__ */
#endif /* MED_NOT_PRESENT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -