2017-10-22 12 views
13

모든 안드로이드 아키텍처 용 ffmpeg 라이브러리를 빌드했습니다. 그러나 일부 세부 사항은 내 마음을 혼란스럽게합니다. 우선 제가 어떻게 구축했는지 단계별로 설명하겠습니다.모든 안드로이드 아키텍처 용 FFmpeg를 올바르게 작성하십시오.

  • 내가 만든 https://www.videolan.org/developers/x264.html
  • 에서 libx264의 최신 버전을 다운로드하고 (거의) 모든 안드로이드 플랫폼 libs와의 작성 (x264 폴더에) build_all.sh 스크립트를 실행합니다. 그런 다음 x264 폴더에 android 폴더가 있습니다. 예 :android/arm64android/x86android/x86_64 x264 폴더
  • 는 내가이 ffmpeg3.3.4
  • https://ffmpeg.org/download.html에서 내가 ffmpeg3.3.4 폴더의 4 개 복사본을 만들어 다운로드합니다. 안드로이드 아키텍처 이름을 사용하여 이름을 지정했습니다. ffmpeg3.3.4-armffmpeg3.3.4-x86ffmpeg3.3.4-x86_64
  • 만든 BUILD_ (아키텍처 이름) ffmpeg3.3.4-arm64처럼 .sh로 안드로이드의 각 플랫폼. 각 아키텍처 이름에 따라 'named'.sh files을 ffmpeg 폴더로 이동하십시오. 예 build_android_x86.sh =>ffmpeg3.3.4-x86

