通过Android实现VR视频的播放

    xiaoxiao2021-03-25  115

    实现VR视频的播放和前面写过的VR全景图的展示差不多,改变的也只是库文件的不同,资源目录下的资源不同而已。下面就来说一下步骤。

    先展示一下效果图 完成步骤: 1.以导入Moudle的方式导入库文件。(videowidget,common,commonwidget)资源获取链接:https://github.com/googlevr/gvr-android-sdk/ 2.在main下新建资产目录asstes,放入视频资源 3.在清单文件application中提高警报权限android:largeHeap=”true” 4.在Moudlede的 build.grable文件里dependencies中添加 compile ‘com.google.android.exoplayer:exoplayer:r1.5.10’ compile ‘com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7’ 5.关联导入的依赖库 6完成xml中的布局,video.VrVideoView,AppCompatSeekBar,TextView 7.使用异步任务AsyncTask,(或EventBus技术)加载视频 8.利用线程进行VR优化。 9.设置VR的监听效果

    具体方法: 1.以导入Moudle的方式导入库文件

    2.添加资产目录。在main新建asstes目录,将VR资源放入 3在清单文件下的application添加 android:largeHeap=”true”的属下节点

    4.在Module的build.gradle文件里dependencie中加入 compile ‘com.google.android.exoplayer:exoplayer:r1.5.10’ compile ‘com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7’ 获取方式:在你下载的VR资源文件路径下(xxxx\gvr-android-sdk-master\samples\sdk-simplevideowidget)build.gradle文件中拷取。

    5.关联你的库文件:ctrl+alt+shift+s在打开的对话框中,选择你原本的项目Moudle,选择Dependencise,点击右上角”+”,选择第三个Module dependency,在打开的对话框中,选择之前导入的库文件。

    6.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>

    7、8,9步中所有的代码都在这了 MainActivity中的代码:

    这里写代码片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;// 进度条 private TextView tv_progress; private VideoLoadTask mVideoLoadTask;// 异步任务 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // A初始化控件 vr_video = (VrVideoView) findViewById(R.id.vr_video); seek_bar = (SeekBar) findViewById(R.id.seek_bar); tv_progress = (TextView) findViewById(R.id.tv_progress); // 隐藏VR效果左下角信息按钮显示 vr_video.setInfoButtonEnabled(false); // 切换VR模式 参数:VrVideoView.DisplayMode.FULLSCREEN_STEREO:设备模式(手机横着放试试) // VrVideoView.DisplayMode..FULLSCREEN_MONO手机模式 vr_video.setDisplayMode(VrVideoView.DisplayMode.FULLSCREEN_STEREO); // 对VR视频进行事件监听 vr_video.setEventListener(new MyEventListener() ); // 播放VR效果,只需要执行异步任务即可 mVideoLoadTask = new VideoLoadTask(); mVideoLoadTask.execute("congo_2048.mp4"); } // B 由于VR资源数据量很大,获取需要时间,故把加载视频放到子线程中进行,主线程来显示,可以使用异步任务AsyncTask,或EventBus技术 // 自定义一个类继承AsyncTask,只使用我们需要的方法,完成在子线程加载视频资源,在主线程显示 private class VideoLoadTask extends AsyncTask<String,Void,Void>{ // B该方法在子线程运行,从本地文件中把资源加载到内存中 @Override protected Void doInBackground(String... params) { // 创建VrVideoView.Options对象,决定VR是普通的效果,还是立体效果 VrVideoView.Options options = new VrVideoView.Options(); // 立体模式 options.inputType = VrVideoView.Options.TYPE_STEREO_OVER_UNDER; // 处理加载的视频格式 // FORMAT_DEFAULT:默认格式(SD卡或assets) // FORMAT_HLS:流媒体数据格式(直播) options.inputFormat = VrVideoView.Options.FORMAT_DEFAULT; try { //提示:视频加载的方法还做了把视频读取到内存中的操作,所以它会有一个矛盾,调用该方法是在主线程还是在子线程(一般我们放在子线程去调用该方法) // 使用VR控件对象,从资产目录加载视频数据,显示效果, 参数1。params对象,2.VrVideoView.Options对象,决定显示的效果 vr_video.loadVideoFromAsset(params[0],options); } catch (IOException e) { e.printStackTrace(); } return null; } } // C因为VR很占用内存,所以当界面进入OnPause状态,暂停VR视图显示, // 进入OnResume状态,继续VR视图显示,进入OnDestroy状态,杀死VR // 当我们失去焦点,回调 @Override protected void onPause() { super.onPause(); // 暂停渲染和显示 vr_video.pauseRendering(); } // 当获取焦点时,回调 @Override protected void onResume() { super.onResume(); vr_video.resumeRendering(); } // 当Activity销毁时,回调 @Override protected void onDestroy() { super.onDestroy(); vr_video.shutdown(); // 在退出Activity时,如果异步任务没有取消,则取消 if (mVideoLoadTask!=null){ if (!mVideoLoadTask.isCancelled()){ mVideoLoadTask.cancel(true); } } } // 对VR运行状态监听类,自定义一个类,继承VrVideoEventListener,复写里面需要的方法 private class MyEventListener extends VrVideoEventListener{ // 当VR视频加载成功的时候回调 什么是回调:当你的程序到达符合某个条件时, // 自动调用某段代码或执行某个方法 @Override public void onLoadSuccess() { super.onLoadSuccess(); // 获取视频长度 long max = vr_video.getDuration(); // 设置seekbar的进度最大值 seek_bar.setMax((int)max); } // 当VR视图加载失败的时候 回调 @Override public void onLoadError(String errorMessage) { super.onLoadError(errorMessage); Toast.makeText(MainActivity.this, "播放失败", Toast.LENGTH_SHORT).show(); } // 当视频开始播放,每次进入下一帧的时候,回调这个方法(就是播放时,会不停的回调该方法) @Override public void onNewFrame() { super.onNewFrame(); // 获取当前视频的播放时间位置 int currentPosition = (int) vr_video.getCurrentPosition(); // 设置seekVar的进度条 seek_bar.setProgress(currentPosition); // 显示播放的进度数字 tv_progress.setText("播放进度:"+String.format("%.2f",currentPosition/1000.f)+String.format("%.2f",vr_video.getDuration()/1000f)); } // 当视频播放结束后的回到方法 @Override public void onCompletion() { super.onCompletion(); // 让视频回到0点 vr_video.seekTo(0); // 让视频停止 vr_video.pauseVideo(); // 同时让进度条回到0点 seek_bar.setProgress(0); // 播放完成后,重新设置标签true,暂停播放 isPaused = true; } // 设置一个视频播放状态的标签 private boolean isPaused = false; // 重写点击视图的方法,使视频被点击时播放或者暂停 @Override public void onClick() { super.onClick(); Log.d("jzs","点击"); // 根据标签判断当前视频的状态,标签false,播放则暂停,标签true,暂停播放 // true代表视频正处于暂停状态 if (isPaused){ // 视频播放 vr_video.playVideo(); }else{// false代表视频正在播放的状态 vr_video.pauseVideo(); } // 对标签操做一次后,进行取反 isPaused = !isPaused; } } }

    共勉!!!!!

    转载请注明原文地址: https://ju.6miu.com/read-24532.html

    最新回复(0)