Rotating an android VideoView

后端 未结 4 1947
迷失自我
迷失自我 2020-11-27 18:43

My application offers only Portrait mode. In a portrait activity I have a fullscreen VideoView. What I want to do is rotate the VideoView ( the actual video, videobuffer) 90

相关标签:
4条回答
  • 2020-11-27 19:12

    VideoView does not support rotation

    you can use

    <com.warnyul.android.widget.FastVideoView
            android:rotation="45"
            android:layout_above="@+id/controller"
            android:id="@+id/video2"
            android:foregroundGravity="center"
            android:layout_centerHorizontal="true"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            />
    

    and must add bellow line to your dependencies in gradle

    implementation 'com.warnyul.android.fast-video-view:fast-video-view:1.0.2'
    
    0 讨论(0)
  • 2020-11-27 19:17

    VideoView does not support rotation of video even if composition matrix is set correctly and rotation attribute is used.

    What you can do is to use TextureView and set its attribute rotation="90" (for example). It then will rotate the frames but the aspect ratio is something that you need to handle your self. In order to do so you can use textureView.setScaleX((screenHeight * 1.0f) / screenWidth)

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <TextureView
            android:id="@+id/playback_video"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerInParent="true"
            android:rotation="90" />
    </RelativeLayout>
    

    It should handle streamed video too. But please think of it as of an example rather than release ready code. I renamed some things and removed others, they don't have relation to the question and this might break something but in general this is workable example.

    public class PlaybackActivity extends Activity implements MediaPlayer.OnErrorListener, OnPreparedListener,
            OnCompletionListener, OnVideoSizeChangedListener, OnBufferingUpdateListener, OnInfoListener,
            SurfaceTextureListener
    {
    
        private MediaPlayer mediaPlayer;
        private TextureView videoView;
        private boolean startedPlayback = false;
        private boolean playerReady = false;
        public static final int MEDIA_INFO_NETWORK_BANDWIDTH = 703;
    
        private void createMediaPlayer() {
            mediaPlayer = new MediaPlayer();
        }
    
        private void releaseMediaPlayer() {
            if (mediaPlayer != null) {
                mediaPlayer.setSurface(null);
                mediaPlayer.release();
                mediaPlayer = null;
            }
        }
    
        public void onCompletion(MediaPlayer mp) {
            Log.w(TAG, "Video playback finished");
        }
    
        @Override
        public boolean onError(MediaPlayer player, int what, int extra) {
            if (what == MediaPlayer.MEDIA_ERROR_UNKNOWN) {
                /*
                 * Restart play back in case we did not start anything yet. This may
                 * be the case when we tried to tune in in very first secs of the
                 * broadcast when there is no data yet.
                 */
                if (liveBroadcast && mediaPlayer != null && !mediaPlayer.isPlaying() && !startedPlayback) {
                    if (checkCount-- > 0) {
                        mediaPlayer.reset();
                        checkBroadcast();
                    } else {
                        Log.w(TAG, "Broadcast finished");
                    }
                } else {
                    Log.w(TAG, "No media in stream");
                }
            } else if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
                Log.w(TAG, "Media service died unexpectedly");
            } else {
                Log.w(TAG, "Unknown media error");
            }
            return true;
        }
    
       @Override
        public boolean onInfo(MediaPlayer mp, int what, int extra) {
            switch (what) {
            case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING:
                Log.w(TAG, "Media is too complex to decode it fast enough.");
                startedPlayback = true;
                break;
            case MEDIA_INFO_NETWORK_BANDWIDTH:
                Log.w(TAG, "Bandwith in recent past.");
                break;
            case MediaPlayer.MEDIA_INFO_BUFFERING_START:
                Log.w(TAG, "Start of media bufferring.");
                startedPlayback = true;
                break;
            case MediaPlayer.MEDIA_INFO_BUFFERING_END:
                Log.w(TAG, "End of media bufferring.");
                startedPlayback = true;
                break;
            case MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING:
                Log.w(TAG, "Media is not properly interleaved.");
                break;
            case MediaPlayer.MEDIA_INFO_NOT_SEEKABLE:
                Log.w(TAG, "Stream is not seekable.");
                break;
            case MediaPlayer.MEDIA_INFO_METADATA_UPDATE:
                Log.w(TAG, "New set of metadata is available.");
                break;
            case MediaPlayer.MEDIA_INFO_UNKNOWN:
            default:
                Log.w(TAG, "Unknown playback info (" + what + ":" + extra + ").");
                break;
            }
            return true;
        }
    
        private void startPlayback() {
            if (mediaPlayer != null) {
                onLoaded(mediaPlayer);
                mediaPlayer.start();
            }
        }
    
        private void pausePlayback() {
            if (mediaPlayer != null && mediaPlayer.isPlaying())
                mediaPlayer.pause();
        }
    
        private void resumePlayback() {
            if (mediaPlayer != null && mediaPlayer.isPlaying())
                mediaPlayer.start();
        }
    
        private void onLoaded(MediaPlayer mp) {
        }
    
        public void onPrepared(MediaPlayer mp) {
            playerReady = true;
            startPlayback();
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
            setContentView(R.layout.playback);
            videoView = (TextureView) findViewById(R.id.playback_video);
            videoView.setOnClickListener(videoViewClickHandler);
            videoView.setSurfaceTextureListener(this);
            createMediaPlayer();
        }
    
       @Override
        protected void onDestroy() {
            releaseMediaPlayer();
            if (surface != null) {
                surface.release();
                surface = null;
            }
            super.onDestroy();
        }
    
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            this.surface = new Surface(surface);
            loadMedia(someurl);
        }
    
        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
            if (this.surface != null) {
                releaseMediaPlayer();
                this.surface.release();
                this.surface = null;
            }
            return true;
        }
    
        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        }
    
        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        }
    
        @Override
        public void onVideoSizeChanged(MediaPlayer mp, int w, int h) {
            if (w > 0 && h > 0 && !videoSizeSetupDone) {
                Log.w(TAG, "Video size changed: " + w + "x" + h);
                changeVideoSize(w, h);
            }
        }
    
        private boolean videoSizeSetupDone = false;
    
        private void changeVideoSize(int width, int height) {
            DisplayMetrics metrics = new DisplayMetrics();
            RelativeLayout.LayoutParams params;
    
            Utils.getScreenMetrics(this, metrics);
            VideoOrientation orientation = someVideoSource.getVideoOrientation();
            if (orientation == LANDSCAPE) {
                params = new RelativeLayout.LayoutParams(metrics.widthPixels, metrics.heightPixels);
            } else {
                float rotation = orientation == BroadcastVideoOrientation.BroadcastVideoFrontCamera ? -90.0f : 90.0f;
                params = new RelativeLayout.LayoutParams(metrics.heightPixels, metrics.widthPixels);
                float scale = (width * 1.0f) / (height * 1.0f);
                videoView.setRotation(rotation);
                videoView.setScaleX(scale);
            }
            params.addRule(RelativeLayout.CENTER_IN_PARENT, -1);
            videoView.setLayoutParams(params);
            videoSizeSetupDone = true;
        }
    
        private void loadMedia(String url) {
            if (surface == null)
                return;
            Log.d(App.TAG, "Loading url: " + url);
    
            startedPlayback = false;
            try {
                mediaPlayer.reset();
                mediaPlayer.setSurface(surface);
                mediaPlayer.setDataSource(url);
                mediaPlayer.setOnPreparedListener(this);
                mediaPlayer.setOnCompletionListener(this);
                mediaPlayer.setOnErrorListener(this);
                mediaPlayer.setOnVideoSizeChangedListener(this);
                mediaPlayer.setScreenOnWhilePlaying(true);
                mediaPlayer.setOnBufferingUpdateListener(this);
                mediaPlayer.setOnInfoListener(this);
                mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mediaPlayer.prepareAsync();
            } catch (Exception e) {
                Log.w(TAG, "Media load failed");
                Utils.alert(this, "Playback Error", e.getMessage(), finishHandler);
            }
        }
    }
    

    Hope this helps. I was looking for this solution for quite long time. Tried almost everything and this seems to be the only way.

    0 讨论(0)
  • 2020-11-27 19:18
     <TextureView
            android:id="@+id/VideoViewfull"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:rotation="90"
        /> 
    mMediaPlayer.setOnVideoSizeChangedListener(newMediaPlayer.OnVideoSizeChangedListener() {
                    @Override
                    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
                        if (width < height) {
    //                        orientation = "vertical";
                            mTextureView.setRotation(90f);
                        } else {
                            DisplayMetrics displayMetrics = new DisplayMetrics();
                       getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
                            int sHeight = displayMetrics.heightPixels;
                            int sntWidth = displayMetrics.widthPixels;
                            FrameLayout.LayoutParams parms = 
                            new FrameLayout.LayoutParams(sHeight,sHeight); 
                            mTextureView.setLayoutParams(parms);
                        }
                    }
                });
    
    0 讨论(0)
  • 2020-11-27 19:19

    You can set the oriantation individually of an activity in the manifest, so your video can be displayed in landscape (and portrait) while the rest of your application is in portrait. see my answer here for a solution on this.

    0 讨论(0)
提交回复
热议问题