學(xué)習(xí)目標(biāo):
Android視頻播放功能在Android應(yīng)用場景(掌握)
視頻播放第一種方式使用系統(tǒng)自帶的播放器(掌握)
視頻播放第二種方式使用VideoView結(jié)合MediaController來播放視頻(掌握)
視頻播放第三種方式使用MediaPlayer類和SurfaceView來實現(xiàn)(掌握)
三種播放視頻方式的分析對比(掌握)
播放視頻資源的格式限制(掌握)
獲取視頻的第一幀
一.在Android中,我們有三種方式來實現(xiàn)視頻的播放:
1、使用其自帶的播放器。指定Action為ACTION_VIEW,Data為Uri,Type為其MIME類型。
2、使用VideoView來播放。在布局文件中使用VideoView結(jié)合MediaController來實現(xiàn)對其控制。
3、使用MediaPlayer類和SurfaceView來實現(xiàn),這種方式很靈活。
本地資源
內(nèi)部URI,比如你可以通過ContentResolver來獲取
外部URL(流)
二.第一種方式--使用系統(tǒng)自帶的播放器
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(vedios[0]), "video/mp4");
startActivity(intent);
三.第二種方式--使用VideoView結(jié)合MediaController來播放視頻
1.布局中添加VideoView
<VideoView
android:id="@+id/vv_vv"
android:layout_width="wrap_content"
android:layout_height="100dp"/>
2.具體代碼
MediaController mediaController = new MediaController(this);
vv_vv.setMediaController(mediaController);
vv_vv.setVideoPath(videos[i]);
vv_vv.start();
mediaController.setPrevNextListeners(new View.OnClickListener() {
@Override
public void onClick(View v) {
//下一個
i++;
if (i > videos.length - 1) {
i = 0;
}
vv_vv.setVideoPath(videos[i]);
vv_vv.start();
}
}, new View.OnClickListener() {
@Override
public void onClick(View v) {
//上一個
i--;
if (i < 0) {
i = videos.length - 1;
}
vv_vv.setVideoPath(videos[i]);
vv_vv.start();
}
});
四.第三種方式--使用MediaPlayer類和SurfaceView來實現(xiàn)
- MediaPlayer主要用于播放音頻,沒有提供圖像輸出界面,所以我們需要借助其他的組件來顯示MediaPlayer播放的圖像輸出,我們可以使用SurfaceView來顯示
a.調(diào)用player.setDataSource()方法設(shè)置要播放的資源,可以是文件、文件路徑、或者URL。
b.調(diào)用player.setDisplay(holder)設(shè)置surfaceHolder,surfaceHolder可以通過surfaceview的getHolder()方法獲得。
c.調(diào)用MediaPlayer.prepare()來準(zhǔn)備。
d.調(diào)用MediaPlayer.start()來播放視頻。
- 布局中添加SurfaceView
<SurfaceView
android:id="@+id/sv"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
2.具體代碼
public class MpActivity extends AppCompatActivity implements View.OnClickListener {
private SurfaceView sv;
private String path;
private Button btn_pause;
private Button btn_stop;
private Button btn_goon;
private MediaPlayer mediaPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mp);
path = getIntent().getStringExtra("path");
initView();
}
private void initView() {
sv = (SurfaceView) findViewById(R.id.sv);
btn_pause = (Button) findViewById(R.id.btn_pause);
btn_pause.setOnClickListener(this);
btn_stop = (Button) findViewById(R.id.btn_stop);
btn_stop.setOnClickListener(this);
btn_goon = (Button) findViewById(R.id.btn_goon);
btn_goon.setOnClickListener(this);
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(path);
mediaPlayer.prepare();
//必須在界面渲染的時候添加,不能在點擊事件中
SurfaceHolder surfaceHolder = sv.getHolder();
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
mediaPlayer.setDisplay(holder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
mediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_pause:
mediaPlayer.pause();
break;
case R.id.btn_stop:
mediaPlayer.stop();
break;
case R.id.btn_goon:
mediaPlayer.start();
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mediaPlayer.stop();
}
}
五.三種播放視頻方式的分析對比
android SDK自帶的 MediaPlayer+SurfaceView或者videoview (簡單快速,格式支持少)
MediaPlayer類是Androd多媒體框架中的一個重要組件,通過該類,我們可以以最小的步驟來獲取,解碼和播放音視頻。它支持三種不同的媒體來源:
在播放網(wǎng)絡(luò)上的視頻流時,Android原生的MediaPlayer支持兩種協(xié)議,HTTP和RTSP,這兩種協(xié)議最大的不同是,RTSP協(xié)議支持實時流媒體的播放,而HTTP協(xié)議不支持。因為VideoView的底層實現(xiàn)是MediaPlayer,因此VideoView也支持以上兩種協(xié)議。 但是Android原生MediaPalyer支持的協(xié)議(不支持RTMP、MMS等)和封裝格式實在太有限了,如果我們想播放那些它不支持的視頻,這時候就需要第三方播放器了,很多第三方播放器的底層實現(xiàn)都是基于FFmpeg,后續(xù)我會專門來講講第三方播放器和FFmpeg的使用。MediaPlayer主要用于播放音頻,沒有提供圖像輸出界面,所以我們需要借助其他的組件來顯示MediaPlayer播放的圖像輸出,我們可以使用SurfaceView來顯示。
除了使用MediaPlayer + SurfaceView播放視頻的方式,我們還可以使用VideoView來直接播放視頻。
SurfaceView播放視頻時,如果不進(jìn)行設(shè)置,視頻寬高總是等于定義的SurfaceView布局寬高,所以視頻可能會被拉伸變形。而使用VideoView時,視頻寬度等于VideoView布局寬,但是高是自適應(yīng)的,自動調(diào)整寬高比到視頻原始比例,所以不會有拉伸。
本地資源,內(nèi)部URI,比如你可以通過ContentResolver來獲取,外部URL(流)
六.播放視頻資源的格式限制
Android官方公布的文檔顯示MediaPlayer支持如下視頻格式:
H.263 X X 3GPP (.3gp)
MPEG-4 (.mp4)?
H.264 AVC X 3GPP (.3gp)
MPEG-4 (.mp4)?
MPEG-4 SP X
3GPP (.3gp)
這些格式的視頻,基本上屬于手機(jī)支持的視頻格式。如果想觀看其他類型格式的視頻,比如flv等,需要下載暴風(fēng)、迅雷等播放器。
七.三方視頻庫
-
Vitamio
Vitamio 是一款 Android與 iOS平臺上的全能多媒體開發(fā)框架,全面支持硬件解碼與 GPU渲染。Vitamio憑借其簡潔易用的 API接口贏得了全球眾多開發(fā)者的青睞。到目前,全球已經(jīng)有超過 1800種應(yīng)用在使用 Vitamio,覆蓋用戶超過 2億。Vitamio 能夠流暢播放720P甚至1080P高清MKV,F(xiàn)LV,MP4,MOV,TS,RMVB等常見格式的視頻,還可以在 Android 與iOS上跨平臺支持 MMS, RTSP,RTMP, HLS(m3u8)等常見的多種視頻流媒體協(xié)議,包括點播與直播。
目前Vitamio的項目托管在Github上面:https://github.com/yixia
JiaoZiVideoPlayer(以前叫節(jié)操播放器)
節(jié)操播放器ijkplayer
項目地址
介紹:Ijkplayer 是Bilibili發(fā)布的基于 FFplay 的輕量級 Android/iOS 視頻播放器。實現(xiàn)了跨平臺功能,API 易于集成;編譯配置可裁剪,方便控制安裝包大??;支持硬件加速解碼,更加省電;提供 Android 平臺下應(yīng)用彈幕集成的解決方案。
八.獲取視頻的第一幀
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(data);
//timeUs 微秒
//option
//OPTION_CLOSEST 在給定的時間,檢索最近一個幀,這個幀不一定是關(guān)鍵幀。
//OPTION_CLOSEST_SYNC 在給定的時間,檢索最近一個同步幀(關(guān)鍵幀)。
//OPTION_NEXT_SYNC 在給定時間之后檢索一個同步幀(關(guān)鍵幀)。
//OPTION_PREVIOUS_SYNC 在給定時間之前檢索一個同步幀(關(guān)鍵幀)
Bitmap frameAtTime = retriever.getFrameAtTime(7000*1000, MediaMetadataRetriever.OPTION_CLOSEST);
mIv.setImageBitmap(frameAtTime);
九.橫豎屏切換
/**
* 切換橫豎屏
*/
private void switchScreen() {
/*if (現(xiàn)在是橫屏){
//切換豎屏
}else {
//切換成橫屏
}*/
///切換屏幕的時候,Activity會重建,怎么解決
//在清單文件配置一下就ok,
//獲取當(dāng)前屏幕方向
int requestedOrientation = getRequestedOrientation();
if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE){
//橫屏,切換豎屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}else {
//切換成橫屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
//screensize,屏幕大小發(fā)生改變;
//orientation屏幕方向發(fā)生改變
//keyboardHidden鍵盤隱藏
-->
<activity
android:name=".VideoViewActivity"
android:configChanges="screenSize|orientation|keyboardHidden" />