@@ -15,8 +15,9 @@ import (
1515//
1616
1717var (
18- errH265CorruptedPacket = errors .New ("corrupted h265 packet" )
19- errInvalidH265PacketType = errors .New ("invalid h265 packet type" )
18+ errH265CorruptedPacket = errors .New ("corrupted h265 packet" )
19+ errInvalidH265PacketType = errors .New ("invalid h265 packet type" )
20+ errExpectFragmentationStartUnit = errors .New ("expecting a fragmentation start unit" )
2021)
2122
2223//
@@ -192,6 +193,15 @@ func (p *H265SingleNALUnitPacket) Payload() []byte {
192193
193194func (p * H265SingleNALUnitPacket ) isH265Packet () {}
194195
196+ func (p * H265SingleNALUnitPacket ) doPackaging (buf []byte ) []byte {
197+ buf = append (buf , annexbNALUStartCode ... )
198+ buf = append (buf , byte (p .payloadHeader >> 8 ), byte (p .payloadHeader & 0xFF ))
199+
200+ buf = append (buf , p .payload ... )
201+
202+ return buf
203+ }
204+
195205//
196206// Aggregation Packets implementation
197207//
@@ -399,6 +409,21 @@ func (p *H265AggregationPacket) OtherUnits() []H265AggregationUnit {
399409
400410func (p * H265AggregationPacket ) isH265Packet () {}
401411
412+ func (p * H265AggregationPacket ) doPackaging (buf []byte ) []byte {
413+ if p .firstUnit == nil {
414+ return buf
415+ }
416+ buf = append (buf , annexbNALUStartCode ... )
417+ buf = append (buf , p .firstUnit .nalUnit ... )
418+
419+ for _ , unit := range p .otherUnits {
420+ buf = append (buf , annexbNALUStartCode ... )
421+ buf = append (buf , unit .nalUnit ... )
422+ }
423+
424+ return buf
425+ }
426+
402427//
403428// Fragmentation Unit implementation
404429//
@@ -536,6 +561,64 @@ func (p *H265FragmentationUnitPacket) Payload() []byte {
536561
537562func (p * H265FragmentationUnitPacket ) isH265Packet () {}
538563
564+ // H265FragmentationPacket represents a Fragmentation packet, which contains one or more Fragmentation Units.
565+ type H265FragmentationPacket struct {
566+ payloadHeader H265NALUHeader
567+ donl * uint16
568+ units []* H265FragmentationUnitPacket
569+ payload []byte
570+ }
571+
572+ func NewH265FragmentationPacket (startUnit * H265FragmentationUnitPacket ) * H265FragmentationPacket {
573+ return & H265FragmentationPacket {
574+ payloadHeader : (startUnit .payloadHeader & 0x81FF ) | (H265NALUHeader (startUnit .FuHeader ().FuType ()) << 9 ),
575+ donl : startUnit .donl ,
576+ units : []* H265FragmentationUnitPacket {startUnit },
577+ }
578+ }
579+
580+ // PayloadHeader returns the NALU header of the packet.
581+ func (p * H265FragmentationPacket ) PayloadHeader () H265NALUHeader {
582+ return p .payloadHeader
583+ }
584+
585+ // DONL returns the DONL of the packet.
586+ func (p * H265FragmentationPacket ) DONL () * uint16 {
587+ return p .donl
588+ }
589+
590+ // Payload returns the Fragmentation packet payload.
591+ func (p * H265FragmentationPacket ) Payload () []byte {
592+ return p .payload
593+ }
594+
595+ func (p * H265FragmentationPacket ) isH265Packet () {}
596+
597+ func (p * H265FragmentationPacket ) doPackaging (buf []byte ) []byte {
598+ if len (p .payload ) == 0 {
599+ return buf
600+ }
601+
602+ buf = append (buf , annexbNALUStartCode ... )
603+ buf = append (buf , byte (p .payloadHeader >> 8 ), byte (p .payloadHeader & 0xFF ))
604+ buf = append (buf , p .payload ... )
605+
606+ return buf
607+ }
608+
609+ func (p * H265FragmentationPacket ) appendUnit (unit * H265FragmentationUnitPacket ) {
610+ if len (p .payload ) > 0 {
611+ // already have end unit
612+ return
613+ }
614+ p .units = append (p .units , unit )
615+ if unit .FuHeader ().E () {
616+ for _ , u := range p .units {
617+ p .payload = append (p .payload , u .payload ... )
618+ }
619+ }
620+ }
621+
539622//
540623// PACI implementation
541624//
@@ -691,6 +774,21 @@ func (p *H265PACIPacket) Unmarshal(payload []byte) ([]byte, error) {
691774
692775func (p * H265PACIPacket ) isH265Packet () {}
693776
777+ func (p * H265PACIPacket ) doPackaging (buf []byte ) []byte {
778+ buf = append (buf , annexbNALUStartCode ... )
779+ buf = append (buf , byte (p .payloadHeader >> 8 ), byte (p .payloadHeader & 0xFF ))
780+
781+ buf = binary .BigEndian .AppendUint16 (buf , p .paciHeaderFields )
782+
783+ if len (p .phes ) > 0 {
784+ buf = append (buf , p .phes ... )
785+ }
786+
787+ buf = append (buf , p .payload ... )
788+
789+ return buf
790+ }
791+
694792//
695793// Temporal Scalability Control Information
696794//
@@ -745,10 +843,11 @@ func (h H265TSCI) RES() uint8 {
745843
746844type isH265Packet interface {
747845 isH265Packet ()
846+ doPackaging ([]byte ) []byte
748847}
749848
750849var (
751- _ isH265Packet = (* H265FragmentationUnitPacket )(nil )
850+ _ isH265Packet = (* H265FragmentationPacket )(nil )
752851 _ isH265Packet = (* H265PACIPacket )(nil )
753852 _ isH265Packet = (* H265SingleNALUnitPacket )(nil )
754853 _ isH265Packet = (* H265AggregationPacket )(nil )
@@ -802,7 +901,15 @@ func (p *H265Packet) Unmarshal(payload []byte) ([]byte, error) { // nolint:cyclo
802901 return nil , err
803902 }
804903
805- p .packet = decoded
904+ if decoded .FuHeader ().S () {
905+ p .packet = NewH265FragmentationPacket (decoded )
906+ } else {
907+ if fu , ok := p .packet .(* H265FragmentationPacket ); ! ok {
908+ return nil , errExpectFragmentationStartUnit
909+ } else {
910+ fu .appendUnit (decoded )
911+ }
912+ }
806913
807914 case payloadHeader .IsAggregationPacket ():
808915 decoded := & H265AggregationPacket {}
@@ -825,7 +932,7 @@ func (p *H265Packet) Unmarshal(payload []byte) ([]byte, error) { // nolint:cyclo
825932 p .packet = decoded
826933 }
827934
828- return nil , nil
935+ return p . packet . doPackaging ( nil ) , nil
829936}
830937
831938// Packet returns the populated packet.
0 commit comments