Fix H264 profile parsing for OpenIPC project

This commit is contained in:
Alexey Khit
2023-08-23 13:26:57 +03:00
parent ea708bb606
commit fc963dfe5c
2 changed files with 34 additions and 6 deletions
+22 -6
View File
@@ -5,8 +5,9 @@ import (
"encoding/binary"
"encoding/hex"
"fmt"
"github.com/AlexxIT/go2rtc/pkg/core"
"strings"
"github.com/AlexxIT/go2rtc/pkg/core"
)
const (
@@ -49,14 +50,23 @@ func Join(ps, iframe []byte) []byte {
return b
}
// https://developers.google.com/cast/docs/media
const (
ProfileBaseline = 0x42
ProfileMain = 0x4D
ProfileHigh = 0x64
CapabilityBaseline = 0xE0
CapabilityMain = 0x40
)
// GetProfileLevelID - get profile from fmtp line
// Some devices won't play video with high level, so limit max profile and max level.
// And return some profile even if fmtp line is empty.
func GetProfileLevelID(fmtp string) string {
// avc1.640029 - H.264 high 4.1 (Chromecast 1st and 2nd Gen)
profile := byte(0x64)
profile := byte(ProfileHigh)
capab := byte(0)
level := byte(0x29)
level := byte(41)
if fmtp != "" {
var conf []byte
@@ -70,12 +80,18 @@ func GetProfileLevelID(fmtp string) string {
conf, _ = hex.DecodeString(s)
}
if conf != nil {
if conf[0] < profile {
if len(conf) == 3 {
// sanitize profile, capab and level to supported values
switch conf[0] {
case ProfileBaseline, ProfileMain:
profile = conf[0]
}
switch conf[1] {
case CapabilityBaseline, CapabilityMain:
capab = conf[1]
}
if conf[2] < level {
switch conf[2] {
case 30, 31, 40:
level = conf[2]
}
}
+12
View File
@@ -39,3 +39,15 @@ func TestDecodeSPS(t *testing.T) {
require.Equal(t, uint16(1920), sps.Width())
require.Equal(t, uint16(1080), sps.Height())
}
func TestGetProfileLevelID(t *testing.T) {
// OpenIPC https://github.com/OpenIPC
s := "profile-level-id=0033e7; packetization-mode=1; "
profile := GetProfileLevelID(s)
require.Equal(t, "640029", profile)
// Eufy T8400 https://github.com/AlexxIT/go2rtc/issues/155
s = "packetization-mode=1;profile-level-id=276400"
profile = GetProfileLevelID(s)
require.Equal(t, "640029", profile)
}