1
0
mirror of git://f0xx.org/android_cast synced 2026-07-29 05:37:52 +03:00

playing with Opus/Speex

This commit is contained in:
Anton Afanasyeu
2026-06-06 20:18:32 +02:00
parent b019e4f22c
commit 46bf0fbbb6
5 changed files with 30 additions and 21 deletions

View File

@@ -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

View File

@@ -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:

View File

@@ -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;

View File

@@ -88,13 +88,13 @@ public final class CodecCatalog {
public static List<AudioCodecChoice> audioCodecChoicesForUi(CastSettings settings) {
List<AudioCodecChoice> 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;
}

View File

@@ -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();