actionscript-3airgpuaway3dstagevideo

VideoTexture downgrades to software Rendering in Air


I'm running a VideoTexture in Away3D, which usually runs fine. I've been attempting to reduce the black gap between videos and trying to get them to line up nicely, however my attempts have lead to video sometimes downgrading to software rendering on mobile, especially when it first starts.

I'm using Away3D with Starling and a shared stage3DProxy.

Here's how I set the video up

            sphereGeometry = new SphereGeometry(5000, 64, 48);
            panoTexture2DBase = new NativeVideoTexture(Model.config.getAssetUrl(Model.currentScene.video), true, true);

            panoTexture2DBase.addEventListener(NativeVideoTexture.VIDEO_START,function(e:Event =null){setTimeout(onVideoStart,1000)});
            panoTextureMaterial = new TextureMaterial(panoTexture2DBase, false, false, false);

            panoVideoMesh = new Mesh(sphereGeometry, panoTextureMaterial);
            panoVideoMesh.scaleX *= -1;

            panoVideoMesh.rotate(Vector3D.Y_AXIS,-90);

            scene.addChild(panoVideoMesh);
            view.render();

            panoTexture2DBase.player.pause();

I use an Away3d NativeVideoTexture to load the netstream. Subsequent videos are generally fine, and hardware accelerated. it's just the first one that always downgrades.

My NativeVideoTexture class

override protected function createTexture(context:Context3D):TextureBase
    {
        try
        {
            trace("Context3D.supportsVideoTexture", Context3D.supportsVideoTexture)

            if (!Context3D.supportsVideoTexture)
            {
                throw new Error("flash.display3D.textures.VideoTexture not supported");
                return null;
            }

            texture = context.createVideoTexture();
            texture.attachNetStream(_player.ns);

            _player.ns.addEventListener(NetStatusEvent.NET_STATUS, netstat);
            _player.ns.seek(1);
            texture.addEventListener(Event.TEXTURE_READY, onTextureReady);
            texture.addEventListener(VideoTextureEvent.RENDER_STATE, onRenderState);

            if (_autoPlay) _player.play();

        }
        catch (e:Error)
        {
            trace(e, e.getStackTrace());
        }

        return texture;
    }

    private function onMetaData(metaData:Object):void
    {
        duration = metaData.duration;  

    }

    private function onTextureReady(e:Event):void
    {
    //  trace("NativeVideoTexture.onTextureReady()");
        if(_player.duration)
            if(_player.ns.time > _player.duration - 1){
                _player.pause();
                dispatchEvent(new Event(VIDEO_STOP));
                _player.seek(0);
            }
            else if(_player.ns.time > 0.01 && waitingForBuffer){
                dispatchEvent(new Event(VIDEO_START));
                waitingForBuffer = false;
            }

    }




    private function onRenderState(e:VideoTextureEvent):void
    {
        trace(e.status);
        if (e.status == VideoStatus.SOFTWARE)
        {
            trace("Indicates software video decoding works.")
        }
        if (e.status == VideoStatus.ACCELERATED)
        {
            trace("Indicates hardware-accelerated (GPU) video decoding works.")
        }
        if (e.status == VideoStatus.UNAVAILABLE)
        {
            trace("Indicates Video decoder is not available.")
        }
    }

Can anyone help me work out why the first video always software renders?

EDIT: I've made some progress

Sometimes it starts in GPU mode, sometimes in software. Is there anything that would cause that?


Solution

  • Hacky but it works.

    If it's going to software render, stop and restart video until it renders on the GPU. Only seems to need it a few times.