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

SDL.png

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

系列内容导读

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

简单的集成

1. 获取源代码

SDL的源代码获取十分简单。访问SDL的官方网站(http://www.libsdl.org/),单击左侧的“Download”进入下载页面,然后下载“SourceCode”栏目下的文件就可以了。
注意:这里使用的是 SDL2-2.0.9

解压完后的文件目录.png

我们在根目录里面有看到,SDL2的源码,已经为我们配置好了多种的编译环境。包括Cmake 和Android.mk文件。这样的话,我们直接使用它自带的编译环境就好了。

2. 创建自己的工程

复制文件

  • 复制源码文件到lib下面


    将整个源码目录复制到lib下面.png
  • 复制Android部分的文件,到src 下


    复制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
错误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的时候,一定会有。。。。
image.png
  1. 源码没有加入编译
    我们通过观察目录发现这个时候。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.

这个对我们基本上用不到。所以其实去掉也无所谓。

  1. 直接在SDL_config_android.h文件中把它注释掉
  2. 然后对应的,把对应Java代码的初始化注释掉。


    对应的代码注释掉.png

这样就可以了。

  • 方案2:将hidapi也添加入编译中
  1. 找到对应的目录,添加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进行修改
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 加入源码目录。进行编译
        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的部分。如图所示的,剩下的文件部分全部注释掉。


从SDL static文件开始,全部注释掉.png

注释掉的原因:
一方面我们不需要它。我们只需要SHARED库就可以了。
另一方面,留着在INSTALL时会报错,简单起见,注释掉就可以。

配置自己的源文件

我们可以看到有android_project项目。
我们切换到目录下,具体看一下


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

添加如下内容

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

这样就就可以运行成功了!!

运行结果

运行结果.png

缺陷

  1. 缺陷就是SDLActivity 这些都已经写死了。其实我们需要的只是一个SDLSurface就可以展示我们想要的。
    没事。这个是后话。后面接着分析。

参考

FFmpeg编程开发笔记 —— Android 移植 FFmpeg + SDL2.0 库

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容