zoukankan      html  css  js  c++  java
  • FFmpeg在Android使用3

            android 移植ffmpeg后so库的使用

      只需要将我们编译好的ffmpeg的so包(在/obj/local/armeabi/libffmpeg.so)copy到所在ndk下的platformsandroid-8arch-armusrlib文件夹下就可以了。
      再看下我们的代码吧:
    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.   
    9.         /* Create a TextView and set its content.  
    10.          * the text is retrieved by calling a native  
    11.          * function.  
    12.          */  
    13.         TextView  tv = new TextView(this);  
    14.         String str = String.valueOf(stringFromJNI());  
    15.         str = str +" "+getVoice();  
    16.         tv.setText(str);  
    17.         setContentView(tv);  
    18.     }  
    19.   
    20.     public native int getVoice();     
    21.     public native String  stringFromJNI();  
    22.     public native String  unimplementedStringFromJNI();  
    23.   
    24.       
    25.     static {    
    26.         System.loadLibrary("ffmpeg");    
    27.          System.loadLibrary("hello-jni");    
    28.      }   
    29. }  
    这个是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.   
    25. #define LOG_TAG    "***************************lixingyun*****************" // 这个是自定义的LOG的标识  
    26. #undef LOG // 取消默认的LOG  
    27. #define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) // 定义LOG类型  
    28. #define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) // 定义LOG类型  
    29. #define LOGW(...)  __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) // 定义LOG类型  
    30. #define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) // 定义LOG类型  
    31. #define LOGF(...)  __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__) // 定义LOG类型  
    32. /* This is a trivial JNI example where we use a native method  
    33.  * to return a new VM String. See the corresponding Java source  
    34.  * file located at:  
    35.  *  
    36.  *   apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java  
    37.  */  
    38. JNIEXPORT jstring Java_com_example_hellojni_HelloJni_stringFromJNI(JNIEnv* env,  
    39.         jobject thiz) {  
    40.     char str[25];  
    41.     sprintf(str, "%d", avcodec_version());  
    42.   
    43.     return (*env)->NewStringUTF(env, str);  
    44.     // return (*env)->NewStringUTF(env, "Hello from JNI !");0  
    45. }  
    46.   
    47. JNIEXPORT jint Java_com_example_hellojni_HelloJni_getVoice(JNIEnv* env,  
    48.         jobject thiz) {  
    49.     int flag = 0;  
    50.     AVPacket aacpkt;  
    51.     aacpkt.data = NULL;  
    52.     aacpkt.size = 0;  
    53.   
    54.     const char *filename = "file:/sdcard/test.mp3";  
    55.     av_init_packet(&aacpkt);  
    56.     av_register_all(); //注册所有可解码类型  
    57.   
    58.     AVFormatContext *pInFmtCtx = NULL; //文件格式  
    59.     AVCodecContext *pInCodecCtx = NULL; //编码格式  
    60.   
    61.     pInFmtCtx = avformat_alloc_context();  
    62.   
    63.     if (av_open_input_file(&pInFmtCtx, filename, NULL, 0, NULL) != 0) //获取文件格式  
    64.         LOGE("av_open_input_file error ");  
    65.     if (av_find_stream_info(pInFmtCtx) 0) //获取文件内音视频流的信息  
    66.         LOGE("av_find_stream_info error ");  
    67.     unsigned int j;  
    68.     // Find the first audio stream  
    69.   
    70.     int audioStream = -1;  
    71.     // Dump information about file onto standard error  
    72.     dump_format(pInFmtCtx, 0, filename, 0);  
    73.   
    74.     //从FormatdContext的中找到对应流对应的编码类型,若是CODEC_TYPE_AUDIO则表示是音频  
    75.     for (j = 0; j pInFmtCtx->nb_streams; j++) //找到音频对应的stream  
    76.         if (pInFmtCtx->streams[j]->codec->codec_type == CODEC_TYPE_AUDIO) {  
    77.             audioStream = j;  
    78.             break;  
    79.         }  
    80.     if (audioStream == -1) {  
    81.         printf("input file has no audio stream ");  
    82.         return 0; // Didn't find a audio stream  
    83.   
    84.     }  
    85.     LOGE("audio stream num: %d ", audioStream);  
    86.   
    87.     pInCodecCtx = pInFmtCtx->streams[audioStream]->codec; //音频的编码上下文  
    88.     AVCodec *pInCodec = NULL;  
    89.     /* FILE *file3 = fopen("codec_private_data_size.txt","w");  
    90.      for(int i = 0; i <200000; i++)  
    91.      {  
    92.      pInCodec = avcodec_find_decoder((CodecID)i);  
    93.      if (pInCodec!=NULL)  
    94.      {  
    95.      fprintf(file3,"%s %d ",pInCodec->name,pInCodec->priv_data_size );  
    96.      }  
    97.      }  
    98.      fclose(file3);  
    99.      system("pause");  
    100.      */  
    101.     pInCodec = avcodec_find_decoder(pInCodecCtx->codec_id); //根据编码ID找到用于解码的结构体  
    102.     if (pInCodec == NULL) {  
    103.         printf("error no Codec found ");  
    104.         return -1; // Codec not found  
    105.     }  
    106.   
    107.     //使用test的代替pInCodecCtx也可以完成解码,可以看出只要获取以下几个重要信息就可以实现解码和重采样  
    108.     AVCodecContext *test = avcodec_alloc_context();  
    109.     test->bit_rate = pInCodecCtx->bit_rate; //重采样用  
    110.     test->sample_rate = pInCodecCtx->sample_rate; //重采样用  
    111.     test->channels = pInCodecCtx->channels; //重采样用  
    112.     test->extradata = pInCodecCtx->extradata; //若有则必有  
    113.     test->extradata_size = pInCodecCtx->extradata_size; //若有则必要  
    114.     test->codec_type = CODEC_TYPE_AUDIO; //不必要  
    115.     test->block_align = pInCodecCtx->block_align; //必要  
    116.   
    117.     if (avcodec_open(test, pInCodec) 0) //将两者结合以便在下面的解码函数中调用pInCodec中的对应解码函数  
    118.             {  
    119.         printf("error avcodec_open failed. ");  
    120.         return -1; // Could not open codec  
    121.   
    122.     }  
    123.   
    124.     if (avcodec_open(pInCodecCtx, pInCodec) 0) {  
    125.         printf("error avcodec_open failed. ");  
    126.         return -1; // Could not open codec  
    127.   
    128.     }  
    129.   
    130.     static AVPacket packet;  
    131.   
    132.     LOGI(" bit_rate = %d  ", pInCodecCtx->bit_rate);  
    133.     LOGI(" sample_rate = %d  ", pInCodecCtx->sample_rate);  
    134.     LOGI(" channels = %d  ", pInCodecCtx->channels);  
    135.     LOGI(" code_name = %s  ", pInCodecCtx->codec->name);  
    136.     //LOGI("extra data size: %d :data%x %x %x %x ",pInCodecCtx->extradata_size,pInCodecCtx->extradata[0]  
    137.     // ,pInCodecCtx->extradata[1],pInCodecCtx->extradata[2],pInCodecCtx->extradata[3]);  
    138.     LOGI(" block_align = %d ", pInCodecCtx->block_align);  
    139.     /********************************************************/  
    140.     unsigned char *outbuf = NULL;  
    141.     outbuf = (unsigned char *) malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE * 2);  
    142.     int outsize;  
    143.     outsize = AVCODEC_MAX_AUDIO_FRAME_SIZE * 2;  
    144.     int len = 0;  
    145.     int size = 0;  
    146.   
    147.     FILE *out_fp;  
    148.   
    149.     out_fp = fopen("out.dat", "wb+");  
    150.     while (av_read_frame(pInFmtCtx, &aacpkt) >= 0) {  
    151.         LOGI("***************************");  
    152.   
    153.         if (aacpkt.stream_index == audioStream) {  
    154.             int declen = 0;  
    155.             size = aacpkt.size;  
    156.             while (aacpkt.size > 0) {  
    157.                 outsize = AVCODEC_MAX_AUDIO_FRAME_SIZE * 2;  
    158.                 memset(outbuf, 0, outsize);  
    159.                 len = avcodec_decode_audio3(pInCodecCtx, (int16_t *) outbuf,  
    160.                         &outsize, &aacpkt);  
    161.                 if (len 0) {  
    162.                     printf("avcodec_decode_audio3 failed! ");  
    163.                     break;  
    164.                 }  
    165.                 if (outsize > 0) {  
    166.                     fwrite(outbuf, 1, outsize, out_fp);  
    167.                     printf("write %d bytes ", outsize);  
    168.                 }  
    169.                 declen += len;  
    170.                 if (declen == size) {  
    171.                     av_free_packet(&aacpkt);  
    172.                     printf("packet decoded succeed! ");  
    173.                     break;  
    174.                 } else if (declen size) {  
    175.                     aacpkt.size -= len;  
    176.                     aacpkt.data += len;  
    177.                 } else {  
    178.                     printf("decode error! ");  
    179.                     break;  
    180.                 }  
    181.   
    182.             }  
    183.   
    184.         }  
    185.   
    186.     }  
    187.   
    188.     fclose(out_fp);  
    189.     // Close the codec  
    190.     avcodec_close(pInCodecCtx);  
    191.   
    192.     // Close the video file  
    193.     av_close_input_file(pInFmtCtx);  
    194.   
    195.     return flag;  
    196.   
    197. }  


      微笑其中的LOGE那几个就是Android下的哦。
      再附上Android.mk的东西吧:
     
    1. LOCAL_PATH := $(call my-dir)  
    2.   
    3. include $(CLEAR_VARS)  
    4. PATH_TO_FFMPEG_SOURCE:=$(LOCAL_PATH)/ffmpeg    
    5. LOCAL_C_INCLUDES += $(PATH_TO_FFMPEG_SOURCE)    
    6. LOCAL_LDLIBS := -lffmpeg -llog    
    7. LOCAL_MODULE    := hello-jni  
    8. LOCAL_SRC_FILES := hello-jni.c  
    9.   
    10. include $(BUILD_SHARED_LIBRARY)  
     
    哈哈,这样就Ok了。
    源码也附上吧.
     
  • 相关阅读:
    Math对象
    MDN中的对象原型
    构造函数的静态成员和实例成员
    js对象的九大特点
    对象数据的使用方法
    创建对象的所有方式
    Linux下gcc编译器的使用
    Linux vim环境设置
    Linux下is not in the sudoers file解决方法
    mySQL相关函数的使用
  • 原文地址:https://www.cnblogs.com/android-blogs/p/5643533.html
Copyright © 2011-2022 走看看