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.NonNull;
20import android.os.Bundle;
21import android.os.Parcel;
22import android.os.Parcelable;
23
24import com.android.internal.util.Preconditions;
25
26/**
27 * Encapsulates the format of tracks played in {@link TvInputService}.
28 */
29public final class TvTrackInfo implements Parcelable {
30    /**
31     * The type value for audio tracks.
32     */
33    public static final int TYPE_AUDIO = 0;
34
35    /**
36     * The type value for video tracks.
37     */
38    public static final int TYPE_VIDEO = 1;
39
40    /**
41     * The type value for subtitle tracks.
42     */
43    public static final int TYPE_SUBTITLE = 2;
44
45    private final int mType;
46    private final String mId;
47    private final String mLanguage;
48    private final CharSequence mDescription;
49    private final int mAudioChannelCount;
50    private final int mAudioSampleRate;
51    private final int mVideoWidth;
52    private final int mVideoHeight;
53    private final float mVideoFrameRate;
54    private final float mVideoPixelAspectRatio;
55    private final Bundle mExtra;
56
57    private TvTrackInfo(int type, String id, String language, CharSequence description,
58            int audioChannelCount, int audioSampleRate, int videoWidth, int videoHeight,
59            float videoFrameRate, float videoPixelAspectRatio, Bundle extra) {
60        mType = type;
61        mId = id;
62        mLanguage = language;
63        mDescription = description;
64        mAudioChannelCount = audioChannelCount;
65        mAudioSampleRate = audioSampleRate;
66        mVideoWidth = videoWidth;
67        mVideoHeight = videoHeight;
68        mVideoFrameRate = videoFrameRate;
69        mVideoPixelAspectRatio = videoPixelAspectRatio;
70        mExtra = extra;
71    }
72
73    private TvTrackInfo(Parcel in) {
74        mType = in.readInt();
75        mId = in.readString();
76        mLanguage = in.readString();
77        mDescription = in.readString();
78        mAudioChannelCount = in.readInt();
79        mAudioSampleRate = in.readInt();
80        mVideoWidth = in.readInt();
81        mVideoHeight = in.readInt();
82        mVideoFrameRate = in.readFloat();
83        mVideoPixelAspectRatio = in.readFloat();
84        mExtra = in.readBundle();
85    }
86
87    /**
88     * Returns the type of the track. The type should be one of the followings:
89     * {@link #TYPE_AUDIO}, {@link #TYPE_VIDEO} and {@link #TYPE_SUBTITLE}.
90     */
91    public final int getType() {
92        return mType;
93    }
94
95    /**
96     * Returns the ID of the track.
97     */
98    public final String getId() {
99        return mId;
100    }
101
102    /**
103     * Returns the language information encoded by either ISO 639-1 or ISO 639-2/T. If the language
104     * is unknown or could not be determined, the corresponding value will be {@code null}.
105     */
106    public final String getLanguage() {
107        return mLanguage;
108    }
109
110    /**
111     * Returns a user readable description for the current track.
112     */
113    public final CharSequence getDescription() {
114        return mDescription;
115    }
116
117    /**
118     * Returns the audio channel count. Valid only for {@link #TYPE_AUDIO} tracks.
119     */
120    public final int getAudioChannelCount() {
121        if (mType != TYPE_AUDIO) {
122            throw new IllegalStateException("Not an audio track");
123        }
124        return mAudioChannelCount;
125    }
126
127    /**
128     * Returns the audio sample rate, in the unit of Hz. Valid only for {@link #TYPE_AUDIO} tracks.
129     */
130    public final int getAudioSampleRate() {
131        if (mType != TYPE_AUDIO) {
132            throw new IllegalStateException("Not an audio track");
133        }
134        return mAudioSampleRate;
135    }
136
137    /**
138     * Returns the width of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
139     * tracks.
140     */
141    public final int getVideoWidth() {
142        if (mType != TYPE_VIDEO) {
143            throw new IllegalStateException("Not a video track");
144        }
145        return mVideoWidth;
146    }
147
148    /**
149     * Returns the height of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
150     * tracks.
151     */
152    public final int getVideoHeight() {
153        if (mType != TYPE_VIDEO) {
154            throw new IllegalStateException("Not a video track");
155        }
156        return mVideoHeight;
157    }
158
159    /**
160     * Returns the frame rate of the video, in the unit of fps (frames per second). Valid only for
161     * {@link #TYPE_VIDEO} tracks.
162     */
163    public final float getVideoFrameRate() {
164        if (mType != TYPE_VIDEO) {
165            throw new IllegalStateException("Not a video track");
166        }
167        return mVideoFrameRate;
168    }
169
170    /**
171     * Returns the pixel aspect ratio (the ratio of a pixel's width to its height) of the video.
172     * Valid only for {@link #TYPE_VIDEO} tracks.
173     */
174    public final float getVideoPixelAspectRatio() {
175        if (mType != TYPE_VIDEO) {
176            throw new IllegalStateException("Not a video track");
177        }
178        return mVideoPixelAspectRatio;
179    }
180
181    /**
182     * Returns the extra information about the current track.
183     */
184    public final Bundle getExtra() {
185        return mExtra;
186    }
187
188    @Override
189    public int describeContents() {
190        return 0;
191    }
192
193    /**
194     * Used to package this object into a {@link Parcel}.
195     *
196     * @param dest The {@link Parcel} to be written.
197     * @param flags The flags used for parceling.
198     */
199    @Override
200    public void writeToParcel(Parcel dest, int flags) {
201        dest.writeInt(mType);
202        dest.writeString(mId);
203        dest.writeString(mLanguage);
204        dest.writeString(mDescription != null ? mDescription.toString() : null);
205        dest.writeInt(mAudioChannelCount);
206        dest.writeInt(mAudioSampleRate);
207        dest.writeInt(mVideoWidth);
208        dest.writeInt(mVideoHeight);
209        dest.writeFloat(mVideoFrameRate);
210        dest.writeFloat(mVideoPixelAspectRatio);
211        dest.writeBundle(mExtra);
212    }
213
214    public static final Parcelable.Creator<TvTrackInfo> CREATOR =
215            new Parcelable.Creator<TvTrackInfo>() {
216                @Override
217                public TvTrackInfo createFromParcel(Parcel in) {
218                    return new TvTrackInfo(in);
219                }
220
221                @Override
222                public TvTrackInfo[] newArray(int size) {
223                    return new TvTrackInfo[size];
224                }
225            };
226
227    /**
228     * A builder class for creating {@link TvTrackInfo} objects.
229     */
230    public static final class Builder {
231        private final String mId;
232        private final int mType;
233        private String mLanguage;
234        private CharSequence mDescription;
235        private int mAudioChannelCount;
236        private int mAudioSampleRate;
237        private int mVideoWidth;
238        private int mVideoHeight;
239        private float mVideoFrameRate;
240        private float mVideoPixelAspectRatio = 1.0f;
241        private Bundle mExtra;
242
243        /**
244         * Create a {@link Builder}. Any field that should be included in the {@link TvTrackInfo}
245         * must be added.
246         *
247         * @param type The type of the track.
248         * @param id The ID of the track that uniquely identifies the current track among all the
249         *            other tracks in the same TV program.
250         */
251        public Builder(int type, @NonNull String id) {
252            if (type != TYPE_AUDIO
253                    && type != TYPE_VIDEO
254                    && type != TYPE_SUBTITLE) {
255                throw new IllegalArgumentException("Unknown type: " + type);
256            }
257            Preconditions.checkNotNull(id);
258            mType = type;
259            mId = id;
260        }
261
262        /**
263         * Sets the language information of the current track.
264         *
265         * @param language The language string encoded by either ISO 639-1 or ISO 639-2/T.
266         */
267        public final Builder setLanguage(String language) {
268            mLanguage = language;
269            return this;
270        }
271
272        /**
273         * Sets a user readable description for the current track.
274         *
275         * @param description The user readable description.
276         */
277        public final Builder setDescription(CharSequence description) {
278            mDescription = description;
279            return this;
280        }
281
282        /**
283         * Sets the audio channel count. Valid only for {@link #TYPE_AUDIO} tracks.
284         *
285         * @param audioChannelCount The audio channel count.
286         */
287        public final Builder setAudioChannelCount(int audioChannelCount) {
288            if (mType != TYPE_AUDIO) {
289                throw new IllegalStateException("Not an audio track");
290            }
291            mAudioChannelCount = audioChannelCount;
292            return this;
293        }
294
295        /**
296         * Sets the audio sample rate, in the unit of Hz. Valid only for {@link #TYPE_AUDIO}
297         * tracks.
298         *
299         * @param audioSampleRate The audio sample rate.
300         */
301        public final Builder setAudioSampleRate(int audioSampleRate) {
302            if (mType != TYPE_AUDIO) {
303                throw new IllegalStateException("Not an audio track");
304            }
305            mAudioSampleRate = audioSampleRate;
306            return this;
307        }
308
309        /**
310         * Sets the width of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
311         * tracks.
312         *
313         * @param videoWidth The width of the video.
314         */
315        public final Builder setVideoWidth(int videoWidth) {
316            if (mType != TYPE_VIDEO) {
317                throw new IllegalStateException("Not a video track");
318            }
319            mVideoWidth = videoWidth;
320            return this;
321        }
322
323        /**
324         * Sets the height of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
325         * tracks.
326         *
327         * @param videoHeight The height of the video.
328         */
329        public final Builder setVideoHeight(int videoHeight) {
330            if (mType != TYPE_VIDEO) {
331                throw new IllegalStateException("Not a video track");
332            }
333            mVideoHeight = videoHeight;
334            return this;
335        }
336
337        /**
338         * Sets the frame rate of the video, in the unit fps (frames per rate). Valid only for
339         * {@link #TYPE_VIDEO} tracks.
340         *
341         * @param videoFrameRate The frame rate of the video.
342         */
343        public final Builder setVideoFrameRate(float videoFrameRate) {
344            if (mType != TYPE_VIDEO) {
345                throw new IllegalStateException("Not a video track");
346            }
347            mVideoFrameRate = videoFrameRate;
348            return this;
349        }
350
351        /**
352         * Sets the pixel aspect ratio (the ratio of a pixel's width to its height) of the video.
353         * Valid only for {@link #TYPE_VIDEO} tracks.
354         *
355         * <p>This is needed for applications to be able to scale the video properly for some video
356         * formats such as 720x576 4:3 and 720x576 16:9 where pixels are not square. By default,
357         * applications assume the value of 1.0 (square pixels), so it is not necessary to set the
358         * pixel aspect ratio for most video formats.
359         *
360         * @param videoPixelAspectRatio The pixel aspect ratio of the video.
361         */
362        public final Builder setVideoPixelAspectRatio(float videoPixelAspectRatio) {
363            if (mType != TYPE_VIDEO) {
364                throw new IllegalStateException("Not a video track");
365            }
366            mVideoPixelAspectRatio = videoPixelAspectRatio;
367            return this;
368        }
369
370        /**
371         * Sets the extra information about the current track.
372         *
373         * @param extra The extra information.
374         */
375        public final Builder setExtra(Bundle extra) {
376            mExtra = new Bundle(extra);
377            return this;
378        }
379
380        /**
381         * Creates a {@link TvTrackInfo} instance with the specified fields.
382         *
383         * @return The new {@link TvTrackInfo} instance
384         */
385        public TvTrackInfo build() {
386            return new TvTrackInfo(mType, mId, mLanguage, mDescription, mAudioChannelCount,
387                    mAudioSampleRate, mVideoWidth, mVideoHeight, mVideoFrameRate,
388                    mVideoPixelAspectRatio, mExtra);
389        }
390    }
391}
392