使用exoplayer2 播放AES加密过的视频流。
目的是为了实现边解密边播放。
转载
https://blog.csdn.net/wanniu/article/details/78533796
//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位置
把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的类型。但是具体细节还是不懂呀