From 83ede2c8642da7be17444ec1d250cb6683d36c4e Mon Sep 17 00:00:00 2001 From: Juliusz Chroboczek Date: Tue, 16 Apr 2024 00:32:22 +0200 Subject: [PATCH] Make parsing of H.264 NALUs optional By default, the H264Packet.Unmarshal performs reassembly of FU-A NALUs. Not only is this ineficient, it also assumes that no packet reordering or packet loss ever happens. Make this optional. --- codecs/common.go | 10 +++++++++- codecs/h264_packet.go | 8 ++++++++ depacketizer.go | 10 ++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/codecs/common.go b/codecs/common.go index 5da8aaf6..decb0e7f 100644 --- a/codecs/common.go +++ b/codecs/common.go @@ -21,9 +21,17 @@ func (d *audioDepacketizer) IsPartitionHead(_ []byte) bool { return true } +func (d *audioDepacketizer) SetZeroAllocation(bool) {} + // videoDepacketizer is a mixin for video codec depacketizers -type videoDepacketizer struct{} +type videoDepacketizer struct { + zeroAllocation bool +} func (d *videoDepacketizer) IsPartitionTail(marker bool, _ []byte) bool { return marker } + +func (d *videoDepacketizer) SetZeroAllocation(zeroAllocation bool) { + d.zeroAllocation = zeroAllocation +} diff --git a/codecs/h264_packet.go b/codecs/h264_packet.go index 49c37da6..3021fc0f 100644 --- a/codecs/h264_packet.go +++ b/codecs/h264_packet.go @@ -208,6 +208,14 @@ func (p *H264Packet) IsDetectedFinalPacketInSequence(rtpPacketMarketBit bool) bo // Unmarshal parses the passed byte slice and stores the result in the H264Packet this method is called upon func (p *H264Packet) Unmarshal(payload []byte) ([]byte, error) { + if p.zeroAllocation { + return payload, nil + } + + return p.parseBody(payload) +} + +func (p *H264Packet) parseBody(payload []byte) ([]byte, error) { if len(payload) == 0 { return nil, fmt.Errorf("%w: %d <=0", errShortPacket, len(payload)) } diff --git a/depacketizer.go b/depacketizer.go index 0439a531..633207ef 100644 --- a/depacketizer.go +++ b/depacketizer.go @@ -5,11 +5,21 @@ package rtp // Depacketizer depacketizes a RTP payload, removing any RTP specific data from the payload type Depacketizer interface { + // Unmarshal parses the RTP payload and returns media. + // Metadata may be stored on the Depacketizer itself Unmarshal(packet []byte) ([]byte, error) + + // SetZeroAllocation enables Zero Allocation mode for the depacketizer + // By default the Depacketizers will allocate as they parse. These allocations + // are needed for Metadata and other optional values. If you don't need this information + // enabling SetZeroAllocation gives you higher performance at a reduced feature set. + SetZeroAllocation(bool) + // Checks if the packet is at the beginning of a partition. This // should return false if the result could not be determined, in // which case the caller will detect timestamp discontinuities. IsPartitionHead(payload []byte) bool + // Checks if the packet is at the end of a partition. This should // return false if the result could not be determined. IsPartitionTail(marker bool, payload []byte) bool