mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
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:
parent
ad69a93708
commit
c66d26b601
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user