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.annotation.Nullable; 22 import android.os.Bundle; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 import android.text.TextUtils; 26 27 import com.android.internal.util.Preconditions; 28 29 import java.lang.annotation.Retention; 30 import java.lang.annotation.RetentionPolicy; 31 import java.util.Objects; 32 33 /** 34 * Encapsulates the format of tracks played in {@link TvInputService}. 35 */ 36 public final class TvTrackInfo implements Parcelable { 37 38 /** @hide */ 39 @Retention(RetentionPolicy.SOURCE) 40 @IntDef({TYPE_AUDIO, TYPE_VIDEO, TYPE_SUBTITLE}) 41 public @interface Type {} 42 43 /** 44 * The type value for audio tracks. 45 */ 46 public static final int TYPE_AUDIO = 0; 47 48 /** 49 * The type value for video tracks. 50 */ 51 public static final int TYPE_VIDEO = 1; 52 53 /** 54 * The type value for subtitle tracks. 55 */ 56 public static final int TYPE_SUBTITLE = 2; 57 58 private final int mType; 59 private final String mId; 60 private final String mLanguage; 61 private final CharSequence mDescription; 62 @Nullable 63 private final String mEncoding; 64 private final boolean mEncrypted; 65 private final int mAudioChannelCount; 66 private final int mAudioSampleRate; 67 private final boolean mAudioDescription; 68 private final boolean mHardOfHearing; 69 private final boolean mSpokenSubtitle; 70 private final int mVideoWidth; 71 private final int mVideoHeight; 72 private final float mVideoFrameRate; 73 private final float mVideoPixelAspectRatio; 74 private final byte mVideoActiveFormatDescription; 75 76 private final Bundle mExtra; 77 TvTrackInfo(int type, String id, String language, CharSequence description, String encoding, boolean encrypted, int audioChannelCount, int audioSampleRate, boolean audioDescription, boolean hardOfHearing, boolean spokenSubtitle, int videoWidth, int videoHeight, float videoFrameRate, float videoPixelAspectRatio, byte videoActiveFormatDescription, Bundle extra)78 private TvTrackInfo(int type, String id, String language, CharSequence description, 79 String encoding, boolean encrypted, int audioChannelCount, int audioSampleRate, 80 boolean audioDescription, boolean hardOfHearing, boolean spokenSubtitle, int videoWidth, 81 int videoHeight, float videoFrameRate, float videoPixelAspectRatio, 82 byte videoActiveFormatDescription, Bundle extra) { 83 mType = type; 84 mId = id; 85 mLanguage = language; 86 mDescription = description; 87 mEncoding = encoding; 88 mEncrypted = encrypted; 89 mAudioChannelCount = audioChannelCount; 90 mAudioSampleRate = audioSampleRate; 91 mAudioDescription = audioDescription; 92 mHardOfHearing = hardOfHearing; 93 mSpokenSubtitle = spokenSubtitle; 94 mVideoWidth = videoWidth; 95 mVideoHeight = videoHeight; 96 mVideoFrameRate = videoFrameRate; 97 mVideoPixelAspectRatio = videoPixelAspectRatio; 98 mVideoActiveFormatDescription = videoActiveFormatDescription; 99 mExtra = extra; 100 } 101 TvTrackInfo(Parcel in)102 private TvTrackInfo(Parcel in) { 103 mType = in.readInt(); 104 mId = in.readString(); 105 mLanguage = in.readString(); 106 mDescription = in.readString(); 107 mEncoding = in.readString(); 108 mEncrypted = in.readInt() != 0; 109 mAudioChannelCount = in.readInt(); 110 mAudioSampleRate = in.readInt(); 111 mAudioDescription = in.readInt() != 0; 112 mHardOfHearing = in.readInt() != 0; 113 mSpokenSubtitle = in.readInt() != 0; 114 mVideoWidth = in.readInt(); 115 mVideoHeight = in.readInt(); 116 mVideoFrameRate = in.readFloat(); 117 mVideoPixelAspectRatio = in.readFloat(); 118 mVideoActiveFormatDescription = in.readByte(); 119 mExtra = in.readBundle(); 120 } 121 122 /** 123 * Returns the type of the track. The type should be one of the followings: 124 * {@link #TYPE_AUDIO}, {@link #TYPE_VIDEO} and {@link #TYPE_SUBTITLE}. 125 */ 126 @Type getType()127 public final int getType() { 128 return mType; 129 } 130 131 /** 132 * Returns the ID of the track. 133 */ getId()134 public final String getId() { 135 return mId; 136 } 137 138 /** 139 * Returns the language information encoded by either ISO 639-1 or ISO 639-2/T. If the language 140 * is unknown or could not be determined, the corresponding value will be {@code null}. 141 */ getLanguage()142 public final String getLanguage() { 143 return mLanguage; 144 } 145 146 /** 147 * Returns a user readable description for the current track. 148 */ getDescription()149 public final CharSequence getDescription() { 150 return mDescription; 151 } 152 153 /** 154 * Returns the codec in the form of mime type. If the encoding is unknown or could not be 155 * determined, the corresponding value will be {@code null}. 156 * 157 * <p>For example of broadcast, codec information may be referred to broadcast standard (e.g. 158 * Component Descriptor of ETSI EN 300 468). In the case that track type is subtitle, mime type 159 * could be defined in broadcast standard (e.g. "text/dvb.subtitle" or "text/dvb.teletext" in 160 * ETSI TS 102 812 V1.3.1 section 7.6). 161 */ 162 @Nullable getEncoding()163 public String getEncoding() { 164 return mEncoding; 165 } 166 167 /** 168 * Returns {@code true} if the track is encrypted, {@code false} otherwise. If the encryption 169 * status is unknown or could not be determined, the corresponding value will be {@code false}. 170 * 171 * <p>For example: ISO/IEC 13818-1 defines a CA descriptor that can be used to determine the 172 * encryption status of some broadcast streams. 173 */ isEncrypted()174 public boolean isEncrypted() { 175 return mEncrypted; 176 } 177 178 /** 179 * Returns the audio channel count. Valid only for {@link #TYPE_AUDIO} tracks. 180 * 181 * @throws IllegalStateException if not called on an audio track 182 */ getAudioChannelCount()183 public final int getAudioChannelCount() { 184 if (mType != TYPE_AUDIO) { 185 throw new IllegalStateException("Not an audio track"); 186 } 187 return mAudioChannelCount; 188 } 189 190 /** 191 * Returns the audio sample rate, in the unit of Hz. Valid only for {@link #TYPE_AUDIO} tracks. 192 * 193 * @throws IllegalStateException if not called on an audio track 194 */ getAudioSampleRate()195 public final int getAudioSampleRate() { 196 if (mType != TYPE_AUDIO) { 197 throw new IllegalStateException("Not an audio track"); 198 } 199 return mAudioSampleRate; 200 } 201 202 /** 203 * Returns {@code true} if the track is an audio description intended for people with visual 204 * impairment, {@code false} otherwise. Valid only for {@link #TYPE_AUDIO} tracks. 205 * 206 * <p>For example of broadcast, audio description information may be referred to broadcast 207 * standard (e.g. ISO 639 Language Descriptor of ISO/IEC 13818-1, Supplementary Audio Language 208 * Descriptor, AC-3 Descriptor, Enhanced AC-3 Descriptor, AAC Descriptor of ETSI EN 300 468). 209 * 210 * @throws IllegalStateException if not called on an audio track 211 */ isAudioDescription()212 public boolean isAudioDescription() { 213 if (mType != TYPE_AUDIO) { 214 throw new IllegalStateException("Not an audio track"); 215 } 216 return mAudioDescription; 217 } 218 219 /** 220 * Returns {@code true} if the track is intended for people with hearing impairment, {@code 221 * false} otherwise. Valid only for {@link #TYPE_AUDIO} and {@link #TYPE_SUBTITLE} tracks. 222 * 223 * <p>For example of broadcast, hard of hearing information may be referred to broadcast 224 * standard (e.g. ISO 639 Language Descriptor of ISO/IEC 13818-1, Supplementary Audio Language 225 * Descriptor, AC-3 Descriptor, Enhanced AC-3 Descriptor, AAC Descriptor of ETSI EN 300 468). 226 * 227 * @throws IllegalStateException if not called on an audio track or a subtitle track 228 */ isHardOfHearing()229 public boolean isHardOfHearing() { 230 if (mType != TYPE_AUDIO && mType != TYPE_SUBTITLE) { 231 throw new IllegalStateException("Not an audio or a subtitle track"); 232 } 233 return mHardOfHearing; 234 } 235 236 /** 237 * Returns {@code true} if the track is a spoken subtitle for people with visual impairment, 238 * {@code false} otherwise. Valid only for {@link #TYPE_AUDIO} tracks. 239 * 240 * <p>For example of broadcast, spoken subtitle information may be referred to broadcast 241 * standard (e.g. Supplementary Audio Language Descriptor of ETSI EN 300 468). 242 * 243 * @throws IllegalStateException if not called on an audio track 244 */ isSpokenSubtitle()245 public boolean isSpokenSubtitle() { 246 if (mType != TYPE_AUDIO) { 247 throw new IllegalStateException("Not an audio track"); 248 } 249 return mSpokenSubtitle; 250 } 251 252 /** 253 * Returns the width of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO} 254 * tracks. 255 * 256 * @throws IllegalStateException if not called on a video track 257 */ getVideoWidth()258 public final int getVideoWidth() { 259 if (mType != TYPE_VIDEO) { 260 throw new IllegalStateException("Not a video track"); 261 } 262 return mVideoWidth; 263 } 264 265 /** 266 * Returns the height of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO} 267 * tracks. 268 * 269 * @throws IllegalStateException if not called on a video track 270 */ getVideoHeight()271 public final int getVideoHeight() { 272 if (mType != TYPE_VIDEO) { 273 throw new IllegalStateException("Not a video track"); 274 } 275 return mVideoHeight; 276 } 277 278 /** 279 * Returns the frame rate of the video, in the unit of fps (frames per second). Valid only for 280 * {@link #TYPE_VIDEO} tracks. 281 * 282 * @throws IllegalStateException if not called on a video track 283 */ getVideoFrameRate()284 public final float getVideoFrameRate() { 285 if (mType != TYPE_VIDEO) { 286 throw new IllegalStateException("Not a video track"); 287 } 288 return mVideoFrameRate; 289 } 290 291 /** 292 * Returns the pixel aspect ratio (the ratio of a pixel's width to its height) of the video. 293 * Valid only for {@link #TYPE_VIDEO} tracks. 294 * 295 * @throws IllegalStateException if not called on a video track 296 */ getVideoPixelAspectRatio()297 public final float getVideoPixelAspectRatio() { 298 if (mType != TYPE_VIDEO) { 299 throw new IllegalStateException("Not a video track"); 300 } 301 return mVideoPixelAspectRatio; 302 } 303 304 /** 305 * Returns the Active Format Description (AFD) code of the video. 306 * Valid only for {@link #TYPE_VIDEO} tracks. 307 * 308 * <p>The complete list of values are defined in ETSI TS 101 154 V1.7.1 Annex B, ATSC A/53 Part 309 * 4 and SMPTE 2016-1-2007. 310 * 311 * @throws IllegalStateException if not called on a video track 312 */ getVideoActiveFormatDescription()313 public final byte getVideoActiveFormatDescription() { 314 if (mType != TYPE_VIDEO) { 315 throw new IllegalStateException("Not a video track"); 316 } 317 return mVideoActiveFormatDescription; 318 } 319 320 /** 321 * Returns the extra information about the current track. 322 */ getExtra()323 public final Bundle getExtra() { 324 return mExtra; 325 } 326 327 @Override describeContents()328 public int describeContents() { 329 return 0; 330 } 331 332 /** 333 * Used to package this object into a {@link Parcel}. 334 * 335 * @param dest The {@link Parcel} to be written. 336 * @param flags The flags used for parceling. 337 */ 338 @Override writeToParcel(@onNull Parcel dest, int flags)339 public void writeToParcel(@NonNull Parcel dest, int flags) { 340 Preconditions.checkNotNull(dest); 341 dest.writeInt(mType); 342 dest.writeString(mId); 343 dest.writeString(mLanguage); 344 dest.writeString(mDescription != null ? mDescription.toString() : null); 345 dest.writeString(mEncoding); 346 dest.writeInt(mEncrypted ? 1 : 0); 347 dest.writeInt(mAudioChannelCount); 348 dest.writeInt(mAudioSampleRate); 349 dest.writeInt(mAudioDescription ? 1 : 0); 350 dest.writeInt(mHardOfHearing ? 1 : 0); 351 dest.writeInt(mSpokenSubtitle ? 1 : 0); 352 dest.writeInt(mVideoWidth); 353 dest.writeInt(mVideoHeight); 354 dest.writeFloat(mVideoFrameRate); 355 dest.writeFloat(mVideoPixelAspectRatio); 356 dest.writeByte(mVideoActiveFormatDescription); 357 dest.writeBundle(mExtra); 358 } 359 360 @Override equals(Object o)361 public boolean equals(Object o) { 362 if (this == o) { 363 return true; 364 } 365 366 if (!(o instanceof TvTrackInfo)) { 367 return false; 368 } 369 370 TvTrackInfo obj = (TvTrackInfo) o; 371 372 if (!TextUtils.equals(mId, obj.mId) || mType != obj.mType 373 || !TextUtils.equals(mLanguage, obj.mLanguage) 374 || !TextUtils.equals(mDescription, obj.mDescription) 375 || !TextUtils.equals(mEncoding, obj.mEncoding) 376 || mEncrypted != obj.mEncrypted) { 377 return false; 378 } 379 380 switch (mType) { 381 case TYPE_AUDIO: 382 return mAudioChannelCount == obj.mAudioChannelCount 383 && mAudioSampleRate == obj.mAudioSampleRate 384 && mAudioDescription == obj.mAudioDescription 385 && mHardOfHearing == obj.mHardOfHearing 386 && mSpokenSubtitle == obj.mSpokenSubtitle; 387 388 case TYPE_VIDEO: 389 return mVideoWidth == obj.mVideoWidth 390 && mVideoHeight == obj.mVideoHeight 391 && mVideoFrameRate == obj.mVideoFrameRate 392 && mVideoPixelAspectRatio == obj.mVideoPixelAspectRatio 393 && mVideoActiveFormatDescription == obj.mVideoActiveFormatDescription; 394 395 case TYPE_SUBTITLE: 396 return mHardOfHearing == obj.mHardOfHearing; 397 } 398 399 return true; 400 } 401 402 @Override hashCode()403 public int hashCode() { 404 int result = Objects.hash(mId, mType, mLanguage, mDescription); 405 406 if (mType == TYPE_AUDIO) { 407 result = Objects.hash(result, mAudioChannelCount, mAudioSampleRate); 408 } else if (mType == TYPE_VIDEO) { 409 result = Objects.hash(result, mVideoWidth, mVideoHeight, mVideoFrameRate, 410 mVideoPixelAspectRatio); 411 } 412 413 return result; 414 } 415 416 public static final @android.annotation.NonNull Parcelable.Creator<TvTrackInfo> CREATOR = 417 new Parcelable.Creator<TvTrackInfo>() { 418 @Override 419 @NonNull 420 public TvTrackInfo createFromParcel(Parcel in) { 421 return new TvTrackInfo(in); 422 } 423 424 @Override 425 @NonNull 426 public TvTrackInfo[] newArray(int size) { 427 return new TvTrackInfo[size]; 428 } 429 }; 430 431 /** 432 * A builder class for creating {@link TvTrackInfo} objects. 433 */ 434 public static final class Builder { 435 private final String mId; 436 private final int mType; 437 private String mLanguage; 438 private CharSequence mDescription; 439 private String mEncoding; 440 private boolean mEncrypted; 441 private int mAudioChannelCount; 442 private int mAudioSampleRate; 443 private boolean mAudioDescription; 444 private boolean mHardOfHearing; 445 private boolean mSpokenSubtitle; 446 private int mVideoWidth; 447 private int mVideoHeight; 448 private float mVideoFrameRate; 449 private float mVideoPixelAspectRatio = 1.0f; 450 private byte mVideoActiveFormatDescription; 451 private Bundle mExtra; 452 453 /** 454 * Create a {@link Builder}. Any field that should be included in the {@link TvTrackInfo} 455 * must be added. 456 * 457 * @param type The type of the track. 458 * @param id The ID of the track that uniquely identifies the current track among all the 459 * other tracks in the same TV program. 460 * @throws IllegalArgumentException if the type is not any of {@link #TYPE_AUDIO}, 461 * {@link #TYPE_VIDEO} and {@link #TYPE_SUBTITLE} 462 */ Builder(@ype int type, @NonNull String id)463 public Builder(@Type int type, @NonNull String id) { 464 if (type != TYPE_AUDIO 465 && type != TYPE_VIDEO 466 && type != TYPE_SUBTITLE) { 467 throw new IllegalArgumentException("Unknown type: " + type); 468 } 469 Preconditions.checkNotNull(id); 470 mType = type; 471 mId = id; 472 } 473 474 /** 475 * Sets the language information of the current track. 476 * 477 * @param language The language string encoded by either ISO 639-1 or ISO 639-2/T. 478 */ 479 @NonNull setLanguage(@onNull String language)480 public Builder setLanguage(@NonNull String language) { 481 Preconditions.checkNotNull(language); 482 mLanguage = language; 483 return this; 484 } 485 486 /** 487 * Sets a user readable description for the current track. 488 * 489 * @param description The user readable description. 490 */ 491 @NonNull setDescription(@onNull CharSequence description)492 public Builder setDescription(@NonNull CharSequence description) { 493 Preconditions.checkNotNull(description); 494 mDescription = description; 495 return this; 496 } 497 498 /** 499 * Sets the encoding of the track. 500 * 501 * <p>For example of broadcast, codec information may be referred to broadcast standard 502 * (e.g. Component Descriptor of ETSI EN 300 468). In the case that track type is subtitle, 503 * mime type could be defined in broadcast standard (e.g. "text/dvb.subtitle" or 504 * "text/dvb.teletext" in ETSI TS 102 812 V1.3.1 section 7.6). 505 * 506 * @param encoding The encoding of the track in the form of mime type. 507 */ 508 @NonNull setEncoding(@ullable String encoding)509 public Builder setEncoding(@Nullable String encoding) { 510 mEncoding = encoding; 511 return this; 512 } 513 514 /** 515 * Sets the encryption status of the track. 516 * 517 * <p>For example: ISO/IEC 13818-1 defines a CA descriptor that can be used to determine the 518 * encryption status of some broadcast streams. 519 * 520 * @param encrypted The encryption status of the track. 521 */ 522 @NonNull setEncrypted(boolean encrypted)523 public Builder setEncrypted(boolean encrypted) { 524 mEncrypted = encrypted; 525 return this; 526 } 527 528 /** 529 * Sets the audio channel count. Valid only for {@link #TYPE_AUDIO} tracks. 530 * 531 * @param audioChannelCount The audio channel count. 532 * @throws IllegalStateException if not called on an audio track 533 */ 534 @NonNull setAudioChannelCount(int audioChannelCount)535 public Builder setAudioChannelCount(int audioChannelCount) { 536 if (mType != TYPE_AUDIO) { 537 throw new IllegalStateException("Not an audio track"); 538 } 539 mAudioChannelCount = audioChannelCount; 540 return this; 541 } 542 543 /** 544 * Sets the audio sample rate, in the unit of Hz. Valid only for {@link #TYPE_AUDIO} 545 * tracks. 546 * 547 * @param audioSampleRate The audio sample rate. 548 * @throws IllegalStateException if not called on an audio track 549 */ 550 @NonNull setAudioSampleRate(int audioSampleRate)551 public Builder setAudioSampleRate(int audioSampleRate) { 552 if (mType != TYPE_AUDIO) { 553 throw new IllegalStateException("Not an audio track"); 554 } 555 mAudioSampleRate = audioSampleRate; 556 return this; 557 } 558 559 /** 560 * Sets the audio description attribute of the audio. Valid only for {@link #TYPE_AUDIO} 561 * tracks. 562 * 563 * <p>For example of broadcast, audio description information may be referred to broadcast 564 * standard (e.g. ISO 639 Language Descriptor of ISO/IEC 13818-1, Supplementary Audio 565 * Language Descriptor, AC-3 Descriptor, Enhanced AC-3 Descriptor, AAC Descriptor of ETSI EN 566 * 300 468). 567 * 568 * @param audioDescription The audio description attribute of the audio. 569 * @throws IllegalStateException if not called on an audio track 570 */ 571 @NonNull setAudioDescription(boolean audioDescription)572 public Builder setAudioDescription(boolean audioDescription) { 573 if (mType != TYPE_AUDIO) { 574 throw new IllegalStateException("Not an audio track"); 575 } 576 mAudioDescription = audioDescription; 577 return this; 578 } 579 580 /** 581 * Sets the hard of hearing attribute of the track. Valid only for {@link #TYPE_AUDIO} and 582 * {@link #TYPE_SUBTITLE} tracks. 583 * 584 * <p>For example of broadcast, hard of hearing information may be referred to broadcast 585 * standard (e.g. ISO 639 Language Descriptor of ISO/IEC 13818-1, Supplementary Audio 586 * Language Descriptor, AC-3 Descriptor, Enhanced AC-3 Descriptor, AAC Descriptor of ETSI EN 587 * 300 468). 588 * 589 * @param hardOfHearing The hard of hearing attribute of the track. 590 * @throws IllegalStateException if not called on an audio track or a subtitle track 591 */ 592 @NonNull setHardOfHearing(boolean hardOfHearing)593 public Builder setHardOfHearing(boolean hardOfHearing) { 594 if (mType != TYPE_AUDIO && mType != TYPE_SUBTITLE) { 595 throw new IllegalStateException("Not an audio track or a subtitle track"); 596 } 597 mHardOfHearing = hardOfHearing; 598 return this; 599 } 600 601 /** 602 * Sets the spoken subtitle attribute of the audio. Valid only for {@link #TYPE_AUDIO} 603 * tracks. 604 * 605 * <p>For example of broadcast, spoken subtitle information may be referred to broadcast 606 * standard (e.g. Supplementary Audio Language Descriptor of ETSI EN 300 468). 607 * 608 * @param spokenSubtitle The spoken subtitle attribute of the audio. 609 * @throws IllegalStateException if not called on an audio track 610 */ 611 @NonNull setSpokenSubtitle(boolean spokenSubtitle)612 public Builder setSpokenSubtitle(boolean spokenSubtitle) { 613 if (mType != TYPE_AUDIO) { 614 throw new IllegalStateException("Not an audio track"); 615 } 616 mSpokenSubtitle = spokenSubtitle; 617 return this; 618 } 619 620 /** 621 * Sets the width of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO} 622 * tracks. 623 * 624 * @param videoWidth The width of the video. 625 * @throws IllegalStateException if not called on a video track 626 */ 627 @NonNull setVideoWidth(int videoWidth)628 public Builder setVideoWidth(int videoWidth) { 629 if (mType != TYPE_VIDEO) { 630 throw new IllegalStateException("Not a video track"); 631 } 632 mVideoWidth = videoWidth; 633 return this; 634 } 635 636 /** 637 * Sets the height of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO} 638 * tracks. 639 * 640 * @param videoHeight The height of the video. 641 * @throws IllegalStateException if not called on a video track 642 */ 643 @NonNull setVideoHeight(int videoHeight)644 public Builder setVideoHeight(int videoHeight) { 645 if (mType != TYPE_VIDEO) { 646 throw new IllegalStateException("Not a video track"); 647 } 648 mVideoHeight = videoHeight; 649 return this; 650 } 651 652 /** 653 * Sets the frame rate of the video, in the unit fps (frames per rate). Valid only for 654 * {@link #TYPE_VIDEO} tracks. 655 * 656 * @param videoFrameRate The frame rate of the video. 657 * @throws IllegalStateException if not called on a video track 658 */ 659 @NonNull setVideoFrameRate(float videoFrameRate)660 public Builder setVideoFrameRate(float videoFrameRate) { 661 if (mType != TYPE_VIDEO) { 662 throw new IllegalStateException("Not a video track"); 663 } 664 mVideoFrameRate = videoFrameRate; 665 return this; 666 } 667 668 /** 669 * Sets the pixel aspect ratio (the ratio of a pixel's width to its height) of the video. 670 * Valid only for {@link #TYPE_VIDEO} tracks. 671 * 672 * <p>This is needed for applications to be able to scale the video properly for some video 673 * formats such as 720x576 4:3 and 720x576 16:9 where pixels are not square. By default, 674 * applications assume the value of 1.0 (square pixels), so it is not necessary to set the 675 * pixel aspect ratio for most video formats. 676 * 677 * @param videoPixelAspectRatio The pixel aspect ratio of the video. 678 * @throws IllegalStateException if not called on a video track 679 */ 680 @NonNull setVideoPixelAspectRatio(float videoPixelAspectRatio)681 public Builder setVideoPixelAspectRatio(float videoPixelAspectRatio) { 682 if (mType != TYPE_VIDEO) { 683 throw new IllegalStateException("Not a video track"); 684 } 685 mVideoPixelAspectRatio = videoPixelAspectRatio; 686 return this; 687 } 688 689 /** 690 * Sets the Active Format Description (AFD) code of the video. 691 * Valid only for {@link #TYPE_VIDEO} tracks. 692 * 693 * <p>This is needed for applications to be able to scale the video properly based on the 694 * information about where in the coded picture the active video is. 695 * The complete list of values are defined in ETSI TS 101 154 V1.7.1 Annex B, ATSC A/53 Part 696 * 4 and SMPTE 2016-1-2007. 697 * 698 * @param videoActiveFormatDescription The AFD code of the video. 699 * @throws IllegalStateException if not called on a video track 700 */ 701 @NonNull setVideoActiveFormatDescription(byte videoActiveFormatDescription)702 public Builder setVideoActiveFormatDescription(byte videoActiveFormatDescription) { 703 if (mType != TYPE_VIDEO) { 704 throw new IllegalStateException("Not a video track"); 705 } 706 mVideoActiveFormatDescription = videoActiveFormatDescription; 707 return this; 708 } 709 710 /** 711 * Sets the extra information about the current track. 712 * 713 * @param extra The extra information. 714 */ 715 @NonNull setExtra(@onNull Bundle extra)716 public Builder setExtra(@NonNull Bundle extra) { 717 Preconditions.checkNotNull(extra); 718 mExtra = new Bundle(extra); 719 return this; 720 } 721 722 /** 723 * Creates a {@link TvTrackInfo} instance with the specified fields. 724 * 725 * @return The new {@link TvTrackInfo} instance 726 */ 727 @NonNull build()728 public TvTrackInfo build() { 729 return new TvTrackInfo(mType, mId, mLanguage, mDescription, mEncoding, mEncrypted, 730 mAudioChannelCount, mAudioSampleRate, mAudioDescription, mHardOfHearing, 731 mSpokenSubtitle, mVideoWidth, mVideoHeight, mVideoFrameRate, 732 mVideoPixelAspectRatio, mVideoActiveFormatDescription, mExtra); 733 } 734 } 735 } 736