mirror of
https://github.com/aler9/gortsplib
synced 2025-10-05 23:26:54 +08:00
rtph264: add DecodeRTPUntilMarker()
This commit is contained in:
@@ -67,7 +67,6 @@ func main() {
|
|||||||
dec := rtph264.NewDecoder()
|
dec := rtph264.NewDecoder()
|
||||||
dtsEst := h264.NewDTSEstimator()
|
dtsEst := h264.NewDTSEstimator()
|
||||||
firstPacketWritten := false
|
firstPacketWritten := false
|
||||||
var naluBuffer [][]byte
|
|
||||||
var startPTS time.Duration
|
var startPTS time.Duration
|
||||||
|
|
||||||
// add an H264 track to the MPEG-TS muxer
|
// add an H264 track to the MPEG-TS muxer
|
||||||
@@ -94,17 +93,12 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert RTP packets into H264 NALUs
|
// decode H264 NALUs from RTP packets
|
||||||
nalus, pts, err := dec.DecodeRTP(&pkt)
|
nalus, pts, err := dec.DecodeRTPUntilMarker(&pkt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// store NALUs in a buffer until a packet with the Marker flag is received
|
|
||||||
naluBuffer = append(naluBuffer, nalus...)
|
|
||||||
|
|
||||||
// RTP marker means that all the NALUs with the same PTS have been received.
|
|
||||||
if pkt.Marker {
|
|
||||||
if !firstPacketWritten {
|
if !firstPacketWritten {
|
||||||
firstPacketWritten = true
|
firstPacketWritten = true
|
||||||
startPTS = pts
|
startPTS = pts
|
||||||
@@ -112,7 +106,7 @@ func main() {
|
|||||||
|
|
||||||
// check whether there's an IDR
|
// check whether there's an IDR
|
||||||
idrPresent := func() bool {
|
idrPresent := func() bool {
|
||||||
for _, nalu := range naluBuffer {
|
for _, nalu := range nalus {
|
||||||
typ := h264.NALUType(nalu[0] & 0x1F)
|
typ := h264.NALUType(nalu[0] & 0x1F)
|
||||||
if typ == h264.NALUTypeIDR {
|
if typ == h264.NALUTypeIDR {
|
||||||
return true
|
return true
|
||||||
@@ -126,7 +120,7 @@ func main() {
|
|||||||
{byte(h264.NALUTypeAccessUnitDelimiter), 240},
|
{byte(h264.NALUTypeAccessUnitDelimiter), 240},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, nalu := range naluBuffer {
|
for _, nalu := range nalus {
|
||||||
// remove existing SPS, PPS, AUD
|
// remove existing SPS, PPS, AUD
|
||||||
typ := h264.NALUType(nalu[0] & 0x1F)
|
typ := h264.NALUType(nalu[0] & 0x1F)
|
||||||
switch typ {
|
switch typ {
|
||||||
@@ -143,8 +137,6 @@ func main() {
|
|||||||
filteredNALUs = append(filteredNALUs, nalu)
|
filteredNALUs = append(filteredNALUs, nalu)
|
||||||
}
|
}
|
||||||
|
|
||||||
naluBuffer = nil
|
|
||||||
|
|
||||||
// encode into Annex-B
|
// encode into Annex-B
|
||||||
enc, err := h264.EncodeAnnexB(filteredNALUs)
|
enc, err := h264.EncodeAnnexB(filteredNALUs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -178,7 +170,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("wrote ts packet")
|
fmt.Println("wrote ts packet")
|
||||||
}
|
|
||||||
})
|
})
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@@ -42,7 +42,10 @@ type Decoder struct {
|
|||||||
// for Decode()
|
// for Decode()
|
||||||
startingPacketReceived bool
|
startingPacketReceived bool
|
||||||
isDecodingFragmented bool
|
isDecodingFragmented bool
|
||||||
fragmentedBuf []byte
|
fragmentedBuffer []byte
|
||||||
|
|
||||||
|
// for DecodeUntilMarker()
|
||||||
|
naluBuffer [][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDecoder allocates a Decoder.
|
// NewDecoder allocates a Decoder.
|
||||||
@@ -67,7 +70,7 @@ func (d *Decoder) Decode(byts []byte) ([][]byte, time.Duration, error) {
|
|||||||
return d.DecodeRTP(&pkt)
|
return d.DecodeRTP(&pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeRTP decodes NALUs from a rtp.Packet.
|
// DecodeRTP decodes NALUs from a RTP/H264 packet.
|
||||||
func (d *Decoder) DecodeRTP(pkt *rtp.Packet) ([][]byte, time.Duration, error) {
|
func (d *Decoder) DecodeRTP(pkt *rtp.Packet) ([][]byte, time.Duration, error) {
|
||||||
if !d.isDecodingFragmented {
|
if !d.isDecodingFragmented {
|
||||||
if !d.initialTsSet {
|
if !d.initialTsSet {
|
||||||
@@ -129,7 +132,7 @@ func (d *Decoder) DecodeRTP(pkt *rtp.Packet) ([][]byte, time.Duration, error) {
|
|||||||
|
|
||||||
nri := (pkt.Payload[0] >> 5) & 0x03
|
nri := (pkt.Payload[0] >> 5) & 0x03
|
||||||
typ := pkt.Payload[1] & 0x1F
|
typ := pkt.Payload[1] & 0x1F
|
||||||
d.fragmentedBuf = append([]byte{(nri << 5) | typ}, pkt.Payload[2:]...)
|
d.fragmentedBuffer = append([]byte{(nri << 5) | typ}, pkt.Payload[2:]...)
|
||||||
|
|
||||||
d.isDecodingFragmented = true
|
d.isDecodingFragmented = true
|
||||||
d.startingPacketReceived = true
|
d.startingPacketReceived = true
|
||||||
@@ -165,7 +168,7 @@ func (d *Decoder) DecodeRTP(pkt *rtp.Packet) ([][]byte, time.Duration, error) {
|
|||||||
return nil, 0, fmt.Errorf("invalid FU-A packet (decoded two starting packets in a row)")
|
return nil, 0, fmt.Errorf("invalid FU-A packet (decoded two starting packets in a row)")
|
||||||
}
|
}
|
||||||
|
|
||||||
d.fragmentedBuf = append(d.fragmentedBuf, pkt.Payload[2:]...)
|
d.fragmentedBuffer = append(d.fragmentedBuffer, pkt.Payload[2:]...)
|
||||||
|
|
||||||
if end != 1 {
|
if end != 1 {
|
||||||
return nil, 0, ErrMorePacketsNeeded
|
return nil, 0, ErrMorePacketsNeeded
|
||||||
@@ -173,7 +176,28 @@ func (d *Decoder) DecodeRTP(pkt *rtp.Packet) ([][]byte, time.Duration, error) {
|
|||||||
|
|
||||||
d.isDecodingFragmented = false
|
d.isDecodingFragmented = false
|
||||||
d.startingPacketReceived = true
|
d.startingPacketReceived = true
|
||||||
return [][]byte{d.fragmentedBuf}, d.decodeTimestamp(pkt.Timestamp), nil
|
return [][]byte{d.fragmentedBuffer}, d.decodeTimestamp(pkt.Timestamp), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeRTPUntilMarker decodes NALUs from a RTP/H264 packet and puts them in a buffer.
|
||||||
|
// When a packet has the marker flag (meaning that all the NALUs with the same PTS have
|
||||||
|
// been received), the buffer is returned.
|
||||||
|
func (d *Decoder) DecodeRTPUntilMarker(pkt *rtp.Packet) ([][]byte, time.Duration, error) {
|
||||||
|
nalus, pts, err := d.DecodeRTP(pkt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.naluBuffer = append(d.naluBuffer, nalus...)
|
||||||
|
|
||||||
|
if !pkt.Marker {
|
||||||
|
return nil, 0, ErrMorePacketsNeeded
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := d.naluBuffer
|
||||||
|
d.naluBuffer = d.naluBuffer[:0]
|
||||||
|
|
||||||
|
return ret, pts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadSPSPPS reads RTP/H264 packets from a reader until SPS and PPS are
|
// ReadSPSPPS reads RTP/H264 packets from a reader until SPS and PPS are
|
||||||
|
Reference in New Issue
Block a user