Add resolution support up to 4k and 60 fps
- Up to 4k with 60 fps
- Not every device can play in that resolution and bitrate
- Add option to hide these high resolution greater than 1080p (2k,4k) for not clutter the menus
- Add a default resolution for the popup, wil be used when opening in popup mode from another app
This commit is contained in:
parent
e5bf98a741
commit
3b9a477499
17 changed files with 632 additions and 200 deletions
|
|
@ -8,12 +8,36 @@ import org.schabi.newpipe.MainActivity;
|
|||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
|
||||
import org.schabi.newpipe.fragments.OnItemSelectedListener;
|
||||
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
|
||||
import org.schabi.newpipe.player.AbstractPlayer;
|
||||
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
public class NavigationHelper {
|
||||
|
||||
public static Intent getOpenPlayerIntent(Context context, Class targetClazz, StreamInfo info, int selectedStreamIndex) {
|
||||
return new Intent(context, targetClazz)
|
||||
.putExtra(AbstractPlayer.VIDEO_TITLE, info.title)
|
||||
.putExtra(AbstractPlayer.VIDEO_URL, info.webpage_url)
|
||||
.putExtra(AbstractPlayer.CHANNEL_NAME, info.uploader)
|
||||
.putExtra(AbstractPlayer.INDEX_SEL_VIDEO_STREAM, selectedStreamIndex)
|
||||
.putExtra(AbstractPlayer.VIDEO_STREAMS_LIST, Utils.getSortedStreamVideosList(context, info.video_streams, info.video_only_streams, false))
|
||||
.putExtra(AbstractPlayer.VIDEO_ONLY_AUDIO_STREAM, Utils.getHighestQualityAudio(info.audio_streams));
|
||||
}
|
||||
|
||||
public static Intent getOpenPlayerIntent(Context context, Class targetClazz, AbstractPlayer instance) {
|
||||
return new Intent(context, targetClazz)
|
||||
.putExtra(AbstractPlayer.VIDEO_TITLE, instance.getVideoTitle())
|
||||
.putExtra(AbstractPlayer.VIDEO_URL, instance.getVideoUrl())
|
||||
.putExtra(AbstractPlayer.CHANNEL_NAME, instance.getChannelName())
|
||||
.putExtra(AbstractPlayer.INDEX_SEL_VIDEO_STREAM, instance.getSelectedStreamIndex())
|
||||
.putExtra(AbstractPlayer.VIDEO_STREAMS_LIST, instance.getVideoStreamsList())
|
||||
.putExtra(AbstractPlayer.VIDEO_ONLY_AUDIO_STREAM, instance.getAudioStream())
|
||||
.putExtra(AbstractPlayer.START_POSITION, ((int) instance.getPlayer().getCurrentPosition()));
|
||||
}
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Through Interface (faster)
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
|
|
|||
|
|
@ -9,28 +9,31 @@ import org.schabi.newpipe.extractor.MediaFormat;
|
|||
import org.schabi.newpipe.extractor.stream_info.AudioStream;
|
||||
import org.schabi.newpipe.extractor.stream_info.VideoStream;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class Utils {
|
||||
|
||||
private static final List<String> HIGH_RESOLUTION_LIST = Arrays.asList("1440p", "2160p", "1440p60", "2160p60");
|
||||
|
||||
/**
|
||||
* Return the index of the default stream in the list, based on the
|
||||
* preferred resolution and format chosen in the settings
|
||||
* Return the index of the default stream in the list, based on the parameters
|
||||
* defaultResolution and preferredFormat
|
||||
*
|
||||
* @param videoStreams the list that will be extracted the index
|
||||
*
|
||||
* @param videoStreams the list that will be extracted the index
|
||||
* @return index of the preferred resolution&format
|
||||
*/
|
||||
public static int getPreferredResolution(Context context, List<VideoStream> videoStreams) {
|
||||
SharedPreferences defaultPreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (defaultPreferences == null) return 0;
|
||||
public static int getDefaultResolution(String defaultResolution, String preferredFormat, List<VideoStream> videoStreams) {
|
||||
|
||||
String defaultResolution = defaultPreferences
|
||||
.getString(context.getString(R.string.default_resolution_key),
|
||||
context.getString(R.string.default_resolution_value));
|
||||
|
||||
String preferredFormat = defaultPreferences
|
||||
.getString(context.getString(R.string.preferred_video_format_key),
|
||||
context.getString(R.string.preferred_video_format_default));
|
||||
if (defaultResolution.equals("Best resolution")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// first try to find the one with the right resolution
|
||||
int selectedFormat = 0;
|
||||
|
|
@ -50,16 +53,69 @@ public class Utils {
|
|||
}
|
||||
}
|
||||
|
||||
if (selectedFormat == 0 && !videoStreams.get(selectedFormat).resolution.contains(defaultResolution.replace("p60", "p"))) {
|
||||
// Maybe there's no 60 fps variant available, so fallback to the normal version
|
||||
String replace = defaultResolution.replace("p60", "p");
|
||||
for (int i = 0; i < videoStreams.size(); i++) {
|
||||
VideoStream item = videoStreams.get(i);
|
||||
if (replace.equals(item.resolution)) selectedFormat = i;
|
||||
}
|
||||
|
||||
// than try to find the one with the right resolution and format
|
||||
for (int i = 0; i < videoStreams.size(); i++) {
|
||||
VideoStream item = videoStreams.get(i);
|
||||
if (replace.equals(item.resolution)
|
||||
&& preferredFormat.equals(MediaFormat.getNameById(item.format))) {
|
||||
selectedFormat = i;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// this is actually an error,
|
||||
// but maybe there is really no stream fitting to the default value.
|
||||
return selectedFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getDefaultResolution(String, String, List)
|
||||
*/
|
||||
public static int getDefaultResolution(Context context, List<VideoStream> videoStreams) {
|
||||
SharedPreferences defaultPreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (defaultPreferences == null) return 0;
|
||||
|
||||
String defaultResolution = defaultPreferences
|
||||
.getString(context.getString(R.string.default_resolution_key), context.getString(R.string.default_resolution_value));
|
||||
|
||||
String preferredFormat = defaultPreferences
|
||||
.getString(context.getString(R.string.preferred_video_format_key), context.getString(R.string.preferred_video_format_default));
|
||||
|
||||
return getDefaultResolution(defaultResolution, preferredFormat, videoStreams);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getDefaultResolution(String, String, List)
|
||||
*/
|
||||
public static int getPopupDefaultResolution(Context context, List<VideoStream> videoStreams) {
|
||||
SharedPreferences defaultPreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (defaultPreferences == null) return 0;
|
||||
|
||||
String defaultResolution = defaultPreferences
|
||||
.getString(context.getString(R.string.default_popup_resolution_key), context.getString(R.string.default_popup_resolution_value));
|
||||
|
||||
String preferredFormat = defaultPreferences
|
||||
.getString(context.getString(R.string.preferred_video_format_key), context.getString(R.string.preferred_video_format_default));
|
||||
|
||||
return getDefaultResolution(defaultResolution, preferredFormat, videoStreams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the default stream in the list, based on the
|
||||
* preferred audio format chosen in the settings
|
||||
*
|
||||
* @param context context to get the preferred audio format
|
||||
* @param audioStreams the list that will be extracted the index
|
||||
*
|
||||
* @return index of the preferred format
|
||||
*/
|
||||
public static int getPreferredAudioFormat(Context context, List<AudioStream> audioStreams) {
|
||||
|
|
@ -88,4 +144,125 @@ public class Utils {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the audio from the list with the highest bitrate
|
||||
*
|
||||
* @param audioStreams list the audio streams
|
||||
* @return audio with highest average bitrate
|
||||
*/
|
||||
public static AudioStream getHighestQualityAudio(List<AudioStream> audioStreams) {
|
||||
int highestQualityIndex = 0;
|
||||
|
||||
for (int i = 1; i < audioStreams.size(); i++) {
|
||||
AudioStream audioStream = audioStreams.get(i);
|
||||
if (audioStream.avgBitrate > audioStreams.get(highestQualityIndex).avgBitrate) highestQualityIndex = i;
|
||||
}
|
||||
|
||||
return audioStreams.get(highestQualityIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join the two lists of video streams (video_only and normal videos), and sort them according with preferred format
|
||||
* chosen by the user
|
||||
*
|
||||
* @param context context to search for the format to give preference
|
||||
* @param videoStreams normal videos list
|
||||
* @param videoOnlyStreams video only stream list
|
||||
* @param ascendingOrder true -> smallest to greatest | false -> greatest to smallest
|
||||
* @return the sorted list
|
||||
*/
|
||||
public static ArrayList<VideoStream> getSortedStreamVideosList(Context context, List<VideoStream> videoStreams, List<VideoStream> videoOnlyStreams, boolean ascendingOrder) {
|
||||
boolean showHigherResolutions = PreferenceManager.getDefaultSharedPreferences(context).getBoolean(context.getString(R.string.show_higher_resolutions_key), false);
|
||||
String preferredFormatString = PreferenceManager.getDefaultSharedPreferences(context).getString(context.getString(R.string.preferred_video_format_key), context.getString(R.string.preferred_video_format_default));
|
||||
MediaFormat preferredFormat = MediaFormat.WEBM;
|
||||
switch (preferredFormatString) {
|
||||
case "WebM":
|
||||
preferredFormat = MediaFormat.WEBM;
|
||||
break;
|
||||
case "MPEG-4":
|
||||
preferredFormat = MediaFormat.MPEG_4;
|
||||
break;
|
||||
case "3GPP":
|
||||
preferredFormat = MediaFormat.v3GPP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return getSortedStreamVideosList(preferredFormat, showHigherResolutions, videoStreams, videoOnlyStreams, ascendingOrder);
|
||||
}
|
||||
//show_higher_resolutions_key
|
||||
|
||||
/**
|
||||
* Join the two lists of video streams (video_only and normal videos), and sort them according with preferred format
|
||||
* chosen by the user
|
||||
*
|
||||
* @param preferredFormat format to give preference
|
||||
* @param showHigherResolutions
|
||||
* @param videoStreams normal videos list
|
||||
* @param videoOnlyStreams video only stream list
|
||||
* @param ascendingOrder true -> smallest to greatest | false -> greatest to smallest @return the sorted list
|
||||
* @return the sorted list
|
||||
*/
|
||||
public static ArrayList<VideoStream> getSortedStreamVideosList(MediaFormat preferredFormat, boolean showHigherResolutions, List<VideoStream> videoStreams, List<VideoStream> videoOnlyStreams, boolean ascendingOrder) {
|
||||
ArrayList<VideoStream> retList = new ArrayList<>();
|
||||
HashMap<String, VideoStream> hashMap = new HashMap<>();
|
||||
|
||||
if (videoOnlyStreams != null) {
|
||||
for (VideoStream stream : videoOnlyStreams) {
|
||||
if (!showHigherResolutions && HIGH_RESOLUTION_LIST.contains(stream.resolution)) continue;
|
||||
retList.add(stream);
|
||||
}
|
||||
}
|
||||
if (videoStreams != null) {
|
||||
for (VideoStream stream : videoStreams) {
|
||||
if (!showHigherResolutions && HIGH_RESOLUTION_LIST.contains(stream.resolution)) continue;
|
||||
retList.add(stream);
|
||||
}
|
||||
}
|
||||
|
||||
// Add all to the hashmap
|
||||
for (VideoStream videoStream : retList) hashMap.put(videoStream.resolution, videoStream);
|
||||
|
||||
// Override the values when the key == resolution, with the preferredFormat
|
||||
for (VideoStream videoStream : retList) {
|
||||
if (videoStream.format == preferredFormat.id) hashMap.put(videoStream.resolution, videoStream);
|
||||
}
|
||||
|
||||
retList.clear();
|
||||
retList.addAll(hashMap.values());
|
||||
sortStreamList(retList, ascendingOrder);
|
||||
return retList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the streams list depending on the parameter ascendingOrder;
|
||||
* <p>
|
||||
* It works like that:<br>
|
||||
* - Take a string resolution, remove the letters, replace "0p60" (for 60fps videos) with "1"
|
||||
* and sort by the greatest:<br>
|
||||
* <blockquote><pre>
|
||||
* 720p -> 720
|
||||
* 720p60 -> 721
|
||||
* 360p -> 360
|
||||
* 1080p -> 1080
|
||||
* 1080p60 -> 1081
|
||||
* <p>
|
||||
* ascendingOrder ? 360 < 720 < 721 < 1080 < 1081
|
||||
* !ascendingOrder ? 1081 < 1080 < 721 < 720 < 360/pre></blockquote>
|
||||
* <p>
|
||||
* @param videoStreams list that the sorting will be applied
|
||||
* @param ascendingOrder true -> smallest to greatest | false -> greatest to smallest
|
||||
*/
|
||||
public static void sortStreamList(List<VideoStream> videoStreams, final boolean ascendingOrder) {
|
||||
Collections.sort(videoStreams, new Comparator<VideoStream>() {
|
||||
@Override
|
||||
public int compare(VideoStream o1, VideoStream o2) {
|
||||
int res1 = Integer.parseInt(o1.resolution.replace("0p60", "1").replaceAll("[^\\d.]", ""));
|
||||
int res2 = Integer.parseInt(o2.resolution.replace("0p60", "1").replaceAll("[^\\d.]", ""));
|
||||
|
||||
return ascendingOrder ? res1 - res2 : res2 - res1;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue