android 移植ffmpeg后so库的使用

  只需要将我们编译好的ffmpeg的so包(在/obj/local/armeabi/libffmpeg.so)copy到所在ndk下的\platforms\android-8\arch-arm\usr\lib文件夹下就可以了。
  再看下我们的代码吧:
  1. public class HelloJni extends Activity
  2. {
  3. /** Called when the activity is first created. */
  4. @Override
  5. public void onCreate(Bundle savedInstanceState)
  6. {
  7. super.onCreate(savedInstanceState);
  8. /* Create a TextView and set its content.
  9. * the text is retrieved by calling a native
  10. * function.
  11. */
  12. TextView  tv = new TextView(this);
  13. String str = String.valueOf(stringFromJNI());
  14. str = str +"\n"+getVoice();
  15. tv.setText(str);
  16. setContentView(tv);
  17. }
  18. public native int getVoice();
  19. public native String  stringFromJNI();
  20. public native String  unimplementedStringFromJNI();
  21. static {
  22. System.loadLibrary("ffmpeg");
  23. System.loadLibrary("hello-jni");
  24. }
  25. }

这个是Android上层的使用。下面附上c层的代码

  1. /*
  2. * Copyright (C) 2009 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. *      http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. #include <string.h>
  18. #include <jni.h>
  19. #include <android/log.h>
  20. #include <ffmpeg/libavcodec/avcodec.h>
  21. #include <ffmpeg/libavformat/avformat.h>
  22. #include <ffmpeg/libswscale/swscale.h>
  23. #include <string.h>
  24. #define LOG_TAG    "***************************lixingyun*****************" // 这个是自定义的LOG的标识
  25. #undef LOG // 取消默认的LOG
  26. #define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) // 定义LOG类型
  27. #define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) // 定义LOG类型
  28. #define LOGW(...)  __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) // 定义LOG类型
  29. #define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) // 定义LOG类型
  30. #define LOGF(...)  __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__) // 定义LOG类型
  31. /* This is a trivial JNI example where we use a native method
  32. * to return a new VM String. See the corresponding Java source
  33. * file located at:
  34. *
  35. *   apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java
  36. */
  37. JNIEXPORT jstring Java_com_example_hellojni_HelloJni_stringFromJNI(JNIEnv* env,
  38. jobject thiz) {
  39. char str[25];
  40. sprintf(str, "%d", avcodec_version());
  41. return (*env)->NewStringUTF(env, str);
  42. // return (*env)->NewStringUTF(env, "Hello from JNI !");0
  43. }
  44. JNIEXPORT jint Java_com_example_hellojni_HelloJni_getVoice(JNIEnv* env,
  45. jobject thiz) {
  46. int flag = 0;
  47. AVPacket aacpkt;
  48. aacpkt.data = NULL;
  49. aacpkt.size = 0;
  50. const char *filename = "file:/sdcard/test.mp3";
  51. av_init_packet(&aacpkt);
  52. av_register_all(); //注册所有可解码类型
  53. AVFormatContext *pInFmtCtx = NULL; //文件格式
  54. AVCodecContext *pInCodecCtx = NULL; //编码格式
  55. pInFmtCtx = avformat_alloc_context();
  56. if (av_open_input_file(&pInFmtCtx, filename, NULL, 0, NULL) != 0) //获取文件格式
  57. LOGE("av_open_input_file error\n");
  58. if (av_find_stream_info(pInFmtCtx) < 0) //获取文件内音视频流的信息
  59. LOGE("av_find_stream_info error\n");
  60. unsigned int j;
  61. // Find the first audio stream
  62. int audioStream = -1;
  63. // Dump information about file onto standard error
  64. dump_format(pInFmtCtx, 0, filename, 0);
  65. //从FormatdContext的中找到对应流对应的编码类型,若是CODEC_TYPE_AUDIO则表示是音频
  66. for (j = 0; j < pInFmtCtx->nb_streams; j++) //找到音频对应的stream
  67. if (pInFmtCtx->streams[j]->codec->codec_type == CODEC_TYPE_AUDIO) {
  68. audioStream = j;
  69. break;
  70. }
  71. if (audioStream == -1) {
  72. printf("input file has no audio stream\n");
  73. return 0; // Didn't find a audio stream
  74. }
  75. LOGE("audio stream num: %d\n", audioStream);
  76. pInCodecCtx = pInFmtCtx->streams[audioStream]->codec; //音频的编码上下文
  77. AVCodec *pInCodec = NULL;
  78. /* FILE *file3 = fopen("codec_private_data_size.txt","w");
  79. for(int i = 0; i <200000; i++)
  80. {
  81. pInCodec = avcodec_find_decoder((CodecID)i);
  82. if (pInCodec!=NULL)
  83. {
  84. fprintf(file3,"%s %d\n",pInCodec->name,pInCodec->priv_data_size );
  85. }
  86. }
  87. fclose(file3);
  88. system("pause");
  89. */
  90. pInCodec = avcodec_find_decoder(pInCodecCtx->codec_id); //根据编码ID找到用于解码的结构体
  91. if (pInCodec == NULL) {
  92. printf("error no Codec found\n");
  93. return -1; // Codec not found
  94. }
  95. //使用test的代替pInCodecCtx也可以完成解码,可以看出只要获取以下几个重要信息就可以实现解码和重采样
  96. AVCodecContext *test = avcodec_alloc_context();
  97. test->bit_rate = pInCodecCtx->bit_rate; //重采样用
  98. test->sample_rate = pInCodecCtx->sample_rate; //重采样用
  99. test->channels = pInCodecCtx->channels; //重采样用
  100. test->extradata = pInCodecCtx->extradata; //若有则必有
  101. test->extradata_size = pInCodecCtx->extradata_size; //若有则必要
  102. test->codec_type = CODEC_TYPE_AUDIO; //不必要
  103. test->block_align = pInCodecCtx->block_align; //必要
  104. if (avcodec_open(test, pInCodec) < 0) //将两者结合以便在下面的解码函数中调用pInCodec中的对应解码函数
  105. {
  106. printf("error avcodec_open failed.\n");
  107. return -1; // Could not open codec
  108. }
  109. if (avcodec_open(pInCodecCtx, pInCodec) < 0) {
  110. printf("error avcodec_open failed.\n");
  111. return -1; // Could not open codec
  112. }
  113. static AVPacket packet;
  114. LOGI(" bit_rate = %d \r\n", pInCodecCtx->bit_rate);
  115. LOGI(" sample_rate = %d \r\n", pInCodecCtx->sample_rate);
  116. LOGI(" channels = %d \r\n", pInCodecCtx->channels);
  117. LOGI(" code_name = %s \r\n", pInCodecCtx->codec->name);
  118. //LOGI("extra data size: %d :data%x %x %x %x\n",pInCodecCtx->extradata_size,pInCodecCtx->extradata[0]
  119. // ,pInCodecCtx->extradata[1],pInCodecCtx->extradata[2],pInCodecCtx->extradata[3]);
  120. LOGI(" block_align = %d\n", pInCodecCtx->block_align);
  121. /********************************************************/
  122. unsigned char *outbuf = NULL;
  123. outbuf = (unsigned char *) malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE * 2);
  124. int outsize;
  125. outsize = AVCODEC_MAX_AUDIO_FRAME_SIZE * 2;
  126. int len = 0;
  127. int size = 0;
  128. FILE *out_fp;
  129. out_fp = fopen("out.dat", "wb+");
  130. while (av_read_frame(pInFmtCtx, &aacpkt) >= 0) {
  131. LOGI("***************************");
  132. if (aacpkt.stream_index == audioStream) {
  133. int declen = 0;
  134. size = aacpkt.size;
  135. while (aacpkt.size > 0) {
  136. outsize = AVCODEC_MAX_AUDIO_FRAME_SIZE * 2;
  137. memset(outbuf, 0, outsize);
  138. len = avcodec_decode_audio3(pInCodecCtx, (int16_t *) outbuf,
  139. &outsize, &aacpkt);
  140. if (len < 0) {
  141. printf("avcodec_decode_audio3 failed!\n");
  142. break;
  143. }
  144. if (outsize > 0) {
  145. fwrite(outbuf, 1, outsize, out_fp);
  146. printf("write %d bytes\n", outsize);
  147. }
  148. declen += len;
  149. if (declen == size) {
  150. av_free_packet(&aacpkt);
  151. printf("packet decoded succeed!\n");
  152. break;
  153. } else if (declen < size) {
  154. aacpkt.size -= len;
  155. aacpkt.data += len;
  156. } else {
  157. printf("decode error!\n");
  158. break;
  159. }
  160. }
  161. }
  162. }
  163. fclose(out_fp);
  164. // Close the codec
  165. avcodec_close(pInCodecCtx);
  166. // Close the video file
  167. av_close_input_file(pInFmtCtx);
  168. return flag;
  169. }
  其中的LOGE那几个就是Android下的哦。
  再附上Android.mk的东西吧:

  1. LOCAL_PATH := $(call my-dir)
  2. include $(CLEAR_VARS)
  3. PATH_TO_FFMPEG_SOURCE:=$(LOCAL_PATH)/ffmpeg
  4. LOCAL_C_INCLUDES += $(PATH_TO_FFMPEG_SOURCE)
  5. LOCAL_LDLIBS := -lffmpeg -llog
  6. LOCAL_MODULE    := hello-jni
  7. LOCAL_SRC_FILES := hello-jni.c
  8. include $(BUILD_SHARED_LIBRARY)
 
