diff --git a/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java
index ef0195d6e3..9544dd8910 100644
--- a/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java
+++ b/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java
@@ -31,18 +31,77 @@ import android.os.Looper;
import android.os.Message;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
- * A {@link TrackRenderer} for textual subtitles. The actual rendering of each line of text to a
- * suitable output (e.g. the display) is delegated to a {@link TextRenderer}.
+ * A {@link TrackRenderer} for subtitles. Text is parsed from sample data using a
+ * {@link SubtitleParser}. The actual rendering of each line of text is delegated to a
+ * {@link TextRenderer}.
+ *
+ * If no {@link SubtitleParser} instances are passed to the constructor, the subtitle type will be
+ * detected automatically for the following supported formats:
+ *
+ *
+ * - WebVTT ({@link com.google.android.exoplayer.text.webvtt.WebvttParser})
+ * - TTML
+ * ({@link com.google.android.exoplayer.text.ttml.TtmlParser})
+ * - SubRip
+ * ({@link com.google.android.exoplayer.text.subrip.SubripParser})
+ * - TX3G
+ * ({@link com.google.android.exoplayer.text.tx3g.Tx3gParser})
+ *
+ *
+ * To override the default parsers, pass one or more {@link SubtitleParser} instances to the
+ * constructor. The first {@link SubtitleParser} that returns {@code true} from
+ * {@link SubtitleParser#canParse(String)} will be used.
*/
@TargetApi(16)
public class TextTrackRenderer extends TrackRenderer implements Callback {
private static final int MSG_UPDATE_OVERLAY = 0;
+ /**
+ * Default parser classes in priority order. They are referred to indirectly so that it is
+ * possible to remove unused parsers.
+ */
+ private static final List> DEFAULT_PARSER_CLASSES;
+ static {
+ DEFAULT_PARSER_CLASSES = new ArrayList<>();
+ // Load parsers using reflection so that they can be deleted cleanly.
+ // Class.forName() appears for each parser so that automated tools like proguard
+ // can detect the use of reflection (see http://proguard.sourceforge.net/FAQ.html#forname).
+ try {
+ DEFAULT_PARSER_CLASSES.add(
+ Class.forName("com.google.android.exoplayer.text.webvtt.WebvttParser")
+ .asSubclass(SubtitleParser.class));
+ } catch (ClassNotFoundException e) {
+ // Parser not found.
+ }
+ try {
+ DEFAULT_PARSER_CLASSES.add(
+ Class.forName("com.google.android.exoplayer.text.ttml.TtmlParser")
+ .asSubclass(SubtitleParser.class));
+ } catch (ClassNotFoundException e) {
+ // Parser not found.
+ }
+ try {
+ DEFAULT_PARSER_CLASSES.add(
+ Class.forName("com.google.android.exoplayer.text.subrip.SubripParser")
+ .asSubclass(SubtitleParser.class));
+ } catch (ClassNotFoundException e) {
+ // Parser not found.
+ }
+ try {
+ DEFAULT_PARSER_CLASSES.add(
+ Class.forName("com.google.android.exoplayer.text.tx3g.Tx3gParser")
+ .asSubclass(SubtitleParser.class));
+ } catch (ClassNotFoundException e) {
+ // Parser not found.
+ }
+ }
+
private final Handler textRendererHandler;
private final TextRenderer textRenderer;
private final SampleSourceReader source;
@@ -68,8 +127,8 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
* normally be the looper associated with the applications' main thread, which can be
* obtained using {@link android.app.Activity#getMainLooper()}. Null may be passed if the
* renderer should be invoked directly on the player's internal rendering thread.
- * @param subtitleParsers An array of available subtitle parsers. Where multiple parsers are able
- * to render a subtitle, the one with the lowest index will be preferred.
+ * @param subtitleParsers {@link SubtitleParser}s to parse text samples, in order of decreasing
+ * priority. If omitted, the default parsers will be used.
*/
public TextTrackRenderer(SampleSource source, TextRenderer textRenderer,
Looper textRendererLooper, SubtitleParser... subtitleParsers) {
@@ -77,7 +136,17 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
this.textRenderer = Assertions.checkNotNull(textRenderer);
this.textRendererHandler = textRendererLooper == null ? null
: new Handler(textRendererLooper, this);
- this.subtitleParsers = Assertions.checkNotNull(subtitleParsers);
+ if (subtitleParsers == null || subtitleParsers.length == 0) {
+ subtitleParsers = new SubtitleParser[DEFAULT_PARSER_CLASSES.size()];
+ for (int i = 0; i < subtitleParsers.length; i++) {
+ try {
+ subtitleParsers[i] = DEFAULT_PARSER_CLASSES.get(i).newInstance();
+ } catch (ReflectiveOperationException e) {
+ throw new IllegalStateException("Unexpected error creating default parser", e);
+ }
+ }
+ }
+ this.subtitleParsers = subtitleParsers;
formatHolder = new MediaFormatHolder();
}