build_android_arm64.sh 예는 FFmpeg 폴더와 계층 구조의 동일 레벨에서 NDK_PATH (C:\Users\MyName\AppData\Local\Android\sdk\ndk-bundle)

  • 넣어 x264 폴더에 모든 ffmpeg3.3.4-arm64ffmpeg3.3.4-armffmpeg3.3.4-x86ffmpeg3.3.4-x86_64 폴더 이동

    #!/bin/bash 
    #Change NDK to your Android NDK location 
    NDK=$HOME/Android/Sdk/ndk-bundle 
    PLATFORM=$NDK/platforms/android-21/arch-arm64/ 
    PREBUILT=$NDK/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64 
    
    GENERAL="\ 
    --enable-small \ 
    --enable-cross-compile \ 
    --extra-libs="-lgcc" \ 
    --arch=aarch64 \ 
    --cc=$PREBUILT/bin/aarch64-linux-android-gcc \ 
    --cross-prefix=$PREBUILT/bin/aarch64-linux-android- \ 
    --nm=$PREBUILT/bin/aarch64-linux-android-nm \ 
    --extra-cflags="-I../x264/android/arm64/include" \ 
    --extra-ldflags="-L../x264/android/arm64/lib" " 
    
    MODULES="\ 
    --enable-gpl \ 
    --enable-libx264" 
    
    
    
    function build_arm64 
    { 
        ./configure \ 
        --logfile=conflog.txt \ 
        --target-os=linux \ 
        --prefix=./android/arm64-v8a \ 
        ${GENERAL} \ 
        --sysroot=$PLATFORM \ 
        --extra-cflags="" \ 
        --extra-ldflags="-lx264 -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib -lc -lm -ldl -llog" \ 
        --enable-shared \ 
        --disable-static \ 
        --disable-doc \ 
        --enable-zlib \ 
        ${MODULES} 
    
        make clean 
        make 
        make install 
    } 
    
    build_arm64 
    
    
    echo Android ARM64 builds finished 
    
    • in (C:\Users\MyName\AppData\Local\Android\sdk\ndk-bundle)
    • 각각 build_android_x86.sh, build_android_x86_64.sh .. 스크립트를 하나씩 자신의 ffmpeg 폴더에서 실행하십시오. 그런 다음 ffmpeg 폴더에 android 폴더가 있습니다. (생성 android 폴더는 라이브러리 폴더가) 모든 예 : ffmpeg3.3.4-x86/android/x86/(bin,inlude,lib,share)
    • 만든 Android.mk 파일 android 폴더를 생성/armName 폴더를 안드로이드 그들 각각을 움직였다. 예컨대 Android.mk =>

      LOCAL_PATH:= $(call my-dir) 
      
      include $(CLEAR_VARS) 
      LOCAL_MODULE:= libavcodec 
      LOCAL_SRC_FILES:= lib/libavcodec-57.so 
      LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include 
      include $(PREBUILT_SHARED_LIBRARY) 
      
      include $(CLEAR_VARS) 
      LOCAL_MODULE:= libavformat 
      LOCAL_SRC_FILES:= lib/libavformat-57.so 
      LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include 
      include $(PREBUILT_SHARED_LIBRARY) 
      
      include $(CLEAR_VARS) 
      LOCAL_MODULE:= libswscale 
      LOCAL_SRC_FILES:= lib/libswscale-4.so 
      LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include 
      include $(PREBUILT_SHARED_LIBRARY) 
      
      include $(CLEAR_VARS) 
      LOCAL_MODULE:= libavutil 
      LOCAL_SRC_FILES:= lib/libavutil-55.so 
      LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include 
      include $(PREBUILT_SHARED_LIBRARY) 
      
      include $(CLEAR_VARS) 
      LOCAL_MODULE:= libavfilter 
      LOCAL_SRC_FILES:= lib/libavfilter-6.so 
      LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include 
      include $(PREBUILT_SHARED_LIBRARY) 
      
      include $(CLEAR_VARS) 
      LOCAL_MODULE:= libswresample 
      LOCAL_SRC_FILES:= lib/libswresample-2.so 
      LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include 
      include $(PREBUILT_SHARED_LIBRARY) 
      
      include $(CLEAR_VARS) 
      LOCAL_MODULE := postproc 
      LOCAL_SRC_FILES := lib/libpostproc-54.so 
      LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include 
      include $(PREBUILT_SHARED_LIBRARY) 
      
      include $(CLEAR_VARS) 
      LOCAL_MODULE := avdevice 
      LOCAL_SRC_FILES := lib/libavdevice-57.so 
      LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include 
      include $(PREBUILT_SHARED_LIBRARY) 
      
    • ffmpeg3.3.4-x86/android/x86/이 내 프로젝트의 폴더 예컨대 x86x86_4arm64arm7 JNI의 폴더 (myproject/app/jni/x86, myproject/app/jni/x86_64) "라는 이름의 팔"만들기.

    • 이동 경로 열린라는 이름의는 FFmpeg 폴더를 하나씩 NDK하고 "라는 이름의 팔"폴더는 FFmpeg 폴더에서 ffmpeg.cffmpeg_filter.cffmpeg_opt.ccmdutils.c 파일을 복사합니다. 예 : ffmpeg.c =>myproject/app/jni/x86

    • 내 프로젝트에 Android.mk 파일을 만들었습니다.

      LOCAL_PATH := $(call my-dir) 
      #$(warning $(LOCAL_PATH)) 
      
      include $(CLEAR_VARS) 
      LOCAL_MODULE := videoEdit 
      LOCAL_LDLIBS := -llog -ljnigraphics -lz -landroid 
      LOCAL_CFLAGS := -Wdeprecated-declarations 
      ANDROID_LIB := -landroid 
      
      $(info $(TARGET_ARCH_ABI)) 
      
      ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) 
          LOCAL_C_INCLUDES:=/Users/MyName/AppData/Local/Android/sdk/ndk-bundle/sources/ffmpeg-3.3.4-armeabi 
          LOCAL_SRC_FILES := videoEdit.c arm7/ffmpeg.c arm7/ffmpeg_filter.c arm7/ffmpeg_opt.c arm7/cmdutils.c 
          LOCAL_CFLAGS += -lx264 -Wl,--no-merge-exidx-entries 
      else 
      
          ifeq ($(TARGET_ARCH_ABI),arm64-v8a) 
            LOCAL_C_INCLUDES:=/Users/MyName/AppData/Local/Android/sdk/ndk-bundle/sources/ffmpeg-3.3.4-arm64-v8a 
            LOCAL_SRC_FILES := videoEdit.c arm64/ffmpeg.c arm64/ffmpeg_filter.c arm64/ffmpeg_opt.c arm64/cmdutils.c 
            LOCAL_CFLAGS += -funwind-tables -Wl,--no-merge-exidx-entries 
          else 
      
           ifeq ($(TARGET_ARCH_ABI),x86_64) 
             LOCAL_C_INCLUDES:=/Users/MyName/AppData/Local/Android/sdk/ndk-bundle/sources/ffmpeg3.3.4-x86_64 
             LOCAL_SRC_FILES := videoEdit.c x86_64/ffmpeg.c x86_64/ffmpeg_filter.c x86_64/ffmpeg_opt.c x86_64/cmdutils.c 
           else 
             LOCAL_C_INCLUDES:=/Users/MyName/AppData/Local/Android/sdk/ndk-bundle/sources/ffmpeg3.3.4-x86 
             LOCAL_SRC_FILES := videoEdit.c x86/ffmpeg.c x86/ffmpeg_filter.c x86/ffmpeg_opt.c x86/cmdutils.c 
           endif 
      
          endif 
      
      endif 
      
      LOCAL_SHARED_LIBRARIES := libavformat libavcodec libswscale libavutil libswresample libavfilter libavdevice libpostproc 
      
      include $(BUILD_SHARED_LIBRARY) 
      
      ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) 
      
          $(call import-module,ffmpeg-3.3.4-armeabi/android/armeabi-v7a) 
      
      else 
      
          ifeq ($(TARGET_ARCH_ABI),arm64-v8a) 
            $(call import-module,ffmpeg-3.3.4-arm64-v8a/android/arm64-v8a) 
          else 
      
           ifeq ($(TARGET_ARCH_ABI),x86_64) 
             $(call import-module,ffmpeg3.3.4-x86_64/android/x86_64) 
           else 
            $(call import-module,ffmpeg3.3.4-x86/android/i686-diasm) 
           endif 
      
          endif 
      
      endif 
      
    • 내 프로젝트에 Created Application.mk 파일.ndk-build 빌드 명령을 실행보다

      APP_ABI := armeabi-v7a, arm64-v8a, x86_64, x86 
      APP_PLATFORM := android-14 
      
    • 만든 videoEdit.c.

    오류없이 작성된. 나는 ffmpeg 명령을 실행할 수 있지만 너무 많은 시간이 걸릴 것이라고 생각합니다. 예를 들어 hflip을 실행하면 15 초 동안 동영상이 뒤집 힙니다.

    코드 예제 : emaulator에 매우 빠르게 작동하지만 실제 장치에 매우 느리게, 안드로이드에서 실행

    JNIEXPORT jint JNICALL Java_com_name_app_library_VideoEditer_natives_VideoEditer_flipHorizontally 
    (JNIEnv *env, jclass someclass, jstring inputFile, jstring outFile) { 
    
        int numberOfArgs = 14; 
    
        char** arguments = calloc(numberOfArgs, sizeof(char*)); 
        const char *in, *out; 
    
        in = (*env)->GetStringUTFChars(env, inputFile, 0); 
        out = (*env)->GetStringUTFChars(env, outFile, 0); 
    
        arguments[0] = "ffmpeg"; 
        arguments[1] = "-i"; 
        arguments[2] = in; 
        arguments[3] = "-c:v"; 
        arguments[4] = "libx264"; 
        arguments[5] = "-preset"; 
        arguments[6] = "ultrafast"; 
        arguments[7] = "-threads"; 
        arguments[8] = "5"; 
        arguments[9] = "-c:a"; 
        arguments[10] = "copy"; 
        arguments[11] = "-vf"; 
        arguments[12] = "hflip"; 
        arguments[13] = out; 
    
        int i; 
        for (i = 0; i < numberOfArgs; i++) { 
         log_message(arguments[i]); 
        } 
        log_message("Printed all"); 
    
        main(numberOfArgs, arguments); 
        free(arguments); 
        (*env)->ReleaseStringUTFChars(env, inputFile, in); 
        (*env)->ReleaseStringUTFChars(env, outFile, out); 
    
        return 0; 
    } 
    

    는 FFmpeg 명령.

    또한 내 마음을 혼란스럽게하는 또 다른 것은 ./configure 명령의 출력입니다. 예 : ffmpeg-3.3.4-arm64-v8a 폴더를 열어 터미널에서 ./configure 명령을 실행합니다. 출력에 ARCH x86 (generic)이 표시됩니다. 모든 플랫폼 출력은 ARCH x86 (generic)과 동일합니다.

    출력 우분투에 만든 모든 단계 편집

    install prefix   /usr/local 
    source path    . 
    C compiler    gcc 
    C library     glibc 
    ARCH      x86 (generic) 
    big-endian    no 
    runtime cpu detection  yes 
    yasm      yes 
    MMX enabled    yes 
    MMXEXT enabled   yes 
    3DNow! enabled   yes 
    3DNow! extended enabled yes 
    SSE enabled    yes 
    SSSE3 enabled    yes 
    AESNI enabled    yes 
    AVX enabled    yes 
    XOP enabled    yes 
    FMA3 enabled    yes 
    FMA4 enabled    yes 
    i686 features enabled  yes 
    CMOV is fast    yes 
    EBX available    yes 
    EBP available    yes 
    debug symbols    yes 
    strip symbols    yes 
    optimize for size   no 
    optimizations    yes 
    static     yes 
    shared     no 
    postprocessing support no 
    network support   yes 
    threading support   pthreads 
    safe bitstream reader  yes 
    texi2html enabled   no 
    perl enabled    yes 
    pod2man enabled   yes 
    makeinfo enabled   no 
    makeinfo supports HTML no 
    
    External libraries: 
    iconv   xlib 
    

    폴더 ffmpeg-3.3.4-arm64-v8a의 명령 ./configure의 다음 창에 모든 폴더를 이동했다. 따라서 경로에 대해 혼동하지 마십시오.

    나는 이러한 모든 단계를 통해 내 단계에 문제가 있는지 묻고 싶습니다. 다른 방법을 따라야하지 않겠습니까? ffmpeg가 실제 장치에서 느리게 실행되는 이유는 무엇입니까? 한 가지 일이 얼마나 심한지, 어떻게 retrica, snapchat, 미러링 된 뒤집기와 같이 비디오 녹화가 가능한지 궁금합니다. 그들이 녹화 된 후에 뒤집을 수 있습니까 (만약 그들이 초 단위로 이것을하고 있다면) 또는 런타임에 뒤집힌 비디오를 녹화하고 있습니까? 내 생각 엔 안드로이드에 대한 ffmpeg 빌드 지저분하고 잘못된 일을하는 것은 매우 쉽습니다. 당신이 나의 계단을보고, 질문하고 조언을 주면, 나는 많이 감사 할 것입니다.

  • +0

    나는 빌드 파일의 아치를 조사 할 것이다. 또한,'$ (import module, android/cpufeatures)'가 빠졌습니까? IIRC에서는 NEON 최적화 코드를 켜기 위해 필요합니다. https://github.com/DrKLO/Telegram/blob/master/TMessagesProj/jni/Android.mk –

    +0

    파일을 빌드하십시오. 미안하지만 이해할 수 없습니다. libx264 파일을 빌드 하시거나 ffmpeg 파일을 빌드 하시겠습니까? – fthopkins

    +0

    당신은 그것이 사실이라면 사실입니다. 나는 $ (call import-module, android/cpufeatures)를 추가하여 효과를 볼 수있다. – fthopkins

    답변

    3
    ARCH      x86 (generic) 
    

    분명히 틀렸어. 특정 아키텍처를 나열해야합니다.

    저는 https://github.com/IljaKosynkin/FFmpeg-Development-Kit이 도움이 될 것이라고 생각합니다. 먼저 모든 아키텍처를 올바르게 빌드 할 수있었습니다. 명령 줄 ffmpeg를 사용하고 있으므로 프로그램을 활성화해야합니다.

    +0

    이 답변은 내 문제에 대한 최선의 접근 방법입니다. 감사. – fthopkins

    +0

    @fthopkins 당신이 뭘 잘못하고 어떻게 해결했는지 알려주세요. 문제를 해결하기 위해 https://github.com/IljaKosynkin/FFmpeg-Development-Kit을 따르셨습니까? 문제를 해결하기 위해 정확히 무엇을 업데이트 했습니까? –