Render Video - VideoView
At the very least for rendering video you'll need an instance of HMSVideoView
and a HMSVideoTrack
instance from a peer.
Adding HMSVideoView dependency
The latest HMSVideoView SDK version is:
dependencies { def hmsVersion = "x.x.x" implementation "live.100ms:android-sdk:$hmsVersion" // Essential base sdk implementation "live.100ms:video-view:$hmsVersion" // HMSVideoView }
Minimum Requirements
- SDK version 2.5.3 or higher
In XML layouts it would look like
<live.hms.videoview.HMSVideoView android:id="@+id/peer_video" android:layout_width="match_parent" android:layout_height="wrap_content" />
The peer's video is in hmsPeer.videoTrack
and their ScreenShare video will be an instance of HMSVideoTrack
in the list hmsPeer.auxiliaryTracks
.
You would get them like so:
val hmsVideoTrack : HMSVideoTrack? = hmsPeer.videoTrack
Getting HMSVideoView
Get an instance of the HMSVideoView.
val hmsVideoView : HMSVideoView = findViewById(R.id.peer_video)
Set the scaling to whatever you prefer. Aspect Fit is recommended for common use cases. See more scale types here.
hmsVideoView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT)
Adding a video to the HMSVideoView
Each time you want to add a video to the HMSVideoView, you'll just need to update addTrack()
.
val hmsVideoTrack : HMSVideotrack = hmsPeer.videoTrack hmsVideoView.addTrack(hmsVideoTrack)
It's also important to remove it when done.
Removing a video from the HMSVideoView
It's very important to remove the video when you're done showing it.
hmsVideoView.removeTrack()
Until you call removeTrack()
the video frame is being streamed over the device's data.
Capture Video Frame
You can get a bitmap object of the frame getting rendered on the HMSVideoView
In case you are calling this API on a videoView
which is rendering localVideoTrack
, it will return a bitmap whose resolution would be equal to the resolution at which this peer is supposed to publish.
hmsVideoView.captureBitmap(onBitmap: (Bitmap?) -> Unit, scale: Float = 1.0f)
Disabling Auto Simulcast
HMSVideoView has an automatic simulcast layer selection capability which is enabled if adaptive bitrate is enabled. You can check more about it here
It will select a layer that best matches the current view frame size and reacts to frame updates. In case manual layer selection is preferred set disableAutoSimulcastLayerSelect
property to true
. By default, the track layer is set to high
.
hmsVideoView.disableAutoSimulcastLayerSelect(true)
Special cases for videos in RecyclerViews
If you're going to be using a RecyclerView to display multiple videos in a grid there are specific places where you should do these operations.
Currently the best known way is in the ViewHolder to have a method for binding items, a method to start the HMSVideoView addTrack()
and a method to removeTrack()
the hmsVideoView.
Two additional Adapter methods are overloaded. onViewAttachedToWindow
and onViewDetachedFromWindow
which will call HMSVideoView adding and removing video track respectively.
Complete source code is available here.
PeerViewHolder
init
Video-Scale type can be set here.
startHMSVideoView
will add the video track.
stopHMSVideoView
will remove the attched video track.
class PeerViewHolder(view: View, private val getItem: (Int) -> TrackPeerMap) : RecyclerView.ViewHolder(view) { init { itemView.findViewById<HMSVideoView>(R.id.peer_video).apply { setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT) } } fun startHMSVideoView() { itemView.findViewById<HMSVideoView>(R.id.peer_video).apply { getItem(adapterPosition).videoTrack?.let { hmsVideoTrack -> hmsVideoTrack.addTrack(this) } } } fun stopHMSVideoView() { itemView.findViewById<HMSVideoView>(R.id.peer_video).apply { if (adapterPosition != -1) { getItem(adapterPosition).videoTrack?.let { hmsVideoTrack -> hmsVideoTrack.removeTrack() } } } } fun bind(peer: TrackPeerMap) { itemView.findViewById<HMSVideoView>(R.id.peer_video).apply { setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT) } ... itemView.findViewById<TextView>(R.id.peerName).text = peer.peer.name } }
PeerAdapter
override fun onBindViewHolder(holder: PeerViewHolder, position: Int) { getItem(position)?.let { holder.stopHMSVideoView() holder.bind(it) } } override fun onViewAttachedToWindow(holder: PeerViewHolder) { super.onViewAttachedToWindow(holder) holder.startHMSVideoView() } override fun onViewDetachedFromWindow(holder: PeerViewHolder) { super.onViewDetachedFromWindow(holder) holder.stopHMSVideoView() } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PeerViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_peer_item, parent, false) return PeerViewHolder(view, ::getItem) }