udpstreamts FIX 19.07.2007

Das Original Benutzerinterface Neutrino-SD incl. zapit, sectionsd, yWeb etc...
arno-neutrinoTV
Einsteiger
Einsteiger
Beiträge: 108
Registriert: Freitag 14. April 2006, 11:21

udpstreamts FIX 19.07.2007

Beitrag von arno-neutrinoTV »

Nachdem ich in den letzten Tagen über das Development-VMWare Image von yjogol gestossen bin, habe ich es endlich geschafft eine tuxbox Entwicklungsumgebung aufzusetzen - Danke an yjogol für das tolle VMware-Image!!

Ich habe es genutzt um mir endlich udpstreamts genauer anzusehen und einige kleine bugs zu fixen. Im Detail hab ich folgendes gefixt:

- Abstürze bei sehr hohen Datenraten sollte nun (fast??) ganz weg sein (getestet mit einem HDTV Sender, und es stürzte nicht ab!! - natürlich ruckelte es, aber das ist normal bei HDTV. Bei ARD/ZDF konnte ich den Absturz nicht mehr beobachten (Symptom: Einfrieren des Bildes, es ging erst weiter wenn man neu auf live geklickt hat). Technisch lag es daran dass manchmal zu schnell gelesen bzw. geschrieben wurde. Abhilfe ist, es einfach bis zu 10 mal zu probieren wenn das Verhalten auftritt, bevor man engültig aufgibt. Bei meinen Test war allerdings IMMER bereits der erste Wiederholungsversuch erfolgreich.

- Wenn man udpstreaming mit neutrinoTV verwendet gab es seit der Einführung von UDP streaming in neutrinoTV eine häßliche Fehlermeldung, die behauptete, dass ein bestimmtes skript nicht ausgeführt werden konnte - die ist weg. Dies wurde erreicht indem ich udpstreamts das "daemon-dasein" beigebracht habe. Insofern man "udpstreamts -b logfile ..." startet so geht udpstreamts in den hintergrund und gibt vor allem alle file-descriptoren frei. Dadurch kehrt der aufruf vom nhttpd sofort zurück und es gibt keine Fehlermeldung. D.h. auch dass udpstreamts nun nachdem es z.B. über nhttpd gestartet wurde völlig unabhängig von diesem läuft.



Man kann die geänderte version hierdownloaden.


Das Archiv enthält folgendes:
  • udpstreamts: Neue binary von udpstreamts für die dbox
    udpstreamts.c: Geänderte quellen von udpstreamts
    udpstreamts.c.diff: Patch von udpstreamts.c gegen aktuelles CVS
    api.sh: Minimal geänderte api.sh - diese ist notwendig damit neutrinoTV die neue udpstreamts besser aufrufen kann
    api.sh.diff: Patch der api.sh gegen aktuelles CVS
Falls es keine Probleme damit gibt, könnte es auch evtl jemand ins CVS einchecken, die notwendigen diffs liegen im zip bei.

Have fun folks..
ingrid
Erleuchteter
Erleuchteter
Beiträge: 600
Registriert: Samstag 14. Oktober 2006, 10:53

Beitrag von ingrid »

arno-neutrinoTV hat geschrieben:getestet mit einem HDTV Sender, und es stürzte nicht ab!! - natürlich ruckelte es, aber das ist normal bei HDTV.
Seit wann kann die dbox 2 HDTV? :gruebel:
arno-neutrinoTV
Einsteiger
Einsteiger
Beiträge: 108
Registriert: Freitag 14. April 2006, 11:21

Beitrag von arno-neutrinoTV »

Kann sie nicht, zumindest nicht die neue MPEG4 Version von HDTV.

Sie kann aber sehr wohl die alte Art, nämlich die mit MPEG2 (z.B. Euro 1080 HD) EMPFANGEN. D.h. es wird versucht es zu dekodieren. Auf dem TV kommt keine Bild weil vmlt einer Video chips mit der Auflösung nicht klar kommt. Bei streamen ist das anders, da ich man ja die daten aus dem stream direkt an den PC schickt und dort dekodiert... naja.. und somit kommt bild und ton am PC an... es hängt natürlich alle paar sekunden, da dann die Bandbreite erschöpft ist.

Grüße
Arno
Grüßle
A.
dbt
Administrator
Beiträge: 2675
Registriert: Donnerstag 28. September 2006, 19:18

Beitrag von dbt »

Hast Du schon sowas wie'n Dauertest gemacht. Dann wärs mit dem CVS kein Problem...
arno-neutrinoTV
Einsteiger
Einsteiger
Beiträge: 108
Registriert: Freitag 14. April 2006, 11:21

Beitrag von arno-neutrinoTV »

Das Ganze läuft bei mir im live-streaming (neutrinoTV) seit heute nacht problemlos durch. Dauertest mit ZDF. Heute morgen teilweise ARD. Bislang keine Problem erkennbar. Manchmal gibts kurze bildstörungen (wenn doch mal ein Paket gekillt wird), aber udpstreamts bleibt am leben - was das wichtigste ist. (Ich streame übrigens über WLAN (54), sitze aber fast neben dem AP.)


Allgemein hab ich in udpstreamts ein paar meldungen mehr eingebaut, und habe den Eindruck, dass es stabiler läuft seit es sich komplett (Schliessen aller deskriptoren) vom nhttpd loslösst. Evtl. gab es da auch noch eine Wechselwirkung die negativen Einfluss hatte.

@yjogol: Damit das Livestreaming von YWeb auch von der geänderten Version profitiert, müsste es mit udpstreamts -b /dev/null <ip> <port> <pid>.. aufgerufen werden. Allerdings achtung, wenn man diesen Aufruf verwendet und noch eine alte udpstreamts zum Einsatz kommt, wird es nicht funktionieren, da die alten udpstreamts natürlich den Paramter -b nicht kennt (-b logfile: steht für backgrounding)

Anders rum sollte es kein Problem sein, d.h. wenn man eine neue Version von udpstreamts ohne -b aufruft, so verhält sie sich genau wie die alte Version (nur ein paar Ausgaben mehr gibt es)

Lange Rede kurzer Sinn, ich würde das ganze noch .. sagen wir mal bis zum WE von allen Seiten testen - evtl. probiert es ja auch noch jmd anders. Wenn es bis dahin zu keinen Problemen bzw. Nebeneffekte kommt wäre ein einchecken sicherlich sinnvoll.

Grüße
Arno
Grüßle
A.
arno-neutrinoTV
Einsteiger
Einsteiger
Beiträge: 108
Registriert: Freitag 14. April 2006, 11:21

Beitrag von arno-neutrinoTV »

UPDATE 19-07-12:00: Eine kleine Änderung an der api.sh (Anpassung für den Fall dass udpstreamts in sbin liegt)

Neue Datei api.sh ist im archiv (api.sh.diff ist auch angepasst)

Bitte neu downloaden.
Grüßle
A.
dwilx

Beitrag von dwilx »

arno-neutrinoTV hat geschrieben:Kann sie nicht, zumindest nicht die neue MPEG4 Version von HDTV.

Sie kann aber sehr wohl die alte Art, nämlich die mit MPEG2 (z.B. Euro 1080 HD) EMPFANGEN. D.h. es wird versucht es zu dekodieren. Auf dem TV kommt keine Bild weil vmlt einer Video chips mit der Auflösung nicht klar kommt. Bei streamen ist das anders, da ich man ja die daten aus dem stream direkt an den PC schickt und dort dekodiert... naja.. und somit kommt bild und ton am PC an... es hängt natürlich alle paar sekunden, da dann die Bandbreite erschöpft ist.

Grüße
Arno
Interessant! Wieder was gelernt! :wink:
arno-neutrinoTV
Einsteiger
Einsteiger
Beiträge: 108
Registriert: Freitag 14. April 2006, 11:21

Beitrag von arno-neutrinoTV »

dixidix hat geschrieben:
arno-neutrinoTV hat geschrieben:Kann sie nicht, zumindest nicht die neue MPEG4 Version von HDTV.

Sie kann aber sehr wohl die alte Art, nämlich die mit MPEG2 (z.B. Euro 1080 HD) EMPFANGEN. D.h. es wird versucht es zu dekodieren. Auf dem TV kommt keine Bild weil vmlt einer Video chips mit der Auflösung nicht klar kommt. Bei streamen ist das anders, da ich man ja die daten aus dem stream direkt an den PC schickt und dort dekodiert... naja.. und somit kommt bild und ton am PC an... es hängt natürlich alle paar sekunden, da dann die Bandbreite erschöpft ist.

Grüße
Arno
Interessant! Wieder was gelernt! :wink:
:) Da hab ich nun was gesagt... :) Naja, also das Beispiel mit dem HDTV sollte nur stellvertretend stehen für einen Sender mit sehr hoher bitrate. Ich wusste einfach, wenn ich solch einen Sender versuche mit der alten version von udpstreamts zu streamen bricht es nach wenigen Sekunden ab - udpstreamts beendete sich, und zwar mit der gleichen Fehlermeldung wie das manchmal bei ARD/ZDF passiert. Daher hab ich zum testen einfach diesen Sender eingeschaltet und udpstreamts auf ihn losgelassen und geschaut ob es überlebt.

