Syan 7 years ago
parent
commit
e0466e3188

+ 3
- 1
AgoraView.js View File

5
 import  React, {Component, PropTypes} from 'react'
5
 import  React, {Component, PropTypes} from 'react'
6
 import {
6
 import {
7
     requireNativeComponent,
7
     requireNativeComponent,
8
-    View
8
+    View,
9
+    Platform
9
 } from 'react-native'
10
 } from 'react-native'
10
 
11
 
11
 export default class AgoraView extends Component {
12
 export default class AgoraView extends Component {
20
 AgoraView.propTypes = {
21
 AgoraView.propTypes = {
21
     showLocalVideo: PropTypes.bool,
22
     showLocalVideo: PropTypes.bool,
22
     remoteUid: PropTypes.number,
23
     remoteUid: PropTypes.number,
24
+    zOrderMediaOverlay: PropTypes.bool,
23
     ...View.propTypes
25
     ...View.propTypes
24
 };
26
 };
25
 
27
 

+ 44
- 234
README.md View File

1
-[![QQ Group](https://img.shields.io/badge/QQ%20Group-471757030-red.svg)]()
1
+##### 有任何问题欢迎加入QQ群进行反馈  471757030
2
 
2
 
3
 # react-native-agora
3
 # react-native-agora
4
 
4
 
5
-## Installation and linking libraries
5
+## 功能介绍
6
+
7
+- 支持 iOS Android  声网Agora视频通讯SDK
8
+- 支持 直播 多人视频会议 语音 功能
9
+
10
+## 安装使用
6
 
11
 
7
 Install with npm:
12
 Install with npm:
8
 
13
 
69
 
74
 
70
 ## Documentation
75
 ## Documentation
71
 
76
 
72
-[声网API文档](https://docs.agora.io/cn/1.11.1/user_guide/API/ios_api_live_cn.html)
77
+[声网API文档](https://document.agora.io/cn/1.12/api/)
73
 
78
 
74
 ##### RtcEngine方法
79
 ##### RtcEngine方法
75
 
80
 
76
 | Property                         | Type                                     | Description                           |
81
 | Property                         | Type                                     | Description                           |
77
 | -------------------------------- | ---------------------------------------- | ------------------------------------- |
82
 | -------------------------------- | ---------------------------------------- | ------------------------------------- |
78
-| init                             | object {appid: 'agora注册的应用id', channelProfile: '频道模式', videoProfile: '视频模式', clientRole: '角色'} | 初始化Agora引擎                            |
83
+| init                             | object {appid: 'agora注册的应用id', channelProfile: '频道模式', videoProfile: '视频模式', clientRole: '角色', swapWidthAndHeight: 'bool值'} | 初始化Agora引擎                            |
79
 | joinChannel                      | string channelName (房间名称)   number uid (用户设置的uid 传0系统会自动分配) | 加入房间                                  |
84
 | joinChannel                      | string channelName (房间名称)   number uid (用户设置的uid 传0系统会自动分配) | 加入房间                                  |
80
 | leaveChannel                     |                                          | 离开频道                                  |
85
 | leaveChannel                     |                                          | 离开频道                                  |
81
 | destroy                          |                                          | 销毁引擎实例                                |
86
 | destroy                          |                                          | 销毁引擎实例                                |
87
+| configPublisher                     | object{} config参数请前往Agora文档查看                                        | 配置旁路直播推流方法                               |
88
+| setLocalRenderMode                     | number mode (1 2 3)                                        | 设置本地视频显示模式                                |
89
+| setRemoteRenderMode                     | number uid  number mode (1 2 3)                                          | 设置远端视频显示模式                                |
90
+| enableAudioVolumeIndication                     | number interval (时间间隔) number smooth(平滑系数。可以设置为 3)                                         | 启用说话者音量提示                                |
82
 | startPreview                     |                                          | 开启视频预览                                |
91
 | startPreview                     |                                          | 开启视频预览                                |
83
 | stopPreview                      |                                          | 关闭视频预览                                |
92
 | stopPreview                      |                                          | 关闭视频预览                                |
84
 | switchCamera                     |                                          | 切换前置/后置摄像头                            |
93
 | switchCamera                     |                                          | 切换前置/后置摄像头                            |
92
 | enableLocalVideo                 | bool (default false)                     | 禁用本地视频功能                              |
101
 | enableLocalVideo                 | bool (default false)                     | 禁用本地视频功能                              |
93
 | muteAllRemoteVideoStreams        | bool (default false)                     | 暂停所有远端视频流                             |
102
 | muteAllRemoteVideoStreams        | bool (default false)                     | 暂停所有远端视频流                             |
94
 | muteRemoteVideoStream            | number uid(用户uid) bool  mute(是否暂停)       | 暂停指定远端视频流                             |
103
 | muteRemoteVideoStream            | number uid(用户uid) bool  mute(是否暂停)       | 暂停指定远端视频流                             |
95
-| startRecordingService (ios only) | string  recordingKey                     | 启动服务端录制服务                             |
96
-| stopRecordingService (ios only)  | string  recordingKey                     | 停止服务端录制服务                             |
104
+| startRecordingService (iOS only) | string  recordingKey                     | 启动服务端录制服务                             |
105
+| stopRecordingService (iOS only)  | string  recordingKey                     | 停止服务端录制服务                             |
97
 | getSdkVersion                    | callback                                 | 获取版本号                                 |
106
 | getSdkVersion                    | callback                                 | 获取版本号                                 |
98
 
107
 
99
 ##### 原生通知事件
108
 ##### 原生通知事件
106
   onUserJoined: data => {},
115
   onUserJoined: data => {},
107
   onError: data => {},
116
   onError: data => {},
108
   onWarning: data => {},
117
   onWarning: data => {},
109
-  onLeaveChannel: data => {}
118
+  onLeaveChannel: data => {},
119
+  onAudioVolumeIndication: data => {}
110
 })
120
 })
111
 ```
121
 ```
112
 
122
 
119
 | onError                   | 错误信息         |
129
 | onError                   | 错误信息         |
120
 | onWarning                 | 警告           |
130
 | onWarning                 | 警告           |
121
 | onLeaveChannel            | 退出频道         |
131
 | onLeaveChannel            | 退出频道         |
132
+| onAudioVolumeIndication            | 音量提示回调         |
133
+
122
 
134
 
123
 ##### AgoraView 组件
135
 ##### AgoraView 组件
124
 
136
 
126
 | -------------- | -------------------- |
138
 | -------------- | -------------------- |
127
 | showLocalVideo | 是否显示本地视频(bool)       |
139
 | showLocalVideo | 是否显示本地视频(bool)       |
128
 | remoteUid      | 显示远程视频(number 传入uid) |
140
 | remoteUid      | 显示远程视频(number 传入uid) |
141
+| zOrderMediaOverlay (Android only)      | 多视频界面覆盖 设置为true优先在上层(bool) |
129
 
142
 
130
-## Usage
143
+
144
+## 运行示例
131
 
145
 
132
 [Example](https://github.com/DBshaoYan/RNAgoraExample)
146
 [Example](https://github.com/DBshaoYan/RNAgoraExample)
133
 
147
 
134
-```
135
-import React, {Component} from 'react';
136
-import {
137
-    StyleSheet,
138
-    View,
139
-    Text,
140
-    TouchableOpacity,
141
-    Image,
142
-    Dimensions
143
-} from 'react-native';
144
-
145
-const {width, height} = Dimensions.get('window');
146
-
147
-import {RtcEngine, AgoraView} from 'react-native-agora'
148
-
149
-export default class Meeting extends Component {
150
-
151
-    constructor(props) {
152
-        super(props);
153
-        this.state = {
154
-            remotes: [],
155
-            isJoinSuccess: false,
156
-            isSpeaker: false,
157
-            isMute: false
158
-        };
159
-    }
160
-
161
-    componentWillMount() {
162
-
163
-        //初始化Agora
164
-        const options = {
165
-            appid: '前往Agora官网进行申请--https://www.agora.io/cn/',
166
-            channelProfile: 1,
167
-            videoProfile: 40,
168
-            clientRole: 1,
169
-        };
170
-        RtcEngine.init(options);
171
-    }
172
-
173
-    componentDidMount() {
174
-
175
-        //加入房间
176
-        RtcEngine.joinChannel();
177
-
178
-        //所以的原生通知统一管理
179
-        RtcEngine.eventEmitter({
180
-            onFirstRemoteVideoDecoded: (data) => {
181
-                console.log(data);
182
-                //有远程视频加入 返回重要的  uid  AgoraView 根据uid 来设置remoteUid值
183
-                const {remotes} = this.state;
184
-
185
-                let arr = [...remotes];
186
-                let sign = false;
187
-                arr.forEach(v => {
188
-                    sign = v === data.uid
189
-                });
190
-
191
-                if (!sign) {
192
-                    arr.push(data.uid)
193
-                }
194
-
195
-                this.setState({
196
-                    remotes: arr
197
-                })
198
-            },
199
-            onUserOffline: (data) => {
200
-             	console.log(data);
201
-              	//有人离开了!
202
-                const {remotes} = this.state;
203
-
204
-                let arr = [...remotes];
205
-
206
-                let newArr = [];
207
-                newArr = arr.filter(v => {
208
-                    return v !== data.uid
209
-                });
210
-
211
-                this.setState({
212
-                    remotes: newArr
213
-                });
214
-            },
215
-            onJoinChannelSuccess: (data) => {
216
-                console.log(data);
217
- 			   //加入房间成功!
218
-                this.setState({
219
-                    isJoinSuccess: true
220
-                });
221
-            },
222
-            onUserJoined: (data) => {
223
-                console.log(data);
224
-                //有人来了!
225
-            },
226
-            onError: (data) => {
227
-                console.log(data);
228
-                //错误!
229
-                RtcEngine.leaveChannel();
230
-            }
231
-        })
232
-    }
233
-
234
-    componentWillUnmount() {
235
-        RtcEngine.removeEmitter()
236
-    }
237
-
238
-    handlerCancel = () => {
239
-        RtcEngine.leaveChannel();
240
-    };
241
-
242
-    handlerSwitchCamera = () => {
243
-        RtcEngine.switchCamera();
244
-    };
245
-
246
-    handlerMuteAllRemoteAudioStreams = () => {
247
-        this.setState({
248
-            isMute: !this.state.isMute
249
-        }, () => {
250
-            RtcEngine.muteAllRemoteAudioStreams(this.state.isMute)
251
-        })
252
-    };
253
-
254
-    handlerSetEnableSpeakerphone = () => {
255
-
256
-        this.setState({
257
-            isSpeaker: !this.state.isSpeaker
258
-        }, () => {
259
-            RtcEngine.setEnableSpeakerphone(this.state.isSpeaker)
260
-        });
261
-
262
-    };
263
-
264
-    render() {
265
-
266
-        const {isMute, isSpeaker, remotes, isJoinSuccess} = this.state;
267
-
268
-        if (!isJoinSuccess) {
269
-            return(
270
-                <View style={{flex:1, backgroundColor:'#fff', justifyContent:'center', alignItems:'center'}}>
271
-                    <Text>正在创建视频会议...</Text>
272
-                </View>
273
-            )
274
-        }
275
-
276
-        return (
277
-            <View style={styles.container}>
278
-                <AgoraView style={styles.localView} showLocalVideo={true} />
279
-                <View style={styles.absView}>
280
-                    <View style={styles.videoView}>
281
-                        {remotes.map((v, k) => {
282
-                            return (
283
-                                <AgoraView
284
-                                    style={styles.remoteView}
285
-                                    key={k}
286
-                                    remoteUid={v}
287
-                                />
288
-                            )
289
-                        })}
290
-                    </View>
291
-                    <View>
292
-                        <TouchableOpacity
293
-                            style={{alignSelf: 'center'}}
294
-                            onPress={this.handlerCancel}>
295
-                            <Image
296
-                                style={{width: 60, height: 60}}
297
-                                source={require('../images/btn_endcall.png')}/>
298
-                        </TouchableOpacity>
299
-                        <View style={styles.bottomView}>
300
-                            <TouchableOpacity onPress={this.handlerMuteAllRemoteAudioStreams} activeOpacity={.7}>
301
-                                <Image
302
-                                    style={{width: 50, height: 50}}
303
-                                    source={ isMute ? require('../images/icon_muted.png') : require('../images/btn_mute.png')}/>
304
-                            </TouchableOpacity>
305
-
306
-                            <TouchableOpacity onPress={this.handlerSwitchCamera} activeOpacity={.7}>
307
-                                <Image
308
-                                    style={{width: 50, height: 50}}
309
-                                    source={ require('../images/btn_switch_camera.png')}/>
310
-                            </TouchableOpacity>
311
-
312
-                            <TouchableOpacity onPress={this.handlerSetEnableSpeakerphone} activeOpacity={.7}>
313
-                                <Image
314
-                                    style={{width: 50, height: 50}}
315
-                                    source={isSpeaker ? require('../images/icon_speaker.png') : require('../images/btn_speaker.png')}/>
316
-                            </TouchableOpacity>
317
-                        </View>
318
-                    </View>
319
-
320
-                </View>
321
-            </View>
322
-        );
323
-    }
324
-}
325
-
326
-const styles = StyleSheet.create({
327
-    container: {
328
-        flex: 1,
329
-        backgroundColor: '#F4F4F4'
330
-    },
331
-    absView: {
332
-        position: 'absolute',
333
-        top: 20,
334
-        left: 0,
335
-        right: 0,
336
-        bottom: 0,
337
-        justifyContent: 'space-between'
338
-    },
339
-    videoView: {
340
-        padding: 5,
341
-        flexWrap: 'wrap',
342
-        flexDirection: 'row',
343
-        zIndex: 100
344
-    },
345
-    localView: {
346
-        flex: 1
347
-    },
348
-    remoteView: {
349
-        width: (width - 40) / 3,
350
-        height: (width - 40) / 3,
351
-        margin: 5
352
-    },
353
-    bottomView: {
354
-        padding: 20,
355
-        flexDirection: 'row',
356
-        justifyContent: 'space-around'
357
-    }
358
-});
359
-```
148
+
149
+## 更新信息
150
+
151
+#### 1.0.8
152
+
153
+ - 更新 Agora SDK 为 1.12
154
+
155
+ - init 不再默认开启视频预览 根据自己需求和时机调用startPreview
156
+
157
+ - init options 新增参数  是否交换宽和高 swapWidthAndHeight 默认false
158
+
159
+ - 新增方法 配置旁路直播推流方法 configPublisher
160
+
161
+ - 新增方法 设置本地视频显示模式 setLocalRenderMode
162
+
163
+ - 新增方法 设置远端视频显示模式 setRemoteRenderMode
164
+
165
+ - 新增方法 启用说话者音量提示 enableAudioVolumeIndication
166
+
167
+ - 新增音量提示回调 onAudioVolumeIndication
168
+
169
+ - Android AgoraView 新增zOrderMediaOverlay属性 解决多视频界面覆盖 设置为true优先在上层

BIN
android/libs/agora-rtc-sdk.jar View File


+ 10
- 3
android/src/main/java/com/syan/agora/AgoraManager.java View File

1
 package com.syan.agora;
1
 package com.syan.agora;
2
 
2
 
3
 import android.content.Context;
3
 import android.content.Context;
4
+import android.util.Log;
4
 import android.util.SparseArray;
5
 import android.util.SparseArray;
5
 import android.view.SurfaceView;
6
 import android.view.SurfaceView;
6
 
7
 
51
         this.context = context;
52
         this.context = context;
52
 
53
 
53
         //创建RtcEngine对象,mRtcEventHandler为RtcEngine的回调
54
         //创建RtcEngine对象,mRtcEventHandler为RtcEngine的回调
54
-        mRtcEngine = RtcEngine.create(context, options.getString("appid"), mRtcEventHandler);
55
+        try {
56
+            mRtcEngine = RtcEngine.create(context, options.getString("appid"), mRtcEventHandler);
57
+
58
+        } catch (Exception e) {
59
+            throw new RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e));
60
+        }
55
         //开启视频功能
61
         //开启视频功能
56
         mRtcEngine.enableVideo();
62
         mRtcEngine.enableVideo();
57
-        //视频配置,设置为360P
58
-        mRtcEngine.setVideoProfile(options.getInt("videoProfile"), true);
63
+        mRtcEngine.setVideoProfile(options.getInt("videoProfile"), options.getBoolean("swapWidthAndHeight")); //视频配置,
59
         mRtcEngine.enableWebSdkInteroperability(true);  //设置和web通信
64
         mRtcEngine.enableWebSdkInteroperability(true);  //设置和web通信
60
         mRtcEngine.setChannelProfile(options.getInt("channelProfile")); //设置模式
65
         mRtcEngine.setChannelProfile(options.getInt("channelProfile")); //设置模式
61
         mRtcEngine.setClientRole(options.getInt("clientRole"), null); //设置角色
66
         mRtcEngine.setClientRole(options.getInt("clientRole"), null); //设置角色
122
     public SurfaceView getSurfaceView(int uid) {
127
     public SurfaceView getSurfaceView(int uid) {
123
         return mSurfaceViews.get(uid);
128
         return mSurfaceViews.get(uid);
124
     }
129
     }
130
+
131
+
125
 }
132
 }

