-
Notifications
You must be signed in to change notification settings - Fork 410
/
VideoStream.java
485 lines (446 loc) · 15.9 KB
/
VideoStream.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
package org.schabi.newpipe.extractor.stream;
/*
* Created by Christian Schabesberger on 04.03.16.
*
* Copyright (C) 2016 Christian Schabesberger <chris.schabesberger@mailbox.org>
* VideoStream.java is part of NewPipe Extractor.
*
* NewPipe Extractor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe Extractor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe Extractor. If not, see <https://www.gnu.org/licenses/>.
*/
import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.services.youtube.ItagItem;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public final class VideoStream extends Stream {
public static final String RESOLUTION_UNKNOWN = "";
/** @deprecated Use {@link #getResolution()} instead. */
@Deprecated
public final String resolution;
/** @deprecated Use {@link #isVideoOnly()} instead. */
@Deprecated
public final boolean isVideoOnly;
// Fields for DASH
private int itag = ITAG_NOT_AVAILABLE_OR_NOT_APPLICABLE;
private int bitrate;
private int initStart;
private int initEnd;
private int indexStart;
private int indexEnd;
private int width;
private int height;
private int fps;
private String quality;
private String codec;
@Nullable private ItagItem itagItem;
/**
* Class to build {@link VideoStream} objects.
*/
@SuppressWarnings("checkstyle:hiddenField")
public static final class Builder {
private String id;
private String content;
private boolean isUrl;
private DeliveryMethod deliveryMethod = DeliveryMethod.PROGRESSIVE_HTTP;
@Nullable
private MediaFormat mediaFormat;
@Nullable
private String manifestUrl;
// Use of the Boolean class instead of the primitive type needed for setter call check
private Boolean isVideoOnly;
private String resolution;
@Nullable
private ItagItem itagItem;
/**
* Create a new {@link Builder} instance with its default values.
*/
public Builder() {
}
/**
* Set the identifier of the {@link VideoStream}.
*
* <p>
* It must not be null, and should be non empty.
* </p>
*
* <p>
* If you are not able to get an identifier, use the static constant {@link
* Stream#ID_UNKNOWN ID_UNKNOWN} of the {@link Stream} class.
* </p>
*
* @param id the identifier of the {@link VideoStream}, which must not be null
* @return this {@link Builder} instance
*/
public Builder setId(@Nonnull final String id) {
this.id = id;
return this;
}
/**
* Set the content of the {@link VideoStream}.
*
* <p>
* It must not be null, and should be non empty.
* </p>
*
* @param content the content of the {@link VideoStream}
* @param isUrl whether the content is a URL
* @return this {@link Builder} instance
*/
public Builder setContent(@Nonnull final String content,
final boolean isUrl) {
this.content = content;
this.isUrl = isUrl;
return this;
}
/**
* Set the {@link MediaFormat} used by the {@link VideoStream}.
*
* <p>
* It should be one of the video {@link MediaFormat}s ({@link MediaFormat#MPEG_4 MPEG_4},
* {@link MediaFormat#v3GPP v3GPP}, or {@link MediaFormat#WEBM WEBM}) but can be {@code
* null} if the media format could not be determined.
* </p>
*
* <p>
* The default value is {@code null}.
* </p>
*
* @param mediaFormat the {@link MediaFormat} of the {@link VideoStream}, which can be null
* @return this {@link Builder} instance
*/
public Builder setMediaFormat(@Nullable final MediaFormat mediaFormat) {
this.mediaFormat = mediaFormat;
return this;
}
/**
* Set the {@link DeliveryMethod} of the {@link VideoStream}.
*
* <p>
* It must not be null.
* </p>
*
* <p>
* The default delivery method is {@link DeliveryMethod#PROGRESSIVE_HTTP}.
* </p>
*
* @param deliveryMethod the {@link DeliveryMethod} of the {@link VideoStream}, which must
* not be null
* @return this {@link Builder} instance
*/
public Builder setDeliveryMethod(@Nonnull final DeliveryMethod deliveryMethod) {
this.deliveryMethod = deliveryMethod;
return this;
}
/**
* Sets the URL of the manifest this stream comes from (if applicable, otherwise null).
*
* @param manifestUrl the URL of the manifest this stream comes from or {@code null}
* @return this {@link Builder} instance
*/
public Builder setManifestUrl(@Nullable final String manifestUrl) {
this.manifestUrl = manifestUrl;
return this;
}
/**
* Set whether the {@link VideoStream} is video-only.
*
* <p>
* This property must be set before building the {@link VideoStream}.
* </p>
*
* @param isVideoOnly whether the {@link VideoStream} is video-only
* @return this {@link Builder} instance
*/
public Builder setIsVideoOnly(final boolean isVideoOnly) {
this.isVideoOnly = isVideoOnly;
return this;
}
/**
* Set the resolution of the {@link VideoStream}.
*
* <p>
* This resolution can be used by clients to know the quality of the video stream.
* </p>
*
* <p>
* If you are not able to know the resolution, you should use {@link #RESOLUTION_UNKNOWN}
* as the resolution of the video stream.
* </p>
*
* <p>
* It must be set before building the builder and not null.
* </p>
*
* @param resolution the resolution of the {@link VideoStream}
* @return this {@link Builder} instance
*/
public Builder setResolution(@Nonnull final String resolution) {
this.resolution = resolution;
return this;
}
/**
* Set the {@link ItagItem} corresponding to the {@link VideoStream}.
*
* <p>
* {@link ItagItem}s are YouTube specific objects, so they are only known for this service
* and can be null.
* </p>
*
* <p>
* The default value is {@code null}.
* </p>
*
* @param itagItem the {@link ItagItem} of the {@link VideoStream}, which can be null
* @return this {@link Builder} instance
*/
public Builder setItagItem(@Nullable final ItagItem itagItem) {
this.itagItem = itagItem;
return this;
}
/**
* Build a {@link VideoStream} using the builder's current values.
*
* <p>
* The identifier, the content (and so the {@code isUrl} boolean), the {@code isVideoOnly}
* and the {@code resolution} properties must have been set.
* </p>
*
* @return a new {@link VideoStream} using the builder's current values
* @throws IllegalStateException if {@code id}, {@code content} (and so {@code isUrl}),
* {@code deliveryMethod}, {@code isVideoOnly} or {@code resolution} have been not set, or
* have been set as {@code null}
*/
@Nonnull
public VideoStream build() {
if (id == null) {
throw new IllegalStateException(
"The identifier of the video stream has been not set or is null. If you "
+ "are not able to get an identifier, use the static constant "
+ "ID_UNKNOWN of the Stream class.");
}
if (content == null) {
throw new IllegalStateException("The content of the video stream has been not set "
+ "or is null. Please specify a non-null one with setContent.");
}
if (deliveryMethod == null) {
throw new IllegalStateException(
"The delivery method of the video stream has been set as null, which is "
+ "not allowed. Pass a valid one instead with setDeliveryMethod.");
}
if (isVideoOnly == null) {
throw new IllegalStateException("The video stream has been not set as a "
+ "video-only stream or as a video stream with embedded audio. Please "
+ "specify this information with setIsVideoOnly.");
}
if (resolution == null) {
throw new IllegalStateException(
"The resolution of the video stream has been not set. Please specify it "
+ "with setResolution (use an empty string if you are not able to "
+ "get it).");
}
return new VideoStream(id, content, isUrl, mediaFormat, deliveryMethod, resolution,
isVideoOnly, manifestUrl, itagItem);
}
}
/**
* Create a new video stream.
*
* @param id the identifier which uniquely identifies the stream, e.g. for YouTube
* this would be the itag
* @param content the content or the URL of the stream, depending on whether isUrl is
* true
* @param isUrl whether content is the URL or the actual content of e.g. a DASH
* manifest
* @param format the {@link MediaFormat} used by the stream, which can be null
* @param deliveryMethod the {@link DeliveryMethod} of the stream
* @param resolution the resolution of the stream
* @param isVideoOnly whether the stream is video-only
* @param itagItem the {@link ItagItem} corresponding to the stream, which cannot be null
* @param manifestUrl the URL of the manifest this stream comes from (if applicable,
* otherwise null)
*/
@SuppressWarnings("checkstyle:ParameterNumber")
private VideoStream(@Nonnull final String id,
@Nonnull final String content,
final boolean isUrl,
@Nullable final MediaFormat format,
@Nonnull final DeliveryMethod deliveryMethod,
@Nonnull final String resolution,
final boolean isVideoOnly,
@Nullable final String manifestUrl,
@Nullable final ItagItem itagItem) {
super(id, content, isUrl, format, deliveryMethod, manifestUrl);
if (itagItem != null) {
this.itagItem = itagItem;
this.itag = itagItem.id;
this.bitrate = itagItem.getBitrate();
this.initStart = itagItem.getInitStart();
this.initEnd = itagItem.getInitEnd();
this.indexStart = itagItem.getIndexStart();
this.indexEnd = itagItem.getIndexEnd();
this.codec = itagItem.getCodec();
this.height = itagItem.getHeight();
this.width = itagItem.getWidth();
this.quality = itagItem.getQuality();
this.fps = itagItem.getFps();
}
this.resolution = resolution;
this.isVideoOnly = isVideoOnly;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equalStats(final Stream cmp) {
return super.equalStats(cmp)
&& cmp instanceof VideoStream
&& resolution.equals(((VideoStream) cmp).resolution)
&& isVideoOnly == ((VideoStream) cmp).isVideoOnly;
}
/**
* Get the video resolution.
*
* <p>
* It can be unknown for some streams, like for HLS master playlists. In this case,
* {@link #RESOLUTION_UNKNOWN} is returned by this method.
* </p>
*
* @return the video resolution or {@link #RESOLUTION_UNKNOWN}
*/
@Nonnull
public String getResolution() {
return resolution;
}
/**
* Return whether the stream is video-only.
*
* <p>
* Video-only streams have no audio.
* </p>
*
* @return {@code true} if this stream is video-only, {@code false} otherwise
*/
public boolean isVideoOnly() {
return isVideoOnly;
}
/**
* Get the itag identifier of the stream.
*
* <p>
* Always equals to {@link #ITAG_NOT_AVAILABLE_OR_NOT_APPLICABLE} for other streams than the
* ones of the YouTube service.
* </p>
*
* @return the number of the {@link ItagItem} passed in the constructor of the video stream.
*/
public int getItag() {
return itag;
}
/**
* Get the bitrate of the stream.
*
* @return the bitrate set from the {@link ItagItem} passed in the constructor of the stream.
*/
public int getBitrate() {
return bitrate;
}
/**
* Get the initialization start of the stream.
*
* @return the initialization start value set from the {@link ItagItem} passed in the
* constructor of the
* stream.
*/
public int getInitStart() {
return initStart;
}
/**
* Get the initialization end of the stream.
*
* @return the initialization end value set from the {@link ItagItem} passed in the constructor
* of the stream.
*/
public int getInitEnd() {
return initEnd;
}
/**
* Get the index start of the stream.
*
* @return the index start value set from the {@link ItagItem} passed in the constructor of the
* stream.
*/
public int getIndexStart() {
return indexStart;
}
/**
* Get the index end of the stream.
*
* @return the index end value set from the {@link ItagItem} passed in the constructor of the
* stream.
*/
public int getIndexEnd() {
return indexEnd;
}
/**
* Get the width of the video stream.
*
* @return the width set from the {@link ItagItem} passed in the constructor of the
* stream.
*/
public int getWidth() {
return width;
}
/**
* Get the height of the video stream.
*
* @return the height set from the {@link ItagItem} passed in the constructor of the
* stream.
*/
public int getHeight() {
return height;
}
/**
* Get the frames per second of the video stream.
*
* @return the frames per second set from the {@link ItagItem} passed in the constructor of the
* stream.
*/
public int getFps() {
return fps;
}
/**
* Get the quality of the stream.
*
* @return the quality label set from the {@link ItagItem} passed in the constructor of the
* stream.
*/
public String getQuality() {
return quality;
}
/**
* Get the codec of the stream.
*
* @return the codec set from the {@link ItagItem} passed in the constructor of the stream.
*/
public String getCodec() {
return codec;
}
/**
* {@inheritDoc}
*/
@Override
@Nullable
public ItagItem getItagItem() {
return itagItem;
}
}