Mit der neuen version von udpstreamts könnt ihr das selber mal testen: Geht einfach auf einen HDTV Sender der alten Generation (die neuen werden sowieso nicht in der Kanalliste gezeigt). Auf dem TV bildschirm werdet ihr von zeit zu zeit halbe bilder sehen.. der ton stockt auch, allerdings hört man machmal etwas. Und nun probiert mal enweder mit ywebLive oder neutrinoTV das Programm zu streamen. Ihr werdet ein Bild bekommen und auch Ton, nur wird es eben alle 1-3 Skeunden für ca. 1 Sekunde stehen.... also mit anderen Worten nicht anschaubar... aber ein netter Test. Theoretisch, wenn genügend Bandbreite da wäre, könnte das streamen dieses Senders gehen (obwohl es am TV nicht anzusehen ist)

Grüße
Arno
Grüßle
A.
mb405
Tuxboxer
Tuxboxer
Beiträge: 2331
Registriert: Donnerstag 24. März 2005, 21:52

Beitrag von mb405 »

gibts das toll den auch mal für linux ??
arno-neutrinoTV
Einsteiger
Einsteiger
Beiträge: 108
Registriert: Freitag 14. April 2006, 11:21

Beitrag von arno-neutrinoTV »

neutrinoTV? Nicht in naher Zukunft. Es ist in .NET geschrieben, d.h. wenn mono irgendwann soweit ist, dass .NET 2.0 unter mono unsterstüzt wird, dann kann man weiter sehen. Allerdings ist das jetzt hier zu weit off-topic...(in Grab gibts ein thread schon seit langer Zeit über neutrinoTV bzw. im JtG forum gibts alles was man zu neutrinoTV wissen muss - hier gehts um udpstreamts welches sowohl von neutrinoTV als auch von yWeb verwendet wird)
Grüßle
A.
PauleFoul
Wissender
Wissender
Beiträge: 1839
Registriert: Sonntag 17. August 2003, 01:39

