Home | History | Annotate | Download | only in tv
      1 /*
      2  * Copyright (C) 2014 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.tv;
     18 
     19 import android.annotation.IntDef;
     20 import android.annotation.NonNull;
     21 import android.os.Bundle;
     22 import android.os.Parcel;
     23 import android.os.Parcelable;
     24 import android.text.TextUtils;
     25 
     26 import com.android.internal.util.Preconditions;
     27 
     28 import java.lang.annotation.Retention;
     29 import java.lang.annotation.RetentionPolicy;
     30 import java.util.Objects;
     31 
     32 /**
     33  * Encapsulates the format of tracks played in {@link TvInputService}.
     34  */
     35 public final class TvTrackInfo implements Parcelable {
     36 
     37     /** @hide */
     38     @Retention(RetentionPolicy.SOURCE)
     39     @IntDef({TYPE_AUDIO, TYPE_VIDEO, TYPE_SUBTITLE})
     40     public @interface Type {}
     41 
     42     /**
     43      * The type value for audio tracks.
     44      */
     45     public static final int TYPE_AUDIO = 0;
     46 
     47     /**
     48      * The type value for video tracks.
     49      */
     50     public static final int TYPE_VIDEO = 1;
     51 
     52     /**
     53      * The type value for subtitle tracks.
     54      */
     55     public static final int TYPE_SUBTITLE = 2;
     56 
     57     private final int mType;
     58     private final String mId;
     59     private final String mLanguage;
     60     private final CharSequence mDescription;
     61     private final int mAudioChannelCount;
     62     private final int mAudioSampleRate;
     63     private final int mVideoWidth;
     64     private final int mVideoHeight;
     65     private final float mVideoFrameRate;
     66     private final float mVideoPixelAspectRatio;
     67     private final byte mVideoActiveFormatDescription;
     68 
     69     private final Bundle mExtra;
     70 
     71     private TvTrackInfo(int type, String id, String language, CharSequence description,
     72             int audioChannelCount, int audioSampleRate, int videoWidth, int videoHeight,
     73             float videoFrameRate, float videoPixelAspectRatio, byte videoActiveFormatDescription,
     74             Bundle extra) {
     75         mType = type;
     76         mId = id;
     77         mLanguage = language;
     78         mDescription = description;
     79         mAudioChannelCount = audioChannelCount;
     80         mAudioSampleRate = audioSampleRate;
     81         mVideoWidth = videoWidth;
     82         mVideoHeight = videoHeight;
     83         mVideoFrameRate = videoFrameRate;
     84         mVideoPixelAspectRatio = videoPixelAspectRatio;
     85         mVideoActiveFormatDescription = videoActiveFormatDescription;
     86         mExtra = extra;
     87     }
     88 
     89     private TvTrackInfo(Parcel in) {
     90         mType = in.readInt();
     91         mId = in.readString();
     92         mLanguage = in.readString();
     93         mDescription = in.readString();
     94         mAudioChannelCount = in.readInt();
     95         mAudioSampleRate = in.readInt();
     96         mVideoWidth = in.readInt();
     97         mVideoHeight = in.readInt();
     98         mVideoFrameRate = in.readFloat();
     99         mVideoPixelAspectRatio = in.readFloat();
    100         mVideoActiveFormatDescription = in.readByte();
    101         mExtra = in.readBundle();
    102     }
    103 
    104     /**
    105      * Returns the type of the track. The type should be one of the followings:
    106      * {@link #TYPE_AUDIO}, {@link #TYPE_VIDEO} and {@link #TYPE_SUBTITLE}.
    107      */
    108     @Type
    109     public final int getType() {
    110         return mType;
    111     }
    112 
    113     /**
    114      * Returns the ID of the track.
    115      */
    116     public final String getId() {
    117         return mId;
    118     }
    119 
    120     /**
    121      * Returns the language information encoded by either ISO 639-1 or ISO 639-2/T. If the language
    122      * is unknown or could not be determined, the corresponding value will be {@code null}.
    123      */
    124     public final String getLanguage() {
    125         return mLanguage;
    126     }
    127 
    128     /**
    129      * Returns a user readable description for the current track.
    130      */
    131     public final CharSequence getDescription() {
    132         return mDescription;
    133     }
    134 
    135     /**
    136      * Returns the audio channel count. Valid only for {@link #TYPE_AUDIO} tracks.
    137      *
    138      * @throws IllegalStateException if not called on an audio track
    139      */
    140     public final int getAudioChannelCount() {
    141         if (mType != TYPE_AUDIO) {
    142             throw new IllegalStateException("Not an audio track");
    143         }
    144         return mAudioChannelCount;
    145     }
    146 
    147     /**
    148      * Returns the audio sample rate, in the unit of Hz. Valid only for {@link #TYPE_AUDIO} tracks.
    149      *
    150      * @throws IllegalStateException if not called on an audio track
    151      */
    152     public final int getAudioSampleRate() {
    153         if (mType != TYPE_AUDIO) {
    154             throw new IllegalStateException("Not an audio track");
    155         }
    156         return mAudioSampleRate;
    157     }
    158 
    159     /**
    160      * Returns the width of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
    161      * tracks.
    162      *
    163      * @throws IllegalStateException if not called on a video track
    164      */
    165     public final int getVideoWidth() {
    166         if (mType != TYPE_VIDEO) {
    167             throw new IllegalStateException("Not a video track");
    168         }
    169         return mVideoWidth;
    170     }
    171 
    172     /**
    173      * Returns the height of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
    174      * tracks.
    175      *
    176      * @throws IllegalStateException if not called on a video track
    177      */
    178     public final int getVideoHeight() {
    179         if (mType != TYPE_VIDEO) {
    180             throw new IllegalStateException("Not a video track");
    181         }
    182         return mVideoHeight;
    183     }
    184 
    185     /**
    186      * Returns the frame rate of the video, in the unit of fps (frames per second). Valid only for
    187      * {@link #TYPE_VIDEO} tracks.
    188      *
    189      * @throws IllegalStateException if not called on a video track
    190      */
    191     public final float getVideoFrameRate() {
    192         if (mType != TYPE_VIDEO) {
    193             throw new IllegalStateException("Not a video track");
    194         }
    195         return mVideoFrameRate;
    196     }
    197 
    198     /**
    199      * Returns the pixel aspect ratio (the ratio of a pixel's width to its height) of the video.
    200      * Valid only for {@link #TYPE_VIDEO} tracks.
    201      *
    202      * @throws IllegalStateException if not called on a video track
    203      */
    204     public final float getVideoPixelAspectRatio() {
    205         if (mType != TYPE_VIDEO) {
    206             throw new IllegalStateException("Not a video track");
    207         }
    208         return mVideoPixelAspectRatio;
    209     }
    210 
    211     /**
    212      * Returns the Active Format Description (AFD) code of the video.
    213      * Valid only for {@link #TYPE_VIDEO} tracks.
    214      *
    215      * <p>The complete list of values are defined in ETSI TS 101 154 V1.7.1 Annex B, ATSC A/53 Part
    216      * 4 and SMPTE 2016-1-2007.
    217      *
    218      * @throws IllegalStateException if not called on a video track
    219      */
    220     public final byte getVideoActiveFormatDescription() {
    221         if (mType != TYPE_VIDEO) {
    222             throw new IllegalStateException("Not a video track");
    223         }
    224         return mVideoActiveFormatDescription;
    225     }
    226 
    227     /**
    228      * Returns the extra information about the current track.
    229      */
    230     public final Bundle getExtra() {
    231         return mExtra;
    232     }
    233 
    234     @Override
    235     public int describeContents() {
    236         return 0;
    237     }
    238 
    239     /**
    240      * Used to package this object into a {@link Parcel}.
    241      *
    242      * @param dest The {@link Parcel} to be written.
    243      * @param flags The flags used for parceling.
    244      */
    245     @Override
    246     public void writeToParcel(Parcel dest, int flags) {
    247         dest.writeInt(mType);
    248         dest.writeString(mId);
    249         dest.writeString(mLanguage);
    250         dest.writeString(mDescription != null ? mDescription.toString() : null);
    251         dest.writeInt(mAudioChannelCount);
    252         dest.writeInt(mAudioSampleRate);
    253         dest.writeInt(mVideoWidth);
    254         dest.writeInt(mVideoHeight);
    255         dest.writeFloat(mVideoFrameRate);
    256         dest.writeFloat(mVideoPixelAspectRatio);
    257         dest.writeByte(mVideoActiveFormatDescription);
    258         dest.writeBundle(mExtra);
    259     }
    260 
    261     @Override
    262     public boolean equals(Object o) {
    263         if (this == o) {
    264           return true;
    265         }
    266 
    267         if (!(o instanceof TvTrackInfo)) {
    268           return false;
    269         }
    270 
    271         TvTrackInfo obj = (TvTrackInfo) o;
    272         return TextUtils.equals(mId, obj.mId)
    273                 && mType == obj.mType
    274                 && TextUtils.equals(mLanguage, obj.mLanguage)
    275                 && TextUtils.equals(mDescription, obj.mDescription)
    276                 && Objects.equals(mExtra, obj.mExtra)
    277                 && (mType == TYPE_AUDIO
    278                         ? mAudioChannelCount == obj.mAudioChannelCount
    279                         && mAudioSampleRate == obj.mAudioSampleRate
    280                         : (mType == TYPE_VIDEO
    281                                 ? mVideoWidth == obj.mVideoWidth
    282                                 && mVideoHeight == obj.mVideoHeight
    283                                 && mVideoFrameRate == obj.mVideoFrameRate
    284                                 && mVideoPixelAspectRatio == obj.mVideoPixelAspectRatio : true));
    285     }
    286 
    287     @Override
    288     public int hashCode() {
    289         return Objects.hashCode(mId);
    290     }
    291 
    292     public static final Parcelable.Creator<TvTrackInfo> CREATOR =
    293             new Parcelable.Creator<TvTrackInfo>() {
    294                 @Override
    295                 public TvTrackInfo createFromParcel(Parcel in) {
    296                     return new TvTrackInfo(in);
    297                 }
    298 
    299                 @Override
    300                 public TvTrackInfo[] newArray(int size) {
    301                     return new TvTrackInfo[size];
    302                 }
    303             };
    304 
    305     /**
    306      * A builder class for creating {@link TvTrackInfo} objects.
    307      */
    308     public static final class Builder {
    309         private final String mId;
    310         private final int mType;
    311         private String mLanguage;
    312         private CharSequence mDescription;
    313         private int mAudioChannelCount;
    314         private int mAudioSampleRate;
    315         private int mVideoWidth;
    316         private int mVideoHeight;
    317         private float mVideoFrameRate;
    318         private float mVideoPixelAspectRatio = 1.0f;
    319         private byte mVideoActiveFormatDescription;
    320         private Bundle mExtra;
    321 
    322         /**
    323          * Create a {@link Builder}. Any field that should be included in the {@link TvTrackInfo}
    324          * must be added.
    325          *
    326          * @param type The type of the track.
    327          * @param id The ID of the track that uniquely identifies the current track among all the
    328          *            other tracks in the same TV program.
    329          * @throws IllegalArgumentException if the type is not any of {@link #TYPE_AUDIO},
    330          *                                  {@link #TYPE_VIDEO} and {@link #TYPE_SUBTITLE}
    331          */
    332         public Builder(@Type int type, @NonNull String id) {
    333             if (type != TYPE_AUDIO
    334                     && type != TYPE_VIDEO
    335                     && type != TYPE_SUBTITLE) {
    336                 throw new IllegalArgumentException("Unknown type: " + type);
    337             }
    338             Preconditions.checkNotNull(id);
    339             mType = type;
    340             mId = id;
    341         }
    342 
    343         /**
    344          * Sets the language information of the current track.
    345          *
    346          * @param language The language string encoded by either ISO 639-1 or ISO 639-2/T.
    347          */
    348         public final Builder setLanguage(String language) {
    349             mLanguage = language;
    350             return this;
    351         }
    352 
    353         /**
    354          * Sets a user readable description for the current track.
    355          *
    356          * @param description The user readable description.
    357          */
    358         public final Builder setDescription(CharSequence description) {
    359             mDescription = description;
    360             return this;
    361         }
    362 
    363         /**
    364          * Sets the audio channel count. Valid only for {@link #TYPE_AUDIO} tracks.
    365          *
    366          * @param audioChannelCount The audio channel count.
    367          * @throws IllegalStateException if not called on an audio track
    368          */
    369         public final Builder setAudioChannelCount(int audioChannelCount) {
    370             if (mType != TYPE_AUDIO) {
    371                 throw new IllegalStateException("Not an audio track");
    372             }
    373             mAudioChannelCount = audioChannelCount;
    374             return this;
    375         }
    376 
    377         /**
    378          * Sets the audio sample rate, in the unit of Hz. Valid only for {@link #TYPE_AUDIO}
    379          * tracks.
    380          *
    381          * @param audioSampleRate The audio sample rate.
    382          * @throws IllegalStateException if not called on an audio track
    383          */
    384         public final Builder setAudioSampleRate(int audioSampleRate) {
    385             if (mType != TYPE_AUDIO) {
    386                 throw new IllegalStateException("Not an audio track");
    387             }
    388             mAudioSampleRate = audioSampleRate;
    389             return this;
    390         }
    391 
    392         /**
    393          * Sets the width of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
    394          * tracks.
    395          *
    396          * @param videoWidth The width of the video.
    397          * @throws IllegalStateException if not called on a video track
    398          */
    399         public final Builder setVideoWidth(int videoWidth) {
    400             if (mType != TYPE_VIDEO) {
    401                 throw new IllegalStateException("Not a video track");
    402             }
    403             mVideoWidth = videoWidth;
    404             return this;
    405         }
    406 
    407         /**
    408          * Sets the height of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
    409          * tracks.
    410          *
    411          * @param videoHeight The height of the video.
    412          * @throws IllegalStateException if not called on a video track
    413          */
    414         public final Builder setVideoHeight(int videoHeight) {
    415             if (mType != TYPE_VIDEO) {
    416                 throw new IllegalStateException("Not a video track");
    417             }
    418             mVideoHeight = videoHeight;
    419             return this;
    420         }
    421 
    422         /**
    423          * Sets the frame rate of the video, in the unit fps (frames per rate). Valid only for
    424          * {@link #TYPE_VIDEO} tracks.
    425          *
    426          * @param videoFrameRate The frame rate of the video.
    427          * @throws IllegalStateException if not called on a video track
    428          */
    429         public final Builder setVideoFrameRate(float videoFrameRate) {
    430             if (mType != TYPE_VIDEO) {
    431                 throw new IllegalStateException("Not a video track");
    432             }
    433             mVideoFrameRate = videoFrameRate;
    434             return this;
    435         }
    436 
    437         /**
    438          * Sets the pixel aspect ratio (the ratio of a pixel's width to its height) of the video.
    439          * Valid only for {@link #TYPE_VIDEO} tracks.
    440          *
    441          * <p>This is needed for applications to be able to scale the video properly for some video
    442          * formats such as 720x576 4:3 and 720x576 16:9 where pixels are not square. By default,
    443          * applications assume the value of 1.0 (square pixels), so it is not necessary to set the
    444          * pixel aspect ratio for most video formats.
    445          *
    446          * @param videoPixelAspectRatio The pixel aspect ratio of the video.
    447          * @throws IllegalStateException if not called on a video track
    448          */
    449         public final Builder setVideoPixelAspectRatio(float videoPixelAspectRatio) {
    450             if (mType != TYPE_VIDEO) {
    451                 throw new IllegalStateException("Not a video track");
    452             }
    453             mVideoPixelAspectRatio = videoPixelAspectRatio;
    454             return this;
    455         }
    456 
    457         /**
    458          * Sets the Active Format Description (AFD) code of the video.
    459          * Valid only for {@link #TYPE_VIDEO} tracks.
    460          *
    461          * <p>This is needed for applications to be able to scale the video properly based on the
    462          * information about where in the coded picture the active video is.
    463          * The complete list of values are defined in ETSI TS 101 154 V1.7.1 Annex B, ATSC A/53 Part
    464          * 4 and SMPTE 2016-1-2007.
    465          *
    466          * @param videoActiveFormatDescription The AFD code of the video.
    467          * @throws IllegalStateException if not called on a video track
    468          */
    469         public final Builder setVideoActiveFormatDescription(byte videoActiveFormatDescription) {
    470             if (mType != TYPE_VIDEO) {
    471                 throw new IllegalStateException("Not a video track");
    472             }
    473             mVideoActiveFormatDescription = videoActiveFormatDescription;
    474             return this;
    475         }
    476 
    477         /**
    478          * Sets the extra information about the current track.
    479          *
    480          * @param extra The extra information.
    481          */
    482         public final Builder setExtra(Bundle extra) {
    483             mExtra = new Bundle(extra);
    484             return this;
    485         }
    486 
    487         /**
    488          * Creates a {@link TvTrackInfo} instance with the specified fields.
    489          *
    490          * @return The new {@link TvTrackInfo} instance
    491          */
    492         public TvTrackInfo build() {
    493             return new TvTrackInfo(mType, mId, mLanguage, mDescription, mAudioChannelCount,
    494                     mAudioSampleRate, mVideoWidth, mVideoHeight, mVideoFrameRate,
    495                     mVideoPixelAspectRatio, mVideoActiveFormatDescription, mExtra);
    496         }
    497     }
    498 }
    499