Datos personalizados byteArray a WebRTC videoTrack

Necesito usar WebRTC para android para enviar el vídeo cortado específico (cara) al videoChannel. Fui capaz de manipular la clase Camera1Session de WebRTC para obtener la cara recortada. En este momento lo estoy configurando a un ImageView. listenForBytebufferFrames() de Camera1Session.java

 private void listenForBytebufferFrames() { this.camera.setPreviewCallbackWithBuffer(new PreviewCallback() { public void onPreviewFrame(byte[] data, Camera callbackCamera) { Camera1Session.this.checkIsOnCameraThread(); if(callbackCamera != Camera1Session.this.camera) { Logging.e("Camera1Session", "Callback from a different camera. This should never happen."); } else if(Camera1Session.this.state != Camera1Session.SessionState.RUNNING) { Logging.d("Camera1Session", "Bytebuffer frame captured but camera is no longer running."); } else { mFrameProcessor.setNextFrame(data, callbackCamera); long captureTimeNs = TimeUnit.MILLISECONDS.toNanos(SystemClock.elapsedRealtime()); if(!Camera1Session.this.firstFrameReported) { int startTimeMs = (int)TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - Camera1Session.this.constructionTimeNs); Camera1Session.camera1StartTimeMsHistogram.addSample(startTimeMs); Camera1Session.this.firstFrameReported = true; } ByteBuffer byteBuffer1 = ByteBuffer.wrap(data); Frame outputFrame = new Frame.Builder() .setImageData(byteBuffer1, Camera1Session.this.captureFormat.width, Camera1Session.this.captureFormat.height, ImageFormat.NV21) .setTimestampMillis(mFrameProcessor.mPendingTimeMillis) .setId(mFrameProcessor.mPendingFrameId) .setRotation(3) .build(); int w = outputFrame.getMetadata().getWidth(); int h = outputFrame.getMetadata().getHeight(); SparseArray<Face> detectedFaces = mDetector.detect(outputFrame); if (detectedFaces.size() > 0) { Face face = detectedFaces.valueAt(0); ByteBuffer byteBufferRaw = outputFrame.getGrayscaleImageData(); byte[] byteBuffer = byteBufferRaw.array(); YuvImage yuvimage = new YuvImage(byteBuffer, ImageFormat.NV21, w, h, null); ByteArrayOutputStream baos = new ByteArrayOutputStream(); //My crop logic to get face co-ordinates yuvimage.compressToJpeg(new Rect(left, top, right, bottom), 80, baos); final byte[] jpegArray = baos.toByteArray(); Bitmap bitmap = BitmapFactory.decodeByteArray(jpegArray, 0, jpegArray.length); Activity currentActivity = getActivity(); if (currentActivity instanceof CallActivity) { ((CallActivity) currentActivity).setBitmapToImageView(bitmap); //face on ImageView is set just fine } Camera1Session.this.events.onByteBufferFrameCaptured(Camera1Session.this, data, Camera1Session.this.captureFormat.width, Camera1Session.this.captureFormat.height, Camera1Session.this.getFrameOrientation(), captureTimeNs); Camera1Session.this.camera.addCallbackBuffer(data); } else { Camera1Session.this.events.onByteBufferFrameCaptured(Camera1Session.this, data, Camera1Session.this.captureFormat.width, Camera1Session.this.captureFormat.height, Camera1Session.this.getFrameOrientation(), captureTimeNs); Camera1Session.this.camera.addCallbackBuffer(data); } } } }); } 

jpegArray es el byteArray final que necesito transmitir a través de WebRTC , lo que intenté con algo como esto:

 Camera1Session.this.events.onByteBufferFrameCaptured(Camera1Session.this, jpegArray, (int) face.getWidth(), (int) face.getHeight(), Camera1Session.this.getFrameOrientation(), captureTimeNs); Camera1Session.this.camera.addCallbackBuffer(jpegArray); 

Configurarlos así me da el siguiente error:

 ../../webrtc/sdk/android/src/jni/androidvideotracksource.cc line 82 Check failed: length >= width * height + 2 * uv_width * ((height + 1) / 2) (2630 vs. 460800) 

Lo que supongo es porque androidvideotracksource no obtiene la misma longitud de byteArray que espera, ya que el marco se recorta ahora. ¿Podría alguien señalarme en la dirección de cómo lograrlo? ¿Es esta la forma correcta / lugar para manipular los datos y alimentar en el videoTrack ?

Edit: bitmap de bitmap de data byteArray no me da una vista previa de la cámara en ImageView , a diferencia de byteArray jpegArray . Tal vez porque están llenos de forma diferente?

3 Solutions collect form web for “Datos personalizados byteArray a WebRTC videoTrack”

¿Podemos usar Datachannel de WebRTC para intercambiar datos personalizados, es decir, cortar la cara de "imagen" en su caso y hacer el cálculo respectivo en el extremo de recepción utilizando cualquier biblioteca de terceros, por ejemplo, OpenGL etc? La razón que estoy sugiriendo es que la alimentación video de WebRTC recibida del canal es una corriente en tiempo real no un bytearray. WebRTC Video por su arquitectura inherente no está destinado a recortar vídeo por otro lado. Si queremos recortar o aumentar video tenemos que usar cualquier biblioteca ar para cumplir con este trabajo.

Siempre podemos aprovechar el canal de datos de WebRTC para intercambiar datos personalizados. No se recomienda usar el canal de video para el mismo porque es en tiempo real no el bytearray.Please revertir en caso de cualquier preocupación.

WebRTC en particular y la transmisión de vídeo en general supone que el vídeo tiene dimensiones fijas. Si desea recortar el rostro detectado, sus opciones son o bien tener la imagen recortada con p.ej. píxeles negros (WebRTC no utiliza transparencia) y recortar el vídeo en el lado del receptor o, si no tiene control sobre El receptor, cambiar el tamaño de la región recortada para rellenar el width * height esperado width * height marco de width * height (también debe mantener la proporción de aspecto esperada).

Tenga en cuenta que JPEG comprimir / descomprimir que se utiliza para recortar el original está lejos de ser eficiente. Algunas otras opciones se pueden encontrar en Recorte de imagen y cambiar el tamaño en Android .

Bueno, esto fue definitivamente un problema de cómo los byte[] data original estaban llenos y el byte[] jpegArray estaba lleno. Cambiar la forma de empacar esto y escalarlo como sugirió AlexCohn funcionó para mí. Encontré ayuda de otro post en StackOverflow en forma de empacarlo. Este es el código para ello:

 private byte[] getNV21(int left, int top, int inputWidth, int inputHeight, Bitmap scaled) { int [] argb = new int[inputWidth * inputHeight]; scaled.getPixels(argb, 0, inputWidth, left, top, inputWidth, inputHeight); byte [] yuv = new byte[inputWidth*inputHeight*3/2]; encodeYUV420SP(yuv, argb, inputWidth, inputHeight); scaled.recycle(); return yuv; } private void encodeYUV420SP(byte[] yuv420sp, int[] argb, int width, int height) { final int frameSize = width * height; int yIndex = 0; int uvIndex = frameSize; int a, R, G, B, Y, U, V; int index = 0; for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { a = (argb[index] & 0xff000000) >> 24; // a is not used obviously R = (argb[index] & 0xff0000) >> 16; G = (argb[index] & 0xff00) >> 8; B = (argb[index] & 0xff) >> 0; // well known RGB to YUV algorithm Y = ( ( 66 * R + 129 * G + 25 * B + 128) >> 8) + 16; U = ( ( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128; V = ( ( 112 * R - 94 * G - 18 * B + 128) >> 8) + 128; // NV21 has a plane of Y and interleaved planes of VU each sampled by a factor of 2 // meaning for every 4 Y pixels there are 1 V and 1 U. Note the sampling is every other // pixel AND every other scanline. yuv420sp[yIndex++] = (byte) ((Y < 0) ? 0 : ((Y > 255) ? 255 : Y)); if (j % 2 == 0 && index % 2 == 0) { yuv420sp[uvIndex++] = (byte)((V<0) ? 0 : ((V > 255) ? 255 : V)); yuv420sp[uvIndex++] = (byte)((U<0) ? 0 : ((U > 255) ? 255 : U)); } index ++; } } }` 

Paso este byte[] data a onByteBufferFrameCaptured y callback :

 Camera1Session.this.events.onByteBufferFrameCaptured( Camera1Session.this, data, w, h, Camera1Session.this.getFrameOrientation(), captureTimeNs); Camera1Session.this.camera.addCallbackBuffer(data); 

Antes de esto, tuve que escalar el mapa de bits que es bastante sencillo:

 int width = bitmapToScale.getWidth(); int height = bitmapToScale.getHeight(); Matrix matrix = new Matrix(); matrix.postScale(newWidth / width, newHeight / height); Bitmap scaledBitmap = Bitmap.createBitmap(bitmapToScale, 0, 0, bitmapToScale.getWidth(), bitmapToScale.getHeight(), matrix, true); 
  • ¿Cómo implementar la videoconferencia de conferencia telefónica de 3 vías con WebRTC Native Code para Android?
  • WebRTC llega a Android WebView? ¿Cuando?
  • Native Android WebRTC aplicación de desarrollo
  • Creación de una aplicación mediante la demostración WebRTC AppRtc
  • Cómo agregar funcionalidad WebRTC en la aplicación de Android
  • Compartición de pantallas de Android con WebRTC
  • WebRTC Conference Quality utilizando varias PeerConnection
  • ERROR al compilar Web RTC
  • Volumen de audio de Android webRTC
  • Flujo de aplicaciones para la conexión peer to peer de Android?
  • Cómo utilizar WebRTC + Pubnub Api para el cliente de chat de vídeo en la aplicación Native android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.