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 using cause ArgumentError: Error #3672 with low performance devices #2837

Closed
itlancer opened this issue Sep 19, 2023 · 1 comment

Comments

@itlancer
Copy link

Problem Description

VideoTexture using cause ArgumentError: Error #3672 with low performance Android devices.
Its hard to 100% reproduce it with pure Stage3D. But it constantly reproducible with video playback in loop simple case using Starling.
Using pure Stage3D it could takes up to 20 minutes to catch such error.

Tested with multiple AIR versions (even with latest AIR 50.2.3.5) with different AIR applications and different Android devices, versions with different architectures.
Same problem in all cases for some low performance devices such as x96mini, x96 Max Plus and other Android TV Boxes with Amlogic S905X3, Amlogic S905Y2 and similar CPUs.
There is no such issue with other platforms (Windows, macOS, iOS).

This issue raised many times earlier:
Gamua/Starling-Framework#1083
Gamua/Starling-Framework#757
Gamua/Starling-Framework#676
https://tracker.adobe.com/#/view/AIR-4198290
https://tracker.adobe.com/#/view/AIR-4198479
https://tracker.adobe.com/#/view/AIR-4198538
https://tracker.adobe.com/#/view/AIR-4198790

Other related issues:
#2835
#2825
#2268
#2125
#1174
#1159
#587
#554
#92
#81
#16

Steps to Reproduce

Launch application with code below with any Android device. It just play video by VideoTexture in a loop.
Note that on video second play this sample will crashes: #2835

Application example with sources, Scout log and video attached.
android_videotexture_argumenterror_3672_2.zip

