summaryrefslogtreecommitdiffstats
path: root/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java')
-rw-r--r--mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java114
1 files changed, 114 insertions, 0 deletions
diff --git a/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java
new file mode 100644
index 0000000000..da53a47dc0
--- /dev/null
+++ b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java
@@ -0,0 +1,114 @@
+/*
+ * 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 org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.ogg;
+
+import org.mozilla.thirdparty.com.google.android.exoplayer2.C;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.ParserException;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.Extractor;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.ExtractorInput;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.ExtractorOutput;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.ExtractorsFactory;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.PositionHolder;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.TrackOutput;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.ParsableByteArray;
+import java.io.IOException;
+
+/**
+ * Extracts data from the Ogg container format.
+ */
+public class OggExtractor implements Extractor {
+
+ /** Factory for {@link OggExtractor} instances. */
+ public static final ExtractorsFactory FACTORY = () -> new Extractor[] {new OggExtractor()};
+
+ private static final int MAX_VERIFICATION_BYTES = 8;
+
+ private ExtractorOutput output;
+ private StreamReader streamReader;
+ private boolean streamReaderInitialized;
+
+ @Override
+ public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
+ try {
+ return sniffInternal(input);
+ } catch (ParserException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public void init(ExtractorOutput output) {
+ this.output = output;
+ }
+
+ @Override
+ public void seek(long position, long timeUs) {
+ if (streamReader != null) {
+ streamReader.seek(position, timeUs);
+ }
+ }
+
+ @Override
+ public void release() {
+ // Do nothing
+ }
+
+ @Override
+ public int read(ExtractorInput input, PositionHolder seekPosition)
+ throws IOException, InterruptedException {
+ if (streamReader == null) {
+ if (!sniffInternal(input)) {
+ throw new ParserException("Failed to determine bitstream type");
+ }
+ input.resetPeekPosition();
+ }
+ if (!streamReaderInitialized) {
+ TrackOutput trackOutput = output.track(0, C.TRACK_TYPE_AUDIO);
+ output.endTracks();
+ streamReader.init(output, trackOutput);
+ streamReaderInitialized = true;
+ }
+ return streamReader.read(input, seekPosition);
+ }
+
+ private boolean sniffInternal(ExtractorInput input) throws IOException, InterruptedException {
+ OggPageHeader header = new OggPageHeader();
+ if (!header.populate(input, true) || (header.type & 0x02) != 0x02) {
+ return false;
+ }
+
+ int length = Math.min(header.bodySize, MAX_VERIFICATION_BYTES);
+ ParsableByteArray scratch = new ParsableByteArray(length);
+ input.peekFully(scratch.data, 0, length);
+
+ if (FlacReader.verifyBitstreamType(resetPosition(scratch))) {
+ streamReader = new FlacReader();
+ } else if (VorbisReader.verifyBitstreamType(resetPosition(scratch))) {
+ streamReader = new VorbisReader();
+ } else if (OpusReader.verifyBitstreamType(resetPosition(scratch))) {
+ streamReader = new OpusReader();
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ private static ParsableByteArray resetPosition(ParsableByteArray scratch) {
+ scratch.setPosition(0);
+ return scratch;
+ }
+
+}