当前位置: 首页 > news >正文

南通市住房和建设局网站免费推广网站大全

南通市住房和建设局网站,免费推广网站大全,做网站好处,深圳集团网站开发公司前言#xff1a; 继上一篇Android AudioFlinger#xff08;三#xff09;—— AndroidAudio Flinger 之设备管理我们知道PlaybackThread继承自Re’fBase#xff0c; 在被第一次引用的时候就会调用onFirstRef#xff0c;实现如下#xff1a; void AudioFlinger::Playbac…前言 继上一篇Android AudioFlinger三—— AndroidAudio Flinger 之设备管理我们知道PlaybackThread继承自Re’fBase 在被第一次引用的时候就会调用onFirstRef实现如下 void AudioFlinger::PlaybackThread::onFirstRef() {run(mThreadName, ANDROID_PRIORITY_URGENT_AUDIO); }很简单就调用了一个run方法去开起了一个ThreadLoop线程 bool AudioFlinger::PlaybackThread::threadLoop() { ... }接下来我们进一步研究下PlaybackThread的循环主题具体做了什么 揭开PlaybackThread面纱 当进入到threadloop就说明playbackthread的音频事务正式开启了。代码比较多但是我们如果仔细看的话会发现关键代码就几处而且都是threadLoop_前缀的threadLoop_standby\threadLoop_mix\threadLoop_sleepTime\threadLoop_write等这也代表这些函数都是threadLoop内部调用的。 bool AudioFlinger::PlaybackThread::threadLoop() { ...while (!exitPending()){...{ // scope for mLock//这个地方框起来主要就是限制自动锁_l的生命周期Mutex::Autolock _l(mLock);//处理config事件processConfigEvents_l(); if ((!mActiveTracks.size() systemTime() mStandbyTimeNs) ||isSuspended()) {if (shouldStandby_l()) {//进入standby状态节省能耗threadLoop_standby();}}//准备音频流mMixerStatus prepareTracks_l(tracksToRemove);} // mLock scope ends...if (mBytesRemaining 0) {mCurrentWriteLength 0;if (mMixerStatus MIXER_TRACKS_READY) {//读取所有active设备数据混音器开始混音threadLoop_mix();} else if ((mMixerStatus ! MIXER_DRAIN_TRACK) (mMixerStatus ! MIXER_DRAIN_ALL)) {//进入休眠threadLoop_sleepTime();}}...if (!waitingAsyncCallback()) {if (mSleepTimeUs 0) {if (mBytesRemaining) {//把混音器处理好的数据写入到输出流设备ret threadLoop_write();} else if ((mMixerStatus MIXER_DRAIN_TRACK) ||(mMixerStatus MIXER_DRAIN_ALL)) {threadLoop_drain();}...}} ... //移除相关的trackthreadLoop_removeTracks(tracksToRemove);tracksToRemove.clear();clearOutputTracks();effectChains.clear();}threadLoop_exit();if (!mStandby) {threadLoop_standby();mStandby true;}releaseWakeLock();return false; }首先exitPending是threadloop循环的条件这个函数是Thread的内部函数它主要就是通过判断mExitPending来决定是否退出线程这个值默认为false在收到requestExit或者requestExitAndWait的时候会变为true然后就会退出循环。 Thread PATH:/system/core/libutils/Threads.cpp processConfigEvents_l: 处理config时间当有配置发声变化的时候会调用sendConfigEvent_l来把事件添加到mConfigEvents中最终processConfigEvents_l检测到就会去处理对应的配置。 threadLoop_standby 判断当前是否符合standby条件符合就调用threadLoop_standby最终的实现其实是hal层实现会做出关闭音频流等操作。 prepareTracks_l 这个函数非常复杂我们简单概括下挑几个重点谈一谈 // prepareTracks_l() must be called with ThreadBase::mLock held AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(Vector spTrack *tracksToRemove) {//获取当前活跃的track数量size_t count mActiveTracks.size();for (size_t i0 ; icount ; i) {//循环每个活跃的trackconst spTrack t mActiveTracks[i];// this const just means the local variable doesnt changeTrack* const track t.get();// process fast tracksif (track-isFastTrack()) {//如果是fasttrack改如何处理} ...{ // local variable scope to avoid goto warning//数据块准备操作audio_track_cblk_t* cblk track-cblk();//获取track的音频信息const uint32_t sampleRate track-mAudioTrackServerProxy-getSampleRate();AudioPlaybackRate playbackRate track-mAudioTrackServerProxy-getPlaybackRate();desiredFrames sourceFramesNeededWithTimestretch(sampleRate, mNormalFrameCount, mSampleRate, playbackRate.mSpeed);desiredFrames mAudioMixer-getUnreleasedFrames(track-name());uint32_t minFrames 1;if ((track-sharedBuffer() 0) !track-isStopped() !track-isPausing() (mMixerStatusIgnoringFastTracks MIXER_TRACKS_READY)) {//至少需要准备的音频帧数minFrames desiredFrames;}size_t framesReady track-framesReady();if ((framesReady minFrames) track-isReady() !track-isPaused() !track-isTerminated()){mixedTracks;// compute volume for this trackuint32_t vl, vr; // in U8.24 integer formatfloat vlf, vrf, vaf; // in [0.0, 1.0] float format//左声道右声道aux level音量// read original volumes with volume controlfloat typeVolume mStreamTypes[track-streamType()].volume;//获取每个stream类型的音频音量float v masterVolume * typeVolume;//主音量和类型音量相乘if (track-isPausing() || mStreamTypes[track-streamType()].mute) {vl vr 0;vlf vrf vaf 0.;//设置0代表静音操作if (track-isPausing()) {track-setPaused();//track设置暂停}} else {spAudioTrackServerProxy proxy track-mAudioTrackServerProxy;gain_minifloat_packed_t vlr proxy-getVolumeLR();//得到音量的增益值vlf float_from_gain(gain_minifloat_unpack_left(vlr));vrf float_from_gain(gain_minifloat_unpack_right(vlr));//转换为浮点值// track volumes come from shared memory, so cant be trusted and must be clamped//判断是否在合理范围内if (vlf GAIN_FLOAT_UNITY) {ALOGV(Track left volume out of range: %.3g, vlf);vlf GAIN_FLOAT_UNITY;}if (vrf GAIN_FLOAT_UNITY) {ALOGV(Track right volume out of range: %.3g, vrf);vrf GAIN_FLOAT_UNITY;}const float vh track-getVolumeHandler()-getVolume(track-mAudioTrackServerProxy-framesReleased()).first;// now apply the master volume and stream type volume and shaper volumevlf * v * vh;vrf * v * vh;// assuming master volume and stream type volume each go up to 1.0,// then derive vl and vr as U8.24 versions for the effect chainconst float scaleto8_24 MAX_GAIN_INT * MAX_GAIN_INT;vl (uint32_t) (scaleto8_24 * vlf);vr (uint32_t) (scaleto8_24 * vrf);// vl and vr are now in U8.24 formatuint16_t sendLevel proxy-getSendLevel_U4_12();// send level comes from shared memory and so may be corruptif (sendLevel MAX_GAIN_INT) {ALOGV(Track send level out of range: %04X, sendLevel);sendLevel MAX_GAIN_INT;}// vaf is represented as [0.0, 1.0] float by rescaling sendLevelvaf v * sendLevel * (1. / MAX_GAIN_INT);}track-setFinalVolume((vrf vlf) / 2.f);// XXX: these things DONT need to be done each timemAudioMixer-setBufferProvider(name, track);mAudioMixer-enable(name);mAudioMixer-setParameter(name, param, AudioMixer::VOLUME0, vlf);mAudioMixer-setParameter(name, param, AudioMixer::VOLUME1, vrf);mAudioMixer-setParameter(name, param, AudioMixer::AUXLEVEL, vaf);...} else {...}} // local variable scope to avoid goto warning}return mixerStatus; }mActiveTracks记录了当前处于活跃状态的track接着就是循环遍历每一个track进行处理获取对应的音频参数。 audio_track_cblk_t是音频数据块后面我们会扩展讲解。 在之后minFrames代表了此次音频播放所需要的最小帧数他的初始值为1。当track-sharedBuffer() 0的时候说明这个AudioTrack不是STATIC模式数据不是一次性传送完成的。 getUnreleasedFrames用来获取音频缓冲区中尚未被音频硬件处理的帧数。 当我们计算出minFrames之后就开始判断当前音频的各种指标是否符合标准。 vlf, vrf, vaf分别表示左声道音量右声道音量AUX level音量浮点数表示。 根据streamType获取对应stream类型音频的音量然后进行判断是否在合理范围内最终经过计算设置到AudioMixer对象中。当准备工作完成后就进入到了真正的混音操作中了。 threadloop_mix:主要就是调用AudioMixer的process函数进行处理这样就进入了audiomixer。 void AudioFlinger::MixerThread::threadLoop_mix() {// 启动混音mAudioMixer-process();mCurrentWriteLength mSinkBufferSize;//当应用程序欠载情况清除时逐步增加睡眠时间。//仅当混频器连续两次准备就绪时才增加睡眠时间//以避免交替的就绪/未就绪条件的稳定状态保持睡眠时间从而导致音频 HAL 欠载。if ((mSleepTimeUs 0) (sleepTimeShift 0)) {sleepTimeShift--;}mSleepTimeUs 0;mStandbyTimeNs systemTime() mStandbyDelayNs;//TODO: delay standby when effects have a tail}最后就是将数据写入HAL层了threadloop_write。 当mNormalSink存在的时候调用他的write函数写入不存在就调用mOutput的write函数mOutput就是 AudioStreamOut。 ssize_t AudioFlinger::PlaybackThread::threadLoop_write() {ssize_t bytesWritten;// If an NBAIO sink is present, use it to write the normal mixers submixif (mNormalSink ! 0) {ssize_t framesWritten mNormalSink-write((char *)mSinkBuffer offset, count);ATRACE_END();if (framesWritten 0) {bytesWritten framesWritten * mFrameSize;} else {bytesWritten framesWritten;}// otherwise use the HAL / AudioStreamOut directly} else {bytesWritten mOutput-write((char *)mSinkBuffer offset, mBytesRemaining);}return bytesWritten; } 写入完成后调用各种清理的函数removeclear等。 // Finally let go of removed track(s), without the lock held // since we cant guarantee the destructors wont acquire that // same lock. This will also mutate and push a new fast mixer state. threadLoop_removeTracks(tracksToRemove); tracksToRemove.clear();// FIXME I dont understand the need for this here; // it was in the original code but maybe the // assignment in saveOutputTracks() makes this unnecessary? clearOutputTracks();// Effect chains will be actually deleted here if they were removed from // mEffectChains list during mixing or effects processing effectChains.clear();void AudioFlinger::PlaybackThread::threadLoop_removeTracks(const Vector spTrack tracksToRemove) {size_t count tracksToRemove.size();if (count 0) {for (size_t i 0 ; i count ; i) {const spTrack track tracksToRemove.itemAt(i);if (track-isExternalTrack()) {AudioSystem::stopOutput(mId, track-streamType(),track-sessionId());if (track-isTerminated()) {AudioSystem::releaseOutput(mId, track-streamType(),track-sessionId());}}}} }
http://www.hkea.cn/news/14478321/

