Android 深入系统完全讲解(32)

Posted 程序员入门进阶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 深入系统完全讲解(32)相关的知识,希望对你有一定的参考价值。

API 简介
getInputBuffers:获取需要编码数据的输入流队列,返回的是一个 ByteBuffer 数组
queueInputBuffer:输入流入队列dequeueInputBuffer:从输入流队列中取数据进行编码操作
getOutputBuffers:获取编解码之后的数据输出流队列,返回的是一个 ByteBuffer 数组
dequeueOutputBuffer:从输出队列中取出编码操作之后的数据
releaseOutputBuffer:处理完成,释放 ByteBuffer 数据
MediaCodec 的作用就是完成重新编码的过程,从一个格式解成自己可以识别的流,然后输
出进行编码变成需要的格式。
下来我们需要停一下脚步,要开始新的篇章。
缓一下,缓一下
在前面课题里面,完成了太多的内容输出,大家也按着操作一步步下来,掌握了原理,逻辑,
以及实战应用。
下来我分享一个,如何用底层 C 库,进行播放音频的库。画面特效如果要学习,需要购买
android OpenGL ES 系列课程。而关于 NDK 的音频库,这里有官方的 OpenSL ES
今天说一下这个。 Android OpenSL ES
我们先从官方网站看下:https://developer.android.google.cn/ndk/guides/audio/opensl
NDK 软件包中包括 Khronos Group 开发的 OpenSL ES™ 1.0.1 API 规范的 Android 专用实
现。利用这个库,不论您是编写合成器、数字音频工作站、卡拉 OK 应用、游戏还是其他
实时应用,都可以使用 C 或 C++ 实现高性能、低延迟的音频。
OpenSL ES™ 标准与 Android Java 框架中的 MediaPlayer 和 MediaRecorderAPI 提供类似的
音频功能。OpenSL ES 提供 C 语言接口和 C++ 绑定,让您可以从使用任意一种语言编写的
代码中调用 API。
OpenSL ES API 可以帮助您开发和提升应用的音频性能。
标准 OpenSL ES 头文件 <SLES/OpenSLES.h> 和 <SLES/OpenSLES_Platform.h> 允许音频输入
和输出。<SLES/OpenSLES_Android.h> 和 <SLES/OpenSLES_AndroidConfiguration.h> 中提供了
其他 Android 专用功能。
本部分首先说明如何将 OpenSL ES 整合到您的应用中。然后,介绍您需要了解的 OpenSL ES
的 Android 实现相关信息,其中首先会重点介绍此实现与参考规范之间的差异,然后介绍
用于确保 Android 兼容性的其他扩展。最后,本部分提供一些补充性的编程说明,用于确
保正确实现 OpenSL ES。我之前推荐过 SDL2.0,但是这个库有个问题,就是它的音频使用的是 Java 端,通过反射回
去播放,这样子的效率就很低。
于是我更换了实现,把 SDL2.0 里面的 audio 播放,用 OpenSL ES 进行替换了。这个实现起来
也比较简单:
我用了市面上做好的库,我们直接存下来就可以,后面说应用。
Opensl_io.h
//
// Created by huizai on 2017/12/4. //
#ifndef FFMPEG_DEMO_OPENSL_IO_H
#define FFMPEG_DEMO_OPENSL_IO_H
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
typedef struct opensl_stream
// engine interfaces
SLObjectItf engineObject;
SLEngineItf engineEngine;
// output mix interfaces
SLObjectItf outputMixObject;
// buffer queue player interfaces
SLObjectItf bqPlayerObject;
SLPlayItf bqPlayerPlay;
SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
SLObjectItf pitchObject;
SLPitchItf bqPitchEngne;
SLPlaybackRateItf bqPlayerRate;
SLPitchItf bqPlayerVolume;
// buffer indexes
int inputDataCount;double time;
uint32_t outchannels; //输出的声道数量
uint32_t sampleRate; //采样率
OPENSL_STREAM;
int android_SetPlayRate(OPENSL_STREAM p,int playRate);
/
Open the audio device with a given sampling rate (sr), input and output channels and IO
buffer size
in frames. Returns a handle to the OpenSL stream
/
OPENSL_STREAM
android_OpenAudioDevice(uint32_t sr, uint32_t inchannels, uint32_t
outchannels, uint32_t bufferframes);
/* Close the audio device
*/
void android_CloseAudioDevice(OPENSL_STREAM p);
/
Write a buffer to the OpenSL stream *p, of size samples. Returns the number of samples
written. */
uint32_t android_AudioOut(OPENSL_STREAM *p, uint16_t *buffer,uint32_t size);
#endif //FFMPEG_DEMO_OPENSL_IO_H
然后 Opensl_io.c
//
// Created by huizai on 2017/12/4. //
#include “Opensl_io.h” static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context);
// creates the OpenSL ES audio engine
static SLresult openSLCreateEngine(OPENSL_STREAM *p)

SLresult result;// create engine
result = slCreateEngine(&(p->engineObject), 0, NULL, 0, NULL, NULL);
if(result != SL_RESULT_SUCCESS) goto engine_end;
// realize the engine
result = (*p->engineObject)->Realize(p->engineObject, SL_BOOLEAN_FALSE);
if(result != SL_RESULT_SUCCESS) goto engine_end;
// get the engine interface, which is needed in order to create other objects
result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE, &(p->engineEngine));
if(result != SL_RESULT_SUCCESS) goto engine_end;
engine_end:
return result;

// opens the OpenSL ES device for output
static SLresult openSLPlayOpen(OPENSL_STREAM *p)

SLresult result;
SLuint32 sr = p->sampleRate;
SLuint32 channels = p->outchannels;
if(channels)
// configure audio source
SLDataLocator_AndroidSimpleBufferQueue loc_bufq =
SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2;
switch(sr)
case 8000:
sr = SL_SAMPLINGRATE_8;
break;
case 11025:
sr = SL_SAMPLINGRATE_11_025;
break;
case 16000:
sr = SL_SAMPLINGRATE_16;
break;
case 22050:
sr = SL_SAMPLINGRATE_22_05;
break;
case 24000:sr = SL_SAMPLINGRATE_24;
break;
case 32000:
sr = SL_SAMPLINGRATE_32;
break;
case 44100:
sr = SL_SAMPLINGRATE_44_1;
break;
case 48000:
sr = SL_SAMPLINGRATE_48;
break;
case 64000:
sr = SL_SAMPLINGRATE_64;
break;
case 88200:
sr = SL_SAMPLINGRATE_88_2;
break;
case 96000:
sr = SL_SAMPLINGRATE_96;
break;
case 192000:
sr = SL_SAMPLINGRATE_192;
break;
default:
break;
return -1;

const SLInterfaceID ids[] = SL_IID_VOLUME;
const SLboolean req[] = SL_BOOLEAN_FALSE;
result = (*p->engineEngine)->CreateOutputMix(p->engineEngine, &(p->outputMixObject), 1, ids, req);
if(result != SL_RESULT_SUCCESS) return result;
// realize the output mix
result = (*p->outputMixObject)->Realize(p->outputMixObject, SL_BOOLEAN_FALSE);
int speakers;
if(channels > 1)
speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
else speakers = SL_SPEAKER_FRONT_CENTER;SLDataFormat_PCM format_pcm = SL_DATAFORMAT_PCM,channels, sr, SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16, (SLuint32)speakers, SL_BYTEORDER_LITTLEENDIAN;
SLDataSource audiosrc = &loc_bufq, &format_pcm;
// configure audio sink
SLDataLocator_OutputMix loc_outmix = SL_DATALOCATOR_OUTPUTMIX, p->outputMixObject;
SLDataSink audioSnk = &loc_outmix, NULL;
// create audio player
const SLInterfaceID ids1[] =
SL_IID_ANDROIDSIMPLEBUFFERQUEUE,SL_IID_PLAYBACKRATE,SL_IID_VOLUME;
const SLboolean req1[] =
SL_BOOLEAN_TRUE,SL_BOOLEAN_TRUE,SL_BOOLEAN_TRUE;
result = (*p->engineEngine)->CreateAudioPlayer(p->engineEngine, &(p->bqPlayerObject), &audioSrc, &audioSnk, 3, ids1, req1);
if(result != SL_RESULT_SUCCESS) return result;
// realize the player
result = (*p->bqPlayerObject)->Realize(p->bqPlayerObject, SL_BOOLEAN_FALSE);
if(result != SL_RESULT_SUCCESS) return result;
// get the play interface
result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_PLAY, &(p->bqPlayerPlay));
if(result != SL_RESULT_SUCCESS) return result;
// get the play rate
result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_VOLUME, &(p->bqPlayerVolume));
if(result != SL_RESULT_SUCCESS) return result;
// get the play volume
result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_PLAYBACKRATE, &(p->bqPlayerRate));
if(result != SL_RESULT_SUCCESS) return result;
// get the buffer queue interface

以上是关于Android 深入系统完全讲解(32)的主要内容,如果未能解决你的问题,请参考以下文章

Android 深入系统完全讲解(32)

Android 深入系统完全讲解(26)

Android 深入系统完全讲解(26)

Android 深入系统完全讲解(33)

Android 深入系统完全讲解(33)

Android 深入系统完全讲解(31)