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

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

#include <stdio.h>#include <stdlib.h>#include <android/log.h>#include "VideoPlayerDecode.h"#include "../ffmpeg/libavutil/avutil.h"#include "../ffmpeg/libavcodec/avcodec.h"#include "../ffmpeg/libavformat/avformat.h"#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "graduation", __VA_ARGS__))AVFormatContext *pFormatCtx = NULL;int             audioStream, delay_time, videoFlag = 0;AVCodecContext  *aCodecCtx;AVCodec         *aCodec;AVFrame         *aFrame;AVPacket        packet;int  frameFinished = 0;JNIEXPORT jint JNICALL Java_com_zhangjie_graduation_videopalyer_jni_VideoPlayerDecode_VideoPlayer(JNIEnv *env, jclass clz, jstring fileName){const char* local_title = (*env)->GetStringUTFChars(env, fileName, NULL);av_register_all();//注册所有支持的文件格式以及编解码器/* *只读取文件头,并不会填充流信息 */if(avformat_open_input(&pFormatCtx, local_title, NULL, NULL) != 0)return -1;/* *获取文件中的流信息,此函数会读取packet,并确定文件中所有流信息, *设置pFormatCtx->streams指向文件中的流,但此函数并不会改变文件指针, *读取的packet会给后面的解码进行处理。 */if(avformat_find_stream_info(pFormatCtx, NULL) < 0)return -1;/* *输出文件的信息,也就是我们在使用ffmpeg时能够看到的文件详细信息, *第二个参数指定输出哪条流的信息,-1代表ffmpeg自己选择。最后一个参数用于 *指定dump的是不是输出文件,我们的dump是输入文件,因此一定要为0 */av_dump_format(pFormatCtx, -1, local_title, 0);int i = 0;for(i=0; i< pFormatCtx->nb_streams; i++){if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){audioStream = i;break;}}if(audioStream < 0)return -1;aCodecCtx = pFormatCtx->streams[audioStream]->codec;aCodec = avcodec_find_decoder(aCodecCtx->codec_id);if(avcodec_open2(aCodecCtx, aCodec, NULL) < 0)return -1;aFrame = avcodec_alloc_frame();if(aFrame == NULL)return -1;int ret;while(videoFlag != -1){if(av_read_frame(pFormatCtx, &packet) < 0)break;if(packet.stream_index == audioStream){ret = avcodec_decode_audio4(aCodecCtx, aFrame, &frameFinished, &packet);if(ret > 0 && frameFinished){int data_size = av_samples_get_buffer_size(aFrame->linesize,aCodecCtx->channels,aFrame->nb_samples,aCodecCtx->sample_fmt, 0);LOGI("audioDecodec  :%d",data_size);}}usleep(50000);while(videoFlag != 0){if(videoFlag == 1)//暂停{sleep(1);}else if(videoFlag == -1) //停止{break;}}av_free_packet(&packet);}av_free(aFrame);avcodec_close(aCodecCtx);avformat_close_input(&pFormatCtx);(*env)->ReleaseStringUTFChars(env, fileName, local_title);}JNIEXPORT jint JNICALL Java_com_zhangjie_graduation_videopalyer_jni_VideoPlayerDecode_VideoPlayerPauseOrPlay  (JNIEnv *env, jclass clz){        if(videoFlag == 1)        {                videoFlag = 0;        }else if(videoFlag == 0){                videoFlag = 1;        }        return videoFlag;}JNIEXPORT jint JNICALL Java_com_zhangjie_graduation_videopalyer_jni_VideoPlayerDecode_VideoPlayerStop  (JNIEnv *env, jclass clz){        videoFlag = -1;}


接下来就是编写Android.mk:

