Android视频采集+H264编码

编码器使用的是x264的开源库,

很容易看懂的

简单的封装了一个JNI库

编码库在BBS里 CSDN的资源太难用了
http://www.eoeandroid.com/viewthread.php?tid=48668&fromuid=110389

x264的编译放方法

export ARM_ROOT=$ANDROID_NDK_ROOT
export ARM_INC=$ARM_ROOT/build/platforms/android-5/arch-arm/usr/include/
export ARM_LIB=$ARM_ROOT/build/platforms/android-5/arch-arm/usr/lib/
export ARM_TOOL=$ARM_ROOT/build/prebuilt/windows/arm-eabi-4.4.0
export ARM_LIBO=$ARM_TOOL/lib/gcc/arm-eabi/4.4.0
export PATH=$ARM_TOOL/bin:$PATH
export ARM_PRE=arm-eabi

./configure --prefix=/home/egmkang/libx264 --enable-shared /
-disable-asm --host=arm-linux --cross-prefix=arm-eabi-/
--extra-cflags=" -I$ARM_INC -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 "/
--extra-ldflags="-nostdlib -Bdynamic -Wl,--no-undefined -Wl,-z,noexecstack  -Wl,-z,nocopyreloc -Wl,-soname,/system/lib/libz.so -Wl,-rpath-link=$ARM_LIB,-dynamic-linker=/system/bin/linker -L$ARM_LIB -nostdlib $ARM_LIB/crtbegin_dynamic.o $ARM_LIB/crtend_android.o -lc -lm -ldl -lgcc"

这里生成的是x264的静态库

整个工程唯一有点麻烦的是 生成 JNI 动态库的时候 报错 。。

后来发现是少链接了一个库,

于是根据x264的编译方法 在Android.mk添加一些配置就可以了。当然这就是难点,在网上查了很多都没有结果。

有些目录的参数自己调整哈

我把前面生成的libx264.a 和 x264.h 文件放到jni的libx264目录下了 有问题自己调整

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)

估计很多人都会发现很熟悉 嘻嘻 这个就是根据

http://www.cnblogs.com/mcodec/articles/1780598.html

改的 连文件名字都没有换!!比较懒

另: 编码的效率很低下啊

AndroidVideo.java

 

  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. }  

 

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. }  

 

posted @ 2010-12-08 16:05  张兴业  阅读(512)  评论(0编辑  收藏  举报