in p2p connection when I'm using RTCVideoView for both local and remote user it's working fine.
Now I have the scenario when I want to replace the RTCVideoView local widget by the CameraPreview ( needed for Machine learning scenario ), the p2p connection is established but local video is freezes
any idea how we can override the RTCVideoView local video by my own camera view widget ?
import 'dart:math';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart' as flutter_webrtc;
import 'package:peerdart/peerdart.dart';
late List<CameraDescription> _cameras;
Future<void> main() async {
try {
WidgetsFlutterBinding.ensureInitialized();
_cameras = await availableCameras();
} on CameraException catch (e) {}
runApp(MaterialApp(
home: WebRTCP2PDemo(cameras: _cameras),
));
}
class WebRTCP2PDemo extends StatefulWidget {
final List<CameraDescription>? cameras;
const WebRTCP2PDemo({Key? key, required this.cameras}) : super(key: key);
@override
_WebRTCP2PDemoState createState() => _WebRTCP2PDemoState();
}
class _WebRTCP2PDemoState extends State<WebRTCP2PDemo> {
final TextEditingController _controller = TextEditingController();
late Peer peer = Peer(options: PeerOptions(debug: LogLevel.All), id: GeneratePeerId());
final _remoteRenderer = flutter_webrtc.RTCVideoRenderer();
bool inCall = false;
CameraController? _cameraController;
String? peerId;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 50,
),
_renderState(),
const Text(
'Connection ID:',
),
SelectableText(
peerId ?? '',
style: TextStyle(fontSize: 48),
),
TextField(
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
controller: _controller,
style: TextStyle(fontSize: 48),
),
ElevatedButton(onPressed: _connect, child: const Text("connect")),
inCall
? Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
border: Border.all(width: 3.0, color: Colors.black38),
color: Colors.transparent,
borderRadius: BorderRadius.all(Radius.circular(5.0)),
),
child: SizedBox(
height: MediaQuery.of(context).size.height / 4,
width: MediaQuery.of(context).size.width,
child: flutter_webrtc.RTCVideoView(
_remoteRenderer,
),
),
),
),
)
: Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
border: Border.all(width: 3.0, color: Colors.black38),
color: Colors.transparent,
borderRadius: BorderRadius.all(Radius.circular(5.0)),
),
child: SizedBox(
height: MediaQuery.of(context).size.height / 4,
width: MediaQuery.of(context).size.width,
child: Center(
child: Text(
'waiting for remote user ...',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 28,
),
),
),
),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
border: Border.all(width: 3.0, color: Colors.black38),
color: Colors.transparent,
borderRadius: BorderRadius.all(Radius.circular(5.0)),
),
child: SizedBox(
height: MediaQuery.of(context).size.height / 3,
width: MediaQuery.of(context).size.width,
child: CameraPreview(_cameraController!),
),
),
),
),
],
)),
);
}
Future initCamera(CameraDescription cameraDescription) async {
_cameraController = CameraController(cameraDescription, ResolutionPreset.high);
try {
await _cameraController?.initialize().then((_) {
if (!mounted) return;
setState(() {});
});
} on CameraException catch (e) {
debugPrint("camera error $e");
}
}
Widget _renderState() {
Color bgColor = inCall ? Colors.green : Colors.grey;
Color txtColor = Colors.white;
String txt = inCall ? "Connected" : "Standby";
return Container(
decoration: BoxDecoration(color: bgColor),
child: Text(
txt,
style: Theme.of(context).textTheme.titleLarge?.copyWith(color: txtColor),
),
);
}
String GeneratePeerId() {
Random random = Random();
int min = 100000;
int max = 999999;
int randomNumber = min + random.nextInt(max - min);
return randomNumber.toString();
}
@override
void initState() {
super.initState();
initCamera(widget.cameras![1]);
peer.on("open").listen((id) {
setState(() {
peerId = peer.id;
});
});
_remoteRenderer.initialize();
peer.on<MediaConnection>("call").listen(
(call) async {
final mediaStream = await flutter_webrtc.navigator.mediaDevices.getUserMedia({
'video': {
'facingMode': 'user',
},
"audio": false
});
call.answer(mediaStream);
call.on("close").listen((event) {
setState(() {
inCall = false;
});
});
call.on<flutter_webrtc.MediaStream>("stream").listen((event) {
_remoteRenderer.srcObject = event;
setState(() {
inCall = true;
});
});
},
);
}
void _connect() async {
FocusManager.instance.primaryFocus?.unfocus();
final mediaStream = await flutter_webrtc.navigator.mediaDevices.getUserMedia({
'video': {
'facingMode': 'user',
},
"audio": false
});
final conn = peer.call(_controller.text, mediaStream);
conn.on("close").listen((event) {
setState(() {
inCall = false;
});
});
conn.on<flutter_webrtc.MediaStream>("stream").listen((event) {
_remoteRenderer.srcObject = event;
setState(() {
inCall = true;
});
});
}
@override
void dispose() {
peer.dispose();
_cameraController?.dispose();
_remoteRenderer.dispose();
super.dispose();
}
}