1
1
// React Imports
2
2
import React , { useCallback , useEffect , useRef , useState } from 'react'
3
+ import Button from 'react-bootstrap/Button'
3
4
// PropTypes is used to validate that the used props are in fact passed to this Component
4
5
import PropTypes from 'prop-types'
6
+ import { View } from 'react-native'
5
7
6
8
// Local Imports
7
9
import { CAMERA_FEED_TOPIC , REALSENSE_WIDTH , REALSENSE_HEIGHT } from '../Constants'
8
10
import { useWindowSize } from '../../helpers'
9
- import { createPeerConnection , closePeerConnection } from '../../webrtc/webrtc_helpers'
11
+ import { WebRTCConnection } from '../../webrtc/webrtc_helpers'
10
12
11
13
/**
12
14
* Takes in an imageWidth and imageHeight, and returns a width and height that
@@ -80,38 +82,49 @@ const VideoFeed = (props) => {
80
82
const [ imgWidth , setImgWidth ] = useState ( 0 )
81
83
const [ imgHeight , setImgHeight ] = useState ( 0 )
82
84
const [ scaleFactor , setScaleFactor ] = useState ( 0.0 )
85
+ const [ refreshCount , setRefreshCount ] = useState ( 0 )
83
86
84
87
// Ref for the video element
85
88
const videoRef = useRef ( null )
89
+ const parentRef = useRef ( null )
90
+
91
+ // Rendering variables
92
+ let textFontSize = '2.5vh'
86
93
87
94
/**
88
95
* Create the peer connection
89
96
*/
90
97
useEffect ( ( ) => {
91
98
// Create the peer connection
92
- console . log ( 'Creating peer connection' , createPeerConnection , props . webrtcURL )
93
- const peer = createPeerConnection ( props . webrtcURL + '/subscribe' , props . topic , ( event ) => {
94
- console . log ( 'Got track event' , event )
95
- if ( event . streams && event . streams [ 0 ] ) {
96
- videoRef . current . srcObject = event . streams [ 0 ]
97
- console . log ( 'video' , videoRef . current )
98
- }
99
+ console . log ( 'Creating peer connection' , props . webrtcURL , refreshCount )
100
+ const webRTCConnection = new WebRTCConnection ( {
101
+ url : props . webrtcURL + '/subscribe' ,
102
+ topic : props . topic ,
103
+ onTrackAdded : ( event ) => {
104
+ console . log ( 'Got track event' , event )
105
+ if ( event . streams && event . streams [ 0 ] ) {
106
+ videoRef . current . srcObject = event . streams [ 0 ]
107
+ console . log ( 'video' , videoRef . current )
108
+ }
109
+ } ,
110
+ transceiverKind : 'video' ,
111
+ transceiverOptions : { direction : 'recvonly' }
99
112
} )
100
- peer . addTransceiver ( 'video' , { direction : 'recvonly' } )
101
113
102
114
return ( ) => {
103
- closePeerConnection ( peer )
115
+ webRTCConnection . close ( )
104
116
}
105
- } , [ props . topic , props . webrtcURL , videoRef ] )
117
+ } , [ props . topic , props . webrtcURL , refreshCount , videoRef ] )
106
118
107
119
// Callback to resize the image based on the parent width and height
108
120
const resizeImage = useCallback ( ( ) => {
109
- if ( ! props . parent . current ) {
121
+ console . log ( 'Resizing image' , parentRef . current )
122
+ if ( ! parentRef . current ) {
110
123
return
111
124
}
112
125
// Get the width and height of the parent DOM element
113
- let parentWidth = props . parent . current . clientWidth
114
- let parentHeight = props . parent . current . clientHeight
126
+ let parentWidth = parentRef . current . clientWidth
127
+ let parentHeight = parentRef . current . clientHeight
115
128
116
129
// Calculate the width and height of the video feed
117
130
let {
@@ -133,12 +146,7 @@ const VideoFeed = (props) => {
133
146
setImgWidth ( childWidth )
134
147
setImgHeight ( childHeight )
135
148
setScaleFactor ( childScaleFactor )
136
- } , [ props . parent , props . marginTop , props . marginBottom , props . marginLeft , props . marginRight ] )
137
-
138
- // When the component is first mounted, resize the image
139
- useEffect ( ( ) => {
140
- resizeImage ( )
141
- } , [ resizeImage ] )
149
+ } , [ parentRef , props . marginTop , props . marginBottom , props . marginLeft , props . marginRight ] )
142
150
143
151
/** When the resize event is triggered, the elements have not yet been laid out,
144
152
* and hence the parent width/height might not be accurate yet based on the
@@ -150,6 +158,11 @@ const VideoFeed = (props) => {
150
158
} , [ resizeImage ] )
151
159
useWindowSize ( resizeImageNextEventCycle )
152
160
161
+ // When the component is first mounted, resize the image
162
+ useEffect ( ( ) => {
163
+ resizeImageNextEventCycle ( )
164
+ } , [ resizeImageNextEventCycle ] )
165
+
153
166
// The callback for when the image is clicked.
154
167
const imageClicked = useCallback (
155
168
( event ) => {
@@ -172,32 +185,65 @@ const VideoFeed = (props) => {
172
185
// Render the component
173
186
return (
174
187
< >
175
- < video
176
- playsInline
177
- autoPlay
178
- muted
179
- ref = { videoRef }
180
- alt = 'Live video feed from the robot'
188
+ < View
189
+ ref = { parentRef }
190
+ style = { {
191
+ flex : 4 ,
192
+ alignItems : 'center' ,
193
+ justifyContent : 'center' ,
194
+ width : '100%' ,
195
+ height : '100%'
196
+ } }
197
+ >
198
+ < video
199
+ playsInline
200
+ autoPlay
201
+ muted
202
+ ref = { videoRef }
203
+ alt = 'Live video feed from the robot'
204
+ style = { {
205
+ width : imgWidth ,
206
+ height : imgHeight ,
207
+ display : 'block' ,
208
+ alignItems : 'center' ,
209
+ justifyContent : 'center'
210
+ } }
211
+ onClick = { props . pointClicked ? imageClicked : null }
212
+ />
213
+ </ View >
214
+ < View
181
215
style = { {
182
- width : imgWidth ,
183
- height : imgHeight ,
184
- display : 'block' ,
216
+ flex : 1 ,
217
+ // TODO: consider replacing 'center' with 'end' if the margin is 0.
185
218
alignItems : 'center' ,
186
- justifyContent : 'center'
219
+ justifyContent : 'start' ,
220
+ width : '100%' ,
221
+ height : '100%'
187
222
} }
188
- onClick = { props . pointClicked ? imageClicked : null }
189
- />
223
+ >
224
+ < Button
225
+ variant = 'warning'
226
+ className = 'mx-2 mb-2 btn-huge'
227
+ size = 'lg'
228
+ style = { {
229
+ fontSize : textFontSize ,
230
+ width : '60%' ,
231
+ color : 'black'
232
+ } }
233
+ onClick = { ( ) => setRefreshCount ( refreshCount + 1 ) }
234
+ >
235
+ Reload Video
236
+ </ Button >
237
+ </ View >
190
238
</ >
191
239
)
192
240
}
193
241
VideoFeed . propTypes = {
194
- // The ref to the parent DOM element. Null if the component is not yet mounted
195
- parent : PropTypes . object . isRequired ,
196
242
// The margins around the video feed
197
- marginTop : PropTypes . number . isRequired ,
198
- marginBottom : PropTypes . number . isRequired ,
199
- marginLeft : PropTypes . number . isRequired ,
200
- marginRight : PropTypes . number . isRequired ,
243
+ marginTop : PropTypes . number ,
244
+ marginBottom : PropTypes . number ,
245
+ marginLeft : PropTypes . number ,
246
+ marginRight : PropTypes . number ,
201
247
// The topic of the video feed
202
248
topic : PropTypes . string . isRequired ,
203
249
/**
@@ -211,6 +257,10 @@ VideoFeed.propTypes = {
211
257
webrtcURL : PropTypes . string . isRequired
212
258
}
213
259
VideoFeed . defaultProps = {
260
+ marginTop : 0 ,
261
+ marginBottom : 0 ,
262
+ marginLeft : 0 ,
263
+ marginRight : 0 ,
214
264
topic : CAMERA_FEED_TOPIC
215
265
}
216
266
0 commit comments