Fix EventMessage timestamp issue

Stop encoding/decoding presentation time as part of the message.
What's actually in emsg boxes is a presentation time delta,
which is why it's only 32 bits, and hence why it doesn't handle
large absolute timestamps. We were using this field to hold
absolute timestamps only for the purpose of passing presentation
times from DashManifestParser.parseEvent back to the calling
method. After this change, we return Pair<Long, EventMessage>
instead.

Issue: #5490
PiperOrigin-RevId: 233561731
This commit is contained in:
olly 2019-02-12 09:18:08 +00:00 committed by Andrew Lewis
parent ad69a93708
commit c66d26b601
12 changed files with 164 additions and 158 deletions

View File

@ -8,6 +8,9 @@
Cast demo app to work with `ExoCastPlayer`.
* HLS:
* Form an adaptive track group out of audio renditions with matching name.
* DASH:
* Fix issue handling large `EventStream` presentation timestamps
([#5490](https://github.com/google/ExoPlayer/issues/5490)).
* `ExtractorMediaSource` renamed to `ProgressiveMediaSource`.
* Support for playing spherical videos on Daydream.
* Improve decoder re-use between playbacks. TODO: Write and link a blog post

View File

@ -601,6 +601,14 @@ public class FragmentedMp4Extractor implements Extractor {
long presentationTimeDeltaUs =
Util.scaleLargeTimestamp(atom.readUnsignedInt(), C.MICROS_PER_SECOND, timescale);
// The presentation_time_delta is accounted for by adjusting the sample timestamp, so we zero it
// in the sample data before writing it to the track outputs.
int position = atom.getPosition();
atom.data[position - 4] = 0;
atom.data[position - 3] = 0;
atom.data[position - 2] = 0;
atom.data[position - 1] = 0;
// Output the sample data.
for (TrackOutput emsgTrackOutput : emsgTrackOutputs) {
atom.setPosition(Atom.FULL_HEADER_SIZE);

View File

@ -44,13 +44,6 @@ public final class EventMessage implements Metadata.Entry {
*/
public final long durationMs;
/**
* The presentation time value of this event message in microseconds.
* <p>
* Except in special cases, application code should <em>not</em> use this field.
*/
public final long presentationTimeUs;
/**
* The instance identifier.
*/
@ -70,22 +63,19 @@ public final class EventMessage implements Metadata.Entry {
* @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, long presentationTimeUs) {
public EventMessage(
String schemeIdUri, String value, long durationMs, long id, byte[] messageData) {
this.schemeIdUri = schemeIdUri;
this.value = value;
this.durationMs = durationMs;
this.id = id;
this.messageData = messageData;
this.presentationTimeUs = presentationTimeUs;
}
/* package */ EventMessage(Parcel in) {
schemeIdUri = castNonNull(in.readString());
value = castNonNull(in.readString());
presentationTimeUs = in.readLong();
durationMs = in.readLong();
id = in.readLong();
messageData = castNonNull(in.createByteArray());
@ -97,7 +87,6 @@ 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);
@ -115,9 +104,11 @@ public final class EventMessage implements Metadata.Entry {
return false;
}
EventMessage other = (EventMessage) obj;
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);
return durationMs == other.durationMs
&& id == other.id
&& Util.areEqual(schemeIdUri, other.schemeIdUri)
&& Util.areEqual(value, other.value)
&& Arrays.equals(messageData, other.messageData);
}
@Override
@ -136,7 +127,6 @@ 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);

View File

@ -15,11 +15,11 @@
*/
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;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util;
import java.nio.ByteBuffer;
@ -27,12 +27,15 @@ import java.util.Arrays;
/**
* Decodes Event Message (emsg) atoms, as defined in ISO/IEC 23009-1:2014, Section 5.10.3.3.
* <p>
* 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).
*
* <p>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). It is expected that the presentation_time_delta field
* should be 0, having already been accounted for by adjusting the sample timestamp.
*/
public final class EventMessageDecoder implements MetadataDecoder {
private static final String TAG = "EventMessageDecoder";
@SuppressWarnings("ByteBufferBackingArray")
@Override
public Metadata decode(MetadataInputBuffer inputBuffer) {
@ -43,13 +46,16 @@ public final class EventMessageDecoder implements MetadataDecoder {
String schemeIdUri = Assertions.checkNotNull(emsgData.readNullTerminatedString());
String value = Assertions.checkNotNull(emsgData.readNullTerminatedString());
long timescale = emsgData.readUnsignedInt();
long presentationTimeUs = Util.scaleLargeTimestamp(emsgData.readUnsignedInt(),
C.MICROS_PER_SECOND, timescale);
long presentationTimeDelta = emsgData.readUnsignedInt();
if (presentationTimeDelta != 0) {
// We expect the source to have accounted for presentation_time_delta by adjusting the sample
// timestamp and zeroing the field in the sample data. Log a warning if the field is non-zero.
Log.w(TAG, "Ignoring non-zero presentation_time_delta: " + presentationTimeDelta);
}
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,
presentationTimeUs));
return new Metadata(new EventMessage(schemeIdUri, value, durationMs, id, messageData));
}
}

View File

@ -16,9 +16,6 @@
package com.google.android.exoplayer2.metadata.emsg;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
@ -37,27 +34,22 @@ public final class EventMessageEncoder {
}
/**
* Encodes an {@link EventMessage} to a byte array that can be decoded by
* {@link EventMessageDecoder}.
* Encodes an {@link EventMessage} to a byte array that can be decoded by {@link
* EventMessageDecoder}.
*
* @param eventMessage The event message to be encoded.
* @param timescale Timescale of the event message, in units per second.
* @return The serialized byte array.
*/
@Nullable
public byte[] encode(EventMessage eventMessage, long timescale) {
Assertions.checkArgument(timescale >= 0);
public byte[] encode(EventMessage eventMessage) {
byteArrayOutputStream.reset();
try {
writeNullTerminatedString(dataOutputStream, eventMessage.schemeIdUri);
String nonNullValue = eventMessage.value != null ? eventMessage.value : "";
writeNullTerminatedString(dataOutputStream, nonNullValue);
writeUnsignedInt(dataOutputStream, timescale);
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);
writeUnsignedInt(dataOutputStream, 1000); // timescale
writeUnsignedInt(dataOutputStream, 0); // presentation_time_delta
writeUnsignedInt(dataOutputStream, eventMessage.durationMs);
writeUnsignedInt(dataOutputStream, eventMessage.id);
dataOutputStream.write(eventMessage.messageData);
dataOutputStream.flush();

View File

@ -51,7 +51,6 @@ 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);
}
}

View File

@ -33,25 +33,27 @@ 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}, 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 = 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);
EventMessage eventMessage =
new EventMessage("urn:test", "123", 3000, 1000403, new byte[] {0, 1, 2, 3, 4});
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, 3, -24, // timescale = 1000
0, 0, 0, 0, // presentation_time_delta = 0
0, 0, 11, -72, // event_duration = 3000
0, 15, 67, -45, // id = 1000403
0, 1, 2, 3, 4
}; // message_data = {0, 1, 2, 3, 4}
byte[] encodedByteArray = new EventMessageEncoder().encode(eventMessage);
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}, 1000000);
byte[] encodedByteArray = new EventMessageEncoder().encode(expectedEmsg, 48000);
EventMessage expectedEmsg =
new EventMessage("urn:test", "123", 3000, 1000403, new byte[] {0, 1, 2, 3, 4});
byte[] encodedByteArray = new EventMessageEncoder().encode(expectedEmsg);
MetadataInputBuffer buffer = new MetadataInputBuffer();
buffer.data = ByteBuffer.allocate(encodedByteArray.length).put(encodedByteArray);
@ -63,30 +65,34 @@ 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}, 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 = 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}, 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 = 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}
EventMessage eventMessage =
new EventMessage("urn:test", "123", 3000, 1000403, new byte[] {0, 1, 2, 3, 4});
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, 3, -24, // timescale = 1000
0, 0, 0, 0, // presentation_time_delta = 0
0, 0, 11, -72, // event_duration = 3000
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});
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, 3, -24, // timescale = 1000
0, 0, 0, 0, // presentation_time_delta = 0
0, 0, 11, -72, // event_duration = 3000
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);
byte[] encodedByteArray = eventMessageEncoder.encode(eventMessage);
assertThat(encodedByteArray).isEqualTo(expectedEmsgBody);
byte[] encodedByteArray1 = eventMessageEncoder.encode(eventMessage1, 48000);
byte[] encodedByteArray1 = eventMessageEncoder.encode(eventMessage1);
assertThat(encodedByteArray1).isEqualTo(expectedEmsgBody1);
}

