FritzBox 6490 DVB-IP Problem - Jetzt wirds angegangen

Wenn man analysiert was cableinfo so tut dann ist er eigntlich nicht mit viel mehr als dem kopieren und schicken von Paketen beschaeftigt.

Mit strace sieht man dass pro loop ein mmap() auf einen 32K grossen /dev/mem bereich gemacht wird. Das liegt innerhalb eines ca. 1-2MB grossen Bereichs in den wohl die DVB-C Daten "gestreamt" werden (wohl ein shared memory mit dem arm core oder direkt dem tuner), in dem das 32K fenster als sliding window verschoben wird.
Dieser 32K Bereich wird dann in 1.3K haeppchen per sendto() an den Empfaenger geschickt. cableinfo verlaesst sich hier also rein auf den UDP stack und macht keine "schweinereien".
Irgendeine Transkodierung die viel Zeit kosten koennte findet offensichtlich nicht statt.

Was man vielleicht optimieren könnte: fuer jeden block wird ein open/close auf /dev/mem gemacht wird, gefolgt von einem mmap/munmap. Anstatt dass man den file deskriptor offen und den ganzem 1MB Bereich gemappt laesst.

Auf https://retdec.com/decompilation/ kann man das ganz "schön" in C source umwandeln :) Zurückübersetzt läufts aber noch nicht.
 
Bei der "Nachnutzung" eines permanenten Mappings über den gesamten Buffer würde ich zumindest die Idee zuvor noch einmal testen (wenn der im I/O-Adressbereich des Prozessors liegt) ... als "user-land process" kommt "cableinfo" wohl auch nur an Adressen heran, die mit ein wenig Pech über einen Cache gemappt sind - weiß ich aber nicht wirklich, müßte/sollte man mal nachsehen für x86.

Aber ich würde eine löchrige Socke gegen einen 300E verwetten (der kriegt ohnehin wohl kein KRACK-Update), daß der "cableinfo" im DVB-C-Repeater auf denselben Quellen basiert und bei MIPS hat dann "cableinfo" auch nur Zugriff auf "kuseg"-Adressen - ich bin mir nicht sicher, ob die auch wirklich auf "kseg1"-Adressen gemappt werden (und nicht auf "kseg0") und damit nicht über den Cache gehen.

Insofern kann das stets neue Mapping schon einen Sinn haben (beim open/close ist das wohl anders) ... auf jeden Fall dürfte durch eine neues Mapping automatisch auch bei x86 für Kohärenz (TLB und Caches) gesorgt werden, auch wenn es natürlich Zeit kostet.
 
Das ist richtig, wobei das sequentielle auslesen eines ~2MB buffers eine effektive Methode ist den cache zu invalidieren (wenn er nur 256KB gross ist ..). Aber das sind wohl eh nur peanuts, ich denke die performance geht woanders verloren.

@MSN: Kannst Du nicht mal testen was passiert wenn du das interface welches zu deinem Switch geht einfach ohne bridge betreibst? D.h. das interface herausnehmen und ihm dessen IP Adresse geben.
Dadurch würde der overhead der software bridge schon mal wegfallen, zumindest für die Daten die zu tvheadend gehen.

(Edit: aber schick vorher die Familie ins Bett ..)
 
du meinst das interface aus der bridge nehmen und in die ethinterfaces packen und darüber dann streamen?
 
So in etwa, aber nicht gleich statisch. Nicht dass du dich bei einem Fehler aussperrst.
Ich habe mal ein interface aus der lan bridge genommen, darauf zwei virtuelle interfaces und am anderen ende zwei clients mit hd streams beliefert. Macht leider keinen Unterschied.
 
Also ich hätte ja echt Interesse daran den cableinfo neu zu kompilieren. Ich schau mir das jetzt mal eben an was der decompiler da ausspuckt. Im normalfall ist sowas aber immer eher unbrauchbar, zumindest wenn man das nicht selbst mit ASM kenntnissen wieder repariert. Wobei der code auf den ersten blick brauchbar aussieht, was jedoch nicht heißt das er auch funktioniert, selbst wenn er perfekt kompilieren würde. Schade das AVM den source code nicht veröffentlicht (wobei da noch niemand angefragt hat soweit ich weiß), dann könnte man das Problem selbst in Angriff nehmen. Mit den jetzigen Infos ist es ja wohl noch nicht möglich das Teil nachzubauen, alleine um herauszufinden wie das nun genau mit dem antunen einer Frequenz und den PIDs und dem ganzen kram funktioniert müsste man wohl Monate investieren.

In cableinfo hab ich in IDA auch den string "lan" gesehen, vermutlich damit er auf der richtigen bridge lauscht. Da muss man vielleicht beim ändern der Interfaces Rücksicht drauf nehmen.

Das open/close verhalten könnte es eventuell erklären: Je mehr streams desto mehr kommt dabei ja an I/O zusammen. Da das Problem ja "Bandbreitenabhängig" ist, also davon wie viel Bandbreite ein Stream beansprucht wäre es Interessant zu wissen ob die Daten in /dev/mem schnell genug und rechtzeitig bereit stehen oder ob die dort nicht rechtzeitig abgeladen werden.

