Android使用C/C++代码或库需要通过JNI方式,详细的可见相关文章。

1. 添加C/C++源文件

复制/opt/android/ndk/android-ndk-r10e/resources/x264下的文件:
x264.h
x264_config.h
到jni目录下

在jni目录下添加
x264encoder.h
x264encoder.cpp
main.cpp
三个源文件,详细源码如下:

  1. /*
  2. *\File
  3. *x264encoder.h
  4. *\Author
  5. *Hank
  6. */
  7. #ifndef x264encoder_h
  8. #define x264encoder_h


  9. extern"C"
  10. {
  11. #include"stdint.h"
  12. #include"x264.h"


  13. enum bitrate_level
  14. {
  15. HIGH_LEVEL=0,
  16. STANDARD_LEVEL=1,
  17. MEDIUM_LEVEL=2,
  18. LOW_LEVEL=3,
  19. };


  20. classX264Encoder
  21. {
  22. public:
  23. X264Encoder();
  24. ~X264Encoder();


  25. bool openX264Encoder();
  26. //long x264EncoderProcess(uint8_t*pSrcData,intsrcDataSize,x264_nal_t**nals,int&nalsCount);


  27. long x264EncoderProcess(x264_picture_t*pPicture,x264_nal_t**nals,int&nalsCount);


  28. bool closeX264Encoder();


  29. void setSourceFormat(unsignedintsourcformat);
  30. void setResolution(unsignedintw,unsignedinth);
  31. void setBitrate(unsignedinti_bitrate);
  32. void setFps(unsignedintfps);
  33. void setI_KeyInt_Max(unsignedinti_frame_max);
  34. void setQp_Max(unsignedintqp_max);
  35. void setQp_Min(unsignedintqp_min);


  36. void forceIDRFrame();


  37. void upgradeBitrateLevel();
  38. void declineBitrateLevel();
  39. void setLeastBitrateLevel();




  40. private:
  41. x264_param_t*pParameter;
  42. x264_t*x264EncoderHandle;
  43. //x264_picture_t*pPicture;
  44. x264_picture_t*pOutput;


  45. unsignedintsourceFormat;
  46. //unsignedinti_bitrate;
  47. unsignedintbitratelevel;
  48. unsignedinti_fps;
  49. unsignedinti_keyint_max;
  50. unsignedintwidth;
  51. unsignedintheight;
  52. unsignedintqp_max;
  53. unsignedintqp_min;


  54. unsignedintcurrent_f_rf_constant;
  55. unsignedintuserSetting_f_rf_constant;


  56. int64_t frameNo;


  57. bool isForceIDRFrameEnabled;
  58. };
  59. }
  60. #endif

