【并行计算与CUDA开发】基于NVIDIA显卡的硬编解码的一点心得 (完结)
1.硬解码软编码方法:大体流程,先用ffmpeg来读取视频文件的包,接着开启两个线程,一个用于硬解码,一个用于软编码,然后将读取的包传给解码器,编码出的frame download到内存,然后做scale处理,将scale后的帧和编码参数一起传给编码函数,最终生成pkt包,将其写入文件。由于CUVID中CuvideoSource不支持rtsp视频流数据,不能由rtsp地址创建VideoSource,所以用ffmpeg来解析rtsp视频流。
解码与编码之间维护一个队列,队列长度定为20(因为解码速度快于编码速度,数据被覆盖,丢帧)。2.软解码软编码方法:目前只是用ffmpeg自带的sample功能,没有经过设计,暂时应用sample进行测试。
3.编解码结构
硬解软编: read(ffmpeg) ---> decoder(NVIDIA) ---> | Queue(20) | ---> encoder(ffmpeg)
软解软编: read(ffmpeg) ---> decoder(ffmpeg) ---> encoder(ffmpeg)
硬解软编基本步骤:
a.利用FFmpeg解析rtsp视频流
b.创建VideoParser
c.利用FFmpeg读取数据包(AVpacket)
d.将数据包传输到VideoParser(AVpacket ---> CUVIDSOURCEDATAPACKET)
e.VideoParser解码数据包
伪代码如下图所示
#include <nvcuvid.h>
#include <cuviddec.h>
//Called when the decoder encounters a video format change or initial sequence header
int CUDAAPI HandleVideoSequence(void * UserData, CUVIDEOFORMAT* pFormat)
{
cuvidCreateDecoder();
}
//Called by the video parser to decode a single picture
int CUDAAPI HandlePictureDecode(void *UserData, CUVIDPICPARAMS* pPicParams)
{
cuvidDecodePicture();
}
//Called by the video parser to display a video frame
int CUDAAPI HandlePicutureDisplay(void *UserData, CUVIDPARSERDISPINFO *pPicParams)
{
cuvidMapVideoFrame();
cuvidUnmapVideoFrame();
download_frame(frame);
queue.enqueue(frame);
}
// new thread read loop, read all frame
void read_loop()
{
while(av_read_frame(ifmt_ctx,pkt) > 0)
{
CUVIDSOURCEDATAPACKET pkt;
pkt.flags = 0;
pkt.payload_size = pkt.size;
pkt.payload = pkt.data;
cuvidParseVideoData(cuParser, &pkt);
}
}
//encode thread
void encode_frame()
{
queue.dequeue(temp_frame);
scale_frame(temp_frame);
encode(temp_frame);
write_to_file();
}
int main()
{
//set video parser paramters. create video parser
//decode frame packet
cuvidCreateVideoParser();
//FFmpeg open rstp strea, read packet data
...
thread(read_loop);
thread(encode_frame);
//destroy resources
cuvidDestroyDecoder();
cuvidDestroyVideoParser();
}
4.目前测试的多路是通过开启多个线程来进行的,下面是测试结果:
路数 硬解软编 软解软编
Fps CPU(%) MEM(%) Fps CPU(%) MEM(%)
1 362 80.8 1.3 344 86.1 0.7
5 81 92.5 1.3*5 72 92.5 0.7*5
10 40.5 92.5 1.3*10 36 92.5 0.7*10
20 20.6 92.5 1.3*20 18 92.5 0.7*20
注释:上面CPU占用率92.5%,CPU空闲都是0,基本CPU在满负荷运行。
需要说明的是,现在测试视频是电影的一个片段10000帧数据,可能运动比较多,如果变成直播可能运动较少,编码会更快。
当硬解码软编码时,如果帧率25fps的时候支持16路,当软解码软编码时,如果帧率25fps的时候支持14路。
5.测试环境以及参数
CPU: Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz
MEM: 8G
OS: ubuntu 12.04
Video:tears640x480p24_1000.y4m(10000frames,rate=1000)
Param:Fps:25,gop:10,bframe:1,rate:40,level 3.1