ffmpeg mit quicksync

  • Antwort bei doom9:


    Wenn es deine GPU nicht kann (entweder MJPEG 4:2:2 speziell nicht, oder MJPEG ganz allgemein nicht), geht's halt nicht; und außerdem wäre die CPU alleine beim Decodieren vielleicht eh schneller als die GPU (inklusive des Transfers in die GPU und daraus zurück).

  • Danke dir.


    Ich hab mal testweise ein AVI mit libx264, lossless encodet um dieses 4:2:0 chroma subsampling zu erhalten (lossless ist Voraussetzung):

    Code
    1. .... -c:a ac3 -b:a 256k -c:v libx264 -preset ultrafast -crf 0 -pix_fmt yuv420p -y 420ll.mkv


    mediainfo:

    Code
    1. VideoID : 1Format : AVCFormat/Info : Advanced Video CodecFormat profile : High 4:4:4 Predictive@L4Format settings : 1 Ref FramesFormat settings, CABAC : NoFormat settings, ReFrames : 1 frameCodec ID : V_MPEG4/ISO/AVCDuration : 5 min 0 sBit rate : 133 Mb/sWidth : 1 920 pixelsHeight : 1 080 pixelsDisplay aspect ratio : 16:9Frame rate mode : ConstantFrame rate : 23.976 (24000/1001) FPSColor space : YUVChroma subsampling : 4:2:0Bit depth : 8 bitsScan type : ProgressiveBits/(Pixel*Frame) : 2.679Stream size : 4.66 GiB (98%)Writing library : x264 core 152 r2854 e9a5903Encoding settings : cabac=0 / ref=1 / deblock=0:0:0 / analyse=0:0 / me=dia / subme=0 / psy=0 / mixed_ref=0 / me_range=16 / chroma_me=1 / trellis=0 / 8x8dct=0 / cqm=0 / deadzone=21,11 / fast_pskip=0 / chroma_qp_offset=0 / threads=12 / lookahead_threads=2 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=0 / weightp=0 / keyint=250 / keyint_min=23 / scenecut=0 / intra_refresh=0 / rc=cqp / mbtree=0 / qp=0Default : YesForced : No


    Funktioniert auch nicht mit vaapi transcoding:

    Code
    1. $ ffmpeg -hide_banner -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i 420ll.mkv -c:v h264_vaapi -b:v 10M -y output.mkvInput #0, matroska,webm, from '420ll.mkv': Metadata: ENCODER : Lavf58.12.100 Duration: 00:05:00.47, start: 0.000000, bitrate: 136154 kb/s Stream #0:0: Video: h264 (High 4:4:4 Predictive), yuv420p(progressive), 1920x1080, 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc (default) Metadata: ENCODER : Lavc58.18.100 libx264 DURATION : 00:05:00.472000000 Stream #0:1: Audio: ac3, 48000 Hz, stereo, fltp, 256 kb/s (default) Metadata: ENCODER : Lavc58.18.100 ac3 DURATION : 00:05:00.416000000Stream mapping: Stream #0:0 -> #0:0 (h264 (native) -> h264 (h264_vaapi)) Stream #0:1 -> #0:1 (ac3 (native) -> vorbis (libvorbis))Press [q] to stop, [?] for help[h264 @ 0x5575607b4980] Failed setup for format vaapi_vld: hwaccel initialisation returned error.Impossible to convert between the formats supported by the filter 'Parsed_null_0' and the filter 'auto_scaler_0'Error reinitializing filters!Failed to inject frame into filter network: Function not implementedError while processing the decoded data for stream #0:0[libvorbis @ 0x5575604a4fc0] 39 frames left in the queue on closingConversion failed!


    Ich kann natürlich auf das Hardwaredecoding verzichten und folgendes ausführen:

    Code
    1. ffmpeg -hide_banner -vaapi_device /dev/dri/renderD128 -i 420ll.mkv -acodec copy -vf 'format=nv12,hwupload' -vcodec h264_vaapi -y -b:v 10M -profile:v high -level 41 -quality 1 -bf 3 -y output.mkv


    Damit erreiche ich max. 4x speed. Das geht einigermaßen. Das erklärt aber auch nicht warum das Hardwaredecoding nicht funktioniert.


    Mit dem mjpeg-avi (yuvj422p) erreiche ich so erbämliche 1,7x speed.
    Ich frage mich, warum ist das mjpeg-decoding unter Linux (arch) so unglaublich langsam ? Unter Windows erreiche ich mit dieser Datei erheblich bessere Performance.


    Ob das vielleicht ein ffmpeg Problem ist ? Weiß jemand wie man mit mencoder dieses 422-Avi nach 4:2:0 wandelt und an ffmpeg übergibt ? Diese piperei ist mir auch ein Buch mit sieben Siegeln. Muß ich mir mal bei Hybrid anschauen.


    Gruß ggrub

  • Zitat

    libx264, lossless encodet um dieses 4:2:0 chroma subsampling zu erhalten


    Nur als Anmerkung: Lossless ist mit 422 nicht standard konform. Lossless ist nur in Hi444PP erlaubt.
    (Darum geht lossless in Hybrid nur mit 'High 4:4:4' oder 'unrestricted'.)


    Zitat

    Weiß jemand wie man mit mencoder dieses 422-Avi nach 4:2:0 wandelt und an ffmpeg übergibt ?


    Welchen Sinn hat das denn? Dann kannst Du auch mehrere ffmpeg Instanzen verwenden, das hattest Du doch schon,..
    (Alles was Du in zwei ffmpeg aufrufen hast, wobei der eine den anderen füttert sollte auch in einem Aufruf gehen.)


    ---

    Code
    1. ffmpeg -vaapi_device /dev/dri/renderD128 -i test_01.avi -vf 'format=yuvj422p,hwupload' -c:v h264_vaapi -threads 8 -qp 18 output.mkv


    Ging ja und war nur langsam, wie sieht es denn aus, wenn Du dort 'format=yuv420p' verwendest anstatt yuvj422p?
    Ist denn bekannt welche Formate hwupload entgegen nehmen kann?


    Cu Selur

  • Zitat

    Lossless ist mit 422 nicht standard konform


    Ok, hab ich notiert. Bleibe ich also bei dem was die Capturekarte direkt zur Verfüung stellt: mjpeg yuvj422p.

    Code
    1. $ ffmpeg -hide_banner -vaapi_device /dev/dri/renderD128 -i mjpeg422.avi -vf 'format=yuv420p,hwupload' -c:v h264_vaapi -threads 8 -qp 18 -y output.mkvGuessed Channel Layout for Input Stream #0.1 : stereoInput #0, avi, from 'mjpeg422.avi': Duration: 00:01:00.60, start: 0.000000, bitrate: 49137 kb/s Stream #0:0: Video: mjpeg (MJPG / 0x47504A4D), yuvj422p(pc, bt470bg/unknown/unknown), 1920x1080, 46824 kb/s, 23.98 fps, 23.98 tbr, 23.98 tbn, 23.98 tbc Stream #0:1: Audio: pcm_s24le ([1][0][0][0] / 0x0001), 48000 Hz, stereo, s32 (24 bit), 2304 kb/sStream mapping: Stream #0:0 -> #0:0 (mjpeg (native) -> h264 (h264_vaapi)) Stream #0:1 -> #0:1 (pcm_s24le (native) -> vorbis (libvorbis))Press [q] to stop, [?] for helpDuplicate formats in ff_merge_formats detected[swscaler @ 0x5655068339c0] deprecated pixel format used, make sure you did set range correctly[h264_vaapi @ 0x5655067e5300] Failed to end picture encode issue: 6 (invalid VASurfaceID).[h264_vaapi @ 0x5655067e5300] Encode failed: -5.Video encoding failedConversion failed!


    Informationen was "hwupload" oder "hwaccel" überhaupt verarbeiten können sind spärlich zu finden und CPU-abhängig. Um das einigermaßen herauszufinden zeigt "vainfo" an:

    Code
    1. $ vainfolibva info: VA-API version 1.1.0libva info: va_getDriverName() returns 0libva info: User requested driver 'i965'libva info: Trying to open /usr/lib/dri/i965_drv_video.solibva info: Found init function __vaDriverInit_1_1libva info: va_openDriver() returns 0vainfo: VA-API version: 1.1 (libva 2.1.0)vainfo: Driver version: Intel i965 driver for Intel(R) Skylake - 2.1.0vainfo: Supported profile and entrypoints VAProfileMPEG2Simple : VAEntrypointVLD VAProfileMPEG2Simple : VAEntrypointEncSlice VAProfileMPEG2Main : VAEntrypointVLD VAProfileMPEG2Main : VAEntrypointEncSlice VAProfileH264ConstrainedBaseline: VAEntrypointVLD VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice VAProfileH264ConstrainedBaseline: VAEntrypointEncSliceLP VAProfileH264ConstrainedBaseline: VAEntrypointFEI VAProfileH264ConstrainedBaseline: VAEntrypointStats VAProfileH264Main : VAEntrypointVLD VAProfileH264Main : VAEntrypointEncSlice VAProfileH264Main : VAEntrypointEncSliceLP VAProfileH264Main : VAEntrypointFEI VAProfileH264Main : VAEntrypointStats VAProfileH264High : VAEntrypointVLD VAProfileH264High : VAEntrypointEncSlice VAProfileH264High : VAEntrypointEncSliceLP VAProfileH264High : VAEntrypointFEI VAProfileH264High : VAEntrypointStats VAProfileH264MultiviewHigh : VAEntrypointVLD VAProfileH264MultiviewHigh : VAEntrypointEncSlice VAProfileH264StereoHigh : VAEntrypointVLD VAProfileH264StereoHigh : VAEntrypointEncSlice VAProfileVC1Simple : VAEntrypointVLD VAProfileVC1Main : VAEntrypointVLD VAProfileVC1Advanced : VAEntrypointVLD VAProfileNone : VAEntrypointVideoProc VAProfileJPEGBaseline : VAEntrypointVLD VAProfileJPEGBaseline : VAEntrypointEncPicture VAProfileVP8Version0_3 : VAEntrypointVLD VAProfileVP8Version0_3 : VAEntrypointEncSlice VAProfileHEVCMain : VAEntrypointVLD VAProfileHEVCMain : VAEntrypointEncSlice


    Unterstützte Kodierungsformate werden mit VAEntrypointEncSlice angezeigt, und alle Dekodierungsformate werden mit VAEntryPointVLD- und VAEntrypointVideoProc angezeigt.


    Wenn man nun davon ausgehen muß das "VAEntrypointEncPicture" ungleich "VAEntrypointEncSlice" ist, funktioniert das Transcoding nicht. Das erklärt aber nicht warum das Hardwaredecoding (VAEntryPointVLD) nicht funktioniert.

    Code
    1. $ ffmpeg -hide_banner -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i mjpeg422.avi -f null -Guessed Channel Layout for Input Stream #0.1 : stereoInput #0, avi, from 'mjpeg422.avi': Duration: 00:01:00.60, start: 0.000000, bitrate: 49137 kb/s Stream #0:0: Video: mjpeg (MJPG / 0x47504A4D), yuvj422p(pc, bt470bg/unknown/unknown), 1920x1080, 46824 kb/s, 23.98 fps, 23.98 tbr, 23.98 tbn, 23.98 tbc Stream #0:1: Audio: pcm_s24le ([1][0][0][0] / 0x0001), 48000 Hz, stereo, s32 (24 bit), 2304 kb/sStream mapping: Stream #0:0 -> #0:0 (mjpeg (native) -> wrapped_avframe (native)) Stream #0:1 -> #0:1 (pcm_s24le (native) -> pcm_s16le (native))Press [q] to stop, [?] for helpffmpeg: gen8_mfd.c:2602: gen8_mfd_jpeg_bsd_object: Assertion `0' failed.Abgebrochen (Speicherabzug geschrieben)


    Ok, dann muß ein anderer Weg her damit das Transcoding funktioniert. Voraussetzung ist nur das lossless Capture.
    Man kann das Capture so konfigurieren das mit ffmpeg, 8bit YUV abgegriffen wird:


    ffmpeg greift also direct auf das Capturedevice zu.
    Zum Encoden "on the fly" kann ich somit jeden internen ffmpeg-codec verwenden. Der muß halt lossless sein und anschließend für´s Transcoding taugen.


    Hat jemand eine Idee ?

  • Sollen wir dir jetzt verlustfrei komprimierende Codecs aufzählen, die ffmpeg für YUV 4:2:2 unterstützt (z.B. Huffyuv / ffvhuff, FFV1, Ut, MagicYUV)? Die sind den Leuten, die im Analog-Capturing-Bereich Interesse haben, schon länger bekannt.

  • ???


    Nein, mit 4:2:2 ist doch kein Transcoding möglich. Ich beende das jetzt auch hiermit.


    Es ist aber sehr wohl möglich Hardware mjpeg-Decoding auszuführen: https://github.com/FFmpeg/FFmp…cda78d3d3537bd1af9c406241


    Allerdings ist das wohl (noch) nicht mit reinkompiliert worden. Sieht man ja hier:

    Code
    1. ffmpeg -codecs | grep vaapi
    2. DEVIL. mjpeg Motion JPEG (decoders: mjpeg mjpeg_cuvid ) (encoders: mjpeg mjpeg_vaapi )


    Also ist nur Encoding mit mjpeg_vaapi möglich.


    Gruß ggrub

  • Verlustlos in YUV 4:2:0 können auch ein paar (Ut, ffvhuff).


    Wenn man auf das letzte Bit Exaktheit verzichten kann, würde ich sonst als Zwischenmaterial noch AVC mit CRF 6..12 (auch als relativ platzsparenden Kompromiss für ein Archivformat) vorschlagen. Das passt in MP4 oder MKV und ist recht wahrscheinlich auch mit Hardware wieder decodierbar. Dann aber den Interlaced-Modus als expliziten CLI-Parameter nicht vergessen.

  • CRF 6-12 geht nur mit Interlaced-Modus ? Das wußte ich auch noch nicht.


    Das wurde mir zugetragen:

    Zitat


    vaapi decode for mjpeg is enabled in this package. It's not viewed with ffmpeg -codecs or -decoders options. vaapi decoding is treated as a hwaccel component, and not as direct decoder, being used with ffmpeg option -hwaccel. You can see it enabled by viewing the ./configure output at build time: Enabled hwaccels: ... mjpeg_vaapi.


    Bringt mich aber leider auch nicht weiter. Hwaccel Mjpeg-Decoding müßte also funktionieren, tut es aber (hier) nicht. Ich brauche halt das verlustlose Material zur Reproduktion im privaten Bereich, ist eine Vorgabe.

  • CRF 6-12 geht nur mit Interlaced-Modus ?


    Natürlich nicht "nur". Aber wer Interlaced-Material in MPEG-4 AVC encodiert, der sollte dafür den Interlaced-Modus aktivieren, damit der Encoder getrennte Fields statt verzahnte (combed) Frames verarbeitet.


    Absolut verlustlos wäre AVC bei x264 CRF 6 vielleicht nicht. Aber ziemlich sicher unmerklich verlustbehaftet. Und eben auch decodierbar durch Decoder, die Lossless-AVC nicht beherrschen. Man kann auch mit dem CRF oder QP noch kleiner werden, bis 2 oder 1, aber QP 6 bei x264 entspricht etwa QP 1 bei Xvid im Quantisierungsgrad, und exakter speichert MJPEG es auch nicht (außer durch Chroma-Subsampling 4:2:2 statt 4:2:0).


    Bei der MJPEG-Decodierung durch VA-API mit Hardware-Unterstützung kann ich dir nicht helfen, da ich nicht den gleichen Grafikchipsatz habe. Wie du schon sagtest, wenn der Chipsatz das eigentlich können soll, kann's immer noch am Treiber liegen, wenn es nicht klappt. Oder an Eigenheiten im MJPEG-Datenstrom (so kann es MJPEG-Encoderhardware geben, die einen gemeinsamen Standardsatz für Huffman-Code-Tabellen zur Komprimierung annimmt und den dann gar nicht erst im Ausgabe-Datenstrom speichert, während sich universelle Decoder vielleicht darauf verlassen, den im Datenstrom zu finden). Alles Spekulation, für fundierte Antworten braucht es hier wohl einen Spezialisten für genau diesen Fall. Aber wo finden?

  • Ok, dann hab ich das falsch verstanden. Das Material (mjpeg) ist Scan type : Progressive. Das wirft jetzt die Frage auf ob "Hwaccel" interlaced Material erwartet. Darüber konnte ich nix erfahren.


    Macht aber nix, weil ich ja jeden ffmpeg-codec verwenden kann, in welcher Form auch immer. Wenn also der "mjpeg-output" interlaced sein muß, kann man das sicher mit ffmpeg Settings beeinflussen.
    Wenn der mjpeg-output proprietär ist, dann kann ich halt den ffmpeg mjpeg-codec verwenden. Irgendwas in dieser Richtung: "-c:v mjpeg -qmin 1 -q:v 1". Muß ich mal schauen was da in Richtung lossless möglich ist.

  • Die Flags darf man nicht überbewerten. Bei Chroma-Subsampling 4:2:2 und feiner spielt ein Interlaced-Flag keine Rolle, weil die Farbigkeit aller Zeilen voneinander unabhängig ist. Bei Subsampling 4:2:0 dagegen ist diese zusätzliche Angabe "überlebenswichtig", weil sich hier zwei Zeilen eine Farbigkeit teilen. Die Frage ist dann: Zwei übereinander liegende Zeilen im Frame oder im Field? Hier der grafische Vergleich. AVC-Encoder unterstützen diese Unterscheidung durch zwei unterschiedliche Arbeitsweisen: progressiv encodieren sie das gesamte Frame, interlaced dagegen die beiden Fields separat.

  • So, hab noch ein paar Tests gemacht.


    Das vom Capture-Device vorgegebene mjpeg_yuvj422p (lossless) avi läßt sich nicht transcoden (mjpeg_vaapi).
    Das von ffmpeg erzeugte mjpeg_yuvj422p läßt sich ebenfalls nicht transcoden (mjpeg_vaapi).
    Das von ffmpeg erzeugte mjpeg_yuvj420p läßt sich transoden (mjpeg_vaapi). Enorm hohe Performance.
    Das von ffmpeg erzeugte mjpeg_yuvj420p läßt sich NICHT transoden (h264_vaapi).


    Fazit: Mit yuvj422p kann vaapi grundsätzlich nix anfangen im Bereich Trancoding. Transcoding von YUVJ420p nach YUV420P ist auch nicht möglich.
    Vaaapi ist verdammt unflexibel muß ich feststellen. So jetzt is aber Ende.

  • Hab jetzt mal den "intel-media-driver" getestet.

    Code
    1. ffmpeg -hide_banner -threads 8 -vaapi_device /dev/dri/renderD128 -i h264_lossless.mkv -vf 'format=nv12,hwupload' -c:v h264_vaapi -pix_fmt vaapi_vld -b:v 10M -profile:v high -level 41 -quality 1 -bf 3 -y output.mkv
    2. ffmpeg -hide_banner -threads 8 -init_hw_device vaapi=intel:/dev/dri/renderD128 -hwaccel vaapi -hwaccel_output_format vaapi -hwaccel_device intel -i mjpeg-420.avi -vf 'format=nv12|vaapi,hwupload' -c:v h264_vaapi -pix_fmt vaapi_vld -b:v 10M -profile:v high -level 41 -quality 1 -bf 3 -y /t00.mkv
    3. ffmpeg -hide_banner -threads 8 -init_hw_device vaapi=intel:/dev/dri/renderD128 -hwaccel vaapi -hwaccel_output_format vaapi -hwaccel_device intel -i mjpeg-422.avi -vf 'format=nv12|vaapi,hwupload' -c:v mjpeg_vaapi -pix_fmt vaapi_vld -y output.avi


    FUNKTIONIERT. Ist erheblich flexibler als der reine "libva-intel-driver". Nur so als Info.