Skip to content

Latest commit

 

History

History
133 lines (97 loc) · 9.93 KB

content_share.md

File metadata and controls

133 lines (97 loc) · 9.93 KB

Content Share

Builders using the Amazon Chime SDK for Android can share a second video stream such as screen capture in a meeting without disrupting their applications existing audio/video stream.

Prerequisites

Sharing content with remote participants

Content share APIs are accessible from AudioVideoFacade. Builders will need to create a ContentShareSource which currently contains just the VideoSource desired to share in the meeting. A bundled screen capture source using MediaProjection is provided in DefaultScreenCaptureSource, but developers can also share any video source which implements VideoSource.

Constructing the provided screen capture source implementation

In DefaultScreenCaptureSource, the video frames are provided via the MediaProjection APIs, so an application will need to complete the following prerequisites before the implementation is ready for use:

  1. (Android Q and above only) Starting in Android Q, a foreground service is required before acquiring a MediaProjection through MediaProjectionManger.getMediaProjection. Applications will need to create a Service, defined in your AndroidManifest.xml and start it as foreground before starting the screen capture source. This will look like the following:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<application>
    <service
        android:name=".ScreenCaptureService"
        android:foregroundServiceType="mediaProjection" />
</application>
  1. To construct a DefaultScreenCaptureSource, request screen capture permissions from the user and use the result in the constructor parameters:
// Call this function when screen capture is desired
fun requestScreenCapturePermission() {
    mediaProjectionManager = getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager

    // Show prompt for screen capture permission
    startActivityForResult(
        mediaProjectionManager.createScreenCaptureIntent(),
        SCREEN_CAPTURE_REQUEST_CODE
    )
}

// Handle the result of permission prompt activity started
// in requestScreenCapturePermission
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    // ...
    if (SCREEN_CAPTURE_REQUEST_CODE == requestCode && resultCode == Activity.RESULT_OK && data != null) {
        // (Android Q and above) Start the service created in step 1
        startService(Intent(this, ScreenCaptureService::class.java))
 
        // Initialize a DefaultScreenCaptureSource instance using given result
        val screenCaptureSource = DefaultScreenCaptureSource(
            this,
            logger,
            // Use the same EglCoreFactory instance as passed into DefaultMeetingSession
            DefaultSurfaceTextureCaptureSourceFactory(
                logger,
                eglCoreFactory),
            resultCode,
            data
        )
        screenCaptureSource.start()
    }
    // ... Complete any other initialization
}

See Custom Video Sources, Processors, and Sinks for more information on the usage of EglCoreFactory. The capture source will not work if the factory is not shared between the capture and the meeting session due to use of GPU based video frames.

Using a custom video source

Refer to the Implementing a custom video source and transmitting section of the custom video guide to build a video source to share. Content share supports sharing any source which implements VideoSource.

Passing a video source into the facade

Once the video source is ready, wrap it with ContentShareSource to share the video.

// Construct the content share source
val contentShareSource = ContentShareSource()
contentShareSource.videoSource = screenCaptureSource // Or a custom source

// Start sharing the content share source to remote participants
audioVideo.startContentShare(contentShareSource)

// ...

// Stop sharing the source
audioVideo.stopContentShare()

Additionally, you can set configuration for content share, e.g. maxBitRateKbps. Actual quality achieved may vary throughout the call depending on what system and network can provide.

val contentShareConfig = LocalVideoConfiguration(200)
meetingSession.audioVideo.startContentShare(contentShareSource, contentShareConfig)

Note that the content share APIs do not manage the source and only provide a sink to transmit captured frames to remote participants, builders will be responsible to take care of its lifecycle including stopping and releasing the capture sources internal resources.

Receiving content share events

Applications can receive content share events by implementing methods from ContentShareObserver and subscribe with addContentShareObserver.

Viewing the content

Content shares are treated as regular audio-video attendees. The attendee ID of a content share is the same as the original attendee, but with a suffix of #content. Applications using the Amazon Chime SDK receive real-time attendee presence and video tile updates callbacks for content attendee using the exact same mechanisms as normal video.

To view the content share:

  1. Create an observer of VideoTileObserver that implements onVideoTileAdded to receive callbacks when the video tile is added.
  2. Subscribe the observer with addVideoTileObserver via audio video facade.
  3. In the onVideoTileAdded, bind the video tile to a VideoRenderView.
override fun onVideoTileAdded(tileState: VideoTileState) {
    // ...
    if (tileState.isContent) {
         audioVideo.bindVideoView(view.video_surface, tileState.tileId)
    }
}

Builders can use the VideoTileState.isContent to check if the video tile is a content share, and any add special logic you need to handle the content share.

You can also use the DefaultModality class to determine that an attendee ID is a content share:

if (DefaultModality(attendeeId).hasModality(ModalityType.Content)) {
  // ...special handling for content share...
}