Commit 65d4b1cf by olly Committed by Oliver Woodman

Make CeaUtil robust against malformed SEI data

I've also added a TODO to not even bother trying to parse CEA from
SEI NAL units if they're fully or partially encrypted, which it's
possible to determine in the FMP4 extractor.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=147613979
parent ec98bd9e
...@@ -1086,6 +1086,7 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -1086,6 +1086,7 @@ public final class FragmentedMp4Extractor implements Extractor {
output.sampleData(nalStartCode, 4); output.sampleData(nalStartCode, 4);
// Write the NAL unit type byte. // Write the NAL unit type byte.
output.sampleData(nalPrefix, 1); output.sampleData(nalPrefix, 1);
// TODO: Don't try and process the SEI NAL unit if the payload is encrypted.
processSeiNalUnitPayload = cea608TrackOutput != null processSeiNalUnitPayload = cea608TrackOutput != null
&& NalUnitUtil.isNalUnitSei(track.format.sampleMimeType, nalPrefixData[4]); && NalUnitUtil.isNalUnitSei(track.format.sampleMimeType, nalPrefixData[4]);
sampleBytesWritten += 5; sampleBytesWritten += 5;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.text.cea; package com.google.android.exoplayer2.text.cea;
import android.util.Log;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
...@@ -24,6 +25,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray; ...@@ -24,6 +25,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
*/ */
public final class CeaUtil { public final class CeaUtil {
private static final String TAG = "CeaUtil";
private static final int PAYLOAD_TYPE_CC = 4; private static final int PAYLOAD_TYPE_CC = 4;
private static final int COUNTRY_CODE = 0xB5; private static final int COUNTRY_CODE = 0xB5;
private static final int PROVIDER_CODE = 0x31; private static final int PROVIDER_CODE = 0x31;
...@@ -40,22 +43,15 @@ public final class CeaUtil { ...@@ -40,22 +43,15 @@ public final class CeaUtil {
*/ */
public static void consume(long presentationTimeUs, ParsableByteArray seiBuffer, public static void consume(long presentationTimeUs, ParsableByteArray seiBuffer,
TrackOutput output) { TrackOutput output) {
int b;
while (seiBuffer.bytesLeft() > 1 /* last byte will be rbsp_trailing_bits */) { while (seiBuffer.bytesLeft() > 1 /* last byte will be rbsp_trailing_bits */) {
// Parse payload type. int payloadType = readNon255TerminatedValue(seiBuffer);
int payloadType = 0; int payloadSize = readNon255TerminatedValue(seiBuffer);
do {
b = seiBuffer.readUnsignedByte();
payloadType += b;
} while (b == 0xFF);
// Parse payload size.
int payloadSize = 0;
do {
b = seiBuffer.readUnsignedByte();
payloadSize += b;
} while (b == 0xFF);
// Process the payload. // 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) // Ignore country_code (1) + provider_code (2) + user_identifier (4)
// + user_data_type_code (1). // + user_data_type_code (1).
seiBuffer.skipBytes(8); seiBuffer.skipBytes(8);
...@@ -77,6 +73,27 @@ public final class CeaUtil { ...@@ -77,6 +73,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. * Inspects an sei message to determine whether it contains CEA-608.
* <p> * <p>
* The position of {@code payload} is left unchanged. * The position of {@code payload} is left unchanged.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment