Skip to content

Commit 62819f5

Browse files
committed
Return packaging bytes for h265 unmarshal
Return packaging bytes for h265 unmarshal
1 parent 0c03bf4 commit 62819f5

File tree

2 files changed

+115
-7
lines changed

2 files changed

+115
-7
lines changed

codecs/h265_packet.go

Lines changed: 112 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ import (
1515
//
1616

1717
var (
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

193194
func (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

400410
func (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

537562
func (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

692775
func (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

746844
type isH265Packet interface {
747845
isH265Packet()
846+
doPackaging([]byte) []byte
748847
}
749848

750849
var (
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.

codecs/h265_packet_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package codecs
55

66
import (
7+
"errors"
78
"testing"
89

910
"github.com/stretchr/testify/assert"
@@ -688,7 +689,7 @@ func TestH265_Packet(t *testing.T) {
688689
// Valid H265FragmentationUnitPacket
689690
{
690691
Raw: []byte{0x62, 0x01, 0x93, 0xcc, 0xdd, 0xaf, 0x0d, 0x5a},
691-
ExpectedPacketType: &H265FragmentationUnitPacket{},
692+
ExpectedPacketType: &H265FragmentationPacket{},
692693
WithDONL: true,
693694
},
694695
// Valid H265AggregationPacket
@@ -763,7 +764,7 @@ func TestH265_Packet_Real(t *testing.T) {
763764
for _, cur := range tt {
764765
pck := &H265Packet{}
765766
_, err := pck.Unmarshal([]byte(cur))
766-
assert.NoError(t, err)
767+
assert.True(t, err == nil || errors.Is(err, errExpectFragmentationStartUnit))
767768
}
768769
}
769770

0 commit comments

Comments
 (0)