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 TvTrackInfo(int type, String id, String language, CharSequence description, int audioChannelCount, int audioSampleRate, int videoWidth, int videoHeight, float videoFrameRate, float videoPixelAspectRatio, byte videoActiveFormatDescription, Bundle extra)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 TvTrackInfo(Parcel in)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 getType()109 public final int getType() { 110 return mType; 111 } 112 113 /** 114 * Returns the ID of the track. 115 */ getId()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 */ getLanguage()124 public final String getLanguage() { 125 return mLanguage; 126 } 127 128 /** 129 * Returns a user readable description for the current track. 130 */ getDescription()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 */ getAudioChannelCount()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 */ getAudioSampleRate()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 */ getVideoWidth()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 */ getVideoHeight()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 */ getVideoFrameRate()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 */ getVideoPixelAspectRatio()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 */ getVideoActiveFormatDescription()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 */ getExtra()230 public final Bundle getExtra() { 231 return mExtra; 232 } 233 234 @Override describeContents()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 writeToParcel(Parcel dest, int flags)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 equals(Object o)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 hashCode()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 */ Builder(@ype int type, @NonNull String id)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 */ setLanguage(String language)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 */ setDescription(CharSequence description)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 */ setAudioChannelCount(int audioChannelCount)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 */ setAudioSampleRate(int audioSampleRate)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 */ setVideoWidth(int videoWidth)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 */ setVideoHeight(int videoHeight)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 */ setVideoFrameRate(float videoFrameRate)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 */ setVideoPixelAspectRatio(float videoPixelAspectRatio)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 */ setVideoActiveFormatDescription(byte videoActiveFormatDescription)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 */ setExtra(Bundle extra)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 */ build()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