github.com/puellanivis/breton@v0.2.16/lib/mpeg/framer/framer.go (about) 1 package framer 2 3 import ( 4 "bufio" 5 "bytes" 6 "io" 7 "net/http" 8 9 "github.com/pkg/errors" 10 ) 11 12 // Various MIME-Types for Audo/Video types. 13 const ( 14 AAC = "audio/x-aac" 15 MP3 = "audio/mp3" 16 H264 = "video/h264" 17 ) 18 19 // Scanner implemnets bufio.Scanner breaking up certain Audio/Video types into packet frames. 20 type Scanner struct { 21 mediaType string 22 frameDetect []byte 23 24 *bufio.Scanner 25 } 26 27 // MediaType returns what MIME-Type was detected by the Scanner. 28 func (s *Scanner) MediaType() string { 29 if len(s.frameDetect) <= 0 { 30 return "unknown/unknown" 31 } 32 33 return s.mediaType 34 } 35 36 // GetPCR returns the current PCR from the Scanner, extracting the information from the MPEG frame header. 37 // 38 // TODO: currently unimplemented. 39 func (s *Scanner) GetPCR() int64 { 40 return 0 41 } 42 43 var ( 44 syncWordMP3nocrc = []byte{0xFF, 0xFA} 45 syncWordMP3 = []byte{0xFF, 0xFB} 46 47 syncWordAACnocrc = []byte{0xFF, 0xF0} 48 syncWordAAC = []byte{0xFF, 0xF1} 49 50 syncWordNAL = []byte{0x00, 0x00, 0x00, 0x01} 51 ) 52 53 // DetectContentType is a dropin replacement and wrapper for http.DetectContentType, 54 // which additionally detects certain Audio/Video types. 55 // 56 // Before defering to http.DetectContentType, it looks for certain MPEG sync words supported by this library. 57 func DetectContentType(data []byte) string { 58 switch { 59 // MPEG ADTS wrapped MP3 60 case bytes.Equal(data[:2], syncWordMP3): 61 return MP3 62 63 // MPEG ADTS wrapped AAC 64 case bytes.Equal(data[:2], syncWordAAC): 65 return AAC 66 67 // H264 byte stream. 68 case bytes.Equal(data[:4], syncWordNAL): 69 return H264 70 } 71 72 return http.DetectContentType(data) 73 } 74 75 func (s *Scanner) splitter(data []byte, atEOF bool) (advance int, token []byte, err error) { 76 if len(s.frameDetect) <= 0 { 77 if len(data) < 4 { 78 return 0, nil, nil 79 } 80 81 switch { 82 // MPEG ADTS wrapped MP3 83 case bytes.Equal(data[:2], syncWordMP3), bytes.Equal(data[:2], syncWordMP3nocrc): 84 s.mediaType = MP3 85 s.frameDetect = append([]byte{}, data[:2]...) 86 87 // MPEG ADTS wrapped AAC 88 case bytes.Equal(data[:2], syncWordAAC), bytes.Equal(data[:2], syncWordAACnocrc): 89 s.mediaType = AAC 90 s.frameDetect = append([]byte{}, data[:2]...) 91 92 // H264 byte stream. 93 case bytes.Equal(data[:4], syncWordNAL): 94 s.mediaType = H264 95 s.frameDetect = append([]byte{}, data[:4]...) 96 97 default: 98 return 0, nil, errors.New("unable to detect type") 99 } 100 } 101 102 advance = 1 103 104 if len(data) < 1 && atEOF { 105 return 0, nil, io.EOF 106 } 107 108 j := bytes.Index(data[advance:], s.frameDetect) 109 if j < 0 { 110 if atEOF { 111 return len(data), data, nil 112 } 113 114 // need more data 115 return 0, nil, nil 116 } 117 118 advance += j 119 return advance, data[:advance], nil 120 } 121 122 // NewScanner returns a new Scanner, which implements bufio.Scanner. 123 // The Scanner reads from the given io.Reader, and chunks the data into packet frames. 124 func NewScanner(r io.Reader) *Scanner { 125 s := &Scanner{ 126 Scanner: bufio.NewScanner(r), 127 } 128 s.Split(s.splitter) 129 return s 130 }