summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Noronha Silva <gns@gnome.org>2013-12-10 19:45:55 +0100
committerDan Winship <danw@gnome.org>2014-02-17 12:27:05 -0500
commit9530c7b58197d7d45e21aa60a9986735ccf515b1 (patch)
tree3ccaf69955349beed2c0c3f671d0deb552bb58c4
parent26a65181db0b1fc3eb97748a5e3d9ceeecdc62e3 (diff)
downloadlibsoup-9530c7b58197d7d45e21aa60a9986735ccf515b1.tar.gz
sniffing: Add audio/video sniffing
-rw-r--r--libsoup/soup-content-sniffer.c111
-rw-r--r--tests/resources/test.aiffbin0 -> 384088 bytes
-rw-r--r--tests/resources/test.mp4bin0 -> 192844 bytes
-rw-r--r--tests/resources/test.oggbin0 -> 16994 bytes
-rw-r--r--tests/resources/test.wavbin0 -> 384080 bytes
-rw-r--r--tests/resources/test.webmbin0 -> 149879 bytes
-rw-r--r--tests/sniffing-test.c19
-rw-r--r--tests/soup-tests.gresource.xml5
8 files changed, 135 insertions, 0 deletions
diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c
index 5e0b2a70..5659af9a 100644
--- a/libsoup/soup-content-sniffer.c
+++ b/libsoup/soup-content-sniffer.c
@@ -177,6 +177,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 char *resource = (const char *)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 {
@@ -462,6 +559,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]])
@@ -714,6 +815,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 00000000..9a1ecbb2
--- /dev/null
+++ b/tests/resources/test.aiff
Binary files differ
diff --git a/tests/resources/test.mp4 b/tests/resources/test.mp4
new file mode 100644
index 00000000..d278c8ad
--- /dev/null
+++ b/tests/resources/test.mp4
Binary files differ
diff --git a/tests/resources/test.ogg b/tests/resources/test.ogg
new file mode 100644
index 00000000..e8f49ac3
--- /dev/null
+++ b/tests/resources/test.ogg
Binary files differ
diff --git a/tests/resources/test.wav b/tests/resources/test.wav
new file mode 100644
index 00000000..11660b29
--- /dev/null
+++ b/tests/resources/test.wav
Binary files differ
diff --git a/tests/resources/test.webm b/tests/resources/test.webm
new file mode 100644
index 00000000..7e53d0b4
--- /dev/null
+++ b/tests/resources/test.webm
Binary files differ
diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c
index 868b7c5f..5b0e6ee7 100644
--- a/tests/sniffing-test.c
+++ b/tests/sniffing-test.c
@@ -567,6 +567,25 @@ main (int argc, char **argv)
"type/image_png/tux.webp => image/webp",
do_sniffing_test);
+ /* Test audio and video sniffing path */
+ g_test_add_data_func ("/sniffing/type/audio/wav",
+ "type/audio_mpeg/test.wav => audio/wave",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/audio/aiff",
+ "type/audio_mpeg/test.aiff => audio/aiff",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/audio/ogg",
+ "type/audio_mpeg/test.ogg => application/ogg",
+ do_sniffing_test);
+ g_test_add_data_func ("/sniffing/type/video/webm",
+ "type/video_theora/test.webm => video/webm",
+ do_sniffing_test);
+
+ /* Test the MP4 sniffing path */
+ g_test_add_data_func ("/sniffing/type/video/mp4",
+ "unknown/test.mp4 => video/mp4",
+ do_sniffing_test);
+
/* The spec tells us to only use the last Content-Type header */
g_test_add_data_func ("/sniffing/multiple-headers",
"multiple_headers/home.gif => image/gif",
diff --git a/tests/soup-tests.gresource.xml b/tests/soup-tests.gresource.xml
index 444ed588..b24a7297 100644
--- a/tests/soup-tests.gresource.xml
+++ b/tests/soup-tests.gresource.xml
@@ -15,7 +15,12 @@
<file>resources/mbox.zlib</file>
<file>resources/ps_binary.ps</file>
<file>resources/rss20.xml</file>
+ <file>resources/test.aiff</file>
<file>resources/test.html</file>
+ <file>resources/test.mp4</file>
+ <file>resources/test.ogg</file>
+ <file>resources/test.wav</file>
+ <file>resources/test.webm</file>
<file>resources/text.txt</file>
<file>resources/text_binary.txt</file>
<file>resources/tux.webp</file>