您的位置:首页 > 移动开发 > Android开发

Android IOS WebRTC 音视频开发总结(八)

2015-02-04 14:19 627 查看
本文转载:http://www.cnblogs.com/lingyunhu/p/4066383.html

这篇文章主要介绍ios webrtcdemo的实现及相关注意事项,转载请说明出处(博客园RTC.Blacker)

前面很多人问webrtc android下有webrtcdemo,ios上怎么找不到,放在哪里呢?

答案:webrtcdemo在ios上没有实现,如果要实现也很简单,既然安卓都有了,依葫芦画瓢即可移植到ios上,不过可能要求您熟悉android语法,这里给出ios上的参考代码:

1 -(BOOL)initWebrtcObjects
2 {
     //转载请说明出处: RTC_Blacker http://www.cnblogs.com/lingyunhu 3     if ((voE = webrtc::VoiceEngine::Create()) == NULL) {
4         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
5         return FALSE;
6     }
7     if ((voeBase = webrtc::VoEBase::GetInterface(voE)) == NULL) {
8         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
9         return FALSE;
10     }
11     if ((voeCodec = webrtc::VoECodec::GetInterface(voE)) == NULL) {
12         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
13         return FALSE;
14     }
15     if ((voeFile=webrtc::VoEFile::GetInterface(voE))==NULL) {
16         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
17     }
18     if ((voeHardware = webrtc::VoEHardware::GetInterface(voE)) == NULL) {
19         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
20         return FALSE;
21     }
22     if ((voeNetwork = webrtc::VoENetwork::GetInterface(voE)) == NULL) {
23         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
24         return FALSE;
25     }
26     if ((voeAudioProccessing = webrtc::VoEAudioProcessing::GetInterface(voE)) == NULL) {
27         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
28         return FALSE;
29     }
30     if ((voeRtpRtcp = webrtc::VoERTP_RTCP::GetInterface(voE)) == NULL) {
31         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
32         return FALSE;
33     }
34
35     if(voeBase->Init()!=0){
36         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
37     }
38
39     if ((viE = webrtc::VideoEngine::Create()) == NULL) {
40         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
41         return FALSE;
42     }
43     if ((vieBase = webrtc::ViEBase::GetInterface(viE)) == NULL) {
44         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
45         return FALSE;
46     }
47     if ((vieCapture = webrtc::ViECapture::GetInterface(viE)) == NULL) {
48         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
49         return FALSE;
50     }
51     if ((vieRender = webrtc::ViERender::GetInterface(viE)) == NULL) {
52         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
53         return FALSE;
54     }
55     if ((vieCodec = webrtc::ViECodec::GetInterface(viE)) == NULL) {
56         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
57         return FALSE;
58     }
59     if ((vieNetwork = webrtc::ViENetwork::GetInterface(viE)) == NULL) {
60         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
61         return FALSE;
62     }
63     if ((vieRtpRtcp = webrtc::ViERTP_RTCP::GetInterface(viE)) == NULL) {
64         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
65         return FALSE;
66     }
67
68     if (vieBase->Init() != 0) {
69         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
70         return FALSE;
71     }
72
73     [self initAudioCodec];
74     [self initVideoCodec];
75
76     captureID = 0;
77     videoChannel = -1;
78
79     return TRUE;
80 }
81
82 -(void)initAudioCodec
83 {
84     memset(&voeCodecInst, 0, sizeof(webrtc::CodecInst));
85
86     if (voeCodec != NULL) {
87         for (int index=0; index < voeCodec->NumOfCodecs(); index++) {
88             webrtc::CodecInst ci;
89             voeCodec->GetCodec(index, ci);
90             if (strncmp(ci.plname, "ISAC", 4) == 0) {
91                 memcpy(&voeCodecInst, &ci, sizeof(webrtc::CodecInst));
92                 break;
93             }
94         }
95         //voeCodecInst.channels = 1;
96         //voeCodecInst.rate = -1;
97     }
98 }
99
100 -(BOOL)start
101 {
102    f ((audioChannel = voeBase->CreateChannel())!=0) {
103         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
104         return FALSE;
105     }
106     if (vieBase->CreateChannel(videoChannel) != 0) {
107         DebugLog(@"AVErr: %d %s at line %d", vieBase->LastError(),__FUNCTION__, __LINE__);
108         return FALSE;
109     }
110     DebugLog(@"AVInfo: CreateChannel success! %d, %d",videoChannel,audioChannel);
111
112     //vieCodec->SetReceiveCodec(videoChannel,videoCodec);
113
114     if(voeAudioProccessing->SetAecmMode()!=0){
115         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
116         return FALSE;
117     }
118     voeAudioProccessing->SetAgcStatus(TRUE, webrtc::kAgcDefault);
119     voeAudioProccessing->SetNsStatus(TRUE, webrtc::kNsHighSuppression);
120     _voice_capture_device_index = -1;
121     voeHardware->SetRecordingDevice(_voice_capture_device_index);
122     voeHardware->SetPlayoutDevice(_voice_playback_device_index);
123     if(voeHardware->SetLoudspeakerStatus(true)!=0){
124         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
125     }
126     voeCodec->SetSendCodec(audioChannel, voeCodecInst);
127
128     RtpRtcpStreamStruct streamStruct=[self createRtpStreamStruct];
129     voeChannelTransport=new webrtc::test::VoiceChannelTransport(voeNetwork, audioChannel);
130     voeChannelTransport->SetLocalReceiver2(localARtpPort.rtp,streamStruct );
131     voeChannelTransport->SetSendDestination2([remoteIPAddress UTF8String], remoteARtpPort.rtp, remoteARtpPort.rtcp);
132
133     if(vieCodec->SetSendCodec(videoChannel, videoCodec) != 0)
134     {
135         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
136         return FALSE;
137     }
138     vieRtpRtcp->SetNACKStatus(videoChannel, TRUE);
139     vieRtpRtcp->SetRTCPStatus(videoChannel, webrtc::kRtcpNonCompound_RFC5506);
140     vieRtpRtcp->SetKeyFrameRequestMethod(videoChannel, webrtc::kViEKeyFrameRequestPliRtcp);
141
142     vieBase->SetVoiceEngine(voE);
143     if (vieBase->ConnectAudioChannel(videoChannel, audioChannel)) {
144         DebugLog(@"AVErr:%s at line %d",__FUNCTION__,__LINE__);
145         return FALSE;
146     }
147
148     if (deviceUniqueID == nil) {
149         DebugLog(@"AVInfo NumberOfCaptureDevices is %d", vieCapture->NumberOfCaptureDevices());
150         int list_count=vieCapture->NumberOfCaptureDevices();
151         if ( list_count> 0) {
152             int list_number=0;
153             if (list_count>1) {
154                 list_number=1;//[[AVShareData instance] isUseFrontCamera]?0:1;
155             }
156             char device_name[KMaxDeviceNameLength];
157             char unique_id[KMaxUniqueIdLength];
158             memset(unique_id, 0, KMaxUniqueIdLength);
159             vieCapture->GetCaptureDevice(list_number, device_name, KMaxDeviceNameLength, unique_id, KMaxUniqueIdLength);
160             deviceUniqueID = [NSString stringWithFormat:@"%s", unique_id];
161         }
162     }
163     DebugLog(@"AVInfo deviceUniqueID is %@", deviceUniqueID);
164
165     if ((vieCapture->AllocateCaptureDevice([deviceUniqueID UTF8String], deviceUniqueID.length, captureID)) != 0) {
166         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
167         return FALSE;
168     }
169
170     DebugLog(@"AVInfo captureID is %d", captureID);
171
172     if (vieCapture->ConnectCaptureDevice(captureID, videoChannel) != 0) {
173         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
174         return FALSE;
175     }
176
177     webrtc::CaptureCapability captureCapability;
178     captureCapability.width=352;
179     captureCapability.height=288;
180     captureCapability.codecType=webrtc::kVideoCodecVP8;
181     captureCapability.maxFPS=DEFAULT_VIDEO_CODEC_MAX_FRAMERATE;
182     //vieCapture->SetRotateCapturedFrames(captureID, <#const webrtc::RotateCapturedFrame rotation#>)
183     if (vieCapture->StartCapture(captureID,captureCapability) != 0) {
184         //if (vieCapture->StartCapture(captureID) != 0) {
185         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
186         return FALSE;
187     }
188     if((vieRender->AddRenderer(captureID, [self localRenderView], 0, 0.0, 0.0, 1.0, 1.0)) != 0){
189         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
190         return FALSE;
191     }
192     /*
193     if((vieRender->AddRenderer(captureID, [self localRenderView2], 0, 0.0, 0.0, 1.0, 1.0)) != 0){
194         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
195         return FALSE;
196     }
197     */
198
199     if (vieRender->StartRender(captureID) != 0) {
200         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
201         return FALSE;
202     }
203     if(vieRender->AddRenderer(videoChannel, [self remoteRenderView], 1, 0.0f, 0.0f, 1.0f, 1.0f)!=0){
204         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
205         return FALSE;
206     }
207     if(vieRender->StartRender(videoChannel)!=0){
208         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
209         return FALSE;
210     }
211
212     if (vieBase->StartReceive(videoChannel)!=0) {
213         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
214         return FALSE;
215     }
216     if (vieBase->StartSend(videoChannel)!=0) {
217         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
218         return FALSE;
219     }
220     if(voeBase->StartReceive(audioChannel) != 0)
221     {
222         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
223         return FALSE;
224     }
225     if(voeBase->StartPlayout(audioChannel) != 0)
226     {
227         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
228         return FALSE;
229     }
230     if(voeBase->StartSend(audioChannel) != 0)
231     {
232         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
233         return FALSE;
234     }
235
236     //webrtc::CodecInst ci;
237     //voeFile->StartRecordingMicrophone(@"a.avi",ci,1000);
238
239     DebugLog(@"AVInfo: %s at line %d success!", __FUNCTION__, __LINE__);
240     return TRUE;
241 }
242
243 -(BOOL)stop
244 {
245     if(voeBase->StopSend(audioChannel)!=0){
246         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
247         return FALSE;
248     }
249     if(voeBase->StopReceive(audioChannel)!=0){
250         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
251         return FALSE;
252     }
253     if(voeBase->StopPlayout(audioChannel)!=0){
254         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
255         return FALSE;
256     }
257
258     if(vieBase->StopSend(videoChannel)!=0){
259         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
260         return FALSE;
261     }
262     if(vieBase->StopReceive(videoChannel)!=0){
263         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
264         return FALSE;
265     }
266     if(vieCapture->StopCapture(captureID)!=0){
267         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
268         return FALSE;
269     }
270     if(vieCapture->ReleaseCaptureDevice(captureID)!=0){
271         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
272         return FALSE;
273     }
274     if(vieRender->StopRender(videoChannel)!=0){
275         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
276         return FALSE;
277     }
278     if(vieRender->RemoveRenderer(videoChannel)!=0){
279         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
280         return FALSE;
281     }
282
283     if(voeBase->DeleteChannel(audioChannel)!=0){
284         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
285         return FALSE;
286     }
287     if(vieBase->DeleteChannel(videoChannel)!=0){
288         DebugLog(@"AVErr: %s at line %d", __FUNCTION__, __LINE__);
289         return FALSE;
290     }
291
292     DebugLog(@"AVInfo: %s at line %d success", __FUNCTION__, __LINE__);
293
294     return TRUE;
295 }


相关说明:

1,声音处理:

1.1. webrtc支持很多种音频编码,ilbc. isac. G711. G722. opus等等,不能编码适用不同场景,可根据自己需求调整.

1.2. 声音处理最大的难题就是噪声,回声,抖动,自动增益的处理,这也是最有价值的部分,webrtc和系统里面都有相应的处理,不过因为安卓机型众多,加上厂商DIY所以不同机器问题不一样,有些问题还得自己去处理,如webrtc团队基本上就不会用小米,酷派啥的测试.

1.3. AECM目前在安卓上都是通过软件在处理,看资料说后面一些厂商会直接集成到硬件上,具体效果拭目以待.

2,视频处理:

2.1. webrtc默认使用vp8编码,这也是Google力推的一种编码格式,后面会推VP9.

2.2. 如果需兼容H264,则需要自己去集成,实际上有人已经这么做了,不过WebRTC后面也会支持H264.

2.3. vp8与和h264孰优孰劣,最好自己去比较测试,不要道听途书,我相信Google力推的东西不会差到哪去.

2.4. NACK,字面解释就是协商确认包,实际就是起到丢包重传的作用,网络不好时因为丢包造成花屏,通过这个可解决,但会带来一定的延迟.

2.5. FEC,字面解释就是向前纠错编码,与NACK不同,包里面已经携带了纠错码,即时前一包未正确接收,也可根据他的信息正确计算出来.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: