行车记录仪 - 录像 - ffmpeg AVPacket 复用

背景

  • 基于ffmpeg实现录像功能,性能不理想,分析现有流程发现:写每一帧数据都需要生成一个AVPacket变量传递给av_write_frame,流程如下:
    在这里插入图片描述

  • av_new_packet函数申请一定大小的内存空间存储媒体数据,av_write_frame执行完后,需要使用av_packet_free释放AVPacket内存空间,在行车记录仪产品大码率(16Mbps),较高帧率(25fps ~ 30fps),长时间持续不断录制的环境下,该循环操作对性能的影响不容忽视,生成AVPacket实测耗时如下:

01-01 08:02:13.393   230   478 I get_packet@CviMuxer.cpp:294 [/mnt/sd/CARDV/MOVIE/1970_01_01_080135_00.MOV]: get_packet take [0] ms
01-01 08:02:13.460   230   478 I get_packet@CviMuxer.cpp:294 [/mnt/sd/CARDV/MOVIE/1970_01_01_080135_00.MOV]: get_packet take [52] ms
01-01 08:02:13.494   230   478 I get_packet@CviMuxer.cpp:294 [/mnt/sd/CARDV/MOVIE/1970_01_01_080135_00.MOV]: get_packet take [2] ms
01-01 08:02:13.503   230   478 I get_packet@CviMuxer.cpp:294 [/mnt/sd/CARDV/MOVIE/1970_01_01_080135_00.MOV]: get_packet take [3] ms
01-01 08:02:13.533   230   478 I get_packet@CviMuxer.cpp:294 [/mnt/sd/CARDV/MOVIE/1970_01_01_080135_00.MOV]: get_packet take [0] ms
01-01 08:02:13.564   230   478 I get_packet@CviMuxer.cpp:294 [/mnt/sd/CARDV/MOVIE/1970_01_01_080135_00.MOV]: get_packet take [2] ms
01-01 08:02:13.571   230   478 I get_packet@CviMuxer.cpp:294 [/mnt/sd/CARDV/MOVIE/1970_01_01_080135_00.MOV]: get_packet take [2] ms
01-01 08:02:13.608   230   478 I get_packet@CviMuxer.cpp:294 [/mnt/sd/CARDV/MOVIE/1970_01_01_080135_00.MOV]: get_packet take [18] ms
01-01 08:02:13.648   230   478 I get_packet@CviMuxer.cpp:294 [/mnt/sd/CARDV/MOVIE/1970_01_01_080135_00.MOV]: get_packet take [8] ms
01-01 08:02:13.978   230   478 I get_packet@CviMuxer.cpp:294 [/mnt/sd/CARDV/MOVIE/1970_01_01_080135_00.MOV]: get_packet take [0] ms
01-01 08:02:14.014   230   478 I get_packet@CviMuxer.cpp:294 [/mnt/sd/CARDV/MOVIE/1970_01_01_080135_00.MOV]: get_packet take [15] ms
01-01 08:02:14.045   230   478 I get_packet@CviMuxer.cpp:294 [/mnt/sd/CARDV/MOVIE/1970_01_01_080135_00.MOV]: get_packet take [12] ms
01-01 08:02:14.060   230   478 I get_packet@CviMuxer.cpp:294 [/mnt/sd/CARDV/MOVIE/1970_01_01_080135_00.MOV]: get_packet take [6] ms
01-01 08:02:14.085   230   478 I get_packet@CviMuxer.cpp:294 [/mnt/sd/CARDV/MOVIE/1970_01_01_080135_00.MOV]: get_packet take [0] ms
01-01 08:02:14.111   230   478 I get_packet@CviMuxer.cpp:294 [/mnt/sd/CARDV/MOVIE/1970_01_01_080135_00.MOV]: get_packet take [15] ms
  • 实测耗时波动较大,最多时耗时200~300ms,优化措施:AVPacket 复用。

AVPacket 复用

  • 先通过av_packet_alloc创建一个AVPacket,后续重复使用该AVPacket,写每一帧数据流程:
    在这里插入图片描述

  • AVPacket操作相关接口实现在:libavcodec/avpacket.c中,AVPacket所需内存空间的申请和扩大都封装在相关函数中,APP只需将size传递进去就可以了。

  • 修改后实测耗时几乎所有都是1ms以下,只有非常小概率会超出1ms,如下:

01-01 08:00:36.497   237   462 I get_packet@CviMuxer.cpp:308 [/mnt/sd/CARDV/MOVIE/1970_01_01_080022_00.MOV]: get_packet take [0] ms
....

data内存复用

  • AVPacket变量以及内存空间可以复用,但是写每一帧都需要将数据memcpy到AVPacket变量的data内存空间中,当数据量较大时memcpy的耗时也会比较明显,可以通过以下函数减少memcpy的使用次数:
int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size)
  • av_packet_from_data函数将参数data指针直接赋值给AVPacket的data指针,不需要做内存拷贝,但是释放AVPacket时av_buffer_unref会释放data指向的内存空间,因此存在一些约束。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值