android exoplayer 直播流,使用exoplayer2 播放AES加密过的视频流。

//google音视频播放框架

compile 'com.google.android.exoplayer:exoplayer:r2.5.4'

利用exoplayer自定义了DataSource来解密AES加密的流。

核心代码:

// 1.创建一个默认TrackSelector,测量播放过程中的带宽。 如果不需要,可以为null。

DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();

//从MediaSource中选出media提供给可用的Render S来渲染,在创建播放器时被注入

TrackSelection.Factory videoTrackSelectionFactory =

new AdaptiveTrackSelection.Factory(bandwidthMeter);

//自适应轨道

TrackSelector trackSelector =

new DefaultTrackSelector(videoTrackSelectionFactory);

//控制MediaSource缓存media

DefaultLoadControl loadControl = new DefaultLoadControl();

WeimsDataSourceFactory 复制 DefaultDataSourceFactory

核心方法:

public DataSource createDataSource() {

return new WeimsDataSource(context, listener, baseDataSourceFactory.createDataSource());

}

WeimsDataSource 复制 DefaultDataSource

核心方法

if (Util.isLocalFileUri(dataSpec.uri)) {

if (dataSpec.uri.getPath().endsWith(".weims")) {

Aes128DataSource aes128DataSource =

new Aes128DataSource(getFileDataSource(), WEKey.getBytes(), WEKey.getBytes());

dataSource = aes128DataSource;

}else {

对本地url增加一个判断

直接使用框架里既有的

Aes128DataSource

new Aes128DataSource(getFileDataSource(), WEKey.getBytes(), WEKey.getBytes());

上流的数据流用fileDataSource包装一次。让其具有文件的长度判断。

(mp4格式头信息在datasourse前 或者 尾部 到至解码失败。

)

upstream The upstream {@link DataSource}.

边解密边播放的定制explay

现在出现的问题:

mp4格式头信息在datasourse前 或者 尾部 到至解码失败。

解决思路:QtFastStart 工具类。可以转换moov位置

78a1b44ff917

image.png

78a1b44ff917

image.png

把moov提到mdat之前。

播放时无法seekto

解决思路:重写框架里的ParsableByteArray

public int readUnsignedIntToInt() {

int result = readInt();

if(result<0)

{

result = -result;

}

return result;

}

这样修改后,会出现,画面显示颜色落差,以及声音音量。错乱。

思路:

发现CBC加密方式,是填充和异或前一个加密块的,来加密现在这个明文块。

发现CBC方式,不适合流加解密。

然后选择CFB128加解密,只因(CFB模式非常适合对流数据进行加密,解密可以并行计算。大佬博文说的:https://blog.csdn.net/chaiyu2002/article/details/79757697)

发现此加解密方式,延时更长,上述问题还是发生。反而CBC方法更好些。问题还待研究。研究源码在解密的时候,发现H264 NULLenght 获取simple长度有问题。MP4格式的H264 特点是:8.MP4文件中的NAL

MP4文件中的一个sample由多个NALU组成。大体结构如下:Length1+NALU1+Length2+NALU2+。。。。其中Length表示下一个NALU的长度(不包括Length本身的长度),而NALU的第一个字节是表示该NALU的头部。通过NALU头部的信息可以得到该NALU的类型。但是具体细节还是不懂呀

78a1b44ff917

1573781920455.gif