您的位置:首页 > 其它

FFmpeg与SDL双剑合璧之ubuntu

2015-09-17 16:50 246 查看
以前所做的工作,大多是把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();

int					OpenFile(const char *pFilePath);

int					GetMediaInfo(int &nFrameW,int &nFrameH);

int					GetOneFrame(AVFrame *pFrame);

private:

AVFormatContext		*m_pFormatCxt;

AVCodecContext		*m_pCodecCtx;

AVCodec			*m_pCodec;

AVPacket		m_Packet;

int			m_nVideoIndex;

int			m_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 once

extern "C" {

#include "SDL.h"

}

#define		MSG_REFRESH_VIDEO		(SDL_USEREVENT+10)

class CSDLPlayer

{

public:

CSDLPlayer();

virtual ~CSDLPlayer();

//³õÊŒ»¯²¥·ÅÆ÷£¬ÉèÖò¥·ÅÆ÷¿ížß

int				InitPlayer(int nWinW, int nWinH);

//³õÊŒ»¯ÎÆÀí£¬ÉèÖÃÎÆÀí¿ížß

int				InitTexture(int nFrameW, int nFrameH);

int				InputFrame(unsigned char *pY, unsigned long Ylinesize,

unsigned char *pU, unsigned long Ulinesize,

unsigned char *pV, unsigned long Vlinesize);

private:

static int			Thread2Refresh(void *opaque);

private:

SDL_Window		*m_pPlayer;

SDL_Rect		m_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;

}

int	CSDLPlayer::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_OPENGL
LIBS	=  -L/home/xy/soft/ffout/lib -lpthread  -lavutil -lavformat -lavcodec -lswscale -lm -lz \
-lSDL2_test -Wl,-rpath,/usr/local/lib -L/usr/local/lib -lSDL2

TARGETS = FFmpegSDL

all: $(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一下,



执行,看效果如何:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: