本文转载:http://blog.csdn.net/yewei02538/article/details/51882933

现在播放网络视频市面上有几个比较主流好用的第三方框架

  • Vitamio ( 体积比较大,有商业化风险 github:https://github.com/yixia/VitamioBundle/)
  • ijkplayer(B站下开源的框架 体积大 配置环境比较麻烦 github:https://github.com/Bilibili/ijkplayer )
  • PLDroidPlayer(七牛根据ijkplayer二次开发的 定制简单 github:https://github.com/pili-engineering/PLDroidPlayer)

当然还有很多别的视频播放框架 因为我只找到这几个= =!

因为项目比较急,所以我用的比较简单的 PLDroidPlayer

首先把需要的jar包和jni文件拷到你的项目中

这个里面有很多控件,你们可以根据自己的需求来用指定的控件,我用的是PLVideoTextureView

<com.pili.pldroid.player.widget.PLVideoTextureView        android:id="@+id/videoView"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_centerInParent="true" />

具体使用:

public class PLVideoTextureActivity extends AppCompatActivity {    private MediaController mMediaController;    private PLVideoTextureView mVideoView;    private Toast mToast = null;    private String mVideoPath = null;    private int mRotation = 0;    private int mDisplayAspectRatio = PLVideoTextureView.ASPECT_RATIO_FIT_PARENT; //default    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);        setContentView(R.layout.activity_pl_video_texture);        mVideoView = (PLVideoTextureView) findViewById(R.id.videoView);        View loadingView = findViewById(R.id.LoadingView);        mVideoView.setBufferingIndicator(loadingView);        mVideoPath = getIntent().getStringExtra("videoPath");        // If you want to fix display orientation such as landscape, you can use the code show as follow        //        // if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {        // mVideoView.setPreviewOrientation(0);        // }        // else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {        // mVideoView.setPreviewOrientation(270);        // }        mVideoPath = getIntent().getStringExtra("videoPath");        AVOptions options = new AVOptions();        int isLiveStreaming = getIntent().getIntExtra("liveStreaming", 1);        // the unit of timeout is ms        options.setInteger(AVOptions.KEY_PREPARE_TIMEOUT, 10 * 1000);        options.setInteger(AVOptions.KEY_GET_AV_FRAME_TIMEOUT, 10 * 1000);        // Some optimization with buffering mechanism when be set to 1        options.setInteger(AVOptions.KEY_LIVE_STREAMING, isLiveStreaming);        if (isLiveStreaming == 1) {            options.setInteger(AVOptions.KEY_DELAY_OPTIMIZATION, 1);        }        // 1 -> hw codec enable, 0 -> disable [recommended]        int codec = getIntent().getIntExtra("mediaCodec", 0);        options.setInteger(AVOptions.KEY_MEDIACODEC, codec);        // whether start play automatically after prepared, default value is 1        options.setInteger(AVOptions.KEY_START_ON_PREPARED, 0);        mVideoView.setAVOptions(options);        // You can mirror the display        // mVideoView.setMirror(true);        // You can also use a custom `MediaController` widget        mMediaController = new MediaController(this, false, isLiveStreaming == 1);        mVideoView.setMediaController(mMediaController);        mVideoView.setOnInfoListener(mOnInfoListener);// mVideoView.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);        mVideoView.setOnBufferingUpdateListener(mOnBufferingUpdateListener);        mVideoView.setOnCompletionListener(mOnCompletionListener);        mVideoView.setOnSeekCompleteListener(mOnSeekCompleteListener);        mVideoView.setOnErrorListener(mOnErrorListener);        mVideoView.setVideoPath(mVideoPath);        mVideoView.setDisplayAspectRatio(PLVideoView.ASPECT_RATIO_PAVED_PARENT);        mVideoView.setOnPreparedListener(mOnPreparedListener);        mVideoView.setOnVideoSizeChangedListener(new PLMediaPlayer.OnVideoSizeChangedListener() {            @Override            public void onVideoSizeChanged(PLMediaPlayer plMediaPlayer, int width, int height) {                Logger.i("width:" + width + "---heightL:" + height);                if (width > height) {                    //视频是横屏 旋转方向                   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);                }            }        });        mVideoView.setVideoPath(mVideoPath);        mVideoView.start();    }    @Override    protected void onPause() {        super.onPause();        mToast = null;        mVideoView.pause();    }    @Override    protected void onResume() {        super.onResume();        mVideoView.start();    }    @Override    protected void onDestroy() {        super.onDestroy();        mVideoView.stopPlayback();    }    public void onClickRotate(View v) {        mRotation = (mRotation + 90) % 360;        mVideoView.setDisplayOrientation(mRotation);    }    public void onClickSwitchScreen(View v) {        mDisplayAspectRatio = (mDisplayAspectRatio + 1) % 5;        mVideoView.setDisplayAspectRatio(mDisplayAspectRatio);        switch (mVideoView.getDisplayAspectRatio()) {            case PLVideoTextureView.ASPECT_RATIO_ORIGIN:                showToastTips("Origin mode");                break;            case PLVideoTextureView.ASPECT_RATIO_FIT_PARENT:                showToastTips("Fit parent !");                break;            case PLVideoTextureView.ASPECT_RATIO_PAVED_PARENT:                showToastTips("Paved parent !");                break;            case PLVideoTextureView.ASPECT_RATIO_16_9:                showToastTips("16 : 9 !");                break;            case PLVideoTextureView.ASPECT_RATIO_4_3:                showToastTips("4 : 3 !");                break;            default:                break;        }    }    private PLMediaPlayer.OnErrorListener mOnErrorListener = new PLMediaPlayer.OnErrorListener() {        @Override        public boolean onError(PLMediaPlayer mp, int errorCode) {            switch (errorCode) {                case PLMediaPlayer.ERROR_CODE_INVALID_URI:                    showToastTips("Invalid URL !");                    break;                case PLMediaPlayer.ERROR_CODE_404_NOT_FOUND:                    showToastTips("404 resource not found !");                    break;                case PLMediaPlayer.ERROR_CODE_CONNECTION_REFUSED:                    showToastTips("Connection refused !");                    break;                case PLMediaPlayer.ERROR_CODE_CONNECTION_TIMEOUT:                    showToastTips("Connection timeout !");                    break;                case PLMediaPlayer.ERROR_CODE_EMPTY_PLAYLIST:                    showToastTips("Empty playlist !");                    break;                case PLMediaPlayer.ERROR_CODE_STREAM_DISCONNECTED:                    showToastTips("Stream disconnected !");                    break;                case PLMediaPlayer.ERROR_CODE_IO_ERROR:                    showToastTips("Network IO Error !");                    break;                case PLMediaPlayer.ERROR_CODE_UNAUTHORIZED:                    showToastTips("Unauthorized Error !");                    break;                case PLMediaPlayer.ERROR_CODE_PREPARE_TIMEOUT:                    showToastTips("Prepare timeout !");                    break;                case PLMediaPlayer.ERROR_CODE_READ_FRAME_TIMEOUT:                    showToastTips("Read frame timeout !");                    break;                case PLMediaPlayer.MEDIA_ERROR_UNKNOWN:                default:                    showToastTips("unknown error !");                    break;            }            // Todo pls handle the error status here, retry or call finish()            finish();            // If you want to retry, do like this:            // mVideoView.setVideoPath(mVideoPath);            // mVideoView.start();            // Return true means the error has been handled            // If return false, then `onCompletion` will be called            return true;        }    };     private PLMediaPlayer.OnCompletionListener mOnCompletionListener = new PLMediaPlayer.OnCompletionListener() {        @Override        public void onCompletion(PLMediaPlayer plMediaPlayer) {// finish();            showToast("视频播放完成");        }    };    private PLMediaPlayer.OnBufferingUpdateListener mOnBufferingUpdateListener = new PLMediaPlayer.OnBufferingUpdateListener() {        @Override        public void onBufferingUpdate(PLMediaPlayer plMediaPlayer, int precent) {        }    };    private PLMediaPlayer.OnSeekCompleteListener mOnSeekCompleteListener = new PLMediaPlayer.OnSeekCompleteListener() {        @Override        public void onSeekComplete(PLMediaPlayer plMediaPlayer) {            Logger.d("onSeekComplete !");        }    };    private PLMediaPlayer.OnPreparedListener mOnPreparedListener = new PLMediaPlayer.OnPreparedListener() {        @Override        public void onPrepared(PLMediaPlayer plMediaPlayer) {        }    };    private PLMediaPlayer.OnInfoListener mOnInfoListener = new PLMediaPlayer.OnInfoListener() {        @Override        public boolean onInfo(PLMediaPlayer plMediaPlayer, int what, int extra) {            switch (what) {                case PLMediaPlayer.MEDIA_INFO_BUFFERING_START:                    Logger.i("正在缓冲----");                    //开始缓存,暂停播放                    if (isPlaying()) {// stopPlayer();                        if (mVideoView != null) {                            mVideoView.pause();                        }                        needResume = true;                    }                    rl_loading.setVisibility(View.VISIBLE);                    break;                case PLMediaPlayer.MEDIA_INFO_BUFFERING_END:                case PLMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:                    Logger.i("缓冲完成----");                    //缓存完成,继续播放                    if (needResume)// startPlayer();                        if (mVideoView != null) {                            mVideoView.start();                        }                    rl_loading.setVisibility(View.GONE);                    break;                case PLMediaPlayer.MEDIA_INFO_BUFFERING_BYTES_UPDATE:                    //显示 下载速度                    Logger.e("download rate:" + extra);                    //mListener.onDownloadRateChanged(arg2);                    break;            }            Logger.i("onInfo:" + what + "___" + extra);            return false;        }    };}

这样就完成了普通视频的播放和旋转视频播放。

看似简单 其实隐藏着大问题 ,也就是我所说的大坑
现在我是这样判断角度的 当视频的宽度大于高度的 我就认为这是一个横屏的视频 ,也就是说假如这个视频是1330X720(我随便说的尺寸,只为举例)现在宽度大于高度了 那么这就是一个横屏的视频,但是我只要播放手机拍摄的视频就会发现视频被放大了 ,但是其实我录制视频的时候是竖着排的 ,可视播放的时候却给我横着过来了,然后我就去看这个手机拍摄视频的尺寸 现在一般录制视频最低都是1280X720 ,恰好符合我判断的逻辑 ,难道他真是横着的? 然后我就用系统自带的播放器打开 ,居然没有横过来 ,而是竖着播放的 ,可它是怎么知道这个方向呢?于是我在百度搜 ,确实可以获取到本地视频的角度,但是好像低版本好像不兼容,然后根据角度去判断 是否需要旋转,可是我这个是网络视频啊 ,网络视频怎么获取到视频角度啊 ? 我第一反应是 上传视频的时候把宽高角度传到服务器 ,然后获取的时候根据这个角度旋转 ,但是别人播放网络视频的时候也没有传角度过去啊 - - 然后我就在github上面问那个作者 ,结果他说:

“onInfo: 10001, 90”, 收到这个消息后,使用 PLVideoTextureView 的 setDisplayOrientation 旋转显示的方向,后面会补充这个回调的接口和文档。

然后我就修改了下代码:

/** * 视频的方向 */private int mVideoRotation;    private boolean needResume;    private PLMediaPlayer.OnInfoListener mOnInfoListener = new PLMediaPlayer.OnInfoListener() {        @Override        public boolean onInfo(PLMediaPlayer plMediaPlayer, int what, int extra) {            switch (what) {                case PLMediaPlayer.MEDIA_INFO_BUFFERING_START:                    Logger.i("正在缓冲----");                    //开始缓存,暂停播放                    if (isPlaying()) {// stopPlayer();                        if (mVideoView != null) {                            mVideoView.pause();                        }                        needResume = true;                    }                    rl_loading.setVisibility(View.VISIBLE);                    break;                case PLMediaPlayer.MEDIA_INFO_BUFFERING_END:                case PLMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:                    Logger.i("缓冲完成----");                    //缓存完成,继续播放                    if (needResume)// startPlayer();                        if (mVideoView != null) {                            mVideoView.start();                        }                    rl_loading.setVisibility(View.GONE);                    break;                case PLMediaPlayer.MEDIA_INFO_BUFFERING_BYTES_UPDATE:                    //显示 下载速度                    Logger.e("download rate:" + extra);                    //mListener.onDownloadRateChanged(arg2);                    break;                case 10001:                    //保存视频角度                    mVideoRotation=extra;                    break;            }            Logger.i("onInfo:" + what + "___" + extra);            return false;        }    };

然后在onVideoSizeChanged的回调里这样

 mVideoView.setOnVideoSizeChangedListener(new PLMediaPlayer.OnVideoSizeChangedListener() {            @Override            public void onVideoSizeChanged(PLMediaPlayer plMediaPlayer, int width, int height) {                Logger.i("width:" + width + "---heightL:" + height);                if (width > height&&mVideoRotation==0) {                    //旋转方向                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);                }                //如果视频角度是90度                if(mVideoRotation==90)                {                   //旋转视频                    mVideoView.setDisplayOrientation(270);                }            }        });

这样 不管是什么视频 播放终于正常了 - -

更多相关文章

  1. 每个Android迷应该使用的75个超酷app
  2. Android播放音频之按钮控制
  3. android一步一步实现视频客户端app(一)
  4. 基于android的网络音乐播放器-网络音乐的搜索和展示(五)
  5. Android多媒体学习七:访问网络上的Audio对应的M3U文件,实现网络音
  6. Android(安卓)短视频编辑开发之摄像头预览实时美颜(三)
  7. 自定义Drawable实现灵动的红鲤鱼动画(上篇)
  8. Android(安卓)Volley完全解析(四),带你从源码的角度理解Volley
  9. Android(安卓)录制手机屏幕视频生成GIF图片实例详解

随机推荐

  1. Android设置手机音量
  2. Android(安卓)监控 网络连接状态
  3. 安卓(android)统计图表の曲线图,折线图
  4. Android同步网络请求工具类HttpURLConnec
  5. android 沉浸式状态栏
  6. android点击界面隐藏键盘
  7. Google cardBoard Android(安卓)API (七)
  8. cocos2d-x获取设备信息
  9. 自带finish清除网络请求的Activity
  10. android编译时报错