哈哈,这样就Ok了。
源码也附上吧.
 

FFmpeg在Android使用3的更多相关文章

  1. How to Build FFmpeg for Android

    http://www.roman10.net/how-to-build-ffmpeg-for-android/ ffmpeg is an open-source platform for record ...

  2. [原]ffmpeg编译android 硬解码支持库 libstagefright

    最近花了一天时间将ffmpeg/tools/build_stagefright执行成功,主要是交叉编译所需要的各种动态库的支持没链接上,导致各种报错,基本上网络上问到的问题我都碰到了,特此记录下来. ...

  3. FFmpeg在Android上的移植之第一步

    http://blog.sina.com.cn/s/blog_69a04cf40100x1fr.html 从事多媒体软件开发的人几乎没有不知道FFmpeg的,很多视频播放器都是基于FFmpeg开发的. ...

  4. FFmpeg的Android平台移植—编译篇

    摘要:本文主要介绍将FFmpeg音视频编解码库移植到Android平台上的编译和基本测试过程. 环境准备: ubuntu-12.04.5 android-ndk64-r10-linux-x86_64. ...

  5. FFmpeg在Android上的移植优化步骤

    http://blog.csdn.net/feixiang_john/article/details/7894188 从事多媒体软件开发的人几乎没有不知道FFmpeg的,很多视频播放器都是基于FFmp ...

  6. FFmpeg for Android compiled with x264, libass, fontconfig, freetype and fribidi

    android下打算使用ffmpeg的 drawtext ,不过需要 --enable-libfreetype  但是freetype是个第三方库,所以需要先编译freetype,然后再编译ffmpe ...

  7. FFmpeg编译Android版本

    FFmpeg是很好用的一个音视频库,功能强大,但是用起来并不是很方便.之前一直不想用FFmpeg,因为感觉编译太麻烦,但是到了不得不用的时候了,没办法,参考了网上大神的方法,在这里自己也记录一下方便以 ...

  8. FFmpeg 移植 Android

    近期项目需要解析苹果的HLS流媒体协议,而FFmpeg从0.11.1“Happiness”版本开始,才增加了对HLS协议的支持.目前网上关于FFmpeg编译移植的文章有很多,但大多都是对旧版本的说明. ...

  9. Mac下通过FFMpeg实现Android手机推流和播放

    一.Mac下搭建推流服务器(Nginx+RTMP+FFMpeg) 安装x264 git clone git://git.videolan.org/x264.git cd x264 ./configur ...