Gibt es eine Möglichkeit den ARM zu stoppen während der x86 weiter läuft? Mich interessiert ob der ARM auch an dem DVB-C Streamen beteiligt ist oder ob dieser abgeschossen werden kann und /dev/mem direkt mit dem Tuner kommuniziert/den speicher teilt.
 
Also ich hätte ja echt Interesse daran den cableinfo neu zu kompilieren.
Das zurueckuebersetzen geht zwar mit ein paar Anpassungen, aber es crasht recht schnell und waere wohl kaum effizient, wenn man sich den code anschaut.

In cableinfo hab ich in IDA auch den string "lan" gesehen
Cableinfo ist nicht auf "lan" fixiert, was den Datentransfer betrifft. Es baut in die m3u daten halt per default die IP addresse des lan interfaces ein, wenn man das aendert streamt es auch auf andere interfaces.

Gibt es eine Möglichkeit den ARM zu stoppen während der x86 weiter läuft
Es wird kurz eine tcp Verbindung zum arm (169.154.1.2) aufgebaut, aber ich sehe dort keinen service der signifikant viel macht.

Generell schlaegt der reine Netzwerktraffic fuer das Senden eines HD streams (14 MBit/sec) mit ca. 5% CPU last zu Buche. Ich habe den stream mal mit wireshark aufgezeichnet und mittels tcpreplay auf der box wieder abgespielt.
memcpy read schafft auf "normalen" speicher 644MB/sec, waehrend es auf den "dvb" speicher 455MB/sec sind (evtl. weil nicht gecacht).

Selbst wenn die Daten also vor dem Schicken einmal umkopiert werden sehe ich keinen Grund was da so viel Performance braucht. Irgendwie scheint mir das tool extrem ineffizient zu sein. Was mich wundert ist dass pro loop nur ein einziger syscall stattfindet (epoll_wait) der auf einen delay schliessen wuerde. Ich hoffe ja nicht dass zwischen den paketen ein busy-wait stattfindet ...

Code:
     0.000282 ioctl(23, 0xc0080644, 0xbfcd74f8) = 0
     0.000322 ioctl(23, 0xc008067c, 0xbfcd74f8) = 0
     0.000318 time(NULL)                = 1517134159
     0.000758 clock_gettime(CLOCK_MONOTONIC, {732853, 306386150}) = 0
     0.000301 clock_gettime(CLOCK_MONOTONIC, {732853, 306671158}) = 0
     0.000276 epoll_wait(8, {}, 256, 1) = 0
     0.001491 clock_gettime(CLOCK_MONOTONIC, {732853, 308430370}) = 0
     0.000418 clock_gettime(CLOCK_MONOTONIC, {732853, 308871918}) = 0
     0.000808 ioctl(23, 0xc02c0620, 0xbfcd74d4) = 0
     0.000291 ioctl(23, 0xc010066f, 0xbfcd74f0) = 0
     0.000462 ioctl(23, 0xc148063e, 0xbfcd73a8) = 0
     0.000363 open("/dev/mem", O_RDWR|O_SYNC) = 26
     0.000778 old_mmap(NULL, 26320, PROT_READ|PROT_WRITE, MAP_SHARED, 26, 0x7dc0000) = 0xb6de2000
     0.000639 close(26)                 = 0
     0.000850 clock_gettime(CLOCK_MONOTONIC, {732853, 313194616}) = 0
     0.000492 sendto(20, "\200!\26#\0\0\0\0002\366\7\347G\23\355\31\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"..., 1328, MSG_DONTWAIT, {sa_family=AF_INET, sin_port=htons(50852), sin_addr=inet_addr("192.168.0.57")}, 16) = 1328
     0.001067 clock_gettime(CLOCK_MONOTONIC, {732853, 314593737}) = 0
     0.000488 sendto(20, "\200!\26$\0\0\0\0002\366\7\347G@\0\32\0\0\260\35\3\373\305\0\0\0\0\340\20(=\363"..., 1328, MSG_DONTWAIT, {sa_family=AF_INET, sin_port=htons(50852), sin_addr=inet_addr("192.168.0.57")}, 16) = 1328
     0.001097 clock_gettime(CLOCK_MONOTONIC, {732853, 316208734}) = 0
     0.000531 sendto(20, "\200!\26%\0\0\0\0002\366\7\347G\23\355\23\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"..., 1328, MSG_DONTWAIT, {sa_family=AF_INET, sin_port=htons(50852), sin_addr=inet_addr("192.168.0.57")}, 16) = 1328
     0.001412 clock_gettime(CLOCK_MONOTONIC, {732853, 318184170}) = 0
 
Mit busy wait meinst du quasi ein while loop bis die entsprechenden Pakete zur Verfügung stehen?

Wie ist das eigentlich mit der "Sender-Unterteilung": Landen die Daten aller Sender munter gemischt in /dev/mem oder ist das nach Tuner/Frequenz sortiert? Ansonsten muss cableinfo ja grundsätzlich alles einlesen, und das ganze dann sortieren und dem richtigen Client zusenden. Was mich wundert ist, das ich das Problem auch habe wenn TVHeadend auf der selben Frequenz mehrere Streams abruft, also wenn sich mehrere Sender eine Frequenz teilen und man davon 3 Stück oder so schaut. Die Daten müssten ja eigentlich sowieso in /dev/mem liegen, da der Tuner die empfängt (außer da wird gefiltert). Dann geht also entweder das davon lesen oder das zum client schreiben nicht schnell genug. Oder aber die Daten sind so groß, das die in /dev/mem schon überschrieben wurden bevor sie gelesen wurden. Ist das möglich?