Beitrag von PauleFoul »

Man kann diesen Sender auch mit dem IDE-IF aufnehmen und die
Datei dann auf dem PC anschauen. Nur leider auch mit vielen
Rucklen. Obwohl die Bandbreite des IDE ja eigentlich reichen sollte...
jmittelst
Tuxboxer
Tuxboxer
Beiträge: 6044
Registriert: Montag 17. November 2003, 06:48

Beitrag von jmittelst »

Hier ist die Frage: Liegt es am IDE-Interface bzw. dessen Performance oder gibt es da vielleicht noch woanders den ein oder anderen Flaschenhals. Wenn die Direktaufnahme in einem Stück war, wird es wahrscheinlich eher nicht an der Performance des Interfaces liegen, denn dann wäre ja die Aufnahme unterbrochen worden.

cu
Jens
arno-neutrinoTV
Einsteiger
Einsteiger
Beiträge: 108
Registriert: Freitag 14. April 2006, 11:21

Beitrag von arno-neutrinoTV »

Hab mir den Fehler, nochmal angesehen. Evtl kann jmd was dazusagen, der genauers Verständnis von den internas hat.


Also ein read auf einem fildescriptor, welcher daten für eine bestimmte PID liefert schlägt mit folgender fehlermeldung fehl:

Code: Alles auswählen

Value too large for defined data type
das passiert bei einem

Code: Alles auswählen

read(dvr,readbuf,size);

Dies kann man bei den HDTV sender ständig und bei Sender mit hohen bitraten manchmal beobachten. Allerdings ist in meinen Tests IMMER der nächste Leseversuch erfolgreich. Daher war ja auch meine Lösungs des Problems, es einfach nochmal (bis maximum 10 mal) zu probieren.

Ich frage mich grade, ob eventuell die eigentliche ursache hier eine falsche berechnung der size sein kann.. hmm aber warum tuts dann im nächsten versuch..
Grüßle
A.
seife
Developer
Beiträge: 4189
Registriert: Sonntag 2. November 2003, 12:36

Beitrag von seife »

arno-neutrinoTV hat geschrieben:Hab mir den Fehler, nochmal angesehen. Evtl kann jmd was dazusagen, der genauers Verständnis von den internas hat.


