android webrtc 视频流源码获取帧图像VideoFrame转bitmap 作为图像识别
16lz
2021-01-26
由于需要使用opencv等项目识别webrtc中的画面需要对webrtc的摄像头进行采集该方法在EglRenderer implements VideoSink 类的onFrame中增加saveImgBitmap(frame)方法来获取图像具体代码如下
// VideoSink interface.@Overridepublic void onFrame(VideoFrame frame){ //将org.webrtc.VideoFrame转bitmap并保存 saveImgBitmap(frame) synchronized (statisticsLock) { ++framesReceived; } final boolean dropOldFrame; synchronized (handlerLock) { if (renderThreadHandler == null) { logD("Dropping frame - Not initialized or already released."); return; } synchronized (frameLock) { dropOldFrame = (pendingFrame != null); if (dropOldFrame) { pendingFrame.release(); } pendingFrame = frame; pendingFrame.retain(); renderThreadHandler.post(this ::renderFrameOnRenderThread); } } if (dropOldFrame) { synchronized (statisticsLock) { ++framesDropped; } } }}
class EglRenderer implements VideoSink { ...... private final Matrix drawMatrix = new Matrix(); // Used for bitmap capturing. private final GlTextureFrameBuffer bitmapTextureFramebuffer = new GlTextureFrameBuffer(GLES20.GL_RGBA); ......public void saveImgBitmap(VideoFrame frame){ drawMatrix.reset(); drawMatrix.preTranslate(0.5f, 0.5f); drawMatrix.preScale(mirrorHorizontally ? -1f : 1f, mirrorVertically ? -1f : 1f); drawMatrix.preScale(1f, -1f); // We want the output to be upside down for Bitmap. drawMatrix.preTranslate(-0.5f, -0.5f); final int scaledWidth = (int) (1 * frame.getRotatedWidth()); final int scaledHeight = (int) (1 * frame.getRotatedHeight()); bitmapTextureFramebuffer.setSize(scaledWidth, scaledHeight); GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, bitmapTextureFramebuffer.getFrameBufferId()); GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, bitmapTextureFramebuffer.getTextureId(), 0); GLES20.glClearColor(0 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); frameDrawer.drawFrame(frame, drawer, drawMatrix, 0 /* viewportX */, 0 /* viewportY */, scaledWidth, scaledHeight); final ByteBuffer bitmapBuffer = ByteBuffer.allocateDirect(scaledWidth * scaledHeight * 4); GLES20.glViewport(0, 0, scaledWidth, scaledHeight); GLES20.glReadPixels( 0, 0, scaledWidth, scaledHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, bitmapBuffer); GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); GlUtil.checkNoGLES2Error("EglRenderer.notifyCallbacks"); final Bitmap bitmap = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888); bitmap.copyPixelsFromBuffer(bitmapBuffer); try { OutputStream outputStream=new FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+"atest/"+System.currentTimeMillis()+".jpg"); bitmap.compress(Bitmap.CompressFormat.JPEG,100,outputStream); } catch (FileNotFoundException e) { e.printStackTrace(); } }}
更多相关文章
- Mac版的Android(安卓)Eclipse识别手机问题
- Android(安卓)银行卡扫描识别获取卡号
- Android摄像头开发:拍照后添加相框,融合相框和图片为一副 图片
- 阿里巴巴人脸离线活体识别Android
- Android(安卓)使用 Android(安卓)Camera API 完成音视频的采集、
- android调用手机摄像头拍照
- 分析各种Android设备屏幕分辨率与适配 - 使用大量真实安卓设备采
- SystemUI密码解锁后指纹识别清除次数
- 语音识别(加注释)