Video Chat on Android very slow !
Hi everyone,
I'm developing an audio/video chat Android application. On my Android device (Samsung Galaxy S), all works... but it is very very slow !!
I launch the application (release version) on my phone and then I launch this application from my computer (from Flash Builder)
Each applications are connected to the Cirrus server and streams are sent/received. On my computer, no problem. But on my phone, the CPU usage grows immediatly (>90 % !) and the app finish to crash.
Before I click on the "connect" button : RAM 26 mb / CPU 0.33% (great !)
When I publish my audio/video via NetStream : RAM 42 mb / CPU 64%
When I publish AND receive an audio/video NetStream : RAM 48 mb / CPU 94%
By the way, my phone is getting hot...
I know that this could be done without such performance problems on Android. The proof : http://coenraets.org/blog/2010/07/video-chat-for-android-in-30-lines-of-code/
Yes, LCCS is use here by C. Coenraets, but LCCS is nothing but a NetConnection/NetStream and a RTMFP solution... So what am i doing wrong ? Any help would be very appreciated.
I paste here the code (firstView of the ViewNavigatorApplication) :
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="HomeView" xmlns:mx="library://ns.adobe.com/flex/mx" actionBarVisible="false">
<fx:Script>
<![CDATA[
/**
* Tezqa | sam@tezqa.com | www.tezqa.com
**/
private var SERVER:String = "rtmfp://p2p.rtmfp.net/";
private var KEY:String = "CIRRUS DEVELOPER KEY";
private var netConnection:NetConnection;
private var netStreamPublisher:NetStream;
private var netStreamSubscriber:NetStream;
private var groupSpecifier:GroupSpecifier;
private var camera:Camera;
private var microphone:Microphone;
private var videoPublisher:Video;
private var videoSubscriber:Video;
private var username:String;
private var budyname:String;
[Bindable] private var connected:Boolean = false;
private function startStop():void {
if (connected) {
disconnect();
} else {
username = usernameInput.text;
budyname = budynameInput.text;
connect();
}
}
private function connect():void {
netConnection = new NetConnection();
netConnection.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
netConnection.connect (SERVER, KEY);
}
private function onConnect():void {
connected = true;
groupSpecifier = new GroupSpecifier ("com.tezqa.mobilecam");
groupSpecifier.multicastEnabled = true;
groupSpecifier.postingEnabled = true;
groupSpecifier.serverChannelEnabled = true;
netStreamPublisher = new NetStream (netConnection, groupSpecifier.groupspecWithAuthorizations());
netStreamPublisher.addEventListener (NetStatusEvent.NET_STATUS, netStatus);
attachCamera();
attachMicrophone();
netStreamPublisher.publish ("stream_" + username, "live");
videoPublisher = new Video(uic1.width, uic1.height);
videoPublisher.attachCamera(camera);
uic1.addChild(videoPublisher);
netStreamSubscriber = new NetStream (netConnection, groupSpecifier.groupspecWithAuthorizations());
netStreamSubscriber.addEventListener (NetStatusEvent.NET_STATUS, netStatus);
netStreamSubscriber.play ("stream_" + budyname);
videoSubscriber = new Video(uic2.width, uic2.height);
videoSubscriber.attachNetStream(netStreamSubscriber);
uic2.addChild(videoSubscriber);
}
public function attachMicrophone():void {
microphone = null;
netStreamPublisher.attachAudio (null);
microphone = Microphone.getEnhancedMicrophone();
if (!microphone) microphone = Microphone.getMicrophone();
if (microphone) {
microphone.codec = SoundCodec.SPEEX;
microphone.framesPerPacket = 1;
microphone.setSilenceLevel(0, 3000);
microphone.gain = 100;
microphone.rate = 22;
netStreamPublisher.attachAudio (microphone);
}
}
public function detachMicrophone():void {
netStreamPublisher.attachAudio (null);
microphone = null;
}
public function attachCamera(cameraPosition:String = "auto"):Camera {
camera = null;
netStreamPublisher.attachCamera(null);
if (cameraPosition == "auto") {
camera = Camera.getCamera();
} else {
if (Camera.names.length == 1) {
camera = Camera.getCamera();
} else {
var tmpCamera:Camera = null;
for (var i:uint = 0; i < Camera.names.length; i++) {
tmpCamera = Camera.getCamera(Camera.names);
if (tmpCamera.position == cameraPosition) {
camera = tmpCamera;
break;
}
}
}
}
if (camera) {
camera.setMode (640, 480, 15, true);
camera.setQuality (15000, 0); // 30000, 0 (adobe settings)
netStreamPublisher.attachCamera (camera);
return camera;
} else {
return null;
}
}
public function detachCamera():void {
netStreamPublisher.attachCamera (null);
camera = null;
}
private function disconnect():void {
detachCamera();
detachMicrophone();
netStreamPublisher.close();
netStreamSubscriber.close();
netStreamPublisher.removeEventListener(NetStatusEvent.NET_STATUS, netStatus);
netStreamSubscriber.removeEventListener(NetStatusEvent.NET_STATUS, netStatus);
netConnection.removeEventListener(NetStatusEvent.NET_STATUS, netStatus);
netStreamPublisher = null;
netStreamSubscriber = null;
netConnection = null;
videoPublisher.clear();
videoPublisher.attachCamera(null);
videoSubscriber.clear();
uic1.removeChild(videoPublisher);
uic2.removeChild(videoSubscriber);
videoPublisher = null;
videoSubscriber = null;
connected = false;
}
private function netStatus(e:NetStatusEvent):void {
switch(e.info.code) {
case "NetConnection.Connect.Success":
onConnect();
break;
default:
break;
}
}
]]>
</fx:Script>
<s:VGroup width="100%" height="100%">
<s:HGroup width="100%" height="100%">
<mx:UIComponent id="uic1" width="50%" height="100%"/>
<mx:UIComponent id="uic2" width="50%" height="100%"/>
</s:HGroup>
<s:Label text="Connected : {connected}" paddingLeft="10"/>
<s:HGroup width="100%" horizontalAlign="center" verticalAlign="middle" paddingBottom="10">
<s:TextInput id="usernameInput" prompt="Enter your name" text="lug" width="35%"/>
<s:TextInput id="budynameInput" prompt="Enter budy name" text="kat" width="35%"/>
<s:Button label="{connected?'Disconnect':'Connect'}" click="startStop()"/>
</s:HGroup>
</s:VGroup>
</s:View>
