这是indexloc提供的服务,不要输入任何密码
Skip to content

OnRoutingChangedListenerApi24::onRoutingChanged takes too long in ExoPlayer:ExoPlayer:Playback thread, result doSomeWork can not render frames timely. #2646

@jinqiang-amzn

Description

@jinqiang-amzn

Version

Media3 main branch

More version details

Issue

In the class OnRoutingChangedListenerApi24 of DefaultAudioSink.java

  private static final class OnRoutingChangedListenerApi24 {

    private final AudioTrack audioTrack;
    private final AudioCapabilitiesReceiver capabilitiesReceiver;

    @Nullable private OnRoutingChangedListener listener;

    public OnRoutingChangedListenerApi24(
        AudioTrack audioTrack, AudioCapabilitiesReceiver capabilitiesReceiver) {
      this.audioTrack = audioTrack;
      this.capabilitiesReceiver = capabilitiesReceiver;
      this.listener = this::onRoutingChanged;
      // the following line gets handler of ExoPlayer:Playback thread
      Handler handler = new Handler(Looper.myLooper());
      audioTrack.addOnRoutingChangedListener(listener, handler);
    }

    public void release() {
      audioTrack.removeOnRoutingChangedListener(checkNotNull(listener));
      listener = null;
    }

    private void onRoutingChanged(AudioRouting router) {
      if (listener == null) {
        // Stale event.
        return;
      }
      @Nullable AudioDeviceInfo routedDevice = router.getRoutedDevice();
      if (routedDevice != null) {
        capabilitiesReceiver.setRoutedDevice(routedDevice);
      }
    }
  }

It sets the handler of ExoPlayer:Playback thread (via Looper.myLooper()) to audioTrack.addOnRoutingChangedListener.

When playing content with ddp audiotrack in offload mode, the onRoutingChanged will be triggered at the first few secs of the playback.

perfetto trace of the issue: androidxmedia3.original.perfetto.trace.zip
Image

When onRoutingChanged takes too long in ExoPlayer:Playback thread, the next doSomeWork has to drop frames since the rendering timestamp are too late.


Optimize propose:

We suggest create a new thread to handle the callback of routing changed

    public OnRoutingChangedListenerApi24(
        AudioTrack audioTrack, AudioCapabilitiesReceiver capabilitiesReceiver) {
      this.audioTrack = audioTrack;
      this.capabilitiesReceiver = capabilitiesReceiver;
      this.listener = this::onRoutingChanged;
      if (routingChangedHandlerThread == null) {
        routingChangedHandlerThread =
            new HandlerThread("ExoPlayer:RoutingChangedHandler", Process.THREAD_PRIORITY_AUDIO);
        routingChangedHandlerThread.start();
      }
      Handler handler = new Handler(routingChangedHandlerThread.getLooper());
      audioTrack.addOnRoutingChangedListener(listener, handler);
    }

perfetto trace of the optimize modification: androidxmedia3.optimized.perfetto.trace.zip
Image

And from our verification with the proposed modification, no more frames dropped are observed at the initial playback.

Devices that reproduce the issue

Amazon Fire TV devices.

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Yes

Reproduction steps

  1. Paying the content with ddp audio track.
  2. When the onRoutingChangedListener of AudioTrack is triggered at the beginning of the playback, onRoutingChanged takes too long in ExoPlayer:Playback thread, the next doSomeWork has to drop frames since the rendering timestamp are too late.

Expected result

The playback should be smooth.

Actual result

Observes visual stutter at the initial playback.

Media

The contents with ddp audio track.

Bug Report

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions