Remove ExoPlayer's RawCcExtractor
RawCC is a Google-internal subtitle format, and is no longer used with ExoPlayer. PiperOrigin-RevId: 446950691
This commit is contained in:
parent
e9919f6da1
commit
4f616d6003
@ -25,14 +25,16 @@
|
||||
* Audio:
|
||||
* Use LG AC3 audio decoder advertising non-standard MIME type.
|
||||
* Ad playback / IMA:
|
||||
* Decrease ad polling rate from every 100ms to every 200ms, to line up with
|
||||
Media Rating Council (MRC) recommendations.
|
||||
* Decrease ad polling rate from every 100ms to every 200ms, to line up
|
||||
with Media Rating Council (MRC) recommendations.
|
||||
* Text:
|
||||
* SSA: Support `OutlineColour` style setting when `BorderStyle == 3` (i.e.
|
||||
`OutlineColour` sets the background of the cue)
|
||||
([#8435](https://github.com/google/ExoPlayer/issues/8435)).
|
||||
* CEA-708: Parse data into multiple service blocks and ignore blocks not
|
||||
associated with the currently selected service number.
|
||||
* Remove `RawCcExtractor`, which was only used to handle a Google-internal
|
||||
subtitle format.
|
||||
* Extractors:
|
||||
* Matroska: Parse `DiscardPadding` for Opus tracks.
|
||||
* Parse bitrates from `esds` boxes.
|
||||
@ -60,16 +62,16 @@
|
||||
re-enables audio passthrough for DTS streams
|
||||
([#10159](https://github.com/google/ExoPlayer/issues/10159)).
|
||||
* HLS:
|
||||
* Fallback to chunkful preparation if the playlist CODECS attribute
|
||||
does not contain the audio codec
|
||||
* Fallback to chunkful preparation if the playlist CODECS attribute does
|
||||
not contain the audio codec
|
||||
([#10065](https://github.com/google/ExoPlayer/issues/10065)).
|
||||
* RTSP:
|
||||
* Add RTP reader for MPEG4
|
||||
([#35](https://github.com/androidx/media/pull/35)).
|
||||
* Add RTP reader for HEVC
|
||||
([#36](https://github.com/androidx/media/pull/36)).
|
||||
* Add RTP reader for AMR. Currently only mono-channel, non-interleaved
|
||||
AMR streams are supported. Compound AMR RTP payload is not supported.
|
||||
* Add RTP reader for AMR. Currently only mono-channel, non-interleaved AMR
|
||||
streams are supported. Compound AMR RTP payload is not supported.
|
||||
([#46](https://github.com/androidx/media/pull/46))
|
||||
* Add RTP reader for VP8
|
||||
([#47](https://github.com/androidx/media/pull/47)).
|
||||
@ -82,15 +84,19 @@
|
||||
* Throw checked exception when parsing RTSP timing
|
||||
([#10165](https://github.com/google/ExoPlayer/issues/10165)).
|
||||
* Session:
|
||||
|
||||
* Fix NPE in MediaControllerImplLegacy
|
||||
([#59](https://github.com/androidx/media/pull/59))
|
||||
* Update session position info on timeline
|
||||
change([#51](https://github.com/androidx/media/issues/51))
|
||||
|
||||
* Data sources:
|
||||
|
||||
* Rename `DummyDataSource` to `PlaceHolderDataSource`.
|
||||
* Workaround OkHttp interrupt handling.
|
||||
|
||||
* Remove deprecated symbols:
|
||||
|
||||
* Remove `Player.Listener.onTracksChanged`. Use
|
||||
`Player.Listener.onTracksInfoChanged` instead.
|
||||
* Remove `Player.getCurrentTrackGroups` and
|
||||
|
@ -36,7 +36,6 @@ import androidx.media3.extractor.SeekMap;
|
||||
import androidx.media3.extractor.TrackOutput;
|
||||
import androidx.media3.extractor.mkv.MatroskaExtractor;
|
||||
import androidx.media3.extractor.mp4.FragmentedMp4Extractor;
|
||||
import androidx.media3.extractor.rawcc.RawCcExtractor;
|
||||
import java.io.IOException;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
@ -58,13 +57,8 @@ public final class BundledChunkExtractor implements ExtractorOutput, ChunkExtrac
|
||||
@Nullable String containerMimeType = format.containerMimeType;
|
||||
Extractor extractor;
|
||||
if (MimeTypes.isText(containerMimeType)) {
|
||||
if (MimeTypes.APPLICATION_RAWCC.equals(containerMimeType)) {
|
||||
// RawCC is special because it's a text specific container format.
|
||||
extractor = new RawCcExtractor(format);
|
||||
} else {
|
||||
// All other text types are raw formats that do not need an extractor.
|
||||
return null;
|
||||
}
|
||||
// Text types do not need an extractor.
|
||||
return null;
|
||||
} else if (MimeTypes.isMatroska(containerMimeType)) {
|
||||
extractor = new MatroskaExtractor(MatroskaExtractor.FLAG_DISABLE_SEEK_FOR_CUES);
|
||||
} else {
|
||||
|
@ -1675,11 +1675,7 @@ public class DashManifestParser extends DefaultHandler
|
||||
} else if (MimeTypes.isVideo(containerMimeType)) {
|
||||
return MimeTypes.getVideoMediaMimeType(codecs);
|
||||
} else if (MimeTypes.isText(containerMimeType)) {
|
||||
if (MimeTypes.APPLICATION_RAWCC.equals(containerMimeType)) {
|
||||
// RawCC is special because it's a text specific container format.
|
||||
return MimeTypes.getTextMediaMimeType(codecs);
|
||||
}
|
||||
// All other text types are raw formats.
|
||||
// Text types are raw formats.
|
||||
return containerMimeType;
|
||||
} else if (MimeTypes.isImage(containerMimeType)) {
|
||||
// Image types are raw formats.
|
||||
|
@ -274,14 +274,6 @@ public class DashManifestParserTest {
|
||||
List<AdaptationSet> adaptationSets = manifest.getPeriod(0).adaptationSets;
|
||||
|
||||
Format format = adaptationSets.get(0).representations.get(0).format;
|
||||
assertThat(format.containerMimeType).isEqualTo(MimeTypes.APPLICATION_RAWCC);
|
||||
assertThat(format.sampleMimeType).isEqualTo(MimeTypes.APPLICATION_CEA608);
|
||||
assertThat(format.codecs).isEqualTo("cea608");
|
||||
assertThat(format.roleFlags).isEqualTo(C.ROLE_FLAG_SUBTITLE | C.ROLE_FLAG_MAIN);
|
||||
assertThat(format.selectionFlags).isEqualTo(0);
|
||||
assertThat(adaptationSets.get(0).type).isEqualTo(C.TRACK_TYPE_TEXT);
|
||||
|
||||
format = adaptationSets.get(1).representations.get(0).format;
|
||||
assertThat(format.containerMimeType).isEqualTo(MimeTypes.APPLICATION_MP4);
|
||||
assertThat(format.sampleMimeType).isEqualTo(MimeTypes.APPLICATION_TTML);
|
||||
assertThat(format.codecs).isEqualTo("stpp.ttml.im1t");
|
||||
@ -291,11 +283,11 @@ public class DashManifestParserTest {
|
||||
|
||||
// Ensure that forced-subtitle and forced_subtitle are both parsed as a 'forced' text track.
|
||||
// https://github.com/google/ExoPlayer/issues/9727
|
||||
format = adaptationSets.get(2).representations.get(0).format;
|
||||
format = adaptationSets.get(1).representations.get(0).format;
|
||||
assertThat(format.roleFlags).isEqualTo(C.ROLE_FLAG_SUBTITLE);
|
||||
assertThat(format.selectionFlags).isEqualTo(C.SELECTION_FLAG_FORCED);
|
||||
|
||||
format = adaptationSets.get(3).representations.get(0).format;
|
||||
format = adaptationSets.get(2).representations.get(0).format;
|
||||
assertThat(format.containerMimeType).isEqualTo(MimeTypes.APPLICATION_TTML);
|
||||
assertThat(format.sampleMimeType).isEqualTo(MimeTypes.APPLICATION_TTML);
|
||||
assertThat(format.codecs).isNull();
|
||||
@ -627,11 +619,10 @@ public class DashManifestParserTest {
|
||||
|
||||
assertThat(manifest.getPeriodCount()).isEqualTo(1);
|
||||
List<AdaptationSet> adaptationSets = manifest.getPeriod(0).adaptationSets;
|
||||
assertThat(adaptationSets).hasSize(4);
|
||||
assertThat(adaptationSets).hasSize(3);
|
||||
assertThat(getAvailabilityTimeOffsetUs(adaptationSets.get(0))).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(getAvailabilityTimeOffsetUs(adaptationSets.get(1))).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(getAvailabilityTimeOffsetUs(adaptationSets.get(2))).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(getAvailabilityTimeOffsetUs(adaptationSets.get(3))).isEqualTo(C.TIME_UNSET);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1,172 +0,0 @@
|
||||
/*
|
||||
* 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 androidx.media3.extractor.rawcc;
|
||||
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.ParserException;
|
||||
import androidx.media3.common.util.Assertions;
|
||||
import androidx.media3.common.util.ParsableByteArray;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.extractor.Extractor;
|
||||
import androidx.media3.extractor.ExtractorInput;
|
||||
import androidx.media3.extractor.ExtractorOutput;
|
||||
import androidx.media3.extractor.PositionHolder;
|
||||
import androidx.media3.extractor.SeekMap;
|
||||
import androidx.media3.extractor.TrackOutput;
|
||||
import java.io.IOException;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
|
||||
/** Extracts data from the RawCC container format. */
|
||||
@UnstableApi
|
||||
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 = 0x52434301;
|
||||
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 Format format;
|
||||
private final ParsableByteArray dataScratch;
|
||||
|
||||
private @MonotonicNonNull TrackOutput trackOutput;
|
||||
private int parserState;
|
||||
private int version;
|
||||
private long timestampUs;
|
||||
private int remainingSampleCount;
|
||||
private int sampleBytesWritten;
|
||||
|
||||
public RawCcExtractor(Format format) {
|
||||
this.format = format;
|
||||
dataScratch = new ParsableByteArray(SCRATCH_SIZE);
|
||||
parserState = STATE_READING_HEADER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(ExtractorOutput output) {
|
||||
output.seekMap(new SeekMap.Unseekable(C.TIME_UNSET));
|
||||
trackOutput = output.track(0, C.TRACK_TYPE_TEXT);
|
||||
trackOutput.format(format);
|
||||
output.endTracks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sniff(ExtractorInput input) throws IOException {
|
||||
dataScratch.reset(/* limit= */ HEADER_SIZE);
|
||||
input.peekFully(dataScratch.getData(), 0, HEADER_SIZE);
|
||||
return dataScratch.readInt() == HEADER_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
|
||||
Assertions.checkStateNotNull(trackOutput); // Asserts that init has been called.
|
||||
while (true) {
|
||||
switch (parserState) {
|
||||
case STATE_READING_HEADER:
|
||||
if (parseHeader(input)) {
|
||||
parserState = STATE_READING_TIMESTAMP_AND_COUNT;
|
||||
} else {
|
||||
return RESULT_END_OF_INPUT;
|
||||
}
|
||||
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, long timeUs) {
|
||||
parserState = STATE_READING_HEADER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
private boolean parseHeader(ExtractorInput input) throws IOException {
|
||||
dataScratch.reset(/* limit= */ HEADER_SIZE);
|
||||
if (input.readFully(dataScratch.getData(), 0, HEADER_SIZE, true)) {
|
||||
if (dataScratch.readInt() != HEADER_ID) {
|
||||
throw new IOException("Input not RawCC");
|
||||
}
|
||||
version = dataScratch.readUnsignedByte();
|
||||
// no versions use the flag fields yet
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean parseTimestampAndSampleCount(ExtractorInput input) throws IOException {
|
||||
if (version == 0) {
|
||||
dataScratch.reset(/* limit= */ TIMESTAMP_SIZE_V0 + 1);
|
||||
if (!input.readFully(dataScratch.getData(), 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) {
|
||||
dataScratch.reset(/* limit= */ TIMESTAMP_SIZE_V1 + 1);
|
||||
if (!input.readFully(dataScratch.getData(), 0, TIMESTAMP_SIZE_V1 + 1, true)) {
|
||||
return false;
|
||||
}
|
||||
timestampUs = dataScratch.readLong();
|
||||
} else {
|
||||
throw ParserException.createForMalformedContainer(
|
||||
"Unsupported version number: " + version, /* cause= */ null);
|
||||
}
|
||||
|
||||
remainingSampleCount = dataScratch.readUnsignedByte();
|
||||
sampleBytesWritten = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@RequiresNonNull("trackOutput")
|
||||
private void parseSamples(ExtractorInput input) throws IOException {
|
||||
for (; remainingSampleCount > 0; remainingSampleCount--) {
|
||||
dataScratch.reset(/* limit= */ 3);
|
||||
input.readFully(dataScratch.getData(), 0, 3);
|
||||
|
||||
trackOutput.sampleData(dataScratch, 3);
|
||||
sampleBytesWritten += 3;
|
||||
}
|
||||
|
||||
if (sampleBytesWritten > 0) {
|
||||
trackOutput.sampleMetadata(timestampUs, C.BUFFER_FLAG_KEY_FRAME, sampleBytesWritten, 0, null);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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 androidx.media3.extractor.rawcc;
|
||||
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.MimeTypes;
|
||||
import androidx.media3.test.utils.ExtractorAsserts;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.ParameterizedRobolectricTestRunner;
|
||||
|
||||
/** Tests for {@link RawCcExtractor}. */
|
||||
@RunWith(ParameterizedRobolectricTestRunner.class)
|
||||
public final class RawCcExtractorTest {
|
||||
|
||||
@ParameterizedRobolectricTestRunner.Parameters(name = "{0}")
|
||||
public static ImmutableList<ExtractorAsserts.SimulationConfig> params() {
|
||||
return ExtractorAsserts.configs();
|
||||
}
|
||||
|
||||
@ParameterizedRobolectricTestRunner.Parameter(0)
|
||||
public ExtractorAsserts.SimulationConfig simulationConfig;
|
||||
|
||||
@Test
|
||||
public void rawCcSample() throws Exception {
|
||||
Format format =
|
||||
new Format.Builder()
|
||||
.setSampleMimeType(MimeTypes.APPLICATION_CEA608)
|
||||
.setCodecs("cea608")
|
||||
.setAccessibilityChannel(1)
|
||||
.build();
|
||||
ExtractorAsserts.assertBehavior(
|
||||
() -> new RawCcExtractor(format), "media/rawcc/sample.rawcc", simulationConfig);
|
||||
}
|
||||
}
|
@ -6,13 +6,6 @@
|
||||
<S d="1000"/>
|
||||
</SegmentTimeline>
|
||||
</SegmentTemplate>
|
||||
<AdaptationSet id="0" mimeType="application/x-rawcc" subsegmentAlignment="true">
|
||||
<Role schemeIdUri="urn:mpeg:DASH:role:2011" value="subtitle"/>
|
||||
<Role schemeIdUri="urn:mpeg:DASH:role:2011" value="main"/>
|
||||
<Representation id="0" codecs="cea608" bandwidth="16">
|
||||
<BaseURL>https://test.com/0</BaseURL>
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet id="0" mimeType="application/mp4" subsegmentAlignment="true">
|
||||
<Role schemeIdUri="urn:mpeg:DASH:role:2011" value="forced-subtitle"/>
|
||||
<Representation id="0" codecs="stpp.ttml.im1t" bandwidth="16">
|
||||
|
Loading…
x
Reference in New Issue
Block a user