Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] VideoTexture flickering with artifacts on start if any DisplayObject with some visual added on stage #2924

Closed
itlancer opened this issue Nov 16, 2023 · 1 comment
Labels

Comments

@itlancer
Copy link

Problem Description

VideoTexture flickering with artifacts on start if any DisplayObject with some visual added on stage for Android.
Seems like small copy of whole Stage shown for a moment. If you have any graphics on Stage - such elements will be captured inside VideoTexture area before it will be started.

Tested with multiple AIR 50.2.x versions, even with latest AIR 50.2.3.8 with different AIR applications, devices, architectures and videos.
Tested with pure Stage3D and with Starling.
Same issue in all cases.
With Windows and macOS all works fine.
Cannot check with iOS because of #1939
There is no such issue using Video object.

Any of DisplayObject (Sprite, Shape and even "empty" Bitmap) added on stage cause VideoTexture flickering/artifacts on start.
Also there is no such issues using "empty" Sprite/Shape. Or using Sprite/Shape with transparent (alpha 0) Graphics.
Also there is no issue if visible=false for such objects or if they have negative coordinates like:

sprite.x = -1080;
sprite.y = -1080;

Any "big" positive coordinates cause issue.
cacheAsBitmap, cacheAsBitmapMatrix and different depthAndStencil values didn't help to resolve this issue.

Related issues:
#2910
#2396
#2017
#392
#151
#87
#81

Steps to Reproduce

Launch application with code below with any Android device. It just play video using VideoTexture in a loop. Sprite, Shape rectangles and "empty" Bitmap added over it as DisplayObjects.

Application example with sources, sample video and demo video attached.
android_videotexture_artifacts_displaylist_bug.zip

