SDL2庫(1)-移植Android 端 CMakeList 集成

SDL.png

項(xiàng)目位置 https://github.com/deepsadness/SDLCmakeDemo

系列內(nèi)容導(dǎo)讀

  1. SDL2-移植Android Studio+CMakeList集成
  2. Android端FFmpeg +SDL2的簡單播放器
  3. SDL2 Android端的簡要分析(VideoSubSystem)
  4. SDL2 Android端的簡要分析(AudioSubSystem)

簡單的集成

1. 獲取源代碼

SDL的源代碼獲取十分簡單。訪問SDL的官方網(wǎng)站(http://www.libsdl.org/),單擊左側(cè)的“Download”進(jìn)入下載頁面,然后下載“SourceCode”欄目下的文件就可以了。
注意:這里使用的是 SDL2-2.0.9

解壓完后的文件目錄.png

我們在根目錄里面有看到,SDL2的源碼,已經(jīng)為我們配置好了多種的編譯環(huán)境。包括Cmake 和Android.mk文件。這樣的話,我們直接使用它自帶的編譯環(huán)境就好了。

2. 創(chuàng)建自己的工程

復(fù)制文件

  • 復(fù)制源碼文件到lib下面


    將整個源碼目錄復(fù)制到lib下面.png
  • 復(fù)制Android部分的文件,到src 下


    復(fù)制Android部分源碼.png
  1. 把整個包復(fù)制過來。因?yàn)橛蠮NI方法,所以包名暫時不能改。
  2. 注意Manifest內(nèi)的內(nèi)容也要對應(yīng)復(fù)制過來

配置CmakeList.txt文件

通過add_subdirectory,直接使用SDL內(nèi)配置好的Cmake。直接將整個庫集成進(jìn)來

#直接添加SDL庫
include_directories(${CMAKE_SOURCE_DIR}/libs/SDL2/include)
add_subdirectory(${CMAKE_SOURCE_DIR}/libs/SDL2)

Ps:這里它的CMakeList.txt文件中富含大量邏輯是學(xué)習(xí)好資料。。但是這里因?yàn)檫叿?,就不做分析了?/p>

發(fā)生錯誤
錯誤1: 找不到 SDL_config.h
錯誤1:找不到 SDL_config.h.png

在上面,我們已經(jīng)添加了include_directories,但是,還提示找不到頭文件。
我們來到提示的SDL_config.h看到。

#ifdef USING_GENERATED_CONFIG_H
#error Wrong SDL_config.h, check your include path?
#endif
Solution

由于是定義來這個宏,導(dǎo)致錯誤,所以我們移除這個宏。
在SDL2源碼目錄下的CMakeLists.txt中,找到USING_GENERATED_CONFIG_H, 并且修改成如下

# 把原來的注釋掉
# add_definitions(-DUSING_GENERATED_CONFIG_H)
# 添加移除掉這個宏
remove_definitions(-DUSING_GENERATED_CONFIG_H)
錯誤2: undefined reference to 'SDL_HIDAPI_JoystickDriver'
  1. 全局搜索
    SDL_joystick.c中發(fā)現(xiàn)發(fā)現(xiàn)SDL_HIDAPI_JoystickDriver是因?yàn)槎x宏SDL_JOYSTICK_HIDAPI才會被初始化的。
    同時這個SDL_JOYSTICK_HIDAPI是直接在SDL_config_android.h中直接寫死的。
    編譯Android的時候,一定會有。。。。
image.png
  1. 源碼沒有加入編譯
    我們通過觀察目錄發(fā)現(xiàn)這個時候。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.

這個對我們基本上用不到。所以其實(shí)去掉也無所謂。

  1. 直接在SDL_config_android.h文件中把它注釋掉
  2. 然后對應(yīng)的,把對應(yīng)Java代碼的初始化注釋掉。


    對應(yīng)的代碼注釋掉.png

這樣就可以了。

  • 方案2:將hidapi也添加入編譯中
  1. 找到對應(yīng)的目錄,添加CMakeList.txt
添加自己的CMakeList.png

我們看到這兒本來是有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})
  1. SDL2根目錄下的CMakeList.txt進(jìn)行修改
SDL2根目錄下的CMakeList.png

找到SDL_SHARED庫定義的地方


SDL_SHARED庫編譯定義的位置.png

修改成如下
如注釋中所見,添加了 判斷,如果是Android的話,就添加hidapi庫,并將其連接到SDL2庫中。

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 ()

同時注釋掉,CMakeList.txt中我們不需要的靜態(tài)庫和INSTALL的部分。如圖所示的,剩下的文件部分全部注釋掉。


從SDL static文件開始,全部注釋掉.png

注釋掉的原因:
一方面我們不需要它。我們只需要SHARED庫就可以了。
另一方面,留著在INSTALL時會報錯,簡單起見,注釋掉就可以。

配置自己的源文件

我們可以看到有android_project項(xiàng)目。
我們切換到目錄下,具體看一下


屏幕快照 2018-11-13 上午9.39.57.png

來看看這里的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)

從這兒我們可以看到,

  1. 源碼的include在外面的目錄下面
  2. 需要添加的連接庫包括 GLES_v1 和GLESv2
  3. 需要自己添加自己的源文件目錄

好。直接修改成CMakeList.txt就可以了。
注意。這里改的是我們自己工程APP下的CMakeList.txt

APP下的CMakeList.png

添加如下內(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})

簡單明了。

3. 編寫自己的native-lib.cpp

簡單的顯示一個圖片地址.下載后,放到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)建窗口的時候,大小都是0
    window = SDL_CreateWindow("SDL_Window", SDL_WINDOWPOS_CENTERED,
                              SDL_WINDOWPOS_CENTERED, 0, 0, SDL_WINDOW_SHOWN);
    //創(chuàng)建Renderer -1 表示使用默認(rèn)的窗口 后面一個是Renderer的方式,0的話,應(yīng)該就是未指定把???
    renderer = SDL_CreateRenderer(window, -1, 0);

    //因?yàn)橹皇呛唵握故疽粋€圖片,所以就創(chuàng)建一個Surface
    SDL_Surface *bmp = SDL_LoadBMP("image.bmp");

    //設(shè)置圖中的透明色。
    SDL_SetColorKey(bmp, SDL_TRUE, 0xffffff);

    //創(chuàng)建一個texture
    SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, bmp);
    //清楚所有的事件?
    SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);

    //進(jìn)入主循環(huán),就是不斷的刷新。這個應(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 后面兩個矩陣,可以分配這個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é)果

運(yùn)行結(jié)果.png

缺陷

  1. 缺陷就是SDLActivity 這些都已經(jīng)寫死了。其實(shí)我們需要的只是一個SDLSurface就可以展示我們想要的。
    沒事。這個是后話。后面接著分析。

參考

FFmpeg編程開發(fā)筆記 —— Android 移植 FFmpeg + SDL2.0 庫

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容