mirror of
https://github.com/androidx/media.git
synced 2025-05-07 15:40:37 +08:00
Use separate mimeType for CEA-608 embedded in MP4
When CEA-608 is embedded in MP4 each packet consists of cc_data_1 and cc_data_2 only. The marker_bits, cc_valid and cc_type are implicit. As a result playback of CEA-608 embedded in MP4 broke when we started passing the extra byte for the TS case (and adjusted the decoder to assume the byte was present). This change introduces a special mimeType for the case where the byte is implicit (!). An alternative option was to insert the extra byte every 2 bytes in the MP4 extractor, but this is really quite fiddly to get right. Also made the loops in the 608/708 decoders robust against input of the wrong length. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=140609304
This commit is contained in:
parent
f702568776
commit
45c68a2fd5
@ -621,8 +621,9 @@ import java.util.List;
|
||||
MimeTypes.APPLICATION_TTML, null, Format.NO_VALUE, 0, language, drmInitData,
|
||||
0 /* subsample timing is absolute */);
|
||||
} else if (childAtomType == Atom.TYPE_c608) {
|
||||
// Defined by the QuickTime File Format specification.
|
||||
out.format = Format.createTextSampleFormat(Integer.toString(trackId),
|
||||
MimeTypes.APPLICATION_CEA608, null, Format.NO_VALUE, 0, language, drmInitData);
|
||||
MimeTypes.APPLICATION_MP4CEA608, null, Format.NO_VALUE, 0, language, drmInitData);
|
||||
out.requiredSampleTransformation = Track.TRANSFORMATION_CEA608_CDAT;
|
||||
} else if (childAtomType == Atom.TYPE_camm) {
|
||||
out.format = Format.createSampleFormat(Integer.toString(trackId),
|
||||
|
@ -75,8 +75,8 @@ public interface SubtitleDecoderFactory {
|
||||
throw new IllegalArgumentException("Attempted to create decoder for unsupported format");
|
||||
}
|
||||
if (clazz == Cea608Decoder.class) {
|
||||
return clazz.asSubclass(SubtitleDecoder.class)
|
||||
.getConstructor(Integer.TYPE).newInstance(format.accessibilityChannel);
|
||||
return clazz.asSubclass(SubtitleDecoder.class).getConstructor(String.class, Integer.TYPE)
|
||||
.newInstance(format.sampleMimeType, format.accessibilityChannel);
|
||||
} else {
|
||||
return clazz.asSubclass(SubtitleDecoder.class).getConstructor().newInstance();
|
||||
}
|
||||
@ -102,6 +102,7 @@ public interface SubtitleDecoderFactory {
|
||||
case MimeTypes.APPLICATION_TX3G:
|
||||
return Class.forName("com.google.android.exoplayer2.text.tx3g.Tx3gDecoder");
|
||||
case MimeTypes.APPLICATION_CEA608:
|
||||
case MimeTypes.APPLICATION_MP4CEA608:
|
||||
return Class.forName("com.google.android.exoplayer2.text.cea.Cea608Decoder");
|
||||
default:
|
||||
return null;
|
||||
|
@ -21,6 +21,7 @@ import com.google.android.exoplayer2.text.Cue;
|
||||
import com.google.android.exoplayer2.text.Subtitle;
|
||||
import com.google.android.exoplayer2.text.SubtitleDecoder;
|
||||
import com.google.android.exoplayer2.text.SubtitleInputBuffer;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||
|
||||
/**
|
||||
@ -52,6 +53,10 @@ public final class Cea608Decoder extends CeaDecoder {
|
||||
// The default number of rows to display in roll-up captions mode.
|
||||
private static final int DEFAULT_CAPTIONS_ROW_COUNT = 4;
|
||||
|
||||
// An implied first byte for packets that are only 2 bytes long, consisting of marker bits
|
||||
// (0b11111) + valid bit (0b1) + NTSC field 1 type bits (0b00).
|
||||
private static final byte CC_IMPLICIT_DATA_HEADER = (byte) 0xFC;
|
||||
|
||||
/**
|
||||
* Command initiating pop-on style captioning. Subsequent data should be loaded into a
|
||||
* non-displayed memory and held there until the {@link #CTRL_END_OF_CAPTION} command is received,
|
||||
@ -164,9 +169,8 @@ public final class Cea608Decoder extends CeaDecoder {
|
||||
};
|
||||
|
||||
private final ParsableByteArray ccData;
|
||||
|
||||
private final StringBuilder captionStringBuilder;
|
||||
|
||||
private final int packetLength;
|
||||
private final int selectedField;
|
||||
|
||||
private int captionMode;
|
||||
@ -179,10 +183,11 @@ public final class Cea608Decoder extends CeaDecoder {
|
||||
private byte repeatableControlCc1;
|
||||
private byte repeatableControlCc2;
|
||||
|
||||
public Cea608Decoder(int accessibilityChannel) {
|
||||
public Cea608Decoder(String mimeType, int accessibilityChannel) {
|
||||
ccData = new ParsableByteArray();
|
||||
|
||||
captionStringBuilder = new StringBuilder();
|
||||
|
||||
packetLength = MimeTypes.APPLICATION_MP4CEA608.equals(mimeType) ? 2 : 3;
|
||||
switch (accessibilityChannel) {
|
||||
case 3:
|
||||
case 4:
|
||||
@ -238,8 +243,9 @@ public final class Cea608Decoder extends CeaDecoder {
|
||||
ccData.reset(inputBuffer.data.array(), inputBuffer.data.limit());
|
||||
boolean captionDataProcessed = false;
|
||||
boolean isRepeatableControl = false;
|
||||
while (ccData.bytesLeft() > 0) {
|
||||
byte ccDataHeader = (byte) ccData.readUnsignedByte();
|
||||
while (ccData.bytesLeft() >= packetLength) {
|
||||
byte ccDataHeader = packetLength == 2 ? CC_IMPLICIT_DATA_HEADER
|
||||
: (byte) ccData.readUnsignedByte();
|
||||
byte ccData1 = (byte) (ccData.readUnsignedByte() & 0x7F);
|
||||
byte ccData2 = (byte) (ccData.readUnsignedByte() & 0x7F);
|
||||
|
||||
|
@ -70,7 +70,8 @@ public final class MimeTypes {
|
||||
public static final String APPLICATION_TTML = BASE_TYPE_APPLICATION + "/ttml+xml";
|
||||
public static final String APPLICATION_M3U8 = BASE_TYPE_APPLICATION + "/x-mpegURL";
|
||||
public static final String APPLICATION_TX3G = BASE_TYPE_APPLICATION + "/x-quicktime-tx3g";
|
||||
public static final String APPLICATION_MP4VTT = BASE_TYPE_APPLICATION + "/x-mp4vtt";
|
||||
public static final String APPLICATION_MP4VTT = BASE_TYPE_APPLICATION + "/x-mp4-vtt";
|
||||
public static final String APPLICATION_MP4CEA608 = BASE_TYPE_APPLICATION + "/x-mp4-cea-608";
|
||||
public static final String APPLICATION_RAWCC = BASE_TYPE_APPLICATION + "/x-rawcc";
|
||||
public static final String APPLICATION_VOBSUB = BASE_TYPE_APPLICATION + "/vobsub";
|
||||
public static final String APPLICATION_PGS = BASE_TYPE_APPLICATION + "/pgs";
|
||||
|
Loading…
x
Reference in New Issue
Block a user