Das ganze Teil müsste man meiner Meinung nach auch multithreaded machen, also pro Client einen Thread starten (und dann gleich noch die 4 Tuner Beschränkung und diese 1 Stream pro IP Beschränkung rausnehmen wenn man das schon mal vernünftig macht). So ein 24 Kanal Tuner reizt mich ja schon irgendwie ;) Auch wenn es da wahrscheinlich dann tatsächlich mit der Bandbreite eng wird.
 
Das Demuxen (bzw. genauer ja das Filtern nach PIDs) des kompletten TS auf dem Transponder dürfte "in Hardware" erfolgen ... es gibt einen entsprechenden Kernel-Driver in der Box (ismddemux_v3).

Schaff' Dir doch einfach mal einen Shell-Zugang zur Box an, da kann man doch vieles dann tatsächlich nachprüfen/-lesen/-sehen und ist nicht mehr überall auf Vermutungen angewiesen - den Demuxer findet man z.B. dann sofort mit "lsmod".

Da es auf der Box selbst ja keine Anzeige-/Ausgabemöglichkeiten gibt (headless device), fehlen aber alle anderen "ismd"-Treiber (das "ISMD" steht für "Intel Streaming Media Driver"), die man ansonsten noch in den Intel-CE-Geräten (z.B. Google-TV oder Boxee) finden konnte, wie "ismdviddec_v2", "ismdaudio" oder "ismdvidpproc". Der CE2600 kann theoretisch sogar noch vieles mehr, wird aber in der AVM-Box praktisch auf das Filtern von TS geschrumpft - das Ergebnis wird dann ins Netz verteilt.

Wenn Du Dich mit dem Thema befassen willst, wirst Du ja sicherlich die Theorie hinter einem "Transport Stream" (MPEG-TS) kennen und mit den Begriffen "MPEG-PS", "PES", "PID", "PMT" und "PAT" genauso etwas anfangen können, wie mit "Demuxen" und "Muxen".

Daß der RTP-Stream zum Client gar nicht mehr alle PIDs eines Transponders enthält, kann man sich spätestens mit dem VLC (unter Codec-Informationen) auch ansehen, wenn man es nicht schon aus der URL für einen Stream schließen will, wo z.B. solche Parameter enthalten sind: pids=0,16,17,18,20,100,101,102,103,104,105,106,2070,2171 - von spezialisierten Tools zur Analyse von TS, PES und PS fange ich gar nicht erst an.

Also muß es zwangsläufig irgendwo einen "Filter" geben, der die nicht benötigten PIDs ausfiltert - es wäre auch ziemlich weich im Kopf, wenn man tatsächlich den gesamten Transponder mit allen dort gesendeten Daten auf die Reise ins Netzwerk schicken würde ... dieser TV-Empfang über die FRITZ!Box zielt ja eher auf einzelne Clients "zum Sehen" ab als auf irgendwelche Media-Center als Konzentratoren oder Recorder dahinter, die dann ihrerseits den kompletten TS erst mal demuxen.

Bei DVB-C in Europa (mit 8 MHz-Kanälen) kann ein MPEG-TS mehr als 50 Mbit/s transportieren (bei QAM256) und da sind dann bei den meisten Providern auch mal 3 MPEG-PS für HD-Sender auf demselben Transponder und bei SD-Programmen sogar noch mehr, je nachdem, wie die VBR-Festlegungen im Encoding (oder Recoding) beim Provider so sind.

Warum sollte man jetzt - solange der Client nur einen Stream "sehen" will - 2/3 der Daten (bei HD, bei SD noch sehr viel mehr) vollkommen umsonst senden und dadurch nicht nur Energie auf der Box verbraten, sondern auch noch Durchsatz im Netzwerk - im schlimmsten Fall sogar im WLAN?

---------------------------------------------------------------------------------------------------------

Auch kann ich bei "vernünftig macht" nur noch in Grenzen folgen, denn die "Grundüberlegungen" (und dafür die passenden Grundkenntnisse) gehören da eben auch dazu - wie man bei einem Wunsch nach einem "24-Kanal-Tuner" (ich übersetze hier mal "Kanal" mit "Transponder", weil Du das vermutlich von anderen STB her kennst und "ein Kanal" halt sowohl "ein Programm" (also ein PS) als auch ein kompletter Transponder (also der gesamte TS) sein könnte) davon ausgehen kann, daß es "wahrscheinlich dann tatsächlich mit der Bandbreite eng wird", ist mir einigermaßen unbegreiflich.

Selbst wenn man mal den Overhead durch Netzwerk-Protokolle nicht einrechnet (der TS auf dem Transponder hat keine "Verpackung" weiter, auch wenn er aus PES-Blöcken an sich besteht - die Daten, um das im Netzwerk zu verteilen, muß der (DVB-C-)"Receiver" dann hinzufügen), wäre bei jeder GbE-Verbindung bereits bei 20 * 51,something Mbit/s deutlich "overload" und die Annahme, dem könnte man dann ja mittels LACP einfach mehr als einen GbE-Port verpassen, läßt eben wieder den physikalischen Aufbau der Box (Dir wurde ja schon eine Quelle dafür ans Herz gelegt) vollkommen außer acht, weil eben der Prozessor nicht einfach über zwei interne Ports an den Switch angebunden werden kann (und von dem kommen die Daten immer noch).

