• Android 使用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" />
    ... prompt'''

    然后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 + "---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 。恰好符合我推断的逻辑 。难道他真是横着的? 然后我就用系统自带的播放器打开 ,竟然没有横过来 ,而是竖着播放的 ,可它是怎么知道这个方向呢?于是我在百度搜 。确实能够获取到本地视频的角度。可是好像低版本号好像不兼容,然后依据角度去推断 是否须要旋转。可是我这个是网络视频啊 ,网络视频怎么获取到视频角度啊 ? 我第一反应是 上传视频的时候把宽高角度传到server ,然后获取的时候依据这个角度旋转 ,可是别人播放网络视频的时候也没有传角度过去啊 - - 然后我就在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 + "---heightL:" + height);
                    if (width > height&&mVideoRotation==0) {
                        //旋转方向
                        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    }
                    //假设视频角度是90度
                    if(mVideoRotation==90)
                    {
                       //旋转视频
                        mVideoView.setDisplayOrientation(270);
                    }
    
                }
            });

    这样 无论是什么视频 播放最终正常了 - -

    转载请注明出处 http://www.weyye.me/detail/Android-PLDroidPlayer%E6%92%AD%E6%94%BE/

  • 相关阅读:
    Java 的字符串,String、StringBuffer、StringBuilder 有什么区别?
    访问一个HTTPS的网站的大致流程
    Spring Boot Mybatis-Plus
    Spring Boot REST
    Spring Boot 以 war 方式部署
    MVC 框架
    HDFS,MongoDB,HBase的区别和使用场景
    什么时候该用NoSQL?
    最近和朋友微信卖螃蟹有点偏离重心了
    我要出去~
  • 原文地址:https://www.cnblogs.com/llguanli/p/8733945.html
Copyright © 2020-2023  润新知