首先在每次MediaPlayer调用create创建的时候,会调用一次prepare,这个时候会走入NuPlayerDriver::prepareAsync中的STATE_UNPREPARED,之后会先调用stop一下,从而将NuPlayer播放器的状态切换为STATE_STOPPED态,之后再次调用prepare进入NuPlayerDriver::prepareAsync的STATE_STOPPED流程

第二次在prepareAsync调用中

status_t NuPlayerDriver::prepareAsync() {ALOGV("prepareAsync(%p)", this);Mutex::Autolock autoLock(mLock);switch (mState) {case STATE_UNPREPARED:mState = STATE_PREPARING;mIsAsyncPrepare = true;mPlayer->prepareAsync();return OK;case STATE_STOPPED:// this is really just paused. handle as seek to startmAtEOS = false;mState = STATE_STOPPED_AND_PREPARING;mIsAsyncPrepare = true;mPlayer->seekToAsync(0, true /* needNotify */);return OK;default:return INVALID_OPERATION;};
}

这里会将播放器的seek调整到0,同时播放器的状态切换为STATE_STOPPED_AND_PREPARING

void NuPlayer::seekToAsync(int64_t seekTimeUs, bool needNotify) {android::CallStack cs("JON");sp<AMessage> msg = new AMessage(kWhatSeek, this);msg->setInt64("seekTimeUs", seekTimeUs);msg->setInt32("needNotify", needNotify);msg->post();
}

消息发往NuPlayerDriver在构造的时候开启的线程"NuPlayerDriver Looper"

void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {...case kWhatSeek:onStart(seekTimeUs);...
}
void NuPlayer::onStart(int64_t startPositionUs) {...postScanSources();...
}
...
void NuPlayer::postScanSources() {if (mScanSourcesPending) {return;}sp<AMessage> msg = new AMessage(kWhatScanSources, this);msg->setInt32("generation", mScanSourcesGeneration);msg->post();mScanSourcesPending = true;
}

消息继续发往子线程处理

void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {case kWhatScanSources:{if (mAudioSink != NULL && mAudioDecoder == NULL) {if (instantiateDecoder(true, &mAudioDecoder) == -EWOULDBLOCK) {rescan = true;}}...}
}
...
status_t NuPlayer::instantiateDecoder(bool audio, sp<DecoderBase> *decoder, bool checkAudioModeChange) {if (audio) {...这里是关键if (checkAudioModeChange) {determineAudioModeChange(format);}if (mOffloadAudio) {const bool hasVideo = (mSource->getFormat(false /*audio */) != NULL);format->setInt32("has-video", hasVideo);*decoder = AVNuFactory::get()->createPassThruDecoder(notify, mSource, mRenderer);} else {AVNuUtils::get()->setCodecOutputFormat(format);mSource->setOffloadAudio(false /* offload */);*decoder = AVNuFactory::get()->createDecoder(notify, mSource, mPID, mRenderer);}        ...
}

如上会完成2件重要的事情,一个是调用determineAudioModeChange完成AudioTrack的创建,另外就是创建音频的decoder,我们当前只关注AudioTrack的创建

void NuPlayer::determineAudioModeChange(const sp<AMessage> &audioFormat) {...走offload模式if (canOffload) {tryOpenAudioSinkForOffload(audioFormat, audioMeta, hasVideo);}....
}
void NuPlayer::tryOpenAudioSinkForOffload(const sp<AMessage> &format, const sp<MetaData> &audioMeta, bool hasVideo) {// Note: This is called early in NuPlayer to determine whether offloading// is possible; otherwise the decoders call the renderer openAudioSink directly.status_t err = mRenderer->openAudioSink(format, true /* offloadOnly */, hasVideo, AUDIO_OUTPUT_FLAG_NONE, &mOffloadAudio, mSource->isStreaming());if (err != OK) {// Any failure we turn off mOffloadAudio.mOffloadAudio = false;} else if (mOffloadAudio) {sendMetaDataToHal(mAudioSink, audioMeta);}
}

frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayerRenderer.cpp

status_t NuPlayer::Renderer::openAudioSink(const sp<AMessage> &format,bool offloadOnly,bool hasVideo,uint32_t flags,bool *isOffloaded,bool isStreaming) {sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);msg->setMessage("format", format);msg->setInt32("offload-only", offloadOnly);msg->setInt32("has-video", hasVideo);msg->setInt32("flags", flags);msg->setInt32("isStreaming", isStreaming);sp<AMessage> response;status_t postStatus = msg->postAndAwaitResponse(&response);...
}

如上消息发往Renderer的子线程NuPlayerRenderer处理,之后调用onOpenAudioSink

status_t NuPlayer::Renderer::onOpenAudioSink(const sp<AMessage> &format,bool offloadOnly,bool hasVideo,uint32_t flags,bool isStreaming) {...err = mAudioSink->open(sampleRate,numChannels,(audio_channel_mask_t)channelMask,audioFormat,0 /* bufferCount - unused */,&NuPlayer::Renderer::AudioSinkCallback,this,(audio_output_flags_t)offloadFlags,&offloadInfo);...err = mAudioSink->start();             ...
}

这里的mAudioSink在Audio播放流程(二)—NuPlayer流程之setDataSource中的setDataSource_pre有完成设置,指向的是MediaPlayerService中的AudioOutput

frameworks\av\media\libmediaplayerservice\MediaPlayerService.cpp

status_t MediaPlayerService::AudioOutput::open(uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,audio_format_t format, int bufferCount,AudioCallback cb, void *cookie,audio_output_flags_t flags,const audio_offload_info_t *offloadInfo,bool doNotReconnect,uint32_t suggestedFrameCount)
{...t = new AudioTrack(mStreamType,sampleRate,format,channelMask,frameCount,flags,NULL, // callbackNULL, // user data0, // notification framesmSessionId,AudioTrack::TRANSFER_DEFAULT,NULL, // offload infomUid,mPid,mAttributes,doNotReconnect,targetSpeed);t->setVolume(mLeftVolume, mRightVolume);mTrack = t;...
}

如上完成了AudioTrack的创建

Audio播放流程(四)---MediaPlayerService流程之AudioTrack的创建相关推荐

  1. Android Audio播放流程详解

    本文涉及的所有代码都是AOSP源码 目录 1. AudioTrack 2.创建AudioTrack对象 1. AudioTrack AudioTrack用于播放PCM流格式的音频数据.播放器会在fra ...

  2. Android7.1 audio 播放流程(三十五)

    android audio 生产者与消费者 简介 全面接触生产者/消费者问题是在操作系统原理中,并发性原理讨论的问题 生产者/消费者问题.最近的工作偏向音频,接着上一篇文章,用生产者,消费者模型来理解 ...

  3. Anbox之server端audio播放流程(十二)

    Anbox是一个免费的开源兼容层,旨在允许为Android开发的移动应用程序和移动游戏在GNU / Linux发行版上运行. 使用LXC执行Android运行时环境,将Android的目录结构重新创建 ...

  4. activiti自己定义流程之Spring整合activiti-modeler5.16实例(四):部署流程定义

    注:(1)环境搭建:activiti自己定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建         (2)创建流程模型:activiti自己定义流程之Spr ...

  5. activiti自定义流程之Spring整合activiti-modeler5.16实例(四):部署流程定义

    注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建         (2)创建流程模型:activiti自定义流程之Sprin ...

  6. AudioTrack播放流程

    AudioTrack介绍 音频播放声音分为MediaPlayer和AudioTrack两种方案的.MediaPlayer可以播放多种格式的声音文件,例如MP3,WAV,OGG,AAC,MIDI等.然而 ...

  7. [原创]FOCUS处理系统流程之:流程批量生成(个人专用懒人版)

    根据标准流程生成整个工区流程文件 (1)可按按目录生成 (2)可替换其中的关键字 标准流程准确,则生成的流程将一点到底,所剩的操作变成鼠标的操作,懒之产物. 界面如下:  ☆其它物探处理原创软件相关☆ ...

  8. Audio播放音频 --- 建立播放通道

    Audio播放音频 - 建立播放通道 简介 虽然文章标题是<建立播放通道>,其实播放通道早在AudioPolicyManager解析configuration配置文件时,openoutpu ...

  9. (连载)Android系统源码分析--Android系统启动流程之Linux内核

    > **这是一个连载的博文系列,我将持续为大家提供尽可能透彻的Android源码分析 [github连载地址](https://github.com/foxleezh/AOSP/issues/3 ...

  10. (连载)Android 8.0 : 系统启动流程之Linux内核

    这是一个连载的博文系列,我将持续为大家提供尽可能透彻的Android源码分析 github连载地址 前言 Android本质上就是一个基于Linux内核的操作系统,与Ubuntu Linux.Fedo ...

最新文章

  1. CMakeFile命令之file
  2. java懒加载设计模式_java设计模式——单例模式
  3. java 规格overview_《Java數據結構和算法》- OverView
  4. vs中四点画矩形的算法_中考热点,初高中衔接之倒角利器四点共圆
  5. php ajax勾选框提交,jQuery选取所有复选框被选中的值并用Ajax异步提交数据的实例...
  6. python虚拟环境搭建mac_在MAC上安装Python虚拟环境
  7. eNSP模拟器中 FTP 实验
  8. Think PHP(TP)框架基础知识
  9. matlab中累乘,numpy中的裁剪、压缩和累乘
  10. 论文-Knowledge Graph Grounded Goal Planning for Open-Domain Conversation Generation
  11. BEV和Pseudo-Lidar
  12. c语言 strcpy作用,c语言中的strcpy什么意思,简单点解释
  13. 计算机基础知识教程excel试题,计算机基础知识试题
  14. 【心随意动】20-SIST研一秋季上学期课程总结【补】
  15. 极速office(excel)如何查找出重复内容
  16. 【ASP.NET Core】处理异常--转
  17. npm下载依赖时的问题
  18. 1658 页的《Java 面试突击核心讲》在牛客网火了,完整版 PDF 开放下载!
  19. mbedtls安装与入门
  20. 操作系统——文件管理实验

热门文章

  1. C++ Primer 5th 第15章 面向对象程序设计
  2. 用微软makecert.exe生成一个自签名的证书
  3. Loadrunner请求自定义的http(json)文件and参数化
  4. 机器学习 - pycharm, pyspark, spark集成篇
  5. python 获取错误日志,并发送邮件
  6. [JavaScript] - replaceAll,将字符串中的字母或数字等全部替换掉的方式
  7. 快速学习nodejs系列:四、nodejs特性1--单线程
  8. spring security oauth2
  9. javascript DOM操作
  10. 用WPF+MongoDB开发房产信息收集器(3)——MongoDB入门