Die Frage, ob das tatsächlich der Prozessor noch schaffen würde, die Daten schnell genug (mit einem "user-land program" und damit verbundenen Kontext-Wechseln) aus dem I/O-Memory des Demuxers (ich nehme mal an, daß der auch mit DMA arbeitet, ist aber nur geraten) in Netzwerk-Pakete zu packen und zu senden, um damit mehr als einen GbE-Port zu bedienen, lasse ich mal komplett außen vor - das kann man wohl nur selbst messen.

Ich kenne jedenfalls den Demuxer im Chipset auch nicht und vielleicht kriegt man es sogar hin, den kompletten TS zu übertragen ins Netzwerk und auf das eigentliche Filtern nach PIDs zu verzichten (notfalls, indem man alle PIDs für den TS irgendwo auflistet) ... aber ich kann mir wieder nur schwer vorstellen, daß der Demuxer tatsächlich über die Möglichkeit verfügt, über seine Backplane die Daten von 24 Tunern (sprich: 24 Transpondern) entgegenzunehmen (ich glaube nicht, daß diese wieder direkt in den Speicher schreiben können) und die dann (und zwar auch alle schön zeitgerecht, denn wir reden hier von Echtzeitverarbeitung und nicht vom Buffern eines YouTube-Streams) im Speicher so abzulegen, daß irgendein "user-land process" wie "cableinfo" die dort abholen und im Netzwerk versenden kann.

Wir reden hier über eine FRITZ!Box, mit einem Dual-Core-ATOM:
Code:
# cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 53
model name      : Intel(R) Atom(TM) CPU  652   @ 1.20GHz
stepping        : 8
cpu MHz         : 1200.052
cache size      : 256 KB
und nicht von DVB-C-Hardware bei einen KNB, der seine TS damit recoded und remixt, bevor er sie aussendet.

Mit ein wenig Pech - ich kenne das auch nicht gut genug für eine definitive Aussage - ist bereits bei 4 Demux-Prozessen dann auch wieder Schluß ... das würde ja auch für vier Streams von vier verschiedenen Transpondern bereits reichen und damit für eine (raw) Bitrate von > 200 Mbit/s, wenn es sich um (DVB-C-)Kanäle mit QAM256 handelt (bei QAM64 sind es "nur" noch knapp 40 Mbit/s pro Channel).

Wie gesagt ... ich habe mich auch nur am Rande damit befaßt, aber man sollte bei seinen "Plänen" schon halbwegs realistisch bleiben und zumindest die Grundlagen des Ganzen auch kennen und einigermaßen verstehen - sonst ist's am Ende alles nur heiße Luft, was dabei herauskommt.

---------------------------------------------------------------------------------------------------------

Ich würde mich jedenfalls erst mal mit den Komponenten des "Intel Media Processor SDK" befassen und mit dem, was man auch auf dem ATOM-Prozessor davon sehen kann (von "/scripts/*" über (ungenutzte Skripte in) "/etc/init.d" bis zu den Modulen aus dem CESDK, die sich im "/lib"-Verzeichnis finden und wo man mal einen Blick mit "strings" hineinwerfen kann) - dann wird so ein Plan ggf. auch etwas realistischer als die Absicht, "cableinfo" durch Reverse-Engineering auf 1001 Tuner aufzublasen (wem die Zahl zu hochgegriffen erscheint, der ändert einfach das zugrundeliegende Zahlensystem).
 
Zuletzt bearbeitet:
Hallo PeterPawn,

den Shell Zugang habe ich bereits, und auch mit VLC habe ich mir bereits die Medien Informationen angesehen: Hier werden mir ALLE Streams mit Namen des Senders die auf dem jeweiligen "Kanal"/Transponder sind angezeigt. Ich war davon ausgegangen, das die Bezeichnung Transponder für SAT vorbehalten ist, und man bei DVB-C von Kanälen spricht, ebenso wie die Upstream und Downstream Kanäle von DOCSIS. Scheinbar ein Trugschluss. Auch sind die URLs in der erzeugten hd.m3u bzw. sd.m3u sehr "PID-reich", also da wird deutlich mehr angefordert als tatsächlich benötigt wird.

Das "vernünftig macht" war darauf bezogen, das jetzige Problem zu lösen und diese 1 Stream pro IP Beschränkung rauszunehmen. Im Sinne von "wenn man schonmal dabei ist das zu tun, kann mans auch gleich richtig machen". Die 24 Tuner sind ja das maximum, also selbst wenn der Prozessor sonstwas leisten könnte.

Du bist von 50 Mbit/s pro Transponder ausgegangen, finde ich etwas hoch wenn man von einem HD Sender ausgeht der gestreamt werden soll. Mir geht es nicht darum die 24 Transponder 1:1 ins LAN zu spiegeln, das wäre wahnsinn und unnötig, mir geht es darum das selbst wenn hier alles an Fernsehern an ist und noch einige Aufnahmen programmiert sind, das zu keinen Problemen führt. Mit 24 Transpondern/Frequenzen wäre das definitiv gegeben, ein HD Stream braucht wenn es Sky Sport HD ist um die 20Mbit/s. Ein IPerf Test hat hier ergeben das 680MBit/s das maximum ist, also wären 32 HD Sender gleichzeitig möglich, wenn die alle so eine hohe Datenrate wie Sky Sport HD hätten. Die meisten sind da aber etwas sparsamer (kostet ja auch mehr) und deshalb wird mit weniger eingespeist.

