Android下编译FFmpeg(添加Androidmk)

来源:互联网 发布:js改变div文字 编辑:程序博客网 时间:2024/05/17 07:38


http://blog.csdn.net/huahuahailang/article/details/27374219



首先要配置ndk,见前面一节:http://blog.csdn.net/huahuahailang/article/details/27373169

下面介绍如何将ffmpeg编译成动态库libffmpegjni.so。

在主目录下新建文件夹ayer/jni,将ffmpeg拷贝到jni目录中。在ayer目录下新建Android.mk文件,程序为:

~/ayer/jni/Android.mk

include $(all-subdir-makefiles)

~/ayer/jni/ffmpeg/Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_WHOLE_STATIC_LIBRARIES := libavformat libavcodec libavutil libpostproc libswscale

LOCAL_MODULE := ffmpeg

include $(BUILD_SHARED_LIBRARY)

include $(call all-makefiles-under,$(LOCAL_PATH))

~/ayer/jni/ffmpeg/av.mk

# LOCAL_PATH is one of libavutil, libavcodec, libavformat, or libswscale

#include $(LOCAL_PATH)/../config-$(TARGET_ARCH).mak

include $(LOCAL_PATH)/../config.mak

OBJS :=

OBJS-yes :=

MMX-OBJS-yes :=

include $(LOCAL_PATH)/Makefile

# collect objects

OBJS-$(HAVE_MMX) += $(MMX-OBJS-yes)

OBJS += $(OBJS-yes)

FFNAME := lib$(NAME)

FFLIBS := $(foreach,NAME,$(FFLIBS),lib$(NAME))

FFCFLAGS  = -DHAVE_AV_CONFIG_H -Wno-sign-compare -Wno-switch -Wno-pointer-sign

FFCFLAGS += -DTARGET_CONFIG=\"config-$(TARGET_ARCH).h\"

