diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java b/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java index 8144880338..0beb644ff6 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java @@ -1086,6 +1086,7 @@ public final class FragmentedMp4Extractor implements Extractor { output.sampleData(nalStartCode, 4); // Write the NAL unit type byte. output.sampleData(nalPrefix, 1); + // TODO: Don't try and process the SEI NAL unit if the payload is encrypted. processSeiNalUnitPayload = cea608TrackOutput != null && NalUnitUtil.isNalUnitSei(track.format.sampleMimeType, nalPrefixData[4]); sampleBytesWritten += 5; diff --git a/library/src/main/java/com/google/android/exoplayer2/text/cea/CeaUtil.java b/library/src/main/java/com/google/android/exoplayer2/text/cea/CeaUtil.java index 3053debfcf..a39c8c8669 100644 --- a/library/src/main/java/com/google/android/exoplayer2/text/cea/CeaUtil.java +++ b/library/src/main/java/com/google/android/exoplayer2/text/cea/CeaUtil.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.text.cea; +import android.util.Log; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.util.ParsableByteArray; @@ -24,6 +25,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray; */ public final class CeaUtil { + private static final String TAG = "CeaUtil"; + private static final int PAYLOAD_TYPE_CC = 4; private static final int COUNTRY_CODE = 0xB5; private static final int PROVIDER_CODE = 0x31; @@ -40,22 +43,15 @@ public final class CeaUtil { */ public static void consume(long presentationTimeUs, ParsableByteArray seiBuffer, TrackOutput output) { - int b; while (seiBuffer.bytesLeft() > 1 /* last byte will be rbsp_trailing_bits */) { - // Parse payload type. - int payloadType = 0; - do { - b = seiBuffer.readUnsignedByte(); - payloadType += b; - } while (b == 0xFF); - // Parse payload size. - int payloadSize = 0; - do { - b = seiBuffer.readUnsignedByte(); - payloadSize += b; - } while (b == 0xFF); + int payloadType = readNon255TerminatedValue(seiBuffer); + int payloadSize = readNon255TerminatedValue(seiBuffer); // Process the payload. - if (isSeiMessageCea608(payloadType, payloadSize, seiBuffer)) { + if (payloadSize == -1 || payloadSize > seiBuffer.bytesLeft()) { + // This might occur if we're trying to read an encrypted SEI NAL unit. + Log.w(TAG, "Skipping remainder of malformed SEI NAL unit."); + seiBuffer.setPosition(seiBuffer.limit()); + } else if (isSeiMessageCea608(payloadType, payloadSize, seiBuffer)) { // Ignore country_code (1) + provider_code (2) + user_identifier (4) // + user_data_type_code (1). seiBuffer.skipBytes(8); @@ -76,6 +72,27 @@ public final class CeaUtil { } } + /** + * Reads a value from the provided buffer consisting of zero or more 0xFF bytes followed by a + * terminating byte not equal to 0xFF. The returned value is ((0xFF * N) + T), where N is the + * number of 0xFF bytes and T is the value of the terminating byte. + * + * @param buffer The buffer from which to read the value. + * @returns The read value, or -1 if the end of the buffer is reached before a value is read. + */ + private static int readNon255TerminatedValue(ParsableByteArray buffer) { + int b; + int value = 0; + do { + if (buffer.bytesLeft() == 0) { + return -1; + } + b = buffer.readUnsignedByte(); + value += b; + } while (b == 0xFF); + return value; + } + /** * Inspects an sei message to determine whether it contains CEA-608. *