Как использовать RajawaliVR или Rajawali для воспроизведения видео 360
Мне трудно понять, как использовать Rajawali для воспроизведения видео 360. Чтобы добиться этого, я перепробовал каждое решение, которое смог найти в Интернете, но потерпел неудачу.
Во-первых, я использовал RajawaliCardboard, и позволил MainActivity расширяться от CardboardActivity
, В то же время, в MyRenderer
класс, я позволил этому классу расширяться от RajawaliCardboardRenderer
учебный класс. В MyRenderer
класс, я переопределил initScene()
функция:
protected void initScene() {
StreamingTexture mTexture = null;
if (externalMemoryAvailable())
{
mVideoPath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/testVideo.mp4";
try{
mPlayer = new MediaPlayer();
mPlayer.setDataSource(mVideoPath);
}catch(IllegalArgumentException e){
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
mPlayer.prepare();
} catch (IOException t) {
t.printStackTrace();
}
mTexture = new StreamingTexture("video", mPlayer);
}
Sphere sphere = createPhotoSphereWithTexture(mTexture);
getCurrentScene().addChild(sphere);
getCurrentCamera().setPosition(Vector3.ZERO);
getCurrentCamera().setFieldOfView(75);
}
private Sphere createPhotoSphereWithTexture(ATexture texture) {
Material material = new Material();
material.setColor(0);
try {
material.addTexture(texture);
} catch (ATexture.TextureException e) {
throw new RuntimeException(e);
}
Sphere sphere = new Sphere(50, 64, 32);
sphere.setScaleX(-1);
sphere.setMaterial(material);
return sphere;
}
Программа может работать без ошибок, но экран черный и без изображения.
Я хочу спросить, что я должен сделать, чтобы улучшить свою программу, и почему я должен сделать, чтобы воспроизвести видео с помощью Rajawali. Кто может мне помочь?
3 ответа
Мне удалось сыграть видео с Раджавали.
public class VideoRenderer extends RajawaliCardboardRenderer {
Context mContext;
private MediaPlayer mMediaPlayer;
private StreamingTexture mVideoTexture;
public VideoRenderer(Context context) {
super(context);
mContext = context;
}
@Override
protected void initScene() {
mMediaPlayer = MediaPlayer.create(getContext(),
R.raw.video);
mMediaPlayer.setLooping(true);
mVideoTexture = new StreamingTexture("sintelTrailer", mMediaPlayer);
Material material = new Material();
material.setColorInfluence(0);
try {
material.addTexture(mVideoTexture);
} catch (ATexture.TextureException e) {
e.printStackTrace();
}
Sphere sphere = new Sphere(50, 64, 32);
sphere.setScaleX(-1);
sphere.setMaterial(material);
getCurrentScene().addChild(sphere);
getCurrentCamera().setPosition(Vector3.ZERO);
getCurrentCamera().setFieldOfView(75);
mMediaPlayer.start();
}
@Override
protected void onRender(long ellapsedRealtime, double deltaTime) {
super.onRender(ellapsedRealtime, deltaTime);
mVideoTexture.update();
}
@Override
public void onPause() {
super.onPause();
if (mMediaPlayer != null)
mMediaPlayer.pause();
}
@Override
public void onResume() {
super.onResume();
if (mMediaPlayer != null)
mMediaPlayer.start();
}
@Override
public void onRenderSurfaceDestroyed(SurfaceTexture surfaceTexture) {
super.onRenderSurfaceDestroyed(surfaceTexture);
mMediaPlayer.stop();
mMediaPlayer.release();
}
public void nextVideo(String nextVideoPath){
try{
mMediaPlayer.stop();
mMediaPlayer.reset();
mMediaPlayer.setDataSource(nextVideoPath);
mMediaPlayer.prepare();
mMediaPlayer.start();
}catch (Exception e){
e.printStackTrace();
}
}
}
Я думаю, что ваша главная ошибка заключается в том, чтобы позвонить MediaPlayer.prepare()
в медиаплеере а не MediaPlayer.prepareAsync()
Вы должны учитывать различные состояния, через которые проходит MediaPlayer при воспроизведении видео. Здесь у вас есть ссылка на диаграмму состояний. Вы должны только позвонить MediaPlayer.start()
как только видеоплеер закончил готовить все, чтобы видео начало воспроизводиться.
Я работаю над тем же (видеоплеер для 360 видео) с Rajawali, и до сих пор мне удалось воспроизвести их в обычном режиме Gyroscope и Touch, но я нахожу множество проблем, чтобы заставить его работать с Google Картонная интеграция, поэтому я сейчас пытаюсь сделать свой собственный рендер "sideBySide".
Если моих комментариев недостаточно, здесь у вас есть пример кода, который я сейчас использую, чтобы воспроизвести видео в виде потоковой текстуры в Сфере. Это часть переопределенного метода initScene()
на класс, который расширяется RajawaliRenderer
//create a 100 segment sphere
earthSphere = new Sphere(1, 100, 100);
//try to set the mediaPLayer data source
mMediaPlayer = new MediaPlayer();
try{
mMediaPlayer.setDataSource(context, Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.pyrex));
}catch(IOException ex){
Log.e("ERROR","couldn attach data source to the media player");
}
mMediaPlayer.setLooping(true); //enable video looping
video = new StreamingTexture("pyrex",mMediaPlayer); //create video texture
mMediaPlayer.prepareAsync(); //prepare the player (asynchronous)
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start(); //start the player only when it is prepared
}
});
//add textture to a new material
Material material = new Material ();
material.setColorInfluence(0f);
try{
material.addTexture(video);
}catch(ATexture.TextureException ex){
Log.e("ERROR","texture error when adding video to material");
}
//set the material to the sphere
earthSphere.setMaterial(material);
earthSphere.setPosition(0, 0, 0);
//add the sphere to the rendering scene
getCurrentScene().addChild(earthSphere);
Поскольку вы хотите воспроизвести видео 360, вам нужен трекер ориентации. Вот пример для картонной деятельности.
public class CardboardRendererExample extends Renderer implements CardboardView.StereoRenderer {
public static final int FIELD_OF_VIEW = 90;
public static final float PLANE_WIDTH = 64.0f;
public static final float PLANE_HEIGHT = 36.0f;
public static final float PLANE_DISTANCE = -64.0f;
private final MediaPlayer mMediaPlayer;
protected StreamingTexture mStreamingTexture;
protected Quaternion mOrientation = Quaternion.getIdentity();
protected Quaternion mEyeOrientation = Quaternion.getIdentity();
protected float[] mHeadView = new float[16];
private Matrix4 mEyeMatrix = new Matrix4();
private Vector3 mEyePosition = new Vector3();
private Matrix4 mHeadViewMatrix4 = new Matrix4();
public CardboardRendererExample(Context context, MediaPlayer mediaPlayer) {
super(context);
mMediaPlayer = mediaPlayer;
}
@Override
protected void initScene() {
getCurrentCamera().setPosition(Vector3.ZERO);
getCurrentCamera().setFieldOfView(FIELD_OF_VIEW);
mStreamingTexture = new StreamingTexture("give_it_some_name", mMediaPlayer);
mStreamingTexture.shouldRecycle(true);
setSceneCachingEnabled(true);
final Plane projectionScreen = new Plane(PLANE_WIDTH, PLANE_HEIGHT, 64, 64);
final Material material = new Material();
material.setColor(0);
material.setColorInfluence(0f);
try {
material.addTexture(mStreamingTexture);
} catch (ATexture.TextureException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
projectionScreen.setDoubleSided(true);
projectionScreen.setMaterial(material);
projectionScreen.setTransparent(true);
projectionScreen.setPosition(0, 0, PLANE_DISTANCE);
getCurrentScene().addChild(projectionScreen);
getCurrentScene().addChild(projectionScreen);
}
@Override
public void onNewFrame(HeadTransform headTransform) {
headTransform.getHeadView(mHeadView, 0);
mHeadViewMatrix4.setAll(mHeadView).inverse();
mOrientation.fromMatrix(mHeadViewMatrix4);
}
@Override
public void onDrawEye(Eye eye) {
getCurrentCamera().updatePerspective(
eye.getFov().getLeft(),
eye.getFov().getRight(),
eye.getFov().getBottom(),
eye.getFov().getTop());
mEyeMatrix.setAll(eye.getEyeView());
mEyeOrientation.fromMatrix(mEyeMatrix);
getCurrentCamera().setOrientation(mEyeOrientation);
mEyePosition = mEyeMatrix.getTranslation(mEyePosition).inverse();
getCurrentCamera().setPosition(mEyePosition);
super.onRenderFrame(null);
}
@Override
public void onFinishFrame(Viewport viewport) {
}
@Override
public void onSurfaceChanged(int width, int height) {
super.onRenderSurfaceSizeChanged(null, width, height);
}
@Override
public void onSurfaceCreated(EGLConfig eglConfig) {
super.onRenderSurfaceCreated(eglConfig, null, -1, -1);
}
@Override
public void onRenderSurfaceCreated(EGLConfig config, GL10 gl, int width, int height) {
super.onRenderSurfaceCreated(config, gl, width, height);
}
@Override
public void onRendererShutdown() {
}
@Override
protected void onRender(long elapsedRealTime, double deltaTime) {
super.onRender(elapsedRealTime, deltaTime);
if (mStreamingTexture != null) {
mStreamingTexture.update();
}
}
@Override
public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) {
}
@Override
public void onTouchEvent(MotionEvent event) {
}
}
В качестве альтернативы вы можете реализовать свой трекер на основе (например)
com.google.vrtoolkit.cardboard.sensors.HeadTracker
Конечно, вы можете избавиться от всех этих полей, но они должны облегчить жизнь GC.