我想将带有透明背景的GLSurfaceView覆盖修改后的SurfaceView,但在SurfaceView上添加GLSurfaceView会导致应用程序崩溃。
修改后的SurfaceView显示从无人机摄像头实时获取的视频,代码直接从Parrot的SDK示例中采样,并且完美运行。 GLSurfaceView是我创建的,具有透明背景。现在它只渲染一个透明背景的绿色三角形,所以我应该能够在后台看到视频。
我已经在另一个项目中测试了GLSurfaceView并且它有效,我已经测试过用它覆盖ImageView并且它也可以工作,但是当我尝试从真实项目覆盖(视频)SurfaceView时,它崩溃了......
这里是GLSurfaceView
的代码:
public class MyGLSurfaceView extends GLSurfaceView {
private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
private float mPreviousX;
private float mPreviousY;
@Override
public boolean onTouchEvent(MotionEvent e) {
// MotionEvent reports input details from the touch screen
// and other input controls. In this case, you are only
// interested in events where the touch position changed.
float x = e.getX();
float y = e.getY();
switch (e.getAction()) {
case MotionEvent.ACTION_MOVE:
float dx = x - mPreviousX;
float dy = y - mPreviousY;
// reverse direction of rotation above the mid-line
if (y > getHeight() / 2) {
dx = dx * -1 ;
}
// reverse direction of rotation to left of the mid-line
if (x < getWidth() / 2) {
dy = dy * -1 ;
}
mRenderer.setAngle(
mRenderer.getAngle() +
((dx + dy) * TOUCH_SCALE_FACTOR));
requestRender();
}
mPreviousX = x;
mPreviousY = y;
return true;
}
private final MyGLRenderer mRenderer;
public MyGLSurfaceView(Context context){
super(context);
SurfaceView sfvTrack = this;
//sfvTrack.setZOrderOnTop(true); // necessary
SurfaceHolder sfhTrackHolder = sfvTrack.getHolder();
sfhTrackHolder.setFormat(PixelFormat.TRANSPARENT);
setEGLConfigChooser(8, 8, 8, 8, 16, 0);
getHolder().setFormat(PixelFormat.TRANSLUCENT);
// Create an OpenGL ES 2.0 context
setEGLContextClientVersion(2);
mRenderer = new MyGLRenderer();
// Set the Renderer for drawing on the GLSurfaceView
setRenderer(mRenderer);
// Render the view only when there is a change in the drawing data
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
}
SurfaceView负责从Parrot的SDKSample中采样的视频:
public class BebopVideoView extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "BebopVideoView";
private static final String VIDEO_MIME_TYPE = "video/avc";
private static final int VIDEO_DEQUEUE_TIMEOUT = 33000;
private MediaCodec mMediaCodec;
private Lock mReadyLock;
private boolean mIsCodecConfigured = false;
private ByteBuffer mSpsBuffer;
private ByteBuffer mPpsBuffer;
private ByteBuffer[] mBuffers;
private static final int VIDEO_WIDTH = 640;
private static final int VIDEO_HEIGHT = 368;
public BebopVideoView(Context context) {
super(context);
customInit();
}
public BebopVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
customInit();
}
public BebopVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
customInit();
}
private void customInit() {
mReadyLock = new ReentrantLock();
getHolder().addCallback(this);
}
public void displayFrame(ARFrame frame) {
mReadyLock.lock();
if ((mMediaCodec != null)) {
if (mIsCodecConfigured) {
// Here we have either a good PFrame, or an IFrame
int index = -1;
try {
index = mMediaCodec.dequeueInputBuffer(VIDEO_DEQUEUE_TIMEOUT);
} catch (IllegalStateException e) {
Log.e(TAG, "Error while dequeue input buffer");
}
if (index >= 0) {
ByteBuffer b;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
b = mMediaCodec.getInputBuffer(index);
} else {
b = mBuffers[index];
b.clear();
}
if (b != null) {
b.put(frame.getByteData(), 0, frame.getDataSize());
}
try {
mMediaCodec.queueInputBuffer(index, 0, frame.getDataSize(), 0, 0);
} catch (IllegalStateException e) {
Log.e(TAG, "Error while queue input buffer");
}
}
}
// Try to display previous frame
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
int outIndex;
try {
outIndex = mMediaCodec.dequeueOutputBuffer(info, 0);
while (outIndex >= 0) {
mMediaCodec.releaseOutputBuffer(outIndex, true);
outIndex = mMediaCodec.dequeueOutputBuffer(info, 0);
}
} catch (IllegalStateException e) {
Log.e(TAG, "Error while dequeue input buffer (outIndex)");
}
}
mReadyLock.unlock();
}
public void configureDecoder(ARControllerCodec codec) {
mReadyLock.lock();
if (codec.getType() == ARCONTROLLER_STREAM_CODEC_TYPE_ENUM.ARCONTROLLER_STREAM_CODEC_TYPE_H264) {
ARControllerCodec.H264 codecH264 = codec.getAsH264();
mSpsBuffer = ByteBuffer.wrap(codecH264.getSps().getByteData());
mPpsBuffer = ByteBuffer.wrap(codecH264.getPps().getByteData());
}
if ((mMediaCodec != null) && (mSpsBuffer != null)) {
configureMediaCodec();
}
mReadyLock.unlock();
}
private void configureMediaCodec() {
mMediaCodec.stop();
MediaFormat format = MediaFormat.createVideoFormat(VIDEO_MIME_TYPE, VIDEO_WIDTH, VIDEO_HEIGHT);
format.setByteBuffer("csd-0", mSpsBuffer);
format.setByteBuffer("csd-1", mPpsBuffer);
mMediaCodec.configure(format, getHolder().getSurface(), null, 0);
mMediaCodec.start();
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
mBuffers = mMediaCodec.getInputBuffers();
}
mIsCodecConfigured = true;
}
private void initMediaCodec(String type) {
try {
mMediaCodec = MediaCodec.createDecoderByType(type);
} catch (IOException e) {
Log.e(TAG, "Exception", e);
}
if ((mMediaCodec != null) && (mSpsBuffer != null)) {
configureMediaCodec();
}
}
private void releaseMediaCodec() {
if (mMediaCodec != null) {
if (mIsCodecConfigured) {
mMediaCodec.stop();
mMediaCodec.release();
}
mIsCodecConfigured = false;
mMediaCodec = null;
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mReadyLock.lock();
initMediaCodec(VIDEO_MIME_TYPE);
mReadyLock.unlock();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mReadyLock.lock();
releaseMediaCodec();
mReadyLock.unlock();
}
}
相关活动的布局(只有前两个块与问题相关):
<RelativeLayout
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"
tools:context=".sample.BebopActivity"
android:id="@+id/piloting_view">
<pact44.drone.sample.BebopVideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<pact44.image3d.lucien.MyGLSurfaceView
android:id="@+id/glView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Emergency"
android:id="@+id/emergencyBt"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:width="150dp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Take picture"
android:id="@+id/takePictureBt"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:width="150dp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/takeOffOrLandBt"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:width="150dp"/>
<Button
android:layout_width="75dp"
android:layout_height="wrap_content"
android:text="right"
android:id="@+id/yawRightBt"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="false"/>
<Button
android:layout_width="75dp"
android:layout_height="wrap_content"
android:text="left"
android:id="@+id/rollLeftBt"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:width="50dp"/>
<Button
android:layout_width="75dp"
android:layout_height="wrap_content"
android:text="left"
android:id="@+id/yawLeftBt"
android:layout_below="@+id/gazUpBt"
android:layout_toLeftOf="@+id/gazUpBt"
android:layout_toStartOf="@+id/gazUpBt"/>
<Button
android:layout_width="75dp"
android:layout_height="wrap_content"
android:text="right"
android:id="@+id/rollRightBt"
android:width="20dp"
android:layout_above="@+id/backBt"
android:layout_toRightOf="@+id/backBt"
android:layout_toEndOf="@+id/backBt"/>
<Button
android:layout_width="110dp"
android:layout_height="wrap_content"
android:text="up"
android:id="@+id/gazUpBt"
android:layout_above="@+id/yawRightBt"
android:layout_toLeftOf="@+id/yawRightBt"
android:layout_toStartOf="@+id/yawRightBt"
android:width="110dp"/>
<Button
android:layout_width="110dp"
android:layout_height="wrap_content"
android:text="down"
android:id="@+id/gazDownBt"
android:width="110dp"
android:layout_below="@+id/yawRightBt"
android:layout_toRightOf="@+id/yawLeftBt"
android:layout_toEndOf="@+id/yawLeftBt"/>
<Button
android:layout_width="110dp"
android:layout_height="wrap_content"
android:text="forward"
android:id="@+id/forwardBt"
android:layout_alignTop="@+id/gazUpBt"
android:layout_toRightOf="@+id/rollLeftBt"
android:layout_toEndOf="@+id/rollLeftBt"
android:width="110dp"/>
<Button
android:layout_width="110dp"
android:layout_height="wrap_content"
android:text="back"
android:id="@+id/backBt"
android:layout_below="@+id/rollLeftBt"
android:layout_toRightOf="@+id/rollLeftBt"
android:layout_toEndOf="@+id/rollLeftBt"
android:width="110dp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Download"
android:id="@+id/downloadBt"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:width="150dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Battery: "
android:id="@+id/textView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:textColor="#ff0000" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="XXX%"
android:id="@+id/batteryLabel"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/textView"
android:layout_toEndOf="@+id/textView"
android:textColor="#ff0000" />
<TextView
android:layout_width="110dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="roll"
android:id="@+id/textView2"
android:width="50dp"
android:textAlignment="center"
android:gravity="center_horizontal"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/rollLeftBt"
android:layout_toEndOf="@+id/rollLeftBt"/>
<TextView
android:layout_width="110dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="yaw"
android:id="@+id/textView3"
android:width="50dp"
android:layout_alignTop="@+id/textView2"
android:layout_alignRight="@+id/gazDownBt"
android:layout_alignEnd="@+id/gazDownBt"
android:gravity="center_horizontal"/>
</RelativeLayout>
我还试图在没有xml的情况下手动创建和添加GLSurfaceView,但是当我使用addContentView(myGLSurfaceView, myRelativeLayoutParams)
时它会崩溃。
感谢您的阅读,祝您度过愉快的一天。
编辑:以下是我从xml添加GLSurfaceView时的崩溃报告:
04-12 21:20:40.631 17164-17164/pact44.droneracingapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: pact44.droneracingapp, PID: 17164
java.lang.RuntimeException: Unable to start activity ComponentInfo{pact44.droneracingapp/pact44.drone.sample.BebopActivity}: android.view.InflateException: Binary XML file line #13: Binary XML file line #13: Error inflating class pact44.image3d.lucien.MyGLSurfaceView
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2464)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2524)
at android.app.ActivityThread.access$900(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1391)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:234)
at android.app.ActivityThread.main(ActivityThread.java:5526)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: android.view.InflateException: Binary XML file line #13: Binary XML file line #13: Error inflating class pact44.image3d.lucien.MyGLSurfaceView
at android.view.LayoutInflater.inflate(LayoutInflater.java:539)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:292)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
at pact44.drone.sample.BebopActivity.onCreate(BebopActivity.java:40)
at android.app.Activity.performCreate(Activity.java:6285)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2417)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2524)
at android.app.ActivityThread.access$900(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1391)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:234)
at android.app.ActivityThread.main(ActivityThread.java:5526)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: android.view.InflateException: Binary XML file line #13: Error inflating class pact44.image3d.lucien.MyGLSurfaceView
at android.view.LayoutInflater.createView(LayoutInflater.java:628)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:764)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:835)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)
at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:292)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
at pact44.drone.sample.BebopActivity.onCreate(BebopActivity.java:40)
at android.app.Activity.performCreate(Activity.java:6285)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2417)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2524)
at android.app.ActivityThread.access$900(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1391)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:234)
at android.app.ActivityThread.main(ActivityThread.java:5526)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet]
at java.lang.Class.getConstructor(Class.java:528)
at java.lang.Class.getConstructor(Class.java:492)
at android.view.LayoutInflater.createView(LayoutInflater.java:592)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:764)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:835)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)
at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:292)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
at pact44.drone.sample.BebopActivity.onCreate(BebopActivity.java:40)
at android.app.Activity.performCreate(Activity.java:6285)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2417)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2524)
at android.app.ActivityThread.access$900(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1391)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:234)
at android.app.ActivityThread.main(ActivityThread.java:5526)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
BebopActivity.java 的第40行对应于指令setContentView(mylayoutwhodoesnotwork);
。从纯java添加GlSurfaceView时,导致错误的行对应于指令addContentView(myAwesomeGLSurfaceView);
。
我没有在代码中看到任何特定错误,在我看来,我想要做的是,即将这两个SurfaceView
放在同一个活动中,一个覆盖另一个,是不可能的...如果是这种情况,创建两个活动,上面的活动具有透明背景,似乎是一个可能的解决方案,但系统可能会停止背景活动,导致视频停止...