diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsTrackMetadataEntry.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsTrackMetadataEntry.java index f26a9b8e9a2..9a9566b63e3 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsTrackMetadataEntry.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsTrackMetadataEntry.java @@ -19,6 +19,7 @@ import android.os.Parcelable; import android.text.TextUtils; import androidx.annotation.Nullable; +import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.metadata.Metadata; import java.util.ArrayList; import java.util.Collections; @@ -30,8 +31,14 @@ public final class HlsTrackMetadataEntry implements Metadata.Entry { /** Holds attributes defined in an EXT-X-STREAM-INF tag. */ public static final class VariantInfo implements Parcelable { - /** The bitrate as declared by the EXT-X-STREAM-INF tag. */ - public final long bitrate; + /** + * The average bitrate as declared by the AVERAGE-BANDWIDTH attribute of the EXT-X-STREAM-INF + * tag, or {@link Format#NO_VALUE} if the attribute is not declared. + */ + public final int averageBitrate; + + /** The peak bitrate as declared by the BANDWIDTH attribute of the EXT-X-STREAM-INF tag. */ + public final int peakBitrate; /** * The VIDEO value as defined in the EXT-X-STREAM-INF tag, or null if the VIDEO attribute is not @@ -60,19 +67,22 @@ public static final class VariantInfo implements Parcelable { /** * Creates an instance. * - * @param bitrate See {@link #bitrate}. + * @param averageBitrate See {@link #averageBitrate}. + * @param peakBitrate See {@link #peakBitrate}. * @param videoGroupId See {@link #videoGroupId}. * @param audioGroupId See {@link #audioGroupId}. * @param subtitleGroupId See {@link #subtitleGroupId}. * @param captionGroupId See {@link #captionGroupId}. */ public VariantInfo( - long bitrate, + int averageBitrate, + int peakBitrate, @Nullable String videoGroupId, @Nullable String audioGroupId, @Nullable String subtitleGroupId, @Nullable String captionGroupId) { - this.bitrate = bitrate; + this.averageBitrate = averageBitrate; + this.peakBitrate = peakBitrate; this.videoGroupId = videoGroupId; this.audioGroupId = audioGroupId; this.subtitleGroupId = subtitleGroupId; @@ -80,7 +90,8 @@ public VariantInfo( } /* package */ VariantInfo(Parcel in) { - bitrate = in.readLong(); + averageBitrate = in.readInt(); + peakBitrate = in.readInt(); videoGroupId = in.readString(); audioGroupId = in.readString(); subtitleGroupId = in.readString(); @@ -96,7 +107,8 @@ public boolean equals(@Nullable Object other) { return false; } VariantInfo that = (VariantInfo) other; - return bitrate == that.bitrate + return averageBitrate == that.averageBitrate + && peakBitrate == that.peakBitrate && TextUtils.equals(videoGroupId, that.videoGroupId) && TextUtils.equals(audioGroupId, that.audioGroupId) && TextUtils.equals(subtitleGroupId, that.subtitleGroupId) @@ -105,7 +117,8 @@ public boolean equals(@Nullable Object other) { @Override public int hashCode() { - int result = (int) (bitrate ^ (bitrate >>> 32)); + int result = averageBitrate; + result = 31 * result + peakBitrate; result = 31 * result + (videoGroupId != null ? videoGroupId.hashCode() : 0); result = 31 * result + (audioGroupId != null ? audioGroupId.hashCode() : 0); result = 31 * result + (subtitleGroupId != null ? subtitleGroupId.hashCode() : 0); @@ -122,7 +135,8 @@ public int describeContents() { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(bitrate); + dest.writeInt(averageBitrate); + dest.writeInt(peakBitrate); dest.writeString(videoGroupId); dest.writeString(audioGroupId); dest.writeString(subtitleGroupId); diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java index 993ce8e5c1a..edd04735f22 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java @@ -303,8 +303,7 @@ private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, Stri } } else if (line.startsWith(TAG_STREAM_INF)) { noClosedCaptions |= line.contains(ATTR_CLOSED_CAPTIONS_NONE); - int bitrate = parseIntAttr(line, REGEX_BANDWIDTH); - // TODO: Plumb this into Format. + int peakBitrate = parseIntAttr(line, REGEX_BANDWIDTH); int averageBitrate = parseOptionalIntAttr(line, REGEX_AVERAGE_BANDWIDTH, -1); String codecs = parseOptionalStringAttr(line, REGEX_CODECS, variableDefinitions); String resolutionString = @@ -343,6 +342,7 @@ private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, Stri replaceVariableReferences( iterator.next(), variableDefinitions); // #EXT-X-STREAM-INF's URI. Uri uri = UriUtil.resolveToUri(baseUri, line); + // TODO: Set Format.averageBitrate. Format format = Format.createVideoContainerFormat( /* id= */ Integer.toString(variants.size()), @@ -351,7 +351,7 @@ private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, Stri /* sampleMimeType= */ null, codecs, /* metadata= */ null, - bitrate, + peakBitrate, width, height, frameRate, @@ -362,14 +362,19 @@ private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, Stri new Variant( uri, format, videoGroupId, audioGroupId, subtitlesGroupId, closedCaptionsGroupId); variants.add(variant); - ArrayList variantInfosForUrl = urlToVariantInfos.get(uri); + @Nullable ArrayList variantInfosForUrl = urlToVariantInfos.get(uri); if (variantInfosForUrl == null) { variantInfosForUrl = new ArrayList<>(); urlToVariantInfos.put(uri, variantInfosForUrl); } variantInfosForUrl.add( new VariantInfo( - bitrate, videoGroupId, audioGroupId, subtitlesGroupId, closedCaptionsGroupId)); + averageBitrate, + peakBitrate, + videoGroupId, + audioGroupId, + subtitlesGroupId, + closedCaptionsGroupId)); } } diff --git a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/HlsTrackMetadataEntryTest.java b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/HlsTrackMetadataEntryTest.java new file mode 100644 index 00000000000..987c2bd1afd --- /dev/null +++ b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/HlsTrackMetadataEntryTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.source.hls; + +import static com.google.common.truth.Truth.assertThat; + +import android.os.Parcel; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.source.hls.HlsTrackMetadataEntry.VariantInfo; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Test for {@link HlsTrackMetadataEntry}. */ +@RunWith(AndroidJUnit4.class) +public class HlsTrackMetadataEntryTest { + + @Test + public void variantInfo_parcelRoundTrip_isEqual() { + VariantInfo variantInfoToParcel = + new VariantInfo( + /* averageBitrate= */ 1024, + /* peakBitrate= */ 2048, + "videoGroupId", + "audioGroupId", + "subtitleGroupId", + "captionGroupId"); + + Parcel parcel = Parcel.obtain(); + variantInfoToParcel.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + + VariantInfo variantInfoFromParcel = VariantInfo.CREATOR.createFromParcel(parcel); + assertThat(variantInfoFromParcel).isEqualTo(variantInfoToParcel); + + parcel.recycle(); + } +} diff --git a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylistParserTest.java b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylistParserTest.java index 0aa78d9f026..78888d36309 100644 --- a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylistParserTest.java +++ b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylistParserTest.java @@ -352,24 +352,24 @@ public void testHlsMetadata() throws IOException { assertThat(playlist.variants.get(0).format.metadata) .isEqualTo( createExtXStreamInfMetadata( - createVariantInfo(/* bitrate= */ 2227464, /* audioGroupId= */ "aud1"), - createVariantInfo(/* bitrate= */ 2448841, /* audioGroupId= */ "aud2"), - createVariantInfo(/* bitrate= */ 2256841, /* audioGroupId= */ "aud3"))); + createVariantInfo(/* peakBitrate= */ 2227464, /* audioGroupId= */ "aud1"), + createVariantInfo(/* peakBitrate= */ 2448841, /* audioGroupId= */ "aud2"), + createVariantInfo(/* peakBitrate= */ 2256841, /* audioGroupId= */ "aud3"))); assertThat(playlist.variants.get(1).format.metadata) .isEqualTo( createExtXStreamInfMetadata( - createVariantInfo(/* bitrate= */ 6453202, /* audioGroupId= */ "aud1"), - createVariantInfo(/* bitrate= */ 6482579, /* audioGroupId= */ "aud3"))); + createVariantInfo(/* peakBitrate= */ 6453202, /* audioGroupId= */ "aud1"), + createVariantInfo(/* peakBitrate= */ 6482579, /* audioGroupId= */ "aud3"))); assertThat(playlist.variants.get(2).format.metadata) .isEqualTo( createExtXStreamInfMetadata( - createVariantInfo(/* bitrate= */ 5054232, /* audioGroupId= */ "aud1"), - createVariantInfo(/* bitrate= */ 5275609, /* audioGroupId= */ "aud2"))); + createVariantInfo(/* peakBitrate= */ 5054232, /* audioGroupId= */ "aud1"), + createVariantInfo(/* peakBitrate= */ 5275609, /* audioGroupId= */ "aud2"))); assertThat(playlist.variants.get(3).format.metadata) .isEqualTo( createExtXStreamInfMetadata( - createVariantInfo(/* bitrate= */ 8399417, /* audioGroupId= */ "aud2"), - createVariantInfo(/* bitrate= */ 8207417, /* audioGroupId= */ "aud3"))); + createVariantInfo(/* peakBitrate= */ 8399417, /* audioGroupId= */ "aud2"), + createVariantInfo(/* peakBitrate= */ 8207417, /* audioGroupId= */ "aud3"))); assertThat(playlist.audios).hasSize(3); assertThat(playlist.audios.get(0).format.metadata) @@ -390,9 +390,10 @@ private static Metadata createExtXMediaMetadata(String groupId, String name) { } private static HlsTrackMetadataEntry.VariantInfo createVariantInfo( - long bitrate, String audioGroupId) { + int peakBitrate, String audioGroupId) { return new HlsTrackMetadataEntry.VariantInfo( - bitrate, + /* averageBitrate= */ Format.NO_VALUE, + /* peakBitrate= */ peakBitrate, /* videoGroupId= */ null, audioGroupId, /* subtitleGroupId= */ "sub1",