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

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

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

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: android