@@ -147,6 +147,13 @@ public VoIPMediaSession(VoIPMediaSessionConfig config)
147
147
}
148
148
}
149
149
150
+ if ( Media . TextSource != null )
151
+ {
152
+ var textTrack = new MediaStreamTrack ( config . MediaEndPoint . TextSource . GetTextSourceFormat ( ) ) ;
153
+ base . addTrack ( textTrack ) ;
154
+ Media . TextSource . OnTextSourceEncodedSample += base . SendText ;
155
+ }
156
+
150
157
if ( Media . VideoSink != null )
151
158
{
152
159
Media . VideoSink . OnVideoSinkDecodedSample += VideoSinkSampleReady ;
@@ -158,8 +165,14 @@ public VoIPMediaSession(VoIPMediaSessionConfig config)
158
165
base . OnRtpPacketReceived += RtpMediaPacketReceived ;
159
166
}
160
167
168
+ if ( Media . TextSink != null )
169
+ {
170
+ base . OnRtpPacketReceived += RtpMediaPacketReceived ;
171
+ }
172
+
161
173
base . OnAudioFormatsNegotiated += AudioFormatsNegotiated ;
162
174
base . OnVideoFormatsNegotiated += VideoFormatsNegotiated ;
175
+ base . OnTextFormatsNegotiated += TextFormatsNegotiated ;
163
176
}
164
177
165
178
private async void VideoSource_OnVideoSourceError ( string errorMessage )
@@ -170,8 +183,11 @@ private async void VideoSource_OnVideoSourceError(string errorMessage)
170
183
171
184
logger . LogWarning ( "Video source for capture device failure. {ErrorMessage}" , errorMessage ) ;
172
185
173
- // Can't use the webcam, switch to the test pattern source.
174
- await _videoTestPatternSource . StartVideo ( ) . ConfigureAwait ( false ) ;
186
+ if ( _videoTestPatternSource != null )
187
+ {
188
+ // Can't use the webcam, switch to the test pattern source.
189
+ await _videoTestPatternSource . StartVideo ( ) . ConfigureAwait ( false ) ;
190
+ }
175
191
}
176
192
}
177
193
@@ -206,42 +222,56 @@ private void VideoFormatsNegotiated(List<VideoFormat> videoFormats)
206
222
_videoTestPatternSource ? . SetVideoSourceFormat ( videoFormat ) ;
207
223
}
208
224
225
+ private void TextFormatsNegotiated ( List < TextFormat > textFormats )
226
+ {
227
+ var textFormat = textFormats . First ( ) ;
228
+ logger . LogDebug ( "Setting text sink and source format to {TextFormatID}:{TextCodec}." , textFormat . FormatID , textFormat . Codec ) ;
229
+ Media . TextSource ? . SetTextSourceFormat ( textFormat ) ;
230
+ }
231
+
209
232
public async override Task Start ( )
210
233
{
211
- if ( ! base . IsStarted )
234
+ await base . Start ( ) . ConfigureAwait ( false ) ;
235
+
236
+ if ( HasAudio )
212
237
{
213
- await base . Start ( ) . ConfigureAwait ( false ) ;
238
+ if ( Media . AudioSource != null )
239
+ {
240
+ await Media . AudioSource . StartAudio ( ) . ConfigureAwait ( false ) ;
241
+ }
242
+ if ( Media . AudioSink != null )
243
+ {
244
+ await Media . AudioSink . StartAudioSink ( ) . ConfigureAwait ( false ) ;
245
+ }
246
+ }
214
247
215
- if ( HasAudio )
248
+ if ( HasVideo && Media . VideoSource != null )
249
+ {
250
+ if ( ! _videoCaptureDeviceFailed )
216
251
{
217
- if ( Media . AudioSource != null )
218
- {
219
- await Media . AudioSource . StartAudio ( ) . ConfigureAwait ( false ) ;
220
- }
221
- if ( Media . AudioSink != null )
222
- {
223
- await Media . AudioSink . StartAudioSink ( ) . ConfigureAwait ( false ) ;
224
- }
252
+ await Media . VideoSource . StartVideo ( ) . ConfigureAwait ( false ) ;
225
253
}
254
+ else
255
+ {
256
+ logger . LogWarning ( "Webcam video source failed before start, switching to test pattern source." ) ;
226
257
227
- if ( HasVideo )
258
+ // The webcam source failed to start. Switch to a test pattern source.
259
+ await _videoTestPatternSource . StartVideo ( ) . ConfigureAwait ( false ) ;
260
+ }
261
+ }
262
+
263
+ if ( HasText )
264
+ {
265
+ if ( Media . TextSource != null )
228
266
{
229
- if ( Media . VideoSource != null )
230
- {
231
- if ( ! _videoCaptureDeviceFailed )
232
- {
233
- await Media . VideoSource . StartVideo ( ) . ConfigureAwait ( false ) ;
234
- }
235
- else
236
- {
237
- logger . LogWarning ( "Webcam video source failed before start, switching to test pattern source." ) ;
238
-
239
- // The webcam source failed to start. Switch to a test pattern source.
240
- await _videoTestPatternSource . StartVideo ( ) . ConfigureAwait ( false ) ;
241
- }
242
- }
267
+ await Media . TextSource . StartText ( ) . ConfigureAwait ( false ) ;
268
+ }
269
+ if ( Media . TextSink != null )
270
+ {
271
+ await Media . TextSink . StartTextSink ( ) . ConfigureAwait ( false ) ;
243
272
}
244
273
}
274
+
245
275
}
246
276
247
277
public async override void Close ( string reason )
@@ -282,6 +312,15 @@ public async override void Close(string reason)
282
312
Media . VideoSink . OnVideoSinkDecodedSample -= VideoSinkSampleReady ;
283
313
base . OnVideoFrameReceived -= Media . VideoSink . GotVideoFrame ;
284
314
}
315
+
316
+ if ( Media . TextSource != null )
317
+ {
318
+ await Media . TextSource . CloseText ( ) . ConfigureAwait ( false ) ;
319
+ }
320
+ if ( Media . TextSink != null )
321
+ {
322
+ await Media . TextSink . CloseTextSink ( ) . ConfigureAwait ( false ) ;
323
+ }
285
324
}
286
325
}
287
326
@@ -301,6 +340,12 @@ protected void RtpMediaPacketReceived(IPEndPoint remoteEndPoint, SDPMediaTypesEn
301
340
302
341
Media . AudioSink . GotAudioRtp ( remoteEndPoint , hdr . SyncSource , hdr . SequenceNumber , hdr . Timestamp , hdr . PayloadType , marker , rtpPacket . Payload ) ;
303
342
}
343
+ else if ( mediaType == SDPMediaTypesEnum . text && Media . TextSink != null )
344
+ {
345
+ logger . LogTrace ( nameof ( RtpMediaPacketReceived ) + " text RTP packet received from {RemoteEndPoint} ssrc {SyncSource} seqnum {SequenceNumber} timestamp {Timestamp} payload type {PayloadType}." , remoteEndPoint , hdr . SyncSource , hdr . SequenceNumber , hdr . Timestamp , hdr . PayloadType ) ;
346
+
347
+ Media . TextSink . GotTextRtp ( remoteEndPoint , hdr . SyncSource , hdr . SequenceNumber , hdr . Timestamp , hdr . PayloadType , hdr . MarkerBit , rtpPacket . Payload ) ;
348
+ }
304
349
}
305
350
306
351
public async Task PutOnHold ( )
@@ -316,10 +361,18 @@ public async Task PutOnHold()
316
361
await Media . VideoSource . PauseVideo ( ) . ConfigureAwait ( false ) ;
317
362
318
363
//_videoTestPatternSource.SetEmbeddedTestPatternPath(VideoTestPatternSource.TEST_PATTERN_INVERTED_RESOURCE_PATH);
319
- _videoTestPatternSource . SetFrameRate ( TEST_PATTERN_ONHOLD_FPS ) ;
364
+ _videoTestPatternSource ? . SetFrameRate ( TEST_PATTERN_ONHOLD_FPS ) ;
320
365
321
366
Media . VideoSource . ForceKeyFrame ( ) ;
322
- await _videoTestPatternSource . ResumeVideo ( ) . ConfigureAwait ( false ) ;
367
+ if ( _videoTestPatternSource != null )
368
+ {
369
+ await _videoTestPatternSource . ResumeVideo ( ) . ConfigureAwait ( false ) ;
370
+ }
371
+ }
372
+
373
+ if ( HasText )
374
+ {
375
+ // TODO can be put on / taken off hold?
323
376
}
324
377
}
325
378
@@ -333,10 +386,13 @@ public async void TakeOffHold()
333
386
334
387
if ( HasVideo )
335
388
{
336
- await _videoTestPatternSource . PauseVideo ( ) . ConfigureAwait ( false ) ;
389
+ if ( _videoTestPatternSource != null )
390
+ {
391
+ await _videoTestPatternSource . PauseVideo ( ) . ConfigureAwait ( false ) ;
392
+ }
337
393
338
394
//_videoTestPatternSource.SetEmbeddedTestPatternPath(VideoTestPatternSource.TEST_PATTERN_RESOURCE_PATH);
339
- _videoTestPatternSource . SetFrameRate ( TEST_PATTERN_FPS ) ;
395
+ _videoTestPatternSource ? . SetFrameRate ( TEST_PATTERN_FPS ) ;
340
396
341
397
Media . VideoSource . ForceKeyFrame ( ) ;
342
398
@@ -346,9 +402,17 @@ public async void TakeOffHold()
346
402
}
347
403
else
348
404
{
349
- await _videoTestPatternSource . ResumeVideo ( ) . ConfigureAwait ( false ) ;
405
+ if ( _videoTestPatternSource != null )
406
+ {
407
+ await _videoTestPatternSource . ResumeVideo ( ) . ConfigureAwait ( false ) ;
408
+ }
350
409
}
351
410
}
411
+
412
+ if ( HasText )
413
+ {
414
+ // TODO can be put on / taken off hold?
415
+ }
352
416
}
353
417
}
354
418
}
0 commit comments