应用nvidia的deepstream技术解码H264视频文件

这个例子是deepstream1.5版本的,deepstream在2.0后sdk变化很大改用gstreamer插件形式了,以前应该是用ffmpeg来做码流相关处理的,nvidia官方说,4.0之后开源了很多东西建议4.0版本之后学习,单独做解码不需要P4/P40/T系列之类显卡,随便一个卡都行,推理的话必须要P/T系列显卡

本事实例是在英伟达官方实例上做的修改,可以将每一帧转换为图片区别为(YUV和RGB)用于智能识别

一直用ffmpeg解码h264视频流,有幸接触一下硬解码简单的做一下笔记

1.首先配置deepstream开发环境,必须要用ubuntu环境(需要P4,P40显卡)。

这里不再赘述,直接下载需要的sdk配置到临时环境变量即可

例:

export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64/:$LD_LIBRARY_PATH

 

2.运行官方sdk带的例子

直接自己新建makefile文件,用到了opencv库/cuda/deepstream/cudnn&tensorrt/videosdk等库

CC = g++ -std=c++11
CFLAGS = -I/usr/local/cuda-9.0/include -I../common
LDFLAGS = -L/usr/local/cuda-9.0/lib64 -L/home/TensorRT/targets/x86_64-linux-gnu/lib
LDFLAGS += -L/home/TensorRT/Bin -L/home/deepstream/lib -L. -L/usr/local/lib
LDFLAGS += -ldeepstream -lpthread -lcudart -lnvparsers -lnvinfer -lcudnn -lcublas -lopencv_core -lopencv_highgui -lopencv_imgcodecs -lopencv_text -lopencv_calib3d -lopencv_freetype -lopencv_tracking
SRC = nvCuvidPerf.cpp

all:
	$(CC) $(CFLAGS) $(SRC) $(LDFLAGS) -o dech264_to_rgb
clean:
	rm -rf *.o dech264_to_rgb

3.跑通之后,就可以在官方案例中编写解码获取数据的程序

官方提供的回调函数如下:

typedef void (*DECODER_CALLBACK)(void *pUserData, DEC_OUTPUT *decOutput);

 

在官方案例的这个位置添加设置回调函数,红色字体是自定义的函数用于解码并获取需要的数据

	//为woker提供profiers
#if 1
	for (int i = 0; i < g_nChannels; ++i) {
		g_vpDecProfilers.push_back(new DecodeProfiler);
		
		//先设置毁掉在启动解码
		pDeviceWorker->setDecCallback((void*)&strFiler, outputData, i);
		pDeviceWorker->setDecodeProfiler(g_vpDecProfilers[i], i);
	}
#endif
	outputData, i);
		pDeviceWorker->setDecodeProfiler(g_vpDecProfilers[i], i);
	}
#endif
	

首先我们来获取YUV数据,只获取第400帧的数据,写成文件可以用YUVViewer这个程序打开查看,如果不是破解版的YUVViewer的话需要打开文件选择文件格式为YUV然后设置宽高图片才能显示

 
int g_nIndex = 0;
void outputData(void *pData, DEC_OUTPUT *pOutData)
{
	if(pOutData->dpFrame_ == NULL)
	  printf("输出YUV数据为空\n");

	//输出用户信息
	//std::string strFiler = *(std::string*)pData;
	//cout << strFiler.c_str() << endl;

        //在这里是测试程序,所以我只解码一帧数据
	g_nIndex++;

	if(g_nIndex == 400)
	{
		LOG_DEBUG(logger, "开始写入数据"); 
		uint8_t *pBuf;
		pBuf = (uint8_t*)malloc(pOutData->frameSize_* sizeof(uint8_t));
		memset((char*)pBuf, 128, pOutData->frameSize_);
		cudaStream_t cst = pOutData->stream_;
		cudaMemcpyAsync(pBuf, pOutData->dpFrame_, pOutData->frameSize_, cudaMemcpyDeviceToHost, cst);	
		int len = fwrite(pBuf, 1, pOutData->frameSize_, g_fp);
		cout << len << endl;
	}
g_nIndex++;
}

 

 

接下来我们在我们来解码获取RGB格式文件,由于哪里都找不到资料,根据自己的理解写出来的有不成功,所以一点一点蒙的,可以用

 

 

int g_nIndex = 0;

void outputData(void *pData, DEC_OUTPUT *pOutData)
{
	if(pOutData->dpFrame_ == NULL)
	  printf("输出YUV数据为空\n");
	g_nIndex++;
	if(g_nIndex == 400)
	{
		LOG_DEBUG(logger, "开始写入数据"); 
		uint8_t *pBuf;
		pBuf = (uint8_t*)malloc(pOutData->frameSize_*4* sizeof(uint8_t));
		memset((char*)pBuf, 128, pOutData->frameSize_);
		//打印输出信息	
		uint8_t* devBuf;
		cudaError_t cudaStatus = cudaMalloc((void**)&devBuf, pOutData->frameSize_*4*sizeof(uint8_t));
		if(cudaStatus != cudaSuccess)
			printf("申请空间失败\n");
		cout << "开始转化文件" << endl;		

		//似乎转出来了,但是看不到图
		//nv12_to_bgr_planar_batch(pOutData->dpFrame_, 1.5*pOutData->nWidthPixels_,  (float*)devBuf, 3*pOutData->nWidthPixels_, pOutData->nWidthPixels_, pOutData->nHeightPixels_, 1, true, pOutData->stream_);
		
		//很清晰的图片
		nv12_to_bgra(pOutData->dpFrame_, pOutData->nWidthPixels_, devBuf, 4*pOutData->nWidthPixels_, pOutData->nWidthPixels_, pOutData->nHeightPixels_, pOutData->stream_);
		
		//转成灰度图片,也是灰灰的一片
		//nv12_to_gray_batch(pOutData->dpFrame_, 1.5*pOutData->nWidthPixels_, (float*)devBuf, 3*pOutData->nWidthPixels_, pOutData->nWidthPixels_, pOutData->nHeightPixels_, 1, pOutData->stream_);
		cudaMemcpyAsync(pBuf, devBuf, pOutData->frameSize_*4*sizeof(uint8_t), cudaMemcpyDeviceToHost, pOutData->stream_);	
			
		//写入来一张倒着的图片很清晰
		int len = fwrite(pBuf, 1, pOutData->frameSize_*4*sizeof(uint8_t), g_fp);
		cout << "写入文件大小" << len << endl;
	        //使用opencv转化并显示图片
		IplImage *pImg = cvCreateImage(cvSize(pOutData->nWidthPixels_, pOutData->nHeightPixels_), IPL_DEPTH_8U, 4);
		memcpy(pImg->imageData, pBuf, pOutData->nWidthPixels_*pOutData->nHeightPixels_* 4);
		cvNamedWindow("显示图片", 1);
		cvShowImage("显示图片", pImg);
		cvSaveImage("1.jpg", pImg);		
		cvReleaseImage(&pImg);
	}
}

加QQ群一起交流学习音视频开发:476513431

 

你可能感兴趣的:(人工智能,图像识别)