ffmpeg移植到andriod

 configure 命令

./configure --target-os=linux --arch=armv41 --enable-cross-compile --cc=/cygdrive/c/android/android-ndk-1.5_r1/build/prebuilt/windows/arm-eabi-4.2.1/bin/arm-eabi-gcc --cross-prefix=/cygdrive/c/android/android-ndk-1.5_r1/build/prebuilt/windows/arm-eabi-4.2.1/bin  --nm=/cygdrive/c/android/android-ndk-1.5_r1/build/prebuilt/windows/arm-eabi-4.2.1/bin/arm-eabi-nm --extra-cflags="-fPIC -DANDROID " --extra-ldflags="-s -nostdlib -Bdynamic -Wl,-T,armelf.x -Wl,-dynamic-linker,/system/bin/linker -lc -lm -ldl crtbegin.o crtend.o --disable-static --enable-shared--disable-static --enable-shared
这个命令是编译shared版本的,完成之后还需要手动修改ar,nm,strip命令,默认是标准gcc要把其修改成arm-eabi为前缀的,还要注意全路径。
编译的时候,restrict的关键词arm-eabi-gcc不认识,可能是编译命令的问题,印象当中从gcc 3.4开始就应该支持了,没办法,只能将所有出现的strict关键词给去掉了。
把libavutil/internal.h中的
#if !HAVE_LLRINT
static av_always_inline av_const long long llrint(double x)
{
    return rint(x);
}
#endif /* HAVE_LLRINT */
#if !HAVE_LRINT
static av_always_inline av_const long int lrint(double x)
{
    return rint(x);
}
#endif /* HAVE_LRINT */
#if !HAVE_LRINTF
static av_always_inline av_const long int lrintf(float x)
{
    return (int)(rint(x));
}
#endif /* HAVE_LRINTF */
#if !HAVE_ROUND
static av_always_inline av_const double round(double x)
{
    return (x > 0) ? floor(x + 0.5) : ceil(x - 0.5);
}
#endif /* HAVE_ROUND */
#if !HAVE_ROUNDF
static av_always_inline av_const float roundf(float x)
{
    return (x > 0) ? floor(x + 0.5) : ceil(x - 0.5);
}
#endif /* HAVE_ROUNDF */
#if !HAVE_TRUNCF
static av_always_inline av_const float truncf(float x)
{
    return (x > 0) ? floor(x) : ceil(x);
}
#endif /* HAVE_TRUNCF */
这些代码删除掉。
编译完成在andriod运行失败,还在调试当中。由于andriod没有提供gdbserver所以,只能以日志的形式来调试输出了。
andriod中log的组件,不知道在c中是否能调用,需要研究一下。
接上:
支持log,只需包含#inlcude 即可
使用方法:
__android_log_vprint(ANDROID_LOG_DEBUG, "FFmpeg", fmt, vl);
static void ding_log(void* ptr, int level, const char* fmt, va_list vl)
{
    //printf(fmt);
//vfprintf(stderr, fmt, vl);
__android_log_vprint(ANDROID_LOG_DEBUG, "FFmpeg", fmt, vl);
}
这样就可以使用android的long方法了。
加入日志之后,发现在libavcodec/opt.c中的av_opt_set_defaults2函数,调用av_set_int时,最后是在av_set_number2,调用case FF_OPT_TYPE_INT:  av_log(0, 10, "num %d, den %d /n", num, den);  *(int       *)dst= llrint(num/den)*intnum; break; crash,具体原因还在调查之中,下午请假,回家了。
医院不上班,下周一再请,又回来上班了。
今天终于找到问题所在了,在libavcodec/optionts.c中有个定义
static const AVOption options[]={
去掉下面2行,即可运行成功了,对这些代码的作用不大清楚,需要深入研究。明白了,这是设定AVCodecContext结构每个变量的初始值。
//{"skip_idct"       , NULL, OFFSET(skip_idct)       , FF_OPT_TYPE_INT, AVDISCARD_DEFAULT, INT_MIN, INT_MAX, V|D, "avdiscard"},
//{"skip_frame"      , NULL, OFFSET(skip_frame)      , FF_OPT_TYPE_INT, AVDISCARD_DEFAULT, INT_MIN, INT_MAX, V|D, "avdiscard"},
把 libavcodec.so.52, libavformat.so.52, libavutil.so.49,上传到android的模拟器里的/system/lib里面。
这样看来的话,用静态库比较好,要编译静态库,只需把configure改成--disable-shared --enable-static就可以了。
这样简单的例子就能运行了。

你可能感兴趣的:(Android,FFmpeg)