Skip to content

Commit

Permalink
Move AV1 Frame to new frame pkg
Browse files Browse the repository at this point in the history
Codecs only contains RTP Payload processing
  • Loading branch information
Sean-Der committed Jun 14, 2023
1 parent e57513f commit 5ac507d
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 19 deletions.
1 change: 1 addition & 0 deletions AUTHORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Michael Uti <utimichael9@gmail.com>
Raphael Derosso Pereira <raphaelpereira@gmail.com>
Rob Lofthouse <ri.lofthouse@gmail.com>
Robin Raymond <robin@goheadroom.com>
Sean DuBois <duboisea@twitch.tv>
Sean DuBois <seaduboi@amazon.com>
Sean DuBois <sean@siobud.com>
Simone Gotti <simone.gotti@gmail.com>
Expand Down
17 changes: 10 additions & 7 deletions codecs/av1_frame.go → pkg/frame/av1.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package codecs
// Package frame provides code to construct complete media frames from packetized media
package frame

// AV1Frame represents a collection of OBUs given a stream of AV1 Packets.
import "github.com/pion/rtp/codecs"

// AV1 represents a collection of OBUs given a stream of AV1 Packets.
// Each AV1 RTP Packet is a collection of OBU Elements. Each OBU Element may be a full OBU, or just a fragment of one.
// AV1Frame provides the tools to construct a collection of OBUs from a collection of OBU Elements. This structure
// AV1 provides the tools to construct a collection of OBUs from a collection of OBU Elements. This structure
// contains an internal cache and should be used for the entire RTP Stream.
type AV1Frame struct {
type AV1 struct {
// Buffer for fragmented OBU. If ReadFrames is called on a RTP Packet
// that doesn't contain a fully formed OBU
obuBuffer []byte
}

func (f *AV1Frame) pushOBUElement(isFirstOBUFragment *bool, obuElement []byte, obuList [][]byte) [][]byte {
func (f *AV1) pushOBUElement(isFirstOBUFragment *bool, obuElement []byte, obuList [][]byte) [][]byte {
if *isFirstOBUFragment {
*isFirstOBUFragment = false
// Discard pushed because we don't have a fragment to combine it with
Expand All @@ -23,8 +26,8 @@ func (f *AV1Frame) pushOBUElement(isFirstOBUFragment *bool, obuElement []byte, o
return append(obuList, obuElement)
}

// ReadFrames processes the AV1Packet and returns fully constructed frames
func (f *AV1Frame) ReadFrames(pkt *AV1Packet) ([][]byte, error) {
// ReadFrames processes the codecs.AV1Packet and returns fully constructed frames
func (f *AV1) ReadFrames(pkt *codecs.AV1Packet) ([][]byte, error) {
OBUs := [][]byte{}
isFirstOBUFragment := pkt.Z

Expand Down
26 changes: 14 additions & 12 deletions codecs/av1_frame_test.go → pkg/frame/av1_test.go
Original file line number Diff line number Diff line change
@@ -1,48 +1,50 @@
package codecs
package frame

import (
"reflect"
"testing"

"github.com/pion/rtp/codecs"
)

// First is Fragment (and no buffer)
// Self contained OBU
// OBU spread across 3 packets
func TestAV1_ReadFrames(t *testing.T) {
// First is Fragment of OBU, but no OBU Elements is cached
f := &AV1Frame{}
frames, err := f.ReadFrames(&AV1Packet{Z: true, OBUElements: [][]byte{{0x01}}})
f := &AV1{}
frames, err := f.ReadFrames(&codecs.AV1Packet{Z: true, OBUElements: [][]byte{{0x01}}})
if err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(frames, [][]byte{}) {
t.Fatalf("No frames should be generated, %v", frames)
}

f = &AV1Frame{}
frames, err = f.ReadFrames(&AV1Packet{OBUElements: [][]byte{{0x01}}})
f = &AV1{}
frames, err = f.ReadFrames(&codecs.AV1Packet{OBUElements: [][]byte{{0x01}}})
if err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(frames, [][]byte{{0x01}}) {
t.Fatalf("One frame should be generated, %v", frames)
}

f = &AV1Frame{}
frames, err = f.ReadFrames(&AV1Packet{Y: true, OBUElements: [][]byte{{0x00}}})
f = &AV1{}
frames, err = f.ReadFrames(&codecs.AV1Packet{Y: true, OBUElements: [][]byte{{0x00}}})
if err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(frames, [][]byte{}) {
t.Fatalf("No frames should be generated, %v", frames)
}

frames, err = f.ReadFrames(&AV1Packet{Z: true, OBUElements: [][]byte{{0x01}}})
frames, err = f.ReadFrames(&codecs.AV1Packet{Z: true, OBUElements: [][]byte{{0x01}}})
if err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(frames, [][]byte{{0x00, 0x01}}) {
t.Fatalf("One frame should be generated, %v", frames)
}
}

// Marshal some AV1 Frames to RTP, assert that AV1Frame can get them back in the original format
// Marshal some AV1 Frames to RTP, assert that AV1 can get them back in the original format
func TestAV1_ReadFrames_E2E(t *testing.T) {
const mtu = 1500
frames := [][]byte{
Expand All @@ -62,11 +64,11 @@ func TestAV1_ReadFrames_E2E(t *testing.T) {
frames[len(frames)-1] = append(frames[len(frames)-1], []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A}...)
}

payloader := &AV1Payloader{}
f := &AV1Frame{}
payloader := &codecs.AV1Payloader{}
f := &AV1{}
for _, originalFrame := range frames {
for _, payload := range payloader.Payload(mtu, originalFrame) {
rtpPacket := &AV1Packet{}
rtpPacket := &codecs.AV1Packet{}
if _, err := rtpPacket.Unmarshal(payload); err != nil {
t.Fatal(err)
}
Expand Down

0 comments on commit 5ac507d

Please sign in to comment.