chenqiyang
2022-09-02 6a99d9bf65aa5878cb409945ed2bdbdcb916d047
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
/*
 * Copyright (c) 2010-2019 Belledonne Communications SARL.
 *
 * This file is part of mediastreamer2.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
 
#ifndef MEDIASTREAM_H
#define MEDIASTREAM_H
 
#include <ortp/ortp.h>
#include <ortp/event.h>
#include <ortp/nack.h>
 
#include <mediastreamer2/msfactory.h>
#include <mediastreamer2/msfilter.h>
#include <mediastreamer2/msticker.h>
#include <mediastreamer2/mssndcard.h>
#include <mediastreamer2/mswebcam.h>
#include <mediastreamer2/msvideo.h>
#include <mediastreamer2/msvideoqualitycontroller.h>
#include <mediastreamer2/bitratecontrol.h>
#include <mediastreamer2/qualityindicator.h>
#include <mediastreamer2/ice.h>
#include <mediastreamer2/zrtp.h>
#include <mediastreamer2/dtls_srtp.h>
#include <mediastreamer2/ms_srtp.h>
#include <mediastreamer2/msequalizer.h>
 
#ifdef __cplusplus
extern "C" {
#endif
 
/**
 * @addtogroup ring_api
 * @{
**/
 
struct _RingStream
{
    MSSndCard *card;
    MSTicker *ticker;
    MSFilter *source;
    MSFilter *gendtmf;
    MSFilter *write_resampler;
    MSFilter *sndwrite;
    MSFilter *decoder;
    int srcpin;
};
 
typedef struct _RingStream RingStream;
 
MS2_PUBLIC RingStream *ring_start(MSFactory *factory, const char * file, int interval, MSSndCard *sndcard);
MS2_PUBLIC RingStream *ring_start_with_cb(MSFactory *factory, const char * file, int interval, MSSndCard *sndcard, MSFilterNotifyFunc func, void * user_data);
MS2_PUBLIC void ring_stop (RingStream * stream);
 
/**
 * Asks the ring filter to route to the selected sound card (currently only used for AAudio and OpenSLES)
 * @param[in] stream The RingStream object
 * @param[in] sndcard_playback The wanted audio output soundcard
 */
MS2_PUBLIC void ring_stream_set_output_ms_snd_card(RingStream *stream, MSSndCard * sndcard_playback);
 
/**
 * Retrieve the current sound card from the audio playback filter (currently only used for AAudio and OpenSLES)
 * @param[in] stream The AudioStream object
 */
MS2_PUBLIC MSSndCard * ring_stream_get_output_ms_snd_card(RingStream *stream);
 
/**
 * @}
**/
/**
 * The MediaStream is an object describing a stream (one of AudioStream or VideoStream).
**/
typedef struct _MediaStream MediaStream;
 
/*
 * internal cb to process rtcp stream
 * */
typedef void (*media_stream_process_rtcp_callback_t)(MediaStream *stream, mblk_t *m);
 
struct _MSMediaStreamSessions{
    RtpSession *rtp_session;
    MSSrtpCtx* srtp_context;
    MSZrtpContext *zrtp_context;
    MSDtlsSrtpContext *dtls_context;
    MSTicker *ticker;
};
 
#ifndef MS_MEDIA_STREAM_SESSIONS_DEFINED
typedef struct _MSMediaStreamSessions MSMediaStreamSessions;
#define MS_MEDIA_STREAM_SESSIONS_DEFINED 1
#endif
 
MS2_PUBLIC void ms_media_stream_sessions_uninit(MSMediaStreamSessions *sessions);
 
typedef enum _MSStreamState{
    MSStreamInitialized,
    MSStreamPreparing,
    MSStreamStarted,
    MSStreamStopped
}MSStreamState;
 
 
typedef enum MediaStreamDir{
    MediaStreamSendRecv,
    MediaStreamSendOnly,
    MediaStreamRecvOnly
}MediaStreamDir;
 
/**
 * Base struct for both AudioStream and VideoStream structure.
**/
struct _MediaStream {
    MSFormatType type;
    MSStreamState state;
    MSMediaStreamSessions sessions;
    OrtpEvQueue *evq;
    MSFilter *rtprecv;
    MSFilter *rtpsend;
    MSFilter *encoder;
    MSFilter *decoder;
    MSFilter *voidsink;
    MSBitrateController *rc;
    MSQualityIndicator *qi;
    IceCheckList *ice_check_list;
    time_t start_time;
    time_t last_iterate_time;
    uint64_t last_packet_count;
    time_t last_packet_time;
    MSQosAnalyzerAlgorithm rc_algorithm;
    PayloadType *current_pt;/*doesn't need to be freed*/
    bool_t rc_enable;
    bool_t is_beginning;
    bool_t owns_sessions;
    bool_t pad;
    /**
     * defines encoder target network bit rate, uses #media_stream_set_target_network_bitrate() setter.
     * */
    int target_bitrate;
    int max_target_bitrate;
    media_stream_process_rtcp_callback_t process_rtcp;
    OrtpEvDispatcher *evd;
    MSFactory *factory;
    MSBandwidthController *bandwidth_controller;
    MSVideoQualityController *video_quality_controller;
    MediaStreamDir direction;
};
 
MS2_PUBLIC void media_stream_init(MediaStream *stream, MSFactory *factory, const MSMediaStreamSessions *sessions);
 
MS2_PUBLIC MSFactory* media_stream_get_factory(MediaStream *stream);
 
/**
 * @addtogroup audio_stream_api
 * @{
**/
 
MS2_PUBLIC bool_t media_stream_started(MediaStream *stream);
 
MS2_PUBLIC int media_stream_join_multicast_group(MediaStream *stream, const char *ip);
 
MS2_PUBLIC bool_t media_stream_dtls_supported(void);
 
/* enable DTLS on the media stream */
MS2_PUBLIC void media_stream_enable_dtls(MediaStream *stream, const MSDtlsSrtpParams *params);
 
MS2_PUBLIC void media_stream_set_rtcp_information(MediaStream *stream, const char *cname, const char *tool);
 
MS2_PUBLIC void media_stream_get_local_rtp_stats(MediaStream *stream, rtp_stats_t *stats);
 
MS2_PUBLIC int media_stream_set_dscp(MediaStream *stream, int dscp);
 
MS2_PUBLIC void media_stream_enable_adaptive_bitrate_control(MediaStream *stream, bool_t enabled);
 
MS2_PUBLIC void media_stream_set_adaptive_bitrate_algorithm(MediaStream *stream, MSQosAnalyzerAlgorithm algorithm);
 
MS2_PUBLIC void media_stream_enable_adaptive_jittcomp(MediaStream *stream, bool_t enabled);
 
MS2_PUBLIC void media_stream_set_ice_check_list(MediaStream *stream, IceCheckList *cl);
 
/*
 * deprecated, use media_stream_set_srtp_recv_key and media_stream_set_srtp_send_key.
**/
MS2_PUBLIC bool_t media_stream_enable_srtp(MediaStream* stream, MSCryptoSuite suite, const char* snd_key, const char* rcv_key);
 
/**
 * @param[in] stream MediaStream object
 * @return true if stream is encrypted
 * */
MS2_PUBLIC bool_t media_stream_secured(const MediaStream *stream);
#define media_stream_is_secured media_stream_secured
 
/**
 * Tells whether AVPF is enabled or not.
 * @param[in] stream #MediaStream object.
 * @return True if AVPF is enabled, false otherwise.
 */
MS2_PUBLIC bool_t media_stream_avpf_enabled(const MediaStream *stream);
 
/**
 * Gets the AVPF Regular RTCP report interval.
 * @param[in] stream #MediaStream object.
 * @return The AVPF Regular RTCP report interval in seconds.
 */
MS2_PUBLIC uint16_t media_stream_get_avpf_rr_interval(const MediaStream *stream);
 
/**
 * Gets the RTP session of the media stream.
 * @param[in] stream #MediaStream object.
 * @return The RTP session of the media stream.
 */
