Video Codec

Note

Cmd operations and test results presented in this chapter are based on the IoT Yocto v22.0 and MT8365 P1V3 (i350-EVK) board.

Video Processing Overview

On IoT Yocto, video encoder, decoder, and format conversion hardware provide the V4L2 interface to userspace programs. GStreamer is integrated to provide wrapper plugins over the V4L2 interface and to assist in setting up video processing pipelines.

Example: Video Playback Using GStreamer

The following examples use GStreamer v4l2h264dec plug-in for hardware-accelerated video decoding. The v4l2convert plug-in is mandatory. This is explained in the sections below.

gst-launch-1.0 -v filesrc location=<your-video-path> ! parsebin ! v4l2h264dec ! v4l2convert output-io-mode=dmabuf-import capture-io-mode=dmabuf ! waylandsink

Note

The V4L2 video decoder assumes that one bitstream buffer must contains a complete frame data. The default input bitstream buffer size of Gstreamer is 2MB. It might be some playback issues on high bitrate video (e.g. 4K 60Mbps) if 2MB is not enough for whole frame data. Applications should handle the buffer allocation by themself.

The Colorimetry Issue of v4l2convert

Sometimes, the gstreamer decoding pipeline will get failed due to not supported “colorimetry”.

gst-launch-1.0 -v filesrc location=/mnt/out-320x240-nv12.avi ! parsebin ! v4l2h264dec ! v4l2convert ! waylandsink
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
/GstPipeline:pipeline0/GstParseBin:parsebin0/GstTypeFindElement:typefind.GstPad:src: caps = video/x-msvideo
/GstPipeline:pipeline0/GstParseBin:parsebin0/GstTypeFindElement:typefind.GstPad:src: caps = NULL
/GstPipeline:pipeline0/GstParseBin:parsebin0/GstH264Parse:h264parse0.GstPad:sink: caps = video/x-h264, variant=(string)itu, framerate=(fraction)30/1, width=(int)320, height=(int)240
/GstPipeline:pipeline0/GstParseBin:parsebin0/GstH264Parse:h264parse0.GstPad:src: caps = video/x-h264, variant=(string)itu, framerate=(fraction)30/1, width=(int)320, height=(int)240, chroma-format=(string)4:2:0, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, colorimetry=(string)2:4:16:3, parsed=(boolean)true, stream-format=(string)byte-stream, alignment=(string)au, profile=(string)baseline, level=(string)1.3
ERROR: from element /GstPipeline:pipeline0/GstParseBin:parsebin0/GstAviDemux:avidemux0: Internal data stream error.
Additional debug info:
../gst-plugins-good-1.20.3/gst/avi/gstavidemux.c(5798): gst_avi_demux_loop (): /GstPipeline:pipeline0/GstParseBin:parsebin0/GstAviDemux:avidemux0:
streaming stopped, reason not-negotiated (-4)
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...

This is a known issue with GStreamer v4l2convert element regarding colorimetry. The gstreamer v4l2convert ended up reducing to a “well known” set of colorspace, but then whenever you do something that isn’t in the subset, in this case, like 2:4:16:3 (reduced range, BT601, BT601, BT470BG), it fails to negotiate.

You can use a caps setter to workaround.

gst-launch-1.0 -v filesrc location=/mnt/out-320x240-nv12.avi ! parsebin ! capssetter replace=true caps="video/x-h264, variant=(string)itu, framerate=(fraction)30/1, width=(int)320, height=(int)240, chroma-format=(string)4:2:0, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, colorimetry=(string)bt601, parsed=(boolean)true, stream-format=(string)byte-stream, alignment=(string)au, profile=(string)constrained-baseline, level=(string)1.3" ! v4l2h264dec ! v4l2convert output-io-mode=dmabuf-import capture-io-mode=dmabuf ! waylandsink

Example: Video Encoding Using GStreamer

The following examples use GStreamer v4l2h264enc plug-in for hardware-accelerated video encoding.

gst-launch-1.0 -v videotestsrc num-buffers=300 ! queue ! video/x-raw,framerate=30/1,width=1920,height=1080,format=NV12 ! v4l2h264enc ! h264parse ! mp4mux ! filesink location=out_1920x1080.mp4

Note

The V4L2 video encoder assumes that output bitstream buffer is big enough for a complete frame data. The encoder will return error when buffer full. Applications should handle the buffer allocation by themself.

The GStreamer framework provides software-based or V4L2 hardware-accelerated video processing. To see the list of V4L2 video codecs available on GStreamer, use the following command:

