Wonky coupling of GStreamer 1.0 NVMM plugins

The GStreamer 1.0 plugins that support NVMM, provided by NVIDIA, have very wonky coupling.

First of all, I have a video file that is mjpeg in mkv. This is what FFmpeg 3.3.1 says about my file:

ubuntu@tegra-ubuntu:~$ ffmpeg -i output2.mkv
    ffmpeg version 3.3.1 Copyright (c) 2000-2017 the FFmpeg developers
    built with gcc 4.8 (Ubuntu/Linaro 4.8.4-2ubuntu1~14.04.3)
    configuration: --prefix=/home/ubuntu/ffmpeg_build --extra-cflags=-I/home/ubuntu/ffmpeg_build/include --extra-ldflags=-L/home/ubuntu/ffmpeg_build/lib --bindir=/home/ubuntu/bin --enable-gpl --enable-libx264 --enable-avresample --enable-nonfree --enable-shared
    libavutil      55. 58.100 / 55. 58.100
    libavcodec     57. 89.100 / 57. 89.100
    libavformat    57. 71.100 / 57. 71.100
    libavdevice    57.  6.100 / 57.  6.100
    libavfilter     6. 82.100 /  6. 82.100
    libavresample   3.  5.  0 /  3.  5.  0
    libswscale      4.  6.100 /  4.  6.100
    libswresample   2.  7.100 /  2.  7.100
    libpostproc    54.  5.100 / 54.  5.100
    Input #0, matroska,webm, from 'output2.mkv':
    Metadata:
        ENCODER         : Lavf56.15.102
    Duration: 00:00:46.17, start: 0.000000, bitrate: 152355 kb/s
        Stream #0:0: Video: mjpeg, yuvj422p(pc, bt470bg/unknown/unknown), 1920x1080, SAR 1:1 DAR 16:9, 30 fps, 30 tbr, 1k tbn, 1k tbc (default)
    At least one output file must be specified

As you can see, it’s mjpeg, in yuvj422p pixel format, bt407bg colourspace, 1920x1080, 30 fps.

I’m going to list 5 examples that involve nvjpegdec and nvvidconv:

Case 1: filesrc location=output2.mkv ! nvjpegdec ! ‘video/x-raw(memory:NVMM)’ ! nvhdmioverlaysink

ubuntu@tegra-ubuntu:~$ gst-launch-1.0 filesrc location=output2.mkv ! nvjpegdec ! nvhdmioverlaysink -v
Setting pipeline to PAUSED ...
Inside NvxLiteH264DecoderLowLatencyInitNvxLiteH264DecoderLowLatencyInit set DPB and MjstreamingPipeline is PREROLLING ...
/GstPipeline:pipeline0/GstNvJpegDec:nvjpegdec0.GstPad:src: caps = video/x-raw(memory:NVMM), format=(string)I420, width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:4:0:0, framerate=(fraction)0/1
/GstPipeline:pipeline0/GstNvHDMIOverlaySink-nvhdmioverlaysink:nvhdmioverlaysink-nvhdmioverlaysink0.GstPad:sink: caps = video/x-raw(memory:NVMM), format=(string)I420, width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:4:0:0, framerate=(fraction)0/1
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
^Chandling interrupt.
Interrupt: Stopping pipeline ...
Execution ended after 0:00:04.133629995
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

Note that nvhdmioverlaysink accepts video/x-raw(memory:NVMM), format=(string)I420 here.

Result: video displayed via HDMI overlay on LCD screen. However, chroma is incorrectly expanded in the vertical direction (doubled in height), while luma remains correct.

Case 2: filesrc location=output2.mkv ! nvjpegdec ! nvvidconv ! ‘video/x-raw(memory:NVMM), format=I420’ ! nvhdmioverlaysink

ubuntu@tegra-ubuntu:~$ gst-launch-1.0 filesrc location=output2.mkv ! nvjpegdec ! nvvidconv ! 'video/x-raw(memory:NVMM), format=I420' ! nvhdmioverlaysink -v
Setting pipeline to PAUSED ...
Inside NvxLiteH264DecoderLowLatencyInitNvxLiteH264DecoderLowLatencyInit set DPB and MjstreamingPipeline is PREROLLING ...
/GstPipeline:pipeline0/GstNvJpegDec:nvjpegdec0.GstPad:src: caps = video/x-raw(memory:NVMM), format=(string)I420, width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:4:0:0, framerate=(fraction)0/1
/GstPipeline:pipeline0/Gstnvvconv:nvvconv0.GstPad:src: caps = video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)0/1, format=(string)I420
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:src: caps = video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)0/1, format=(string)I420
/GstPipeline:pipeline0/GstNvHDMIOverlaySink-nvhdmioverlaysink:nvhdmioverlaysink-nvhdmioverlaysink0.GstPad:sink: caps = video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)0/1, format=(string)I420
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:sink: caps = video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)0/1, format=(string)I420
/GstPipeline:pipeline0/Gstnvvconv:nvvconv0.GstPad:sink: caps = video/x-raw(memory:NVMM), format=(string)I420, width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:4:0:0, framerate=(fraction)0/1
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
^Chandling interrupt.
Interrupt: Stopping pipeline ...
Execution ended after 0:00:03.995583364
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

Note that both the src and sink pads of nvvidconv are negotiated as video/x-raw(memory:NVMM), format=(string)I420, so the conversion should a no-op.

Result: the overlay is completely green.

Case 3: filesrc location=output2.mkv ! nvjpegdec ! nvvidconv ! ‘video/x-raw(memory:NVMM), format=UYVY’ ! nvhdmioverlaysink

