diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java index fbe3184c0d..57e7f0bfd6 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java @@ -41,6 +41,13 @@ public final class EventMessage implements Metadata.Entry { */ public final long durationMs; + /** + * The presentation time value of this event message in microseconds. + *
+ * Except in special cases, application code should not use this field. + */ + public final long presentationTimeUs; + /** * The instance identifier. */ @@ -55,25 +62,27 @@ public final class EventMessage implements Metadata.Entry { private int hashCode; /** - * * @param schemeIdUri The message scheme. * @param value The value for the event. * @param durationMs The duration of the event in milliseconds. * @param id The instance identifier. * @param messageData The body of the message. + * @param presentationTimeUs The presentation time value of this event message in microseconds. */ public EventMessage(String schemeIdUri, String value, long durationMs, long id, - byte[] messageData) { + byte[] messageData, long presentationTimeUs) { this.schemeIdUri = schemeIdUri; this.value = value; this.durationMs = durationMs; this.id = id; this.messageData = messageData; + this.presentationTimeUs = presentationTimeUs; } /* package */ EventMessage(Parcel in) { schemeIdUri = in.readString(); value = in.readString(); + presentationTimeUs = in.readLong(); durationMs = in.readLong(); id = in.readLong(); messageData = in.createByteArray(); @@ -85,6 +94,7 @@ public final class EventMessage implements Metadata.Entry { int result = 17; result = 31 * result + (schemeIdUri != null ? schemeIdUri.hashCode() : 0); result = 31 * result + (value != null ? value.hashCode() : 0); + result = 31 * result + (int) (presentationTimeUs ^ (presentationTimeUs >>> 32)); result = 31 * result + (int) (durationMs ^ (durationMs >>> 32)); result = 31 * result + (int) (id ^ (id >>> 32)); result = 31 * result + Arrays.hashCode(messageData); @@ -102,9 +112,9 @@ public final class EventMessage implements Metadata.Entry { return false; } EventMessage other = (EventMessage) obj; - return durationMs == other.durationMs && id == other.id - && Util.areEqual(schemeIdUri, other.schemeIdUri) && Util.areEqual(value, other.value) - && Arrays.equals(messageData, other.messageData); + return presentationTimeUs == other.presentationTimeUs && durationMs == other.durationMs + && id == other.id && Util.areEqual(schemeIdUri, other.schemeIdUri) + && Util.areEqual(value, other.value) && Arrays.equals(messageData, other.messageData); } // Parcelable implementation. @@ -118,6 +128,7 @@ public final class EventMessage implements Metadata.Entry { public void writeToParcel(Parcel dest, int flags) { dest.writeString(schemeIdUri); dest.writeString(value); + dest.writeLong(presentationTimeUs); dest.writeLong(durationMs); dest.writeLong(id); dest.writeByteArray(messageData); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessageDecoder.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessageDecoder.java index 266988246d..7e5125e71c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessageDecoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessageDecoder.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.metadata.emsg; +import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.MetadataDecoder; import com.google.android.exoplayer2.metadata.MetadataInputBuffer; @@ -24,7 +25,7 @@ import java.nio.ByteBuffer; import java.util.Arrays; /** - * Decodes Event Message (emsg) atoms, as defined in ISO 23009-1. + * Decodes Event Message (emsg) atoms, as defined in ISO/IEC 23009-1:2014, Section 5.10.3.3. *
* Atom data should be provided to the decoder without the full atom header (i.e. starting from the
* first byte of the scheme_id_uri field).
@@ -40,11 +41,13 @@ public final class EventMessageDecoder implements MetadataDecoder {
String schemeIdUri = emsgData.readNullTerminatedString();
String value = emsgData.readNullTerminatedString();
long timescale = emsgData.readUnsignedInt();
- emsgData.skipBytes(4); // presentation_time_delta
+ long presentationTimeUs = Util.scaleLargeTimestamp(emsgData.readUnsignedInt(),
+ C.MICROS_PER_SECOND, timescale);
long durationMs = Util.scaleLargeTimestamp(emsgData.readUnsignedInt(), 1000, timescale);
long id = emsgData.readUnsignedInt();
byte[] messageData = Arrays.copyOfRange(data, emsgData.getPosition(), size);
- return new Metadata(new EventMessage(schemeIdUri, value, durationMs, id, messageData));
+ return new Metadata(new EventMessage(schemeIdUri, value, durationMs, id, messageData,
+ presentationTimeUs));
}
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessageEncoder.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessageEncoder.java
index 2bd54367e1..eca498a6df 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessageEncoder.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessageEncoder.java
@@ -42,11 +42,10 @@ public final class EventMessageEncoder {
*
* @param eventMessage The event message to be encoded.
* @param timescale Timescale of the event message, in units per second.
- * @param presentationTimeUs The presentation time of the event message in microseconds.
* @return The serialized byte array.
*/
@Nullable
- public byte[] encode(EventMessage eventMessage, long timescale, long presentationTimeUs) {
+ public byte[] encode(EventMessage eventMessage, long timescale) {
Assertions.checkArgument(timescale >= 0);
byteArrayOutputStream.reset();
try {
@@ -54,8 +53,8 @@ public final class EventMessageEncoder {
String nonNullValue = eventMessage.value != null ? eventMessage.value : "";
writeNullTerminatedString(dataOutputStream, nonNullValue);
writeUnsignedInt(dataOutputStream, timescale);
- long presentationTime = Util.scaleLargeTimestamp(presentationTimeUs, timescale,
- C.MICROS_PER_SECOND);
+ long presentationTime = Util.scaleLargeTimestamp(eventMessage.presentationTimeUs,
+ timescale, C.MICROS_PER_SECOND);
writeUnsignedInt(dataOutputStream, presentationTime);
long duration = Util.scaleLargeTimestamp(eventMessage.durationMs, timescale, 1000);
writeUnsignedInt(dataOutputStream, duration);
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageDecoderTest.java b/library/core/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageDecoderTest.java
index 1ce0ccb93d..3a6e96b3e8 100644
--- a/library/core/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageDecoderTest.java
+++ b/library/core/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageDecoderTest.java
@@ -38,7 +38,7 @@ public final class EventMessageDecoderTest {
117, 114, 110, 58, 116, 101, 115, 116, 0, // scheme_id_uri = "urn:test"
49, 50, 51, 0, // value = "123"
0, 0, -69, -128, // timescale = 48000
- 0, 0, 0, 0, // presentation_time_delta (ignored) = 0
+ 0, 0, -69, -128, // presentation_time_delta = 48000
0, 2, 50, -128, // event_duration = 144000
0, 15, 67, -45, // id = 1000403
0, 1, 2, 3, 4}; // message_data = {0, 1, 2, 3, 4}
@@ -53,6 +53,7 @@ public final class EventMessageDecoderTest {
assertThat(eventMessage.durationMs).isEqualTo(3000);
assertThat(eventMessage.id).isEqualTo(1000403);
assertThat(eventMessage.messageData).isEqualTo(new byte[]{0, 1, 2, 3, 4});
+ assertThat(eventMessage.presentationTimeUs).isEqualTo(1000000);
}
}
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageEncoderTest.java b/library/core/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageEncoderTest.java
index f526fc3451..f0a6d3e19b 100644
--- a/library/core/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageEncoderTest.java
+++ b/library/core/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageEncoderTest.java
@@ -36,24 +36,24 @@ public final class EventMessageEncoderTest {
@Test
public void testEncodeEventStream() throws IOException {
EventMessage eventMessage = new EventMessage("urn:test", "123", 3000, 1000403,
- new byte[] {0, 1, 2, 3, 4});
+ new byte[] {0, 1, 2, 3, 4}, 1000000);
byte[] expectedEmsgBody = new byte[] {
117, 114, 110, 58, 116, 101, 115, 116, 0, // scheme_id_uri = "urn:test"
49, 50, 51, 0, // value = "123"
0, 0, -69, -128, // timescale = 48000
- 0, 0, -69, -128, // presentation_time_delta = 48
+ 0, 0, -69, -128, // presentation_time_delta = 48000
0, 2, 50, -128, // event_duration = 144000
0, 15, 67, -45, // id = 1000403
0, 1, 2, 3, 4}; // message_data = {0, 1, 2, 3, 4}
- byte[] encodedByteArray = new EventMessageEncoder().encode(eventMessage, 48000, 1000000);
+ byte[] encodedByteArray = new EventMessageEncoder().encode(eventMessage, 48000);
assertThat(encodedByteArray).isEqualTo(expectedEmsgBody);
}
@Test
public void testEncodeDecodeEventStream() throws IOException {
EventMessage expectedEmsg = new EventMessage("urn:test", "123", 3000, 1000403,
- new byte[] {0, 1, 2, 3, 4});
- byte[] encodedByteArray = new EventMessageEncoder().encode(expectedEmsg, 48000, 1);
+ new byte[] {0, 1, 2, 3, 4}, 1000000);
+ byte[] encodedByteArray = new EventMessageEncoder().encode(expectedEmsg, 48000);
MetadataInputBuffer buffer = new MetadataInputBuffer();
buffer.data = ByteBuffer.allocate(encodedByteArray.length).put(encodedByteArray);
@@ -66,29 +66,29 @@ public final class EventMessageEncoderTest {
@Test
public void testEncodeEventStreamMultipleTimesWorkingCorrectly() throws IOException {
EventMessage eventMessage = new EventMessage("urn:test", "123", 3000, 1000403,
- new byte[] {0, 1, 2, 3, 4});
+ new byte[] {0, 1, 2, 3, 4}, 1000000);
byte[] expectedEmsgBody = new byte[] {
117, 114, 110, 58, 116, 101, 115, 116, 0, // scheme_id_uri = "urn:test"
49, 50, 51, 0, // value = "123"
0, 0, -69, -128, // timescale = 48000
- 0, 0, -69, -128, // presentation_time_delta = 48
+ 0, 0, -69, -128, // presentation_time_delta = 48000
0, 2, 50, -128, // event_duration = 144000
0, 15, 67, -45, // id = 1000403
0, 1, 2, 3, 4}; // message_data = {0, 1, 2, 3, 4}
EventMessage eventMessage1 = new EventMessage("urn:test", "123", 3000, 1000402,
- new byte[] {4, 3, 2, 1, 0});
+ new byte[] {4, 3, 2, 1, 0}, 1000000);
byte[] expectedEmsgBody1 = new byte[] {
117, 114, 110, 58, 116, 101, 115, 116, 0, // scheme_id_uri = "urn:test"
49, 50, 51, 0, // value = "123"
0, 0, -69, -128, // timescale = 48000
- 0, 0, -69, -128, // presentation_time_delta = 48
+ 0, 0, -69, -128, // presentation_time_delta = 48000
0, 2, 50, -128, // event_duration = 144000
0, 15, 67, -46, // id = 1000402
4, 3, 2, 1, 0}; // message_data = {4, 3, 2, 1, 0}
EventMessageEncoder eventMessageEncoder = new EventMessageEncoder();
- byte[] encodedByteArray = eventMessageEncoder.encode(eventMessage, 48000, 1000000);
+ byte[] encodedByteArray = eventMessageEncoder.encode(eventMessage, 48000);
assertThat(encodedByteArray).isEqualTo(expectedEmsgBody);
- byte[] encodedByteArray1 = eventMessageEncoder.encode(eventMessage1, 48000, 1000000);
+ byte[] encodedByteArray1 = eventMessageEncoder.encode(eventMessage1, 48000);
assertThat(encodedByteArray1).isEqualTo(expectedEmsgBody1);
}
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageTest.java b/library/core/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageTest.java
index b48a071d0d..58f2b9f55d 100644
--- a/library/core/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageTest.java
+++ b/library/core/src/test/java/com/google/android/exoplayer2/metadata/emsg/EventMessageTest.java
@@ -33,7 +33,7 @@ public final class EventMessageTest {
@Test
public void testEventMessageParcelable() {
EventMessage eventMessage = new EventMessage("urn:test", "123", 3000, 1000403,
- new byte[] {0, 1, 2, 3, 4});
+ new byte[] {0, 1, 2, 3, 4}, 1000);
// Write to parcel.
Parcel parcel = Parcel.obtain();
eventMessage.writeToParcel(parcel, 0);
diff --git a/library/dash/src/androidTest/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java b/library/dash/src/androidTest/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java
index 37dc6a748e..5c54a7884b 100644
--- a/library/dash/src/androidTest/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java
+++ b/library/dash/src/androidTest/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java
@@ -84,7 +84,7 @@ public class DashManifestParserTest extends InstrumentationTestCase {
EventStream eventStream1 = period.eventStreams.get(0);
assertEquals(1, eventStream1.events.length);
EventMessage expectedEvent1 = new EventMessage("urn:uuid:XYZY", "call", 10000, 0,
- "+ 1 800 10101010".getBytes());
+ "+ 1 800 10101010".getBytes(), 0);
assertEquals(expectedEvent1, eventStream1.events[0]);
// assert CData-structured event stream
@@ -102,7 +102,7 @@ public class DashManifestParserTest extends InstrumentationTestCase {
+ "