0.2.42 - DTS surround sound support

This commit is contained in:
ponzischeme89
2026-08-10 12:23:23 +12:00
parent 32c0054c44
commit f41db66ac6
29 changed files with 1363 additions and 128 deletions
@@ -0,0 +1,69 @@
package com.ponzischeme89.memby.data
import com.ponzischeme89.memby.data.model.DeviceProfile
import com.ponzischeme89.memby.data.playback.AudioPassthroughMode
import com.ponzischeme89.memby.data.playback.AudioPassthroughPreference
import com.ponzischeme89.memby.data.playback.DeviceAudioCapabilities
import com.ponzischeme89.memby.data.playback.SurroundCodec
import com.ponzischeme89.memby.data.playback.channelLimitFor
import com.ponzischeme89.memby.data.playback.embyAudioCodecs
import com.ponzischeme89.memby.data.playback.gatewayAudioTokens
import com.ponzischeme89.memby.data.playback.passthroughFor
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
class DeviceAudioCapabilitiesTest {
private val capabilities = DeviceAudioCapabilities(
passthrough = setOf(SurroundCodec.AC3, SurroundCodec.EAC3),
decode = SurroundCodec.entries.toSet(),
maxChannelCount = 6,
probed = true,
)
@Test
fun `automatic follows detected receiver formats`() {
assertEquals(
setOf(SurroundCodec.AC3, SurroundCodec.EAC3),
capabilities.passthroughFor(AudioPassthroughPreference.AUTOMATIC),
)
}
@Test
fun `manual is authoritative and adds extension carriers`() {
val manual = AudioPassthroughPreference(
AudioPassthroughMode.MANUAL,
setOf(SurroundCodec.DTS_HD, SurroundCodec.ATMOS),
)
assertEquals(
setOf(SurroundCodec.DTS_HD, SurroundCodec.DTS, SurroundCodec.ATMOS, SurroundCodec.EAC3),
capabilities.passthroughFor(manual),
)
}
@Test
fun `software decodable codecs stay direct playable with passthrough off`() {
val off = AudioPassthroughPreference(AudioPassthroughMode.MANUAL, emptySet())
val codecs = capabilities.embyAudioCodecs(off)
SurroundCodec.entries.flatMap { it.embyCodecs }.forEach { codec ->
assertTrue("missing $codec from $codecs", codec in codecs.split(','))
}
assertEquals(6, capabilities.channelLimitFor(off))
}
@Test
fun `gateway separates decode and passthrough evidence`() {
val tokens = capabilities.gatewayAudioTokens(AudioPassthroughPreference.AUTOMATIC)
assertTrue("audio_ac3_passthrough" in tokens)
assertTrue("audio_truehd_decode" in tokens)
assertTrue("audio_max_channels_8" in tokens)
}
@Test
fun `device profile copies video when only audio conversion is needed`() {
val profile = DeviceProfile.embyAndroidTv(audio = capabilities)
assertTrue(profile.directPlayProfiles.single().audioCodec.contains("truehd"))
assertEquals("eac3,ac3,aac,mp3", profile.transcodingProfiles.single().audioCodec)
assertEquals("h264", profile.transcodingProfiles.single().videoCodec)
}
}
@@ -1,6 +1,7 @@
package com.ponzischeme89.memby.data
import com.ponzischeme89.memby.data.model.DeviceProfile
import com.ponzischeme89.memby.data.playback.DeviceAudioCapabilities
import com.ponzischeme89.memby.data.playback.DevicePlaybackCapabilities
import com.ponzischeme89.memby.data.playback.VideoDecoderCapabilities
import org.junit.Assert.assertEquals
@@ -33,12 +34,19 @@ class PlaybackReportMathTest {
@Test
fun directPlayProfileAdvertisesHevcOnlyForCapableTvs() {
val baseline = DeviceProfile.embyAndroidTv().directPlayProfiles.single()
val capable = DeviceProfile.embyAndroidTv(supportsHevc = true).directPlayProfiles.single()
val baseline = DeviceProfile.embyAndroidTv(
audio = DeviceAudioCapabilities(),
).directPlayProfiles.single()
val capable = DeviceProfile.embyAndroidTv(
capabilities = DevicePlaybackCapabilities(
hevc = VideoDecoderCapabilities(supported = true),
),
audio = DeviceAudioCapabilities(),
).directPlayProfiles.single()
assertEquals("h264", baseline.videoCodec)
assertEquals("h264,hevc", capable.videoCodec)
assertEquals("aac,mp3", capable.audioCodec)
assertEquals("aac,mp3,flac,opus,vorbis,pcm_s16le,pcm_s24le", capable.audioCodec)
assertFalse(capable.videoCodec.contains("av1"))
assertFalse(capable.audioCodec.contains("eac3"))
}