+ 66
- 2
android/src/main/java/com/syan/agora/AgoraModule.java View File

10
 import com.facebook.react.bridge.ReactContextBaseJavaModule;
10
 import com.facebook.react.bridge.ReactContextBaseJavaModule;
11
 import com.facebook.react.bridge.ReactMethod;
11
 import com.facebook.react.bridge.ReactMethod;
12
 import com.facebook.react.bridge.ReadableMap;
12
 import com.facebook.react.bridge.ReadableMap;
13
+import com.facebook.react.bridge.WritableArray;
13
 import com.facebook.react.bridge.WritableMap;
14
 import com.facebook.react.bridge.WritableMap;
14
 import com.facebook.react.modules.core.DeviceEventManagerModule;
15
 import com.facebook.react.modules.core.DeviceEventManagerModule;
15
 
16
 
16
 import io.agora.rtc.IRtcEngineEventHandler;
17
 import io.agora.rtc.IRtcEngineEventHandler;
18
+import io.agora.rtc.PublisherConfiguration;
17
 import io.agora.rtc.RtcEngine;
19
 import io.agora.rtc.RtcEngine;
18
 
20
 
19
 import static com.facebook.react.bridge.UiThreadUtil.runOnUiThread;
21
 import static com.facebook.react.bridge.UiThreadUtil.runOnUiThread;
89
 
91
 
90
         }
92
         }
91
 
93
 
94
+        /**
95
+         * 说话声音音量提示回调
96
+         */
97
+        @Override
98
+        public void onAudioVolumeIndication(final AudioVolumeInfo[] speakers,
99
+                                             final int totalVolume ) {
100
+
101
+            runOnUiThread(new Runnable() {
102
+                @Override
103
+                public void run() {
104
+
105
+                    WritableArray arr = Arguments.createArray();
106
+                    for (int i = 0; i < speakers.length; i++) {
107
+                        WritableMap obj = Arguments.createMap();
108
+                        obj.putInt("uid", speakers[i].uid);
109
+                        obj.putInt("volume", speakers[i].volume);
110
+                    }
111
+
112
+                    WritableMap map = Arguments.createMap();
113
+                    map.putString("type", "onAudioVolumeIndication");
114
+                    map.putArray("speakers", arr);
115
+                    map.putInt("totalVolume", totalVolume);
116
+                    commonEvent(map);
117
+                }
118
+            });
119
+        }
120
+
92
         /**
121
         /**
93
          * 错误信息
122
          * 错误信息
94
          */
123
          */
158
     @ReactMethod
187
     @ReactMethod
159
     public void init(ReadableMap options) {
188
     public void init(ReadableMap options) {
160
         AgoraManager.getInstance().init(getReactApplicationContext(), mRtcEventHandler, options);
189
         AgoraManager.getInstance().init(getReactApplicationContext(), mRtcEventHandler, options);
161
-        AgoraManager.getInstance().setupLocalVideo().startPreview();
162
     }
190
     }
163
 
191
 
164
     //进入房间
192
     //进入房间
186
         AgoraManager.getInstance().stopPreview();
214
         AgoraManager.getInstance().stopPreview();
187
     }
215
     }
188
 
216
 