ALL_S_FILES := $(wildcard $(LOCAL_PATH)/$(TARGET_ARCH)/*.S)

ALL_S_FILES := $(addprefix $(TARGET_ARCH)/, $(notdir $(ALL_S_FILES)))

ifneq ($(ALL_S_FILES),)

ALL_S_OBJS := $(patsubst %.S,%.o,$(ALL_S_FILES))

C_OBJS := $(filter-out $(ALL_S_OBJS),$(OBJS))

S_OBJS := $(filter $(ALL_S_OBJS),$(OBJS))

else

C_OBJS := $(OBJS)

S_OBJS :=

endif

C_FILES := $(patsubst %.o,%.c,$(C_OBJS))

S_FILES := $(patsubst %.o,%.S,$(S_OBJS))

FFFILES := $(sort $(S_FILES)) $(sort $(C_FILES))

~/ayer/jni/ffmpeg/libavcodec/Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

include $(LOCAL_PATH)/../av.mk

LOCAL_SRC_FILES:= $(FFFILES)

LOCAL_C_INCLUDES:= \

$(LOCAL_PATH) \

$(LOCAL_PATH)/..

LOCAL_CFLAGS += $(FFCFLAGS)

LOCAL_LDLIBS := -lz

LOCAL_STATIC_LIBRARIES := $(FFLIBS)

LOCAL_MODULE := $(FFNAME)

include $(BUILD_STATIC_LIBRARY)

~/ayer/jni/ffmpeg/libavformat/Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

include $(LOCAL_PATH)/../av.mk

LOCAL_SRC_FILES:= $(FFFILES)

LOCAL_C_INCLUDES:= \

$(LOCAL_PATH) \

$(LOCAL_PATH)/..

LOCAL_CFLAGS += $(FFCFLAGS)

LOCAL_CFLAGS += -include "string.h" -Dipv6mr_interface=ipv6mr_ifindex

LOCAL_LDLIBS := -lz

LOCAL_STATIC_LIBRARIES := $(FFLIBS)

LOCAL_MODULE := $(FFNAME)

include $(BUILD_STATIC_LIBRARY)

~/ayer/jni/ffmpeg/libavfilter/Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

include $(LOCAL_PATH)/../av.mk

LOCAL_SRC_FILES:= $(FFFILES)

LOCAL_C_INCLUDES:= \

$(LOCAL_PATH) \

$(LOCAL_PATH)/..

LOCAL_CFLAGS += $(FFCFLAGS)

LOCAL_LDLIBS := -lz

LOCAL_STATIC_LIBRARIES := $(FFLIBS)

LOCAL_MODULE := $(FFNAME)

include $(BUILD_STATIC_LIBRARY)

~/ayer/jni/ffmpeg/libavutil/Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

include $(LOCAL_PATH)/../av.mk

LOCAL_SRC_FILES:= $(FFFILES)

LOCAL_C_INCLUDES:= \

$(LOCAL_PATH) \

$(LOCAL_PATH)/..

LOCAL_CFLAGS += $(FFCFLAGS)

LOCAL_LDLIBS := -lz

LOCAL_STATIC_LIBRARIES := $(FFLIBS)

LOCAL_MODULE := $(FFNAME)

include $(BUILD_STATIC_LIBRARY)

~/ayer/jni/ffmpeg/libpostproc/Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

include $(LOCAL_PATH)/../av.mk

LOCAL_SRC_FILES:= $(FFFILES)

LOCAL_C_INCLUDES:= \

$(LOCAL_PATH) \

$(LOCAL_PATH)/..

LOCAL_CFLAGS += $(FFCFLAGS)

LOCAL_LDLIBS := -lz

LOCAL_STATIC_LIBRARIES := $(FFLIBS)

LOCAL_MODULE := $(FFNAME)

include $(BUILD_STATIC_LIBRARY)

~/ayer/jni/ffmpeg/libswscale/Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

include $(LOCAL_PATH)/../av.mk

LOCAL_SRC_FILES:= $(FFFILES)

LOCAL_C_INCLUDES:= \

$(LOCAL_PATH) \

$(LOCAL_PATH)/..

LOCAL_CFLAGS += $(FFCFLAGS)

LOCAL_LDLIBS := -lz

LOCAL_STATIC_LIBRARIES := $(FFLIBS)

LOCAL_MODULE := $(FFNAME)

include $(BUILD_STATIC_LIBRARY)

编写配置脚本:~/ayer/jni/ffmpeg/config.sh

意其中的NDK路径,请修改成你系统中对应的安装路径

 

#!/bin/bash

source config_common.sh

PREBUILT=/home/huaguanglu/bysj/android-ndk-r8b/toolchains/arm-Linux-androideabi-4.4.3/prebuilt/linux-x86 

PLATFORM=/home/huaguanglu/bysj/android-ndk-r8b/platforms/android-9/arch-arm 

NDK_ROOT=/home/huaguanglu/bysj/android-ndk-r8b

./configure --target-os=linux \

--arch=arm \

--extra-cflags="-I${NDK_ROOT}/platforms/android-9/arch-arm/usr/include -fPIC -DANDROID -std=c99" \

--disable-everything \

--enable-version3 \

--enable-gpl \

--enable-nonfree \

--disable-stripping \

--disable-ffmpeg \

--disable-ffplay \

--disable-ffserver \

--disable-ffprobe \

--disable-encoders \

--disable-muxers \

--disable-devices \

--disable-protocols \

--disable-network \

--disable-avdevice \

--disable-asm \

--enable-decoder=h264 \

--enable-swscale \

--enable-cross-compile \

--cc=$PREBUILT/bin/arm-linux-androideabi-gcc \

--cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \

--strip=$PREBUILT/bin/arm-linux-androideabi-strip \

--extra-cflags="-fPIC -DANDROID" \

--extra-ldflags="-Wl,-T,$PREBUILT/arm-linux-androideabi/lib/ldscripts/armelf_linux_eabi.x -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib $PREBUILT/lib/gcc/arm-linux-androideabi/4.4.3/crtbegin.o $PREBUILT/lib/gcc/arm-linux-androideabi/4.4.3/crtend.o -lc -lm -ldl"

终端输入命令:

chmod 755 config.sh

./config.sh

这时会在~/ayer/jni/ffmpeg目录下生成三个文件: config.hconfig.makconfig.log

我们需要修改config.h文件,将其中的

#define av_restrict restrict

修改成

#define av_restrict

修改ffmpeg代码,以便在NDK中编译通过

libavfilter目录中的Makefile的末尾处多了 Clean 这个玩意儿 将其注释掉或者删掉。

修改~/ayer/jni/ffmpeg/libavutil/libm.h文件,将其中的所有static方法都注释掉

修改ffmpeg源码目录中的libavcodevlibavfilterlibavformatlibavutillibpostproclibswscale中的Makefile,将Makefile中的开头:include $(SUBDIR)../config.mak都注释掉。

进入目录:~/ayer

2)、运行命令:ndk-build,找到该命令的前提是你已经把NDK目录加到了PATH系统环境变量中。

假如你没有错误,恭喜你,在目录~/ayer/libs/armeabi下会有libffmpeg.so文件。

使用JNI链接JavaC

将上面配置好的ffmpeg复制到目录android-ndk-r8b下。将上面生成的libffmpeg.so复制到目录...\android-ndk-r8b\platforms\android-8\arch-arm\usr\lib下,进入目录android-ndk-r8b\samples,新建文件夹Tiquffmpeg,在Tiquffmpeg目录下新建文件夹jni目录,将上面配置好的ffmpeg复制到jni目录下。在jni目录下新建文件Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

PATH_TO_FFMPEG:=$(LOCAL_PATH)/ffmpeg

LOCAL_C_INCLUDES+=$(PATH_TO_FFMPEG)

LOCAL_LDLIBS:=-lffmpeg -llog

LOCAL_SRC_FILES := VideoTiqu.c

LOCAL_MODULE := ffmpegjni

include $(BUILD_SHARED_LIBRARY)

include $(all-subdir-makefiles)

jni目录下新建文件Application.mk

APP_PLATFORM := android-8

#APP_ABI := armeabi

APP_ABI := armeabi-v7a

APP_CFLAGS:=-DDISABLE_NEON

jni目录下新建文件VideoTiqu.c,写上jni程序,终端到jni目录下,输入ndk-build,就会在目录android-ndk-r8b\samples\Tiquffmpeg\libs\armeabi-v7a下生成libffmpegjni.so动态库文件。

VideoTiqu.c的程序为:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <string.h>  
  2. #include <jni.h>  
  3. #include <stdio.h>  
  4. #include <stdlib.h>  
  5. #include <android/log.h>  
  6. #include <ffmpeg/libavcodec/avcodec.h>  
  7.   
  8. struct AVFormatContext *pFormatCtx;  
  9. int             i, videoStream;  
  10. struct AVCodecContext  *pAVCodecCtx;  
  11. struct AVCodec         *pAVCodec;  
  12. struct AVPacket        mAVPacket;  
  13. struct AVFrame         *pAVFrame;   
  14. struct AVFrame         *pAVFrameYUV;  
  15. struct SwsContext      *pImageConvertCtx ;  
  16.   
  17. int iWidth=0;  
  18. int iHeight=0;  
  19.       
  20. int *colortab=NULL;  
  21. int *u_b_tab=NULL;  
  22. int *u_g_tab=NULL;  
  23. int *v_g_tab=NULL;  
  24. int *v_r_tab=NULL;  
  25.   
  26. //short *tmp_pic=NULL;  
  27.   
  28. unsigned int *rgb_2_pix=NULL;  
  29. unsigned int *r_2_pix=NULL;  
  30. unsigned int *g_2_pix=NULL;  
  31. unsigned int *b_2_pix=NULL;  
  32.   
  33. #define LOG_TAG "VideoTiqu.c"  
  34.   
  35. #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)  
  36.           
  37. void DeleteYUVTab()  
  38. {  
  39. //  av_free(tmp_pic);  
  40.       
  41.     av_free(colortab);  
  42.     av_free(rgb_2_pix);  
  43. }  
  44.   
  45. void CreateYUVTab_16()  
  46. {  
  47.     int i;  
  48.     int u, v;  
  49.       
  50. //  tmp_pic = (short*)av_malloc(iWidth*iHeight*2);   
  51.   
  52.     colortab = (int *)av_malloc(4*256*sizeof(int));  
  53.     u_b_tab = &colortab[0*256];  
  54.     u_g_tab = &colortab[1*256];  
  55.     v_g_tab = &colortab[2*256];  
  56.     v_r_tab = &colortab[3*256];  
  57.   
  58.     for (i=0; i<256; i++)  
  59.     {  
  60.         u = v = (i-128);  
  61.   
  62.         u_b_tab[i] = (int) ( 1.772 * u);  
  63.         u_g_tab[i] = (int) ( 0.34414 * u);  
  64.         v_g_tab[i] = (int) ( 0.71414 * v);   
  65.         v_r_tab[i] = (int) ( 1.402 * v);  
  66.     }  
  67.   
  68.     rgb_2_pix = (unsigned int *)av_malloc(3*768*sizeof(unsigned int));  
  69.   
  70.     r_2_pix = &rgb_2_pix[0*768];  
  71.     g_2_pix = &rgb_2_pix[1*768];  
  72.     b_2_pix = &rgb_2_pix[2*768];  
  73.   
  74.     for(i=0; i<256; i++)  
  75.     {  
  76.         r_2_pix[i] = 0;  
  77.         g_2_pix[i] = 0;  
  78.         b_2_pix[i] = 0;  
  79.     }  
  80.   
  81.     for(i=0; i<256; i++)  
  82.     {  
  83.         r_2_pix[i+256] = (i & 0xF8) << 8;  
  84.         g_2_pix[i+256] = (i & 0xFC) << 3;  
  85.         b_2_pix[i+256] = (i ) >> 3;  
  86.     }  
  87.   
  88.     for(i=0; i<256; i++)  
  89.     {  
  90.         r_2_pix[i+512] = 0xF8 << 8;  
  91.         g_2_pix[i+512] = 0xFC << 3;  
  92.         b_2_pix[i+512] = 0x1F;  
  93.     }  
  94.   
  95.     r_2_pix += 256;  
  96.     g_2_pix += 256;  
  97.     b_2_pix += 256;  
  98. }  
  99.   
  100. void DisplayYUV_16(unsigned int *pdst1, unsigned char *y, unsigned char *u, unsigned char *v, int width, int height, int src_ystride, int src_uvstride, int dst_ystride)  
  101. {  
  102.     int i, j;  
  103.     int r, g, b, rgb;  
  104.   
  105.     int yy, ub, ug, vg, vr;  
  106.   
  107.     unsigned char* yoff;  
  108.     unsigned char* uoff;  
  109.     unsigned char* voff;  
  110.       
  111.     unsigned int* pdst=pdst1;  
  112.   
  113.     int width2 = width/2;  
  114.     int height2 = height/2;  
  115.       
  116.     if(width2>iWidth/2)  
  117.     {  
  118.         width2=iWidth/2;  
  119.   
  120.         y+=(width-iWidth)/4*2;  
  121.         u+=(width-iWidth)/4;  
  122.         v+=(width-iWidth)/4;  
  123.     }  
  124.   
  125.     if(height2>iHeight)  
  126.         height2=iHeight;  
  127.   
  128.     for(j=0; j<height2; j++) // 涓€娆?x2鍏卞洓涓儚绱?   {  
  129.         yoff = y + j * 2 * src_ystride;  
  130.         uoff = u + j * src_uvstride;  
  131.         voff = v + j * src_uvstride;  
  132.   
  133.         for(i=0; i<width2; i++)  
  134.         {  
  135.             yy  = *(yoff+(i<<1));  
  136.             ub = u_b_tab[*(uoff+i)];  
  137.             ug = u_g_tab[*(uoff+i)];  
  138.             vg = v_g_tab[*(voff+i)];  
  139.             vr = v_r_tab[*(voff+i)];  
  140.   
  141.             b = yy + ub;  
  142.             g = yy - ug - vg;  
  143.             r = yy + vr;  
  144.   
  145.             rgb = r_2_pix[r] + g_2_pix[g] + b_2_pix[b];  
  146.   
  147.             yy = *(yoff+(i<<1)+1);  
  148.             b = yy + ub;  
  149.             g = yy - ug - vg;  
  150.             r = yy + vr;  
  151.   
  152.             pdst[(j*dst_ystride+i)] = (rgb)+((r_2_pix[r] + g_2_pix[g] + b_2_pix[b])<<16);  
  153.   
  154.             yy = *(yoff+(i<<1)+src_ystride);  
  155.             b = yy + ub;  
  156.             g = yy - ug - vg;  
  157.             r = yy + vr;  
  158.   
  159.             rgb = r_2_pix[r] + g_2_pix[g] + b_2_pix[b];  
  160.   
  161.             yy = *(yoff+(i<<1)+src_ystride+1);  
  162.             b = yy + ub;  
  163.             g = yy - ug - vg;  
  164.             r = yy + vr;  
  165.   
  166.             pdst [((2*j+1)*dst_ystride+i*2)>>1] = (rgb)+((r_2_pix[r] + g_2_pix[g] + b_2_pix[b])<<16);  
  167.         }  
  168.     }  
  169. }  
  170.   
  171. JNIEXPORT jint JNICALL Java_com_videoqt_VideoTiquJni_DecoderBegin  
  172.   (JNIEnv* env, jobject thiz, jint width, jint height)  
  173. {  
  174. /*FILE * fp_ceshi=fopen("/sdcard/x264_ceshiceshi.txt","w"); 
  175. fprintf(fp_ceshi,"fp_ceshi\r\n"); 
  176. fflush(fp_ceshi);*/  
  177.     iWidth=width;  
  178.     iHeight=height;  
  179.     if(pAVCodecCtx!=NULL)  
  180.     {  
  181.         avcodec_close(pAVCodecCtx);  
  182.         pAVCodecCtx=NULL;  
  183.     }     
  184.     if(pAVFrame!=NULL)  
  185.     {  
  186.         av_free(pAVFrame);  
  187.         pAVFrame=NULL;  
  188.     }  
  189.     // Register all formats and codecs  
  190.     av_register_all();  
  191.     LOGD("avcodec register success");  
  192.       
  193.     pAVCodec=avcodec_find_decoder(CODEC_ID_H264);  
  194.     if(pAVCodec==NULL)  
  195.         return -1;  
  196.   
  197.     LOGD("avcodec find decoder success");  
  198.     //init AVCodecContext  
  199.     pAVCodecCtx=avcodec_alloc_context3(pAVCodec);  
  200.     if(pAVCodecCtx==NULL)  
  201.     return -1;  
  202.     LOGD("avcodec alloc context success");  
  203.   
  204.       
  205.     /* we do not send complete frames */  
  206.     if(pAVCodec->capabilities & CODEC_CAP_TRUNCATED)  
  207.         pAVCodecCtx->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */  
  208.   
  209.     /* open it */     
  210.     if (avcodec_open(pAVCodecCtx, pAVCodec) < 0)return -1;  
  211.   
  212.     LOGD("avcodec open success");  
  213.   
  214.     av_init_packet(&mAVPacket);  
  215.       
  216.     pAVFrame=avcodec_alloc_frame();  
  217.     if(pAVFrame==NULL)return -1;  
  218.   
  219.     LOGD("avcodec frame allocat success");  
  220.   
  221.     //pImageConvertCtx = sws_getContext(pAVCodecCtx->width, pAVCodecCtx->height, PIX_FMT_YUV420P,  pAVCodecCtx->width, pAVCodecCtx->height,PIX_FMT_RGB565LE, SWS_BICUBIC,  NULL, NULL, NULL);     
  222.     //LOGD("sws_getContext  return =%d",pImageConvertCtx);  
  223.   
  224.     LOGD("avcodec context  success");  
  225.   
  226.     CreateYUVTab_16();  
  227.     LOGD("create yuv table success");  
  228.   
  229.       
  230.           
  231.       
  232.     return 1;  
  233. }  
  234.   
  235. JNIEXPORT jint JNICALL Java_com_videoqt_VideoTiquJni_DecoderEnd  
  236.   (JNIEnv* env, jobject thiz)  
  237. {  
  238.     if(pAVCodecCtx!=NULL)  
  239.     {  
  240.   
  241.         avcodec_close(pAVCodecCtx);  
  242.         pAVCodecCtx=NULL;  
  243.     }  
  244.   
  245.     if(pAVFrame!=NULL)  
  246.     {  
  247.   
  248.         av_free(pAVFrame);  
  249.         pAVFrame=NULL;  
  250.     }  
  251.     DeleteYUVTab();  
  252.     return 1;  
  253.   
  254. }  
  255.   
  256. JNIEXPORT jint JNICALL Java_com_videoqt_VideoTiquJni_DecoderContinue  
  257.   (JNIEnv* env, jobject thiz, jbyteArray in, jint inbuf_size, jbyteArray out)  
  258. {  
  259.     int i;  
  260.   
  261.     jbyte * inbuf = (jbyte*)(*env)->GetByteArrayElements(env, in, 0);  
  262.     jbyte * Picture= (jbyte*)(*env)->GetByteArrayElements(env, out, 0);  
  263.   
  264.     avcodec_get_frame_defaults(pAVFrame);  
  265.     mAVPacket.data=inbuf;  
  266.     mAVPacket.size=inbuf_size;  
  267.     int len =-1, got_picture=0;  
  268.     len = avcodec_decode_video2(pAVCodecCtx, pAVFrame, &got_picture, &mAVPacket);  
  269.   
  270.     if(len<0)  
  271.     {  
  272.         LOGD("len=-1,decode error");  
  273.         return len;  
  274.     }  
  275.   
  276.     if(got_picture>0)  
  277.     {  
  278.         LOGD("GOT PICTURE");  
  279.         /*pImageConvertCtx = sws_getContext (pAVCodecCtx->width, 
  280.                         pAVCodecCtx->height, pAVCodecCtx->pix_fmt, 
  281.                         pAVCodecCtx->width, pAVCodecCtx->height, 
  282.                         PIX_FMT_RGB565LE, SWS_BICUBIC, NULL, NULL, NULL); 
  283.         sws_scale (pImageConvertCtx, pAVFrame->data, pAVFrame->linesize,0, pAVCodecCtx->height, pAVFrame->data, pAVFrame->linesize); 
  284.  
  285.         */  
  286.         DisplayYUV_16((int*)Picture, pAVFrame->data[0], pAVFrame->data[1], pAVFrame->data[2], pAVCodecCtx->width, pAVCodecCtx->height, pAVFrame->linesize[0], pAVFrame->linesize[1], iWidth);    
  287.     }  
  288.     else  
  289.         LOGD("GOT PICTURE fail");  
  290.     //if(consumed_bytes > 0)  
  291.     //{  
  292.         //DisplayYUV_16((int*)Pixel, picture->data[0], picture->data[1], picture->data[2], c->width, c->height, picture->linesize[0], picture->linesize[1], iWidth);  
  293. /* 
  294.         for(i=0; i<c->height; i++) 
  295.             fwrite(picture->data[0] + i * picture->linesize[0], 1, c->width, outf); 
  296.  
  297.         for(i=0; i<c->height/2; i++) 
  298.             fwrite(picture->data[1] + i * picture->linesize[1], 1, c->width/2, outf); 
  299.  
  300.         for(i=0; i<c->height/2; i++) 
  301.             fwrite(picture->data[2] + i * picture->linesize[2], 1, c->width/2, outf); 
  302. // */  
  303.     //}  
  304.       
  305.     (*env)->ReleaseByteArrayElements(env, in, inbuf, 0);      
  306.     (*env)->ReleaseByteArrayElements(env, out, Picture, 0);   
  307.   
  308.     return len;   
  309. }  


0
0



0 0