/*
* \File
* x264encoder.cpp
* \Author
* Hank
*/

  1. #include<stdlib.h>
  2. #include<string.h>
  3. #include"x264encoder.h"


  4. //new versionforx264 encoder
  5. X264Encoder::X264Encoder()
  6. {
  7. this->bitratelevel=STANDARD_LEVEL;
  8. qp_max=30;
  9. qp_min=0;
  10. i_fps=20;
  11. i_keyint_max=300;
  12. width=352;
  13. height=288;


  14. frameNo=0;
  15. isForceIDRFrameEnabled=false;


  16. pParameter=NULL;
  17. x264EncoderHandle=NULL;
  18. //pPicture=NULL;
  19. pOutput=NULL;
  20. }


  21. X264Encoder::~X264Encoder()
  22. {
  23. this->closeX264Encoder();
  24. }


  25. void X264Encoder::setSourceFormat(unsignedintsourcformat)
  26. {
  27. this->sourceFormat=sourcformat;
  28. }


  29. void X264Encoder::setResolution(unsignedintw,unsignedinth)
  30. {
  31. width=w;
  32. height=h;
  33. }


  34. void X264Encoder::setBitrate(unsignedinti_bitrate)
  35. {
  36. if(i_bitrate>0&&i_bitrate<=64){
  37. this->bitratelevel=LOW_LEVEL;
  38. }elseif(i_bitrate>64&&i_bitrate<=128){
  39. this->bitratelevel=MEDIUM_LEVEL;
  40. }elseif(i_bitrate>128&&i_bitrate<=256){
  41. this->bitratelevel=STANDARD_LEVEL;
  42. }elseif(i_bitrate>256&&i_bitrate<=384){
  43. this->bitratelevel=HIGH_LEVEL;
  44. }elseif(i_bitrate>384&&i_bitrate<=512){
  45. this->bitratelevel=HIGH_LEVEL;
  46. }else{
  47. this->bitratelevel=STANDARD_LEVEL;
  48. }
  49. }


  50. void X264Encoder::setFps(unsignedintfps)
  51. {
  52. i_fps=fps;
  53. }


  54. void X264Encoder::setI_KeyInt_Max(unsignedinti_frame_max)
  55. {
  56. i_keyint_max=i_frame_max;
  57. }


  58. void X264Encoder::setQp_Max(unsignedintqp_max)
  59. {
  60. this->qp_max=qp_max;
  61. }


  62. void X264Encoder::setQp_Min(unsignedintqp_min)
  63. {
  64. this->qp_min=qp_min;
  65. }


  66. bool X264Encoder::openX264Encoder(){
  67. this->closeX264Encoder();


  68. if(!pParameter)
  69. {
  70. pParameter=(x264_param_t*)malloc(sizeof(x264_param_t));


  71. if(!pParameter){
  72. this->closeX264Encoder();
  73. returnfalse;
  74. }
  75. memset(pParameter,0,sizeof(x264_param_t));
  76. }


  77. intret=x264_param_default_preset(pParameter,"ultrafast","zerolatency");
  78. if(ret!=0){
  79. this->closeX264Encoder();
  80. returnfalse;
  81. }


  82. pParameter->i_level_idc=30;


  83. pParameter->i_width=width;
  84. pParameter->i_height=height;


  85. pParameter->b_deterministic=1;
  86. //pParameter->b_sliced_threads=1;
  87. pParameter->i_threads=1;


  88. pParameter->i_csp=X264_CSP_I420;//X264_CSP_NV12;//X264_CSP_I420;


  89. pParameter->i_fps_num=i_fps;
  90. pParameter->i_fps_den=1;
  91. pParameter->i_bframe=0;
  92. pParameter->i_keyint_max=i_keyint_max;

  93. //pParameter->b_open_gop=1;

  94. //pParameter->rc.i_bitrate=i_bitrate;

  95. pParameter->rc.i_rc_method=X264_RC_CRF;//X264_RC_CQP;

  96. if(this->bitratelevel==LOW_LEVEL){
  97. pParameter->rc.f_rf_constant=32;
  98. }elseif(this->bitratelevel==MEDIUM_LEVEL){
  99. pParameter->rc.f_rf_constant=29;
  100. }elseif(this->bitratelevel==STANDARD_LEVEL){
  101. pParameter->rc.f_rf_constant=26;
  102. }elseif(this->bitratelevel==HIGH_LEVEL){
  103. pParameter->rc.f_rf_constant=24;
  104. }else{
  105. pParameter->rc.f_rf_constant=24;
  106. }

  107. current_f_rf_constant=pParameter->rc.f_rf_constant;
  108. userSetting_f_rf_constant=pParameter->rc.f_rf_constant;

  109. //from huxiaopeng
  110. pParameter->analyse.b_transform_8x8=1;
  111. pParameter->rc.f_aq_strength=1.5;

  112. pParameter->rc.i_aq_mode=0;
  113. pParameter->rc.f_qcompress=0.0;
  114. pParameter->rc.f_ip_factor=0.5;
  115. pParameter->rc.f_rate_tolerance=0.1;

  116. pParameter->analyse.i_direct_mv_pred=X264_DIRECT_PRED_AUTO;
  117. pParameter->analyse.i_me_method=X264_ME_DIA;
  118. pParameter->analyse.i_me_range=16;
  119. pParameter->analyse.i_subpel_refine=2;
  120. //pParameter->analyse.i_noise_reduction=1;

  121. pParameter->i_slice_max_size=1200;

  122. //pParameter->i_nal_hrd=X264_NAL_HRD_NONE;

  123. pParameter->b_deblocking_filter=1;
  124. pParameter->i_deblocking_filter_alphac0=4;
  125. pParameter->i_deblocking_filter_beta=4;

  126. pParameter->rc.b_mb_tree=0;

  127. pParameter->i_log_level=X264_LOG_NONE;

  128. if(x264_param_apply_profile(pParameter,"baseline"))
  129. //if(x264_param_apply_profile(pParameter,"main"))
  130. {
  131. this->closeX264Encoder();

  132. returnfalse;
  133. }

  134. if(!x264EncoderHandle){
  135. x264EncoderHandle=x264_encoder_open(pParameter);

  136. if(!x264EncoderHandle){
  137. this->closeX264Encoder();

  138. returnfalse;
  139. }
  140. }


  141. if(!pOutput){
  142. pOutput=(x264_picture_t*)malloc(sizeof(x264_picture_t));

  143. if(!pOutput){
  144. this->closeX264Encoder();
  145. returnfalse;
  146. }

  147. memset(pOutput,0,sizeof(x264_picture_t));
  148. }

  149. returntrue;
  150. }


  151. void X264Encoder::forceIDRFrame()
  152. {
  153. isForceIDRFrameEnabled=true;
  154. }


  155. void X264Encoder::upgradeBitrateLevel()
  156. {
  157. /*
  158. if(this->bitratelevel==HIGH_LEVEL){
  159. return;
  160. }


  161. this->bitratelevel++;


  162. if(this->bitratelevel==LOW_LEVEL){
  163. pParameter->rc.f_rf_constant=30;
  164. }elseif(this->bitratelevel==MEDIUM_LEVEL){
  165. pParameter->rc.f_rf_constant=27;
  166. }elseif(this->bitratelevel==STANDARD_LEVEL){
  167. pParameter->rc.f_rf_constant=24;
  168. }elseif(this->bitratelevel==HIGH_LEVEL){
  169. pParameter->rc.f_rf_constant=22;
  170. }else{
  171. pParameter->rc.f_rf_constant=23;
  172. }
  173. */


  174. if(userSetting_f_rf_constant>=current_f_rf_constant){
  175. return;
  176. }


  177. pParameter->rc.f_rf_constant--;
  178. current_f_rf_constant=pParameter->rc.f_rf_constant;


  179. x264_encoder_reconfig(x264EncoderHandle,pParameter);
  180. }


  181. void X264Encoder::setLeastBitrateLevel()
  182. {
  183. pParameter->rc.f_rf_constant=32;
  184. current_f_rf_constant=pParameter->rc.f_rf_constant;


  185. x264_encoder_reconfig(x264EncoderHandle,pParameter);
  186. }


  187. void X264Encoder::declineBitrateLevel()
  188. {


  189. if(32<=current_f_rf_constant){
  190. return;
  191. }


  192. pParameter->rc.f_rf_constant++;
  193. current_f_rf_constant=pParameter->rc.f_rf_constant;


  194. x264_encoder_reconfig(x264EncoderHandle,pParameter);
  195. }


  196. long X264Encoder::x264EncoderProcess(x264_picture_t*pPicture,x264_nal_t**nals,int&nalsCount)
  197. {
  198. pPicture->i_pts=(int64_t)(frameNo*pParameter->i_fps_den);
  199. pPicture->i_type=X264_TYPE_AUTO;
  200. pPicture->i_qpplus1=0;//X264_QP_AUTO;

  201. if(isForceIDRFrameEnabled){
  202. pPicture->i_type=X264_TYPE_IDR;
  203. isForceIDRFrameEnabled=false;
  204. }

  205. int32_t framesize=-1;


  206. framesize=x264_encoder_encode(x264EncoderHandle,nals,&nalsCount,pPicture,pOutput);


  207. if(framesize>0){
  208. frameNo++;
  209. }

  210. return framesize;
  211. }



  212. bool X264Encoder::closeX264Encoder()
  213. {
  214. if(pOutput){
  215. free(pOutput);
  216. pOutput=NULL;
  217. }
  218. /*
  219. if(pPicture){
  220. free(pPicture);
  221. pPicture=NULL;
  222. }
  223. */
  224. if(pParameter){
  225. free(pParameter);
  226. pParameter=NULL;
  227. }

  228. if(x264EncoderHandle){
  229. x264_encoder_close(x264EncoderHandle);
  230. x264EncoderHandle=NULL;
  231. }

  232. returntrue;
  233. }

