Make ExtractorSampleSource amenable to proguarding.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=122085277
This commit is contained in:
olly 2016-05-11 13:12:41 -07:00 committed by Oliver Woodman
parent 356288a018
commit f9f95d638b
5 changed files with 137 additions and 115 deletions

View File

@ -283,8 +283,8 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
case Util.TYPE_OTHER: case Util.TYPE_OTHER:
Allocator allocator = new DefaultAllocator(C.DEFAULT_BUFFER_SEGMENT_SIZE); Allocator allocator = new DefaultAllocator(C.DEFAULT_BUFFER_SEGMENT_SIZE);
DataSource dataSource = dataSourceFactory.createDataSource(player.getBandwidthMeter()); DataSource dataSource = dataSourceFactory.createDataSource(player.getBandwidthMeter());
return new ExtractorSampleSource(uri, dataSource, allocator, return new ExtractorSampleSource(uri, dataSource, allocator, C.DEFAULT_MUXED_BUFFER_SIZE,
C.DEFAULT_MUXED_BUFFER_SIZE, player.getMainHandler(), player, 0); player.getMainHandler(), player, 0, ExtractorSampleSource.newDefaultExtractors());
default: default:
throw new IllegalStateException("Unsupported type: " + type); throw new IllegalStateException("Unsupported type: " + type);
} }

View File

@ -19,6 +19,7 @@ import com.google.android.exoplayer.DefaultTrackSelector;
import com.google.android.exoplayer.ExoPlaybackException; import com.google.android.exoplayer.ExoPlaybackException;
import com.google.android.exoplayer.ExoPlayer; import com.google.android.exoplayer.ExoPlayer;
import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.TrackRenderer;
import com.google.android.exoplayer.extractor.Extractor;
import com.google.android.exoplayer.extractor.ExtractorSampleSource; import com.google.android.exoplayer.extractor.ExtractorSampleSource;
import com.google.android.exoplayer.extractor.mkv.MatroskaExtractor; import com.google.android.exoplayer.extractor.mkv.MatroskaExtractor;
import com.google.android.exoplayer.upstream.DefaultAllocator; import com.google.android.exoplayer.upstream.DefaultAllocator;
@ -83,7 +84,7 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
new DefaultDataSource(context, null, Util.getUserAgent(context, "ExoPlayerExtFlacTest"), new DefaultDataSource(context, null, Util.getUserAgent(context, "ExoPlayerExtFlacTest"),
false), false),
new DefaultAllocator(BUFFER_SEGMENT_SIZE), BUFFER_SEGMENT_SIZE * BUFFER_SEGMENT_COUNT, new DefaultAllocator(BUFFER_SEGMENT_SIZE), BUFFER_SEGMENT_SIZE * BUFFER_SEGMENT_COUNT,
new MatroskaExtractor()); new Extractor[] {new MatroskaExtractor()});
player.setSource(sampleSource); player.setSource(sampleSource);
player.setPlayWhenReady(true); player.setPlayWhenReady(true);
Looper.loop(); Looper.loop();

View File

@ -19,6 +19,7 @@ import com.google.android.exoplayer.DefaultTrackSelector;
import com.google.android.exoplayer.ExoPlaybackException; import com.google.android.exoplayer.ExoPlaybackException;
import com.google.android.exoplayer.ExoPlayer; import com.google.android.exoplayer.ExoPlayer;
import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.TrackRenderer;
import com.google.android.exoplayer.extractor.Extractor;
import com.google.android.exoplayer.extractor.ExtractorSampleSource; import com.google.android.exoplayer.extractor.ExtractorSampleSource;
import com.google.android.exoplayer.extractor.mkv.MatroskaExtractor; import com.google.android.exoplayer.extractor.mkv.MatroskaExtractor;
import com.google.android.exoplayer.upstream.DefaultAllocator; import com.google.android.exoplayer.upstream.DefaultAllocator;
@ -83,7 +84,7 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
new DefaultDataSource(context, null, Util.getUserAgent(context, "ExoPlayerExtOpusTest"), new DefaultDataSource(context, null, Util.getUserAgent(context, "ExoPlayerExtOpusTest"),
false), false),
new DefaultAllocator(BUFFER_SEGMENT_SIZE), BUFFER_SEGMENT_SIZE * BUFFER_SEGMENT_COUNT, new DefaultAllocator(BUFFER_SEGMENT_SIZE), BUFFER_SEGMENT_SIZE * BUFFER_SEGMENT_COUNT,
new MatroskaExtractor()); new Extractor[] {new MatroskaExtractor()});
player.setSource(sampleSource); player.setSource(sampleSource);
player.setPlayWhenReady(true); player.setPlayWhenReady(true);
Looper.loop(); Looper.loop();