#################################################################              ffmpeg-prebuilt         ###############################################################declare the prebuilt libraryinclude $(CLEAR_VARS)LOCAL_MODULE := ffmpeg-prebuiltLOCAL_SRC_FILES := ffmpeg/android/armv7-a/libffmpeg-neon.soLOCAL_EXPORT_C_INCLUDES := ffmpeg/android/armv7-a/includeLOCAL_EXPORT_LDLIBS := ffmpeg/android/armv7-a/libffmpeg-neon.soLOCAL_PRELINK_MODULE := trueinclude $(PREBUILT_SHARED_LIBRARY)##########################################################              ffmpeg-test-neno.so             ################################################################include $(CLEAR_VARS)TARGET_ARCH_ABI=armeabi-v7aLOCAL_ARM_MODE=armLOCAL_ARM_NEON=trueLOCAL_ALLOW_UNDEFINED_SYMBOLS=falseLOCAL_MODULE := ffmpeg-test-neonLOCAL_SRC_FILES := jniffmpeg/Decodec_Audio.cLOCAL_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/android/armv7-a/include \                    $(LOCAL_PATH)/ffmpeg \                    $(LOCAL_PATH)/ffmpeg/libavutil \                    $(LOCAL_PATH)/ffmpeg/libavcodec \                    $(LOCAL_PATH)/ffmpeg/libavformat \                    $(LOCAL_PATH)/ffmpeg/libavcodec \                    $(LOCAL_PATH)/ffmpeg/libswscale \                    $(LOCAL_PATH)/jniffmpeg \                    $(LOCAL_PATH)LOCAL_SHARED_LIBRARY := ffmpeg-prebuiltLOCAL_LDLIBS    := -llog -ljnigraphics -lz -lm $(LOCAL_PATH)/ffmpeg/android/armv7-a/libffmpeg-neon.soinclude $(BUILD_SHARED_LIBRARY)


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

root@zhangjie:/Graduation/jni# ndk-buildInstall        : libffmpeg-neon.so => libs/armeabi/libffmpeg-neon.soCompile arm    : ffmpeg-test-neon <= Decodec_Audio.cSharedLibrary  : libffmpeg-test-neon.soInstall        : libffmpeg-test-neon.so => libs/armeabi/libffmpeg-test-neon.so


把编译出来的

libffmpeg-test-neon.so
libffmpeg-neon.so

   

拷贝到之前android功能下的libs/armeabi目录下面,点击视频,视频文件开始解码音频,当解码成功,则打印出解码音频包的大小:


06-07 04:51:30.953: I/graduation(7014): audioDecodec  :204806-07 04:51:31.000: I/graduation(7014): audioDecodec  :204806-07 04:51:31.109: I/graduation(7014): audioDecodec  :204806-07 04:51:31.156: I/graduation(7014): audioDecodec  :204806-07 04:51:31.257: I/graduation(7014): audioDecodec  :204806-07 04:51:31.304: I/graduation(7014): audioDecodec  :204806-07 04:51:31.406: I/graduation(7014): audioDecodec  :204806-07 04:51:31.460: I/graduation(7014): audioDecodec  :204806-07 04:51:31.554: I/graduation(7014): audioDecodec  :204806-07 04:51:31.609: I/graduation(7014): audioDecodec  :204806-07 04:51:31.710: I/graduation(7014): audioDecodec  :204806-07 04:51:31.757: I/graduation(7014): audioDecodec  :204806-07 04:51:31.859: I/graduation(7014): audioDecodec  :204806-07 04:51:31.914: I/graduation(7014): audioDecodec  :204806-07 04:51:32.015: I/graduation(7014): audioDecodec  :204806-07 04:51:32.062: I/graduation(7014): audioDecodec  :204806-07 04:51:32.164: I/graduation(7014): audioDecodec  :204806-07 04:51:32.210: I/graduation(7014): audioDecodec  :204806-07 04:51:32.312: I/graduation(7014): audioDecodec  :204806-07 04:51:32.367: I/graduation(7014): audioDecodec  :204806-07 04:51:32.468: I/graduation(7014): audioDecodec  :204806-07 04:51:32.515: I/graduation(7014): audioDecodec  :204806-07 04:51:32.617: I/graduation(7014): audioDecodec  :204806-07 04:51:32.671: I/graduation(7014): audioDecodec  :204806-07 04:51:32.773: I/graduation(7014): audioDecodec  :2048

在logcat里面可以看到解码音频成功,下面一章我们将解码出来的音频进行播放。

更多相关文章

  1. Android开发实践:Android.mk模板
  2. Android(安卓)获取ROOT权限原理解析
  3. Flutter 解决webview_flutter 插件Android端无法上传文件问题
  4. 手把手教您-将Android的Camera源码导入到eclipse中进行开发
  5. Android中怎么使图片显示
  6. Android数据存储方案ContentProvider存储数据
  7. 使用Android内部的DownloadProvider下载文件,并获取cache权限
  8. android之文件上传
  9. NPM 和webpack 的基础使用

随机推荐

  1. MySQL之PXC集群搭建的方法步骤
  2. Mysql 用户权限管理实现
  3. MySQL 查询速度慢的原因
  4. MySQL 全文索引使用指南
  5. 52条SQL语句教你性能优化
  6. 简单了解 MySQL 中相关的锁
  7. mysql在项目中怎么选事务隔离级别
  8. .Net Core导入千万级数据至Mysql的步骤
  9. MySQL大小写敏感的注意事项
  10. MySQL 使用事件(Events)完成计划任务