package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.NetStatusEvent;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import starling.core.Starling;
	import starling.display.Image;
	import starling.textures.Texture;
	
	public class AndroidVideoTextureArgumentError3672 extends Sprite {
		private var _netConnection:NetConnection;
		private var _netStream:NetStream;
		
		private var _videoImage:Image;
		private var _videoTexture:Texture;
		
		public function AndroidVideoTextureArgumentError3672() {
			addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event):void {
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			StarlingManager.instance.addEventListener(Event.COMPLETE, starling_complete);
			StarlingManager.instance.init(stage);
		}
		
		private function starling_complete(e:Event):void {
			playVideo();
		}
		
		private function playVideo():void {
			_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.client = {onMetaData:getMeta};
				_netStream.addEventListener(NetStatusEvent.NET_STATUS, netStream_netStatus);
				
				attachNetStream(_netStream);
				_netStream.play("video.mp4");
			}
		}
		
		private function attachNetStream(netStream:NetStream):void {
			if (netStream != null){
				try {
					_videoTexture = Texture.fromNetStream(netStream, Starling.current.contentScaleFactor, onTextureComplete);
				} catch (e:Error) {
					trace("video texture creating error", e.message, e.errorID);
				}
			}
		}
		
		private function disposeData():void {
			if (_videoImage != null) {
				if (_videoImage.parent) {
					_videoImage.parent.removeChild(_videoImage);
				}
				_videoImage.dispose();
				_videoImage = null;
			}
			if (_videoTexture != null) {
				_videoTexture.dispose();//This ilne cause crash
				_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;
			}
		}

		/**
		 * On Starling Texture complete
		 */
		private function onTextureComplete(t: Texture):void {
			_videoImage = new Image(_videoTexture);
			_videoImage.width = 640;
			_videoImage.height = 480;

			StarlingManager.instance.root.addChild(_videoImage);
		}
		
		private function netStream_netStatus(e:NetStatusEvent):void {
			trace(e.info.code);
			if (e.info.code == "NetStream.Play.Stop"){
				disposeData();
				playVideo();
			}
		}

		private function getMeta(mdata:Object):void { }
		
	}
}
package {
	import flash.display.Stage;
	import flash.display.Stage3D;
	import flash.display3D.Context3DProfile;
	import flash.display3D.Context3DRenderMode;
	import flash.events.ErrorEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.geom.Rectangle;

	import starling.core.Starling;
	import starling.display.Sprite;
	import starling.events.Event;
	
	public class StarlingManager extends EventDispatcher {

		private static const MAX_VIEW_PORT_SIZE:Number = 16384;
		private static const MIN_VIEW_PORT_SIZE:Number = 32;

		private static var _instance:StarlingManager;

		public static function get instance():StarlingManager {
			if (_instance == null) {
				_instance = new StarlingManager();
			}
			return _instance;
		}

		private var _waiting:Boolean;
		private var _inited:Boolean;
		private var _stage:Stage;
		private var _starling:Starling;

		public function StarlingManager() {}

		/**
		 * Initialization
		 *
		 * @param	stage
		 */
		public function init(stage:Stage):void {
			if (!_inited && !_waiting) {
				_waiting = true;
				_stage = stage;
				Starling.multitouchEnabled = true;

				stage3DReady(stage.stage3Ds[0]);
			}
		}

		private function stage3DReady(stage3D:Stage3D):void {
			var contextProfiles:Array = [
				Context3DProfile.BASELINE,
				Context3DProfile.BASELINE_EXTENDED,
				Context3DProfile.STANDARD,
				Context3DProfile.STANDARD_CONSTRAINED,
				Context3DProfile.STANDARD_EXTENDED
			];

			_starling = new Starling(Sprite, _stage, null, stage3D, Context3DRenderMode.AUTO, contextProfiles);
			_starling.enableErrorChecking = true;

			_starling.addEventListener(starling.events.Event.ROOT_CREATED, starling_rootCreated);
			_starling.supportHighResolutions = true;
			_starling.start();

			_stage.addEventListener(flash.events.Event.RESIZE, stage_resizeHandler, false, int.MAX_VALUE);
		}

		private function stage3D_error(e:flash.events.ErrorEvent):void {
			trace("stage3D_error", e.errorID, e.text);
		}

		private function starling_rootCreated(e:starling.events.Event):void {
			_inited = true;
			_waiting = false;
			invalidate();
			dispatchEvent(new flash.events.Event(flash.events.Event.COMPLETE));
		}

		/**
		 * Update on resize
		 * @param	event
		 */
		private function stage_resizeHandler(event:flash.events.Event):void {
			invalidate();
		}

		private function invalidate():void {
			const width:Number = _stage.stageWidth;
			const height:Number = _stage.stageHeight;

			_starling.stage.stageWidth = width;
			_starling.stage.stageHeight = height;

			const viewPort:Rectangle = _starling.viewPort;
			viewPort.width = width;
			viewPort.height = height;

			if (viewPort.width < MIN_VIEW_PORT_SIZE) {
				viewPort.width = MIN_VIEW_PORT_SIZE;
			} else if (viewPort.width > MAX_VIEW_PORT_SIZE) {
				viewPort.width = MAX_VIEW_PORT_SIZE;
			}
			if (viewPort.height < MIN_VIEW_PORT_SIZE) {
				viewPort.height = MIN_VIEW_PORT_SIZE;
			} else if (viewPort.height > MAX_VIEW_PORT_SIZE) {
				viewPort.height = MAX_VIEW_PORT_SIZE;
			}

			_starling.viewPort = viewPort;
		}
	
		public function get root():Sprite { return _starling.root as Sprite; }

	}
}

Actual Result:
ArgumentError: Error #3672 just after start video playback:

Exception: ArgumentError
flash.display3D::Context3D/createVertexBuffer
starling.rendering::VertexData/createVertexBuffer
starling.rendering::Effect/uploadVertexData
starling.display::MeshBatch/syncVertexBuffer
starling.display::MeshBatch/render
starling.rendering::Painter/drawBatch
BatchProcessor/finishBatch
starling.rendering::Painter/finishFrame
starling.core::Starling/render
starling.core::Starling/nextFrame
starling.core::Starling/onEnterFrame

Expected Result:
Application playback video in a loop without errors.

Known Workarounds

none
Do not use VideoTexture.

@itlancer
Copy link
Author

itlancer commented Nov 5, 2023

Fixed with latest AIR 50.2.3.7.
Thanks!

@itlancer itlancer closed this as completed Nov 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants