SDL是一个跨平台的渲染组件,眼下已经推出到2.0.3版本号,支持Win/Linux/OSX/Android。网上非常多介绍大多是基于SDL1.2版本号的,与2.0版本号有一定的区别,本文演示怎样用SDL2.0版本号播放视频(仅视频)。

SDL下载站点:http://libsdl.org

參考网址:http://blog.csdn.net/dawdo222/article/details/8692834

上代码:

// 演示怎样用SDL2进行播放
//可參考http://blog.csdn.net/dawdo222/article/details/8692834 #include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
#include <io.h>
#include <direct.h>
#include <windows.h> extern "C"
{
// ffmpeg
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
// SDL
#include "SDL203include/SDL.h"
#include "SDL203include/SDL_thread.h"
}; #pragma comment(lib,"../lib/avutil.lib")
#pragma comment(lib,"../lib/avcodec.lib")
#pragma comment(lib,"../lib/avformat.lib")
#pragma comment(lib,"../lib/swscale.lib")
#pragma comment(lib,"../lib/sdl2.lib") //把參数转换为utf8
void prepare_app_arguments2(int *argc_ptr, char ***argv_ptr)
{
int i, nSize, newSize, buffsize;
char *argv;
char **argv2;
wchar_t* lpWideCharStr;
char* buf;
char** win32_argv_utf8 = NULL;
argv2 = *argv_ptr; buffsize = 0;
/* determine the UTF-8 buffer size (including NULL-termination symbols) */
for (i = 0; i < *argc_ptr; i++)
{
argv = argv2[i];
nSize = MultiByteToWideChar(CP_ACP, 0, argv, strlen(argv)*sizeof(char), NULL, 0);
lpWideCharStr = (wchar_t*)av_mallocz( (nSize+1) * sizeof(wchar_t));
MultiByteToWideChar(CP_ACP, 0, argv, strlen(argv)*sizeof(wchar_t), lpWideCharStr, nSize);
buffsize += WideCharToMultiByte(CP_UTF8, 0, lpWideCharStr, -1, NULL, 0, NULL, NULL);
av_free(lpWideCharStr);
} win32_argv_utf8 = (char**)av_mallocz(sizeof(char *) * (*argc_ptr + 1) + buffsize); for (i = 0; i < *argc_ptr; i++)
{
argv = argv2[i];
nSize = MultiByteToWideChar(CP_ACP, 0, argv, strlen(argv)*sizeof(char), NULL, 0);
lpWideCharStr = (wchar_t*)av_mallocz( (nSize+1) * sizeof(wchar_t));
memset(lpWideCharStr, 0, (nSize+1)*sizeof(wchar_t));
nSize = MultiByteToWideChar(CP_ACP, 0, argv, strlen(argv)*sizeof(wchar_t), lpWideCharStr, nSize);
nSize =WideCharToMultiByte(CP_UTF8 ,0,lpWideCharStr,-1,NULL,0,NULL,NULL);
buf = (char*)av_mallocz( (nSize+1) * sizeof(char));//new char[nSize+1];
memset(buf, 0, nSize+1);
newSize = WideCharToMultiByte(CP_UTF8 ,0,lpWideCharStr,-1,buf,nSize,NULL,NULL);
av_free(lpWideCharStr);
win32_argv_utf8[i] = buf;
}
*argc_ptr = *argc_ptr;
*argv_ptr = win32_argv_utf8;
} int _tmain(int argc, char* argv[])
{
///////////////////////////////////////////////////////////////////////////////
// ffmpeg
// Register all formats and codecs
av_register_all(); // Open video file
AVFormatContext *pFormatCtx = NULL;
prepare_app_arguments2(&argc, &argv);//转成UTF-8
const char* filename = "d:\\clip\\avander2.mp4";//argv[1];
if( avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0 ) {
return -1; // Couldn't open file
} // Retrieve stream information
if( avformat_find_stream_info(pFormatCtx, NULL) < 0 ) {
return -1; // Couldn't find stream information
} // Dump information about file onto standard error
av_dump_format(pFormatCtx, 0, filename, 0);
// Find the first video stream
int videoStream = -1;
for(int i=0; i < pFormatCtx->nb_streams; i++) {
if( pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) {
videoStream = i;
break;
}
}
if( videoStream == -1) {
return -1; // Didn't find a video stream
} // Get a pointer to the codec context for the video stream
AVCodecContext * pCodecCtx = pFormatCtx->streams[videoStream]->codec; // Find the decoder for the video stream
AVCodec* pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if( pCodec == NULL ) {
fprintf(stderr, "Unsupported codec!\n");
return -1; // Codec not found
} // Open codec
AVDictionary* optionsDict = NULL;
if( avcodec_open2(pCodecCtx, pCodec, &optionsDict) < 0 ) {
return -1; // Could not open codec
}
//源颜色格式
AVPixelFormat src_fix_fmt = pCodecCtx->pix_fmt; //AV_PIX_FMT_YUV420P
//目标颜色格式
AVPixelFormat dst_fix_fmt = PIX_FMT_BGR24;//PIX_FMT_YUV420P
// Allocate video frame
AVFrame* pFrame = av_frame_alloc();
AVFrame* pFrameYUV = av_frame_alloc();
if( pFrameYUV == NULL ) {
return -1;
} struct SwsContext* sws_ctx = sws_getContext(
pCodecCtx->width,
pCodecCtx->height,
pCodecCtx->pix_fmt,
pCodecCtx->width,
pCodecCtx->height,
dst_fix_fmt,//PIX_FMT_BGR24,//PIX_FMT_YUV420P,
SWS_BILINEAR,
NULL,
NULL,
NULL); int numBytes = avpicture_get_size(
dst_fix_fmt,//PIX_FMT_YUV420P,
pCodecCtx->width,
pCodecCtx->height);
uint8_t* buffer = (uint8_t *)av_malloc( numBytes*sizeof(uint8_t) ); avpicture_fill((AVPicture *)pFrameYUV, buffer, dst_fix_fmt,//PIX_FMT_YUV420P,
pCodecCtx->width, pCodecCtx->height); // Read frames and save first five frames to disk
SDL_Rect sdlRect;
sdlRect.x = 0;
sdlRect.y = 0;
sdlRect.w = pCodecCtx->width;
sdlRect.h = pCodecCtx->height; //////////////////////////////////////////////////////
// SDL
if( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER )) {
fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
exit(1);
} SDL_Window* sdlWindow = SDL_CreateWindow("My Game Window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
pCodecCtx->width, pCodecCtx->height,
0);
if( !sdlWindow ) {
fprintf(stderr, "SDL: could not set video mode - exiting\n");
exit(1);
} SDL_Renderer* sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_TARGETTEXTURE); //原本第三个參数是0
SDL_Texture* sdlTexture = SDL_CreateTexture(
sdlRenderer,
SDL_PIXELFORMAT_BGR24,//SDL_PIXELFORMAT_YV12,
SDL_TEXTUREACCESS_STATIC,//SDL_TEXTUREACCESS_STREAMING,
pCodecCtx->width,
pCodecCtx->height);
if(!sdlTexture)
return -1;
SDL_SetTextureBlendMode(sdlTexture,SDL_BLENDMODE_BLEND ); AVPacket packet;
SDL_Event event;
while( av_read_frame(pFormatCtx, &packet) >= 0 ) {
// Is this a packet from the video stream?
if( packet.stream_index == videoStream ) {
// Decode video frame
int frameFinished;
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); // Did we get a video frame?
if( frameFinished ) {
sws_scale(
sws_ctx,
(uint8_t const * const *)pFrame->data,
pFrame->linesize,
0,
pCodecCtx->height,
pFrameYUV->data,
pFrameYUV->linesize
); SDL_UpdateTexture( sdlTexture, &sdlRect, pFrameYUV->data[0], pFrameYUV->linesize[0] );
SDL_RenderClear( sdlRenderer );
SDL_RenderCopy( sdlRenderer, sdlTexture, &sdlRect, &sdlRect );
SDL_RenderPresent( sdlRenderer );
}
SDL_Delay(50);
} // 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(0);
break;
default:
break;
} } SDL_DestroyTexture(sdlTexture); // Free the YUV frame
av_free(pFrame);
av_free(pFrameYUV); // Close the codec
avcodec_close(pCodecCtx); // Close the video file
avformat_close_input(&pFormatCtx); return 0;
}

