应用nvidia的deepstream技术解码H264视频文件
2018-02-22 07:54
1326 查看
本事实例是在英伟达官方实例上做的修改,可以将每一帧转换为图片区别为(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等库
3.跑通之后,就可以在官方案例中编写解码获取数据的程序
官方提供的回调函数如下:
typedef void (*DECODER_CALLBACK)(void *pUserData, DEC_OUTPUT *decOutput);
在官方案例的这个位置添加设置回调函数,红色字体是自定义的函数用于解码并获取需要的数据
首先我们来获取YUV数据,只获取第400帧的数据,写成文件可以用YUVViewer这个程序打开查看,如果不是破解版的YUVViewer的话需要打开文件选择文件格式为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/zhuoshi/Zs/TR/TensorRT-3.0.2/targets/x86_64-linux-gnu/lib LDFLAGS += -L/home/zhuoshi/Zs/Bin -L/home/xu/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
首先我们来获取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); } }
相关文章推荐
- 利用DirectShow实现对视频文件H264编码与解码基类 3
- (转)视频图像编解码技术:JPEG编解码文件结构分析
- 【Linux_Fedora_应用系列】_2_如何安装视频播放器和视频文件解码
- 利用DirectShow实现对视频文件H264编码与解码基类
- 视频图像编解码技术:JPEG编解码文件结构分析
- 利用DirectShow实现对视频文件H264编码与解码基类
- 可伸缩视频编解码SVC技术介绍应用分析
- 利用DirectShow实现对视频文件H264编码与解码基类
- 利用DirectShow实现对视频文件H264编码与解码基类 2
- 利用DirectShow实现对视频文件H264编码与解码基类 3
- 转:关于视频H264编解码的应用实现
- 利用DirectShow实现对视频文件H264编码与解码基类 2
- 关于视频H264编解码的应用实现
- Android本地视频播放器开发--ffmpeg解码视频文件中的音频(2)
- ffmpeg封装h264裸流为mp4文件,视频播放速度特别慢-解决
- C#开发微信门户及应用(19)-微信企业号的消息发送(文本、图片、文件、语音、视频、图文消息等)
- 音视频网络传输技术在安防系统中的应用
- Android应用开发之实现视频文件的上传
- 分配input port buffers、提取视频文件压缩数据、复制压缩数据到input buffer、H.264硬件解码器开始解码过程分析
- H264的视频格式H264支持4:2:0的连续或隔行视频的编码和解码