mpp
mpp copied to clipboard
使用mpi_enc_test,去除代码内Hello world hahaha和SEI字段后,编码结果里PPS丢失
环境:
RK3399
使用旧版本的mpp库(并非是字符串配置编码参数,是用结构体配置)
使用原本mpi_enc_test时可以正常编码,header_mode为MPP_ENC_HEADER_MODE_EACH_IDR
测试命令
mpi_enc_test -t 7 -w 1920 -h 1080 -o /tmp/enc.h264
其内部NALU结构如下:
在代码内去除如下两处
/* optional */
p->sei_mode = MPP_ENC_SEI_MODE_ONE_FRAME;
ret = mpi->control(ctx, MPP_ENC_SET_SEI_CFG, &p->sei_mode);
if (ret) {
mpp_err("mpi control enc set sei cfg failed ret %d\n", ret);
goto RET;
}
MppEncUserData user_data;
char *str = "Hello world hahahaha lalalala\n";
{
MppMeta meta = mpp_frame_get_meta(frame);
if ((p->frame_count & 2) == 0) {
user_data.pdata = str;
user_data.len = strlen(str) + 1;
mpp_meta_set_ptr(meta, KEY_USER_DATA, &user_data);
}
if (p->osd_enable) {
/* gen and cfg osd plt */
mpi_enc_gen_osd_data(&p->osd_data, p->osd_idx_buf, p->frame_count);
mpp_meta_set_ptr(meta, KEY_OSD_DATA, (void*)&p->osd_data);
}
}
注释上述代码后,编码视频仍然可播放(因为mpi_enc_test程序在一开始就获取了一次SPS和PPS写入文件)
但是其IDR帧内单元结构少了PPS,其内容变为如下:
跟踪旧版mpp库内部 mpp_enc_v2.cpp:mpp_enc_thread()
TASK_REENCODE:
// 15. restore and process dpb
@@ -733,6 +797,14 @@ void *mpp_enc_thread(void *data)
}
frm->reencode = 0;
+ ptr = (char*) mpp_packet_get_pos(packet);
+ pktlen = mpp_packet_get_length(packet);
+ buflen = 0;
+ for (int i = 0; i < (pktlen > 30 ? 30 : pktlen); i++) {
+ buflen += snprintf(buf + buflen, sizeof(buf) - buflen, "%02x ", ptr[i]);
+ }
+ mpp_log("%s reencode: siz:%d data: [%s]", __func__, pktlen, buf);
+
// check for header adding
mpp_assert(hal_task->length == mpp_packet_get_length(packet));
@@ -780,6 +852,14 @@ void *mpp_enc_thread(void *data)
/* setup output packet and meta data */
mpp_packet_set_length(packet, hal_task->length);
+ ptr = (char*) mpp_packet_get_pos(packet);
+ pktlen = mpp_packet_get_length(packet);
+ buflen = 0;
+ for (int i = 0; i < (pktlen > 30 ? 30 : pktlen); i++) {
+ buflen += snprintf(buf + buflen, sizeof(buf) - buflen, "%02x ", ptr[i]);
+ }
+ mpp_log("%s TASK_DONE: siz:%d data: [%s]", __func__, pktlen, buf);
+
{
MppMeta meta = mpp_packet_get_meta(packet);
添加打印后,看编码日志大概是会在这个位置出现异常
mpp[26620]: mpp_enc_v2: mpp_enc_thread reencode: siz:24 data: [00 00 00 01 67 64 00 28 ac 1a d0 0f 00 44 bc a8 00 00 00 01 68 ce 3c 80 ]
mpp[26620]: mpp_enc_v2: mpp_enc_thread TASK_DONE: siz:121700 data: [00 00 00 01 67 64 00 28 ac 1a d0 0f 00 44 bc a8 00 00 00 01 25 b8 00 04 3f e5 ca 44 5f a8 ]
这两条日志打印之前的代码是hal相关的调用(mpp_enc_hal_start)等,我看不到源码
我尚未确认最新的mpp库是否有此问题,先发出来麻烦看一下是什么原因,谢谢!
hal 代码里用的是函数指针,找一下都 hal 里不同硬件的实现,都可以看到代码
hal 代码里用的是函数指针,找一下都 hal 里不同硬件的实现,都可以看到代码
您好,代码在哪里?我没看到hal,只能搜到头文件
您好,我又确认了一下正常的h264编码结果,其内部SEI实际上有时候正常,
有时候缺少了7个字节,SEI 0x05类型没有正常以0x80结尾
hal 代码里用的是函数指针,找一下都 hal 里不同硬件的实现,都可以看到代码
@HermanChen hello,请问有什么相关的指导么?我目前觉得就是交给hal那边编码的时候,生成的结果的位置比预想的生成位置往前了几个字节……
@HermanChen 您好,问题基本上解决了
- hal代码找到了,是我搜索没搜清楚;没弄错的话代码应该是
hal_h264e_vepu2_v2.c
- 本issue的问题没有具体定位什么原因,这个情况只有在1080P编码、High Profile情况下才出现,720P或者是Base Profile情况下正常;最后我把我 rk3399 原有SDK内库换成 github这边的mpp库最新提交就解决了问题。
- 此外我获取SPS、PPS方法使用的是
MPP_ENC_GET_HDR_SYNC
造成的问题,demo里用的MPP_ENC_GET_EXTRA_INFO
,我把这个改掉之后,会在1080P、High Profile的编码情况下,产生 SPS后面跟上IDR帧的情况。也没有确认原因。MPP_ENC_GET_EXTRA_INFO
还是mpp的文档里说不要用我才换的MPP_ENC_GET_HDR_SYNC
;目前可能只好继续用原来的方法。
该问题梳理总结如上,您确认后可以关闭此issue了。
使用 MPP_ENC_GET_HDR_SYNC 和 MPP_ENC_GET_EXTRA_INFO 两种的接口参数是有不同的,但是效果应该是一样的…… 需要注意的是,这两个接口需要在所有的参数配置都完成之后再调用,才能得到正确的结果。
怀疑问题根本原因是这样的: MPP_ENC_GET_EXTRA_INFO 得到的是内部数据的 packet 结构信息,在编码器配置更新之后,里面的内容也给更新了,再去拷贝数据是正常的。 MPP_ENC_GET_HDR_SYNC 是在接口调用时刻就进行拷贝,把当时参数条件下生成的不正常的头就拷贝出现,等编码器配置完成完成之后,拷贝出来的数据就和真正编码器内部的数据不一致了。
怀疑问题根本原因是这样的: MPP_ENC_GET_EXTRA_INFO 得到的是内部数据的 packet 结构信息,在编码器配置更新之后,里面的内容也给更新了,再去拷贝数据是正常的。 MPP_ENC_GET_HDR_SYNC 是在接口调用时刻就进行拷贝,把当时参数条件下生成的不正常的头就拷贝出现,等编码器配置完成完成之后,拷贝出来的数据就和真正编码器内部的数据不一致了。
您这个说法我有个疑问,因为在MPP_ENC_HEADER_MODE_EACH_IDR
情况下,每次编码到I帧都需要复制一次SPS PPS吧?
然后好像我mpp库换成github上的是没什么问题的样子
新的mpp库里编码出来一定带有两段SEI,这两段SEI都是完整的
怀疑问题根本原因是这样的: MPP_ENC_GET_EXTRA_INFO 得到的是内部数据的 packet 结构信息,在编码器配置更新之后,里面的内容也给更新了,再去拷贝数据是正常的。 MPP_ENC_GET_HDR_SYNC 是在接口调用时刻就进行拷贝,把当时参数条件下生成的不正常的头就拷贝出现,等编码器配置完成完成之后,拷贝出来的数据就和真正编码器内部的数据不一致了。
您这个说法我有个疑问,因为在
MPP_ENC_HEADER_MODE_EACH_IDR
情况下,每次编码到I帧都需要复制一次SPS PPS吧? 然后好像我mpp库换成github上的是没什么问题的样子
是的,开起来就每次编码都带 SPS/PPS 输出
新的mpp库里编码出来一定带有两段SEI,这两段SEI都是完整的
嗯,是用来保存码控信息的