Android 使用PLDroidPlayer播放网络视频 根据视频角度自动旋转

来源:互联网 发布:ubuntu 声音图标 灰色 编辑:程序博客网 时间:2024/05/20 09:48

现在市面上有几个比较主流好用的第三方框架

  • 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/video"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_centerInParent="true" />

然后findviewbyid找到它

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;        }    };
  • 1
  • 2

然后在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

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

原文地址:http://blog.csdn.net/yewei02538/article/details/51882933

阅读全文
0 0