Unable to free my webcam in Actionscript 3.0 - actionscript-3

To free my webcam I'm using
onScrenVideo.attachCamera(null)
where onScreenVideo is a Video object.
However, this just doesn't seem to work. Even after this line executes, the webcam light remains ON.
I have scoured the Internet for a solution to this problem and everyone seems to be unanimous that this is the only way to turn the webcam off (for example : Close webcam usage via actionscript), however, this just doesn't seem to be working for me.
Can anyone help?
Thanks
Edit: Adding relevant code.
All the variables are declared previously. Here's the code to set up the Camera and attach it to the video.
testCurrCam = Camera.getCamera();
onScreenVideo = new Video(240, 180);
onScreenVideo.smoothing = true;
onScreenVideo.x = 0;
onScreenVideo.y = 0;
addChild(onScreenVideo);
testCurrCam.setQuality(0, 70);
testCurrCam.setMode(640, 480, 10);
onScreenVideo.attachCamera(testCurrCam);
And here's a function which is called by Javascript using ExternalInterface. The call works perfectly fine, because I've checked using an alert box after the if condition.
private function stopCam(): void {
if (contains(onScreenVideo)) {
onScreenVideo.attachCamera(null);
this.removeChild(onScreenVideo);
onScreenVideo = null;
testCurrCam = null;
} else
return;
}

Related

GameInput.DEVICE_ADDED not triggering at application startup

