1 /*
2  * Copyright 2015 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 
17 package android.media;
18 
19 import java.lang.annotation.Retention;
20 import java.lang.annotation.RetentionPolicy;
21 
22 import android.annotation.IntDef;
23 
24 /**
25  * Structure for common A/V sync params.
26  *
27  * Used by {@link MediaSync} {link MediaSync#getSyncParams()} and
28  * {link MediaSync#setSyncParams(SyncParams)}
29  * to control A/V sync behavior.
30  * <p> <strong>audio adjust mode:</strong>
31  * select handling of audio track when changing playback speed due to sync.
32  * <ul>
33  * <li> {@link SyncParams#AUDIO_ADJUST_MODE_DEFAULT}:
34  *   System will determine best handling. </li>
35  * <li> {@link SyncParams#AUDIO_ADJUST_MODE_STRETCH}:
36  *   Change the speed of audio playback without altering its pitch.</li>
37  * <li> {@link SyncParams#AUDIO_ADJUST_MODE_RESAMPLE}:
38  *   Change the speed of audio playback by resampling the audio.</li>
39  * </ul>
40  * <p> <strong>sync source:</strong> select
41  * clock source for sync.
42  * <ul>
43  * <li> {@link SyncParams#SYNC_SOURCE_DEFAULT}:
44  *   System will determine best selection.</li>
45  * <li> {@link SyncParams#SYNC_SOURCE_SYSTEM_CLOCK}:
46  *   Use system clock for sync source.</li>
47  * <li> {@link SyncParams#SYNC_SOURCE_AUDIO}:
48  *   Use audio track for sync source.</li>
49  * <li> {@link SyncParams#SYNC_SOURCE_VSYNC}:
50  *   Syncronize media to vsync.</li>
51  * </ul>
52  * <p> <strong>tolerance:</strong> specifies the amount of allowed playback rate
53  * change to keep media in sync with the sync source. The handling of this depends
54  * on the sync source, but must not be negative, and must be less than one.
55  * <p> <strong>frameRate:</strong> initial hint for video frame rate. Used when
56  * sync source is vsync. Negative values can be used to clear a previous hint.
57  */
58 public final class SyncParams {
59     /** @hide */
60     @IntDef(
61         value = {
62                 SYNC_SOURCE_DEFAULT,
63                 SYNC_SOURCE_SYSTEM_CLOCK,
64                 SYNC_SOURCE_AUDIO,
65                 SYNC_SOURCE_VSYNC,
66         }
67     )
68     @Retention(RetentionPolicy.SOURCE)
69     public @interface SyncSource {}
70 
71     /**
72      * Use the default sync source (default). If media has video, the sync renders to a
73      * surface that directly renders to a display, and tolerance is non zero (e.g. not
74      * less than 0.001) vsync source is used for clock source.  Otherwise, if media has
75      * audio, audio track is used. Finally, if media has no audio, system clock is used.
76      */
77     public static final int SYNC_SOURCE_DEFAULT = 0;
78 
79     /**
80      * Use system monotonic clock for sync source.
81      *
82      * @see System#nanoTime
83      */
84     public static final int SYNC_SOURCE_SYSTEM_CLOCK = 1;
85 
86     /**
87      * Use audio track for sync source. This requires audio data and an audio track.
88      *
89      * @see AudioTrack#getTimeStamp
90      */
91     public static final int SYNC_SOURCE_AUDIO = 2;
92 
93     /**
94      * Use vsync as the sync source. This requires video data and an output surface that
95      * directly renders to the display, e.g. {@link android.view.SurfaceView}
96      * <p>
97      * This mode allows smoother playback experience by adjusting the playback speed
98      * to match the vsync rate, e.g. playing 30fps content on a 59.94Hz display.
99      * When using this mode, the tolerance should be set to greater than 0 (e.g. at least
100      * 1/1000), so that the playback speed can actually be adjusted.
101      * <p>
102      * This mode can also be used to play 25fps content on a 60Hz display using
103      * a 2:3 pulldown (basically playing the content at 24fps), which results on
104      * better playback experience on most devices. In this case the tolerance should be
105      * at least (1/24).
106      *
107      * @see android.view.Choreographer.FrameCallback#doFrame
108      * @see android.view.Display#getAppVsyncOffsetNanos
109      */
110     public static final int SYNC_SOURCE_VSYNC = 3;
111 
112     /** @hide */
113     @IntDef(
114         value = {
115                 AUDIO_ADJUST_MODE_DEFAULT,
116                 AUDIO_ADJUST_MODE_STRETCH,
117                 AUDIO_ADJUST_MODE_RESAMPLE,
118         }
119     )
120     @Retention(RetentionPolicy.SOURCE)
121     public @interface AudioAdjustMode {}
122 
123     /**
124      * System will determine best handling of audio for playback rate
125      * adjustments.
126      * <p>
127      * Used by default. This will make audio play faster or slower as required
128      * by the sync source without changing its pitch; however, system may fall
129      * back to some other method (e.g. change the pitch, or mute the audio) if
130      * time stretching is no longer supported for the playback rate.
131      */
132     public static final int AUDIO_ADJUST_MODE_DEFAULT = 0;
133 
134     /**
135      * Time stretch audio when playback rate must be adjusted.
136      * <p>
137      * This will make audio play faster or slower as required by the sync source
138      * without changing its pitch, as long as it is supported for the playback
139      * rate.
140      *
141      * @see MediaSync#PLAYBACK_RATE_AUDIO_MODE_STRETCH
142      * @see MediaPlayer#PLAYBACK_RATE_AUDIO_MODE_STRETCH
143      */
144     public static final int AUDIO_ADJUST_MODE_STRETCH = 1;
145 
146     /**
147      * Resample audio when playback rate must be adjusted.
148      * <p>
149      * This will make audio play faster or slower as required by the sync source
150      * by changing its pitch (making it lower to play slower, and higher to play
151      * faster.)
152      *
153      * @see MediaSync#PLAYBACK_RATE_AUDIO_MODE_RESAMPLE
154      * @see MediaPlayer#PLAYBACK_RATE_AUDIO_MODE_RESAMPLE
155      */
156     public static final int AUDIO_ADJUST_MODE_RESAMPLE = 2;
157 
158     // flags to indicate which params are actually set
159     private static final int SET_SYNC_SOURCE         = 1 << 0;
160     private static final int SET_AUDIO_ADJUST_MODE   = 1 << 1;
161     private static final int SET_TOLERANCE           = 1 << 2;
162     private static final int SET_FRAME_RATE          = 1 << 3;
163     private int mSet = 0;
164 
165     // params
166     private int mAudioAdjustMode = AUDIO_ADJUST_MODE_DEFAULT;
167     private int mSyncSource = SYNC_SOURCE_DEFAULT;
168     private float mTolerance = 0.f;
169     private float mFrameRate = 0.f;
170 
171     /**
172      * Allows defaults to be returned for properties not set.
173      * Otherwise a {@link java.lang.IllegalArgumentException} exception
174      * is raised when getting those properties
175      * which have defaults but have never been set.
176      * @return this <code>SyncParams</code> instance.
177      */
allowDefaults()178     public SyncParams allowDefaults() {
179         mSet |= SET_SYNC_SOURCE | SET_AUDIO_ADJUST_MODE | SET_TOLERANCE;
180         return this;
181     }
182 
183     /**
184      * Sets the audio adjust mode.
185      * @param audioAdjustMode
186      * @return this <code>SyncParams</code> instance.
187      */
setAudioAdjustMode(@udioAdjustMode int audioAdjustMode)188     public SyncParams setAudioAdjustMode(@AudioAdjustMode int audioAdjustMode) {
189         mAudioAdjustMode = audioAdjustMode;
190         mSet |= SET_AUDIO_ADJUST_MODE;
191         return this;
192     }
193 
194     /**
195      * Retrieves the audio adjust mode.
196      * @return audio adjust mode
197      * @throws IllegalStateException if the audio adjust mode is not set.
198      */
getAudioAdjustMode()199     public @AudioAdjustMode int getAudioAdjustMode() {
200         if ((mSet & SET_AUDIO_ADJUST_MODE) == 0) {
201             throw new IllegalStateException("audio adjust mode not set");
202         }
203         return mAudioAdjustMode;
204     }
205 
206     /**
207      * Sets the sync source.
208      * @param syncSource
209      * @return this <code>SyncParams</code> instance.
210      */
setSyncSource(@yncSource int syncSource)211     public SyncParams setSyncSource(@SyncSource int syncSource) {
212         mSyncSource = syncSource;
213         mSet |= SET_SYNC_SOURCE;
214         return this;
215     }
216 
217     /**
218      * Retrieves the sync source.
219      * @return sync source
220      * @throws IllegalStateException if the sync source is not set.
221      */
getSyncSource()222     public @SyncSource int getSyncSource() {
223         if ((mSet & SET_SYNC_SOURCE) == 0) {
224             throw new IllegalStateException("sync source not set");
225         }
226         return mSyncSource;
227     }
228 
229     /**
230      * Sets the tolerance. The default tolerance is platform specific, but is never more than 1/24.
231      * @param tolerance A non-negative number representing
232      *     the maximum deviation of the playback rate from the playback rate
233      *     set. ({@code abs(actual_rate - set_rate) / set_rate})
234      * @return this <code>SyncParams</code> instance.
235      * @throws InvalidArgumentException if the tolerance is negative, or not less than one
236      */
setTolerance(float tolerance)237     public SyncParams setTolerance(float tolerance) {
238         if (tolerance < 0.f || tolerance >= 1.f) {
239             throw new IllegalArgumentException("tolerance must be less than one and non-negative");
240         }
241         mTolerance = tolerance;
242         mSet |= SET_TOLERANCE;
243         return this;
244     }
245 
246     /**
247      * Retrieves the tolerance factor.
248      * @return tolerance factor. A non-negative number representing
249      *     the maximum deviation of the playback rate from the playback rate
250      *     set. ({@code abs(actual_rate - set_rate) / set_rate})
251      * @throws IllegalStateException if tolerance is not set.
252      */
getTolerance()253     public float getTolerance() {
254         if ((mSet & SET_TOLERANCE) == 0) {
255             throw new IllegalStateException("tolerance not set");
256         }
257         return mTolerance;
258     }
259 
260     /**
261      * Sets the video frame rate hint to be used. By default the frame rate is unspecified.
262      * @param frameRate A non-negative number used as an initial hint on
263      *     the video frame rate to be used when using vsync as the sync source. A negative
264      *     number is used to clear a previous hint.
265      * @return this <code>SyncParams</code> instance.
266      */
setFrameRate(float frameRate)267     public SyncParams setFrameRate(float frameRate) {
268         mFrameRate = frameRate;
269         mSet |= SET_FRAME_RATE;
270         return this;
271     }
272 
273     /**
274      * Retrieves the video frame rate hint.
275      * @return frame rate factor. A non-negative number representing
276      *     the maximum deviation of the playback rate from the playback rate
277      *     set. ({@code abs(actual_rate - set_rate) / set_rate}), or a negative
278      *     number representing the desire to clear a previous hint using these params.
279      * @throws IllegalStateException if frame rate is not set.
280      */
getFrameRate()281     public float getFrameRate() {
282         if ((mSet & SET_FRAME_RATE) == 0) {
283             throw new IllegalStateException("frame rate not set");
284         }
285         return mFrameRate;
286     }
287 
288 }
289