Also ein read auf einem fildescriptor, welcher daten für eine bestimmte PID liefert schlägt mit folgender fehlermeldung fehl:

Code: Alles auswählen

Value too large for defined data type
das passiert bei einem

Code: Alles auswählen

read(dvr,readbuf,size);
Das ist vermutlich EOVERFLOW. Mein manpage zu read() sagt zwar nicht, daß (und unter welchen Umständen) EOVERFLOW zurückgegeben wird, aber ich vermute, daß entweder der Puffer zu klein ist, oder einfach zu langsam gelesen wird.
Dies kann man bei den HDTV sender ständig und bei Sender mit hohen bitraten manchmal beobachten. Allerdings ist in meinen Tests IMMER der nächste Leseversuch erfolgreich. Daher war ja auch meine Lösungs des Problems, es einfach nochmal (bis maximum 10 mal) zu probieren.
Ich habe mir deinen diff nicht angeschaut (ein zip auspacken ist mir jetzt doch zuviel Action), aber ich vermute daß du auf keinen Fall die ersten 9mal die Daten wegschmeißen solltest. Ich würde eher versuchen, auf EOVERFLOW zu testen, und in diesem Fall den Fehler einfach zu ignorieren, die Daten (die ja trotz dem Fehler vermutlich gelesen wurden, oder etwa nicht?) aufs Netzwerk pusten und in der Schleife weiter zu lesen. Durch den EOVERFLOW gingen zwar vermutlich Daten verloren, aber man muß ja nicht noch mehr "mutwillig" wegschmeißen.

EDIT:
Ich habe grad in den Kernelquellen nachgeschaut, und wenn ich das richtig verstanden habe (was durchaus nicht der Fall sein muß :-), dann kommt EOVERFLOW zurück, wenn seit dem letzten Lesen ein Overflow im Ringbuffer des Kernels auftrat. Dagegen kann man dann eh nichts mehr tun, ich würde also mal versuchen, diesen Fehler einfach zu ignorieren.

Code: Alles auswählen

ret=read(dvr,readbuf,size);
if (ret < 0 && errno != EOVERFLOW) {
        //fehlerbehandlung;
} else {
        // weitermachen, als ob nix wäre;
}
arno-neutrinoTV
Einsteiger
Einsteiger
Beiträge: 108
Registriert: Freitag 14. April 2006, 11:21

Beitrag von arno-neutrinoTV »

Hi seife,

danke für deine Mühe. Ich bin mittlerweile auch bis zum ringbuffer vorgerungen, und vermute genau das Gleich wie duschreibst: Bereits im kernel konnte nicht schnell genug gelsen werden, d.h. man kann eigentlich nichts mehr machen.

Die Idee auf EOVERFLOW getrennt zu reagieren hab ich so noch nciht drin - momentan reagiere ich bei jedem Fahler, indem ich es einfach nochmal probiere. Daten gibts im Fehlerfall keine (Rer Rücgabewert ist -1, d.h. ich konnte nix lesen)

Die aktuelle Stelle sieht so aus

Code: Alles auswählen

/*
			 * read as much bytes as needed to fill the buffer
			 * as much as possible and to end with a complete
			 * transport stream packet
			 */
			rsize = read(dvr, readbuf + read_offset, sizeof(readbuf) - read_offset - size_offset);


			/*
			* retry to read
			*/
			retries = 0;
			while((rsize == -1) && (retries < MAX_RETRIES)){
				retries++;
				fprintf(stderr,"Error reading from dvr, still trying..(%i/%i)\n",retries,MAX_RETRIES);
				rsize = read(dvr, readbuf + read_offset, sizeof(readbuf) - read_offset - size_offset);
			}


			if (rsize == -1) {
				perror("Error reading from dvr. Giving up");
				break;
			}
Um nur den EOVERFLOW zu ignorieren müsste ich das vermutlich so ändern:

Code: Alles auswählen

/*
			 * read as much bytes as needed to fill the buffer
			 * as much as possible and to end with a complete
			 * transport stream packet
			 */
			rsize = read(dvr, readbuf + read_offset, sizeof(readbuf) - read_offset - size_offset);


			/*
			* retry to read
			*/
			retries = 0;
			while((rsize == -1) && (retries < MAX_RETRIES) && (errno == EOVERFLOW)){
				retries++;
				fprintf(stderr,"Error reading from dvr, still trying..(%i/%i)\n",retries,MAX_RETRIES);
				rsize = read(dvr, readbuf + read_offset, sizeof(readbuf) - read_offset - size_offset);
			}


			if (rsize == -1) {
				perror("Error reading from dvr. Giving up");
				break;
			}
