x264 for Android 的编译

此编译参考了 https://my.oschina.net/lifj/blog/709188 , http://blog.csdn.net/xyz_lmn/article/details/6063300 两位博客的文章。

在Linux/Mac下,开始x264的编译工作。

首先从官网上下载最新的x264源码:http://www.videolan.org/developers/x264.html。这里贴一下git的地址:

# git clone http://git.videolan.org/git/x264.git

下载完成之后,就可以开始编译了。

在x264的源码根目录下建一个build_android.sh文件,然后写入以下编译代码

#!/bin/bash
#这里需要配置一下你的NDK的根目录。
ANDROID_NDK=$NDK_HOME

if [ -z "$ANDROID_NDK" ]; then
	echo "You must define ANDROID_NDK before starting."
	echo "They must point to your NDK directories.\n"
	exit 1
fi

# Detect OS
OS=`uname`
HOST_ARCH=`uname -m`
export CCACHE=; type ccache >/dev/null 2>&1 && export CCACHE=ccache
if [ $OS == 'Linux' ]; then
	export HOST_SYSTEM=linux-$HOST_ARCH
elif [ $OS == 'Darwin' ]; then
	export HOST_SYSTEM=darwin-$HOST_ARCH
fi

SOURCE=`pwd`
#这里配置最终生成。a的目录
PREFIX=$SOURCE/build/android/arm/
#目标编译版本
SYSROOT=$ANDROID_NDK/platforms/android-14/arch-arm
#arm-linux-androideabi-4.9 这个数字可能需要变化。不同的NDK版本版本号不一致。
#目标编译版本和toolchains下的目录有对应关系。arch-arm对应arm-linux或aarch64。arch-mips对应mipsel-linux或米皮sel-linux。x86同样。
CROSS_PREFIX=$ANDROID_NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/$HOST_SYSTEM/bin/arm-linux-androideabi-
EXTRA_CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=neon -D__ARM_ARCH_7__ -D__ARM_ARCH_7A__"
EXTRA_LDFLAGS="-nostdlib"

./configure  --prefix=$PREFIX \
	--cross-prefix=$CROSS_PREFIX \
	--extra-cflags="$EXTRA_CFLAGS" \
	--extra-ldflags="$EXTRA_LDFLAGS" \
	--enable-pic \
	--enable-static \
	--enable-strip \
	--disable-cli \
	--host=arm-linux \
	--disable-asm  \
	--sysroot=$SYSROOT

make clean
make STRIP= -j4 install || exit 1

然后赋予build_android.sh执行权限。根目录下运行:

# ./build_android.sh

应该不会出错(如果有错,欢迎在文章下面评论,我会尽量帮助完善)。

编译完成之后,在源码的目录中,多了一个build目录。这个目录里面就是我们想要的头文件和静态库。两个头文件,和一个.a的静态库

include
  |______x264_config.h
  |______x264.h
lib
  |______libx264.a

先编译出静态库.a 文件,有了这几个文件,之后就可以编译android的so库了.

我把前面生成的build/android/arm/下面的include 和 lib 文件放到jni的目录下了 有问题自己调整

