Playing VR Video through Android

Keywords: Android Google SDK xml

The implementation of VR video playback is similar to the previous VR panorama display. What changes is only the difference of library files and resources under the resource directory. Here are the steps.

Let's show you the effect first.
Complete the steps:
1. Import library files by importing Moudle. (video widget, common, commonwidget) resource access link: https://github.com/googlevr/gvr-android-sdk/
2. Create new asset directory asstes under main and put in video resources
3. Increase the alert permission android:largeHeap= "true" in the manifest file application
4. Add dependencies in Mouldlede's build.grable file
compile 'com.google.android.exoplayer:exoplayer:r1.5.10'
compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7'
5. Dependency libraries for associated imports
6 Complete the layout in xml, video.VrVideoView, AppCompatSeekBar, TextView
7. Using AsyncTask (or EventBus technology) to load videos
8. VR optimization using threads.
9. The Monitoring Effect of Setting up VR

Specific methods:
1. Import library files by importing Moudle

2. Add the asset catalogue. Create a new asstes directory in main to put VR resources in

3 Add android:largeHeap= "true" subordinate node to application under manifest file

4. Add dependencie s in the build.gradle file of Modele
compile 'com.google.android.exoplayer:exoplayer:r1.5.10'
compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7'
Access: Copy in the build.gradle file under the VR resource file path you downloaded (xxxx gvr-android-sdk-master samples sdk-simplevideowidget).

5. Relevant to your library file: ctrl+alt+shift+s in the open dialog box, select your original project Moudle, select Dependencise, click on the top right corner "+", select the third Module dependency, in the open dialog box, select the library file imported before.

6. Code in xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.zhiyuan3g.vrvideo.MainActivity">

    <com.google.vr.sdk.widgets.video.VrVideoView
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:id="@+id/vr_video">
    </com.google.vr.sdk.widgets.video.VrVideoView>

    <android.support.v7.widget.AppCompatSeekBar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/seek_bar"/>

    <TextView
        android:id="@+id/tv_progress"
        android:textSize="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

All the code in steps 7, 8, 9 is here.
Code in MainActivity:

Write code slices here.import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.google.vr.sdk.widgets.common.VrWidgetView;
import com.google.vr.sdk.widgets.video.VrVideoEventListener;
import com.google.vr.sdk.widgets.video.VrVideoView;

import java.io.IOException;

public class MainActivity extends AppCompatActivity {

    private VrVideoView vr_video;
    private SeekBar seek_bar;// Progress bar
    private TextView tv_progress;
    private VideoLoadTask mVideoLoadTask;// Asynchronous task

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // A Initialization Control
        vr_video = (VrVideoView) findViewById(R.id.vr_video);
        seek_bar = (SeekBar) findViewById(R.id.seek_bar);
        tv_progress = (TextView) findViewById(R.id.tv_progress);

        // Hidden VR effect information button display in lower left corner
        vr_video.setInfoButtonEnabled(false);
        // Switching VR Mode Parameters: VrVideoView.DisplayMode.FULLSCREEN_STEREO: Device Mode (Mobile Phone Play Horizontally)
        //                 VrVideoView. DisplayMode. FULLSCREEN_MONO Mobile Mode
        vr_video.setDisplayMode(VrVideoView.DisplayMode.FULLSCREEN_STEREO);

        //  Event Monitoring for VR Video
        vr_video.setEventListener(new MyEventListener() );

