Gab*_*tin 5 android opengl-es glsl
我有一个基于grafika 示例的直播应用程序,我通过 RTMP 发送我的视频源以进行直播。
我现在想通过在我的视频流上覆盖文本或徽标来为我的视频添加水印。我知道这可以通过 GLSL 过滤来完成,但我不知道如何根据我链接的示例来实现这一点。
我尝试使用 Alpha 混合,但似乎这两种纹理格式在某种程度上不兼容(一种是 TEXTURE_EXTERNAL_OES,另一种是 TEXTURE_2D),而我只是得到一个黑框作为回报。
编辑:
我的代码基于Kickflip API:
class CameraSurfaceRenderer implements GLSurfaceView.Renderer {
private static final String TAG = "CameraSurfaceRenderer";
private static final boolean VERBOSE = false;
private CameraEncoder mCameraEncoder;
private FullFrameRect mFullScreenCamera;
private FullFrameRect mFullScreenOverlay; // For texture overlay
private final float[] mSTMatrix = new float[16];
private int mOverlayTextureId;
private int mCameraTextureId;
private boolean mRecordingEnabled;
private int mFrameCount;
// Keep track of selected filters + relevant state
private boolean mIncomingSizeUpdated;
private int mIncomingWidth;
private int mIncomingHeight;
private int mCurrentFilter;
private int mNewFilter;
boolean showBox = false;
/**
* Constructs CameraSurfaceRenderer.
* <p>
* @param recorder video encoder object
*/
public CameraSurfaceRenderer(CameraEncoder recorder) {
mCameraEncoder = recorder;
mCameraTextureId = -1;
mFrameCount = -1;
SessionConfig config = recorder.getConfig();
mIncomingWidth = config.getVideoWidth();
mIncomingHeight = config.getVideoHeight();
mIncomingSizeUpdated = true; // Force texture size update on next onDrawFrame
mCurrentFilter = -1;
mNewFilter = Filters.FILTER_NONE;
mRecordingEnabled = false;
}
/**
* Notifies the renderer that we want to stop or start recording.
*/
public void changeRecordingState(boolean isRecording) {
Log.d(TAG, "changeRecordingState: was " + mRecordingEnabled + " now " + isRecording);
mRecordingEnabled = isRecording;
}
@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
Log.d(TAG, "onSurfaceCreated");
// Set up the texture blitter that will be used for on-screen display. This
// is *not* applied to the recording, because that uses a separate shader.
mFullScreenCamera = new FullFrameRect(
new Texture2dProgram(Texture2dProgram.ProgramType.TEXTURE_EXT));
// For texture overlay:
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
mFullScreenOverlay = new FullFrameRect(
new Texture2dProgram(Texture2dProgram.ProgramType.TEXTURE_2D));
mOverlayTextureId = GlUtil.createTextureWithTextContent("hello!");
mOverlayTextureId = GlUtil.createTextureFromImage(mCameraView.getContext(), R.drawable.red_dot);
mCameraTextureId = mFullScreenCamera.createTextureObject();
mCameraEncoder.onSurfaceCreated(mCameraTextureId);
mFrameCount = 0;
}
@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
Log.d(TAG, "onSurfaceChanged " + width + "x" + height);
}
@Override
public void onDrawFrame(GL10 unused) {
if (VERBOSE){
if(mFrameCount % 30 == 0){
Log.d(TAG, "onDrawFrame tex=" + mCameraTextureId);
mCameraEncoder.logSavedEglState();
}
}
if (mCurrentFilter != mNewFilter) {
Filters.updateFilter(mFullScreenCamera, mNewFilter);
mCurrentFilter = mNewFilter;
mIncomingSizeUpdated = true;
}
if (mIncomingSizeUpdated) {
mFullScreenCamera.getProgram().setTexSize(mIncomingWidth, mIncomingHeight);
mFullScreenOverlay.getProgram().setTexSize(mIncomingWidth, mIncomingHeight);
mIncomingSizeUpdated = false;
Log.i(TAG, "setTexSize on display Texture");
}
// Draw the video frame.
if(mCameraEncoder.isSurfaceTextureReadyForDisplay()){
mCameraEncoder.getSurfaceTextureForDisplay().updateTexImage();
mCameraEncoder.getSurfaceTextureForDisplay().getTransformMatrix(mSTMatrix);
//Drawing texture overlay:
mFullScreenOverlay.drawFrame(mOverlayTextureId, mSTMatrix);
mFullScreenCamera.drawFrame(mCameraTextureId, mSTMatrix);
}
mFrameCount++;
}
public void signalVertialVideo(FullFrameRect.SCREEN_ROTATION isVertical) {
if (mFullScreenCamera != null) mFullScreenCamera.adjustForVerticalVideo(isVertical, false);
}
/**
* Changes the filter that we're applying to the camera preview.
*/
public void changeFilterMode(int filter) {
mNewFilter = filter;
}
public void handleTouchEvent(MotionEvent ev){
mFullScreenCamera.handleTouchEvent(ev);
}
}
Run Code Online (Sandbox Code Playgroud)
这是在屏幕上渲染图像 (GLSurfaceView) 的代码,但这实际上并未覆盖在视频上。如果我没记错的话,这是在CameraEncoder上完成的。
问题是,将代码从 CameraSurfaceRenderer 复制到 CameraEncoder(它们在过滤器方面都有相似的代码)不会提供叠加的文本/图像。
纹理对象使用 GL_TEXTURE_EXTERNAL_OES 纹理目标,该目标由 GL_OES_EGL_image_external OpenGL ES 扩展定义。这限制了纹理的使用方式。每次绑定纹理时,都必须将其绑定到 GL_TEXTURE_EXTERNAL_OES 目标而不是 GL_TEXTURE_2D 目标。此外,任何从纹理采样的 OpenGL ES 2.0 着色器都必须使用“#extension GL_OES_EGL_image_external : require”指令来声明其对此扩展的使用。此类着色器还必须使用samplerExternalOES GLSL 采样器类型访问纹理。
https://developer.android.com/reference/android/graphics/SurfaceTexture.html
发布你用来进行 alpha 混合的代码,我可能可以修复它。
我可能会覆盖Texture2dProgram并将其传递给全帧渲染器。它具有使用GL_TEXTURE_EXTERNAL_OES
扩展进行渲染的示例代码。基本上,@Overridedraw
函数,调用基本实现,绑定水印并绘制。
那应该是在相机和视频编码器之间。
归档时间: |
|
查看次数: |
987 次 |
最近记录: |