From e527d49e550d64732ccb2e24c4b152c3c911fd24 Mon Sep 17 00:00:00 2001 From: David Symonds Date: Tue, 26 Jul 2011 13:28:20 +1000 Subject: [PATCH] http: implement MP4 sniffing. R=rsc CC=golang-dev https://golang.org/cl/4809044 --- src/pkg/http/sniff.go | 29 ++++++++++++++++++++++++++++- src/pkg/http/sniff_test.go | 2 ++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/pkg/http/sniff.go b/src/pkg/http/sniff.go index bf8ce24545..97b234e281 100644 --- a/src/pkg/http/sniff.go +++ b/src/pkg/http/sniff.go @@ -6,6 +6,7 @@ package http import ( "bytes" + "encoding/binary" ) // Content-type sniffing algorithm. @@ -97,7 +98,7 @@ var sniffSignatures = []sniffSig{ &exactSig{[]byte("\x50\x4B\x03\x04"), "application/zip"}, &exactSig{[]byte("\x1F\x8B\x08"), "application/x-gzip"}, - // TODO(dsymonds): MP4. + mp4Sig(0), textSig(0), // should be last } @@ -159,6 +160,32 @@ func (h htmlSig) match(data []byte, firstNonWS int) string { return "text/html; charset=utf-8" } +type mp4Sig int + +func (mp4Sig) match(data []byte, firstNonWS int) string { + // c.f. section 6.1. + if len(data) < 8 { + return "" + } + boxSize := int(binary.BigEndian.Uint32(data[:4])) + if boxSize%4 != 0 || len(data) < boxSize { + return "" + } + if !bytes.Equal(data[4:8], []byte("ftyp")) { + return "" + } + for st := 8; st < boxSize; st += 4 { + if st == 12 { + // minor version number + continue + } + if bytes.Equal(data[st:st+3], []byte("mp4")) { + return "video/mp4" + } + } + return "" +} + type textSig int func (textSig) match(data []byte, firstNonWS int) string { diff --git a/src/pkg/http/sniff_test.go b/src/pkg/http/sniff_test.go index 2d01807f69..baf3a418b5 100644 --- a/src/pkg/http/sniff_test.go +++ b/src/pkg/http/sniff_test.go @@ -34,6 +34,8 @@ var sniffTests = []struct { // Image types. {"GIF 87a", []byte(`GIF87a`), "image/gif"}, {"GIF 89a", []byte(`GIF89a...`), "image/gif"}, + + {"MP4", []byte("\x00\x00\x00\x18ftypmp42\x00\x00\x00\x00mp42isom<\x06t\xbfmdat"), "video/mp4"}, } func TestDetectContentType(t *testing.T) {