I'm posting this question because i'm having a little problem with the GameInput API in an adobe AIR desktop app.
I tested the API in a test app and it worked just fine. However, when i added it to my real app (a game), it doesn't trigger anymore at startup.
Everything else works, and if i disconnect/reconnect the controller, everything works fine. However, the initial trigger of the callback function isn't working anymore.
Any idea why ?
Here's what i do:
if (GameInput.isSupported) //GAMEPADS SUPPORT
{
gameInput = new GameInput();
gameInput.addEventListener(GameInputEvent.DEVICE_ADDED, controllerAdded);
gameInput.addEventListener(GameInputEvent.DEVICE_REMOVED, controllerRemoved);
gameInput.addEventListener(GameInputEvent.DEVICE_UNUSABLE, controllerProblem);
} //GAMEPAD SUPPORT
public function controllerAdded(e:GameInputEvent):void
{
var vec:Vector.<String> = new Vector.<String>();
gamepad = GameInput.getDeviceAt(0);
vec[0] = gamepad.getControlAt(0).id;
gamepad.enabled = true;
gamepad.sampleInterval = 10;
gamepad.startCachingSamples(5, vec); // numSamples = 5
for (var i:int = 0; i < gamepad.numControls; ++i)
gamepad.getControlAt(i).addEventListener(Event.CHANGE, handleChangeEvent);
}
I am guessing it could be a focus issue or something related but i really don't see why this would be happening.
My app looks like this:
Core (class called from swf and manages the whole app)
Screens (different classes that inherit movieclip but have logic inside, such as game, optionscreen, etc.)
The Gameinput api intialization is done in the core, after the instanciation of the object (using Event.ADDED_TO_STAGE).
The GameInputEvent class represents an event that is dispatched when a game input device has either been added or removed from the application platform
So if you launch the app and allready have a device, no event will be triggered which sounds like your issue. Why don't you just check devices during intialization and then work with them at that point?
if (GameInput.isSupported) //GAMEPADS SUPPORT
{
gameInput = new GameInput();
gameInput.addEventListener(GameInputEvent.DEVICE_ADDED, controllerAdded);
gameInput.addEventListener(GameInputEvent.DEVICE_REMOVED, controllerRemoved);
gameInput.addEventListener(GameInputEvent.DEVICE_UNUSABLE, controllerProblem);
if(GameInput.numDevices > 0) {
/*enter code here/*
}
}
Well it seems the GameInput API by Adobe is too unstable.
I've decided to use AirControl instead and it works much better...
I'm therefore closing this question.

Getting Bitmap from Video decoded with Nestream AppendBytes (AS3)?

I am wondering if someone who has handled NetStream.appendBytes in Flash knows how to get the bitmapData from a decoded video frame? I have already looked at this question but that is from 3 years ago and the more recent comment/answer seems to be gone. In 2014 has anyone managed to turn those bytes into a bitmap? I am working with Flash Player 11.8 and this is not a desktop/AIR app.
In the image below I can do steps 1) and 2) but there's a brick wall at step 3)
The problem is that simply using bitmapdata.draw(video_container); does not work but instead it throws a Policy File error even though I am using a byteArray (from local video file in the same directory as the SWF). No internet is even involved but Flash tells me that "No Policy File granted permission from the server" or such nonsense. I think the error is just a bail-out insteading of straight up saying "You are not allowed to do this.."
I have tried: trying to appease this Crossdomain.xml issue anyway and looking into all known security/domain settings. I came to the conclusion that the error is not the problem but a side effect of the issue.. The issue here being that: Flash Player is aware of the SWF's location and of any files local to it. That's okay when you pass a String as URL etc but when the Netstream data is not local to the SWF domain then it becomes a Policy File issue. Problem is my data is in the Memory not in a folder like the SWF and therefore cannot alllow bitmapData.draw since it cannot "police" an array of bytes, any known fixes for this?... (I can't even say the words I really wanted to use).
What I am trying to achieve: Is to essentially use Netstream as an H.263 or H.264 image decoder in the same way Loader is a JPEG-to-Bitmap decoder or LoadCompressed.. is an MP3-to-PCM decoder. You know, access the raw material (here RGB pixels), apply some effects functions and then send to screen or save to disk.
I know it is a little late, but I think I found a solution for your problem.
So, to avoid the Security sandbox violation #2123 Error, you have just to do like this :
// ...
net_stream.play(null);
net_stream.play('');
// ...
Hope that can help.
I know this question is a couple months old, but I wanted to post the correct answer (because I just had this problem as well and other will too).
Correct answer:
It's a bug that has been open at adobe for almost 2 years
Link to the bug on Adobe
Work Around until the bug gets fixed (I am using this and it works great):
Workaround using Sprite and graphics
To take a snapshot from a video stream we don't need NetStream.appendBytes which inject data into a NetStream object.
For that we can use BitmapData.draw which has some security constraints. That's why in many times we get a flash security error. About that, Adobe said :
"... This method is supported over RTMP in Flash Player 9.0.115.0 and later and in Adobe AIR. You can control access to streams on Flash Media Server in a server-side script. For more information, see the Client.audioSampleAccess and Client.videoSampleAccess properties in Server-Side ActionScript Language Reference for Adobe Flash Media Server. If the source object and (in the case of a Sprite or MovieClip object) all of its child objects do not come from the same domain as the caller, or are not in a content that is accessible to the caller by having called the Security.allowDomain() method, a call to the draw() throws a SecurityError exception. This restriction does not apply to AIR content in the application security sandbox. ...".
For crossdomain file creation and some other security config for AMS server, you can take a look on this post : Crossdomain Video Snapshot - Fixing BitmapData.draw() Security Sandbox Violation.
After allowing our script to get data from our video stream, we can pass to the code.
I wrote a code that play a video stream ( rtmp or http ) and take a snapshot to show it in the stage or save it as a file after applying a pixel effect :
const server:String = null; //'rtmp://localhost/vod'
const stream:String = 'stream'; // 'mp4:big_buck_bunny_480p_h264.mp4';
var nc:NetConnection;
var ns:NetStream;
var video:Video;
const jpg_quality:int = 80;
const px_size:int = 10;
nc = new NetConnection();
nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, function(e:AsyncErrorEvent):void{});
nc.addEventListener(NetStatusEvent.NET_STATUS, function(e:NetStatusEvent):void{
if(e.info.code == 'NetConnection.Connect.Success'){
ns = new NetStream(nc);
ns.addEventListener(NetStatusEvent.NET_STATUS, function(e:NetStatusEvent):void{});
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, function(e:AsyncErrorEvent):void{});
video = new Video(320, 180);
video.x = video.y = 10;
video.attachNetStream(ns);
addChild(video);
ns.play(stream);
}
})
nc.connect(server);
btn_show.addEventListener(
MouseEvent.CLICK,
function(e:MouseEvent): void{
var bmp:Bitmap = pixelate(video, px_size);
bmp.x = 10;
bmp.y = 220;
addChild(bmp);
}
)
btn_save.addEventListener(
MouseEvent.CLICK,
function(e:MouseEvent): void{
var bmp:Bitmap = pixelate(video, px_size);
var jpg_encoder:JPGEncoder = new JPGEncoder(80);
var jpg_stream:ByteArray = jpg_encoder.encode(bmp.bitmapData);
var file:FileReference = new FileReference();
file.save(jpg_stream, 'snapshot_'+int(ns.time)+'.jpg');
}
)
function pixelate(target:DisplayObject, px_size:uint):Bitmap {
var i:uint, j:uint = 0;
var s:uint = px_size;
var d:DisplayObject = target;
var w:uint = d.width;
var h:uint = d.height;
var bmd_src:BitmapData = new BitmapData(w, h);
bmd_src.draw(d);
var bmd_final:BitmapData = new BitmapData(w, h);
var rec:Rectangle = new Rectangle();
rec.width = rec.height = s;
for (i = 0; i < w; i += s){
for (j = 0; j < h; j += s){
rec.x = i;
rec.y = j;
bmd_final.fillRect(rec, bmd_src.getPixel32(i, j));
}
}
bmd_src.dispose();
bmd_src = null;
return new Bitmap(bmd_final);
}
Of course, this is just a simple example to show the manner to get a snapshot from a video stream, you should adapt and improve it to your needs ...
I hope all that can help you.

add equalizer for online flash radio

i have tried add equalizer my online radio. i was used http://www.everyday3d.com/blog/index.php/2008/03/26/classic-sound-equalizer-in-flashas3/
flash source file . it's working fine when i am worked in flash ide. but on my server the equalizer doesnot show. but if the playing file is mp3 format it will worked but if we play the stream url it's not working. i dont know how can i fix this. i am using as3, i am new to flash. please help any one. thanks advance
the equalizer code
var es:EqualizerSettings = new EqualizerSettings();
es.numOfBars = 80;
es.height = 30;
es.barSize = 3;
es.vgrid = true;
es.hgrid = 2;
es.colorManager = new GradientBarColor(0xffff4444);
es.effect = EqualizerSettings.FX_REFLECTION;
var e:Equalizer = new Equalizer();
e.update(es);
e.x = 100;
e.y = 60;
addChild(e);
addEventListener(Event.ENTER_FRAME, e.render);
What Gio said, SoundMixer.computeSpectrum-based approach, such as the one linked in your question, suffers from security problems. But there are alternatives, for example check this code: http://wonderfl.net/c/euIb/read (some of stream URLs in it are dead, and it might not work right away - so try it with your own stream URL)

How to loop FLV seamlessly

I am playing looped FLVs in the "standard way":
netstream.addEventListener(NetStatusEvent.NET_STATUS, onStatus);
...
public function onStatus(item:Object):void {
if (item.info.code == "NetStream.Play.Stop") {
if (loop) netstream.seek(0);
}
When played through Flash CS 5.5 authoring tool (Test Movie or Debug Movie), the videos loop seamlessly. But! When played in the browser or standalone debug Flash player (both v.11.2.202.233) there is an abnormal pause of about 1 sec before the video "rewinds".
Is this a bug with the latest Flash player?
For People who have the same issue, try changing the aforementioned code to this:
public function onStatus(item:Object):void {
if (item.info.code == "NetStream.Buffer.Empty") {
if (loop) netstream.seek(0);
}
It will get rid of the flicker. If you listen to "NetStream.Play.Stop", it will cause a flicker.
You don't need to embed anything. This works just fine on IOS, Android and PC.
This is a known bug with Flash Player 11+ and AIR 3+. Bug report is here, and you should upvote & : https://bugbase.adobe.com/index.cfm?event=bug&id=3349340
Known workarounds that will create a seamless loop:
1) Embed the video in the SWF. Not ideal, and not possible in some cases.
2) Create dual NetSteam objects and switch between them. An example of the event fired when ns1, the first of two NetStreams objects, reaches it's end:
if (e.info.code == "NetStream.Play.Stop"){
vid.attachNetStream(ns2);
ns2.resume();
activeNs = ns2;
ns1.seek(0);
ns1.pause();
}
Replace ns1 with ns2 on the other event listener. A useless duplication of objects and handlers, but there you go.
3) Use AIR 2.x / Flash Player 10.x (not really a solution at all, except for Linux users)
We noticed this on the transition from Flash 10 to to Flash 11. Flash 10 loops seamlessly, but Flash 11 has a ~1 second stall when calling seek(0) from NetStream.Play.Stop.
Embedding the media in the SWF is not an option for us.
The following code provides a more seamless loop - still not perfect, but much better.
var mStream:NetStream;
var mDuration:Number;
...
addEventListener(Event.ENTER_FRAME, onEnterFrame);
...
function onEnterFrame(e:Event):void
{
if( mStream.time > (mDuration-0.05) )
{
if( mLooping )
{
mStream.seek(0);
}
}
}
function onMetaData(info:Object)
{
mDuration = info.duration;
}
Hope it helps.
I seem to have achieved this using an FLVPlayback component along with a few tips.
What's more, it's running seamlessly on desktop, iPhone 4S and 3GS! (via an AIR app)
_videoFLV = new FLVPlayback();
_videoFLV.fullScreenTakeOver = false;
_videoFLV.autoPlay = false;
_videoFLV.autoRewind = true;
_videoFLV.isLive = false;
_videoFLV.skin = null;
_videoFLV.y = 150;
_videoFLV.bufferTime = .1;
_videoFLV.width = 320;
_videoFLV.height = 320;
_videoFLV.addEventListener(MetadataEvent.CUE_POINT, video_cp_listener, false, 0, true);
_videoFLV.source = "includes/10sec.flv";
addChild(_videoFLV);
With the listener function...
function video_cp_listener(eventObject:MetadataEvent):void {
if (eventObject.info.name == "endpoint") {
_videoFLV.seek(0);
_videoFLV.play();
}
}
Importantly I think you must set the width and height to match your flv file. i.e. no scaling whatsoever.
The flv has a cue point named 'endpoint' added 1 frame before the end of the file (assuming your start and end frame are the same this will be required).I added this using Adobe Media Encoder.
The only way to loop an flv seamlessly is to embed inside the swf. It is converted to a MovieClip and you then handle it with play(), stop(), nextFrame(), prevFrame() etc.
When embedding in Flash Authoring tool (dragging flv file on stage), make sure that you select:
"Embed FLV in SWF..."
Symbol Type : "Movie clip"
All checked : "Place instance on stage", "Expand timeline...", "Include audio"

Actionscript 3: Monitoring the activity level for multiple Microphones doesn't seem to work

For a project I want to show all available webcams and microphones, so that the user can easily select whichever webcam/microphone combination they prefer. I run into an issue with the microphones listing though.
Each microphone is listed with an activity animation and it's name. I am able to list all Microphones just fine (using the Microphone.names Array), but it seems like I can only get the activity viewer to work for one microphone. The other microphones show up with '-1' activity, which (as far as I know) is Flex for 'present, but not in use'. When unplugging the microphone that does show activity, the next one (in my case, the mic-in line on my motherboard) shows up with '0' activity (it's not connected, so that makes sense).
During my testing I have a total of 3 microphones available, the not-connected onboard mic-in port, and two connected microphones.
For testing purposes I use a timer that traces the current microphone activity each 100ms and the graph is also shown.
It does not seem to matter what default microphone I set via flash' settings panel.
The code
I've only attached the revelant code snippets below to make it easier for you to read through them. Please let me know if you prefer the entire code.
Main application.mxml
Note: cont is a VBox. i is defined before this code snippet.
var mics:Array = Microphone.names;
for(i=0; i < mics.length; i++){
var mic:settingsMicEntry = new assets.settingsMicEntry;
mic.d = {name: mics[i], index: i};
cont.addChild(mic);
}
assets/settingsMicEntry.mxml
timer is defined before this code snippet. the SoundTransform is added to silence local microphone playback. Excluding this code does not solve the problem, sadly (I've tried). display is an MXML Canvas object.
mic = Microphone.getMicrophone(d.index);
if(mic){
// Temporary: The Microphones' visualizer
var bar:Box = new Box();
bar.y = 50;
bar.height = 0;
bar.width = 66;
bar.setStyle("backgroundColor", 0x003300);
display.addChild(bar);
var tf:SoundTransform = new SoundTransform(0);
mic.setLoopBack(true);
mic.soundTransform = tf;
timer = new Timer(100);
timer.addEventListener(TimerEvent.TIMER, function(e:TimerEvent):void{
var h:int = Math.floor((display.height/100)*mic.activityLevel);
bar.height = (h>-1) ? h : 0;
bar.y = (h>-1) ? display.height-h : display.height;
trace('TIMER: '+h+' from '+d.name);
});
timer.start();
}
I'm pulling my hear out here, so any help is much appreciated!
Thanks,
-Dave
Ps.: Pardon the messiness of the code!
You can set up a mock NetStream connection using the OSMF library.
You'll need to import the classes from the NetMocker project (under libs/adobe - org.osmf.netmocker) and the classes NetConnectionCodes and NetStreamCodes (under framework/OSMF - org.osmf.net).
Check out that you need to create one NetStream for each microphone