MS2_PUBLIC RtpSession * media_stream_get_rtp_session(const MediaStream *stream);
 
MS2_PUBLIC const MSQualityIndicator *media_stream_get_quality_indicator(MediaStream *stream);
/* *
 * returns a realtime indicator of the stream quality between 0 and 5
 * */
MS2_PUBLIC float media_stream_get_quality_rating(MediaStream *stream);
 
MS2_PUBLIC float media_stream_get_average_quality_rating(MediaStream *stream);
 
MS2_PUBLIC float media_stream_get_lq_quality_rating(MediaStream *stream);
 
MS2_PUBLIC float media_stream_get_average_lq_quality_rating(MediaStream *stream);
 
/**
 * <br>For multirate codecs like OPUS, encoder output target bitrate must be set.
 * <br>Encoder will compute output codec bitrate from this value.
 * <br> default value is the value corresponding the rtp PayloadType
 * @param stream stream to apply parameter on
 * @param target_bitrate in bit per seconds
 * @return 0 if succeed
 * */
MS2_PUBLIC int media_stream_set_target_network_bitrate(MediaStream *stream,int target_bitrate);
 
/**
 * Set a maximum target bitrate for the stream. Indeed, the MSBandwidthController may adapt the target bitrate
 * according to network conditions, which includes the possibility to increase it if remote side sends a TMMBR
 * to invite to increase bitrate. The max_network_bitrate defines the upper limit for increasing the bitrate usage automatically.
 * @param stream stream to apply parameter on
 * @param target_bitrate in bit per seconds
**/
MS2_PUBLIC int media_stream_set_max_network_bitrate(MediaStream *stream,int max_bitrate);
 
/**
 * get the stream target bitrate.
 * @param stream stream to apply parameter on
 * @return target_bitrate in bit per seconds
 * */
MS2_PUBLIC int media_stream_get_target_network_bitrate(const MediaStream *stream);
 
/**
 * get current stream  upload bitrate. Value is updated every seconds
 * @param stream
 * @return bitrate in bit per seconds
 * */
MS2_PUBLIC float media_stream_get_up_bw(const MediaStream *stream);
 
/**
 * get current stream download bitrate. Value is updated every seconds
 * @param stream
 * @return bitrate in bit per seconds
 * */
MS2_PUBLIC float media_stream_get_down_bw(const MediaStream *stream);
 
/**
 * get current stream rtcp upload bitrate. Value is updated every seconds
 * @param stream
 * @return bitrate in bit per seconds
 * */
MS2_PUBLIC float media_stream_get_rtcp_up_bw(const MediaStream *stream);
 
/**
 * get current stream rtcp download bitrate. Value is updated every seconds
 * @param stream
 * @return bitrate in bit per seconds
 * */
MS2_PUBLIC float media_stream_get_rtcp_down_bw(const MediaStream *stream);
 
/**
 * Returns the sessions that were used in the media stream (RTP, SRTP, ZRTP...) so that they can be re-used.
 * As a result of calling this function, the media stream no longer owns the sessions and thus will not free them.
**/
MS2_PUBLIC void media_stream_reclaim_sessions(MediaStream *stream, MSMediaStreamSessions *sessions);
 
 
MS2_PUBLIC void media_stream_iterate(MediaStream * stream);
 
MS2_PUBLIC void media_stream_set_direction(MediaStream *stream, MediaStreamDir dir);
 
MS2_PUBLIC MediaStreamDir media_stream_get_direction(const MediaStream *stream);
 
/**
 * Returns TRUE if stream was still actively receiving packets (RTP or RTCP) in the last period specified in timeout_seconds.
**/
MS2_PUBLIC bool_t media_stream_alive(MediaStream *stream, int timeout_seconds);
 
/**
 * @return current streams state
 * */
MS2_PUBLIC MSStreamState media_stream_get_state(const MediaStream *stream);
 
MS2_PUBLIC OrtpEvDispatcher* media_stream_get_event_dispatcher(const MediaStream *stream);
 
typedef enum EchoLimiterType{
    ELInactive,
    ELControlMic,
    ELControlFull
} EchoLimiterType;
 
 
typedef enum EqualizerLocation {
    MSEqualizerHP = 0,
    MSEqualizerMic
} EqualizerLocation;
 
 
typedef enum MSResourceType{
    MSResourceInvalid,
    MSResourceDefault,
    MSResourceFile,
    MSResourceRtp,
    MSResourceCamera,
    MSResourceSoundcard,
    MSResourceVoid
}MSResourceType;
 
MS2_PUBLIC const char *ms_resource_type_to_string(MSResourceType type);
 
/**
 * Structure describing the input or the output of a MediaStream.
 * type must be set to one the member of the MSResourceType enum, and the correspoding
 * resource argument must be set: the file name (const char*) for MSResourceFile,
 * the RtpSession for MSResourceRtp, an MSWebCam for MSResourceCamera, an MSSndCard for MSResourceSoundcard.
 * @warning due to implementation, if RTP is to be used for input and output, the same RtpSession must be passed for both sides.
 */
typedef struct _MSMediaResource{
    MSResourceType type;
    union{
        void *resource_arg;
        const char *file;
        RtpSession *session;
        MSWebCam *camera;
        MSSndCard *soundcard;
    };
}MSMediaResource;
 
 
MS2_PUBLIC bool_t ms_media_resource_is_consistent(const MSMediaResource *r);
#define ms_media_resource_get_file(r)        (((r)->type == MSResourceFile) ? (r)->file : NULL)
#define ms_media_resource_get_rtp_session(r)    (((r)->type == MSResourceRtp) ? (r)->session : NULL)
#define ms_media_resource_get_camera(r)        (((r)->type == MSResourceCamera) ? (r)->camera : NULL)
#define ms_media_resource_get_soundcard(r)    (((r)->type == MSResourceSoundcard) ? (r)->soundcard : NULL)
/**
 * Structure describing the input/output of a MediaStream.
 * Input and output are described as MSMediaResource.
 */
typedef struct _MSMediaStreamIO {
    MSMediaResource input;
    MSMediaResource output;
} MSMediaStreamIO;
 
#define MS_MEDIA_STREAM_IO_INITIALIZER { {MSResourceInvalid}, {MSResourceInvalid} }
 
MS2_PUBLIC bool_t ms_media_stream_io_is_consistent(const MSMediaStreamIO *io);
 
struct _AudioStream
{
    MediaStream ms;
    MSSndCard *playcard;
    MSSndCard *captcard;
    MSFilter *soundread;
    MSFilter *soundwrite;
    MSFilter *dtmfgen;
    MSFilter *dtmfgen_rtp;
    MSFilter *plc;
    MSFilter *ec;/*echo canceler*/
    MSFilter *volsend,*volrecv; /*MSVolumes*/
    MSFilter *local_mixer;
    MSFilter *local_player;
    MSFilter *local_player_resampler;
    MSFilter *read_decoder; /* Used when the input is done via RTP */
    MSFilter *write_encoder; /* Used when the output is done via RTP */
    MSFilter *read_resampler;
    MSFilter *write_resampler;
    MSFilter *mic_equalizer;
    MSFilter *spk_equalizer;
    MSFilter *dummy;
    MSFilter *recv_tee;
    MSFilter *recorder_mixer;
    MSFilter *recorder;
    MSFilter *outbound_mixer;
    struct {
        MSFilter *resampler;
        MSFilter *encoder;
        MSFilter *recorder;
        MSFilter *video_input;
    }av_recorder;
    struct _AVPlayer{
        MSFilter *player;
        MSFilter *resampler;
        MSFilter *decoder;
        MSFilter *video_output;
        int audiopin;
        int videopin;
        bool_t plumbed;
    }av_player;
    MSFilter *flowcontrol;
    RtpSession *rtp_io_session; /**< The RTP session used for RTP input/output. */
    MSFilter *vaddtx;
    char *recorder_file;
    EchoLimiterType el_type; /*use echo limiter: two MSVolume, measured input level controlling local output level*/
    EqualizerLocation eq_loc;
    uint32_t features;
    int sample_rate;
    int nchannels;
    struct _VideoStream *videostream;/*the stream with which this audiostream is paired*/
    MSAudioRoute audio_route;
    bool_t play_dtmfs;
    bool_t use_ec;
    bool_t use_gc;
    bool_t use_agc;
 
