替换成sdl2

This commit is contained in:
xiongziliang 2018-04-17 21:38:13 +08:00
parent 6a9bc8aca5
commit bd04b2e2ab
4 changed files with 219 additions and 101 deletions

15
cmake/FindSDL2.cmake Normal file
View File

@ -0,0 +1,15 @@
find_path(SDL2_INCLUDE_DIR
NAMES SDL2/SDL.h
HINTS SDL2
PATHS $ENV{HOME}/sdl2/include)
find_library(SDL2_LIBRARY
NAMES SDL2
PATHS $ENV{HOME}/sdl2/lib/x86)
set(SDL2_LIBRARIES ${SDL2_LIBRARY})
set(SDL2_INCLUDE_DIRS ${SDL2_INCLUDE_DIR})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SDL2 DEFAULT_MSG SDL2_LIBRARY SDL2_INCLUDE_DIR)

View File

@ -1,10 +1,10 @@
#SDL #SDL2
find_package(SDL QUIET) find_package(SDL2 QUIET)
if(SDL_FOUND) if (SDL2_FOUND)
include_directories(${SDL_INCLUDE_DIR}) include_directories(${SDL2_INCLUDE_DIR})
list(APPEND LINK_LIB_LIST ${SDL_LIBRARY}) list(APPEND LINK_LIB_LIST ${SDL2_LIBRARY})
message(STATUS " found SDL") message(STATUS "found SDL2:${SDL2_INCLUDE_DIR},${SDL2_LIBRARY}")
endif() endif (SDL2_FOUND)
#ffmpeg/libutil #ffmpeg/libutil
find_package(AVUTIL QUIET) find_package(AVUTIL QUIET)
@ -24,10 +24,10 @@ endif()
aux_source_directory(. TEST_SRC_LIST) aux_source_directory(. TEST_SRC_LIST)
#ffmpeg/libavcodec ffmpeg/libavcodec SDL test_player #ffmpeg/libavcodec ffmpeg/libavcodec SDL test_player
if(SDL_FOUND AND AVCODEC_FOUND AND AVUTIL_FOUND) if(SDL2_FOUND AND AVCODEC_FOUND AND AVUTIL_FOUND)
message(STATUS "test_player will be compiled") message(STATUS "test_player will be compiled")
else() else()
message(STATUS "test_player ingored, please install sdl ffmpeg/libavcodec ffmpeg/libavcodec") message(STATUS "test_player ingored, please install sdl2 ffmpeg/libavcodec ffmpeg/libavutil")
list(REMOVE_ITEM TEST_SRC_LIST ./test_player.cpp) list(REMOVE_ITEM TEST_SRC_LIST ./test_player.cpp)
endif() endif()
@ -50,4 +50,3 @@ endforeach()

View File

