一种自恢复的视频解码方法

文档序号:1925598 发布日期:2021-12-03 浏览:18次 >En<

阅读说明:本技术 一种自恢复的视频解码方法 (Self-recovery video decoding method ) 是由 高娟 于 2021-08-06 设计创作,主要内容包括:本发明一种自恢复的视频解码方法,首先,移植ffmpeg到海思平台,对ffmpeg进行源码修改使其适配海思芯片。其次,启动ffmpeg的动态库对网络传输的数据进行参数帧和图像帧的组合,获取完整图像信息,然后,建立过滤机制,动态筛选错误帧,分析编码规律,调整错误数据包内数据帧顺序,将可解码的数据包再传送给海思芯片的硬解码模块。最后,创建获取图像线程,从解码通道获取已解码的图像数据,启动自恢复脚本监控解码程序防止异常退出,从而完成解码任务。(The invention relates to a self-recovery video decoding method, which comprises the steps of firstly, transplanting ffmpeg to a Haisi platform, and modifying source codes of the ffmpeg to enable the ffmpeg to be adapted to a Haisi chip. Secondly, starting a dynamic library of the ffmpeg to combine parameter frames and image frames of data transmitted by the network to obtain complete image information, then establishing a filtering mechanism, dynamically screening error frames, analyzing a coding rule, adjusting the sequence of data frames in an error data packet, and transmitting the decodable data packet to a hard decoding module of the Haesi chip. And finally, establishing an image acquisition thread, acquiring decoded image data from the decoding channel, and starting a self-recovery script monitoring decoding program to prevent abnormal exit, thereby completing a decoding task.)

一种自恢复的视频解码方法

技术领域

本发明属于linux系统下视频解码技术,特别是一种自恢复的视频解码方法。

背景技术

Hi3559AV100是专业的8K Ultra HD Mobile Camera SOC,它提供了8K30/4K120广播级图像质量的数字视频录制,支持多路Sensor输入,支持H.265编码输出或影视级的RAW数据输出,并集成高性能ISP处理,同时采用先进低功耗工艺和低功耗架构设计,为用户提供了卓越的图像处理能力。Hi3559AV100支持业界领先的多路4K Sensor输入,多路ISP图像处理,支持HDR10高动态范围技术标准,并支持多路全景硬件拼接。在支持8K30/4K120视频录制下,Hi3559AV100提供硬化的6-Dof数字防抖,减少了对机械云台的依赖。

但是Hi3559AV100属于硬解码范畴,在协议帧不完全符合解码协议,或者错误帧比较多的情况下,解码效率比较低下或者不能解码,并且对于带有参数帧的图像信息,硬解码模块无法提取参数信息。另外,硬解码模块存在可能因为内存泄露或者设备错误而异常退出的情况。

发明内容

本发明解决的技术问题是:克服现有技术的不足,提供了一种自恢复的视频解码方法,在系统为linux的应用场景下,针对海思Hi3559AV100芯片特点,并结合硬解码模块属性和软解码特点,设计实现了一种linux系统下基于自恢复机制的视频解码方案设计方法。

本发明的技术解决方案是:

第一方面,一种自恢复的视频解码方法,包括如下步骤:

1)配置ffmpeg的编译属性和参数,将ffmpeg动态库移植到海思平台;

2)创建网络接收任务接收主机传送的原始压缩数据;

3)创建获取数据包线程,使用ffmpeg动态库获取含有带有含参数帧的图像数据包;

4)建立过滤机制,筛选错误帧,组合成可解码的数据包发送到芯片的硬解码模块;

5)获取解码模块内的解码图像;

6)启动自恢复脚本监控解码程序。

可选地,步骤6)所述启动自恢复脚本监控解码程序的方法,具体为:

61)在系统/etc/rcS/路径下设置自恢复脚本S09Decode;

62)获取decode_video运行时的进程号;

63)使用ps命令获取decode_video进程的运行状态;

64)如果decode_video的运行状态为运行状态stillRunning,则延时5ms,并返回步骤62);如果decode_video为退出状态则执行下一步;

65)在decode的初始化函数中添加退出解码通道,释放视频缓存块,释放系统资源;

66)使用cd命令进入到decode_video所在目录,执行decode程序;

67)返回到步骤62)。

