Gstreamer on TX1: H265 Compression of videotestsrc works, but fails with filesrc data

Possibly similar to “nvvidconv plugin and v4l2 camera problem” @ https://devtalk.nvidia.com/default/topic/932320/jetson-tx1/nvvidconv-plugin-and-v4l2-camera-problem-/

I find the H.265 encoding works great when I use a videotestsrc as the video source:

gst-launch-1.0 videotestsrc  ! 'video/x-raw, format=(string)UYVY, width=(int)1280, height=(int)720, framerate=(fraction)60/1' ! nvvidconv ! 'video/x-raw(memory:NVMM), format=(string)NV12' ! omxh265enc ! 'video/x-h265, stream-format=(string)byte-stream' ! filesink location=test.mp4

But when I switch to a filesrc:

gst-launch-1.0 filesrc location=720P60.yuv  ! 'video/x-raw, format=(string)UYVY, width=(int)1280, height=(int)720, framerate=(fraction)60/1' ! nvvidconv ! 'video/x-raw(memory:NVMM), format=(string)NV12' ! omxh265enc ! 'video/x-h265, stream-format=(string)byte-stream' ! filesink location=test.mp4

I get a long stream of error messages

NVMAP_IOC_WRITE failed: Bad address
NVMAP_IOC_WRITE failed: Bad address
. . .

as long as the stream is running, and no output from the filesink. Naturally, I suspected the input file, so I generated a fresh one via:

gst-launch-1.0 nvcamerasrc ! 'video/x-raw(memory:NVMM), width=(int)1280, height=(int)720,format=(string)I420, framerate=(fraction)60/1' ! nvvidconv ! 'video/x-raw, format=(string)I420, framerate=(fraction)60/1' ! filesink location='camera.yuv' -e

and tried to compress this similarly:

gst-launch-1.0 filesrc location=camera.yuv  ! 'video/x-raw, format=(string)I420, width=(int)1280, height=(int)720, framerate=(fraction)60/1' ! nvvidconv ! 'video/x-raw(memory:NVMM), format=(string)NV12' ! omxh265enc ! 'video/x-h265, stream-format=(string)byte-stream' ! filesink location=camera.mp4 -e

And still get the stream of errors. The messages seem to come from nvvidconv, because this stream doesn’t yield them:

gst-launch-1.0 filesrc location=CH2_COMPONENT_720P60.yuv  ! 'video/x-raw, format=(string)UYVY, width=(int)1280, height=(int)720, framerate=(fraction)60/1' ! filesink location=test.mp4

but this stream (which adds nvvidconv) does:

gst-launch-1.0 filesrc location=CH2_COMPONENT_720P60.yuv  ! 'video/x-raw, format=(string)UYVY, width=(int)1280, height=(int)720, framerate=(fraction)60/1' ! nvvidconv ! 'video/x-raw(memory:NVMM), format=(string)NV12' ! filesink location=test.mp4

The results are the same whether the stream is constructed with gst-launch-1.0 or with C code (the later being my real goal… a simple C program to drive H265 compression.)

Suggestions? Work-arounds? Source? AdvTHANKSance ← Thanks in advance

How about the following:

gst-launch-1.0 filesrc location=720P60.yuv  ! 'video/x-raw, format=(string)UYVY, width=(int)1280, height=(int)720, framerate=(fraction)60/1' ! queue ! nvvidconv ! 'video/x-raw(memory:NVMM), format=(string)NV12' ! omxh265enc ! 'video/x-h265, stream-format=(string)byte-stream' ! queue ! filesink location=test.mp4 sync=false

Thanks for the suggestion! Still just get a stream of NVMAP_IOC_WRITE failed: Bad address errors though. I’ll read-up on queue elements …

I wonder if gstreamer is not providing properly aligned buffers from the filesrc element, or using memmap?

I don’t know of a way to check this… do you? Ideally (in my under-educated perspective) gst-inspect would show all characteristics of elements which allow / disallow them to operate successfully together in a stream. If buffer alignment, or differing buffer memory address spaces, are factors, these should be dutifully reported.

For my part, I’ll try appsrc next, there-by implementing my own filesrc. Wish me luck… I’ll report the outcome.

Significant progress: have discovered that the filesrc element needs to have its blocksize parameter set, e.g. to video width x height x bytes-per-pixel. That, at least, allows me to construct an H.265 compression stream with the (more generic) videoconvert converter. Hopefully further experimentation will yield a stream which leverages nvvidconv instead, for lower CPU demands.

So the (self-discovered) answer to the original challenge:

gst-launch-1.0 filesrc location=720P60.yuv  !  ...

is to add the blocksize parameter to filesrc

gst-launch-1.0 filesrc location=720P60.yuv blocksize=1843200 !  ...

The generic videoconvert element complains about unexpected blocksize. It might be nice if the nvvidconv element did the same… would have saved me some time.

Hi rdavis,

I’m not really sure it is required, but for the use case you mentioned, the “videoparse” element takes care of it, you can use “videoparse” element as following:

gst-launch-1.0 filesrc location=camera.yuv  ! videoparse format=2 width=1280 height=720 framerate= 60/1 ! nvvidconv ! 'video/x-raw(memory:NVMM), format=(string)NV12' ! omxh265enc ! 'video/x-h265, stream-format=(string)byte-stream' ! filesink location=camera.mp4 -e

This element is generally used in such use cases.

Thanks

Hi

To my understanding your pipeline creates a video-stream but no .mp4 file. If you want to store the video you need a muxer element to pack the video into a container. There is qtmux for mp4-containers or matroskamux for mkv-containers, but unfortunately I have only been able to use matroskamux in a pipeline.

Also make sure to add the -e at the end to send EOS on aborting the pipeline. Example:

gst-launch-1.0 videotestsrc  ! 'video/x-raw, format=(string)UYVY, width=(int)1280, height=(int)720, framerate=(fraction)60/1' ! nvvidconv ! 'video/x-raw(memory:NVMM), format=(string)NV12' ! omxh265enc ! 'video/x-h265, stream-format=(string)byte-stream' ! h265parse ! matroskamux ! filesink location=test.mkv -e

Also h265parse requires a newer version of GStreamer (e.g. 1.6).

Thanks for this advice! I’m content to evoke H265 bitstreams at this point, for study, and don’t need to interleave other streams. The raw bitstreams are playable. I give them a .h265 extension and they play in videos when I double-click them…

Yup, good catch. Thanks!

This is likely more robust that my work-around… since I have to factor in bytes/pixel. Thanks for this advice, kaycc!