Проблема при передаче настроенной Egl поверхности на родную и пуш данных

Во-первых, спасибо Фаддену за ваши замечательные примеры.

Я попытался следовать этому примеру ContinuousCapture.java и создал следующую программу.

1)

Я пытаюсь отобразить изображение в TextureView на собственном слое, получив ссылку ANativeWwindow и используя методы ANative lock и unlockpost, чтобы получитьBufferQueue и заполнить данные.

То есть:

ANativeWindow_lock(*window, &buffer, NULL)

ANativeWindow_unlockAndPost(*window);

2)

В то же время я хочу получить данные с этой поверхности и передать их кодировщику. Или отобразить его на другой поверхности.

В качестве первого шага я создал приведенный ниже класс, который инициализирует EglCore в другой поток и пытается настроить заданную пользователем поверхность в EglContext. Все идет нормально. Но когда я пытаюсь скопировать данные в буфер, как я упоминал ранее с помощью методов lock & 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 ответ

В то же время я хочу получить данные с этой поверхности и передать их кодировщику

Вы не можете получить данные с поверхности. Поверхности являются стороной производителя пары производитель-потребитель.

Вы получаете "уже подключенные" ошибки, потому что вы пытаетесь подключить второго производителя к Surface.

(Если вы хотите выбрать nits, BufferQueue будет повторно использовать буферы, не очищая их, поэтому производитель часто может видеть данные из кадра или двух назад. Но, поскольку производитель создал эти кадры в первую очередь, в этом нет особой ценности. вытаскивая их обратно. И нет никакой гарантии, что BufferQueue не даст вам пустой буфер или не выведет их из строя.)

Хорошей новостью является то, что для SurfaceTexture потребитель находится в процессе, и данные доступны в виде "внешней" текстуры GLES. Класс TextureView предоставляет удобный getBitmap() метод, который отображает самый последний кадр в растровое изображение, предоставляя прямой доступ к пикселям. (Вы можете сделать что-то подобное, отрисовав текстуру за кадром pbuffer и чтение пикселей с glReadPixels().)

Таким образом, для реализации желаемого решения проще всего было бы просто использовать вызов TextureView для получения растрового изображения.

Более подробную информацию о Surfaces можно найти в документации по графической архитектуре.

Другие вопросы по тегам