赞
踩
repositories {
google()
jcenter()
}
在build.gradle您的应用模块的文件中添加一个依赖项。以下内容将对完整的ExoPlayer库添加依赖项:
这里我们选择最新的:
implementation 'com.google.android.exoplayer:exoplayer:2.11.7'
作为完整库的替代方法,可以仅依赖实际需要的库模块。例如,以下内容将添加对Core,DASH和UI
库模块的依赖关系,这可能是播放DASH内容的应用程序所必需的:
implementation 'com.google.android.exoplayer:exoplayer-core:2.11.7'
implementation 'com.google.android.exoplayer:exoplayer-dash:2.11.7'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.2.11.7'
可用的库模块在下面列出。向完整的ExoPlayer库添加依赖项等效于分别为所有库模块添加依赖项。
库名称 | 主要功能 |
---|---|
exoplayer-cor | 核心功能 |
exoplayer-dash | 支持DASH内容 |
exoplayer-hlsr | 支持HLS内容 |
exoplayer-smoothstreamingr | 支持SmoothStreaming内容 |
exoplayer-uir | 与ExoPlayer一起使用的UI组件和资源 |
除了库模块之外,ExoPlayer还具有多个扩展模块,这些扩展模块依赖于外部库来提供附加功能。浏览 扩展目录及其各自的自述文件以了解详细信息。
compileOptions {
targetCompatibility JavaVersion.VERSION_1_8
}
有兴趣的可以自己复写源码,增加定制功能;
可以使用SimpleExoPlayer.Builder或 创建实例ExoPlayer.Builder。这些构建器提供了一系列用于创建ExoPlayer实例的定制选项。对于绝大多数用例, SimpleExoPlayer.Builder都应使用。此构建器返回 SimpleExoPlayer,它扩展ExoPlayer为添加其他高级播放器功能。以下代码是创建的示例SimpleExoPlayer。
SimpleExoPlayer mPlayer = new SimpleExoPlayer.Builder(mContext).build();
可以参考个人Exoplayer Demo Git:
https://github.com/xiaxiaxa/ExoPlayerDemo.git
package com.mgtv.exodemo.activity; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.net.Uri; import android.util.Log; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.hls.HlsMediaSource; import com.google.android.exoplayer2.ui.PlayerView; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; import com.mgtv.exodemo.MyApplication; import com.mgtv.exodemo.R; public class ExoPlayerActivity extends BaseActivity { private Context mContext; private PlayerView mPlayerView = null; private SimpleExoPlayer mPlayer; private DataSource.Factory mediaDataSourceFactory; private MediaSource mediaSourceHls; // private UdpDataSource udpDataSourceRtp; private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter(); private String videoUrlRtp = "rtp://239.76.245.115:1234"; private String videoUrlHls = "http://10.255.30.137:8082/EDS/RedirectPlay/000000000000/vod/f95e41c67ca2410c89b335ee5f5eecb8/3cc6fae6d07740aa8d57934e26cc2632?UserToken=123456789&UserName=6830018"; private void initExoPlayer() { mPlayer = new SimpleExoPlayer.Builder(mContext).build(); mPlayerView.setPlayer(mPlayer); Uri playHlsUri = Uri.parse(videoUrlHls); // Uri playRtpUri = Uri.parse(videoUrlRtp); /**使用dash的解析库*/ /* dashMediaSource = new DashMediaSource(playHlsUri,mediaDataSourceFactory, new DefaultDashChunkSource.Factory(mediaDataSourceFactory ),null,null);*/ /**====解析hls===begin*/ mediaSourceHls = new HlsMediaSource.Factory(mediaDataSourceFactory) .createMediaSource(playHlsUri, null, null); Log.d("exo", "Mr.xw==mediaSource==" + mediaSourceHls); mPlayer.prepare(mediaSourceHls); mPlayerView.setPlayer(mPlayer); mPlayer.setPlayWhenReady(true); /**====解析hls===end*/ /**====解析rtp===begin 这块需要复写udp方法,暂未实现*/ /* mediaSourceHls = new UdpDataSource(mediaDataSourceFactory) .createMediaSource(playHlsUri, null, null); Log.d("exo", "Mr.xw==mediaSource==" + mediaSourceHls); mPlayerView.setPlayer(mPlayer); mPlayer.setPlayWhenReady(true);*/ /**====解析rtp===end*/ } @Override public int getLayoutRes() { getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); return R.layout.exoplayer; } @Override public void init() { mContext = this; mPlayerView = findViewById(R.id.exo_vr); mediaDataSourceFactory = buildDataSourceFactory(true); initExoPlayer(); } private DataSource.Factory buildDataSourceFactory(boolean useBandwidthMeter) { return ((MyApplication) getApplication()) .buildDataSourceFactory(useBandwidthMeter ? null : null); } @Override public void onPointerCaptureChanged(boolean hasCapture) { } @Override protected void onStop() { super.onStop(); } @Override protected void onPause() { super.onPause(); releaseData(); } @Override protected void onDestroy() { super.onDestroy(); releaseData(); } private void releaseData() { if (isFinishing()) { if (mPlayer != null) { mPlayer.stop(); mPlayer.release(); mPlayer = null; } if (mPlayerView!=null){ mPlayerView.destroyDrawingCache(); mPlayerView = null; } } } }
apply plugin: 'com.android.application' android { compileSdkVersion 29 buildToolsVersion "30.0.0" defaultConfig { applicationId "com.mgtv.exodemo" minSdkVersion 19 targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } compileOptions { targetCompatibility JavaVersion.VERSION_1_8 } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } dependencies { implementation 'com.google.android.exoplayer:exoplayer:2.11.7' implementation 'com.google.android.exoplayer:exoplayer-core:2.11.7' implementation 'com.google.android.exoplayer:exoplayer-dash:2.11.7' implementation 'com.google.android.exoplayer:exoplayer-hls:2.11.7' implementation 'com.google.android.exoplayer:exoplayer-ui:2.11.7' implementation 'com.google.android.exoplayer:extension-rtmp:2.11.7' implementation fileTree(dir: 'libs', include: ['*.jar']) implementation files('libs/xutils.jar') implementation 'androidx.appcompat:appcompat:1.1.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' }
ExoPlayer库的核心是ExoPlayer接口。Exoplayer把播放类型、存储位置和渲染方式等任务委派给不同的部件,然后在创建播放器或后台播放的时候把这些部件注入。这些部件包括:
如果标准实现不能满足需求,也可以使用自定义实现。例如,自定义LoadControl 可以改变播放器的缓冲策略,或自定义Renderer 可实现 Android 本身不支持的视频编解码器。
ExoPlayer提供默认的音频和视频渲染器,利用了Android框架中的MediaCodec和AudioTrack类。这两个都需要一个SampleSource对象中注入,用来实现媒体示例的播放。
组件的注入在当前ExoPlayer库中是普遍存在的。下图展示了使用一个ExoPlayer来配置和播放MP4媒体流的高级对象模型。默认的音频和视频渲染器已经被注解到ExoPlayer中。ExtractorSampleSource类的实现被注解到渲染器中用于提供简单的媒体播放功能。DataSource和Extractor示例被注解到ExtractorSampleSource来支持加载媒体流和在被加载的数据中提取样板。在这个示例中DefaultUriDataSource和Mp4Extractor被用于播放从URIs中导入的MP4流。
可以参考官网文档:
[developer guide]:
https://google.github.io/ExoPlayer/guide.html
[class reference]:
https://google.github.io/ExoPlayer/doc/reference
[release notes]:
https://github.com/google/ExoPlayer/blob/release-v2/RELEASENOTES.md
[developer blog]:
https://medium.com/google-exoplayer
我们重点看下MediaSource的使用;
在ExoPlayer中,每个media都由 MediaSource 表示。 ExoPlayer库为DASH(DashMediaSource),SmoothStreaming(SsMediaSource),HLS(HlsMediaSource)和常规媒体文件(ExtractorMediaSource)提供了MediaSource实现。 在 main demo app 的PlayerActivity中可以找到如何实例化所有四个示例。
需要注意:MediaSource实例不适用于重新使用的情况。 如果您想用相同的media多次准备播放器,请每次使用新的实例。
除了上述的MediaSource实现外,ExoPlayer库还提供了MergingMediaSource,LoopingMediaSource,ConcatenatingMediaSource和DynamicConcatenatingMediaSource。这些MediaSource实现可以通过组合来实现更复杂的播放功能。下面描述了一些常见的用例。请注意,尽管在视频播放的上下文中描述了以下示例,但它们同样适用于仅播放音频,以及任何支持的媒体类型的播放的情况。
序号 | 主要功能 |
---|---|
1 | 从侧面加载字幕文件 |
2 | 循环播放视频 |
3 | 播放一系列视频 |
4 | 高级组合 |
// Build the video MediaSource.
MediaSource videoSource =
new ExtractorMediaSource.Factory(...).createMediaSource(videoUri);
// Build the subtitle MediaSource.
Format subtitleFormat = Format.createTextSampleFormat(
id, // An identifier for the track. May be null.
MimeTypes.APPLICATION_SUBRIP, // The mime type. Must be set correctly.
selectionFlags, // Selection flags for the track.
language); // The subtitle language. May be null.
MediaSource subtitleSource =
new SingleSampleMediaSource.Factory(...)
.createMediaSource(subtitleUri, subtitleFormat, C.TIME_UNSET);
// Plays the video with the sideloaded subtitle.
MergingMediaSource mergedSource =
new MergingMediaSource(videoSource, subtitleSource);
无限循环,通常最好使用 ExoPlayer.setRepeatMode 而不是 LoopingMediaSource。
MediaSource source =
new ExtractorMediaSource.Factory(...).createMediaSource(videoUri);
// Plays the video twice.
LoopingMediaSource loopingSource = new LoopingMediaSource(source, 2);
ConcatenatingMediaSource 可以连续播放两个或多个单独的MediaSource。 比如按顺序播放了两个视频的例子。 数据源之间的转换是无缝的。对连接的源具有相同的格式这一点不做强制要求,您可以把两个不同格式的数据源连接起来。
MediaSource firstSource =
new ExtractorMediaSource.Factory(...).createMediaSource(firstVideoUri);
MediaSource secondSource =
new ExtractorMediaSource.Factory(...).createMediaSource(secondVideoUri);
// Plays the first video, then the second video.
ConcatenatingMediaSource concatenatedSource =
new ConcatenatingMediaSource(firstSource, secondSource);
DynamicConcatenatingMediaSource 类似于 ConcatenatingMediaSource,不同之处在于它允许在播放前和播放期间动态添加,删除和移动MediaSource。 DynamicConcatenatingMediaSource非常适合于播放列表的使用场景,即用户可以在播放期间修改播放列表。
MediaSource 实例不应该多次添加到 DynamicConcatenatingMediaSource中,或者在之前被删除的情况下重新添加。 推荐创建新的实例去操作。
有可能进一步将复合MediaSources组合起来,用于更多不常见的用法。 给定两个视频A和B,以下示例显示LoopingMediaSource和ConcatenatingMediaSource如何一起使用来播放序列(A,A,B)。
ediaSource firstSource =
new ExtractorMediaSource.Factory(...).createMediaSource(firstVideoUri);
MediaSource secondSource =
new ExtractorMediaSource.Factory(...).createMediaSource(secondVideoUri);
// Plays the first video twice.
LoopingMediaSource firstSourceTwice = new LoopingMediaSource(firstSource, 2);
// Plays the first video twice, then the second video.
ConcatenatingMediaSource concatenatedSource =
new ConcatenatingMediaSource(firstSourceTwice, secondSource);
或者
MediaSource firstSource = new ExtractorMediaSource.Builder(firstVideoUri, ...).build();
MediaSource secondSource = new ExtractorMediaSource.Builder(secondVideoUri, ...).build();
// Plays the first video twice, then the second video.
ConcatenatingMediaSource concatenatedSource =
new ConcatenatingMediaSource(firstSource, firstSource, secondSource);
除非文档明确允许,否则避免在组合中多次使用相同的MediaSource实例很重要。 上面的示例中使用firstSource两次就是这种情况,因为用于ConcatenatingMediaSource的Javadoc明确指出允许重复条目。 然而,一般来说,由构造组成的对象的图形应该是树形结构(这个地方不好翻译,英文不好见谅)。 在组合中使用多个等效的MediaSource实例是允许的。
个人觉得使用ExoPlayer的一个特别之处是ExoPlayer支持数字版权管理(DRM)保护回放;
ExoPlayer库提供了一个DrmSessionManager的默认实现,名为DefaultDrmSessionManager,它使用MediaDrm。会话管理器支持在设备上存在模块DRM组件的任何DRM方案。所有的Android设备都需要支持Widevine模块DRM(使用L3安全性,尽管许多设备也支持L1)。某些设备可能支持其他方案,例如PlayReady。所有的Android TV 设备都支持PlayReady。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。