相关文章:

  • 海南做网站的技术公司网站建筑设计
  • 商洛城乡建设局网站广东做淘宝的都在哪里网站
  • 天津正规制作网站公司广州天河区建设网站
  • 网页设计素材网站网站权重提升
  • 视频当背景图片 网站开发高级软件开发培训
  • 哪里有网站建设加工vs 2008 建立网站
  • 大型网站只做要多少钱照片合成制作app
  • 10大营销理论优化方法
  • 网站建设账户搭建台州网站建设蓝渊
  • microsoft免费网站沈阳男科最好的男科医院
  • 福州专业网站制作设计上海企业展厅设计公司
  • 网站开发合同印花税wordpress ie9
  • 外国人爱做视频网站吗成都网站建设潮州
  • 工作室网站wordpress 工作流程
  • 门户网站制作流程博客织梦网站模版怎么用
  • 企业内部网站建设费用个人网站开发平台有哪些
  • word怎么做网站iis 子网站
  • 沧州有做网站的吗如何网上查个人房产信息
  • 通州顺德网站建设企业自助网站建设
  • 做网站能带来什么问题自建app
  • 网站免费做测算的网站
  • 深圳全国网站制作哪个好微商城小程序免费
  • 软件商店正版下载安装爱站工具seo综合查询
  • 个人网站开发需求分析网站服务器放置地查询
  • 建设银行网站流水账单怎么打随申行是国企嘛?
  • 全国高校校园网站联盟建设红番茄 网站点评
  • 农业做的好的网站嘉兴网站快速排名优化
  • 做网站比较好的公司有哪些建站优化推广
  • 网站内容由什么组成部分组成部分网站全站搜索代码
  • app网站免费简单门户网站开发