Skip to content

Commit a0bf941

Browse files
committed
Merge branch 'feature/offload' into minor
2 parents 6a2dfda + ce4fe70 commit a0bf941

File tree

9 files changed

+115
-22
lines changed

9 files changed

+115
-22
lines changed

just_audio/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 0.10.5
2+
3+
* Disable Android audio offload by default to prevent playback issues.
4+
* Add androidAudioOffloadPreferences.
5+
* Deprecate androidOffloadSchedulingEnabled.
6+
17
## 0.10.4
28

39
* Fix bug on simultaneous loads.

just_audio/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ await player.stop(); // Stop and free resources
2525

2626
### Migrating to 0.10.x
2727

28-
* iOS: You may remove the compile flag `AUDIO_SESSION_MICROPHONE=0` since this is now the default.
28+
* iOS: As of audio_session 0.2.x, you may remove the compile flag `AUDIO_SESSION_MICROPHONE=0` as this is now the default.
2929
* Instead of `player.setAudioSource(ConcatenatingAudioSource(children: sources))` use `player.setAudioSources(sources)`.
3030
* Instead of `LoopingAudioSource(child: source, count: N)` use `...List.filled(N, source)`.
3131
* Instead of listening to `player.playbackEventStream.onError`, listen to `player.errorStream`.