    bool_t mic_eq_active;
    bool_t spk_eq_active;
    bool_t use_ng;/*noise gate*/
    bool_t is_ec_delay_set;
    bool_t disable_record_on_mute;
    float last_mic_gain_level_db;
};
 
/**
 * The AudioStream holds all resources to create and run typical VoIP audiostream.
**/
typedef struct _AudioStream AudioStream;
 
 
/* start a thread that does sampling->encoding->rtp_sending|rtp_receiving->decoding->playing */
MS2_PUBLIC AudioStream *audio_stream_start(MSFactory* factory, RtpProfile * prof, int locport, const char *remip,
                 int remport, int payload_type, int jitt_comp, bool_t echo_cancel);
 
MS2_PUBLIC AudioStream *audio_stream_start_with_sndcards(MSFactory* factory, RtpProfile* prof, int locport, const char *remip4, int remport, int payload_type, int jitt_comp, MSSndCard *playcard,
                                                         MSSndCard *captcard, bool_t echocancel);
 
MS2_PUBLIC int audio_stream_start_with_files (AudioStream * stream, RtpProfile * prof,
                        const char *remip, int remport, int rem_rtcp_port,
                        int pt, int jitt_comp,
                        const char * infile,  const char * outfile);
 
/**
 * Start an audio stream according to the specified AudioStreamIO.
 *
 * @param[in] stream AudioStream object previously created with audio_stream_new().
 * @param[in] profile RtpProfile object holding the PayloadType that can be used during the audio session.
 * @param[in] rem_rtp_ip The remote IP address where to send the encoded audio to.
 * @param[in] rem_rtp_port The remote port where to send the encoded audio to.
 * @param[in] rem_rtcp_ip The remote IP address for RTCP.
 * @param[in] rem_rtcp_port The remote port for RTCP.
 * @param[in] payload_type The payload type number used to send the audio stream. A valid PayloadType must be available at this index in the profile.
 * @param[in] io A MSMediaStreamIO describing the local input/output of the audio stream.
 */
MS2_PUBLIC int audio_stream_start_from_io(AudioStream *stream, RtpProfile *profile, const char *rem_rtp_ip, int rem_rtp_port,
    const char *rem_rtcp_ip, int rem_rtcp_port, int payload_type, const MSMediaStreamIO *io);
 
/**
 * Starts an audio stream from/to local wav files or soundcards.
 *
 * This method starts the processing of the audio stream, that is playing from wav file or soundcard, voice processing, encoding,
 * sending through RTP, receiving from RTP, decoding, voice processing and wav file recording or soundcard playback.
 *
 *
 * @param stream an AudioStream previously created with audio_stream_new().
 * @param profile a RtpProfile containing all PayloadType possible during the audio session.
 * @param rem_rtp_ip remote IP address where to send the encoded audio.
 * @param rem_rtp_port remote IP port where to send the encoded audio.
 * @param rem_rtcp_ip remote IP address for RTCP.
 * @param rem_rtcp_port remote port for RTCP.
 * @param payload payload type index to use for the sending stream. This index must point to a valid PayloadType in the RtpProfile.
 * @param jitt_comp Nominal jitter buffer size in milliseconds.
 * @param infile path to wav file to play out (can be NULL)
 * @param outfile path to wav file to record into (can be NULL)
 * @param playcard The soundcard to be used for playback (can be NULL)
 * @param captcard The soundcard to be used for catpure. (can be NULL)
 * @param use_ec whether echo cancellation is to be performed.
 * @return 0 if sucessful, -1 otherwise.
**/
MS2_PUBLIC int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char *rem_rtp_ip,int rem_rtp_port,
    const char *rem_rtcp_ip, int rem_rtcp_port, int payload,int jitt_comp, const char *infile, const char *outfile,
    MSSndCard *playcard, MSSndCard *captcard, bool_t use_ec);
 
 
MS2_PUBLIC void audio_stream_play(AudioStream *st, const char *name);
MS2_PUBLIC void audio_stream_record(AudioStream *st, const char *name);
 
static MS2_INLINE void audio_stream_set_rtcp_information(AudioStream *st, const char *cname, const char *tool) {
    media_stream_set_rtcp_information(&st->ms, cname, tool);
}
 
MS2_PUBLIC void audio_stream_play_received_dtmfs(AudioStream *st, bool_t yesno);
 
/**
 * Creates an AudioStream object listening on a RTP port.
 * @param loc_rtp_port the local UDP port to listen for RTP packets.
 * @param loc_rtcp_port the local UDP port to listen for RTCP packets
 * @param ipv6 TRUE if ipv6 must be used.
 * @param factory
 * @return a new AudioStream.
**/
MS2_PUBLIC AudioStream *audio_stream_new(MSFactory* factory, int loc_rtp_port, int loc_rtcp_port, bool_t ipv6);
 
/**
 * Creates an AudioStream object listening on a RTP port for a dedicated address.
 * @param loc_ip the local ip to listen for RTP packets. Can be ::, O.O.O.O or any ip4/6 addresses
 * @param loc_rtp_port the local UDP port to listen for RTP packets.
 * @param loc_rtcp_port the local UDP port to listen for RTCP packets
 * @param factory
 * @return a new AudioStream.
**/
MS2_PUBLIC AudioStream *audio_stream_new2(MSFactory* factory, const char* ip, int loc_rtp_port, int loc_rtcp_port);
 
 
/**Creates an AudioStream object from initialized MSMediaStreamSessions.
 * @param sessions the MSMediaStreamSessions
 * @param factory the MSFActory from the core object
 * @return a new AudioStream
**/
MS2_PUBLIC AudioStream *audio_stream_new_with_sessions(MSFactory* factory, const MSMediaStreamSessions *sessions);
 
#define AUDIO_STREAM_FEATURE_PLC         (1 << 0)
#define AUDIO_STREAM_FEATURE_EC         (1 << 1)
#define AUDIO_STREAM_FEATURE_EQUALIZER        (1 << 2)
#define AUDIO_STREAM_FEATURE_VOL_SND         (1 << 3)
#define AUDIO_STREAM_FEATURE_VOL_RCV         (1 << 4)
#define AUDIO_STREAM_FEATURE_DTMF        (1 << 5)
#define AUDIO_STREAM_FEATURE_DTMF_ECHO        (1 << 6)
#define AUDIO_STREAM_FEATURE_MIXED_RECORDING    (1 << 7)
#define AUDIO_STREAM_FEATURE_LOCAL_PLAYING    (1 << 8)
#define AUDIO_STREAM_FEATURE_REMOTE_PLAYING    (1 << 9)
#define AUDIO_STREAM_FEATURE_FLOW_CONTROL    (1 << 10)
 
#define AUDIO_STREAM_FEATURE_ALL    (\
                    AUDIO_STREAM_FEATURE_PLC | \
                    AUDIO_STREAM_FEATURE_EC | \
                    AUDIO_STREAM_FEATURE_EQUALIZER | \
                    AUDIO_STREAM_FEATURE_VOL_SND | \
                    AUDIO_STREAM_FEATURE_VOL_RCV | \
                    AUDIO_STREAM_FEATURE_DTMF | \
                    AUDIO_STREAM_FEATURE_DTMF_ECHO |\
                    AUDIO_STREAM_FEATURE_MIXED_RECORDING |\
                    AUDIO_STREAM_FEATURE_LOCAL_PLAYING | \
                    AUDIO_STREAM_FEATURE_REMOTE_PLAYING | \
                    AUDIO_STREAM_FEATURE_FLOW_CONTROL \
                    )
 
 
MS2_PUBLIC uint32_t audio_stream_get_features(AudioStream *st);
MS2_PUBLIC void audio_stream_set_features(AudioStream *st, uint32_t features);
 