/*
* \File
* main.cpp
* \Author
* Hank
*/


  1. #include<string.h>
  2. #include<stdlib.h>
  3. #include<arpa/inet.h>
  4. #include<stdio.h>
  5. #include<wchar.h>
  6. #include<time.h>


  7. #include<jni.h>


  8. /*forandroid logs*/
  9. #include<android/log.h>


  10. #include"x264.h"
  11. #include"x264_config.h"
  12. #include"x264encoder.h"


  13. #define LOG_TAG"android-ffmpeg-tutorial01"
  14. #define LOGI(...)__android_log_print(4,LOG_TAG,__VA_ARGS__);
  15. #define LOGE(...)__android_log_print(6,LOG_TAG,__VA_ARGS__);






  16. jint naMain(JNIEnv*pEnv,jobject pObj,jobject pMainAct,
  17. jstring pFileName,jint pNumOfFrames,
  18. jint picWidth,jint picHeight){
  19. /*Preset*/
  20. intnumOfFrames=pNumOfFrames;
  21. intpictureWidth=picWidth;
  22. intpictureHeight=picHeight;
  23. intpresetBitrate=512;
  24. intpresetFps=25;
  25. intpictureSize=pictureWidth*pictureHeight;
  26. intencodeTime=0;

  27. X264Encoder x264Encoder;

  28. x264Encoder.setBitrate(presetBitrate);
  29. x264Encoder.setResolution(pictureWidth,pictureHeight);
  30. x264Encoder.setFps(presetFps);

  31. char*yuvFilename=NULL;
  32. char*avcFilename=NULL;
  33. char str[80];

  34. FILE*inputFile=NULL;
  35. FILE*outputFile=NULL;

  36. //GetCstringfrom JNI jstring
  37. yuvFilename=(char*)pEnv->GetStringUTFChars(pFileName,NULL);
  38. if((inputFile=fopen(yuvFilename,"rb"))==NULL){
  39. LOGI("Can not open inputfile %s",yuvFilename);
  40. return-1;
  41. }

  42. strcpy(str,yuvFilename);
  43. strcat(str,".h264");
  44. avcFilename=str;
  45. LOGI("Output file: %s",avcFilename);
  46. if((outputFile=fopen(avcFilename,"wb"))==NULL){
  47. LOGI("Can not open outputfile %s",avcFilename);
  48. return-1;
  49. }


  50. x264_picture_t inputPicture;
  51. x264_picture_alloc(&inputPicture,X264_CSP_I420,pictureWidth,pictureHeight);

  52. x264_nal_t*p_nals=NULL;
  53. intnalsCount=0;
  54. intret=0;
  55. intj=0;


  56. if(x264Encoder.openX264Encoder())
  57. {
  58. struct timeval start,end;
  59. struct timeval sum;
  60. sum.tv_sec=0;
  61. sum.tv_usec=0;

  62. /*Including thetimeof read&write file
  63. gettimeofday(&start,NULL);
  64. LOGI("Encode start time : %ld.%ld",start.tv_sec,start.tv_usec);
  65. */

  66. for(j=0;j<numOfFrames;j++)
  67. {
  68. ret=fread(inputPicture.img.plane[0],1,pictureSize,inputFile);
  69. if(ret<pictureSize)
  70. {
  71. break;
  72. }
  73. fread(inputPicture.img.plane[1],1,pictureSize/4,inputFile);
  74. fread(inputPicture.img.plane[2],1,pictureSize/4,inputFile);

  75. gettimeofday(&start,NULL);

  76. x264Encoder.x264EncoderProcess(&inputPicture,&p_nals,nalsCount);

  77. gettimeofday(&end,NULL);

  78. if(end.tv_sec>start.tv_sec){
  79. sum.tv_sec+=(end.tv_sec-(start.tv_sec+1));
  80. sum.tv_usec+=((1000000-start.tv_usec)+end.tv_usec);
  81. LOGI("A Spend time: %ld.%ld",sum.tv_sec,sum.tv_usec);
  82. }else{
  83. sum.tv_sec+=(end.tv_sec-start.tv_sec);
  84. sum.tv_usec+=(end.tv_usec-start.tv_usec);
  85. LOGI("B Spend time: %ld.%ld",sum.tv_sec,sum.tv_usec);
  86. }

  87. if(p_nals)
  88. {
  89. for(inti=0;i<nalsCount;i++)
  90. {
  91. ret=fwrite(p_nals[i].p_payload,p_nals[i].i_payload,1,outputFile);
  92. LOGI("Write NO %d frame",j);
  93. LOGI("Should write %d bytes, in fact write %d bytes into %s",p_nals[i].i_payload,ret,avcFilename);
  94. }
  95. }
  96. }

  97. /*Including thetimeof read&write file
  98. gettimeofday(&end,NULL);
  99. LOGI("Encode end time : %ld.%ld",end.tv_sec,end.tv_usec);
  100. if(end.tv_sec>start.tv_sec){
  101. encodeTime=(end.tv_sec-(start.tv_sec+1))*1000000+((1000000-start.tv_usec)+end.tv_usec);
  102. LOGI("Spend time: %ld.%ld",(end.tv_sec-(start.tv_sec+1)),((1000000-start.tv_usec)+end.tv_usec));
  103. }else{
  104. encodeTime=(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec);
  105. LOGI("Spend time: %ld.%ld",(end.tv_sec-start.tv_sec),end.tv_usec-start.tv_usec);
  106. }
  107. */
  108. encodeTime=(sum.tv_sec+(sum.tv_usec/1000000))*1000000+(sum.tv_usec%1000000);
  109. LOGI("Spend time: %ld.%ld",sum.tv_sec,sum.tv_usec);

  110. }

  111. fclose(inputFile);
  112. fclose(outputFile);

  113. LOGI("Closed the files!");

  114. x264_picture_clean(&inputPicture);

  115. x264Encoder.closeX264Encoder();
  116. LOGI("Closed the handler of encoder!");

  117. return encodeTime;
  118. //return 0;
  119. }




  120. staticconstJNINativeMethod gMethods[]={
  121. {"naMain",
  122. "(Lroman10/tutorial/android_ffmpeg_tutorial01/MainActivity;Ljava/lang/String;III)I",
  123. (void*)naMain
  124. },
  125. };


  126. jint JNI_OnLoad(JavaVM*vm,void*reserved)
  127. {
  128. JNIEnv*env=NULL;jint result=-1;

  129. if((vm->GetEnv((void**)&env,JNI_VERSION_1_6))!=JNI_OK)return-1;

  130. jclass clazz;staticconstchar*const
  131. kClassName="roman10/tutorial/android_ffmpeg_tutorial01/MainActivity";

  132. clazz=env->FindClass(kClassName);if(clazz==NULL){printf("cannot
  133. get class:%s\n",kClassName);return-1;}

  134. if(env->RegisterNatives(clazz,gMethods,
  135. sizeof(gMethods)/sizeof(gMethods[0]))!=JNI_OK){printf("register
  136. native method failed!\n");return-1;}

  137. return JNI_VERSION_1_6;
  138. }

2. 修改相关配置并编译

1). 修改jni/Android.mk成如下:
#
# \File
# Android.mk
#
LOCAL_PATH := $(call my-dir)


include $(CLEAR_VARS)


LOCAL_MODULE := tutorial01
#LOCAL_SRC_FILES := tutorial01.c
LOCAL_SRC_FILES := x264encoder.cpp main.cpp
LOCAL_LDLIBS := -llog -ljnigraphics -lz
#LOCAL_SHARED_LIBRARIES := libavformat libavcodec libswscale libavutil
LOCAL_SHARED_LIBRARIES := libx264


include $(BUILD_SHARED_LIBRARY)
$(call import-module,x264-snapshot-20151015-2245/android/arm)




2). 修改 jni/Application.mk成如下:
#
# \File
# Android.mk
#
APP_ABI := armeabi
#APP_ABI := armeabi-v7a
APP_PLATFORM := android-10




3). 修改 src/build.gradle成如下
apply plugin: 'com.android.application'


android {
compileSdkVersion 23
buildToolsVersion "23.0.1"


defaultConfig {
applicationId "roman10.tutorial.android_ffmpeg_tutorial01"
minSdkVersion 19
targetSdkVersion 23


sourceSets.main{
jni.srcDirs=[]
jniLibs.srcDir "src/main/libs"
}
}


buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
debug {
debuggable true
jniDebuggable true
renderscriptDebuggable false
}
}
}


