- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在使用 OpenTok Android SDK 2.4+( https://tokbox.com/developer/sdks/android/ )
目前在 SDK 中,它在方形区域显示发布者(相机预览),但我希望它显示为圆形(圆形的发布者相机 View )。
注意:PublisherView 使用 OpenGL GLSurfaceView 显示相机预览。
我通过扩展类“BaseVideoRenderer”使用附加的“CustomVideoRenderer.java”类。我不熟悉 OpenGL,所以无法理解我应该在代码中更改什么。
所以请帮我摆脱它..以圆形显示发布者 View 。
public class CustomVideoRenderer extends BaseVideoRenderer {
private Context mContext;
private GLSurfaceView mView;
private MyRenderer mRenderer;
static class MyRenderer implements GLSurfaceView.Renderer {
int mTextureIds[] = new int[3];
float[] mScaleMatrix = new float[16];
private FloatBuffer mVertexBuffer;
private FloatBuffer mTextureBuffer;
private ShortBuffer mDrawListBuffer;
boolean mVideoFitEnabled = true;
boolean mVideoDisabled = false;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static final int TEXTURECOORDS_PER_VERTEX = 2;
static float mXYZCoords[] = {-1.0f, 1.0f, 0.0f, // top left
-1.0f, -1.0f, 0.0f, // bottom left
1.0f, -1.0f, 0.0f, // bottom right
1.0f, 1.0f, 0.0f // top right
};
static float mUVCoords[] = {0, 0, // top left
0, 1, // bottom left
1, 1, // bottom right
1, 0}; // top right
private short mVertexIndex[] = {0, 1, 2, 0, 2, 3}; // order to draw
// vertices
private final String vertexShaderCode = "uniform mat4 uMVPMatrix;"
+ "attribute vec4 aPosition;\n"
+ "attribute vec2 aTextureCoord;\n"
+ "varying vec2 vTextureCoord;\n" + "void main() {\n"
+ " gl_Position = uMVPMatrix * aPosition;\n"
+ " vTextureCoord = aTextureCoord;\n" + "}\n";
private final String fragmentShaderCode = "precision mediump float;\n"
+ "uniform sampler2D Ytex;\n"
+ "uniform sampler2D Utex,Vtex;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main(void) {\n"
+ " float nx,ny,r,g,b,y,u,v;\n"
+ " mediump vec4 txl,ux,vx;"
+ " nx=vTextureCoord[0];\n"
+ " ny=vTextureCoord[1];\n"
+ " y=texture2D(Ytex,vec2(nx,ny)).r;\n"
+ " u=texture2D(Utex,vec2(nx,ny)).r;\n"
+ " v=texture2D(Vtex,vec2(nx,ny)).r;\n"
+ " y=1.0-1.1643*(y-0.0625);\n" // Invert effect
// + " y=1.1643*(y-0.0625);\n" // Normal renderer
+ " u=u-0.5;\n" + " v=v-0.5;\n" + " r=y+1.5958*v;\n"
+ " g=y-0.39173*u-0.81290*v;\n" + " b=y+2.017*u;\n"
+ " gl_FragColor=vec4(r,g,b,1.0);\n" + "}\n";
ReentrantLock mFrameLock = new ReentrantLock();
Frame mCurrentFrame;
private int mProgram;
private int mTextureWidth;
private int mTextureHeight;
private int mViewportWidth;
private int mViewportHeight;
public MyRenderer()
{
ByteBuffer bb = ByteBuffer.allocateDirect(mXYZCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
mVertexBuffer = bb.asFloatBuffer();
mVertexBuffer.put(mXYZCoords);
mVertexBuffer.position(0);
ByteBuffer tb = ByteBuffer.allocateDirect(mUVCoords.length * 4);
tb.order(ByteOrder.nativeOrder());
mTextureBuffer = tb.asFloatBuffer();
mTextureBuffer.put(mUVCoords);
mTextureBuffer.position(0);
ByteBuffer dlb = ByteBuffer.allocateDirect(mVertexIndex.length * 2);
dlb.order(ByteOrder.nativeOrder());
mDrawListBuffer = dlb.asShortBuffer();
mDrawListBuffer.put(mVertexIndex);
mDrawListBuffer.position(0);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
gl.glClearColor(0, 0, 0, 1);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL ES
// Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex
// shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment
// shader to
// program
GLES20.glLinkProgram(mProgram);
int positionHandle = GLES20.glGetAttribLocation(mProgram,
"aPosition");
int textureHandle = GLES20.glGetAttribLocation(mProgram,
"aTextureCoord");
GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false, COORDS_PER_VERTEX * 4,
mVertexBuffer);
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glVertexAttribPointer(textureHandle,
TEXTURECOORDS_PER_VERTEX, GLES20.GL_FLOAT, false,
TEXTURECOORDS_PER_VERTEX * 4, mTextureBuffer);
GLES20.glEnableVertexAttribArray(textureHandle);
GLES20.glUseProgram(mProgram);
int i = GLES20.glGetUniformLocation(mProgram, "Ytex");
GLES20.glUniform1i(i, 0); /* Bind Ytex to texture unit 0 */
i = GLES20.glGetUniformLocation(mProgram, "Utex");
GLES20.glUniform1i(i, 1); /* Bind Utex to texture unit 1 */
i = GLES20.glGetUniformLocation(mProgram, "Vtex");
GLES20.glUniform1i(i, 2); /* Bind Vtex to texture unit 2 */
mTextureWidth = 0;
mTextureHeight = 0;
}
static void initializeTexture(int name, int id, int width, int height) {
GLES20.glActiveTexture(name);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, id);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE,
width, height, 0, GLES20.GL_LUMINANCE,
GLES20.GL_UNSIGNED_BYTE, null);
}
void setupTextures(Frame frame) {
if (mTextureIds[0] != 0) {
GLES20.glDeleteTextures(3, mTextureIds, 0);
}
GLES20.glGenTextures(3, mTextureIds, 0);
int w = frame.getWidth();
int h = frame.getHeight();
int hw = (w + 1) >> 1;
int hh = (h + 1) >> 1;
initializeTexture(GLES20.GL_TEXTURE0, mTextureIds[0], w, h);
initializeTexture(GLES20.GL_TEXTURE1, mTextureIds[1], hw, hh);
initializeTexture(GLES20.GL_TEXTURE2, mTextureIds[2], hw, hh);
mTextureWidth = frame.getWidth();
mTextureHeight = frame.getHeight();
}
void updateTextures(Frame frame) {
int width = frame.getWidth();
int height = frame.getHeight();
int half_width = (width + 1) >> 1;
int half_height = (height + 1) >> 1;
int y_size = width * height;
int uv_size = half_width * half_height;
ByteBuffer bb = frame.getBuffer();
// If we are reusing this frame, make sure we reset position and
// limit
bb.clear();
if (bb.remaining() == y_size + uv_size * 2) {
bb.position(0);
GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
GLES20.glPixelStorei(GLES20.GL_PACK_ALIGNMENT, 1);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[0]);
GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, width,
height, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE,
bb);
bb.position(y_size);
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[1]);
GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
half_width, half_height, GLES20.GL_LUMINANCE,
GLES20.GL_UNSIGNED_BYTE, bb);
bb.position(y_size + uv_size);
GLES20.glActiveTexture(GLES20.GL_TEXTURE2);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[2]);
GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
half_width, half_height, GLES20.GL_LUMINANCE,
GLES20.GL_UNSIGNED_BYTE, bb);
} else {
mTextureWidth = 0;
mTextureHeight = 0;
}
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
mViewportWidth = width;
mViewportHeight = height;
}
@Override
public void onDrawFrame(GL10 gl) {
mFrameLock.lock();
if (mCurrentFrame != null && !mVideoDisabled) {
GLES20.glUseProgram(mProgram);
if (mTextureWidth != mCurrentFrame.getWidth()
|| mTextureHeight != mCurrentFrame.getHeight()) {
setupTextures(mCurrentFrame);
}
updateTextures(mCurrentFrame);
Matrix.setIdentityM(mScaleMatrix, 0);
float scaleX = 1.0f, scaleY = 1.0f;
float ratio = (float) mCurrentFrame.getWidth()
/ mCurrentFrame.getHeight();
float vratio = (float) mViewportWidth / mViewportHeight;
if (mVideoFitEnabled) {
if (ratio > vratio) {
scaleY = vratio / ratio;
} else {
scaleX = ratio / vratio;
}
} else {
if (ratio < vratio) {
scaleY = vratio / ratio;
} else {
scaleX = ratio / vratio;
}
}
Matrix.scaleM(mScaleMatrix, 0,
scaleX * (mCurrentFrame.isMirroredX() ? -1.0f : 1.0f),
scaleY, 1);
int mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram,
"uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false,
mScaleMatrix, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, mVertexIndex.length,
GLES20.GL_UNSIGNED_SHORT, mDrawListBuffer);
} else {
//black frame when video is disabled
gl.glClearColor(0, 0, 0, 1);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
}
mFrameLock.unlock();
}
public void displayFrame(Frame frame) {
mFrameLock.lock();
if (this.mCurrentFrame != null) {
this.mCurrentFrame.recycle();
}
this.mCurrentFrame = frame;
mFrameLock.unlock();
}
public static int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public void disableVideo(boolean b) {
mFrameLock.lock();
mVideoDisabled = b;
if (mVideoDisabled) {
if (this.mCurrentFrame != null) {
this.mCurrentFrame.recycle();
}
this.mCurrentFrame = null;
}
mFrameLock.unlock();
}
public void enableVideoFit(boolean enableVideoFit) {
mVideoFitEnabled = enableVideoFit;
}
}
public CustomVideoRenderer(Context context) {
this.mContext = context;
mView = new GLSurfaceView(context);
mView.setEGLContextClientVersion(2);
mRenderer = new MyRenderer();
mView.setRenderer(mRenderer);
mView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
@Override
public void onFrame(Frame frame) {
mRenderer.displayFrame(frame);
mView.requestRender();
}
@Override
public void setStyle(String key, String value) {
if (BaseVideoRenderer.STYLE_VIDEO_SCALE.equals(key)) {
if (BaseVideoRenderer.STYLE_VIDEO_FIT.equals(value)) {
mRenderer.enableVideoFit(true);
} else if (BaseVideoRenderer.STYLE_VIDEO_FILL.equals(value)) {
mRenderer.enableVideoFit(false);
}
}
}
@Override
public void onVideoPropertiesChanged(boolean videoEnabled) {
mRenderer.disableVideo(!videoEnabled);
}
@Override
public View getView() {
return mView;
}
@Override
public void onPause() {
mView.onPause();
}
@Override
public void onResume() {
mView.onResume();
}
最佳答案
https://tokbox.com/developer/sdks/android/reference/com/opentok/android/Session.SessionOptions.html
您可以使用 TextureViews() 返回一个 TextureViews,然后通常的圆角方法似乎可以工作。
关于android - OpenTok Android Lib 如何以圆形显示发布者 View (相机预览),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32867599/
我想使用 Java 实现各种发布者/订阅者模式,但目前没有想法。 有 1 个发布者和 N 个订阅者,发布者发布对象,然后每个订阅者需要按照正确的顺序处理每个对象一次且仅一次。发布者和每个订阅者在自己的
我正在学习发布者/订阅者模式,并做了一个简单的例子来更好地理解它。 var Publisher = { subscribers: {}, Subscribe: functi
这是我目前挂断的一般设计问题。它导致了一些心理代码块......如果它只是一个常见的陷阱,我不想继续这样,但如果它被接受使用,我想继续,因为代码非常干净并且解耦(除了横切消息)。 我在代码中有一个基于
当我打开安装程序(使用NSIS创建)时,会出现UAC对话框,其中包含有关安装程序的信息。字段发布者为“未知”。我听说过对应用程序进行数字签名,您知道如何在NSIS中执行此操作吗? 如何将字段/属性发布
我正在使用具有 DefaultMessageListenerContainer 的 pub/sub 模型。我已将并发消费者配置为 5 个。如何唯一标识每个消费者? 我试图将相应监听器处理的每个事件存储
我想创建一个可以从不同线程调用的 RabbitMQ 发布者。 根据 RabbitMQ 最佳实践,我不应允许在不同线程中使用同一 channel ,因此在发布者的多个实例中共享此 channel 将导致
是否可以仅通过使用事件(即不是列表或字典)在 WCF 中实现发布者/订阅者模型? 如果是,请向我提供示例应用程序的网络链接,或任何讨论此问题的文章。 最佳答案 是的。 Here是一篇关于它的 MSDN
我使用 rosjava 作为订阅者和 rospy 作为发布者实现了发布/订阅。但是,我没有收到 rospy 的任何消息。我在这里错过了什么吗? JAVA 订阅者(假设 IP 为:1.1.1.1) pu
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
我正在尝试签署一个小程序,这样发布者就不会显示为“未知”: 我为一个组织工作,我们有我们自己的证书颁发机构,证书链如下:ORG Root CA > ORG Trusted Certification
这是对我尝试使用 combine 实现的目标的过度简化。 如果发生某些事情,我需要向共享发布者注入(inject)一个值。 在这里您可以看到,如果 map 接收到数字 2,我使用原始发布者上的发送命令
我们有以下使用 .NET RabbitMQ 库的场景: 工作线程从队列中获取“请求”消息,并将它们分派(dispatch)到多个工作线程上进行处理。完成后,每个工作线程都会发送另一条消息。 我的问题是
当我将一些 Objective-C 代码移植到 Swift 时,我试图更好地理解新的 Combine 框架以及我如何使用它来重新创建一个通用的设计模式。 在这种情况下,设计模式是单个对象(管理器、服务
我有一个基本的 ZeroMQ 场景,由两个发布者和一个订阅者组成。在我决定将局域网内不同计算机上的所有进程分开之前,这在本地计算机上一直运行良好。这就是我创建 ZeroMQ 套接字的方式(简化的 Py
我目前正在尝试使用 0MQ 创建代理。我想订阅一个不在 0MQ 下运行的发布者。我的意思是我有发送 XML 文件的远程发布者的地址和端口,我想获取该文件。不幸的是,我没有收到发布者的任何消息,但它发送
我尝试使用 C++ 在 ZeroMQ 中开发发布者订阅者模型,我从 JSON 文件中提取对象值并将其发送到另一端。 我的订户部分运行良好,但出现任何错误。但是我在发布者部分面临以下错误:(在 if 语
我问过 Google 并搜索过 NServiceBus 网站和论坛,但我似乎找不到任何关于如何编写 Java 应用程序来订阅发布者的说明性指导。有没有人有任何这样的联系或经验? 最佳答案 这种情况并没
有谁知道如何使用 CruiseControl.Net 发布到 FTP 服务器? 最佳答案 我认为没有特定的方法可以做到这一点。您当然可以始终在 cruise control.net 的窗口中运行命令行
我正在尝试使用Ocelot在ASP.Net API网关中使用JWT承载身份验证,以与多个授权机构/发行者一起工作。一个颁发者是Auth0,另一个是基于IdentityServer4的内部身份验证服务器
如何删除 Visual Studio Marketplace 发布者? 在 https://marketplace.visualstudio.com/manage/publishers/ 上查看我的帐
我是一名优秀的程序员,十分优秀!