Meine "Pläne" sind erstmal nur das Teil auf die versprochenen 4 Sender zu bringen, relativ egal wie. Alles andere ist zwar schön, aber wie du schon sagst wird es dann sehr schnell sehr unrealistisch. Selbst mit 2 Fritzboxen mit jeweils 4 Tunern wäre ich mehr als glücklich, das sind 8 Transponder von 33 die eingespeist sind. Wenn man da sämtliche SD Kanäle rausnimmt sowie die ganzen VF Varianten dann bleiben um die 12 Transponder wo wirklich sinnvoller Inhalt draufliegt.
 
Die Vielzahl der PIDs, die von der FRITZ!Box übermittelt werden für einen Sender, beinhaltet i.d.R. einen Video-Stream, einen oder mehrere Audiostreams und noch ein paar mit Untertiteln - hängt halt vom Sender ab.

Jeder TS auf einem Transponder (meinetwegen kann man den auch "channel" nennen, nur ist im Deutschen der (Fernseh-)Kanal halt mit einer anderen Bedeutung verbunden) enthält eine PAT (Program Association Table), die wieder für jeden im TS enthaltenen "Service" (aka "Sender") eine Beschreibung in Form einer PMT (Program Map Table) bereithält (genauer die PID des Stream, in dem diese enthalten ist). In der PMT findet sich dann für jeden ES (Elementary Stream), der zu einem Service gehört, dessen PID (für den PES).

"Über" der PAT eines TS gibt es dann noch die NIT (Network Information Table), in der ein TS einem "Anbieter" zugeordnet wird und ggf. weitere Transponder dieses Anbieters gelistet sind.

Die (von der FRITZ!Box nicht gefilterten) Vorschauinformationen liegen als EIT (Event Information Table) vor, ob ein Service eine EIT hat und ob er verschlüsselt ist oder nicht, steht dann in der SDT (Service Description Table). So eine EIT steckt dann in einem ES mit der PID 0x12 (also 18 dezimal) und da dort eben i.d.R. für alle Services auf dem Transponder die Daten enthalten sind (obwohl es auch die für einen "fremden" sein dürfen, es gibt unterschiedliche Table-IDs für EITs), sieht man die auch im VLC, wenn der übertragene Stream PID 18 einschließt (der VLC kann dann die EIT-Elemente dekodieren).

Diese verschiedenen Informationen (SI - Service Information) müssen dann mit unterschiedlicher Häufigkeit im Datenstrom auf einem Transponder/Channel enthalten sein - dort holen sich Receiver (und die FRITZ!Box) dann ihre Informationen ab.

Das ist alles in den entsprechenden Standards beschrieben: http://www.etsi.org/deliver/etsi_en/300400_300499/300468/01.15.01_60/en_300468v011501p.pdf und der grundlegende Aufbau eines MPEG-Streams ist auch derselbe, egal auf welchem Weg man den am Ende empfängt. Das ist die "Gemeinsamkeit" in den ganzen "DVB-C/S/T"-Standards, nämlich das DVB (Digital Video Broadcasting).

Wenn es also gelingt, einen kompletten TS ohne Filterung ins Netzwerk an einen Server zu übertragen, dann kann der (genug Power oder passenden Hardware-Support vorausgesetzt, auch eine STB empfängt ja immer "alles" und kann das nur in Hardware ziemlich effektiv filtern und decodieren) problemlos alle im Mux enthaltenen Services speichern - wenn er will sogar den kompletten TS, wobei auch hier wohl fast alle Receiver (ich kenne jedenfalls keinen anderen) nur die PIDs herausfiltern, die zum aufzunehmenden Programm gehören (und nicht mal immer alle Audio-PIDs auf einmal speichern). Liegen auf so einem Transponder dann 10 SD-Sender (bei entsprechend kleiner Datenrate kein Problem, nur eben ein besch****enes Bild), kann man schon mit dem einen Transponder halt 10 Programme aufzeichnen (das kennt sicherlich jeder, der einen Linux-Receiver wie die DreamBox oder Vu-Geräte oder irgendwas anderes besitzt).

