1
0
mirror of https://github.com/mpv-player/mpv synced 2025-01-02 04:42:10 +00:00

retrieve metadata from FLAC files (patch by Benjamin Zores < ben _at_ geexbox.org >)

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@17899 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
aurel 2006-03-20 20:06:04 +00:00
parent 05a8589af1
commit 88901c08d4

View File

@ -130,6 +130,150 @@ static mp3_hdr_t *add_mp3_hdr(mp3_hdr_t **list, off_t st_pos,
return NULL;
}
#define FLAC_SIGNATURE_SIZE 4
#define FLAC_STREAMINFO_SIZE 34
#define FLAC_SEEKPOINT_SIZE 18
enum {
FLAC_STREAMINFO = 0,
FLAC_PADDING,
FLAC_APPLICATION,
FLAC_SEEKTABLE,
FLAC_VORBIS_COMMENT,
FLAC_CUESHEET
} flac_preamble_t;
static void
get_flac_metadata (demuxer_t* demuxer)
{
uint8_t preamble[4];
unsigned int blk_len;
stream_t *s = NULL;
if (!demuxer)
return;
s = demuxer->stream;
if (!s)
return;
/* file is qualified; skip over the signature bytes in the stream */
stream_seek (s, 4);
/* loop through the metadata blocks; use a do-while construct since there
* will always be 1 metadata block */
do {
int r;
r = stream_read (s, (char *) preamble, FLAC_SIGNATURE_SIZE);
if (r != FLAC_SIGNATURE_SIZE)
return;
blk_len = (preamble[1] << 16) | (preamble[2] << 8) | (preamble[3] << 0);
switch (preamble[0] & 0x7F)
{
case FLAC_STREAMINFO:
{
if (blk_len != FLAC_STREAMINFO_SIZE)
return;
stream_skip (s, FLAC_STREAMINFO_SIZE);
break;
}
case FLAC_PADDING:
stream_skip (s, blk_len);
break;
case FLAC_APPLICATION:
stream_skip (s, blk_len);
break;
case FLAC_SEEKTABLE:
{
int seekpoint_count, i;
seekpoint_count = blk_len / FLAC_SEEKPOINT_SIZE;
for (i = 0; i < seekpoint_count; i++)
if (stream_skip (s, FLAC_SEEKPOINT_SIZE) != 1)
return;
break;
}
case FLAC_VORBIS_COMMENT:
{
/* For a description of the format please have a look at */
/* http://www.xiph.org/vorbis/doc/v-comment.html */
uint32_t length, comment_list_len;
char comments[blk_len];
void *ptr = comments;
char *comment;
int cn;
char c;
if (stream_read (s, comments, blk_len) == blk_len)
{
uint8_t *p = ptr;
length = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
ptr += 4 + length;
p = ptr;
comment_list_len = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
ptr += 4;
cn = 0;
for (; cn < comment_list_len; cn++)
{
p = ptr;
length = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
ptr += 4;
comment = (char *) ptr;
c = comment[length];
comment[length] = 0;
if (!strncasecmp ("TITLE=", comment, 6) && (length - 6 > 0))
demux_info_add (demuxer, "Title", comment + 6);
else if (!strncasecmp ("ARTIST=", comment, 7) && (length - 7 > 0))
demux_info_add (demuxer, "Artist", comment + 7);
else if (!strncasecmp ("ALBUM=", comment, 6) && (length - 6 > 0))
demux_info_add (demuxer, "Album", comment + 6);
else if (!strncasecmp ("DATE=", comment, 5) && (length - 5 > 0))
demux_info_add (demuxer, "Year", comment + 5);
else if (!strncasecmp ("GENRE=", comment, 6) && (length - 6 > 0))
demux_info_add (demuxer, "Genre", comment + 6);
else if (!strncasecmp ("Comment=", comment, 8) && (length - 8 > 0))
demux_info_add (demuxer, "Comment", comment + 8);
else if (!strncasecmp ("TRACKNUMBER=", comment, 12)
&& (length - 12 > 0))
{
char buf[31];
buf[30] = '\0';
sprintf (buf, "%d", atoi (comment + 12));
demux_info_add(demuxer, "Track", buf);
}
comment[length] = c;
ptr += length;
}
}
break;
}
case FLAC_CUESHEET:
stream_skip (s, blk_len);
break;
default:
/* 6-127 are presently reserved */
stream_skip (s, blk_len);
break;
}
} while ((preamble[0] & 0x80) == 0);
}
static int demux_audio_open(demuxer_t* demuxer) {
stream_t *s;
sh_audio_t* sh_audio;
@ -352,6 +496,7 @@ static int demux_audio_open(demuxer_t* demuxer) {
sh_audio->format = mmioFOURCC('f', 'L', 'a', 'C');
demuxer->movi_start = stream_tell(s);
demuxer->movi_end = s->end_pos;
get_flac_metadata (demuxer);
break;
}