Skip to content

Commit

Permalink
Make CeaUtil robust against malformed SEI data
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ojw28 committed Feb 15, 2017
1 parent ec98bd9 commit 65d4b1c
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1086,6 +1086,7 @@ private boolean readSample(ExtractorInput input) throws IOException, Interrupted
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -24,6 +25,8 @@
*/
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;
Expand All @@ -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);
Expand All @@ -76,6 +72,27 @@ public static void consume(long presentationTimeUs, ParsableByteArray seiBuffer,
}
}

/**
* 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.
* <p>
Expand Down

0 comments on commit 65d4b1c

Please sign in to comment.