在jni目录创建H264Android.c文件,代码:

  1. #include <string.h>  
  2. #include <jni.h>  
  3. #include <stdio.h>  
  4. #include <stdlib.h>  
  5. #include <arpa/inet.h>  
  6. #include <x264.h>  
  7. #define DATA_MAX 3000000  
  8. #define H264_MTU 1024  
  9. typedef struct  
  10. {  
  11.     x264_param_t * param;  
  12.     x264_t *handle;  
  13.     x264_picture_t * picture;  
  14.     x264_nal_t  *nal;  
  15. } Encoder;  
  16. jlong Java_h264_com_H264Encoder_CompressBegin(JNIEnv* env, jobject thiz,  
  17.         jint width, jint height) {  
  18.     Encoder * en = (Encoder *) malloc(sizeof(Encoder));  
  19.     en->param = (x264_param_t *) malloc(sizeof(x264_param_t));  
  20.     en->picture = (x264_param_t *) malloc(sizeof(x264_picture_t));  
  21.     x264_param_default(en->param); //set default param  
  22.     //en->param->rc.i_rc_method = X264_RC_CQP;  
  23.     en->param->i_log_level = X264_LOG_NONE;  
  24.     en->param->i_width = width; //set frame width  
  25.     en->param->i_height = height; //set frame height  
  26.     en->param->rc.i_lookahead =0;  
  27.     en->param->i_bframe=0;  
  28.     en->param->i_fps_num =5;  
  29.     en->param->i_fps_den = 1;  
  30.     if ((en->handle = x264_encoder_open(en->param)) == 0) {  
  31.         return 0;  
  32.     }  
  33.     /* Create a new pic */  
  34.     x264_picture_alloc(en->picture, X264_CSP_I420, en->param->i_width,  
  35.             en->param->i_height);  
  36.     return (jlong) en;  
  37. }  
  38. jint Java_h264_com_H264Encoder_CompressEnd(JNIEnv* env, jobject thiz,jlong handle)  
  39. {  
  40.     Encoder * en = (Encoder *) handle;  
  41.     if(en->picture)  
  42.     {  
  43.         x264_picture_clean(en->picture);  
  44.         free(en->picture);  
  45.         en->picture  = 0;  
  46.     }  
  47.     if(en->param)  
  48.     {  
  49.         free(en->param);  
  50.         en->param=0;  
  51.     }  
  52.     if(en->handle)  
  53.     {  
  54.         x264_encoder_close(en->handle);  
  55.     }  
  56.     free(en);  
  57.     return 0;  
  58. }  
  59. jint Java_h264_com_H264Encoder_CompressBuffer(JNIEnv* env, jobject thiz,jlong handle,jint type,jbyteArray in, jint insize,jbyteArray out)  
  60. {  
  61.     Encoder * en = (Encoder *) handle;  
  62.     x264_picture_t pic_out;  
  63.     int i_data=0;  
  64.     int nNal=-1;  
  65.     int result=0;  
  66.     int i=0,j=0;  
  67.     int nPix=0;  
  68.     jbyte * Buf = (jbyte*)(*env)->GetByteArrayElements(env, in, 0);  
  69.     jbyte * h264Buf = (jbyte*)(*env)->GetByteArrayElements(env, out, 0);  
  70.     unsigned char * pTmpOut = h264Buf;  
  71.     int nPicSize=en->param->i_width*en->param->i_height;  
  72.     /* 
  73.     Y数据全部从在一块,UV数据使用interleave方式存储 
  74.     YYYY 
  75.     YYYY 
  76.     UVUV 
  77.      */  
  78.     jbyte * y=en->picture->img.plane[0];  
  79.     jbyte * v=en->picture->img.plane[1];  
  80.     jbyte * u=en->picture->img.plane[2];  
  81.     memcpy(en->picture->img.plane[0],Buf,nPicSize);  
  82.     for (i=0;i<nPicSize/4;i++)  
  83.     {  
  84.         *(u+i)=*(Buf+nPicSize+i*2);  
  85.         *(v+i)=*(Buf+nPicSize+i*2+1);  
  86.     }  
  87.     switch (type)  
  88.     {  
  89.     case 0:  
  90.         en->picture->i_type = X264_TYPE_P;  
  91.         break;  
  92.     case 1:  
  93.         en->picture->i_type = X264_TYPE_IDR;  
  94.         break;  
  95.     case 2:  
  96.         en->picture->i_type = X264_TYPE_I;  
  97.         break;  
  98.     default:  
  99.         en->picture->i_type = X264_TYPE_AUTO;  
  100.         break;  
  101.     }  
  102.     if( x264_encoder_encode( en->handle, &(en->nal), &nNal, en->picture ,&pic_out) < 0 )  
  103.     {  
  104.         return -1;  
  105.     }  
  106.     for (i = 0; i < nNal; i++){  
  107.           memcpy(pTmpOut, en->nal[i].p_payload, en->nal[i].i_payload);  
  108.           pTmpOut += en->nal[i].i_payload;  
  109.           result+=en->nal[i].i_payload;  
  110.     }  
  111.     return result;  
  112. }  

 

再创建Android.mk文件


LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES +=$(LOCAL_PATH)/libx264/include
LOCAL_MODULE    := H264Android
LOCAL_SRC_FILES := H264Android.c 
LOCAL_LDFLAGS += $(LOCAL_PATH)/libx264/lib/libx264.a
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -lgcc


include $(BUILD_SHARED_LIBRARY)

之后进入jni目录使用ndk-build进行编译就行了。 之后会就出现libH264Android.so。

测试Android代码 (备注:此代码借鉴别人所写,本人测试可用于检测是否编译成功,但效果不佳。其他效果问题自己研究~)

AndroidVideo.Java

 

