move unrolled mime type check for broader use (#3326)

* move unrolled mime type check for broader use

* Use in IsSvcCodec and make MimeType exported

* test

* tidy branches

* tidy

---------

Co-authored-by: Paul Wells <paulwe@gmail.com>
This commit is contained in:
Raja SubramanianandPaul Wells authored and GitHub committed 2025-01-13 10:24:03 +05:30
1 parent 53d300ba71
commit 7c58fdf329
3 files changed
+175 -9

No files matched your search

+8 -9
View File
@@ -785,8 +785,9 @@ func (b *Buffer) getExtPacket(rtpPacket *rtp.Packet, arrivalTime int64, flowStat
// DD-TODO : notify active decode target change if changed.
}
}
switch b.mime {
case "video/vp8":
switch utils.MatchMimeType(b.mime) {
case utils.MimeTypeVP8:
vp8Packet := VP8{}
if err := vp8Packet.Unmarshal(rtpPacket.Payload); err != nil {
b.logger.Warnw("could not unmarshal VP8 packet", err)
@@ -802,7 +803,7 @@ func (b *Buffer) getExtPacket(rtpPacket *rtp.Packet, arrivalTime int64, flowStat
ep.Payload = vp8Packet
ep.Spatial = InvalidLayerSpatial // vp8 don't have spatial scalability, reset to invalid
case "video/vp9":
case utils.MimeTypeVP9:
if ep.DependencyDescriptor == nil {
var vp9Packet codecs.VP9Packet
_, err := vp9Packet.Unmarshal(rtpPacket.Payload)
@@ -818,11 +819,11 @@ func (b *Buffer) getExtPacket(rtpPacket *rtp.Packet, arrivalTime int64, flowStat
}
ep.KeyFrame = IsVP9KeyFrame(rtpPacket.Payload)
case "video/h264":
case utils.MimeTypeH264:
ep.KeyFrame = IsH264KeyFrame(rtpPacket.Payload)
ep.Spatial = InvalidLayerSpatial // h.264 don't have spatial scalability, reset to invalid
case "video/av1":
case utils.MimeTypeAV1:
ep.KeyFrame = IsAV1KeyFrame(rtpPacket.Payload)
}
@@ -1122,10 +1123,8 @@ func (b *Buffer) GetTemporalLayerFpsForSpatial(layer int32) []float32 {
// SVC-TODO: May only need to differentiate between simulcast and non-simulcast
// SVC-TODO: i. e. may be possible to treat single layer as SVC to get proper/intended functionality.
func IsSvcCodec(mime string) bool {
switch strings.ToLower(mime) {
case "video/av1":
fallthrough
case "video/vp9":
switch utils.MatchMimeType(mime) {
case utils.MimeTypeAV1, utils.MimeTypeVP9:
return true
}
return false
+102
View File
@@ -0,0 +1,102 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package utils
type MimeType int
const (
MimeTypeUnknown MimeType = iota
MimeTypeVP8
MimeTypeVP9
MimeTypeH264
MimeTypeAV1
)
func MatchMimeType(mimeType string) MimeType {
switch len(mimeType) {
case 9:
switch mimeType[0] {
case 'v', 'V':
switch mimeType[1] {
case 'i', 'I':
switch mimeType[2] {
case 'd', 'D':
switch mimeType[3] {
case 'e', 'E':
switch mimeType[4] {
case 'o', 'O':
switch mimeType[5] {
case '/':
switch mimeType[6] {
case 'v', 'V':
switch mimeType[7] {
case 'p', 'P':
switch mimeType[8] {
case '8':
return MimeTypeVP8
case '9':
return MimeTypeVP9
}
}
case 'a', 'A':
switch mimeType[7] {
case 'v', 'V':
switch mimeType[8] {
case '1':
return MimeTypeAV1
}
}
}
}
}
}
}
}
}
case 10:
switch mimeType[0] {
case 'v', 'V':
switch mimeType[1] {
case 'i', 'I':
switch mimeType[2] {
case 'd', 'D':
switch mimeType[3] {
case 'e', 'E':
switch mimeType[4] {
case 'o', 'O':
switch mimeType[5] {
case '/':
switch mimeType[6] {
case 'h', 'H':
switch mimeType[7] {
case '2':
switch mimeType[8] {
case '6':
switch mimeType[9] {
case '4':
return MimeTypeH264
}
}
}
}
}
}
}
}
}
}
}
return MimeTypeUnknown
}
+65
View File
@@ -0,0 +1,65 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package utils
import (
"strings"
"testing"
"github.com/stretchr/testify/require"
)
func toLowerSwitch(mimeType string) MimeType {
switch strings.ToLower(mimeType) {
case "video/vp8":
return MimeTypeVP8
case "video/vp9":
return MimeTypeVP9
case "video/h264":
return MimeTypeH264
case "video/av1":
return MimeTypeAV1
default:
return MimeTypeUnknown
}
}
func TestMimeTypeMatch(t *testing.T) {
require.Equal(t, MimeTypeVP8, MatchMimeType("VIDEO/VP8"), "VIDEO/VP8")
require.Equal(t, MimeTypeVP9, MatchMimeType("VIDEO/VP9"), "VIDEO/VP9")
require.Equal(t, MimeTypeH264, MatchMimeType("VIDEO/H264"), "VIDEO/H264")
require.Equal(t, MimeTypeAV1, MatchMimeType("VIDEO/AV1"), "VIDEO/AV1")
}
func BenchmarkMimeTypeMatch(b *testing.B) {
mimeTypes := []string{
"video/VP8",
"video/VP9",
"video/H264",
"video/AV1",
}
b.Run("ToLower/switch", func(b *testing.B) {
for i := range b.N {
_ = toLowerSwitch(mimeTypes[i%len(mimeTypes)])
}
})
b.Run("MatchMimeType", func(b *testing.B) {
for i := range b.N {
_ = MatchMimeType(mimeTypes[i%len(mimeTypes)])
}
})
}