dependencies {
compile 'com.android.support:support-v4:18.0.0'
}


4). 编译
在main目录下:
$ cd app/src/main
$ ndk-build
[armeabi] Compile++ thumb: tutorial01 <= x264encoder.cpp
[armeabi] Compile++ thumb: tutorial01 <= main.cpp
[armeabi] Prebuilt : libx264.so <= <NDK>/sources/x264-snapshot-20151015-2245/android/arm/lib/
[armeabi] SharedLibrary : libtutorial01.so
[armeabi] Install : libtutorial01.so => libs/armeabi/libtutorial01.so
[armeabi] Install : libx264.so => libs/armeabi/libx264.so


表示编码成功;


3. 修改java源文件

修改MainActivity.java,添加调用的接口
public class MainActivity extends Activity {

// 调用参数的预定义
private static final String FRAME_DUMP_FOLDER_PATH = Environment.getExternalStorageDirectory()
+ File.separator + "android-264-encoder";
private static final String INPUT_YUV_FILENAME = "test_1920x1080.yuv";
private static int pWidth = 1920;
private static int pHeight = 1080;




@override
protected Void doInBackground(Void... params){
// 实际调用
encodeTime = naMain(mlOuterAct,
FRAME_DUMP_FOLDER_PATH + File.separator + INPUT_YUV_FILENAME,
mlNumOfFrames,
pWidth, pHeight );
}




/*
* 接口声明
* pVideoFileName : 表示输入文件名
* pNumOfFrame : 编码帧数
* Width : YUV源文件的图像宽度
* Height : YUV源文件的图像高度
*/
private static native int naMain(MainActivity pObject,
String pVideoFileName, int pNumOfFrame,
int Width, int Height);


// 库加载
static {
System.loadLibrary("x264");
System.loadLibrary("tutorial01");
}
}

再以android工程方式,编译运行;

更多相关文章

  1. c/c++ android 平台交叉编译 {ERROR: Failed to create toolchai
  2. ubutun下NDK编译环境配置
  3. Android(安卓)编译错误总结及收集
  4. Android(安卓)Studio的各种冷知识,黑科技
  5. Android(安卓)Studio修改项目编译版本
  6. android ffmpeg4.0.2编译过程记录
  7. Android(安卓)2.3 CTS测试修改测试结果和调试方法
  8. Android(安卓)CPU, Compilers, D8 & R8
  9. Android多窗口的实现 - 开源

随机推荐

  1. android技术要点梳理
  2. Android启动脚本init.rc
  3. andorid padding margin
  4. Android性能调优工具TraceView介绍
  5. android中Layoutopt的使用
  6. Android之Wifi学习(1)
  7. 使用User Agent分辨出Android设备类型的
  8. 在 Android(安卓)模拟器中启用摄像头支持
  9. Android之UI学习篇二:TextVeiw显示表情和
  10. Android(安卓)基础总结:(十)ContentResolver