217
+    //配置旁路直播推流
218
+    @ReactMethod
219
+    public void configPublisher(ReadableMap options) {
220
+        PublisherConfiguration config = new PublisherConfiguration.Builder()
221
+                .owner(options.getBoolean("owner"))
222
+                .size(options.getInt("width"), options.getInt("height"))
223
+                .frameRate(options.getInt("framerate"))
224
+                .biteRate(options.getInt("bitrate"))
225
+                .defaultLayout(options.getInt("defaultLayout"))
226
+                .streamLifeCycle(options.getInt("lifeCycle"))
227
+                .rawStreamUrl(options.getString("rawStreamUrl"))
228
+                .publishUrl(options.getString("publishUrl"))
229
+                .extraInfo(options.getString("extraInfo"))
230
+                .build();
231
+
232
+        AgoraManager.getInstance().mRtcEngine.configPublisher(config);
233
+    }
234
+
235
+    //设置本地视频显示模式
236
+    @ReactMethod
237
+    public void setLocalRenderMode(int mode) {
238
+        AgoraManager.getInstance().mRtcEngine.setLocalRenderMode(mode);
239
+    }
240
+
241
+    //设置远端视频显示模式
242
+    @ReactMethod
243
+    public void setRemoteRenderMode(int uid, int mode) {
244
+        AgoraManager.getInstance().mRtcEngine.setRemoteRenderMode(uid, mode);
245
+    }
246
+
247
+    //启用说话者音量提示
248
+    @ReactMethod
249
+    public void enableAudioVolumeIndication(int interval, int smooth) {
250
+        AgoraManager.getInstance().mRtcEngine.enableAudioVolumeIndication(interval, smooth);
251
+    }
252
+
189
     //打开音频
253
     //打开音频
190
     @ReactMethod
254
     @ReactMethod
191
     public void enableAudio() {
255
     public void enableAudio() {
273
     //查询 SDK 版本号
337
     //查询 SDK 版本号
274
     @ReactMethod
338
     @ReactMethod
275
     public void getSdkVersion(Callback callback) {
339
     public void getSdkVersion(Callback callback) {
276
-        callback.invoke( RtcEngine.getSdkVersion());
340
+        callback.invoke(RtcEngine.getSdkVersion());
277
     }
341
     }
278
 
342
 
279
     private void commonEvent(WritableMap map) {
343
     private void commonEvent(WritableMap map) {

+ 16
- 9
android/src/main/java/com/syan/agora/AgoraViewManage.java View File

1
 package com.syan.agora;
1
 package com.syan.agora;
2
 
2
 
3
 import android.view.SurfaceView;
3
 import android.view.SurfaceView;
4
-import android.view.View;
5
 
4
 
6
 import com.facebook.react.uimanager.SimpleViewManager;
5
 import com.facebook.react.uimanager.SimpleViewManager;
7
 import com.facebook.react.uimanager.ThemedReactContext;
6
 import com.facebook.react.uimanager.ThemedReactContext;
15
 
14
 
16
     public static final String REACT_CLASS = "RCTAgoraView";
15
     public static final String REACT_CLASS = "RCTAgoraView";
17
 
16
 
17
+    public SurfaceView surfaceView;
18
+
18
     @Override
19
     @Override
19
     public String getName() {
20
     public String getName() {
20
         return REACT_CLASS;
21
         return REACT_CLASS;
28
     @ReactProp(name = "showLocalVideo")
29
     @ReactProp(name = "showLocalVideo")
29
     public void setShowLocalVideo(final AgoraVideoView agoraVideoView, boolean showLocalVideo) {
30
     public void setShowLocalVideo(final AgoraVideoView agoraVideoView, boolean showLocalVideo) {
30
 
31
 
31
-        if (showLocalVideo) {
32
-            SurfaceView surfaceView = AgoraManager.getInstance().getLocalSurfaceView();
33
-            surfaceView.setVisibility(View.VISIBLE);
34
-            agoraVideoView.addView(surfaceView);
35
-        }
32
+        AgoraManager.getInstance().setupLocalVideo();
33
+        surfaceView = AgoraManager.getInstance().getLocalSurfaceView();
34
+        //surfaceView.setVisibility(View.VISIBLE);
35
+        agoraVideoView.addView(surfaceView);
36
+//        surfaceView.setZOrderMediaOverlay(true);
37
+
38
+    }
39
+
40
+    @ReactProp(name = "zOrderMediaOverlay")
41
+    public void setZOrderMediaOverlay(final AgoraVideoView agoraVideoView, boolean zOrderMediaOverlay) {
42
+        surfaceView.setZOrderMediaOverlay(zOrderMediaOverlay);
36
     }
43
     }
37
 
44
 
38
     @ReactProp(name = "remoteUid")
45
     @ReactProp(name = "remoteUid")
39
     public void setRemoteUid(final AgoraVideoView agoraVideoView, int remoteUid) {
46
     public void setRemoteUid(final AgoraVideoView agoraVideoView, int remoteUid) {
40
         AgoraManager.getInstance().setupRemoteVideo(remoteUid);
47
         AgoraManager.getInstance().setupRemoteVideo(remoteUid);
41
-        SurfaceView surfaceView = AgoraManager.getInstance().getSurfaceView(remoteUid);
42
-        surfaceView.setVisibility(View.VISIBLE);
48
+        surfaceView = AgoraManager.getInstance().getSurfaceView(remoteUid);
49
+        //surfaceView.setVisibility(View.VISIBLE);
43
         agoraVideoView.addView(surfaceView);
50
         agoraVideoView.addView(surfaceView);
44
-        surfaceView.setZOrderMediaOverlay(true);
51
+//        surfaceView.setZOrderMediaOverlay(true);
45
     }
52
     }
46
 }
53
 }

BIN
android/src/main/jniLibs/arm64-v8a/libagora-rtc-sdk-jni.so View File


BIN
android/src/main/jniLibs/armeabi-v7a/libagora-rtc-sdk-jni.so View File


+ 113
- 47
android/src/main/jniLibs/include/IAgoraRtcEngine.h View File

72
         ptr_ = ptr;
72
         ptr_ = ptr;
73
     }
73
     }
74
     template<class C1, class C2>
74
     template<class C1, class C2>
75
-    void queryInterface(C1& c, C2 iid) {
76
-		pointer_type p;
77
-        if (!c.queryInterface(iid, (void**)&p))
78
-			reset(p);
75
+    bool queryInterface(C1* c, C2 iid) {
76
+        pointer_type p = NULL;
77
+        if (c && !c->queryInterface(iid, (void**)&p))
78
+        {
79
+            reset(p);
80
+        }
81
+        return p != NULL;;
79
 	}
82
 	}
80
 private:
83
 private:
81
     AutoPtr(const AutoPtr&);
84
     AutoPtr(const AutoPtr&);
129
     // sdk: 100~1000
132
     // sdk: 100~1000
130
     WARN_SWITCH_LIVE_VIDEO_TIMEOUT = 111,
133
     WARN_SWITCH_LIVE_VIDEO_TIMEOUT = 111,
131
 	WARN_SET_CLIENT_ROLE_TIMEOUT = 118,
134
 	WARN_SET_CLIENT_ROLE_TIMEOUT = 118,
132
-    WARN_SET_CLIENT_ROLE_NOT_AUTHORIZED = 119,
133
 };
135
 };
134
 
136
 
135
 enum ERROR_CODE_TYPE
137
 enum ERROR_CODE_TYPE
168
 	ERR_BITRATE_LIMIT = 115,
170
 	ERR_BITRATE_LIMIT = 115,
169
 	ERR_TOO_MANY_DATA_STREAMS = 116,
171
 	ERR_TOO_MANY_DATA_STREAMS = 116,
170
 	ERR_STREAM_MESSAGE_TIMEOUT = 117,
172
 	ERR_STREAM_MESSAGE_TIMEOUT = 117,
173
+    ERR_SET_CLIENT_ROLE_NOT_AUTHORIZED = 119,
171
 
174
 
172
     //1001~2000
175
     //1001~2000
173
     ERR_LOAD_MEDIA_ENGINE = 1001,
176
     ERR_LOAD_MEDIA_ENGINE = 1001,
230
     MEDIA_ENGINE_RECORDING_WARNING = 2,
233
     MEDIA_ENGINE_RECORDING_WARNING = 2,
231
     MEDIA_ENGINE_PLAYOUT_WARNING = 3,
234
     MEDIA_ENGINE_PLAYOUT_WARNING = 3,
232
     MEDIA_ENGINE_AUDIO_FILE_MIX_FINISH = 10,
235
     MEDIA_ENGINE_AUDIO_FILE_MIX_FINISH = 10,
233
-    MEDIA_ENGINE_AUDIO_SAMPLE_RATE_RECONFIG_FINISH = 11,
234
     // media engine role changed
236
     // media engine role changed
235
     MEDIA_ENGINE_ROLE_BROADCASTER_SOLO = 20,
237
     MEDIA_ENGINE_ROLE_BROADCASTER_SOLO = 20,
236
     MEDIA_ENGINE_ROLE_BROADCASTER_INTERACTIVE = 21,
238
     MEDIA_ENGINE_ROLE_BROADCASTER_INTERACTIVE = 21,
258
     VIDEO_CAPTURE_DEVICE = 3,
260
     VIDEO_CAPTURE_DEVICE = 3,
259
 };
261
 };
260
 
262
 
263
+enum AUDIO_RECORDING_QUALITY_TYPE
264
+{
265
+    AUDIO_RECORDING_QUALITY_LOW = 0,
266
+    AUDIO_RECORDING_QUALITY_MEDIUM = 1,
267
+    AUDIO_RECORDING_QUALITY_HIGH = 2,
268
+};
269
+
261
 enum QUALITY_TYPE
270
 enum QUALITY_TYPE
262
 {
271
 {
263
     QUALITY_UNKNOWN = 0,
272
     QUALITY_UNKNOWN = 0,
276
     RENDER_MODE_ADAPTIVE = 3,
285
     RENDER_MODE_ADAPTIVE = 3,
277
 };
286
 };
278
 
287
 
288
+enum VIDEO_MIRROR_MODE_TYPE
289
+{
290
+    VIDEO_MIRROR_MODE_AUTO = 0,//determined by SDK
291
+    VIDEO_MIRROR_MODE_ENABLED = 1,//enabled mirror
292
+    VIDEO_MIRROR_MODE_DISABLED = 2,//disable mirror
293
+};
294
+
279
 enum VIDEO_PROFILE_TYPE
