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