gst-inspect-1.0 | grep v4l2.*
video4linux2:  v4l2src: Video (video4linux2) Source
video4linux2:  v4l2sink: Video (video4linux2) Sink
video4linux2:  v4l2radio: Radio (video4linux2) Tuner
video4linux2:  v4l2deviceprovider (GstDeviceProviderFactory)
video4linux2:  v4l2convert: V4L2 Video Converter
video4linux2:  v4l2mpeg4dec: V4L2 MPEG4 Decoder
video4linux2:  v4l2video0mpeg4dec: V4L2 MPEG4 Decoder
video4linux2:  v4l2h264dec: V4L2 H264 Decoder
video4linux2:  v4l2h265dec: V4L2 H265 Decoder
video4linux2:  v4l2vp8dec: V4L2 VP8 Decoder
video4linux2:  v4l2vp9dec: V4L2 VP9 Decoder
video4linux2:  v4l2h264enc: V4L2 H.264 Encoder

Video Codec Devices and V4L2 Interface

The hardware video decoder and encoder support V4L2 API in IoT Yocto. To check V4L2 devices in the console, run the following commands:

ls -l /sys/class/video4linux/
lrwxrwxrwx 1 root root 0 Sep 20 10:43 video0 -> ../../devices/platform/soc/16000000.codec/video4linux/video0
lrwxrwxrwx 1 root root 0 Sep 20 10:43 video1 -> ../../devices/platform/soc/17020000.codec/video4linux/video1
lrwxrwxrwx 1 root root 0 Sep 20 10:43 video2 -> ../../devices/platform/soc/14004000.mdp_rdma0/video4linux/video2

Another utility to enumerate the v4l2 devices is v4l2-sysfs-path:

v4l2-sysfs-path
Video device: video2
Video device: video0
Video device: video1
Alsa playback device(s): hw:0,0 hw:0,1

You can also use v4l2-dbg -D -d <device#> to query information about each V4L2 video device, for example:

v4l2-dbg -D -d 0
Driver info:
        Driver name   : mtk-vcodec-dec
        Card type     : platform:mt8167
        Bus info      : platform:mt8167
        Driver version: 5.10.73
        Capabilities  : 0x84204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
                Device Capabilities
v4l2-dbg -D -d 1
Driver info:
        Driver name   : mtk-vcodec-enc
        Card type     : platform:mt8167
        Bus info      : platform:mt8167
        Driver version: 5.10.73
        Capabilities  : 0x84204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
                Device Capabilities
v4l2-dbg -D -d 2
Driver info:
        Driver name   : mtk-mdp
        Card type     : 14004000.mdp_rdma0
        Bus info      : platform:mt8173
        Driver version: 5.10.73
        Capabilities  : 0x84204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
                Device Capabilities

As shown in the example above, there are 3 device nodes related to video codec:

  1. Video Decoder (/dev/video0 and /sys/devices/platform/soc/16000000.codec/video4linux/video0)

  2. Video Encoder (/dev/video1 and /sys/devices/platform/soc/17020000.codec/video4linux/video1)

  3. MDP (/dev/video2 and /sys/devices/platform/soc/14004000.mdp_rdma0/video4linux/video2)

All three devices are M2M (memory-to-memory) devices.

The userspace clients should access these devices through the V4L2 userspace API. IoT Yocto integrates the GStreamer framework, which provides V4L2 plugins for evaluation and application development.

Note

The video decoder device cannot decode into YUYV or NV12 formats directly. It can only decode the bitstream into a proprietary format. Please refer to the sections below to convert the proprietary format to the buffer format you require.

Output Format of Video Decoder

One thing worth notice is that the output buffer format of the video decoder device is a proprietary format. This can be observed with the following commands:

v4l2-ctl --list-formats -d 0
ioctl: VIDIOC_ENUM_FMT
    Type: Video Capture Multiplanar

    [0]: 'MT21' (Mediatek Compressed Format, compressed)
    [1]: 'MM21' (Mediatek block Format, compressed)

To see other information such as accepted bitstream format, please add --all parameter:

v4l2-ctl --all -d 0
Driver Info:
        Driver name      : mtk-vcodec-dec
        Card type        : platform:mt8167
        Bus info         : platform:mt8167
        Driver version   : 5.10.73
        Capabilities     : 0x84204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps      : 0x04204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