package {
	import flash.display.Sprite;
	import flash.display.Stage3D;
	import flash.events.Event;
	import flash.events.NetStatusEvent;
	import flash.net.NetStream;
	import flash.display3D.Context3D;
	import flash.display3D.IndexBuffer3D;
	import flash.geom.Matrix3D;
	import flash.net.NetConnection;
	import flash.display3D.textures.VideoTexture;
	import com.adobe.utils.AGALMiniAssembler;
	import flash.display3D.Context3DProgramType;
	import flash.display3D.Context3DVertexBufferFormat;
	import flash.display3D.VertexBuffer3D;
	import flash.display3D.Program3D;
	import flash.display3D.Context3DProfile;
	import flash.display.Bitmap;
	import flash.desktop.NativeApplication;
	import flash.desktop.SystemIdleMode;
	import flash.display.Shape;
	
	public class AndroidVideoTextureArtifactsDisplayListBug extends Sprite {
		private var stage3D:Stage3D;
		private var context3D:Context3D;
		private var indexbuffer:IndexBuffer3D;
		private var matrix:Matrix3D;
		private var _netConnection:NetConnection;
		private var _netStream:NetStream;
		private var videoTexture:VideoTexture;
		
		public function AndroidVideoTextureArtifactsDisplayListBug() {
			NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
			
			//Any of these DisplayObjects ("empty" Bitmap, Sprite and Shape) cause VideoTexture flickering/artifacts on start
			var bitmap:Bitmap = new Bitmap();
			addChild(bitmap);
			
			var sp:Sprite = new Sprite();
			sp.graphics.beginFill(0xff0000, 0.5);//If alpha not 0 - issue exists
			sp.graphics.drawRect(0, 0, 100, 100);
			sp.graphics.endFill();
			addChild(sp);
			
			var shape:Shape = new Shape();
			shape.graphics.beginFill(0xffff00, 0.5);//If alpha not 0 - issue exists
			shape.graphics.drawRect(0, 100, 100, 100);
			shape.graphics.endFill();
			addChild(shape);
			
			
			stage3D = stage.stage3Ds[0];
			stage3D.addEventListener(Event.CONTEXT3D_CREATE, contextCreated);
			stage3D.requestContext3D();
		}
		
		private function contextCreated(event:Event):void {
			context3D = stage.stage3Ds[0].context3D;
			context3D.enableErrorChecking = true;
			context3D.configureBackBuffer(640, 480, 4, true, true, true);
			
			trace(context3D.driverInfo, context3D.profile);
			
			playVideo();
		}
		
		private function playVideo():void {
			removeEventListener(Event.ENTER_FRAME, enterFrame);
			
			if (videoTexture != null) {
				videoTexture.removeEventListener(Event.TEXTURE_READY, renderState);
				videoTexture.attachNetStream(null);
				videoTexture.dispose();
				videoTexture = null;
			}
			if (_netStream != null) {
				_netStream.removeEventListener(NetStatusEvent.NET_STATUS, netStream_netStatus);
				_netStream.close();
				_netStream = null;
			}
			if (_netConnection != null) {
				_netConnection.removeEventListener(NetStatusEvent.NET_STATUS, netConnection_netStatus);
				_netConnection.close();
				_netConnection = null;
			}
			
			
			var vertices:Vector.<Number> = Vector.<Number>([
			1, -1, 0, 1, 0,
			1, 1, 0, 1, 1,
			-1, 1, 0, 0, 1,
			-1,-1, 0, 0, 0
			]);
			
			var vertexbuffer:VertexBuffer3D = context3D.createVertexBuffer(4, 5);
			vertexbuffer.uploadFromVector(vertices, 0, 4);
			
			indexbuffer = context3D.createIndexBuffer(6);
			indexbuffer.uploadFromVector(Vector.<uint>([0, 1, 2, 2, 3, 0]), 0, 6);
			
			var vertexShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
			vertexShaderAssembler.assemble(Context3DProgramType.VERTEX, "m44 op, va0, vc0\n" + "mov v0, va1");
			
			var fragmentShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
			fragmentShaderAssembler.assemble( Context3DProgramType.FRAGMENT, "tex ft1, v0, fs0 <2d,linear, nomip>\n" + "mov oc, ft1");
			
			var program:Program3D = context3D.createProgram();
			program.upload( vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode);
			
			context3D.setVertexBufferAt(0, vertexbuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
			context3D.setVertexBufferAt(1, vertexbuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
			
			videoTexture = context3D.createVideoTexture();
			context3D.setTextureAt(0, videoTexture);
			
			context3D.setProgram(program);
			matrix = new Matrix3D();
			matrix.appendScale(1, -1, 1);
			context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true);
			
			
			_netConnection = new NetConnection();
			_netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnection_netStatus);
			_netConnection.connect(null);
		}
		
		private function netConnection_netStatus(e:NetStatusEvent):void {
			if (e.info.code == "NetConnection.Connect.Success"){
				_netStream = new NetStream(_netConnection);
				_netStream.addEventListener(NetStatusEvent.NET_STATUS, netStream_netStatus);
				_netStream.client = {onMetaData:getMeta, onPlayStatus:onPlayStatus};
				_netStream.play("neon.mp4");
				videoTexture.attachNetStream(_netStream);
				
				videoTexture.addEventListener(Event.TEXTURE_READY, renderState);
			}
		}
		
		private function netStream_netStatus(event:NetStatusEvent):void {
			trace(event.info.code);
			switch (event.info.code){
				case "NetStream.Play.StreamNotFound":
					trace("Stream not found");
					break;
				case "NetStream.Play.Stop":
					playVideo();
					break;
				default:
					break;
			}
		}

		private function getMeta(mdata:Object):void {
			trace("metadata");
		}

		private function onPlayStatus(infoObject:Object):void {
			trace("onPlayStatus", infoObject.code);
		}

		private function renderState(e:Event):void {
			videoTexture.removeEventListener(Event.TEXTURE_READY, renderState);
			trace("renderState");
			render();
			addEventListener(Event.ENTER_FRAME, enterFrame);
		}
	
		private function enterFrame(event:Event):void {
			render();
		}

		private function render():void {
			context3D.clear(1, 0, 0, 1);
			context3D.drawTriangles(indexbuffer);
			context3D.present();
		}

	}
}

Actual Result:
On every video playback start you will see flickering with artifacts:

android_videotexture_artifacts_displaylist_bug.mp4

No errors in Scout or LogCat detected (except #2910).

Expected Result:
Application playback video in a loop without flickering/artifacts.

Known Workarounds

none

@itlancer itlancer added the Bug label Nov 16, 2023
@itlancer
Copy link
Author

Fixed. Tested with latest AIR 50.2.4.4.
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant