package com.devbrackets.android.exomedia;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.devbrackets.android.exomedia.core.source.MediaSourceProvider;
import com.devbrackets.android.exomedia.core.source.builder.DashMediaSourceBuilder;
import com.devbrackets.android.exomedia.core.source.builder.HlsMediaSourceBuilder;
import com.devbrackets.android.exomedia.core.source.builder.SsMediaSourceBuilder;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.upstream.TransferListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* A standard entry point for registering additional {@link com.google.android.exoplayer2.Renderer}s and
* {@link com.google.android.exoplayer2.source.MediaSource}s
*/
public class ExoMedia {
public interface HttpDataSourceFactoryProvider {
@NonNull
HttpDataSource.BaseFactory provide(@NonNull String userAgent, @Nullable TransferListener<? super DataSource> listener);
}
public enum RendererType {
AUDIO,
VIDEO,
CLOSED_CAPTION,
METADATA
}
/**
* Registers additional customized {@link com.google.android.exoplayer2.Renderer}s
* that will be used by the {@link com.google.android.exoplayer2.source.MediaSource}s to
* correctly play media.
*
* @param type The type for the renderer
* @param clazz The class of the customized Renderer
*/
public static void registerRenderer(@NonNull RendererType type, @NonNull Class<? super Renderer> clazz) {
Data.registeredRendererClasses.get(type).add(clazz.getName());
}
/**
* Registers additional {@link com.google.android.exoplayer2.source.MediaSource}s for the specified file
* extensions (and regexes). {@link com.google.android.exoplayer2.source.MediaSource}s registered here will take
* precedence to the pre-configured ones.
*
* @param builder The builder for additional or customized media sources
*/
public static void registerMediaSourceBuilder(@NonNull MediaSourceProvider.SourceTypeBuilder builder) {
Data.sourceTypeBuilders.add(0, builder);
}
/**
* Specifies the provider to use when building {@link com.google.android.exoplayer2.upstream.HttpDataSource.BaseFactory}
* instances for use with the {@link com.devbrackets.android.exomedia.core.source.builder.MediaSourceBuilder}s. This will
* only be used for builders that haven't customized the {@link com.devbrackets.android.exomedia.core.source.builder.MediaSourceBuilder#buildDataSourceFactory(Context, String, TransferListener)}
* method.
*
* @param provider The provider to use for the {@link com.devbrackets.android.exomedia.core.source.builder.MediaSourceBuilder}s
*/
public static void setHttpDataSourceFactoryProvider(@Nullable HttpDataSourceFactoryProvider provider) {
Data.httpDataSourceFactoryProvider = provider;
}
/**
* Specifies the {@link LoadControl} to use when building the {@link com.google.android.exoplayer2.ExoPlayer} instance
* used in the {@link com.devbrackets.android.exomedia.ui.widget.VideoView} and {@link AudioPlayer}. This allows the
* buffering amounts to be modified to better suit your needs which can be easily specified by using an instance of
* {@link com.google.android.exoplayer2.DefaultLoadControl}. When the <code>loadControl</code> is <code>null</code>
* the default instance of the {@link com.google.android.exoplayer2.DefaultLoadControl} will be used. This will only
* take effect for any instances created <i>after</i> this was set.
*
* @param loadControl The {@link LoadControl} to use for any new {@link com.google.android.exoplayer2.ExoPlayer} instances
*/
public static void setLoadControl(@Nullable LoadControl loadControl) {
Data.loadControl = loadControl;
}
public static class Data {
@NonNull
public static final Map<RendererType, List<String>> registeredRendererClasses = new HashMap<>();
@NonNull
public static final List<MediaSourceProvider.SourceTypeBuilder> sourceTypeBuilders = new ArrayList<>();
@Nullable
public static volatile HttpDataSourceFactoryProvider httpDataSourceFactoryProvider;
@Nullable
public static volatile LoadControl loadControl;
static {
instantiateRendererClasses();
instantiateSourceProviders();
}
private static void instantiateRendererClasses() {
// Instantiates the required values
registeredRendererClasses.put(RendererType.AUDIO, new LinkedList<String>());
registeredRendererClasses.put(RendererType.VIDEO, new LinkedList<String>());
registeredRendererClasses.put(RendererType.CLOSED_CAPTION, new LinkedList<String>());
registeredRendererClasses.put(RendererType.METADATA, new LinkedList<String>());
// Adds the ExoPlayer extension library renderers
List<String> audioClasses = registeredRendererClasses.get(RendererType.AUDIO);
audioClasses.add("com.google.android.exoplayer2.ext.opus.LibopusAudioRenderer");
audioClasses.add("com.google.android.exoplayer2.ext.flac.LibflacAudioRenderer");
audioClasses.add("com.google.android.exoplayer2.ext.ffmpeg.FfmpegAudioRenderer");
List<String> videoClasses = registeredRendererClasses.get(RendererType.VIDEO);
videoClasses.add("com.google.android.exoplayer2.ext.vp9.LibvpxVideoRenderer");
}
private static void instantiateSourceProviders() {
// Adds the HLS, SmoothStream, and MPEG Dash registrations
sourceTypeBuilders.add(new MediaSourceProvider.SourceTypeBuilder(new HlsMediaSourceBuilder(), ".m3u8", ".*m3u8.*"));
sourceTypeBuilders.add(new MediaSourceProvider.SourceTypeBuilder(new DashMediaSourceBuilder(), ".mpd", ".*mpd.*"));
sourceTypeBuilders.add(new MediaSourceProvider.SourceTypeBuilder(new SsMediaSourceBuilder(), ".ism", ".*ism.*"));
}
}
}