Как поделиться экраном удаленно в видео / аудио звонке? - PullRequest
0 голосов
/ 14 февраля 2019

Я пытаюсь создать приложение для видеовызовов, которое имеет функцию совместного использования экрана.Пользователи могут поделиться своим экраном во время разговора.Я использую WebRTC SDK для достижения своей цели, но у них есть решение для общего экрана, когда вызов начинается, а не для общего экрана, когда вызов продолжается.Можно отметить опцию общего доступа к экрану и начать вызов, но не может начать общий доступ к экрану во время вызова.

Я добавил кнопку на экране CallActivity, которая по щелчку вызывает класс MediaProjection для Android, чтобы вызвать экран, но наложенныйэкран не отображается удаленно.

public void onScreenShare(boolean isScreenShared) {
    screencaptureEnabled = isScreenShared;
    if (screencaptureEnabled && videoWidth == 0 && videoHeight == 0) {
        DisplayMetrics displayMetrics = getDisplayMetrics();
        videoWidth = displayMetrics.widthPixels;
        videoHeight = displayMetrics.heightPixels;
    }

    if (isPemitted()) {
        startScreenCapture();
    } else {
        Log.i(TAG, "onScreenShare: not permitted");
    }

    /*if (peerConnectionClient != null) {
        peerConnectionClient.stopVideoSource();
    }*/
}

private void startScreenCapture() {
    MediaProjectionManager mediaProjectionManager =
            (MediaProjectionManager) getApplication().getSystemService(
                    Context.MEDIA_PROJECTION_SERVICE);
    startActivityForResult(
            mediaProjectionManager.createScreenCaptureIntent(), 
CAPTURE_PERMISSION_REQUEST_CODE);
    Log.d("tagged", ">>>>Method called :- ");
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) 
{
    Log.d("tagged", ">>>>Method called :- " + requestCode);
    if (requestCode != CAPTURE_PERMISSION_REQUEST_CODE)
        return;
    else {
        mediaProjectionPermissionResultCode = resultCode;
        mediaProjectionPermissionResultData = data;

if (peerConnectionParameters.videoCallEnabled) {
        videoCapturer = createVideoCapturer();
    }
    peerConnectionClient.createPeerConnection(
            localProxyVideoSink, remoteSinks, videoCapturer, 
 signalingParameters);
    }
}

private @Nullable
VideoCapturer createScreenCapturer() {
    Log.d("CheckMedia", ">>>Checking " + 
mediaProjectionPermissionResultData);
    if (mediaProjectionPermissionResultCode != Activity.RESULT_OK) {
        reportError("User didn't give permission to capture the screen.");
        return null;
    }
    return new ScreenCapturerAndroid(
            mediaProjectionPermissionResultData, new 
MediaProjection.Callback() {
        @Override
        public void onStop() {
            reportError("User revoked permission to capture the screen.");
        }
    });
}

Этот код запускает трансляцию на локальное устройство, но ничего не передает на удаленном устройстве.

ОБНОВЛЕНИЕ

 private void switchCameraInternal() {
    if (videoCapturer instanceof CameraVideoCapturer) {
        if (!isVideoCallEnabled() || isError) {
            Log.e(TAG,
                    "Failed to switch camera. Video: " + 
 isVideoCallEnabled() + ". Error : " + isError);
            return; // No video is sent or only one camera is available or 
 error happened.
        }
        Log.d(TAG, "Switch camera");
        CameraVideoCapturer cameraVideoCapturer = (CameraVideoCapturer) 
 videoCapturer;
        cameraVideoCapturer.switchCamera(null);

    } else {
        Log.d(TAG, "Will not switch camera, video caputurer is not a 
camera");
    }
 }

public void switchCamera() {
    executor.execute(this::switchCameraInternal);
}

private void startScreenSharing() {
    if (videoCapturer instanceof ScreenCapturerAndroid) {
        if (!isVideoCallEnabled() || isError) {
            Log.e(TAG,
                    "Failed to share screen. Video: " + isVideoCallEnabled() 
+ ". Error : " + isError);
            return; // No video is sent or only one camera is available or 
error happened.
        }
        ScreenCapturerAndroid screenCapturerAndroid = 
(ScreenCapturerAndroid) videoCapturer;
        screenCapturerAndroid.startCapture(500, 500, 30);
    }
}

public void screenSharing() {
    executor.execute(this::startScreenSharing);
}

Я внес изменения и сделал код похожим на код switchCamera (), но я получаю исключение Not On Camera Thread.

1 Ответ

0 голосов
/ 14 февраля 2019

Я не уверен, что вы можете транслировать с Camera и Screen одновременно.Однако, что вы можете сделать:

  1. Пользователь нажимает кнопку общего доступа к экрану
  2. Вы удаляете свою Камера видеодорожку из вашей PeerConnection, используя PeerConnection.removeTrack(RtpSender sender)
  3. Вы создаете свой экран видео дорожку, используя ScreenCapturerAndroid (как вы уже делаете)
  4. Вы добавляете дорожку к своему PeerConnection

Если вы говорите, что общий ресурс экрана работает без вызова, то шаги 4 и 5 уже должны быть выполнены.

Не забудьте утилизировать / освободить все ресурсы, связанные с Camera, при удалении его дорожки.

Также, чтобы остановить общий доступ к Screen и вернуться к Camera , просто выполните описанные выше шаги для дорожки Screen .

Для справки: PeerConnection.java

ОБНОВЛЕНИЕ:

Вот часть клиента WebRTC, которая позволяет мне достичь того, кем вы являетесьзапрашивая (вы можете адаптировать его к вашей текущей базе кода):

private fun stopCameraShare(){
        videoCapturerAndroid?.stopCapture()
        localRenderer.dispose()
        localVideoView.release()
        localVideoView.clearImage()
        stream?.removeTrack(localVideoTrack)
        localVideoTrack.dispose()
    }
private fun shareScreen(){
        stopCameraShare()
        val mediaProjectionManager = activity!!.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
        startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), 29)
    }

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (requestCode != 29)
            return
        initVideos()
        videoCapturerAndroid = ScreenCapturerAndroid(
            data, object : MediaProjection.Callback() {
                override fun onStop() {
                    Timber.e("User revoked permission to capture the screen.")
                }
            })
        peerConnectionFactory.setVideoHwAccelerationOptions(rootEglBase.eglBaseContext, rootEglBase.eglBaseContext)
        videoSource = peerConnectionFactory.createVideoSource(videoCapturerAndroid)
        localVideoTrack = peerConnectionFactory.createVideoTrack("100", videoSource)
        videoCapturerAndroid?.startCapture(300, 300, 30)
        stream?.addTrack(localVideoTrack)
    }

PS: очень важно peerConnectionFactory.setVideoHwAccelerationOptions(rootEglBase.eglBaseContext, rootEglBase.eglBaseContext)

Надеюсь, что это будетпомочь вам!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...