问题在通过EGL配置表面为本地和推动数据 [英] Issue in passing Egl configured surface to native and push the data

查看:1685
本文介绍了问题在通过EGL配置表面为本地和推动数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先感谢法登的精彩例子。

我试着以下<一href="https://github.com/google/grafika/blob/master/src/com/android/grafika/ContinuousCaptureActivity.java"相对=nofollow>这个的ContinuousCapture.java例子,并制作了下面的程序。

1)

我试图通过获取其ANativeWwindow参照显示图像进入TextureView在本机层,并用ANative锁和unlockpost方法来获取 BufferQueue 并填充数据。

即:

  ANativeWindow_lock(*窗口,和放大器;缓冲器,NULL)

ANativeWindow_unlockAndPost(*窗口);
 

2)

同时,我想要从这个表面的数据,并将其传递给EN codeR。或者,显示它到另一个面。

作为第一步,我已经创建了以下类它初始化EglCore成不同的线程,并试图在EglContext配置用户指定表面。到目前为止,一切都很好。 但是,当我尝试将数据复制到我早些时候锁和放大器提到的缓冲; unlockAndPost方法,我recive下面的错误。

  E / BufferQueueProducer:[无名的-7679-0]连接(P):已连接(CUR = 1 REQ = 2)
E / BufferQueueProducer:[无名的-7679-0]连接(P):已连接(CUR = 1 REQ = 2)
E / BufferQueueProducer:[无名的-7679-0]连接(P):已连接(CUR = 1 REQ = 2)
 

问: 它是正确的做法?还是我忽略了一些东西?

 包com.super.dump

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

进口的java.io.File;
进口java.io.IOException异常;



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

进口的java.io.File;
进口java.io.IOException异常;
进口java.lang.ref.WeakReference;
进口java.nio.ByteBuffer中;
进口java.nio.ByteOrder中;

 公共类SuperDump {

    RenderThread放疗;
    表面userProvidedSurface;


    公共SuperDump(){
        userProvidedSurface = NULL;
        RT =零;
    }


    公共无效的init(表面userSurface)
    {
        如果(userSurface!= NULL){
            userProvidedSurface = userSurface;
            RT =新RenderThread(userProvidedSurface);
            rT.start();
            rT.waitUntilRendererReady();
        }
    }


    私有类RenderThread继承Thread {

        公共字符串标记=RenderThread;
        RenderHandler mHandler;
        私有对象mSyncForRenderAvailability =新的对象();
        布尔mIsRendererReady = FALSE;

        私人EglCore mEglCore;
        私人表面mSurfaceUser;
        私人WindowSurface mSurfaceWindowUser;


        公共RenderThread(){

        }

        公共RenderThread(表面userSurface){
            mSurfaceUser = userSurface;
        }



        @覆盖
        公共无效的run(){
            活套prepare()。
            mHandler =新RenderHandler(本);

            mEglCore =新EglCore(空,EglCore.FLAG_RECORDABLE);
            mSurfaceWindowUser =新WindowSurface(mEglCore,mSurfaceUser,假);

            同步(mSyncForRenderAvailability){

                mIsRendererReady =真;
                mSyncForRenderAvailability.notifyAll();
            }

            Looper.loop();
            Log.d(TAG,RenderThread结束。);
        }

        公共RenderHandler getHandler(){
            返回mHandler;
        }


        公共无效waitUntilRendererReady()
        {
            同步(mSyncForRenderAvailability){
                而(!mIsRendererReady){
                    尝试 {
                        mSyncForRenderAvailability.wait();
                    }赶上(InterruptedException异常E){
                        Log.d(TAG,等待中断..);
                    }
                }
            }
        }

} // RenderThread





   私有静态类RenderHandler扩展处理程序{

       公共字符串标记=RenderHandler;
       私有静态最终诠释MSG_RENDER_QUIT = 1;

        私人的WeakReference&LT; RenderThread&GT; mWeakRenderThread;

        公共RenderHandler(RenderThread RT)
        {
            mWeakRenderThread =新的WeakReference&LT; RenderThread&GT;(RT);
        }

       公共无效stopMe(){
           的sendMessage(obtainMessage(MSG_RENDER_QUIT));
       }

        @覆盖
       公共无效的handleMessage(信息MSG){

           Log.d(TAG,里面的handleMessage ..);

            开关(msg.what){
                案例MSG_RENDER_QUIT:
                    Looper.getMainLooper()退出()。 //从线程分离。
            }
       }




   } // RenderHandler类。
}; // SuperDump类
 

请帮我。

解决方案
  

同时,我想从这个表面检索数据并把它传递给EN codeR

您不能检索从表面数据。表面的生产者 - 消费者对制片方。

你得到了已连接的错误,因为你试图第二生产者附着在表面。

(如果你想挑选尼特,BufferQueue将重新使用缓冲剂,但不清除它们,所以制片人经常可以看到的数据帧或两回,但由于生产者创造这些帧摆在首位,有没有在拉他们回来了多少价值,而且也不能保证BufferQueue不会给你一个空的缓冲区,或present出来的顺序。)

好消息是,对于一个表面纹理,消费者在进程和访问数据为GLES外部的质感。该TextureView类提供了一个方便的 getBitmap()方法呈现最新的帧转换为位图,允许直接访问像素。 (你可以做同样的事情通过渲染纹理到离屏幕的pbuffer 和阅读像素用 glReadPixels()

因此​​,为了实现你想要的解决方案,最简单的事情是只用TextureView调用来获取位图。

有关曲面的更多信息可以在图形架构文档被发现。

First, thanks to fadden for your wonderful examples.

I tried following this ContinuousCapture.java example, and produced the below program.

1)

I am trying to display the image into TextureView in the native layer by getting its ANativeWwindow reference, and using ANative lock and unlockpost methods to acquire the BufferQueue and to fill the data.

Ie:

ANativeWindow_lock(*window, &buffer, NULL)

ANativeWindow_unlockAndPost(*window);

2)

At the same time i want to retrieve the data from this Surface and pass it to the encoder. Or, display it into another surface.

As a first step, I have created the below Class which initializes the EglCore into different thread, and tries to Configure user given surface in EglContext. So, far so good. But when i try to copy the data into the buffer as i mentioned earlier by lock & unlockAndPost methods, i recive the below errors.

 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)

Question: Is it the right approach?. OR did i overlook something?

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

Kindly help me.

解决方案

At the same time i want to retrieve the data from this Surface and pass it to the encoder

You can't retrieve data from a Surface. Surfaces are the producer side of a producer-consumer pair.

You're getting the "already connected" errors because you're attempting to attach a second producer to the Surface.

(If you want to pick nits, BufferQueue will re-use buffers without clearing them, so the producer can often see the data from a frame or two back. But since the producer created those frames in the first place, there's not much value in pulling them back out. And there is no guarantee that BufferQueue won't give you an empty buffer, or present them out of order.)

The good news is that, for a SurfaceTexture, the consumer is in-process and the data is accessible as a GLES "external" texture. The TextureView class provides a convenient getBitmap() method that renders the most recent frame into a Bitmap, allowing direct access to the pixels. (You can do something similar by rendering the texture to an off-screen pbuffer and reading the pixels out with glReadPixels().)

So to implement the solution you want, the easiest thing would be to just use the TextureView call to get a Bitmap.

More information about Surfaces can be found in the graphics architecture doc.

这篇关于问题在通过EGL配置表面为本地和推动数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