2012-12-10 90 views
1

我發現了關於FFMPEG的多個問題和教程,但我似乎並沒有理解其中的大多數。我讀過的所有指南,錯過了很大的差距,並不傾向於解釋事情。如何構建+將FFMPEG包含到現有的Android項目中

我有一個現有的Android應用程序,使用稱爲AAC解碼器的第三方庫流式音頻。由於各種原因,我需要切換到使用FFMPEG,但無法弄清楚如何。我設法遵循指南來構建FFMPEG,但後來我不明白我應該如何處理輸出。

我的應用程序只需從遠程URL傳輸音頻。這些流可以有多種格式。

如果任何人都可以將我鏈接到一些全面的,詳細的指南,或向我提供說明,那就太好了。

謝謝。

+0

查看http://stackoverflow.com/questions/12136078/ffmpeg-for-android-toolchains-arm-linux-armeabi-eabi-pkg-config-is-there-any有趣的信息 – SirDarius

回答

7

我創建的腳本建立FFmpeg的,在這裏看到我的回答:

arm-linux-androideabi-gcc is unable to create an executable - compile ffmpeg for android armeabi devices

一個你編譯你的項目的根目錄創建一個「JNI」文件夾中的FFmpeg。在JNI文件夾中創建Android.mk與這些內容:

include $(call all-subdir-makefiles) 

然後與這些內容創建Application.mk:

APP_ABI := armeabi armeabi-v7a x86 

接着,在JNI文件夾中創建下面的文件夾結構:

ffmpeg/ffmpeg/

在第一個ffmpeg文件夾中創建另一個Android。MK:

LOCAL_PATH := $(call my-dir) 

include $(CLEAR_VARS) 
LOCAL_MODULE := libavcodec 
LOCAL_SRC_FILES := ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so 
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/include 
include $(PREBUILT_SHARED_LIBRARY) 

include $(CLEAR_VARS) 
LOCAL_MODULE := libavformat 
LOCAL_SRC_FILES := ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so 
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/include 
include $(PREBUILT_SHARED_LIBRARY) 

include $(CLEAR_VARS) 
LOCAL_MODULE := libavutil 
LOCAL_SRC_FILES := ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so 
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/include 
include $(PREBUILT_SHARED_LIBRARY) 

LOCAL_PATH:= $(call my-dir) 

最後,將建立文件夾的內容(從構建腳本)來/ JNI /的ffmpeg/ffmpeg的/

從項目的根目錄運行:

ndk-build clean 

然後運行:

ndk-build 

如果您感覺懶惰,您可以簡單地從我的項目中下載jni文件夾並刪除在「元數據」和「運動員」的文件夾:

http://svn.code.sf.net/p/servestream/code/trunk/jni/

讓我知道如果您有任何其他問題。

+1

謝謝。我可以建立圖書館,但我不知道如何從那裏着手,你有什麼指導呢? – SteveEdson

+0

感謝您的編輯,我試圖使用您的構建腳本,但在結束時,就在退出消息之前,我得到錯誤'i686-linux-android-gcc無法創建可執行文件。 C編譯器測試失敗。我正在使用android-ndk-r8c。有任何想法嗎? – SteveEdson

+0

不,Mac OSX,我現在就試試Ubuntu VM。除非有解決辦法? – SteveEdson

2

你需要交叉編譯FFMPEG的Android支持。在您的項目中創建jni文件夾,並在jni中放入FFMPEG文件夾。設置android NDK

這是我用來交叉編譯ffmpeg for android的Config.sh的一個副本。

Config.sh 


#!/bin/sh 
PLATFORM=/home/nishant/Desktop/android/android-ndk-r5b/platforms/android-8/arch-arm 
PREBUILT=/home/nishant/Desktop/android/android-ndk-r5b/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86 
LIBX264=/home/nishant/Desktop/android/workspace/DemoProject/jni/x264 
LIB=/home/nishant/Desktop/android/workspace/DemoProject/jni 
EXTRA_LIBS="-lgcc -lm -ldl -lz -lc" 
#EXTRA_EXE_LDFLAGS="$PLATFORM/usr/lib/crtbegin_dynamic.o $PLATFORM/usr/lib/crtend_android.o" 

