Fix H264 profile parsing for OpenIPC project
This commit is contained in:
+22
-6
@@ -5,8 +5,9 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/AlexxIT/go2rtc/pkg/core"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/AlexxIT/go2rtc/pkg/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -49,14 +50,23 @@ func Join(ps, iframe []byte) []byte {
|
|||||||
return b
|
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
|
// GetProfileLevelID - get profile from fmtp line
|
||||||
// Some devices won't play video with high level, so limit max profile and max level.
|
// 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.
|
// And return some profile even if fmtp line is empty.
|
||||||
func GetProfileLevelID(fmtp string) string {
|
func GetProfileLevelID(fmtp string) string {
|
||||||
// avc1.640029 - H.264 high 4.1 (Chromecast 1st and 2nd Gen)
|
// avc1.640029 - H.264 high 4.1 (Chromecast 1st and 2nd Gen)
|
||||||
profile := byte(0x64)
|
profile := byte(ProfileHigh)
|
||||||
capab := byte(0)
|
capab := byte(0)
|
||||||
level := byte(0x29)
|
level := byte(41)
|
||||||
|
|
||||||
if fmtp != "" {
|
if fmtp != "" {
|
||||||
var conf []byte
|
var conf []byte
|
||||||
@@ -70,12 +80,18 @@ func GetProfileLevelID(fmtp string) string {
|
|||||||
conf, _ = hex.DecodeString(s)
|
conf, _ = hex.DecodeString(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
if conf != nil {
|
if len(conf) == 3 {
|
||||||
if conf[0] < profile {
|
// sanitize profile, capab and level to supported values
|
||||||
|
switch conf[0] {
|
||||||
|
case ProfileBaseline, ProfileMain:
|
||||||
profile = conf[0]
|
profile = conf[0]
|
||||||
|
}
|
||||||
|
switch conf[1] {
|
||||||
|
case CapabilityBaseline, CapabilityMain:
|
||||||
capab = conf[1]
|
capab = conf[1]
|
||||||
}
|
}
|
||||||
if conf[2] < level {
|
switch conf[2] {
|
||||||
|
case 30, 31, 40:
|
||||||
level = conf[2]
|
level = conf[2]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,3 +39,15 @@ func TestDecodeSPS(t *testing.T) {
|
|||||||
require.Equal(t, uint16(1920), sps.Width())
|
require.Equal(t, uint16(1920), sps.Width())
|
||||||
require.Equal(t, uint16(1080), sps.Height())
|
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)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user