ffmpeg结合SDL编写播放器
创建播放窗口
SDL_Surface *screen = NULL;
screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, , );
if (!screen)
{
fprintf(stderr,"SDL: could not set video node - exiting\n");
exit();
}
转化yuv
SDL_ SetVideoMode设置具有指定width,height和bitsperpixel的视频模式。从SDL1.2.10开始。如果width和height都为0,他将使用当前视频模式(或桌面模式,如果没有设置模式)的宽度和高度。
现在我们在屏幕上创建一个 YUV 的播放平面,以便我们可以输入视频,并设置我们的 SWSContext 将图像数据转换为YUV420 ,YUV 是包含原图像最完整的格式,没有做压缩,减损。
bmp = SDL_CreateYUVOverlay(pCodecCtx->width,
pCodecCtx->height,
SDL_YV12_OVERLAY,
screen); //Initialize SWS context for software scaling
sws_ctx = sws_getContext
(
pCodecCtx->width,
pCodecCtx->height,
pCodecCtx->pix_fmt,
pCodecCtx->width,
pCodecCtx->height,
AV_PIX_FMT_YUV420P,
SWS_BILINEAR,
NULL, NULL, NULL
);
显示图片
在上一节中我们使用函数将每一帧图像都保存下来了,这一节将替换那个函数,改为将每一帧图像都转码送入 sdl 播放。
if (frameFinished)
{
SDL_LockYUVOverlay(bmp); AVPicture pict;
pict.data[] = bmp->pixels[];
pict.data[] = bmp->pixels[];
pict.data[] = bmp->pixels[]; pict.linesize[] = bmp->pitches[];
pict.linesize[] = bmp->pitches[];
pict.linesize[] = bmp->pitches[]; //Convert the image from its native format to RGB
sws_scale(sws_ctx,
(uint8_t const * const *)pFrame->data,
pFrame->linesize,
,
pCodecCtx->height,
//pFrameRGB->data,
//pFrameRGB->linesize
pict.data,
pict.linesize
);
SDL_UnlockYUVOverlay(bmp); rect.x = ;
rect.y = ;
rect.w = pCodecCtx->width;
rect.h = pCodecCtx->height;
SDL_DisplayYUVOverlay(bmp,&rect);
SDL_Delay();
}
本节代码在开始的时候使用了 SDL_LockYUVOverlay ,将 bmp 給锁定,因为此时要播放它,如果一个线程在播放它,另一个线程在处理它,修改它,就会出错,在完成播放后,将锁定取消。
这里的视频我按照25帧每秒,所以每隔40ms就暂停一下,如果将时间修改得太短,视频就在飞速前进,体验就不好了。
清理内存
SDL_Event event;
av_free_packet(&packet);
SDL_PollEvent(&event);
switch(event.type)
{
case SDL_QUIT:
{
SDL_Quit();
exit();
break;
} default:
{
break;
}
}
源码:
#include<stdio.h>
#include<libavcodec/avcodec.h>
#include<libavformat/avformat.h>
#include<libswscale/swscale.h> #include<SDL.h>
#include<SDL_thread.h> #ifdef __MINGW32__
#undef main /*Prevents SDL from overriding main()*/
#endif int main(int argc, char *argv[])
{
AVFormatContext *pFormatCtx = NULL;
AVCodecContext *pCodecCtx = NULL;
AVCodec *pCodec = NULL;
AVFrame *pFrame = NULL;
AVPacket packet;
int i,videoStream;
int frameFinished; AVDictionary *optionsDict = NULL;
struct SwsContext *sws_ctx = NULL; SDL_Overlay *bmp = NULL;
SDL_Surface *screen = NULL;
SDL_Rect rect;
SDL_Event event; if (argc < )
{
printf("Please provide a movie file\n");
return -;
} //register all formats and codecs
av_register_all(); if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER))
{
fprintf(stderr,"Could not initialize SDL - %s\n",SDL_GetError());
exit();
} //open video file
if (avformat_open_input(&pFormatCtx,argv[], NULL, NULL) != )
{
return -; //couldn't open file
} //retrieve stream information
if (avformat_find_stream_info(pFormatCtx, NULL) < )
{
return -; //couldn't find stream information
} //dump information about file onto standard error
av_dump_format(pFormatCtx, , argv[], ); //find the first video stream
videoStream = -;
for (i = ; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoStream = i;
break;
}
} if (videoStream == -)
{
return -; //Don't find a video stream
} //Get a pointer to the codec context for the video stream
pCodecCtx = pFormatCtx->streams[videoStream]->codec; //Find the decoder for the video stream
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL)
{
fprintf(stderr,"Unsupported codec!\n");
return -; //Codec not found
} //open codec
if (avcodec_open2(pCodecCtx, pCodec, &optionsDict) < )
{
return -; //Could not open codec
} //Allcocate an AVFrame structure
pFrame = av_frame_alloc();
//pFrameRGB = av_frame_alloc(); #ifdef __DARWIN__
screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, , );
#else
screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, , );
#endif
if (!screen)
{
fprintf(stderr,"SDL: could not set video node - exiting\n");
exit();
} //Allocate a place to put our YUV image on that screen
bmp = SDL_CreateYUVOverlay(pCodecCtx->width,
pCodecCtx->height,
SDL_YV12_OVERLAY,
screen); //Initialize SWS context for software scaling
sws_ctx = sws_getContext
(
pCodecCtx->width,
pCodecCtx->height,
pCodecCtx->pix_fmt,
pCodecCtx->width,
pCodecCtx->height,
AV_PIX_FMT_YUV420P,
SWS_BILINEAR,
NULL, NULL, NULL
); //Assign appropriate parts of buffer to image planes in pFrameRGB
//Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVFPicture
//Read frames and save first five frames to disk
i = ;
while (av_read_frame(pFormatCtx, &packet) >= )
{
//Is this a packet from video stream
if (packet.stream_index == videoStream)
{
//decode video frame
avcodec_decode_video2(pCodecCtx, pFrame,
&frameFinished, &packet); //Did wo get a video frame
if (frameFinished)
{
SDL_LockYUVOverlay(bmp); AVPicture pict;
pict.data[] = bmp->pixels[];
pict.data[] = bmp->pixels[];
pict.data[] = bmp->pixels[]; pict.linesize[] = bmp->pitches[];
pict.linesize[] = bmp->pitches[];
pict.linesize[] = bmp->pitches[]; //Convert the image from its native format to RGB
sws_scale(sws_ctx,
(uint8_t const * const *)pFrame->data,
pFrame->linesize,
,
pCodecCtx->height,
//pFrameRGB->data,
//pFrameRGB->linesize
pict.data,
pict.linesize
);
SDL_UnlockYUVOverlay(bmp); rect.x = ;
rect.y = ;
rect.w = pCodecCtx->width;
rect.h = pCodecCtx->height;
SDL_DisplayYUVOverlay(bmp,&rect);
SDL_Delay();
}
} //Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
SDL_PollEvent(&event);
switch(event.type)
{
case SDL_QUIT:
{
SDL_Quit();
exit();
break;
} default:
{
break;
}
}
} //Free the YUV frame
av_free(pFrame); //Close the codec
avcodec_close(pCodecCtx); //Close the video file
avformat_close_input(&pFormatCtx);
return ;
}
Makefile
DIR_INC = -I/usr/local/include
DIR_LIB = -L/usr/local/lib LIBS = -lavformat\
-lavcodec\
-lva-x11 \
-lva \
-lxcb-shm \
-lxcb-xfixes \
-lxcb-render \
-lxcb-shape \
-lxcb -lX11 \
-lasound \
-lz \
-lswresample \
-lswscale \
-lavutil \
-lm \
-pthread \
`sdl-config --cflags --libs` FLAGS = -Wall -ggdb project : project.c
gcc project.c ${FLAGS} ${DIR_INC} ${DIR_LIB} ${LIBS} -o project .PHONY:clean
clean:
rm project
ffmpeg结合SDL编写播放器的更多相关文章
- ffmpeg结合SDL编写播放器(三)
接下来是解析影片的帧 /*** project.c ***/ #include<stdio.h> #include<libavcodec/avcodec.h> #include ...
- ffmpeg结合SDL编写播放器(二)
我们将对帧数据做一些处理,比如将每一帧的 图像转为jpg或者bmp或者ppm等格式保存下来. 举例:在ffmpeg-2.8.8文件夹下编写test.c程序 /* test.c */ #include& ...
- ffmpeg结合SDL编写播放器(一)
ffmpeg 工具是一个高效快速的命令行工具,进行视音频不同格式之间的转换. ffmpeg命令行 ffmpeg可以读取任意数量的输入“文件”(可以是常规文件,管道,网络流,抓取设备等)读取,由 -i ...
- H.264:FFMpeg 实现简单的播放器
H.264:FFMpeg 实现简单的播放器 FFMPEG工程浩大,可以参考的书籍又不是很多,因此很多刚学习FFMPEG的人常常感觉到无从下手.我刚接触FFMPEG的时候也感觉不知从何学起. 因此我 ...
- H264-YUV通过RTP接收视频流ffmpeg解码SDL实时播放
写在前面的话 写一个简单的播放器,通过RTP接收视频流,进行实时播放.最初,使用ffplay或者vlc接收按照SDP协议文件可以播放视频,但是视频中断后重启,不能正确的解包,时常会出现如下的错误信息. ...
- FFmpeg入门,简单播放器
一个偶然的机缘,好像要做直播相关的项目 为了筹备,前期做一些只是储备,于是开始学习ffmpeg 这是学习的第一课 做一个简单的播放器,播放视频画面帧 思路是,将视频文件解码,得到帧,然后使用定时器,1 ...
- JavaCV 学习(二):使用 JavaCV + FFmpeg 制作拉流播放器
一.前言 在 Android 音视频开发学习思路 中,我们不断的学习和了解音视频相关的知识,随着知识点不断的学习,我们现在应该做的事情,就是将知识点不断的串联起来.这样才能得到更深层次的领悟.通过整理 ...
- ffmpeg学习(三)——ffmpeg+SDL2 实现简单播放器
本篇实现基于ffmpeg动态库用测试程序播放本地文件和RTSP视频流. 参考文章:http://blog.csdn.net/leixiaohua1020/article/details/8652605 ...
- 基于FFmpeg和Qt的播放器 QtAV库
http://blog.csdn.net/ibingow/article/details/8144795
随机推荐
- TreeView树,全选,反选,平级选操作
首先事件选择,选择的是MouseUp事件.为啥?因为凡是跟Check有关的,在选中父节点或者子节点,都会二次触发.然后发生的就是死循环. Up事件就可以避免二次触发.Down事件呢?那就触发After ...
- 【转载】C#的Merge方法合并两个DataTable对象的数据
在C#中的Datatable类中,可以使用DataTable类的Merge方法对两个相同结构的DataTable对象进行求并集运算,将两个DataTable对象的数据行合并到其中一个DataTable ...
- Java 之 LinkedList 集合
一.LinkedList 概述 java.util.LinkedList 集合数据存储的结构是链表结构. 特点:增删快,查询慢 LinkedList 是一个双向链表,如下图 注意:该集合实现不是同步 ...
- Maven国内源设置 - OSChina国内源失效了,别更新了
Maven国内源设置 - OSChina国内源失效了,别更新了 原文:http://blog.csdn.net/chwshuang/article/details/52198932 最近在写一个Spr ...
- filter-grok,dissect匹配数据
Grok(正则捕获).Dissect(切分): grok使用正则匹配来提取非结构化日志数并据解析为结构化和可查询的内容. dissect使用多种定界符(非数字和字母的符号,split只能一次只能使用一 ...
- linux常见依赖
1. 搭建LNMP环境用到的依赖包 yum -y install gcc gcc-c++ libxml2 libxml2-devel openssl openssl-devel curl libcur ...
- Linux操作系统内核编译之NTFS文件系统模块支持案例
Linux操作系统内核编译之NTFS文件系统模块支持案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.内核编译概述 单内核体系设计.但充分借鉴了微内核设计体系的优点,为内核引 ...
- Django bootstrap按钮点击后激活active
现在有个需求,就是在导航栏上有若干个按钮,我想实现的功能是当点击某个按钮后修改文字颜色,这样网站会更人性化.现总结方法如下: index.html: <ul class="navbar ...
- python3接口自动化:绕过验证码登陆
import requests import json from time import sleep class Test: url= "http://www.cnblogs.com/&qu ...
- P1081 开车旅行[倍增](毒瘤题)
其实就是个大模拟. 首先,根据题意,小A和小B从任意一个城市开始走,无论\(X\)如何,其路径是一定唯一的. 显然对于两问都可以想出一个\(O(n^2)\)的暴力,即直接一步一步地向右走. 首先,我们 ...