1

まず、すばらしい例を提供してくれた fadden に感謝します。

このContinuousCapture.java の例に従って試してみ たところ、以下のプログラムが作成されました。

1)

ANativeWwindow 参照を取得し、ANative lock メソッドと unlockpost メソッドを使用して BufferQueue を取得し、データを入力することで、ネイティブ レイヤーの TextureView に画像を表示しようとして ます。

すなわち:

ANativeWindow_lock(*window, &buffer, NULL)

ANativeWindow_unlockAndPost(*window);

2)

同時に、この Surface からデータを取得してエンコーダに渡したいと考えています。または、別の面に表示します。

最初のステップとして、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

親切に私を助けてください。

4

1 に答える 1

0

同時に、この Surface からデータを取得してエンコーダに渡したい

Surface からデータを取得することはできません。サーフェスは、生産者と消費者のペアの生産者側です。

2 番目のプロデューサーを Surface に接続しようとしているため、「既に接続されています」というエラーが表示されます。

(ニットを選択したい場合、BufferQueue はバッファーをクリアせずに再利用するため、プロデューサーは 1 つまたは 2 つのフレームからデータを参照できます。しかし、プロデューサーは最初にこれらのフレームを作成したため、また、BufferQueue が空のバッファーを提供しない、またはそれらを順不同で提示しないという保証はありません。)

幸いなことに、SurfaceTexture の場合、コンシューマはインプロセスであり、データは GLES の「外部」テクスチャとしてアクセスできます。getBitmap()TextureView クラスは、最新のフレームをビットマップにレンダリングする便利なメソッドを提供し、ピクセルへの直接アクセスを可能にします。(テクスチャをオフスクリーンにレンダリングしpbuffer、 でピクセルを読み取ることで、同様のことができますglReadPixels()。)

したがって、必要なソリューションを実装するには、TextureView 呼び出しを使用してビットマップを取得するのが最も簡単です。

サーフェスの詳細については、グラフィックス アーキテクチャ ドキュメントを参照してください。

于 2015-11-20T17:19:10.277 に答える