295
 enum VIDEO_PROFILE_TYPE
280
 {                                   // res       fps  kbps
296
 {                                   // res       fps  kbps
281
     VIDEO_PROFILE_120P = 0,         // 160x120   15   65
297
     VIDEO_PROFILE_120P = 0,         // 160x120   15   65
435
     {}
451
     {}
436
 };
452
 };
437
 
453
 
454
+typedef struct Rect {
455
+    int top;
456
+    int left;
457
+    int bottom;
458
+    int right;
459
+
460
+    Rect(): top(0), left(0), bottom(0), right(0) {}
461
+    Rect(int t, int l, int b, int r): top(t), left(l), bottom(b), right(r) {}
462
+} Rect;
463
+
438
 #if defined(_WIN32)
464
 #if defined(_WIN32)
439
 
465
 
440
 enum RTMP_STREAM_LIFE_CYCLE_TYPE
466
 enum RTMP_STREAM_LIFE_CYCLE_TYPE
451
 	int defaultLayout;
477
 	int defaultLayout;
452
 	int lifecycle;
478
 	int lifecycle;
453
 	bool owner;
479
 	bool owner;
480
+	int injectStreamWidth;
481
+	int injectStreamHeight;
482
+	const char* injectStreamUrl;
454
 	const char* publishUrl;
483
 	const char* publishUrl;
455
 	const char* rawStreamUrl;
484
 	const char* rawStreamUrl;
456
 	const char* extraInfo;
485
 	const char* extraInfo;
457
 
486
 
487
+
458
 	PublisherConfiguration()
488
 	PublisherConfiguration()
459
 		: width(640)
489
 		: width(640)
460
 		, height(360)
490
 		, height(360)
463
 		, defaultLayout(1)
493
 		, defaultLayout(1)
464
 		, lifecycle(RTMP_STREAM_LIFE_CYCLE_BIND2CHANNEL)
494
 		, lifecycle(RTMP_STREAM_LIFE_CYCLE_BIND2CHANNEL)
465
 		, owner(true)
495
 		, owner(true)
496
+		, injectStreamWidth(0)
497
+		, injectStreamHeight(0)
498
+		, injectStreamUrl(NULL)
466
 		, publishUrl(NULL)
499
 		, publishUrl(NULL)
467
 		, rawStreamUrl(NULL)
500
 		, rawStreamUrl(NULL)
468
 		, extraInfo(NULL)
501
 		, extraInfo(NULL)
673
     virtual void onAudioMixingFinished() {
706
     virtual void onAudioMixingFinished() {
674
     }
707
     }
675
 
708
 
709
+    /**
710
+    * When audio effect playback finished, this function will be called
711
+    */
712
+    virtual void onAudioEffectFinished(int soundId) {
713
+    }
714
+
676
     /**
715
     /**
677
     * when the video device state changed(plugged or removed), the function will be called
716
     * when the video device state changed(plugged or removed), the function will be called
678
     * @param [in] deviceId
717
     * @param [in] deviceId
957
         (void)uid;
996
         (void)uid;
958
         (void)elapsed;
997
         (void)elapsed;
959
     }
998
     }
960
-
999
+    /** @param [in] uid
1000
+    *        the speaker uid who is talking in the channel
1001
+    */
1002
+    virtual void onActiveSpeaker(uid_t uid) {
1003
+        (void)uid;
1004
+    }
961
 };
1005
 };
962
 
1006
 
963
 /**
1007
 /**
1566
 class AAudioDeviceManager : public agora::util::AutoPtr<IAudioDeviceManager>
1610
 class AAudioDeviceManager : public agora::util::AutoPtr<IAudioDeviceManager>
1567
 {
1611
 {
1568
 public:
1612
 public:
1569
-    AAudioDeviceManager(IRtcEngine& engine)
1613
+    AAudioDeviceManager(IRtcEngine* engine)
1570
     {
1614
     {
1571
 		queryInterface(engine, AGORA_IID_AUDIO_DEVICE_MANAGER);
1615
 		queryInterface(engine, AGORA_IID_AUDIO_DEVICE_MANAGER);
1572
     }
1616
     }
1575
 class AVideoDeviceManager : public agora::util::AutoPtr<IVideoDeviceManager>
1619
 class AVideoDeviceManager : public agora::util::AutoPtr<IVideoDeviceManager>
1576
 {
1620
 {
1577
 public:
1621
 public:
1578
-    AVideoDeviceManager(IRtcEngine& engine)
1622
+    AVideoDeviceManager(IRtcEngine* engine)
1579
     {
1623
     {
1580
 		queryInterface(engine, AGORA_IID_VIDEO_DEVICE_MANAGER);
1624
 		queryInterface(engine, AGORA_IID_VIDEO_DEVICE_MANAGER);
1581
     }
1625
     }
1584
 class AParameter : public agora::util::AutoPtr<IRtcEngineParameter>
1628
 class AParameter : public agora::util::AutoPtr<IRtcEngineParameter>
1585
 {
1629
 {
1586
 public:
1630
 public:
1587
-    AParameter(IRtcEngine& engine)
1631
+    AParameter(IRtcEngine& engine) { initialize(&engine); }
1632
+    AParameter(IRtcEngine* engine) { initialize(engine); }
1633
+    AParameter(IRtcEngineParameter* p) :agora::util::AutoPtr<IRtcEngineParameter>(p) {}
1634
+private:
1635
+    bool initialize(IRtcEngine* engine)
1588
     {
1636
     {
1589
-        IRtcEngineParameter* p;
1590
-        if (!engine.queryInterface(AGORA_IID_RTC_ENGINE_PARAMETER, (void**)&p))
1637
+        IRtcEngineParameter* p = NULL;
1638
+        if (engine && !engine->queryInterface(AGORA_IID_RTC_ENGINE_PARAMETER, (void**)&p))
1591
             reset(p);
1639
             reset(p);
1640
+        return p != NULL;
1592
     }
1641
     }
1593
-    AParameter(IRtcEngineParameter* p)
1594
-        :agora::util::AutoPtr<IRtcEngineParameter>(p)
1595
-    {}
1596
 };
1642
 };
1597
 
1643
 
1598
 class RtcEngineParameters
1644
 class RtcEngineParameters
1599
 {
1645
 {
1600
 public:
1646
 public:
1601
     RtcEngineParameters(IRtcEngine& engine)
1647
     RtcEngineParameters(IRtcEngine& engine)
1648
+        :m_parameter(&engine){}
1649
+    RtcEngineParameters(IRtcEngine* engine)
1602
         :m_parameter(engine){}
1650
         :m_parameter(engine){}
1603
 
1651
 
1604
     /**
1652
     /**
1710
     *        the .wav file path you want to saved
1758
     *        the .wav file path you want to saved
1711
     * @return return 0 if success or an error code
1759
     * @return return 0 if success or an error code
1712
     */
1760
     */
1713
-    int startAudioRecording(const char* filePath) {
1761
+    int startAudioRecording(const char* filePath, AUDIO_RECORDING_QUALITY_TYPE quality) {
1714
         if (!m_parameter) return -ERR_NOT_INITIALIZED;
1762
         if (!m_parameter) return -ERR_NOT_INITIALIZED;
1715
 #if defined(_WIN32)
1763
 #if defined(_WIN32)
1716
-		util::AString path;
1717
-		if (!m_parameter->convertPath(filePath, path))
1718
-			filePath = path->c_str();
1719
-		else
1720
-			return -ERR_INVALID_ARGUMENT;
1764
+        util::AString path;
1765
+        if (!m_parameter->convertPath(filePath, path))
1766
+            filePath = path->c_str();
1767
+        else
1768
+            return -ERR_INVALID_ARGUMENT;
1721
 #endif
1769
 #endif
1722
-		return m_parameter->setString("che.audio.start_recording", filePath);
1770
+        return setObject("che.audio.start_recording", "{\"filePath\":\"%s\",\"quality\":%d}", filePath, quality);
1723
     }
1771
     }
1724
 
1772
 
1725
     /**
1773
     /**
1799
         return m_parameter ? m_parameter->setInt("che.audio.mixing.file.position", pos) : -ERR_NOT_INITIALIZED;
1847
         return m_parameter ? m_parameter->setInt("che.audio.mixing.file.position", pos) : -ERR_NOT_INITIALIZED;
1800
     }
1848
     }
1801
 #if defined(__APPLE__)
1849
 #if defined(__APPLE__)
1802
-	/**
1803
-	* start screen capture
1804
-	* @return return 0 if success or an error code
1805
-	*/
1806
-	int startScreenCapture(unsigned int windowId) {
1807
-        return m_parameter ? m_parameter->setUInt("che.video.start_screen_capture", windowId) : -ERR_NOT_INITIALIZED;
1808
-	}
1809
-
1810
     /**
1850
     /**
1811
-     * specify window id to capture
1812
-     * @return return 0 if success or an error code
1851
+     * start screen/windows capture
1852
+     *
1853
+     *  @param windowId screen capture, if windowId is 0; windows capture if windowsId isn't 0;
1854
+     *  @param rect     valid when windowId is 0; whole screen if rect is NULL.
1855
+     *
1856
+     *  @return return 0 if success or an error code
1813
      */
1857
      */
1814
-    int setScreenCaptureWindow(unsigned int windowId) {
1815
-        return m_parameter ? m_parameter->setUInt("che.video.set_screen_capture_window", windowId) : -ERR_NOT_INITIALIZED;
1858
+    int startScreenCapture(unsigned int windowId, int captureFreq, const Rect *rect) {
1859
+        if (!rect)
1860
+            return setObject("che.video.start_screen_capture", "{\"id\":%u,\"captureFreq\":%d}", windowId, captureFreq);
1861
+        else
1862
+            return setObject("che.video.start_screen_capture", "{\"id\":%u,\"captureFreq\":%d,\"top\":%d,\"left\":%d,\"bottom\":%d,\"right\":%d}", windowId, captureFreq, rect->top, rect->left, rect->bottom, rect->right);
1816
     }
1863
     }
