GitHub:https://github.com/wanliyang1990/wlmedia
功能
**支持:http、https、rtsp、rtp、rtmp、byte[]、加密視頻和各種文件格式視頻;
**截圖、音軌選擇、自定義視頻濾鏡、變速變調、聲道切換、無縫切換surface(surfaceview和textureview)、視頻比例設置等;
視頻演示
1、Usage
Gradle:
implementation 'ywl.ywl5320:wlmedia:1.0.5'
2、實例圖片
3、調用方式
配置NDK編譯平臺:
defaultConfig {
...
ndk {
abiFilter("arm64-v8a")
abiFilter("armeabi-v7a")
abiFilter("x86")
abiFilter("x86_64")
}
...
}
基本權限
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
4、接入代碼
4.1、視頻surface選擇
// WlSurfaceView 一般播放使用
<com.ywl5320.wlmedia.surface.WlSurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent" />
// WlTextureView 需要做透明、移動、旋轉等使用
<com.ywl5320.wlmedia.surface.WlTextureView
android:layout_width="match_parent"
android:layout_height="match_parent" />
4.2、創建播放器
4.2.1 播放視頻
WlMedia wlMedia = WlMedia.getInstance();//單例模式主要用於視頻,音頻可以new對象
wlMedia.setPlayModel(WlPlayModel.PLAYMODEL_AUDIO_VIDEO);//同時播放音頻視頻
wlSurfaceView.setWlMedia(wlMedia);//給視頻surface設置播放器
//異步準備完成後開始播放
wlMedia.setOnPreparedListener(new WlOnPreparedListener() {
@Override
public void onPrepared() {
wlMedia.start();//開始播放
}
});
//surface初始化好了後 開始播放視頻(用於一打開activity就播放場景)
wlSurfaceView.setOnVideoViewListener(new WlOnVideoViewListener() {
@Override
public void initSuccess() {
wlMedia.setSource("/storage/sdcard1/fcrs.1080p.mp4");//設置數據源
wlMedia.prepared();//異步開始準備播放
}
@Override
public void moveSlide(double value) {
}
@Override
public void movdFinish(double value) {
wlMedia.seek(value);//seek
}
});
//自定義濾鏡方式
String fs = "precision mediump float;" +
"varying vec2 ft_Position;" +
"uniform sampler2D sTexture; " +
"void main() " +
"{ " +
"vec4 v=texture2D(sTexture, ft_Position); " +
"float average = (v.r + v.g + v.b) / 3.0;" +
"gl_FragColor = vec4(average, average, average, v.a);" +
"}";
wlMedia.setfShader(fs);
wlMedia.changeFilter();
4.2.2 播放音頻
WlMedia wlMedia = new WlMedia();
wlMedia.setPlayModel(WlPlayModel.PLAYMODEL_ONLY_AUDIO);//設置只播放音頻(必須)
wlMedia.setSource(WlAssetsUtil.getAssetsFilePath(this, "mydream.m4a"));//設置數據源
wlMedia.setOnPreparedListener(new WlOnPreparedListener() {
@Override
public void onPrepared() {
wlMedia.start();
}
});
wlMedia.prepared();
4.2.3 播放加密視頻文件
WlMedia wlMedia = WlMedia.getInstance();//單例模式主要用於視頻,音頻可以new對象
wlMedia.setPlayModel(WlPlayModel.PLAYMODEL_AUDIO_VIDEO);
wlSurfaceView.setWlMedia(wlMedia);
wlMedia.setBufferSource(true, true);//必須都爲true
wlMedia.setOnDecryptListener(new WlOnDecryptListener() {
//解密算法
@Override
public byte[] decrypt(byte[] encrypt_data) {
int length = encrypt_data.length;
for(int i = 0; i < length; i++)
{
encrypt_data[i] = (byte) ((int)encrypt_data[i] ^ 666);
}
WlLog.d("decrypt");
return encrypt_data;
}
});
wlSurfaceView.setOnVideoViewListener(new WlOnVideoViewListener() {
@Override
public void initSuccess() {
wlMedia.setSource(WlAssetsUtil.getAssetsFilePath(WlEncryptActivity.this, "fhcq-ylgzy-dj-encrypt.mkv"));//加密視頻源
wlMedia.prepared();
}
@Override
public void moveSlide(double value) {
}
@Override
public void movdFinish(double value) {
wlMedia.seek(value);
}
});
4.2.4 播放byte[]音視頻數據
WlMedia wlMedia = WlMedia.getInstance();//單例模式主要用於視頻,音頻可以new對象
wlMedia.setBufferSource(true, false);//必須第一個爲true,第二個爲false
wlMedia.setPlayModel(WlPlayModel.PLAYMODEL_ONLY_VIDEO);//根據byte類型來設置(可以音頻、視頻、音視頻)
wlTextureView.setWlMedia(wlMedia);
wlMedia.setOnPreparedListener(new WlOnPreparedListener() {
@Override
public void onPrepared() {
wlMedia.start();
}
});
wlTextureView.setOnVideoViewListener(new WlOnVideoViewListener() {
@Override
public void initSuccess() {
new Thread(new Runnable() {
long length = 0;
@Override
public void run() {
try {
//從文件模擬byte[]數據
File file = new File(WlAssetsUtil.getAssetsFilePath(WlBufferActivity.this, "mytest.h264"));
FileInputStream fi = new FileInputStream(file);
byte[] buffer = new byte[1024 * 64];
int buffersize = 0;
int bufferQueueSize = 0;
exit = false;
while(true)
{
if(exit)
{
break;
}
if(wlMedia.isPlay())
{
WlLog.d("read thread " + bufferQueueSize);
if(bufferQueueSize < 20)//控制隊列大小,不然內存可能會增大溢出
{
buffersize = fi.read(buffer);
if(buffersize <= 0)
{
WlLog.d("read thread ============================== read buffer exit ...");
wlMedia.putBufferSource(null, -1);
break;
}
bufferQueueSize = wlMedia.putBufferSource(buffer, buffersize);//返回值爲底層buffer隊列個數
while(bufferQueueSize < 0)
{
bufferQueueSize = wlMedia.putBufferSource(buffer, buffersize);
}
}
else
{
bufferQueueSize = wlMedia.putBufferSource(null, 0);
}
sleep(10);
}
else
{
WlLog.d("buffer exit");
break;
}
}
wlMedia.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
wlMedia.prepared();
}
@Override
public void moveSlide(double value) {
}
@Override
public void movdFinish(double value) {
}
});
5、API
5.1 播放器API
public WlMedia();//構造函數,不依賴上下文
public void setSource(String source);//設置數據源(可以是file、url)
public void setPlayModel(WlPlayModel playModel);//設置音視頻播放模式(可以獨立播放音頻和視頻或者同時播放音視頻,默認同時播放音視頻)
public void setCodecType(WlCodecType codecType);//設置解碼器類型(默認優先使用硬解碼)
public void prepared();異步開始準備播放,成功後會回調WlOnPreparedListener接口
public void next();//切歌(數據源設置方法爲:setSource)
public void start();//開始播放(當異步準備完成後,在WlOnPreparedListener回調裏面開始播放)
public void pause();//播放暫停
public void resume();//暫停後恢復播放
public boolean isPlay();//判斷是否在播放中
public void setMute(WlMute mute);//設置聲道(立體聲、左聲道、右聲道)
public void setVolume(int percent);//設置聲音(0~100)
public void setSpeed(float speed);//設置播放速度(0.5f~2f)
public void setPitch(float pitch);//設置播放音調(0.5f~2f)
public void seek(double secds);//seek 目前是到關鍵幀(實測精確到時間幀,體驗不好,平均等待時間過長,故棄之)
public void setSampleRate(WlSampleRate wlSampleRate);//設置音頻採樣率(用於回調pcm時需要制定採樣率情況)
public void setShowPcm(boolean showPcm);//設置是否回調pcm音頻數據,回調方法:WlOnPcmDataListener
public double getNowClock();//獲取當前播放時間
public double getDuration();//獲取時長(如果有在異步準備好後可獲取)
public void takePicture();//視頻截圖(是截取surface屏幕圖片,自己可根據surface大小和視頻寬高對視頻圖片進行裁剪),回調方法:WlOnTakePictureListener
public int putBufferSource(byte[] buffer, int buffer_len);//byte[]方式播放數據入口,返回值爲底層隊列大小,當buffer_len == 0時,也返回底層隊列大小。
public void seekNoCallTime();//設置不回調時間,可用於seek過程中UI展示(具體看自己的需求)
public void onSurfaceCreate(Surface surface);//設置surface(用於自定義surfaceview)
public void onSurfaceChange(int width, int height, Surface surface);//surface大小改變
public void onSurfaceDestroy();//surface銷燬
public void release();//回收surface底層opengl資源
public void setTransportModel(WlTransportModel transportModel);//設置播放rtsp的方式(UDP/TCP)
public void setClearLastPicture(boolean clearLastPicture);//視頻播放完最後一幀是否清屏,true:停留在最後一幀;false:清屏爲黑色
/**
* 設置數據源模式
* 1、bufferSource爲true,encryptFileSource爲false時,是byte[]模式
* 2、bufferSource爲true,encryptFileSource爲true時,是file模式,可用於加密視頻播放,(回WlOnDecryptListener調裏面自己解密)
* @param bufferSource byte[]模式
* @param encryptFileSource 是否加密
*/
public void setBufferSource(boolean bufferSource, boolean encryptFileSource);
public void setvShader(String vShader);//設置頂點着色器
public void setfShader(String fShader);//設置紋理着色器
public void changeFilter();//設置着色器後用於使之生效(切換濾鏡)
public void scaleVideo(int w, int h);//設置視頻寬高比
public int getVideoWidth();//獲取視頻寬
public int getVideoHeight();//獲取視頻高
public String[] getAudioChannels();//獲取所有音軌,返回音軌名字(默認爲Audio)
public void setAudioChannel(int index);//設置播放音軌,index爲getAudioChannels中得到音軌的索引
public void setDelayOffsetTime(double offsetTime);//用於單獨播放視頻(buffer)時動態調整視頻渲染速率,單位秒。
5.2 WlSurfaceView和WlTextureView
SDK自帶這2個自定義surfaceview,通過setWlMedia方法與播放器關聯,updateMedia方法用於播放中切換顯示surface;WlOnVideoViewListener爲surface初始化完成回調。
開發者可以根據自己情況自定義自己的surfaceview,實現自己的特殊需求。
***注:***
自定義surface必須調用方法:
public void onSurfaceCreate(Surface surface);
public void onSurfaceChange(int width, int height, Surface surface);
public void onSurfaceDestroy();
5.3 回調函數
public interface WlOnPreparedListener; //異步準備完成回調
public interface WlOnTimeInfoListener; //播放時間回調
public interface WlOnLoadListener; //加載狀態回調
public interface WlOnErrorListener; //錯誤回調
public interface WlOnCompleteListener; //播放(資源回收)完成回調
public interface WlOnDecryptListener; //解密算法回調
public interface WlOnPcmDataListener; //音頻PCM數據回調
public interface WlOnTakePictureListener; //截圖回調
public interface WlOnVideoViewListener; //surface 初始化完成回調
6、混淆
-keep class com.ywl5320.wlmedia.* {*;}
7、注意事項
7.1播放器activity配置:
android:configChanges="orientation|keyboardHidden|screenSize"
android:launchMode="singleTask"//(建議)
7.2播放器生命週期邏輯
播放器結束有2個回調:error和complete,二者只可能回調其中一個,所以回收回收資源可以在這個2個回調裏面進行。
如:activity:back->stop->error/complete->release->finish