Mit diesem Code würde EOVERFLOW bis zu 10 mal ignoriert werden (mit gleichzeitigem erneuten Versuch. Jeglicher anderer Fehler würde nicht mehrmal probiert werden, und udpstreamts beendet ich quasi sofort.

Was meints du/ihr?
Grüßle
A.
seife
Developer
Beiträge: 4189
Registriert: Sonntag 2. November 2003, 12:36

Beitrag von seife »

arno-neutrinoTV hat geschrieben:Die Idee auf EOVERFLOW getrennt zu reagieren hab ich so noch nciht drin - momentan reagiere ich bei jedem Fahler, indem ich es einfach nochmal probiere. Daten gibts im Fehlerfall keine (Rer Rücgabewert ist -1, d.h. ich konnte nix lesen)
ich habe grad nochmal im Kernel-Treiber (drivers/media/dvb/dvb-core/dmxdev.c) nachgeschaut, und es ist so: Wenn ein Overflow aufgetreten ist, wird dvb_ringbuffer_flush() aufgerufen, ich vermute, daß das die noch vorhandenen Daten verwirft, und dann EOVERFLOW ausgegeben => es kommen keine Daten.
Mit diesem Code würde EOVERFLOW bis zu 10 mal ignoriert werden (mit gleichzeitigem erneuten Versuch. Jeglicher anderer Fehler würde nicht mehrmal probiert werden, und udpstreamts beendet ich quasi sofort.

Was meints du/ihr?
Nachdem ich den Kernel-Code nochmal angeschaut habe, glaube ich, daß es keinen Unterschied machen würde. Traten denn bei deinen Tests jemals andere Fehler auf?
Eine Frage wäre noch, ob evtl. der retry-read() nach einem anderen Fehler blockieren könnte, und somit die Loop nie verlassen würde (nach dem Motto: "read schlägt fehl mit 'gerät kaputt', der nächste read() hängt dann", das glaube ich allerdings nicht wirklich. Insofern sieht dein aktueller Code schon mal gut aus.

Achtung: ich bin hier purer Theoretiker, ich kenne mich damit nicht wirklich aus, also meine Tips mit Vorsicht genießen :-)
arno-neutrinoTV
Einsteiger
Einsteiger
Beiträge: 108
Registriert: Freitag 14. April 2006, 11:21

Beitrag von arno-neutrinoTV »

seife hat geschrieben: ich habe grad nochmal im Kernel-Treiber (drivers/media/dvb/dvb-core/dmxdev.c) nachgeschaut, und es ist so: Wenn ein Overflow aufgetreten ist, wird dvb_ringbuffer_flush() aufgerufen, ich vermute, daß das die noch vorhandenen Daten verwirft, und dann EOVERFLOW ausgegeben => es kommen keine Daten.
Jup, das ist konsitent mit meinen Test.
seife hat geschrieben: Nachdem ich den Kernel-Code nochmal angeschaut habe, glaube ich, daß es keinen Unterschied machen würde. Traten denn bei deinen Tests jemals andere Fehler auf?
Bislang konnte ich weder einen anderen Fehler beobachten, noch mehr als ein notwendiger Versuch bis man wieder Daten bekommt. D.h. mit dem ersten retry funktioniert es dann meistens.. allerdings sind dann die daten halt weg... kann man aber nciht ändern - es sei denn man ändert an den treiber *angst* :)
seife hat geschrieben: Eine Frage wäre noch, ob evtl. der retry-read() nach einem anderen Fehler blockieren könnte, und somit die Loop nie verlassen würde (nach dem Motto: "read schlägt fehl mit 'gerät kaputt', der nächste read() hängt dann", das glaube ich allerdings nicht wirklich. Insofern sieht dein aktueller Code schon mal gut aus.
kann sie nicht, da sdefinitv nach 10 versuchen die schelfe verlassen wird (retries). Mit der letzen Änderung sogar sofort wenn es ein andere Fehler (also nicht EOVERFLOW) war

Hmm.. du scheinst dich recht gut in den Kernelquellen auzukennenb - glaubst du man kann da etwas fixe, also ist das überhaupt möglich?
Grüßle
A.
seife
Developer
Beiträge: 4189
Registriert: Sonntag 2. November 2003, 12:36

Beitrag von seife »

Evtl. könnte man die Puffer im Treiber vergrößern. Allerdings bringt das nicht wirklich was - wenn du die Daten nicht schnell genug loswirst, wirst du sie nicht schnell genug los. Ein größerer Puffer im Kernel ändert da nichts, er läuft nur etwas später über (und du verlierst dann mehr Daten).
Was du tun kannst: einen großen Puffer im streamts anlegen und den dann entsprechend verwalten (z.B. ein Thread der in den Puffer schreibt, und ein anderer Thread der dann aus dem Puffer liest und das aufs Netzwerk bläst). Damit kannst du Spitzen in der Bitrate evtl. abpuffern (ähnlich wie es der Movieplayer macht). Ich vermute daß eine Puffergröße dafür, um hilfreich zu sein, in der Größenordnung von "einige MB" liegen müßte. Im Kernel will man eher nicht so große Puffer, da dieser Speicher immer und dauerhaft verbraucht ist.

Und nein, ich kenne mich nicht wirklich mit Kernel-Code aus, ich kämpfe mich auch immer durch die Quellen. Ich muß aber zugeben daß ich bei Bedarf Zugriff auf Leute habe, die sich richtig gut damit auskennen :-)
arno-neutrinoTV
Einsteiger
Einsteiger
Beiträge: 108
Registriert: Freitag 14. April 2006, 11:21

Beitrag von arno-neutrinoTV »

Hi,

hehe, wir suchen hier grade parallel a den gleichen stellen. Ich habe gerade eben mit der puffergröße in udpstreamts experimetiert. Hatte ein Puffergröße von kanpp ein MB gewählt, die Effekte blieben allerdings. Bin auch nicht sicher wieviel Speicher ich udpstreamts wirklich verbraten darf, ohne dass es jmd anders stört.

Das man im Kernel den Puffer nicht (allzusehr) vergrößern kann/soll leuchtet mir sofort ein. Macht eigentlich kein Sinn. Ich weiss allerdings grade nicht auf was der steht, D.h. das wäre höchstens überlegenswert, wenn dort ein unnatürlich kleiner Puffer wäre - was ich aber nciht glaube

Leider ist udpstreamts momentan noch nicht auf threads geschrieben, d.h. es wird gelesen, dann wird geschrieben. Ich denke dadurch kommt es zu den überlaufen, da in der Zeit wo geschrieben wird, natürlich nicht gelesen werden kann. Da würde ein thread helfen. Das ist natürlich eine größere Änderung, der ich mich aber evtl annehme. Momentan setz ich den Puffer einfach mal auf ca. 1 MB und lade dann die neue Version hoch. Evtl. können dann ja wieder Leute testen und sagen ob es zu konflikten kommt.
Grüßle
A.
arno-neutrinoTV
Einsteiger
Einsteiger
Beiträge: 108
Registriert: Freitag 14. April 2006, 11:21

Beitrag von arno-neutrinoTV »

Ergebniss meiner Test mit verschieden großen Buffer hat ergeben, dass es momentan keinen Sinn mach den buffur zu erhöhen. Wenn der buffer größer ist, brauch die sende routing länger zum verschicken, also füllt sich gleichzeitig der speicher mehr mit daten aus dem TS an, also kommt es eher zu abbrüchen. Daher hab ich den Puffer auf 32*7*188 belassen.

Ich habe noch ein paar andere Kleinigkeiten eingebaut, vor allem fürs debugging und hab die wiederhoversuche beim SENDEN per #ifdef abgeschaltet, weil es sonst anscheinen zu Problemen mit YWebLive kommen konnte. Die aktuelle Version läuft bei mir absolut stabil - konnte keine ungeünschte abbrüche beobachten.

Habe noch ein bischen Code für das handel eines kill-signals eingebaut, damit der demuxer immer sauber geschlossen wird. Ist einfach sauberer, auch wenn es anscheinend auch ohne das ging.

Bitte neu downloaden und testen.

Hier das diff von udpstreamts zum aktuellen CVS:

Code: Alles auswählen

49a50
> #include <sys/signal.h>
50a52
> #include <errno.h>
72a75,81
> #define MAX_RETRIES 10
> 
> #undef UDPSTREAMTS_DEBUG
> #undef USE_SEND_RETRY
> 
> 
> char exiting = 0;
119a129,132
> 	#ifdef USE_SEND_RETRY
> 	unsigned int retries=0;
> 	#endif
> 
162a176,189
> 		#ifdef USE_SEND_RETRY
> 		/*
> 		* retry to send
> 		*/
>                 retries = 0;
> 		while((written == -1) && (retries < MAX_RETRIES)){
> 			retries++;
> 			fprintf(stderr,"Error writing to socket, still trying..(%i/%i);",retries,MAX_RETRIES);
> 			perror(" Reason");
> 			written = write(fd, bp, UDP_PACKET_SIZE);
> 		}
> 		#endif
> 
> 
167,168c194,197
< 			perror("write");
<                         return -1;
---
> 
> 			perror("Error writing to socket, giving up");
> 			return -1;
> 
226a256,267
> void
> sig_handler(int sig) /* signal handler */
> {
> 	switch(sig)
> 	{
> 		case SIGTERM:
> 		/* do the cleanup */
> 		printf("Got kill signal. Cleaning and bailing out...\n");
> 		exiting = 1;
> 		break;
> 	}
> }
237c278,284
< 	int i;
---
> 	int i,j;
> 
> 	int argp = 1, retries=0;
> 
> 	#ifdef UDPSTREAMTS_DEBUG
> 	int min_read = READ_BUFFER_SIZE+1, max_read = -1;
> 	#endif
244c291,299
< 
---
> 	#ifdef UDPSTREAMTS_DEBUG
> 		printf("udpstreamts (compiled in debug mode) starting... \n");
> 		printf("Size of readbuffer: %d bytes\n", READ_BUFFER_SIZE);
> 		printf("Size of writebuffer: %d bytes\n", UDP_PACKET_SIZE);
> 		printf("\n");
> 	#else
> 		printf("udpstreamts starting... \n");
> 		printf("\n");		
> 	#endif
250c305
< 		fprintf(stderr, "usage: %s <ip> <port> <pid> [<pid> ...]\n", argv[0]);
---
> 		fprintf(stderr, "usage: %s [-b <logfile>] <ip> <port> <pid> [<pid> ...]\n", argv[0]);
253a309,351
> 	/* inserted A.Wacker 19.07.2007 for starting udpstreamts in background */
> 	if (!strncmp(argv[1],"-b",2)) {
>         	printf("Daemonizing %s and logging to %s...\n", argv[0], argv[2]);
> 		fflush(stdout);
>         	
> 		/* daemonize */
> 		j=fork();
> 		if (j<0) exit(1); /* fork error */
> 		if (j>0) exit(0); /* parent exits */
> 		/* child daemon continous */
> 		
> 		setsid(); /* obtain a new process group */
> 
> 		for (j=getdtablesize();j>=0;--j) close(j); /* close all descriptors */
> 
> 		j = open(argv[2], O_RDWR|O_CREAT|O_TRUNC); /*open stdin */
> 		dup(j); /* stdout */
> 		dup(j); /* stderr */
> 
> 		if (j == -1)
>         	{
> 			perror("Cannot open logfile for writing");
>         	}
> 		
> 		chdir ("/");
> 
> 		signal(SIGCHLD,SIG_IGN); /* ignore child terminate signal */
> 		signal(SIGTERM,sig_handler); /* termination signal from kill */
> 		
> 		
> 		/* check again if there are enough arguments */
> 		if (argc < 6) {
> 			fprintf(stderr, "usage: %s [-b <logfile>] <ip> <port> <pid> [<pid> ...]\n", argv[0]);
> 			return EXIT_FAILURE;
> 		}
> 
> 		/* finally shift the remaining arguments, so that the rest of the code remains untouched */
> 		argp = 3;
> 	}
> 	printf("Preparing to send the transport stream to %s:%s ...\n",argv[argp],argv[argp+1]);
>     	/* end changes 19.07.2007 */
> 
> 
263,264c361,362
< 	sin.sin_addr.s_addr = inet_addr(argv[1]);
< 	sin.sin_port = htons(strtoul(argv[2], NULL, 0));
---
> 	sin.sin_addr.s_addr = inet_addr(argv[argp]);
> 	sin.sin_port = htons(strtoul(argv[argp+1], NULL, 0));
282,283c380,385
< 	for (i = 0; i < argc - 3; i++)
< 		dmx[i] = dmx_pid_filter_start(strtoul(argv[i + 3], NULL, 0));
---
> 	for (i = 0; i < (argc - (argp+2)); i++)
> 	{
> 		printf("Preparing demuxer for streaming PID %i: %s ...\n",i ,argv[i + (argp + 2)]);
> 		dmx[i] = dmx_pid_filter_start(strtoul(argv[i + (argp + 2)], NULL, 0));
> 	}
> 	fflush(stdout);
291c393
< 		perror("read");
---
> 		perror("Error reading from dvr");
311a414,428
> 
> 			/*
> 			* retry to read
> 			*/
> 			retries = 0;
> 			while((rsize == -1) && (retries < MAX_RETRIES) && (errno==EOVERFLOW)){
> 				retries++;
> 				#ifdef UDPSTREAMTS_DEBUG
> 				fprintf(stderr,"Error reading from dvr, still trying..(%i/%i)",retries,MAX_RETRIES);
> 				perror("; Reason");
> 				#endif
> 				rsize = read(dvr, readbuf + read_offset, sizeof(readbuf) - read_offset - size_offset);
> 			}
> 
> 
313c430
< 				perror("read");
---
> 				perror("Error reading from dvr. Giving up");
330a448,467
> 
> 			#ifdef UDPSTREAMTS_DEBUG
> 			/* just for debugging*/
> 			if(rsize>max_read)
> 			{
> 				max_read = rsize;
> 				printf("New max read size: %d\n",max_read);
> 			}
> 			if(rsize<min_read)
> 			{
> 				min_read = rsize;
> 				printf("New min read size: %d\n",min_read);
> 			}
> 			if ((rsize!=max_read) && (rsize!=min_read))
> 			{
> 				printf("Current read size: %d\n",rsize);
> 			}
> 			#endif
> 
> 
336a474
> 
367c505
< 		} while (wsize >= 0);
---
> 		} while (wsize >= 0 && !exiting);
370c508,512
< 	for (i = 0; i < argc - 3; i++)
---
> 	printf("Prepare for shutdown ");
> 
> 	for (i = 0; i < (argc - (argp+2)); i++)
> 	{
> 		fprintf(stdout,".");
371a514
> 	}
374a518,522
> 	/* just to be sure, that everything is closed */
> 	for (j=getdtablesize();j>=3;--j) close(j); /* close all descriptors, except std dscr. */
> 
> 	printf(" done. Goodby!\n");
> 
Zuletzt geändert von arno-neutrinoTV am Samstag 21. Juli 2007, 18:26, insgesamt 1-mal geändert.
new.life
Erleuchteter
Erleuchteter
Beiträge: 797
Registriert: Sonntag 19. Februar 2006, 01:17