1864
+
1817
     /**
1865
     /**
1818
      * stop screen capture
1866
      * stop screen capture
1819
      * @return return 0 if success or an error code
1867
      * @return return 0 if success or an error code
1823
     }
1871
     }
1824
 #elif defined(_WIN32)
1872
 #elif defined(_WIN32)
1825
     /**
1873
     /**
1826
-     * start screen capture
1827
-     * @return return 0 if success or an error code
1828
-     */
1829
-    int startScreenCapture(HWND windowId) {
1830
-        return m_parameter ? m_parameter->setUInt("che.video.start_screen_capture", (unsigned int)windowId) : -ERR_NOT_INITIALIZED;
1831
-    }
1832
-    
1833
-    /**
1834
-     * specify window id to capture
1835
-     * @return return 0 if success or an error code
1874
+     * start screen/windows capture
1875
+     *
1876
+     *  @param windowId screen capture, if windowId is 0; windows capture if windowsId isn't 0;
1877
+     *  @param rect     valid when windowId is 0; whole screen if rect is NULL.
1878
+     *
1879
+     *  @return return 0 if success or an error code
1836
      */
1880
      */
1837
-    int setScreenCaptureWindow(HWND windowId) {
1838
-        return m_parameter ? m_parameter->setUInt("che.video.set_screen_capture_window", (unsigned int)windowId) : -ERR_NOT_INITIALIZED;
1881
+    int startScreenCapture(HWND windowId, int captureFreq, const Rect *rect) {
1882
+        if (!rect)
1883
+            return setObject("che.video.start_screen_capture", "{\"id\":%u,\"captureFreq\":%d}", (unsigned int)windowId, captureFreq);
1884
+        else
1885
+            return setObject("che.video.start_screen_capture", "{\"id\":%u,\"captureFreq\":%d,\"top\":%d,\"left\":%d,\"bottom\":%d,\"right\":%d}", (unsigned int)windowId, captureFreq, rect->top, rect->left, rect->bottom, rect->right);
1839
     }
1886
     }
1887
+
1840
     /**
1888
     /**
1841
      * stop screen capture
1889
      * stop screen capture
1842
      * @return return 0 if success or an error code
1890
      * @return return 0 if success or an error code
1894
         return setObject("che.video.render_mode", "{\"uid\":%u,\"mode\":%d}", uid, renderMode);
1942
         return setObject("che.video.render_mode", "{\"uid\":%u,\"mode\":%d}", uid, renderMode);
1895
     }
1943
     }
1896
     
1944
     
1945
+    int setLocalVideoMirrorMode(VIDEO_MIRROR_MODE_TYPE mirrorMode) {
1946
+        if (!m_parameter) return -ERR_NOT_INITIALIZED;
1947
+        const char *value;
1948
+        switch (mirrorMode) {
1949
+        case VIDEO_MIRROR_MODE_AUTO:
1950
+            value = "default";
1951
+            break;
1952
+        case VIDEO_MIRROR_MODE_ENABLED:
1953
+            value = "forceMirror";
1954
+            break;
1955
+        case VIDEO_MIRROR_MODE_DISABLED:
1956
+            value = "disableMirror";
1957
+            break;
1958
+        default:
1959
+            return -ERR_INVALID_ARGUMENT;
1960
+        }
1961
+        return m_parameter->setString("che.video.localViewMirrorSetting", value);
1962
+    }
1897
 	int startRecordingService(const char* recordingKey) {
1963
 	int startRecordingService(const char* recordingKey) {
1898
         return m_parameter ? m_parameter->setString("rtc.api.start_recording_service", recordingKey) : -ERR_NOT_INITIALIZED;
1964
         return m_parameter ? m_parameter->setString("rtc.api.start_recording_service", recordingKey) : -ERR_NOT_INITIALIZED;
1899
     }
1965
     }
1942
     }
2008
     }
1943
     //only for live broadcasting
2009
     //only for live broadcasting
1944
     int setVideoQualityParameters(bool preferFrameRateOverImageQuality) {
2010
     int setVideoQualityParameters(bool preferFrameRateOverImageQuality) {
1945
-        return m_parameter ? m_parameter->setBool("rtc.video.prefer_frame_rate", preferFrameRateOverImageQuality) : -ERR_NOT_INITIALIZED;
2011
+        return setParameters("{\"rtc.video.prefer_frame_rate\":%s,\"che.video.prefer_frame_rate\":%s}", preferFrameRateOverImageQuality ? "true" : "false", preferFrameRateOverImageQuality ? "true" : "false");
1946
     }
2012
     }
1947
 protected:
2013
 protected:
1948
     AParameter& parameter() {
2014
     AParameter& parameter() {

BIN
android/src/main/jniLibs/x86/libagora-rtc-sdk-jni.so View File


+ 59
- 4
ios/RCTAgora/RCTAgora.m View File

59
     //启用双流模式
59
     //启用双流模式
60
     [self.rtcEngine enableDualStreamMode:YES];
60
     [self.rtcEngine enableDualStreamMode:YES];
61
     [self.rtcEngine enableVideo];
61
     [self.rtcEngine enableVideo];
62
-    [self.rtcEngine setVideoProfile:[options[@"videoProfile"] integerValue]swapWidthAndHeight:YES];
62
+    [self.rtcEngine setVideoProfile:[options[@"videoProfile"] integerValue]swapWidthAndHeight:[options[@"swapWidthAndHeight"]boolValue]];
63
     [self.rtcEngine setClientRole:[options[@"clientRole"] integerValue] withKey:nil];
63
     [self.rtcEngine setClientRole:[options[@"clientRole"] integerValue] withKey:nil];
64
     
64
     
65
-    //开启预览
66
-    [self.rtcEngine startPreview];
67
-    
68
     //Agora Native SDK 与 Agora Web SDK 间的互通
65
     //Agora Native SDK 与 Agora Web SDK 间的互通
69
     [self.rtcEngine enableWebSdkInteroperability:YES];
66
     [self.rtcEngine enableWebSdkInteroperability:YES];
70
     
67
     
113
 //开启视频预览
110
 //开启视频预览
114
 RCT_EXPORT_METHOD(startPreview){
111
 RCT_EXPORT_METHOD(startPreview){
115
     [self.rtcEngine startPreview];
112
     [self.rtcEngine startPreview];
113
+}
114
+
115
+//配置旁路直播推流(configPublisher)
116
+//请确保用户已经调用 setClientRole() 且已将用户角色设为主播
117
+//主播必须在加入频道前调用本章 API
118
+RCT_EXPORT_METHOD(configPublisher:(NSDictionary *)config){
119
+    AgoraPublisherConfiguration *apc = [AgoraPublisherConfiguration new];
116
     
120
     
121
+    apc.width = [config[@"width"] integerValue];  //旁路直播的输出码流的宽度
122
+    apc.height = [config[@"height"] integerValue]; //旁路直播的输出码流的高度
123
+    apc.framerate = [config[@"framerate"] integerValue]; //旁路直播的输出码率帧率
124
+    apc.bitrate = [config[@"bitrate"] integerValue]; //旁路直播输出码流的码率
125
+    apc.defaultLayout = [config[@"defaultLayout"] integerValue]; //设置流生命周期
126
+    apc.lifeCycle = [config[@"lifeCycle"] integerValue]; //默认合图布局
127
+    apc.publishUrl = config[@"publishUrl"]; //合图推流地址
128
+    apc.rawStreamUrl = config[@"rawStreamUrl"]; //单流地址
129
+    apc.extraInfo = config[@"extraInfo"]; //其他信息
130
+    apc.owner = [config[@"owner"] boolValue]; //是否将当前主播设为该 RTMP 流的主人
131
+  
132
+    [self.rtcEngine configPublisher:apc];
133
+}
134
+
135
+//设置本地视频显示模式
136
+RCT_EXPORT_METHOD(setLocalRenderMode:(NSUInteger)mode){
137
+    [self.rtcEngine setLocalRenderMode:mode];
117
 }
138
 }
118
 
139
 
140
+//设置远端视频显示模式
141
+RCT_EXPORT_METHOD(setRemoteRenderMode:(NSUInteger)uid mode:(NSUInteger)mode){
142
+    [self.rtcEngine setRemoteRenderMode:uid mode:mode];
143
+}
144
+
145
+//启用说话者音量提示
146
+RCT_EXPORT_METHOD(enableAudioVolumeIndication:(NSUInteger)interval smooth:(NSUInteger)smooth){
147
+    [self.rtcEngine enableAudioVolumeIndication:interval smooth:smooth];
148
+}
149
+
150
+//开启屏幕共享
151
+//RCT_EXPORT_METHOD(startScreenCapture:(NSUInteger)windowId){
152
+//
153
+//}
154
+
119
 //关闭视频预览
155
 //关闭视频预览
120
 RCT_EXPORT_METHOD(stopPreview){
156
 RCT_EXPORT_METHOD(stopPreview){
121
     [self.rtcEngine stopPreview];
157
     [self.rtcEngine stopPreview];
265
     [self sendEvent:params];
301
     [self sendEvent:params];
266
 }
302
 }
267
 
303
 
304
+/*
305
+ 音量提示回调
306
+ 需要开启enableAudioVolumeIndication
307
+ */
308
+- (void)rtcEngine:(AgoraRtcEngineKit *)engine reportAudioVolumeIndicationOfSpeakers:(NSArray*)speakers totalVolume:(NSInteger)totalVolume {
309
+    NSMutableDictionary *params = @{}.mutableCopy;
310
+    params[@"type"] = @"onAudioVolumeIndication";
311
+    
312
+    NSMutableArray *arr = [NSMutableArray array];
313
+    for (AgoraRtcAudioVolumeInfo *obj in speakers) {
314
+        [arr addObject:@{@"uid":[NSNumber numberWithInteger:obj.uid], @"volume":[NSNumber numberWithInteger:obj.volume]}];
315
+    }
316
+    
317
+    params[@"speakers"] = arr;
318
+    params[@"totalVolume"] = [NSNumber numberWithInteger:totalVolume];
319
+    
320
+    [self sendEvent:params];
321
+}
322
+
268
 - (void)sendEvent:(NSDictionary *)params {
323
 - (void)sendEvent:(NSDictionary *)params {
269
     [_bridge.eventDispatcher sendDeviceEventWithName:@"agoraEvent" body:params];
324
     [_bridge.eventDispatcher sendDeviceEventWithName:@"agoraEvent" body:params];
270
 }
325
 }

BIN
ios/RCTAgora/libs/AgoraRtcCryptoLoader.framework/AgoraRtcCryptoLoader View File


