【笔记】An ffmpeg and SDL Tutorial 02《视频播放》
来源:互联网 发布:淘粉吧和淘宝的关系 编辑:程序博客网 时间:2024/06/05 03:12
概述
在这里使用的版本是SDL2。实际上SDL本身并不提供视音频播放的功能,它只是封装了视音频播放的底层API。在Windows平台下,SDL封装了Direct3D这类的API用于播放视频;封装了DirectSound这类的API用于播放音频。因为SDL的编写目的就是简化视音频播放的开发难度,所以使用SDL播放视频(YUV/RGB)和音频(PCM)数据非常的容易。
SDL简介
SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。用下面这张图可以很明确地说明SDL的用途。
SDL实际上并不限于视音频的播放,它将功能分成下列数个子系统(subsystem):
Video(图像):图像控制以及线程(thread)和事件管理(event)。
Audio(声音):声音控制
Joystick(摇杆):游戏摇杆控制
CD-ROM(光盘驱动器):光盘媒体控制
Window Management(视窗管理):与视窗程序设计集成
Event(事件驱动):处理事件驱动
在Windows下,SDL与DirectX的对应关系如下。
SDL
DirectX
SDL_Video、SDL_Image
DirectDraw、Direct3D
SDL_Audio、SDL_Mixer
DirectSound
SDL_Joystick、SDL_Base
DirectInput
SDL_Net
DirectPlay
SDL流程图及主要数据结构
就像FFmpeg一样,SDL2也有固定的执行逻辑,其流程图如下所示:
C++代码及解释
class CMySDL2{public:CMySDL2();~CMySDL2();intInit(int width, int height);intUnInit();voidTick_Render(AVFrame *pFrame);// 消息处理voidTick_Event();private:intm_nW;intm_nH;SDL_Window*m_pWindow;SDL_Renderer*m_pRenderer;SDL_Texture*m_pTexture;SDL_Rectm_sdlRect;};int CMySDL2::Init(int width, int height){if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)){printf("Could not initialize SDL - %s\n", SDL_GetError());return -1;}//SDL 2.0 Support for multiple windowsm_nW = width;m_nH = height;m_pWindow = SDL_CreateWindow("Simplest ffmpeg player's Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,m_nW, m_nH, SDL_WINDOW_OPENGL);if (!m_pWindow){printf("SDL: could not create window - exiting:%s\n", SDL_GetError());return -1;}m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);m_pTexture = SDL_CreateTexture(m_pRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, m_nW, m_nH);m_sdlRect.x = 0;m_sdlRect.y = 0;m_sdlRect.w = m_nW;m_sdlRect.h = m_nH;return 0;}int CMySDL2::UnInit(){SDL_Quit();return 0;}void CMySDL2::Tick_Render(AVFrame *pFrame){SDL_UpdateTexture(m_pTexture, NULL, pFrame->data[0], m_nW);m_sdlRect.x = 0;m_sdlRect.y = 0;m_sdlRect.w = m_nW;m_sdlRect.h = m_nH;SDL_RenderClear(m_pRenderer);//SDL_RenderCopy( sdlRenderer, sdlTexture, &sdlRect, &sdlRect ); SDL_RenderCopy(m_pRenderer, m_pTexture, NULL, &m_sdlRect);SDL_RenderPresent(m_pRenderer);}void CMySDL2::Tick_Event(){static SDL_Event event;SDL_PollEvent(&event);switch (event.type) {case SDL_QUIT:SDL_Quit();exit(0);break;default:break;}}// 函数 函数调用int main(int argc, char **argv){my::InitFFmpegLibrary();CMyFFmpeg my;my.Init("video\\yu_15s.mp4");my.Log_StructInfo();CMyDecoder dec;dec.Init(&my, AV_PIX_FMT_YUV420P);AVFrame*pFrame;CMySDL2 mySDL;mySDL.Init(my.GetWidth(), my.GetHeight());std::ofstream ofile;ofile.open("my.yuv", std::ios::binary);while (true){pFrame = dec.GetFrame();if (pFrame){mySDL.Tick_Render(pFrame);}mySDL.Tick_Event();Sleep(10);}mySDL.UnInit(); return 0;}
总结
最后总结下编写代码中遇到的两个问题:SDL绘图崩溃、视频花屏。相关代码可以查看GIT的历史记录。
SDL绘图崩溃:avcodec_decode_video2解码出来的数据必须sws_scale后才能使用:因为解出来的可能有黑边,长宽不一定就是视频的长宽。
视频花屏:av_frame_unref(pFrame);只能在程序运行结束后调用。可以查看CMyDecoder的Init和Uninit相关代码。
- 【笔记】An ffmpeg and SDL Tutorial 02《视频播放》
- 【笔记】An ffmpeg and SDL Tutorial 00
- An ffmpeg and SDL Tutorial 02
- An ffmpeg and SDL Tutorial
- An ffmpeg and SDL Tutorial
- An ffmpeg and SDL Tutorial
- An ffmpeg and SDL Tutorial
- 【笔记】An ffmpeg and SDL Tutorial 01《视频帧保存到PPM文件》
- An ffmpeg and SDL Tutorial 学习笔记(一)
- An ffmpeg and SDL Tutorial 学习笔记(二)
- An ffmpeg and SDL Tutorial 学习笔记(三)
- An ffmpeg and SDL Tutorial 学习笔记(四)
- An ffmpeg and SDL Tutorial 学习笔记(五)
- An ffmpeg and SDL Tutorial 学习笔记(六)
- An ffmpeg and SDL Tutorial 学习笔记(七)
- An ffmpeg and SDL Tutorial 01
- An ffmpeg and SDL Tutorial 00
- An ffmpeg and SDL Tutorial 03
- usaco Shaping Regions
- 点击小图查看大图jQuery插件FancyBox魔幻灯箱
- Servlet
- Dom4j解析XML文本,遍历指定节点下的节点内容和属性,并存入List<Map<String,Object>
- Codeforces 621E Wet Shark and Blocks【Dp+矩阵快速幂】
- 【笔记】An ffmpeg and SDL Tutorial 02《视频播放》
- 一洽客服客户试用转化率100%
- setInterval设置停止和循环
- Web前端——Javascript复习(数组)
- 前端小白进阶Day5-优化卡片
- C++中的头文件(.h)和源文件(.cc)
- Android插件学习汇总(持续更新)
- Android实现手势检测
- 从未如此惊艳!你好,SuperTextView