Commit 4f7be196 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Implement pid and mark rewriting for VP9, fix VP9 sync bits.

The sync bits were incorrect.  In addition, we need to set the
marker at the new end of the frame when doing spatial decimation.
parent 56226a29
...@@ -230,12 +230,15 @@ func KeyframeDimensions(codec string, packet *rtp.Packet) (uint32, uint32) { ...@@ -230,12 +230,15 @@ func KeyframeDimensions(codec string, packet *rtp.Packet) (uint32, uint32) {
type Flags struct { type Flags struct {
Seqno uint16 Seqno uint16
Marker bool
Start bool Start bool
Pid uint16 // only if it needs rewriting End bool
Keyframe bool
Pid uint16
Tid uint8 Tid uint8
Sid uint8 Sid uint8
TidUpSync bool TidUpSync bool
SidSync bool SidUpSync bool
SidNonReference bool SidNonReference bool
Discardable bool Discardable bool
} }
...@@ -248,6 +251,7 @@ func PacketFlags(codec string, buf []byte) (Flags, error) { ...@@ -248,6 +251,7 @@ func PacketFlags(codec string, buf []byte) (Flags, error) {
var flags Flags var flags Flags
flags.Seqno = (uint16(buf[2]) << 8) | uint16(buf[3]) flags.Seqno = (uint16(buf[2]) << 8) | uint16(buf[3])
flags.Marker = (buf[1] & 0x80) != 0
if strings.EqualFold(codec, "video/vp8") { if strings.EqualFold(codec, "video/vp8") {
var packet rtp.Packet var packet rtp.Packet
...@@ -261,10 +265,13 @@ func PacketFlags(codec string, buf []byte) (Flags, error) { ...@@ -261,10 +265,13 @@ func PacketFlags(codec string, buf []byte) (Flags, error) {
return flags, err return flags, err
} }
flags.Start = vp8.S == 1 && vp8.PID == 0 flags.Start = vp8.S != 0 && vp8.PID == 0
flags.End = packet.Marker
flags.Keyframe = vp8.S != 0 && (vp8.Payload[0]&0x1) == 0
flags.Pid = vp8.PictureID flags.Pid = vp8.PictureID
flags.Tid = vp8.TID flags.Tid = vp8.TID
flags.TidUpSync = vp8.Y == 1 flags.TidUpSync = flags.Keyframe || vp8.Y == 1
flags.SidUpSync = flags.Keyframe
flags.Discardable = vp8.N == 1 flags.Discardable = vp8.N == 1
return flags, nil return flags, nil
} else if strings.EqualFold(codec, "video/vp9") { } else if strings.EqualFold(codec, "video/vp9") {
...@@ -279,22 +286,35 @@ func PacketFlags(codec string, buf []byte) (Flags, error) { ...@@ -279,22 +286,35 @@ func PacketFlags(codec string, buf []byte) (Flags, error) {
return flags, err return flags, err
} }
flags.Start = vp9.B flags.Start = vp9.B
flags.End = vp9.E
if (vp9.Payload[0] & 0xc0) == 0x80 {
profile := (vp9.Payload[0] >> 4) & 0x3
if profile != 3 {
flags.Keyframe = (vp9.Payload[0] & 0xC) == 0
} else {
flags.Keyframe = (vp9.Payload[0] & 0x6) == 0
}
}
flags.Pid = vp9.PictureID
flags.Tid = vp9.TID flags.Tid = vp9.TID
flags.Sid = vp9.SID flags.Sid = vp9.SID
flags.TidUpSync = vp9.U flags.TidUpSync = flags.Keyframe || vp9.U
flags.SidSync = vp9.P flags.SidUpSync = flags.Keyframe || !vp9.P
// not yet in pion/rtp
flags.SidNonReference = (packet.Payload[0] & 0x01) != 0 flags.SidNonReference = (packet.Payload[0] & 0x01) != 0
return flags, nil return flags, nil
} }
return flags, nil return flags, nil
} }
func RewritePacket(codec string, data []byte, seqno uint16, delta uint16) error { func RewritePacket(codec string, data []byte, setMarker bool, seqno uint16, delta uint16) error {
if len(data) < 12 { if len(data) < 12 {
return errTruncated return errTruncated
} }
if(setMarker) {
data[1] |= 0x80
}
data[2] = uint8(seqno >> 8) data[2] = uint8(seqno >> 8)
data[3] = uint8(seqno) data[3] = uint8(seqno)
if delta == 0 { if delta == 0 {
...@@ -335,6 +355,23 @@ func RewritePacket(codec string, data []byte, seqno uint16, delta uint16) error ...@@ -335,6 +355,23 @@ func RewritePacket(codec string, data []byte, seqno uint16, delta uint16) error
data[offset+2] = (data[offset+2] + uint8(delta)) & 0x7F data[offset+2] = (data[offset+2] + uint8(delta)) & 0x7F
} }
return nil return nil
} else if strings.EqualFold(codec, "video/vp9") {
i := (data[offset] & 0x80) != 0
if !i {
return nil
}
m := (data[offset+1] & 0x80) != 0
if m {
pid := (uint16(data[offset+1]&0x7F) << 8) |
uint16(data[offset+2])
pid = (pid + delta) & 0x7FFF
data[offset+1] = 0x80 | byte((pid>>8)&0x7F)
data[offset+2] = byte(pid & 0xFF)
} else {
data[offset+1] = (data[offset+1] + uint8(delta)) & 0x7F
}
return nil
} }
return errUnsupportedCodec return errUnsupportedCodec
} }
...@@ -138,7 +138,7 @@ var vp8 = []byte{ ...@@ -138,7 +138,7 @@ var vp8 = []byte{
0, 0, 0, 0, 0, 0, 0, 0,
} }
func TestPacketFlags(t *testing.T) { func TestPacketFlagsVP8(t *testing.T) {
buf := append([]byte{}, vp8...) buf := append([]byte{}, vp8...)
flags, err := PacketFlags("video/vp8", buf) flags, err := PacketFlags("video/vp8", buf)
if flags.Seqno != 42 || !flags.Start || flags.Pid != 57 || if flags.Seqno != 42 || !flags.Start || flags.Pid != 57 ||
...@@ -151,17 +151,56 @@ func TestPacketFlags(t *testing.T) { ...@@ -151,17 +151,56 @@ func TestPacketFlags(t *testing.T) {
} }
} }
func TestRewrite(t *testing.T) { func TestRewriteVP8(t *testing.T) {
for i := uint16(0); i < 0x7fff; i++ { for i := uint16(0); i < 0x7fff; i++ {
buf := append([]byte{}, vp8...) buf := append([]byte{}, vp8...)
err := RewritePacket("video/vp8", buf, i, i) err := RewritePacket("video/vp8", buf, true, i, i)
if err != nil { if err != nil {
t.Errorf("rewrite: %v", err) t.Errorf("rewrite: %v", err)
continue continue
} }
flags, err := PacketFlags("video/vp8", buf) flags, err := PacketFlags("video/vp8", buf)
if err != nil || flags.Seqno != i || if err != nil || flags.Seqno != i ||
flags.Pid != (57+i)&0x7FFF { flags.Pid != (57+i)&0x7FFF || !flags.Marker {
t.Errorf("Expected %v %v, got %v %v (%v)",
i, (57+i)&0x7FFF,
flags.Seqno, flags.Pid, err)
}
}
}
var vp9 = []byte{
0x80, 0, 0, 42,
0, 0, 0, 0,
0, 0, 0, 0,
0x88, 0x80, 57, 0,
}
func TestPacketFlagsVP9(t *testing.T) {
buf := append([]byte{}, vp9...)
flags, err := PacketFlags("video/vp9", buf)
if flags.Seqno != 42 || !flags.Start || flags.Pid != 57 ||
flags.Sid != 0 || flags.Tid != 0 ||
flags.TidUpSync || flags.Discardable || err != nil {
t.Errorf("Got %v, %v, %v, %v, %v, %v (%v)",
flags.Seqno, flags.Start, flags.Pid, flags.Sid,
flags.TidUpSync, flags.Discardable, err,
)
}
}
func TestRewriteVP9(t *testing.T) {
for i := uint16(0); i < 0x7fff; i++ {
buf := append([]byte{}, vp9...)
err := RewritePacket("video/vp9", buf, true, i, i)
if err != nil {
t.Errorf("rewrite: %v", err)
continue
}
flags, err := PacketFlags("video/vp9", buf)
if err != nil || flags.Seqno != i ||
flags.Pid != (57+i)&0x7FFF || !flags.Marker {
t.Errorf("Expected %v %v, got %v %v (%v)", t.Errorf("Expected %v %v, got %v %v (%v)",
i, (57+i)&0x7FFF, i, (57+i)&0x7FFF,
flags.Seqno, flags.Pid, err) flags.Seqno, flags.Pid, err)
......
...@@ -248,9 +248,23 @@ func (down *rtpDownTrack) Write(buf []byte) (int, error) { ...@@ -248,9 +248,23 @@ func (down *rtpDownTrack) Write(buf []byte) (int, error) {
} }
if flags.Start && (layer.sid != layer.wantedSid) { if flags.Start && (layer.sid != layer.wantedSid) {
if flags.SidSync { if layer.wantedSid < layer.sid {
layer.sid = layer.wantedSid if flags.Keyframe {
down.setLayerInfo(layer) layer.sid = layer.wantedSid
down.setLayerInfo(layer)
} else {
down.remote.RequestKeyframe()
}
} else if layer.wantedSid > layer.sid {
if flags.Keyframe {
layer.sid = layer.wantedSid
down.setLayerInfo(layer)
} else if flags.SidUpSync {
layer.sid = layer.sid + 1
down.setLayerInfo(layer)
} else {
down.remote.RequestKeyframe()
}
} }
} }
...@@ -267,7 +281,9 @@ func (down *rtpDownTrack) Write(buf []byte) (int, error) { ...@@ -267,7 +281,9 @@ func (down *rtpDownTrack) Write(buf []byte) (int, error) {
return 0, nil return 0, nil
} }
if newseqno == flags.Seqno && piddelta == 0 { setMarker := flags.Sid == layer.sid && flags.End && !flags.Marker
if !setMarker && newseqno == flags.Seqno && piddelta == 0 {
return down.write(buf) return down.write(buf)
} }
...@@ -276,7 +292,7 @@ func (down *rtpDownTrack) Write(buf []byte) (int, error) { ...@@ -276,7 +292,7 @@ func (down *rtpDownTrack) Write(buf []byte) (int, error) {
buf2 := ibuf2.([]byte) buf2 := ibuf2.([]byte)
n := copy(buf2, buf) n := copy(buf2, buf)
err = codecs.RewritePacket(codec, buf2[:n], newseqno, piddelta) err = codecs.RewritePacket(codec, buf2[:n], setMarker, newseqno, piddelta)
if err != nil { if err != nil {
return 0, err return 0, err
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment