FFmpeg(七)音频的播放
一、Open SL ES播放声音流程
简单说明
Open SL ES是android内部的接口,本身可以解码音频,但是我们用FFmpeg,,也可以来录音 。
SL引擎:上下文
混音器:两路声音的混合
Play:控制播放 , 有一个队列来存储播放的数据,设置一个回调的方法,播放之后调一下回调方法拿数据,
二、函数说明
1.初始化引擎
SLresult re; //存放引擎本身,上下文
SLEngineItf en; //存放引擎的接口
slCreateEngine(&engineSL,0,0,0,0,0);//创建对象
Realize(engineSL,SL_BOOLEAN_FALSE);//实例化(内部的数据分配内存) 都是这个模式,先创建,然后实例化,在获取接口
GetInterface(engineSL,SL_IID_ENGINE,&en);//获取接口SLEngineItf ,通过第二个参数获取对应的接口
2.输出设备
SLObjectItf mix = NULL;
SLresult re = 0;
CreateOutputMix(eng,&mix,0,0,0);//创建输出设备
Realize(mix,SL_BOOLEAN_FALSE);//实例化
//下面两个是存储
SLDataLocator_OutputMix outmix = {SL_DATALOCATOR_OUTPUTMIX,mix};
SLDataSink audioSink= {&outmix,0};
3.配置音频信息
SLDataLocator_AndroidSimpleBufferQueue que = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,10}; //以什么样的方式交互
//音频格式
SLDataFormat_PCM pcm = {
SL_DATAFORMAT_PCM,//支持PCM格式的数据
2,// 声道数
SL_SAMPLINGRATE_44_1,//44100Hz的频率(采样率)
SL_PCMSAMPLEFORMAT_FIXED_16, //位数
SL_PCMSAMPLEFORMAT_FIXED_16,//和位数一支即可
SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT,//立体声(前作前右)
SL_BYTEORDER_LITTLEENDIAN //字节序,小端还是大端,默认小端 (高位还是地位在前)
};
SLDataSource ds = {&que,&pcm};//包装成配置信息
4.创建播放器
SLObjectItf player = NULL;
SLPlayItf iplayer = NULL;
CreateAudioPlayer(eng,&player,&ds,&audioSink,sizeof(ids)/sizeof(SLInterfaceID),ids,req);//利用前面的配置来创建
Realize(player,SL_BOOLEAN_FALSE);//实例化
GetInterface(player,SL_IID_PLAY,&iplayer); // 获取接口
GetInterface(player,SL_IID_BUFFERQUEUE,&pcmQue);//缓冲队列
(*pcmQue)->RegisterCallback(pcmQue,PcmCall,0);//设置回调函数,播放队列空调用
(*iplayer)->SetPlayState(iplayer,SL_PLAYSTATE_PLAYING); //设置为播放状态play状态、暂停状态、
(*pcmQue)->Enqueue(pcmQue,"",1); //启动队列回调 先压入一点数据
代码展示:
- #include <jni.h>
- #include <string>
- #include <SLES/OpenSLES.h>
- #include <SLES/OpenSLES_Android.h>
- #include <android/log.h>
- #define LOGD(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR,"ywl5320",FORMAT,##__VA_ARGS__);
- //1 创建引擎
- static SLObjectItf engineSL = NULL;
- SLEngineItf CreateSL()
- {
- SLresult re;
- SLEngineItf en;
- re = slCreateEngine(&engineSL,,,,,);
- if(re != SL_RESULT_SUCCESS) return NULL;
- re = (*engineSL)->Realize(engineSL,SL_BOOLEAN_FALSE);
- if(re != SL_RESULT_SUCCESS) return NULL;
- re = (*engineSL)->GetInterface(engineSL,SL_IID_ENGINE,&en);
- if(re != SL_RESULT_SUCCESS) return NULL;
- return en;
- }
- void PcmCall(SLAndroidSimpleBufferQueueItf bf,void *contex)
- {
- LOGD("PcmCall");
- static FILE *fp = NULL;
- static char *buf = NULL;
- if(!buf)
- {
- buf = new char[*];
- }
- if(!fp)
- {
- fp = fopen("/sdcard/test.pcm","rb");
- }
- if(!fp)return;
- if(feof(fp) == )
- {
- int len = fread(buf,,,fp);
- if(len > )
- (*bf)->Enqueue(bf,buf,len);
- }
- }
- extern "C"
- JNIEXPORT jstring
- JNICALL
- Java_aplay_testopensl_MainActivity_stringFromJNI(
- JNIEnv *env,
- jobject /* this */) {
- std::string hello = "Hello from C++";
- //1 创建引擎
- SLEngineItf eng = CreateSL();
- if(eng){
- LOGD("CreateSL success! ");
- }else{
- LOGD("CreateSL failed! ");
- }
- //2 创建混音器
- SLObjectItf mix = NULL;
- SLresult re = ;
- re = (*eng)->CreateOutputMix(eng,&mix,,,);
- if(re !=SL_RESULT_SUCCESS )
- {
- LOGD("SL_RESULT_SUCCESS failed!");
- }
- re = (*mix)->Realize(mix,SL_BOOLEAN_FALSE);
- if(re !=SL_RESULT_SUCCESS )
- {
- LOGD("(*mix)->Realize failed!");
- }
- SLDataLocator_OutputMix outmix = {SL_DATALOCATOR_OUTPUTMIX,mix};
- SLDataSink audioSink= {&outmix,};
- //3 配置音频信息
- //缓冲队列
- SLDataLocator_AndroidSimpleBufferQueue que = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,}; //以什么样的方式交互
- //音频格式
- SLDataFormat_PCM pcm = {
- SL_DATAFORMAT_PCM,//支持PCM格式的数据
- ,// 声道数
- SL_SAMPLINGRATE_44_1,//44100Hz的频率(采样率)
- SL_PCMSAMPLEFORMAT_FIXED_16, //位数
- SL_PCMSAMPLEFORMAT_FIXED_16,//和位数一支即可
- SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT,//立体声(前作前右)
- SL_BYTEORDER_LITTLEENDIAN //字节序,小端还是大端,默认小端 (高位还是地位在前)
- };
- SLDataSource ds = {&que,&pcm};//包装成配置信息
- //4 创建播放器
- SLObjectItf player = NULL;
- SLPlayItf iplayer = NULL;
- SLAndroidSimpleBufferQueueItf pcmQue = NULL;
- const SLInterfaceID ids[] = {SL_IID_BUFFERQUEUE};
- const SLboolean req[] = {SL_BOOLEAN_TRUE};
- re = (*eng)->CreateAudioPlayer(eng,&player,&ds,&audioSink,sizeof(ids)/sizeof(SLInterfaceID),ids,req);//利用前面的配置来创建
- if(re !=SL_RESULT_SUCCESS )
- {
- LOGD("CreateAudioPlayer failed!");
- } else{
- LOGD("CreateAudioPlayer success!");
- }
- (*player)->Realize(player,SL_BOOLEAN_FALSE);//实例化
- //获取player接口
- re = (*player)->GetInterface(player,SL_IID_PLAY,&iplayer); // 获取接口
- if(re !=SL_RESULT_SUCCESS )
- {
- LOGD("GetInterface SL_IID_PLAY failed!");
- }
- re = (*player)->GetInterface(player,SL_IID_BUFFERQUEUE,&pcmQue);//缓冲队列
- if(re !=SL_RESULT_SUCCESS )
- {
- LOGD("GetInterface SL_IID_BUFFERQUEUE failed!");
- }
- //设置回调函数,播放队列空调用
- (*pcmQue)->RegisterCallback(pcmQue,PcmCall,);//断音,很快的一个操作
- //设置为播放状态
- (*iplayer)->SetPlayState(iplayer,SL_PLAYSTATE_PLAYING); // play状态、暂停状态、
- //启动队列回调
- (*pcmQue)->Enqueue(pcmQue,"",); // 先压入一点数据
- return env->NewStringUTF(hello.c_str());
- }
- /**
- 1.初始化引擎
- SLresult re; //存放引擎本身,上下文
- SLEngineItf en; //存放引擎的接口
- slCreateEngine(&engineSL,0,0,0,0,0);//创建对象
- Realize(engineSL,SL_BOOLEAN_FALSE);//实例化(内部的数据分配内存) 都是这个模式,先创建,然后实例化,在获取接口
- GetInterface(engineSL,SL_IID_ENGINE,&en);//获取接口SLEngineItf ,通过第二个参数获取对应的接口
- 2.输出设备
- SLObjectItf mix = NULL;
- SLresult re = 0;
- CreateOutputMix(eng,&mix,0,0,0);//创建输出设备
- Realize(mix,SL_BOOLEAN_FALSE);//实例化
- //下面两个是存储
- SLDataLocator_OutputMix outmix = {SL_DATALOCATOR_OUTPUTMIX,mix};
- SLDataSink audioSink= {&outmix,0};
- 3.配置音频信息
- SLDataLocator_AndroidSimpleBufferQueue que = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,10}; //以什么样的方式交互
- //音频格式
- SLDataFormat_PCM pcm = {
- SL_DATAFORMAT_PCM,//支持PCM格式的数据
- 2,// 声道数
- SL_SAMPLINGRATE_44_1,//44100Hz的频率(采样率)
- SL_PCMSAMPLEFORMAT_FIXED_16, //位数
- SL_PCMSAMPLEFORMAT_FIXED_16,//和位数一支即可
- SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT,//立体声(前作前右)
- SL_BYTEORDER_LITTLEENDIAN //字节序,小端还是大端,默认小端 (高位还是地位在前)
- };
- SLDataSource ds = {&que,&pcm};//包装成配置信息
- 4.创建播放器
- SLObjectItf player = NULL;
- SLPlayItf iplayer = NULL;
- CreateAudioPlayer(eng,&player,&ds,&audioSink,sizeof(ids)/sizeof(SLInterfaceID),ids,req);//利用前面的配置来创建
- Realize(player,SL_BOOLEAN_FALSE);//实例化
- GetInterface(player,SL_IID_PLAY,&iplayer); // 获取接口
- GetInterface(player,SL_IID_BUFFERQUEUE,&pcmQue);//缓冲队列
- (*pcmQue)->RegisterCallback(pcmQue,PcmCall,0);//设置回调函数,播放队列空调用
- (*iplayer)->SetPlayState(iplayer,SL_PLAYSTATE_PLAYING); //设置为播放状态play状态、暂停状态、
- (*pcmQue)->Enqueue(pcmQue,"",1); //启动队列回调 先压入一点数据
- */
FFmpeg(七)音频的播放的更多相关文章
- FFmpeg学习3:播放音频
参考dranger tutorial,本文将介绍如何使用FFmpeg解码音频数据,并使用SDL将解码后的数据输出. 本文主要包含以下几方面的内容: 关于播放音频的需要的一些基础知识介绍 使用SDL2播 ...
- FFMPEG + SDL音频播放分析
目录 [hide] 1 抽象流程: 2 关键实现: 2.1 main()函数 2.2 decode_thread()读取文件信息和音频包 2.3 stream_component_open():设置音 ...
- FFmpeg 入门(3):播放音频
本文转自:FFmpeg 入门(3):播放音频 | www.samirchen.com 音频 SDL 提供了播放音频的方法.SDL_OpenAudio 函数用来让设备播放音频,它需要我们传入一个包含了所 ...
- [转]FFMPEG视音频编解码零基础学习方法
在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...
- [总结]FFMPEG视音频编解码零基础学习方法--转
ffmpeg编解码学习 目录(?)[-] ffmpeg程序的使用ffmpegexeffplayexeffprobeexe 1 ffmpegexe 2 ffplayexe 3 ffprobeexe ...
- FFMPEG视音频编解码零基础学习方法
在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...
- FFMPEG视音频编解码零基础学习方法-b
感谢大神分享,虽然现在还看不懂,留着大家一起看啦 PS:有不少人不清楚“FFmpeg”应该怎么读.它读作“ef ef em peg” 0. 背景知识 本章主要介绍一下FFMPEG都用在了哪里(在这里仅 ...
- [总结]FFMPEG视音频编解码零基础学习方法
在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...
- 【转】[总结]FFMPEG视音频编解码零基础学习方法
在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...
- 浏览器音频兼容和ffmpeg的音频转码使用
浏览器对各音/视频格式的支持问题 浏览器测试效果图 ffmpeg在音频格式转换,和从视频中提取音频的简单实用 1.百度搜索浏览器对于音频文件的兼容,排在前面的文章大部分是复制粘贴很久以前的文章,容易误 ...
随机推荐
- hdu6437 Problem L.Videos(网络流)
Problem L.Videos Problem Description: C-bacteria takes charge of two kinds of videos: ’The Collectio ...
- 洛谷p2015二叉苹果树&yzoj1856多叉苹果树题解
二叉 多叉 有一棵苹果树,如果树枝有分叉,可以是分多叉,分叉数k>=0(就是说儿子的结点数大于等于0)这棵树共有N个结点(叶子点或者树枝分叉点),编号为1~N,树根编号一定是1.我们用一根树枝两 ...
- Springboot源码分析之Spring循环依赖揭秘
摘要: 若你是一个有经验的程序员,那你在开发中必然碰到过这种现象:事务不生效.或许刚说到这,有的小伙伴就会大惊失色了.Spring不是解决了循环依赖问题吗,它是怎么又会发生循环依赖的呢?,接下来就让我 ...
- SVN更新失败
一.svn更新失败 使用svn遇到的问题是,更新失败,代码被锁定. 解决办法: 在项目上右键,如图所示: 图一: 图二: 之后再更新,基本上都没有问题了.如果还有问题,看下面. 二.工具清理 ...
- html5表单与Jquery Ajax配合使用
html5的表单控件提供了很多格式检测功能,可以省去很多烦人的javascript验证代码,例如pattern属性和require属性,但触发的条件是表单提交,如果想通过ajax提交表单,就出现了不能 ...
- Winform中设置ZedGraph曲线图的字体样式是避免出现边框
场景 Winforn中设置ZedGraph曲线图的属性.坐标轴属性.刻度属性: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...
- Hive bucket表
Hive 桶 对于每一个表(table)或者分区, Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分.Hive也是 针对某一列进行桶的组织.Hive采用对列值哈希,然后除以桶的个数求余 ...
- 关于spring boot多张表建立外健的讨论
现在有四张表:student(学生表).blogs(博客表).comment(评论表).reply(回复表) 现在说一下这四张表: student(学生表):学生的信息记录表 blogs(博客表):学 ...
- Stanford公开课《编译原理》学习笔记(1~4课)
目录 一. 编译的基本流程 二. Lexical Analysis(词法分析阶段) 2.1 Lexical Specification(分词原则) 2.2 Finite Automata (典型分词算 ...
- Python连载39-生成器、next函数、yield返回值
一.生成器 1.定义(generator):一边循环一边计算下一个元素的机制/算法 2.满三个条件 (1)每次调用都能产生出for循环需要的下一个元素 (2)如果达到最后一个后,能够爆出StopIt ...