        // Playing VR effects requires only performing asynchronous tasks.
        mVideoLoadTask = new VideoLoadTask();
        mVideoLoadTask.execute("congo_2048.mp4");
    }

    // B Because of the large amount of VR resource data, it takes time to obtain, so the loading video is put into the sub-thread. The main thread shows that asynchronous task AsyncTask or EventBus technology can be used.

    // Customize a class to inherit AsyncTask and use only the method we need to load video resources in the sub-thread and display them in the main thread.
    private class  VideoLoadTask extends AsyncTask<String,Void,Void>{
        // B This method runs in sub-threads and loads resources into memory from local files.
        @Override
        protected Void doInBackground(String... params) {

            // Create the VrVideoView.Options object to determine whether the VR is normal or stereoscopic
            VrVideoView.Options options = new VrVideoView.Options();
            // Stereoscopic mode
            options.inputType = VrVideoView.Options.TYPE_STEREO_OVER_UNDER;
            // Processing Loaded Video Format
            // FORMAT_DEFAULT: Default format (SD card or assets)
            // FORMAT_HLS: Streaming Media Data Format (Live)
            options.inputFormat = VrVideoView.Options.FORMAT_DEFAULT;

            try {
                //Tip: Video loading method also does the operation of reading video into memory, so it will have a contradiction, call this method in the main thread or in the sub-thread (usually we put it in the sub-thread to call this method)
                // Use VR control object to load video data from asset catalog, display effect, parameter 1. params object, 2.VrVideoView.Options object, determines the effect of the display
                vr_video.loadVideoFromAsset(params[0],options);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

    }
    // C Because VR occupies a lot of memory, when the interface enters the OnPause state, pause the VR view display.
    // Enter OnResume status, continue VR view display, enter OnDestroy status, kill VR
    // When we lose focus, call back
    @Override
    protected void onPause() {
        super.onPause();
        // Pause rendering and display
        vr_video.pauseRendering();
    }

    // Callback when focusing

    @Override
    protected void onResume() {
        super.onResume();
        vr_video.resumeRendering();

    }
    // Callback when Activity is destroyed

    @Override
    protected void onDestroy() {
        super.onDestroy();

        vr_video.shutdown();
        // When exiting Activity, if the asynchronous task is not cancelled, it is cancelled
        if (mVideoLoadTask!=null){
            if (!mVideoLoadTask.isCancelled()){
                mVideoLoadTask.cancel(true);
            }
        }
    }
    // For VR runtime monitor class, customize a class, inherit VrVideoEventListener, and copy the method needed in it
    private class MyEventListener extends VrVideoEventListener{

        // What is a callback when VR video loading is successful: When your program reaches a certain condition,
        // Automatically call a piece of code or execute a method
        @Override
        public void onLoadSuccess() {
            super.onLoadSuccess();
            // Getting Video Length
            long max = vr_video.getDuration();
            // Setting the maximum progress of seekbar
            seek_bar.setMax((int)max);
        }

        // Callback when VR view loading fails
        @Override
        public void onLoadError(String errorMessage) {
            super.onLoadError(errorMessage);
            Toast.makeText(MainActivity.this, "Broadcast failure", Toast.LENGTH_SHORT).show();
        }

        // When the video starts to play, every time it enters the next frame, it calls back the method.
        @Override
        public void onNewFrame() {
            super.onNewFrame();
            // Get the playback time and location of the current video
            int currentPosition = (int) vr_video.getCurrentPosition();
            // Setting progress bar of seekVar
            seek_bar.setProgress(currentPosition);
            // Display progress figures for playback
            tv_progress.setText("Play progress:"+String.format("%.2f",currentPosition/1000.f)+String.format("%.2f",vr_video.getDuration()/1000f));
        }

        // Back-to-back method after video playback
        @Override
        public void onCompletion() {
            super.onCompletion();
            // Get the video back to 0:00
            vr_video.seekTo(0);
            // Let Video Stop
            vr_video.pauseVideo();
            // At the same time, let the progress bar go back to 0.
            seek_bar.setProgress(0);

            // After playback, reset the label true and suspend playback
            isPaused = true;
        }

        // Set a label for video playback status
        private boolean isPaused = false;

        // Rewrite the click view so that the video is played or paused when it is clicked
        @Override
        public void onClick() {
            super.onClick();
            Log.d("jzs","click");

            // Judge the status of the current video according to the tag. The tag is false, the playback is paused, the tag is true, and the playback is suspended.
            // true means the video is paused
            if (isPaused){
                // Video playback
                vr_video.playVideo();
            }else{// false represents the status of the video being played.
                vr_video.pauseVideo();
            }
            // After doing label manipulation once, take back the label
            isPaused = !isPaused;
        }
    }
}

Together!!!!!

Posted by blackhorse on Mon, 15 Apr 2019 10:15:31 -0700