Priority: 2
Format Video Capture Multiplanar:
        Width/Height      : 64/64
        Pixel Format      : 'MT21' (Mediatek Compressed Format)
        Field             : None
        Number of planes  : 2
        Flags             :
        Colorspace        : Rec. 709
        Transfer Function : Default
        YCbCr/HSV Encoding: Default
        Quantization      : Default
        Plane 0           :
        Bytes per Line : 64
        Size Image     : 4096
        Plane 1           :
        Bytes per Line : 64
        Size Image     : 2048
Format Video Output Multiplanar:
        Width/Height      : 64/64
        Pixel Format      : 'H264' (H.264)
        Field             : None
        Number of planes  : 1
        Flags             :
        Colorspace        : Rec. 709
        Transfer Function : Default
        YCbCr/HSV Encoding: Default
        Quantization      : Default
        Plane 0           :
        Bytes per Line : 0
        Size Image     : 1048576
Selection Video Capture: compose, Left 0, Top 0, Width 64, Height 64, Flags:
Selection Video Capture: compose_default, Left 0, Top 0, Width 64, Height 64, Flags:
Selection Video Capture: compose_bounds, Left 0, Top 0, Width 64, Height 64, Flags:

User Controls

min_number_of_capture_buffers 0x00980927 (int)    : min=0 max=32 step=1 default=1 value=0 flags=read-only, volatile

Note

Please note that the term Format Video Capture means the format of a capture device, which produces buffers. On the contrary, the term Format Video Output means the format of a video output device, which takes buffers as inputs.

Therefore, for a M2M device like the decoder,

  • the Video Output format is the input buffer format of the decoder device.

  • the Video Capture format is the output buffer format of the decoder device.

MDP and Format Conversion

The proprietary MT21 or MM21 format cannot be decoded by software converters and must be passed to the MDP device. Therefore, a playback video pipeline always consists of video decoder hardware and MDP hardware.

The MDP device is also capable of resizing video frames and converting buffer pixel formats, the supported formats can be listed by the v4l2-ctl command:

v4l2-ctl --list-formats -d 2
ioctl: VIDIOC_ENUM_FMT
    Type: Video Capture Multiplanar

    [0]: 'NM12' (Y/CbCr 4:2:0 (N-C))
    [1]: 'NV12' (Y/CbCr 4:2:0)
    [2]: 'NM21' (Y/CrCb 4:2:0 (N-C))
    [3]: 'NV21' (Y/CrCb 4:2:0)
    [4]: 'YM21' (Planar YVU 4:2:0 (N-C))
    [5]: 'YM12' (Planar YUV 4:2:0 (N-C))
    [6]: 'YV12' (Planar YVU 4:2:0)
    [7]: 'YU12' (Planar YUV 4:2:0)
    [8]: '422P' (Planar YUV 4:2:2)
    [9]: 'NV16' (Y/CbCr 4:2:2)
    [10]: 'NM16' (Y/CbCr 4:2:2 (N-C))
    [11]: 'YUYV' (YUYV 4:2:2)
    [12]: 'UYVY' (UYVY 4:2:2)
    [13]: 'YVYU' (YVYU 4:2:2)
    [14]: 'VYUY' (VYUY 4:2:2)
    [15]: 'BA24' (32-bit ARGB 8-8-8-8)
    [16]: 'AR24' (32-bit BGRA 8-8-8-8)
    [17]: 'BX24' (32-bit XRGB 8-8-8-8)
    [18]: 'XR24' (32-bit BGRX 8-8-8-8)
    [19]: 'RGBP' (16-bit RGB 5-6-5)
    [20]: 'RGB3' (24-bit RGB 8-8-8)
    [21]: 'BGR3' (24-bit BGR 8-8-8)

The v4l2convert plug-in in GStreamer framework conveniently wraps the format conversion and resizing capabilities of MDP.

VPUD Daemon

Although the video devices are accessible through V4L2 interfaces, the kernel driver of video processing hardware delegates most of the hardware configuration logics to userspace daemons. These daemon is:

  • vpud serves the video encoder and decoder drivers.

The daemon do not provide interfaces to other userspace clients. It only works with the kernel driver. All the video processing functionalities should be accessed through the V4L2 interface on IoT Yocto.

Therefore, the video processing drivers stop working if the vpud processe is not initialized or stopped.

On IoT Yocto, the daemon is launched during the system boot process.

Video Encoder Extra-Controls

As a V4L2 video encoder, mtk-vcodec-enc also provides extra-controls to set encoder capabilities.

extra-controls of mtk-vcodec-enc

