summaryrefslogtreecommitdiff
path: root/src/demuxers/demux_mpgaudio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/demuxers/demux_mpgaudio.c')
-rw-r--r--src/demuxers/demux_mpgaudio.c225
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);
}
}