/* * Copyright 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.media; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import android.annotation.IntDef; /** * Structure for common A/V sync params. * * Used by {@link MediaSync} {link MediaSync#getSyncParams()} and * {link MediaSync#setSyncParams(SyncParams)} * to control A/V sync behavior. *
audio adjust mode: * select handling of audio track when changing playback speed due to sync. *
sync source: select * clock source for sync. *
tolerance: specifies the amount of allowed playback rate * change to keep media in sync with the sync source. The handling of this depends * on the sync source, but must not be negative, and must be less than one. *
frameRate: initial hint for video frame rate. Used when * sync source is vsync. Negative values can be used to clear a previous hint. */ public final class SyncParams { /** @hide */ @IntDef( value = { SYNC_SOURCE_DEFAULT, SYNC_SOURCE_SYSTEM_CLOCK, SYNC_SOURCE_AUDIO, SYNC_SOURCE_VSYNC, } ) @Retention(RetentionPolicy.SOURCE) public @interface SyncSource {} /** * Use the default sync source (default). If media has video, the sync renders to a * surface that directly renders to a display, and tolerance is non zero (e.g. not * less than 0.001) vsync source is used for clock source. Otherwise, if media has * audio, audio track is used. Finally, if media has no audio, system clock is used. */ public static final int SYNC_SOURCE_DEFAULT = 0; /** * Use system monotonic clock for sync source. * * @see System#nanoTime */ public static final int SYNC_SOURCE_SYSTEM_CLOCK = 1; /** * Use audio track for sync source. This requires audio data and an audio track. * * @see AudioTrack#getTimeStamp */ public static final int SYNC_SOURCE_AUDIO = 2; /** * Use vsync as the sync source. This requires video data and an output surface that * directly renders to the display, e.g. {@link android.view.SurfaceView} *
* This mode allows smoother playback experience by adjusting the playback speed * to match the vsync rate, e.g. playing 30fps content on a 59.94Hz display. * When using this mode, the tolerance should be set to greater than 0 (e.g. at least * 1/1000), so that the playback speed can actually be adjusted. *
* This mode can also be used to play 25fps content on a 60Hz display using * a 2:3 pulldown (basically playing the content at 24fps), which results on * better playback experience on most devices. In this case the tolerance should be * at least (1/24). * * @see android.view.Choreographer.FrameCallback#doFrame * @see android.view.Display#getAppVsyncOffsetNanos */ public static final int SYNC_SOURCE_VSYNC = 3; /** @hide */ @IntDef( value = { AUDIO_ADJUST_MODE_DEFAULT, AUDIO_ADJUST_MODE_STRETCH, AUDIO_ADJUST_MODE_RESAMPLE, } ) @Retention(RetentionPolicy.SOURCE) public @interface AudioAdjustMode {} /** * System will determine best handling of audio for playback rate * adjustments. *
* Used by default. This will make audio play faster or slower as required * by the sync source without changing its pitch; however, system may fall * back to some other method (e.g. change the pitch, or mute the audio) if * time stretching is no longer supported for the playback rate. */ public static final int AUDIO_ADJUST_MODE_DEFAULT = 0; /** * Time stretch audio when playback rate must be adjusted. *
* This will make audio play faster or slower as required by the sync source * without changing its pitch, as long as it is supported for the playback * rate. * * @see MediaSync#PLAYBACK_RATE_AUDIO_MODE_STRETCH * @see MediaPlayer#PLAYBACK_RATE_AUDIO_MODE_STRETCH */ public static final int AUDIO_ADJUST_MODE_STRETCH = 1; /** * Resample audio when playback rate must be adjusted. *
* This will make audio play faster or slower as required by the sync source
* by changing its pitch (making it lower to play slower, and higher to play
* faster.)
*
* @see MediaSync#PLAYBACK_RATE_AUDIO_MODE_RESAMPLE
* @see MediaPlayer#PLAYBACK_RATE_AUDIO_MODE_RESAMPLE
*/
public static final int AUDIO_ADJUST_MODE_RESAMPLE = 2;
// flags to indicate which params are actually set
private static final int SET_SYNC_SOURCE = 1 << 0;
private static final int SET_AUDIO_ADJUST_MODE = 1 << 1;
private static final int SET_TOLERANCE = 1 << 2;
private static final int SET_FRAME_RATE = 1 << 3;
private int mSet = 0;
// params
private int mAudioAdjustMode = AUDIO_ADJUST_MODE_DEFAULT;
private int mSyncSource = SYNC_SOURCE_DEFAULT;
private float mTolerance = 0.f;
private float mFrameRate = 0.f;
/**
* Allows defaults to be returned for properties not set.
* Otherwise a {@link java.lang.IllegalArgumentException} exception
* is raised when getting those properties
* which have defaults but have never been set.
* @return this SyncParams
instance.
*/
public SyncParams allowDefaults() {
mSet |= SET_SYNC_SOURCE | SET_AUDIO_ADJUST_MODE | SET_TOLERANCE;
return this;
}
/**
* Sets the audio adjust mode.
* @param audioAdjustMode
* @return this SyncParams
instance.
*/
public SyncParams setAudioAdjustMode(@AudioAdjustMode int audioAdjustMode) {
mAudioAdjustMode = audioAdjustMode;
mSet |= SET_AUDIO_ADJUST_MODE;
return this;
}
/**
* Retrieves the audio adjust mode.
* @return audio adjust mode
* @throws IllegalStateException if the audio adjust mode is not set.
*/
public @AudioAdjustMode int getAudioAdjustMode() {
if ((mSet & SET_AUDIO_ADJUST_MODE) == 0) {
throw new IllegalStateException("audio adjust mode not set");
}
return mAudioAdjustMode;
}
/**
* Sets the sync source.
* @param syncSource
* @return this SyncParams
instance.
*/
public SyncParams setSyncSource(@SyncSource int syncSource) {
mSyncSource = syncSource;
mSet |= SET_SYNC_SOURCE;
return this;
}
/**
* Retrieves the sync source.
* @return sync source
* @throws IllegalStateException if the sync source is not set.
*/
public @SyncSource int getSyncSource() {
if ((mSet & SET_SYNC_SOURCE) == 0) {
throw new IllegalStateException("sync source not set");
}
return mSyncSource;
}
/**
* Sets the tolerance. The default tolerance is platform specific, but is never more than 1/24.
* @param tolerance A non-negative number representing
* the maximum deviation of the playback rate from the playback rate
* set. ({@code abs(actual_rate - set_rate) / set_rate})
* @return this SyncParams
instance.
* @throws InvalidArgumentException if the tolerance is negative, or not less than one
*/
public SyncParams setTolerance(float tolerance) {
if (tolerance < 0.f || tolerance >= 1.f) {
throw new IllegalArgumentException("tolerance must be less than one and non-negative");
}
mTolerance = tolerance;
mSet |= SET_TOLERANCE;
return this;
}
/**
* Retrieves the tolerance factor.
* @return tolerance factor. A non-negative number representing
* the maximum deviation of the playback rate from the playback rate
* set. ({@code abs(actual_rate - set_rate) / set_rate})
* @throws IllegalStateException if tolerance is not set.
*/
public float getTolerance() {
if ((mSet & SET_TOLERANCE) == 0) {
throw new IllegalStateException("tolerance not set");
}
return mTolerance;
}
/**
* Sets the video frame rate hint to be used. By default the frame rate is unspecified.
* @param frameRate A non-negative number used as an initial hint on
* the video frame rate to be used when using vsync as the sync source. A negative
* number is used to clear a previous hint.
* @return this SyncParams
instance.
*/
public SyncParams setFrameRate(float frameRate) {
mFrameRate = frameRate;
mSet |= SET_FRAME_RATE;
return this;
}
/**
* Retrieves the video frame rate hint.
* @return frame rate factor. A non-negative number representing
* the maximum deviation of the playback rate from the playback rate
* set. ({@code abs(actual_rate - set_rate) / set_rate}), or a negative
* number representing the desire to clear a previous hint using these params.
* @throws IllegalStateException if frame rate is not set.
*/
public float getFrameRate() {
if ((mSet & SET_FRAME_RATE) == 0) {
throw new IllegalStateException("frame rate not set");
}
return mFrameRate;
}
}