可选地,步骤1)所述将ffmpeg动态库到海思平台,具体为:

11)首先,配置ffmpeg编译属性,根据平台类型、cpu类型、编码解码器属性、格式转换属性、交叉编译属性配置参数;

12)修改acodec.h文件,增加变量:参数帧长度sei_len和数组sei_buf,同时,根据应用层需求确定其参数帧大小SEI_BUF_SIZE;

13)在hevc_sei.c文件中的decode_nal_sei_prefix函数中添加获取参数帧功能:获取函数中的参数size,将size赋值给sei_len,判断size是否小于等于SEI_BUF_SIZE,如果满足条件则拷贝上下文参数数组gb内数据到sei_buf,拷贝的长度为size,拷贝的sei_buf的数组下标i为gb数组的索引index除以8,即sei_buf[i]=gb_buf[index/8];

14)然后,执行configure命令,在配置文件夹的子文件夹lib下将生成的解码库libavcodec、libavformat、libavutil、libswscale;

15)最后,将动态库拷贝到解码板卡的/usr/lib路径下。

可选地,步骤2)所述接收主机传送的原始压缩图像,具体为:

21)首先,获取配置文件中的接收ip和端口;

22)然后,以接收ip地址和端口号为参数创建和绑定网络套接字,待创建成功后进行步骤23);

23)其次,清零接收缓冲区,等待接收到网络发送的图像数据后,进入步骤24);

24)判断本次接收的图像数据的长度是否大于零,如果大于零则进行下一步,否则回到步骤23);

25)判断协议帧头是否符合协议要求,如不符合就丢弃该帧;如果符合则将图像帧存入数据接收区。

可选地,步骤3)所述创建获取数据包线程,具体为:

321)获取从网络读取的图像数据数组首地址指针bufPtr和长度bufLen;

322)判断当前的数据长度bufLen是否大于0,如果是则继续下一步,如果不是,则退出本次数据的解码过程,等待网络下次发送数据;

323)传送数据数组首地址指针bufPtr和长度bufLen给软解码模块,使用库函数av_parser_parse2对数据按帧进行分割,如果从数组能成功获得一个完整的图像帧数据包则记录继续下一步,如果不是则退出本次解码过程,等待下次网络传送的图像数据数组;

324)保存本次数据数组中图像帧分割的数据包长度ret,从数据数组总长度bufLen剔除本次分割的图像帧数据包长度ret,并向前移动首地址指针bufPtr,移动次数等于图像帧数据包长度ret;

325)将本次分割的图像完整数据包放到待解码队列中。

可选地,步骤4)所述建立过滤机制,筛选错误帧的方法,具体为:

41)判断图像类型,分析不同类型需要的slice个数图像数据包中含P帧的个数,并记录在该通道的数据结构变量PSliceNumber;

42)判断当前数据包大小是否大于协议帧规定的最大数,如果大于则退出本次数据包的过滤过程,待接收到新的图像数据包后返回步骤41),否则进行下一步;

43)循环遍历本次数据包内的数据,依次判断当前帧是否符合h265协议帧头,如果符合则进行下一步,如果不符合则跳转到步骤49);

44)判断当前帧是否为P帧或者I帧,如果是,则需要增加本通道本次传输的数据包内sllice个数temp_PSliceNumber,进入下一步;如果不是则跳转到步骤46);

45)如果当前数据包的temp_PSliceNumber等于2,则再次判断p_slice是否为0,如果是,则设置p_size为i,并更新记录slice标志p_slice为1;

46)判断当前帧类型是否为SPS,是SPS则置标志top为1,反之,则直接进入48);

47)继续判断当前帧是否为参数帧,如果是则将当前数据包数组ptr内的i位置拷贝到数据结构Idr_buf,保存sei帧之前的帧头信息,记录当前保存帧头的数据大小Idr_Size为i,将首次出现sps标识entryFlag为1,并清零top为0;完成后进入步骤48);

48)判断当前通道的图像数据是否需要插入I帧,并且entryFlag为1,如果上述两个条件成立则判断当前帧类型是否为p帧,如果是p帧则将数据包的帧类型字节内容由0x02改成0x26,改P帧为I帧;反之则直接进入步骤49);

49)继续查看数据包内ptr是否还有其他数据需要遍历查询,如果有就回到步骤43),如果没有就继续下一步;

