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;
-
-
-
-
-
-
-
-
-
- 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();
- }
-
-
-
-
-
- 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;
- }
-
-
- 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);
-
- 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;
- }
- }
- });
- }
-
-
-
-
-
- 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;
-
-
- 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.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() {
-
- if(mVideoView!=null){
- mVideoView.stopPlayback();
- }
- super.onDestroy();
- }
-
-
- }