If I publish Windows Projector (.exe) with no hardware acceleration, everything works fine, but if I select direct or gpu harware acceleration I will not get the security panel to show up at all. Anyone else have this same issue, or is it just me?
Basically I would like to publish a stand-alone webcam game, but if I try to use getCamera(), the user will not see the security question at all, and I will not get the camera initialized.Does anyone know a workaround for this? I would love to get HW acceleration to my game.
import flash.system.Security;
import flash.system.SecurityPanel;
//import flash.media.Camera;
Security.showSettings(SecurityPanel.CAMERA);
//var camera:Camera=Camera.getCamera();
I got this to work, but I created a projector through the stand alone and the "Create Projector" menu, not through the Flash IDE. I was able to get the panel to show up using the latest flash.
compiler settings: -swf-version=16 -use-gpu=true
// test showing stage3D + panel
final public class Test extends Sprite {
private var cam:Camera;
private var video:Video = new Video();
public function Test():void {
var stage3D:Stage3D = stage.stage3Ds[0];
stage3D.addEventListener(Event.CONTEXT3D_CREATE, handleContext);
stage3D.requestContext3D();
trace(cam.name);
}
/**
* #private
*/
private function handleContext(e:Event):void {
var stage3D:Stage3D = stage.stage3Ds[0];
var context:Context3D = stage3D.context3D;
context.configureBackBuffer(stage.stageWidth, stage.stageHeight, 0, true);
context.clear(0,0,0,1);
context.present();
Security.showSettings(SecurityPanel.CAMERA);
cam = Camera.getCamera();
cam.setMode(640,360,30);
video.attachCamera(cam);
// change to upload via texture instead
addChild(video);
}
In my experience, hardware acceleration gains are only very minimal without using specific gpu apis. Camera in my experience instead accelerated, only specific types of video decompression. If you're not using Stage3D, you probably won't get any visible gains.
Related
IDE: FLASH CS6 Professional
SDK: AIR 18 for Android
I'm trying to use Workers for my app.
The problem is, it doesn't work that it suppose to be.
public class Main extends Sprite {
private var worker:Worker;
public function Main() {
var ba:ByteArray = this.loaderInfo.bytes;
if(Worker.current.isPrimordial){
worker = WorkerDomain.current.createWorker(ba);
worker.start();
trace("Created Main");
}else{
trace("Created Worker");
}
}
}
It should output
Created Main
Created Worker
but i'm only getting
[SWF] Test.swf - 2831 bytes after decompression
Created Main
[UnloadSWF] Test.swf
Test Movie terminated.
EDIT:
Ok i tried to publish the app and ran it. It works like it should be. But why doesn't it work when i try to ran it with Adobe Debug Launcher ?
This is what it looks like on Android Debug Launcher (ADL)
ADL
This is what it looks like when Published.
Published
EDIT 2:
Tried it with Flash Professional CC 2015. Upgraded to AIR SDK 19.0.0.213.
Still the same result. What a pain Adobe.
It should work, but Flash Pro CS6 doesn't show the worker's trace statements. Check flashlog.txt or send messages from the worker to the main SWF over a MessageChannel.
I made a lib to support use of Workers, if you want use you can check it in GitHub, it is open source project.. hope help ASWorker Link
The implementation is like this
package
{
import com.tavernari.asworker.ASWorker;
import com.tavernari.asworker.notification.NotificationCenter;
import com.tavernari.asworker.notification.NotificationCenterEvent;
import flash.display.Sprite;
public class ASWorkerDemo extends Sprite
{
private var asWorker:ASWorker;
//BOTH AREA
public function ASWorkerDemo()
{
//important know, all class start here will be replicated in all works.
asWorker = new ASWorker(this.stage, uiWorkerStartedHandler, backWorkerStartedHandler);
}
//BOTH AREA END
//UI AREA START
private function uiWorkerStartedHandler():void{
//implement all class or calls for your UI
NotificationCenter.addEventListener("FROM_BACK_EVENT_MESSAGE", onFromBackEventMessageHandler );
}
private function onFromBackEventMessageHandler(e:NotificationCenterEvent):void
{
trace(e.data);
if(e.data == "completed job"){
NotificationCenter.dispatchEventBetweenWorkers( new NotificationCenterEvent("NEXT_MESSAGE") );
}
}
//UI AREA END
//BACK AREA START
private function backWorkerStartedHandler():void{
//implement all class or calls for your BACK operations
NotificationCenter.addEventListener("NEXT_MESSAGE", uiCallForNextMessageHandler );
}
private function uiCallForNextMessageHandler():void
{
for(var i:int = 0; i < 15; ++i){
NotificationCenter.dispatchEventBetweenWorkers( new NotificationCenterEvent("FROM_BACK_EVENT_MESSAGE", false, i) );
}
NotificationCenter.dispatchEventBetweenWorkers( new NotificationCenterEvent("FROM_BACK_EVENT_MESSAGE", false, "completed job") );
}
// BACK AREA END
}
}
Good luck with Workers
Air 20.0.0.204 ADL is also not enjoying anything worker related (from my limited experimentation), however the desktop Flash Player seems to work just fine. This makes debugging convoluted and problematic when you are using Air specific libraries in your project and prefer not to wildcard variable types.
At the moment, workers are only supported on desktop platform. This Adobe developer's guide page specifically mentions "for desktop platforms".
Meanwhile, there is an AS3-Worker-Compat library by Jeff Ward that enables you to write code with Workers that will still work correctly in an environment that doesn't support Workers (of course, in this case your code will run in single-threaded mode).
I think many people are waiting for Adobe to implement workers for mobile, hopefully it will come in the future.
I tried following a combination of Lee Brimlow's blitting tutorial series and and the technique in Rex Van der spuy's "advanced game design with flash"
I am a developer working on a web online virutal world made in flash. I made a phone application (works similar to the phone in grand theft auto games). Anyway, when a message is sent we want to play this crazy animation of an envelope flying around and transforming with sparkles around it. It was laggy (especially on older computers) so I thought it would be a great chance to use blitting. However, the blitting animation actually plays slower than a regular movieclip!! What the heck is going on here? Is blitting only better for mobile devices and actually slower on computers? Maybe I am doing something wrong. Here is my code:
// THIS PART HAPPENS WHEN PHONE IT INITIALIZED
//**
//---------------- Blitting stuff ----------------------------------
// add this bitmap stage to the display list so we can see it
_bitmapStage = new BitmapData(550, 400, true, 0xD6D6D6);
_phoneItself.addChild(new Bitmap(_bitmapStage));
var _spritesheetClass:Class = getDefinitionByName("ESpritesheet_1") as Class;
_spritesheet = new _spritesheetClass() as BitmapData;
_envelopeBlit = new BlitSprite(_spritesheet, BlitConfig.envelopeAnimAry , _bitmapStage);
_envelopeBlit.x = -100;
_envelopeBlit.y = 0;
_envelopePlayTimer = new Timer(5, 0);
_envelopePlayTimer.addEventListener(TimerEvent.TIMER, onEnterTimerFrame);
_envelopeBlit.addEventListener("ENV_ANIM_DONE", onEnvAnimFinished);
// a "BlitSprite" is a class that I made. It looks like this:
package com.fs.util_j.blit_utils
{
import flash.display.BitmapData;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.geom.Point;
import flash.geom.Rectangle;
public class BlitSprite extends EventDispatcher
{
private var _fullSpriteSheet:BitmapData;
private var _rects:Array;
private var _bitmapStage:BitmapData;
private var pos:Point = new Point ();
public var x:Number = 0;
public var y:Number = 0;
public var _animIndex:
int = 0;
private var _count:int = 0;
public var animate:Boolean = true;
private var _whiteTransparent:BitmapData;
private var _envelopeAnimAry:Array;
private var _model:Object;
public function BlitSprite(fullSpriteSheet:BitmapData, envelopeAnimAry:Array, bitmapStage:BitmapData, model:Object = null)
{
_fullSpriteSheet = fullSpriteSheet;
_envelopeAnimAry = envelopeAnimAry;
_bitmapStage = bitmapStage;
_model= model;
init();
}
private function init():void
{
// _whiteTransparent = new BitmapData(100, 100, true, 0x80FFffFF);
this.addEventListener("ENV_ANIM_DONE", onEvnAnimDone);
}
protected function onEvnAnimDone(event:Event):void
{
}
public function render():void
{
// pos.x = x - _rects[_animIndex].width*.5;
// pos.y = y - _rects[_animIndex].width*.5;
// if (_count % 1 == 0 && animate == true)
// {
// trace("rendering");
if (_animIndex == (_envelopeAnimAry.length - 1) )
{
// _animIndex = 0;
dispatchEvent(new Event("ENV_ANIM_DONE", true));
animate = false;
// trace("!!!!animate over " + _model.animOver);
// if (_model != null)
// {
// _model.animOver = true;
// }
// trace("!!!!animate over " + _model.animOver);
}
else
{
_animIndex++;
}
pos.x = x + _envelopeAnimAry[_animIndex][1];
pos.y = y + _envelopeAnimAry[_animIndex][2];
_bitmapStage.copyPixels(_fullSpriteSheet, _envelopeAnimAry[_animIndex][0], pos, null, null, true);
}
}
}
// THIS PART HAPPENS WHEN PHONE'S SEND BUTTON IS CLICKED
_envelopeBlit.animate = true;
_envelopeBlit._animIndex = 0;
_darkSquare.visible = true;
_envelopePlayTimer.addEventListener(TimerEvent.TIMER, onEnterTimerFrame);
_envelopePlayTimer.start();
it also uses BlitConfig which stores the info about the spritesheet spit out by TexturePacker
package com.fs.pack.phone.configuration
{
import flash.geom.Rectangle;
public final class BlitConfig
{
public static var _sending_message_real_20001:Rectangle = new Rectangle(300,1020,144,102);
public static var _sending_message_real_20002:Rectangle = new Rectangle(452,1012,144,102);
public static var _sending_message_real_20003:Rectangle = new Rectangle(852,852,146,102);
public static var _sending_message_real_20004:Rectangle = new Rectangle(2,1018,146,102);
public static var _sending_message_real_20005:Rectangle = new Rectangle(702,822,148,102);
.
.
.
public static var _sending_message_real_20139:Rectangle = new Rectangle(932,144,1,1);
public static var envelopeAnimAry:Array = [
// rectangle, x offset, y offset
[ _sending_message_real_20001, 184,155],
[ _sending_message_real_20002, 184,155],
[ _sending_message_real_20003, 183,155],
[ _sending_message_real_20004, 183,155],
.
.
.
[ _sending_message_real_20139, 0,0]
]
public function BlitConfig()
{
}
}
}
EDIT:
Knowing that this is not mobile, my answer below is irrelevant. I will leave it there, though, in case someone is having trouble with blitting on mobile in the future.
With regards to this specific question, you are running your timer every 5ms. First off, the lowest range that a Timer is accurate is >15ms so that will never be a viable solution. For any Timer relating to displaying soemthing on the stage, you should never do it less than a single frame. (1000/stage.framerate. ~40ms for a 30fps app)
For blitting, the goal is to reduce calculations and rendering. The way you have this set up right now, it looks like you are blitting every 5ms. That is actually more than 8 times as often as the MovieClip is rendering. You should reduce how often you blit. Only do it when a change has actually been made beyond translation. Doing it any more often than that is overkill and the reason it is so slow (again, creating bitmaps is slow)
In general, you do not want to blit in an AIR for Mobile application (which I assume you are doing since you mentioned the phone being initialized). I'm not sure if it is okay to do it using other/native SDKs, but avoid it in AIR.
Essentially, it comes down to how blitting works. Blitting takes a screen capture and displays that on the stage rather than the actual object. In general, this is great. It means that your display objects, particularly vectors which are slow to render, have to render far less often. It is especially good when animating because an object tends to re-render every time it is translated in any way, but not a bitmap.
On mobile platforms, however, creating that bitmap is incredibly slow. I've never looked into how the SDK creates the Bitmaps, but it doesn't do it efficiently (it often makes me wonder if it does it pixel-by-pixel). On desktops, this is generally fine. There is plenty of CPU and plenty of RAM to make this happen quickly. On mobile, however, that luxury is not there at the moment. So when you blit and create that bitmap, it takes a while to run that process.
The problem is exacerbated on high-resolution screens. An app I developed from January to May of this year selectively used blitting to use filters in a GPU accelerated environment. On an iPad 2, the blitting took my app from 30fps to ~24fps. Not a big deal, not anything the user would notice. On an iPad 3 with retina display, however, it dropped down to 10fps. It makes sense when you think about it, as retina iPads have 4x as many pixels as non-retina iPads do.
If you do want to use blitting on mobile, I recommend a few things:
Use GPU rendering mode. Without it, you stand no chance. Be aware that, at least with pre-AIR 3.7, filters were not supported in GPU mode. I am unsure if that is still the case. You should avoid using filters on mobile regardless, though, as they are very slow to render
Make sure to test a release-mode application. Depending on build settings, the difference between debug mode and a release mode app can be substantial, especially on iOS. An app I just developed went from taking 2-3 seconds to create a new Flex View in debug mode to less than a frame (~40ms) to do it in release mode on an iPhone 4
Use blitting sparingly. Only do it where absolutely necessary
Look for ways to simplify your display list. It is easy to have an object with 40 children to create a button. Instead, look for ways to simplify that into fewer objects and fewer filters (even if removing a filter requires you add another object). I don't believe this will help with the actual blitting process, but it should help with rendering the objects in the first place.
So in general, use blitting sparingly on mobile because bitmap creation is slow.
I am using the JWPlayer source code for 6.0.2813 (http://developer.longtailvideo.com/trac/) and It seems the even though I have a movieclip and I added the jwplayer class as a child, the jwplayer creates itself as a child of the main stage, thus allowing it to expand to the bound of the stage and not my movieclip (which I want to be a resizeable/draggable container) in my flash.
I asked the forums for help but they said they never intended it this way and wasn't much help. I was hoping someone familar with the source code could point my in the right direction.
How can I get the JWPlayer to be contained to a movieclip?
Edit:
I made a little bit of progress.
I found the RootReference class in com/longtailvideo/jwplayer/utils/RootReference.as
public function RootReference(displayObj:DisplayObject) {
if (!RootReference.root) {
RootReference.root = displayObj.root;
RootReference.stage = displayObj.stage;
try {
Security.allowDomain("*");
} catch(e:Error) {
// This may not work in the AIR testing suite
}
}
}
And noticed that the RootReference.stage is where things get added as a child. RootReference.stage = displayObj.stage; where the player class object is sent as displayObj I changed it to be RootReference.stage = MovieClip(root).gui.video_container;
Then throughout the code RootReference.stage.stageHeight and RootReference.stage.stageWidth was used so I switched it to RootReference.stage.height and RootReference.stage.width. This got it to compile and now the video is within the container but the video's top left is center on my video_container's center and the video isn't resized to the size of my container, but rather the size of the video. Also the controls are completely messed up.
But I was able to resize and move the video around
Assuming my testing scenarios are representative of your use-cases, I think I managed to hack up a work around.
The gist of the approach is to replace RootReference.root and RootReference.stage with a fake stage object that you control. Because most of the jwPlayer classes refer to those static variables instead of their own root and stage variables, this seems to work, for the most part. What ended up being the most complicated issue was working with the Stage.stageVideo objects, which I think are the hardware accelerated video objects. These are always attached to the stage and thus weren't compatible with the fake stage object. The main issue with those is positioning, and I have it mostly worked out, but there is still one glitch which I'll describe later but it should be ok, now.
The jwPlayer embed script was causing a lot of problems, so to get started I switched to normal SWFObject-based embedding and added a javascript function to the page called getFlashvars() that returned the configuration settings. Then, I changed the com.longtailvideo.jwplayer.utils.Configger.loadExternal() method to the following:
private function loadExternal():void {
if (ExternalInterface.available) {
try {
//var flashvars:Object = ExternalInterface.call("jwplayer.embed.flash.getVars", ExternalInterface.objectID);
var flashvars:Object = ExternalInterface.call("getFlashvars");
if (flashvars !== null) {
// TODO: add ability to pass in JSON directly instead of going to/from a string
for (var param:String in flashvars) {
setConfigParam(param, flashvars[param]);
}
dispatchEvent(new Event(Event.COMPLETE));
return;
}
} catch (e:Error) {}
}
}
That's something you probably don't have to deal with per not using a webpage.
The fake stage class is called StageInterceptor and is a singleton. To apply it, there were minor changes in the RootReference class:
package com.longtailvideo.jwplayer.utils {
import flash.display.DisplayObject;
import flash.display.Stage;
import flash.system.Security;
// added --------
import somePackage.StageInterceptor;
/**
* Maintains a static reference to the stage and root of the application.
*
* #author Pablo Schklowsky
*/
/* Modified for a stackoverflow question: http://stackoverflow.com/questions/13325318/jwplayer-trying-to-bound-the-video-player-inside-my-own-container */
public class RootReference {
/** The root DisplayObject of the application. **/
public static var root:DisplayObject;
// altered --------
/** A reference to the stage. **/
private static var _stage:StageInterceptor;
// altered --------
public static function get stage():StageInterceptor {
return _stage;
}
public function RootReference(displayObj:DisplayObject) {
if (!RootReference.root) {
// altered --------
RootReference.root = StageInterceptor.singleton;
RootReference._stage = StageInterceptor.singleton;
try {
Security.allowDomain("*");
} catch(e:Error) {
// This may not work in the AIR testing suite
}
}
}
}
}
Also, I removed the set stage() setter method from the class.
In the document class, I have the following code. The MouseEvent.CLICK handler is to test positioning and re-sizing the movie. The only thing you really need are the first few lines:
// add StageInterceptor to the display tree
addChild(StageInterceptor.singleton);
// add the jwPlayer:
var p:Player = new Player();
StageInterceptor.singleton.addChild(p);
// for testing only:
stage.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void {
var stg:StageInterceptor = StageInterceptor.singleton;
if (e.altKey) {
// click + alt: ignored (so can play, etc)
return;
} else if (e.shiftKey) {
// click + shift: resizes
stg.width = e.stageX - stg.x;
stg.height = e.stageY - stg.y;
} else {
// click: moves video
stg.x = e.stageX;
stg.y = e.stageY;
}
});
I put StageInterceptor in the package somePackage. It looks like this:
package somePackage
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.InteractiveObject;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.media.StageVideo;
public class StageInterceptor extends Sprite
{
private static var _singleton:StageInterceptor = new StageInterceptor();
public static function get singleton():StageInterceptor {
return _singleton;
}
private var _bg:Bitmap;
public function StageInterceptor()
{
super();
scrollRect = new Rectangle(0, 0, 500, 500);
var bmpData:BitmapData = new BitmapData(500, 500, false, 0);
_bg = new Bitmap(bmpData);
_bg.alpha = 0.1;
_bg.cacheAsBitmap = true;
addChild(_bg);
if (stage) {
initOnStage();
} else {
addEventListener(Event.ADDED_TO_STAGE, initOnStage);
}
}
private function initOnStage(e:Event = null):void {
if (e) {
removeEventListener(Event.ADDED_TO_STAGE, initOnStage);
}
stage.addEventListener(Event.RESIZE, onStageResized);
}
private function onStageResized(e:Event):void {
e.stopImmediatePropagation();
dispatchEvent(new Event(Event.RESIZE));
updateStageVids();
}
public function updateStageVids():void {
if (stage.stageVideos.length > 0) {
for each (var sv:StageVideo in stage.stageVideos) {
if (!sv.videoWidth || !sv.videoHeight) {
continue;
}
var rect:Rectangle = stretch(sv.videoWidth, sv.videoHeight, width, height);
rect.x = Math.max(0, x + 0.5 * (width - rect.width))
rect.y = Math.max(0, y + 0.5 * (height - rect.height));
sv.viewPort = rect;
}
}
}
override public function get width():Number {
return scrollRect.width;
}
override public function set width(value:Number):void {
if (value != width) {
_bg.width = value;
scrollRect = new Rectangle(0, 0, value, scrollRect.height);
dispatchEvent(new Event(Event.RESIZE));
updateStageVids();
}
}
override public function set height(value:Number):void {
if (value != height) {
_bg.height = value;
scrollRect = new Rectangle(0, 0, scrollRect.width, value);
dispatchEvent(new Event(Event.RESIZE));
updateStageVids();
}
}
override public function get height():Number {
return scrollRect.height;
}
public function get stageWidth():Number {
return scrollRect.width;
}
public function get stageHeight():Number {
return scrollRect.height;
}
public function get scaleMode():String {
return stage.scaleMode;
}
public function set scaleMode(value:String):void {
stage.scaleMode = value;
}
public function get displayState():String {
return stage.displayState;
}
public function set displayState(value:String):void {
stage.displayState = value;
}
public function get focus():InteractiveObject {
return stage.focus;
}
public function set focus(value:InteractiveObject):void {
stage.focus = value;
}
public function get stageVideos():* {
return stage.stageVideos;
}
override public function set x(value:Number):void {
if (value != x) {
super.x = value;
updateStageVids();
}
}
override public function set y(value:Number):void {
if (value != y) {
super.y = value;
updateStageVids();
}
}
/**
* Copied from com.longtailvideo.jwplayer.utils.Stretcher, modified to only
* do 'uniform' stretch and to return a Rectangle class.
**/
public static function stretch(elmW:Number, elmH:Number, availW:Number, availH:Number):Rectangle {
var scale:Number = Math.min(availW / elmW, availH / elmH);
elmW = Math.round(elmW * scale);
elmH = Math.round(elmH * scale);
return new Rectangle(0, 0, elmW, elmH);
}
}
}
The issue that remains has to do with the positioning of video instances when they are initialized. I think simply calling StageInterceptor.singleton.updateStageVids(); at the right point will do the trick, but I'm not sure. The edit below covers how this was addressed.
I'm not sure how well this will work if you're not using stageVideo. But, with any luck, this will move things in the right direction.
Edit:
I've updated the StageInterceptor class to do a better job scaling and positioning the video.
Also, it looks like the initial position of videos (at least when it's a stageVideo, is that what you're using?) can be corrected by a small edit in the com.longtailvideo.jwplayer.media.VideoMediaProvider class. Adding import somePackage.StageInterceptor; to the import statements at the top and then replacing this line (link to source):
_stage.viewPort = new Rectangle(_media.x,_media.y,_media.width,_media.height);
To:
StageInterceptor.singleton.updateStageVids();
So the method looks like:
/** Resize the video or stage.**/
override public function resize(width:Number, height:Number):void {
if(_media) {
Stretcher.stretch(_media, width, height, _config.stretching);
if (_stage) {
//_stage.viewPort = new Rectangle(_media.x,_media.y,_media.width,_media.height);
StageInterceptor.singleton.updateStageVids();
}
}
}
This should do the trick, but I haven't tested it for non stageVideos. And, this update also assumes you're playing videos progressively, not using RTMP media.
Edit:
To enable moving and resizing the player with non-StageVideo videos, but still progressively loaded, the contents of the com.longtailvideo.jwplayer.view.View.resizeMasker() method need to be either commented out or deleted:
protected function resizeMasker():void {
/*
if (_displayMasker == null)
setupDisplayMask();
_displayMasker.graphics.clear();
_displayMasker.graphics.beginFill(0, 1);
_displayMasker.graphics.drawRect(_components.display.x, _components.display.y, _player.config.width, _player.config.height);
_displayMasker.graphics.endFill();
*/
}
I also want to mention the open source version of the jwPlayer is governed under the Creative Commons license, as noted on their site:
JW Player 6 — Open Source Edition
The use of the JW Player Open Source edition is governed by a Creative Commons license. In short:
JW Player Open Source - You can use, modify, copy, and distribute this edition as long as it's for non-commercial use, you provide attribution, and share under a similar license.
The license summary and full text can be found here: CC BY-NC-SA 3.0
I'll address the jwPlayer portion of your question since flash is not my forte.
The problem here is jwPlayer is not a simple flash player, but also a HTML5 Multimedia Player as well.
Solution 1: SWFObject embedded in your Flash Object
Since jwPlayer is already compatible with SWFObject, use that (i.e., swfobject.js) as a mediator to load the player.swf file (aka jwPlayer) into your flash stage. To be sure, SWFObject acts as a container and will be the "bounded item" in your stage, as opposed to using jwPlayer directly.
Here is an online demo illustrating this solution except it's using a simple flash video player.
Flash Web Site with embedded SWFObject Logo Playing Music Video
Flash Web Site Documentation on swfObject
Note the HTML source page for that flash website shows RockOnFlashLogo.swf as the file being shown in the browsers entire viewport. Looking deeper, it's written in AS3.
Unlike jwPlayer v4 where many ideas floated on the internet to embed that version into flash websites due to its lax security, I think you'll have issues with current jwPlayer license checking, webpage Ready Event Listeners, and popular plugin integration... not to mention issues that may arise from streaming video content.
IMHO, the newer jwPlayer API and Player are intended to be use via webpage installation.
Solution 2: SWFObject On-Top of your Flash Object
This method treats jwPlayer how it was meant to be used; as a webpage installation. My motivation came from this online demo for Google Chrome Experiment | The Wilderness Downtown.
That demo places strategically synchronized browser windows on-top of the main browser window. Although the main browser window is in charge, all windows make up the entire experience. The same method, but flash flavored, can be done with your current project with excellent results.
Your Flash Object is in charge and contains within an interactive frame that is allocated for the jwPlayer webpage component. To be sure, this interactive frame for jwPlayer can accept relocation (e.g., via dragging frame edges) and resize (e.g, frame has resize-icon bottom-right) which is then relayed to the webpage component (i.e., player.swf) via SWFObject standard embed techniques (i.e., location and size set with jQuery).
Here's a basic cross-section of a webpage for three layered items:
The black layer is the HTML of the webpage. The red layer is your flash object which contains also has the built-in interactive frame shown in aqua. The green top layer is the SWFObject for jwPlayer's player.swf file.
Here's how it would work from jwPlayer to your flash object:
1. Webpage jwPlayer API has event listener active and can accept JavaScript.
2. Then jwPlayer API receives 'play' status from player, updates player event status.
3. Player Event Status is true for Play, and therefore triggers conditional if statement.
4. That if statement then transmits JavaScript to your flash object, indicating play mode is true.
5. Your flash object receives this JavaScript of play event, and dims the stage, less the aqua frame.
Here's how it would work from your flash object to jwPlayer:
1. The aqua frame has user interaction when it's moved to left side of stage.
2. Your AS3 code moves the aqua frame accordingly, while sending out JavaScript of that location.
3. Webpage receives JavaScript and invokes function to position jwPlayer player at new location.
Tip: If using a custom jwPlayer Skin, incorporate that skin theme into your flash object for a uniform look.
The benefit of this scenario is that jwPlayer maintains 100% integrity while both these flash objects work in tandem on your webpage. No hacks, no breakage, no unforeseen consequences, and no headaches... it's standard jwPlayer API and AS3 markup in use.
Hovering over the jwPlayer itself is 100% jwPlayer, while being bound to your flash object indirectly.
Per your written comments that JW Player will not have any access to JavaScript and will be using Firefox Source that is a specialized 3D Game/Chat Engine without access to any DOM elements outside the player, the best solution is to use JW Player Enterprise Edition.
That solution will put you in touch with the Marketing & Engineering department which can provide a turnkey solution to have JW Player integrated into your own product.
Click the image below which includes Licensing information as well:
I have two swfs:
application swf
p2p client swf that allows to load data using rtmfp replication
technology (through cirrus service)
The main idea is to have one p2p loader on the certain domain that will able to work in p2p network without asking many times for permission for each domain, so for instance:
application 1 (http://domain1.com/app.swf) |
application 2 (http://domain2.com/app.swf) | <--> p2p data loader (http://domainp2p.com/p2pcli.swf)
application N (http://domainN.com/app.swf) |
The p2p client loads binary data by request, content really does not matter I believe.
So, I load p2pclient swf using following class (app.swf)
public class ClientLoader {
// .. some code
public function load(cb:Function, err:Function):void
{
_cb = cb;
_err = err;
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, _onLoaded);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, _onIoError);
loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _onSecurityError);
// note that context has neither application domain nor security domain
loader.load(new URLRequest(_url), new LoaderContext());
}
private function _onLoaded(e:Event):void
{
trace("Loaded. Connecting to the p2p network...");
_client = e.target.content;
_client.addEventListener(Event.CONNECT, _onClientReady);
_client.connect();
}
private function _onClientReady(e:Event):void
{
_cb(_client);
}
}
}
The p2pclient itself (p2pcli.swf):
public class P2P extends Sprite
{
public function SqP2P() {
Security.allowDomain("*");
}
public function connect():void
{
_connection = new NetConnection();
_connection.addEventListener(NetStatusEvent.NET_STATUS, _netStatus);
_connection.connect(CIRRUS_ADDRESS, CIRRUS_KEY);
// after successful connect this method called
_loadGroup();
}
private method _loadGroup():void
{
var spec:GroupSpecifier = new GroupSpecifier(_name);
spec.serverChannelEnabled = true;
spec.objectReplicationEnabled = true;
_group = new NetGroup(connection, spec.groupspecWithAuthorizations());
_group.addEventListener(NetStatusEvent.NET_STATUS, _netStatus);
}
private function _netStatus(event:NetStatusEvent):void
{
trace("NetStatusEvent:", event.info.code);
}
}
But it looks like that Flash Player ignores the security session and is trying to save the pop-up settings for the domain that app.swf belongs to, but not for the p2pcli.swf domain. Why?!
I have absolutely same code, but p2pcli.swf replaced with swf that stores data in Local Shared Object and all the domain1-2-N.com has access to it.
Any ideas?
I know, my English is crap :(
I really am not totally sure, but I'll throw my answer out there in case it is helpful.
Based on the general purpose of such security messages, I'm not entirely sure you CAN keep that dialog from showing up. In some cases, I'm certain Peer Assisted Networking can be a security risk for some people (and anyway, it is using their bandwidth.) The settings for turning on and off that notification are user-side, in the Flash settings dialog (Control Panel in Windows 7...), thus that hints that it is inherently hardwired into the Flash platform.
Of course, since I'm more of an Adobe AIR specialist, I could be completely wrong...for your project's sake, I'm sincerely hoping I AM!
And, for the record, your English was almost perfect. I tweaked one paragraph for clarity, but otherwise, spot on. :D
I'm implementing an Augmented Reality application for android using Flash. In order to get the application working on my Android Phone (nexus One) the Phone Camera must be activated as well. So I need 2 layers one for the background which is the feed of my phone camera and an other one on top of it which is the view from away3d in this case.
So setting up a BitmapData object to hold the information of the most recent webcam still-frame I can make this work.
If I use papervision3D library and FLARToolkit we setting up the BitmapData using the following part of the code found from this video tutorial:
//import libraries
import org.libspark.flartoolkit.core.raster.rgb.FLARRgbRaster_BitmapData;
import org.libspark.flartoolkit.detector.FLARSingleMarkerDetector;
private function setupCamera():void
{
vid = new Video(640, 480);
cam = Camera.getCamera();
cam.setMode(320, 240, 10);
vid.attachCamera(cam);
addChild(vid);
}
private function setupBitmap():void
{
bmd = new BitmapData(640, 480);
bmd.draw(vid);
raster = new FLARRgbRaster_BitmapData(bmd);
detector = new FLARSingleMarkerDetector(fparams, mpattern, 80);
}
private function loop(e:Event):void
{
if(detector.detectMarkerLite(raster, 80) && detector.getConfidence() > 0.5)
{
vp.visible = true;
detector.getTransformMatrix(trans);
container.setTransformMatrix(trans);
bre.renderScene(scene, camera, vp);
}
else{
vp.visible = false}
}
catch(e:Error){}}}}
However, to implement my application Im using Away3D engine and FLARManager and the way of doing that is very different as I can understand. I have implement the following code but the only think it does is just show the Flash Camera in the front of the 3D view and I can't check if my application is work or not since it doesn't show me any 3D Object when I place the marker in front of the screen.
My code is:
//Setting Up Away3DLite Camera3D
import com.transmote.flar.camera.FLARCamera_Away3DLite;
private var camera3D:FLARCamera_Away3DLite;
this.camera3D = new FLARCamera_Away3DLite(this.flarManager, new Rectangle(0, 0, this.stage.stageWidth, this.stage.stageHeight));
//Setting Up the bitmapData
private function bitmap():void
{
c = Camera.getCamera();
c.setMode(320,240,10)
this.v.attachCamera(c);
addChild(this.v);
bmd = new BitmapData(640,480);
bmd.draw(this.v);
}
Can you please help me to find out how can I combine those two?
I will really appreciate any advice i can get from you.
Thank you
To isolate your problem, I'd try to break these two things up and make sure each part works first. It's sounds like you've got the camera part working, try doing just some 3D (no AR) draw a cube or something. Then try implementing the AR but have it do something simple like trace something out or making an object visible or invisible. Then start combining them.