Android本地视频播放器开发--ffmpeg解码视频文件中的音频(1)

来源:互联网 发布:把淘宝链接转换成文字 编辑:程序博客网 时间:2024/05/16 18:17

在上一章中Android本地视频播放器开发--NDK编译FFmpeg能够获取编译出来的ffmpeg库,接下来就是调用ffmpeg来实现解码,这里我们先解码音频,然后在播放音频,同时为了适应性我会用不同的方法进行播放例如使用Android提供的AudioTrack,SDL、OpengAL,OpenSL ES,最终合入视频播放器的是OpenSL ES,这样可以减少CPU的利用率。接下来在这一章中,先简单的介绍如何解码音频,在下一章中,实现音频的播放。

首先就是编写调用ffmpeg的文件这里命名为:Decodec_Audio.c

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. #include <android/log.h>  
  5.   
  6. #include "VideoPlayerDecode.h"  
  7. #include "../ffmpeg/libavutil/avutil.h"  
  8. #include "../ffmpeg/libavcodec/avcodec.h"  
  9. #include "../ffmpeg/libavformat/avformat.h"  
  10.   
  11. #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "graduation", __VA_ARGS__))  
  12.   
  13. AVFormatContext *pFormatCtx = NULL;  
  14. int             audioStream, delay_time, videoFlag = 0;  
  15. AVCodecContext  *aCodecCtx;  
  16. AVCodec         *aCodec;  
  17. AVFrame         *aFrame;  
  18. AVPacket        packet;  
  19. int  frameFinished = 0;  
  20.   
  21.     JNIEXPORT jint JNICALL Java_com_zhangjie_graduation_videopalyer_jni_VideoPlayerDecode_VideoPlayer  
  22. (JNIEnv *env, jclass clz, jstring fileName)  
  23. {  
  24.     const char* local_title = (*env)->GetStringUTFChars(env, fileName, NULL);  
  25.     av_register_all();//注册所有支持的文件格式以及编解码器  
  26.     /* 
  27.      *只读取文件头,并不会填充流信息 
  28.      */  
  29.     if(avformat_open_input(&pFormatCtx, local_title, NULL, NULL) != 0)  
  30.         return -1;  
  31.     /* 
  32.      *获取文件中的流信息,此函数会读取packet,并确定文件中所有流信息, 
  33.      *设置pFormatCtx->streams指向文件中的流,但此函数并不会改变文件指针, 
  34.      *读取的packet会给后面的解码进行处理。 
  35.      */  
  36.     if(avformat_find_stream_info(pFormatCtx, NULL) < 0)  
  37.         return -1;  
  38.     /* 
  39.      *输出文件的信息,也就是我们在使用ffmpeg时能够看到的文件详细信息, 
  40.      *第二个参数指定输出哪条流的信息,-1代表ffmpeg自己选择。最后一个参数用于 
  41.      *指定dump的是不是输出文件,我们的dump是输入文件,因此一定要为0 
  42.      */  
  43.     av_dump_format(pFormatCtx, -1, local_title, 0);  
  44.     int i = 0;  
  45.     for(i=0; i< pFormatCtx->nb_streams; i++)  
  46.     {  
  47.         if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){  
  48.             audioStream = i;  
  49.             break;  
  50.         }  
  51.     }  
  52.   
  53.     if(audioStream < 0)return -1;  
  54.     aCodecCtx = pFormatCtx->streams[audioStream]->codec;  
  55.     aCodec = avcodec_find_decoder(aCodecCtx->codec_id);  
  56.     if(avcodec_open2(aCodecCtx, aCodec, NULL) < 0)return -1;  
  57.     aFrame = avcodec_alloc_frame();  
  58.     if(aFrame == NULL)return -1;  
  59.     int ret;  
  60.     while(videoFlag != -1)  
  61.     {  
  62.         if(av_read_frame(pFormatCtx, &packet) < 0)break;  
  63.         if(packet.stream_index == audioStream)  
  64.         {  
  65.             ret = avcodec_decode_audio4(aCodecCtx, aFrame, &frameFinished, &packet);  
  66.             if(ret > 0 && frameFinished)  
  67.             {  
  68.                 int data_size = av_samples_get_buffer_size(  
  69.                         aFrame->linesize,aCodecCtx->channels,  
  70.                         aFrame->nb_samples,aCodecCtx->sample_fmt, 0);  
  71.                 LOGI("audioDecodec  :%d",data_size);  
  72.             }  
  73.   
  74.         }  
  75.         usleep(50000);  
  76.         while(videoFlag != 0)  
  77.         {  
  78.             if(videoFlag == 1)//暂停  
  79.             {  
  80.                 sleep(1);  
  81.             }else if(videoFlag == -1) //停止  
  82.             {  
  83.                 break;  
  84.             }  
  85.         }  
  86.         av_free_packet(&packet);  
  87.     }  
  88.     av_free(aFrame);  
  89.     avcodec_close(aCodecCtx);  
  90.     avformat_close_input(&pFormatCtx);  
  91.     (*env)->ReleaseStringUTFChars(env, fileName, local_title);  
  92. }  
  93.   
  94. JNIEXPORT jint JNICALL Java_com_zhangjie_graduation_videopalyer_jni_VideoPlayerDecode_VideoPlayerPauseOrPlay  
  95.   (JNIEnv *env, jclass clz)  
  96. {  
  97.         if(videoFlag == 1)  
  98.         {  
  99.                 videoFlag = 0;  
  100.         }else if(videoFlag == 0){  
  101.                 videoFlag = 1;  
  102.         }  
  103.         return videoFlag;  
  104. }  
  105.   
  106. JNIEXPORT jint JNICALL Java_com_zhangjie_graduation_videopalyer_jni_VideoPlayerDecode_VideoPlayerStop  
  107.   (JNIEnv *env, jclass clz)  
  108. {  
  109.         videoFlag = -1;  
  110. }  

