Skip to content

Commit 1a49c38

Browse files
authored
Merge branch 'main' into add-font-based-metrics
2 parents 51ef750 + 6b08824 commit 1a49c38

File tree

7 files changed

+89
-16
lines changed

7 files changed

+89
-16
lines changed

cobalt/android/apk/app/src/main/java/dev/cobalt/media/AudioTrackBridge.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import android.media.AudioFormat;
2121
import android.media.AudioManager;
2222
import android.media.AudioTrack;
23+
import android.media.PlaybackParams;
2324
import android.os.Build;
2425
import androidx.annotation.GuardedBy;
2526
import androidx.annotation.RequiresApi;
@@ -227,11 +228,34 @@ public void release() {
227228
mAvSyncPacketBytesRemaining = 0;
228229
}
229230

231+
232+
@CalledByNative
233+
public boolean setPlaybackRate(float playbackRate) {
234+
if (mAudioTrack == null) {
235+
Log.e(TAG, "Unable to setPlaybackRate with NULL audio track.");
236+
return false;
237+
}
238+
if (!mTunnelModeEnabled) {
239+
Log.i(TAG, "Skip SetPlaybackRate for non tunnel mode tracks.");
240+
return true;
241+
}
242+
243+
try {
244+
PlaybackParams params = mAudioTrack.getPlaybackParams();
245+
params.setSpeed(playbackRate);
246+
mAudioTrack.setPlaybackParams(params);
247+
} catch (IllegalArgumentException | IllegalStateException e) {
248+
Log.e(TAG, String.format("Unable to setPlaybackRate, error: %s", e.toString()));
249+
return false;
250+
}
251+
return true;
252+
}
253+
230254
@CalledByNative
231255
public int setVolume(float gain) {
232256
if (mAudioTrack == null) {
233257
Log.e(TAG, "Unable to setVolume with NULL audio track.");
234-
return 0;
258+
return AudioTrack.ERROR_INVALID_OPERATION;
235259
}
236260
return mAudioTrack.setVolume(gain);
237261
}

