Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better video toggle with black frame sender #101

Merged
merged 32 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f08bb1c
trials
Aug 15, 2024
7ba6c55
fix screenshare on targetSdk 34
Aug 15, 2024
56c589c
Merge branch 'master' into fixSdk34ScreenShare
Aug 15, 2024
5848de1
screen share integration test
Aug 15, 2024
42d126d
switch video source during conference
Aug 22, 2024
ec680c6
Merge branch 'fixSdk34ScreenShare' into screenShareConference
Aug 22, 2024
99dd3ec
integration test, some improvement to sample
Aug 22, 2024
f613a23
small fix
Aug 22, 2024
b9ac365
sample fix
Aug 22, 2024
54517f4
Merge branch 'master' into screenShareConference
Aug 23, 2024
a5c719c
Merge branch 'master' into screenShareConference
Aug 23, 2024
7ff820f
trials
Aug 26, 2024
6c31ddd
ws url fix
Aug 26, 2024
94cedd2
black frame sender
Aug 27, 2024
d4d53c4
black frame sender
Aug 27, 2024
2628d47
Merge branch 'screenShareConference' into betterVideoToggle
Aug 27, 2024
2d23864
fixes and integration test
Aug 27, 2024
aae9359
unittest
Aug 28, 2024
3953d44
Merge branch 'master' into betterVideoToggle
Aug 28, 2024
0427665
remove debug stuff on publish activity
Aug 28, 2024
69fe085
small fix
Aug 30, 2024
332f3ac
integration test fix
Sep 1, 2024
6ef3097
Merge branch 'master' into betterVideoToggle
Sep 1, 2024
be2be82
black frame sender refactor and faster test trials
Sep 3, 2024
c3b510e
faster integration tests
Sep 4, 2024
d0a47a9
nptr check
Sep 4, 2024
098d77c
nptr trial
Sep 4, 2024
d8ba692
debug ci
Sep 4, 2024
9def482
fix
Sep 4, 2024
b517220
improve black frame sender
Sep 5, 2024
e604d72
stability
Sep 6, 2024
71407dd
stability
Sep 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,15 @@ void publish(String streamId, String token, boolean videoCallEnabled, boolean au

/**
* This is used to join a conference room
* @param roomId: id for the conference room
* @param streamId: id for the participant
*
* @param roomId: id for the conference room
* @param streamId: id for the participant
* @param videoCallEnabled: true if it's a video call
* @param audioCallEnabled: true if it's an audio call
* @param token: token to authenticate
* @param subscriberId: id of the subscriber
* @param subscriberCode: code of the subscriber
* @param streamName: name of the stream
* @param token: token to authenticate
* @param subscriberId: id of the subscriber
* @param subscriberCode: code of the subscriber
* @param streamName: name of the stream
*/
void joinToConferenceRoom(String roomId, String streamId, boolean videoCallEnabled, boolean audioCallEnabled, String token, String subscriberId, String subscriberCode, String streamName);

Expand Down Expand Up @@ -161,21 +162,26 @@ void publish(String streamId, String token, boolean videoCallEnabled, boolean au

/**
* Sets quality of a stream/subtrack to certain resolution.
*
* @param mainTrackStreamId : If its a single stream pass its streamId as mainTrackId. If you want to change resolution of a subtrack, pass mainTrack stream Id and subtrack stream Id.
* @param subTrackStreamId : If you want to change resolution of sub track, pass its subTrack stream Id. If you dont want to change subtrack resolution pass null or empty str.
* @param subTrackStreamId : If you want to change resolution of sub track, pass its subTrack stream Id. If you dont want to change subtrack resolution pass null or empty str.
* @param resolutionHeight: The height to be forced. If you set the height to zero, it will become auto. example: For 720p pass 720 as resolution.
*/
void forceStreamQuality(String mainTrackStreamId, String subTrackStreamId, int resolutionHeight);

/**
* enable/disable video stream
* enable/disable video stream of call. Use this before call start.
* Eg if you call this method before call start with false, you wont be able to turn on video stream during call.
* For in call video sending toggle use toggleSendVideo
*
* @param enabled true for enable, false for disable
*/
void setVideoEnabled(boolean enabled);

/**
* enable/disable audio stream
* enable/disable audio stream of call.
* Use this before call start.
* For in call audio sending(for example muting microphone) toggle use toggleSendAudio
*
* @param enabled true for enable, false for disable
*/
Expand All @@ -184,11 +190,11 @@ void publish(String streamId, String token, boolean videoCallEnabled, boolean au
/**
* enable/disable played track stream from the server
*
* @param streamId id for the main track
* @param selecetedTrack id for the subtrack
* @param enabled true for enable, false for disable
* @param streamId id for the main track
* @param selectedTrack id for the subtrack
* @param enabled true for enable, false for disable
*/
void enableTrack(String streamId, String selecetedTrack, boolean enabled);
void enableTrack(String streamId, String selectedTrack, boolean enabled);

/**
* Called to set the renderer for a video track
Expand Down Expand Up @@ -331,4 +337,35 @@ void publish(String streamId, String token, boolean videoCallEnabled, boolean au
* Returns true if SDK resources are released and its shutdown, false otherwise.
*/
boolean isShutdown();

/**
* Use this to get the local audio track status.
* E.g., if the microphone is off, it will return false. If the microphone is on, it will return true.
*/
boolean isLocalAudioTrackEnabled();

/**
* Use this to toggle sending video during a call.
* E.g., turn the camera on or off during a call.
*/
void toggleSendVideo(boolean enableVideo);

/**
* Use this to toggle sending audio during a call.
* E.g., call this with false to mute the microphone during a call.
*/
void toggleSendAudio(boolean enableAudio);

/**
* Get the audio sending status.
* E.g., if the microphone is muted, it will return false; otherwise, it will return true.
*/
boolean isSendAudioEnabled();

/**
* Get the video sending status.
* E.g., if the camera is turned off, it will return false; otherwise, it will return true.
*/
boolean isSendVideoEnabled();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package io.antmedia.webrtcandroidframework.core;

import android.os.SystemClock;

import org.webrtc.*;

import java.nio.ByteBuffer;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


public class BlackFrameSender {
public static int BLACK_FRAME_SENDING_FREQUENCY_MS = 3000;
private CustomVideoCapturer videoCapturer;
private ScheduledExecutorService executorService;
private boolean running;
private int frameWidth = 240;
private int frameHeight = 426;
private ByteBuffer yBuffer;
private ByteBuffer uBuffer;
private ByteBuffer vBuffer;

public BlackFrameSender(CustomVideoCapturer videoCapturer) {
this.videoCapturer = videoCapturer;
allocateBlackFrameBuffers();
}

public void start(){
if(executorService == null){
executorService = Executors.newScheduledThreadPool(1);
executorService.scheduleWithFixedDelay(() -> {

try{
videoCapturer.writeFrame(createBlackFrame());
}catch (Exception e){
e.printStackTrace();
}

}, 0, BLACK_FRAME_SENDING_FREQUENCY_MS, TimeUnit.MILLISECONDS);
running = true;
}


}
public void stop(){
if(executorService != null){
executorService.shutdown();
executorService = null;
running = false;
releaseByteBuffers();
}
}

public void releaseByteBuffers(){
if (yBuffer != null) {
yBuffer.clear();
yBuffer = null;
}
if (uBuffer != null) {
uBuffer.clear();
uBuffer = null;
}
if (vBuffer != null) {
vBuffer.clear();
vBuffer = null;
}
}

public boolean isRunning(){
return running;
}

//capture time needs to be incremented. Otherwise server does not ingest the stream.
public VideoFrame createBlackFrame() {
long captureTimeNs = TimeUnit.MILLISECONDS.toNanos(SystemClock.elapsedRealtime());
return new VideoFrame(createBlackFrameBuffer(), 0, captureTimeNs);
}

public void allocateBlackFrameBuffers(){

int ySize = frameWidth * frameHeight;
int uvWidth = frameWidth / 2;
int uvHeight = frameHeight / 2;
int uvSize = uvWidth * uvHeight;

yBuffer = ByteBuffer.allocateDirect(ySize);
uBuffer = ByteBuffer.allocateDirect(uvSize);
vBuffer = ByteBuffer.allocateDirect(uvSize);

for (int i = 0; i < ySize; i++) {
yBuffer.put((byte) 0);
}

for (int i = 0; i < uvSize; i++) {
uBuffer.put((byte) 128);
vBuffer.put((byte) 128);
}

yBuffer.flip();
uBuffer.flip();
vBuffer.flip();

}

public JavaI420Buffer createBlackFrameBuffer(){
int uvWidth = frameWidth / 2;
return JavaI420Buffer.wrap(frameWidth, frameHeight, yBuffer, frameWidth, uBuffer, uvWidth, vBuffer, uvWidth, null);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,13 @@ public void setQueuedRemoteCandidates(List<IceCandidate> queuedRemoteCandidates)

private String roomId;

private BlackFrameSender blackFrameSender;

private boolean sendVideoEnabled = true;

private boolean sendAudioEnabled = true;


public void createReconnectorRunnables() {
//only used in conference.
publishReconnectorRunnable = () -> {
Expand Down Expand Up @@ -387,6 +394,8 @@ public WebRTCClient(WebRTCClientConfig config) {
mainHandler = new Handler(config.activity.getMainLooper());
iceServers.add(PeerConnection.IceServer.builder(config.stunServerUri)
.createIceServer());
sendAudioEnabled = config.audioCallEnabled;
sendVideoEnabled = config.videoCallEnabled;

if(config.turnServerUri != null) {
iceServers.add(PeerConnection.IceServer.builder(config.turnServerUri)
Expand Down Expand Up @@ -974,7 +983,7 @@ private void publishPlayIfRequested() {

public void publish(String streamId) {
publish(streamId, null, true, true,
null, null, streamId, "qdadsas");
null, null, streamId, null);
}


Expand Down Expand Up @@ -2175,13 +2184,16 @@ public void closeInternal() {
eglBase.release();
eglBase = null;
}
if(blackFrameSender != null){
blackFrameSender.stop();
blackFrameSender = null;
}

localVideoSink.setTarget(null);

Log.d(TAG, "Closing peer connection done.");
onPeerConnectionClosed();


clearStatsCollector();
reconnectionInProgress = false;
peerReconnectionHandler.removeCallbacksAndMessages(null);
Expand Down Expand Up @@ -2248,6 +2260,36 @@ public void setVideoEnabled(final boolean enable) {
});
}

public void toggleSendAudio(boolean enableAudio) {
executor.execute(() -> {
sendAudioEnabled = enableAudio;
if (localAudioTrack != null) {
localAudioTrack.setEnabled(enableAudio);
}
});
}

public void toggleSendVideo(boolean enableVideo) {
if(!config.videoCallEnabled){
Log.i(TAG, "Cannot change send video because video call is disabled.");
return;
}
executor.execute(() -> {
sendVideoEnabled = enableVideo;
if (enableVideo) {
if(blackFrameSender != null && blackFrameSender.isRunning()){
blackFrameSender.stop();
blackFrameSender = null;
}
changeVideoSource(StreamSource.FRONT_CAMERA);
} else {
changeVideoSource(StreamSource.CUSTOM);
blackFrameSender = new BlackFrameSender((CustomVideoCapturer) getVideoCapturer());
blackFrameSender.start();
}
});
}

public void createOffer(String streamId) {

executor.execute(() -> {
Expand Down Expand Up @@ -2719,6 +2761,20 @@ public void toggleAudioOfAllParticipants(boolean enabled) {
}
}

public boolean isLocalVideoTrackEnabled(){
if(localVideoTrack == null){
return false;
}
return localVideoTrack.enabled();
}

public boolean isLocalAudioTrackEnabled(){
if(localAudioTrack == null){
return false;
}
return localAudioTrack.enabled();
}

public void setHandler(Handler handler) {
this.handler = handler;
}
Expand All @@ -2742,6 +2798,10 @@ public VideoCapturer getVideoCapturer() {
return videoCapturer;
}

public void setVideoCapturer(VideoCapturer videoCapturer){
this.videoCapturer = videoCapturer;
}

public void setRemoveVideoRotationExtension(boolean removeVideoRotationExtension) {
this.removeVideoRotationExtension = removeVideoRotationExtension;
}
Expand Down Expand Up @@ -2778,4 +2838,27 @@ public boolean isShutdown() {
return released;
}

@Override
public boolean isSendVideoEnabled() {
return sendVideoEnabled;
}

@Override
public boolean isSendAudioEnabled() {
return sendAudioEnabled;
}

public BlackFrameSender getBlackFrameSender() {
return blackFrameSender;
}

@androidx.annotation.Nullable
public AudioTrack getLocalAudioTrack() {
return localAudioTrack;
}

public void setLocalAudioTrack(@androidx.annotation.Nullable AudioTrack localAudioTrack) {
this.localAudioTrack = localAudioTrack;
}

}
Loading
Loading