1unitedpower: pic refreshen

Beitrag lesen

Hallo xharx,

Ich fürchte du wirst dein Ziel auf diesem Wege nicht erreichen können. Du peilst 60 Bilder pro Sekunde an und für jedes Bild startest du eine eigene http-Anfrage. Jede Frage-Antwort-Runde hat damit gerade mal ein Zeitfenster von 16,67ms und da ist die clientseitige Weiterverarbeitung noch gar nicht berücksichtigt, die nimmt auch nochmal Zeit in Anspruch. Du müsstest auch noch berücksichtigen, dass die Server-Antworten nicht zwingend in der Reihenfolge eintreffen, in der du sie angefragt hast. Du müsstest die Antworten also noch ordnen und ggf. alle überholten Anfragen abbrechen, um die Netzwerk-Auslastung nicht unkontrolliert in die Höhe zu treiben.

		imgData=0;
		canvas=0;
		canvasheight=480;
		canvaswidth=640;
		function render() {
			var myAjax = new XMLHttpRequest();
			myAjax.responseType="arraybuffer";
			if (myAjax.response==0) console.log("network error");
			myAjax.onreadystatechange=function(){
				if (myAjax.readyState==4 && myAjax.status==200){
					if (!canvas) {
						canvas=document.getElementById("canvasid");
						console.log("canvasneu");
						context=canvas.getContext('2d');
						if (context) {
							if (!imgData) {
								imgData=context.getImageData(0,0,canvaswidth,canvasheight);
							}
						}
					}
					else {
						responsearray=new Uint8Array(myAjax.response);
						i=responsearray.length;
						while (i--) imgData.data[i]=responsearray[i];
						responsearray=null;
						context.putImageData(imgData, 0, 0);
					}
				}

			};
			myAjax.open("GET", "canvasdata", true);
			myAjax.send();
		}
		function animate() {
			render();
			requestAnimationFrame(animate);
		}
		animate();

Und dann hast du noch ein Problem in deinem Rendering-Loop: Bei jedem Aufruf von requestAnimationFrame wird jeweils nur der grün markierte Code ausgeführt. In diesem Bereich sendest du die http-Anfragen ab, gezeichnet wird da gar nichts. Das kann nämlich erst passieren, wenn die Server-Antwort eintrifft, also in dem rot-markierten Bereich, aber bis dahin hat der Browser den Frame längst gezeichnet. Dann trifft irgendwann die Server-Antwort ein, du zeichnest tatsächlich etwas auf das Canvas und unterbrichst dann trotzdem den Browser bei seinem aktuellen Zeichenvorgang. Das Skelett, für deinen Rendering-Loop, sollte also eher so aussehen:

function fetchBitmap() {
  const request = new XMLHttpRequest()
  request.open("GET", "canvasdata")
  request.addEventListener("load", onLoad)
}

function onLoad (response) {
  // … verarbeite response weiter zu imgData …
  requestAnimationFrame(() => render(imgData))
}

function render (imgData) {
  context.putImageData(imgData, 0, 0)
  fetchBitmap()
}

Letzten Endes bleibt aber das Problem, dass jeder Frame auch eine http-Anfrage voraussetzt und dafür zu wenig Zeit bleibt. Ich rate dir auf jeden Fall dazu, serverseitig ein richtiges Video zu generieren und keine Einzelbilder. Der Unterschied ist in etwa der zwischen einem HD-Kino und einem Daumenkino.