NewPipeExtractor/extractor/src/main/java/org/schabi/newpipe/extractor/stream/AudioStream.java

442 lines
15 KiB
Java

package org.schabi.newpipe.extractor.stream;
/*
* Created by Christian Schabesberger on 04.03.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* AudioStream.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;
import java.util.Objects;
public final class AudioStream extends Stream {
public static final int UNKNOWN_BITRATE = -1;
private final int averageBitrate;
// 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 String quality;
private String codec;
// Fields about the audio track id/name
private String audioTrackId;
private String audioTrackName;
@Nullable
private ItagItem itagItem;
/**
* Class to build {@link AudioStream} 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;
private int averageBitrate = UNKNOWN_BITRATE;
@Nullable
private String audioTrackId;
@Nullable
private String audioTrackName;
@Nullable
private ItagItem itagItem;
/**
* Create a new {@link Builder} instance with its default values.
*/
public Builder() {
}
/**
* Set the identifier of the {@link AudioStream}.
*
* <p>
* It <b>must not be null</b> 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 AudioStream}, 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 AudioStream}.
*
* <p>
* It must not be null, and should be non empty.
* </p>
*
* @param content the content of the {@link AudioStream}
* @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 AudioStream}.
*
* <p>
* It should be one of the audio {@link MediaFormat}s ({@link MediaFormat#M4A M4A},
* {@link MediaFormat#WEBMA WEBMA}, {@link MediaFormat#MP3 MP3}, {@link MediaFormat#OPUS
* OPUS}, {@link MediaFormat#OGG OGG}, or {@link MediaFormat#WEBMA_OPUS WEBMA_OPUS}) 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 AudioStream}, 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 AudioStream}.
*
* <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 AudioStream}, 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 the average bitrate of the {@link AudioStream}.
*
* <p>
* The default value is {@link #UNKNOWN_BITRATE}.
* </p>
*
* @param averageBitrate the average bitrate of the {@link AudioStream}, which should
* positive
* @return this {@link Builder} instance
*/
public Builder setAverageBitrate(final int averageBitrate) {
this.averageBitrate = averageBitrate;
return this;
}
/**
* Set the audio track id of the {@link AudioStream}.
*
* @param audioTrackId the audio track id of the {@link AudioStream}
* @return this {@link Builder} instance
*/
public Builder setAudioTrackId(@Nullable final String audioTrackId) {
this.audioTrackId = audioTrackId;
return this;
}
/**
* Set the audio track name of the {@link AudioStream}.
*
* @param audioTrackName the audio track name of the {@link AudioStream}
* @return this {@link Builder} instance
*/
public Builder setAudioTrackName(@Nullable final String audioTrackName) {
this.audioTrackName = audioTrackName;
return this;
}
/**
* Set the {@link ItagItem} corresponding to the {@link AudioStream}.
*
* <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 AudioStream}, which can be null
* @return this {@link Builder} instance
*/
public Builder setItagItem(@Nullable final ItagItem itagItem) {
this.itagItem = itagItem;
return this;
}
/**
* Build an {@link AudioStream} using the builder's current values.
*
* <p>
* The identifier and the content (and so the {@code isUrl} boolean) properties must have
* been set.
* </p>
*
* @return a new {@link AudioStream} using the builder's current values
* @throws IllegalStateException if {@code id}, {@code content} (and so {@code isUrl}) or
* {@code deliveryMethod} have been not set, or have been set as {@code null}
*/
@Nonnull
public AudioStream build() {
if (id == null) {
throw new IllegalStateException(
"The identifier of the audio 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 audio 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 audio stream has been set as null, which is "
+ "not allowed. Pass a valid one instead with setDeliveryMethod.");
}
return new AudioStream(id, content, isUrl, mediaFormat, deliveryMethod, averageBitrate,
manifestUrl, audioTrackId, audioTrackName, itagItem);
}
}
/**
* Create a new audio 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 averageBitrate the average bitrate of the stream (which can be unknown, see
* {@link #UNKNOWN_BITRATE})
* @param audioTrackId the id of the audio track
* @param audioTrackName the name of the audio track
* @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 AudioStream(@Nonnull final String id,
@Nonnull final String content,
final boolean isUrl,
@Nullable final MediaFormat format,
@Nonnull final DeliveryMethod deliveryMethod,
final int averageBitrate,
@Nullable final String manifestUrl,
@Nullable final String audioTrackId,
@Nullable final String audioTrackName,
@Nullable final ItagItem itagItem) {
super(id, content, isUrl, format, deliveryMethod, manifestUrl);
if (itagItem != null) {
this.itagItem = itagItem;
this.itag = itagItem.id;
this.quality = itagItem.getQuality();
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.averageBitrate = averageBitrate;
this.audioTrackId = audioTrackId;
this.audioTrackName = audioTrackName;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equalStats(final Stream cmp) {
return super.equalStats(cmp) && cmp instanceof AudioStream
&& averageBitrate == ((AudioStream) cmp).averageBitrate
&& Objects.equals(audioTrackId, ((AudioStream) cmp).audioTrackId);
}
/**
* Get the average bitrate of the stream.
*
* @return the average bitrate or {@link #UNKNOWN_BITRATE} if it is unknown
*/
public int getAverageBitrate() {
return averageBitrate;
}
/**
* 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 audio 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 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;
}
/**
* Get the id of the audio track.
*
* @return the id of the audio track
*/
@Nullable
public String getAudioTrackId() {
return audioTrackId;
}
/**
* Get the name of the audio track.
*
* @return the name of the audio track
*/
@Nullable
public String getAudioTrackName() {
return audioTrackName;
}
/**
* {@inheritDoc}
*/
@Override
@Nullable
public ItagItem getItagItem() {
return itagItem;
}
}