2016-04-04 2 views
0

Я работаю над проектом с использованием IP-камеры Wi-Fi. Я могу передать видео на поверхность. Мне нужно захватить изображение или сделать снимок экрана с поверхности. Всякий раз, когда я пытаюсь сделать снимок экрана, я получаю черное изображение поверхности. кто-нибудь знает, как захватить поверхностный вид, пока поток видео включен.?Снимок экрана с поверхности (предварительный просмотр камеры RTSP)

Я пробовал следующий код и получал исключение незаконного аргумента в egl.eglMakeCurrent (отображение, поверхность, поверхность, eglContext); эта линия в 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; 
} 
+0

только google вы найдете много сообщений на стеке тоже –

+0

ребята, я пробовал эти методы. К сожалению, это не сработало. – Sreyas

+0

@Shanu, тогда объясните, где эти методы терпят неудачу для вас ... – ben75

ответ

0

Как различные ссылки, размещенные в комментариях указать, вы не можете захватить кадр из SurfaceView. Подход glReadPixels() работает только тогда, когда он называется доeglSwapBuffers(), то есть до того, как рендеринг был отправлен на поверхность; поскольку вы пытаетесь захватить видеопоток, а не рендеринг GLES, это не сработает.

link posted by @AjayPandya будет работать, поскольку он направляет видео на SurfaceTexture, которая преобразует каждый кадр в текстуру GLES. С этим вы можете визуализировать кадр с помощью GLES и захватить его до его отправки в SurfaceView.

Другой подход заключается в использовании класса MediaProjection для захвата экрана через виртуальный дисплей, но это имеет несколько недостатков (например, видео будет масштабироваться до размеров экрана).

Смежные вопросы