2012-12-10 39 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

我编辑了我的答案。 –

相关问题