static jint android_media_AudioTrack_native_setup(
JNIEnv *env,
jobjectthiz, jobject weak_this,
jintstreamType,
jint sampleRateInHertz,
jint javaChannelMask,
jint audioFormat,
jint buffSizeInBytes,
jint memoryMode,
jintArray jSession){
.......
// initialize the native AudioTrack object
switch (memoryMode) {
case MODE_STREAM:
//STREAM模式,现在没有申请共享内存,后续Track对象通过
//AudioFlinger中的Client对象申请heap空间给mCblk进行数据传输
lpTrack->set(
atStreamType,// stream type
sampleRateInHertz,
format,// word length, PCM
nativeChannelMask,
frameCount,
AUDIO_OUTPUT_FLAG_NONE,
audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
0,// shared mem
true,// thread can call Java
sessionId);// audio session ID
break;
case MODE_STATIC:
// STATIC模式,为AudioTrack分配共享内存区域,大小为buffSizeInBytes
//后续会将这些buff分配给track的mCblk进行数据传输
if (!lpJniStorage->allocSharedMem(buffSizeInBytes)) {
ALOGE("Error creating AudioTrack in static mode: error creating mem heap base");
goto native_init_failure;
}
lpTrack->set(
atStreamType,// stream type
sampleRateInHertz,
format,// word length, PCM
nativeChannelMask,
frameCount,
AUDIO_OUTPUT_FLAG_NONE,
audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
lpJniStorage->mMemBase,// shared mem
true,// thread can call Java
sessionId);// audio session ID
break;
default:
ALOGE("Unknown mode %d", memoryMode);
goto native_init_failure;
}
......
}
status_t AudioTrack::set(
audio_stream_type_t streamType,
uint32_tsampleRate,
audio_format_tformat,
audio_channel_mask_tchannelMask,
intframeCountInt,
audio_output_flags_t flags,
callback_tcbf,
void* user,
intnotificationFrames,
constsp<IMemory>& sharedBuffer,
boolthreadCanCallJava,
int sessionId,
transfer_type transferType,
constaudio_offload_info_t *offloadInfo,
int uid){
......
/*cbf为JNI层设置的回调函数
因为cbf是audioCallback不为空,所以这里会启动一个AudioTrackThread线程。
这个线程是用于AudioTrack(native)与AudioTrack(java)间的数据事件通知的,
这就为上层应用处理事件提供了一个入口,包括:
EVENT_MORE_DATA = 0, //请求写入更多数据
EVENT_UNDERRUN = 1, //PCM 缓冲发生了underrun
EVENT_LOOP_END = 2, //到达loop end,loopcount!=null从loop start重新开始回放
EVENT_MARKER = 3, //Playback head在指定的位置,参考setMarkerPosition
EVENT_NEW_POS = 4, //Playback head在一个新的位置,参考setPositionUpdatePeriod
EVENT_BUFFER_END = 5 //Playback head在buffer末尾
EVENT_NEW_IAUDIOTRACK = 6, //recreate audiotrack
EVENT_STREAM_END = 7, //AF和HW端数据播放完毕
EVENT_NEW_TIMESTAMP = 8 //暂时未用
*/
if (cbf != NULL) {
mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
mAudioTrackThread->run("AudioTrack",ANDROID_PRIORITY_AUDIO, 0 /*stack*/);
}
......
}
//调用java层用户实现的函数</p><p>static void audioCallback(int event, void* user, void *info) {
audiotrack_callback_cookie*callbackInfo = (audiotrack_callback_cookie *)user;
{
Mutex::Autolock l(sLock);
if(sAudioTrackCallBackCookies.indexOf(callbackInfo) < 0) {
return;
}
callbackInfo->busy =true; }
switch (event) {
caseAudioTrack::EVENT_MARKER: {
JNIEnv *env =AndroidRuntime::getJNIEnv();
if (user != NULL&& env != NULL) {
env->CallStaticVoidMethod(
callbackInfo->audioTrack_class,
javaAudioTrackFields.postNativeEventInJava,
callbackInfo->audioTrack_ref, event, 0,0, NULL);
if(env->ExceptionCheck()) {
env->ExceptionDescribe();
Audio笔记之AudioTrackThread
最新推荐文章于 2022-04-10 10:10:17 发布
本文详细探讨了Android中AudioTrack的使用,包括初始化设置、音频数据写入、播放控制等方面,揭示了实现音频播放的关键步骤和技术要点。
摘要由CSDN通过智能技术生成