just_audio/android/src/main/java/com/ryanheise/just_audio/AudioPlayer.java

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ public class AudioPlayer implements MethodCallHandler, Player.Listener, Metadata
9696
private AudioAttributes pendingAudioAttributes;
9797
private LoadControl loadControl;
9898
private boolean offloadSchedulingEnabled;
99+
private AudioOffloadPreferences audioOffloadPreferences;
99100
private boolean useLazyPreparation;
100101
private LivePlaybackSpeedControl livePlaybackSpeedControl;
101102
private List<Object> rawAudioEffects;
@@ -145,13 +146,32 @@ public AudioPlayer(
145146
final String id,
146147
Map<?, ?> audioLoadConfiguration,
147148
List<Object> rawAudioEffects,
149+
Map<?, ?> audioOffloadPreferences,
148150
Boolean offloadSchedulingEnabled,
149151
boolean useLazyPreparation
150152
) {
151153
this.context = applicationContext;
152154
this.rawAudioEffects = rawAudioEffects;
153155
this.offloadSchedulingEnabled = offloadSchedulingEnabled != null ? offloadSchedulingEnabled : false;
154156
this.useLazyPreparation = useLazyPreparation;
157+
158+
if (audioOffloadPreferences != null) {
159+
this.audioOffloadPreferences = new AudioOffloadPreferences.Builder()
160+
.setIsGaplessSupportRequired((Boolean)audioOffloadPreferences.get("isGaplessSupportRequired"))
161+
.setIsSpeedChangeSupportRequired((Boolean)audioOffloadPreferences.get("isSpeedChangeSupportRequired"))
162+
.setAudioOffloadMode((Integer)audioOffloadPreferences.get("audioOffloadMode"))
163+
.build();
164+
} else {
165+
final int offloadMode = offloadSchedulingEnabled
166+
? AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED
167+
: AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_DISABLED;
168+
this.audioOffloadPreferences = new AudioOffloadPreferences.Builder()
169+
.setIsGaplessSupportRequired(!offloadSchedulingEnabled)
170+
.setIsSpeedChangeSupportRequired(!offloadSchedulingEnabled)
171+
.setAudioOffloadMode(offloadMode)
172+
.build();
173+
}
174+
155175
methodChannel = new MethodChannel(messenger, "com.ryanheise.just_audio.methods." + id);
156176
methodChannel.setMethodCallHandler(this);
157177
eventChannel = new BetterEventChannel(messenger, "com.ryanheise.just_audio.events." + id);
@@ -772,27 +792,10 @@ private void ensurePlayerInitialized() {
772792
builder.setLivePlaybackSpeedControl(livePlaybackSpeedControl);
773793
}
774794
player = builder.build();
775-
// The latest ExoPlayer enables offload scheduling by default but
776-
// it doesn't support gapless playback below SDK level 33 or speec
777-
// changing. To maintain backwards compatibility within just_audio,
778-
// we set gapless playback and speed changing support as required,
779-
// and let ExoPlayer choose whether it can enable offload
780-
// scheduling depending on device support. If the app passes in
781-
// androidOffloadSchedulingEnabled: true, we simply remove these
782-
// requirements which may prevent gapless and speed changing from
783-
// working, but will allow offload to work. A future release may
784-
// expose more parameters to the app concerning offloading
785-
// preferences.
786795
player.setTrackSelectionParameters(
787796
player.getTrackSelectionParameters()
788797
.buildUpon()
789-
.setAudioOffloadPreferences(
790-
new AudioOffloadPreferences.Builder()
791-
.setIsGaplessSupportRequired(!offloadSchedulingEnabled)
792-
.setIsSpeedChangeSupportRequired(!offloadSchedulingEnabled)
793-
.setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
794-
.build()
795-
)
798+
.setAudioOffloadPreferences(audioOffloadPreferences)
796799
.build()
797800
);
798801
setAudioSessionId(player.getAudioSessionId());

just_audio/android/src/main/java/com/ryanheise/just_audio/MainMethodCallHandler.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public void onMethodCall(MethodCall call, @NonNull Result result) {
4242
id,
4343
call.argument("audioLoadConfiguration"),
4444
rawAudioEffects,
45+
call.argument("androidAudioOffloadPreferences"),
4546
call.argument("androidOffloadSchedulingEnabled"),
4647
call.argument("useLazyPreparation")
4748
)

just_audio/lib/just_audio.dart

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ class AudioPlayer {
7070

7171
final bool _androidOffloadSchedulingEnabled;
7272

73+
final AndroidAudioOffloadPreferences? _androidAudioOffloadPreferences;
74+
7375
/// This is `true` when the audio player needs to engage the native platform
7476
/// side of the plugin to decode or play audio, and is `false` when the native
7577
/// resources are not needed (i.e. after initial instantiation and after [stop]).
@@ -231,13 +233,18 @@ class AudioPlayer {
231233
/// next audio source on load errors, and will give up after [maxSkipsOnError]
232234
/// attempts. This is supported on Android, iOS and web. For other platforms,
233235
/// check the documentation of the respective platform implementation.
236+
///
237+
/// [androidAudioOffloadPreferences] specifies whether audio offload is enabled
238+
/// on Android.
234239
AudioPlayer({
235240
String? userAgent,
236241
bool handleInterruptions = true,
237242
bool androidApplyAudioAttributes = true,
238243
bool handleAudioSessionActivation = true,
239244
AudioLoadConfiguration? audioLoadConfiguration,
240245
AudioPipeline? audioPipeline,
246+
AndroidAudioOffloadPreferences? androidAudioOffloadPreferences,
247+
@Deprecated('Use androidAudioOffloadPreferences instead')
241248
bool androidOffloadSchedulingEnabled = false,
242249
bool useProxyForRequestHeaders = true,
243250
bool useLazyPreparation = true,
@@ -251,6 +258,7 @@ class AudioPlayer {
251258
_audioLoadConfiguration = audioLoadConfiguration,
252259
_audioPipeline = audioPipeline ?? AudioPipeline(),
253260
_androidOffloadSchedulingEnabled = androidOffloadSchedulingEnabled,
261+
_androidAudioOffloadPreferences = androidAudioOffloadPreferences,
254262
_useProxyForRequestHeaders = useProxyForRequestHeaders,
255263
// ignore: deprecated_member_use_from_same_package
256264
_playlist = ConcatenatingAudioSource._playlist(
@@ -1640,6 +1648,8 @@ class AudioPlayer {
16401648
: [],
16411649
androidOffloadSchedulingEnabled:
16421650
_androidOffloadSchedulingEnabled,
1651+
androidAudioOffloadPreferences:
1652+
_androidAudioOffloadPreferences?._toMessage(),
16431653
useLazyPreparation: _playlist.useLazyPreparation,
16441654
)))
16451655
: (_idlePlatform = _IdleAudioPlayer(
@@ -2360,6 +2370,47 @@ class AndroidLivePlaybackSpeedControl {
23602370
);
23612371
}
23622372

2373+
/// Audio offload modes for Android.
2374+
enum AndroidAudioOffloadMode { disabled, enabled }
2375+
2376+
/// Audio offload preferences for Android.
2377+
///
2378+
/// IMPORTANT: activation of audio offload depends on a negotiation between
2379+
/// ExoPlayer and the device to determine whether offload can be supported for a
2380+
/// given format and with given constraints (gapless, speed change). However,
2381+
/// several instances have been reported where the device incorrectly confirms
2382+
/// support for audio offload when it doesn't, and this can result in buggy
2383+
/// audio playback. Therefore, it is advised that you programmatically enable
2384+
/// audio offload only on device/OS combinations that you have tested and
2385+
/// verified to work.
2386+
class AndroidAudioOffloadPreferences {
2387+
/// The preferred audio offload mode.
2388+
final AndroidAudioOffloadMode audioOffloadMode;
2389+
2390+
/// Constrains enablement of audio offload to happen only if the device
2391+
/// can fulfill any gapless transitions that might exist in the playlist
2392+
/// during offload.
2393+
final bool isGaplessSupportRequired;
2394+
2395+
/// Constrains enablement of audio offload to happen only if the device
2396+
/// can fulfill any speed change request during offload.
2397+
final bool isSpeedChangeSupportRequired;
2398+
2399+
const AndroidAudioOffloadPreferences({
2400+
this.audioOffloadMode = AndroidAudioOffloadMode.disabled,
2401+
this.isGaplessSupportRequired = false,
2402+
this.isSpeedChangeSupportRequired = false,
2403+
});
2404+
2405+
AndroidAudioOffloadPreferencesMessage _toMessage() =>
2406+
AndroidAudioOffloadPreferencesMessage(
2407+
audioOffloadMode:
2408+
AndroidAudioOffloadModeMessage.values[audioOffloadMode.index],
2409+
isGaplessSupportRequired: isGaplessSupportRequired,
2410+
isSpeedChangeSupportRequired: isSpeedChangeSupportRequired,
2411+
);
2412+
}
2413+
23632414
class ProgressiveAudioSourceOptions {
23642415
final AndroidExtractorOptions? androidExtractorOptions;
23652416
final DarwinAssetOptions? darwinAssetOptions;

just_audio/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: just_audio
22
description: A feature-rich audio player for Flutter. Loop, clip and sequence any sound from any source (asset/file/URL/stream) in gapless playlists.
3-
version: 0.10.4
3+
version: 0.10.5
44
repository: https://github.com/ryanheise/just_audio/tree/minor/just_audio
55
issue_tracker: https://github.com/ryanheise/just_audio/issues
66
topics:
@@ -14,7 +14,7 @@ environment:
1414
flutter: ">=3.27.0"
1515

1616
dependencies:
17-
just_audio_platform_interface: ^4.5.0
17+
just_audio_platform_interface: ^4.6.0
1818
# just_audio_platform_interface:
1919
# path: ../just_audio_platform_interface
2020
just_audio_web: ^0.4.15

just_audio_platform_interface/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 4.6.0
2+
3+
* Add androidAudioOffloadPreferences.
4+
15
## 4.5.0
26

37
* Add errorCode/errorMessage to PlaybackEventMessage.

just_audio_platform_interface/lib/just_audio_platform_interface.dart

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,8 @@ class InitRequest {
413413
final AudioLoadConfigurationMessage? audioLoadConfiguration;
414414
final List<AudioEffectMessage> androidAudioEffects;
415415
final List<AudioEffectMessage> darwinAudioEffects;
416+
417+
final AndroidAudioOffloadPreferencesMessage? androidAudioOffloadPreferences;
416418
final bool? androidOffloadSchedulingEnabled;
417419
final bool useLazyPreparation;
418420

@@ -421,6 +423,7 @@ class InitRequest {
421423
this.audioLoadConfiguration,
422424
this.androidAudioEffects = const [],
423425
this.darwinAudioEffects = const [],
426+
this.androidAudioOffloadPreferences,
424427
this.androidOffloadSchedulingEnabled,
425428
this.useLazyPreparation = true,
426429
});
@@ -434,6 +437,8 @@ class InitRequest {
434437
'darwinAudioEffects': darwinAudioEffects
435438
.map((audioEffect) => audioEffect.toMap())
436439
.toList(),
440+
'androidAudioOffloadPreferences':
441+
androidAudioOffloadPreferences?.toMap(),
437442
'androidOffloadSchedulingEnabled': androidOffloadSchedulingEnabled,
438443
'useLazyPreparation': useLazyPreparation,
439444
};
@@ -1055,6 +1060,29 @@ class AndroidLivePlaybackSpeedControlMessage {
10551060
};
10561061
}
10571062

1063+
/// The loop mode communicated to the platform implementation.
1064+
enum AndroidAudioOffloadModeMessage { disabled, enabled }
1065+
1066+
/// Information communicated to the platform implementation when setting the
1067+
/// audio offload preferences.
1068+
class AndroidAudioOffloadPreferencesMessage {
1069+
final AndroidAudioOffloadModeMessage audioOffloadMode;
1070+
final bool isGaplessSupportRequired;
1071+
final bool isSpeedChangeSupportRequired;
1072+
1073+
AndroidAudioOffloadPreferencesMessage({
1074+
required this.audioOffloadMode,
1075+
required this.isGaplessSupportRequired,
1076+
required this.isSpeedChangeSupportRequired,
1077+
});
1078+
1079+
Map<dynamic, dynamic> toMap() => <dynamic, dynamic>{
1080+
'audioOffloadMode': audioOffloadMode.index,
1081+
'isGaplessSupportRequired': isGaplessSupportRequired,
1082+
'isSpeedChangeSupportRequired': isSpeedChangeSupportRequired,
1083+
};
1084+
}
1085+
10581086
/// Progressive audio source options to be communicated with the platform
10591087
/// implementation.
10601088
class ProgressiveAudioSourceOptionsMessage {

just_audio_platform_interface/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: A common platform interface for the just_audio plugin. Different pl
33
homepage: https://github.com/ryanheise/just_audio/tree/master/just_audio_platform_interface
44
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
55
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
6-
version: 4.5.0
6+
version: 4.6.0
77

88
dependencies:
99
flutter:

0 commit comments

Comments
 (0)