The RK3568 has powerful codec capability, and its codec supports maximum 4096x2304@60fps decoding and 1920x1080@100fps encoding. Therefore, it can be developed once and ported between multiple platforms.
If you use RK Debian system, you can use the compilation environment that comes with the board to compile the code development. The traditional cross-compilation method can also be used. These two methods are described separately below.
1、Download the source code
git clone https://github.com/rockchip-linux/mpp.git
2、Install the compilation tool:
sudo apt-get update
sudo apt-get install gcc g++ cmake -y
3、Configure the compilation tools
cd mpp/build/linux/aarch64
vim arm.linux.cross.cmake
##################################################
Change the following
SET(CMAKE_C_COMPILER "aarch64-linux-gnu-gcc")
SET(CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++")
to
SET(CMAKE_C_COMPILER "gcc")
SET(CMAKE_CXX_COMPILER "g++")
##################################################
4、Compile and install
./make-Makefiles.bash
make
sudo make install
1、Use the demo, there are compiled programs under mpp/build/linux/aarch64/test
cd test
./mpp_info_test
2、View output
tail -10f /var/log/messages
If a full version of the linux sdk for rk356x is available, the source code for mpp is located in the external/mpp directory, if not, it can be compiled with the command
git clone https://github.com/rockchip-linux/mpp.git
It is recommended to use the release branch to pull one down. After pulling it, go to this directory. All paths described below are relative to this mpp project.
The directories are described. The header files are in the inc directory and include these
The demo source code for testing is in the test directory
Then the mpp directory is the mpp source code used to compile out the dynamic libraries. This library is usually pre-built into the filesystem. In YYT-3568's debian, you can find this library in /lib.
The source code for the demo for testing is in the test directory
The mpp directory is the mpp source code used to compile out the dynamic libraries. This library is usually pre-built into the filesystem. In YYT-3568 debian, you can find this library in /lib.
After compilation, the dynamic libraries are under build/linux/aarch64/mpp
Noting its linking relationship, the dynamic library that ends up being used is the librockchip_mpp.so.1 file.
Then the test demo compiles the executable under build/linux/aarch64/test.
The following demo uses mpi_enc_test from the demo, which is used for encoding. The so-called encoding, is the original RAW image data, such as YUV422 YUV420 NV12 NV16 these data formats, compression, compression methods usually have H264 H265, etc., compression after the volume is reduced, easy to store, transmission.
Using the following command can capture 10 frames of camera data (the camera is using mipi-csi2, after rkisp). The camera data is RAW data and the ISP is using NV16 format
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1632,height=1224,pixelformat=NV12 --stream-mmap=3 --stream-skip=3 --stream-to=/tmp/cif.out --stream-count=10 --stream-poll
After capturing it, use the command ls -ll to see its size. You can see that images in this data format take up a lot of space
Then use the following command to encode it
./mpi_enc_test -w 1632 -h 1224 -t 7 -i cif.out -o cif.h264 -n 10 -f 0
where -w is the width -h is the height -t specifies the output format, 7 for H264, -i -o are the input and output file names respectively, -n is the number of frames, -f specifies the input format, 0 for YUV420SP, NV12
After encoding, the output file is cif.h264, you can see that its space consumption is greatly reduced.
The output information of mpp can be found in the syslog
less /var/log/syslog
Copy the cif.h264 and cif.out files to the PC virtual machine ubuntu, then use the following command to play the cif.out
W=1632; H=1224; mplayer cif.out -loop 0 -demuxer rawvideo -fps 30 -rawvideo w=${W}:h=${H}:size=$((${W}*${H}*3/2)):format=NV12
Then use the following command to play cif.h264
mplayer cif.h264 -loop 0
As you can see, the picture quality is about the same, although the footprint is drastically reduced. And this is the point of using the board-side encoder.
The following is an example of the mpi_enc_test source code in the demo to introduce the use of the mpp dynamic library.
This source file is located in the test directory of the mpp project
First look at the main function, it first uses mpi_enc_test_cmd_update_by_args to parse out all the parameters, and then executes the encoding through the enc_test_multi function
int main(int argc, char **argv)
{
RK_S32 ret = MPP_NOK;
MpiEncTestArgs* cmd = mpi_enc_test_cmd_get();
// parse the cmd option
ret = mpi_enc_test_cmd_update_by_args(cmd, argc, argv);
if (ret)
goto DONE;
mpi_enc_test_cmd_show_opt(cmd);
ret = enc_test_multi(cmd, argv[0]);
DONE:
mpi_enc_test_cmd_put(cmd);
return ret;
}
The mpi_enc_test_cmd_update_by_args function is to parse the arguments one by one and check the arguments, and then fill in the incomplete ones.
where MPP_RET mpp_opt_parse(MppOpt opt, int argc, char **argv); is to parse out the arguments when executing the mpi_enc_test command and put them inside MppOpt opt.
MPP_RET mpi_enc_test_cmd_update_by_args(MpiEncTestArgs* cmd, int argc, char **argv)
{
MppOpt opts = NULL;
RK_S32 ret = -1;
RK_U32 i;
...
/* should change node count when option increases */
mpp_opt_setup(opts, cmd, 67, enc_opt_cnt);
for (i = 0; i < enc_opt_cnt; i++)
mpp_opt_add(opts, &enc_opts[i]);
/* mark option end */
mpp_opt_add(opts, NULL);
ret = mpp_opt_parse(opts, argc, argv);
...
if (!cmd->hor_stride)
cmd->hor_stride = mpi_enc_width_default_stride(cmd->width, cmd->format);
if (!cmd->ver_stride)
cmd->ver_stride = cmd->height;
...
if (cmd->rc_mode == MPP_ENC_RC_MODE_FIXQP) {
if (!cmd->qp_init) {
if (cmd->type == MPP_VIDEO_CodingAVC ||
cmd->type == MPP_VIDEO_CodingHEVC)
cmd->qp_init = 26;
}
}
if (cmd->trace_fps) {
fps_calc_init(&cmd->fps);
mpp_assert(cmd->fps);
fps_calc_set_cb(cmd->fps, show_enc_fps);
}
...
return ret;
}
The main function calls
int enc_test_multi(MiEncTestArgs* cmd, const char *name).
This function creates a thread and executes
void *enc_test(void *arg).
function, this function is to loop through the encoding operations
void *enc_test(void *arg)
{
...
mpp_log_q(quiet, "%s start\n", info->name);
...
ret = test_ctx_init(info);
...
ret = mpp_buffer_group_get_internal(&p->buf_grp, MPP_BUFFER_TYPE_DRM);
...
ret = mpp_buffer_get(p->buf_grp, &p->frm_buf, p->frame_size + p->header_size);
...
ret = mpp_buffer_get(p->buf_grp, &p->pkt_buf, p->frame_size);
...
ret = mpp_buffer_get(p->buf_grp, &p->md_info, p->mdinfo_size);
...
// encoder demo
ret = mpp_create(&p->ctx, &p->mpi);
...
mpp_log_q(quiet, "%p encoder test start w %d h %d type %d\n",
p->ctx, p->width, p->height, p->type);
ret = p->mpi->control(p->ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout);
...
ret = mpp_init(p->ctx, MPP_CTX_ENC, p->type);
...
ret = mpp_enc_cfg_init(&p->cfg);
...
ret = test_mpp_enc_cfg_setup(info);
...
t_s = mpp_time();
ret = test_mpp_run(info);
t_e = mpp_time();
ret = p->mpi->reset(p->ctx);
...
return NULL;
}
This function first initializes a buffer, then puts the info, data, etc. of the input file into this buffer, and then calls
mpp_create
to instantiate a MppCtx
and then use
mpp_init
initialize it, and then use
mpp_enc_cfg_init
to set it up, and finally set it up in the
test_mpp_run
call
mpi->encode_put_frame(ctx, frame).
mpi->encode_get_packet(ctx, &packet).
Send the raw data of a frame to mpp, and get the encoded data of a packet from mpp
Loop through multiple packets to get the final encoded file
The specific MPP API can be found in the MPP documentation at docs/Linux/Multimedia/Rockchip_Developer_Guide_MPP_CN.pdf