BIN
ios/RCTAgora/libs/AgoraRtcEngineKit.framework/AgoraRtcEngineKit View File


+ 54
- 29
ios/RCTAgora/libs/AgoraRtcEngineKit.framework/Headers/AgoraRtcEngineKit.h View File

39
     AgoraRtc_Warn_Adm_PlaybackMalfunction = 1020,
39
     AgoraRtc_Warn_Adm_PlaybackMalfunction = 1020,
40
     AgoraRtc_Warn_Adm_RecordMalfunction = 1021,
40
     AgoraRtc_Warn_Adm_RecordMalfunction = 1021,
41
     AgoraRtc_Warn_Adm_Interruption = 1025,
41
     AgoraRtc_Warn_Adm_Interruption = 1025,
42
-    AgoraRtc_Warn_Adm_RouteChange = 1026,
43
     AgoraRtc_Warn_Apm_Howling = 1051,
42
     AgoraRtc_Warn_Apm_Howling = 1051,
44
 };
43
 };
45
 
44
 
188
     AgoraRtc_VideoStream_Low = 1,
187
     AgoraRtc_VideoStream_Low = 1,
189
 };
188
 };
190
 
189
 
191
-typedef NS_ENUM(NSInteger, AudioOutputRouting)
190
+typedef NS_ENUM(NSInteger, AgoraRtcAudioOutputRouting)
192
 {
191
 {
193
-    AudioOutputRouting_Default = -1,
194
-    AudioOutputRouting_Headset = 0,
195
-    AudioOutputRouting_Earpiece = 1,
196
-    AudioOutputRouting_HeadsetNoMic = 2,
197
-    AudioOutputRouting_Speakerphone = 3,
198
-    AudioOutputRouting_Loudspeaker = 4,
199
-    AudioOutputRouting_HeadsetBluetooth = 5
192
+    AgoraRtc_AudioOutputRouting_Default = -1,
193
+    AgoraRtc_AudioOutputRouting_Headset = 0,
194
+    AgoraRtc_AudioOutputRouting_Earpiece = 1,
195
+    AgoraRtc_AudioOutputRouting_HeadsetNoMic = 2,
196
+    AgoraRtc_AudioOutputRouting_Speakerphone = 3,
197
+    AgoraRtc_AudioOutputRouting_Loudspeaker = 4,
198
+    AgoraRtc_AudioOutputRouting_HeadsetBluetooth = 5
199
+};
200
+
201
+typedef NS_ENUM(NSInteger, AgoraRtcAudioRecordingQuality) {
202
+    AgoraRtc_AudioRecordingQuality_Low = 0,
203
+    AgoraRtc_AudioRecordingQuality_Medium = 1,
204
+    AgoraRtc_AudioRecordingQuality_High = 2
200
 };
205
 };
201
 
206
 
202
 typedef NS_ENUM(NSUInteger, AgoraRtcLogFilter) {
207
 typedef NS_ENUM(NSUInteger, AgoraRtcLogFilter) {
372
 @property (assign, nonatomic) NSInteger bitrate;
377
 @property (assign, nonatomic) NSInteger bitrate;
373
 @property (assign, nonatomic) NSInteger defaultLayout;
378
 @property (assign, nonatomic) NSInteger defaultLayout;
374
 @property (assign, nonatomic) AgoraRtmpStreamLifeCycle lifeCycle;
379
 @property (assign, nonatomic) AgoraRtmpStreamLifeCycle lifeCycle;
380
+@property (assign, nonatomic) NSInteger injectStreamWidth;
381
+@property (assign, nonatomic) NSInteger injectStreamHeight;
382
+@property (copy, nonatomic) NSString* injectStreamUrl;
375
 @property (copy, nonatomic) NSString* publishUrl;
383
 @property (copy, nonatomic) NSString* publishUrl;
376
 @property (copy, nonatomic) NSString* rawStreamUrl;
384
 @property (copy, nonatomic) NSString* rawStreamUrl;
377
 @property (copy, nonatomic) NSString* extraInfo;
385
 @property (copy, nonatomic) NSString* extraInfo;
387
 - (AgoraPublisherConfigurationBuilder *) setPublisherUrl:(NSString*)url;
395
 - (AgoraPublisherConfigurationBuilder *) setPublisherUrl:(NSString*)url;
388
 - (AgoraPublisherConfigurationBuilder *) setRawStreamUrl:(NSString*)url;
396
 - (AgoraPublisherConfigurationBuilder *) setRawStreamUrl:(NSString*)url;
389
 - (AgoraPublisherConfigurationBuilder *) setExtraInfo:(NSString *)info;
397
 - (AgoraPublisherConfigurationBuilder *) setExtraInfo:(NSString *)info;
398
+- (AgoraPublisherConfigurationBuilder *) injectStream:(NSString *)url width:(NSInteger)width height:(NSInteger)height;
390
 - (AgoraPublisherConfiguration *) build;
399
 - (AgoraPublisherConfiguration *) build;
391
 @end
400
 @end
392
 
401
 
500
  *  @param engine The engine kit
509
  *  @param engine The engine kit
501
  *  @param routing the current audio output routing
510
  *  @param routing the current audio output routing
502
  */
511
  */
503
-- (void)rtcEngine:(AgoraRtcEngineKit *)engine didAudioRouteChanged:(AudioOutputRouting)routing;
512
+- (void)rtcEngine:(AgoraRtcEngineKit *)engine didAudioRouteChanged:(AgoraRtcAudioOutputRouting)routing;
504
 
513
 
505
 
514
 
506
 /**
515
 /**
549
  */
558
  */
550
 - (void)rtcEngineMediaEngineDidAudioMixingFinish:(AgoraRtcEngineKit *)engine;
559
 - (void)rtcEngineMediaEngineDidAudioMixingFinish:(AgoraRtcEngineKit *)engine;
551
 
560
 
561
+/**
562
+ *  Event of meida engine finish audio mixing.
563
+ *
564
+ *  @param engine The engine kit
565
+ */
566
+- (void)rtcEngineMediaEngineDidAudioEffectFinish:(AgoraRtcEngineKit *)engine soundId:(NSInteger)soundId;
567
+
552
 /**
568
 /**
553
  *  Event of camera opened
569
  *  Event of camera opened
554
  *
570
  *
723
  */
739
  */
724
 - (void)rtcEngine:(AgoraRtcEngineKit *)engine firstRemoteAudioFrameOfUid:(NSUInteger)uid elapsed:(NSInteger)elapsed;
740
 - (void)rtcEngine:(AgoraRtcEngineKit *)engine firstRemoteAudioFrameOfUid:(NSUInteger)uid elapsed:(NSInteger)elapsed;
725
 
741
 
742
+
743
+/**
744
+ *  The sdk reports who is active speaker in the channel
745
+ *
746
+ *  @param engine      The engine kit
747
+ *  @param speakerUid  The speaker who is talking
748
+ */
749
+- (void)rtcEngine:(AgoraRtcEngineKit *)engine activeSpeaker:(NSUInteger)speakerUid;
726
 @end
750
 @end
727
 
751
 
728
 
752
 
1004
  *  Start recording conversation to file specified by the file path.
1028
  *  Start recording conversation to file specified by the file path.
1005
  *
1029
  *
1006
  *  @param filePath file path to save recorded conversation.
1030
  *  @param filePath file path to save recorded conversation.
1031
+ *  @param quality  encode quality for the record file
1007
  *
1032
  *
1008
  *  @return 0 when executed successfully. return negative value if failed.
1033
  *  @return 0 when executed successfully. return negative value if failed.
1009
  */
1034
  */
1010
-- (int)startAudioRecording:(NSString*)filePath;
1035
+- (int)startAudioRecording:(NSString*)filePath
1036
+                   quality:(AgoraRtcAudioRecordingQuality)quality;
1011
 
1037
 
1012
 
1038
 
1013
 /**
1039
 /**
1029
 - (int)getAudioMixingCurrentPosition;
1055
 - (int)getAudioMixingCurrentPosition;
1030
 - (int)setAudioMixingPosition:(NSInteger) pos;
1056
 - (int)setAudioMixingPosition:(NSInteger) pos;
1031
 
1057
 
1032
-/**
1033
- *  Start screen capture
1034
- *
1035
- *  @return 0 when executed successfully. return negative value if failed.
1036
- */
1037
-- (int)startScreenCapture:(NSUInteger)windowId;
1038
-
1039
-
1040
-/**
1041
- *  Stop screen capture
1042
- *
1043
- *  @return 0 when executed successfully. return negative value if failed.
1044
- */
1045
-- (int)stopScreenCapture;
1046
 
1058
 
1047
 
1059
 
1048
-- (int)setScreenCaptureId:(NSUInteger)windowId;
1060
+//- (int)setScreenCaptureId:(NSUInteger)windowId;
1049
 
1061
 
1050
 
1062
 
1051
 /**
1063
 /**
1322
 - (int)clearVideoCompositingLayout;
1334
 - (int)clearVideoCompositingLayout;
1323
 
1335
 
1324
 #if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC))
1336
 #if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC))
1337
+/**
1338
+ *  Start screen capture
1339
+ *
1340
+ *  @return 0 when executed successfully. return negative value if failed.
1341
+ */
1342
+- (int)startScreenCapture:(NSUInteger)windowId withCaptureFreq: (int) captureFreq AndRect :(CGRect)rect;
1343
+
1344
+
1345
+/**
1346
+ *  Stop screen capture
1347
+ *
1348
+ *  @return 0 when executed successfully. return negative value if failed.
1349
+ */
1350
+- (int)stopScreenCapture;
1325
 
1351
 
1326
 - (void) monitorDeviceChange: (BOOL)enabled;
1352
 - (void) monitorDeviceChange: (BOOL)enabled;
1327
 - (NSArray*) enumerateDevices:(AgoraRtcDeviceType)type;  // return array of AgoraRtcDeviceInfo
1353
 - (NSArray*) enumerateDevices:(AgoraRtcDeviceType)type;  // return array of AgoraRtcDeviceInfo
1340
 - (int) stopCaptureDeviceTest;
1366
 - (int) stopCaptureDeviceTest;
1341
 #endif
1367
 #endif
1342
 
1368
 
1343
-- (int) checkAVUrlCompatibility:(NSURL*)url
1344
-                 completionBlock:(void(^)())checkCompletionBlock;
1345
-
1346
 //Audio Effects
1369
 //Audio Effects
1347
 - (double) getEffectsVolume;
1370
 - (double) getEffectsVolume;
1348
 - (int) setEffectsVolume:(double) volume;
1371
 - (int) setEffectsVolume:(double) volume;
1372
+- (int) setVolumeOfEffect:(int) soundId
1373
+               withVolume:(double) volume;
1349
 - (int) playEffect:(int) soundId
1374
 - (int) playEffect:(int) soundId
1350
           filePath:(NSString*)filePath
1375
           filePath:(NSString*)filePath
1351
               loop:(BOOL)loop
1376
               loop:(BOOL)loop

+ 113
- 47
ios/RCTAgora/libs/AgoraRtcEngineKit.framework/Headers/IAgoraRtcEngine.h View File

72
         ptr_ = ptr;
72
         ptr_ = ptr;
73
     }
73
     }