410)判断当前通道的insertIDR标志和entryFlag是否都为1,如果是则继续下一步,如果不是则进行步骤413);

411)判断当前temp_PSliceNumber是否等于本通道图像类型应该具备的PSliceNumber,如果是则下一步,如果不是则丢弃该数据包,退出该数据包的解码过程;待接收到新的图像数据包后返回步骤41);

412)将当前数据包内完整图像帧大小为size的数据,拷贝到Idr_Buf中,拷贝的位置从Idr_Buf的Idr_Size开始,将size的大小增大Idr_Size,再次将Idr_Buf的数据拷贝到ptr中,拷贝的数据大小为size;

413)判断当前temp_PSliceNumber是否等于本通道图像类型应该具备的PSliceNumber,如果是则进行下一步,如果不是则进行步骤415);

414)判断p_slice是否为1,如果是则将p_size赋值给size,清零p_slice;反之,则直接进入步骤415);

415)将当前通道的图像参数帧大小记录在seiSize中,同时拷贝当前图像的参数帧到当前通道的待解码图像数据结构体decodeArray中,将参数个数seiCount作为待解码图像的时间戳u64PTS;

416)查询当前通道的解码状态,并把状态结构体中的已解码图像帧数保存到u32DecodeStreamFrames;

417)获取当前通道待解码图像数据的首地址ptr和数据长度size,时间戳u64PTS,并以流形式发送到硬解码模块;

418)循环查询解码器的工作状态,直至获得新的解码图像;

419)调用海思库函数查询解码器通道状态;

420)判断通道内剩余需解码的字节数是否为0,如果是则进去下一步,如果不是则延时1ms跳转到步骤419);

421)解码器通道已经解码后的图像帧数是否与之前保存的u32DecodeStreamFrames不相等,或者该通道的insertIDR标识为1,如果是进入下一步,反之,则到步骤423);

422)将insrtIDR标识清零,增加参数帧的个数,判断如果seiCount大于协议指定大的最大值SEI_NUM,则将参数帧的个数标志seiCount清零,进入步骤426);反之,则直接进入下一步;

423)复位解码器,进入步骤424);

424)判断解码器复位标志resetFlag是否为0,如果是则进入下一步,如果不是则继续等待1ms,跳转到步骤423);

425)将复位状态resetState置1,调用库函数停止解码通道的视频流接收任务,销毁解码通道,重启解码通道,将插入I帧的标志insertIDR置1,复位状态resetState置0,进入下一步;

426)结束本次过滤过程。

可选地,步骤5)所述获取解码模块内的解码图像的方法,具体为:

51)创建获取解码图像线程;

52)进入图像获取循环;

53)查询通道内的复位状态resetState是否为1,如果是1则延时1ms,继续查询复位状态,如果不是则进行下一步;

54)调用库函数HI_MPI_VDEC_GetFrame获取图像存储的内存地址;如果失败则跳转到步骤53),如果成功则进入下一步;

55)将复位标志resetFlag置1;

56)遍历decodeArray结构体中参数帧,对比保存的时间戳u64PTS与当前的解码图像的u64PTS是否一致,如果一致则需要发送该图像数据;

57)创建网络发送任务,将步骤54)中的内存地址保存的数据发送到主机。

第二方面,一种处理装置,包括:

存储器,用于存储计算机程序;

处理器,用于从所述存储器调用并运行所述计算机程序,以执行第一方面所述方法。

一种计算机可读存储介质,所述计算机可读存储介质中存储有计算机程序或指令,当所述计算机程序或指令被执行时,实现第一方面所述的方法。

一种计算机程序产品,所述计算机程序产品包括指令,当所述计算机程序产品在计算机上运行时,使得计算机执行第一方面所述的方法。

本发明与现有技术相比的优点在于:

本发明采用ffmpeg解码库获取原始帧中参数帧信息和数据帧信息,获取完整图像帧数据包,同时建立过滤机制筛选出错误帧,调整数据包内的帧顺序,传输可解码的完整数据包给硬解码模块,完成解码功能,利用自恢复机制监控解码程序模块异常退出,从而保证持续解码。

附图说明

图1为本发明一种自恢复的视频解码方法实现流程图。

具体实施方式

