Skip to content

Commit

Permalink
feat(android): support multiple VideoFrameProcessors
Browse files Browse the repository at this point in the history
  • Loading branch information
wjaykim committed Feb 22, 2023
1 parent 871e29e commit 107106d
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 24 deletions.
32 changes: 20 additions & 12 deletions android/src/main/java/com/oney/WebRTCModule/GetUserMediaImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

/**
* The implementation of {@code getUserMedia} extracted into a separate file in
Expand Down Expand Up @@ -389,28 +392,33 @@ VideoTrack createVideoTrack(AbstractVideoCaptureController videoCaptureControlle
}

/**
* Set video effect to the TrackPrivate corresponding to the trackId with the help of VideoEffectProcessor
* corresponding to the name.
* Set video effects to the TrackPrivate corresponding to the trackId with the help of VideoEffectProcessor
* corresponding to the names.
* @param trackId TrackPrivate id
* @param name VideoEffectProcessor name
* @param names VideoEffectProcessor names
*/
void setVideoEffect(String trackId, String name) {
void setVideoEffects(String trackId, ReadableArray names) {
TrackPrivate track = tracks.get(trackId);

if (track != null && track.videoCaptureController instanceof CameraCaptureController) {
VideoSource videoSource = (VideoSource) track.mediaSource;
SurfaceTextureHelper surfaceTextureHelper = track.surfaceTextureHelper;

if (name != null) {
VideoFrameProcessor videoFrameProcessor = ProcessorProvider.getProcessor(name);

if (videoFrameProcessor == null) {
Log.e(TAG, "no videoFrameProcessor associated with this name");
return;
}
if (names != null) {
List<VideoFrameProcessor> processors = names.toArrayList().stream()
.filter(name -> name instanceof String)
.map(name -> {
VideoFrameProcessor videoFrameProcessor = ProcessorProvider.getProcessor((String) name);
if (videoFrameProcessor == null) {
Log.e(TAG, "no videoFrameProcessor associated with this name: " + name);
}
return videoFrameProcessor;
})
.filter(Objects::nonNull)
.collect(Collectors.toList());

VideoEffectProcessor videoEffectProcessor =
new VideoEffectProcessor(videoFrameProcessor, surfaceTextureHelper);
new VideoEffectProcessor(videoFrameProcessors, surfaceTextureHelper);
videoSource.setVideoProcessor(videoEffectProcessor);

} else {
Expand Down
7 changes: 5 additions & 2 deletions android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -862,9 +862,12 @@ private ReadableArray getTransceiversInfo(PeerConnection peerConnection) {
return transceiverUpdates;
}


@ReactMethod
public void mediaStreamTrackSetVideoEffect(String id, String name) {
ThreadUtils.runOnExecutor(() -> { getUserMediaImpl.setVideoEffect(id, name); });
public void mediaStreamTrackSetVideoEffects(String id, ReadableArray names) {
ThreadUtils.runOnExecutor(() -> {
getUserMediaImpl.setVideoEffects(id, names);
});
}

@ReactMethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@
import org.webrtc.VideoProcessor;
import org.webrtc.VideoSink;

import java.util.List;

/**
* Lightweight abstraction for an object that can receive video frames, process and add effects in
* them, and pass them on to another object.
*/
public class VideoEffectProcessor implements VideoProcessor {
private VideoSink mSink;
final private SurfaceTextureHelper textureHelper;
final private VideoFrameProcessor videoFrameProcessor;
final private List<VideoFrameProcessor> videoFrameProcessors;

public VideoEffectProcessor(VideoFrameProcessor processor, SurfaceTextureHelper textureHelper) {
public VideoEffectProcessor(List<VideoFrameProcessor> processors, SurfaceTextureHelper textureHelper) {
this.textureHelper = textureHelper;
this.videoFrameProcessor = processor;
this.videoFrameProcessors = processors;
}

@Override
Expand All @@ -39,15 +41,12 @@ public void setSink(VideoSink sink) {
@Override
public void onFrameCaptured(VideoFrame frame) {
frame.retain();
VideoFrame outputFrame = videoFrameProcessor.process(frame, textureHelper);

if (outputFrame == null) {
mSink.onFrame(frame);
frame.release();
return;
VideoFrame outputFrame = frame;
for (VideoFrameProcessor processor : this.videoFrameProcessors) {
outputFrame = processor.process(outputFrame, textureHelper);
}

mSink.onFrame(outputFrame);
outputFrame.release();
frame.release();
}
}

0 comments on commit 107106d

Please sign in to comment.