2016-04-04 9 views
0

Ich habe an einem Projekt mit einer WiFi-IP-Kamera gearbeitet. Ich kann das Video zu einer Oberflächenansicht streamen. Ich muss ein Bild aufnehmen oder einen Screenshot einer Oberflächenansicht machen. Immer wenn ich versuche, einen Screenshot aufzunehmen, erhalte ich ein schwarzes Bild der Oberflächenansicht. weiß jemand, wie man eine Oberflächenansicht aufnimmt, während der Videostream eingeschaltet ist?Screenshot einer Oberflächenansicht (RTSP IP-Kameravorschau)

Ich habe versucht den folgenden Code und eine ungültige Argument Ausnahme bei egl.eglMakeCurrent (Anzeige, Oberfläche, Oberfläche, eglContext); diese Linie in initGLFr() Funktion

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

nur Google finden Sie viele Post auf Stapel zu –

+0

Jungs Ich habe diese Methoden ausprobiert. Hat leider nicht funktioniert. – Sreyas

+0

@Shanu dann erklären, wo diese Methoden für Sie fehlschlagen ... – ben75

Antwort

0

Da die verschiedenen in den Kommentaren ausgebrachten Links hinweisen, können Sie nicht ein Bild aus einem Surface greifen. Die Methode glReadPixels() funktioniert nur, wenn sie voreglSwapBuffers() heißt, d. H. Bevor das Rendering an die Oberfläche gesendet wurde; Da Sie versuchen, einen Video-Feed statt GLES-Rendering zu erfassen, funktioniert das nicht.

Die link posted by @AjayPandya wird funktionieren, da es das Video zu einem SurfaceTexture leitet, das jeden Frame in eine GLES-Textur konvertiert. Damit können Sie den Rahmen mit GLES rendern und vor dem Senden an das SurfaceView aufnehmen.

Ein anderer Ansatz besteht darin, die MediaProjection Klasse zu verwenden, um den Bildschirm über eine virtuelle Anzeige zu erfassen, aber das hat einige Nachteile (z. B. wird das Video auf Bildschirmabmessungen skaliert).