MS2_PUBLIC void audio_stream_prepare_sound(AudioStream *st, MSSndCard *playcard, MSSndCard *captcard);
MS2_PUBLIC void audio_stream_unprepare_sound(AudioStream *st);
MS2_PUBLIC bool_t audio_stream_started(AudioStream *stream);
/**
 * Starts an audio stream from local soundcards.
 *
 * This method starts the processing of the audio stream, that is capture from soundcard, voice processing, encoding,
 * sending through RTP, receiving from RTP, decoding, voice processing and soundcard playback.
 *
 * @param stream an AudioStream previously created with audio_stream_new().
 * @param prof a RtpProfile containing all PayloadType possible during the audio session.
 * @param remip remote IP address where to send the encoded audio.
 * @param remport remote IP port where to send the encoded audio
 * @param rem_rtcp_port remote port for RTCP.
 * @param payload_type payload type index to use for the sending stream. This index must point to a valid PayloadType in the RtpProfile.
 * @param jitt_comp Nominal jitter buffer size in milliseconds.
 * @param playcard The soundcard to be used for playback
 * @param captcard The soundcard to be used for catpure.
 * @param echo_cancel whether echo cancellation is to be performed.
**/
MS2_PUBLIC int audio_stream_start_now(AudioStream * stream, RtpProfile * prof,  const char *remip, int remport, int rem_rtcp_port, int payload_type, int jitt_comp,MSSndCard *playcard, MSSndCard *captcard, bool_t echo_cancel);
MS2_PUBLIC void audio_stream_set_relay_session_id(AudioStream *stream, const char *relay_session_id);
/*returns true if we are still receiving some data from remote end in the last timeout seconds*/
MS2_PUBLIC bool_t audio_stream_alive(AudioStream * stream, int timeout);
 
/**
 * Executes background low priority tasks related to audio processing (RTP statistics analysis).
 * It should be called periodically, for example with an interval of 100 ms or so.
 */
MS2_PUBLIC void audio_stream_iterate(AudioStream *stream);
 
/**
 * enable echo-limiter dispositve: one MSVolume in input branch controls a MSVolume in the output branch
 * */
MS2_PUBLIC void audio_stream_enable_echo_limiter(AudioStream *stream, EchoLimiterType type);
 
/**
 * enable gain control, to be done before start()
 * */
MS2_PUBLIC void audio_stream_enable_gain_control(AudioStream *stream, bool_t val);
 
/**
 * enable automatic gain control, to be done before start()
 * */
MS2_PUBLIC void audio_stream_enable_automatic_gain_control(AudioStream *stream, bool_t val);
 
/**
 * to be done before start
 *  */
MS2_PUBLIC void audio_stream_set_echo_canceller_params(AudioStream *st, int tail_len_ms, int delay_ms, int framesize);
 
 
/**
 * to be done before start
 *  */
MS2_PUBLIC void audio_stream_enable_echo_canceller(AudioStream *st, bool_t enabled);
/**
 * enable adaptive rate control
 * */
static MS2_INLINE void audio_stream_enable_adaptive_bitrate_control(AudioStream *stream, bool_t enabled) {
    media_stream_enable_adaptive_bitrate_control(&stream->ms, enabled);
}
 
/**
 *  Enable adaptive jitter compensation
 *  */
static MS2_INLINE void audio_stream_enable_adaptive_jittcomp(AudioStream *stream, bool_t enabled) {
    media_stream_enable_adaptive_jittcomp(&stream->ms, enabled);
}
/**
 * Calling this method with disable=true will cause the microhone to be completely deactivated when muted
 * Currently only implemented for IOS, this will cause the playback sound to be interrupted for a short moment while the audio is reconfigured.
 * On IOS 14, it will also disable Apple's microphone recording indicator when microphone is muted.
 *
 * @param stream The stream.
 * @param disable True if you wish to entirely stop the audio recording when muting the microphone.
 */
MS2_PUBLIC void audio_stream_disable_record_on_mute(AudioStream *stream, bool_t disable);
 
/**
 * Mute or unmute the microphone
 * For IOS, if "audio_stream_disable_record_on_mute" was enabled, this will completely stop the microphone recording.
 * Else, sound recording remains active but silence is sent instead of recorded audiow@
 *
 * @param stream The stream.
 * @param enable Wether the microphone must be enabled.
 */
MS2_PUBLIC void audio_stream_enable_mic(AudioStream *stream, bool_t enable);
 
/**
 * Apply a software gain on the microphone.
 * Be note that this method neither changes the volume gain
 * of the sound card nor the system mixer one. If you intends
 * to control the volume gain at sound card level, you should
 * use audio_stream_set_sound_card_input_gain() instead.
 *
 * @param stream The stream.
 * @param gain_db Gain to apply in dB.
 */
MS2_PUBLIC void audio_stream_set_mic_gain_db(AudioStream *stream, float gain_db);
 
 
/**
 * @deprecated
 * Like audio_stream_set_mic_gain_db() excepted that the gain is specified
 * in percentage.
 *
 * @param stream The stream.
 * @param gain Gain to apply in percentage of the max supported gain.
 */
MS2_PUBLIC void audio_stream_set_mic_gain(AudioStream *stream, float gain);
 
/**
 *  enable/disable rtp stream
 */
MS2_PUBLIC void audio_stream_mute_rtp(AudioStream *stream, bool_t val);
 
/**
 * Apply a gain on received RTP packets.
 * @param stream An AudioStream.
 * @param gain_db Gain to apply in dB.
 */
MS2_PUBLIC void audio_stream_set_spk_gain_db(AudioStream *stream, float gain_db);
 
/**
 * Like audio_stream_set_spk_gain_db() excepted that the gain is specified
 * in percentage.
 *
 * @param stream The stream.
 * @param gain Gain to apply in percentage of the max supported gain.
 */
MS2_PUBLIC void audio_stream_set_spk_gain(AudioStream *stream, float gain);
 
/**
 * Set microphone volume gain.
 * If the sound backend supports it, the set volume gain will be synchronized
 * with the host system mixer. If you intended to apply a static software gain,
 * you should use audio_stream_set_mic_gain_db() or audio_stream_set_mic_gain().
 *
 * @param stream The audio stream.
 * @param gain Percentage of the max supported volume gain. Valid values are in [0.0 : 1.0].
 */
MS2_PUBLIC void audio_stream_set_sound_card_input_gain(AudioStream *stream, float gain);
 
/**
 * Get microphone volume gain.
 * @param stream The audio stream.
 * @return double Volume gain in percentage of the max suppored gain.
 * Valid returned values are in [0.0 : 1.0]. A negative value is returned in case of failure.
 */
MS2_PUBLIC float audio_stream_get_sound_card_input_gain(const AudioStream *stream);
 
/**
 * Set speaker volume gain.
 * If the sound backend supports it, the set volume gain will be synchronized
 * with the host system mixer.
 * @param stream The audio stream.
 * @param gain Percentage of the max supported volume gain. Valid values are in [0.0 : 1.0].
 */
MS2_PUBLIC void audio_stream_set_sound_card_output_gain(AudioStream *stream, float volume);
 
/**
 * Get speaker volume gain.
 * @param stream The audio stream.
 * @return Volume gain in percentage of the max suppored gain.
 * Valid returned values are in [0.0 : 1.0]. A negative value is returned in case of failure.
 */
MS2_PUBLIC float audio_stream_get_sound_card_output_gain(const AudioStream *stream);
 
/**
 * enable noise gate, must be done before start()
 * */
MS2_PUBLIC void audio_stream_enable_noise_gate(AudioStream *stream, bool_t val);
 
/**
 * Enable a parametric equalizer
 * @param[in] stream An AudioStream
 * @param[in] location Location of the equalizer to enable (speaker or microphone)
 * @param[in] enabled Whether the equalizer must be enabled
 */
MS2_PUBLIC void audio_stream_enable_equalizer(AudioStream *stream, EqualizerLocation location, bool_t enabled);
 