上述代码演示了怎样把视频帧转换为BGR24格式,然后用SDL的纹理函数渲染到屏幕上。

不完好的地方:没有音频部分,更没有视音频同步,播放帧率固定设为20帧/秒。

演示基于SDL2.0+FFmpeg的播放器的更多相关文章

  1. 基于ffmpeg网络播放器的教程与总结

    基于ffmpeg网络播放器的教程与总结   一.         概述 为了解决在线无广告播放youku网上的视频.(youku把每个视频切换成若干个小视频). 视频资源解析可以从www.flvcd. ...

  2. FFmpeg简易播放器的实现-视频播放

    本文为作者原创:https://www.cnblogs.com/leisure_chn/p/10047035.html,转载请注明出处 基于FFmpeg和SDL实现的简易视频播放器,主要分为读取视频文 ...

  3. FFmpeg简易播放器的实现-音视频播放

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10235926.html 基于FFmpeg和SDL实现的简易视频播放器,主要分为读取视频文 ...

  4. FFmpeg简易播放器的实现-音频播放

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10068490.html 基于FFmpeg和SDL实现的简易视频播放器,主要分为读取视频文 ...

  5. FFmpeg简易播放器的实现-最简版

    本文为作者原创:https://www.cnblogs.com/leisure_chn/p/10040202.html,转载请注明出处 基于FFmpeg和SDL实现的简易视频播放器,主要分为读取视频文 ...

  6. FFmpeg简易播放器的实现-音视频同步

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10284653.html 基于FFmpeg和SDL实现的简易视频播放器,主要分为读取视频文 ...

  7. 基于jQuery仿QQ音乐播放器网页版代码

    基于jQuery仿QQ音乐播放器网页版代码是一款黑色样式风格的网页QQ音乐播放器样式代码.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div class="m ...

  8. iOS之基于FreeStreamer的简单音乐播放器(模仿QQ音乐)

    代码地址如下:http://www.demodashi.com/demo/11944.html 天道酬勤 前言 作为一名iOS开发者,每当使用APP的时候,总难免会情不自禁的去想想,这个怎么做的?该怎 ...

  9. 基于MFC的Media Player播放器的制作(3---功能实现)

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. 下面我们试试一下,按下退出Button退出播放器的功能: 首先,我们双击退出Button按钮,就会弹出下图的框: 上面的弄好之后我们就实现 ...