@ -1,9 +1,7 @@
/* /*
* MIT License * MIT License
* *
* Copyright (c) 2016 xiongziliang <771730766@qq.com> * Copyright (c) 2017 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -23,7 +21,6 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
#ifndef YUVDISPLAYER_H_ #ifndef YUVDISPLAYER_H_
#define YUVDISPLAYER_H_ #define YUVDISPLAYER_H_
#include <stdexcept> #include <stdexcept>
@ -31,68 +28,176 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include <SDL/SDL.h> #include "SDL2/SDL.h"
#include <libavcodec/avcodec.h> #include "libavcodec/avcodec.h"
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
namespace ZL { #if defined(_WIN32)
namespace Screen { #pragma comment(lib,"SDL2.lib")
#endif //defined(_WIN32)
using namespace ZL::Util;
#define REFRESH_EVENT (SDL_USEREVENT + 1)
class SDLDisplayerHelper
{
public:
static SDLDisplayerHelper &Instance(){
static SDLDisplayerHelper *instance(new SDLDisplayerHelper);
return *instance;
}
static void Destory(){
delete &Instance();
}
template<typename FUN>
void doTask(FUN &&f){
{
lock_guard<mutex> lck(_mtxTask);
_taskList.emplace_back(f);
}
SDL_Event event;
event.type = REFRESH_EVENT;
SDL_PushEvent(&event);
}
private:
SDLDisplayerHelper(){
_loopThread.reset(new std::thread(&SDLDisplayerHelper::runLoop,this));
};
~SDLDisplayerHelper(){
doTask([](){return false;});
_loopThread->join();
_loopThread.reset();
};
void runLoop(){
bool flag = true;
std::function<bool ()> task;
SDL_Event event;
while(flag){
SDL_WaitEvent(&event);
if (event.type == REFRESH_EVENT)
{
{
lock_guard<mutex> lck(_mtxTask);
if(_taskList.empty()){
//not reachable
continue;
}
task = _taskList.front();
_taskList.pop_front();
}
flag = task();
}
}
}
std::deque<std::function<bool ()> > _taskList;
std::shared_ptr<thread> _loopThread;
std::mutex _mtxTask;
};
class YuvDisplayer { class YuvDisplayer {
public: public:
YuvDisplayer(){ YuvDisplayer(void *hwnd = nullptr,const char *title = "untitled"){
static onceToken token([]() { static onceToken token([]() {
if(SDL_Init(SDL_INIT_EVERYTHING) == -1) { if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) == -1) {
throw std::runtime_error("初始化SDL失败"); string err = "初始化SDL失败:";
err+= SDL_GetError();
ErrorL << err;
throw std::runtime_error(err);
} }
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_CRITICAL);
SDL_LogSetOutputFunction([](void *userdata, int category, SDL_LogPriority priority, const char *message){
DebugL << category << " " << priority << message;
},nullptr);
InfoL << "SDL_Init";
}, []() { }, []() {
SDLDisplayerHelper::Destory();
SDL_Quit(); SDL_Quit();
InfoL << "SDL_Quit";
}); });
_title = title;
_hwnd = hwnd;
} }
virtual ~YuvDisplayer(){ virtual ~YuvDisplayer(){
if(m_pOverlay){ if (_texture) {
SDL_FreeYUVOverlay(m_pOverlay); SDL_DestroyTexture(_texture);
_texture = nullptr;
}
if (_render) {
SDL_DestroyRenderer(_render);
_render = nullptr;
}
if (_win) {
SDL_DestroyWindow(_win);
_win = nullptr;
} }
} }
bool displayYUV(AVFrame *pFrame){ bool displayYUV(AVFrame *pFrame){
if (!m_pScreen) { if (!_win) {
/* Set up the screen */ if (_hwnd) {
m_pScreen = SDL_SetVideoMode(1366, 768, 16, SDL_SWSURFACE); _win = SDL_CreateWindowFrom(_hwnd);
}else {
_win = SDL_CreateWindow(_title.data(),
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
pFrame->width,
pFrame->height,
SDL_WINDOW_OPENGL);
} }
if (!m_pOverlay && m_pScreen) {
/* Create a YUV overlay */
m_pOverlay = SDL_CreateYUVOverlay(pFrame->width, pFrame->height, SDL_YV12_OVERLAY, m_pScreen);
/* Set the window caption */
SDL_WM_SetCaption("YUV Window", NULL);
} }
if (m_pOverlay) { if (_win && ! _render){
/* Apply the image to the screen */ #if 0
m_pOverlay->pixels[0] = pFrame->data[0]; SDL_RENDERER_SOFTWARE = 0x00000001, /**< The renderer is a software fallback */
m_pOverlay->pixels[2] = pFrame->data[1]; SDL_RENDERER_ACCELERATED = 0x00000002, /**< The renderer uses hardware
m_pOverlay->pixels[1] = pFrame->data[2]; acceleration */
SDL_RENDERER_PRESENTVSYNC = 0x00000004, /**< Present is synchronized
with the refresh rate */
SDL_RENDERER_TARGETTEXTURE = 0x00000008 /**< The renderer supports
rendering to texture */
#endif
#if defined(__linux__)
_render = SDL_CreateRenderer(_win, -1, SDL_RENDERER_SOFTWARE);
#else
_render = SDL_CreateRenderer(_win, -1, SDL_RENDERER_ACCELERATED);
#endif
}
if (_render && !_texture) {
_texture = SDL_CreateTexture(_render, SDL_PIXELFORMAT_IYUV,
SDL_TEXTUREACCESS_STREAMING,
pFrame->width,
pFrame->height);
}
if (_texture) {
SDL_UpdateYUVTexture(_texture, nullptr,
pFrame->data[0], pFrame->linesize[0],
pFrame->data[1], pFrame->linesize[1],
pFrame->data[2], pFrame->linesize[2]);
m_pOverlay->pitches[0] = pFrame->linesize[0]; //SDL_UpdateTexture(_texture, nullptr, pFrame->data[0], pFrame->linesize[0]);
m_pOverlay->pitches[2] = pFrame->linesize[1]; SDL_RenderClear(_render);
m_pOverlay->pitches[1] = pFrame->linesize[2]; SDL_RenderCopy(_render, _texture, nullptr, nullptr);
SDL_RenderPresent(_render);
/* Update the screen */
SDL_Rect rect = { 0 ,0 ,1366,768};
SDL_LockYUVOverlay(m_pOverlay);
SDL_DisplayYUVOverlay(m_pOverlay, &rect);
SDL_UnlockYUVOverlay(m_pOverlay);
return true; return true;
} }
return false; return false;
} }
private: private:
SDL_Surface* m_pScreen = nullptr; string _title;
SDL_Overlay* m_pOverlay = nullptr; SDL_Window *_win = nullptr;
SDL_Renderer *_render = nullptr;
SDL_Texture *_texture = nullptr;
void *_hwnd = nullptr;
}; };
} /* namespace Screen */
} /* namespace ZL */
#endif /* YUVDISPLAYER_H_ */ #endif /* YUVDISPLAYER_H_ */

View File

@ -36,7 +36,6 @@
#include "Network/sockutil.h" #include "Network/sockutil.h"
using namespace std; using namespace std;
using namespace ZL::Screen;
using namespace ZL::Codec; using namespace ZL::Codec;
using namespace ZL::Util; using namespace ZL::Util;
using namespace ZL::Thread; using namespace ZL::Thread;
@ -72,15 +71,15 @@ int main(int argc, char *argv[]){
H264Decoder decoder; H264Decoder decoder;
YuvDisplayer displayer; YuvDisplayer displayer;
ThreadPool pool(1);
player->setOnVideoCB([&](const H264Frame &frame) { player->setOnVideoCB([&](const H264Frame &frame) {
pool.async([&,frame]() { SDLDisplayerHelper::Instance().doTask([&, frame]() {
AVFrame *pFrame = nullptr; AVFrame *pFrame = nullptr;
bool flag = decoder.inputVideo((unsigned char *) frame.data.data(), frame.data.size(), frame.timeStamp, &pFrame); bool flag = decoder.inputVideo((unsigned char *) frame.data.data(), frame.data.size(), frame.timeStamp, &pFrame);
if (flag) { if (flag) {
//DebugL << pFrame->pkt_pts; //DebugL << pFrame->pkt_pts;
displayer.displayYUV(pFrame); displayer.displayYUV(pFrame);
} }
return true;
}); });
}); });