Simplify EventMessageEncoder/Decoder serialization

We're no longer tied to the emsg spec, so we can skip unused fields
and assume ms for duration.

Also remove @Nullable annotation from EventMessageEncoder#encode, it
seems the current implementation never returns null

PiperOrigin-RevId: 262135009
This commit is contained in:
ibaker 2019-08-07 15:56:25 +01:00 committed by Oliver Woodman
parent bb6b0e1a5a
commit a08b537e8e
4 changed files with 40 additions and 67 deletions

View File

@ -15,22 +15,17 @@
*/ */
package com.google.android.exoplayer2.metadata.emsg; 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.Metadata;
import com.google.android.exoplayer2.metadata.MetadataDecoder; import com.google.android.exoplayer2.metadata.MetadataDecoder;
import com.google.android.exoplayer2.metadata.MetadataInputBuffer; import com.google.android.exoplayer2.metadata.MetadataInputBuffer;
import com.google.android.exoplayer2.util.Assertions; 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.ParsableByteArray;
import com.google.android.exoplayer2.util.Util;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Arrays; import java.util.Arrays;
/** Decodes data encoded by {@link EventMessageEncoder}. */ /** Decodes data encoded by {@link EventMessageEncoder}. */
public final class EventMessageDecoder implements MetadataDecoder { public final class EventMessageDecoder implements MetadataDecoder {
private static final String TAG = "EventMessageDecoder";
@SuppressWarnings("ByteBufferBackingArray") @SuppressWarnings("ByteBufferBackingArray")
@Override @Override
public Metadata decode(MetadataInputBuffer inputBuffer) { public Metadata decode(MetadataInputBuffer inputBuffer) {
@ -43,15 +38,7 @@ public final class EventMessageDecoder implements MetadataDecoder {
public EventMessage decode(ParsableByteArray emsgData) { public EventMessage decode(ParsableByteArray emsgData) {
String schemeIdUri = Assertions.checkNotNull(emsgData.readNullTerminatedString()); String schemeIdUri = Assertions.checkNotNull(emsgData.readNullTerminatedString());
String value = Assertions.checkNotNull(emsgData.readNullTerminatedString()); String value = Assertions.checkNotNull(emsgData.readNullTerminatedString());
long timescale = emsgData.readUnsignedInt(); long durationMs = emsgData.readUnsignedInt();
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(), C.MILLIS_PER_SECOND, timescale);
long id = emsgData.readUnsignedInt(); long id = emsgData.readUnsignedInt();
byte[] messageData = byte[] messageData =
Arrays.copyOfRange(emsgData.data, emsgData.getPosition(), emsgData.limit()); Arrays.copyOfRange(emsgData.data, emsgData.getPosition(), emsgData.limit());

View File

@ -15,7 +15,6 @@
*/ */
package com.google.android.exoplayer2.metadata.emsg; package com.google.android.exoplayer2.metadata.emsg;
import androidx.annotation.Nullable;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
@ -40,15 +39,12 @@ public final class EventMessageEncoder {
* @param eventMessage The event message to be encoded. * @param eventMessage The event message to be encoded.
* @return The serialized byte array. * @return The serialized byte array.
*/ */
@Nullable
public byte[] encode(EventMessage eventMessage) { public byte[] encode(EventMessage eventMessage) {
byteArrayOutputStream.reset(); byteArrayOutputStream.reset();
try { try {
writeNullTerminatedString(dataOutputStream, eventMessage.schemeIdUri); writeNullTerminatedString(dataOutputStream, eventMessage.schemeIdUri);
String nonNullValue = eventMessage.value != null ? eventMessage.value : ""; String nonNullValue = eventMessage.value != null ? eventMessage.value : "";
writeNullTerminatedString(dataOutputStream, nonNullValue); writeNullTerminatedString(dataOutputStream, nonNullValue);
writeUnsignedInt(dataOutputStream, 1000); // timescale
writeUnsignedInt(dataOutputStream, 0); // presentation_time_delta
writeUnsignedInt(dataOutputStream, eventMessage.durationMs); writeUnsignedInt(dataOutputStream, eventMessage.durationMs);
writeUnsignedInt(dataOutputStream, eventMessage.id); writeUnsignedInt(dataOutputStream, eventMessage.id);
dataOutputStream.write(eventMessage.messageData); dataOutputStream.write(eventMessage.messageData);

View File

@ -15,6 +15,8 @@
*/ */
package com.google.android.exoplayer2.metadata.emsg; package com.google.android.exoplayer2.metadata.emsg;
import static com.google.android.exoplayer2.testutil.TestUtil.createByteArray;
import static com.google.android.exoplayer2.testutil.TestUtil.joinByteArrays;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
@ -30,18 +32,19 @@ public final class EventMessageDecoderTest {
@Test @Test
public void testDecodeEventMessage() { public void testDecodeEventMessage() {
byte[] rawEmsgBody = new byte[] { byte[] rawEmsgBody =
117, 114, 110, 58, 116, 101, 115, 116, 0, // scheme_id_uri = "urn:test" joinByteArrays(
49, 50, 51, 0, // value = "123" createByteArray(117, 114, 110, 58, 116, 101, 115, 116, 0), // scheme_id_uri = "urn:test"
0, 0, -69, -128, // timescale = 48000 createByteArray(49, 50, 51, 0), // value = "123"
0, 0, -69, -128, // presentation_time_delta = 48000 createByteArray(0, 0, 11, 184), // event_duration_ms = 3000
0, 2, 50, -128, // event_duration = 144000 createByteArray(0, 15, 67, 211), // id = 1000403
0, 15, 67, -45, // id = 1000403 createByteArray(0, 1, 2, 3, 4)); // message_data = {0, 1, 2, 3, 4}
0, 1, 2, 3, 4}; // message_data = {0, 1, 2, 3, 4}
EventMessageDecoder decoder = new EventMessageDecoder(); EventMessageDecoder decoder = new EventMessageDecoder();
MetadataInputBuffer buffer = new MetadataInputBuffer(); MetadataInputBuffer buffer = new MetadataInputBuffer();
buffer.data = ByteBuffer.allocate(rawEmsgBody.length).put(rawEmsgBody); buffer.data = ByteBuffer.allocate(rawEmsgBody.length).put(rawEmsgBody);
Metadata metadata = decoder.decode(buffer); Metadata metadata = decoder.decode(buffer);
assertThat(metadata.length()).isEqualTo(1); assertThat(metadata.length()).isEqualTo(1);
EventMessage eventMessage = (EventMessage) metadata.get(0); EventMessage eventMessage = (EventMessage) metadata.get(0);
assertThat(eventMessage.schemeIdUri).isEqualTo("urn:test"); assertThat(eventMessage.schemeIdUri).isEqualTo("urn:test");

View File

@ -15,6 +15,8 @@
*/ */
package com.google.android.exoplayer2.metadata.emsg; package com.google.android.exoplayer2.metadata.emsg;
import static com.google.android.exoplayer2.testutil.TestUtil.createByteArray;
import static com.google.android.exoplayer2.testutil.TestUtil.joinByteArrays;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
@ -29,67 +31,52 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public final class EventMessageEncoderTest { public final class EventMessageEncoderTest {
private static final EventMessage DECODED_MESSAGE =
new EventMessage("urn:test", "123", 3000, 1000403, new byte[] {0, 1, 2, 3, 4});
private static final byte[] ENCODED_MESSAGE =
joinByteArrays(
createByteArray(117, 114, 110, 58, 116, 101, 115, 116, 0), // scheme_id_uri = "urn:test"
createByteArray(49, 50, 51, 0), // value = "123"
createByteArray(0, 0, 11, 184), // event_duration_ms = 3000
createByteArray(0, 15, 67, 211), // id = 1000403
createByteArray(0, 1, 2, 3, 4)); // message_data = {0, 1, 2, 3, 4}
@Test @Test
public void testEncodeEventStream() throws IOException { public void testEncodeEventStream() throws IOException {
EventMessage eventMessage = byte[] foo = new byte[] {1, 2, 3};
new EventMessage("urn:test", "123", 3000, 1000403, new byte[] {0, 1, 2, 3, 4});
byte[] expectedEmsgBody = byte[] encodedByteArray = new EventMessageEncoder().encode(DECODED_MESSAGE);
new byte[] { assertThat(encodedByteArray).isEqualTo(ENCODED_MESSAGE);
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 @Test
public void testEncodeDecodeEventStream() throws IOException { public void testEncodeDecodeEventStream() throws IOException {
EventMessage expectedEmsg = byte[] encodedByteArray = new EventMessageEncoder().encode(DECODED_MESSAGE);
new EventMessage("urn:test", "123", 3000, 1000403, new byte[] {0, 1, 2, 3, 4});
byte[] encodedByteArray = new EventMessageEncoder().encode(expectedEmsg);
MetadataInputBuffer buffer = new MetadataInputBuffer(); MetadataInputBuffer buffer = new MetadataInputBuffer();
buffer.data = ByteBuffer.allocate(encodedByteArray.length).put(encodedByteArray); buffer.data = ByteBuffer.allocate(encodedByteArray.length).put(encodedByteArray);
EventMessageDecoder decoder = new EventMessageDecoder(); EventMessageDecoder decoder = new EventMessageDecoder();
Metadata metadata = decoder.decode(buffer); Metadata metadata = decoder.decode(buffer);
assertThat(metadata.length()).isEqualTo(1); assertThat(metadata.length()).isEqualTo(1);
assertThat(metadata.get(0)).isEqualTo(expectedEmsg); assertThat(metadata.get(0)).isEqualTo(DECODED_MESSAGE);
} }
@Test @Test
public void testEncodeEventStreamMultipleTimesWorkingCorrectly() throws IOException { public void testEncodeEventStreamMultipleTimesWorkingCorrectly() throws IOException {
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 = EventMessage eventMessage1 =
new EventMessage("urn:test", "123", 3000, 1000402, new byte[] {4, 3, 2, 1, 0}); new EventMessage("urn:test", "123", 3000, 1000402, new byte[] {4, 3, 2, 1, 0});
byte[] expectedEmsgBody1 = byte[] expectedEmsgBody1 =
new byte[] { joinByteArrays(
117, 114, 110, 58, 116, 101, 115, 116, 0, // scheme_id_uri = "urn:test" createByteArray(117, 114, 110, 58, 116, 101, 115, 116, 0), // scheme_id_uri = "urn:test"
49, 50, 51, 0, // value = "123" createByteArray(49, 50, 51, 0), // value = "123"
0, 0, 3, -24, // timescale = 1000 createByteArray(0, 0, 11, 184), // event_duration_ms = 3000
0, 0, 0, 0, // presentation_time_delta = 0 createByteArray(0, 15, 67, 210), // id = 1000402
0, 0, 11, -72, // event_duration = 3000 createByteArray(4, 3, 2, 1, 0)); // message_data = {4, 3, 2, 1, 0}
0, 15, 67, -46, // id = 1000402
4, 3, 2, 1, 0
}; // message_data = {4, 3, 2, 1, 0}
EventMessageEncoder eventMessageEncoder = new EventMessageEncoder(); EventMessageEncoder eventMessageEncoder = new EventMessageEncoder();
byte[] encodedByteArray = eventMessageEncoder.encode(eventMessage); byte[] encodedByteArray = eventMessageEncoder.encode(DECODED_MESSAGE);
assertThat(encodedByteArray).isEqualTo(expectedEmsgBody); assertThat(encodedByteArray).isEqualTo(ENCODED_MESSAGE);
byte[] encodedByteArray1 = eventMessageEncoder.encode(eventMessage1); byte[] encodedByteArray1 = eventMessageEncoder.encode(eventMessage1);
assertThat(encodedByteArray1).isEqualTo(expectedEmsgBody1); assertThat(encodedByteArray1).isEqualTo(expectedEmsgBody1);
} }