ffmpeg解码+opencv显示
2015-07-09 12:51
363 查看
ffmpeg 解码h264,并OPENCV显示
(2013-12-18 10:31:01)转载▼
#pragma comment(lib, "avcodec.lib ")
#pragma comment(lib, "avformat.lib ")
#pragma comment(lib, "avutil.lib ")
#pragma comment(lib, "avdevice.lib ")
#pragma comment(lib, "avfilter.lib ")
#pragma comment(lib, "postproc.lib ")
#pragma comment(lib, "swresample.lib")
#pragma comment(lib, "swscale.lib ")
#pragma comment(lib, "libmysql.lib ")
#pragma comment(lib, "opencv_highgui243d.lib")
#pragma comment(lib, "opencv_core243d.lib ")
int _tmain(int argc, _TCHAR* argv[])
{
***Frame *pFrame = NULL,*pFrameRGB = NULL;
***FormatContext *pFormatCtx = NULL;
int i=0, videoindex=0;
***CodecContext *pCodecCtx = NULL;
***Codec *pCodec = NULL;
char filepath[]="opencv.h264";
IplImage* pCVFrame = NULL;
int nFrame = 0;
uint8_t *out_bufferRGB;
int ret, got_picture;
static struct SwsContext *img_convert_ctx = NULL;
int y_size = 0;
***Packet *packet = NULL;
//ffmpeg注册复用器,编码器等的函数av_register_all()。
//该函数在所有基于ffmpeg的应用程序中几乎都是第一个被调用的。只有调用了该函数,才能使用复用器,编码器等。
av_register_all();
//需要播放网络视频
avformat_network_init();
pFormatCtx = avformat_alloc_context();
//打开视频文件
if(avformat_open_input(&pFormatCtx,filepath,NULL,NULL)!=0)
{
printf("无法打开文件\n");
return -1;
}
//查找文件的流信息
if(av_find_stream_info(pFormatCtx)<0)
{
printf("Couldn't find stream information.\n");
return -1;
}
cvNamedWindow("decode");
//遍历文件的各个流,找到第一个视频流,并记录该流的编码信息
videoindex=-1;
for(i=0; inb_streams; i++)
{
if(pFormatCtx->streams[i]->codec->codec_type==***MEDIA_TYPE_VIDEO)
{
videoindex=i;
break;
}
}
if(videoindex==-1)
{
printf("Didn't find a video stream.\n");
return -1;
}
pCodecCtx=pFormatCtx->streams[videoindex]->codec;
//在库里面查找支持该格式的解码器
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL)
{
printf("Codec not found.\n");
return -1;
}
//打开解码器
if(avcodec_open(pCodecCtx, pCodec)<0)
{
printf("Could not open codec.\n");
return -1;
}
//分配一个帧指针,指向解码后的原始帧
pFrame=avcodec_alloc_frame();
//分配一个帧指针,指向存放转换成RGB后的帧
pFrameRGB = avcodec_alloc_frame();
//给pFrameRGB帧加上分配的内存;
out_bufferRGB=new uint8_t[avpicture_get_size(PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height)];
avpicture_fill((***Picture *)pFrameRGB, out_bufferRGB, PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height);
y_size = pCodecCtx->width * pCodecCtx->height;
//分配帧内存
packet=(***Packet *)malloc(sizeof(***Packet));
av_new_packet(packet, y_size);
//输出一下信息-----------------------------
printf("文件信息-----------------------------------------\n");
av_dump_format(pFormatCtx,0,filepath,0);//av_dump_format只是个调试函数,输出文件的音、视频流的基本信息了,帧率、分辨率、音频采样等等
printf("-------------------------------------------------\n");
//av_read_frame 读取一个帧(到最后帧则break)
while(av_read_frame(pFormatCtx, packet)>=0)
{
if(packet->stream_index==videoindex)
{
//解码一个帧
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
if(ret < 0)
{
printf("解码错误\n");
return -1;
}
if(got_picture)
{
printf("帧号: %d \n",nFrame);
nFrame++;
//根据编码信息设置渲染格式
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
//----------------------opencv
if (NULL == pCVFrame)
{
pCVFrame=cvCreateImage(cvSize(pCodecCtx->width, pCodecCtx->height),8,3);
}
if(img_convert_ctx != NULL)
{
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
memcpy(pCVFrame->imageData,out_bufferRGB,pCodecCtx->width*pCodecCtx->height*24/8);
pCVFrame->widthStep=pCodecCtx->width*3; //4096
pCVFrame->origin=0;
cvShowImage("decode",pCVFrame);//显示
//cvReleaseImage( &pCVFrame ); //释放图像
//如果不设置由于这是个循环,会导致看不到显示出来的图像
if( cvWaitKey(20) >= 0 )
break;
}
}
}
}
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
if(got_picture)
{
printf("最后一帧 %d\n", nFrame);
nFrame++;
//根据编码信息设置渲染格式
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
//----------------------opencv
if (NULL == pCVFrame)
{
pCVFrame=cvCreateImage(cvSize(pCodecCtx->width, pCodecCtx->height),8,3);
}
if(img_convert_ctx != NULL)
{
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
memcpy(pCVFrame->imageData,out_bufferRGB,pCodecCtx->width*pCodecCtx->height*24/8);
pCVFrame->widthStep=pCodecCtx->width*3; //4096
pCVFrame->origin=0;
cvShowImage("decode",pCVFrame);//显示
cvWaitKey(20);
}
}
//释放本次读取的帧内存
av_free_packet(packet);
cvReleaseImage( &pCVFrame ); //释放图像
delete[] out_bufferRGB;
av_free(pFrameRGB);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
return 0;
}
相关文章推荐
- Linux的s、t、i、a权限
- SharePoint自动化系列——Set MMS field value using PowerShell.
- 细说Linux系统优化
- Emgucv传递Image类参数给Opencv的Mat类
- windows下使用xShell向远程linux上传文件
- setsockopt()用法(参数详细说明)
- 如何加入该网站for Linux(绑定域名)
- linux下安装gsoap
- linux awk命令详解
- linux 全盘搜索
- Openfire 性能优化
- 网站设计,你需要注意什么?
- Linux下安装禅道管理系统7.2
- OpenCV3.0.0API文档中英文对照
- tar,tar.gz,zip,tar.bz2压缩算法比较,tar.bz2压缩率最大最耗cpu
- AccessController.doPrivileged
- Apache Bench测试web性能
- 实现自动定期删除Nginx日志的方法
- linux的mkdir命令
- Linux 多线程编程实例