package org.schabi.newpipe.extractor.stream; /* * Created by Christian Schabesberger on 04.03.16. * * Copyright (C) Christian Schabesberger 2016 * 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 . */ 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}. * *

* It must not be null, and should be non empty. *

* *

* If you are not able to get an identifier, use the static constant {@link * Stream#ID_UNKNOWN ID_UNKNOWN} of the {@link Stream} class. *

* * @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}. * *

* It must not be null, and should be non empty. *

* * @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}. * *

* 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. *

* *

* The default value is {@code null}. *

* * @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}. * *

* It must not be null. *

* *

* The default delivery method is {@link DeliveryMethod#PROGRESSIVE_HTTP}. *

* * @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. * *

* This property must be set before building the {@link VideoStream}. *

* * @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}. * *

* This resolution can be used by clients to know the quality of the video stream. *

* *

* If you are not able to know the resolution, you should use {@link #RESOLUTION_UNKNOWN} * as the resolution of the video stream. *

* *

* It must be set before building the builder and not null. *

* * @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}. * *

* {@link ItagItem}s are YouTube specific objects, so they are only known for this service * and can be null. *

* *

* The default value is {@code null}. *

* * @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. * *

* The identifier, the content (and so the {@code isUrl} boolean), the {@code isVideoOnly} * and the {@code resolution} properties must have been set. *

* * @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. * *

* It can be unknown for some streams, like for HLS master playlists. In this case, * {@link #RESOLUTION_UNKNOWN} is returned by this method. *

* * @return the video resolution or {@link #RESOLUTION_UNKNOWN} */ @Nonnull public String getResolution() { return resolution; } /** * Return whether the stream is video-only. * *

* Video-only streams have no audio. *

* * @return {@code true} if this stream is video-only, {@code false} otherwise */ public boolean isVideoOnly() { return isVideoOnly; } /** * Get the itag identifier of the stream. * *

* Always equals to {@link #ITAG_NOT_AVAILABLE_OR_NOT_APPLICABLE} for other streams than the * ones of the YouTube service. *

* * @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; } }