diff --git a/aacparser/parser.go b/aacparser/parser.go index db8dc64..0a3a1f4 100644 --- a/aacparser/parser.go +++ b/aacparser/parser.go @@ -112,12 +112,14 @@ func MakeADTSHeader(config MPEG4AudioConfig, samples int, payloadLength int) (he return } -func ExtractADTSFrames(frames []byte) (config MPEG4AudioConfig, payload []byte, samples int, err error) { +func ExtractADTSFrames(frames []byte) (config MPEG4AudioConfig, payload [][]byte, samples int, err error) { for len(frames) > 0 { var n, framelen int - if config, payload, n, framelen, err = ReadADTSFrame(frames); err != nil { + var _payload []byte + if config, _payload, n, framelen, err = ReadADTSFrame(frames); err != nil { return } + payload = append(payload, _payload) frames = frames[framelen:] samples += n } diff --git a/h264parser/parser.go b/h264parser/parser.go index 17b5745..5d05769 100644 --- a/h264parser/parser.go +++ b/h264parser/parser.go @@ -301,9 +301,7 @@ type SPSInfo struct { } func ParseSPS(data []byte) (self SPSInfo, err error) { - r := &bits.GolombBitReader{ - R: bytes.NewReader(data), - } + r := &bits.GolombBitReader{R: bytes.NewReader(data)} if _, err = r.ReadBits(8); err != nil { return @@ -662,3 +660,69 @@ func ParseAVCDecoderConfRecord(config []byte) (self AVCDecoderConfRecord, err er return } +type SliceType uint + +func (self SliceType) String() string { + switch self { + case P: + return "P" + case B: + return "B" + case I: + return "I" + } + return "" +} + +const ( + P = iota+1 + B + I +) + +func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) { + + if len(packet) <= 1 { + err = fmt.Errorf("packet too short to parse slice header") + return + } + + nal_unit_type := packet[0]&0x1f + switch nal_unit_type { + case 1,2,5,19: + // slice_layer_without_partitioning_rbsp + // slice_data_partition_a_layer_rbsp + + default: + err = fmt.Errorf("nal_unit_type=%d has no slice header", nal_unit_type) + return + } + + r := &bits.GolombBitReader{R: bytes.NewReader(packet[1:])} + + // first_mb_in_slice + if _, err = r.ReadExponentialGolombCode(); err != nil { + return + } + + // slice_type + var u uint + if u, err = r.ReadExponentialGolombCode(); err != nil { + return + } + + switch u { + case 0,3,5,8: + sliceType = P + case 1,6: + sliceType = B + case 2,4,7,9: + sliceType = I + default: + err = fmt.Errorf("slice_type=%d invalid", u) + return + } + + return +} +