| /* |
| * Copyright 2017 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 android.annotation.IntDef; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| |
| /** |
| * Structure for source buffering management params. |
| * |
| * Used by {@link MediaPlayer#getDefaultBufferingParams()}, |
| * {@link MediaPlayer#getBufferingParams()} and |
| * {@link MediaPlayer#setBufferingParams(BufferingParams)} |
| * to control source buffering behavior. |
| * |
| * <p>There are two stages of source buffering in {@link MediaPlayer}: initial buffering |
| * (when {@link MediaPlayer} is being prepared) and rebuffering (when {@link MediaPlayer} |
| * is playing back source). {@link BufferingParams} includes mode and corresponding |
| * watermarks for each stage of source buffering. The watermarks could be either size |
| * based (in milliseconds), or time based (in kilobytes) or both, depending on the mode. |
| * |
| * <p>There are 4 buffering modes: {@link #BUFFERING_MODE_NONE}, |
| * {@link #BUFFERING_MODE_TIME_ONLY}, {@link #BUFFERING_MODE_SIZE_ONLY} and |
| * {@link #BUFFERING_MODE_TIME_THEN_SIZE}. |
| * {@link MediaPlayer} source component has default buffering modes which can be queried |
| * by calling {@link MediaPlayer#getDefaultBufferingParams()}. |
| * Users should always use those default modes or their downsized version when trying to |
| * change buffering params. For example, {@link #BUFFERING_MODE_TIME_THEN_SIZE} can be |
| * downsized to {@link #BUFFERING_MODE_NONE}, {@link #BUFFERING_MODE_TIME_ONLY} or |
| * {@link #BUFFERING_MODE_SIZE_ONLY}. But {@link #BUFFERING_MODE_TIME_ONLY} can not be |
| * downsized to {@link #BUFFERING_MODE_SIZE_ONLY}. |
| * <ul> |
| * <li><strong>initial buffering stage:</strong> has one watermark which is used when |
| * {@link MediaPlayer} is being prepared. When cached data amount exceeds this watermark, |
| * {@link MediaPlayer} is prepared.</li> |
| * <li><strong>rebuffering stage:</strong> has two watermarks, low and high, which are |
| * used when {@link MediaPlayer} is playing back content. |
| * <ul> |
| * <li> When cached data amount exceeds high watermark, {@link MediaPlayer} will pause |
| * buffering. Buffering will resume when cache runs below some limit which could be low |
| * watermark or some intermediate value decided by the source component.</li> |
| * <li> When cached data amount runs below low watermark, {@link MediaPlayer} will paused |
| * playback. Playback will resume when cached data amount exceeds high watermark |
| * or reaches end of stream.</li> |
| * </ul> |
| * </ul> |
| * <p>Users should use {@link Builder} to change {@link BufferingParams}. |
| * @hide |
| */ |
| public final class BufferingParams implements Parcelable { |
| /** |
| * This mode indicates that source buffering is not supported. |
| */ |
| public static final int BUFFERING_MODE_NONE = 0; |
| /** |
| * This mode indicates that only time based source buffering is supported. This means |
| * the watermark(s) are time based. |
| */ |
| public static final int BUFFERING_MODE_TIME_ONLY = 1; |
| /** |
| * This mode indicates that only size based source buffering is supported. This means |
| * the watermark(s) are size based. |
| */ |
| public static final int BUFFERING_MODE_SIZE_ONLY = 2; |
| /** |
| * This mode indicates that both time and size based source buffering are supported, |
| * and time based calculation precedes size based. Size based calculation will be used |
| * only when time information is not available from the source. |
| */ |
| public static final int BUFFERING_MODE_TIME_THEN_SIZE = 3; |
| |
| /** @hide */ |
| @IntDef( |
| value = { |
| BUFFERING_MODE_NONE, |
| BUFFERING_MODE_TIME_ONLY, |
| BUFFERING_MODE_SIZE_ONLY, |
| BUFFERING_MODE_TIME_THEN_SIZE, |
| } |
| ) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface BufferingMode {} |
| |
| private static final int BUFFERING_NO_WATERMARK = -1; |
| |
| // params |
| private int mInitialBufferingMode = BUFFERING_MODE_NONE; |
| private int mRebufferingMode = BUFFERING_MODE_NONE; |
| |
| private int mInitialWatermarkMs = BUFFERING_NO_WATERMARK; |
| private int mInitialWatermarkKB = BUFFERING_NO_WATERMARK; |
| |
| private int mRebufferingWatermarkLowMs = BUFFERING_NO_WATERMARK; |
| private int mRebufferingWatermarkHighMs = BUFFERING_NO_WATERMARK; |
| private int mRebufferingWatermarkLowKB = BUFFERING_NO_WATERMARK; |
| private int mRebufferingWatermarkHighKB = BUFFERING_NO_WATERMARK; |
| |
| private BufferingParams() { |
| } |
| |
| /** |
| * Return the initial buffering mode used when {@link MediaPlayer} is being prepared. |
| * @return one of the values that can be set in {@link Builder#setInitialBufferingMode(int)} |
| */ |
| public int getInitialBufferingMode() { |
| return mInitialBufferingMode; |
| } |
| |
| /** |
| * Return the rebuffering mode used when {@link MediaPlayer} is playing back source. |
| * @return one of the values that can be set in {@link Builder#setRebufferingMode(int)} |
| */ |
| public int getRebufferingMode() { |
| return mRebufferingMode; |
| } |
| |
| /** |
| * Return the time based initial buffering watermark in milliseconds. |
| * It is meaningful only when initial buffering mode obatined from |
| * {@link #getInitialBufferingMode()} is time based. |
| * @return time based initial buffering watermark in milliseconds |
| */ |
| public int getInitialBufferingWatermarkMs() { |
| return mInitialWatermarkMs; |
| } |
| |
| /** |
| * Return the size based initial buffering watermark in kilobytes. |
| * It is meaningful only when initial buffering mode obatined from |
| * {@link #getInitialBufferingMode()} is size based. |
| * @return size based initial buffering watermark in kilobytes |
| */ |
| public int getInitialBufferingWatermarkKB() { |
| return mInitialWatermarkKB; |
| } |
| |
| /** |
| * Return the time based low watermark in milliseconds for rebuffering. |
| * It is meaningful only when rebuffering mode obatined from |
| * {@link #getRebufferingMode()} is time based. |
| * @return time based low watermark for rebuffering in milliseconds |
| */ |
| public int getRebufferingWatermarkLowMs() { |
| return mRebufferingWatermarkLowMs; |
| } |
| |
| /** |
| * Return the time based high watermark in milliseconds for rebuffering. |
| * It is meaningful only when rebuffering mode obatined from |
| * {@link #getRebufferingMode()} is time based. |
| * @return time based high watermark for rebuffering in milliseconds |
| */ |
| public int getRebufferingWatermarkHighMs() { |
| return mRebufferingWatermarkHighMs; |
| } |
| |
| /** |
| * Return the size based low watermark in kilobytes for rebuffering. |
| * It is meaningful only when rebuffering mode obatined from |
| * {@link #getRebufferingMode()} is size based. |
| * @return size based low watermark for rebuffering in kilobytes |
| */ |
| public int getRebufferingWatermarkLowKB() { |
| return mRebufferingWatermarkLowKB; |
| } |
| |
| /** |
| * Return the size based high watermark in kilobytes for rebuffering. |
| * It is meaningful only when rebuffering mode obatined from |
| * {@link #getRebufferingMode()} is size based. |
| * @return size based high watermark for rebuffering in kilobytes |
| */ |
| public int getRebufferingWatermarkHighKB() { |
| return mRebufferingWatermarkHighKB; |
| } |
| |
| /** |
| * Builder class for {@link BufferingParams} objects. |
| * <p> Here is an example where <code>Builder</code> is used to define the |
| * {@link BufferingParams} to be used by a {@link MediaPlayer} instance: |
| * |
| * <pre class="prettyprint"> |
| * BufferingParams myParams = mediaplayer.getDefaultBufferingParams(); |
| * myParams = new BufferingParams.Builder(myParams) |
| * .setInitialBufferingWatermarkMs(10000) |
| * .build(); |
| * mediaplayer.setBufferingParams(myParams); |
| * </pre> |
| */ |
| public static class Builder { |
| private int mInitialBufferingMode = BUFFERING_MODE_NONE; |
| private int mRebufferingMode = BUFFERING_MODE_NONE; |
| |
| private int mInitialWatermarkMs = BUFFERING_NO_WATERMARK; |
| private int mInitialWatermarkKB = BUFFERING_NO_WATERMARK; |
| |
| private int mRebufferingWatermarkLowMs = BUFFERING_NO_WATERMARK; |
| private int mRebufferingWatermarkHighMs = BUFFERING_NO_WATERMARK; |
| private int mRebufferingWatermarkLowKB = BUFFERING_NO_WATERMARK; |
| private int mRebufferingWatermarkHighKB = BUFFERING_NO_WATERMARK; |
| |
| /** |
| * Constructs a new Builder with the defaults. |
| * By default, both initial buffering mode and rebuffering mode are |
| * {@link BufferingParams#BUFFERING_MODE_NONE}, and all watermarks are -1. |
| */ |
| public Builder() { |
| } |
| |
| /** |
| * Constructs a new Builder from a given {@link BufferingParams} instance |
| * @param bp the {@link BufferingParams} object whose data will be reused |
| * in the new Builder. |
| */ |
| public Builder(BufferingParams bp) { |
| mInitialBufferingMode = bp.mInitialBufferingMode; |
| mRebufferingMode = bp.mRebufferingMode; |
| |
| mInitialWatermarkMs = bp.mInitialWatermarkMs; |
| mInitialWatermarkKB = bp.mInitialWatermarkKB; |
| |
| mRebufferingWatermarkLowMs = bp.mRebufferingWatermarkLowMs; |
| mRebufferingWatermarkHighMs = bp.mRebufferingWatermarkHighMs; |
| mRebufferingWatermarkLowKB = bp.mRebufferingWatermarkLowKB; |
| mRebufferingWatermarkHighKB = bp.mRebufferingWatermarkHighKB; |
| } |
| |
| /** |
| * Combines all of the fields that have been set and return a new |
| * {@link BufferingParams} object. <code>IllegalStateException</code> will be |
| * thrown if there is conflict between fields. |
| * @return a new {@link BufferingParams} object |
| */ |
| public BufferingParams build() { |
| if (isTimeBasedMode(mRebufferingMode) |
| && mRebufferingWatermarkLowMs > mRebufferingWatermarkHighMs) { |
| throw new IllegalStateException("Illegal watermark:" |
| + mRebufferingWatermarkLowMs + " : " + mRebufferingWatermarkHighMs); |
| } |
| if (isSizeBasedMode(mRebufferingMode) |
| && mRebufferingWatermarkLowKB > mRebufferingWatermarkHighKB) { |
| throw new IllegalStateException("Illegal watermark:" |
| + mRebufferingWatermarkLowKB + " : " + mRebufferingWatermarkHighKB); |
| } |
| |
| BufferingParams bp = new BufferingParams(); |
| bp.mInitialBufferingMode = mInitialBufferingMode; |
| bp.mRebufferingMode = mRebufferingMode; |
| |
| bp.mInitialWatermarkMs = mInitialWatermarkMs; |
| bp.mInitialWatermarkKB = mInitialWatermarkKB; |
| |
| bp.mRebufferingWatermarkLowMs = mRebufferingWatermarkLowMs; |
| bp.mRebufferingWatermarkHighMs = mRebufferingWatermarkHighMs; |
| bp.mRebufferingWatermarkLowKB = mRebufferingWatermarkLowKB; |
| bp.mRebufferingWatermarkHighKB = mRebufferingWatermarkHighKB; |
| return bp; |
| } |
| |
| private boolean isTimeBasedMode(int mode) { |
| return (mode == BUFFERING_MODE_TIME_ONLY || mode == BUFFERING_MODE_TIME_THEN_SIZE); |
| } |
| |
| private boolean isSizeBasedMode(int mode) { |
| return (mode == BUFFERING_MODE_SIZE_ONLY || mode == BUFFERING_MODE_TIME_THEN_SIZE); |
| } |
| |
| /** |
| * Sets the initial buffering mode. |
| * @param mode one of {@link BufferingParams#BUFFERING_MODE_NONE}, |
| * {@link BufferingParams#BUFFERING_MODE_TIME_ONLY}, |
| * {@link BufferingParams#BUFFERING_MODE_SIZE_ONLY}, |
| * {@link BufferingParams#BUFFERING_MODE_TIME_THEN_SIZE}, |
| * @return the same Builder instance. |
| */ |
| public Builder setInitialBufferingMode(@BufferingMode int mode) { |
| switch (mode) { |
| case BUFFERING_MODE_NONE: |
| case BUFFERING_MODE_TIME_ONLY: |
| case BUFFERING_MODE_SIZE_ONLY: |
| case BUFFERING_MODE_TIME_THEN_SIZE: |
| mInitialBufferingMode = mode; |
| break; |
| default: |
| throw new IllegalArgumentException("Illegal buffering mode " + mode); |
| } |
| return this; |
| } |
| |
| /** |
| * Sets the rebuffering mode. |
| * @param mode one of {@link BufferingParams#BUFFERING_MODE_NONE}, |
| * {@link BufferingParams#BUFFERING_MODE_TIME_ONLY}, |
| * {@link BufferingParams#BUFFERING_MODE_SIZE_ONLY}, |
| * {@link BufferingParams#BUFFERING_MODE_TIME_THEN_SIZE}, |
| * @return the same Builder instance. |
| */ |
| public Builder setRebufferingMode(@BufferingMode int mode) { |
| switch (mode) { |
| case BUFFERING_MODE_NONE: |
| case BUFFERING_MODE_TIME_ONLY: |
| case BUFFERING_MODE_SIZE_ONLY: |
| case BUFFERING_MODE_TIME_THEN_SIZE: |
| mRebufferingMode = mode; |
| break; |
| default: |
| throw new IllegalArgumentException("Illegal buffering mode " + mode); |
| } |
| return this; |
| } |
| |
| /** |
| * Sets the time based watermark in milliseconds for initial buffering. |
| * @param watermarkMs time based watermark in milliseconds |
| * @return the same Builder instance. |
| */ |
| public Builder setInitialBufferingWatermarkMs(int watermarkMs) { |
| mInitialWatermarkMs = watermarkMs; |
| return this; |
| } |
| |
| /** |
| * Sets the size based watermark in kilobytes for initial buffering. |
| * @param watermarkKB size based watermark in kilobytes |
| * @return the same Builder instance. |
| */ |
| public Builder setInitialBufferingWatermarkKB(int watermarkKB) { |
| mInitialWatermarkKB = watermarkKB; |
| return this; |
| } |
| |
| /** |
| * Sets the time based low watermark in milliseconds for rebuffering. |
| * @param watermarkMs time based low watermark in milliseconds |
| * @return the same Builder instance. |
| */ |
| public Builder setRebufferingWatermarkLowMs(int watermarkMs) { |
| mRebufferingWatermarkLowMs = watermarkMs; |
| return this; |
| } |
| |
| /** |
| * Sets the time based high watermark in milliseconds for rebuffering. |
| * @param watermarkMs time based high watermark in milliseconds |
| * @return the same Builder instance. |
| */ |
| public Builder setRebufferingWatermarkHighMs(int watermarkMs) { |
| mRebufferingWatermarkHighMs = watermarkMs; |
| return this; |
| } |
| |
| /** |
| * Sets the size based low watermark in milliseconds for rebuffering. |
| * @param watermarkKB size based low watermark in milliseconds |
| * @return the same Builder instance. |
| */ |
| public Builder setRebufferingWatermarkLowKB(int watermarkKB) { |
| mRebufferingWatermarkLowKB = watermarkKB; |
| return this; |
| } |
| |
| /** |
| * Sets the size based high watermark in milliseconds for rebuffering. |
| * @param watermarkKB size based high watermark in milliseconds |
| * @return the same Builder instance. |
| */ |
| public Builder setRebufferingWatermarkHighKB(int watermarkKB) { |
| mRebufferingWatermarkHighKB = watermarkKB; |
| return this; |
| } |
| |
| /** |
| * Sets the time based low and high watermarks in milliseconds for rebuffering. |
| * @param lowWatermarkMs time based low watermark in milliseconds |
| * @param highWatermarkMs time based high watermark in milliseconds |
| * @return the same Builder instance. |
| */ |
| public Builder setRebufferingWatermarksMs(int lowWatermarkMs, int highWatermarkMs) { |
| mRebufferingWatermarkLowMs = lowWatermarkMs; |
| mRebufferingWatermarkHighMs = highWatermarkMs; |
| return this; |
| } |
| |
| /** |
| * Sets the size based low and high watermarks in kilobytes for rebuffering. |
| * @param lowWatermarkKB size based low watermark in kilobytes |
| * @param highWatermarkKB size based high watermark in kilobytes |
| * @return the same Builder instance. |
| */ |
| public Builder setRebufferingWatermarksKB(int lowWatermarkKB, int highWatermarkKB) { |
| mRebufferingWatermarkLowKB = lowWatermarkKB; |
| mRebufferingWatermarkHighKB = highWatermarkKB; |
| return this; |
| } |
| } |
| |
| private BufferingParams(Parcel in) { |
| mInitialBufferingMode = in.readInt(); |
| mRebufferingMode = in.readInt(); |
| |
| mInitialWatermarkMs = in.readInt(); |
| mInitialWatermarkKB = in.readInt(); |
| |
| mRebufferingWatermarkLowMs = in.readInt(); |
| mRebufferingWatermarkHighMs = in.readInt(); |
| mRebufferingWatermarkLowKB = in.readInt(); |
| mRebufferingWatermarkHighKB = in.readInt(); |
| } |
| |
| public static final Parcelable.Creator<BufferingParams> CREATOR = |
| new Parcelable.Creator<BufferingParams>() { |
| @Override |
| public BufferingParams createFromParcel(Parcel in) { |
| return new BufferingParams(in); |
| } |
| |
| @Override |
| public BufferingParams[] newArray(int size) { |
| return new BufferingParams[size]; |
| } |
| }; |
| |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(Parcel dest, int flags) { |
| dest.writeInt(mInitialBufferingMode); |
| dest.writeInt(mRebufferingMode); |
| |
| dest.writeInt(mInitialWatermarkMs); |
| dest.writeInt(mInitialWatermarkKB); |
| |
| dest.writeInt(mRebufferingWatermarkLowMs); |
| dest.writeInt(mRebufferingWatermarkHighMs); |
| dest.writeInt(mRebufferingWatermarkLowKB); |
| dest.writeInt(mRebufferingWatermarkHighKB); |
| } |
| } |