webRTC 读取帧保存为bitmap

简介: webRTC 读取帧保存为bitmap

1.在onFrame方法中传入frame

public void onFrame(VideoFrame frame) {
    saveImgBitmap(frame);
}

2.saveImgBitmap的实现

将frame转换为bitmap

    public Bitmap saveImgBitmap(VideoFrame frame){
        final Matrix drawMatrix = new Matrix();
        // Used for bitmap capturing.
        final GlTextureFrameBuffer bitmapTextureFramebuffer =
                new GlTextureFrameBuffer(GLES20.GL_RGBA);
        drawMatrix.reset();
        drawMatrix.preTranslate(0.5f, 0.5f);
        //控制图片的方向
        drawMatrix.preScale( -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);
        VideoFrameDrawer frameDrawer = new VideoFrameDrawer();
        RendererCommon.GlDrawer drawer = new GlRectDrawer();
        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 {
            File file = new File("/data/data/com.xxx.diagnose/files"+ "/test.jpg");
            if (!file.exists()){
                file.createNewFile();
            }
            OutputStream outputStream=new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.JPEG,100,outputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }
目录
相关文章
|
计算机视觉
opencv之 读取视频的帧数变成图片
opencv之 读取视频的帧数变成图片
126 0
|
6月前
|
编解码
视频I420裸流保存为文件
视频I420裸流保存为文件
av_read_frame每次返回的视频和音频帧数
av_read_frame每次返回的视频和音频帧数
73 0
av_read_frame每次返回的视频和音频帧数
|
内存技术
【音频处理】WAV 文件格式分析 ( 逐个字节解析文件头 | 相关字段的计算公式 )(三)
【音频处理】WAV 文件格式分析 ( 逐个字节解析文件头 | 相关字段的计算公式 )(三)
223 0
【音频处理】WAV 文件格式分析 ( 逐个字节解析文件头 | 相关字段的计算公式 )(三)
|
内存技术
【音频处理】WAV 文件格式分析 ( 逐个字节解析文件头 | 相关字段的计算公式 )(一)
【音频处理】WAV 文件格式分析 ( 逐个字节解析文件头 | 相关字段的计算公式 )(一)
412 0
【音频处理】WAV 文件格式分析 ( 逐个字节解析文件头 | 相关字段的计算公式 )(一)
|
内存技术
【音频处理】WAV 文件格式分析 ( 逐个字节解析文件头 | 相关字段的计算公式 )(二)
【音频处理】WAV 文件格式分析 ( 逐个字节解析文件头 | 相关字段的计算公式 )(二)
192 0
【音频处理】WAV 文件格式分析 ( 逐个字节解析文件头 | 相关字段的计算公式 )(二)
|
监控 Android开发 开发者
【Android 高性能音频】AAudio 音频流 缓冲区 简介 ( AAudio 音频流内部缓冲区 | 缓冲区帧容量 | 缓冲区帧大小 | 音频数据读写缓冲区 )
【Android 高性能音频】AAudio 音频流 缓冲区 简介 ( AAudio 音频流内部缓冲区 | 缓冲区帧容量 | 缓冲区帧大小 | 音频数据读写缓冲区 )
491 0
【Android 高性能音频】AAudio 音频流 缓冲区 简介 ( AAudio 音频流内部缓冲区 | 缓冲区帧容量 | 缓冲区帧大小 | 音频数据读写缓冲区 )
像素缓冲区对象(PBO) 的Streaming-Texture上传 源码解析
像素缓冲区对象(PBO) 的Streaming-Texture上传 源码解析
219 0
像素缓冲区对象(PBO) 的Streaming-Texture上传 源码解析
|
编解码 移动开发 Android开发
一文分析 mp4对比m3u8 第一帧加载慢的原因
公司要求对视频的 秒开率(1秒内成功加载的播放数 / 播放总数)、失败率 (播放失败的次数 / 播放总数) 等进行优化。经过线上AB测试发现,`m3u8视频(第一段切片为1~3秒)`在秒开率、失败率等性能指标上均优于`普通mp4视频`。这里探究一下,m3u8视频(第一段切片为1~3秒) 在秒开率上均优于 普通mp4视频 的原因。
1097 0