Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 使用PLDroidPlayer播放網絡視頻 根據視頻角度自動旋轉

Android 使用PLDroidPlayer播放網絡視頻 根據視頻角度自動旋轉

編輯:關於Android編程

最近因為項目需求 ,需要播放網絡視頻 ,於是乎 研究了一番 ,說說我遇到的那些坑

現在市面上有幾個比較主流好用的第三方框架

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


... 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:" + 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. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved