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 android.media.AudioTrack#getTimestamp(android.media.AudioTimestamp) 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 public static final int AUDIO_ADJUST_MODE_STRETCH = 1; 142 143 /** 144 * Resample audio when playback rate must be adjusted. 145 * <p> 146 * This will make audio play faster or slower as required by the sync source 147 * by changing its pitch (making it lower to play slower, and higher to play 148 * faster.) 149 */ 150 public static final int AUDIO_ADJUST_MODE_RESAMPLE = 2; 151 152 // flags to indicate which params are actually set 153 private static final int SET_SYNC_SOURCE = 1 << 0; 154 private static final int SET_AUDIO_ADJUST_MODE = 1 << 1; 155 private static final int SET_TOLERANCE = 1 << 2; 156 private static final int SET_FRAME_RATE = 1 << 3; 157 private int mSet = 0; 158 159 // params 160 private int mAudioAdjustMode = AUDIO_ADJUST_MODE_DEFAULT; 161 private int mSyncSource = SYNC_SOURCE_DEFAULT; 162 private float mTolerance = 0.f; 163 private float mFrameRate = 0.f; 164 165 /** 166 * Allows defaults to be returned for properties not set. 167 * Otherwise a {@link java.lang.IllegalArgumentException} exception 168 * is raised when getting those properties 169 * which have defaults but have never been set. 170 * @return this <code>SyncParams</code> instance. 171 */ allowDefaults()172 public SyncParams allowDefaults() { 173 mSet |= SET_SYNC_SOURCE | SET_AUDIO_ADJUST_MODE | SET_TOLERANCE; 174 return this; 175 } 176 177 /** 178 * Sets the audio adjust mode. 179 * @param audioAdjustMode 180 * @return this <code>SyncParams</code> instance. 181 */ setAudioAdjustMode(@udioAdjustMode int audioAdjustMode)182 public SyncParams setAudioAdjustMode(@AudioAdjustMode int audioAdjustMode) { 183 mAudioAdjustMode = audioAdjustMode; 184 mSet |= SET_AUDIO_ADJUST_MODE; 185 return this; 186 } 187 188 /** 189 * Retrieves the audio adjust mode. 190 * @return audio adjust mode 191 * @throws IllegalStateException if the audio adjust mode is not set. 192 */ getAudioAdjustMode()193 public @AudioAdjustMode int getAudioAdjustMode() { 194 if ((mSet & SET_AUDIO_ADJUST_MODE) == 0) { 195 throw new IllegalStateException("audio adjust mode not set"); 196 } 197 return mAudioAdjustMode; 198 } 199 200 /** 201 * Sets the sync source. 202 * @param syncSource 203 * @return this <code>SyncParams</code> instance. 204 */ setSyncSource(@yncSource int syncSource)205 public SyncParams setSyncSource(@SyncSource int syncSource) { 206 mSyncSource = syncSource; 207 mSet |= SET_SYNC_SOURCE; 208 return this; 209 } 210 211 /** 212 * Retrieves the sync source. 213 * @return sync source 214 * @throws IllegalStateException if the sync source is not set. 215 */ getSyncSource()216 public @SyncSource int getSyncSource() { 217 if ((mSet & SET_SYNC_SOURCE) == 0) { 218 throw new IllegalStateException("sync source not set"); 219 } 220 return mSyncSource; 221 } 222 223 /** 224 * Sets the tolerance. The default tolerance is platform specific, but is never more than 1/24. 225 * @param tolerance A non-negative number representing 226 * the maximum deviation of the playback rate from the playback rate 227 * set. ({@code abs(actual_rate - set_rate) / set_rate}) 228 * @return this <code>SyncParams</code> instance. 229 * @throws IllegalArgumentException if the tolerance is negative, or not less than one. 230 */ setTolerance(float tolerance)231 public SyncParams setTolerance(float tolerance) { 232 if (tolerance < 0.f || tolerance >= 1.f) { 233 throw new IllegalArgumentException("tolerance must be less than one and non-negative"); 234 } 235 mTolerance = tolerance; 236 mSet |= SET_TOLERANCE; 237 return this; 238 } 239 240 /** 241 * Retrieves the tolerance factor. 242 * @return tolerance factor. A non-negative number representing 243 * the maximum deviation of the playback rate from the playback rate 244 * set. ({@code abs(actual_rate - set_rate) / set_rate}) 245 * @throws IllegalStateException if tolerance is not set. 246 */ getTolerance()247 public float getTolerance() { 248 if ((mSet & SET_TOLERANCE) == 0) { 249 throw new IllegalStateException("tolerance not set"); 250 } 251 return mTolerance; 252 } 253 254 /** 255 * Sets the video frame rate hint to be used. By default the frame rate is unspecified. 256 * @param frameRate A non-negative number used as an initial hint on 257 * the video frame rate to be used when using vsync as the sync source. A negative 258 * number is used to clear a previous hint. 259 * @return this <code>SyncParams</code> instance. 260 */ setFrameRate(float frameRate)261 public SyncParams setFrameRate(float frameRate) { 262 mFrameRate = frameRate; 263 mSet |= SET_FRAME_RATE; 264 return this; 265 } 266 267 /** 268 * Retrieves the video frame rate hint. 269 * @return frame rate factor. A non-negative number representing 270 * the maximum deviation of the playback rate from the playback rate 271 * set. ({@code abs(actual_rate - set_rate) / set_rate}), or a negative 272 * number representing the desire to clear a previous hint using these params. 273 * @throws IllegalStateException if frame rate is not set. 274 */ getFrameRate()275 public float getFrameRate() { 276 if ((mSet & SET_FRAME_RATE) == 0) { 277 throw new IllegalStateException("frame rate not set"); 278 } 279 return mFrameRate; 280 } 281 282 } 283