接下来就是编写Android.mk:

[html] view plaincopy
  1. #######################################################  
  2. ##########              ffmpeg-prebuilt         #######  
  3. #######################################################  
  4. #declare the prebuilt library  
  5. include $(CLEAR_VARS)  
  6. LOCAL_MODULE :ffmpeg-prebuilt  
  7. LOCAL_SRC_FILES :ffmpeg/android/armv7-a/libffmpeg-neon.so  
  8. LOCAL_EXPORT_C_INCLUDES :ffmpeg/android/armv7-a/include  
  9. LOCAL_EXPORT_LDLIBS :ffmpeg/android/armv7-a/libffmpeg-neon.so  
  10. LOCAL_PRELINK_MODULE :true  
  11. include $(PREBUILT_SHARED_LIBRARY)  
  12.   
  13. ########################################################  
  14. ##              ffmpeg-test-neno.so             ########  
  15. ########################################################  
  16. include $(CLEAR_VARS)  
  17. TARGET_ARCH_ABI=armeabi-v7a  
  18. LOCAL_ARM_MODE=arm  
  19. LOCAL_ARM_NEON=true  
  20. LOCAL_ALLOW_UNDEFINED_SYMBOLS=false  
  21. LOCAL_MODULE :ffmpeg-test-neon  
  22. LOCAL_SRC_FILES :jniffmpeg/Decodec_Audio.c  
  23.   
  24. LOCAL_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/android/armv7-a/include \  
  25.                     $(LOCAL_PATH)/ffmpeg \  
  26.                     $(LOCAL_PATH)/ffmpeg/libavutil \  
  27.                     $(LOCAL_PATH)/ffmpeg/libavcodec \  
  28.                     $(LOCAL_PATH)/ffmpeg/libavformat \  
  29.                     $(LOCAL_PATH)/ffmpeg/libavcodec \  
  30.                     $(LOCAL_PATH)/ffmpeg/libswscale \  
  31.                     $(LOCAL_PATH)/jniffmpeg \  
  32.                     $(LOCAL_PATH)  
  33. LOCAL_SHARED_LIBRARY :ffmpeg-prebuilt  
  34. LOCAL_LDLIBS    := -llog -ljnigraphics -lz -lm $(LOCAL_PATH)/ffmpeg/android/armv7-a/libffmpeg-neon.so  
  35. include $(BUILD_SHARED_LIBRARY)  

