Copy link to clipboard
Copied
Can somebody tell me how to write an app that display a picture of the webcam on screen, change the size of video shown and remove it from the screen without the camera eventually not displaying and the created handles being left behind.
From my investigation any camera with the usbvideo.sys driver is affected, which will be at least 50% of webcams out there.
Sometimes air locks up and becomes unresponsive / sometimes it just stops displaying the camera, it depends upon the camera.
Tested with lots of different cameras on Windows 7 and 8 with lots of versions of the Air/Flex Frameworks.
Heres a simple app to test it.
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="windowedapplication1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.collections.ArrayList;
import mx.events.FlexEvent;
import spark.events.IndexChangeEvent;
private var camera:Camera;
[Bindable]
private var cams:ArrayList;
private var video:Video;
[Bindable]
private var autoInProgress:Boolean;
[Bindable]
private var totalAttempts:int = 0;
private var currentAttempts:int = 0;
protected function windowedapplication1_creationCompleteHandler(event:FlexEvent):void
{
cams = new ArrayList(Camera.names);
}
protected function selectedCamera_changeHandler(event:IndexChangeEvent):void
{
camera = Camera.getCamera(selectedCamera.selectedIndex.toString());
if (camera)
camera.setMode(640, 480, 30);
}
private function start() : void {
currentAttempts = 0;
autoInProgress = true;
if (resizeTest.selected) {
addVideoAndAttachCamera();
resize();
}
else {
attachDetach();
}
}
private function addVideoAndAttachCamera() : void {
if (camera) {
video = new Video(camera.width, camera.height);
videoContainer.addChild(video);
video.attachCamera(camera);
}
}
private function detachCameraAndRemoveVideo() : void {
video.attachCamera(null);
video.clear();
videoContainer.removeChild(video);
video = null;
}
private function attachDetach() : void {
++ currentAttempts;
++ totalAttempts;
if (camera) {
addVideoAndAttachCamera();
memoryUsage.text = "System Memory Usage: " + (System.totalMemory).toString() + "bytes";
setTimeout(function():void {
detachCameraAndRemoveVideo();
if (currentAttempts < int(attempts.selectedItem)) {
attachDetach();
}
else {
autoInProgress = false;
}
}, int(delay.selectedItem));
}
}
private function resize() : void {
++ currentAttempts;
++ totalAttempts;
if (camera) {
camera.setMode(640, 480, 30);
memoryUsage.text = "System Memory Usage: " + (System.totalMemory).toString() + "bytes";
setTimeout(function():void {
if (currentAttempts < int(attempts.selectedItem)) {
resize();
}
else {
detachCameraAndRemoveVideo();
autoInProgress = false;
}
}, int(delay.selectedItem));
}
}
]]>
</fx:Script>
<s:VGroup>
<s:HGroup>
<s:Label enabled="{!autoInProgress}" text="Camera" />
<s:ComboBox enabled="{!autoInProgress}"
id="selectedCamera"
dataProvider="{cams}"
change="selectedCamera_changeHandler(event)"/>
<s:Label id="memoryUsage" />
<s:Label text="{totalAttempts}" />
</s:HGroup>
<s:HGroup>
<s:Label text="Auto Connect/Disconnect" enabled="{!autoInProgress}" />
<s:ComboBox id="attempts" enabled="{!autoInProgress}" selectedIndex="1">
<mx:ArrayCollection>
<fx:String>1</fx:String>
<fx:String>5</fx:String>
<fx:String>10</fx:String>
<fx:String>50</fx:String>
<fx:String>75</fx:String>
<fx:String>100</fx:String>
<fx:String>500</fx:String>
<fx:String>1000</fx:String>
<fx:String>5000</fx:String>
<fx:String>10000</fx:String>
</mx:ArrayCollection>
</s:ComboBox>
<s:Label text="times" enabled="{!autoInProgress}" />
<s:CheckBox id="resizeTest" label="Resize Test?" />
<s:Button enabled="{!autoInProgress}" click="start()" label="Start" />
</s:HGroup>
<s:HGroup>
<s:Label text="Delay" enabled="{!autoInProgress}" />
<s:ComboBox id="delay" enabled="{!autoInProgress}" selectedIndex="1">
<mx:ArrayCollection>
<fx:String>1000</fx:String>
<fx:String>1500</fx:String>
<fx:String>2000</fx:String>
<fx:String>3000</fx:String>
</mx:ArrayCollection>
</s:ComboBox>
</s:HGroup>
<mx:UIComponent id="videoContainer" width="640" height="480" />
</s:VGroup>
</s:WindowedApplication>
The resizeTest checkbox shows that you can make the camera lockup just by repetitively calling cam.setMode().
I have submitted a bug into the bugbase. Bug#3850401 - Handle leak with video.attachCamera leading to inoperable camera