/**
 * Apply a gain on a given frequency band.
 * @param[in] stream An AudioStream
 * @param[in] location Location of the concerned equalizer (speaker or microphone)
 * @param[in] gain Description of the band and the gain to apply.
 */
MS2_PUBLIC void audio_stream_equalizer_set_gain(AudioStream *stream, EqualizerLocation location, const MSEqualizerGain *gain);
 
/**
 *  stop the audio streaming thread and free everything
 *  */
MS2_PUBLIC void audio_stream_stop (AudioStream * stream);
 
/**
 *  send a dtmf
 *  */
MS2_PUBLIC int audio_stream_send_dtmf (AudioStream * stream, char dtmf);
 
MS2_PUBLIC MSFilter *audio_stream_get_local_player(AudioStream *stream);
 
MS2_PUBLIC int audio_stream_mixed_record_open(AudioStream *st, const char*filename);
 
MS2_PUBLIC int audio_stream_mixed_record_start(AudioStream *st);
 
MS2_PUBLIC int audio_stream_mixed_record_stop(AudioStream *st);
 
/**
 * Open a player to play an audio/video file to remote end.
 * The player is returned as a MSFilter so that application can make usual player controls on it using the MSPlayerInterface.
**/
MS2_PUBLIC MSFilter * audio_stream_open_remote_play(AudioStream *stream, const char *filename);
 
MS2_PUBLIC void audio_stream_close_remote_play(AudioStream *stream);
 
MS2_PUBLIC void audio_stream_set_default_card(int cardindex);
 
/* retrieve RTP statistics*/
static MS2_INLINE void audio_stream_get_local_rtp_stats(AudioStream *stream, rtp_stats_t *stats) {
    media_stream_get_local_rtp_stats(&stream->ms, stats);
}
 
/* returns a realtime indicator of the stream quality between 0 and 5 */
MS2_PUBLIC float audio_stream_get_quality_rating(AudioStream *stream);
 
/* returns the quality rating as an average since the start of the streaming session.*/
MS2_PUBLIC float audio_stream_get_average_quality_rating(AudioStream *stream);
 
/* returns a realtime indicator of the listening quality of the stream between 0 and 5 */
MS2_PUBLIC float audio_stream_get_lq_quality_rating(AudioStream *stream);
 
/* returns the listening quality rating as an average since the start of the streaming session.*/
MS2_PUBLIC float audio_stream_get_average_lq_quality_rating(AudioStream *stream);
 
/* enable ZRTP on the audio stream */
MS2_PUBLIC void audio_stream_enable_zrtp(AudioStream *stream, MSZrtpParams *params);
MS2_PUBLIC void audio_stream_start_zrtp(AudioStream *stream);
 
/**
 * return TRUE if zrtp is enabled, it does not mean that stream is encrypted, but only that zrtp is configured to know encryption status, uses #
 * */
bool_t  audio_stream_zrtp_enabled(const AudioStream *stream);
 
/* enable SRTP on the audio stream */
static MS2_INLINE bool_t audio_stream_enable_srtp(AudioStream* stream, MSCryptoSuite suite, const char* snd_key, const char* rcv_key) {
    return media_stream_enable_srtp(&stream->ms, suite, snd_key, rcv_key);
}
 
static MS2_INLINE int audio_stream_set_dscp(AudioStream *stream, int dscp) {
    return media_stream_set_dscp(&stream->ms, dscp);
}
 
/**
 * Gets the RTP session of an audio stream.
 * @param[in] stream #MediaStream object.
 * @return The RTP session of the audio stream.
 */
static MS2_INLINE RtpSession * audio_stream_get_rtp_session(const AudioStream *stream) {
    return media_stream_get_rtp_session(&stream->ms);
}
 
 
 
/**
 * @}
**/
 
 
/**
 * @addtogroup video_stream_api
 * @{
**/
 
typedef void (*VideoStreamRenderCallback)(void *user_pointer, const MSPicture *local_view, const MSPicture *remote_view);
typedef void (*VideoStreamEventCallback)(void *user_pointer, const MSFilter *f, const unsigned int event_id, const void *args);
typedef void (*VideoStreamCameraNotWorkingCallback)(void *user_pointer, const MSWebCam *old_webcam);
typedef void (*VideoStreamEncoderControlCb)(struct _VideoStream *, unsigned int method_id, void *arg, void *user_data);
 
struct _MediastreamVideoStat
{
    int counter_rcvd_pli; /*Picture Loss Indication counter */
    int counter_rcvd_sli;/* Slice Loss Indication counter */
    int counter_rcvd_rpsi; /*Reference Picture Selection Indication */
    int counter_rcvd_fir; /* Full INTRA-frame Request */
};
 
typedef struct _MediastreamVideoStat MediaStreamVideoStat;
 
struct _VideoStream
{
    MediaStream ms;
    MSFilter *jpegwriter;
    MSFilter *local_jpegwriter;
    MSFilter *output;
    MSFilter *output2;
    MSFilter *pixconv;
    MSFilter *qrcode;
    MSFilter *recorder_output; /*can be an ItcSink to send video to the audiostream's multimedia recorder, or directly a MkvRecorder */
    MSFilter *sizeconv;
    MSFilter *source;
    MSFilter *tee;
    MSFilter *tee2;
    MSFilter *tee3;
    MSFilter *void_source;
    MSVideoSize sent_vsize;
    MSVideoSize preview_vsize;
    float forced_fps; /*the target fps explicitely set by application, overrides internally selected fps*/
    float configured_fps; /*the fps that was configured to the encoder. It might be different from the one really obtained from camera.*/
    float real_fps; /*the fps obtained from camera.*/
    int corner; /*for selfview*/
    VideoStreamRenderCallback rendercb;
    void *render_pointer;
    VideoStreamEventCallback eventcb;
    void *event_pointer;
    char *display_name;
    void *window_id;
    void *preview_window_id;
    MediaStreamDir dir; /* Not used anymore, see direction in MediaStream */
    MSRect decode_rect; //Used for the qrcode decoder
    MSWebCam *cam;
    RtpSession *rtp_io_session; /**< The RTP session used for RTP input/output. */
    char *preset;
    MSVideoConfiguration *vconf_list;
    struct _AudioStream *audiostream;/*the audio stream with which this videostream is paired*/
    OrtpNackContext *nack_context;
    int device_orientation; /* warning: meaning of this variable depends on the platform (Android, iOS, ...) */
    uint64_t last_reported_decoding_error_time;
    uint64_t last_fps_check;
    uint64_t last_camera_check;
    int dead_camera_check_count;
    VideoStreamCameraNotWorkingCallback cameracb;
    void *camera_pointer;
    MediaStreamVideoStat ms_video_stat;
    VideoStreamEncoderControlCb encoder_control_cb;
    void *encoder_control_cb_user_data;
    bool_t use_preview_window;
    bool_t enable_qrcode_decoder;
    bool_t freeze_on_error;
    bool_t display_filter_auto_rotate_enabled;
    
    bool_t source_performs_encoding;
    bool_t output_performs_decoding;
    bool_t player_active;
    bool_t staticimage_webcam_fps_optimization; /* if TRUE, the StaticImage webcam will ignore the fps target in order to save CPU time. Default is TRUE */
};
 
typedef struct _VideoStream VideoStream;
 
 
 
MS2_PUBLIC VideoStream *video_stream_new(MSFactory* factory, int loc_rtp_port, int loc_rtcp_port, bool_t use_ipv6);
/**
 * Creates a VideoStream object listening on a RTP port for a dedicated address.
 * @param loc_ip the local ip to listen for RTP packets. Can be ::, O.O.O.O or any ip4/6 addresses
 * @param [in] loc_rtp_port the local UDP port to listen for RTP packets.
 * @param [in] loc_rtcp_port the local UDP port to listen for RTCP packets
 * @return a new VideoStream.
**/
MS2_PUBLIC VideoStream *video_stream_new2(MSFactory* factory, const char* ip, int loc_rtp_port, int loc_rtcp_port);
 
MS2_PUBLIC VideoStream *video_stream_new_with_sessions(MSFactory* factory, const MSMediaStreamSessions *sessions);
 
