hevc_FPS_changer

  • Hallo zusammen,

    Ich hatte beim re-encoden einer Serie versehentlich 23.976 (24000/1001) anstatt 25 FPS angegeben was logischerweise zu einer gewaltigen Versatz bei Video/Audio führte.
    Da ich nicht alle Episoden wieder neu coden wollte, suchte ich nach einem Programm mit dem man die FPS des Elementar-Streams ändern konnte.
    Leider erfolglos.

    Daher hab ich einfach selbst eins geschrieben.
    https://github.com/hydra44/hevc_FPS_changer

    Wer's gerne testen möchte kann sich das Python Script gerne runterladen.
    Bitte Bugs und Änderungswünsche hier im Thread.

    Limits:
    Nur RAW-HEVC Streams werden unterstützt
    Python 3.x wird benötigt
    Nur single SPS Streams werden (derzeit) unterstützt ... hab leider keine multi-SPS Clips zum testen/entwickeln ...

    Ein letztes:
    Im Prinzip kann jeder die SW so benutzen wie er will und auch in andere Sachen integrieren ...
    Daher wollte ich noch "Das Übliche" wie "Haftungsausschluss" und "License" dazu packen. Was/welche/woher nimmt man da am besten ? (Oder ist meine saloppe Formulierung in der Readme.md ausreichend :D) )

  • Hm ... ok :daumen:
    und wie oft repeated der den header ... oder besser gefragt in welchem Abstand schreibt der 'nen Neuen ?

    Nachtrag: :grübeln: so wie's ausschaut wird bei der " --repeat-headers" Option nach jedem GOP und somit vor jedem IDR Frame ein VPS, SPS, PPS und SEI_Prefix geschrieben

    Einmal editiert, zuletzt von may24 (2. Juni 2017 um 00:15)

  • Hm, macht es überhaupt Sinn einen multi-SPS check/modifier einzubauen ?

    Ich meine, der einzige "use case" der mir einfällt warum man überhaupt multi VPS/SPS/PPS bräuchte, wäre beim TV wenn zwischen 4k/HD/SD umgeschaltet wird.
    Vielleicht noch bei VOD ?

  • Nachtrag: :grübeln: so wie's ausschaut wird bei der " --repeat-headers" Option nach jedem GOP und somit vor jedem IDR Frame ein VPS, SPS, PPS und SEI_Prefix geschrieben


    Nicht nur IDR, ist etwas komplizierter. Stichwort OpenGOP.

    Ich meine, der einzige "use case" der mir einfällt warum man überhaupt multi VPS/SPS/PPS bräuchte, wäre beim TV wenn zwischen 4k/HD/SD umgeschaltet wird.


    Und woher bekomme ich VPS/SPS, wenn ich frisch in einen Sender zappe? Das muß laufend gesendet werden.

  • Ok, ich arbeite an einer neuen Version die den Ganzen File parsen kann ...

    Dabei ist mir was aufgefallen ... Stimmt es das in HEVC die Horizontale mod2 und die Vertikale mod16 sein muss ? Oder ist hier nur meine Interpretation des Binärcodes falsch ?

  • jup, und es kommt noch schlimmer ...
    Ich habe gerade ein neues Testfile erzeugt ... mit anderen Presets ... und siehe da: NICHTS passt mehr.

    Nach einiger Analyse kam jetzt heraus das der (z.B.) FPS Wert nur manchmal als mod4 gespeichert ist ... er kann aber auch als mod16 gespeichert sein. (mod8 ??)
    D.h. es gibt irgendwo ein Flag welches indiziert welcher Modulo gerade verwendet wird ... was natürlich unbekannt ist !

    Oder weiß da jemand mehr ?

  • :D

    Anmerkung: Ich habe immer "mod16" oder "mod4" in Klammern geschrieben um aufzuzeigen das es hier um ein Vielfaches von 16 o. 4 und nicht um eine Modulo Operation an dieser Stelle geht !

    ok ...
    Erstes Testfile mit 1000 Frames gecoded mit folgenden Settings:

    Code
    "C:\Program Files (x86)\Video Tools\avs2pipemod-1.1.1\avs2pipemod.exe" -rawvideo "test.avs" | "C:\Program Files\x265\x265-2.4_37.exe" --preset slower --crf 24 --psy-rd 2.0 --psy-rdoq 10.0 --aq-mode 3 --rd 5 --me star --no-open-gop --no-sao --ctu 32 --limit-modes --input-res 1280x720 --input-depth 16 --fps 24000/1003 --output "test.h265" --input -

    Wie man sofort erkennt wird nur ein SPS geschrieben. Ich habe bewusst eine völlig abstruse Geschwindigkeit genommen um die Werte besser wiederzufinden.
    Hier mal ein Ausschnitt aus dem SPS mit den relevanten Bytes:

    Code
    00 fa c0 00 17 70

    Die ersten 2 Bytes geben den Denominator an: 0xFA -> 250 -> x4 (mod4) -> 1000
    Die nächsten 2 Byte das "Offset" des Denominators (1003 kann man ja nicht durch 4 teilen ...) Nur das erste der zwei Bytes wird scheinbar ausgewertet ...
    0xC0 ist zwar dezimal 192 steht aber in diesem Fall aber für 3. ( 0x40 = 1, 0x80 = 2) ... (mod64 ???)
    Die letzten Bytes markieren die eigentlichen FPS: 0x1770 -> 6000 -> x4 (mod4) -> 24000

    ABER
    Nächstes testfile mit folgenden Optionen gecoded:

    Code
    "C:\Program Files (x86)\Video Tools\avs2pipemod-1.1.1\avs2pipemod.exe" -rawvideo "test.avs" | "C:\Program Files\x265\x265-2.4_37.exe" --preset faster --crf 24 --repeat-headers --limit-modes --ctu 32 --input-res 1280x720 --input-depth 16 --fps 24000/1003 --output "test.h265" --input -

    Diese Settings packen alle "paar Frames" einen neuen VPS/SPS/PPS in den Stream ...
    Nur jetzt schaut's folgendermaßen aus:

    Code
    00 3e b0 00 05 dc

    Erste 2 Byte: 0x3e -> 62 -> x16 (mod16) -> 992
    Zweite 2 Bytes: 0xb0 -> 176 (nur das erste Byte wird ausgewertet ... und ja, hier ist alles "big" ;) ) Teilt man die 176 durch 16 (anstatt durch 64 wie im Beispiel oben) so bekommt man 11. Addiert man das zu 992 -> 1003
    Drittes Byte Paar: 0x05dc -> 1500 -> x16 (mod16) -> 24000

    Und nun die Große Preisfrage: Wo/wie bzw. an welcher Stelle wird angegeben ob nun in mod4, mod16 oder ... gearbeitet wird ?
    Ums besser/komplizierter zu machen sollte man sich mal einen Stream mit dem hevcbrowser anschauen

  • Ich glaube, Du schaust Dir die falschen Bits an. Wenn Du etwas nach links/rechts schaust, paßt es. Jede Verschiebung um ein Bit im Binärsystem ist Multiplikation mit 2, darum immer diese Faktoren.

    80 40 00 00 FA C0 00 17 70 02 00 => 1000 0000 01[00 0000 0000 0000 0000 0000 1111 1010 11][00 0000 0000 0000 0001 0111 0111 0000 00]00 0010 0000 0000
    0000 0000 0000 0000 0000 0011 1110 1011 => 1003
    0000 0000 0000 0000 0101 1101 1100 0000 => 24000
    (je 32 bit für vui_num_units_in_tick und vui_time_scale)

    10 00 00 3E B0 00 05 DC 00 80 00 => 0001 [0000 0000 0000 0000 0000 0011 1110 1011] [0000 0000 0000 0000 0101 1101 1100 0000] 0000 1000 0000 0000 0000
    0000 0000 0000 0000 0000 0011 1110 1011 => 1003
    0000 0000 0000 0000 0101 1101 1100 0000 => 24000

    6 Mal editiert, zuletzt von sneaker2 (13. Juni 2017 um 00:36)

  • :dejection: ... ich komm nicht weiter ...

    Das Problem ist das sps:vui:time_scale & sps:vui:num_units_in_tick nicht immer an der selben Stelle im SPS stehen ... Nichtmal der SPS hat eine feste Größe und kann variieren.
    Was soviel bedeutet wie: es müssen vorher noch einige andere Bit/Bytes analysiert werden um auf die tatsächliche Position im SPS zu kommen.
    FFMpeg hat in seiner Doku die Struktur zwar abgebildet, jedoch werde ich da nicht ganz schlau draus ...

    hevc_ps.c - Ab Zeile 538 ...

    Zeile 642: vui->vui_timing_info_present_flag = get_bits1(gb);
    Ok, ab hier wird's interessant, aber ich kann nicht erkennen wie dieses Flag "gefunden" wird.

    Ich bin nicht der CPP Programmierer (komme aus dem Java Umfeld) und benötige daher etwas Hilfe den Code zu verstehen

    Das Problem scheinen die Flags zu sein ...
    Klar, meine Test-Streams haben unterschiedliche Settings und somit sind natürlich auch andere Optionen ein bzw. ausgeschaltet.
    Doch schaut man sich den Code binär an, gibt es Verschiebungen um 2 und manchmal 4 Bits ... Was ein "Ortung" extrem schwierig macht !Das würde bedeuten, die Flags werden scheinbar nicht als int's sondern wohl als Bit's gespeichert ...

    Einmal editiert, zuletzt von may24 (22. Juni 2017 um 22:17)

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!