diff options
Diffstat (limited to 'src/demuxers/demux_mpgaudio.c')
-rw-r--r-- | src/demuxers/demux_mpgaudio.c | 225 |
1 files changed, 14 insertions, 211 deletions
diff --git a/src/demuxers/demux_mpgaudio.c b/src/demuxers/demux_mpgaudio.c index 2ab7a4323..2b73cbc9e 100644 --- a/src/demuxers/demux_mpgaudio.c +++ b/src/demuxers/demux_mpgaudio.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_mpgaudio.c,v 1.131 2003/12/06 19:06:31 tmattern Exp $ + * $Id: demux_mpgaudio.c,v 1.132 2003/12/07 23:05:41 tmattern Exp $ * * demultiplexer for mpeg audio (i.e. mp3) streams * @@ -47,6 +47,7 @@ #include "compat.h" #include "bswap.h" #include "group_audio.h" +#include "id3.h" #define NUM_PREVIEW_BUFFERS 10 #define SNIFF_BUFFER_LENGTH 1024 @@ -68,23 +69,6 @@ #define XING_TOC_FLAG 0x0004 #define XING_VBR_SCALE_FLAG 0x0008 -/* id3v2 */ -#define ID3V22_TAG FOURCC_TAG('I', 'D', '3', 2) /* id3 v2.2 tags */ -#define ID3V23_TAG FOURCC_TAG('I', 'D', '3', 3) /* id3 v2.3 tags */ -#define ID3V24_TAG FOURCC_TAG('I', 'D', '3', 4) /* id3 v2.4 tags */ -#define ID3V2_UNSYNCH_FLAG 0x8000 - -/* id2v2.2 */ -#define ID3V2_COMPRESS_FLAG 0x4000 - -/* id2v2.3 */ -#define ID3V2_EXTHEAD_FLAG 0x4000 -#define ID3V2_EXP_FLAG 0x2000 - -/* id2v2.4 */ -#define ID3V2_FOOTER_FLAG 0x1000 - - typedef struct { /* header */ uint16_t frame_sync; @@ -109,33 +93,6 @@ typedef struct { double duration; /* in 1/90000 s */ } mpg_audio_frame_t; -typedef struct { - uint32_t id; - uint8_t revision; - uint8_t flags; - uint32_t size; -} id3v2_header_t; - -typedef struct { - uint32_t id; - uint32_t size; -} id3v22_frame_header_t; - -typedef struct { - uint32_t id; - uint32_t size; - uint16_t flags; -} id3v23_frame_header_t; - -typedef struct { - char tag[3]; - char title[30]; - char artist[30]; - char album[30]; - char year[4]; - char comment[30]; - char genre; -} id3v1_tag_t; typedef struct { @@ -533,165 +490,6 @@ static int sniff_buffer_looks_like_mp3 (input_plugin_t *input) return 0; } -static void read_id3_tags (demux_mpgaudio_t *this) { - - off_t len; - id3v1_tag_t tag; - - /* id3v1 */ - len = this->input->read (this->input, (char *)&tag, 128); - - if (len > 0) { - - if ( (tag.tag[0]=='T') && (tag.tag[1]=='A') && (tag.tag[2]=='G') ) { - - lprintf("id3v1 tag found\n"); - _x_meta_info_n_set(this->stream, XINE_META_INFO_TITLE, tag.title, 30); - _x_meta_info_n_set(this->stream, XINE_META_INFO_ARTIST, tag.artist, 30); - _x_meta_info_n_set(this->stream, XINE_META_INFO_ALBUM, tag.album, 30); - _x_meta_info_n_set(this->stream, XINE_META_INFO_COMMENT, tag.comment, 30); - } - } -} - -static int id3v2_parse_header(input_plugin_t *input, uint8_t *mp3_frame_header, - id3v2_header_t *tag_header) { - uint8_t buf[6]; - - tag_header->id = BE_32(mp3_frame_header); - if (input->read (input, buf, 6) == 6) { - tag_header->revision = buf[0]; - tag_header->flags = buf[1]; - - /* only 7 bits per byte */ - tag_header->size = (buf[2] << 21) + (buf[3] << 14) + (buf[4] << 7) + buf[5]; - lprintf("tag: ID3 v2.%d.%d\n", mp3_frame_header[3], tag_header->revision); - lprintf("flags: %d\n", tag_header->flags); - lprintf("size: %d\n", tag_header->size); - return 1; - } else { - return 0; - } -} - -static int id3v22_parse_frame_header(input_plugin_t *input, - id3v22_frame_header_t *frame_header) { - uint8_t buf[6]; - - if (input->read (input, buf, 6) == 6) { - frame_header->id = (buf[0] << 16) + (buf[1] << 8) + buf[2]; - - /* only 7 bits per byte */ - frame_header->size = (buf[3] << 14) + (buf[4] << 7) + buf[5]; - - lprintf("frame: %c%c%c: size: %d\n", buf[0], buf[1], buf[2], - frame_header->size); - - return 1; - } else { - return 0; - } -} - -static int id3v22_interp_frame(demux_mpgaudio_t *this, - id3v22_frame_header_t *frame_header) { - /* - * FIXME: supports unicode - */ - char buf[4096]; - - if (frame_header->size > 4096) { - lprintf("too long\n"); - return 1; - } - - if (this->input->read (this->input, buf, frame_header->size) == frame_header->size) { - buf[frame_header->size] = 0; - - switch (frame_header->id) { - case (FOURCC_TAG(0, 'T', 'T', '1')): - _x_meta_info_set(this->stream, XINE_META_INFO_GENRE, buf + 1); - break; - - case (FOURCC_TAG(0, 'T', 'T', '2')): - _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, buf + 1); - break; - - case (FOURCC_TAG(0, 'T', 'P', '1')): - _x_meta_info_set(this->stream, XINE_META_INFO_ARTIST, buf + 1); - break; - - case (FOURCC_TAG(0, 'T', 'A', 'L')): - _x_meta_info_set(this->stream, XINE_META_INFO_ALBUM, buf + 1); - break; - - case (FOURCC_TAG(0, 'T', 'Y', 'E')): - _x_meta_info_set(this->stream, XINE_META_INFO_YEAR, buf + 1); - break; - - case (FOURCC_TAG(0, 'C', 'O', 'M')): - _x_meta_info_set(this->stream, XINE_META_INFO_COMMENT, buf + 1 + 3); - break; - - default: - lprintf("unhandled frame\n"); - } - - return 1; - } else { - lprintf("read error\n"); - return 0; - } -} - - -static int id3v22_parse_tag(demux_mpgaudio_t *this, int8_t *mp3_frame_header) { - id3v2_header_t tag_header; - id3v22_frame_header_t tag_frame_header; - int pos = 0; - - if (id3v2_parse_header(this->input, mp3_frame_header, &tag_header)) { - - if (tag_header.flags & ID3V2_COMPRESS_FLAG) { - /* compressed tag ? just skip it */ - this->input->seek (this->input, tag_header.size - pos, SEEK_CUR); - } else { - - while ((pos + 6) <= tag_header.size) { - if (id3v22_parse_frame_header(this->input, &tag_frame_header)) { - pos += 6; - if (tag_frame_header.id && tag_frame_header.size) { - if ((pos + tag_frame_header.size) <= tag_header.size) { - if (!id3v22_interp_frame(this, &tag_frame_header)) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "id2v22: invalid frame content\n"); - } - } else { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "id3v22: invalid frame header\n"); - this->input->seek (this->input, tag_header.size - pos, SEEK_CUR); - return 1; - } - pos += tag_frame_header.size; - } else { - /* end of frames, the rest is padding */ - this->input->seek (this->input, tag_header.size - pos, SEEK_CUR); - return 1; - } - } else { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "id2v22: id3v2_parse_frame_header problem\n"); - return 0; - } - } - } - return 1; - } else { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "id3v22: id3v2_parse_header problem\n"); - return 0; - } -} - static int mpg123_read_frame_header(demux_mpgaudio_t *this, uint8_t *header_buf, int bytes) { off_t len; int i; @@ -725,19 +523,24 @@ static int demux_mpgaudio_next (demux_mpgaudio_t *this, int decoder_flags) { return mpg123_parse_frame_payload(this, header_buf, decoder_flags); } else if ((BE_32(header_buf)) == ID3V22_TAG) { - lprintf("ID3V2.2 tag\n"); - if (!id3v22_parse_tag(this, header_buf)) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_mpgaudio: ID3V2.2 tag\n"); + if (!id3v22_parse_tag(this->input, this->stream, header_buf)) { return 0; } bytes = 4; } else if ((BE_32(header_buf)) == ID3V23_TAG) { - lprintf("ID3V2.3 tag\n"); - /* TODO: add parsing here */ - bytes = 1; /* resync */ + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_mpgaudio: ID3V2.3 tag\n"); + if (!id3v23_parse_tag(this->input, this->stream, header_buf)) { + return 0; + } + bytes = 4; } else if ((BE_32(header_buf)) == ID3V24_TAG) { - lprintf("ID3V2.4 tag\n"); + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_mpgaudio: ID3V2.4 tag\n"); /* TODO: add parsing here */ bytes = 1; /* resync */ @@ -832,7 +635,7 @@ static void demux_mpgaudio_send_headers (demux_plugin_t *this_gen) { pos = this->input->get_length(this->input) - 128; if(pos > 0) { if (pos == this->input->seek (this->input, pos, SEEK_SET)) - read_id3_tags (this); + id3v1_parse_tag (this->input, this->stream); } } |