mirror of
https://github.com/TeamNewPipe/NewPipe.git
synced 2024-11-22 11:02:35 +01:00
Throw a dedicated exception when errors occur in PlaybackResolver
A new exception, ResolverException, a subclass of PlaybackResolver, is now thrown when errors occur in PlaybackResolver, instead of an IOException
This commit is contained in:
parent
036196a487
commit
21c9530e8b
@ -17,7 +17,6 @@ import org.schabi.newpipe.player.mediaitem.MediaItemTag;
|
|||||||
import org.schabi.newpipe.player.mediaitem.StreamInfoTag;
|
import org.schabi.newpipe.player.mediaitem.StreamInfoTag;
|
||||||
import org.schabi.newpipe.util.ListHelper;
|
import org.schabi.newpipe.util.ListHelper;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class AudioPlaybackResolver implements PlaybackResolver {
|
public class AudioPlaybackResolver implements PlaybackResolver {
|
||||||
@ -55,8 +54,8 @@ public class AudioPlaybackResolver implements PlaybackResolver {
|
|||||||
try {
|
try {
|
||||||
return PlaybackResolver.buildMediaSource(
|
return PlaybackResolver.buildMediaSource(
|
||||||
dataSource, audio, info, PlaybackResolver.cacheKeyOf(info, audio), tag);
|
dataSource, audio, info, PlaybackResolver.cacheKeyOf(info, audio), tag);
|
||||||
} catch (final IOException e) {
|
} catch (final ResolverException e) {
|
||||||
Log.e(TAG, "Unable to create audio source:", e);
|
Log.e(TAG, "Unable to create audio source", e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,17 +97,22 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the cache key of a video stream. A cache key is unique to the features of the
|
* Builds the cache key of a {@link VideoStream video stream}.
|
||||||
* provided video stream, and when possible independent of <i>transient</i> parameters (such as
|
|
||||||
* the url of the stream). This ensures that there are no conflicts, but also that the cache is
|
|
||||||
* used as much as possible: the same cache should be used for two streams which have the same
|
|
||||||
* features but e.g. a different url, since the url might have been reloaded in the meantime,
|
|
||||||
* but the stream actually referenced by the url is still the same.
|
|
||||||
*
|
*
|
||||||
* @param info the stream info, to distinguish between streams with the same features but coming
|
* <p>
|
||||||
* from different stream infos
|
* A cache key is unique to the features of the provided video stream, and when possible
|
||||||
* @param videoStream the video stream for which the cache key should be created
|
* independent of <i>transient</i> parameters (such as the URL of the stream).
|
||||||
* @return a key to be used to store the cache of the provided video stream
|
* This ensures that there are no conflicts, but also that the cache is used as much as
|
||||||
|
* possible: the same cache should be used for two streams which have the same features but
|
||||||
|
* e.g. a different URL, since the URL might have been reloaded in the meantime, but the stream
|
||||||
|
* actually referenced by the URL is still the same.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param info the {@link StreamInfo stream info}, to distinguish between streams with
|
||||||
|
* the same features but coming from different stream infos
|
||||||
|
* @param videoStream the {@link VideoStream video stream} for which the cache key should be
|
||||||
|
* created
|
||||||
|
* @return a key to be used to store the cache of the provided {@link VideoStream video stream}
|
||||||
*/
|
*/
|
||||||
static String cacheKeyOf(final StreamInfo info, final VideoStream videoStream) {
|
static String cacheKeyOf(final StreamInfo info, final VideoStream videoStream) {
|
||||||
final boolean resolutionUnknown = videoStream.getResolution().equals(RESOLUTION_UNKNOWN);
|
final boolean resolutionUnknown = videoStream.getResolution().equals(RESOLUTION_UNKNOWN);
|
||||||
@ -127,17 +132,22 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the cache key of an audio stream. A cache key is unique to the features of the
|
* Builds the cache key of an audio stream.
|
||||||
* provided audio stream, and when possible independent of <i>transient</i> parameters (such as
|
|
||||||
* the url of the stream). This ensures that there are no conflicts, but also that the cache is
|
|
||||||
* used as much as possible: the same cache should be used for two streams which have the same
|
|
||||||
* features but e.g. a different url, since the url might have been reloaded in the meantime,
|
|
||||||
* but the stream actually referenced by the url is still the same.
|
|
||||||
*
|
*
|
||||||
* @param info the stream info, to distinguish between streams with the same features but coming
|
* <p>
|
||||||
* from different stream infos
|
* A cache key is unique to the features of the provided {@link AudioStream audio stream}, and
|
||||||
* @param audioStream the audio stream for which the cache key should be created
|
* when possible independent of <i>transient</i> parameters (such as the URL of the stream).
|
||||||
* @return a key to be used to store the cache of the provided audio stream
|
* This ensures that there are no conflicts, but also that the cache is used as much as
|
||||||
|
* possible: the same cache should be used for two streams which have the same features but
|
||||||
|
* e.g. a different URL, since the URL might have been reloaded in the meantime, but the stream
|
||||||
|
* actually referenced by the URL is still the same.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param info the {@link StreamInfo stream info}, to distinguish between streams with
|
||||||
|
* the same features but coming from different stream infos
|
||||||
|
* @param audioStream the {@link AudioStream audio stream} for which the cache key should be
|
||||||
|
* created
|
||||||
|
* @return a key to be used to store the cache of the provided {@link AudioStream audio stream}
|
||||||
*/
|
*/
|
||||||
static String cacheKeyOf(final StreamInfo info, final AudioStream audioStream) {
|
static String cacheKeyOf(final StreamInfo info, final AudioStream audioStream) {
|
||||||
final boolean averageBitrateUnknown = audioStream.getAverageBitrate() == UNKNOWN_BITRATE;
|
final boolean averageBitrateUnknown = audioStream.getAverageBitrate() == UNKNOWN_BITRATE;
|
||||||
@ -158,16 +168,20 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
@Nullable
|
@Nullable
|
||||||
static MediaSource maybeBuildLiveMediaSource(final PlayerDataSource dataSource,
|
static MediaSource maybeBuildLiveMediaSource(final PlayerDataSource dataSource,
|
||||||
final StreamInfo info) {
|
final StreamInfo info) {
|
||||||
final StreamType streamType = info.getStreamType();
|
if (!StreamTypeUtil.isLiveStream(info.getStreamType())) {
|
||||||
if (!StreamTypeUtil.isLiveStream(streamType)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final StreamInfoTag tag = StreamInfoTag.of(info);
|
try {
|
||||||
if (!info.getHlsUrl().isEmpty()) {
|
final StreamInfoTag tag = StreamInfoTag.of(info);
|
||||||
return buildLiveMediaSource(dataSource, info.getHlsUrl(), C.TYPE_HLS, tag);
|
if (!info.getHlsUrl().isEmpty()) {
|
||||||
} else if (!info.getDashMpdUrl().isEmpty()) {
|
return buildLiveMediaSource(dataSource, info.getHlsUrl(), C.TYPE_HLS, tag);
|
||||||
return buildLiveMediaSource(dataSource, info.getDashMpdUrl(), C.TYPE_DASH, tag);
|
} else if (!info.getDashMpdUrl().isEmpty()) {
|
||||||
|
return buildLiveMediaSource(dataSource, info.getDashMpdUrl(), C.TYPE_DASH, tag);
|
||||||
|
}
|
||||||
|
} catch (final Exception e) {
|
||||||
|
Log.w(TAG, "Error when generating live media source, falling back to standard sources",
|
||||||
|
e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -176,7 +190,7 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
static MediaSource buildLiveMediaSource(final PlayerDataSource dataSource,
|
static MediaSource buildLiveMediaSource(final PlayerDataSource dataSource,
|
||||||
final String sourceUrl,
|
final String sourceUrl,
|
||||||
@C.ContentType final int type,
|
@C.ContentType final int type,
|
||||||
final MediaItemTag metadata) {
|
final MediaItemTag metadata) throws ResolverException {
|
||||||
final MediaSource.Factory factory;
|
final MediaSource.Factory factory;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case C.TYPE_SS:
|
case C.TYPE_SS:
|
||||||
@ -188,8 +202,10 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
case C.TYPE_HLS:
|
case C.TYPE_HLS:
|
||||||
factory = dataSource.getLiveHlsMediaSourceFactory();
|
factory = dataSource.getLiveHlsMediaSourceFactory();
|
||||||
break;
|
break;
|
||||||
case C.TYPE_OTHER: case C.TYPE_RTSP: default:
|
case C.TYPE_OTHER:
|
||||||
throw new IllegalStateException("Unsupported type: " + type);
|
case C.TYPE_RTSP:
|
||||||
|
default:
|
||||||
|
throw new ResolverException("Unsupported type: " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
return factory.createMediaSource(
|
return factory.createMediaSource(
|
||||||
@ -210,8 +226,7 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
final Stream stream,
|
final Stream stream,
|
||||||
final StreamInfo streamInfo,
|
final StreamInfo streamInfo,
|
||||||
final String cacheKey,
|
final String cacheKey,
|
||||||
final MediaItemTag metadata)
|
final MediaItemTag metadata) throws ResolverException {
|
||||||
throws IOException {
|
|
||||||
if (streamInfo.getService() == ServiceList.YouTube) {
|
if (streamInfo.getService() == ServiceList.YouTube) {
|
||||||
return createYoutubeMediaSource(stream, streamInfo, dataSource, cacheKey, metadata);
|
return createYoutubeMediaSource(stream, streamInfo, dataSource, cacheKey, metadata);
|
||||||
}
|
}
|
||||||
@ -228,7 +243,7 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
return buildSSMediaSource(dataSource, stream, cacheKey, metadata);
|
return buildSSMediaSource(dataSource, stream, cacheKey, metadata);
|
||||||
// Torrent streams are not supported by ExoPlayer
|
// Torrent streams are not supported by ExoPlayer
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Unsupported delivery type: " + deliveryMethod);
|
throw new ResolverException("Unsupported delivery type: " + deliveryMethod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,11 +251,11 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
final PlayerDataSource dataSource,
|
final PlayerDataSource dataSource,
|
||||||
final Stream stream,
|
final Stream stream,
|
||||||
final String cacheKey,
|
final String cacheKey,
|
||||||
final MediaItemTag metadata) throws IOException {
|
final MediaItemTag metadata) throws ResolverException {
|
||||||
final String url = stream.getContent();
|
final String url = stream.getContent();
|
||||||
|
|
||||||
if (isNullOrEmpty(url)) {
|
if (isNullOrEmpty(url)) {
|
||||||
throw new IOException(
|
throw new ResolverException(
|
||||||
"Try to generate a progressive media source from an empty string or from a "
|
"Try to generate a progressive media source from an empty string or from a "
|
||||||
+ "null object");
|
+ "null object");
|
||||||
} else {
|
} else {
|
||||||
@ -257,11 +272,11 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
final Stream stream,
|
final Stream stream,
|
||||||
final String cacheKey,
|
final String cacheKey,
|
||||||
final MediaItemTag metadata)
|
final MediaItemTag metadata)
|
||||||
throws IOException {
|
throws ResolverException {
|
||||||
final boolean isUrlStream = stream.isUrl();
|
final boolean isUrlStream = stream.isUrl();
|
||||||
if (isUrlStream && isNullOrEmpty(stream.getContent())) {
|
if (isUrlStream && isNullOrEmpty(stream.getContent())) {
|
||||||
throw new IOException("Try to generate a DASH media source from an empty string or "
|
throw new ResolverException(
|
||||||
+ "from a null object");
|
"Could not build a DASH media source from an empty or a null URL content");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUrlStream) {
|
if (isUrlStream) {
|
||||||
@ -279,41 +294,42 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
|
|
||||||
final Uri uri = Uri.parse(baseUrl);
|
final Uri uri = Uri.parse(baseUrl);
|
||||||
|
|
||||||
return dataSource.getDashMediaSourceFactory().createMediaSource(
|
try {
|
||||||
createDashManifest(stream.getContent(), stream),
|
return dataSource.getDashMediaSourceFactory().createMediaSource(
|
||||||
new MediaItem.Builder()
|
createDashManifest(stream.getContent(), stream),
|
||||||
.setTag(metadata)
|
new MediaItem.Builder()
|
||||||
.setUri(uri)
|
.setTag(metadata)
|
||||||
.setCustomCacheKey(cacheKey)
|
.setUri(uri)
|
||||||
.build());
|
.setCustomCacheKey(cacheKey)
|
||||||
|
.build());
|
||||||
|
} catch (final IOException e) {
|
||||||
|
throw new ResolverException(
|
||||||
|
"Could not create a DASH media source/manifest from the manifest text");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DashManifest createDashManifest(final String manifestContent,
|
private static DashManifest createDashManifest(final String manifestContent,
|
||||||
final Stream stream) throws IOException {
|
final Stream stream) throws IOException {
|
||||||
try {
|
final ByteArrayInputStream dashManifestInput = new ByteArrayInputStream(
|
||||||
final ByteArrayInputStream dashManifestInput = new ByteArrayInputStream(
|
manifestContent.getBytes(StandardCharsets.UTF_8));
|
||||||
manifestContent.getBytes(StandardCharsets.UTF_8));
|
String baseUrl = stream.getManifestUrl();
|
||||||
String baseUrl = stream.getManifestUrl();
|
if (baseUrl == null) {
|
||||||
if (baseUrl == null) {
|
baseUrl = "";
|
||||||
baseUrl = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return new DashManifestParser().parse(Uri.parse(baseUrl), dashManifestInput);
|
|
||||||
} catch (final IOException e) {
|
|
||||||
throw new IOException("Error when parsing manual DASH manifest", e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new DashManifestParser().parse(Uri.parse(baseUrl), dashManifestInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HlsMediaSource buildHlsMediaSource(final PlayerDataSource dataSource,
|
private static HlsMediaSource buildHlsMediaSource(final PlayerDataSource dataSource,
|
||||||
final Stream stream,
|
final Stream stream,
|
||||||
final String cacheKey,
|
final String cacheKey,
|
||||||
final MediaItemTag metadata)
|
final MediaItemTag metadata)
|
||||||
throws IOException {
|
throws ResolverException {
|
||||||
final boolean isUrlStream = stream.isUrl();
|
final boolean isUrlStream = stream.isUrl();
|
||||||
if (isUrlStream && isNullOrEmpty(stream.getContent())) {
|
if (isUrlStream && isNullOrEmpty(stream.getContent())) {
|
||||||
throw new IOException("Try to generate an HLS media source from an empty string or "
|
throw new ResolverException(
|
||||||
+ "from a null object");
|
"Could not build a HLS media source from an empty or a null URL content");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUrlStream) {
|
if (isUrlStream) {
|
||||||
@ -337,7 +353,7 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
stream.getContent().getBytes(StandardCharsets.UTF_8));
|
stream.getContent().getBytes(StandardCharsets.UTF_8));
|
||||||
hlsPlaylist = new HlsPlaylistParser().parse(uri, hlsManifestInput);
|
hlsPlaylist = new HlsPlaylistParser().parse(uri, hlsManifestInput);
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
throw new IOException("Error when parsing manual HLS manifest", e);
|
throw new ResolverException("Error when parsing manual HLS manifest", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dataSource.getHlsMediaSourceFactory(
|
return dataSource.getHlsMediaSourceFactory(
|
||||||
@ -354,11 +370,11 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
final Stream stream,
|
final Stream stream,
|
||||||
final String cacheKey,
|
final String cacheKey,
|
||||||
final MediaItemTag metadata)
|
final MediaItemTag metadata)
|
||||||
throws IOException {
|
throws ResolverException {
|
||||||
final boolean isUrlStream = stream.isUrl();
|
final boolean isUrlStream = stream.isUrl();
|
||||||
if (isUrlStream && isNullOrEmpty(stream.getContent())) {
|
if (isUrlStream && isNullOrEmpty(stream.getContent())) {
|
||||||
throw new IOException("Try to generate an SmoothStreaming media source from an empty "
|
throw new ResolverException(
|
||||||
+ "string or from a null object");
|
"Could not build a SS media source from an empty or a null URL content");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUrlStream) {
|
if (isUrlStream) {
|
||||||
@ -383,7 +399,7 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
smoothStreamingManifest = new SsManifestParser().parse(uri,
|
smoothStreamingManifest = new SsManifestParser().parse(uri,
|
||||||
smoothStreamingManifestInput);
|
smoothStreamingManifestInput);
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
throw new IOException("Error when parsing manual SmoothStreaming manifest", e);
|
throw new ResolverException("Error when parsing manual SS manifest", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dataSource.getSSMediaSourceFactory().createMediaSource(
|
return dataSource.getSSMediaSourceFactory().createMediaSource(
|
||||||
@ -404,10 +420,10 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
final PlayerDataSource dataSource,
|
final PlayerDataSource dataSource,
|
||||||
final String cacheKey,
|
final String cacheKey,
|
||||||
final MediaItemTag metadata)
|
final MediaItemTag metadata)
|
||||||
throws IOException {
|
throws ResolverException {
|
||||||
if (!(stream instanceof AudioStream || stream instanceof VideoStream)) {
|
if (!(stream instanceof AudioStream || stream instanceof VideoStream)) {
|
||||||
throw new IOException("Try to generate a DASH manifest of a YouTube "
|
throw new ResolverException("Generation of YouTube DASH manifest for "
|
||||||
+ stream.getClass() + " " + stream.getContent());
|
+ stream.getClass().getSimpleName() + " is not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
final StreamType streamType = streamInfo.getStreamType();
|
final StreamType streamType = streamInfo.getStreamType();
|
||||||
@ -430,15 +446,15 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
return buildYoutubeManualDashMediaSource(dataSource,
|
return buildYoutubeManualDashMediaSource(dataSource,
|
||||||
createDashManifest(manifestString, stream), stream, cacheKey,
|
createDashManifest(manifestString, stream), stream, cacheKey,
|
||||||
metadata);
|
metadata);
|
||||||
} catch (final CreationException | NullPointerException e) {
|
} catch (final CreationException | IOException | NullPointerException e) {
|
||||||
Log.e(TAG, "Error when generating the DASH manifest of YouTube ended live stream",
|
Log.e(TAG, "Error when generating the DASH manifest of YouTube ended live stream",
|
||||||
e);
|
e);
|
||||||
throw new IOException("Error when generating the DASH manifest of YouTube ended "
|
throw new ResolverException(
|
||||||
+ "live stream " + stream.getContent(), e);
|
"Error when generating the DASH manifest of YouTube ended live stream", e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("DASH manifest generation of YouTube livestreams is "
|
throw new ResolverException(
|
||||||
+ "not supported");
|
"DASH manifest generation of YouTube livestreams is not supported");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,7 +463,7 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
final Stream stream,
|
final Stream stream,
|
||||||
final StreamInfo streamInfo,
|
final StreamInfo streamInfo,
|
||||||
final String cacheKey,
|
final String cacheKey,
|
||||||
final MediaItemTag metadata) throws IOException {
|
final MediaItemTag metadata) throws ResolverException {
|
||||||
final DeliveryMethod deliveryMethod = stream.getDeliveryMethod();
|
final DeliveryMethod deliveryMethod = stream.getDeliveryMethod();
|
||||||
switch (deliveryMethod) {
|
switch (deliveryMethod) {
|
||||||
case PROGRESSIVE_HTTP:
|
case PROGRESSIVE_HTTP:
|
||||||
@ -488,12 +504,11 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
return buildYoutubeManualDashMediaSource(dataSource,
|
return buildYoutubeManualDashMediaSource(dataSource,
|
||||||
createDashManifest(manifestString, stream), stream, cacheKey,
|
createDashManifest(manifestString, stream), stream, cacheKey,
|
||||||
metadata);
|
metadata);
|
||||||
} catch (final CreationException | NullPointerException e) {
|
} catch (final CreationException | IOException | NullPointerException e) {
|
||||||
Log.e(TAG,
|
Log.e(TAG,
|
||||||
"Error when generating the DASH manifest of YouTube OTF stream", e);
|
"Error when generating the DASH manifest of YouTube OTF stream", e);
|
||||||
throw new IOException(
|
throw new ResolverException(
|
||||||
"Error when generating the DASH manifest of YouTube OTF stream "
|
"Error when generating the DASH manifest of YouTube OTF stream", e);
|
||||||
+ stream.getContent(), e);
|
|
||||||
}
|
}
|
||||||
case HLS:
|
case HLS:
|
||||||
return dataSource.getYoutubeHlsMediaSourceFactory().createMediaSource(
|
return dataSource.getYoutubeHlsMediaSourceFactory().createMediaSource(
|
||||||
@ -503,7 +518,7 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
.setCustomCacheKey(cacheKey)
|
.setCustomCacheKey(cacheKey)
|
||||||
.build());
|
.build());
|
||||||
default:
|
default:
|
||||||
throw new IOException("Unsupported delivery method for YouTube contents: "
|
throw new ResolverException("Unsupported delivery method for YouTube contents: "
|
||||||
+ deliveryMethod);
|
+ deliveryMethod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -535,4 +550,17 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
|
|||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
//region resolver exception
|
||||||
|
final class ResolverException extends Exception {
|
||||||
|
public ResolverException(final String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResolverException(final String message, final Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//endregion
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ import org.schabi.newpipe.player.mediaitem.MediaItemTag;
|
|||||||
import org.schabi.newpipe.player.mediaitem.StreamInfoTag;
|
import org.schabi.newpipe.player.mediaitem.StreamInfoTag;
|
||||||
import org.schabi.newpipe.util.ListHelper;
|
import org.schabi.newpipe.util.ListHelper;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -94,8 +93,8 @@ public class VideoPlaybackResolver implements PlaybackResolver {
|
|||||||
final MediaSource streamSource = PlaybackResolver.buildMediaSource(
|
final MediaSource streamSource = PlaybackResolver.buildMediaSource(
|
||||||
dataSource, video, info, PlaybackResolver.cacheKeyOf(info, video), tag);
|
dataSource, video, info, PlaybackResolver.cacheKeyOf(info, video), tag);
|
||||||
mediaSources.add(streamSource);
|
mediaSources.add(streamSource);
|
||||||
} catch (final IOException e) {
|
} catch (final ResolverException e) {
|
||||||
Log.e(TAG, "Unable to create video source:", e);
|
Log.e(TAG, "Unable to create video source", e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,8 +112,8 @@ public class VideoPlaybackResolver implements PlaybackResolver {
|
|||||||
dataSource, audio, info, PlaybackResolver.cacheKeyOf(info, audio), tag);
|
dataSource, audio, info, PlaybackResolver.cacheKeyOf(info, audio), tag);
|
||||||
mediaSources.add(audioSource);
|
mediaSources.add(audioSource);
|
||||||
streamSourceType = SourceType.VIDEO_WITH_SEPARATED_AUDIO;
|
streamSourceType = SourceType.VIDEO_WITH_SEPARATED_AUDIO;
|
||||||
} catch (final IOException e) {
|
} catch (final ResolverException e) {
|
||||||
Log.e(TAG, "Unable to create audio source:", e);
|
Log.e(TAG, "Unable to create audio source", e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user