29
29
import android .os .Looper ;
30
30
import android .os .ResultReceiver ;
31
31
import android .provider .MediaStore ;
32
- import android .util .DisplayMetrics ;
33
32
import android .util .Log ;
33
+ import android .util .Pair ;
34
34
import android .util .Range ;
35
35
import android .util .SparseArray ;
36
36
import android .view .Display ;
58
58
import org .webrtc .AudioTrack ;
59
59
import org .webrtc .Camera1Capturer ;
60
60
import org .webrtc .Camera1Enumerator ;
61
+ import org .webrtc .Camera1Helper ;
61
62
import org .webrtc .Camera2Capturer ;
62
63
import org .webrtc .Camera2Enumerator ;
64
+ import org .webrtc .Camera2Helper ;
63
65
import org .webrtc .CameraEnumerationAndroid .CaptureFormat ;
64
66
import org .webrtc .CameraEnumerator ;
65
67
import org .webrtc .CameraVideoCapturer ;
66
68
import org .webrtc .MediaConstraints ;
67
69
import org .webrtc .MediaStream ;
68
70
import org .webrtc .MediaStreamTrack ;
69
71
import org .webrtc .PeerConnectionFactory ;
72
+ import org .webrtc .Size ;
70
73
import org .webrtc .SurfaceTextureHelper ;
71
74
import org .webrtc .VideoCapturer ;
72
75
import org .webrtc .VideoSource ;
@@ -266,13 +269,12 @@ private void addDefaultAudioConstraints(MediaConstraints audioConstraints) {
266
269
* @param isFacing 'user' mapped with 'front' is true (default) 'environment' mapped with 'back'
267
270
* is false
268
271
* @param sourceId (String) use this sourceId and ignore facing mode if specified.
269
- * @return VideoCapturer can invoke with <tt>startCapture</tt>/<tt>stopCapture</tt> <tt>null</tt>
272
+ * @return Pair of deviceName to VideoCapturer. Can invoke with <tt>startCapture</tt>/<tt>stopCapture</tt> <tt>null</tt>
270
273
* if not matched camera with specified facing mode.
271
274
*/
272
- private Map <String , VideoCapturer > createVideoCapturer (
275
+ private Pair <String , VideoCapturer > createVideoCapturer (
273
276
CameraEnumerator enumerator , boolean isFacing , String sourceId , CameraEventsHandler cameraEventsHandler ) {
274
- VideoCapturer videoCapturer = null ;
275
- Map <String , VideoCapturer > result = new HashMap <String , VideoCapturer >();
277
+ VideoCapturer videoCapturer ;
276
278
// if sourceId given, use specified sourceId first
277
279
final String [] deviceNames = enumerator .getDeviceNames ();
278
280
if (sourceId != null && !sourceId .equals ("" )) {
@@ -281,8 +283,7 @@ private Map<String, VideoCapturer> createVideoCapturer(
281
283
videoCapturer = enumerator .createCapturer (name , cameraEventsHandler );
282
284
if (videoCapturer != null ) {
283
285
Log .d (TAG , "create user specified camera " + name + " succeeded" );
284
- result .put (name , videoCapturer );
285
- return result ;
286
+ return new Pair <>(name , videoCapturer );
286
287
} else {
287
288
Log .d (TAG , "create user specified camera " + name + " failed" );
288
289
break ; // fallback to facing mode
@@ -298,22 +299,22 @@ private Map<String, VideoCapturer> createVideoCapturer(
298
299
videoCapturer = enumerator .createCapturer (name , cameraEventsHandler );
299
300
if (videoCapturer != null ) {
300
301
Log .d (TAG , "Create " + facingStr + " camera " + name + " succeeded" );
301
- result . put ( name , videoCapturer );
302
- return result ;
302
+
303
+ return new Pair <>( name , videoCapturer ) ;
303
304
} else {
304
305
Log .e (TAG , "Create " + facingStr + " camera " + name + " failed" );
305
306
}
306
307
}
307
308
}
308
309
309
310
// falling back to the first available camera
310
- if (videoCapturer == null && deviceNames .length > 0 ) {
311
+ if (deviceNames .length > 0 ) {
311
312
videoCapturer = enumerator .createCapturer (deviceNames [0 ], cameraEventsHandler );
312
313
Log .d (TAG , "Falling back to the first available camera" );
313
- result . put (deviceNames [0 ], videoCapturer );
314
+ return new Pair <> (deviceNames [0 ], videoCapturer );
314
315
}
315
316
316
- return result ;
317
+ return null ;
317
318
}
318
319
319
320
/**
@@ -741,21 +742,14 @@ private ConstraintsMap getUserVideo(ConstraintsMap constraints, MediaStream medi
741
742
isFacing = facingMode == null || !facingMode .equals ("environment" );
742
743
String deviceId = getSourceIdConstraint (videoConstraintsMap );
743
744
CameraEventsHandler cameraEventsHandler = new CameraEventsHandler ();
744
- Map <String , VideoCapturer > result = createVideoCapturer (cameraEnumerator , isFacing , deviceId , cameraEventsHandler );
745
+ Pair <String , VideoCapturer > result = createVideoCapturer (cameraEnumerator , isFacing , deviceId , cameraEventsHandler );
745
746
746
747
if (result == null ) {
747
748
return null ;
748
749
}
749
750
750
- if (deviceId == null ) {
751
- if (!result .keySet ().isEmpty ()) {
752
- deviceId = result .keySet ().iterator ().next ();
753
- } else {
754
- return null ;
755
- }
756
- }
757
-
758
- VideoCapturer videoCapturer = result .get (deviceId );
751
+ deviceId = result .first ;
752
+ VideoCapturer videoCapturer = result .second ;
759
753
760
754
PeerConnectionFactory pcFactory = stateProvider .getPeerConnectionFactory ();
761
755
VideoSource videoSource = pcFactory .createVideoSource (false );
@@ -768,36 +762,56 @@ private ConstraintsMap getUserVideo(ConstraintsMap constraints, MediaStream medi
768
762
VideoCapturerInfo info = new VideoCapturerInfo ();
769
763
770
764
Integer videoWidth = getConstrainInt (videoConstraintsMap , "width" );
771
- info . width = videoWidth != null
765
+ int targetWidth = videoWidth != null
772
766
? videoWidth
773
767
: videoConstraintsMandatory != null && videoConstraintsMandatory .hasKey ("minWidth" )
774
768
? videoConstraintsMandatory .getInt ("minWidth" )
775
769
: DEFAULT_WIDTH ;
776
770
777
771
Integer videoHeight = getConstrainInt (videoConstraintsMap , "height" );
778
- info . height = videoHeight != null
772
+ int targetHeight = videoHeight != null
779
773
? videoHeight
780
774
: videoConstraintsMandatory != null && videoConstraintsMandatory .hasKey ("minHeight" )
781
775
? videoConstraintsMandatory .getInt ("minHeight" )
782
776
: DEFAULT_HEIGHT ;
783
777
784
778
Integer videoFrameRate = getConstrainInt (videoConstraintsMap , "frameRate" );
785
- info . fps = videoFrameRate != null
779
+ int targetFps = videoFrameRate != null
786
780
? videoFrameRate
787
781
: videoConstraintsMandatory != null && videoConstraintsMandatory .hasKey ("minFrameRate" )
788
782
? videoConstraintsMandatory .getInt ("minFrameRate" )
789
783
: DEFAULT_FPS ;
784
+
785
+ info .width = targetWidth ;
786
+ info .height = targetHeight ;
787
+ info .fps = targetFps ;
790
788
info .capturer = videoCapturer ;
789
+
790
+ // Find actual capture format.
791
+ Size actualSize = null ;
792
+ if (videoCapturer instanceof Camera1Capturer ) {
793
+ int cameraId = Camera1Helper .getCameraId (deviceId );
794
+ actualSize = Camera1Helper .findClosestCaptureFormat (cameraId , targetWidth , targetHeight );
795
+ } else if (videoCapturer instanceof Camera2Capturer ) {
796
+ CameraManager cameraManager = (CameraManager ) applicationContext .getSystemService (Context .CAMERA_SERVICE );
797
+ actualSize = Camera2Helper .findClosestCaptureFormat (cameraManager , deviceId , targetWidth , targetHeight );
798
+ }
799
+
800
+ if (actualSize != null ) {
801
+ info .width = actualSize .width ;
802
+ info .height = actualSize .height ;
803
+ }
804
+
791
805
info .cameraEventsHandler = cameraEventsHandler ;
792
- videoCapturer .startCapture (info . width , info . height , info . fps );
806
+ videoCapturer .startCapture (targetWidth , targetHeight , targetFps );
793
807
794
808
cameraEventsHandler .waitForCameraOpen ();
795
809
796
810
String trackId = stateProvider .getNextTrackUUID ();
797
811
mVideoCapturers .put (trackId , info );
798
812
mSurfaceTextureHelpers .put (trackId , surfaceTextureHelper );
799
- Log . d ( TAG , "changeCaptureFormat: " + info . width + "x" + info . height + "@" + info . fps );
800
- videoSource . adaptOutputFormat ( info .width , info .height , info .fps );
813
+
814
+ Log . d ( TAG , "Target: " + targetWidth + "x" + targetHeight + "@" + targetFps + ", Actual: " + info .width + "x" + info .height + "@" + info .fps );
801
815
802
816
VideoTrack track = pcFactory .createVideoTrack (trackId , videoSource );
803
817
mediaStream .addTrack (track );
@@ -1284,7 +1298,7 @@ public interface IsCameraEnabled {
1284
1298
boolean isEnabled (String id );
1285
1299
}
1286
1300
1287
- public class VideoCapturerInfo {
1301
+ public static class VideoCapturerInfo {
1288
1302
VideoCapturer capturer ;
1289
1303
int width ;
1290
1304
int height ;
0 commit comments