View File

@ -30,8 +30,8 @@ public final class EventMessageTest {
@Test
public void testEventMessageParcelable() {
EventMessage eventMessage = new EventMessage("urn:test", "123", 3000, 1000403,
new byte[] {0, 1, 2, 3, 4}, 1000);
EventMessage eventMessage =
new EventMessage("urn:test", "123", 3000, 1000403, new byte[] {0, 1, 2, 3, 4});
// Write to parcel.
Parcel parcel = Parcel.obtain();
eventMessage.writeToParcel(parcel, 0);

View File

@ -112,8 +112,7 @@ import java.io.IOException;
}
}
int sampleIndex = currentIndex++;
byte[] serializedEvent = eventMessageEncoder.encode(eventStream.events[sampleIndex],
eventStream.timescale);
byte[] serializedEvent = eventMessageEncoder.encode(eventStream.events[sampleIndex]);
if (serializedEvent != null) {
buffer.ensureSpaceForWrite(serializedEvent.length);
buffer.setFlags(C.BUFFER_FLAG_KEY_FRAME);

View File

@ -829,13 +829,13 @@ public class DashManifestParser extends DefaultHandler
String schemeIdUri = parseString(xpp, "schemeIdUri", "");
String value = parseString(xpp, "value", "");
long timescale = parseLong(xpp, "timescale", 1);
List<EventMessage> eventMessages = new ArrayList<>();
List<Pair<Long, EventMessage>> eventMessages = new ArrayList<>();
ByteArrayOutputStream scratchOutputStream = new ByteArrayOutputStream(512);
do {
xpp.next();
if (XmlPullParserUtil.isStartTag(xpp, "Event")) {
EventMessage event = parseEvent(xpp, schemeIdUri, value, timescale,
scratchOutputStream);
Pair<Long, EventMessage> event =
parseEvent(xpp, schemeIdUri, value, timescale, scratchOutputStream);
eventMessages.add(event);
} else {
maybeSkipTag(xpp);
@ -845,9 +845,9 @@ public class DashManifestParser extends DefaultHandler
long[] presentationTimesUs = new long[eventMessages.size()];
EventMessage[] events = new EventMessage[eventMessages.size()];
for (int i = 0; i < eventMessages.size(); i++) {
EventMessage event = eventMessages.get(i);
presentationTimesUs[i] = event.presentationTimeUs;
events[i] = event;
Pair<Long, EventMessage> event = eventMessages.get(i);
presentationTimesUs[i] = event.first;
events[i] = event.second;
}
return buildEventStream(schemeIdUri, value, timescale, presentationTimesUs, events);
}
@ -866,11 +866,12 @@ public class DashManifestParser extends DefaultHandler
* @param timescale The timescale of the parent EventStream.
* @param scratchOutputStream A {@link ByteArrayOutputStream} that is used when parsing event
* objects.
* @return The {@link EventMessage} parsed from this EventStream node.
* @return A pair containing the node's presentation timestamp in microseconds and the parsed
* {@link EventMessage}.
* @throws XmlPullParserException If there is any error parsing this node.
* @throws IOException If there is any error reading from the underlying input stream.
*/
protected EventMessage parseEvent(
protected Pair<Long, EventMessage> parseEvent(
XmlPullParser xpp,
String schemeIdUri,
String value,
@ -885,13 +886,14 @@ public class DashManifestParser extends DefaultHandler
timescale);
String messageData = parseString(xpp, "messageData", null);
byte[] eventObject = parseEventObject(xpp, scratchOutputStream);
return buildEvent(
schemeIdUri,
value,
id,
durationMs,
messageData == null ? eventObject : Util.getUtf8Bytes(messageData),
presentationTimesUs);
return Pair.create(
presentationTimesUs,
buildEvent(
schemeIdUri,
value,
id,
durationMs,
messageData == null ? eventObject : Util.getUtf8Bytes(messageData)));
}
/**
@ -958,9 +960,9 @@ public class DashManifestParser extends DefaultHandler
return scratchOutputStream.toByteArray();
}
protected EventMessage buildEvent(String schemeIdUri, String value, long id,
long durationMs, byte[] messageData, long presentationTimeUs) {
return new EventMessage(schemeIdUri, value, durationMs, id, messageData, presentationTimeUs);
protected EventMessage buildEvent(
String schemeIdUri, String value, long id, long durationMs, byte[] messageData) {
return new EventMessage(schemeIdUri, value, durationMs, id, messageData);
}
protected List<SegmentTimelineElement> parseSegmentTimeline(XmlPullParser xpp)

View File

@ -111,7 +111,7 @@ public final class EventSampleStreamTest {
@Test
public void testReadDataReturnDataAfterFormat() {
long presentationTimeUs = 1000000;
EventMessage eventMessage = newEventMessageWithIdAndTime(1, presentationTimeUs);
EventMessage eventMessage = newEventMessageWithId(1);
EventStream eventStream = new EventStream(SCHEME_ID, VALUE, TIME_SCALE,
new long[] {presentationTimeUs}, new EventMessage[] {eventMessage});
EventSampleStream sampleStream = new EventSampleStream(eventStream, FORMAT, false);
@ -133,8 +133,8 @@ public final class EventSampleStreamTest {
public void testSkipDataThenReadDataReturnDataFromSkippedPosition() {
long presentationTimeUs1 = 1000000;
long presentationTimeUs2 = 2000000;
EventMessage eventMessage1 = newEventMessageWithIdAndTime(1, presentationTimeUs1);
EventMessage eventMessage2 = newEventMessageWithIdAndTime(2, presentationTimeUs2);
EventMessage eventMessage1 = newEventMessageWithId(1);
EventMessage eventMessage2 = newEventMessageWithId(2);
EventStream eventStream = new EventStream(SCHEME_ID, VALUE, TIME_SCALE,
new long[] {presentationTimeUs1, presentationTimeUs2},
new EventMessage[] {eventMessage1, eventMessage2});
@ -159,8 +159,8 @@ public final class EventSampleStreamTest {
public void testSeekToUsThenReadDataReturnDataFromSeekPosition() {
long presentationTimeUs1 = 1000000;
long presentationTimeUs2 = 2000000;
EventMessage eventMessage1 = newEventMessageWithIdAndTime(1, presentationTimeUs1);
EventMessage eventMessage2 = newEventMessageWithIdAndTime(2, presentationTimeUs2);
EventMessage eventMessage1 = newEventMessageWithId(1);
EventMessage eventMessage2 = newEventMessageWithId(2);
EventStream eventStream = new EventStream(SCHEME_ID, VALUE, TIME_SCALE,
new long[] {presentationTimeUs1, presentationTimeUs2},
new EventMessage[] {eventMessage1, eventMessage2});
@ -186,9 +186,9 @@ public final class EventSampleStreamTest {
long presentationTimeUs1 = 1000000;
long presentationTimeUs2 = 2000000;
long presentationTimeUs3 = 3000000;
EventMessage eventMessage1 = newEventMessageWithIdAndTime(1, presentationTimeUs1);
EventMessage eventMessage2 = newEventMessageWithIdAndTime(2, presentationTimeUs2);
EventMessage eventMessage3 = newEventMessageWithIdAndTime(3, presentationTimeUs3);
EventMessage eventMessage1 = newEventMessageWithId(1);
EventMessage eventMessage2 = newEventMessageWithId(2);
EventMessage eventMessage3 = newEventMessageWithId(3);
EventStream eventStream1 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE,
new long[] {presentationTimeUs1, presentationTimeUs2},
new EventMessage[] {eventMessage1, eventMessage2});
@ -220,9 +220,9 @@ public final class EventSampleStreamTest {
long presentationTimeUs1 = 1000000;
long presentationTimeUs2 = 2000000;
long presentationTimeUs3 = 3000000;
EventMessage eventMessage1 = newEventMessageWithIdAndTime(1, presentationTimeUs1);
EventMessage eventMessage2 = newEventMessageWithIdAndTime(2, presentationTimeUs2);
EventMessage eventMessage3 = newEventMessageWithIdAndTime(3, presentationTimeUs3);
EventMessage eventMessage1 = newEventMessageWithId(1);
EventMessage eventMessage2 = newEventMessageWithId(2);
EventMessage eventMessage3 = newEventMessageWithId(3);
EventStream eventStream1 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE,
new long[] {presentationTimeUs1, presentationTimeUs2},
new EventMessage[] {eventMessage1, eventMessage2});
@ -253,9 +253,9 @@ public final class EventSampleStreamTest {
long presentationTimeUs1 = 1000000;
long presentationTimeUs2 = 2000000;
long presentationTimeUs3 = 3000000;
EventMessage eventMessage1 = newEventMessageWithIdAndTime(1, presentationTimeUs1);
EventMessage eventMessage2 = newEventMessageWithIdAndTime(2, presentationTimeUs2);
EventMessage eventMessage3 = newEventMessageWithIdAndTime(3, presentationTimeUs3);
EventMessage eventMessage1 = newEventMessageWithId(1);
EventMessage eventMessage2 = newEventMessageWithId(2);
EventMessage eventMessage3 = newEventMessageWithId(3);
EventStream eventStream1 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE,
new long[] {presentationTimeUs1},
new EventMessage[] {eventMessage1});
@ -287,9 +287,9 @@ public final class EventSampleStreamTest {
long presentationTimeUs1 = 1000000;
long presentationTimeUs2 = 2000000;
long presentationTimeUs3 = 3000000;
EventMessage eventMessage1 = newEventMessageWithIdAndTime(1, presentationTimeUs1);
EventMessage eventMessage2 = newEventMessageWithIdAndTime(2, presentationTimeUs2);
EventMessage eventMessage3 = newEventMessageWithIdAndTime(3, presentationTimeUs3);
EventMessage eventMessage1 = newEventMessageWithId(1);
EventMessage eventMessage2 = newEventMessageWithId(2);
EventMessage eventMessage3 = newEventMessageWithId(3);
EventStream eventStream1 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE,
new long[] {presentationTimeUs1, presentationTimeUs2},
new EventMessage[] {eventMessage1, eventMessage2});
@ -319,9 +319,9 @@ public final class EventSampleStreamTest {
long presentationTimeUs1 = 1000000;
long presentationTimeUs2 = 2000000;
long presentationTimeUs3 = 3000000;
EventMessage eventMessage1 = newEventMessageWithIdAndTime(1, presentationTimeUs1);
EventMessage eventMessage2 = newEventMessageWithIdAndTime(2, presentationTimeUs2);
EventMessage eventMessage3 = newEventMessageWithIdAndTime(3, presentationTimeUs3);
EventMessage eventMessage1 = newEventMessageWithId(1);
EventMessage eventMessage2 = newEventMessageWithId(2);
EventMessage eventMessage3 = newEventMessageWithId(3);
EventStream eventStream1 = new EventStream(SCHEME_ID, VALUE, TIME_SCALE,
new long[] {presentationTimeUs1},
new EventMessage[] {eventMessage1});
@ -345,12 +345,12 @@ public final class EventSampleStreamTest {
return sampleStream.readData(formatHolder, inputBuffer, false);
}
private EventMessage newEventMessageWithIdAndTime(int id, long presentationTimeUs) {
return new EventMessage(SCHEME_ID, VALUE, DURATION_MS, id, MESSAGE_DATA, presentationTimeUs);
private EventMessage newEventMessageWithId(int id) {
return new EventMessage(SCHEME_ID, VALUE, DURATION_MS, id, MESSAGE_DATA);
}
private byte[] getEncodedMessage(EventMessage eventMessage) {
return eventMessageEncoder.encode(eventMessage, TIME_SCALE);
return eventMessageEncoder.encode(eventMessage);
}
}

View File

@ -104,52 +104,53 @@ public class DashManifestParserTest {
"call",
10000,
0,
"+ 1 800 10101010".getBytes(Charset.forName(C.UTF8_NAME)),
0);
"+ 1 800 10101010".getBytes(Charset.forName(C.UTF8_NAME)));
assertThat(eventStream1.events[0]).isEqualTo(expectedEvent1);
assertThat(eventStream1.presentationTimesUs[0]).isEqualTo(0);
// assert CData-structured event stream
EventStream eventStream2 = period.eventStreams.get(1);
assertThat(eventStream2.events.length).isEqualTo(1);
assertThat(eventStream2.events[0])
.isEqualTo(
new EventMessage(
"urn:dvb:iptv:cpm:2014",
"",
1500000,
1,
Util.getUtf8Bytes(
"<![CDATA[<BroadcastEvent>\n"
+ " <Program crid=\"crid://broadcaster.example.com/ABCDEF\"/>\n"
+ " <InstanceDescription>\n"
+ " <Title xml:lang=\"en\">The title</Title>\n"
+ " <Synopsis xml:lang=\"en\" length=\"medium\">"
+ "The description</Synopsis>\n"
+ " <ParentalGuidance>\n"
+ " <mpeg7:ParentalRating href=\"urn:dvb:iptv:rating:2014:15\"/>\n"
+ " <mpeg7:Region>GB</mpeg7:Region>\n"
+ " </ParentalGuidance>\n"
+ " </InstanceDescription>\n"
+ " </BroadcastEvent>]]>"),
300000000));
EventMessage expectedEvent2 =
new EventMessage(
"urn:dvb:iptv:cpm:2014",
"",
1500000,
1,
Util.getUtf8Bytes(
"<![CDATA[<BroadcastEvent>\n"
+ " <Program crid=\"crid://broadcaster.example.com/ABCDEF\"/>\n"
+ " <InstanceDescription>\n"
+ " <Title xml:lang=\"en\">The title</Title>\n"
+ " <Synopsis xml:lang=\"en\" length=\"medium\">"
+ "The description</Synopsis>\n"
+ " <ParentalGuidance>\n"
+ " <mpeg7:ParentalRating href=\"urn:dvb:iptv:rating:2014:15\"/>\n"
+ " <mpeg7:Region>GB</mpeg7:Region>\n"
+ " </ParentalGuidance>\n"
+ " </InstanceDescription>\n"
+ " </BroadcastEvent>]]>"));
assertThat(eventStream2.events[0]).isEqualTo(expectedEvent2);
assertThat(eventStream2.presentationTimesUs[0]).isEqualTo(300000000);
// assert xml-structured event stream
EventStream eventStream3 = period.eventStreams.get(2);
assertThat(eventStream3.events.length).isEqualTo(1);
assertThat(eventStream3.events[0])
.isEqualTo(
new EventMessage(
"urn:scte:scte35:2014:xml+bin",
"",
1000000,
2,
Util.getUtf8Bytes(
"<scte35:Signal>\n"
+ " <scte35:Binary>\n"
+ " /DAIAAAAAAAAAAAQAAZ/I0VniQAQAgBDVUVJQAAAAH+cAAAAAA==\n"
+ " </scte35:Binary>\n"
+ " </scte35:Signal>"),
1000000000));
EventMessage expectedEvent3 =
new EventMessage(
"urn:scte:scte35:2014:xml+bin",
"",
1000000,
2,
Util.getUtf8Bytes(
"<scte35:Signal>\n"
+ " <scte35:Binary>\n"
+ " /DAIAAAAAAAAAAAQAAZ/I0VniQAQAgBDVUVJQAAAAH+cAAAAAA==\n"
+ " </scte35:Binary>\n"
+ " </scte35:Signal>"));
assertThat(eventStream3.events[0]).isEqualTo(expectedEvent3);
assertThat(eventStream3.presentationTimesUs[0]).isEqualTo(1000000000);
}
@Test