項(xiàng)目位置 https://github.com/deepsadness/SDLCmakeDemo
系列內(nèi)容導(dǎo)讀
- SDL2-移植Android Studio+CMakeList集成
- Android端FFmpeg +SDL2的簡(jiǎn)單播放器
- SDL2 Android端的簡(jiǎn)要分析(VideoSubSystem)
- SDL2 Android端的簡(jiǎn)要分析(AudioSubSystem)
簡(jiǎn)單的集成
1. 獲取源代碼
SDL的源代碼獲取十分簡(jiǎn)單旧乞。訪問SDL的官方網(wǎng)站(http://www.libsdl.org/)要销,單擊左側(cè)的“Download”進(jìn)入下載頁(yè)面,然后下載“SourceCode”欄目下的文件就可以了。
注意:這里使用的是 SDL2-2.0.9
我們?cè)诟夸浝锩嬗锌吹缴置琒DL2的源碼,已經(jīng)為我們配置好了多種的編譯環(huán)境泥张。包括Cmake 和Android.mk文件莹痢。這樣的話种蘸,我們直接使用它自帶的編譯環(huán)境就好了墓赴。
2. 創(chuàng)建自己的工程
復(fù)制文件
-
復(fù)制源碼文件到lib下面
將整個(gè)源碼目錄復(fù)制到lib下面.png -
復(fù)制Android部分的文件,到src 下
復(fù)制Android部分源碼.png
- 把整個(gè)包復(fù)制過來航瞭。因?yàn)橛蠮NI方法诫硕,所以包名暫時(shí)不能改。
- 注意Manifest內(nèi)的內(nèi)容也要對(duì)應(yīng)復(fù)制過來
配置CmakeList.txt
文件
通過add_subdirectory
,直接使用SDL內(nèi)配置好的Cmake
刊侯。直接將整個(gè)庫(kù)集成進(jìn)來
#直接添加SDL庫(kù)
include_directories(${CMAKE_SOURCE_DIR}/libs/SDL2/include)
add_subdirectory(${CMAKE_SOURCE_DIR}/libs/SDL2)
Ps:這里它的CMakeList.txt文件中富含大量邏輯是學(xué)習(xí)好資料章办。。但是這里因?yàn)檫叿虮醭梗筒蛔龇治隽恕?/p>
發(fā)生錯(cuò)誤
錯(cuò)誤1: 找不到 SDL_config.h
在上面藕届,我們已經(jīng)添加了include_directories
,但是,還提示找不到頭文件亭饵。
我們來到提示的SDL_config.h看到休偶。
#ifdef USING_GENERATED_CONFIG_H
#error Wrong SDL_config.h, check your include path?
#endif
Solution
由于是定義來這個(gè)宏,導(dǎo)致錯(cuò)誤辜羊,所以我們移除這個(gè)宏踏兜。
在SDL2源碼目錄下的CMakeLists.txt
中,找到USING_GENERATED_CONFIG_H
, 并且修改成如下
# 把原來的注釋掉
# add_definitions(-DUSING_GENERATED_CONFIG_H)
# 添加移除掉這個(gè)宏
remove_definitions(-DUSING_GENERATED_CONFIG_H)
錯(cuò)誤2: undefined reference to 'SDL_HIDAPI_JoystickDriver'
- 全局搜索
SDL_joystick.c
中發(fā)現(xiàn)發(fā)現(xiàn)SDL_HIDAPI_JoystickDriver
是因?yàn)槎x宏SDL_JOYSTICK_HIDAPI
才會(huì)被初始化的只冻。
同時(shí)這個(gè)SDL_JOYSTICK_HIDAPI
是直接在SDL_config_android.h
中直接寫死的庇麦。
編譯Android的時(shí)候计技,一定會(huì)有喜德。。垮媒。舍悯。
-
源碼沒有加入編譯
我們通過觀察目錄發(fā)現(xiàn)這個(gè)時(shí)候。hidapi并沒有加入編譯
hidapi目錄沒有變色睡雇,說明沒有加入編譯.png
Solution
兩種方案萌衬。
-
方案1:直接去掉SDL_JOYSTICK_HIDAPI宏
通過了解,我們知道
Within the latest SDL2 development code, HIDAPI joystick drivers have been added to this library for providing more consistent support for the Xbox, PlayStation 4, and Nintendo Switch Pro controllers. HIDAPI is a multi-platform library for HID devices on Windows/Linux/macOS and now this unified code is used across platforms.
這個(gè)對(duì)我們基本上用不到它抱。所以其實(shí)去掉也無所謂秕豫。
- 直接在
SDL_config_android.h
文件中把它注釋掉 -
然后對(duì)應(yīng)的,把對(duì)應(yīng)Java代碼的初始化注釋掉观蓄。
對(duì)應(yīng)的代碼注釋掉.png
這樣就可以了混移。
- 方案2:將hidapi也添加入編譯中
- 找到對(duì)應(yīng)的目錄,添加
CMakeList.txt
我們看到這兒本來是有Android.mk文件的侮穿。
換的CMakeList如下:
cmake_minimum_required(VERSION 2.8.11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Werror")
include_directories(${CMAKE_SOURCE_DIR}/../hidapi/hidapi/hidapi.h)
add_library(hidapi SHARED hid.cpp)
find_library(ANDROID_LOG_LIBRARY log)
target_link_libraries(hidapi ${ANDROID_LOG_LIBRARY})
- 在SDL2根目錄下的
CMakeList.txt
進(jìn)行修改
找到SDL_SHARED庫(kù)定義的地方
修改成如下
如注釋中所見歌径,添加了 判斷,如果是Android的話亲茅,就添加hidapi
庫(kù)回铛,并將其連接到SDL2庫(kù)中狗准。
if (SDL_SHARED)
#自己添加的hidapi
if(ANDROID)
![屏幕快照 2018-11-14 上午1.14.37.png](https://upload-images.jianshu.io/upload_images/1877190-17f1fcabb9472722.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
# 將hidapi 加入源碼目錄。進(jìn)行編譯
file(GLOB HIDAPI_SOURCE ${CMAKE_SOURCE_DIR}/libs/SDL2/src/joystick/hidapi/*.c)
set(SOURCE_FILES "${SOURCE_FILES};${HIDAPI_SOURCE}")
# 將前面定義茵肃,作為子模塊腔长,進(jìn)行編譯
add_subdirectory(${SDL2_SOURCE_DIR}/src/hidapi/android)
endif ()
add_library(SDL2 SHARED ${SOURCE_FILES} ${VERSION_SOURCES})
if (APPLE)
set_target_properties(SDL2 PROPERTIES
MACOSX_RPATH 1
OUTPUT_NAME "SDL2-${LT_RELEASE}")
elseif (UNIX AND NOT ANDROID)
set_target_properties(SDL2 PROPERTIES
VERSION ${LT_VERSION}
SOVERSION ${LT_REVISION}
OUTPUT_NAME "SDL2-${LT_RELEASE}")
else ()
set_target_properties(SDL2 PROPERTIES
VERSION ${SDL_VERSION}
SOVERSION ${LT_REVISION}
OUTPUT_NAME "SDL2")
endif ()
if (MSVC AND NOT LIBC)
# Don't try to link with the default set of libraries.
set_target_properties(SDL2 PROPERTIES LINK_FLAGS_RELEASE "/NODEFAULTLIB")
set_target_properties(SDL2 PROPERTIES LINK_FLAGS_DEBUG "/NODEFAULTLIB")
set_target_properties(SDL2 PROPERTIES STATIC_LIBRARY_FLAGS "/NODEFAULTLIB")
endif ()
set(_INSTALL_LIBS "SDL2" ${_INSTALL_LIBS})
#自己添加的hidapi ,把它添加到里面編譯
if(ANDROID)
target_link_libraries(SDL2 ${EXTRA_LIBS} ${EXTRA_LDFLAGS} hidapi)
else ()
target_link_libraries(SDL2 ${EXTRA_LIBS} ${EXTRA_LDFLAGS})
endif ()
target_include_directories(SDL2 PUBLIC "$<BUILD_INTERFACE:${SDL2_SOURCE_DIR}/include>" $<INSTALL_INTERFACE:include/SDL2>)
if (NOT ANDROID)
set_target_properties(SDL2 PROPERTIES DEBUG_POSTFIX ${SDL_CMAKE_DEBUG_POSTFIX})
endif ()
endif ()
同時(shí)注釋掉免姿,CMakeList.txt中我們不需要的靜態(tài)庫(kù)和INSTALL的部分饼酿。如圖所示的,剩下的文件部分全部注釋掉胚膊。
注釋掉的原因:
一方面我們不需要它。我們只需要SHARED庫(kù)就可以了紊婉。
另一方面药版,留著在INSTALL時(shí)會(huì)報(bào)錯(cuò),簡(jiǎn)單起見喻犁,注釋掉就可以槽片。
配置自己的源文件
我們可以看到有android_project項(xiàng)目。
我們切換到目錄下肢础,具體看一下
來看看這里的Android.mk文件是怎么寫的
先看Application.mk
這里是能夠編譯各種版本
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
支持的Api 版本是14
# Min runtime API level
APP_PLATFORM=android-14
看一下src/Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := main
SDL_PATH := ../SDL
LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include
# Add your application source files here...
LOCAL_SRC_FILES := YourSourceHere.c
LOCAL_SHARED_LIBRARIES := SDL2
LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog
include $(BUILD_SHARED_LIBRARY)
從這兒我們可以看到还栓,
- 源碼的include在外面的目錄下面
- 需要添加的連接庫(kù)包括 GLES_v1 和GLESv2
- 需要自己添加自己的源文件目錄
好。直接修改成CMakeList.txt
就可以了传轰。
注意剩盒。這里改的是我們自己工程APP下的CMakeList.txt
添加如下內(nèi)容
add_library(
#他原來的名字,就是叫main 保持一致
main
SHARED
src/main/cpp/native-lib.cpp)
find_library(
log-lib
log)
target_link_libraries(
main
SDL2
GLESv1_CM
GLESv2
ffmpeg
${log-lib})
簡(jiǎn)單明了慨蛙。
3. 編寫自己的native-lib.cpp
簡(jiǎn)單的顯示一個(gè)圖片地址.下載后辽聊,放到Asset文件夾中。
//把顯示圖片的原來的main方法給注釋掉了
extern "C"
//這里是直接定義了SDL的main方法嗎
int main(int argc, char *argv[]) {
// 打印ffmpeg信息
const char *str = avcodec_configuration();
ALOGI("avcodec_configuration: %s", str);
char *video_path = argv[1];
ALOGI("video_path : %s", video_path);
//開始準(zhǔn)備sdl的部分
//SDL 要素 window render texture
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Event event;
//初始化SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
ALOGE("Could not initialize SDL - %s", SDL_GetError());
return 1;
}
//創(chuàng)建窗口 位置是中間期贫。大小是0 跟匆,SDL創(chuàng)建窗口的時(shí)候,大小都是0
window = SDL_CreateWindow("SDL_Window", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, 0, 0, SDL_WINDOW_SHOWN);
//創(chuàng)建Renderer -1 表示使用默認(rèn)的窗口 后面一個(gè)是Renderer的方式通砍,0的話玛臂,應(yīng)該就是未指定把?封孙?迹冤?
renderer = SDL_CreateRenderer(window, -1, 0);
//因?yàn)橹皇呛?jiǎn)單展示一個(gè)圖片,所以就創(chuàng)建一個(gè)Surface
SDL_Surface *bmp = SDL_LoadBMP("image.bmp");
//設(shè)置圖中的透明色敛瓷。
SDL_SetColorKey(bmp, SDL_TRUE, 0xffffff);
//創(chuàng)建一個(gè)texture
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, bmp);
//清楚所有的事件叁巨?
SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);
//進(jìn)入主循環(huán),就是不斷的刷新呐籽。這個(gè)應(yīng)該是根據(jù)屏幕刷新率去刷新嗎锋勺?
while (1) {
if (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
break;
}
}
//先填充窗口的顏色
SDL_SetRenderDrawColor(renderer, 0, 133, 119, 255);
SDL_RenderClear(renderer);
//RenderCopy RenderPresent 后面兩個(gè)矩陣蚀瘸,可以分配這個(gè)texture的大小
SDL_RenderCopy(renderer, texture, NULL, NULL);
//刷新屏幕
SDL_RenderPresent(renderer);
}
SDL_FreeSurface(bmp);
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
這樣就就可以運(yùn)行成功了!庶橱!
運(yùn)行結(jié)果
缺陷
- 缺陷就是SDLActivity 這些都已經(jīng)寫死了贮勃。其實(shí)我們需要的只是一個(gè)SDLSurface就可以展示我們想要的。
沒事苏章。這個(gè)是后話寂嘉。后面接著分析。