mirror of
git://f0xx.org/android_cast
synced 2026-07-29 08:19:00 +03:00
stage 1
This commit is contained in:
@@ -45,7 +45,9 @@ public class CastSettings implements Serializable {
|
||||
/** Future Speex (UI disabled until integrated). */
|
||||
SPEEX,
|
||||
/** Future Opus with in-band FEC (UI disabled until integrated). */
|
||||
OPUS
|
||||
OPUS,
|
||||
/** Explicit AAC passthrough wrapper for debug comparisons. */
|
||||
PASSTHROUGH_DEBUG
|
||||
}
|
||||
|
||||
public enum AdjustmentPreset {
|
||||
|
||||
@@ -604,6 +604,8 @@ public final class CastSettingsBinder {
|
||||
return activity.getString(R.string.codec_speex);
|
||||
case OPUS:
|
||||
return activity.getString(R.string.codec_opus);
|
||||
case PASSTHROUGH_DEBUG:
|
||||
return activity.getString(R.string.codec_audio_passthrough_debug);
|
||||
case AUTO:
|
||||
default:
|
||||
return activity.getString(R.string.codec_audio_auto);
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.foxx.androidcast.CastTuningEngine;
|
||||
import com.foxx.androidcast.media.CodecNegotiator;
|
||||
import com.foxx.androidcast.media.codec.CodecSessionRegistry;
|
||||
import com.foxx.androidcast.media.codec.PassthroughCodecPolicy;
|
||||
import com.foxx.androidcast.media.codec.jni.NativeCodecBridge;
|
||||
import com.foxx.androidcast.network.control.NetworkStatsSnapshot;
|
||||
import com.foxx.androidcast.network.diag.DiagPingMetrics;
|
||||
import com.foxx.androidcast.receiver.StreamMetrics;
|
||||
@@ -393,9 +394,17 @@ public final class CastDiagnosticsFormatter {
|
||||
if (prefs != null && prefs.isAudioRequested()) {
|
||||
CastSettings.AudioCodec ac = prefs.getAudioCodec();
|
||||
if (ac == CastSettings.AudioCodec.OPUS) {
|
||||
html.append(" · <font color='").append(COLOR_OK).append("'>Opus in-band FEC</font>");
|
||||
if (NativeCodecBridge.isOpusAvailable()) {
|
||||
html.append(" · <font color='").append(COLOR_OK).append("'>Opus in-band FEC</font>");
|
||||
} else {
|
||||
html.append(" · <font color='").append(COLOR_WARN).append("'>Opus fallback AAC</font>");
|
||||
}
|
||||
} else if (ac == CastSettings.AudioCodec.SPEEX) {
|
||||
html.append(" · <font color='").append(COLOR_OK).append("'>Speex FEC</font>");
|
||||
if (NativeCodecBridge.isSpeexAvailable()) {
|
||||
html.append(" · <font color='").append(COLOR_OK).append("'>Speex FEC</font>");
|
||||
} else {
|
||||
html.append(" · <font color='").append(COLOR_WARN).append("'>Speex fallback AAC</font>");
|
||||
}
|
||||
} else {
|
||||
html.append(" · AAC-LC (MediaCodec)");
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ package com.foxx.androidcast.diagnostics;
|
||||
* Digest: SHA256 1c6f25ad871cb71788ed6fd1817d4d59d22d5ef6638704c9483937a2a9c15977
|
||||
**********************************************************************/
|
||||
import com.foxx.androidcast.CastSettings;
|
||||
import com.foxx.androidcast.media.codec.jni.NativeCodecBridge;
|
||||
|
||||
/** Human-readable names for diagnostics (no bare AUTO enum tokens). */
|
||||
public final class CastDiagnosticsLabels {
|
||||
@@ -137,9 +138,13 @@ public final class CastDiagnosticsLabels {
|
||||
case AAC:
|
||||
return "AAC-LC (forced)";
|
||||
case SPEEX:
|
||||
return "Speex (stub → AAC)";
|
||||
return NativeCodecBridge.isSpeexAvailable()
|
||||
? "Speex (native)" : "Speex (fallback AAC)";
|
||||
case OPUS:
|
||||
return "Opus + in-band FEC (stub → AAC)";
|
||||
return NativeCodecBridge.isOpusAvailable()
|
||||
? "Opus + in-band FEC (native)" : "Opus (fallback AAC)";
|
||||
case PASSTHROUGH_DEBUG:
|
||||
return "Passthrough AAC (debug)";
|
||||
case AUTO:
|
||||
default:
|
||||
return "AUTO (AAC via MediaCodec)";
|
||||
|
||||
@@ -248,10 +248,13 @@ public final class CodecPriorityCatalog {
|
||||
|
||||
public static CodecTier tierForAudioPreference(CastSettings.AudioCodec preference) {
|
||||
if (preference == CastSettings.AudioCodec.SPEEX) {
|
||||
return CodecTier.PASSTHROUGH;
|
||||
return NativeCodecBridge.isSpeexAvailable() ? CodecTier.SOFTWARE : CodecTier.PASSTHROUGH;
|
||||
}
|
||||
if (preference == CastSettings.AudioCodec.OPUS) {
|
||||
return CodecTier.SOFTWARE;
|
||||
return NativeCodecBridge.isOpusAvailable() ? CodecTier.SOFTWARE : CodecTier.PASSTHROUGH;
|
||||
}
|
||||
if (preference == CastSettings.AudioCodec.PASSTHROUGH_DEBUG) {
|
||||
return CodecTier.PASSTHROUGH;
|
||||
}
|
||||
return CodecTier.HARDWARE;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,8 @@ public enum CodecPriorityId {
|
||||
return OPUS;
|
||||
case SPEEX:
|
||||
return SPEEX;
|
||||
case PASSTHROUGH_DEBUG:
|
||||
return PCM;
|
||||
case AUTO:
|
||||
default:
|
||||
return null;
|
||||
|
||||
@@ -14,8 +14,11 @@ package com.foxx.androidcast.media.codec;
|
||||
/** Implementation backing negotiated / configured audio. */
|
||||
public enum AudioCodecBackend {
|
||||
MEDIA_CODEC_AAC("MediaCodec AAC-LC"),
|
||||
SPEEX_NATIVE("Speex native"),
|
||||
OPUS_NATIVE("Opus native"),
|
||||
SPEEX_STUB("Speex (stub → AAC passthrough)"),
|
||||
OPUS_STUB("Opus (stub → AAC passthrough)"),
|
||||
PASSTHROUGH_DEBUG("Passthrough AAC (debug)"),
|
||||
DISABLED("off"),
|
||||
UNKNOWN("?");
|
||||
|
||||
|
||||
@@ -21,7 +21,9 @@ public final class AudioCodecFactory {
|
||||
public static AudioEncoderSink createEncoder(CastSettings.AudioCodec preference) {
|
||||
CodecSessionRegistry.setAudioPreference(preference);
|
||||
AudioCodecBackend backend = PassthroughCodecPolicy.audioBackendFor(preference, true);
|
||||
if (backend == AudioCodecBackend.SPEEX_STUB || backend == AudioCodecBackend.OPUS_STUB) {
|
||||
if (backend == AudioCodecBackend.SPEEX_STUB
|
||||
|| backend == AudioCodecBackend.OPUS_STUB
|
||||
|| backend == AudioCodecBackend.PASSTHROUGH_DEBUG) {
|
||||
return new PassthroughAudioEncoderSink(new AudioEncoder(), preference);
|
||||
}
|
||||
return new AudioEncoder();
|
||||
|
||||
@@ -31,6 +31,8 @@ final class PassthroughAudioEncoderSink implements AudioEncoderSink {
|
||||
CodecSessionRegistry.setAudioBackend(AudioCodecBackend.OPUS_STUB);
|
||||
} else if (preference == CastSettings.AudioCodec.SPEEX) {
|
||||
CodecSessionRegistry.setAudioBackend(AudioCodecBackend.SPEEX_STUB);
|
||||
} else if (preference == CastSettings.AudioCodec.PASSTHROUGH_DEBUG) {
|
||||
CodecSessionRegistry.setAudioBackend(AudioCodecBackend.PASSTHROUGH_DEBUG);
|
||||
}
|
||||
delegate.prepare(callback);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,12 @@ 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;
|
||||
case PASSTHROUGH_DEBUG:
|
||||
return CastSettings.AudioCodec.AUTO;
|
||||
default:
|
||||
return preference;
|
||||
@@ -70,10 +75,15 @@ public final class PassthroughCodecPolicy {
|
||||
return AudioCodecBackend.DISABLED;
|
||||
}
|
||||
if (preference == CastSettings.AudioCodec.SPEEX) {
|
||||
return AudioCodecBackend.SPEEX_STUB;
|
||||
return NativeCodecBridge.isSpeexAvailable()
|
||||
? AudioCodecBackend.SPEEX_NATIVE : AudioCodecBackend.SPEEX_STUB;
|
||||
}
|
||||
if (preference == CastSettings.AudioCodec.OPUS) {
|
||||
return AudioCodecBackend.OPUS_STUB;
|
||||
return NativeCodecBridge.isOpusAvailable()
|
||||
? AudioCodecBackend.OPUS_NATIVE : AudioCodecBackend.OPUS_STUB;
|
||||
}
|
||||
if (preference == CastSettings.AudioCodec.PASSTHROUGH_DEBUG) {
|
||||
return AudioCodecBackend.PASSTHROUGH_DEBUG;
|
||||
}
|
||||
return AudioCodecBackend.MEDIA_CODEC_AAC;
|
||||
}
|
||||
@@ -150,6 +160,8 @@ public final class PassthroughCodecPolicy {
|
||||
return "Opus";
|
||||
case AAC:
|
||||
return "AAC";
|
||||
case PASSTHROUGH_DEBUG:
|
||||
return "Passthrough (debug)";
|
||||
case AUTO:
|
||||
default:
|
||||
return "AUTO (AAC)";
|
||||
|
||||
@@ -13,6 +13,7 @@ package com.foxx.androidcast.network;
|
||||
**********************************************************************/
|
||||
import android.media.MediaFormat;
|
||||
|
||||
import com.foxx.androidcast.media.codec.jni.NativeCodecBridge;
|
||||
import com.foxx.androidcast.sender.CodecCatalog;
|
||||
|
||||
import java.util.List;
|
||||
@@ -28,6 +29,8 @@ public final class CastCodecFlags {
|
||||
public static final int AUDIO_UNKNOWN = 0;
|
||||
public static final int AUDIO_PCM = 1;
|
||||
public static final int AUDIO_AAC = 2;
|
||||
public static final int AUDIO_OPUS = 4;
|
||||
public static final int AUDIO_SPEEX = 8;
|
||||
|
||||
private CastCodecFlags() {}
|
||||
|
||||
@@ -59,6 +62,13 @@ public final class CastCodecFlags {
|
||||
}
|
||||
|
||||
public static int localAudioMask() {
|
||||
return AUDIO_AAC | AUDIO_PCM;
|
||||
int mask = AUDIO_AAC | AUDIO_PCM;
|
||||
if (NativeCodecBridge.isOpusAvailable()) {
|
||||
mask |= AUDIO_OPUS;
|
||||
}
|
||||
if (NativeCodecBridge.isSpeexAvailable()) {
|
||||
mask |= AUDIO_SPEEX;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ public final class CastProtocol {
|
||||
dos.writeInt(settings.getCaptureMode().ordinal());
|
||||
dos.writeInt(settings.getStreamProtection().ordinal());
|
||||
dos.writeInt(settings.getReceiverDisplayResolution().ordinal());
|
||||
dos.writeInt(settings.getAudioCodec().ordinal());
|
||||
dos.flush();
|
||||
return bos.toByteArray();
|
||||
}
|
||||
@@ -147,6 +148,10 @@ public final class CastProtocol {
|
||||
readEnum(CastSettings.ReceiverDisplayResolution.values(), dis.readInt(),
|
||||
CastSettings.ReceiverDisplayResolution.AUTO_FIT));
|
||||
}
|
||||
if (dis.available() > 0) {
|
||||
settings.setAudioCodec(readEnum(CastSettings.AudioCodec.values(), dis.readInt(),
|
||||
CastSettings.AudioCodec.AUTO));
|
||||
}
|
||||
} else {
|
||||
dis.reset();
|
||||
settings.setTransport(dis.readUTF());
|
||||
|
||||
@@ -88,10 +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.AAC, true, settings));
|
||||
out.add(scoredAudio(CastSettings.AudioCodec.OPUS, true, settings));
|
||||
out.add(scoredAudio(CastSettings.AudioCodec.SPEEX, true, settings));
|
||||
out.add(scoredAudio(CastSettings.AudioCodec.OPUS, opus, settings));
|
||||
out.add(scoredAudio(CastSettings.AudioCodec.SPEEX, speex, settings));
|
||||
out.add(scoredAudio(CastSettings.AudioCodec.PASSTHROUGH_DEBUG, true, settings));
|
||||
sortAudioChoices(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -226,12 +226,13 @@
|
||||
<string name="dev_reload_codecs_json">Перезагрузить codecs.json</string>
|
||||
<string name="dev_reload_codecs_json_hint">Подгружает overrides из assets/codecs.json без перезапуска. Откройте настройки снова, чтобы обновить списки.</string>
|
||||
<string name="codec_priority_score_suffix"> · %1$d</string>
|
||||
<string name="label_audio_codec">Кодек для звука</string>
|
||||
<string name="label_audio_codec">Аудио кодек</string>
|
||||
<string name="codec_libvpx_vp8">libvpx (VP8)</string>
|
||||
<string name="codec_libvpx_vp9">libvpx (VP9)</string>
|
||||
<string name="codec_aac">AAC</string>
|
||||
<string name="codec_speex">Speex</string>
|
||||
<string name="codec_opus">Opus</string>
|
||||
<string name="codec_audio_passthrough_debug">Passthrough (отладка)</string>
|
||||
<string name="codec_audio_auto">AUTO (AAC)</string>
|
||||
<string name="pip_enter">Картинка в картинке (PiP)</string>
|
||||
<string name="pip_unavailable">Режим «картинка в картинке» (PiP) недоступен на этом устройстве</string>
|
||||
|
||||
@@ -318,12 +318,13 @@
|
||||
<string name="ota_download_failed">Download failed: %1$s</string>
|
||||
<string name="ota_notification_channel_name">App updates</string>
|
||||
<string name="codec_priority_score_suffix"> · %1$d</string>
|
||||
<string name="label_audio_codec">Voice codec</string>
|
||||
<string name="label_audio_codec">Audio codec</string>
|
||||
<string name="codec_libvpx_vp8">libvpx (VP8)</string>
|
||||
<string name="codec_libvpx_vp9">libvpx (VP9)</string>
|
||||
<string name="codec_aac">AAC</string>
|
||||
<string name="codec_speex">Speex</string>
|
||||
<string name="codec_opus">Opus</string>
|
||||
<string name="codec_audio_passthrough_debug">Passthrough (debug)</string>
|
||||
<string name="codec_audio_auto">AUTO (AAC)</string>
|
||||
<string name="pip_enter">Picture-in-picture</string>
|
||||
<string name="pip_unavailable">Picture-in-picture is not available on this device</string>
|
||||
|
||||
Reference in New Issue
Block a user