• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.android.exoplayer2.audio;
17 
18 import static com.google.android.exoplayer2.util.Util.castNonNull;
19 
20 import android.os.Handler;
21 import android.os.SystemClock;
22 import androidx.annotation.Nullable;
23 import com.google.android.exoplayer2.C;
24 import com.google.android.exoplayer2.Format;
25 import com.google.android.exoplayer2.Renderer;
26 import com.google.android.exoplayer2.decoder.DecoderCounters;
27 import com.google.android.exoplayer2.util.Assertions;
28 
29 /**
30  * Listener of audio {@link Renderer} events. All methods have no-op default implementations to
31  * allow selective overrides.
32  */
33 public interface AudioRendererEventListener {
34 
35   /**
36    * Called when the renderer is enabled.
37    *
38    * @param counters {@link DecoderCounters} that will be updated by the renderer for as long as it
39    *     remains enabled.
40    */
onAudioEnabled(DecoderCounters counters)41   default void onAudioEnabled(DecoderCounters counters) {}
42 
43   /**
44    * Called when the audio session is set.
45    *
46    * @param audioSessionId The audio session id.
47    */
onAudioSessionId(int audioSessionId)48   default void onAudioSessionId(int audioSessionId) {}
49 
50   /**
51    * Called when a decoder is created.
52    *
53    * @param decoderName The decoder that was created.
54    * @param initializedTimestampMs {@link SystemClock#elapsedRealtime()} when initialization
55    *     finished.
56    * @param initializationDurationMs The time taken to initialize the decoder in milliseconds.
57    */
onAudioDecoderInitialized( String decoderName, long initializedTimestampMs, long initializationDurationMs)58   default void onAudioDecoderInitialized(
59       String decoderName, long initializedTimestampMs, long initializationDurationMs) {}
60 
61   /**
62    * Called when the format of the media being consumed by the renderer changes.
63    *
64    * @param format The new format.
65    */
onAudioInputFormatChanged(Format format)66   default void onAudioInputFormatChanged(Format format) {}
67 
68   /**
69    * Called when an {@link AudioSink} underrun occurs.
70    *
71    * @param bufferSize The size of the {@link AudioSink}'s buffer, in bytes.
72    * @param bufferSizeMs The size of the {@link AudioSink}'s buffer, in milliseconds, if it is
73    *     configured for PCM output. {@link C#TIME_UNSET} if it is configured for passthrough output,
74    *     as the buffered media can have a variable bitrate so the duration may be unknown.
75    * @param elapsedSinceLastFeedMs The time since the {@link AudioSink} was last fed data.
76    */
onAudioSinkUnderrun( int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs)77   default void onAudioSinkUnderrun(
78       int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {}
79 
80   /**
81    * Called when the renderer is disabled.
82    *
83    * @param counters {@link DecoderCounters} that were updated by the renderer.
84    */
onAudioDisabled(DecoderCounters counters)85   default void onAudioDisabled(DecoderCounters counters) {}
86 
87   /**
88    * Called when skipping silences is enabled or disabled in the audio stream.
89    *
90    * @param skipSilenceEnabled Whether skipping silences in the audio stream is enabled.
91    */
onSkipSilenceEnabledChanged(boolean skipSilenceEnabled)92   default void onSkipSilenceEnabledChanged(boolean skipSilenceEnabled) {}
93 
94   /** Dispatches events to a {@link AudioRendererEventListener}. */
95   final class EventDispatcher {
96 
97     @Nullable private final Handler handler;
98     @Nullable private final AudioRendererEventListener listener;
99 
100     /**
101      * @param handler A handler for dispatching events, or null if creating a dummy instance.
102      * @param listener The listener to which events should be dispatched, or null if creating a
103      *     dummy instance.
104      */
EventDispatcher(@ullable Handler handler, @Nullable AudioRendererEventListener listener)105     public EventDispatcher(@Nullable Handler handler,
106         @Nullable AudioRendererEventListener listener) {
107       this.handler = listener != null ? Assertions.checkNotNull(handler) : null;
108       this.listener = listener;
109     }
110 
111     /**
112      * Invokes {@link AudioRendererEventListener#onAudioEnabled(DecoderCounters)}.
113      */
enabled(final DecoderCounters decoderCounters)114     public void enabled(final DecoderCounters decoderCounters) {
115       if (handler != null) {
116         handler.post(() -> castNonNull(listener).onAudioEnabled(decoderCounters));
117       }
118     }
119 
120     /**
121      * Invokes {@link AudioRendererEventListener#onAudioDecoderInitialized(String, long, long)}.
122      */
decoderInitialized(final String decoderName, final long initializedTimestampMs, final long initializationDurationMs)123     public void decoderInitialized(final String decoderName,
124         final long initializedTimestampMs, final long initializationDurationMs) {
125       if (handler != null) {
126         handler.post(
127             () ->
128                 castNonNull(listener)
129                     .onAudioDecoderInitialized(
130                         decoderName, initializedTimestampMs, initializationDurationMs));
131       }
132     }
133 
134     /**
135      * Invokes {@link AudioRendererEventListener#onAudioInputFormatChanged(Format)}.
136      */
inputFormatChanged(final Format format)137     public void inputFormatChanged(final Format format) {
138       if (handler != null) {
139         handler.post(() -> castNonNull(listener).onAudioInputFormatChanged(format));
140       }
141     }
142 
143     /**
144      * Invokes {@link AudioRendererEventListener#onAudioSinkUnderrun(int, long, long)}.
145      */
audioTrackUnderrun(final int bufferSize, final long bufferSizeMs, final long elapsedSinceLastFeedMs)146     public void audioTrackUnderrun(final int bufferSize, final long bufferSizeMs,
147         final long elapsedSinceLastFeedMs) {
148       if (handler != null) {
149         handler.post(
150             () ->
151                 castNonNull(listener)
152                     .onAudioSinkUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs));
153       }
154     }
155 
156     /**
157      * Invokes {@link AudioRendererEventListener#onAudioDisabled(DecoderCounters)}.
158      */
disabled(final DecoderCounters counters)159     public void disabled(final DecoderCounters counters) {
160       counters.ensureUpdated();
161       if (handler != null) {
162         handler.post(
163             () -> {
164               counters.ensureUpdated();
165               castNonNull(listener).onAudioDisabled(counters);
166             });
167       }
168     }
169 
170     /**
171      * Invokes {@link AudioRendererEventListener#onAudioSessionId(int)}.
172      */
audioSessionId(final int audioSessionId)173     public void audioSessionId(final int audioSessionId) {
174       if (handler != null) {
175         handler.post(() -> castNonNull(listener).onAudioSessionId(audioSessionId));
176       }
177     }
178 
179     /** Invokes {@link AudioRendererEventListener#onSkipSilenceEnabledChanged(boolean)}. */
skipSilenceEnabledChanged(final boolean skipSilenceEnabled)180     public void skipSilenceEnabledChanged(final boolean skipSilenceEnabled) {
181       if (handler != null) {
182         handler.post(() -> castNonNull(listener).onSkipSilenceEnabledChanged(skipSilenceEnabled));
183       }
184     }
185   }
186 }
187