将Egl配置的表面传递给本机并推送数据

时间:2015-11-20 14:49:45

标签: android opengl-es egl grafika

首先,感谢fadden为你的精彩例子。

我尝试了this ContinuousCapture.java示例,并制作了以下程序。

1)

我试图通过获取其ANativeWwindow引用,并使用ANative lock和unlockpost方法获取 BufferQueue 并填充数据。

即:

ANativeWindow_lock(*window, &buffer, NULL)

ANativeWindow_unlockAndPost(*window);

2)

同时我想从这个Surface中检索数据并将其传递给编码器。或者,将其显示在另一个表面。

作为第一步,我创建了下面的Class,它将EglCore初始化为不同的线程,并尝试在EglContext中配置用户给定的表面。到现在为止还挺好。 但是,当我尝试将数据复制到缓冲区时,正如我之前提到的那样,锁定& unlockAndPost方法,我收到以下错误。

 E/BufferQueueProducer: [unnamed-7679-0] connect(P): already connected (cur=1 req=2)
E/BufferQueueProducer: [unnamed-7679-0] connect(P): already connected (cur=1 req=2)
E/BufferQueueProducer: [unnamed-7679-0] connect(P): already connected (cur=1 req=2)

问题: 这是正确的方法吗?或者我忽略了什么?

package com.super.dump

import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.opengl.EGLSurface;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.util.SparseArray;
import android.view.Surface;

import java.io.File;
import java.io.IOException;



import android.graphics.SurfaceTexture;
import android.opengl.EGL14;
import android.opengl.EGLSurface;
import android.opengl.GLES20;
import android.os.Environment;
import android.util.Log;
import android.util.SparseArray;
import android.view.Surface;
import android.view.View;
import android.widget.TextView;

import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

 public class SuperDump {

    RenderThread rT;
    Surface userProvidedSurface;


    public SuperDump() {
        userProvidedSurface = null;
        rT = null;
    }


    public void init(Surface userSurface)
    {
        if ( userSurface != null) {
            userProvidedSurface = userSurface;
            rT = new RenderThread(userProvidedSurface);
            rT.start();
            rT.waitUntilRendererReady();
        }
    }


    private class RenderThread extends Thread {

        public String TAG = "RenderThread";
        RenderHandler mHandler;
        private Object mSyncForRenderAvailability = new Object();
        boolean mIsRendererReady = false;

        private EglCore mEglCore;
        private Surface mSurfaceUser;
        private WindowSurface mSurfaceWindowUser;


        public RenderThread() {

        }

        public RenderThread(Surface userSurface) {
            mSurfaceUser = userSurface;
        }



        @Override
        public void run() {
            Looper.prepare();
            mHandler = new RenderHandler(this);

            mEglCore = new EglCore(null, EglCore.FLAG_RECORDABLE);
            mSurfaceWindowUser = new WindowSurface(mEglCore, mSurfaceUser, false);

            synchronized (mSyncForRenderAvailability) {

                mIsRendererReady = true;
                mSyncForRenderAvailability.notifyAll();
            }

            Looper.loop();
            Log.d (TAG, "End of RenderThread..");
        }

        public RenderHandler getHandler() {
            return mHandler;
        }


        public void waitUntilRendererReady()
        {
            synchronized (mSyncForRenderAvailability) {
                while(!mIsRendererReady) {
                    try {
                        mSyncForRenderAvailability.wait();
                    } catch (InterruptedException e) {
                        Log.d (TAG,  "Wait interrupted..");
                    }
                }
            }
        }

}  // RenderThread





   private static class RenderHandler extends Handler {

       public String TAG = "RenderHandler";
       private static final int MSG_RENDER_QUIT = 1;

        private WeakReference<RenderThread> mWeakRenderThread;

        public RenderHandler(RenderThread rT)
        {
            mWeakRenderThread = new WeakReference<RenderThread>(rT);
        }

       public void stopMe() {
           sendMessage(obtainMessage(MSG_RENDER_QUIT));
       }

        @Override
       public void handleMessage(Message msg) {

           Log.d (TAG, "Inside handleMessage..");

            switch(msg.what) {
                case MSG_RENDER_QUIT:
                    Looper.getMainLooper().quit();  // detaching from thread.
            }
       }




   }  // RenderHandler Class.
}; //SuperDump class

请帮助我。

1 个答案:

答案 0 :(得分:0)

  

同时我想从这个Surface中检索数据并将其传递给编码器

您无法从Surface检索数据。 Surfaces是生产者 - 消费者对的生产者。

你已经连接了#34;已经连接了#34;错误,因为您试图将第二个生产者附加到Surface。

(如果你想选择尼特,BufferQueue将重新使用缓冲区而不清除它们,因此生产者通常可以看到一两帧的数据。但是由于生产者首先创建了这些帧,所以&# 39;将它们拉回来没什么价值。并且无法保证BufferQueue不会给你一个空的缓冲区,或者不按顺序显示它们。)

好消息是,对于SurfaceTexture,消费者正在进行中,并且数据可以作为GLES&#34;外部&#34;质地。 TextureView类提供了一种方便的getBitmap()方法,可将最新的帧渲染为位图,允许直接访问像素。 (您可以通过将纹理渲染到屏幕外pbuffer并使用glReadPixels()读取像素来执行类似操作。)

因此,要实现所需的解决方案,最简单的方法就是使用TextureView调用来获取Bitmap。

有关Surfaces的更多信息,请参阅graphics architecture doc