结合图1,为了解决linux系统下视频解码问题,采用基于过滤机制的ffmpeg软解码和海思芯片模块硬解码结合的方法。下面对本发明的内容作进一步描述。

1)移植ffmpeg到海思平台

首先,配置ffmpeg编译属性。然后,修改ffmpeg源码,使其具备返回参数帧的功能,交叉编译ffmpeg源码。最后,获取ffmpeg解码动态库拷贝到海思开发板。

11)首先,配置ffmpeg编译属性,根据平台类型、cpu类型、编码解码器属性、格式转换属性、交叉编译属性配置参数。

12)修改acodec.h文件,增加变量:参数帧长度sei_len和数组sei_buf,根据应用层需求确定其参数帧大小SEI_BUF_SIZE;

13)在hevc_sei.c文件中的decode_nal_sei_prefix函数中添加获取参数帧功能:获取函数中的参数size,将size赋值给sei_len,判断size是否小于或等于SEI_BUF_SIZE,如果满足条件则拷贝上下文参数数组gb内数据到sei_buf,拷贝的长度为size,拷贝的sei_buf的数组下标i为gb数组的索引index除以8,即sei_buf[i]=gb_buf[index/8];

14)然后,执行configure命令,在配置文件夹的子文件夹lib下将生成的解码库libavcodec、libavformat、libavutil、libswscale;

15)最后,将动态库拷贝到解码板卡的/usr/lib路径下。

2)创建网络接收线程接收主机发送的原始压缩图像数据

首先,根据配置文件获取传输中的ip和端口号信息。然后,阻塞等待网络发送的图像数据。

21)首先,获取配置文件中接收ip和端口。

22)然后,以接收ip地址和端口号为参数创建和绑定网络套接字,待创建成功后进行步骤23);

23)其次,清零接收缓冲区,等待接收到网络发送的图像数据后,进入步骤24);

24)判断本次接收的图像数据的长度是否大于零,如果大于零则进行下一步,否则回到步骤23)。

25)判断协议帧头是否符合协议要求,如不符合就丢弃该帧;如果符合则将图像帧存入数据接收区。

3)使用ffmpeg动态库获取含参数帧的完整压缩图像数据包

首先,初始化ffmpeg使用环境。其次,创建获取数据包线程。然后,使用ffmpeg动态库获取压缩图像的含参数帧的完整数据包。

31)初始化解码库使用环境

首先,设置解码器类型,采用HEVC(h265)类型的解码器。然后,初始化解码器上下文环境,动态申请图像帧存储空间。

32)创建ffmpeg获取数据包线程,线程具体流程如下:

321)获取从网络读取的图像数据数组首地址指针bufPtr和长度bufLen;

322)判断当前的数据长度bufLen是否大于0,如果是则继续下一步,如果不是,则退出本次数据的解码过程,等待网络下次发送数据;

323)传送数据数组首地址指针bufPtr和长度bufLen给软解码模块,使用库函数av_parser_parse2对数据按帧进行分割,如果从数组能成功获得一个完整的图像帧数据包则记录继续下一步,如果不是则退出本次解码过程,等待下次网络传送的图像数据数组;

324)保存本次数据数组中图像帧分割的数据包长度ret,从数据数组总长度bufLen剔除本次分割的图像帧数据包长度ret,并向前移动首地址指针bufPtr,移动次数等于图像帧数据包长度ret;

325)将本次分割的图像完整数据包放到待解码队列中。

4)对完整数据包进行过滤并发送给解码模块

建立过滤机制,分析数据包内的帧个数和帧类型,针对压缩原理和图像类型分类保存不同图像需要的协议帧个数和帧类型。同时,根据错误类型对图像数据进行再处理,从而组合可解码的数据包给硬解码模块。具体步骤如下:

41)判断图像类型,分析不同类型需要的slice个数图像数据包中含P帧的个数),并记录在该通道的数据结构变量PSliceNumber;

42)判断当前数据包大小是否大于协议帧规定的最大数,如果大于则退出本次数据包的过滤过程,待接收到新的图像数据包后返回步骤41),否则进行下一步;

43)循环遍历本次数据包内的数据,遍历从0到(size-3),size为该数据包的大小,分类判断当前帧是否符合h265协议帧头(即具备连续三个字节为00 0001),如果符合则进行下一步,如果不符合则跳转到步骤49);

