2015-07-06 4 views
1

Я пытаюсь отобразить экран моего устройства Android в браузере, используя projection API и Webrtc.Android - Get byte [] from Surface/virtualDisplay

Projection API выводит свой вывод на Surface и возвращает виртуальное изображение. Я сделал это до этого. Я видел библиотеку webrtc для Android. они сделали это для ввода только с камеры устройства. Я пытаюсь прочитать и изменить код webrtc, чтобы передать все, что показано на поверхности.

Мой вопрос: как я могу получать байт [] данные из surface, как функция Camera.PreviewCallback. Какие еще доступны другие варианты?

+0

Если рамки маленькие, вы можете передать их целиком. Если они нечасты, вы можете конвертировать их в JPEG или PNG. Если вы хотите, чтобы что-то приближалось к частоте обновления дисплея, вам нужно использовать видеокодер, чтобы преобразовать их в видеопоток. Ваш вопрос немного расплывчато для stackoverflow - этот сайт предназначен для конкретных вопросов программирования. – fadden

+0

@fadden Не могли бы вы взглянуть на этот вопрос: http://stackoverflow.com/questions/31183009/use-surfacetexture-to-render-video-stream-to-android-ordinary-view-above-api-lev Мне просто нужно, чтобы вы сказали «Да» или «Нет». – dragonfly

+0

@fadden. Я обновил вопрос. Просьба представить ваш комментарий. Если я думаю в неправильном направлении. пожалуйста, направьте меня в правильном направлении. – shubendrak

ответ

2

Вот как я решил свою проблему. Я использовал класс ImageReader как

imageReader = ImageReader.newInstance(displayWidth, displayHeight, PixelFormat.RGBA_8888, 2); 
mediaProjection.createVirtualDisplay("screencapture", 
        displayWidth, displayHeight, density, 
        flags, imageReader.getSurface(), null, handler); 
imageReader.setOnImageAvailableListener(new ImageAvailableListener(), null); 


private class ImageAvailableListener implements ImageReader.OnImageAvailableListener { 
    @Override 
    public void onImageAvailable(ImageReader reader) { 
     Image image = null; 
     Bitmap bitmap = null; 

     ByteArrayOutputStream stream = null; 

     try { 
      image = imageReader.acquireLatestImage(); 
      if (image != null) { 
       Image.Plane[] planes = image.getPlanes(); 
       ByteBuffer buffer = planes[0].getBuffer(); 
       int pixelStride = planes[0].getPixelStride(); 
       int rowStride = planes[0].getRowStride(); 
       int rowPadding = rowStride - pixelStride * displayWidth; 

       // create bitmap 
       bitmap = Bitmap.createBitmap(displayWidth + rowPadding/pixelStride, 
         displayHeight, Bitmap.Config.ARGB_8888); 
       bitmap.copyPixelsFromBuffer(buffer); 
        stream = new ByteArrayOutputStream(); 
        bitmap.compress(Bitmap.CompressFormat.JPEG, 50, stream); 
        StringBuilder sb = new StringBuilder(); 
        sb.append("data:image/png;base64,"); 
        sb.append(StringUtils.newStringUtf8(Base64.encode(stream.toByteArray(), Base64.DEFAULT))); 
       WebrtcClient.sendProjection(sb.toString()); 
      } 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

Я превращающий байты [] в Base64 строку и отправкой к через WebRTC datachannel.

+0

Какова была производительность ImageReader в этом случае, с точки зрения FPS? И почему вы решили отправить поток через datachannel, а не обычный видео канал? –

+0

@MichaelP Производительность ImageReader неплоха. Если вы не хотите иметь дело с поверхностной текстурой, тогда ImageReader является самым быстрым способом получить байт [] с поверхности. Я использовал для этого проекта webrtc-android sdk. Они подключили видео канал для работы с камерой устройства. Я попытался изменить это поведение, отредактировав исходный код и получив очень мало успеха. Вышеупомянутое решение отлично работало для меня. – shubendrak

+0

@Shubenda, спасибо за ваш ответ. Я на самом деле пытаюсь сделать то же самое, и сегодня я провожу весь день, пытаясь понять, как изменить свой код, чтобы сделать это. Это мой новый вопрос http://stackoverflow.com/questions/32084067/android-webrtc-custom-capturer Они действительно тесно связаны с оболочкой Java с реализацией C++. Вы упомянули SurfaceTexture, я не думаю, что SurfaceTexture может дать вам поверхность ввода (или взять поверхность), поэтому кажется, что единственным решением является использование ImageReader. Я просто хотел убедиться, что это не так медленно, как вызов glReadPixels, и он может сделать 30 FPS –

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

  • Нет связанных вопросов^_^