/** 
 * Use media_stream_set_direction() instead 
 **/
MS2_DEPRECATED MS2_PUBLIC void video_stream_set_direction(VideoStream *vs, MediaStreamDir dir);
static MS2_INLINE void video_stream_enable_adaptive_bitrate_control(VideoStream *stream, bool_t enabled) {
    media_stream_enable_adaptive_bitrate_control(&stream->ms, enabled);
}
static MS2_INLINE void video_stream_enable_adaptive_jittcomp(VideoStream *stream, bool_t enabled) {
    media_stream_enable_adaptive_jittcomp(&stream->ms, enabled);
}
MS2_PUBLIC void video_stream_set_render_callback(VideoStream *s, VideoStreamRenderCallback cb, void *user_pointer);
MS2_PUBLIC void video_stream_set_event_callback(VideoStream *s, VideoStreamEventCallback cb, void *user_pointer);
MS2_PUBLIC void video_stream_set_camera_not_working_callback(VideoStream *s, VideoStreamCameraNotWorkingCallback cb, void *user_pointer);
MS2_PUBLIC void video_stream_set_display_filter_name(VideoStream *s, const char *fname);
MS2_PUBLIC int video_stream_start_with_source(VideoStream *stream, RtpProfile *profile, const char *rem_rtp_ip, int rem_rtp_port,
        const char *rem_rtcp_ip, int rem_rtcp_port, int payload, int jitt_comp, MSWebCam* cam, MSFilter* source);
MS2_PUBLIC int video_stream_start(VideoStream * stream, RtpProfile *profile, const char *rem_rtp_ip, int rem_rtp_port, const char *rem_rtcp_ip,
                  int rem_rtcp_port, int payload, int jitt_comp, MSWebCam *device);
MS2_PUBLIC int video_stream_start_with_files(VideoStream *stream, RtpProfile *profile, const char *rem_rtp_ip, int rem_rtp_port,
        const char *rem_rtcp_ip, int rem_rtcp_port, int payload_type, const char *play_file, const char *record_file);
 
/**
 * Start a video stream according to the specified VideoStreamIO.
 *
 * @param[in] stream VideoStream object previously created with video_stream_new().
 * @param[in] profile RtpProfile object holding the PayloadType that can be used during the video session.
 * @param[in] rem_rtp_ip The remote IP address where to send the encoded video to.
 * @param[in] rem_rtp_port The remote port where to send the encoded video to.
 * @param[in] rem_rtcp_ip The remote IP address for RTCP.
 * @param[in] rem_rtcp_port The remote port for RTCP.
 * @param[in] payload_type The payload type number used to send the video stream. A valid PayloadType must be available at this index in the profile.
 * @param[in] io A VideoStreamIO describing the input/output of the video stream.
 */
MS2_PUBLIC int video_stream_start_from_io(VideoStream *stream, RtpProfile *profile, const char *rem_rtp_ip, int rem_rtp_port,
    const char *rem_rtcp_ip, int rem_rtcp_port, int payload_type, const MSMediaStreamIO *io);
 
MS2_PUBLIC void video_stream_prepare_video(VideoStream *stream);
MS2_PUBLIC void video_stream_unprepare_video(VideoStream *stream);
 
 
MS2_PUBLIC void video_stream_set_relay_session_id(VideoStream *stream, const char *relay_session_id);
static MS2_INLINE void video_stream_set_rtcp_information(VideoStream *st, const char *cname, const char *tool) {
    media_stream_set_rtcp_information(&st->ms, cname, tool);
}
/*
 * returns current MSWebCam for a given stream
 * */
MS2_PUBLIC const MSWebCam * video_stream_get_camera(const VideoStream *stream);
 
/**
 * Returns the current video stream source filter. Be careful, this source will be
 * destroyed if the stream is stopped.
 * @return current stream source
 */
MS2_PUBLIC MSFilter* video_stream_get_source_filter(const VideoStream* stream);
 
MS2_PUBLIC void video_stream_change_camera(VideoStream *stream, MSWebCam *cam);
 
MS2_PUBLIC void video_stream_change_camera_skip_bitrate(VideoStream *stream, MSWebCam *cam);
 
/**
 * @brief This functions changes the source filter for the passed video stream.
 * @details This is quite the same function as \ref video_stream_change_camera, but this one
 * allows you to pass the source filter that is created for the camera and reuse it. This gives you the
 * ability to switch rapidly between two streams, whereas re-creating them each time would be
 * costly (especially with webcams).
 *
 * @note Since the \ref video_stream_stop() will automatically destroy the source, it is
 *        advised that you use \ref video_stream_stop_keep_source() instead, so that you
 *        can manually destroy the source filters after the stream is stopped.
 *
 * Example usage:
 *
 *        video_stream_start(stream, profile, [...], noWebcamDevice);
 *        // We manage the sources for the stream ourselves:
 *        MSFilter* noWebCamFilter = video_stream_get_source_filter(stream);
 *        MSFilter* frontCamFilter = ms_web_cam_create_reader(frontCamDevice);
 *
 *         sleep(1);
 *         video_stream_change_source_filter(stream, frontCamDevice, frontCamFilter, TRUE); // will keep the previous filter
 *         sleep(1);
 *         video_stream_change_source_filter(stream, noWebcamDevice, noWebCamFilter, TRUE); // keep the previous filter
 *
 *        sleep(1)
 *        video_stream_stop_keep_source(stream);
 *        ms_filter_destroy(noWebCamFilter);
 *        ms_filter_destroy(frontCamFilter);
 *
 *
 * @param stream the video stream to modify
 * @param cam the camera that you want to set as the new source
 * @param cam_filter the filter for this camera. It can be obtained with ms_web_cam_create_reader(cam)
 * @return the previous source if keep_previous_source is TRUE, otherwise NULL
 */
MS2_PUBLIC MSFilter* video_stream_change_source_filter(VideoStream *stream, MSWebCam* cam, MSFilter* filter, bool_t keep_previous_source );
 
/**
 * @brief This is the same function as \ref video_stream_change_source_filter() called with keep_source=1, but
 *  the new filter will be created from the MSWebcam that is passed as argument.
 *
 *  @param stream the video stream
 *  @param cam the MSWebcam from which the new source filter should be created.
 *  @return the previous source filter
 */
MS2_PUBLIC MSFilter* video_stream_change_camera_keep_previous_source(VideoStream *stream, MSWebCam *cam);
 
 
/* Calling video_stream_set_sent_video_size() or changing the bitrate value in the used PayloadType during a stream is running does nothing.
The following function allows to take into account new parameters by redrawing the sending graph*/
MS2_PUBLIC void video_stream_update_video_params(VideoStream *stream);
/*function to call periodically to handle various events */
MS2_PUBLIC void video_stream_iterate(VideoStream *stream);
 
/*
 * Assign a specific callback to process PLI, SLI, FIR received by RTCP.
 * When set to NULL, or not assigned, the default behavior is to target these commands to the video encoder.
 */ 
MS2_PUBLIC void video_stream_set_encoder_control_callback(VideoStream *stream, VideoStreamEncoderControlCb cb, void *user_data);
 
/**
 * Asks the video stream to send a Full-Intra Request.
 * @param[in] stream The videostream object.
 */
MS2_PUBLIC void video_stream_send_fir(VideoStream *stream);
 
/**
 * Asks the video stream to generate a Video Fast Update (generally after receiving a Full-Intra Request.
 * @param[in] stream The videostream object.
 */
MS2_PUBLIC void video_stream_send_vfu(VideoStream *stream);
 
MS2_PUBLIC void video_stream_stop(VideoStream * stream);
 
/**
 * Stop the video stream, but does not destroy the source of the video. This function
 * can be use in conjunction with \ref video_stream_change_source_filter() to allow
 * manual management of the source filters for a video stream.
 * @param stream the stream to stop
 * @return returns the source of the video stream, which you should manually destroy when appropriate.
 */
MS2_PUBLIC MSFilter* video_stream_stop_keep_source(VideoStream * stream);
 