44)判断当前帧是否为P帧或者I帧,如果是,则需要增加本通道本次传输的数据包内sllice个数temp_PSliceNumber,进入下一步;如果不是则跳转到步骤46);

45)如果当前数据包的temp_PSliceNumber等于2,则再次判断当前slice=是否为本数据包第一个slice即p_slice是否为0,如果是,则记录当前数据包ptr内遍历字节所在的位置i,即设置p_size为i,并更新记录slice标志p_slice为1,表示已经存在一个slice;

46)判断当前帧类型是否为SPS,是SPS则置标志top为1并进入步骤47),反之,则直接进入48);

47)判断top是否为1,如果是,则继续判断当前帧是否为参数帧(sei帧),如果是则将当前数据包数组ptr内的i位置拷贝到数据结构Idr_buf,保存sei帧之前的帧头信息(vps,pps,sps帧),记录当前保存帧头的数据大小Idr_Size为i,将首次出现sps标识entryFlag为1,并清零top为0;完成后进入步骤48);

48)判断当前通道的图像数据是否需要插入I帧(用insertIDR标识),并且entryFlag为1,如果上述两个条件成立则判断当前帧类型是否为p帧,如果是p帧则将数据包的帧类型字节内容由0x02改成0x26,即改P帧为I帧;反之则直接进入步骤49);

49)继续查看数据包内ptr是否还有其他数据需要遍历查询,如果有就回到步骤43),如果没有就继续下一步;

410)判断当前通道的insertIDR标志和entryFlag是否都为1,如果是则继续下一步,如果不是则进行步骤413);

411)判断当前temp_PSliceNumber是否等于本通道图像类型应该具备的PSliceNumber,如果是则下一步,如果不是则丢弃该数据包,退出该数据包的解码过程;待接收到新的图像数据包后返回步骤41);

412)将当前数据包内完整图像帧大小为size的数据,拷贝到Idr_Buf中,拷贝的位置从Idr_Buf的Idr_Size开始,将size的大小增大Idr_Size(即当前数据包大小需要插入之前保存的帧头信息),再次将Idr_Buf的数据拷贝到ptr中,拷贝的数据大小为size;

413)判断当前temp_PSliceNumber是否等于本通道图像类型应该具备的PSliceNumber,如果是则进行下一步,如果不是则进行步骤415);

414)判断p_slice是否为1,如果是则将p_size赋值给size(即只取),清零p_slice并进入步骤415);反之,则直接进入步骤415);

415)将当前通道的图像参数帧大小记录在seiSize中,同时拷贝当前图像的参数帧到当前通道的待解码图像数据结构体decodeArray中,将参数个数seiCount作为待解码图像的时间戳u64PTS;

416)查询当前通道的解码状态,并把状态结构体中的已解码图像帧数保存到u32DecodeStreamFrames;

417)获取当前通道待解码图像数据的首地址ptr和数据长度size,时间戳u64PTS,并以流形式发送到解码模块;

418)循环查询解码器的工作状态,直至获得新的解码图像;

419)调用海思库函数查询解码器通道状态;

420)判断通道内剩余需解码的字节数是否为0,如果是则进去下一步,如果不是则延时1ms跳转到步骤419);

421)解码器通道已经解码后的图像帧数是否与之前保存的u32DecodeStreamFrames不相等,或者该通道的insertIDR(需要插入I帧)标识为1,如果是进入下一步,如果不是则到步骤423);

422)将insrtIDR标识清零,增加参数帧的个数(seiCount增加1),判断如果seiCount大于协议指定大的最大值SEI_NUM,则将参数帧的个数标志seiCount清零,进入步骤426);反之,则直接进入下一步;

423)复位解码器,进入步骤424);

424)判断解码器复位标志resetFlag是否为0,如果是则进入下一步,如果不是则继续等待1ms,跳转到步骤423);

425)将复位状态resetState置1,调用库函数停止解码通道的视频流接收任务,销毁解码通道,重启解码通道,将插入I帧的标志insertIDR置1,复位状态resetState置0,进入下一步;

426)结束本次过滤过程;

5)获取解码器通道内的图像

