shithub: sox

Download patch

ref: 55272cd7e8ed79f7e5caaaa04ab8486d1afa2fb0
parent: dceeb3a64f343c91723e6367022caa849030e4b8
author: cbagwell <cbagwell>
date: Sun Oct 10 19:24:09 EDT 2004

All any size IDv3 tag to be skipped past.

--- a/src/mp3.c
+++ b/src/mp3.c
@@ -28,7 +28,7 @@
 #define MIN(s1,s2) ((s1)<(s2)?(s1):(s2))
 #endif
 
-#define INPUT_BUFFER_SIZE       (100 * 1024)
+#define INPUT_BUFFER_SIZE       (ST_BUFSIZ)
 
 /* Private data */
 struct mp3priv {
@@ -132,7 +132,7 @@
 
         /* We need to decode the first frame,
          * so we know the output format */
-
+more_data:
         ReadSize=st_read(ft, p->InputBuffer, 1, INPUT_BUFFER_SIZE);
         if(ReadSize<=0)
         {
@@ -150,25 +150,32 @@
          * that we have a valid MP3 and also skips past ID3v2 tags
          * at the beginning of the audio file.
          */
-        /* FIXME: Doesn't this throw away the first frame of audio
-         * when there is no ID3v2 at the beginning?
-         */
         while(mad_frame_decode(p->Frame,p->Stream)) {
             int tagsize;
-            if ((p->Stream->bufend - p->Stream->this_frame) == 0) {
+            size_t remaining;
 
-              /* we assume that, if the first frame fails, the file is not an MP3 file */
-              
-              st_fail_errno(ft,ST_EOF,"The file is not an MP3 file or it is corrupted");
-              return ST_EOF;
+            remaining = p->Stream->bufend - p->Stream->this_frame;
+            if (remaining <= 8) {
+                /* Read another buffer full of data. */
+                memmove(p->InputBuffer, p->Stream->this_frame, remaining);
+
+                ReadSize=st_read(ft, p->InputBuffer+remaining, 1, INPUT_BUFFER_SIZE-remaining);
+                if (ReadSize <= 0) {
+                  st_fail_errno(ft,ST_EOF,"The file is not an MP3 file or it is corrupted");
+                  return ST_EOF;
+                }
+
+                remaining+=ReadSize;
+                mad_stream_buffer(p->Stream, p->InputBuffer, remaining);
+                p->Stream->error = 0;
             }
 
-            /* Skip pas this frame, based on tag size.  If invalid
+            /* Skip past this frame, based on tag size.  If invalid
              * tag then Walk threw the stream one byte at a time (tagsize=1)
              * until we find a valid frame.  Previous if() will
              * abort once we got a certain distance.
              */
-            if ((tagsize=tagtype(p->Stream->this_frame, p->Stream->bufend - p->Stream->this_frame)) == 0)
+            if ((tagsize=tagtype(p->Stream->this_frame, remaining)) == 0)
                 tagsize = 1; /* Walk through the stream. */
 
             /* ID3v2 tags can be any size.  That means they can
@@ -175,15 +182,24 @@
              * span a buffer larger then INPUT_BUFFER_SIZE.  That
              * means that we really need a loop to continue reading
              * more data.
-             * For now, I'm just making the input buffer pretty
-             * large to handle most cases and hope someone else
-             * write more robust code later!
              */
-            if (tagsize > (p->Stream->bufend - p->Stream->this_frame))
+            if (tagsize > remaining)
             {
-                st_fail_errno(ft, ST_EOF, "Found ID3 tag that is larger then initial buffer. Can't handle this right now\n", (p->Stream->bufend - p->Stream->this_frame));
-                return ST_EOF;
+                /* Discard the remaining data and read the rest of the tag
+                 * data from the file and start over.
+                 */
+                tagsize -= remaining;
+                while (tagsize > 0)
+                {
+                    if (tagsize < INPUT_BUFFER_SIZE)
+                        ReadSize=st_read(ft, p->InputBuffer, 1, tagsize);
+                    else
+                        ReadSize=st_read(ft, p->InputBuffer, 1, INPUT_BUFFER_SIZE);
+                    tagsize -= ReadSize;
+                }
+                goto more_data;
             }
+
             mad_stream_skip(p->Stream, tagsize);
         }