ExoPlayer Demo 媒体类型参数

ExoPlayer是Google开源的播放器,可以算是MediaPlayer的扩展版本吧,因为跟一些小伙伴发起了一个播放器开发的项目,所以接下来打算把学到的东西都写下来。一来,可以方便和其他小伙伴交流,二来,也方便以后自己复习。碍于自己Android知识水平有限,如有错误还请大家多多指教。

  • 注:ExoPlayer版本 r1.5.9,单独分离出来的ExoPlayerDemo

在Demo中可以看到,流媒体播放的请求都是以Intent的形式,封装一个Sample去拉起一个播放页面的Activity。

1
2
3
4
5
6
Intent mpdIntent = new Intent(mContext, PlayerActivity.class)
.setData(Uri.parse(sample.uri))
.putExtra(PlayerActivity.CONTENT_ID_EXTRA, sample.contentId)
.putExtra(PlayerActivity.CONTENT_TYPE_EXTRA, sample.type)
.putExtra(PlayerActivity.PROVIDER_EXTRA, sample.provider);
mContext.startActivity(mpdIntent);

而在Sample的构造方法中,需要传入媒体的类型:

1
2
3
4
public static final Sample[] CNTV_DASH = new Sample[]{
new Sample("CCTV-1HD",
"http://vod.cdn4.cmvideo.cn/envivo_v/HD/cctv1/450/01.m3u8", Util.TYPE_HLS),
};

同时在PlayerActivity中可以看到,根据不同的流媒体类型会回调不同的接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private RendererBuilder getRendererBuilder() {
String userAgent = Util.getUserAgent(this, "PlayerActivity");
switch (contentType) {
case Util.TYPE_SS:
return new SmoothStreamingRendererBuilder(this, userAgent,
contentUri.toString(),
new SmoothStreamingTestMediaDrmCallback());
case Util.TYPE_DASH:
return new DashRendererBuilder(this, userAgent, contentUri.toString(),
new WidevineTestMediaDrmCallback(contentId, provider));
case Util.TYPE_HLS:
return new HlsRendererBuilder(this, userAgent, contentUri.toString());
case Util.TYPE_OTHER:
return new ExtractorRendererBuilder(this, userAgent, contentUri);
default:
throw new IllegalStateException("Unsupported type: " + contentType);
}
}

接着前面的线索,查找Util类中的类型参数,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* Value returned by {@link #inferContentType(String)} for DASH manifests.
*/

public static final int TYPE_DASH = 0;

/**
* Value returned by {@link #inferContentType(String)} for Smooth Streaming manifests.
*/

public static final int TYPE_SS = 1;

/**
* Value returned by {@link #inferContentType(String)} for HLS manifests.
*/

public static final int TYPE_HLS = 2;

/**
* Value returned by {@link #inferContentType(String)} for files other than DASH,
* HLS or Smooth Streaming manifests.
*/

public static final int TYPE_OTHER = 3;

看到这里,直观的反应是这四个参数代表不同的流媒体协议。之前都流媒体的协议并不是很了解,于是开始搜索。找到了部分跟协议相关的知识,比如自适性串流。阅读后对流媒体协议有了初步的了解,但感觉还是跟给出的四个类型对不上。终于注意到 inferContentType(String) 这个方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* Makes a best guess to infer the type from a file name.
*
* @param fileName Name of the file. It can include the path of the file.
* @return One of {@link #TYPE_DASH}, {@link #TYPE_SS}, {@link #TYPE_HLS} or
* {@link #TYPE_OTHER}.
*/

public static int inferContentType(String fileName) {
if (fileName == null) {
return TYPE_OTHER;
} else if (fileName.endsWith(".mpd")) {
return TYPE_DASH;
} else if (fileName.endsWith(".ism")) {
return TYPE_SS;
} else if (fileName.endsWith(".m3u8")) {
return TYPE_HLS;
} else {
return TYPE_OTHER;
}
}

查看inferContentType的调用会发现,在传入的Sample没有设置类型的时候,会调用该方法检测Uri的后缀,然后根据后缀进行如上分类,并不是代表某一个协议的意思。我用一个MP4格式的本地视频,以TYPE_SS的类型传入,发现也是能播放的。猜测这个类型参数可能在播放时会进行某些优化。只好在接下来的学习中再去解决自己的疑惑了。