ubuntu@tegra-ubuntu:~$ gst-launch-1.0 filesrc location=output2.mkv ! nvjpegdec ! nvvidconv ! 'video/x-raw(memory:NVMM), format=UYVY' ! nvhdmioverlaysink -v
Setting pipeline to PAUSED ...
Inside NvxLiteH264DecoderLowLatencyInitNvxLiteH264DecoderLowLatencyInit set DPB and MjstreamingPipeline is PREROLLING ...
/GstPipeline:pipeline0/GstNvJpegDec:nvjpegdec0.GstPad:src: caps = video/x-raw(memory:NVMM), format=(string)I420, width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:4:0:0, framerate=(fraction)0/1
/GstPipeline:pipeline0/Gstnvvconv:nvvconv0.GstPad:src: caps = video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)0/1, format=(string)UYVY
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:src: caps = video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)0/1, format=(string)UYVY
/GstPipeline:pipeline0/GstNvHDMIOverlaySink-nvhdmioverlaysink:nvhdmioverlaysink-nvhdmioverlaysink0.GstPad:sink: caps = video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)0/1, format=(string)UYVY
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:sink: caps = video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)0/1, format=(string)UYVY
/GstPipeline:pipeline0/Gstnvvconv:nvvconv0.GstPad:sink: caps = video/x-raw(memory:NVMM), format=(string)I420, width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:4:0:0, framerate=(fraction)0/1
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
^Chandling interrupt.
Interrupt: Stopping pipeline ...
Execution ended after 0:00:10.847353605
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

Note that nvhdmioverlaysink claims to accept video/x-raw(memory:NVMM), format=(string)UYVY here.

Result: the overlay is completely black.

Case 4: filesrc location=output2.mkv ! nvjpegdec ! nvvidconv ! ‘video/x-raw(memory:NVMM), format=GRAY8’ ! nvhdmioverlaysink

ubuntu@tegra-ubuntu:~$ gst-launch-1.0 filesrc location=output2.mkv ! nvjpegdec ! nvvidconv ! 'video/x-raw(memory:NVMM), format=GRAY8' ! nvhdmioverlaysink -v
Setting pipeline to PAUSED ...
Inside NvxLiteH264DecoderLowLatencyInitNvxLiteH264DecoderLowLatencyInit set DPB and MjstreamingPipeline is PREROLLING ...
/GstPipeline:pipeline0/GstNvJpegDec:nvjpegdec0.GstPad:src: caps = video/x-raw(memory:NVMM), format=(string)I420, width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:4:0:0, framerate=(fraction)0/1
/GstPipeline:pipeline0/Gstnvvconv:nvvconv0.GstPad:src: caps = video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)0/1, format=(string)GRAY8
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:src: caps = video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)0/1, format=(string)GRAY8
/GstPipeline:pipeline0/GstNvHDMIOverlaySink-nvhdmioverlaysink:nvhdmioverlaysink-nvhdmioverlaysink0.GstPad:sink: caps = video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)0/1, format=(string)GRAY8
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:sink: caps = video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)0/1, format=(string)GRAY8
/GstPipeline:pipeline0/Gstnvvconv:nvvconv0.GstPad:sink: caps = video/x-raw(memory:NVMM), format=(string)I420, width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:4:0:0, framerate=(fraction)0/1
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
^Chandling interrupt.
Interrupt: Stopping pipeline ...
Execution ended after 0:00:03.511661359
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

Note that between nvvidconv and nvhdmioverlaysink, the caps are negotiated as video/x-raw(memory:NVMM), format=(string)GRAY8, so I expect the resulting rendered video to be in grayscale.

Result: video rendered in correct colours, not in grayscale, via HDMI overlay on LCD screen (WHAT!?)

Case 5: filesrc location=output2.mkv ! nvjpegdec ! ‘video/x-raw(memory:NVMM)’ ! nvvidconv ! xvimagesink

ubuntu@tegra-ubuntu:~$ gst-launch-1.0 filesrc location=output2.mkv ! nvjpegdec ! 'video/x-raw(memory:NVMM)' ! nvvidconv ! xvimagesink -v
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
/GstPipeline:pipeline0/GstNvJpegDec:nvjpegdec0.GstPad:src: caps = video/x-raw(memory:NVMM), format=(string)I420, width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:4:0:0, framerate=(fraction)0/1
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:src: caps = video/x-raw(memory:NVMM), format=(string)I420, width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:4:0:0, framerate=(fraction)0/1
/GstPipeline:pipeline0/Gstnvvconv:nvvconv0.GstPad:src: caps = video/x-raw, width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)0/1, format=(string)UYVY
/GstPipeline:pipeline0/GstXvImageSink:xvimagesink0.GstPad:sink: caps = video/x-raw, width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)0/1, format=(string)UYVY
/GstPipeline:pipeline0/Gstnvvconv:nvvconv0.GstPad:sink: caps = video/x-raw(memory:NVMM), format=(string)I420, width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:4:0:0, framerate=(fraction)0/1
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:sink: caps = video/x-raw(memory:NVMM), format=(string)I420, width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)1:4:0:0, framerate=(fraction)0/1
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
ERROR: from element /GstPipeline:pipeline0/GstXvImageSink:xvimagesink0: Output window was closed
Additional debug info:
xvimagesink.c(551): gst_xvimagesink_handle_xevents (): /GstPipeline:pipeline0/GstXvImageSink:xvimagesink0
Execution ended after 0:00:08.186343916
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

Note that I now try to convert from I420 in NVMM to UYVY in regular RAM, so that I can display the video in standard sinks like xvimagesink.

Result: video rendered in a window in correct colours, but the whole image is slightly stretched vertically, with the bottom cropped.

Please share the mkv file so that we can give suggestion.