From 7bc1241e06ee06d6f693d4ec69bc9f6f6fbff167 Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Tue, 21 Jul 2015 09:59:22 +0100 Subject: [PATCH] Reflect subtitle parsers. --- .../exoplayer/text/TextTrackRenderer.java | 79 +++++++++++++++++-- 1 file changed, 74 insertions(+), 5 deletions(-) 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: + * + *

+ * + *

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(); }