Beitrag von new.life »

arno-neutrinoTV hat geschrieben:..Bitte neu downloaden und testen..
ist udpstreamts in dem neuen zip-archiv wirklich aktuell? Laut Datum ist udpstreamts noch vom 19.7 im Unterschied zu *.diff und *.c die das Datum vom 21.7 haben.
arno-neutrinoTV
Einsteiger
Einsteiger
Beiträge: 108
Registriert: Freitag 14. April 2006, 11:21

Beitrag von arno-neutrinoTV »

uiii.. du hast recht.. gib mir ne sekunde
Grüßle
A.
arno-neutrinoTV
Einsteiger
Einsteiger
Beiträge: 108
Registriert: Freitag 14. April 2006, 11:21

Beitrag von arno-neutrinoTV »

updated.
Grüßle
A.
new.life
Erleuchteter
Erleuchteter
Beiträge: 797
Registriert: Sonntag 19. Februar 2006, 01:17

Beitrag von new.life »

funktioniert jetzt ohne Y-Live zu beeinträchtigen...getestet mit Notebook über WLAN.
Den Vorteil den UDP bringen müsste habe ich nicht: Y-Live mit UDP bricht irgendwann (nach vielen Artefakten) ab und der Stream 'erholt' sich auch nicht mehr. Das gleiche Experiment (mit Notebook im Hinterhof spazieren) mit Y-Live und TCP wiederholt bringt weder Artefakte noch Abbruch...läuft also wesentlich besser.
arno-neutrinoTV
Einsteiger
Einsteiger
Beiträge: 108
Registriert: Freitag 14. April 2006, 11:21

Beitrag von arno-neutrinoTV »

..das ist eine andere geschichte. Das was du beschreibst ist leider für den WLAN Fall normal. Liegt aber nicht an der box, sondern in diesem Fall am WLAN.

Den Vorteil von udp gewinnt man nur bei 100% WLAN (also wenn man quasi neben dem AP sitzt) oder mit nem Kabel. In diesen Fällen ist udpstreaming besser, da es bei hohen datenraten besser über das interface der dbox raus kommt.

BTW: bei WLAN sollte man zusätzlich clientseitig den Puffer auf ca. 1500-2000ms setzen. Alles ander führt fast auschliesslich zu artefakte.
Grüßle
A.