./configure --target-os=linux \ 
    --arch=arm \ 
    --enable-version3 \ 
    --enable-gpl \ 
    --enable-nonfree \ 
    --disable-stripping \ 
    --disable-ffmpeg \ 
    --disable-ffplay \ 
    --disable-ffserver \ 
    --disable-ffprobe \ 
    --enable-encoders \ 
    --enable-libfaac \ 
    --disable-muxers \ 
    --disable-devices \ 
    --disable-protocols \ 
    --enable-protocol=file \ 
    --enable-avfilter \ 
    --disable-network \ 
    --disable-mpegaudio-hp \ 
    --disable-avdevice \ 
    --enable-cross-compile \ 
    --cc=$PREBUILT/bin/arm-eabi-gcc \ 
    --nm=$PREBUILT/bin/arm-eabi-nm \ 
    --prefix=/home/nishant/Desktop/android/workspace/DemoProject/jni \ 
    --cross-prefix=$PREBUILT/bin/arm-eabi- \ 
    --enable-postproc \ 
    --extra-libs="$EXTRA_LIBS" \ 
    --extra-cflags="-I$PLATFORM/usr/include/ -I$LIB/include/ -I/home/admin1/x264 -std=gnu99 -fPIC -DANDROID -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -DANDROID -Wa,--noexecstack -MMD -MP" \ 
    --disable-asm \ 
    --enable-neon \ 
    --enable-armv5te \ 
    --enable-static \ 
    --disable-shared \ 
    --extra-ldflags="-Wl,-rpath-link=$LIB/lib -L$LIB/lib -nostdlib -Bdynamic -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,nocopyreloc -Wl,-soname,/system/lib/libz.so -Wl,-rpath-link=$PLATFORM/usr/lib,-dynamic-linker=/system/bin/linker -L/usr/lib -L$PLATFORM/usr/lib -nostdlib $PLATFORM/usr/lib/crtbegin_dynamic.o $PLATFORM/usr/lib/crtend_android.o" 

您可以使用此Config文件交叉編譯ffmpeg並對其進行一些修改。

使用ndk-build命令編譯config.sh

編輯:

FFMPEG是捆綁在一起的所有音頻編碼器和解碼器。對於AAC編碼和解碼,請使用libfaaclibfaad。您可以在libavcodecsapi-example.c文件中找到音頻解碼示例。您需要創建一個JNI Wrapper Class來操作編解碼器。來自該文件的解碼示例之一,我在這裏發佈。

static void audio_decode_example(const char *outfilename, const char *filename) 
{ 
    AVCodec *codec; 
    AVCodecContext *c= NULL; 
    int out_size, len; 
    FILE *f, *outfile; 
    uint8_t *outbuf; 
    uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; 
    AVPacket avpkt; 

    av_init_packet(&avpkt); 

    printf("Audio decoding\n"); 

    /* find the mpeg audio decoder */ 
    codec = avcodec_find_decoder(CODEC_ID_MP2); 
    if (!codec) { 
     fprintf(stderr, "codec not found\n"); 
     exit(1); 
    } 

    c= avcodec_alloc_context(); 

    /* open it */ 
    if (avcodec_open(c, codec) < 0) { 
     fprintf(stderr, "could not open codec\n"); 
     exit(1); 
    } 

    outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); 

    f = fopen(filename, "rb"); 
    if (!f) { 
     fprintf(stderr, "could not open %s\n", filename); 
     exit(1); 
    } 
    outfile = fopen(outfilename, "wb"); 
    if (!outfile) { 
     av_free(c); 
     exit(1); 
    } 

    /* decode until eof */ 
    avpkt.data = inbuf; 
    avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f); 

    while (avpkt.size > 0) { 
     out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; 
     len = avcodec_decode_audio3(c, (short *)outbuf, &out_size, &avpkt); 
     if (len < 0) { 
      fprintf(stderr, "Error while decoding\n"); 
      exit(1); 
     } 
     if (out_size > 0) { 
      /* if a frame has been decoded, output it */ 
      fwrite(outbuf, 1, out_size, outfile); 
     } 
     avpkt.size -= len; 
     avpkt.data += len; 
     if (avpkt.size < AUDIO_REFILL_THRESH) { 
      /* Refill the input buffer, to avoid trying to decode 
      * incomplete frames. Instead of this, one could also use 
      * a parser, or use a proper container format through 
      * libavformat. */ 
      memmove(inbuf, avpkt.data, avpkt.size); 
      avpkt.data = inbuf; 
      len = fread(avpkt.data + avpkt.size, 1, 
         AUDIO_INBUF_SIZE - avpkt.size, f); 
      if (len > 0) 
       avpkt.size += len; 
     } 
    } 

    fclose(outfile); 
    fclose(f); 
    free(outbuf); 

    avcodec_close(c); 
    av_free(c); 
} 

希望它能幫助你。

+0

謝謝,一旦FFMPEG lib已經內置到文件夾中,我該從哪裏去?我想我明白我必須爲本地函數創建一些包裝。我在哪裏可以找到我需要的功能?在此之後我該怎麼辦?乾杯 – SteveEdson

+0

我編輯了我的答案。 –

相關問題