首先,感谢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
请帮助我。
答案 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。