104 lines
3.7 KiB
Go
104 lines
3.7 KiB
Go
package emby
|
|
|
|
import "testing"
|
|
|
|
func TestDirectPlayVideoCodecsIncludeHEVCOnlyForCapableClient(t *testing.T) {
|
|
if got := directPlayVideoCodecs(false); got != "h264" {
|
|
t.Fatalf("baseline codecs = %q", got)
|
|
}
|
|
if got := directPlayVideoCodecs(true); got != "h264,hevc" {
|
|
t.Fatalf("HEVC codecs = %q", got)
|
|
}
|
|
}
|
|
|
|
// Emby shows the device profile's name in its playback device list, so it carries the
|
|
// client identity — never the product name, which is what it said before.
|
|
func TestAndroidTVProfileReportsTheClientIdentityNotTheProductName(t *testing.T) {
|
|
profile := androidTVDeviceProfile(PlaybackCapabilities{})
|
|
if got := profile["Name"]; got != "MbyATV" {
|
|
t.Fatalf("device profile name = %v, want MbyATV", got)
|
|
}
|
|
}
|
|
|
|
func TestAndroidTVProfileConstrainsCodecLevelAndResolution(t *testing.T) {
|
|
profile := androidTVDeviceProfile(PlaybackCapabilities{
|
|
H264Profiles: []string{"baseline", "main", "high"},
|
|
H264Level: 52, H264MaxWidth: 3840, H264MaxHeight: 2160,
|
|
HEVC: true, HEVCMain: true, HEVCMain10: true,
|
|
HEVCMainLevel: 153, HEVCMain10Level: 153,
|
|
HEVCMaxWidth: 3840, HEVCMaxHeight: 2160,
|
|
})
|
|
direct := profile["DirectPlayProfiles"].([]map[string]string)
|
|
if direct[0]["VideoCodec"] != "h264,hevc" {
|
|
t.Fatalf("direct video codecs = %q", direct[0]["VideoCodec"])
|
|
}
|
|
transcode := profile["TranscodingProfiles"].([]map[string]string)
|
|
if transcode[0]["VideoCodec"] != "h264,hevc" {
|
|
t.Fatalf("stream-copy codecs = %q", transcode[0]["VideoCodec"])
|
|
}
|
|
codecProfiles := profile["CodecProfiles"].([]map[string]any)
|
|
if len(codecProfiles) < 6 {
|
|
t.Fatalf("codec profiles = %#v", codecProfiles)
|
|
}
|
|
}
|
|
|
|
func TestForcedTranscodeProfileCannotStreamCopyHEVC(t *testing.T) {
|
|
profile := androidTVDeviceProfile(PlaybackCapabilities{
|
|
HEVC: true, HEVCMain: true, HEVCMain10: true,
|
|
})
|
|
forceH264TranscodeProfile(profile)
|
|
|
|
if direct := profile["DirectPlayProfiles"].([]map[string]string); len(direct) != 0 {
|
|
t.Fatalf("direct profiles = %#v", direct)
|
|
}
|
|
transcode := profile["TranscodingProfiles"].([]map[string]string)
|
|
if len(transcode) != 1 || transcode[0]["VideoCodec"] != "h264" {
|
|
t.Fatalf("transcoding profiles = %#v", transcode)
|
|
}
|
|
for _, codecProfile := range profile["CodecProfiles"].([]map[string]any) {
|
|
if codecProfile["Codec"] == "hevc" {
|
|
t.Fatalf("HEVC constraint survived fallback: %#v", codecProfile)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAudioProfileAdvertisesDecodeAndPassthroughWithoutReencodingVideo(t *testing.T) {
|
|
profile := androidTVDeviceProfile(PlaybackCapabilities{
|
|
HEVC: true, AudioProfileV1: true, AudioMaxChannels: 8,
|
|
AudioPassthrough: map[string]bool{"ac3": true, "eac3": true},
|
|
AudioDecode: map[string]bool{
|
|
"ac3": true, "eac3": true, "atmos": true, "dts": true,
|
|
"dts_hd": true, "truehd": true,
|
|
},
|
|
})
|
|
direct := profile["DirectPlayProfiles"].([]map[string]string)[0]
|
|
for _, codec := range []string{"flac", "opus", "ac3", "eac3", "dts", "dtshd", "truehd"} {
|
|
if !containsCommaValue(direct["AudioCodec"], codec) {
|
|
t.Fatalf("direct audio codecs %q missing %q", direct["AudioCodec"], codec)
|
|
}
|
|
}
|
|
transcode := profile["TranscodingProfiles"].([]map[string]string)[0]
|
|
if transcode["VideoCodec"] != "h264,hevc" || transcode["AudioCodec"] != "eac3,ac3,aac,mp3" {
|
|
t.Fatalf("audio conversion profile = %#v", transcode)
|
|
}
|
|
profiles := profile["CodecProfiles"].([]map[string]any)
|
|
audio := profiles[len(profiles)-1]
|
|
conditions := audio["Conditions"].([]map[string]any)
|
|
if audio["Type"] != "VideoAudio" || conditions[0]["Value"] != "8" {
|
|
t.Fatalf("audio constraints = %#v", audio)
|
|
}
|
|
}
|
|
|
|
func containsCommaValue(values, wanted string) bool {
|
|
start := 0
|
|
for i := 0; i <= len(values); i++ {
|
|
if i == len(values) || values[i] == ',' {
|
|
if values[start:i] == wanted {
|
|
return true
|
|
}
|
|
start = i + 1
|
|
}
|
|
}
|
|
return false
|
|
}
|