Home | History | Annotate | Download | only in media
      1 /*
      2  * Copyright 2017 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 android.annotation.IntDef;
     20 import android.os.Parcel;
     21 import android.os.Parcelable;
     22 
     23 import java.lang.annotation.Retention;
     24 import java.lang.annotation.RetentionPolicy;
     25 
     26 /**
     27  * Structure for source buffering management params.
     28  *
     29  * Used by {@link MediaPlayer#getDefaultBufferingParams()},
     30  * {@link MediaPlayer#getBufferingParams()} and
     31  * {@link MediaPlayer#setBufferingParams(BufferingParams)}
     32  * to control source buffering behavior.
     33  *
     34  * <p>There are two stages of source buffering in {@link MediaPlayer}: initial buffering
     35  * (when {@link MediaPlayer} is being prepared) and rebuffering (when {@link MediaPlayer}
     36  * is playing back source). {@link BufferingParams} includes mode and corresponding
     37  * watermarks for each stage of source buffering. The watermarks could be either size
     38  * based (in milliseconds), or time based (in kilobytes) or both, depending on the mode.
     39  *
     40  * <p>There are 4 buffering modes: {@link #BUFFERING_MODE_NONE},
     41  * {@link #BUFFERING_MODE_TIME_ONLY}, {@link #BUFFERING_MODE_SIZE_ONLY} and
     42  * {@link #BUFFERING_MODE_TIME_THEN_SIZE}.
     43  * {@link MediaPlayer} source component has default buffering modes which can be queried
     44  * by calling {@link MediaPlayer#getDefaultBufferingParams()}.
     45  * Users should always use those default modes or their downsized version when trying to
     46  * change buffering params. For example, {@link #BUFFERING_MODE_TIME_THEN_SIZE} can be
     47  * downsized to {@link #BUFFERING_MODE_NONE}, {@link #BUFFERING_MODE_TIME_ONLY} or
     48  * {@link #BUFFERING_MODE_SIZE_ONLY}. But {@link #BUFFERING_MODE_TIME_ONLY} can not be
     49  * downsized to {@link #BUFFERING_MODE_SIZE_ONLY}.
     50  * <ul>
     51  * <li><strong>initial buffering stage:</strong> has one watermark which is used when
     52  * {@link MediaPlayer} is being prepared. When cached data amount exceeds this watermark,
     53  * {@link MediaPlayer} is prepared.</li>
     54  * <li><strong>rebuffering stage:</strong> has two watermarks, low and high, which are
     55  * used when {@link MediaPlayer} is playing back content.
     56  * <ul>
     57  * <li> When cached data amount exceeds high watermark, {@link MediaPlayer} will pause
     58  * buffering. Buffering will resume when cache runs below some limit which could be low
     59  * watermark or some intermediate value decided by the source component.</li>
     60  * <li> When cached data amount runs below low watermark, {@link MediaPlayer} will paused
     61  * playback. Playback will resume when cached data amount exceeds high watermark
     62  * or reaches end of stream.</li>
     63  * </ul>
     64  * </ul>
     65  * <p>Users should use {@link Builder} to change {@link BufferingParams}.
     66  * @hide
     67  */
     68 public final class BufferingParams implements Parcelable {
     69     /**
     70      * This mode indicates that source buffering is not supported.
     71      */
     72     public static final int BUFFERING_MODE_NONE = 0;
     73     /**
     74      * This mode indicates that only time based source buffering is supported. This means
     75      * the watermark(s) are time based.
     76      */
     77     public static final int BUFFERING_MODE_TIME_ONLY = 1;
     78     /**
     79      * This mode indicates that only size based source buffering is supported. This means
     80      * the watermark(s) are size based.
     81      */
     82     public static final int BUFFERING_MODE_SIZE_ONLY = 2;
     83     /**
     84      * This mode indicates that both time and size based source buffering are supported,
     85      * and time based calculation precedes size based. Size based calculation will be used
     86      * only when time information is not available from the source.
     87      */
     88     public static final int BUFFERING_MODE_TIME_THEN_SIZE = 3;
     89 
     90     /** @hide */
     91     @IntDef(
     92         value = {
     93                 BUFFERING_MODE_NONE,
     94                 BUFFERING_MODE_TIME_ONLY,
     95                 BUFFERING_MODE_SIZE_ONLY,
     96                 BUFFERING_MODE_TIME_THEN_SIZE,
     97         }
     98     )
     99     @Retention(RetentionPolicy.SOURCE)
    100     public @interface BufferingMode {}
    101 
    102     private static final int BUFFERING_NO_WATERMARK = -1;
    103 
    104     // params
    105     private int mInitialBufferingMode = BUFFERING_MODE_NONE;
    106     private int mRebufferingMode = BUFFERING_MODE_NONE;
    107 
    108     private int mInitialWatermarkMs = BUFFERING_NO_WATERMARK;
    109     private int mInitialWatermarkKB = BUFFERING_NO_WATERMARK;
    110 
    111     private int mRebufferingWatermarkLowMs = BUFFERING_NO_WATERMARK;
    112     private int mRebufferingWatermarkHighMs = BUFFERING_NO_WATERMARK;
    113     private int mRebufferingWatermarkLowKB = BUFFERING_NO_WATERMARK;
    114     private int mRebufferingWatermarkHighKB = BUFFERING_NO_WATERMARK;
    115 
    116     private BufferingParams() {
    117     }
    118 
    119     /**
    120      * Return the initial buffering mode used when {@link MediaPlayer} is being prepared.
    121      * @return one of the values that can be set in {@link Builder#setInitialBufferingMode(int)}
    122      */
    123     public int getInitialBufferingMode() {
    124         return mInitialBufferingMode;
    125     }
    126 
    127     /**
    128      * Return the rebuffering mode used when {@link MediaPlayer} is playing back source.
    129      * @return one of the values that can be set in {@link Builder#setRebufferingMode(int)}
    130      */
    131     public int getRebufferingMode() {
    132         return mRebufferingMode;
    133     }
    134 
    135     /**
    136      * Return the time based initial buffering watermark in milliseconds.
    137      * It is meaningful only when initial buffering mode obatined from
    138      * {@link #getInitialBufferingMode()} is time based.
    139      * @return time based initial buffering watermark in milliseconds
    140      */
    141     public int getInitialBufferingWatermarkMs() {
    142         return mInitialWatermarkMs;
    143     }
    144 
    145     /**
    146      * Return the size based initial buffering watermark in kilobytes.
    147      * It is meaningful only when initial buffering mode obatined from
    148      * {@link #getInitialBufferingMode()} is size based.
    149      * @return size based initial buffering watermark in kilobytes
    150      */
    151     public int getInitialBufferingWatermarkKB() {
    152         return mInitialWatermarkKB;
    153     }
    154 
    155     /**
    156      * Return the time based low watermark in milliseconds for rebuffering.
    157      * It is meaningful only when rebuffering mode obatined from
    158      * {@link #getRebufferingMode()} is time based.
    159      * @return time based low watermark for rebuffering in milliseconds
    160      */
    161     public int getRebufferingWatermarkLowMs() {
    162         return mRebufferingWatermarkLowMs;
    163     }
    164 
    165     /**
    166      * Return the time based high watermark in milliseconds for rebuffering.
    167      * It is meaningful only when rebuffering mode obatined from
    168      * {@link #getRebufferingMode()} is time based.
    169      * @return time based high watermark for rebuffering in milliseconds
    170      */
    171     public int getRebufferingWatermarkHighMs() {
    172         return mRebufferingWatermarkHighMs;
    173     }
    174 
    175     /**
    176      * Return the size based low watermark in kilobytes for rebuffering.
    177      * It is meaningful only when rebuffering mode obatined from
    178      * {@link #getRebufferingMode()} is size based.
    179      * @return size based low watermark for rebuffering in kilobytes
    180      */
    181     public int getRebufferingWatermarkLowKB() {
    182         return mRebufferingWatermarkLowKB;
    183     }
    184 
    185     /**
    186      * Return the size based high watermark in kilobytes for rebuffering.
    187      * It is meaningful only when rebuffering mode obatined from
    188      * {@link #getRebufferingMode()} is size based.
    189      * @return size based high watermark for rebuffering in kilobytes
    190      */
    191     public int getRebufferingWatermarkHighKB() {
    192         return mRebufferingWatermarkHighKB;
    193     }
    194 
    195     /**
    196      * Builder class for {@link BufferingParams} objects.
    197      * <p> Here is an example where <code>Builder</code> is used to define the
    198      * {@link BufferingParams} to be used by a {@link MediaPlayer} instance:
    199      *
    200      * <pre class="prettyprint">
    201      * BufferingParams myParams = mediaplayer.getDefaultBufferingParams();
    202      * myParams = new BufferingParams.Builder(myParams)
    203      *             .setInitialBufferingWatermarkMs(10000)
    204      *             .build();
    205      * mediaplayer.setBufferingParams(myParams);
    206      * </pre>
    207      */
    208     public static class Builder {
    209         private int mInitialBufferingMode = BUFFERING_MODE_NONE;
    210         private int mRebufferingMode = BUFFERING_MODE_NONE;
    211 
    212         private int mInitialWatermarkMs = BUFFERING_NO_WATERMARK;
    213         private int mInitialWatermarkKB = BUFFERING_NO_WATERMARK;
    214 
    215         private int mRebufferingWatermarkLowMs = BUFFERING_NO_WATERMARK;
    216         private int mRebufferingWatermarkHighMs = BUFFERING_NO_WATERMARK;
    217         private int mRebufferingWatermarkLowKB = BUFFERING_NO_WATERMARK;
    218         private int mRebufferingWatermarkHighKB = BUFFERING_NO_WATERMARK;
    219 
    220         /**
    221          * Constructs a new Builder with the defaults.
    222          * By default, both initial buffering mode and rebuffering mode are
    223          * {@link BufferingParams#BUFFERING_MODE_NONE}, and all watermarks are -1.
    224          */
    225         public Builder() {
    226         }
    227 
    228         /**
    229          * Constructs a new Builder from a given {@link BufferingParams} instance
    230          * @param bp the {@link BufferingParams} object whose data will be reused
    231          * in the new Builder.
    232          */
    233         public Builder(BufferingParams bp) {
    234             mInitialBufferingMode = bp.mInitialBufferingMode;
    235             mRebufferingMode = bp.mRebufferingMode;
    236 
    237             mInitialWatermarkMs = bp.mInitialWatermarkMs;
    238             mInitialWatermarkKB = bp.mInitialWatermarkKB;
    239 
    240             mRebufferingWatermarkLowMs = bp.mRebufferingWatermarkLowMs;
    241             mRebufferingWatermarkHighMs = bp.mRebufferingWatermarkHighMs;
    242             mRebufferingWatermarkLowKB = bp.mRebufferingWatermarkLowKB;
    243             mRebufferingWatermarkHighKB = bp.mRebufferingWatermarkHighKB;
    244         }
    245 
    246         /**
    247          * Combines all of the fields that have been set and return a new
    248          * {@link BufferingParams} object. <code>IllegalStateException</code> will be
    249          * thrown if there is conflict between fields.
    250          * @return a new {@link BufferingParams} object
    251          */
    252         public BufferingParams build() {
    253             if (isTimeBasedMode(mRebufferingMode)
    254                     && mRebufferingWatermarkLowMs > mRebufferingWatermarkHighMs) {
    255                 throw new IllegalStateException("Illegal watermark:"
    256                         + mRebufferingWatermarkLowMs + " : " + mRebufferingWatermarkHighMs);
    257             }
    258             if (isSizeBasedMode(mRebufferingMode)
    259                     && mRebufferingWatermarkLowKB > mRebufferingWatermarkHighKB) {
    260                 throw new IllegalStateException("Illegal watermark:"
    261                         + mRebufferingWatermarkLowKB + " : " + mRebufferingWatermarkHighKB);
    262             }
    263 
    264             BufferingParams bp = new BufferingParams();
    265             bp.mInitialBufferingMode = mInitialBufferingMode;
    266             bp.mRebufferingMode = mRebufferingMode;
    267 
    268             bp.mInitialWatermarkMs = mInitialWatermarkMs;
    269             bp.mInitialWatermarkKB = mInitialWatermarkKB;
    270 
    271             bp.mRebufferingWatermarkLowMs = mRebufferingWatermarkLowMs;
    272             bp.mRebufferingWatermarkHighMs = mRebufferingWatermarkHighMs;
    273             bp.mRebufferingWatermarkLowKB = mRebufferingWatermarkLowKB;
    274             bp.mRebufferingWatermarkHighKB = mRebufferingWatermarkHighKB;
    275             return bp;
    276         }
    277 
    278         private boolean isTimeBasedMode(int mode) {
    279             return (mode == BUFFERING_MODE_TIME_ONLY || mode == BUFFERING_MODE_TIME_THEN_SIZE);
    280         }
    281 
    282         private boolean isSizeBasedMode(int mode) {
    283             return (mode == BUFFERING_MODE_SIZE_ONLY || mode == BUFFERING_MODE_TIME_THEN_SIZE);
    284         }
    285 
    286         /**
    287          * Sets the initial buffering mode.
    288          * @param mode one of {@link BufferingParams#BUFFERING_MODE_NONE},
    289          *     {@link BufferingParams#BUFFERING_MODE_TIME_ONLY},
    290          *     {@link BufferingParams#BUFFERING_MODE_SIZE_ONLY},
    291          *     {@link BufferingParams#BUFFERING_MODE_TIME_THEN_SIZE},
    292          * @return the same Builder instance.
    293          */
    294         public Builder setInitialBufferingMode(@BufferingMode int mode) {
    295             switch (mode) {
    296                 case BUFFERING_MODE_NONE:
    297                 case BUFFERING_MODE_TIME_ONLY:
    298                 case BUFFERING_MODE_SIZE_ONLY:
    299                 case BUFFERING_MODE_TIME_THEN_SIZE:
    300                      mInitialBufferingMode = mode;
    301                      break;
    302                 default:
    303                      throw new IllegalArgumentException("Illegal buffering mode " + mode);
    304             }
    305             return this;
    306         }
    307 
    308         /**
    309          * Sets the rebuffering mode.
    310          * @param mode one of {@link BufferingParams#BUFFERING_MODE_NONE},
    311          *     {@link BufferingParams#BUFFERING_MODE_TIME_ONLY},
    312          *     {@link BufferingParams#BUFFERING_MODE_SIZE_ONLY},
    313          *     {@link BufferingParams#BUFFERING_MODE_TIME_THEN_SIZE},
    314          * @return the same Builder instance.
    315          */
    316         public Builder setRebufferingMode(@BufferingMode int mode) {
    317             switch (mode) {
    318                 case BUFFERING_MODE_NONE:
    319                 case BUFFERING_MODE_TIME_ONLY:
    320                 case BUFFERING_MODE_SIZE_ONLY:
    321                 case BUFFERING_MODE_TIME_THEN_SIZE:
    322                      mRebufferingMode = mode;
    323                      break;
    324                 default:
    325                      throw new IllegalArgumentException("Illegal buffering mode " + mode);
    326             }
    327             return this;
    328         }
    329 
    330         /**
    331          * Sets the time based watermark in milliseconds for initial buffering.
    332          * @param watermarkMs time based watermark in milliseconds
    333          * @return the same Builder instance.
    334          */
    335         public Builder setInitialBufferingWatermarkMs(int watermarkMs) {
    336             mInitialWatermarkMs = watermarkMs;
    337             return this;
    338         }
    339 
    340         /**
    341          * Sets the size based watermark in kilobytes for initial buffering.
    342          * @param watermarkKB size based watermark in kilobytes
    343          * @return the same Builder instance.
    344          */
    345         public Builder setInitialBufferingWatermarkKB(int watermarkKB) {
    346             mInitialWatermarkKB = watermarkKB;
    347             return this;
    348         }
    349 
    350         /**
    351          * Sets the time based low watermark in milliseconds for rebuffering.
    352          * @param watermarkMs time based low watermark in milliseconds
    353          * @return the same Builder instance.
    354          */
    355         public Builder setRebufferingWatermarkLowMs(int watermarkMs) {
    356             mRebufferingWatermarkLowMs = watermarkMs;
    357             return this;
    358         }
    359 
    360         /**
    361          * Sets the time based high watermark in milliseconds for rebuffering.
    362          * @param watermarkMs time based high watermark in milliseconds
    363          * @return the same Builder instance.
    364          */
    365         public Builder setRebufferingWatermarkHighMs(int watermarkMs) {
    366             mRebufferingWatermarkHighMs = watermarkMs;
    367             return this;
    368         }
    369 
    370         /**
    371          * Sets the size based low watermark in milliseconds for rebuffering.
    372          * @param watermarkKB size based low watermark in milliseconds
    373          * @return the same Builder instance.
    374          */
    375         public Builder setRebufferingWatermarkLowKB(int watermarkKB) {
    376             mRebufferingWatermarkLowKB = watermarkKB;
    377             return this;
    378         }
    379 
    380         /**
    381          * Sets the size based high watermark in milliseconds for rebuffering.
    382          * @param watermarkKB size based high watermark in milliseconds
    383          * @return the same Builder instance.
    384          */
    385         public Builder setRebufferingWatermarkHighKB(int watermarkKB) {
    386             mRebufferingWatermarkHighKB = watermarkKB;
    387             return this;
    388         }
    389 
    390         /**
    391          * Sets the time based low and high watermarks in milliseconds for rebuffering.
    392          * @param lowWatermarkMs time based low watermark in milliseconds
    393          * @param highWatermarkMs time based high watermark in milliseconds
    394          * @return the same Builder instance.
    395          */
    396         public Builder setRebufferingWatermarksMs(int lowWatermarkMs, int highWatermarkMs) {
    397             mRebufferingWatermarkLowMs = lowWatermarkMs;
    398             mRebufferingWatermarkHighMs = highWatermarkMs;
    399             return this;
    400         }
    401 
    402         /**
    403          * Sets the size based low and high watermarks in kilobytes for rebuffering.
    404          * @param lowWatermarkKB size based low watermark in kilobytes
    405          * @param highWatermarkKB size based high watermark in kilobytes
    406          * @return the same Builder instance.
    407          */
    408         public Builder setRebufferingWatermarksKB(int lowWatermarkKB, int highWatermarkKB) {
    409             mRebufferingWatermarkLowKB = lowWatermarkKB;
    410             mRebufferingWatermarkHighKB = highWatermarkKB;
    411             return this;
    412         }
    413     }
    414 
    415     private BufferingParams(Parcel in) {
    416         mInitialBufferingMode = in.readInt();
    417         mRebufferingMode = in.readInt();
    418 
    419         mInitialWatermarkMs = in.readInt();
    420         mInitialWatermarkKB = in.readInt();
    421 
    422         mRebufferingWatermarkLowMs = in.readInt();
    423         mRebufferingWatermarkHighMs = in.readInt();
    424         mRebufferingWatermarkLowKB = in.readInt();
    425         mRebufferingWatermarkHighKB = in.readInt();
    426     }
    427 
    428     public static final Parcelable.Creator<BufferingParams> CREATOR =
    429             new Parcelable.Creator<BufferingParams>() {
    430                 @Override
    431                 public BufferingParams createFromParcel(Parcel in) {
    432                     return new BufferingParams(in);
    433                 }
    434 
    435                 @Override
    436                 public BufferingParams[] newArray(int size) {
    437                     return new BufferingParams[size];
    438                 }
    439             };
    440 
    441 
    442     @Override
    443     public int describeContents() {
    444         return 0;
    445     }
    446 
    447     @Override
    448     public void writeToParcel(Parcel dest, int flags) {
    449         dest.writeInt(mInitialBufferingMode);
    450         dest.writeInt(mRebufferingMode);
    451 
    452         dest.writeInt(mInitialWatermarkMs);
    453         dest.writeInt(mInitialWatermarkKB);
    454 
    455         dest.writeInt(mRebufferingWatermarkLowMs);
    456         dest.writeInt(mRebufferingWatermarkHighMs);
    457         dest.writeInt(mRebufferingWatermarkLowKB);
    458         dest.writeInt(mRebufferingWatermarkHighKB);
    459     }
    460 }
    461