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