View File

@ -19,6 +19,7 @@ import com.google.android.exoplayer.DefaultTrackSelector;
import com.google.android.exoplayer.ExoPlaybackException; import com.google.android.exoplayer.ExoPlaybackException;
import com.google.android.exoplayer.ExoPlayer; import com.google.android.exoplayer.ExoPlayer;
import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.TrackRenderer;
import com.google.android.exoplayer.extractor.Extractor;
import com.google.android.exoplayer.extractor.ExtractorSampleSource; import com.google.android.exoplayer.extractor.ExtractorSampleSource;
import com.google.android.exoplayer.extractor.mkv.MatroskaExtractor; import com.google.android.exoplayer.extractor.mkv.MatroskaExtractor;
import com.google.android.exoplayer.upstream.DefaultAllocator; import com.google.android.exoplayer.upstream.DefaultAllocator;
@ -99,7 +100,7 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
new DefaultDataSource(context, null, Util.getUserAgent(context, "ExoPlayerExtVP9Test"), new DefaultDataSource(context, null, Util.getUserAgent(context, "ExoPlayerExtVP9Test"),
false), false),
new DefaultAllocator(BUFFER_SEGMENT_SIZE), BUFFER_SEGMENT_SIZE * BUFFER_SEGMENT_COUNT, new DefaultAllocator(BUFFER_SEGMENT_SIZE), BUFFER_SEGMENT_SIZE * BUFFER_SEGMENT_COUNT,
new MatroskaExtractor()); new Extractor[] {new MatroskaExtractor()});
player.sendMessage(videoRenderer, LibvpxVideoTrackRenderer.MSG_SET_OUTPUT_BUFFER_RENDERER, player.sendMessage(videoRenderer, LibvpxVideoTrackRenderer.MSG_SET_OUTPUT_BUFFER_RENDERER,
new VpxVideoSurfaceView(context)); new VpxVideoSurfaceView(context));
player.setSource(sampleSource); player.setSource(sampleSource);

View File