package h264.com;
  1. import java.io.File;  
  2. import java.io.RandomAccessFile;  
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.os.Bundle;  
  6. import android.view.View;  
  7. import android.content.res.Configuration;  
  8. import android.os.Bundle;  
  9. import android.util.Log;  
  10. import android.view.SurfaceHolder;  
  11. import android.view.SurfaceView;  
  12. import android.view.Window;  
  13. import android.view.WindowManager;  
  14. import android.view.SurfaceHolder.Callback;  
  15. import android.graphics.PixelFormat;  
  16. import android.hardware.Camera;  
  17. public class AndroidVideo extends Activity implements Callback,  
  18.         Camera.PictureCallback {  
  19.     private SurfaceView mSurfaceView = null;  
  20.     private SurfaceHolder mSurfaceHolder = null;  
  21.     private Camera mCamera = null;  
  22.     private boolean mPreviewRunning = false;  
  23.     public void onCreate(Bundle savedInstanceState) {  
  24.         super.onCreate(savedInstanceState);  
  25.         getWindow().setFormat(PixelFormat.TRANSLUCENT);  
  26.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  27.         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
  28.                 WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  29.         setContentView(R.layout.camera);  
  30.         mSurfaceView = (SurfaceView) this.findViewById(R.id.surface_camera);  
  31.         mSurfaceHolder = mSurfaceView.getHolder();  
  32.         mSurfaceHolder.addCallback(this);  
  33.         mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
  34.     }  
  35.       
  36.     @Override  
  37.     public void onPictureTaken(byte[] data, Camera camera) {  
  38.     }  
  39.     @Override  
  40.     public void surfaceChanged(SurfaceHolder holder, int format, int width,  
  41.             int height) {  
  42.         if (mPreviewRunning) {  
  43.             mCamera.stopPreview();  
  44.         }  
  45.         Camera.Parameters p = mCamera.getParameters();  
  46.         p.setPreviewSize(352288);  
  47.         mCamera.setPreviewCallback(new H264Encoder(352288));  
  48.         mCamera.setParameters(p);  
  49.         try {  
  50.             mCamera.setPreviewDisplay(holder);  
  51.         } catch (Exception ex) {  
  52.         }  
  53.         mCamera.startPreview();  
  54.         mPreviewRunning = true;  
  55.     }  
  56.     @Override  
  57.     public void surfaceCreated(SurfaceHolder holder) {  
  58.         mCamera = Camera.open();  
  59.     }  
  60.     @Override  
  61.     public void surfaceDestroyed(SurfaceHolder holder) {  
  62.         if (mCamera != null) {  
  63.             mCamera.setPreviewCallback(null);  
  64.             mCamera.stopPreview();  
  65.             mPreviewRunning = false;  
  66.             mCamera.release();  
  67.             mCamera = null;  
  68.         }  
  69.     }  
  70.     public void onConfigurationChanged(Configuration newConfig) {  
  71.         try {  
  72.             super.onConfigurationChanged(newConfig);  
  73.             if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {  
  74.             } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {  
  75.             }  
  76.         } catch (Exception ex) {  
  77.         }  
  78.     }  
  79. }  
  80. class H264Encoder implements Camera.PreviewCallback {  
  81.     long encoder=0;  
  82.     RandomAccessFile raf=null;  
  83.     byte[] h264Buff =null;  
  84.     static {  
  85.         System.loadLibrary("H264Android");  
  86.     }  
  87.     private H264Encoder(){};  
  88.       
  89.     public H264Encoder(int width, int height) {  
  90.         encoder = CompressBegin(width, height);  
  91.         h264Buff = new byte[width * height *8];  
  92.         try {  
  93.             File file = new File("/sdcard/camera.h264");  
  94.             raf = new RandomAccessFile(file, "rw");  
  95.         } catch (Exception ex) {  
  96.             Log.v("System.out", ex.toString());  
  97.         }  
  98.           
  99.     };  
  100.     protected void finalize()  
  101.     {  
  102.         CompressEnd(encoder);  
  103.         if (null != raf)  
  104.         {  
  105.             try {  
  106.                 raf.close();  
  107.             } catch (Exception ex) {  
  108.                 Log.v("System.out", ex.toString());  
  109.             }  
  110.         }  
  111.         try {  
  112.             super.finalize();  
  113.         } catch (Throwable e) {  
  114.             // TODO Auto-generated catch block  
  115.             e.printStackTrace();  
  116.         }  
  117.     }  
  118.     private native long CompressBegin(int width,int height);  
  119.     private native int CompressBuffer(long encoder, int type,byte[] in, int insize,byte[] out);  
  120.     private native int CompressEnd(long encoder);  
  121.     @Override  
  122.     public void onPreviewFrame(byte[] data, Camera camera) {      
  123.           
  124.         int result=CompressBuffer(encoder, -1, data, data.length,h264Buff);  
  125.         try {  
  126.             if (result>0)  
  127.                 raf.write(h264Buff, 0, result);  
  128.         } catch (Exception ex) {  
  129.             Log.v("System.out", ex.toString());  
  130.         }  
  131.     }  
  132.       
  133. }  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值