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 17package android.media.tv; 18 19import android.annotation.IntDef; 20import android.annotation.NonNull; 21import android.os.Bundle; 22import android.os.Parcel; 23import android.os.Parcelable; 24import android.text.TextUtils; 25 26import com.android.internal.util.Preconditions; 27 28import java.lang.annotation.Retention; 29import java.lang.annotation.RetentionPolicy; 30import java.util.Objects; 31 32/** 33 * Encapsulates the format of tracks played in {@link TvInputService}. 34 */ 35public 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