表面视图的屏幕截图(RTSP IP摄像机预览)

时间:2016-04-04 09:41:23

标签: android surfaceview

我一直在使用wifi网络摄像头进行项目。我能够将视频流式传输到surfaceview。我需要拍摄图像或想要拍摄表面视图的屏幕截图。每当我尝试捕捉屏幕截图时,我都会看到表面视图的黑色图像。有没有人知道如何在视频流开启时捕获表面视图。?

我尝试了以下代码并在egl.eglMakeCurrent(display,surface,surface,eglContext)中获得了一个Illegal参数异常; initGLFr()函数中的这一行

private void initGLFr()
{
    egl = (EGL10) EGLContext.getEGL();
    display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
    int[] ver = new int[2];
    egl.eglInitialize(display, ver);

    int[] configSpec = {EGL10.EGL_NONE};
    EGLConfig[] configOut = new EGLConfig[1];
    int[] nConfig = new int[1];
    egl.eglChooseConfig(display, configSpec, configOut, 1, nConfig);
    config = configOut[0];
    eglContext = egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, null);
    GLSurfaceView surfaceView = new GLSurfaceView(this);
    SurfaceHolder holder = surfaceView.getHolder();
    //////////////// ERROR!!!///////////
    surface = egl.eglCreateWindowSurface(display, config, holder, null);
    ///////////////////////////////////
    egl.eglMakeCurrent(display, surface, surface, eglContext);
    gl = (GL11) eglContext.getGL();
}

public void savePixels(int x, int y, int w, int h, GL10 gl)
{
    if (gl == null)
        return;

    synchronized (this) {
        if (mSavedBM != null) {
            mSavedBM.recycle();
            mSavedBM = null;
        }
    }

    int b[] = new int[w * (y + h)];
            int bt[] = new int[w * h];
    IntBuffer ib = IntBuffer.wrap(b);
    ib.position(0);
    gl.glReadPixels(x, 0, w, y + h, GL10.GL_RGBA,GL10.GL_UNSIGNED_BYTE,ib);

    for (int i = 0, k = 0; i < h; i++, k++)
    {
        //OpenGLbitmap is incompatible with Android bitmap
        //and so, some corrections need to be done.
        for (int j = 0; j < w; j++)
        {
            int pix = b[i * w + j];
            int pb = (pix >> 16) & 0xff;
            int pr = (pix << 16) & 0x00ff0000;
            int pix1 = (pix & 0xff00ff00) | pr | pb;
            bt[(h - k - 1) * w + j] = pix1;
        }
    }

    Bitmap sb = Bitmap.createBitmap(bt, w, h, Bitmap.Config.ARGB_8888);
    synchronized (this)
    {
        mSavedBM = sb;
    }
}

static String saveBitmap(Bitmap bitmap, String dir, String baseName) {
    try {
        File sdcard = Environment.getExternalStorageDirectory();
        File pictureDir = new File(sdcard, dir);
        pictureDir.mkdirs();
        File f = null;
        for (int i = 1; i < 200; ++i) {
            String name = baseName + i + ".png";
            f = new File(pictureDir, name);
            if (!f.exists()) {
                break;
            }
        }
        if (!f.exists()) {
            String name = f.getAbsolutePath();
            FileOutputStream fos = new FileOutputStream(name);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
            fos.flush();
            fos.close();
            return name;
        }
    } catch (Exception e) {

    } finally {

        //if (fos != null) {
        // fos.close();
        // }

    }
    return null;
}

1 个答案:

答案 0 :(得分:0)

由于评论中发布的各种链接指出,您无法从SurfaceView中获取框架。 glReadPixels()方法仅在 eglSwapBuffers()之前称为时,即在渲染发送到Surface之前;因为你试图捕捉视频信息,而不是GLES渲染,这是行不通的。

link posted by @AjayPandya将起作用,因为它将视频定向到SurfaceTexture,将每个帧转换为GLES纹理。有了它,您可以使用GLES渲染帧,并在将其发送到SurfaceView之前抓取它。

另一种方法是使用MediaProjection类通过虚拟显示捕获屏幕,但这有一些缺点(例如视频将缩放到屏幕尺寸)。