74
     template<class C1, class C2>
74
     template<class C1, class C2>
75
-    void queryInterface(C1& c, C2 iid) {
76
-		pointer_type p;
77
-        if (!c.queryInterface(iid, (void**)&p))
78
-			reset(p);
75
+    bool queryInterface(C1* c, C2 iid) {
76
+        pointer_type p = NULL;
77
+        if (c && !c->queryInterface(iid, (void**)&p))
78
+        {
79
+            reset(p);
80
+        }
81
+        return p != NULL;;
79
 	}
82
 	}
80
 private:
83
 private:
81
     AutoPtr(const AutoPtr&);
84
     AutoPtr(const AutoPtr&);
129
     // sdk: 100~1000
132
     // sdk: 100~1000
130
     WARN_SWITCH_LIVE_VIDEO_TIMEOUT = 111,
133
     WARN_SWITCH_LIVE_VIDEO_TIMEOUT = 111,
131
 	WARN_SET_CLIENT_ROLE_TIMEOUT = 118,
134
 	WARN_SET_CLIENT_ROLE_TIMEOUT = 118,
132
-    WARN_SET_CLIENT_ROLE_NOT_AUTHORIZED = 119,
133
 };
135
 };
134
 
136
 
135
 enum ERROR_CODE_TYPE
137
 enum ERROR_CODE_TYPE
168
 	ERR_BITRATE_LIMIT = 115,
170
 	ERR_BITRATE_LIMIT = 115,
169
 	ERR_TOO_MANY_DATA_STREAMS = 116,
171
 	ERR_TOO_MANY_DATA_STREAMS = 116,
170
 	ERR_STREAM_MESSAGE_TIMEOUT = 117,
172
 	ERR_STREAM_MESSAGE_TIMEOUT = 117,
173
+    ERR_SET_CLIENT_ROLE_NOT_AUTHORIZED = 119,
171
 
174
 
172
     //1001~2000
175
     //1001~2000
173
     ERR_LOAD_MEDIA_ENGINE = 1001,
176
     ERR_LOAD_MEDIA_ENGINE = 1001,
230
     MEDIA_ENGINE_RECORDING_WARNING = 2,
233
     MEDIA_ENGINE_RECORDING_WARNING = 2,
231
     MEDIA_ENGINE_PLAYOUT_WARNING = 3,
234
     MEDIA_ENGINE_PLAYOUT_WARNING = 3,
232
     MEDIA_ENGINE_AUDIO_FILE_MIX_FINISH = 10,
235
     MEDIA_ENGINE_AUDIO_FILE_MIX_FINISH = 10,
233
-    MEDIA_ENGINE_AUDIO_SAMPLE_RATE_RECONFIG_FINISH = 11,
234
     // media engine role changed
236
     // media engine role changed
235
     MEDIA_ENGINE_ROLE_BROADCASTER_SOLO = 20,
237
     MEDIA_ENGINE_ROLE_BROADCASTER_SOLO = 20,
236
     MEDIA_ENGINE_ROLE_BROADCASTER_INTERACTIVE = 21,
238
     MEDIA_ENGINE_ROLE_BROADCASTER_INTERACTIVE = 21,
258
     VIDEO_CAPTURE_DEVICE = 3,
260
     VIDEO_CAPTURE_DEVICE = 3,
259
 };
261
 };
260
 
262
 
263
+enum AUDIO_RECORDING_QUALITY_TYPE
264
+{
265
+    AUDIO_RECORDING_QUALITY_LOW = 0,
266
+    AUDIO_RECORDING_QUALITY_MEDIUM = 1,
267
+    AUDIO_RECORDING_QUALITY_HIGH = 2,
268
+};
269
+
261
 enum QUALITY_TYPE
270
 enum QUALITY_TYPE
262
 {
271
 {
263
     QUALITY_UNKNOWN = 0,
272
     QUALITY_UNKNOWN = 0,
276
     RENDER_MODE_ADAPTIVE = 3,
285
     RENDER_MODE_ADAPTIVE = 3,
277
 };
286
 };
278
 
287
 
288
+enum VIDEO_MIRROR_MODE_TYPE
289
+{
290
+    VIDEO_MIRROR_MODE_AUTO = 0,//determined by SDK
291
+    VIDEO_MIRROR_MODE_ENABLED = 1,//enabled mirror
292
+    VIDEO_MIRROR_MODE_DISABLED = 2,//disable mirror
293
+};
294
+
279
 enum VIDEO_PROFILE_TYPE
295
 enum VIDEO_PROFILE_TYPE
280
 {                                   // res       fps  kbps
296
 {                                   // res       fps  kbps
281
     VIDEO_PROFILE_120P = 0,         // 160x120   15   65
297
     VIDEO_PROFILE_120P = 0,         // 160x120   15   65
435
     {}
451
     {}
436
 };
452
 };
437
 
453
 
454
+typedef struct Rect {
455
+    int top;
456
+    int left;
457
+    int bottom;
458
+    int right;
459
+
460
+    Rect(): top(0), left(0), bottom(0), right(0) {}
461
+    Rect(int t, int l, int b, int r): top(t), left(l), bottom(b), right(r) {}
462
+} Rect;
463
+
438
 #if defined(_WIN32)
464
 #if defined(_WIN32)
439
 
465
 
440
 enum RTMP_STREAM_LIFE_CYCLE_TYPE
466
 enum RTMP_STREAM_LIFE_CYCLE_TYPE
451
 	int defaultLayout;
477
 	int defaultLayout;
452
 	int lifecycle;
478
 	int lifecycle;
453
 	bool owner;
479
 	bool owner;
480
+	int injectStreamWidth;
481
+	int injectStreamHeight;
482
+	const char* injectStreamUrl;
454
 	const char* publishUrl;
483
 	const char* publishUrl;
455
 	const char* rawStreamUrl;
484
 	const char* rawStreamUrl;
456
 	const char* extraInfo;
485
 	const char* extraInfo;
457
 
486
 
487
+
458
 	PublisherConfiguration()
488
 	PublisherConfiguration()
459
 		: width(640)
489
 		: width(640)
460
 		, height(360)
490
 		, height(360)
463
 		, defaultLayout(1)
493
 		, defaultLayout(1)
464
 		, lifecycle(RTMP_STREAM_LIFE_CYCLE_BIND2CHANNEL)
494
 		, lifecycle(RTMP_STREAM_LIFE_CYCLE_BIND2CHANNEL)
465
 		, owner(true)
495
 		, owner(true)
496
+		, injectStreamWidth(0)
497
+		, injectStreamHeight(0)
498
+		, injectStreamUrl(NULL)
466
 		, publishUrl(NULL)
499
 		, publishUrl(NULL)
467
 		, rawStreamUrl(NULL)
500
 		, rawStreamUrl(NULL)
468
 		, extraInfo(NULL)
501
 		, extraInfo(NULL)
673
     virtual void onAudioMixingFinished() {
706
     virtual void onAudioMixingFinished() {
674
     }
707
     }
675
 
708
 
709
+    /**
710
+    * When audio effect playback finished, this function will be called
711
+    */
712
+    virtual void onAudioEffectFinished(int soundId) {
713
+    }
714
+
676
     /**
715
     /**
677
     * when the video device state changed(plugged or removed), the function will be called
716
     * when the video device state changed(plugged or removed), the function will be called
678
     * @param [in] deviceId
717
     * @param [in] deviceId
957
         (void)uid;
996
         (void)uid;
958
         (void)elapsed;
997
         (void)elapsed;
959
     }
998
     }
960
-
999
+    /** @param [in] uid
1000
+    *        the speaker uid who is talking in the channel
1001
+    */
1002
+    virtual void onActiveSpeaker(uid_t uid) {
1003
+        (void)uid;
1004
+    }
961
 };
1005
 };
962
 
1006
 
