allow ffmpeg to read mp3s beginning with partial frames
[ffmpeg.git] / libavformat / mp3.c
index 7b1a147..1aa0514 100644 (file)
@@ -17,6 +17,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 #include "avformat.h"
+#include "mpegaudio.h"
 
 #define ID3_HEADER_SIZE 10
 #define ID3_TAG_SIZE 128
@@ -243,27 +244,38 @@ static void id3_create_tag(AVFormatContext *s, uint8_t *buf)
 
 static int mp3_read_probe(AVProbeData *p)
 {
-    int d;
+    int max_frames;
+    int fsize, frames;
+    uint32_t header;
+    uint8_t *buf, *buf2, *end;
+    AVCodecContext avctx;
 
-    if(p->buf_size < 4)
+    if(p->buf_size < ID3_HEADER_SIZE)
         return 0;
 
-    if(p->buf[0] == 'I' && p->buf[1] == 'D' && p->buf[2] == '3' &&
-       p->buf[3] < 5)
+    if(id3_match(p->buf))
         return AVPROBE_SCORE_MAX;
 
-    if(p->buf[0] != 0xff)
-        return 0;
-
-    d = p->buf[1];
-    if((d & 0xe0) != 0xe0 || ((d & 0x18) == 0x08 || (d & 0x06) == 0))
-        return 0;
+    max_frames = 0;
+    buf = p->buf;
+    end = buf + FFMIN(4096, p->buf_size - sizeof(uint32_t));
 
-    d = p->buf[2];
-    if((d & 0xf0) == 0xf0 || (d & 0x0c) == 0x0c)
-        return 0;
+    for(; buf < end; buf++) {
+        buf2 = buf;
 
-    return AVPROBE_SCORE_MAX;
+        for(frames = 0; buf < end; frames++) {
+            header = (buf2[0] << 24) | (buf2[1] << 16) | (buf2[2] << 8) | buf2[3];
+            fsize = mpa_decode_header(&avctx, header);
+            if(fsize < 0)
+                break;
+            buf2 += fsize;
+        }
+        max_frames = FFMAX(max_frames, frames);
+    }
+    if     (max_frames>=3) return AVPROBE_SCORE_MAX/2+1;
+    else if(max_frames==2) return AVPROBE_SCORE_MAX/4;
+    else if(max_frames==1) return 1;
+    else                   return 0;
 }
 
 static int mp3_read_header(AVFormatContext *s,