随机推荐

  1. QC缺陷管理操作-细说(转)

    一.缺陷常用字段说明 二.缺陷管理流程图 三.开发人员修改缺陷填写规范 四.项目经理决定延期修改缺陷 一.缺陷常用字段说明 1.摘要 对缺陷的简单描述.摘要包括该缺陷所属的模块名称-子模块名称,以及简 ...

  2. iOS上的jQuery.on()冒泡事件绑定 以及 iOS绝对定位元素中的输入框

    上周遇到两个坑. 一是jQuery的on方法 事件冒泡,在iOS中有问题. $("body").on("click",".contentup" ...

  3. jquery 实现层级下拉框联动效果 代码

    <select name="fCareId" id="fCareId"> <option selected="selected&qu ...

  4. switch_to 理解

    最近看linux0.11源码时,看到任务切换函数switch_to,感觉很晦涩,于是在网上查了一些资料,现在终于有些眉目,特记录于此,以方便大家参考,有什么错误或不足之处,还请大家指出~ switch ...

  5. C# Lambda Expressions 简介

    C# Lambda Expressions 简介 原文http://msdn2.microsoft.com/en-us/library/bb397687.aspx 翻译:朱之光 (larry1zhu@ ...

  6. hdu 1863 畅通工程(最小生成树,基础)

    题目 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include<string.h> #include <ma ...

  7. POJ 2299 Ultra-QuickSort (排序+数据离散化+求顺序数)

    题意:给出一个序列,求至少需要用到多少次操作,才能将序列从小到大排序. 思路: 数据量很大,n<500000,所以用冒泡模拟是超时的. 接下来就想到了求顺序数,总共需要交换的次数为每个数后面有多 ...

  8. 2013 Multi-University Training Contest 1 3-idiots

    解题报告: 记录 A_i 为长度为 i 的树枝的数量,并让 A 对它本身做 FFT,得到任意选两个树枝能得到的各个和的数量.枚举第三边, 计算出所有两边之和大于第三条边的方案数,并把前两条边包含最长边 ...

  9. React表单组件自定义-可控及不可控组件

    一.可控组件 <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset=" ...

  10. NewPascal(也许只是对FreePascal的一种封装)

    NewPascal is a breath of fresh air and long tradition! NewPascal offers a ready-to-be-used and up-to ...