963
 /**
1007
 /**
1566
 class AAudioDeviceManager : public agora::util::AutoPtr<IAudioDeviceManager>
1610
 class AAudioDeviceManager : public agora::util::AutoPtr<IAudioDeviceManager>
1567
 {
1611
 {
1568
 public:
1612
 public:
1569
-    AAudioDeviceManager(IRtcEngine& engine)
1613
+    AAudioDeviceManager(IRtcEngine* engine)
1570
     {
1614
     {
1571
 		queryInterface(engine, AGORA_IID_AUDIO_DEVICE_MANAGER);
1615
 		queryInterface(engine, AGORA_IID_AUDIO_DEVICE_MANAGER);
1572
     }
1616
     }
1575
 class AVideoDeviceManager : public agora::util::AutoPtr<IVideoDeviceManager>
1619
 class AVideoDeviceManager : public agora::util::AutoPtr<IVideoDeviceManager>
1576
 {
1620
 {
1577
 public:
1621
 public:
1578
-    AVideoDeviceManager(IRtcEngine& engine)
1622
+    AVideoDeviceManager(IRtcEngine* engine)
1579
     {
1623
     {
1580
 		queryInterface(engine, AGORA_IID_VIDEO_DEVICE_MANAGER);
1624
 		queryInterface(engine, AGORA_IID_VIDEO_DEVICE_MANAGER);
1581
     }
1625
     }
1584
 class AParameter : public agora::util::AutoPtr<IRtcEngineParameter>
1628
 class AParameter : public agora::util::AutoPtr<IRtcEngineParameter>
1585
 {
1629
 {
1586
 public:
1630
 public:
1587
-    AParameter(IRtcEngine& engine)
1631
+    AParameter(IRtcEngine& engine) { initialize(&engine); }
1632
+    AParameter(IRtcEngine* engine) { initialize(engine); }
1633
+    AParameter(IRtcEngineParameter* p) :agora::util::AutoPtr<IRtcEngineParameter>(p) {}
1634
+private:
1635
+    bool initialize(IRtcEngine* engine)
1588
     {
1636
     {
1589
-        IRtcEngineParameter* p;
1590
-        if (!engine.queryInterface(AGORA_IID_RTC_ENGINE_PARAMETER, (void**)&p))
1637
+        IRtcEngineParameter* p = NULL;
1638
+        if (engine && !engine->queryInterface(AGORA_IID_RTC_ENGINE_PARAMETER, (void**)&p))
1591
             reset(p);
1639
             reset(p);
1640
+        return p != NULL;
1592
     }
1641
     }
1593
-    AParameter(IRtcEngineParameter* p)
1594
-        :agora::util::AutoPtr<IRtcEngineParameter>(p)
1595
-    {}
1596
 };
1642
 };
1597
 
1643
 
1598
 class RtcEngineParameters
1644
 class RtcEngineParameters
1599
 {
1645
 {
1600
 public:
1646
 public:
1601
     RtcEngineParameters(IRtcEngine& engine)
1647
     RtcEngineParameters(IRtcEngine& engine)
1648
+        :m_parameter(&engine){}
1649
+    RtcEngineParameters(IRtcEngine* engine)
1602
         :m_parameter(engine){}
1650
         :m_parameter(engine){}
1603
 
1651
 
1604
     /**
1652
     /**
1710
     *        the .wav file path you want to saved
1758
     *        the .wav file path you want to saved
1711
     * @return return 0 if success or an error code
1759
     * @return return 0 if success or an error code
1712
     */
1760
     */
1713
-    int startAudioRecording(const char* filePath) {
1761
+    int startAudioRecording(const char* filePath, AUDIO_RECORDING_QUALITY_TYPE quality) {
1714
         if (!m_parameter) return -ERR_NOT_INITIALIZED;
1762
         if (!m_parameter) return -ERR_NOT_INITIALIZED;
1715
 #if defined(_WIN32)
1763
 #if defined(_WIN32)
1716
-		util::AString path;
1717
-		if (!m_parameter->convertPath(filePath, path))
1718
-			filePath = path->c_str();
1719
-		else
1720
-			return -ERR_INVALID_ARGUMENT;
1764
+        util::AString path;
1765
+        if (!m_parameter->convertPath(filePath, path))
1766
+            filePath = path->c_str();
1767
+        else
1768
+            return -ERR_INVALID_ARGUMENT;
1721
 #endif
1769
 #endif
1722
-		return m_parameter->setString("che.audio.start_recording", filePath);
1770
+        return setObject("che.audio.start_recording", "{\"filePath\":\"%s\",\"quality\":%d}", filePath, quality);
1723
     }
1771
     }
1724
 
1772
 
1725
     /**
1773
     /**
1799
         return m_parameter ? m_parameter->setInt("che.audio.mixing.file.position", pos) : -ERR_NOT_INITIALIZED;
1847
         return m_parameter ? m_parameter->setInt("che.audio.mixing.file.position", pos) : -ERR_NOT_INITIALIZED;
1800
     }
1848
     }
1801
 #if defined(__APPLE__)
1849
 #if defined(__APPLE__)
1802
-	/**
1803
-	* start screen capture
1804
-	* @return return 0 if success or an error code
1805
-	*/
1806
-	int startScreenCapture(unsigned int windowId) {
1807
-        return m_parameter ? m_parameter->setUInt("che.video.start_screen_capture", windowId) : -ERR_NOT_INITIALIZED;
1808
-	}
1809
-
1810
     /**
1850
     /**
1811
-     * specify window id to capture
1812
-     * @return return 0 if success or an error code
1851
+     * start screen/windows capture
1852
+     *
1853
+     *  @param windowId screen capture, if windowId is 0; windows capture if windowsId isn't 0;
1854
+     *  @param rect     valid when windowId is 0; whole screen if rect is NULL.
1855
+     *
1856
+     *  @return return 0 if success or an error code
1813
      */
1857
      */
1814
-    int setScreenCaptureWindow(unsigned int windowId) {
1815
-        return m_parameter ? m_parameter->setUInt("che.video.set_screen_capture_window", windowId) : -ERR_NOT_INITIALIZED;
1858
+    int startScreenCapture(unsigned int windowId, int captureFreq, const Rect *rect) {
1859
+        if (!rect)
1860
+            return setObject("che.video.start_screen_capture", "{\"id\":%u,\"captureFreq\":%d}", windowId, captureFreq);
1861
+        else
1862
+            return setObject("che.video.start_screen_capture", "{\"id\":%u,\"captureFreq\":%d,\"top\":%d,\"left\":%d,\"bottom\":%d,\"right\":%d}", windowId, captureFreq, rect->top, rect->left, rect->bottom, rect->right);
1816
     }
1863
     }
1864
+
1817
     /**
1865
     /**
1818
      * stop screen capture
1866
      * stop screen capture
1819
      * @return return 0 if success or an error code
1867
      * @return return 0 if success or an error code
1823
     }
1871
     }
1824
 #elif defined(_WIN32)
1872
 #elif defined(_WIN32)
1825
     /**
1873
     /**
1826
-     * start screen capture
1827
-     * @return return 0 if success or an error code
1828
-     */
1829
-    int startScreenCapture(HWND windowId) {
1830
-        return m_parameter ? m_parameter->setUInt("che.video.start_screen_capture", (unsigned int)windowId) : -ERR_NOT_INITIALIZED;
1831
-    }
1832
-    
1833
-    /**
1834
-     * specify window id to capture
1835
-     * @return return 0 if success or an error code
1874
+     * start screen/windows capture
1875
+     *
1876
+     *  @param windowId screen capture, if windowId is 0; windows capture if windowsId isn't 0;
1877
+     *  @param rect     valid when windowId is 0; whole screen if rect is NULL.
1878
+     *
1879
+     *  @return return 0 if success or an error code
1836
      */
1880
      */
1837
-    int setScreenCaptureWindow(HWND windowId) {
1838
-        return m_parameter ? m_parameter->setUInt("che.video.set_screen_capture_window", (unsigned int)windowId) : -ERR_NOT_INITIALIZED;
1881
+    int startScreenCapture(HWND windowId, int captureFreq, const Rect *rect) {
1882
+        if (!rect)
1883
+            return setObject("che.video.start_screen_capture", "{\"id\":%u,\"captureFreq\":%d}", (unsigned int)windowId, captureFreq);
1884
+        else
1885
+            return setObject("che.video.start_screen_capture", "{\"id\":%u,\"captureFreq\":%d,\"top\":%d,\"left\":%d,\"bottom\":%d,\"right\":%d}", (unsigned int)windowId, captureFreq, rect->top, rect->left, rect->bottom, rect->right);
1839
     }
1886
     }
1887
+
1840
     /**
1888
     /**
1841
      * stop screen capture
1889
      * stop screen capture
1842
      * @return return 0 if success or an error code
1890
      * @return return 0 if success or an error code
1894
         return setObject("che.video.render_mode", "{\"uid\":%u,\"mode\":%d}", uid, renderMode);
1942
         return setObject("che.video.render_mode", "{\"uid\":%u,\"mode\":%d}", uid, renderMode);
1895
     }
1943
     }
1896
     
1944
     
1945
+    int setLocalVideoMirrorMode(VIDEO_MIRROR_MODE_TYPE mirrorMode) {
1946
+        if (!m_parameter) return -ERR_NOT_INITIALIZED;
1947
+        const char *value;
1948
+        switch (mirrorMode) {
1949
+        case VIDEO_MIRROR_MODE_AUTO:
1950
+            value = "default";
1951
+            break;
1952
+        case VIDEO_MIRROR_MODE_ENABLED:
1953
+            value = "forceMirror";
1954
+            break;
1955
+        case VIDEO_MIRROR_MODE_DISABLED:
1956
+            value = "disableMirror";
1957
+            break;
1958
+        default:
1959
+            return -ERR_INVALID_ARGUMENT;
1960
+        }
1961
+        return m_parameter->setString("che.video.localViewMirrorSetting", value);
1962
+    }
1897
 	int startRecordingService(const char* recordingKey) {
1963
 	int startRecordingService(const char* recordingKey) {
1898
         return m_parameter ? m_parameter->setString("rtc.api.start_recording_service", recordingKey) : -ERR_NOT_INITIALIZED;
1964
         return m_parameter ? m_parameter->setString("rtc.api.start_recording_service", recordingKey) : -ERR_NOT_INITIALIZED;
1899
     }
1965
     }
1942
     }
2008
     }
1943
     //only for live broadcasting
2009
     //only for live broadcasting
1944
     int setVideoQualityParameters(bool preferFrameRateOverImageQuality) {
2010
     int setVideoQualityParameters(bool preferFrameRateOverImageQuality) {
1945
-        return m_parameter ? m_parameter->setBool("rtc.video.prefer_frame_rate", preferFrameRateOverImageQuality) : -ERR_NOT_INITIALIZED;
2011
+        return setParameters("{\"rtc.video.prefer_frame_rate\":%s,\"che.video.prefer_frame_rate\":%s}", preferFrameRateOverImageQuality ? "true" : "false", preferFrameRateOverImageQuality ? "true" : "false");
1946
     }
2012
     }
1947
 protected:
2013
 protected:
1948
     AParameter& parameter() {
2014
     AParameter& parameter() {

+ 5
- 2
package.json View File

1
 {
1
 {
2
   "name": "react-native-agora",
2
   "name": "react-native-agora",
3
-  "version": "1.0.7",
3
+  "version": "1.0.8",
4
   "description": "声网Agora",
4
   "description": "声网Agora",
5
   "main": "index.js",
5
   "main": "index.js",
6
   "scripts": {
6
   "scripts": {
13
   "keywords": [
13
   "keywords": [
14
     "agora",
14
     "agora",
15
     "react-native",
15
     "react-native",
16
-    "react-native-agora"
16
+    "react-native-agora",
17
+    "live",
18
+    "react",
19
+    "Agora"
17
   ],
20
   ],
18
   "author": "",
21
   "author": "",
19
   "license": "ISC",
22
   "license": "ISC",