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 a1196c41c8..bbf7476d25 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 androidx.annotation.Nullable; import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.MetadataDecoder; import com.google.android.exoplayer2.metadata.MetadataInputBuffer; @@ -28,21 +29,31 @@ public final class EventMessageDecoder implements MetadataDecoder { @SuppressWarnings("ByteBufferBackingArray") @Override + @Nullable public Metadata decode(MetadataInputBuffer inputBuffer) { ByteBuffer buffer = Assertions.checkNotNull(inputBuffer.data); byte[] data = buffer.array(); int size = buffer.limit(); - return new Metadata(decode(new ParsableByteArray(data, size))); + EventMessage decodedEventMessage = decode(new ParsableByteArray(data, size)); + if (decodedEventMessage == null) { + return null; + } else { + return new Metadata(decodedEventMessage); + } } + @Nullable public EventMessage decode(ParsableByteArray emsgData) { - String schemeIdUri = Assertions.checkNotNull(emsgData.readNullTerminatedString()); - String value = Assertions.checkNotNull(emsgData.readNullTerminatedString()); - long durationMs = emsgData.readUnsignedInt(); - long id = emsgData.readUnsignedInt(); - byte[] messageData = - Arrays.copyOfRange(emsgData.data, emsgData.getPosition(), emsgData.limit()); - return new EventMessage(schemeIdUri, value, durationMs, id, messageData); + try { + String schemeIdUri = Assertions.checkNotNull(emsgData.readNullTerminatedString()); + String value = Assertions.checkNotNull(emsgData.readNullTerminatedString()); + long durationMs = emsgData.readUnsignedInt(); + long id = emsgData.readUnsignedInt(); + byte[] messageData = + Arrays.copyOfRange(emsgData.data, emsgData.getPosition(), emsgData.limit()); + return new EventMessage(schemeIdUri, value, durationMs, id, messageData); + } catch (RuntimeException e) { + return null; + } } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/metadata/MetadataRendererTest.java b/library/core/src/test/java/com/google/android/exoplayer2/metadata/MetadataRendererTest.java index 4de8bb76cc..26dcefc611 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/metadata/MetadataRendererTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/metadata/MetadataRendererTest.java @@ -55,13 +55,20 @@ public class MetadataRendererTest { /* id= */ 0, "Test data".getBytes(UTF_8)); - List metadata = runRenderer(eventMessageEncoder.encode(emsg)); + List metadata = runRenderer(EMSG_FORMAT, eventMessageEncoder.encode(emsg)); assertThat(metadata).hasSize(1); assertThat(metadata.get(0).length()).isEqualTo(1); assertThat(metadata.get(0).get(0)).isEqualTo(emsg); } + @Test + public void decodeMetadata_skipsMalformed() throws Exception { + List metadata = runRenderer(EMSG_FORMAT, "not valid emsg bytes".getBytes(UTF_8)); + + assertThat(metadata).isEmpty(); + } + @Test public void decodeMetadata_handlesWrappedMetadata() throws Exception { EventMessage emsg = @@ -72,7 +79,7 @@ public class MetadataRendererTest { /* id= */ 0, encodeTxxxId3Frame("Test description", "Test value")); - List metadata = runRenderer(eventMessageEncoder.encode(emsg)); + List metadata = runRenderer(EMSG_FORMAT, eventMessageEncoder.encode(emsg)); assertThat(metadata).hasSize(1); assertThat(metadata.get(0).length()).isEqualTo(1); @@ -91,17 +98,18 @@ public class MetadataRendererTest { /* id= */ 0, "Not a real ID3 tag".getBytes(ISO_8859_1)); - List metadata = runRenderer(eventMessageEncoder.encode(emsg)); + List metadata = runRenderer(EMSG_FORMAT, eventMessageEncoder.encode(emsg)); assertThat(metadata).isEmpty(); } - private static List runRenderer(byte[] input) throws ExoPlaybackException { + private static List runRenderer(Format format, byte[] input) + throws ExoPlaybackException { List metadata = new ArrayList<>(); MetadataRenderer renderer = new MetadataRenderer(metadata::add, /* outputLooper= */ null); renderer.replaceStream( - new Format[] {EMSG_FORMAT}, - new FakeSampleStream(EMSG_FORMAT, /* eventDispatcher= */ null, input), + new Format[] {format}, + new FakeSampleStream(format, /* eventDispatcher= */ null, input), /* offsetUs= */ 0L); renderer.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0); // Read the format renderer.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0); // Read the data diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java index af4bf3ad70..883ca7420e 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java @@ -360,6 +360,9 @@ public final class PlayerEmsgHandler implements Handler.Callback { } long eventTimeUs = inputBuffer.timeUs; Metadata metadata = decoder.decode(inputBuffer); + if (metadata == null) { + continue; + } EventMessage eventMessage = (EventMessage) metadata.get(0); if (isPlayerEmsgEvent(eventMessage.schemeIdUri, eventMessage.value)) { parsePlayerEmsgEvent(eventTimeUs, eventMessage);