Android视频采集+H264编码

 

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

很容易看懂的

简单的封装了一个JNI库

编码库在BBS里 CSDN的资源太难用了

http://www.eoeandroid.com/forum.php?mod=viewthread&tid=52739&extra=

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.rosoo.net/a/201106/14632.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(352, 288); 
  47.         mCamera.setPreviewCallback(new H264Encoder(352, 288)); 
  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
  74.  == Configuration.ORIENTATION_LANDSCAPE) { 
  75.             } else if (this.getResources().getConfiguration().orientation
  76.  == Configuration.ORIENTATION_PORTRAIT) { 
  77.             } 
  78.         } catch (Exception ex) { 
  79.         } 
  80.     } 
  81. class H264Encoder implements Camera.PreviewCallback { 
  82.     long encoder=0; 
  83.     RandomAccessFile raf=null; 
  84.     byte[] h264Buff =null; 
  85.     static { 
  86.         System.loadLibrary("H264Android"); 
  87.     } 
  88.     private H264Encoder(){}; 
  89.      
  90.     public H264Encoder(int width, int height) { 
  91.         encoder = CompressBegin(width, height); 
  92.         h264Buff = new byte[width * height *8]; 
  93.         try { 
  94.             File file = new File("/sdcard/camera.h264"); 
  95.             raf = new RandomAccessFile(file, "rw"); 
  96.         } catch (Exception ex) { 
  97.             Log.v("System.out", ex.toString()); 
  98.         } 
  99.          
  100.     }; 
  101.     protected void finalize() 
  102.     { 
  103.         CompressEnd(encoder); 
  104.         if (null != raf) 
  105.         { 
  106.             try { 
  107.                 raf.close(); 
  108.             } catch (Exception ex) { 
  109.                 Log.v("System.out", ex.toString()); 
  110.             } 
  111.         } 
  112.         try { 
  113.             super.finalize(); 
  114.         } catch (Throwable e) { 
  115.             // TODO Auto-generated catch block 
  116.             e.printStackTrace(); 
  117.         } 
  118.     } 
  119.     private native long CompressBegin(int width,int height); 
  120.     private native int CompressBuffer(long encoder, int type,byte[] in
  121. int insize,byte[] out); 
  122.     private native int CompressEnd(long encoder); 
  123.     @Override 
  124.     public void onPreviewFrame(byte[] data, Camera camera) {     
  125.          
  126.         int result=CompressBuffer(encoder, -1, data, data.length,h264Buff); 
  127.         try { 
  128.             if (result>0) 
  129.                 raf.write(h264Buff, 0, result); 
  130.         } catch (Exception ex) { 
  131.             Log.v("System.out", ex.toString()); 
  132.         } 
  133.     } 
  134.      
 

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

你可能感兴趣的:(Android视频采集+H264编码)