项目地址,求star
https://github.com/979451341/AudioVideoStudyCodeTwo/tree/master/FFmpeg%E6%92%AD%E6%94%BE%E9%9F%B3%E4%B9%90%EF%BC%88%E4%BF%9D%E7%A8%8B%E5%BA%8F%E4%B8%8D%E6%AD%BB%EF%BC%89

这个是FFmpeg解码出音频,给AudioTrack播放,这回才算是java与c语言之间合作

这回我们将会从c++里调用java函数,下面就是关于c++使用AudioTrack的代码

    private AudioTrack audioTrack;
// 这个方法 是C进行调用 通道数
public void createTrack(int sampleRateInHz,int nb_channals) { int channaleConfig;//通道数
if (nb_channals == 1) {
channaleConfig = AudioFormat.CHANNEL_OUT_MONO;
} else if (nb_channals == 2) {
channaleConfig = AudioFormat.CHANNEL_OUT_STEREO;
}else {
channaleConfig = AudioFormat.CHANNEL_OUT_MONO;
}
int buffersize=AudioTrack.getMinBufferSize(sampleRateInHz,
channaleConfig, AudioFormat.ENCODING_PCM_16BIT);
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,sampleRateInHz,channaleConfig,
AudioFormat.ENCODING_PCM_16BIT,buffersize,AudioTrack.MODE_STREAM);
audioTrack.play();
} //C传入音频数据
public void playTrack(byte[] buffer, int lenth) {
if (audioTrack != null && audioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) {
audioTrack.write(buffer, 0, lenth);
}
}

我们再来看看c++的代码

首先注册组件,然后得到音频流

     av_register_all();
AVFormatContext *pFormatCtx = avformat_alloc_context();
//open
if (avformat_open_input(&pFormatCtx, input, NULL, NULL) != 0) {
LOGE("%s","打开输入视频文件失败");
return;
}
//获取视频信息
if(avformat_find_stream_info(pFormatCtx,NULL) < 0){
LOGE("%s","获取视频信息失败");
return;
}
int audio_stream_idx=-1;
int i=0;
for (int i = 0; i < pFormatCtx->nb_streams; ++i) {
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
LOGE(" 找到音频id %d", pFormatCtx->streams[i]->codec->codec_type);
audio_stream_idx=i;
break;
}
}

获取解码器

    //获取解码器上下文
AVCodecContext *pCodecCtx=pFormatCtx->streams[audio_stream_idx]->codec;
//获取解码器
AVCodec *pCodex = avcodec_find_decoder(pCodecCtx->codec_id);
//打开解码器
if (avcodec_open2(pCodecCtx, pCodex, NULL)<0) {
}

设置缓存区,保存解码前后的数据

    //申请avpakcet,装解码前的数据
AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));
//申请avframe,装解码后的数据
AVFrame *frame = av_frame_alloc();

设置解码出的声音一系列的属性,比如:单声道、双声道、采集点大小、采集率,还可以在这里对声音添加特效,

    //得到SwrContext ,进行重采样,具体参考http://blog.csdn.net/jammg/article/details/52688506
SwrContext *swrContext = swr_alloc();
//缓存区
uint8_t *out_buffer = (uint8_t *) av_malloc(44100 * 2);
//输出的声道布局(立体声)
uint64_t out_ch_layout=AV_CH_LAYOUT_STEREO;
//输出采样位数 16位
enum AVSampleFormat out_formart=AV_SAMPLE_FMT_S16;
//输出的采样率必须与输入相同
int out_sample_rate = pCodecCtx->sample_rate; //swr_alloc_set_opts将PCM源文件的采样格式转换为自己希望的采样格式
swr_alloc_set_opts(swrContext, out_ch_layout, out_formart, out_sample_rate,
pCodecCtx->channel_layout, pCodecCtx->sample_fmt, pCodecCtx->sample_rate, 0,
NULL); swr_init(swrContext);
// 获取通道数 2
int out_channer_nb = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO);

通过反射能够运行java函数

//    反射得到Class类型
jclass david_player = env->GetObjectClass(instance);
// 反射得到createAudio方法
jmethodID createAudio = env->GetMethodID(david_player, "createTrack", "(II)V");
// 反射调用createAudio
env->CallVoidMethod(instance, createAudio, 44100, out_channer_nb);
jmethodID audio_write = env->GetMethodID(david_player, "playTrack", "([BI)V");

在一边解码的时候一边给数据给AudioTrack播放

    while (av_read_frame(pFormatCtx, packet) >= 0) {
if (packet->stream_index == audio_stream_idx) {
// 解码 mp3 编码格式frame----pcm frame
avcodec_decode_audio4(pCodecCtx, frame, &got_frame, packet);
if (got_frame) {
LOGE("解码");
swr_convert(swrContext, &out_buffer, 44100 * 2, (const uint8_t **) frame->data, frame->nb_samples);
// 缓冲区的大小
int size = av_samples_get_buffer_size(NULL, out_channer_nb, frame->nb_samples,
AV_SAMPLE_FMT_S16, 1);
jbyteArray audio_sample_array = env->NewByteArray(size);
env->SetByteArrayRegion(audio_sample_array, 0, size, (const jbyte *) out_buffer);
env->CallVoidMethod(instance, audio_write, audio_sample_array, size);
env->DeleteLocalRef(audio_sample_array);
}
}
}

释放资源

    av_frame_free(&frame);
swr_free(&swrContext);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
env->ReleaseStringUTFChars(input_, input);

FFmpeg只是音视频处理的工具,他没有播放视频和音频的能力,所以我们需要SurfaceView显示视频,AudioTrack播放声音,而且OpenGLES也能播放声音,这个后面说

下一次就是说如何将视频的声音给听换掉,也就是将音视频的解码和编码都来搞一次

Android 音视频深入 十一 FFmpeg和AudioTrack播放声音(附源码下载)的更多相关文章

  1. Android中Canvas绘图基础详解(附源码下载) (转)

    Android中Canvas绘图基础详解(附源码下载) 原文链接  http://blog.csdn.net/iispring/article/details/49770651   AndroidCa ...

  2. Android 高仿 频道管理----网易、今日头条、腾讯视频 (可以拖动的GridView)附源码DEMO

    距离上次发布(android高仿系列)今日头条 --新闻阅读器 (二) 相关的内容已经半个月了,最近利用空闲时间,把今日头条客户端完善了下.完善的功能一个一个全部实现后,就放整个源码.开发的进度就是按 ...

  3. Android 音视频开发(三):使用 AudioTrack 播放PCM音频

    一.AudioTrack 基本使用 AudioTrack 类可以完成Android平台上音频数据的输出任务.AudioTrack有两种数据加载模式(MODE_STREAM和MODE_STATIC),对 ...

  4. Android 音视频深入 二十 FFmpeg视频压缩(附源码下载)

    项目源码https://github.com/979451341/FFmpegCompress 这个视频压缩是通过类似在mac终端上输入FFmpeg命令来完成,意思是我们需要在Android上达到能够 ...

  5. Android 音视频深入 六 使用FFmpeg播放视频(附源码下载)

    本篇项目地址,求starhttps://github.com/979451341/Audio-and-video-learning-materials/tree/master/FFmpeg%E6%92 ...

  6. Android 音视频深入 十六 FFmpeg 推流手机摄像头,实现直播 (附源码下载)

    源码地址https://github.com/979451341/RtmpCamera/tree/master 配置RMTP服务器,虽然之前说了,这里就直接粘贴过来吧 1.配置RTMP服务器 这个我不 ...

  7. Android 音视频深入 十五 FFmpeg 推流mp4文件(附源码下载)

    源码地址https://github.com/979451341/Rtmp 1.配置RTMP服务器 这个我不多说贴两个博客分别是在mac和windows环境上的,大家跟着弄 MAC搭建RTMP服务器h ...

  8. Android 音视频深入 十九 使用ijkplayer做个视频播放器(附源码下载)

    项目地址https://github.com/979451341/Myijkplayer 前段时候我觉得FFmpeg做个视频播放器好难,虽然播放上没问题,但暂停还有通过拖动进度条来设置播放进度,这些都 ...

  9. Android 音视频深入 八 小视频录制(附源码下载)

    本篇项目地址,求starthttps://github.com/979451341/Audio-and-video-learning-materials/tree/master/%E5%B0%8F%E ...

随机推荐

  1. cocos2d-x JS 富文本

    var str1 = "兑换成功后,系统会生成“";var str2 = "红包兑换码";var str3 = "”,请复制该兑换码,并粘贴在&quo ...

  2. Lambda表达式详解(例子详解)(转自:http://blog.csdn.net/damon316/article/details/51734661)

    Lambda表达式详解(例子详解)     lambda简介 lambda运算符:所有的lambda表达式都是用新的lambda运算符 " => ",可以叫他,“转到”或者 ...

  3. linux C access

    [1]作用 确定文件的访问权限 [2]头文件 #include <unistd.h> [3]函数定义 int access(const char * pathname,  int mode ...

  4. 创建多线程的第一种方式——创建Thread子类和重写run方法

    创建多线程的第一种方式——创建Thread子类和重写run方法: 第二种方式——实现Runnable接口,实现类传参给父类Thread类构造方法创建线程: 第一种方式创建Thread子类和重写run方 ...

  5. idea软件快速设置主题颜色

    打开idea,然后在File->setting->在搜索框里面输入theme->然后点击appearance->将theme的主题设置为IntellilJ,然后就可以了,如下图 ...

  6. JAVA值传递之基本数据类型和引用数据类型

    #1.基本数据类型值传递 package 经典小Demo.值传递; public class Test { public static void main(String[] args) { int a ...

  7. 异步async、await和Future的使用技巧

    由于前面的HTTP请求用到了异步操作,不少小伙伴都被这个问题折了下腰,今天总结分享下实战成果.Dart是一个单线程的语言,遇到有延迟的运算(比如IO操作.延时执行)时,线程中按顺序执行的运算就会阻塞, ...

  8. Quick Union

    Quick Union quick union就是快速连接 和quick find相同,也是构建一个数组id[],不过存的值换一种理解: 每个数组内的元素看做一个结点,结点内的值即id[i]看做i的前 ...

  9. 腾讯出品的一个超棒的 Android UI 库

    腾讯出品的一个超棒的 Android UI 库 相信做 Android 久了大家都会有种体会,那就是 Android 开发相对于前端开发来说统一的 UI 开源库比较少.造成这种现象的原因一方面是大多数 ...

  10. D1图论最短路专题

    第一题:poj3660 其实是Floyed算法的拓展:Floyd-Wareshall.初始时,若两头牛关系确定则fij = 1. 对于一头牛若确定的关系=n-1,这说明这头牛的排名是确定的. 通过寻找 ...