FFmpeg与SDL双剑合璧之ubuntu
SDL
Simple Directmedia Layer
项目地址:https://gitcode.com/gh_mirrors/sd/SDL
免费下载资源
·
以前所做的工作,大多是把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一下,
执行,看效果如何:
GitHub 加速计划 / sd / SDL
8.9 K
1.68 K
下载
Simple Directmedia Layer
最近提交(Master分支:2 个月前 )
a57c5669 - 2 个月前
20a6193e - 2 个月前
更多推荐
已为社区贡献4条内容
所有评论(0)