【实例简介】

有相关文档和测试demo,回音消除等处理,学习WebRTC、回音消除的同学可以好好参考

【实例截图】

219bf62ea24f553fc9638f2468fa0d1d.png

e62d51ef49da1b6d75f1f4579ffa6ba6.png

c079e99dde1104016cf5049293b4228d.png

ed7df13402523f0fea503e5388dbf4fe.png

2fa818e252ddfa3fb81fe6ed0d8cd161.png

【核心代码】

/*

* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.

*

* Use of this source code is governed by a BSD-style license

* that can be found in the LICENSE file in the root of the source

* tree. An additional intellectual property rights grant can be found

* in the file PATENTS. All contributing project authors may

* be found in the AUTHORS file in the root of the source tree.

*/

package org.webrtc.webrtcdemo;

import android.app.ActionBar.Tab;

import android.app.ActionBar.TabListener;

import android.app.ActionBar;

import android.app.Activity;

import android.app.Fragment;

import android.app.FragmentTransaction;

import android.content.pm.ActivityInfo;

import android.media.AudioManager;

import android.os.Bundle;

import android.os.Handler;

import android.view.KeyEvent;

import android.view.Menu;

import android.view.MenuInflater;

import android.view.MenuItem;

import android.view.WindowManager;

public class WebRTCDemo extends Activity implements MenuStateProvider {

// From http://developer.android.com/guide/topics/ui/actionbar.html

public static class TabListener

implements ActionBar.TabListener {

private Fragment fragment;

private final Activity activity;

private final String tag;

private final Class instance;

private final Bundle args;

public TabListener(Activity activity, String tag, Class clz) {

this(activity, tag, clz, null);

}

public TabListener(Activity activity, String tag, Class clz,

Bundle args) {

this.activity = activity;

this.tag = tag;

this.instance = clz;

this.args = args;

}

public void onTabSelected(Tab tab, FragmentTransaction ft) {

// Check if the fragment is already initialized

if (fragment == null) {

// If not, instantiate and add it to the activity

fragment = Fragment.instantiate(activity, instance.getName(), args);

ft.add(android.R.id.content, fragment, tag);

} else {

// If it exists, simply attach it in order to show it

ft.attach(fragment);

}

}

public void onTabUnselected(Tab tab, FragmentTransaction ft) {

if (fragment != null) {

// Detach the fragment, because another one is being attached

ft.detach(fragment);

}

}

public void onTabReselected(Tab tab, FragmentTransaction ft) {

// User selected the already selected tab. Do nothing.

}

}

private NativeWebRtcContextRegistry contextRegistry = null;

private MediaEngine mediaEngine = null;

private Handler handler;

public MediaEngine getEngine() { return mediaEngine; }

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// Global settings.

getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

// State.

// Must be instantiated before MediaEngine.

contextRegistry = new NativeWebRtcContextRegistry();

contextRegistry.register(this);

// Load all settings dictated in xml.

mediaEngine = new MediaEngine(this);

mediaEngine.setRemoteIp(getResources().getString(R.string.loopbackIp));

mediaEngine.setTrace(getResources().getBoolean(

R.bool.trace_enabled_default));

mediaEngine.setAudio(getResources().getBoolean(

R.bool.audio_enabled_default));

mediaEngine.setAudioCodec(mediaEngine.getIsacIndex());

mediaEngine.setAudioRxPort(getResources().getInteger(

R.integer.aRxPortDefault));

mediaEngine.setAudioTxPort(getResources().getInteger(

R.integer.aTxPortDefault));

mediaEngine.setSpeaker(getResources().getBoolean(

R.bool.speaker_enabled_default));

mediaEngine.setDebuging(getResources().getBoolean(

R.bool.apm_debug_enabled_default));

mediaEngine.setReceiveVideo(getResources().getBoolean(

R.bool.video_receive_enabled_default));

mediaEngine.setSendVideo(getResources().getBoolean(

R.bool.video_send_enabled_default));

mediaEngine.setVideoCodec(getResources().getInteger(

R.integer.video_codec_default));

// TODO(hellner): resolutions should probably be in the xml as well.

mediaEngine.setResolutionIndex(MediaEngine.numberOfResolutions() - 2);

mediaEngine.setVideoTxPort(getResources().getInteger(

R.integer.vTxPortDefault));

mediaEngine.setVideoRxPort(getResources().getInteger(

R.integer.vRxPortDefault));

mediaEngine.setNack(getResources().getBoolean(R.bool.nack_enabled_default));

mediaEngine.setViewSelection(getResources().getInteger(

R.integer.defaultView));

// Create action bar with all tabs.

ActionBar actionBar = getActionBar();

actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

actionBar.setDisplayShowTitleEnabled(false);

Tab tab = actionBar.newTab()

.setText("Main")

.setTabListener(new TabListener(

this, "main", MainMenuFragment.class));

actionBar.addTab(tab);

tab = actionBar.newTab()

.setText("Settings")

.setTabListener(new TabListener(

this, "Settings", SettingsMenuFragment.class));

actionBar.addTab(tab);

tab = actionBar.newTab()

.setText("Video")

.setTabListener(new TabListener(

this, "video", VideoMenuFragment.class));

actionBar.addTab(tab);

tab = actionBar.newTab()

.setText("Audio")

.setTabListener(new TabListener(

this, "Audio", AudioMenuFragment.class));

actionBar.addTab(tab);

enableTimedStartStop();

// Hint that voice call audio stream should be used for hardware volume

// controls.

setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

MenuInflater inflater = getMenuInflater();

inflater.inflate(R.menu.main_activity_actions, menu);

return super.onCreateOptionsMenu(menu);

}

@Override

public boolean onOptionsItemSelected(MenuItem item) {

// Handle presses on the action bar items

switch (item.getItemId()) {

case R.id.action_exit:

MainMenuFragment main = (MainMenuFragment)getFragmentManager()

.findFragmentByTag("main");

main.stopAll();

finish();

return true;

default:

return super.onOptionsItemSelected(item);

}

}

@Override

public void onDestroy() {

disableTimedStartStop();

mediaEngine.dispose();

contextRegistry.unRegister();

super.onDestroy();

}

@Override

public boolean onKeyDown(int keyCode, KeyEvent event) {

if (keyCode == KeyEvent.KEYCODE_BACK) {

// Prevent app from running in the background.

MainMenuFragment main = (MainMenuFragment)getFragmentManager()

.findFragmentByTag("main");

main.stopAll();

finish();

return true;

}

return super.onKeyDown(keyCode, event);

}

private int getCallRestartPeriodicity() {

return getResources().getInteger(R.integer.call_restart_periodicity_ms);

}

// Thread repeatedly calling start/stop.

void enableTimedStartStop() {

if (getCallRestartPeriodicity() > 0) {

// Periodicity == 0 Disabled.

handler = new Handler();

handler.postDelayed(startOrStopCallback, getCallRestartPeriodicity());

}

}

void disableTimedStartStop() {

if (handler != null) {

handler.removeCallbacks(startOrStopCallback);

}

}

private Runnable startOrStopCallback = new Runnable() {

public void run() {

MainMenuFragment main = (MainMenuFragment)getFragmentManager()

.findFragmentByTag("main");

main.toggleStart();

handler.postDelayed(startOrStopCallback, getCallRestartPeriodicity());

}

};

}

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