#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事件控制)的更多相关文章

  1. Android应用--简、美音乐播放器增加音量控制

    Android应用--简.美音乐播放器增加音量控制 2013年6月26日简.美音乐播放器继续完善中.. 题外话:上一篇博客是在6月11号发的,那篇博客似乎有点问题,可能是因为代码结构有点乱的原因,很难 ...

  2. 腾讯X5内核使用详解(X5内核播放器使用如何去除控制栏全屏播放)以及一些注意事项

    例子下载地址 https://www.lanzous.com/i2zsv5g      GIT就不用了麻烦的不行 本人安卓刚学 就上X5内核弄了老长时间由于对maven 和idea不熟悉刚开始导包都是 ...

  3. FFmpeg入门,简单播放器

    一个偶然的机缘,好像要做直播相关的项目 为了筹备,前期做一些只是储备,于是开始学习ffmpeg 这是学习的第一课 做一个简单的播放器,播放视频画面帧 思路是,将视频文件解码,得到帧,然后使用定时器,1 ...

  4. 基于libvlc和wxWidgets的简单播放器代码阅读

    源代码来自 http://git.videolan.org/?p=vlc.git;a=blob_plain;f=doc/libvlc/wx_player.cpp // g++ wx_player.cp ...

  5. ffmpeg学习(三)——ffmpeg+SDL2 实现简单播放器

    本篇实现基于ffmpeg动态库用测试程序播放本地文件和RTSP视频流. 参考文章:http://blog.csdn.net/leixiaohua1020/article/details/8652605 ...

  6. 100行代码实现最简单的基于FFMPEG+SDL的视频播放器(SDL1.x)【转】

    转自:http://blog.csdn.net/leixiaohua1020/article/details/8652605 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] ...

  7. 最简单的基于FFMPEG+SDL的视频播放器 ver2 (采用SDL2.0)

    ===================================================== 最简单的基于FFmpeg的视频播放器系列文章列表: 100行代码实现最简单的基于FFMPEG ...

  8. 【转】100行代码实现最简单的基于FFMPEG+SDL的视频播放器

    FFMPEG工程浩大,可以参考的书籍又不是很多,因此很多刚学习FFMPEG的人常常感觉到无从下手.我刚接触FFMPEG的时候也感觉不知从何学起. 因此我把自己做项目过程中实现的一个非常简单的视频播放器 ...

  9. 最简单的基于FFMPEG+SDL的视频播放器 ver2 (採用SDL2.0)

    ===================================================== 最简单的基于FFmpeg的视频播放器系列文章列表: 100行代码实现最简单的基于FFMPEG ...

随机推荐

  1. Magento的基本架构解析

    Magento的基本架构解析 magento 是在Zend框架基础上建立起来的,这点保证了代码的安全性及稳定性.选择Zend的原因有很多,但是最基本的是因为 zend框架提供了面向对象的代码库并且有很 ...

  2. magento 安装

    magento 安装其实很简单. 第一步,打开,你下载好的程序,找到php.ini.simple,根据这里面的的要求,来修改,你本地或服务器 php.ini的配置. 第二步,开始安装了(注意,先在你的 ...

  3. 区间重叠计算及IntervalTree初识

    最近被人问到这样一个问题的解决方案:在一个餐馆的预定系统中,接受用户在未来任意一段时间内的预订用餐,用户在预订的时候需要提供用餐的开始时间和结束,餐馆的餐桌是用限的,问题是,系统要在最快的时间段计算出 ...

  4. (转)小心FPGA的JTAG口(上电和下电顺序)

    同志们,根据ALTERA官方FAE(现场应用工程师)的强烈建议,请注意不要随意带电插拔你的JTAG下载接口,否则会损坏FPGA芯片的JTAG口信号管脚.现象:在排除了下载线的问题后,还是不能访问FPG ...

  5. 003:Posix IPC的消息队列

    1:与FIFO相比,FIFO要求对一个管道写入之前,必须有进程进行读打开.消息队列则不需要有进行在队列上等待消息的到达. 2:POSIX每次读取总是返回优先级最高的,system V则可以返回任意优先 ...

  6. [原创]java WEB学习笔记104:Spring学习---AOP 前奏,通过一个问题引入动态代理

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  7. maven打包日志输出优化-去掉泛型与过时的警告

    pom.xml配置 1.使用eclipse编译 <!-- Eclipse编译代码时,使用的是自带的JDT(Java Development Tools), 而Maven默认使用的是JAVA_HO ...

  8. $.ajx的用法

    $.ajax({type:'post',//可选geturl:'action.php',//这里是接收数据的PHP程序data:'data='dsa'',//传给PHP的数据,多个参数用&连接 ...

  9. Javascript 中判断对象为空

    发现了一个巧妙的实现: 需要检查一个对象(Object)是否为空,即不包含任何元素.Javascript 中的对象就是一个字典,其中包含了一系列的键值对(Key Value Pair).检查一个对象是 ...

  10. 商品条形码(JBarcode)Java版(二)

    下午开了一个下午的会议,其实开会我听不进去,因为今天妖都特别冷,下班在公司等待小媳妇一个钟头,然后带着她去吃饭,吃完饭回到家.她做运动,我就开始慢慢整理我自己的小博客. ——题记 先说一下,写这篇文章 ...