From 46bf0fbbb69138eabbed75e9e3aa66185f32c555 Mon Sep 17 00:00:00 2001 From: Anton Afanasyeu Date: Sat, 6 Jun 2026 20:18:32 +0200 Subject: [PATCH] playing with Opus/Speex --- .../com/foxx/androidcast/CastSettings.java | 4 ++-- .../media/codec/PassthroughCodecPolicy.java | 5 +---- .../androidcast/network/CastCodecFlags.java | 14 +++---------- .../foxx/androidcast/sender/CodecCatalog.java | 8 ++++---- .../media/AudioNegotiatorTest.java | 20 +++++++++++++++++++ 5 files changed, 30 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/foxx/androidcast/CastSettings.java b/app/src/main/java/com/foxx/androidcast/CastSettings.java index 3020af2..739a33a 100644 --- a/app/src/main/java/com/foxx/androidcast/CastSettings.java +++ b/app/src/main/java/com/foxx/androidcast/CastSettings.java @@ -42,9 +42,9 @@ public class CastSettings implements Serializable { public enum AudioCodec { AUTO, AAC, - /** Future Speex (UI disabled until integrated). */ + /** Speex (native when built; otherwise stub AAC + Speex backend label). */ SPEEX, - /** Future Opus with in-band FEC (UI disabled until integrated). */ + /** Opus with in-band FEC when native; otherwise stub AAC + Opus backend label. */ OPUS, /** Explicit AAC passthrough wrapper for debug comparisons. */ PASSTHROUGH_DEBUG diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughCodecPolicy.java b/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughCodecPolicy.java index aa1c317..863d853 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughCodecPolicy.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughCodecPolicy.java @@ -57,11 +57,8 @@ public final class PassthroughCodecPolicy { } switch (preference) { case SPEEX: - return NativeCodecBridge.isSpeexAvailable() - ? CastSettings.AudioCodec.SPEEX : CastSettings.AudioCodec.AUTO; case OPUS: - return NativeCodecBridge.isOpusAvailable() - ? CastSettings.AudioCodec.OPUS : CastSettings.AudioCodec.AUTO; + return preference; case PASSTHROUGH_DEBUG: return CastSettings.AudioCodec.AUTO; default: diff --git a/app/src/main/java/com/foxx/androidcast/network/CastCodecFlags.java b/app/src/main/java/com/foxx/androidcast/network/CastCodecFlags.java index c4e47f1..8922abd 100644 --- a/app/src/main/java/com/foxx/androidcast/network/CastCodecFlags.java +++ b/app/src/main/java/com/foxx/androidcast/network/CastCodecFlags.java @@ -14,7 +14,6 @@ package com.foxx.androidcast.network; import android.media.MediaFormat; import com.foxx.androidcast.CastSettings; -import com.foxx.androidcast.media.codec.jni.NativeCodecBridge; import com.foxx.androidcast.sender.CodecCatalog; import java.util.List; @@ -63,14 +62,8 @@ public final class CastCodecFlags { } public static int localAudioMask() { - int mask = AUDIO_AAC | AUDIO_PCM; - if (NativeCodecBridge.isOpusAvailable()) { - mask |= AUDIO_OPUS; - } - if (NativeCodecBridge.isSpeexAvailable()) { - mask |= AUDIO_SPEEX; - } - return mask; + // Advertise Opus/Speex for stub negotiation even when native probes are false. + return AUDIO_AAC | AUDIO_PCM | AUDIO_OPUS | AUDIO_SPEEX; } public static int localDecoderAudioMask() { @@ -108,9 +101,8 @@ public final class CastCodecFlags { } switch (codec) { case OPUS: - return NativeCodecBridge.isOpusAvailable(); case SPEEX: - return NativeCodecBridge.isSpeexAvailable(); + return true; case AAC: case PASSTHROUGH_DEBUG: return true; diff --git a/app/src/main/java/com/foxx/androidcast/sender/CodecCatalog.java b/app/src/main/java/com/foxx/androidcast/sender/CodecCatalog.java index 663955c..293291f 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/CodecCatalog.java +++ b/app/src/main/java/com/foxx/androidcast/sender/CodecCatalog.java @@ -88,13 +88,13 @@ public final class CodecCatalog { public static List audioCodecChoicesForUi(CastSettings settings) { List out = new ArrayList<>(); - boolean opus = NativeCodecBridge.isOpusAvailable(); - boolean speex = NativeCodecBridge.isSpeexAvailable(); out.add(new AudioCodecChoice(CastSettings.AudioCodec.AUTO, true, 0)); - out.add(scoredAudio(CastSettings.AudioCodec.OPUS, opus, settings)); + // Selectable even without native .so — stub path uses AAC + OPUS/SPEEX backend label (validation). + out.add(scoredAudio(CastSettings.AudioCodec.OPUS, true, settings)); out.add(scoredAudio(CastSettings.AudioCodec.AAC, true, settings)); - out.add(scoredAudio(CastSettings.AudioCodec.SPEEX, speex, settings)); + out.add(scoredAudio(CastSettings.AudioCodec.SPEEX, true, settings)); out.add(scoredAudio(CastSettings.AudioCodec.PASSTHROUGH_DEBUG, true, settings)); + sortAudioChoices(out); return out; } diff --git a/app/src/test/java/com/foxx/androidcast/media/AudioNegotiatorTest.java b/app/src/test/java/com/foxx/androidcast/media/AudioNegotiatorTest.java index e830e90..2b73860 100644 --- a/app/src/test/java/com/foxx/androidcast/media/AudioNegotiatorTest.java +++ b/app/src/test/java/com/foxx/androidcast/media/AudioNegotiatorTest.java @@ -50,6 +50,26 @@ public class AudioNegotiatorTest { assertEquals(CastSettings.AudioCodec.AAC, picked); } + @Test + public void explicitOpusNegotiatesWhenLinkSupportsOpus() { + CastSettings settings = new CastSettings(); + int mask = CastCodecFlags.AUDIO_AAC | CastCodecFlags.AUDIO_OPUS; + + CastSettings.AudioCodec picked = AudioNegotiator.negotiate( + mask, mask, CastSettings.AudioCodec.OPUS, settings); + assertEquals(CastSettings.AudioCodec.OPUS, picked); + } + + @Test + public void explicitSpeexNegotiatesWhenLinkSupportsSpeex() { + CastSettings settings = new CastSettings(); + int mask = CastCodecFlags.AUDIO_AAC | CastCodecFlags.AUDIO_SPEEX; + + CastSettings.AudioCodec picked = AudioNegotiator.negotiate( + mask, mask, CastSettings.AudioCodec.SPEEX, settings); + assertEquals(CastSettings.AudioCodec.SPEEX, picked); + } + @Test public void manualPreferenceOrderIsFixedInCatalog() { CastSettings.AudioCodec[] order = CodecPriorityCatalog.manualAudioPreferences();