建立获取解码图像任务,实时读取解码器工作状态,调用库函数获取解码通道内解码图像,通过网络发送任务将解码图像数据发送给主机。具体步骤如下:

51)创建获取解码图像线程;

52)进入图像获取循环;

53)查询通道内的复位状态resetState是否为1,如果是1则延时1ms,继续查询复位状态,如果不是则进行下一步;

54)调用库函数HI_MPI_VDEC_GetFrame获取图像存储的内存地址,如果失败则跳转到步骤53),如果成功则进入下一步;

55)将复位标志resetFlag置1;

56)遍历decodeArray结构体中参数帧,对比保存的时间戳u64PTS与当前的解码图像的u64PTS是否一致,如果一致则需要发送该图像数据;

57)创建网络发送任务,将步骤54)中的内存地址保存的数据发送到主机。

6)启动自恢复进程监控解码程序

在系统的自运行路径下设置自恢复脚本,脚本内容实时监控解码程序的运行状态。如监控到解码程序异常退出,则自动恢复解码程序。同时,在程序再启动开始前停止解码通道发送视频流的线程,退出视频缓冲块,释放系统资源。具体步骤如下:

61)在系统/etc/rcS/路径下设置自恢复脚本S09Decode;

62)获取decode_video运行时的进程号;

63)使用ps命令获取decode_video进程的运行状态;

64)如果decode_video的运行状态为运行状态stillRunning,则延时5ms,并返回步骤62);如果decode_video为退出状态则执行下一步;

65)在decode的初始化函数中添加退出解码通道,释放视频缓存块,释放系统资源;

66)使用cd命令进入到decode_video所在目录,执行decode程序;

67)返回到步骤62)。

本发明所述步骤1)对板卡进行了解码环境的配置,对其软解码库ffmpeg移植适应海思平台,同时对ffmpeg进行修改,使其返回的图像数据包带有参数帧。步骤2)对原始的压缩数据进行帧头分析,初步过滤不符合协议要求的错误帧;步骤3)为ffmpeg创建使用环境,并指定启动要求的解码器,可针对原始数据进行协议分析。同时,从网络接收的数据区循环获取原始数据,调用库函数获取可组合成带有参数帧的完整图像帧的数据包的长度,从网络接收数据区从剔除该长度并循环反复进行直到数据区没有任何数据。步骤4)建立过滤机制,动态筛选出不符合协议规定的错误帧,分析编码规律,调整数据包图像帧顺序,根据编码器特性动态修改帧类型,使其组合成可解码的图像数据包。同时,实时监控解码器状态,根据当前数据包的需求启动复位解码通道操作,使其解码模块持续进行工作。步骤5)创建获取数据线程,根据复位状态启动库函数获取解码通道内的图像,并在数据后修改其复位状态使得步骤4能实时更新解码器工作状态,通过网络发送任务将解码图像发送到主机。步骤6)针对linux系统自运行脚本路径特点,启动监控解码程序的脚本,实时判断解码程序所在的进程的运行状态,在异常退出时释放资源并再次启动解码程序,从而保证解码持续进行。

利用上述技术方案,采用上述操作步骤,本发明可以实现linux系统下视频解码和传输问题,该方法已经经过了算法验证,并进行了实验检验。结果标明,该方案可以为解决图像解码问题,采用软解码方法,组成包含图像帧和参数帧的完整数据包,采用过滤机制,动态筛选不符合协议类型的错误帧,获取可解码的图像数据包,再使用芯片的硬解码模块完成解码过程,有效减少解码时间。

本发明虽然已以较佳实施例公开如上,但其并不是用来限定本发明,任何本领域技术人员在不脱离本发明的精神和范围内,都可以利用上述揭示的方法和技术内容对本发明技术方案做出可能的变动和修改,因此,凡是未脱离本发明技术方案的内容,依据本发明的技术实质对以上实施例所作的任何简单修改、等同变化及修饰,均属于本发明技术方案的保护范围。

本发明说明书中未作详细描述的内容属本领域技术人员的公知技术。

15页详细技术资料下载
上一篇:一种医用注射器针头装配设备
下一篇:编码装置、解码装置、编码方法、解码方法和非暂时性存储介质

网友询问留言

已有0条留言

还没有人留言评论。精彩留言会获得点赞!

精彩留言,会给你点赞!

技术分类