Aber häufig genug machen dann auch die Aufzeichnungsmedien schlapp (mit der Folge von Frame-Drops, weil Daten dazwischen nicht rechtzeitig geschrieben werden konnten) ... auch das muß man eben dann erst mal hinkriegen, daß eine HDD (meinetwegen 2,5" mit 5.400 min ** -1 - die sind dann wieder schön leise und wohnzimmertauglich) die Daten für mehrere Streams schnell genug wegschreiben kann - da darf es am Ende keinen unnötigen Positioniervorgänge geben, nur weil irgendeine "free blocks chain" mal schnell aktualisiert werden muß - wobei es natürlich auch wieder eine Rolle spielt, wie das HDD-Interface ans System angebunden ist (bei USB2.0 ist dann spätestens bei ~30 MB/s auch Ende der Fahnenstange).
 
Wenn ich per TVHeadend 3 HD sender mit der selben Trägerfrequenz empfange, verbruacht das nur einen einzigen Tuner auf der FB. Die PIDs filtert TVHeadend also irgendwie später raus.

Bei 3 HD Streams auf der selben Frequenz meldet TVHeadend ~22Mb/s, bei 2 wird es nicht signifikant weniger. Bei nur einem sender sind es dann noch 8Mb/s.

Heißt also:
- Die FB schickt immer nur die PIDs die angefragt werden
- Man kann die PIDs für mehrere Sender auf der selben Trägerfrequenz über eine einzige verbindung empfangen

Also habe ich mal verglichen: 3 Sender auf verschiedenen Trägerfrequenzen und 3 Sender auf der selben Trägerfrequenz. Da verhält sich aber offenbar beides gleich: Artefakte bei vollbildwechseln. Wenn sowas wie ein interview läuft wo nur der mund bewegt wird ist es artefaktfrei.
 
Die Artefakte bei Vollbildwechseln haben was damit zutun, das in der Regel nur Änderungen übertragen werden und immer mal wieder ein Referenzbild. Die Referenzbilder sind möglicherweise auch von der Kopfstelle so getimed, das die nicht alle auf einmal gesendet werden.

Ich hab mich jetzt mal mit den riesigen Mengen an Informationen über den Chip beschäftigt, am besten wäre wohl ein kernel module was den ganzen krams übernimmt, also quasi cableinfo als kernel modul machen. Das wäre noch mal zusätzliche Geschwindigkeit. Wenn man das noch multithreaded schafft dann ist es an Leistung kaum noch zu überbieten wenn man das anständig implementiert. Nachteil ist hier natürlich das es perfekt sein muss, sonst gibt das ständig einen Kernel Panic.
 
kernel module? umpf... sourcen wirds kaum geben, oder? also reverse... :/ aber wer??? kann das und hat zeit & lust dazu?
 
Ich habe mal den frameverlauf mittels tcpdump mitgemessen, und das Ergebnis deckt sich mit der Analyse des codes:
  1. Das Paketintervall ist immer ~0,4ms, egal ob SD oder HD, egal ob 1 oder 2 streams mehr habe ich nicht getestet.
  2. Es wird immer ein burst von 20 paketen geschickt, alternierend zwischen den streams.
  3. Das Intervall zwischen den bursts ist ca. 11-22ms, je nachdem ob SD oder HD. In dieses Intervall versucht die Box alle Pakete (mit dem 0,5ms Abstand) hineinzuquetschen, wass irgendwann einfach nicht mehr geht.
Wie gesagt, ich habe es nur mit zwei streams getestet, was bei mir schon zum stottern reicht. Gemessen einfach mit tcpdump -i lan ... auf dem atom.
Hier mal ein bild (rot/gruen sind die beiden streams, 1 balken =1 paket).

Wuerde cableinfo nicht das starre 0,5ms Intervall zwischen ALLEN paketen einhalten, sondern die 20-pakete bursts ineinander verschachtelt verschicken dann hätte es, denke ich, genug Zeit und CPU performance. Aber so ....

Edit:
Mit ltrace sieht man dass zum timen funktionen aus der libavmcsock aufgerufen werden:

Code:
csock_sockaddr_set_inaddr(0xbfc7b71c, 0xb73eaa08, 0xef02, 0xb7281800) = 0x3900a8c0
csock_send_datagram(0xb7288aa0, 0xbfc7b71c, 0xb7281810, 1328 <unfinished ...>
slab_cbcontext_free(0xb7281800, 0x806704a, 188, 16)                 = 0
<... csock_send_datagram resumed> )                                 = 0
timercb_del(0, 0x37389181, 1316, 1316)                              = 1
timercb_add(0, 0x8062670, 2500, 1000)                               = 0x37389181
slab_dmalloc(1484, 0x806704a, 176, 1392)                            = 0xb7281800
csock_sockaddr_set_inaddr(0xbfc7b71c, 0xb73eaa08, 0xef02, 0xb7281800) = 0x3900a8c0
csock_send_datagram(0xb7288aa0, 0xbfc7b71c, 0xb7281810, 1328 <unfinished ...>
slab_cbcontext_free(0xb7281800, 0x806704a, 188, 16)                 = 0
<... csock_send_datagram resumed> )                                 = 0
timercb_del(0, 0x37389181, 1316, 1316)                              = 1
timercb_add(0, 0x8062670, 2500, 1000)                               = 0x37389181

Ist da evtl. die API von anderen Projekten bekannt? Man koennte cableinfo mit LD_PRELOAD was anderes unterjubeln und die intervalle verringern.

UgHCJd9
 

Anhänge

  • hd_dual.png
    hd_dual.png
    384.6 KB · Aufrufe: 17
  • hd_dual2.png
    hd_dual2.png
    80.9 KB · Aufrufe: 16
Zuletzt bearbeitet:
Ich gehe mal davon aus, daß da dem Demuxer ein Buffer vorgegeben wird und der dann - wenn der Buffer gefüllt wurde - irgendeinen IRQ auslöst, in dessen Folge "cableinfo" geweckt wird (oder das "epoll_wait" dann - anders als in Deinen strace-Auszug weiter vorne - auch mal mit einem "bereiten" FD antwortet innerhalb des 1ms-Timeouts ... oben ist es ja ein "timeout" ohne bereiten FD, wie der Return-Code von 0 zeigt) und die Daten dann verschicken will.

In ein Ethernet-Paket kriegt man max. 7 Pakete aus dem TS hinein (eines hat eine Größe von 188 Byte), weil sich zzgl. der verschiedenen Header (IP, UDP, RTP) eine Payload-Größe von 1356 Bytes ergibt - in so einem Paket sind dann 7 * 188 = 1316 Bytes aus dem TS enthalten.

Wenn man also einen wirklich "konstanten" Datenstrom erzeugen wollte und jeweils diese 1316 Bytes versenden will, sowie sie angekommen sind, müßte man das irgendwie so in Auftrag geben können, daß der Demuxer Bescheid gibt, sowie dieser Buffer gefüllt ist. Das ist ja keinesfalls nach einer konstanten Zeit der Fall ... das hängt davon ab, welche PIDs gefiltert werden und in welcher Frequenz die Pakete für diese PIDs auf dem TS auftreten.

Wenn AVM hier jeweils 20 Pakete verschickt, wird da wohl irgendetwas eingestellt sein, was dafür sorgt, daß nach 140 PES-Paketen der "cableinfo" mal zum Versand aufgefordert wird.

Das Einrichten und Löschen von Timer-Callbacks würde ich eher der Tatsache zurechnen, daß da irgendwelche Timeout-Vorkehrungen getroffen werden ... man müßte mal an Adresse 0x08062670 mit einem Debugger nachsehen, was die Callback-Routine (das dürfte ihre Adresse sein oder zumindest die einer Datenstruktur, wo die Adresse der Callback-Routine drinsteht - wobei ich die vom Wert her eher im Code-Segment ansiedeln würde als in den Daten, wenn man sie mit denen von den Socket-Calls vergleicht) da genau machen würde.
 
Der code der callbackfunktion setzt nur ein flag in einer Datenstruktur auf 1 (result + 260):

Code:
// Address range: 0x8062670 - 0x8062685
// XXX timer callback
int32_t function_8062670(int32_t result) {
    // 0x8062670
    g2 = result;
    if (result != 0) {
        // 0x806267a
        *(int32_t *)(result + 260) = 1;
        // branch -> 0x8062684
    }
    // 0x8062684
    return result;
}

Es gibt nur eine andere stelle im code welches dieses flag abfraegt, und das ist im wesentlichen eine busy-wait loop:

Code:
// Address range: 0x8060508 - 0x8060577
// wait for time callback or time out XXX
int32_t function_8060508_wait_pktinterval(void) {
(...)
        while (true) {
            int32_t v4 = *(int32_t *)(v3 + 88); // 0x806052d
            g5 = v4;
            if (v4 != 0) {
                // 0x8060534
                // triggered in timer callback XXX
                if (*(int32_t *)(v4 + 260) != 0) {
                    // 0x806053d
                    if (*(int32_t *)(v3 + 48) != 5) {
                        // 0x8060543
                        g4++;
                        // branch -> 0x8060567
                      lab_0x8060567_2:;
                        int32_t v5 = *(int32_t *)v3; // 0x8060567
                        g7 = v5;
                        if (v5 == 0) {
                            // break -> 0x8060569
                            break; // exit loop XXX
                        }
                        v3 = v5;
                        // continue -> 0x806052d
                        continue; //poll loop XXX
                    }
(...)

Ich habe im cableinfo mittels eines runtime debuggers einen parallel-thread gestartet der das flag in einer loop permanent auf 1 setzt.

Damit sehe ich dass die Paket-intervalle teils auf 0,1ms heruntergehen. Ob das am geänderten Laufzeitverhalten liegt (noch eine 100% CPU last) oder ob ich damit tatsaechlich (manchmal) die loop eliminiert habe kann ich noch nicht sagen.
Aber es zeigt zumindest dass das starre 0,5ms Intervall nicht noetig ist, die stream-Qualitaet hat nicht gelitten.

@Flole, du wolltest doch Assembler patchen. Der caller von timercb_add(0, 0x8062670) setzt das flag explizit auf 0, vielleicht kann man das leicht aendern. Ich bin nicht so gut in x86 ..
 
Ich versuche erstmal zu verstehen was da genau passiert, klar kann ich da alles mögliche patchen, ich schau gleich mal nach was man da machen kann. Das Parameter auf 1 ändern wäre also dein Ansatz? Ich kenne mich noch nicht so gut mit den ganzen "innereien" von Linux und geschweige denn AVM aus, deswegen muss ich mir vieles da erst einmal anschauen um die Zusammenhänge zu verstehen.

Seit heute gibts ja auch UHD Sender bei Vodafone und Unitymedia. Und wie könnte es bei teilweise 100000 kbit/s und fast dauerhaft über 60000kbit/s auch anders sein, ist der Empfang natürlich mit der Fritzbox absolut unmöglich. Das ist mehr Standbild als Bewegung was da passiert.

EDIT: So, ich hab das mal eben gepatcht und es scheint besser zu sein. Die gepatchte Version unterliegt aber warscheinlich dem Copyright von AVM, eine veröffentlichung ist deshalb nicht möglich (wer fragt dem wird aber auch geholfen, dennoch ist Sky UHD nach wie vor nicht möglich).
 
Zuletzt bearbeitet:
@fesc:
Du solltest das trotzdem noch einmal genauer anschauen ... die Paket-Intervalle können nicht konstant sein (die Daten sind ja nicht "regelmäßig verteilt" auf dem Transponder, das ist praktisch überall VBR und da hängt die Bitrate eines Streams und damit die Anzahl der Pakete pro Zeiteinheit dann sogar davon ab, wieviele Änderungen sich in den Deltas wiederfinden müssen - egal ob das jetzt komplette Frames bei SD sind oder nur Slices bei HD) und solange man nicht weiß, wie die Kommunikation zwischen dem Demuxer und dem Rest des Systems abläuft, kann das genauso gut auch sein, daß der "cableinfo" ganz stump einige Daten mehrfach sendet (weil er z.B. das nimmt, was da gerade im Buffer steht, wenn ihm irgendein Flag sagt: "Buffer ist gefüllt") und erst der Client die dann tatsächlich als doppelt verwirft. Eine rein timerbasierte Schleife zum Versenden von RTP-Paketen, die man aus einem TS erzeugen muß, macht einfach keinen richtigen Sinn - die Daten kommen nicht "synchron" herein und eine Angabe von 8 Mbit/s für einen Stream ist immer nur ein Mittelwert über eine definierte Zeitspanne, solange da nicht tatsächlich CBR verwendet wird (und selbst dann ist ein TS nicht konstant, solange da PIDs für SI ebenfalls enthalten sind - denn die kommen auch nicht mit konstanten Raten, da gibt es nur "Mindestintervalle", nach denen sie einmal im Stream auftreten sollen).

Der Player muß die A/V-Pakete des PES ja dann wieder in die korrekte Reihenfolge bringen und zum Abspielen "auswählen". Wenn der jetzt doppelte PES-Pakete findet (die haben i.d.R. einen Timecode), wäre es am schlauesten, die einfach zu verwerfen (was soll er auch sonst damit machen, er kann die ja nicht einfach auch doppelt in den Video-Stream einbetten) - und solange es nicht irgendwo eine verkettete Liste oder einen Ringpuffer für die Kommunikation mit dem Demuxer gibt (worüber der den tatsächlichen Füllstand der Buffer mitteilen kann) und das einfach daran festgemacht wird, daß der Demuxer (hier muß man ja schreiben "vermeintlich", wenn Du das Flag manipulierst) eine ausreichende Anzahl von Paketen bereitgestellt hat, die der "cableinfo" dann auch sendet, würde das nur unnütze Last verursachen.

Was passiert denn jetzt, wo Du dieses Flag immer auf "1" hältst? Kommen da immer noch 20 (UDP-)Pakete am Stück pro "Sender" oder sind es jetzt - wegen des kürzeren Intervalls - auch weniger Pakete, die für einen Sender als "Burst" verschickt werden?

Wenn das immer noch 20 am Stück sein sollten, wäre die Vermutung mit dem doppelten Senden ja wieder naheliegend - wie sollten ansonsten in einem viel kürzeren Zeitraum genauso viele Daten für die gefilterten PIDs im TS auftauchen, wie in einem längeren? Hier könnte man ja mal einen Stream speichern lassen und ihm dann mit einem Analysator zuleibe rücken ... z.B. mit ProjectX - dann sollte man doppelte Daten dadurch sehen können (im ausführlichen Protokoll), daß die beim Demuxen/Korrigieren verworfen werden und es eine entsprechend große Differenz bei den Frame-Countern zwischen Ein- und Ausgabe gibt. Aber auch "ffprobe" könnte man ja mal auf so einen Stream loslassen ...

Auch das x86-Patchen ist nun keine wirkliche Kunst, solange es nur darum geht, irgendwelche Befehle eben gerade nicht auszuführen ... dafür gibt es explizit eine ASM-Instruktion "NOP" mit dem OP-Code 0x90 - das gab es früher in vielen Binaries auch als "patch area", wo größere Blöcke mit solchen NOP-Instruktionen vorgehalten wurden, damit man irgendwo einen Sprung dorthin (mit Rückkehrmöglichkeit) einpatchen und in diesen Patch-Bereich dann zusätzlichen Code einfügen konnte.
 
Das mit den 20 paketen ist der worst case. D.h. es gibt einen ~25ms timeslot (SD) der strikt eingehalten wird. Pro timeslot werden bis zu 20 pakete eines streams geschickt, mit einem abstand von ca. ca 0.5ms. Es kann schon passieren dass innerehalb eines timeslots wenige bis gar kein paket geschickt werden (vielleicht warte ich ja mal auf Sendeschluss :)
Wenn aber viele streams viele Daten haben, dann ist der timeslot halt schnell voll. Und ich bin nach wie vor der Ansicht dass man das besser organisiern koennte ..

Aber mit meinen Patchversuchen bin ich erst mal gescheitert, die magische Konstante oder Funktion habe ich bisher nicht gefunden. Wer es probieren will, function_80635be()->function_8063578() wird mit Zeitinformationen gefuettert und macht einiges an (float) Rechnerei. Alles was nach Zeitinformationen fuer timercb_add() aussieht bewirkt bisher nichts.
 

Anhänge

  • single_sd.png
    single_sd.png
    202.9 KB · Aufrufe: 19
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.