2
0
Эх сурвалжийг харах

added h2d.Video (hl support with ffmpeg/video.hdll only for now)

Nicolas Cannasse 8 жил өмнө
parent
commit
e91a6c82e7
2 өөрчлөгдсөн 172 нэмэгдсэн , 0 устгасан
  1. 137 0
      h2d/Video.hx
  2. 35 0
      samples/Video.hx

+ 137 - 0
h2d/Video.hx

@@ -0,0 +1,137 @@
+package h2d;
+
+#if hl
+private abstract VideoImpl(hl.Abstract<"hl_video">) {
+
+	@:hlNative("video","video_close") public function close() : Void {
+	}
+
+	@:hlNative("video","video_decode_frame") public function decodeFrame( out : hl.Bytes, time : hl.Ref<Float> ) : Bool {
+		return false;
+	}
+
+	@:hlNative("video","video_get_size") public function getSize( width : hl.Ref<Int>, height : hl.Ref<Int> ) : Void {
+	}
+
+	@:hlNative("video","video_open") public static function open( file : hl.Bytes ) : VideoImpl {
+		return null;
+	}
+
+	@:hlNative("video","video_init") public static function init() {
+	}
+
+}
+#end
+
+class Video extends Drawable {
+
+	#if hl
+	static var INIT_DONE = false;
+	var v : VideoImpl;
+	#end
+	var pixels : hxd.Pixels;
+	var texture : h3d.mat.Texture;
+	var tile : h2d.Tile;
+	var playTime : Float;
+	var videoTime : Float;
+	var frameReady : Bool;
+
+	public var videoWidth(default, null) : Int;
+	public var videoHeight(default, null) : Int;
+	public var playing(default, null) : Bool;
+	public var time(get, null) : Float;
+
+	public function new(?parent) {
+		super(parent);
+		blendMode = None;
+		filter = true;
+	}
+
+	public dynamic function onError( msg : String ) {
+	}
+
+	public dynamic function onEnd() {
+	}
+
+	public function get_time() {
+		return playing ? haxe.Timer.stamp() - playTime : 0;
+	}
+
+	public function dispose() {
+		#if hl
+		if( v != null ) {
+			v.close();
+			v = null;
+		};
+		#end
+		if( texture != null ) {
+			texture.dispose();
+			texture = null;
+		}
+		tile = null;
+		pixels = null;
+		videoWidth = 0;
+		videoHeight = 0;
+		time = 0;
+		playing = false;
+		frameReady = false;
+	}
+
+	public function load( path : String, ?onReady : Void -> Void ) {
+		dispose();
+
+		#if hl
+		if( !INIT_DONE ) { INIT_DONE = true; VideoImpl.init(); }
+		v = VideoImpl.open(@:privateAccess path.toUtf8());
+		if( v == null ) {
+			onError("Failed to init video " + path);
+			return;
+		}
+		var w = 0, h = 0;
+		v.getSize(w, h);
+		videoWidth = w;
+		videoHeight = h;
+		playing = true;
+		playTime = haxe.Timer.stamp();
+		videoTime = 0.;
+		if( onReady != null ) onReady();
+		#else
+		onError("Video not supported on this platform");
+		#end
+	}
+
+	override function draw(ctx:RenderContext) {
+		if( tile != null )
+			ctx.drawTile(this, tile);
+	}
+
+
+	override function sync(ctx:RenderContext) {
+		if( !playing )
+			return;
+		if( texture == null ) {
+			var w = videoWidth, h = videoHeight;
+			pixels = new hxd.Pixels(w, h, haxe.io.Bytes.alloc(w * h * 4), h3d.mat.Texture.nativeFormat);
+			texture = new h3d.mat.Texture(w, h);
+			tile = h2d.Tile.fromTexture(texture);
+			if( h3d.mat.Texture.nativeFlip ) {
+				pixels.flags.set(FlipY);
+				tile.flipY();
+				tile.dy = 0;
+			}
+		}
+		if( frameReady ) {
+			texture.uploadPixels(pixels);
+			frameReady = false;
+		}
+		if( time >= videoTime ) {
+			#if hl
+			var t = 0.;
+			v.decodeFrame(pixels.bytes, t);
+			videoTime = t;
+			#end
+			frameReady = true; // delay decode/upload for more reliable FPS
+		}
+	}
+
+}

+ 35 - 0
samples/Video.hx

@@ -0,0 +1,35 @@
+
+class Video extends hxd.App {
+
+	var video : h2d.Video;
+	var tf : h2d.Text;
+
+	override function init() {
+		tf = new h2d.Text(hxd.res.DefaultFont.get(), s2d);
+		video = new h2d.Video(s2d);
+		video.onError = function(e) {
+			tf.text = e;
+			tf.textColor = 0xFF0000;
+		};
+		function start() {
+			video.load("testVideo.avi");
+		}
+		video.onEnd = start;
+		start();
+	}
+
+	override function update(dt:Float) {
+		if( video.videoWidth != 0 && video.videoHeight != 0 ) {
+			tf.text = (Std.int(video.time*10)/10)+"s";
+			var scale = hxd.Math.min(s2d.width / video.videoWidth, s2d.height / video.videoHeight);
+			video.setScale(scale);
+			video.x = Std.int((s2d.width - video.videoWidth * scale) * 0.5);
+			video.y = Std.int((s2d.height - video.videoHeight * scale) * 0.5);
+		}
+	}
+
+	static function main() {
+		new Video();
+	}
+
+}