Video
This page will show several example pipelines for getting video through our boards using the gstreamer-imx set of plugins. The gstreamer-imx set of plugins have several elements that can be used to output a frame to a display. Please see Yocto/gstreamer for element specifics.
Output
Generally, a 'sink' plugin is one that will take a video stream and output it to a display. Please refer to the Yocto/Video_Out page for details on the video out devices on the ventana platform.
A complete list of output sinks on the imx6:
gstreamer-imx
specific sinks- imxg2dvideosink
- imxipuvideosink
- imxpxpvideosink
- imxeglvivsink
- Other GStreamer sinks
- autovideosink
- fbdevsink
- fdsink
- ximagesink/xvimagesink
- fakesink
- v4l2sink
Plus many more! Execute a gst-inspect-1.0 | grep sink
to see a complete list of video sinks available.
imxg2dvideosink
This video sink is very versatile in that it can output any image size. It can also transform images (changing size, rotation etc), place images in specified locations, and can accept the following video formats: RGBx, BGRx, RGBA, BGRA, RGB16, NV12, NV21, I420, YV12, YUY2, UYVY
For drawing to a display, this is our recommended GStreamer video sink.
The imxg2dvideosink
also supports vertical sync to eliminate screen tearing. To enable this set the use-vsync
property to true.
imxipuvideosink
This video sink is not nearly as versatile in output sizes. In many cases, it will refuse a format and bail out. However, one advantage it has over the imxg2dvideosink
is that it includes a deinterlacer and can sink more video formats: RGB16, BGR, RGB, BGRx, BGRA, RGBx, RGBA, ABGR, UYVY, v308, NV12, YV12, I420, Y42B, Y444
This is only recommended if you require a deinterlacer to eliminate the effect of interlaced video effects or requires a certain video format only this video sink can provide.
To enable the deinterlacer set the deinterlace=true
property.
The imxipuvideosink also supports vertical sync to eliminate screen tearing. To enable this set the use-vsync=true
property.
imxpxpvideosink
This sink is only available on the i.mx6solo and i.mx6dl processors. It can do the same as the above (minus having a built-in deinterlacer), and has support for the following video formats: BGRx, RGB16, I420, YV12, Y42B, NV12, YUY2, UYVY, YVYU
This is recommended if resources are limited and you require offloading some processing to the PXP engine.
Setting the use-vsync=true
property is useful to prevent screen tearing in the video.
imxeglvivsink
This sink is very useful when you have a X11 display, and uses Vivante direct textures to output to the primary display. Like the imxipuvideosink
, it has a flexible output video format list: I420, YV12, NV12, NV21, UYVY, RGB16, RGBA, BGRA, RGBx, BGRx, BGR, ARGB, ABGR, xRGB, xBGR
This is recommended when running a pipeline which will output to a display with X11/wayland. To use double-buffering (to eliminate tearing) set the FB_MULTI_BUFFER env variable to 2.
autovideosink
This GStreamer sink is not really a 'video' sink in the traditional sense. Similar to playbin
and decodebin
, this element selects what it thinks is the best available video sink and uses it. This will typically use imxg2dvideosink
unless format choices require one of the other sinks. Generally this is not recommended as it avoids understanding the specific pipeline that is in use.
You can add a verbose flag gst-launch-1.0 -v
to see details about the elements and caps chosen when using any type of 'auto' element or 'bin' element.
fbdevsink
This sink allows you to directly output to the framebuffer.
fdsink
This sink allows you to write to an open file descriptor.
ximagexsink/xvimagesink
These sinks output to the X11 display using standard Xlib API calls. The xvimagesink
is used for XFree86 video out.
fakesink
This is a very useful video sink. It takes whatever frames is given to it and drops them. This might help debugging pipelines if problems ever arise.
gst-launch-1.0 videotestsrc pattern=0 ! fakesink
v4l2sink
This sink is useful when displaying frames on a video4linux2 device. Generally not used on imx6 based product unless all other sinks fail.
Examples
Using the above, an example video output pipeline might look like the following:
gst-launch-1.0 videotestsrc pattern=18 ! imxg2dvideosink framebuffer=/dev/fb0
Input
An input source is anything coming from an input on the device, e.g. HDMI input/USB Web Cam. In order to capture these frames and display it. Please refer to the Yocto/Video_In page for details on the video in devices on the Ventana platform.
A complete list of input sources on the imx6:
- gstreamer-imx specific sources
- imxv4l2videosrc
- Other GStreamer sources
- autovideosrc
- videotestsrc
- v4l2src
Plus many more! Execute a gst-inspect-1.0 | grep src
to see a complete list of video sinks available.
If the is-live
property is set to true this will cause buffers to be discarded on a pipeline paused state and pipelines will not participate in the PREROLL phase of a pipeline.
video4linux2 devices and v4l2-ctl
The imxv4l2videosrc
and v4l2src
elements capture from a video4linux2 device. You can use the v4l2-ctl
application to to interact with the device to get/set various capabilities and controls.
For example:
- display all details about /dev/video1:
v4l2-ctl -d /dev/video1 --all
Note that the IMX6 capture driver uses the v4l-int-dev API which creates a 'master' and 'slave' relationship between the CPU's IPU capture driver (mxc_capture) and the driver for the actual image sensor or video decoder (ie adv7180 analog video decoder or tda1997x HDMI receiver). As such the V4L2 API and v4l2-ctl
may not give you access to all the knobs that may exist on the 'slave' or 'sensor' driver. Please see the Yocto/Video_In page for more details.
imxv4l2videosrc
This is the recommended video capture source element for the least amount of CPU overhead if you are going to be using any of the IMX6 IPU/VPU/GPU capabilities such as displaying on an IMX6 output, encoding/decoding/transcoding video, video composition, or using any of the other transforms such as colorspace conversion, scaling, or de-interlacing.
This is because the imxv4l2videosrc element is necessary to achieve zero-copy where DMA-able buffers can be shared among gstreamer elements and eliminate CPU-intensive memory copies.
The v4l CSI drivers in the Gateworks downstream vendor kernel has some extra calls that allow one to retrieve the physical address that corresponds to a v4l buffer and since the IPU, G2D, VPU, PxP driver API's all use physical addresses to access data via DMA, this allows for zero-copy.
See also v4l2-ctl above
autovideosrc
Like the other auto*
GStreamer plugins, this one attempts to pick a video source and use it.
videotestsrc
This is a very useful plugin for testing. It can output a huge number for raw video formats: I420, YV12, YUY2, UYVY, AYUV, RGBx, BGRx, xRGB, xBGR, RGBA, BGRA, ARGB, ABGR, RGB, BGR, Y41B, Y42B, YVYU, Y444, v210, v216, NV12, NV21, NV16, NV24, GRAY8, GRAY16_BE, GRAY16_LE, v308, RGB16, BGR16, RGB15, BGR15, UYVP, A420, RGB8P, YUV9, YVU9, IYU1, ARGB64, AYUV64, r210, I420_10LE, I420_10BE, I422_10LE, I422_10BE, Y444_10LE, Y444_10BE, GBR, GBR_10LE, GBR_10BE, NV12_64Z32
In addition, it can output several bayer video formats: bggr, rggb, grbg, gbrg
Selecting a test pattern from the range of 0 - 22, you can verify colors, movement, among other things.
v4l2src
This plugin is similar to the imxv4l2videosrc
plugin in that it uses the v4l2 api to capture video from input sources, however it does not have access to the physical memory addresses necessary to achieve zero-copy and therefore is typically more CPU intensive depending on your pipeline. If you are going to be using any IMX6 IPU/GPU/VPU capabilities, use imxv4l2videosrc instead.
Note that v4l2src
is always live regardless of the is-live property.
See also v4l2-ctl above
Examples
Here are some capture examples:
- Use a videotestsrc as the source and output to a fakesink
gst-launch-1.0 videotestsrc pattern=0 ! fakesink
- Use imxv4l2videosrc to capture video from camera source (/dev/video0 in this case) and output to the first video device via imxg2dvideosink
gst-launch-1.0 imxv4l2videosrc device=/dev/video0 ! imxg2dvideosink
Colorspace Converting and/or Video Scaling
Often times, a colorspace conversion or scaling is required in order to link GStreamer elements together. This is often due to the fact that not all elements can every format available.
A list of available video transforms:
- gstreamer-imx specific hardware-accelerated converters:
- imxipuvideotransform (uses IMX6 IPU)
- imxg2dvideotransform (uses IMX6 GPU)
- imxpxpvideotransform (uses IMX6 PXP)
- Note again that the PXP is only available on the i.mx6solo and i.mx6dl processors.
- Other GStreamer colorspace converters (software based):
- autovideoconvert
- videoconvert
- rgb2bayer
imxipuvideotransform
This plugin can convert between input type RGB16, BGR, RGB, BGRx, BGRA, RGBx, RGBA, ABGR, UYVY, v308, NV12, YV12, I420, Y42B, Y444 to output type RGB16, BGR, RGB, BGRx, BGRA, RGBx, RGBA, ABGR, UYVY, v308, NV12, YV12, I420, Y42B, Y444 video formats. Further, this element can deinterlace video before sending a frame on, which can be very useful depending on your video types.
To enable deinterlacing set the deinterlace=true
property on the element.
This is the recommended video transform, however please note that the IPU cannot accept non-standard video resolutions.
imxg2dvideotransform
This plugin can convert between input type RGBx, BGRx, RGBA, BGRA, RGB16, NV12, NV21, I420, YV12, YUY2, UYVY and output type RGBx, BGRx, RGBA, BGRA, RGB16. This video transform obviously doesn't support any many video formats as the imxipuvideotransform, which is why it is not recommended.
imxpxpvideotransform
This plugin can convert between input type BGRx, RGB16, I420, YV12, Y42B, NV12, YUY2, UYVY, YVYU and output type BGRx, BGRA, RGB16, GRAY8. Like the imxg2dvideotransform, it cannot handle many video formats, which is why it is not recommended.
autovideoconvert
Like the other auto* plugins, this one chooses the best plugin it thinks can convert one video format to another. It is generally not recommended.
videoconvert
This is the GStreamer software video colorspace converter. Because it is software based, it can output a whole slew of video formats:
Input type I420, YV12, YUY2, UYVY, AYUV, RGBx, BGRx, xRGB, xBGR, RGBA, BGRA, ARGB, ABGR, RGB, BGR, Y41B, Y42B, YVYU, Y444, v210, v216, NV12, NV21, NV16, NV24, GRAY8, GRAY16_BE, GRAY16_LE, v308, RGB16, BGR16, RGB15, BGR15, UYVP, A420, RGB8P, YUV9, YVU9, IYU1, ARGB64, AYUV64, r210, I420_10LE, I420_10BE, I422_10LE, I422_10BE, Y444_10LE, Y444_10BE, GBR, GBR_10LE, GBR_10BE, NV12_64Z32 to output type I420, YV12, YUY2, UYVY, AYUV, RGBx, BGRx, xRGB, xBGR, RGBA, BGRA, ARGB, ABGR, RGB, BGR, Y41B, Y42B, YVYU, Y444, v210, v216, NV12, NV21, NV16, NV24, GRAY8, GRAY16_BE, GRAY16_LE, v308, RGB16, BGR16, RGB15, BGR15, UYVP, A420, RGB8P, YUV9, YVU9, IYU1, ARGB64, AYUV64, r210, I420_10LE, I420_10BE, I422_10LE, I422_10BE, Y444_10LE, Y444_10BE, GBR, GBR_10LE, GBR_10BE, NV12_64Z32.
This converter is only recommended when the above cannot be used. Because it is software based, it's performance cost is very high.
rgb2bayer
This plugin can convert between the following: Input type bggr, gbrg, grbg, rggb to output type ARGB.
Examples
Examples using colorspace conversion:
- Loopback video from a non-IMX capture source to IMX output:
gst-launch-1.0 v4l2src device=/dev/video0 ! imxipuvideotransform ! imxg2dvideosink
- Take IMX video input /dev/video0 and output it to /dev/fb0 using the IPU to both colorspace convert and display:
gst-launch-1.0 imxv4l2videosrc device=/dev/video0 ! imxipuvideotransform ! imxipuvideosink framebuffer=/dev/fb0
Screen Tearing
Screen tearing occurs when the video output is not in sync with the display's refresh rate. The process of synchronizing the output to the refresh rate is also referred to as "vsync".
If the video frames are displayed directly on the framebuffer, this is easy to fix. The blitter-based video sinks (the IPU, G2D, PxP sinks: imxipuvideosink
, imxg2dvideosink
, imxpxpvideosink
) have a use-vsync
property, which is set to false by default. If set to true, it reconfigures the framebuffer, enlarging its virtual height. It then performs page flipping during playback. The page flipping is synchronized to the display's refresh rate, eliminating the tearing effects. If imxeglvivsink
is used, the FB_MULTI_BUFFER
environment variable needs to be set to 2. This instructs the Vivante EGL libraries to set up the framebuffer in a way that is similar to what the blitter-based sinks do.
In X11, vsync is not doable from the gstreamer-imx side. It would require changes to the existing i.MX6 X11 driver. So far, no such change has been made, meaning that as of now, tearing-free video playback in X11 is not possible.
In Wayland, vsync is possible when using Weston as the Wayland compositor. Weston can use OpenGL ES for rendering and also Vivante's G2D. With OpenGL ES, the FB_MULTI_BUFFER
approach mentioned above enables vsync for Weston output. This means that the export FB_MULTI_BUFFER=2
line needs to be added to the Weston init script. imxeglvivsink
can then be used to display video in Wayland, and it will automatically be in sync with the display's refresh rate.
References:
Interlaced Video and Deinterlacing
Interlaced video is a technique for doubling the perceived frame rate of a video display without consuming extra bandwidth. The interlaced signal contains two fields of a video frame captured at two different times. The alternative to interlaced video is called progressive video. While reducing bandwidth this can cause a perceived flicker effect as well as a very apparent artifact seen during motion. For example a car moving horizontally across a scene will show every other vertical line differently: the second field interlaced with the first field will be a full frame period ahead in time from the other. The visual affect can be seen in this image from Wikipedia
Television signals are typically interlaced, or at least were until recently. For example, analog television standards such as NTSC used in North America as well as the PAL and SECAM formats used abroad use interlaced video and therefore any analog video decoder such as the ADV7180 found on many Gateworks Ventana boards will capture interlaced video and are subject to interlacing artifacts. Interlaced video is still used in High Definition signals as well and the letter at the end of the format tells you if its interlaced (ie 480i, 720i, 1080i) or progressive (ie 480p, 720p, 1080p).
To use the IMX6 to deinterlace video you can use the deinterlace=true
property of the imxipuvideosink
or imxipuvideotransform
elements.
References:
- Wikipedia interlaced video - includes several images demonstrating interlacing artifacts
- Wikipedia deinterlacing
Caps Filters
GStreamer has a concept called caps filters. A 'cap' is used to describe the type of data that links two pads (two plugins). For example, adding a -v flag to a pipeline pipe will output the caps negotiated between these two plugins:
# gst-launch-1.0 -v videotestsrc ! fakesink Setting pipeline to PAUSED ... Pipeline is PREROLLING ... /GstPipeline:pipeline0/GstVideoTestSrc:videotestsrc0.GstPad:src: caps = "video/x-raw\,\ format\=\(string\)I420\,\ width\=\(int\)320\,\ height\=\(int\)240\,\ framerate\=\(fraction\)30/1\,\ pixel-aspect-ratio\=\(fraction\)1/1\,\ interlace-mode\=\(string\)progressive" /GstPipeline:pipeline0/GstFakeSink:fakesink0.GstPad:sink: caps = "video/x-raw\,\ format\=\(string\)I420\,\ width\=\(int\)320\,\ height\=\(int\)240\,\ framerate\=\(fraction\)30/1\,\ pixel-aspect-ratio\=\(fraction\)1/1\,\ interlace-mode\=\(string\)progressive" Pipeline is PREROLLED ... Setting pipeline to PLAYING ... New clock: GstSystemClock
In the output, the caps = "video/x-raw\,\ format\=\(string\)I420\,\ width\=\(int\)320\,\ height\=\(int\)240\,\ framerate\=\(fraction\)30/1\,\ pixel-aspect-ratio\=\(fraction\)1/1\,\ interlace-mode\=\(string\)progressive"
are the video caps negotiated between the two. You can also force in a caps filter between two elements:
~# gst-launch-1.0 -v videotestsrc ! 'video/x-raw, format=UYVY, width=1920, height=1080, framerate=10/1' ! fakesink Setting pipeline to PAUSED ... Pipeline is PREROLLING ... /GstPipeline:pipeline0/GstVideoTestSrc:videotestsrc0.GstPad:src: caps = "video/x-raw\,\ format\=\(string\)UYVY\,\ width\=\(int\)1920\,\ height\=\(int\)1080\,\ framerate\=\(fraction\)10/1\,\ pixel-aspect-ratio\=\(fraction\)1/1\,\ interlace-mode\=\(string\)progressive" /GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:src: caps = "video/x-raw\,\ format\=\(string\)UYVY\,\ width\=\(int\)1920\,\ height\=\(int\)1080\,\ framerate\=\(fraction\)10/1\,\ pixel-aspect-ratio\=\(fraction\)1/1\,\ interlace-mode\=\(string\)progressive" /GstPipeline:pipeline0/GstFakeSink:fakesink0.GstPad:sink: caps = "video/x-raw\,\ format\=\(string\)UYVY\,\ width\=\(int\)1920\,\ height\=\(int\)1080\,\ framerate\=\(fraction\)10/1\,\ pixel-aspect-ratio\=\(fraction\)1/1\,\ interlace-mode\=\(string\)progressive" /GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:sink: caps = "video/x-raw\,\ format\=\(string\)UYVY\,\ width\=\(int\)1920\,\ height\=\(int\)1080\,\ framerate\=\(fraction\)10/1\,\ pixel-aspect-ratio\=\(fraction\)1/1\,\ interlace-mode\=\(string\)progressive" Pipeline is PREROLLED ... Setting pipeline to PLAYING ... New clock: GstSystemClock
As you can see, the caps filter I introduced changed both the video format, resolution, and framerate of the video stream coming out of the videotestsrc
plugin. Caps filters are useful when you want to capture at a specific resolution/format, changing audio sample rate etc.
Loopback Test
Looping video (i.e. going from an input source back out to an output sink) is something that can be useful if doing colorspace conversions/video composition/resizing etc. The easiest method of confirming video in to out is by doing something like the following:
# Take camera input /dev/video0 and output it to /dev/fb0 using the GPU
gst-launch-1.0 imxv4l2videosrc ! imxg2dvideosink
However, there are some input devices that the GPU sink cannot accept, and therefore you'll need to do a colorspace conversion:
# Take camera input /dev/video0, colorspace convert it using the IPU, and finally output it to /dev/fb0 using the GPU gst-launch-1.0 imxv4l2videosrc device=/dev/video0 ! imxipuvideotransform ! imxg2dvideosink
Some other examples:
- Take camera input /dev/video0 and output it to /dev/fb0 using the IPU to both colorspace convert and display
gst-launch-1.0 imxv4l2videosrc ! imxipuvideotransform ! imxipuvideosink
- Take two inputs, and place them in separate sections of the screen using both IPU and GPU
gst-launch-1.0 \ imxv4l2videosrc device=/dev/video0 ! imxipuvideosink window-width=480 window-height=272 \ videotestsrc ! imxg2dvideosink window-width=480 window-height=272 window-x-coord=900
- Take camera input on HDMI and output to HDMI monitor and also record to file
gst-launch-1.0 imxv4l2videosrc device=/dev/video0 ! imxipuvideotransform ! tee name=t ! queue ! imxg2dvideosink t. ! queue ! imxvpuenc_h264 quant-param=25 ! filesink location=/home/root/file.mp4
Encoding
Encoding a file means to take a raw stream and convert it to a file format (e.g. avi/mp4 etc). The hardware accelerated encoder elements on the i.mx6 are: imxvpuenc_h263, imxvpuenc_h264, imxvpuenc_mpeg4, and imxvpuenc_mjpeg. See below for some examples.
VBR/CBR
Variable Bitrate (VBR) and Constant Bitrate (CBR) are some some parameters you can pass into an encoder. For example, the imxvpuenc_h263 encoder can set it's bitrate property for CBR, or can change quant-param for VBR. When setting the bitrate, you're guaranteed a maximum bitrate of that stream. For example, if filming an action scene, the bitrate is guaranteed to not exceed 10mbps. However, on calm scenes, the camera might decide to lower it's own bitrate (depending on if it's doing it's own compression). On the other hand, the quant-param will take in whatever bitrate was decided on by the camera and only attempt to quantize it. That is, a quantization level of 25 means each frame will be split into 25 chunks from the original, thus lowering it's quality (and dynamically changing the bitrate).
h264
h264 is a very popular encoding technology. It is most often used for HD content, such as Blu-rays and HDTV. See below for an example using the hardware accelerated h264 encoder:
# Take camera input /dev/video0, encode it to h264 at a bitrate of 10mbit/s (CBR) and save to a file. gst-launch-1.0 imxv4l2videosrc device=/dev/video0 ! imxvpuenc_h264 bitrate=10000 ! filesink location=/tmp/file.mp4
Some cameras provide output that the vpu encoder can't handle, thus colorspace convert it first:
# Take camera input /dev/video0, colorspace convert it, encode it to h264 at a quant-param level of 25 (VBR) and save to a file gst-launch-1.0 imxv4l2videosrc device=/dev/video0 ! imxipuvideotransform ! imxvpuenc_h264 quant-param=25 ! filesink location=/tmp/file.mp4
mpeg4
mpeg4 is another very popular encoding technology. It is the older version of h264, but is still prevalent. See below for examples using the hardware accelerated mpeg4 encoder:
# Take camera input /dev/video0, encode it to mpeg4 at a bitrate of 10mbit/s (CBR) and save to a file. gst-launch-1.0 imxv4l2videosrc device=/dev/video0 ! imxvpuenc_mpeg4 bitrate=10000 ! filesink location=/tmp/file.mp4
mjpeg
mjpeg is the format often used when saving a .jpg file, or using the .jpg compression technology over a stream of frames. Please note that mjpeg's bitrate/quant-param parameters don't work. Currently, there is no way to vary the compression rate of the mjpeg. See below for an example usage:
- Take 1 frame, encode it to mjpeg, and save to a file
gst-launch-1.0 videotestsrc pattern=0 num-buffers=1 ! imxvpuenc_mjpeg ! filesink location=/tmp/file.mjpg
- Take 50 frames, encode it to mjpeg, and save to a file
gst-launch-1.0 videotestsrc pattern=0 num-buffers=50 ! imxvpuenc_mjpeg ! filesink location=/tmp/file.mjpg
jpeg
jpeg is an image format, usually used to display single frame captures. For example, a user can capture a single frame from a camera or other source via the jpegenc element and display it in their favorite image viewer. For example:
- Capture a frame and save it to a .jpg file
gst-launch-1.0 imxv4l2videosrc device=/dev/video0 num-buffers=1 ! jpegenc ! filesink location=/tmp/file.jpg
Decoding
Like encoding, you can go the other way (in order to display video on a monitor).
Instead of having a different plugin element for each codec supported, the imxvpudec
plugin element will automatically use the appropriate VPU decoder. However, it is necessary to have a bitstream parser in order to detect and split up the video into elements depending on the codec in use.
Note that the following examples assume you are using raw video encoded files, not container formats used for mimxed multimedia types (audio + video) such as ogg, avi, or mov (Quicktime). For information on de-muxing container formats see Yocto/gstreamer/multimedia
H.264
Decoding a h264 file might look like this:
- Take an input, decode, and display
gst-launch-1.0 filesrc location=/tmp/file.h264 ! h264parse ! imxvpudec ! imxipuvideotransform ! imxipuvideosink
MPEG4
Decoding an MPEG4 file might look like this:
- Take an input, decode, and display
gst-launch-1.0 filesrc location=/tmp/file.mp4 ! mpeg4videoparse ! imxvpudec ! imxipuvideotransform ! imxipuvideosink
Transcoding
Transcoding is the ability for a file to be converted to another format. For example:
- Take a file in the AVI format, and converts it to a h264 at a bitrate of 5mbit/s.
gst-launch-1.0 filesrc location=/tmp/file.avi ! imxvpudec ! queue2 ! imxvpuenc_h264 bitrate=5000 ! filesink location=file.mp4