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
原创粉丝点击