@ -108,94 +108,8 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
private static final int MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA = -1; private static final int MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA = -1;
/** // Lazily initialized default extractor classes in priority order.
* Default extractor classes in priority order. They are referred to indirectly so that it is private static List<Class<? extends Extractor>> defaultExtractorClasses;
* possible to remove unused extractors.
*/
private static final List<Class<? extends Extractor>> DEFAULT_EXTRACTOR_CLASSES;
static {
DEFAULT_EXTRACTOR_CLASSES = new ArrayList<>();
// Load extractors using reflection so that they can be deleted cleanly.
// Class.forName(<class name>) appears for each extractor so that automated tools like proguard
// can detect the use of reflection (see http://proguard.sourceforge.net/FAQ.html#forname).
try {
DEFAULT_EXTRACTOR_CLASSES.add(
Class.forName("com.google.android.exoplayer.extractor.mkv.MatroskaExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
DEFAULT_EXTRACTOR_CLASSES.add(
Class.forName("com.google.android.exoplayer.extractor.mp4.FragmentedMp4Extractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
DEFAULT_EXTRACTOR_CLASSES.add(
Class.forName("com.google.android.exoplayer.extractor.mp4.Mp4Extractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
DEFAULT_EXTRACTOR_CLASSES.add(
Class.forName("com.google.android.exoplayer.extractor.mp3.Mp3Extractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
DEFAULT_EXTRACTOR_CLASSES.add(
Class.forName("com.google.android.exoplayer.extractor.ts.AdtsExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
DEFAULT_EXTRACTOR_CLASSES.add(
Class.forName("com.google.android.exoplayer.extractor.ts.TsExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
DEFAULT_EXTRACTOR_CLASSES.add(
Class.forName("com.google.android.exoplayer.extractor.flv.FlvExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
DEFAULT_EXTRACTOR_CLASSES.add(
Class.forName("com.google.android.exoplayer.extractor.ogg.OggExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
DEFAULT_EXTRACTOR_CLASSES.add(
Class.forName("com.google.android.exoplayer.extractor.ts.PsExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
DEFAULT_EXTRACTOR_CLASSES.add(
Class.forName("com.google.android.exoplayer.extractor.wav.WavExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
DEFAULT_EXTRACTOR_CLASSES.add(
Class.forName("com.google.android.exoplayer.ext.flac.FlacExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
}
private final Loader loader; private final Loader loader;
private final ExtractorHolder extractorHolder; private final ExtractorHolder extractorHolder;
@ -235,11 +149,13 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
* @param allocator An {@link Allocator} from which to obtain memory allocations. * @param allocator An {@link Allocator} from which to obtain memory allocations.
* @param requestedBufferSize The requested total buffer size for storing sample data, in bytes. * @param requestedBufferSize The requested total buffer size for storing sample data, in bytes.
* The actual allocated size may exceed the value passed in if the implementation requires it. * The actual allocated size may exceed the value passed in if the implementation requires it.
* @param extractors {@link Extractor}s to extract the media stream, in order of decreasing * @param extractors {@link Extractor}s to process the media stream. Where the possible formats
* priority. If omitted, the default extractors will be used. * are known, instantiate and inject only instances of the corresponding {@link Extractor}s.
* Where this is not possible, {@link #newDefaultExtractors()} can be used to construct an
* array of default extractors.
*/ */
public ExtractorSampleSource(Uri uri, DataSource dataSource, Allocator allocator, public ExtractorSampleSource(Uri uri, DataSource dataSource, Allocator allocator,
int requestedBufferSize, Extractor... extractors) { int requestedBufferSize, Extractor[] extractors) {
this(uri, dataSource, allocator, requestedBufferSize, MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA, this(uri, dataSource, allocator, requestedBufferSize, MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA,
extractors); extractors);
} }
@ -254,12 +170,14 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
* null if delivery of events is not required. * null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required.
* @param eventSourceId An identifier that gets passed to {@code eventListener} methods. * @param eventSourceId An identifier that gets passed to {@code eventListener} methods.
* @param extractors {@link Extractor}s to extract the media stream, in order of decreasing * @param extractors {@link Extractor}s to process the media stream. Where the possible formats
* priority. If omitted, the default extractors will be used. * are known, instantiate and inject only instances of the corresponding {@link Extractor}s.
* Where this is not possible, {@link #newDefaultExtractors()} can be used to construct an
* array of default extractors.
*/ */
public ExtractorSampleSource(Uri uri, DataSource dataSource, Allocator allocator, public ExtractorSampleSource(Uri uri, DataSource dataSource, Allocator allocator,
int requestedBufferSize, Handler eventHandler, EventListener eventListener, int requestedBufferSize, Handler eventHandler, EventListener eventListener,
int eventSourceId, Extractor... extractors) { int eventSourceId, Extractor[] extractors) {
this(uri, dataSource, allocator, requestedBufferSize, MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA, this(uri, dataSource, allocator, requestedBufferSize, MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA,
eventHandler, eventListener, eventSourceId, extractors); eventHandler, eventListener, eventSourceId, extractors);
} }
@ -272,11 +190,13 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
* The actual allocated size may exceed the value passed in if the implementation requires it. * The actual allocated size may exceed the value passed in if the implementation requires it.
* @param minLoadableRetryCount The minimum number of times that the sample source will retry * @param minLoadableRetryCount The minimum number of times that the sample source will retry
* if a loading error occurs. * if a loading error occurs.
* @param extractors {@link Extractor}s to extract the media stream, in order of decreasing * @param extractors {@link Extractor}s to process the media stream. Where the possible formats
* priority. If omitted, the default extractors will be used. * are known, instantiate and inject only instances of the corresponding {@link Extractor}s.
* Where this is not possible, {@link #newDefaultExtractors()} can be used to construct an
* array of default extractors.
*/ */
public ExtractorSampleSource(Uri uri, DataSource dataSource, Allocator allocator, public ExtractorSampleSource(Uri uri, DataSource dataSource, Allocator allocator,
int requestedBufferSize, int minLoadableRetryCount, Extractor... extractors) { int requestedBufferSize, int minLoadableRetryCount, Extractor[] extractors) {
this(uri, dataSource, allocator, requestedBufferSize, minLoadableRetryCount, null, null, 0, this(uri, dataSource, allocator, requestedBufferSize, minLoadableRetryCount, null, null, 0,
extractors); extractors);
} }
@ -293,12 +213,15 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
* null if delivery of events is not required. * null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required.
* @param eventSourceId An identifier that gets passed to {@code eventListener} methods. * @param eventSourceId An identifier that gets passed to {@code eventListener} methods.
* @param extractors {@link Extractor}s to extract the media stream, in order of decreasing * @param extractors {@link Extractor}s to process the media stream. Where the possible formats
* priority. If omitted, the default extractors will be used. * are known, instantiate and inject only instances of the corresponding {@link Extractor}s.
* Where this is not possible {@link #newDefaultExtractors()} can be used to construct an
* array of default extractors.
*/ */
public ExtractorSampleSource(Uri uri, DataSource dataSource, Allocator allocator, public ExtractorSampleSource(Uri uri, DataSource dataSource, Allocator allocator,
int requestedBufferSize, int minLoadableRetryCount, Handler eventHandler, int requestedBufferSize, int minLoadableRetryCount, Handler eventHandler,
EventListener eventListener, int eventSourceId, Extractor... extractors) { EventListener eventListener, int eventSourceId, Extractor[] extractors) {
Assertions.checkState(extractors != null && extractors.length > 0);
this.uri = uri; this.uri = uri;
this.dataSource = dataSource; this.dataSource = dataSource;
this.eventListener = eventListener; this.eventListener = eventListener;
@ -311,21 +234,117 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
int initialMinRetryCount = minLoadableRetryCount == MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA int initialMinRetryCount = minLoadableRetryCount == MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA
? DEFAULT_MIN_LOADABLE_RETRY_COUNT_ON_DEMAND : minLoadableRetryCount; ? DEFAULT_MIN_LOADABLE_RETRY_COUNT_ON_DEMAND : minLoadableRetryCount;
loader = new Loader("Loader:ExtractorSampleSource", initialMinRetryCount); loader = new Loader("Loader:ExtractorSampleSource", initialMinRetryCount);
if (extractors == null || extractors.length == 0) {
extractors = new Extractor[DEFAULT_EXTRACTOR_CLASSES.size()];
for (int i = 0; i < extractors.length; i++) {
try {
extractors[i] = DEFAULT_EXTRACTOR_CLASSES.get(i).newInstance();
} catch (Exception e) {
throw new IllegalStateException("Unexpected error creating default extractor", e);
}
}
}
extractorHolder = new ExtractorHolder(extractors, this); extractorHolder = new ExtractorHolder(extractors, this);
pendingResetPositionUs = C.UNSET_TIME_US; pendingResetPositionUs = C.UNSET_TIME_US;
sampleQueues = new DefaultTrackOutput[0]; sampleQueues = new DefaultTrackOutput[0];
} }
/**
* Builds default extractors that can be passed to an {@link ExtractorSampleSource} constructor.
*
* @return An array of default extractors.
*/
public static Extractor[] newDefaultExtractors() {
synchronized (ExtractorSampleSource.class) {
if (defaultExtractorClasses == null) {
// Lazily initialize defaultExtractorClasses.
List<Class<? extends Extractor>> extractorClasses = new ArrayList<>();
// We reference extractors using reflection so that they can be deleted cleanly.
// Class.forName is used so that automated tools like proguard can detect the use of
// reflection (see http://proguard.sourceforge.net/FAQ.html#forname).
try {
extractorClasses.add(
Class.forName("com.google.android.exoplayer.extractor.mkv.MatroskaExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
extractorClasses.add(
Class.forName("com.google.android.exoplayer.extractor.mp4.FragmentedMp4Extractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
extractorClasses.add(
Class.forName("com.google.android.exoplayer.extractor.mp4.Mp4Extractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
extractorClasses.add(
Class.forName("com.google.android.exoplayer.extractor.mp3.Mp3Extractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
extractorClasses.add(
Class.forName("com.google.android.exoplayer.extractor.ts.AdtsExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
extractorClasses.add(
Class.forName("com.google.android.exoplayer.extractor.ts.TsExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
extractorClasses.add(
Class.forName("com.google.android.exoplayer.extractor.flv.FlvExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
extractorClasses.add(
Class.forName("com.google.android.exoplayer.extractor.ogg.OggExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
extractorClasses.add(
Class.forName("com.google.android.exoplayer.extractor.ts.PsExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
extractorClasses.add(
Class.forName("com.google.android.exoplayer.extractor.wav.WavExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
try {
extractorClasses.add(
Class.forName("com.google.android.exoplayer.ext.flac.FlacExtractor")
.asSubclass(Extractor.class));
} catch (ClassNotFoundException e) {
// Extractor not found.
}
defaultExtractorClasses = extractorClasses;
}
}
Extractor[] extractors = new Extractor[defaultExtractorClasses.size()];
for (int i = 0; i < extractors.length; i++) {
try {
extractors[i] = defaultExtractorClasses.get(i).newInstance();
} catch (Exception e) {
// Should never happen.
throw new IllegalStateException("Unexpected error creating default extractor", e);
}
}
return extractors;
}
// SampleSource implementation. // SampleSource implementation.
@Override @Override