天天看點

SDL2庫(1)-移植Android 端 CMakeList 內建

SDL2庫(1)-移植Android 端 CMakeList 內建

SDL.png

項目位置 https://github.com/deepsadness/SDLCmakeDemo

簡單的內建

1. 擷取源代碼

SDL的源代碼擷取十分簡單。通路SDL的官方網站(http://www.libsdl.org/),單擊左側的“Download”進入下載下傳頁面,然後下載下傳“SourceCode”欄目下的檔案就可以了。

注意:這裡使用的是 SDL2-2.0.9

SDL2庫(1)-移植Android 端 CMakeList 內建

解壓完後的檔案目錄.png

我們在根目錄裡面有看到,SDL2的源碼,已經為我們配置好了多種的編譯環境。包括Cmake 和Android.mk檔案。這樣的話,我們直接使用它自帶的編譯環境就好了。

2. 建立自己的工程

複制檔案

  • 複制源碼檔案到lib下面
SDL2庫(1)-移植Android 端 CMakeList 內建

将整個源碼目錄複制到lib下面.png

  • 複制Android部分的檔案,到src 下
SDL2庫(1)-移植Android 端 CMakeList 內建

複制Android部分源碼.png

  1. 把整個包複制過來。因為有JNI方法,是以包名暫時不能改。
  2. 注意Manifest内的内容也要對應複制過來

配置

CmakeList.txt

檔案

通過

add_subdirectory

,直接使用SDL内配置好的

Cmake

。直接将整個庫內建進來

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

複制

Ps:這裡它的CMakeList.txt檔案中富含大量邏輯是學習好資料。。但是這裡因為邊幅原因,就不做分析了。
發生錯誤

錯誤1: 找不到 SDL_config.h

SDL2庫(1)-移植Android 端 CMakeList 內建

錯誤1:找不到 SDL_config.h.png

在上面,我們已經添加了

include_directories

,但是,還提示找不到頭檔案。

我們來到提示的SDL_config.h看到。

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

複制

Solution

由于是定義來這個宏,導緻錯誤,是以我們移除這個宏。

在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

    中發現發現

    SDL_HIDAPI_JoystickDriver

    是因為定義宏

    SDL_JOYSTICK_HIDAPI

    才會被初始化的。

    同時這個

    SDL_JOYSTICK_HIDAPI

    是直接在

    SDL_config_android.h

    中直接寫死的。

    編譯Android的時候,一定會有。。。。

SDL2庫(1)-移植Android 端 CMakeList 內建

image.png

  1. 源碼沒有加入編譯

    我們通過觀察目錄發現這個時候。hidapi并沒有加入編譯

SDL2庫(1)-移植Android 端 CMakeList 內建

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.

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

  1. 直接在

    SDL_config_android.h

    檔案中把它注釋掉
  2. 然後對應的,把對應Java代碼的初始化注釋掉。
SDL2庫(1)-移植Android 端 CMakeList 內建

對應的代碼注釋掉.png

這樣就可以了。

  • 方案2:将hidapi也添加入編譯中
  1. 找到對應的目錄,添加

    CMakeList.txt

SDL2庫(1)-移植Android 端 CMakeList 內建

添加自己的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

    進行修改
SDL2庫(1)-移植Android 端 CMakeList 內建

SDL2根目錄下的CMakeList.png

找到SDL_SHARED庫定義的地方

SDL2庫(1)-移植Android 端 CMakeList 內建

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 加入源碼目錄。進行編譯
        file(GLOB HIDAPI_SOURCE ${CMAKE_SOURCE_DIR}/libs/SDL2/src/joystick/hidapi/*.c)
        set(SOURCE_FILES "${SOURCE_FILES};${HIDAPI_SOURCE}")
        # 将前面定義,作為子子產品,進行編譯
        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中我們不需要的靜态庫和INSTALL的部分。如圖所示的,剩下的檔案部分全部注釋掉。

SDL2庫(1)-移植Android 端 CMakeList 內建

從SDL static檔案開始,全部注釋掉.png

注釋掉的原因:

一方面我們不需要它。我們隻需要SHARED庫就可以了。

另一方面,留着在INSTALL時會報錯,簡單起見,注釋掉就可以。

配置自己的源檔案

我們可以看到有android_project項目。

我們切換到目錄下,具體看一下

SDL2庫(1)-移植Android 端 CMakeList 內建

螢幕快照 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

SDL2庫(1)-移植Android 端 CMakeList 內建

APP下的CMakeList.png

添加如下内容

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

    //開始準備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;
    }

    //建立視窗  位置是中間。大小是0 ,SDL建立視窗的時候,大小都是0
    window = SDL_CreateWindow("SDL_Window", SDL_WINDOWPOS_CENTERED,
                              SDL_WINDOWPOS_CENTERED, 0, 0, SDL_WINDOW_SHOWN);
    //建立Renderer -1 表示使用預設的視窗 後面一個是Renderer的方式,0的話,應該就是未指定把???
    renderer = SDL_CreateRenderer(window, -1, 0);

    //因為隻是簡單展示一個圖檔,是以就建立一個Surface
    SDL_Surface *bmp = SDL_LoadBMP("image.bmp");

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

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

    //進入主循環,就是不斷的重新整理。這個應該是根據螢幕重新整理率去重新整理嗎?
    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;
}           

複制

這樣就就可以運作成功了!!

運作結果

SDL2庫(1)-移植Android 端 CMakeList 內建

運作結果.png

缺陷

  1. 缺陷就是SDLActivity 這些都已經寫死了。其實我們需要的隻是一個SDLSurface就可以展示我們想要的。

    沒事。這個是後話。後面接着分析。

參考

FFmpeg程式設計開發筆記 —— Android 移植 FFmpeg + SDL2.0 庫