然后在终端运行ndk-build,运行结果如下:

[cpp] view plaincopy
  1. root@zhangjie:/Graduation/jni# ndk-build  
  2. Install        : libffmpeg-neon.so => libs/armeabi/libffmpeg-neon.so  
  3. Compile arm    : ffmpeg-test-neon <= Decodec_Audio.c  
  4. SharedLibrary  : libffmpeg-test-neon.so  
  5. Install        : libffmpeg-test-neon.so => libs/armeabi/libffmpeg-test-neon.so  

把编译出来的
[cpp] view plaincopy
  1. libffmpeg-test-neon.so<pre name="code" class="cpp" style="font-size: 14px;">libffmpeg-neon.so</pre><p></p>  
  2. <pre></pre>  
  3. <p></p>  
  4. <p><span style="font-size:14px">拷贝到之前android功能下的libs/armeabi目录下面,点击视频,视频文件开始解码音频,当解码成功,则打印出解码音频包的大小:</span></p>  
  5. <p><span style="font-size:14px"><img src="" alt=""><br>  
  6. </span></p>  
  7. <p><span style="font-size:14px"></span></p><pre name="code" class="cpp">06-07 04:51:30.953: I/graduation(7014): audioDecodec  :2048  
  8. 06-07 04:51:31.000: I/graduation(7014): audioDecodec  :2048  
  9. 06-07 04:51:31.109: I/graduation(7014): audioDecodec  :2048  
  10. 06-07 04:51:31.156: I/graduation(7014): audioDecodec  :2048  
  11. 06-07 04:51:31.257: I/graduation(7014): audioDecodec  :2048  
  12. 06-07 04:51:31.304: I/graduation(7014): audioDecodec  :2048  
  13. 06-07 04:51:31.406: I/graduation(7014): audioDecodec  :2048  
  14. 06-07 04:51:31.460: I/graduation(7014): audioDecodec  :2048  
  15. 06-07 04:51:31.554: I/graduation(7014): audioDecodec  :2048  
  16. 06-07 04:51:31.609: I/graduation(7014): audioDecodec  :2048  
  17. 06-07 04:51:31.710: I/graduation(7014): audioDecodec  :2048  
  18. 06-07 04:51:31.757: I/graduation(7014): audioDecodec  :2048  
  19. 06-07 04:51:31.859: I/graduation(7014): audioDecodec  :2048  
  20. 06-07 04:51:31.914: I/graduation(7014): audioDecodec  :2048  
  21. 06-07 04:51:32.015: I/graduation(7014): audioDecodec  :2048  
  22. 06-07 04:51:32.062: I/graduation(7014): audioDecodec  :2048  
  23. 06-07 04:51:32.164: I/graduation(7014): audioDecodec  :2048  
  24. 06-07 04:51:32.210: I/graduation(7014): audioDecodec  :2048  
  25. 06-07 04:51:32.312: I/graduation(7014): audioDecodec  :2048  
  26. 06-07 04:51:32.367: I/graduation(7014): audioDecodec  :2048  
  27. 06-07 04:51:32.468: I/graduation(7014): audioDecodec  :2048  
  28. 06-07 04:51:32.515: I/graduation(7014): audioDecodec  :2048  
  29. 06-07 04:51:32.617: I/graduation(7014): audioDecodec  :2048  
  30. 06-07 04:51:32.671: I/graduation(7014): audioDecodec  :2048  
  31. 06-07 04:51:32.773: I/graduation(7014): audioDecodec  :2048</pre><br>  
  32. 在logcat里面可以看到解码音频成功,下面一章我们将解码出来的音频进行播放。<p></p>  
  33. 处在:http://blog.csdn.net/jwzhangjie/article/details/9046427
0 0
原创粉丝点击