FFmpeg与SDL双剑合璧之ubuntu
来源:互联网 发布:淘宝买东西的流程 编辑:程序博客网 时间:2024/06/05 00:30
以前所做的工作,大多是把FFmpeg用在windows平台,采用D3D或者OpenGL的方式进行渲染呈现;
前面两篇文章中,已经做好了ubuntu平台下的ffmpeg编译与简单调试(ubuntu编译ffmpeg并且demo测试),以及windows平台下的ffmpeg解码SDL显示(FFmpeg与SDL双剑合璧之Windows);
梳理一下手上已经具备的材料:
①ffmpeg解码,SDL播放的Demo(windows平台);
②ubuntu平台下编译好的ffmpeg库;
③ubuntu平台下编译好的SDL库;
第③份材料,没有写出来,因为太简单了,大致操作步骤是:
1.下载SDL源码(SDL),解压;
2.打开终端,切换到SDL源码解压后的目录,执行./configure
3.make
4.sudo make install
OVER;
接下来,就是把windows平台下的代码直接搬过来,没有多少需要修改的地方,主要是库的引用上下了点功夫
一个需要注意的,对于ffmpeg库的调用,需要在包含头文件之前,定义一下
#define __STDC_CONSTANT_MACROS
下面上干货:
//FFDecoder.h#pragma once#define __STDC_CONSTANT_MACROS extern "C" {#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/avutil.h" #include "libavutil/opt.h"#include "libswscale/swscale.h"}class CFFDecoder{public:CFFDecoder();virtual ~CFFDecoder();intOpenFile(const char *pFilePath);intGetMediaInfo(int &nFrameW,int &nFrameH);intGetOneFrame(AVFrame *pFrame);private:AVFormatContext*m_pFormatCxt;AVCodecContext*m_pCodecCtx;AVCodec*m_pCodec;AVPacketm_Packet;intm_nVideoIndex;intm_nAudioIndex;};
//FFDecoder.cpp#include "FFDecoder.h"CFFDecoder::CFFDecoder(){m_pFormatCxt = avformat_alloc_context();m_pCodecCtx = NULL;m_pCodec = NULL;m_nVideoIndex = -1;m_nAudioIndex = -1;}CFFDecoder::~CFFDecoder(){}int CFFDecoder::OpenFile(const char *pFilePath){av_register_all();if(avformat_open_input(&m_pFormatCxt,pFilePath,NULL,NULL)<0){return -1;}if (avformat_find_stream_info(m_pFormatCxt,NULL)<0){return -2;}//ÕÒµœÒôÊÓƵ¶ÔÓŠµÄÁ÷ÍšµÀfor (int i=0;i<m_pFormatCxt->nb_streams;i++){if (m_pFormatCxt->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){m_nVideoIndex = i;}else if (m_pFormatCxt->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){m_nAudioIndex = i;}}if (m_nVideoIndex == -1){return -3;}//Žò¿ªÏàÓŠµÄœâÂëÆ÷m_pCodecCtx = m_pFormatCxt->streams[m_nVideoIndex]->codec;m_pCodec = avcodec_find_decoder(m_pCodecCtx->codec_id);;if(m_pCodec==NULL){ return -4; }if(avcodec_open2(m_pCodecCtx, m_pCodec,NULL)<0){return -5;}return 0;}int CFFDecoder::GetMediaInfo(int &nFrameW,int &nFrameH){if(m_pCodecCtx==NULL)return -1;nFrameW = m_pCodecCtx->width;nFrameH = m_pCodecCtx->height;return 0;}int CFFDecoder::GetOneFrame(AVFrame *pFrame){if(m_pFormatCxt==NULL)return 0;int nGotPicture=-1;if(av_read_frame(m_pFormatCxt,&m_Packet)>=0){//ÅжÏÊÇ·ñΪµ±Ç°ÊÓƵÁ÷Öеİüif (m_Packet.stream_index == m_nVideoIndex){int nLen = avcodec_decode_video2(m_pCodecCtx,pFrame,&nGotPicture,&m_Packet);if (nLen<0){return 0;}if (nGotPicture){//³É¹ŠµÃµœÒ»Ö¡ÊýŸÝreturn nLen;}}}return 0;}
//SDLPlayer.h#pragma onceextern "C" {#include "SDL.h"}#defineMSG_REFRESH_VIDEO(SDL_USEREVENT+10)class CSDLPlayer{public:CSDLPlayer();virtual ~CSDLPlayer();//³õÊŒ»¯²¥·ÅÆ÷£¬ÉèÖò¥·ÅÆ÷¿ížßintInitPlayer(int nWinW, int nWinH);//³õÊŒ»¯ÎÆÀí£¬ÉèÖÃÎÆÀí¿ížßintInitTexture(int nFrameW, int nFrameH);intInputFrame(unsigned char *pY, unsigned long Ylinesize,unsigned char *pU, unsigned long Ulinesize,unsigned char *pV, unsigned long Vlinesize);private:static intThread2Refresh(void *opaque);private:SDL_Window*m_pPlayer;SDL_Rectm_rect; SDL_Renderer*m_pReader;SDL_Texture*m_pTexture;};
//SDLPlayer.cpp#include "SDLPlayer.h"CSDLPlayer::CSDLPlayer(){m_pPlayer = NULL;m_pReader = NULL;m_pTexture = NULL;}CSDLPlayer::~CSDLPlayer(){}int CSDLPlayer::Thread2Refresh(void *opaque){ while(1){SDL_Event evt;evt.type = MSG_REFRESH_VIDEO;SDL_PushEvent(&evt);SDL_Delay(40);}return 0; } int CSDLPlayer::InitPlayer(int nWinW, int nWinH){if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { return -1; } m_pPlayer=SDL_CreateWindow("Hello SDL",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,nWinW,nWinH,SDL_WINDOW_RESIZABLE|SDL_WINDOW_OPENGL);SDL_Thread *refresh_thread = SDL_CreateThread(Thread2Refresh,NULL,NULL);return 0;}int CSDLPlayer::InitTexture(int nFrameW, int nFrameH){if(m_pPlayer==NULL)return 0;m_pReader = SDL_CreateRenderer(m_pPlayer,-1,0);m_pTexture = SDL_CreateTexture(m_pReader,SDL_PIXELFORMAT_IYUV,SDL_TEXTUREACCESS_STREAMING,nFrameW,nFrameH);m_rect.x = 0;m_rect.y = 0;m_rect.w = nFrameW;m_rect.h = nFrameH;return 0;}intCSDLPlayer::InputFrame(unsigned char *pY, unsigned long Ylinesize, unsigned char *pU, unsigned long Ulinesize, unsigned char *pV, unsigned long Vlinesize){if(m_pPlayer==NULL || m_pReader==NULL || m_pTexture==NULL)return -1;//ʵÏÖÏûÏ¢£¬ÊÇΪÁË¿ØÖƲ¥·ÅËÙ¶ÈÒÑŸ±ÜÃ⎰¿Ú³öÏÖÎŽÏìӊ׎̬SDL_Event evt;SDL_WaitEvent(&evt);//SDL_Log("#####EVENT evt.type=0x%d\n",evt.type);if(evt.type == SDL_WINDOWEVENT){SDL_Log("WINDOWEVENT evt.type=0x%x,evt.window.event=0x%d\n",evt.type,evt.window.event);if(evt.window.event==SDL_WINDOWEVENT_CLOSE){SDL_Window *pWindow=SDL_GetWindowFromID(evt.window.windowID);if(pWindow == m_pPlayer){SDL_DestroyWindow(pWindow);m_pPlayer = NULL;}}}if(evt.type!=MSG_REFRESH_VIDEO)return -1;SDL_Rect sdlRect; sdlRect.x = 0; sdlRect.y = 0; SDL_GetWindowSize(m_pPlayer,&sdlRect.w,&sdlRect.h);//SDL_UpdateTexture(m_pTexture,&m_rect,pYUVData,linesize);//¿ÉÒÔŽŠÀíÄÇЩyuvÄÚŽæÊýŸÝ²»Á¬ÐøµÄÇé¿öSDL_UpdateYUVTexture(m_pTexture,&m_rect,pY,Ylinesize,pU,Ulinesize,pV,Vlinesize);SDL_RenderClear( m_pReader ); SDL_RenderCopy( m_pReader, m_pTexture, &m_rect, &sdlRect); SDL_RenderPresent( m_pReader ); SDL_Delay(10);return 0;}
下面是调用的主函数
//FFmpegSDL.cpp#include "FFDecoder.h"#include "SDLPlayer.h"int main(int argc, char* argv[]){CFFDecoder dec;CSDLPlayer player[2];dec.OpenFile("/home/xy/Videos/Wild.mp4");int nFrameW=0,nFrameH=0;dec.GetMediaInfo(nFrameW,nFrameH);player[0].InitPlayer(800,600);player[0].InitTexture(nFrameW,nFrameH);player[1].InitPlayer(800,600);player[1].InitTexture(nFrameW,nFrameH);AVFrame *pFrame=av_frame_alloc(); while(1){if(dec.GetOneFrame(pFrame)>0){player[0].InputFrame(pFrame->data[0],pFrame->linesize[0],pFrame->data[1],pFrame->linesize[1],pFrame->data[2],pFrame->linesize[2]);player[1].InputFrame(pFrame->data[0],pFrame->linesize[0],pFrame->data[1],pFrame->linesize[1],pFrame->data[2],pFrame->linesize[2]);}}return 0;}
接下来是主菜,makefile
srcdir = .CC = g++EXE= CFLAGS = -I/home/xy/soft/ffout/include -D_REENTRANT -I/usr/local/include/SDL2 -DHAVE_OPENGLLIBS= -L/home/xy/soft/ffout/lib -lpthread -lavutil -lavformat -lavcodec -lswscale -lm -lz \-lSDL2_test -Wl,-rpath,/usr/local/lib -L/usr/local/lib -lSDL2TARGETS = FFmpegSDLall: $(TARGETS)FFmpegSDL$(EXE): $(srcdir)/FFDecoder.cpp $(srcdir)/FFDecoder.h $(srcdir)/SDLPlayer.cpp $(srcdir)/SDLPlayer.h $(srcdir)/FFmpegSDL.cpp$(CC) $^ -o $(TARGETS) $(CFLAGS) $(LIBS)clean:rm -f $(TARGETS)
工作到此为止,收获的时间到了,cd到这些源代码所在的目录,make一下,
执行,看效果如何:
0 0
- FFmpeg与SDL双剑合璧之ubuntu
- FFmpeg与SDL双剑合璧之Windows
- FFmpeg与SDL双剑合璧之MFC
- JUnit4 与 JMock 之双剑合璧
- JUnit4 与 JMock 之双剑合璧
- JUnit4 与 JMock 之双剑合璧
- JUnit4 与 JMock 之双剑合璧
- JUnit4 与 JMock 之双剑合璧-4
- ubuntu 搭建 sdl+ffmpeg
- ”NSA武器库-永恒之蓝“与“Wannacry蠕虫勒索软件”的双剑合璧
- 马克飞象与印象笔记的双剑合璧
- 双剑合璧 面试无敌
- 双剑合璧 面试无敌
- MarkDown、Vim双剑合璧
- Ubuntu环境下安装FFMPEG+SDL
- ubuntu ffmpeg+sdl编译安装过程记录
- Ubuntu下编译ffmpeg、SDL、SDL_net库
- IOS 项目加入SDL库 --- FFMPEG+SDL学习 之 二
- 欢迎使用CSDN-markdown编辑器
- 「图论」最短路径长度-Dijkstra
- 利用devstack,在openstack-ceilometer 环境下配置监控项
- 部门下拉框的树状结构展示小功能的实现
- 数一数你连听都没听过的古典小说有多少?
- FFmpeg与SDL双剑合璧之ubuntu
- IIS配置问题
- Spring-简要了解
- 小猪CMS修改登录入口和退出修改
- 2015.9.17总结
- 第四十一天 Path(画路径)、Bitmap、Slider(手机联系人首字母选项)
- UVALive 3177 Beijing Guards
- boostrap框架下的导航栏切换
- 获取某目录下的所有java源码文件名