MFC 播放视频 FFMPEG SDL

使用MFC播放RTSP视频流 采用vlc的sdk有延时,使用FFMPEG SDL机制会好很多,本文总结了网络上的《只需四行代码即可简单实现SDL嵌入MFC播放视频和图片》和《100行代码实现最简单的基于FFMPEG+SDL的视频播放器》先向两位作者表示感谢!



void CSnapDemoDlg::OnStartrealplay()//播放对应函数

{

NET_SDK_CLIENTINFO clientinfo;

···

clientinfo.hPlayWnd = GetDlgItem(IDC_PREVIEW_WND)->GetSafeHwnd();//获取窗口句柄


//===获取播放视频窗口的大小

CRect struRect;
::GetWindowRect(clientinfo.hPlayWnd,&struRect);
int withvalue = (struRect.right - struRect.left);
int heightvalue = (struRect.bottom - struRect.top);
flag = 0;
//===把SDL窗口添加到MFC中
char variable[256];
sprintf(variable,"SDL_WINDOWID=0x%1x",clientinfo.hPlayWnd); // 格式化字符串
SDL_putenv(variable);


//===解码 显示
AVFormatContext *pFormatCtx;
int i, videoindex;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
char filepath[]="rtsp://192.168.1.102:8556/PSIA/Streaming/channels/2?videoCodecType=H.264";


av_register_all();//注册所有的文件格式和编解码器的库
avformat_network_init();//打开流媒体初始化
pFormatCtx = avformat_alloc_context();

if(avformat_open_input(&pFormatCtx,filepath,NULL,NULL)!=0)//打开流媒体或者本地文件
{
printf("Couldn't open input stream.(无法打开输入流)\n");
//return -1;
}
if(av_find_stream_info(pFormatCtx)<0)//获取流信息
{
printf("Couldn't find stream information.(无法获取流信息)\n");
//return -1;
}
videoindex=-1;
for(i=0; i<pFormatCtx->nb_streams; i++) 
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_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_open2(pCodecCtx, pCodec,NULL)<0)//打开编解码器
{
printf("Could not open codec.(无法打开解码器)\n");
//return -1;
}
AVFrame *pFrame,*pFrameYUV;//pFrame保存原始的帧 pFrameYUV保存转换后的帧
pFrame=avcodec_alloc_frame();
pFrameYUV=avcodec_alloc_frame();
uint8_t *out_buffer;


out_buffer=new uint8_t[avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)];//放置原始的数据

avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P,  pCodecCtx->width, pCodecCtx->height);//把帧和我们新申请的内存来结合
//------------SDL----------------
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {  
printf( "Could not initialize SDL - %s\n", SDL_GetError()); 
//return -1;

SDL_Surface *screen; 
//creen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);//创建了一个给定高度和宽度的屏幕SDL窗口的大小
screen = SDL_SetVideoMode(withvalue, heightvalue, 0, 0);//此处和rect大小共同确定播放窗口大小
if(!screen) {  
printf("SDL: could not set video mode - exiting\n");  
//return -1;
}
SDL_Overlay *bmp; 
bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,SDL_YV12_OVERLAY, screen); //在屏幕上来创建一个 YUV 覆盖以便于我们输入视频上去参数为原始视频流大小
SDL_Rect rect;
//---------------
int ret, got_picture;
int y_size = pCodecCtx->width * pCodecCtx->height;


AVPacket *packet=(AVPacket *)av_malloc(sizeof(AVPacket));
av_new_packet(packet, y_size);
//输出一下信息-----------------------------
printf("File Information(文件信息)---------------------\n");
av_dump_format(pFormatCtx,0,filepath,0);
printf("-------------------------------------------------\n");
struct SwsContext *img_convert_ctx;


img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); 
//------------------------------
while(av_read_frame(pFormatCtx, packet)>=0)
{
if(flag == 1)//关闭视频标志位
{
break;
}
if(packet->stream_index==videoindex)
{
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
if(ret < 0)
{
printf("Decode Error.(解码错误)\n");
//return -1;
}
if(got_picture)
{
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);

SDL_LockYUVOverlay(bmp);
bmp->pixels[0]=pFrameYUV->data[0];
bmp->pixels[2]=pFrameYUV->data[1];
bmp->pixels[1]=pFrameYUV->data[2];     
bmp->pitches[0]=pFrameYUV->linesize[0];
bmp->pitches[2]=pFrameYUV->linesize[1];   
bmp->pitches[1]=pFrameYUV->linesize[2];
SDL_UnlockYUVOverlay(bmp); 
rect.x = 0;    
rect.y = 0;    
//==
rect.w = withvalue;   //rect 为在SDL中显示图像的大小
rect.h = heightvalue;
//==
SDL_DisplayYUVOverlay(bmp, &rect); 
//延时40ms
SDL_Delay(20);
}
}
av_free_packet(packet);
}
sws_freeContext(img_convert_ctx);


delete[] out_buffer;
av_free(pFrameYUV);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);


return 0;

}

对应的lib dll和头文件在:

http://download.csdn.net/detail/qin5016/7593121


VC2010环境配置:


工程属性 ==》 C/C++  ==》常规 ==》 附加包含目录 添加对应头文件

工程属性 ==》 连接器 ==》 输入 ==》 lib添加


在工程头文件中添加:

extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
//新版里的图像转换结构需要引入的头文件
#include "libswscale/swscale.h"
//SDL
#include "sdl/SDL.h"
#include "sdl/SDL_thread.h"
};













  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值