feat: added HLS playback support

This commit is contained in:
Stefan Schueller 2021-01-24 17:58:40 +01:00
parent 3730804c8f
commit 9870fe3f18
5 changed files with 198 additions and 14 deletions

View File

@ -241,17 +241,29 @@ public class VideoPlayerFragment extends Fragment implements VideoRendererEventL
Integer videoQuality = sharedPref.getInt(getString(R.string.pref_quality_key), 999999);
String urlToPlay = null;
boolean isHLS = false;
// try HLS stream first
// get video qualities
// TODO: if auto is set all versions except 0p should be added to a track and have exoplayer auto select optimal bitrate
if (video.getFiles().size() > 0) {
String urlToPlay = video.getFiles().get( 0 ).getFileUrl(); // default, take first found, usually highest res
for ( File file : video.getFiles() ) {
// Set quality if it matches
if ( file.getResolution().getId().equals( videoQuality ) ) {
urlToPlay = file.getFileUrl();
if (video.getStreamingPlaylists().size() > 0) {
urlToPlay = video.getStreamingPlaylists().get( 0 ).getPlaylistUrl();
isHLS = true;
} else {
if (video.getFiles().size() > 0) {
urlToPlay = video.getFiles().get( 0 ).getFileUrl(); // default, take first found, usually highest res
for ( File file : video.getFiles() ) {
// Set quality if it matches
if ( file.getResolution().getId().equals( videoQuality ) ) {
urlToPlay = file.getFileUrl();
}
}
}
mService.setCurrentStreamUrl( urlToPlay );
}
if (!urlToPlay.isEmpty()) {
mService.setCurrentStreamUrl( urlToPlay, isHLS);
torrentStatus.setVisibility(View.GONE);
startPlayer();
} else {
@ -357,7 +369,7 @@ public class VideoPlayerFragment extends Fragment implements VideoRendererEventL
public void onStreamReady(Torrent torrent) {
String videopath = Uri.fromFile(torrent.getVideoFile()).toString();
Log.d(TAG, "Ready! torrentStream videopath:" + videopath);
mService.setCurrentStreamUrl(videopath);
mService.setCurrentStreamUrl(videopath, false);
startPlayer();
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2020 Stefan Schüller <sschueller@techdroid.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model;
public class State {
private Integer id;
private String label;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
}

View File

@ -0,0 +1,77 @@
/*
* Copyright (C) 2020 Stefan Schüller <sschueller@techdroid.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.schueller.peertube.model;
import java.util.ArrayList;
public class StreamingPlaylist {
private Integer id;
private Integer type;
private String playlistUrl;
private String segmentsSha256Url;
private ArrayList<String> redundancies;
private ArrayList<File> files;
public Integer getId() {
return id;
}
public void setId(final Integer id) {
this.id = id;
}
public Integer getType() {
return type;
}
public void setType(final Integer type) {
this.type = type;
}
public String getPlaylistUrl() {
return playlistUrl;
}
public void setPlaylistUrl(final String playlistUrl) {
this.playlistUrl = playlistUrl;
}
public String getSegmentsSha256Url() {
return segmentsSha256Url;
}
public void setSegmentsSha256Url(final String segmentsSha256Url) {
this.segmentsSha256Url = segmentsSha256Url;
}
public ArrayList<String> getRedundancies() {
return redundancies;
}
public void setRedundancies(final ArrayList<String> redundancies) {
this.redundancies = redundancies;
}
public ArrayList<File> getFiles() {
return files;
}
public void setFiles(final ArrayList<File> files) {
this.files = files;
}
}

View File

@ -60,11 +60,19 @@ public class Video {
private Channel channel;
private Account account;
private ArrayList tags;
private ArrayList<String> tags;
private Boolean commentsEnabled;
private Boolean downloadEnabled;
private Boolean waitTranscoding;
private State state;
private ArrayList<String> trackerUrls;
private ArrayList<File> files;
private ArrayList<StreamingPlaylist> streamingPlaylists;
public Video() {
}
@ -253,11 +261,11 @@ public class Video {
this.account = account;
}
public ArrayList getTags() {
public ArrayList<String> getTags() {
return tags;
}
public void setTags(ArrayList tags) {
public void setTags(ArrayList<String> tags) {
this.tags = tags;
}
@ -277,7 +285,45 @@ public class Video {
this.files = files;
}
public Boolean getDownloadEnabled() {
return downloadEnabled;
}
public void setDownloadEnabled(final Boolean downloadEnabled) {
this.downloadEnabled = downloadEnabled;
}
public Boolean getWaitTranscoding() {
return waitTranscoding;
}
public void setWaitTranscoding(final Boolean waitTranscoding) {
this.waitTranscoding = waitTranscoding;
}
public State getState() {
return state;
}
public void setState(final State state) {
this.state = state;
}
public ArrayList<String> getTrackerUrls() {
return trackerUrls;
}
public void setTrackerUrls(final ArrayList<String> trackerUrls) {
this.trackerUrls = trackerUrls;
}
public ArrayList<StreamingPlaylist> getStreamingPlaylists() {
return streamingPlaylists;
}
public void setStreamingPlaylists(final ArrayList<StreamingPlaylist> streamingPlaylists) {
this.streamingPlaylists = streamingPlaylists;
}
public static MediaDescriptionCompat getMediaDescription(Context context, Video video) {

View File

@ -56,6 +56,7 @@ import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSourceFactory;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.ui.PlayerNotificationManager;
import com.google.android.exoplayer2.upstream.DataSource;
@ -93,6 +94,8 @@ public class VideoPlayerService extends Service {
private String currentStreamUrl;
private boolean currentStreamUrlIsHLS;
private PlayerNotificationManager playerNotificationManager;
private IntentFilter becomeNoisyIntentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
@ -190,8 +193,9 @@ public class VideoPlayerService extends Service {
currentVideo = video;
}
public void setCurrentStreamUrl(String streamUrl) {
public void setCurrentStreamUrl(String streamUrl, boolean isHLS) {
Log.v(TAG, "setCurrentStreamUrl..." + streamUrl);
currentStreamUrlIsHLS = isHLS;
currentStreamUrl = streamUrl;
}
@ -233,8 +237,14 @@ public class VideoPlayerService extends Service {
DataSource.Factory dataSourceFactory = new OkHttpDataSourceFactory(okhttpClientBuilder.build(), Util.getUserAgent(getApplicationContext(), "PeerTube"));
// Create a progressive media source pointing to a stream uri.
MediaSource mediaSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(MediaItem.fromUri(Uri.parse(currentStreamUrl)));
MediaSource mediaSource;
if (currentStreamUrlIsHLS) {
mediaSource = new HlsMediaSource.Factory(dataSourceFactory)
.createMediaSource(MediaItem.fromUri(Uri.parse(currentStreamUrl)));
} else {
mediaSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(MediaItem.fromUri(Uri.parse(currentStreamUrl)));
}
// Set the media source to be played.
player.setMediaSource(mediaSource);