Android播放本地文件視頻是硬解,這樣對CPU佔用比較少,所以將直播收到的數據臨時緩存3個文件,給定每個文件的大小,然後進行播放。後續還會進行優化。
具體實現代碼如下:
- package com.cayden.videodemo;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.net.DatagramPacket;
- import java.net.DatagramSocket;
- import android.app.Activity;
- import android.app.ProgressDialog;
- import android.content.Intent;
- import android.media.MediaPlayer;
- import android.media.MediaPlayer.OnCompletionListener;
- import android.media.MediaPlayer.OnErrorListener;
- import android.media.MediaPlayer.OnPreparedListener;
- import android.os.Bundle;
- import android.os.Environment;
- import android.os.Handler;
- import android.os.Message;
- import android.util.Log;
- import android.view.View;
- import android.widget.MediaController;
- import android.widget.TextView;
- import android.widget.VideoView;
- import com.cayden.videodemo.R;
- /**
- *
- * 接收UDP TS流實現邊緩存邊播放<br/>
- * 該類可以實現,但存在以下不足<br/>
- * 1、播放過程會稍微卡一下這是 由於播放時候setOnCompletionListener中方法被執行<br/>
- * 2、需要思考怎麼解決調用onError方法
- * @author cuiran
- * @version 1.0.0
- */
- public class UDPFileMPlayer extends Activity {
- private static final String TAG="UDPFileMPlayer";
- private VideoView mVideoView;
- private TextView tvcache;
- private String remoteUrl;
- private String localUrl;
- private ProgressDialog progressDialog = null;
- private Thread receiveThread=null;
- /**
- * 定義了初始緩存區的大小,當視頻加載到初始緩存區滿的時候,播放器開始播放,
- */
- private static final int READY_BUFF = 1316 * 1024*10;
- private static final String FILE_DIR=Environment.getExternalStorageDirectory().getAbsolutePath()+"/VideoCache/";
- /**
- * 核心交換緩存區,主要是用來動態調節緩存區,當網絡環境較好的時候,該緩存區爲初始大小,
- * 當網絡環境差的時候,該緩存區會動態增加,主要就是爲了避免視頻播放的時候出現一卡一卡的現象。
- */
- private static final int CACHE_BUFF = 10 * 1024;
- /**
- * 單播或組播端口
- */
- private static final int PORT = 1234;
- private boolean isready = false;
- private boolean iserror = false;
- private int errorCnt = 0;
- private int curPosition = 0;
- private long mediaLength = 0;
- private long readSize = 0;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.bbvideoplayer);
- findViews();
- init();
- playvideo();
- }
- /**
- * 初始化組件
- * 2013-11-21 下午2:20:10
- *
- */
- private void findViews() {
- this.mVideoView = (VideoView) findViewById(R.id.bbvideoview);
- this.tvcache = (TextView) findViewById(R.id.tvcache);
- }
- private void init() {
- Intent intent = getIntent();
- this.remoteUrl = intent.getStringExtra("url");
- System.out.println("remoteUrl: " + remoteUrl);
- if (this.remoteUrl == null) {
- finish();
- return;
- }
- // this.localUrl = intent.getStringExtra("cache");
- mVideoView.setMediaController(new MediaController(this));
- mVideoView.setOnPreparedListener(new OnPreparedListener() {
- public void onPrepared(MediaPlayer mediaplayer) {
- Log.i(TAG, "onPrepared");
- dismissProgressDialog();
- mVideoView.seekTo(curPosition);
- mediaplayer.start();
- }
- });
- mVideoView.setOnCompletionListener(new OnCompletionListener() {
- public void onCompletion(MediaPlayer mediaplayer) {
- Log.i(TAG, "onCompletion"+localUrl);
- // curPosition = 0;
- if(localUrl.endsWith("1.mp4")){
- localUrl=localUrl.replace("1.mp4", "2.mp4");
- mVideoView.setVideoPath(localUrl);
- mVideoView.start();
- }else if(localUrl.endsWith("2.mp4")){
- localUrl=localUrl.replace("2.mp4", "3.mp4");
- mVideoView.setVideoPath(localUrl);
- mVideoView.start();
- }else{
- localUrl=localUrl.replace("3.mp4", "1.mp4");
- mVideoView.setVideoPath(localUrl);
- mVideoView.start();
- }
- }
- });
- mVideoView.setOnErrorListener(new OnErrorListener() {
- public boolean onError(MediaPlayer mediaplayer, int i, int j) {
- Log.i(TAG, "onError");
- iserror = true;
- errorCnt++;
- mVideoView.pause();
- showProgressDialog();
- return true;
- }
- });
- }
- private void showProgressDialog() {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (progressDialog == null) {
- progressDialog = ProgressDialog.show(UDPFileMPlayer.this,
- "視頻緩存", "正在努力加載中 ...", true, false);
- }
- }
- });
- }
- private void dismissProgressDialog() {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (progressDialog != null) {
- progressDialog.dismiss();
- progressDialog = null;
- }
- }
- });
- }
- /**
- * 播放視頻
- * 2013-11-21 下午2:20:34
- *
- */
- private void playvideo() {
- showProgressDialog();
- receiveThread=new Thread(new Runnable() {
- @Override
- public void run() {
- FileOutputStream out = null;
- DatagramSocket dataSocket=null;
- DatagramPacket dataPacket=null;
- try {
- dataSocket = new DatagramSocket(PORT);
- byte[] receiveByte = new byte[8192];
- dataPacket = new DatagramPacket(receiveByte, receiveByte.length);
- Log.i(TAG, "UDP服務啓動...");
- if (localUrl == null) {
- localUrl = FILE_DIR+"1.mp4";
- }
- Log.i(TAG, "localUrl="+localUrl);
- File cacheFile = new File(localUrl);
- if (!cacheFile.exists()) {
- cacheFile.getParentFile().mkdirs();
- cacheFile.createNewFile();
- }
- out = new FileOutputStream(cacheFile, true);
- int size = 0;
- long lastReadSize = 0;
- int number=0;
- int fileNum=0;
- // mHandler.sendEmptyMessage(VIDEO_STATE_UPDATE);
- while(size==0){
- // 無數據,則循環
- dataSocket.receive(dataPacket);
- size = dataPacket.getLength();
- if (size > 0) {
- try {
- if(readSize>=READY_BUFF){
- fileNum++;
- switch(fileNum%3){
- case 0:
- out=new FileOutputStream(FILE_DIR+"1.mp4");
- break;
- case 1:
- out=new FileOutputStream(FILE_DIR+"2.mp4");
- break;
- case 2:
- out=new FileOutputStream(FILE_DIR+"3.mp4");
- break;
- }
- readSize=0;
- if (!isready) {
- mHandler.sendEmptyMessage(CACHE_VIDEO_READY);
- }
- }
- out.write(dataPacket.getData(), 0, size);
- out.flush();
- readSize += size;
- size = 0;// 循環接收
- } catch (Exception e) {
- Log.e(TAG, "出現異常0",e);
- }
- }else{
- Log.i(TAG, "TS流停止發送數據");
- }
- }
- mHandler.sendEmptyMessage(CACHE_VIDEO_END);
- } catch (Exception e) {
- Log.e(TAG, "出現異常",e);
- } finally {
- if (out != null) {
- try {
- out.close();
- } catch (IOException e) {
- //
- Log.e(TAG, "出現異常1",e);
- }
- }
- if (dataSocket != null) {
- try {
- dataSocket.close();
- } catch (Exception e) {
- Log.e(TAG, "出現異常2",e);
- }
- }
- }
- }
- });
- receiveThread.start();
- }
- private final static int VIDEO_STATE_UPDATE = 0;
- /**
- * 緩存準備
- */
- private final static int CACHE_VIDEO_READY = 1;
- /**
- * 緩存修改
- */
- private final static int CACHE_VIDEO_UPDATE = 2;
- /**
- * 緩存結束
- */
- private final static int CACHE_VIDEO_END = 3;
- /**
- * 緩存播放
- */
- private final static int CACHE_VIDEO_PLAY = 4;
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case VIDEO_STATE_UPDATE:
- boolean isPlay=mVideoView.isPlaying();
- Log.i(TAG, "更新顯示 isPlay="+isPlay);
- double cachepercent = readSize * 100.00 / mediaLength * 1.0;
- String s = String.format("已緩存: [%.2f%%]", cachepercent);
- if (isPlay) {
- curPosition = mVideoView.getCurrentPosition();
- int duration = mVideoView.getDuration();
- duration = duration == 0 ? 1 : duration;
- double playpercent = curPosition * 100.00 / duration * 1.0;
- int i = curPosition / 1000;
- int hour = i / (60 * 60);
- int minute = i / 60 % 60;
- int second = i % 60;
- s += String.format(" 播放: %02d:%02d:%02d [%.2f%%]", hour,
- minute, second, playpercent);
- }
- //
- // tvcache.setText(s);
- tvcache.setVisibility(View.GONE);
- mHandler.sendEmptyMessageDelayed(VIDEO_STATE_UPDATE, 1000);
- break;
- case CACHE_VIDEO_READY:
- Log.i(TAG, "緩存準備");
- isready = true;
- mVideoView.setVideoPath(localUrl);
- mVideoView.start();
- break;
- case CACHE_VIDEO_UPDATE:
- Log.i(TAG, "緩存修改"+iserror);
- if (iserror) {
- mVideoView.setVideoPath(localUrl);
- mVideoView.start();
- iserror = false;
- }
- break;
- case CACHE_VIDEO_END:
- Log.i(TAG, "緩存結束"+iserror);
- if (iserror) {
- mVideoView.setVideoPath(localUrl);
- mVideoView.start();
- iserror = false;
- }
- break;
- case CACHE_VIDEO_PLAY:
- Log.i(TAG, "CACHE_VIDEO_PLAY");
- mVideoView.setVideoPath(localUrl);
- mVideoView.start();
- mHandler.sendEmptyMessageDelayed(CACHE_VIDEO_PLAY, 5000);
- break;
- }
- super.handleMessage(msg);
- }
- };
- @Override
- protected void onDestroy() {
- // TODO Auto-generated method stub
- if(mVideoView!=null){
- mVideoView.stopPlayback();
- }
- super.onDestroy();
- }
- }
分享是人類進步的源泉,可參考:http://blog.csdn.net/cuiran/article/details/40855677