随机推荐

  1. W​i​n​D​B​G​调​试​技​巧

    参考链接:http://wenku.baidu.com/view/4e58744dcf84b9d528ea7a42.html

  2. java学习笔记01--数据类型

    java学习笔记01--数据类型 java数据类型划分 分为两大类型: 1)基本数据类型:类似于普通的值. 2)引用数据类型:传递的是内存的地址. 浮点类型实际上就是表示小数. java基本数据类型 ...

  3. Android---两个视图间的淡入淡出

    本文译自:http://developer.android.com/training/animation/crossfade.html 淡入淡出动画(也可以作为溶解动画)是指在渐渐的淡出一个UI组件的 ...

  4. NET实现的DDD、CQRS与微服务架构

    WeText项目:一个基于.NET实现的DDD.CQRS与微服务架构的演示案例 最近出于工作需要,了解了一下微服务架构(Microservice Architecture,MSA).我经过两周业余时间 ...

  5. cocos2.2.3 HelloCpp TestCpp android 环境搭建 编译

    cygwin make PATH->E:\cygwin\bin JAVA_HOME->C:\Program Files\Java\jdk1.8.0_05 Eclipse->Windo ...

  6. nyoj 130 同样的雪花 【哈希】

    同样的雪花 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描写叙述 You may have heard that no two snowflakes are alike. ...

  7. 蜗牛—JSONJ学习ava转变

    最近,写网站管理员,使用异步通信技术,所使用的方法是JSON数据传输模式 需要以下jar文件 然后,自己写了一点点经常使用代码 Java的List和数组要用JSONArray对象 Map和实体用JSO ...

  8. poj 2769 Reduced ID Numbers(memset使用技巧)

    Description T. Chur teaches various groups of students at university U. Every U-student has a unique ...

  9. 【Java 它 JVM】对象的创建过程

    虚拟机会new 指令: 1.检查指令的参数可在对类的符号引用的恒定饮食定位,并检查是否已装上代表这个类的符号引用.分析和初始化.假设没有.您必须运行相应的类加载过程. 2.类加载通过审查,虚拟机将分配 ...

  10. F5 root密码恢复

    使用串口线缆链接F5的串口和PC相连接,调节串口的波特率为12000,重启F5 后在启动菜单上和linux 单用户模式一样操作即可.