mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Extend support of 608 captions in SEI messages
Issue:#3816 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=185124378
This commit is contained in:
parent
6aad066d51
commit
d274ca6750
1 changed files with 42 additions and 50 deletions
|
|
@ -19,18 +19,19 @@ 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;
|
||||||
|
import com.google.android.exoplayer2.util.Util;
|
||||||
|
|
||||||
/**
|
/** Utility methods for handling CEA-608/708 messages. Defined in A/53 Part 4:2009. */
|
||||||
* Utility methods for handling CEA-608/708 messages.
|
|
||||||
*/
|
|
||||||
public final class CeaUtil {
|
public final class CeaUtil {
|
||||||
|
|
||||||
private static final String TAG = "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_ATSC = 0x31;
|
||||||
private static final int USER_ID = 0x47413934; // "GA94"
|
private static final int PROVIDER_CODE_DIRECTV = 0x2F;
|
||||||
|
private static final int USER_ID_GA94 = Util.getIntegerCodeForString("GA94");
|
||||||
|
private static final int USER_ID_DTG1 = Util.getIntegerCodeForString("DTG1");
|
||||||
private static final int USER_DATA_TYPE_CODE = 0x3;
|
private static final int USER_DATA_TYPE_CODE = 0x3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -46,15 +47,32 @@ public final class CeaUtil {
|
||||||
while (seiBuffer.bytesLeft() > 1 /* last byte will be rbsp_trailing_bits */) {
|
while (seiBuffer.bytesLeft() > 1 /* last byte will be rbsp_trailing_bits */) {
|
||||||
int payloadType = readNon255TerminatedValue(seiBuffer);
|
int payloadType = readNon255TerminatedValue(seiBuffer);
|
||||||
int payloadSize = readNon255TerminatedValue(seiBuffer);
|
int payloadSize = readNon255TerminatedValue(seiBuffer);
|
||||||
|
int nextPayloadPosition = seiBuffer.getPosition() + payloadSize;
|
||||||
// Process the payload.
|
// Process the payload.
|
||||||
if (payloadSize == -1 || payloadSize > seiBuffer.bytesLeft()) {
|
if (payloadSize == -1 || payloadSize > seiBuffer.bytesLeft()) {
|
||||||
// This might occur if we're trying to read an encrypted SEI NAL unit.
|
// This might occur if we're trying to read an encrypted SEI NAL unit.
|
||||||
Log.w(TAG, "Skipping remainder of malformed SEI NAL unit.");
|
Log.w(TAG, "Skipping remainder of malformed SEI NAL unit.");
|
||||||
seiBuffer.setPosition(seiBuffer.limit());
|
seiBuffer.setPosition(seiBuffer.limit());
|
||||||
} else if (isSeiMessageCea608(payloadType, payloadSize, seiBuffer)) {
|
} else if (payloadType == PAYLOAD_TYPE_CC && payloadSize >= 8) {
|
||||||
// Ignore country_code (1) + provider_code (2) + user_identifier (4)
|
int countryCode = seiBuffer.readUnsignedByte();
|
||||||
// + user_data_type_code (1).
|
int providerCode = seiBuffer.readUnsignedShort();
|
||||||
seiBuffer.skipBytes(8);
|
int userIdentifier = 0;
|
||||||
|
if (providerCode == PROVIDER_CODE_ATSC) {
|
||||||
|
userIdentifier = seiBuffer.readInt();
|
||||||
|
}
|
||||||
|
int userDataTypeCode = seiBuffer.readUnsignedByte();
|
||||||
|
if (providerCode == PROVIDER_CODE_DIRECTV) {
|
||||||
|
seiBuffer.skipBytes(1); // user_data_length.
|
||||||
|
}
|
||||||
|
boolean messageIsSupportedCeaCaption =
|
||||||
|
countryCode == COUNTRY_CODE
|
||||||
|
&& (providerCode == PROVIDER_CODE_ATSC || providerCode == PROVIDER_CODE_DIRECTV)
|
||||||
|
&& userDataTypeCode == USER_DATA_TYPE_CODE;
|
||||||
|
if (providerCode == PROVIDER_CODE_ATSC) {
|
||||||
|
messageIsSupportedCeaCaption &=
|
||||||
|
userIdentifier == USER_ID_GA94 || userIdentifier == USER_ID_DTG1;
|
||||||
|
}
|
||||||
|
if (messageIsSupportedCeaCaption) {
|
||||||
// Ignore first three bits: reserved (1) + process_cc_data_flag (1) + zero_bit (1).
|
// Ignore first three bits: reserved (1) + process_cc_data_flag (1) + zero_bit (1).
|
||||||
int ccCount = seiBuffer.readUnsignedByte() & 0x1F;
|
int ccCount = seiBuffer.readUnsignedByte() & 0x1F;
|
||||||
// Ignore em_data (1)
|
// Ignore em_data (1)
|
||||||
|
|
@ -66,14 +84,13 @@ public final class CeaUtil {
|
||||||
for (TrackOutput output : outputs) {
|
for (TrackOutput output : outputs) {
|
||||||
seiBuffer.setPosition(sampleStartPosition);
|
seiBuffer.setPosition(sampleStartPosition);
|
||||||
output.sampleData(seiBuffer, sampleLength);
|
output.sampleData(seiBuffer, sampleLength);
|
||||||
output.sampleMetadata(presentationTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleLength, 0, null);
|
output.sampleMetadata(
|
||||||
|
presentationTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleLength, 0, null);
|
||||||
}
|
}
|
||||||
// Ignore trailing information in SEI, if any.
|
|
||||||
seiBuffer.skipBytes(payloadSize - (10 + ccCount * 3));
|
|
||||||
} else {
|
|
||||||
seiBuffer.skipBytes(payloadSize);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
seiBuffer.setPosition(nextPayloadPosition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -97,31 +114,6 @@ public final class CeaUtil {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Inspects an sei message to determine whether it contains CEA-608.
|
|
||||||
* <p>
|
|
||||||
* The position of {@code payload} is left unchanged.
|
|
||||||
*
|
|
||||||
* @param payloadType The payload type of the message.
|
|
||||||
* @param payloadLength The length of the payload.
|
|
||||||
* @param payload A {@link ParsableByteArray} containing the payload.
|
|
||||||
* @return Whether the sei message contains CEA-608.
|
|
||||||
*/
|
|
||||||
private static boolean isSeiMessageCea608(int payloadType, int payloadLength,
|
|
||||||
ParsableByteArray payload) {
|
|
||||||
if (payloadType != PAYLOAD_TYPE_CC || payloadLength < 8) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int startPosition = payload.getPosition();
|
|
||||||
int countryCode = payload.readUnsignedByte();
|
|
||||||
int providerCode = payload.readUnsignedShort();
|
|
||||||
int userIdentifier = payload.readInt();
|
|
||||||
int userDataTypeCode = payload.readUnsignedByte();
|
|
||||||
payload.setPosition(startPosition);
|
|
||||||
return countryCode == COUNTRY_CODE && providerCode == PROVIDER_CODE
|
|
||||||
&& userIdentifier == USER_ID && userDataTypeCode == USER_DATA_TYPE_CODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private CeaUtil() {}
|
private CeaUtil() {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue