--- icecast-2.3.2/src/format_mp3.c~	2007-10-19 03:02:35.000000000 +0000
+++ icecast-2.3.2/src/format_mp3.c	2011-09-01 15:14:04.076836673 +0000
@@ -483,6 +483,162 @@
     return 1;
 }
 
+static int bitrate_table[2][3][14] =
+{
+ {
+   /* MPEG-2 Layer III */
+   { 8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160},
+   /* MPEG-2 Layer II */
+   { 8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160},
+   /* MPEG-2 Layer I */
+   {32, 48, 56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256}
+ },
+ {
+   /* MPEG-1 Layer III */
+   {32, 40, 48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320},
+   /* MPEG-1 Layer II */
+   {32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384},
+   /* MPEG-1 Layer I */
+   {32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448}
+ }
+};
+
+static int samplerate_table[4][3] =
+{
+   {11025, 12000,  8000}, /* MPEG-2 LSF */
+   {    0,     0,     0}, /* Reserved */
+   {22050, 24000, 16000}, /* MPEG-2 */
+   {44100, 48000, 32000}  /* MPEG-1 */
+};
+
+static int framesize_table[2][3] =
+{
+ /* L.III  L.II   L.I */
+   {  576, 1152,  384}, /* MPEG-2 */
+   { 1152, 1152,  384}  /* MPEG-1 */
+};
+
+static int slotsize_table[3] =
+{
+   1, /* L. III */
+   1, /* L. II  */
+   4  /* L. I   */
+};
+
+static int validate_header(mpeg_frame_t *fr)
+{
+    unsigned char version_code, layer_code, bitrate_code, 
+                  samplerate_code, padding;
+    char message[200];
+
+#define MAX_FRAME_LEN 2880  /* 160kbps Layer II @ 8kHz */
+
+    /* Check sync word is present */
+    if (fr->data[0] != 0xff || (fr->data[1] & 0xe0) != 0xe0)
+        goto invalid_frame;
+
+    /* Validate header by checking no reserved values are present */
+    if ( (version_code    = (fr->data[1] & 0x18) >> 3) ==  1
+      || (layer_code      = (fr->data[1] & 0x06) >> 1) ==  0
+      || (bitrate_code    = (fr->data[2] & 0xf0) >> 4) == 15
+      || (samplerate_code = (fr->data[2] & 0x0c) >> 2) ==  3)
+        goto invalid_frame;
+
+    if (bitrate_code == 0) /* Free-format bitrate */
+        /* We can't calculate the frame length anyway from this so can go no 
+         * further with validation, so return the header as invalid. This is
+         * arguably a bug. */
+        goto invalid_frame;
+
+    /* Calculate data length of frame */
+    fr->kbps = bitrate_table[version_code & 1][layer_code - 1][bitrate_code - 1];
+    fr->sample_rate_Hz = samplerate_table[version_code][samplerate_code];
+    padding = (fr->data[2] & 0x02) >> 1;
+    fr->bytes = (framesize_table[version_code & 1][layer_code - 1] / 8 
+                 / slotsize_table[layer_code - 1] * fr->kbps * 1000 
+                 / fr->sample_rate_Hz + padding)
+                * slotsize_table[layer_code - 1];
+
+    if (fr->bytes <= 0 || fr->bytes > MAX_FRAME_LEN)
+        goto invalid_frame;
+
+    if ((fr->data[3] & 0xc0) >> 6 == 3) /* mono */
+        fr->channels = 1;
+    else
+        fr->channels = 2;
+
+    return fr->bytes;
+
+invalid_frame:
+    fr->bytes = -1;
+    return -1;
+}
+
+/* Parse the MP3 data (also handles MPEG audio layers I/II) to check if there
+ * is a partial frame at the end of the data. If so the partial data is stored
+ * in the MP3 state (where it will be appended to the next time complete_read()
+ * is called) and the modified refbuf containing only complete frames is 
+ * returned.
+ * Note that incomplete frames occuring at the *start* of the data buffer are
+ * ignored. This is so that huge frames (greater than the REFBUF size) can still
+ * be handled correctly.
+ */
+static void remove_partial_frames(refbuf_t *refbuf, mp3_state *source_mp3)
+{
+    int frame_offset = 0, valid_frames = 0;
+
+    /* while there are enough bytes remaining for a valid header */
+    while (refbuf->len - frame_offset >= 4)
+    {
+        mpeg_frame_t fr;
+
+        /* check the header is valid and determine the total frame length */
+        fr.data = (unsigned char *)refbuf->data+frame_offset;
+        validate_header(&fr);
+
+        /* If any frames are bigger than the refbuf size, then we need to leave
+         * them intact and just put up with the fact they will be split up. Such
+         * huge frames should be very rare in practice. */
+        if (fr.bytes > REFBUF_SIZE)
+            return;
+
+        if (fr.bytes > 0) /* if header is valid */
+        {
+            if(frame_offset + fr.bytes > refbuf->len)
+                /* this frame extends beyond the buffer */
+                break;
+
+            valid_frames++;
+            /* Skip to start of next frame */
+            frame_offset += fr.bytes;
+            continue;
+        }
+
+        /* Validation failed: shift forward by one byte and keep searching for header */
+        frame_offset++;
+    }
+
+    if (frame_offset == refbuf->len || valid_frames == 0)
+        /* buffer contained only either wholly complete or wholly partial frames */
+        return;
+
+    /* Allocate a new refbuf to hold the partial last frame. When complete_read()
+     * is called again it will append to this. */
+    source_mp3->read_data = refbuf_new (REFBUF_SIZE);
+    source_mp3->read_count = refbuf->len - frame_offset;
+
+    /* Copy the partial frame into the new refbuf and reduce the byte count for 
+     * the existing refbuf accordingly. */
+    memcpy (source_mp3->read_data->data, refbuf->data+frame_offset,
+            source_mp3->read_count);
+    refbuf->len = frame_offset;
+
+    /* Finally adjust the metadata interval offset to avoid "double-counting" of 
+     * the bytes in the partial frame. */
+    source_mp3->offset -= source_mp3->read_count;
+
+    return;
+}
 
 /* read an mp3 stream which does not have shoutcast style metadata */
 static refbuf_t *mp3_get_no_meta (source_t *source)
@@ -503,7 +659,10 @@
     }
     refbuf->associated = source_mp3->metadata;
     refbuf_addref (source_mp3->metadata);
+
+    remove_partial_frames(refbuf, source_mp3);
     refbuf->sync_point = 1;
+
     return refbuf;
 }
 
@@ -623,6 +782,8 @@
     }
     refbuf->associated = source_mp3->metadata;
     refbuf_addref (source_mp3->metadata);
+
+    remove_partial_frames(refbuf, source_mp3);
     refbuf->sync_point = 1;
 
     return refbuf;
--- icecast-2.3.2/src/format_mp3.h~	2006-09-21 01:49:16.000000000 +0000
+++ icecast-2.3.2/src/format_mp3.h	2011-08-31 16:34:05.888838280 +0000
@@ -37,6 +37,16 @@
     char build_metadata[4081];
 } mp3_state;
 
+typedef struct
+{
+    unsigned char *data; /* Pointer to complete MPEG audio frame (including 
+                          * sync word and header */
+    int bytes;           /* Length of MPEG frame in bytes */
+    int kbps;            /* Bitrate in kilobits per second */
+    int sample_rate_Hz;  /* Sample rate in hertz */
+    int channels;        /* Number of channels (mono/stereo) */
+} mpeg_frame_t;
+
 int format_mp3_get_plugin(struct source_tag *src);
 
 #endif  /* __FORMAT_MP3_H__ */
