diff --git a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java index 68e50b9c1..0164b708f 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java @@ -107,11 +107,8 @@ public final class ListHelper { public static int getDefaultAudioFormat(final Context context, final List audioStreams) { - final MediaFormat defaultFormat = getDefaultFormat(context, - R.string.default_audio_format_key, R.string.default_audio_format_value); - - return getAudioIndexByHighestRank(defaultFormat, audioStreams, - getAudioStreamComparator(context)); + return getAudioIndexByHighestRank(audioStreams, + getAudioTrackComparator(context).thenComparing(getAudioFormatComparator(context))); } public static int getAudioFormatIndex(final Context context, @@ -222,8 +219,7 @@ public final class ListHelper { final HashMap collectedStreams = new HashMap<>(); - final Comparator cmp = - getAudioStreamFormatComparator(isLimitingDataUsage(context)); + final Comparator cmp = getAudioFormatComparator(context); for (final AudioStream stream : audioStreams) { if (stream.getDeliveryMethod() == DeliveryMethod.TORRENT) { @@ -417,32 +413,18 @@ public final class ListHelper { * Get the audio-stream from the list with the highest rank, depending on the comparator. * Format will be ignored if it yields no results. * - * @param targetedFormat The target format type or null if it doesn't matter * @param audioStreams List of audio streams * @param comparator The comparator used for determining the max/best/highest ranked value * @return Index of audio stream that produces the highest ranked result or -1 if not found */ - static int getAudioIndexByHighestRank(@Nullable final MediaFormat targetedFormat, - @Nullable final List audioStreams, - final Comparator comparator) { + static int getAudioIndexByHighestRank(@Nullable final List audioStreams, + final Comparator comparator) { if (audioStreams == null || audioStreams.isEmpty()) { return -1; } final AudioStream highestRankedAudioStream = audioStreams.stream() - .filter(audioStream -> targetedFormat == null - || audioStream.getFormat() == targetedFormat) - .max(comparator) - .orElse(null); - - if (highestRankedAudioStream == null) { - // Fallback: Ignore targetedFormat if not null - if (targetedFormat != null) { - return getAudioIndexByHighestRank(null, audioStreams, comparator); - } - // targetedFormat is already null -> return -1 - return -1; - } + .max(comparator).orElse(null); return audioStreams.indexOf(highestRankedAudioStream); } @@ -631,14 +613,27 @@ public final class ListHelper { return manager.isActiveNetworkMetered(); } + /** + * Get a {@link Comparator} to compare {@link AudioStream}s by their format and bitrate. + * @param context app context + * @return Comparator + */ + private static Comparator getAudioFormatComparator( + final @NonNull Context context) { + final MediaFormat defaultFormat = getDefaultFormat(context, + R.string.default_audio_format_key, R.string.default_audio_format_value); + return getAudioFormatComparator(defaultFormat, isLimitingDataUsage(context)); + } + /** * Get a {@link Comparator} to compare {@link AudioStream}s by their format and bitrate. * + * @param defaultFormat the default format to look for * @param limitDataUsage choose low bitrate audio stream * @return Comparator */ - private static Comparator getAudioStreamFormatComparator( - final boolean limitDataUsage) { + static Comparator getAudioFormatComparator( + @Nullable final MediaFormat defaultFormat, final boolean limitDataUsage) { final List formatRanking = limitDataUsage ? AUDIO_FORMAT_EFFICIENCY_RANKING : AUDIO_FORMAT_QUALITY_RANKING; @@ -648,18 +643,22 @@ public final class ListHelper { bitrateComparator = bitrateComparator.reversed(); } - return bitrateComparator.thenComparingInt( + return Comparator.comparing(AudioStream::getFormat, (o1, o2) -> { + if (defaultFormat != null) { + return Boolean.compare(o1 == defaultFormat, o2 == defaultFormat); + } + return 0; + }).thenComparing(bitrateComparator).thenComparingInt( stream -> formatRanking.indexOf(stream.getFormat())); } /** - * Get a {@link Comparator} to compare {@link AudioStream}s by their language, format - * and bitrate. + * Get a {@link Comparator} to compare {@link AudioStream}s by their tracks. * * @param context App context * @return Comparator */ - private static Comparator getAudioStreamComparator( + private static Comparator getAudioTrackComparator( @NonNull final Context context) { final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); @@ -671,23 +670,21 @@ public final class ListHelper { preferences.getBoolean(context.getString(R.string.prefer_descriptive_audio_key), false); - return getAudioStreamComparator(preferredLanguage, preferOriginalAudio, - preferDescriptiveAudio, isLimitingDataUsage(context)); + return getAudioTrackComparator(preferredLanguage, preferOriginalAudio, + preferDescriptiveAudio); } /** - * Get a {@link Comparator} to compare {@link AudioStream}s by their language, format - * and bitrate. + * Get a {@link Comparator} to compare {@link AudioStream}s by their tracks. + * * @param preferredLanguage Preferred audio stream language * @param preferOriginalAudio Get the original audio track regardless of its language * @param preferDescriptiveAudio Prefer the descriptive audio track if available - * @param limitDataUsage choose low bitrate audio stream * @return Comparator */ - static Comparator getAudioStreamComparator(final Locale preferredLanguage, - final boolean preferOriginalAudio, - final boolean preferDescriptiveAudio, - final boolean limitDataUsage) { + static Comparator getAudioTrackComparator( + final Locale preferredLanguage, final boolean preferOriginalAudio, + final boolean preferDescriptiveAudio) { final String langCode = preferredLanguage.getISO3Language(); final List trackTypeRanking = preferDescriptiveAudio ? AUDIO_TRACK_TYPE_RANKING_DESCRIPTIVE : AUDIO_TRACK_TYPE_RANKING; @@ -706,7 +703,6 @@ public final class ListHelper { .thenComparing(AudioStream::getAudioLocale, Comparator.nullsFirst(Comparator.comparing( locale -> locale.getISO3Language().equals( - Locale.ENGLISH.getISO3Language())))) - .thenComparing(getAudioStreamFormatComparator(limitDataUsage)); + Locale.ENGLISH.getISO3Language())))); } } diff --git a/app/src/test/java/org/schabi/newpipe/util/ListHelperTest.java b/app/src/test/java/org/schabi/newpipe/util/ListHelperTest.java index 4619f8ad7..b4a4167cf 100644 --- a/app/src/test/java/org/schabi/newpipe/util/ListHelperTest.java +++ b/app/src/test/java/org/schabi/newpipe/util/ListHelperTest.java @@ -211,20 +211,21 @@ public class ListHelperTest { @Test public void getHighestQualityAudioFormatTest() { - final Comparator cmp = - ListHelper.getAudioStreamComparator(Locale.ENGLISH, false, false, false); + Comparator cmp = ListHelper.getAudioFormatComparator(MediaFormat.M4A, false); AudioStream stream = AUDIO_STREAMS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - MediaFormat.M4A, AUDIO_STREAMS_TEST_LIST, cmp)); + AUDIO_STREAMS_TEST_LIST, cmp)); assertEquals(320, stream.getAverageBitrate()); assertEquals(MediaFormat.M4A, stream.getFormat()); + cmp = ListHelper.getAudioFormatComparator(MediaFormat.WEBMA, false); stream = AUDIO_STREAMS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - MediaFormat.WEBMA, AUDIO_STREAMS_TEST_LIST, cmp)); + AUDIO_STREAMS_TEST_LIST, cmp)); assertEquals(320, stream.getAverageBitrate()); assertEquals(MediaFormat.WEBMA, stream.getFormat()); + cmp = ListHelper.getAudioFormatComparator(MediaFormat.MP3, false); stream = AUDIO_STREAMS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - MediaFormat.MP3, AUDIO_STREAMS_TEST_LIST, cmp)); + AUDIO_STREAMS_TEST_LIST, cmp)); assertEquals(192, stream.getAverageBitrate()); assertEquals(MediaFormat.MP3, stream.getFormat()); } @@ -232,7 +233,7 @@ public class ListHelperTest { @Test public void getHighestQualityAudioFormatPreferredAbsent() { final Comparator cmp = - ListHelper.getAudioStreamComparator(Locale.ENGLISH, false, false, false); + ListHelper.getAudioFormatComparator(MediaFormat.MP3, false); ////////////////////////////////////////// // Doesn't contain the preferred format // @@ -243,8 +244,7 @@ public class ListHelperTest { generateAudioStream("webma-192", MediaFormat.WEBMA, 192)); // List doesn't contains this format // It should fallback to the highest bitrate audio no matter what format it is - AudioStream stream = testList.get(ListHelper.getAudioIndexByHighestRank( - MediaFormat.MP3, testList, cmp)); + AudioStream stream = testList.get(ListHelper.getAudioIndexByHighestRank(testList, cmp)); assertEquals(192, stream.getAverageBitrate()); assertEquals(MediaFormat.WEBMA, stream.getFormat()); @@ -263,7 +263,7 @@ public class ListHelperTest { // List doesn't contains this format, it should fallback to the highest bitrate audio and // the highest quality format. stream = - testList.get(ListHelper.getAudioIndexByHighestRank(MediaFormat.MP3, testList, cmp)); + testList.get(ListHelper.getAudioIndexByHighestRank(testList, cmp)); assertEquals(192, stream.getAverageBitrate()); assertEquals(MediaFormat.M4A, stream.getFormat()); @@ -271,44 +271,42 @@ public class ListHelperTest { // it's not a preferred format. testList.add(generateAudioStream("webma-192-5", MediaFormat.WEBMA, 192)); stream = - testList.get(ListHelper.getAudioIndexByHighestRank(MediaFormat.MP3, testList, cmp)); + testList.get(ListHelper.getAudioIndexByHighestRank(testList, cmp)); assertEquals(192, stream.getAverageBitrate()); assertEquals(MediaFormat.M4A, stream.getFormat()); } @Test public void getHighestQualityAudioNull() { - final Comparator cmp = - ListHelper.getAudioStreamComparator(Locale.ENGLISH, false, false, false); - assertEquals(-1, ListHelper.getAudioIndexByHighestRank(null, null, cmp)); - assertEquals(-1, ListHelper.getAudioIndexByHighestRank(null, new ArrayList<>(), cmp)); + final Comparator cmp = ListHelper.getAudioFormatComparator(null, false); + assertEquals(-1, ListHelper.getAudioIndexByHighestRank(null, cmp)); + assertEquals(-1, ListHelper.getAudioIndexByHighestRank(new ArrayList<>(), cmp)); } @Test public void getLowestQualityAudioFormatTest() { - final Comparator cmp = - ListHelper.getAudioStreamComparator(Locale.ENGLISH, false, false, true); - + Comparator cmp = ListHelper.getAudioFormatComparator(MediaFormat.M4A, true); AudioStream stream = AUDIO_STREAMS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - MediaFormat.M4A, AUDIO_STREAMS_TEST_LIST, cmp)); + AUDIO_STREAMS_TEST_LIST, cmp)); assertEquals(128, stream.getAverageBitrate()); assertEquals(MediaFormat.M4A, stream.getFormat()); + cmp = ListHelper.getAudioFormatComparator(MediaFormat.WEBMA, true); stream = AUDIO_STREAMS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - MediaFormat.WEBMA, AUDIO_STREAMS_TEST_LIST, cmp)); + AUDIO_STREAMS_TEST_LIST, cmp)); assertEquals(64, stream.getAverageBitrate()); assertEquals(MediaFormat.WEBMA, stream.getFormat()); + cmp = ListHelper.getAudioFormatComparator(MediaFormat.MP3, true); stream = AUDIO_STREAMS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - MediaFormat.MP3, AUDIO_STREAMS_TEST_LIST, cmp)); + AUDIO_STREAMS_TEST_LIST, cmp)); assertEquals(64, stream.getAverageBitrate()); assertEquals(MediaFormat.MP3, stream.getFormat()); } @Test public void getLowestQualityAudioFormatPreferredAbsent() { - final Comparator cmp = - ListHelper.getAudioStreamComparator(Locale.ENGLISH, false, false, true); + Comparator cmp = ListHelper.getAudioFormatComparator(MediaFormat.MP3, true); ////////////////////////////////////////// // Doesn't contain the preferred format // @@ -319,15 +317,13 @@ public class ListHelperTest { generateAudioStream("webma-192-1", MediaFormat.WEBMA, 192))); // List doesn't contains this format // It should fallback to the most compact audio no matter what format it is. - AudioStream stream = testList.get(ListHelper.getAudioIndexByHighestRank( - MediaFormat.MP3, testList, cmp)); + AudioStream stream = testList.get(ListHelper.getAudioIndexByHighestRank(testList, cmp)); assertEquals(128, stream.getAverageBitrate()); assertEquals(MediaFormat.M4A, stream.getFormat()); // WEBMA is more compact than M4A testList.add(generateAudioStream("webma-192-2", MediaFormat.WEBMA, 128)); - stream = - testList.get(ListHelper.getAudioIndexByHighestRank(MediaFormat.MP3, testList, cmp)); + stream = testList.get(ListHelper.getAudioIndexByHighestRank(testList, cmp)); assertEquals(128, stream.getAverageBitrate()); assertEquals(MediaFormat.WEBMA, stream.getFormat()); @@ -345,56 +341,56 @@ public class ListHelperTest { // List doesn't contain this format // It should fallback to the most compact audio no matter what format it is. stream = testList.get( - ListHelper.getAudioIndexByHighestRank(MediaFormat.MP3, testList, cmp)); + ListHelper.getAudioIndexByHighestRank(testList, cmp)); assertEquals(192, stream.getAverageBitrate()); assertEquals(MediaFormat.WEBMA, stream.getFormat()); // Should be same as above + cmp = ListHelper.getAudioFormatComparator(null, true); stream = testList.get( - ListHelper.getAudioIndexByHighestRank(null, testList, cmp)); + ListHelper.getAudioIndexByHighestRank(testList, cmp)); assertEquals(192, stream.getAverageBitrate()); assertEquals(MediaFormat.WEBMA, stream.getFormat()); } @Test public void getLowestQualityAudioNull() { - final Comparator cmp = - ListHelper.getAudioStreamComparator(Locale.ENGLISH, false, false, false); - assertEquals(-1, ListHelper.getAudioIndexByHighestRank(null, null, cmp)); - assertEquals(-1, ListHelper.getAudioIndexByHighestRank(null, new ArrayList<>(), cmp)); + final Comparator cmp = ListHelper.getAudioFormatComparator(null, false); + assertEquals(-1, ListHelper.getAudioIndexByHighestRank(null, cmp)); + assertEquals(-1, ListHelper.getAudioIndexByHighestRank(new ArrayList<>(), cmp)); } @Test public void getAudioTrack() { // English language Comparator cmp = - ListHelper.getAudioStreamComparator(Locale.ENGLISH, false, false, false); + ListHelper.getAudioTrackComparator(Locale.ENGLISH, false, false); AudioStream stream = AUDIO_TRACKS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - null, AUDIO_TRACKS_TEST_LIST, cmp)); + AUDIO_TRACKS_TEST_LIST, cmp)); assertEquals("en.or", stream.getId()); // German language - cmp = ListHelper.getAudioStreamComparator(Locale.GERMAN, false, false, false); + cmp = ListHelper.getAudioTrackComparator(Locale.GERMAN, false, false); stream = AUDIO_TRACKS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - null, AUDIO_TRACKS_TEST_LIST, cmp)); + AUDIO_TRACKS_TEST_LIST, cmp)); assertEquals("de.du", stream.getId()); // German language, but prefer original - cmp = ListHelper.getAudioStreamComparator(Locale.GERMAN, true, false, false); + cmp = ListHelper.getAudioTrackComparator(Locale.GERMAN, true, false); stream = AUDIO_TRACKS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - null, AUDIO_TRACKS_TEST_LIST, cmp)); + AUDIO_TRACKS_TEST_LIST, cmp)); assertEquals("en.or", stream.getId()); // Prefer descriptive audio - cmp = ListHelper.getAudioStreamComparator(Locale.ENGLISH, false, true, false); + cmp = ListHelper.getAudioTrackComparator(Locale.ENGLISH, false, true); stream = AUDIO_TRACKS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - null, AUDIO_TRACKS_TEST_LIST, cmp)); + AUDIO_TRACKS_TEST_LIST, cmp)); assertEquals("en.ds", stream.getId()); // Japanese language, fall back to original - cmp = ListHelper.getAudioStreamComparator(Locale.JAPANESE, true, false, false); + cmp = ListHelper.getAudioTrackComparator(Locale.JAPANESE, true, false); stream = AUDIO_TRACKS_TEST_LIST.get(ListHelper.getAudioIndexByHighestRank( - null, AUDIO_TRACKS_TEST_LIST, cmp)); + AUDIO_TRACKS_TEST_LIST, cmp)); assertEquals("en.or", stream.getId()); }