[libsoup/content-sniffing-update: 8/8] Add audio/video sniffing



commit 78b5fed3609e733f4305c1944aedcdfe0f9620be
Author: Gustavo Noronha Silva <gns gnome org>
Date:   Tue Dec 10 19:45:55 2013 +0100

    Add audio/video sniffing

 libsoup/soup-content-sniffer.c |  111 ++++++++++++++++++++++++++++++++++++++++
 tests/resources/test.aiff      |  Bin 0 -> 384088 bytes
 tests/resources/test.ogg       |  Bin 0 -> 16994 bytes
 tests/resources/test.wav       |  Bin 0 -> 384080 bytes
 tests/resources/test.webm      |  Bin 0 -> 149879 bytes
 tests/sniffing-test.c          |    9 +++
 6 files changed, 120 insertions(+), 0 deletions(-)
---
diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c
index 5c5ae83..0f6be72 100644
--- a/libsoup/soup-content-sniffer.c
+++ b/libsoup/soup-content-sniffer.c
@@ -176,6 +176,103 @@ sniff_images (SoupContentSniffer *sniffer, SoupBuffer *buffer)
 }
 
 /* This table is based on the MIMESNIFF spec;
+ * See 6.2 Matching an audio or video type pattern
+ */
+static SoupContentSnifferMediaPattern audio_video_types_table[] = {
+       { (const guchar *)"\xFF\xFF\xFF\xFF",
+         (const guchar *)"\x1A\x45\xDF\xA3",
+         4,
+         "video/webm" },
+
+       { (const guchar *)"\xFF\xFF\xFF\xFF",
+         (const guchar *)".snd",
+         4,
+         "audio/basic" },
+
+
+       { (const guchar *)"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF",
+        (const guchar *)"FORM\0\0\0\0AIFF",
+         12,
+         "audio/aiff" },
+
+       { (const guchar *)"\xFF\xFF\xFF",
+         (const guchar *)"ID3",
+         3,
+         "audio/mpeg" },
+
+       { (const guchar *)"\xFF\xFF\xFF\xFF\xFF",
+         (const guchar *)"OggS\0",
+         5,
+         "application/ogg" },
+
+       { (const guchar *)"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
+         (const guchar *)"MThd\x00\x00\x00\x06",
+         8,
+         "audio/midi" },
+
+       { (const guchar *)"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF",
+         (const guchar *)"RIFF\x00\x00\x00\x00AVI ",
+         12,
+         "video/avi" },
+
+       { (const guchar *)"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF",
+         (const guchar *)"RIFF\x00\x00\x00\x00WAVE",
+         12,
+         "audio/wave" },
+};
+
+static gboolean
+sniff_mp4 (SoupContentSniffer *sniffer, SoupBuffer *buffer)
+{
+       const gchar *resource = (const gchar *)buffer->data;
+       int resource_length = MIN (512, buffer->length);
+       guint32 box_size = *((guint32*)resource);
+       int i;
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+       box_size = (box_size >> 24) |
+                  ((box_size << 8) & 0x00FF0000) |
+                  ((box_size >> 8) & 0x0000FF00) |
+                  (box_size << 24);
+#endif
+
+       if (resource_length < 12 || resource_length < box_size || box_size % 4 != 0)
+               return FALSE;
+
+       if (!g_str_has_prefix (resource + 4, "ftyp"))
+               return FALSE;
+
+       if (!g_str_has_prefix (resource + 8, "mp4"))
+               return FALSE;
+
+       for (i = 16; i < box_size && i < resource_length; i = i + 4) {
+               if (g_str_has_prefix (resource + i, "mp4"))
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
+static char*
+sniff_audio_video (SoupContentSniffer *sniffer, SoupBuffer *buffer)
+{
+       char *sniffed_type;
+
+       sniffed_type = sniff_media (sniffer,
+                                   buffer,
+                                   audio_video_types_table,
+                                   G_N_ELEMENTS (audio_video_types_table));
+
+       if (sniffed_type != NULL)
+               return sniffed_type;
+
+       if (sniff_mp4 (sniffer, buffer))
+               return g_strdup ("video/mp4");
+
+       return NULL;
+}
+
+/* This table is based on the MIMESNIFF spec;
  * See 7.1 Identifying a resource with an unknown MIME type
  */
 typedef struct {
@@ -459,6 +556,10 @@ sniff_unknown (SoupContentSniffer *sniffer, SoupBuffer *buffer,
        if (sniffed_type != NULL)
                return sniffed_type;
 
+       sniffed_type = sniff_audio_video (sniffer, buffer);
+
+       if (sniffed_type != NULL)
+               return sniffed_type;
 
        for (i = 0; i < resource_length; i++) {
                if (byte_looks_binary[resource[i]])
@@ -711,6 +812,16 @@ soup_content_sniffer_real_sniff (SoupContentSniffer *sniffer, SoupMessage *msg,
                return g_strdup (content_type);
        }
 
+       /* 7. Audio and video types. */
+       if (!g_ascii_strncasecmp (content_type, "audio/", 6) ||
+           !g_ascii_strncasecmp (content_type, "video/", 6) ||
+           !g_ascii_strcasecmp (content_type, "application/ogg")) {
+               sniffed_type = sniff_audio_video (sniffer, buffer);
+               if (sniffed_type != NULL)
+                       return sniffed_type;
+               return g_strdup (content_type);
+        }
+
        /* If we got text/plain, use text_or_binary */
        if (g_str_equal (content_type, "text/plain")) {
                return sniff_text_or_binary (sniffer, buffer);
diff --git a/tests/resources/test.aiff b/tests/resources/test.aiff
new file mode 100644
index 0000000..9a1ecbb
Binary files /dev/null and b/tests/resources/test.aiff differ
diff --git a/tests/resources/test.ogg b/tests/resources/test.ogg
new file mode 100644
index 0000000..e8f49ac
Binary files /dev/null and b/tests/resources/test.ogg differ
diff --git a/tests/resources/test.wav b/tests/resources/test.wav
new file mode 100644
index 0000000..11660b2
Binary files /dev/null and b/tests/resources/test.wav differ
diff --git a/tests/resources/test.webm b/tests/resources/test.webm
new file mode 100644
index 0000000..7e53d0b
Binary files /dev/null and b/tests/resources/test.webm differ
diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c
index d53d06f..ba34c80 100644
--- a/tests/sniffing-test.c
+++ b/tests/sniffing-test.c
@@ -600,6 +600,15 @@ main (int argc, char **argv)
        test_sniffing ("/type/image_png/home.jpg", "image/jpeg");
        test_sniffing ("/type/image_png/tux.webp", "image/webp");
 
+       /* Test audio and video sniffing path */
+       test_sniffing ("/type/audio_mpeg/test.wav", "audio/wave");
+       test_sniffing ("/type/audio_mpeg/test.aiff", "audio/aiff");
+       test_sniffing ("/type/audio_mpeg/test.ogg", "application/ogg");
+       test_sniffing ("/type/video_theora/test.webm", "video/webm");
+
+       /* Test the MP4 sniffing path */
+       test_sniffing ("/unknown/test.mp4", "video/mp4");
+
        /* The spec tells us to only use the last Content-Type header */
 
        test_sniffing ("/multiple_headers/home.gif", "image/gif");


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]