Merge updates from GitHub.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=120332794
This commit is contained in:
olly 2016-04-20 06:59:04 -07:00 committed by Oliver Woodman
parent 7638bea016
commit 2a37b02ee2
2 changed files with 112 additions and 1 deletions

View File

@ -44,6 +44,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
/**
* Extracts data from a Matroska or WebM file.
@ -64,6 +65,7 @@ public final class MatroskaExtractor implements Extractor {
private static final String CODEC_ID_MPEG4_AP = "V_MPEG4/ISO/AP";
private static final String CODEC_ID_H264 = "V_MPEG4/ISO/AVC";
private static final String CODEC_ID_H265 = "V_MPEGH/ISO/HEVC";
private static final String CODEC_ID_FOURCC = "V_MS/VFW/FOURCC";
private static final String CODEC_ID_VORBIS = "A_VORBIS";
private static final String CODEC_ID_OPUS = "A_OPUS";
private static final String CODEC_ID_AAC = "A_AAC";
@ -75,6 +77,8 @@ public final class MatroskaExtractor implements Extractor {
private static final String CODEC_ID_DTS_EXPRESS = "A_DTS/EXPRESS";
private static final String CODEC_ID_DTS_LOSSLESS = "A_DTS/LOSSLESS";
private static final String CODEC_ID_FLAC = "A_FLAC";
private static final String CODEC_ID_ACM = "A_MS/ACM";
private static final String CODEC_ID_PCM_INT_LIT = "A_PCM/INT/LIT";
private static final String CODEC_ID_SUBRIP = "S_TEXT/UTF8";
private static final String CODEC_ID_VOBSUB = "S_VOBSUB";
private static final String CODEC_ID_PGS = "S_HDMV/PGS";
@ -123,6 +127,7 @@ public final class MatroskaExtractor implements Extractor {
private static final int ID_DISPLAY_UNIT = 0x54B2;
private static final int ID_AUDIO = 0xE1;
private static final int ID_CHANNELS = 0x9F;
private static final int ID_AUDIO_BIT_DEPTH = 0x6264;
private static final int ID_SAMPLING_FREQUENCY = 0xB5;
private static final int ID_CONTENT_ENCODINGS = 0x6D80;
private static final int ID_CONTENT_ENCODING = 0x6240;
@ -148,6 +153,8 @@ public final class MatroskaExtractor implements Extractor {
private static final int LACING_FIXED_SIZE = 2;
private static final int LACING_EBML = 3;
private static final int FOURCC_COMPRESSION_VC1 = 0x31435657;
/**
* A template for the prefix that must be added to each subrip sample. The 12 byte end timecode
* starting at {@link #SUBRIP_PREFIX_END_TIMECODE_OFFSET} is set to a dummy value, and must be
@ -174,6 +181,23 @@ public final class MatroskaExtractor implements Extractor {
*/
private static final int SUBRIP_TIMECODE_LENGTH = 12;
/**
* The length in bytes of a WAVEFORMATEX structure.
*/
private static final int WAVE_FORMAT_SIZE = 18;
/**
* Format tag indicating a WAVEFORMATEXTENSIBLE structure.
*/
private static final int WAVE_FORMAT_EXTENSIBLE = 0xFFFE;
/**
* Format tag for PCM.
*/
private static final int WAVE_FORMAT_PCM = 1;
/**
* Sub format for PCM.
*/
private static final UUID WAVE_SUBFORMAT_PCM = new UUID(0x0100000000001000L, 0x800000AA00389B71L);
private final EbmlReader reader;
private final VarintReader varintReader;
private final SparseArray<Track> tracks;
@ -330,6 +354,7 @@ public final class MatroskaExtractor implements Extractor {
case ID_CODEC_DELAY:
case ID_SEEK_PRE_ROLL:
case ID_CHANNELS:
case ID_AUDIO_BIT_DEPTH:
case ID_CONTENT_ENCODING_ORDER:
case ID_CONTENT_ENCODING_SCOPE:
case ID_CONTENT_COMPRESSION_ALGORITHM:
@ -535,7 +560,7 @@ public final class MatroskaExtractor implements Extractor {
return;
case ID_DEFAULT_DURATION:
currentTrack.defaultSampleDurationNs = (int) value;
break;
return;
case ID_CODEC_DELAY:
currentTrack.codecDelayNs = value;
return;
@ -545,6 +570,9 @@ public final class MatroskaExtractor implements Extractor {
case ID_CHANNELS:
currentTrack.channelCount = (int) value;
return;
case ID_AUDIO_BIT_DEPTH:
currentTrack.audioBitDepth = (int) value;
return;
case ID_REFERENCE_BLOCK:
sampleSeenReferenceBlock = true;
return;
@ -1058,6 +1086,7 @@ public final class MatroskaExtractor implements Extractor {
|| CODEC_ID_MPEG4_AP.equals(codecId)
|| CODEC_ID_H264.equals(codecId)
|| CODEC_ID_H265.equals(codecId)
|| CODEC_ID_FOURCC.equals(codecId)
|| CODEC_ID_OPUS.equals(codecId)
|| CODEC_ID_VORBIS.equals(codecId)
|| CODEC_ID_AAC.equals(codecId)
@ -1069,6 +1098,8 @@ public final class MatroskaExtractor implements Extractor {
|| CODEC_ID_DTS_EXPRESS.equals(codecId)
|| CODEC_ID_DTS_LOSSLESS.equals(codecId)
|| CODEC_ID_FLAC.equals(codecId)
|| CODEC_ID_ACM.equals(codecId)
|| CODEC_ID_PCM_INT_LIT.equals(codecId)
|| CODEC_ID_SUBRIP.equals(codecId)
|| CODEC_ID_VOBSUB.equals(codecId)
|| CODEC_ID_PGS.equals(codecId);
@ -1161,6 +1192,7 @@ public final class MatroskaExtractor implements Extractor {
// Audio elements. Initially set to their default values.
public int channelCount = 1;
public int audioBitDepth = -1;
public int sampleRate = 8000;
public long codecDelayNs = 0;
public long seekPreRollNs = 0;
@ -1210,6 +1242,10 @@ public final class MatroskaExtractor implements Extractor {
initializationData = hevcData.first;
nalUnitLengthFieldLength = hevcData.second;
break;
case CODEC_ID_FOURCC:
mimeType = MimeTypes.VIDEO_VC1;
initializationData = parseFourCcVc1Private(new ParsableByteArray(codecPrivate));
break;
case CODEC_ID_VORBIS:
mimeType = MimeTypes.AUDIO_VORBIS;
maxInputSize = VORBIS_MAX_INPUT_SIZE;
@ -1253,6 +1289,21 @@ public final class MatroskaExtractor implements Extractor {
mimeType = MimeTypes.AUDIO_FLAC;
initializationData = Collections.singletonList(codecPrivate);
break;
case CODEC_ID_ACM:
mimeType = MimeTypes.AUDIO_RAW;
if (!parseMsAcmCodecPrivate(new ParsableByteArray(codecPrivate))) {
throw new ParserException("Non-PCM MS/ACM is unsupported");
}
if (audioBitDepth != 16) {
throw new ParserException("Unsupported PCM bit depth: " + audioBitDepth);
}
break;
case CODEC_ID_PCM_INT_LIT:
mimeType = MimeTypes.AUDIO_RAW;
if (audioBitDepth != 16) {
throw new ParserException("Unsupported PCM bit depth: " + audioBitDepth);
}
break;
case CODEC_ID_SUBRIP:
mimeType = MimeTypes.APPLICATION_SUBRIP;
break;
@ -1300,6 +1351,42 @@ public final class MatroskaExtractor implements Extractor {
this.output.format(format);
}
/**
* Builds initialization data for a {@link Format} from FourCC codec private data.
* <p>
* VC1 is the only supported compression type.
*
* @return The initialization data for the {@link Format}.
* @throws ParserException If the initialization data could not be built.
*/
private static List<byte[]> parseFourCcVc1Private(ParsableByteArray buffer)
throws ParserException {
try {
buffer.skipBytes(16); // size(4), width(4), height(4), planes(2), bitcount(2).
long compression = buffer.readLittleEndianUnsignedInt();
if (compression != FOURCC_COMPRESSION_VC1) {
throw new ParserException("Unsupported FourCC compression type: " + compression);
}
// Search for the initialization data from the end of the BITMAPINFOHEADER. The last 20
// bytes of which are: sizeImage(4), xPel/m (4), yPel/m (4), clrUsed(4), clrImportant(4).
int startOffset = buffer.getPosition() + 20;
byte[] bufferData = buffer.data;
for (int offset = startOffset; offset < bufferData.length - 4; offset++) {
if (bufferData[offset] == 0x00 && bufferData[offset + 1] == 0x00
&& bufferData[offset + 2] == 0x01 && bufferData[offset + 3] == 0x0F) {
// We've found the initialization data.
byte[] initializationData = Arrays.copyOfRange(bufferData, offset, bufferData.length);
return Collections.singletonList(initializationData);
}
}
throw new ParserException("Failed to find FourCC VC1 initialization data");
} catch (ArrayIndexOutOfBoundsException e) {
throw new ParserException("Error parsing FourCC VC1 codec private");
}
}
/**
* Builds initialization data for a {@link Format} from H.264 (AVC) codec private data.
*
@ -1434,6 +1521,29 @@ public final class MatroskaExtractor implements Extractor {
}
}
/**
* Parses an MS/ACM codec private, returning whether it indicates PCM audio.
*
* @return True if the codec private indicates PCM audio. False otherwise.
* @throws ParserException If a parsing error occurs.
*/
private static boolean parseMsAcmCodecPrivate(ParsableByteArray buffer) throws ParserException {
try {
int formatTag = buffer.readLittleEndianUnsignedShort();
if (formatTag == WAVE_FORMAT_PCM) {
return true;
} else if (formatTag == WAVE_FORMAT_EXTENSIBLE) {
buffer.setPosition(WAVE_FORMAT_SIZE + 6); // unionSamples(2), channelMask(4)
return buffer.readLong() == WAVE_SUBFORMAT_PCM.getMostSignificantBits()
&& buffer.readLong() == WAVE_SUBFORMAT_PCM.getLeastSignificantBits();
} else {
return false;
}
} catch (ArrayIndexOutOfBoundsException e) {
throw new ParserException("Error parsing MS/ACM codec private");
}
}
}
}

View File

@ -34,6 +34,7 @@ public final class MimeTypes {
public static final String VIDEO_VP9 = BASE_TYPE_VIDEO + "/x-vnd.on2.vp9";
public static final String VIDEO_MP4V = BASE_TYPE_VIDEO + "/mp4v-es";
public static final String VIDEO_MPEG2 = BASE_TYPE_VIDEO + "/mpeg2";
public static final String VIDEO_VC1 = BASE_TYPE_VIDEO + "/wvc1";
public static final String AUDIO_MP4 = BASE_TYPE_AUDIO + "/mp4";
public static final String AUDIO_AAC = BASE_TYPE_AUDIO + "/mp4a-latm";