diff --git a/library/src/androidTest/java/com/google/android/exoplayer2/util/UtilTest.java b/library/src/androidTest/java/com/google/android/exoplayer2/util/UtilTest.java index e3d681d6dd..8d74379093 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer2/util/UtilTest.java +++ b/library/src/androidTest/java/com/google/android/exoplayer2/util/UtilTest.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.util; +import android.test.MoreAsserts; import com.google.android.exoplayer2.testutil.TestUtil; import java.text.ParseException; import java.util.ArrayList; @@ -145,6 +146,20 @@ public class UtilTest extends TestCase { assertEquals(1407322800000L, Util.parseXsDateTime("2014-08-06T11:00:00Z")); } + public void testGetHexStringByteArray() throws Exception { + assertHexStringByteArray("", new byte[] {}); + assertHexStringByteArray("01", new byte[] {1}); + assertHexStringByteArray("FF", new byte[] {(byte) 255}); + assertHexStringByteArray("01020304", new byte[] {1, 2, 3, 4}); + assertHexStringByteArray("0123456789ABCDEF", + new byte[] {1, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF}); + } + + private void assertHexStringByteArray(String hex, byte[] array) { + assertEquals(hex, Util.getHexString(array)); + MoreAsserts.assertEquals(array, Util.getBytesFromHexString(hex)); + } + public void testUnescapeInvalidFileName() { assertNull(Util.unescapeFileName("%a")); assertNull(Util.unescapeFileName("%xyz")); diff --git a/library/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java b/library/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java index 0fc4ef89df..291267da03 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java @@ -109,7 +109,7 @@ public final class DashMediaSource implements MediaSource { this.chunkSourceFactory = chunkSourceFactory; this.minLoadableRetryCount = minLoadableRetryCount; eventDispatcher = new EventDispatcher(eventHandler, eventListener); - manifestParser = new DashManifestParser(); + manifestParser = new DashManifestParser(generateContentId()); manifestCallback = new ManifestCallback(); manifestUriLock = new Object(); periodsById = new SparseArray<>(); @@ -441,6 +441,10 @@ public final class DashMediaSource implements MediaSource { } } + private String generateContentId() { + return Util.sha1(manifestUri.toString()); + } + private static final class PeriodSeekInfo { public static PeriodSeekInfo createPeriodSeekInfo(Period period, long durationUs) { diff --git a/library/src/main/java/com/google/android/exoplayer2/util/Util.java b/library/src/main/java/com/google/android/exoplayer2/util/Util.java index 008ffb429a..8af70b938f 100644 --- a/library/src/main/java/com/google/android/exoplayer2/util/Util.java +++ b/library/src/main/java/com/google/android/exoplayer2/util/Util.java @@ -33,8 +33,11 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.text.ParseException; import java.util.Arrays; import java.util.Calendar; @@ -112,6 +115,8 @@ public final class Util { private static final Pattern ESCAPED_CHARACTER_PATTERN = Pattern.compile("%([A-Fa-f0-9]{2})"); + private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray(); + private Util() {} /** @@ -636,6 +641,17 @@ public final class Util { return data; } + /** Returns a hex string representation of the given byte array. */ + public static String getHexString(byte[] bytes) { + char[] hexChars = new char[bytes.length * 2]; + int i = 0; + for (byte v : bytes) { + hexChars[i++] = HEX_DIGITS[(v >> 4) & 0xf]; + hexChars[i++] = HEX_DIGITS[v & 0xf]; + } + return new String(hexChars); + } + /** * Returns a string with comma delimited simple names of each object's class. * @@ -839,4 +855,17 @@ public final class Util { } return builder.toString(); } + + /** Returns the SHA-1 digest of input as a hex string. */ + public static String sha1(String input) { + try { + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + byte[] bytes = input.getBytes("UTF-8"); + digest.update(bytes, 0, bytes.length); + return getHexString(digest.digest()); + } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + }