mirror of
https://github.com/androidx/media.git
synced 2025-05-12 10:09:55 +08:00
Added support for RawCC (i.e. out-of-band EIA-608)
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=128397367
This commit is contained in:
parent
75e2aee92e
commit
1d79c26b34
BIN
library/src/androidTest/assets/rawcc/sample.rawcc
Normal file
BIN
library/src/androidTest/assets/rawcc/sample.rawcc
Normal file
Binary file not shown.
329
library/src/androidTest/assets/rawcc/sample.rawcc.0.dump
Normal file
329
library/src/androidTest/assets/rawcc/sample.rawcc.0.dump
Normal file
@ -0,0 +1,329 @@
|
||||
seekMap:
|
||||
isSeekable = false
|
||||
duration = UNSET TIME
|
||||
getPosition(0) = 0
|
||||
numberOfTracks = 1
|
||||
track 0:
|
||||
format:
|
||||
bitrate = -1
|
||||
id = null
|
||||
containerMimeType = null
|
||||
sampleMimeType = application/eia-608
|
||||
maxInputSize = -1
|
||||
width = -1
|
||||
height = -1
|
||||
frameRate = -1.0
|
||||
rotationDegrees = -1
|
||||
pixelWidthHeightRatio = -1.0
|
||||
channelCount = -1
|
||||
sampleRate = -1
|
||||
pcmEncoding = -1
|
||||
encoderDelay = -1
|
||||
encoderPadding = -1
|
||||
subsampleOffsetUs = 9223372036854775807
|
||||
selectionFlags = 0
|
||||
language = null
|
||||
drmInitData = -
|
||||
initializationData:
|
||||
sample count = 75
|
||||
sample 0:
|
||||
time = 37657512133
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 1:
|
||||
time = 37657545511
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6CD
|
||||
sample 2:
|
||||
time = 37657578866
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6DC
|
||||
sample 3:
|
||||
time = 37657612244
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF65B
|
||||
sample 4:
|
||||
time = 37657645600
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6CD
|
||||
sample 5:
|
||||
time = 37657678977
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF67B
|
||||
sample 6:
|
||||
time = 37657712333
|
||||
flags = 1
|
||||
data = length 2, hash 2B5
|
||||
sample 7:
|
||||
time = 37657745711
|
||||
flags = 1
|
||||
data = length 2, hash F5
|
||||
sample 8:
|
||||
time = 37657779066
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF87A
|
||||
sample 9:
|
||||
time = 37657812444
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF698
|
||||
sample 10:
|
||||
time = 37657845800
|
||||
flags = 1
|
||||
data = length 2, hash 1F4
|
||||
sample 11:
|
||||
time = 37657879177
|
||||
flags = 1
|
||||
data = length 2, hash 803
|
||||
sample 12:
|
||||
time = 37657912533
|
||||
flags = 1
|
||||
data = length 2, hash 1F8
|
||||
sample 13:
|
||||
time = 37657945911
|
||||
flags = 1
|
||||
data = length 2, hash 117A
|
||||
sample 14:
|
||||
time = 37657979266
|
||||
flags = 1
|
||||
data = length 2, hash 166
|
||||
sample 15:
|
||||
time = 37658012644
|
||||
flags = 1
|
||||
data = length 2, hash 105A
|
||||
sample 16:
|
||||
time = 37658046000
|
||||
flags = 1
|
||||
data = length 2, hash FCF
|
||||
sample 17:
|
||||
time = 37658079377
|
||||
flags = 1
|
||||
data = length 2, hash 1253
|
||||
sample 18:
|
||||
time = 37658112733
|
||||
flags = 1
|
||||
data = length 2, hash 11DA
|
||||
sample 19:
|
||||
time = 37658146111
|
||||
flags = 1
|
||||
data = length 2, hash 795
|
||||
sample 20:
|
||||
time = 37658179466
|
||||
flags = 1
|
||||
data = length 2, hash 103E
|
||||
sample 21:
|
||||
time = 37658212844
|
||||
flags = 1
|
||||
data = length 2, hash 120F
|
||||
sample 22:
|
||||
time = 37658246200
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF698
|
||||
sample 23:
|
||||
time = 37658279577
|
||||
flags = 1
|
||||
data = length 2, hash 1F4
|
||||
sample 24:
|
||||
time = 37658312933
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF71B
|
||||
sample 25:
|
||||
time = 37658346311
|
||||
flags = 1
|
||||
data = length 2, hash F91
|
||||
sample 26:
|
||||
time = 37658379666
|
||||
flags = 1
|
||||
data = length 2, hash 166
|
||||
sample 27:
|
||||
time = 37658413044
|
||||
flags = 1
|
||||
data = length 2, hash 1023
|
||||
sample 28:
|
||||
time = 37658446400
|
||||
flags = 1
|
||||
data = length 2, hash 117A
|
||||
sample 29:
|
||||
time = 37658479777
|
||||
flags = 1
|
||||
data = length 2, hash 784
|
||||
sample 30:
|
||||
time = 37658513133
|
||||
flags = 1
|
||||
data = length 2, hash 1F8
|
||||
sample 31:
|
||||
time = 37658546511
|
||||
flags = 1
|
||||
data = length 2, hash 10D9
|
||||
sample 32:
|
||||
time = 37658579866
|
||||
flags = 1
|
||||
data = length 2, hash 935
|
||||
sample 33:
|
||||
time = 37658613244
|
||||
flags = 1
|
||||
data = length 2, hash 2B5
|
||||
sample 34:
|
||||
time = 37658646600
|
||||
flags = 1
|
||||
data = length 2, hash F5
|
||||
sample 35:
|
||||
time = 37658679977
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF87A
|
||||
sample 36:
|
||||
time = 37658713333
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF698
|
||||
sample 37:
|
||||
time = 37658746711
|
||||
flags = 1
|
||||
data = length 2, hash 1F4
|
||||
sample 38:
|
||||
time = 37658780066
|
||||
flags = 1
|
||||
data = length 2, hash 793
|
||||
sample 39:
|
||||
time = 37658813444
|
||||
flags = 1
|
||||
data = length 2, hash FF0
|
||||
sample 40:
|
||||
time = 37658846800
|
||||
flags = 1
|
||||
data = length 2, hash 16B
|
||||
sample 41:
|
||||
time = 37658880177
|
||||
flags = 1
|
||||
data = length 2, hash 2C0
|
||||
sample 42:
|
||||
time = 37658913533
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF953
|
||||
sample 43:
|
||||
time = 37658946911
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 44:
|
||||
time = 37658980266
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 45:
|
||||
time = 37659013644
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 46:
|
||||
time = 37659047000
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 47:
|
||||
time = 37659080377
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 48:
|
||||
time = 37659113733
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 49:
|
||||
time = 37659147111
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 50:
|
||||
time = 37659180466
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 51:
|
||||
time = 37659213844
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 52:
|
||||
time = 37659247200
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 53:
|
||||
time = 37659280577
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 54:
|
||||
time = 37659313933
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 55:
|
||||
time = 37659347311
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 56:
|
||||
time = 37659380666
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 57:
|
||||
time = 37659414044
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 58:
|
||||
time = 37659447400
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 59:
|
||||
time = 37659480777
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 60:
|
||||
time = 37659514133
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 61:
|
||||
time = 37659547511
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 62:
|
||||
time = 37659580866
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 63:
|
||||
time = 37659614244
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6CD
|
||||
sample 64:
|
||||
time = 37659647600
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6DC
|
||||
sample 65:
|
||||
time = 37659680977
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF65B
|
||||
sample 66:
|
||||
time = 37659714333
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6CD
|
||||
sample 67:
|
||||
time = 37659747711
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6FF
|
||||
sample 68:
|
||||
time = 37659781066
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6AC
|
||||
sample 69:
|
||||
time = 37659814444
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF5FE
|
||||
sample 70:
|
||||
time = 37659847800
|
||||
flags = 1
|
||||
data = length 2, hash FFFFFEF7
|
||||
sample 71:
|
||||
time = 37659881177
|
||||
flags = 1
|
||||
data = length 2, hash 120C
|
||||
sample 72:
|
||||
time = 37659914533
|
||||
flags = 1
|
||||
data = length 2, hash 1124
|
||||
sample 73:
|
||||
time = 37659947911
|
||||
flags = 1
|
||||
data = length 2, hash 1A9
|
||||
sample 74:
|
||||
time = 37659981266
|
||||
flags = 1
|
||||
data = length 2, hash 935
|
||||
tracksEnded = true
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2.extractor.rawcc;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.test.InstrumentationTestCase;
|
||||
import com.google.android.exoplayer2.extractor.Extractor;
|
||||
import com.google.android.exoplayer2.testutil.TestUtil;
|
||||
|
||||
/**
|
||||
* Tests for {@link RawCcExtractor}.
|
||||
*/
|
||||
@TargetApi(16)
|
||||
public final class RawCcExtractorTest extends InstrumentationTestCase {
|
||||
|
||||
public void testRawCcSample() throws Exception {
|
||||
TestUtil.assertOutput(new TestUtil.ExtractorFactory() {
|
||||
@Override
|
||||
public Extractor create() {
|
||||
return new RawCcExtractor();
|
||||
}
|
||||
}, "rawcc/sample.rawcc", getInstrumentation());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2.extractor.rawcc;
|
||||
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.ParserException;
|
||||
import com.google.android.exoplayer2.extractor.Extractor;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorOutput;
|
||||
import com.google.android.exoplayer2.extractor.PositionHolder;
|
||||
import com.google.android.exoplayer2.extractor.SeekMap;
|
||||
import com.google.android.exoplayer2.extractor.TrackOutput;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Extracts EIA-608 data from a RawCC file
|
||||
*/
|
||||
public final class RawCcExtractor implements Extractor {
|
||||
|
||||
private static final int SCRATCH_SIZE = 9;
|
||||
private static final int HEADER_SIZE = 8;
|
||||
private static final int HEADER_ID = Util.getIntegerCodeForString("RCC\u0001");
|
||||
private static final int TIMESTAMP_SIZE_V0 = 4;
|
||||
private static final int TIMESTAMP_SIZE_V1 = 8;
|
||||
|
||||
// Parser states.
|
||||
private static final int STATE_READING_HEADER = 0;
|
||||
private static final int STATE_READING_TIMESTAMP_AND_COUNT = 1;
|
||||
private static final int STATE_READING_SAMPLES = 2;
|
||||
|
||||
private final ParsableByteArray dataScratch;
|
||||
|
||||
private ExtractorOutput extractorOutput;
|
||||
private TrackOutput trackOutput;
|
||||
|
||||
private int parserState;
|
||||
private int version;
|
||||
private long timestampUs;
|
||||
private int remainingSampleCount;
|
||||
private int sampleBytesWritten;
|
||||
|
||||
public RawCcExtractor() {
|
||||
dataScratch = new ParsableByteArray(SCRATCH_SIZE);
|
||||
parserState = STATE_READING_HEADER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(ExtractorOutput output) {
|
||||
this.extractorOutput = output;
|
||||
extractorOutput.seekMap(new SeekMap.Unseekable(C.UNSET_TIME_US));
|
||||
trackOutput = extractorOutput.track(0);
|
||||
extractorOutput.endTracks();
|
||||
|
||||
trackOutput.format(Format.createTextSampleFormat(null, MimeTypes.APPLICATION_EIA608,
|
||||
null, Format.NO_VALUE, 0, null, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
|
||||
dataScratch.reset();
|
||||
input.peekFully(dataScratch.data, 0, HEADER_SIZE);
|
||||
return dataScratch.readInt() == HEADER_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(ExtractorInput input, PositionHolder seekPosition)
|
||||
throws IOException, InterruptedException {
|
||||
while (true) {
|
||||
switch (parserState) {
|
||||
case STATE_READING_HEADER:
|
||||
parseHeader(input);
|
||||
parserState = STATE_READING_TIMESTAMP_AND_COUNT;
|
||||
break;
|
||||
case STATE_READING_TIMESTAMP_AND_COUNT:
|
||||
if (parseTimestampAndSampleCount(input)) {
|
||||
parserState = STATE_READING_SAMPLES;
|
||||
} else {
|
||||
parserState = STATE_READING_HEADER;
|
||||
return RESULT_END_OF_INPUT;
|
||||
}
|
||||
break;
|
||||
case STATE_READING_SAMPLES:
|
||||
parseSamples(input);
|
||||
parserState = STATE_READING_TIMESTAMP_AND_COUNT;
|
||||
return RESULT_CONTINUE;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seek(long position) {
|
||||
parserState = STATE_READING_HEADER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
private void parseHeader(ExtractorInput input) throws IOException, InterruptedException {
|
||||
dataScratch.reset();
|
||||
input.readFully(dataScratch.data, 0, HEADER_SIZE);
|
||||
if (dataScratch.readInt() != HEADER_ID) {
|
||||
throw new IOException("Input not RawCC");
|
||||
}
|
||||
version = dataScratch.readUnsignedByte();
|
||||
// no versions use the flag fields yet
|
||||
}
|
||||
|
||||
private boolean parseTimestampAndSampleCount(ExtractorInput input) throws IOException,
|
||||
InterruptedException {
|
||||
dataScratch.reset();
|
||||
if (version == 0) {
|
||||
if (!input.readFully(dataScratch.data, 0, TIMESTAMP_SIZE_V0 + 1, true)) {
|
||||
return false;
|
||||
}
|
||||
// version 0 timestamps are 45kHz, so we need to convert them into us
|
||||
timestampUs = dataScratch.readUnsignedInt() * 1000 / 45;
|
||||
} else if (version == 1) {
|
||||
if (!input.readFully(dataScratch.data, 0, TIMESTAMP_SIZE_V1 + 1, true)) {
|
||||
return false;
|
||||
}
|
||||
timestampUs = dataScratch.readLong();
|
||||
} else {
|
||||
throw new ParserException("Unsupported version number: " + version);
|
||||
}
|
||||
|
||||
remainingSampleCount = dataScratch.readUnsignedByte();
|
||||
sampleBytesWritten = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void parseSamples(ExtractorInput input) throws IOException, InterruptedException {
|
||||
for (; remainingSampleCount > 0; remainingSampleCount--) {
|
||||
dataScratch.reset();
|
||||
input.readFully(dataScratch.data, 0, 3);
|
||||
|
||||
// only accept EIA-608 packets which have validity (6th bit) == 1 and
|
||||
// type (7-8th bits) == 0; i.e. ccDataPkt[0] == 0bXXXXX100
|
||||
int ccValidityAndType = dataScratch.readUnsignedByte() & 0x07;
|
||||
if (ccValidityAndType == 0x04) {
|
||||
trackOutput.sampleData(dataScratch, 2);
|
||||
sampleBytesWritten += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (sampleBytesWritten > 0) {
|
||||
trackOutput.sampleMetadata(timestampUs, C.BUFFER_FLAG_KEY_FRAME, sampleBytesWritten, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -50,10 +50,12 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput
|
||||
private final Extractor extractor;
|
||||
private final Format manifestFormat;
|
||||
private final boolean preferManifestDrmInitData;
|
||||
private final boolean resendFormatOnInit;
|
||||
|
||||
private boolean extractorInitialized;
|
||||
private SingleTrackMetadataOutput metadataOutput;
|
||||
private TrackOutput trackOutput;
|
||||
private Format sentFormat;
|
||||
|
||||
// Accessed only on the loader thread.
|
||||
private boolean seenTrack;
|
||||
@ -67,9 +69,24 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput
|
||||
*/
|
||||
public ChunkExtractorWrapper(Extractor extractor, Format manifestFormat,
|
||||
boolean preferManifestDrmInitData) {
|
||||
this(extractor, manifestFormat, preferManifestDrmInitData, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param extractor The extractor to wrap.
|
||||
* @param manifestFormat A manifest defined {@link Format} whose data should be merged into any
|
||||
* sample {@link Format} output from the {@link Extractor}.
|
||||
* @param preferManifestDrmInitData Whether {@link DrmInitData} defined in {@code manifestFormat}
|
||||
* should be preferred when the sample and manifest {@link Format}s are merged.
|
||||
* @param resendFormatOnInit Whether the extractor should resend the previous {@link Format} when
|
||||
* it is initialized via {@link #init(SingleTrackMetadataOutput, TrackOutput)}.
|
||||
*/
|
||||
public ChunkExtractorWrapper(Extractor extractor, Format manifestFormat,
|
||||
boolean preferManifestDrmInitData, boolean resendFormatOnInit) {
|
||||
this.extractor = extractor;
|
||||
this.manifestFormat = manifestFormat;
|
||||
this.preferManifestDrmInitData = preferManifestDrmInitData;
|
||||
this.resendFormatOnInit = resendFormatOnInit;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -87,6 +104,9 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput
|
||||
extractorInitialized = true;
|
||||
} else {
|
||||
extractor.seek(0);
|
||||
if (resendFormatOnInit && sentFormat != null) {
|
||||
trackOutput.format(sentFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,8 +147,8 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput
|
||||
|
||||
@Override
|
||||
public void format(Format format) {
|
||||
trackOutput.format(format.copyWithManifestFormatInfo(manifestFormat,
|
||||
preferManifestDrmInitData));
|
||||
sentFormat = format.copyWithManifestFormatInfo(manifestFormat, preferManifestDrmInitData);
|
||||
trackOutput.format(sentFormat);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -15,12 +15,15 @@
|
||||
*/
|
||||
package com.google.android.exoplayer2.source.dash;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.extractor.ChunkIndex;
|
||||
import com.google.android.exoplayer2.extractor.Extractor;
|
||||
import com.google.android.exoplayer2.extractor.SeekMap;
|
||||
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
|
||||
import com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor;
|
||||
import com.google.android.exoplayer2.extractor.rawcc.RawCcExtractor;
|
||||
import com.google.android.exoplayer2.source.BehindLiveWindowException;
|
||||
import com.google.android.exoplayer2.source.chunk.Chunk;
|
||||
import com.google.android.exoplayer2.source.chunk.ChunkExtractorWrapper;
|
||||
@ -41,9 +44,6 @@ import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidResponseCode
|
||||
import com.google.android.exoplayer2.upstream.Loader;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
||||
import android.os.SystemClock;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
@ -384,12 +384,25 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||
this.periodDurationUs = periodDurationUs;
|
||||
this.representation = representation;
|
||||
String containerMimeType = representation.format.containerMimeType;
|
||||
// Prefer drmInitData obtained from the manifest over drmInitData obtained from the stream,
|
||||
// as per DASH IF Interoperability Recommendations V3.0, 7.5.3.
|
||||
extractorWrapper = mimeTypeIsRawText(containerMimeType) ? null : new ChunkExtractorWrapper(
|
||||
mimeTypeIsWebm(containerMimeType) ? new MatroskaExtractor()
|
||||
: new FragmentedMp4Extractor(),
|
||||
representation.format, true /* preferManifestDrmInitData */);
|
||||
if (mimeTypeIsRawText(containerMimeType)) {
|
||||
extractorWrapper = null;
|
||||
} else {
|
||||
boolean resendFormatOnInit = false;
|
||||
Extractor extractor;
|
||||
if (MimeTypes.APPLICATION_RAWCC.equals(containerMimeType)) {
|
||||
extractor = new RawCcExtractor();
|
||||
resendFormatOnInit = true;
|
||||
} else if (mimeTypeIsWebm(containerMimeType)) {
|
||||
extractor = new MatroskaExtractor();
|
||||
} else {
|
||||
extractor = new FragmentedMp4Extractor();
|
||||
}
|
||||
// Prefer drmInitData obtained from the manifest over drmInitData obtained from the stream,
|
||||
// as per DASH IF Interoperability Recommendations V3.0, 7.5.3.
|
||||
extractorWrapper = new ChunkExtractorWrapper(extractor,
|
||||
representation.format, true /* preferManifestDrmInitData */,
|
||||
resendFormatOnInit);
|
||||
}
|
||||
segmentIndex = representation.getIndex();
|
||||
}
|
||||
|
||||
|
@ -299,7 +299,8 @@ public class DashManifestParser extends DefaultHandler
|
||||
return C.TRACK_TYPE_VIDEO;
|
||||
} else if (MimeTypes.isAudio(sampleMimeType)) {
|
||||
return C.TRACK_TYPE_AUDIO;
|
||||
} else if (mimeTypeIsRawText(sampleMimeType)) {
|
||||
} else if (mimeTypeIsRawText(sampleMimeType)
|
||||
|| MimeTypes.APPLICATION_RAWCC.equals(format.containerMimeType)) {
|
||||
return C.TRACK_TYPE_TEXT;
|
||||
}
|
||||
return C.TRACK_TYPE_UNKNOWN;
|
||||
@ -650,6 +651,12 @@ public class DashManifestParser extends DefaultHandler
|
||||
return MimeTypes.getAudioMediaMimeType(codecs);
|
||||
} else if (MimeTypes.isVideo(containerMimeType)) {
|
||||
return MimeTypes.getVideoMediaMimeType(codecs);
|
||||
} else if (MimeTypes.APPLICATION_RAWCC.equals(containerMimeType)) {
|
||||
// We currently only support EIA-608 through RawCC
|
||||
if (codecs != null && codecs.contains("eia608")) {
|
||||
return MimeTypes.APPLICATION_EIA608;
|
||||
}
|
||||
return null;
|
||||
} else if (mimeTypeIsRawText(containerMimeType)) {
|
||||
return containerMimeType;
|
||||
} else if (MimeTypes.APPLICATION_MP4.equals(containerMimeType)) {
|
||||
|
@ -66,6 +66,7 @@ public final class MimeTypes {
|
||||
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_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