From dec40bcbd36e84a35367160a008818a9402ac04f Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Wed, 1 Oct 2014 22:14:44 +0100 Subject: [PATCH] Add file missing from "Improve subtitle handling" change. --- .../exoplayer/text/SubtitleParserHelper.java | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 library/src/main/java/com/google/android/exoplayer/text/SubtitleParserHelper.java diff --git a/library/src/main/java/com/google/android/exoplayer/text/SubtitleParserHelper.java b/library/src/main/java/com/google/android/exoplayer/text/SubtitleParserHelper.java new file mode 100644 index 0000000000..cafdb89f25 --- /dev/null +++ b/library/src/main/java/com/google/android/exoplayer/text/SubtitleParserHelper.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2014 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.exoplayer.text; + +import com.google.android.exoplayer.SampleHolder; +import com.google.android.exoplayer.util.Assertions; + +import android.media.MediaCodec; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Wraps a {@link SubtitleParser}, exposing an interface similar to {@link MediaCodec} for + * asynchronous parsing of subtitles. + */ +public class SubtitleParserHelper implements Handler.Callback { + + private final SubtitleParser parser; + + private final Handler handler; + private SampleHolder sampleHolder; + private boolean parsing; + private Subtitle result; + private IOException error; + + /** + * @param looper The {@link Looper} associated with the thread on which parsing should occur. + * @param parser The parser that should be used to parse the raw data. + */ + public SubtitleParserHelper(Looper looper, SubtitleParser parser) { + this.handler = new Handler(looper, this); + this.parser = parser; + flush(); + } + + /** + * Flushes the helper, canceling the current parsing operation, if there is one. + */ + public synchronized void flush() { + sampleHolder = new SampleHolder(true); + parsing = false; + result = null; + error = null; + } + + /** + * Whether the helper is currently performing a parsing operation. + * + * @return True if the helper is currently performing a parsing operation. False otherwise. + */ + public synchronized boolean isParsing() { + return parsing; + } + + /** + * Gets the holder that should be populated with data to be parsed. + *

+ * The returned holder will remain valid unless {@link #flush()} is called. If {@link #flush()} + * is called the holder is replaced, and this method should be called again to obtain the new + * holder. + * + * @return The holder that should be populated with data to be parsed. + */ + public synchronized SampleHolder getSampleHolder() { + return sampleHolder; + } + + /** + * Start a parsing operation. + *

+ * The holder returned by {@link #getSampleHolder()} should be populated with the data to be + * parsed prior to calling this method. + */ + public synchronized void startParseOperation() { + Assertions.checkState(!parsing); + parsing = true; + result = null; + error = null; + handler.obtainMessage(0, sampleHolder).sendToTarget(); + } + + /** + * Gets the result of the most recent parsing operation. + *

+ * The result is cleared as a result of calling this method, and so subsequent calls will return + * null until a subsequent parsing operation has finished. + * + * @return The result of the parsing operation, or null. + * @throws IOException If the parsing operation failed. + */ + public synchronized Subtitle getAndClearResult() throws IOException { + try { + if (error != null) { + throw error; + } + return result; + } finally { + error = null; + result = null; + } + } + + @Override + public boolean handleMessage(Message msg) { + Subtitle result; + IOException error; + SampleHolder holder = (SampleHolder) msg.obj; + try { + InputStream inputStream = new ByteArrayInputStream(holder.data.array(), 0, holder.size); + result = parser.parse(inputStream, null, sampleHolder.timeUs); + error = null; + } catch (IOException e) { + result = null; + error = e; + } + synchronized (this) { + if (sampleHolder != holder) { + // A flush has occurred since this holder was posted. Do nothing. + } else { + holder.data.position(0); + this.result = result; + this.error = error; + this.parsing = false; + } + } + return true; + } + +}