简单播放器(增加sdl事件控制)
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include <time.h> #define SFM_REFRESH_EVENT (SDL_USEREVENT + 1) int thread_exit=;
//Thread
int sfp_refresh_thread(void *opaque)
{
SDL_Event event;
while (thread_exit==) {
event.type = SFM_REFRESH_EVENT;
SDL_PushEvent(&event);
//Wait 40 ms
SDL_Delay();
}
return ;
} int main(int argc, char* argv[])
{
AVFormatContext *pFormatCtx;//格式上下文结构体
int i, videoindex;
AVCodecContext *pCodecCtx;//codec上下文
AVCodec *pCodec;//codec int screen_w=,screen_h=;
SDL_Window *screen;
SDL_Renderer* sdlRenderer;
SDL_Texture* sdlTexture;
SDL_Rect sdlRect;
SDL_Thread *video_tid;
SDL_Event event; av_register_all();//ffmpeg flow 0,注册codec
avformat_network_init();//如要打开网络流,必须运行此函数
pFormatCtx = avformat_alloc_context();//格式上下文结构体指针开空间
if(avformat_open_input(&pFormatCtx, argv[], NULL, NULL) != )//打开多媒体文件
{
printf("open file error\n");
return -;
} AVDictionary* pOptions = NULL;
if ( avformat_find_stream_info(pFormatCtx, &pOptions) < )//读取音视频数据相关信息,参数0:上下文结构体指针,参数1:option
{
return -;
}
av_dump_format(pFormatCtx, , argv[], );//调试函数,输出文件的音、视频流的基本信息 //获取视频的时长
if(pFormatCtx->duration != AV_NOPTS_VALUE)
{
int hours, mins, secs, us;
int64_t duration = pFormatCtx->duration + ;
secs = duration / AV_TIME_BASE;
us = duration % AV_TIME_BASE;
mins = secs / ;
secs %= ;
hours = mins/ ;
mins %= ;
printf("%02d:%02d:%02d.%02d\n", hours, mins, secs, ( * us) / AV_TIME_BASE);
} i = ;
int videostream = -;
printf("pFormatCtx->nb_streams=%d\n", pFormatCtx->nb_streams);
for(i=;i<pFormatCtx->nb_streams;i++)//遍历多媒体文件中的每一个流,判断是否为视频。
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videostream = i;
break;
}
}
printf("videostream=%d\n", videostream); if (- == videostream)
{
printf("error no video stream\n");
return;
} pCodecCtx = pFormatCtx->streams[videostream]->codec;//codec上下文指定到格式上下文中的codec pCodec = avcodec_find_decoder( pCodecCtx->codec_id );//找到一个codec,必须先调用av_register_all() if(NULL == pCodec)
{
printf("couldn't find the decode\n");
return -;
} if( avcodec_open2(pCodecCtx, pCodec, NULL) < )//初始化一个视音频编解码器的AVCodecContext
{
printf("open decode error\n");
return -;
} AVFrame *pFrame,*pFrameYUV;//Frame结构体
pFrame = av_frame_alloc();//原始帧
pFrameYUV = av_frame_alloc();//YUV帧
uint8_t *out_buffer; int num = avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
printf("num=%d\n", num); out_buffer = (uint8_t *)av_malloc(num*sizeof(uint8_t));
avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);//将pFrameYUV和out_buffer联系起来(pFrame指向一段内存) AVPacket packet;//packet结构体
int ret = -;
i = ;
struct SwsContext *img_convert_ctx = NULL;//图像格式转化上下文
img_convert_ctx = sws_getContext(pCodecCtx->width,pCodecCtx->height,pCodecCtx->pix_fmt , pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);//初始化SWS,图片格式转化上下文 if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER))
{
printf( "Could not initialize SDL - %s\n", SDL_GetError());
return -;
} screen_w = pCodecCtx->width;
screen_h = pCodecCtx->height;
//SDL 2.0 Support for multiple windows
screen = SDL_CreateWindow("Simplest ffmpeg player's Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
screen_w, screen_h,
SDL_WINDOW_OPENGL); if(!screen)
{
printf("SDL: could not create window - exiting:%s\n",SDL_GetError());
return -;
} sdlRenderer = SDL_CreateRenderer(screen, -, );
sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING,pCodecCtx->width,pCodecCtx->height);
sdlRect.x=;
sdlRect.y=;
sdlRect.w=screen_w;
sdlRect.h=screen_h; int f1 = ;
int f2 = ;
int got_picture = -; video_tid = SDL_CreateThread(sfp_refresh_thread,NULL,NULL);
time_t t;
time(&t);
printf("begin :%s\n", ctime(&t)); while ()
{
SDL_WaitEvent(&event);
if(event.type==SFM_REFRESH_EVENT)
{
if(av_read_frame(pFormatCtx, &packet)>=)//读取码流中的音频若干帧或者视频一帧,作为packet
{
f1++;
if(packet.stream_index == videostream)//如果是视频
{
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &packet);//解码一帧视频数据。输入一个压缩编码的结构体AVPacket,输出一个解码后的结构体AVFrame if(ret < )
{
printf("decode error\n");
return -;
} if(got_picture)
{
//转换
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize,
, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);//将输出结果转化成YUV SDL_UpdateYUVTexture(sdlTexture, &sdlRect,
pFrameYUV->data[], pFrameYUV->linesize[],
pFrameYUV->data[], pFrameYUV->linesize[],
pFrameYUV->data[], pFrameYUV->linesize[]); SDL_RenderClear( sdlRenderer );
SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, &sdlRect);
SDL_RenderPresent( sdlRenderer ); //SDL_Delay(40); f2++; }
} av_free_packet(&packet);
}
else
{
thread_exit=;
break;
}
} } time(&t);
printf("begin :%s\n", ctime(&t)); SDL_Quit(); sws_freeContext(img_convert_ctx); free(out_buffer);
av_free(pFrameYUV); // Free the YUV frame
av_free(pFrame); // Close the codec
avcodec_close(pCodecCtx); // Close the video file
avformat_close_input(&pFormatCtx); printf("f1=%d\n", f1);
printf("f2=%d\n", f2); return ;
}
简单播放器(增加sdl事件控制)的更多相关文章
- Android应用--简、美音乐播放器增加音量控制
Android应用--简.美音乐播放器增加音量控制 2013年6月26日简.美音乐播放器继续完善中.. 题外话:上一篇博客是在6月11号发的,那篇博客似乎有点问题,可能是因为代码结构有点乱的原因,很难 ...
- 腾讯X5内核使用详解(X5内核播放器使用如何去除控制栏全屏播放)以及一些注意事项
例子下载地址 https://www.lanzous.com/i2zsv5g GIT就不用了麻烦的不行 本人安卓刚学 就上X5内核弄了老长时间由于对maven 和idea不熟悉刚开始导包都是 ...
- FFmpeg入门,简单播放器
一个偶然的机缘,好像要做直播相关的项目 为了筹备,前期做一些只是储备,于是开始学习ffmpeg 这是学习的第一课 做一个简单的播放器,播放视频画面帧 思路是,将视频文件解码,得到帧,然后使用定时器,1 ...
- 基于libvlc和wxWidgets的简单播放器代码阅读
源代码来自 http://git.videolan.org/?p=vlc.git;a=blob_plain;f=doc/libvlc/wx_player.cpp // g++ wx_player.cp ...
- ffmpeg学习(三)——ffmpeg+SDL2 实现简单播放器
本篇实现基于ffmpeg动态库用测试程序播放本地文件和RTSP视频流. 参考文章:http://blog.csdn.net/leixiaohua1020/article/details/8652605 ...
- 100行代码实现最简单的基于FFMPEG+SDL的视频播放器(SDL1.x)【转】
转自:http://blog.csdn.net/leixiaohua1020/article/details/8652605 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] ...
- 最简单的基于FFMPEG+SDL的视频播放器 ver2 (采用SDL2.0)
===================================================== 最简单的基于FFmpeg的视频播放器系列文章列表: 100行代码实现最简单的基于FFMPEG ...
- 【转】100行代码实现最简单的基于FFMPEG+SDL的视频播放器
FFMPEG工程浩大,可以参考的书籍又不是很多,因此很多刚学习FFMPEG的人常常感觉到无从下手.我刚接触FFMPEG的时候也感觉不知从何学起. 因此我把自己做项目过程中实现的一个非常简单的视频播放器 ...
- 最简单的基于FFMPEG+SDL的视频播放器 ver2 (採用SDL2.0)
===================================================== 最简单的基于FFmpeg的视频播放器系列文章列表: 100行代码实现最简单的基于FFMPEG ...
随机推荐
- IIS 7.5 + PHP-5.6.3 + mysql-5.6.21.1
禅道项目管理软件源码下载:http://sourceforge.net/projects/zentao/files/6.3/ZenTaoPMS.6.3.stable.zip/download Stp1 ...
- MySQL的下载与安装 和 navicat for mysql 安装使用
新手上路-MySQL安装 目录结构 Windows平台 MySQL安装 示例数据导入 Linux平台 CentOS系统 Ubuntu系统 FAQ 密码生成工具-keepass 修改提示符 图形工具 删 ...
- php 设计模式
一.工厂模式 1.创建接口类,规范方法,要实现这个接口的类必须实现这个接口的所有方法,接口的方法默认是抽象的,所以不再方法前面加 abstract interface people{ public f ...
- linux-bash shell学习
什么是shell?shell就相当于是计算机给我提供的一个操作系统的接口,这里说的bash shell是一种命令行方面的软件,提供给用户来操作系统.
- apt-get update : pulic key error
apt-get update 出现 这种错误 Reading package lists... Done W: There is no public key available for the fo ...
- 安装fcitx [Crunch bang] [debian]
第一步: sudo apt-get install fcitx fcitx-sunpinyin fcitx-ui-classic fcitx-table fcitx-config-common fc ...
- 微信 回调模式 echostr校验失败,请您检查是否正确解密并输出明文echostr
- C# BackgroundWorker组件学习入门介绍
C# BackgroundWorker组件学习入门介绍 一个程序中需要进行大量的运算,并且需要在运算过程中支持用户一定的交互,为了获得更好的用户体验,使用BackgroundWorker来完成这一功能 ...
- 基于配置文件(xml)的S2S3H3搭建
本次环境选择:JDK1.6+MySQL数据库+C3P0连接池+(struts2,spring3,hibernate3) 首先,创建WEB工程 然后倒入相关jar包(maven项目,在pom.xml中导 ...
- 使用C#反射中的MakeGenericType函数,来为泛型方法和泛型类指定(泛型的)类型
C#反射中的MakeGenericType函数可以用来指定泛型方法和泛型类的具体类型,方法如下面代码所示这里就不多讲了,详情看下面代码一切就清楚了: using System; using Syste ...