本文主要是介绍Android-接收UDP TS流实现边缓存边播放,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
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
这篇关于Android-接收UDP TS流实现边缓存边播放的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!