MS2_PUBLIC bool_t video_stream_started(VideoStream *stream);
 
/**
 * Try to set the size of the video that is sent. Since this relies also on the
 * bitrate specified, make sure to set the payload bitrate accordingly with
 * rtp_profile_get_payload and normal_bitrate value otherwise the best
 * possible resolution will be taken instead of the requested one.
 * @param[in] stream The videostream for which to get the sent video size.
 * @param[in] vsize The sent video size wished.
 */
MS2_PUBLIC void video_stream_set_sent_video_size(VideoStream *stream, MSVideoSize vsize);
 
/**
 * Gets the size of the video that is sent.
 * @param[in] stream The videostream for which to get the sent video size.
 * @return The sent video size or MS_VIDEO_SIZE_UNKNOWN if not available.
 */
MS2_PUBLIC MSVideoSize video_stream_get_sent_video_size(const VideoStream *stream);
 
/**
 * Gets the size of the video that is received.
 * @param[in] stream The videostream for which to get the received video size.
 * @return The received video size or MS_VIDEO_SIZE_UNKNOWN if not available.
 */
MS2_PUBLIC MSVideoSize video_stream_get_received_video_size(const VideoStream *stream);
 
/**
 * Gets the framerate of the video that is sent.
 * @param[in] stream The videostream.
 * @return The actual framerate, 0 if not available..
 */
MS2_PUBLIC float video_stream_get_sent_framerate(const VideoStream *stream);
 
/**
 * Gets the framerate of the video that is received.
 * @param[in] stream The videostream.
 * @return The received framerate or 0 if not available.
 */
MS2_PUBLIC float video_stream_get_received_framerate(const VideoStream *stream);
 
MS2_PUBLIC void video_stream_enable_self_view(VideoStream *stream, bool_t val);
MS2_PUBLIC void * video_stream_get_native_window_id(VideoStream *stream);
MS2_PUBLIC void video_stream_set_native_window_id(VideoStream *stream, void *id);
MS2_PUBLIC void video_stream_set_native_preview_window_id(VideoStream *stream, void *id);
MS2_PUBLIC void * video_stream_get_native_preview_window_id(VideoStream *stream);
MS2_PUBLIC void video_stream_use_preview_video_window(VideoStream *stream, bool_t yesno);
MS2_PUBLIC void video_stream_set_device_rotation(VideoStream *stream, int orientation);
MS2_PUBLIC void video_stream_show_video(VideoStream *stream, bool_t show);
MS2_PUBLIC void video_stream_set_freeze_on_error(VideoStream *stream, bool_t yesno);
 
/**
 * @brief Gets the camera sensor rotation.
 *
 * This is needed on some mobile platforms to get the number of degrees the camera sensor
 * is rotated relative to the screen.
 *
 * @param stream The video stream related to the operation
 * @return The camera sensor rotation in degrees (0 to 360) or -1 if it could not be retrieved
 */
MS2_PUBLIC int video_stream_get_camera_sensor_rotation(VideoStream *stream);
 
/*provided for compatibility, use media_stream_set_direction() instead */
MS2_PUBLIC int video_stream_recv_only_start(VideoStream *videostream, RtpProfile *profile, const char *addr, int port, int used_pt, int jitt_comp);
MS2_PUBLIC int video_stream_send_only_start(VideoStream *videostream,
                RtpProfile *profile, const char *addr, int port, int rtcp_port,
                int used_pt, int  jitt_comp, MSWebCam *device);
MS2_PUBLIC void video_stream_recv_only_stop(VideoStream *vs);
MS2_PUBLIC void video_stream_send_only_stop(VideoStream *vs);
 
/* enable ZRTP on the video stream using information from the audio stream */
MS2_PUBLIC void video_stream_enable_zrtp(VideoStream *vstream, AudioStream *astream);
MS2_PUBLIC void video_stream_start_zrtp(VideoStream *stream);
 
/* enable SRTP on the video stream */
static MS2_INLINE bool_t video_stream_enable_strp(VideoStream* stream, MSCryptoSuite suite, const char* snd_key, const char* rcv_key) {
    return media_stream_enable_srtp(&stream->ms, suite, snd_key, rcv_key);
}
 
/* if enabled, the display filter will internaly rotate the video, according to the device orientation */
MS2_PUBLIC void video_stream_enable_display_filter_auto_rotate(VideoStream* stream, bool_t enable);
 
/* retrieve RTP statistics*/
static MS2_INLINE void video_stream_get_local_rtp_stats(VideoStream *stream, rtp_stats_t *stats) {
    media_stream_get_local_rtp_stats(&stream->ms, stats);
}
 
static MS2_INLINE int video_stream_set_dscp(VideoStream *stream, int dscp) {
    return media_stream_set_dscp(&stream->ms, dscp);
}
 
/**
 * Gets the RTP session of a video stream.
 * @param[in] stream #MediaStream object.
 * @return The RTP session of the video stream.
 */
static MS2_INLINE RtpSession * video_stream_get_rtp_session(const VideoStream *stream) {
    return media_stream_get_rtp_session(&stream->ms);
}
 
/**
 * Ask the video stream whether a decoding error should be reported (eg. to send a VFU request).
 * @param[in] stream The VideoStream object.
 * @param[in] ms The minimum interval in milliseconds between to decoding error report.
 * @return TRUE if the decoding error should be reported, FALSE otherwise.
 */
MS2_PUBLIC bool_t video_stream_is_decoding_error_to_be_reported(VideoStream *stream, uint32_t ms);
 
/**
 * Tell the video stream that a decoding error has been reported.
 * @param[in] stream The VideoStream object.
 */
MS2_PUBLIC void video_stream_decoding_error_reported(VideoStream *stream);
 
/**
 * Tell the video stream that a decoding error has been recovered so that new decoding can be reported sooner.
 * @param[in] stream The VideoStream object.
 */
MS2_PUBLIC void video_stream_decoding_error_recovered(VideoStream *stream);
 
 
/**
 * Force a resolution for the preview.
 * @param[in] stream The VideoStream object.
 * @param[in] vsize video resolution.
**/
MS2_PUBLIC void video_stream_set_preview_size(VideoStream *stream, MSVideoSize vsize);
 
/**
 * Force a resolution for the preview.
 * @param[in] stream The VideoStream object.
 * @param[in] fps the frame rate in frame/seconds. A value of zero means "use encoder default value".
**/
MS2_PUBLIC void video_stream_set_fps(VideoStream *stream, float fps);
 
/**
 * Link the audio stream with an existing video stream.
 * This is necessary to enable recording of audio & video into a multimedia file.
 */
MS2_PUBLIC void audio_stream_link_video(AudioStream *stream, VideoStream *video);
 
/**
 * Unlink the audio stream from the video stream.
 * This must be done if the video stream is about to be stopped.
**/
MS2_PUBLIC void audio_stream_unlink_video(AudioStream *stream, VideoStream *video);
 
/**
 * Set a video preset to be used for the video stream.
 * @param[in] stream VideoStream object
 * @param[in] preset The name of the video preset to be used.
 */
MS2_PUBLIC void video_stream_use_video_preset(VideoStream *stream, const char *preset);
 
/**
 * Returns the name of the video preset used for the video stream.
 * @param[in] stream VideoStream object
 */
MS2_PUBLIC const char* video_stream_get_video_preset(VideoStream *stream);
 
 
/**
 * Open a player to play a video file (mkv) to remote end.
 * The player is returned as a MSFilter so that application can make usual player controls on it using the MSPlayerInterface.
**/
MS2_PUBLIC MSFilter * video_stream_open_remote_play(VideoStream *stream, const char *filename);
 
MS2_PUBLIC void video_stream_close_remote_play(VideoStream *stream);
 
/**
 * Open a recorder to record the video coming from remote end into a mkv file.
 * This must be done before the stream is started.
**/
MS2_PUBLIC MSFilter * video_stream_open_remote_record(VideoStream *stream, const char *filename);
 
MS2_PUBLIC void video_stream_close_remote_record(VideoStream *stream);
 
