rewrite handleH264Payload, support BuggyCameraHasAnnexbH264Packet

This commit is contained in:
nareix 2016-06-15 10:28:34 +08:00
parent e6b1c2561e
commit b0ccdad10b

173
client.go
View File

@ -531,16 +531,7 @@ func (self *Stream) makeCodecData() (err error) {
case av.H264: case av.H264:
for _, nalu := range media.SpropParameterSets { for _, nalu := range media.SpropParameterSets {
if len(nalu) > 0 { if len(nalu) > 0 {
switch nalu[0] & 0x1f { self.handleH264Payload(0, nalu)
case 7:
if len(self.sps) == 0 {
self.sps = nalu
}
case 8:
if len(self.pps) == 0 {
self.pps = nalu
}
}
} }
} }
@ -548,16 +539,7 @@ func (self *Stream) makeCodecData() (err error) {
if nalus, ok := h264parser.SplitNALUs(media.Config); ok { if nalus, ok := h264parser.SplitNALUs(media.Config); ok {
for _, nalu := range nalus { for _, nalu := range nalus {
if len(nalu) > 0 { if len(nalu) > 0 {
switch nalu[0] & 0x1f { self.handleH264Payload(0, nalu)
case 7:
if len(self.sps) == 0 {
self.sps = nalu
}
case 8:
if len(self.pps) == 0 {
self.pps = nalu
}
}
} }
} }
} }
@ -600,7 +582,30 @@ func (self *Stream) makeCodecData() (err error) {
return return
} }
func (self *Stream) handleH264Payload(naluType byte, timestamp uint32, packet []byte) (err error) { func (self *Stream) handleBuggyCameraHasAnnexbH264Packet(timestamp uint32, packet []byte) (isBuggy bool, err error) {
if len(packet) >= 4 && packet[0] == 0 && packet[1] == 0 && packet[2] == 0 && packet[3] == 1 {
isBuggy = true
if nalus, ok := h264parser.SplitNALUs(packet); ok {
for _, nalu := range nalus {
if len(nalu) > 0 {
if err = self.handleH264Payload(timestamp, nalu); err != nil {
return
}
}
}
}
}
return
}
func (self *Stream) handleH264Payload(timestamp uint32, packet []byte) (err error) {
var isBuggy bool
if isBuggy, err = self.handleBuggyCameraHasAnnexbH264Packet(timestamp, packet); isBuggy {
return
}
naluType := packet[0]&0x1f
/* /*
Table 7-1 NAL unit type codes Table 7-1 NAL unit type codes
1 Coded slice of a non-IDR picture 1 Coded slice of a non-IDR picture
@ -608,68 +613,6 @@ func (self *Stream) handleH264Payload(naluType byte, timestamp uint32, packet []
6 Supplemental enhancement information (SEI) 6 Supplemental enhancement information (SEI)
7 Sequence parameter set 7 Sequence parameter set
8 Picture parameter set 8 Picture parameter set
*/
switch naluType {
case 6: // SEI ignored
case 7: // sps
if self.client != nil && self.client.DebugRtp {
fmt.Println("rtsp: got sps")
}
if bytes.Compare(self.sps, packet) != 0 {
self.spsChanged = true
self.sps = packet
if self.client != nil && self.client.DebugRtp {
fmt.Println("rtsp: sps changed")
}
}
case 8: // pps
if self.client != nil && self.client.DebugRtp {
fmt.Println("rtsp: got pps")
}
if bytes.Compare(self.pps, packet) != 0 {
self.ppsChanged = true
self.pps = packet
if self.client != nil && self.client.DebugRtp {
fmt.Println("rtsp: pps changed")
}
}
default:
if naluType == 5 {
self.pkt.IsKeyFrame = true
}
self.gotpkt = true
self.pkt.Data = packet
self.timestamp = timestamp
}
return
}
func (self *Stream) handlePacket(timestamp uint32, packet []byte) (err error) {
if self.isCodecDataChange() {
err = ErrCodecDataChange
return
}
switch self.Type() {
case av.H264:
/*
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
*/
naluType := packet[0] & 0x1f
/*
NAL Unit Packet Packet Type Name Section
Type Type
-------------------------------------------------------------
0 reserved -
1-23 NAL unit Single NAL unit packet 5.6 1-23 NAL unit Single NAL unit packet 5.6
24 STAP-A Single-time aggregation packet 5.7.1 24 STAP-A Single-time aggregation packet 5.7.1
25 STAP-B Single-time aggregation packet 5.7.1 25 STAP-B Single-time aggregation packet 5.7.1
@ -681,12 +624,49 @@ func (self *Stream) handlePacket(timestamp uint32, packet []byte) (err error) {
*/ */
switch { switch {
default:
case naluType >= 1 && naluType <= 23: if naluType >= 1 && naluType <= 23 {
if err = self.handleH264Payload(naluType, timestamp, packet); err != nil { if naluType == 5 {
self.pkt.IsKeyFrame = true
}
self.gotpkt = true
self.pkt.Data = packet
self.timestamp = timestamp
} else {
err = fmt.Errorf("rtsp: unsupported H264 naluType=%d", naluType)
return return
} }
case naluType == 6: // SEI ignored
case naluType == 7: // sps
if self.client != nil && self.client.DebugRtp {
fmt.Println("rtsp: got sps")
}
if len(self.sps) == 0 {
self.sps = packet
} else if bytes.Compare(self.sps, packet) != 0 {
self.spsChanged = true
self.sps = packet
if self.client != nil && self.client.DebugRtp {
fmt.Println("rtsp: sps changed")
}
}
case naluType == 8: // pps
if self.client != nil && self.client.DebugRtp {
fmt.Println("rtsp: got pps")
}
if len(self.pps) == 0 {
self.pps = packet
} else if bytes.Compare(self.pps, packet) != 0 {
self.ppsChanged = true
self.pps = packet
if self.client != nil && self.client.DebugRtp {
fmt.Println("rtsp: pps changed")
}
}
case naluType == 28: // FU-A case naluType == 28: // FU-A
/* /*
0 1 2 3 0 1 2 3
@ -740,13 +720,12 @@ func (self *Stream) handlePacket(timestamp uint32, packet []byte) (err error) {
fuHeader := packet[1] fuHeader := packet[1]
isStart := fuHeader&0x80 != 0 isStart := fuHeader&0x80 != 0
isEnd := fuHeader&0x40 != 0 isEnd := fuHeader&0x40 != 0
naluType := fuHeader & 0x1f
if isStart { if isStart {
self.fuBuffer = []byte{fuIndicator&0xe0 | fuHeader&0x1f} self.fuBuffer = []byte{fuIndicator&0xe0 | fuHeader&0x1f}
} }
self.fuBuffer = append(self.fuBuffer, packet[2:]...) self.fuBuffer = append(self.fuBuffer, packet[2:]...)
if isEnd { if isEnd {
if err = self.handleH264Payload(naluType, timestamp, self.fuBuffer); err != nil { if err = self.handleH264Payload(timestamp, self.fuBuffer); err != nil {
return return
} }
} }
@ -754,9 +733,23 @@ func (self *Stream) handlePacket(timestamp uint32, packet []byte) (err error) {
case naluType == 24: case naluType == 24:
err = fmt.Errorf("rtsp: unsupported H264 STAP-A") err = fmt.Errorf("rtsp: unsupported H264 STAP-A")
return return
}
default: return
err = fmt.Errorf("rtsp: unsupported H264 naluType=%d", naluType) }
func (self *Stream) handlePacket(timestamp uint32, packet []byte) (err error) {
if self.isCodecDataChange() {
err = ErrCodecDataChange
return
}
switch self.Type() {
case av.H264:
if self.client != nil && self.client.DebugRtp {
fmt.Printf("rtsp: h264 data=%x\n", packet)
}
if err = self.handleH264Payload(timestamp, packet); err != nil {
return return
} }