Commit 0a7011b3 by tonihei Committed by Oliver Woodman

Support default style in Tx3g decoder.

The track initialization data of Tx3g includes default style values for
font styles, colour, and font family. Additionally the decoder now supports
vertical subtitle placements other than the Tx3g default of 85% video height.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=152930057
parent 1a22a4be
......@@ -82,6 +82,16 @@ public final class C {
public static final String UTF16_NAME = "UTF-16";
/**
* * The name of the serif font family.
*/
public static final String SERIF_NAME = "serif";
/**
* * The name of the sans-serif font family.
*/
public static final String SANS_SERIF_NAME = "sans-serif";
/**
* Crypto modes for a codec.
*/
@Retention(RetentionPolicy.SOURCE)
......
......@@ -283,30 +283,31 @@ public final class Format implements Parcelable {
public static Format createTextSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, @C.SelectionFlags int selectionFlags, String language, DrmInitData drmInitData) {
return createTextSampleFormat(id, sampleMimeType, codecs, bitrate, selectionFlags, language,
NO_VALUE, drmInitData, OFFSET_SAMPLE_RELATIVE);
NO_VALUE, drmInitData, OFFSET_SAMPLE_RELATIVE, Collections.<byte[]>emptyList());
}
public static Format createTextSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, @C.SelectionFlags int selectionFlags, String language, int accessibilityChannel,
DrmInitData drmInitData) {
return createTextSampleFormat(id, sampleMimeType, codecs, bitrate, selectionFlags, language,
accessibilityChannel, drmInitData, OFFSET_SAMPLE_RELATIVE);
accessibilityChannel, drmInitData, OFFSET_SAMPLE_RELATIVE, Collections.<byte[]>emptyList());
}
public static Format createTextSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, @C.SelectionFlags int selectionFlags, String language, DrmInitData drmInitData,
long subsampleOffsetUs) {
return createTextSampleFormat(id, sampleMimeType, codecs, bitrate, selectionFlags, language,
NO_VALUE, drmInitData, subsampleOffsetUs);
NO_VALUE, drmInitData, subsampleOffsetUs, Collections.<byte[]>emptyList());
}
public static Format createTextSampleFormat(String id, String sampleMimeType, String codecs,
int bitrate, @C.SelectionFlags int selectionFlags, String language,
int accessibilityChannel, DrmInitData drmInitData, long subsampleOffsetUs) {
int accessibilityChannel, DrmInitData drmInitData, long subsampleOffsetUs,
List<byte[]> initializationData) {
return new Format(id, null, sampleMimeType, codecs, bitrate, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, NO_VALUE, NO_VALUE, null, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
NO_VALUE, selectionFlags, language, accessibilityChannel, subsampleOffsetUs, null,
drmInitData, null);
NO_VALUE, selectionFlags, language, accessibilityChannel, subsampleOffsetUs,
initializationData, drmInitData, null);
}
// Image.
......@@ -438,6 +439,7 @@ public final class Format implements Parcelable {
drmInitData, metadata);
}
@SuppressWarnings("ReferenceEquality")
public Format copyWithManifestFormatInfo(Format manifestFormat) {
if (this == manifestFormat) {
// No need to copy from ourselves.
......
......@@ -611,24 +611,11 @@ import java.util.List;
|| childAtomType == Atom.TYPE__mp3 || childAtomType == Atom.TYPE_alac) {
parseAudioSampleEntry(stsd, childAtomType, childStartPosition, childAtomSize, trackId,
language, isQuickTime, drmInitData, out, i);
} else if (childAtomType == Atom.TYPE_TTML) {
out.format = Format.createTextSampleFormat(Integer.toString(trackId),
MimeTypes.APPLICATION_TTML, null, Format.NO_VALUE, 0, language, drmInitData);
} else if (childAtomType == Atom.TYPE_tx3g) {
out.format = Format.createTextSampleFormat(Integer.toString(trackId),
MimeTypes.APPLICATION_TX3G, null, Format.NO_VALUE, 0, language, drmInitData);
} else if (childAtomType == Atom.TYPE_wvtt) {
out.format = Format.createTextSampleFormat(Integer.toString(trackId),
MimeTypes.APPLICATION_MP4VTT, null, Format.NO_VALUE, 0, language, drmInitData);
} else if (childAtomType == Atom.TYPE_stpp) {
out.format = Format.createTextSampleFormat(Integer.toString(trackId),
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_MP4CEA608, null, Format.NO_VALUE, 0, language, drmInitData);
out.requiredSampleTransformation = Track.TRANSFORMATION_CEA608_CDAT;
} else if (childAtomType == Atom.TYPE_TTML || childAtomType == Atom.TYPE_tx3g
|| childAtomType == Atom.TYPE_wvtt || childAtomType == Atom.TYPE_stpp
|| childAtomType == Atom.TYPE_c608) {
parseTextSampleEntry(stsd, childAtomType, childStartPosition, childAtomSize, trackId,
language, drmInitData, out);
} else if (childAtomType == Atom.TYPE_camm) {
out.format = Format.createSampleFormat(Integer.toString(trackId),
MimeTypes.APPLICATION_CAMERA_MOTION, null, Format.NO_VALUE, drmInitData);
......@@ -638,12 +625,49 @@ import java.util.List;
return out;
}
private static void parseTextSampleEntry(ParsableByteArray parent, int atomType, int position,
int atomSize, int trackId, String language, DrmInitData drmInitData, StsdData out)
throws ParserException {
parent.setPosition(position + Atom.HEADER_SIZE + StsdData.STSD_HEADER_SIZE);
// Default values.
List<byte[]> initializationData = null;
long subsampleOffsetUs = Format.OFFSET_SAMPLE_RELATIVE;
String mimeType;
if (atomType == Atom.TYPE_TTML) {
mimeType = MimeTypes.APPLICATION_TTML;
} else if (atomType == Atom.TYPE_tx3g) {
mimeType = MimeTypes.APPLICATION_TX3G;
int sampleDescriptionLength = atomSize - Atom.HEADER_SIZE - 8;
byte[] sampleDescriptionData = new byte[sampleDescriptionLength];
parent.readBytes(sampleDescriptionData, 0, sampleDescriptionLength);
initializationData = Collections.singletonList(sampleDescriptionData);
} else if (atomType == Atom.TYPE_wvtt) {
mimeType = MimeTypes.APPLICATION_MP4VTT;
} else if (atomType == Atom.TYPE_stpp) {
mimeType = MimeTypes.APPLICATION_TTML;
subsampleOffsetUs = 0; // Subsample timing is absolute.
} else if (atomType == Atom.TYPE_c608) {
// Defined by the QuickTime File Format specification.
mimeType = MimeTypes.APPLICATION_MP4CEA608;
out.requiredSampleTransformation = Track.TRANSFORMATION_CEA608_CDAT;
} else {
// Never happens.
throw new IllegalStateException();
}
out.format = Format.createTextSampleFormat(Integer.toString(trackId), mimeType, null,
Format.NO_VALUE, 0, language, Format.NO_VALUE, drmInitData, subsampleOffsetUs,
initializationData);
}
private static void parseVideoSampleEntry(ParsableByteArray parent, int atomType, int position,
int size, int trackId, int rotationDegrees, DrmInitData drmInitData, StsdData out,
int entryIndex) throws ParserException {
parent.setPosition(position + Atom.HEADER_SIZE);
parent.setPosition(position + Atom.HEADER_SIZE + StsdData.STSD_HEADER_SIZE);
parent.skipBytes(24);
parent.skipBytes(16);
int width = parent.readUnsignedShort();
int height = parent.readUnsignedShort();
boolean pixelWidthHeightRatioFromPasp = false;
......@@ -784,15 +808,14 @@ import java.util.List;
private static void parseAudioSampleEntry(ParsableByteArray parent, int atomType, int position,
int size, int trackId, String language, boolean isQuickTime, DrmInitData drmInitData,
StsdData out, int entryIndex) {
parent.setPosition(position + Atom.HEADER_SIZE);
parent.setPosition(position + Atom.HEADER_SIZE + StsdData.STSD_HEADER_SIZE);
int quickTimeSoundDescriptionVersion = 0;
if (isQuickTime) {
parent.skipBytes(8);
quickTimeSoundDescriptionVersion = parent.readUnsignedShort();
parent.skipBytes(6);
} else {
parent.skipBytes(16);
parent.skipBytes(8);
}
int channelCount;
......@@ -1177,6 +1200,8 @@ import java.util.List;
*/
private static final class StsdData {
public static final int STSD_HEADER_SIZE = 8;
public final TrackEncryptionBox[] trackEncryptionBoxes;
public Format format;
......
......@@ -92,7 +92,7 @@ public interface SubtitleDecoderFactory {
case MimeTypes.APPLICATION_SUBRIP:
return new SubripDecoder();
case MimeTypes.APPLICATION_TX3G:
return new Tx3gDecoder();
return new Tx3gDecoder(format.initializationData);
case MimeTypes.APPLICATION_CEA608:
case MimeTypes.APPLICATION_MP4CEA608:
return new Cea608Decoder(format.sampleMimeType, format.accessibilityChannel);
......
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