starboard/android/shared/audio_track_audio_sink_type.cc

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,19 @@ AudioTrackAudioSink::~AudioTrackAudioSink() {
188188

189189
void AudioTrackAudioSink::SetPlaybackRate(double playback_rate) {
190190
SB_DCHECK_GE(playback_rate, 0.0);
191-
if (playback_rate != 0.0 && playback_rate != 1.0) {
192-
SB_NOTIMPLEMENTED() << "TODO: Only playback rates of 0.0 and 1.0 are "
193-
"currently supported.";
194-
playback_rate = (playback_rate > 0.0) ? 1.0 : 0.0;
191+
SB_DLOG(INFO) << "Set playback rate to " << playback_rate;
192+
193+
{
194+
std::lock_guard lock(mutex_);
195+
playback_rate_ = playback_rate;
196+
}
197+
198+
// AudioTrack doesn't support playback speed of 0.
199+
if (playback_rate > 0.0) {
200+
// AudioTrackBridge.setPlaybackRate() currently is only enabled for tunnel
201+
// mode. It will be no-op for non tunnel player.
202+
bridge_.SetPlaybackRate(playback_rate);
195203
}
196-
std::lock_guard lock(mutex_);
197-
playback_rate_ = playback_rate;
198204
}
199205

200206
// TODO: Break down the function into manageable pieces.
@@ -439,6 +445,21 @@ int AudioTrackAudioSinkType::GetMinBufferSizeInFrames(
439445
int sampling_frequency_hz) {
440446
SB_CHECK(audio_track_audio_sink_type_);
441447
JNIEnv* env = AttachCurrentThread();
448+
449+
const bool force_tunnel_mode =
450+
features::FeatureList::IsEnabled(features::kForceTunnelMode);
451+
if (force_tunnel_mode) {
452+
// AudioTrack.setPlaybackParams() needs extra buffer to support playback
453+
// speed greater than 1.0x.
454+
const double kMaxPlaybackSpeed = 2.0;
455+
return std::max<int>(
456+
AudioOutputManager::GetInstance()->GetMinBufferSizeInFrames(
457+
env, sample_type, channels, sampling_frequency_hz),
458+
audio_track_audio_sink_type_->GetMinBufferSizeInFramesInternal(
459+
channels, sample_type, sampling_frequency_hz) *
460+
kMaxPlaybackSpeed);
461+
}
462+
442463
return std::max(
443464
AudioOutputManager::GetInstance()->GetMinBufferSizeInFrames(
444465
env, sample_type, channels, sampling_frequency_hz),

starboard/android/shared/audio_track_bridge.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "starboard/android/shared/audio_output_manager.h"
2020
#include "starboard/android/shared/media_common.h"
2121
#include "starboard/audio_sink.h"
22+
#include "starboard/common/check_op.h"
2223
#include "starboard/common/log.h"
2324
#include "starboard/shared/starboard/media/media_util.h"
2425

@@ -241,6 +242,21 @@ int AudioTrackBridge::WriteSample(const uint8_t* samples,
241242
return bytes_written;
242243
}
243244

245+
void AudioTrackBridge::SetPlaybackRate(
246+
double playback_rate,
247+
JNIEnv* env /*= AttachCurrentThread()*/) {
248+
SB_DCHECK(env);
249+
SB_DCHECK(is_valid());
250+
// AudioTrack doesn't support playback speed of 0.
251+
SB_DCHECK_GT(playback_rate, 0.0);
252+
253+
jboolean status = Java_AudioTrackBridge_setPlaybackRate(
254+
env, j_audio_track_bridge_, static_cast<float>(playback_rate));
255+
if (!status) {
256+
SB_LOG(ERROR) << "Failed to set playback rate to " << playback_rate;
257+
}
258+
}
259+
244260
void AudioTrackBridge::SetVolume(double volume,
245261
JNIEnv* env /*= AttachCurrentThread()*/) {
246262
SB_DCHECK(env);

starboard/android/shared/audio_track_bridge.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ class AudioTrackBridge {
7171
int64_t sync_time,
7272
JNIEnv* env = base::android::AttachCurrentThread());
7373

74+
void SetPlaybackRate(double playback_rate,
75+
JNIEnv* env = base::android::AttachCurrentThread());
7476
void SetVolume(double volume,
7577
JNIEnv* env = base::android::AttachCurrentThread());
7678

starboard/android/shared/player_components_factory.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ class AudioRendererSinkAndroid : public AudioRendererSinkImpl {
9494
return tunnel_mode_audio_session_id_ != -1;
9595
}
9696

97+
bool AllowDirectPlaybackRateSetting() const override {
98+
return tunnel_mode_audio_session_id_ != -1;
99+
}
100+
97101
private:
98102
bool IsAudioSampleTypeSupported(
99103
SbMediaAudioSampleType audio_sample_type) const override {

starboard/shared/starboard/player/filter/audio_renderer_internal_pcm.cc

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,13 @@ void AudioRendererPcm::SetPlaybackRate(double playback_rate) {
214214

215215
playback_rate_ = playback_rate;
216216

217-
audio_renderer_sink_->SetPlaybackRate(playback_rate_ > 0.0 ? 1.0 : 0.0);
217+
double adjusted_playback_rate = playback_rate_ > 0.0 ? 1.0 : 0.0;
218+
if (audio_renderer_sink_->AllowDirectPlaybackRateSetting()) {
219+
adjusted_playback_rate = playback_rate_;
220+
}
221+
222+
audio_renderer_sink_->SetPlaybackRate(adjusted_playback_rate);
218223
if (audio_renderer_sink_->HasStarted()) {
219-
// TODO: Remove SetPlaybackRate() support from audio sink as it only need to
220-
// support play/pause.
221224
if (playback_rate_ > 0.0) {
222225
if (process_audio_data_job_token_.is_valid()) {
223226
RemoveJobByToken(process_audio_data_job_token_);
@@ -334,14 +337,12 @@ int64_t AudioRendererPcm::GetCurrentMediaTime(bool* is_playing,
334337
frames_played =
335338
audio_frame_tracker_.GetFutureFramesPlayedAdjustedToPlaybackRate(
336339
elapsed_frames, playback_rate);
337-
#if BUILDFLAG(IS_ANDROID)
338340
if (audio_renderer_sink_->AllowOverflowAudioSamples()) {
339341
// A simple workaround to handle silence frames for tunnel mode player.
340342
// |playback_rate| is ignored as tunnel mode doesn't support
341343
// vsp.
342344
frames_played += audio_frame_tracker_.GetOverflowedFrames();
343345
}
344-
#endif // BUILDFLAG(IS_ANDROID)
345346
media_time =
346347
seeking_to_time_ + frames_played * 1'000'000LL / samples_per_second;
347348
if (media_time < last_media_time_) {
@@ -490,15 +491,13 @@ void AudioRendererPcm::UpdateVariablesOnSinkThread_Locked(
490491
frames_consumed_set_at_ = system_time_on_consume_frames;
491492
}
492493

493-
#if BUILDFLAG(IS_ANDROID)
494494
if (audio_renderer_sink_->AllowOverflowAudioSamples()) {
495495
auto silence_frames_consumed =
496496
frames_consumed_on_sink_thread_ - non_silence_frames_consumed;
497497
frames_consumed_by_sink_since_last_get_current_time_ +=
498498
silence_frames_consumed;
499499
frames_consumed_set_at_ = system_time_on_consume_frames;
500500
}
501-
#endif // BUILDFLAG(IS_ANDROID)
502501

503502
consume_frames_called_ = true;
504503
frames_consumed_on_sink_thread_ = 0;
@@ -723,16 +722,22 @@ bool AudioRendererPcm::AppendAudioToFrameBuffer(bool* is_frame_buffer_full) {
723722

724723
int offset_to_append = total_frames_sent_to_sink_ % max_cached_frames_;
725724

725+
double adjusted_playback_rate = playback_rate_;
726+
if (audio_renderer_sink_->AllowDirectPlaybackRateSetting()) {
727+
adjusted_playback_rate = 1.0;
728+
}
729+
726730
scoped_refptr<DecodedAudio> decoded_audio = time_stretcher_.Read(
727-
max_cached_frames_ - frames_in_buffer, playback_rate_);
731+
max_cached_frames_ - frames_in_buffer, adjusted_playback_rate);
728732
SB_DCHECK(decoded_audio);
729733

730734
{
731735
std::lock_guard lock(mutex_);
732736
if (decoded_audio->frames() == 0 && eos_state_ == kEOSDecoded) {
733737
eos_state_ = kEOSSentToSink;
734738
}
735-
audio_frame_tracker_.AddFrames(decoded_audio->frames(), playback_rate_);
739+
audio_frame_tracker_.AddFrames(decoded_audio->frames(),
740+
adjusted_playback_rate);
736741
}
737742

738743
// |time_stretcher_| only support kSbMediaAudioSampleTypeFloat32 and

starboard/shared/starboard/player/filter/audio_renderer_sink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class AudioRendererSink {
6868
virtual void SetPlaybackRate(double playback_rate) = 0;
6969

7070
virtual bool AllowOverflowAudioSamples() const { return false; }
71+
virtual bool AllowDirectPlaybackRateSetting() const { return false; }
7172
};
7273

7374
} // namespace starboard

0 commit comments

Comments
 (0)