CID

Command(String)

Value

Default Value

Note

V4L2_CID_MPEG_VIDEO_BITRATE

video_bitrate

1~20000000

20000000

V4L2_CID_MPEG_VIDEO_GOP_SIZE

video_gop_size

0~65535

0

size 0 means I-VOP only

V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME

force_key_frame

0~0

0

to force set I-VOP on the next output frame

V4L2_CID_MPEG_VIDEO_HEADER_MODE

sequence_header_mode

0~1

1

0: separate mode, 1: joined-with-1st-frame mode.

V4L2_CID_MPEG_VIDEO_H264_PROFILE

h264_profile

0, 2, 4

4

0: BASELINE, 2: MAIN, 4: HIGH

V4L2_CID_MPEG_VIDEO_H264_LEVEL

h264_level

0, 2~13

11

support LEVEL_1_0~LEVEL_4_2, exclude LEVEL_1B)

Note

Gstreamer is not fully support video header mode V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE.

For example, to compress a H.264 main profile and level 4.1 video bitstream with 512kbps bitrate:

gst-launch-1.0 -v videotestsrc num-buffers=300 ! "video/x-raw,format=NV12, width=720, height=480, framerate=30/1"  ! v4l2h264enc extra-controls="cid,video_gop_size=30,video_bitrate=512000,sequence_header_mode=1" ! "video/x-h264,level=(string)4.1,profile=main" ! h264parse ! mp4mux ! filesink location=/tmp/test-h264.mp4
...
Execution ended after 0:00:01.554987154
Setting pipeline to NULL ...
Freeing pipeline ...

Note

To modify profile & level, please set it via gst-caps. If set by extra-controls directly, The profile & level will be overridden during gst caps negotiation.

Performance Measurement

Software vs. Hardware Decoder and Converter

On IoT Yocto, it provides VCODEC and MDP, which are hardware components to accelerate the video pipeline. You can still use software components to process the video, but the performance may be terrible due to the CPU performance. In this section, there are software and hardware samples for you to compare the framerate influence. The scenario is to decode a 720P/30FPS video, convert it to a 1080P/30FPS video, and then show it on the screen. fpsdisplaysink is used to calculate the framerate.

To use the software method:

gst-launch-1.0 -v filesrc location=<your-video-path> ! parsebin ! avdec_h264 ! \
videoscale ! video/x-raw,width=1920,height=1080 ! fpsdisplaysink video-sink=waylandsink text-overlay=false
...
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0/GstTextOverlay:fps-display-text-overlay: text = rendered: 181, dropped: 0, current: 18.74, average: 18.92
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 181, dropped: 0, current: 18.74, average: 18.92

To use the hardware method:

gst-launch-1.0 -v filesrc location=<your-video-path> ! parsebin ! v4l2h264dec ! \
v4l2convert output-io-mode=5 ! video/x-raw,width=1920,height=1080 ! fpsdisplaysink video-sink=waylandsink text-overlay=false
...
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0/GstTextOverlay:fps-display-text-overlay: text = rendered: 268, dropped: 1, current: 27.95, average: 27.80
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 268, dropped: 1, current: 27.95, average: 27.80

The average framerate of the software method is about 18.92 FPS while the average framerate of the hardware method is 27.80 FPS. The heavier loading it takes, the more difference it creates.

Note

When using fpsdisplaysink to check performance, please add ‘text-overlay=false’ to prevent drawing FPS information on the display overlay. It might cost a lot of CPU computing power.

Gstreamer Pipeline for Performance Test

Note

The following test results are based on Genio 1200-EVK.

For the decoder performance test, fpsdisplaysink is used to show FPS information, and waylandsink is assigned as the video-sink to check the quality of the screen.

An example of the performance test on a 4K60fps H264 video playback:

gst-launch-1.0 -v filesrc location=H264_3840x2160_60fps.mp4 ! parsebin ! queue ! v4l2h264dec ! queue ! \
v4l2convert output-io-mode=dmabuf-import capture-io-mode=dmabuf ! queue ! fpsdisplaysink video-sink=waylandsink text-overlay=false
...
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0/GstWaylandSink:waylandsink0: sync = true
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 32, dropped: 0, current: 63.65, average: 63.65
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 62, dropped: 0, current: 58.81, average: 61.21
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 93, dropped: 0, current: 61.20, average: 61.21

Note

The Gstreamer element queue is added to the pipeline to remove the buffer dependency between elements.

An example of the performance test on a 4K60fps H265 video playback:

gst-launch-1.0 -v filesrc location=H265_3840x2160_60fps.mp4 ! parsebin ! queue ! v4l2h265dec ! queue ! \
v4l2convert output-io-mode=dmabuf-import capture-io-mode=dmabuf ! queue ! fpsdisplaysink video-sink=waylandsink text-overlay=false
...
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0/GstWaylandSink:waylandsink0: sync = true
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 32, dropped: 0, current: 63.70, average: 63.70
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 62, dropped: 0, current: 59.99, average: 61.85
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 93, dropped: 0, current: 60.00, average: 61.22

An example of the performance test on a FHD60fps MPEG4 video playback:

gst-launch-1.0 -v filesrc location=MPEG4_1920x1080_60fps.mp4 ! parsebin ! queue ! v4l2mpeg4dec ! queue ! \
v4l2convert output-io-mode=dmabuf-import capture-io-mode=dmabuf ! queue ! fpsdisplaysink video-sink=waylandsink text-overlay=false
...
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0/GstWaylandSink:waylandsink0: sync = true
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 32, dropped: 0, current: 63.75, average: 63.75
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 63, dropped: 0, current: 60.00, average: 61.85
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 94, dropped: 0, current: 59.99, average: 61.23

For the encoder performance test, fpsdisplaysink is used to show FPS information, and fakesink is assigned as the video-sink to remove the overhead of the file writer. In the following test, we simply use the decoded video frames as the encoder input sources.

Note

There is a hardware limitation that the input frame buffer MUST align to 16x16 (the buffer width is the multiple of 16 and the buffer height is the multiple of 16)

An example of the performance test on a 4K60fps H264 video encoding:

gst-launch-1.0 -v filesrc location=H264_3840x2160_60fps.mp4 ! parsebin ! queue ! v4l2h264dec ! queue ! \
v4l2convert output-io-mode=dmabuf-import capture-io-mode=dmabuf ! queue ! v4l2h264enc output-io-mode=dmabuf-import ! queue ! \
fpsdisplaysink video-sink=fakesink text-overlay=false
...
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0/GstFakeSink:fakesink0: sync = true
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 32, dropped: 0, current: 63.93, average: 63.93
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 63, dropped: 0, current: 60.00, average: 61.93
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 93, dropped: 0, current: 60.00, average: 61.30

Note

The buffer type output-io-mode=dmabuf-import was assigned to v4l2h264enc to prevent the buffer copy of the input source.

An example of the performance test on a 4K60fps H265 video encoding:

gst-launch-1.0 -v filesrc location=H264_3840x2160_60fps.mp4 ! parsebin ! queue ! v4l2h264dec ! queue ! \
v4l2convert output-io-mode=dmabuf-import capture-io-mode=dmabuf ! queue ! v4l2h265enc output-io-mode=dmabuf-import ! queue ! \
fpsdisplaysink video-sink=fakesink text-overlay=false
...
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0/GstFakeSink:fakesink0: sync = true
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 32, dropped: 0, current: 63.88, average: 63.88
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 63, dropped: 0, current: 60.04, average: 61.93
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 93, dropped: 0, current: 60.00, average: 61.29

An example of the performance test on a FHD120fps H264 video encoding:

gst-launch-1.0 -v filesrc location=H264_1920x1080_120fps.mp4 ! parsebin ! queue ! v4l2h264dec ! queue ! \
v4l2convert output-io-mode=dmabuf-import capture-io-mode=dmabuf ! video/x-raw,width=1920,height=1088 ! queue ! \
v4l2h264enc output-io-mode=dmabuf-import ! queue ! fpsdisplaysink video-sink=fakesink text-overlay=false
...
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0/GstFakeSink:fakesink0: sync = true
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 62, dropped: 0, current: 123.86, average: 123.86
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 123, dropped: 0, current: 120.06, average: 121.94
/GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0: last-message = rendered: 183, dropped: 0, current: 119.99, average: 121.30

Note

In the test, the FHD video frames outputted by the v4l2h264dec was converted to 1920x1088 for v4l2h264enc due to the encoder hardware limitation (16x16 alignment). It can be removed if the frame buffer size is already 16x16 alignment.

FAQ

Is there any low level library that can be used to control video HW encoder & decoder?

We only support video encode/decode via V4L2 framework.

You can try to include gstreamer library in your application to control V4L2 framework. Please refer to the gstreamer hello-world example or simplely use gst_parse_launch to parse the gst-launch commands.