8000 New video constraints syntax by davidliu · Pull Request #790 · flutter-webrtc/flutter-webrtc · GitHub
[go: up one dir, main page]

Skip to content
8000

New video constraints syntax #790

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

Merged
merged 7 commits into from
Dec 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

10000
Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 45 additions & 38 deletions android/src/main/java/com/cloudwebrtc/webrtc/GetUserMediaImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class GetUserMediaImpl {
private static final String PERMISSION_AUDIO = Manifest.permission.RECORD_AUDIO;
private static final String PERMISSION_VIDEO = Manifest.permission.CAMERA;
private static final String PERMISSION_SCREEN = "android.permission.MediaProjection";
private static int CAPTURE_PERMISSION_REQUEST_CODE = 1;
private static final int CAPTURE_PERMISSION_REQUEST_CODE = 1;
private static final String GRANT_RESULTS = "GRANT_RESULT";
private static final String PERMISSIONS = "PERMISSION";
private static final String PROJECTION_DATA = "PROJECTION_DATA";
Expand All @@ -103,8 +103,6 @@ class GetUserMediaImpl {
private final Context applicationContext;

static final int minAPILevel = Build.VERSION_CODES.LOLLIPOP;
private MediaProjectionManager mProjectionManager = null;
private static MediaProjection sMediaProjection = null;

final AudioSamplesInterceptor inputSamplesInterceptor = new AudioSamplesInterceptor();
private OutputAudioSamplesInterceptor outputSamplesInterceptor = null;
Expand Down Expand Up @@ -351,23 +349,6 @@ private AudioTrack getUserAudio(ConstraintsMap constraints) {
void getUserMedia(
final ConstraintsMap constraints, final Result result, final MediaStream mediaStream) {

// TODO: change getUserMedia constraints format to support new syntax
// constraint format seems changed, and there is no mandatory any more.
// and has a new syntax/attrs to specify resolution
// should change `parseConstraints()` according
// see: https://www.w3.org/TR/mediacapture-streams/#idl-def-MediaTrackConstraints

ConstraintsMap videoConstraintsMap = null;
ConstraintsMap videoConstraintsMandatory = null;

if (constraints.getType("video") == ObjectType.Map) {
videoConstraintsMap = constraints.getMap("video");
if (videoConstraintsMap.hasKey("mandatory")
&& videoConstraintsMap.getType("mandatory") == ObjectType.Map) {
videoConstraintsMandatory = videoConstraintsMap.getMap("mandatory");
}
}

final ArrayList<String> requestPermissions = new ArrayList<>();

if (constraints.hasKey("audio")) {
Expand Down Expand Up @@ -441,18 +422,6 @@ public void invoke(Object... args) {

void getDisplayMedia(
final ConstraintsMap constraints, final Result result, final MediaStream mediaStream) {
ConstraintsMap videoConstraintsMap = null;
ConstraintsMap videoConstraintsMandatory = null;

if (constraints.getType("video") == ObjectType.Map) {
videoConstraintsMap = constraints.getMap("video");
if (videoConstraintsMap.hasKey("mandatory")
&& videoConstraintsMap.getType("mandatory") == ObjectType.Map) {
videoConstraintsMandatory = videoConstraintsMap.getMap("mandatory");
}
}

final ConstraintsMap videoConstraintsMandatory2 = videoConstraintsMandatory;

screenRequestPremissions(
new ResultReceiver(new Handler(Looper.getMainLooper())) {
Expand Down Expand Up @@ -640,6 +609,34 @@ private void getUserMedia(

private boolean isFacing = true;

/**
* @return Returns the integer at the key, or the `ideal` property if it is a map.
*/
@Nullable
private Integer getConstrainInt(@Nullable ConstraintsMap constraintsMap, String key) {
if(constraintsMap == null){
return null;
}

if (constraintsMap.getType(key) == ObjectType.Number) {
try {
return constraintsMap.getInt(key);
} catch (Exception e) {
// Could be a double instead
return (int) Math.round(constraintsMap.getDouble(key));
}
}

if (constraintsMap.getType(key) == ObjectType.Map) {
ConstraintsMap innerMap = constraintsMap.getMap(key);
if (constraintsMap.getType("ideal") == ObjectType.Number) {
return innerMap.getInt("ideal");
}
}

return null;
}

private VideoTrack getUserVideo(ConstraintsMap constraints) {
ConstraintsMap videoConstraintsMap = null;
ConstraintsMap videoConstraintsMandatory = null;
Expand All @@ -651,6 +648,7 @@ private VideoTrack getUserVideo(ConstraintsMap constraints) {
}
}


Log.i(TAG, "getUserMedia(video): " + videoConstraintsMap);

// NOTE: to support Camera2, the device should:
Expand Down Expand Up @@ -688,16 +686,25 @@ private VideoTrack getUserVideo(ConstraintsMap constraints) {
surfaceTextureHelper, applicationContext, videoSource.getCapturerObserver());

VideoCapturerInfo info = new VideoCapturerInfo();
info.width =
videoConstraintsMandatory != null && videoConstraintsMandatory.hasKey("minWidth")

Integer videoWidth = getConstrainInt(videoConstraintsMap, "width");
info.width = videoWidth != null
? videoWidth
: videoConstraintsMandatory != null && videoConstraintsMandatory.hasKey("minWidth")
? videoConstraintsMandatory.getInt("minWidth")
: DEFAULT_WIDTH;
info.height =
videoConstraintsMandatory != null && videoConstraintsMandatory.hasKey("minHeight")

Integer videoHeight = getConstrainInt(videoConstraintsMap, "height");
info.height = videoHeight != null
? videoHeight
: videoConstraintsMandatory != null && videoConstraintsMandatory.hasKey("minHeight")
? videoConstraintsMandatory.getInt("minHeight")
: DEFAULT_HEIGHT;
info.fps =
videoConstraintsMandatory != null && videoConstraintsMandatory.hasKey("minFrameRate")

Integer videoFrameRate = getConstrainInt(videoConstraintsMap, "frameRate");
info.fps = videoFrameRate != null
? videoFrameRate
: videoConstraintsMandatory != null && videoConstraintsMandatory.hasKey("minFrameRate")
? videoConstraintsMandatory.getInt("minFrameRate")
: DEFAULT_FPS;
info.capturer = videoCapturer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,11 @@ public ConstraintsArray getArray(String name){
public ArrayList<Object> getListArray(String name){
return (ArrayList<Object>) mMap.get(name);
}

@Override
public String toString() {
return "ConstraintsMap{" +
"mMap=" + mMap +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ public class MediaConstraintsUtils {
public static MediaConstraints parseMediaConstraints(ConstraintsMap constraints) {
MediaConstraints mediaConstraints = new MediaConstraints();

// TODO: change getUserMedia constraints format to support new syntax
// constraint format seems changed, and there is no mandatory any more.
// and has a new syntax/attrs to specify resolution
// should change `parseConstraints()` according
// see: https://www.w3.org/TR/mediacapture-streams/#idl-def-MediaTrackConstraints
if (constraints.hasKey("mandatory")
&& constraints.getType("mandatory") == ObjectType.Map) {
parseConstraints(constraints.getMap("mandatory"),
Expand Down
40 changes: 34 additions & 6 deletions common/cpp/src/flutter_media_stream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -133,36 +133,64 @@ std::string getSourceIdConstraint(const EncodableMap& mediaConstraints) {
return "";
}

EncodableValue getConstrainInt(const EncodableMap& constraints, const std::string& key) {
EncodableValue value;
auto it = constraints.find(EncodableValue(key));
if(it != constraints.end()) {
if(TypeIs<int>(it->second)) {
return it->second;
}

if(TypeIs<EncodableMap>(it->second)) {
EncodableMap innerMap = GetValue<EncodableMap>(it->second);
auto it2 = innerMap.find(EncodableValue("ideal"));
if(it2 != constraints.end() && TypeIs<int>(it2->second)){
return it2->second;
}
}
}

return EncodableValue();
}

void FlutterMediaStream::GetUserVideo(const EncodableMap& constraints,
scoped_refptr<RTCMediaStream> stream,
EncodableMap& params) {
EncodableMap video_constraints;
EncodableMap video_mandatory;
auto it = constraints.find(EncodableValue("video"));
if (it != constraints.end() && TypeIs<EncodableMap>(it->second)) {
EncodableMap video_map = GetValue<EncodableMap>(it->second);
if (video_map.find(EncodableValue("mandatory")) != video_map.end()) {
video_constraints = GetValue<EncodableMap>(it->second);
if (video_constraints.find(EncodableValue("mandatory")) != video_constraints.end()) {
video_mandatory =
GetValue<EncodableMap>(video_map.find(EncodableValue("mandatory"))->second);
GetValue<EncodableMap>(video_constraints.find(EncodableValue("mandatory"))->second);
}
}

std::string facing_mode = getFacingMode(video_constraints);
//bool isFacing = facing_mode == "" || facing_mode != "environment";
std::string sourceId = getSourceIdConstraint(video_constraints);

EncodableValue widthValue = findEncodableValue(video_mandatory, "minWidth");
EncodableValue widthValue = getConstrainInt(video_constraints, "width");

if (widthValue == EncodableValue())
widthValue = findEncodableValue(video_mandatory, "minWidth");

if (widthValue == EncodableValue())
widthValue = findEncodableValue(video_mandatory, "width");

EncodableValue heightValue = findEncodableValue(video_mandatory, "minHeight");
EncodableValue heightValue = getConstrainInt(video_constraints, "height");

if(heightValue == EncodableValue())
heightValue = findEncodableValue(video_mandatory, "minHeight");

if (heightValue == EncodableValue())
heightValue = findEncodableValue(video_mandatory, "height");

EncodableValue fpsValue = getConstrainInt(video_constraints, "frameRate");

EncodableValue fpsValue = findEncodableValue(video_mandatory, "minFrameRate");
if(fpsValue == EncodableValue())
fpsValue = findEncodableValue(video_mandatory, "minFrameRate");

if (fpsValue == EncodableValue())
fpsValue = findEncodableValue(video_mandatory, "frameRate");
Expand Down
43 changes: 43 additions & 0 deletions common/darwin/Classes/FlutterRTCMediaStream.m
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,34 @@ - (void)getUserMedia:(NSDictionary *)constraints
successCallback(mediaStream);
}

- (int)getConstrainInt:(NSDictionary *)constraints
forKey:(NSString *)key {

if (![constraints isKindOfClass:[NSDictionary class]]) {
return 0;
}

id constraint = constraints[key];
if ([constraint isKindOfClass:[NSNumber class]]) {
return [constraint intValue];
} else if ([constraint isKindOfClass:[NSString class]]) {
int possibleValue = [constraint intValue];
if (possibleValue != 0) {
return possibleValue;
}
} else if ([constraint isKindOfClass:[NSDictionary class]]) {
id idealConstraint = constraint[@"ideal"];
if([idealConstraint isKindOfClass: [NSString class]]) {
int possibleValue = [idealConstraint intValue];
if(possibleValue != 0){
return possibleValue;
}
}
}

return 0;
}

/**
* Initializes a new {@link RTCVideoTrack} which satisfies specific constraints,
* adds it to a specific {@link RTCMediaStream}, and reports success to a
Expand Down Expand Up @@ -301,6 +329,21 @@ - (void)getUserVideo:(NSDictionary *)constraints
}
}

int possibleWidth = [self getConstrainInt:videoConstraints forKey:@"width"];
if(possibleWidth != 0){
self._targetWidth = possibleWidth;
}

int possibleHeight = [self getConstrainInt:videoConstraints forKey:@"height"];
if(possibleHeight != 0){
self._targetHeight = possibleHeight;
}

int possibleFps = [self getConstrainInt:videoConstraints forKey:@"frameRate"];
if(possibleFps != 0){
self._targetFps = possibleFps;
}

if (videoDevice) {
RTCVideoSource *videoSource = [self.peerConnectionFactory videoSource];
if (self.videoCapturer) {
Expand Down
0