MS2_PUBLIC void video_stream_enable_retransmission_on_nack(VideoStream *stream, bool_t enable);
MS2_PUBLIC void video_stream_set_retransmission_on_nack_max_packet(VideoStream *stream, unsigned int max);
 
/**
 * Small API to display a local preview window.
**/
 
typedef VideoStream VideoPreview;
 
MS2_PUBLIC VideoPreview * video_preview_new(MSFactory *factory);
#define video_preview_set_event_callback(p,c,u) video_stream_set_event_callback(p,c,u)
#define video_preview_set_size(p,s) video_stream_set_sent_video_size(p,s)
#define video_preview_set_display_filter_name(p,dt) video_stream_set_display_filter_name(p,dt)
#define video_preview_set_native_window_id(p,id) video_stream_set_native_preview_window_id(p,id)
#define video_preview_get_native_window_id(p) video_stream_get_native_preview_window_id(p)
#define video_preview_set_fps(p,fps) video_stream_set_fps((VideoStream*)p,fps)
#define video_preview_set_device_rotation(p, r) video_stream_set_device_rotation(p, r)
MS2_PUBLIC void video_preview_start(VideoPreview *stream, MSWebCam *device);
MS2_PUBLIC void video_preview_enable_qrcode(VideoPreview *stream, bool_t enable);
MS2_PUBLIC void video_preview_set_decode_rect(VideoPreview *stream, MSRect rect);
MS2_PUBLIC bool_t video_preview_qrcode_enabled(VideoPreview *stream);
MS2_PUBLIC MSVideoSize video_preview_get_current_size(VideoPreview *stream);
MS2_PUBLIC void video_preview_stop(VideoPreview *stream);
MS2_PUBLIC void video_preview_change_camera(VideoPreview *stream, MSWebCam *cam);
MS2_PUBLIC void video_preview_update_video_params(VideoPreview *stream);
 
 
/**
 * Stops the video preview graph but keep the source filter for reuse.
 * This is useful when transitioning from a preview-only to a duplex video.
 * The filter needs to be passed to the #video_stream_start_with_source function,
 * otherwise you should destroy it.
 * @param[in] stream VideoPreview object
 * @return The source filter to be passed to the #video_stream_start_with_source function.
 */
MS2_PUBLIC MSFilter* video_preview_stop_reuse_source(VideoPreview *stream);
 
/*
 * Returns the web cam descriptor for the mire kind of camera.
**/
MS2_PUBLIC MSWebCamDesc *ms_mire_webcam_desc_get(void);
 
/**
 * Create an RTP session for duplex communication.
 * @param[in] local_ip The local IP to bind the RTP and RTCP sockets to.
 * @param[in] local_rtp_port The local port to bind the RTP socket to.
 * @param[in] local_rtcp_port The local port to bind the RTCP socket to.
 */
MS2_PUBLIC RtpSession * ms_create_duplex_rtp_session(const char* local_ip, int loc_rtp_port, int loc_rtcp_port, int mtu);
 
/**
 * Asks the audio playback filter to route to the selected device (currently only used for blackberry)
 * @param[in] stream The AudioStream object
 * @param[in] route The wanted audio output device (earpiece, speaker)
 */
MS2_PUBLIC void audio_stream_set_audio_route(AudioStream *stream, MSAudioRoute route);
 
/**
 * Asks the audio capture filter to route to the selected sound card (currently only used for AAudio and OpenSLES)
 * @param[in] stream The AudioStream object
 * @param[in] sndcard_capture The wanted audio input soundcard
 */
MS2_PUBLIC void audio_stream_set_input_ms_snd_card(AudioStream *stream, MSSndCard * sndcard_capture);
 
/**
 * Asks the audio playback filter to route to the selected sound card (currently only used for AAudio and OpenSLES)
 * @param[in] stream The AudioStream object
 * @param[in] sndcard_playback The wanted audio output soundcard
 */
MS2_PUBLIC void audio_stream_set_output_ms_snd_card(AudioStream *stream, MSSndCard * sndcard_playback);
 
/**
 * Retrieve the current sound card from the audio capture filter (currently only used for AAudio and OpenSLES)
 * @param[in] stream The AudioStream object
 */
MS2_PUBLIC MSSndCard * audio_stream_get_input_ms_snd_card(AudioStream *stream);
 
/**
 * Retrieve the current sound card from the audio playback filter (currently only used for AAudio and OpenSLES)
 * @param[in] stream The AudioStream object
 */
MS2_PUBLIC MSSndCard * audio_stream_get_output_ms_snd_card(AudioStream *stream);
 
/**
 * @}
**/
 
/**
 * @addtogroup text_stream_api
 * @{
**/
 
struct _TextStream
{
    MediaStream ms;
    MSFilter *rttsource;
    MSFilter *rttsink;
    int pt_t140;
    int pt_red;
};
 
typedef struct _TextStream TextStream;
 
/**
 * Creates a TextStream object listening on a RTP port.
 * @param loc_rtp_port the local UDP port to listen for RTP packets.
 * @param loc_rtcp_port the local UDP port to listen for RTCP packets
 * @param ipv6 TRUE if ipv6 must be used.
 * @param factory
 * @return a new TextStream.
**/
MS2_PUBLIC TextStream *text_stream_new(MSFactory *factory, int loc_rtp_port, int loc_rtcp_port, bool_t ipv6);
 
/**
 * Creates a TextStream object from initialized MSMediaStreamSessions.
 * @param sessions the MSMediaStreamSessions
 * @param factory
 * @return a new TextStream
**/
MS2_PUBLIC TextStream *text_stream_new_with_sessions(MSFactory *factory, const MSMediaStreamSessions *sessions);
 
/**
 * Creates a TextStream object listening on a RTP port for a dedicated address.
 * @param loc_ip the local ip to listen for RTP packets. Can be ::, O.O.O.O or any ip4/6 addresses
 * @param [in] loc_rtp_port the local UDP port to listen for RTP packets.
 * @param [in] loc_rtcp_port the local UDP port to listen for RTCP packets
 * @param factory
 * @return a new TextStream.
**/
MS2_PUBLIC TextStream *text_stream_new2(MSFactory *factory, const char* ip, int loc_rtp_port, int loc_rtcp_port);
 
/**
 * Starts a text stream.
 *
 * @param[in] stream TextStream object previously created with text_stream_new().
 * @param[in] profile RtpProfile object holding the PayloadType that can be used during the text session.
 * @param[in] rem_rtp_addr The remote IP address where to send the text to.
 * @param[in] rem_rtp_port The remote port where to send the text to.
 * @param[in] rem_rtcp_addr The remote IP address for RTCP.
 * @param[in] rem_rtcp_port The remote port for RTCP.
 * @param[in] payload_type The payload type number used to send the text stream. A valid PayloadType must be available at this index in the profile.
 * @param[in] factory
 */
MS2_PUBLIC TextStream* text_stream_start(TextStream *stream, RtpProfile *profile, const char *rem_rtp_addr, int rem_rtp_port, const char *rem_rtcp_addr, int rem_rtcp_port,
                                         int payload_type);
 
/**
 *  Stops the text streaming thread and free everything
**/
MS2_PUBLIC void text_stream_stop (TextStream * stream);
 
/**
 * Executes background low priority tasks related to text processing (RTP statistics analysis).
 * It should be called periodically, for example with an interval of 100 ms or so.
 *
 * @param[in] stream TextStream object previously created with text_stream_new().
 */
MS2_PUBLIC void text_stream_iterate(TextStream *stream);
 
/**
 * Writes a character to stream in UTF-32 format.
 *
 * @param[in] stream TextStream object previously created with text_stream_new().
 * @param[in] i the Char in UTF-32 format.
 **/
MS2_PUBLIC void text_stream_putchar32(TextStream *stream, uint32_t i);
 
MS2_PUBLIC void text_stream_prepare_text(TextStream *stream);
MS2_PUBLIC void text_stream_unprepare_text(TextStream *stream);
 
/**
 * @}
**/
 
 
#ifdef __cplusplus
}
#endif
 
#endif