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

朋友帮忙做网站 费用多少上海建筑建材业网招标

朋友帮忙做网站 费用多少,上海建筑建材业网招标,优书网,长沙网络营销学校1、背景 在学习audio的过程中#xff0c;看到了大神zyuanyun的博客#xff0c;在博客的结尾#xff0c;大神留下了这些问题#xff1a; 但是大神没有出后续的博文来说明audio环形缓冲队列的具体实现#xff0c;这勾起了我强烈的好奇心。经过一段时间的走读代码#xff…1、背景 在学习audio的过程中看到了大神zyuanyun的博客在博客的结尾大神留下了这些问题 但是大神没有出后续的博文来说明audio环形缓冲队列的具体实现这勾起了我强烈的好奇心。经过一段时间的走读代码同时阅读其他大佬的博文把环形缓冲队列的内容整理出来。 2、AudioPolicyService、AudioFlinger及相关类 AudioPolicyService简称APS是负责音频策略的制定者比如什么时候打开音频接口设备、某种Stream类型的音频对应什么设备等等AudioFlinger简称AF负责音频策略的具体执行比如如何与音频设备通信如何维护现有系统中的音频设备以及多个音频流的混音如何处理等。 环形缓冲队列大致可以以下面这幅图来描述其流程 3、Track的创建 AudioTrack的创建经过漫长的调用链最终是/frameworks/av/services/audioflinger/Tracks.cpp里完成创建的。 // TrackBase constructor must be called with AudioFlinger::mLock held AudioFlinger::ThreadBase::TrackBase::TrackBase(){//计算最小帧大小size_t minBufferSize buffer NULL ? roundup(frameCount) : frameCount;……minBufferSize * mFrameSize;size_t size sizeof(audio_track_cblk_t);if (buffer NULL alloc ALLOC_CBLK) {// check overflow when computing allocation size for streaming tracks.if (size SIZE_MAX - bufferSize) {android_errorWriteLog(0x534e4554, 34749571);return;}size bufferSize;}if (client ! 0) {//为客户端分配内存mCblkMemory client-heap()-allocate(size);……} else {mCblk (audio_track_cblk_t *) malloc(size);……}// construct the shared structure in-place.if (mCblk ! NULL) {// 这是 C 的 placement new定位创建对象语法new(BUFFER) CLASS();// 可以在特定内存位置上构造一个对象// 这里在匿名共享内存首地址上构造了一个 audio_track_cblk_t 对象// 这样 AudioTrack 与 AudioFlinger 都能访问这个 audio_track_cblk_t 对象了new(mCblk) audio_track_cblk_t();switch (alloc) {……case ALLOC_CBLK:// clear all buffersif (buffer NULL) {// 数据 FIFO 的首地址紧靠控制块audio_track_cblk_t之后// | |// | ------------------- mCblkMemory --------------------- |// | |// --------------------------------------------------------// | audio_track_cblk_t | Buffer |// --------------------------------------------------------// ^ ^// | |// mCblk mBuffer//这里mCblk被强制转型成占用内存1字节的char类型这个1在后面会用到mBuffer (char*)mCblk sizeof(audio_track_cblk_t);memset(mBuffer, 0, bufferSize);} else {// 数据传输模式为 MODE_STATIC/TRANSFER_SHARED 时直接指向 sharedBuffer// sharedBuffer 是应用进程分配的匿名共享内存应用进程已经一次性把数据// 写到 sharedBuffer 来了AudioFlinger 可以直接从这里读取// -------------------- -----------------------------------// | audio_track_cblk_t | | sharedBuffer |// -------------------- -----------------------------------// ^ ^// | |// mCblk mBuffermBuffer buffer;}break;……}……} }4、生产者向共享内存写入数据 4.1 4.2 向共享内存写入数据 //framework/av/media/libaudioclient/AudioTrack.cpp ssize_t AudioTrack::write(const void* buffer, size_t userSize, bool blocking) {……size_t written 0;Buffer audioBuffer;while (userSize mFrameSize) {// 单帧数据量 frameSize channelCount * bytesPerSample// 对于双声道16位采样的音频数据来说frameSize 2 * 2 4(bytes)// 用户传入的数据帧数 frameCount userSize / frameSizeaudioBuffer.frameCount userSize / mFrameSize;// obtainBuffer() 从 FIFO 上得到一块可用区间status_t err obtainBuffer(audioBuffer,blocking ? ClientProxy::kForever : ClientProxy::kNonBlocking);……size_t toWrite audioBuffer.size;memcpy(audioBuffer.i8, buffer, toWrite);buffer ((const char *) buffer) toWrite;userSize - toWrite;written toWrite;releaseBuffer(audioBuffer);}……return written; }status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, const struct timespec *requested,struct timespec *elapsed, size_t *nonContig) {// previous and new IAudioTrack sequence numbers are used to detect track re-creationuint32_t oldSequence 0;uint32_t newSequence;Proxy::Buffer buffer;status_t status NO_ERROR;static const int32_t kMaxTries 5;int32_t tryCounter kMaxTries;do {// obtainBuffer() is called with mutex unlocked, so keep extra references to these fields to// keep them from going away if another thread re-creates the track during obtainBuffer()spAudioTrackClientProxy proxy;spIMemory iMem;{ // start of lock scopeAutoMutex lock(mLock);……// Keep the extra referencesproxy mProxy;iMem mCblkMemory;……} // end of lock scopebuffer.mFrameCount audioBuffer-frameCount;// FIXME starts the requested timeout and elapsed over from scratchstatus proxy-obtainBuffer(buffer, requested, elapsed);} while (((status DEAD_OBJECT) || (status NOT_ENOUGH_DATA)) (tryCounter-- 0));audioBuffer-frameCount buffer.mFrameCount;audioBuffer-size buffer.mFrameCount * mFrameSize;audioBuffer-raw buffer.mRaw;if (nonContig ! NULL) {*nonContig buffer.mNonContig;}return status; }//framework/av/media/libaudioclient/AudioTrackShared.cpp __attribute__((no_sanitize(integer))) status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *requested,struct timespec *elapsed) {……struct timespec before;bool beforeIsValid false;audio_track_cblk_t* cblk mCblk;bool ignoreInitialPendingInterrupt true;for (;;) {int32_t flags android_atomic_and(~CBLK_INTERRUPT, cblk-mFlags);……int32_t front;int32_t rear;if (mIsOut) {front android_atomic_acquire_load(cblk-u.mStreaming.mFront);rear cblk-u.mStreaming.mRear;} else {// On the other hand, this barrier is required.rear android_atomic_acquire_load(cblk-u.mStreaming.mRear);front cblk-u.mStreaming.mFront;}// write to rear, read from frontssize_t filled audio_utils::safe_sub_overflow(rear, front);……ssize_t adjustableSize (ssize_t) getBufferSizeInFrames();ssize_t avail (mIsOut) ? adjustableSize - filled : filled;if (avail 0) {avail 0;} else if (avail 0) {// avail may be non-contiguous, so return only the first contiguous chunksize_t part1;if (mIsOut) {rear mFrameCountP2 - 1;part1 mFrameCountP2 - rear;} else {front mFrameCountP2 - 1;part1 mFrameCountP2 - front;}if (part1 (size_t)avail) {part1 avail;}if (part1 buffer-mFrameCount) {part1 buffer-mFrameCount;}buffer-mFrameCount part1;buffer-mRaw part1 0 ?((char *) mBuffers)[(mIsOut ? rear : front) * mFrameSize] : NULL;buffer-mNonContig avail - part1;mUnreleased part1;status NO_ERROR;break;}struct timespec remaining;const struct timespec *ts;……int32_t old android_atomic_and(~CBLK_FUTEX_WAKE, cblk-mFutex);if (!(old CBLK_FUTEX_WAKE)) {……errno 0;(void) syscall(__NR_futex, cblk-mFutex,mClientInServer ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT, old ~CBLK_FUTEX_WAKE, ts);……}}end:……return status; }void ClientProxy::releaseBuffer(Buffer* buffer) {size_t stepCount buffer-mFrameCount;……mUnreleased - stepCount;audio_track_cblk_t* cblk mCblk;// Both of these barriers are requiredif (mIsOut) {int32_t rear cblk-u.mStreaming.mRear;android_atomic_release_store(stepCount rear, cblk-u.mStreaming.mRear);} else {int32_t front cblk-u.mStreaming.mFront;android_atomic_release_store(stepCount front, cblk-u.mStreaming.mFront);} }4、消费者从共享内存读数据 找到当前活动的track需要经过很长的准备及调用链可以参考这篇博客。 4.1 PlaybackThread的混音 代码路径frameworks/av/services/audioflinger/Threads.cpp void AudioFlinger::MixerThread::threadLoop_mix() {// mix buffers...mAudioMixer-process();mCurrentWriteLength mSinkBufferSize;…… }process()方法之后进入track的混音流程代码位于frameworks/av/media/libaudioprocessing/AudioMixer.cpp。来看process()的定义 using process_hook_t void(AudioMixer::*)();process_hook_t mHook AudioMixer::process__nop; void invalidate() {mHook AudioMixer::process__validate;}void process__validate();void process__nop();void process__genericNoResampling();void process__genericResampling();void process__oneTrack16BitsStereoNoResampling();template int MIXTYPE, typename TO, typename TI, typename TAvoid process__noResampleOneTrack(); hook是一个函数指针根据不同场景会分别指向不同函数实现。详细可以参考这篇博客以及这篇博客。以process__nop方法为例 void AudioMixer::process__nop() {for (const auto pair : mGroups) {const auto group pair.second;const std::shared_ptrTrack t mTracks[group[0]];memset(t-mainBuffer, 0,mFrameCount * audio_bytes_per_frame(t-mMixerChannelCount t-mMixerHapticChannelCount, t-mMixerFormat));// now consume datafor (const int name : group) {const std::shared_ptrTrack t mTracks[name];size_t outFrames mFrameCount;while (outFrames) {t-buffer.frameCount outFrames;t-bufferProvider-getNextBuffer(t-buffer);if (t-buffer.raw NULL) break;outFrames - t-buffer.frameCount;t-bufferProvider-releaseBuffer(t-buffer);}}} }frameworks/av/services/audioflinger/Tracks.cpp status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer) {ServerProxy::Buffer buf;size_t desiredFrames buffer-frameCount;buf.mFrameCount desiredFrames;status_t status mServerProxy-obtainBuffer(buf);buffer-frameCount buf.mFrameCount;buffer-raw buf.mRaw;if (buf.mFrameCount 0 !isStopping() !isStopped() !isPaused()) {mAudioTrackServerProxy-tallyUnderrunFrames(desiredFrames);} else {mAudioTrackServerProxy-tallyUnderrunFrames(0);}return status; }void AudioFlinger::PlaybackThread::Track::releaseBuffer(AudioBufferProvider::Buffer* buffer) {interceptBuffer(*buffer);TrackBase::releaseBuffer(buffer); }/frameworks/av/media/libaudioclient/AudioTrackShared.cpp status_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush) {{audio_track_cblk_t* cblk mCblk;// compute number of frames available to write (AudioTrack) or read (AudioRecord),// or use previous cached value from framesReady(), with added barrier if it omits.int32_t front;int32_t rear;// See notes on barriers at ClientProxy::obtainBuffer()if (mIsOut) {flushBufferIfNeeded(); // might modify mFrontrear getRear();front cblk-u.mStreaming.mFront;} else {front android_atomic_acquire_load(cblk-u.mStreaming.mFront);rear cblk-u.mStreaming.mRear;}……// availToServer may be non-contiguous, so return only the first contiguous chunksize_t part1;if (mIsOut) {front mFrameCountP2 - 1;part1 mFrameCountP2 - front;} else {rear mFrameCountP2 - 1;part1 mFrameCountP2 - rear;}if (part1 availToServer) {part1 availToServer;}size_t ask buffer-mFrameCount;…… }int32_t AudioTrackServerProxy::getRear() const {const int32_t stop android_atomic_acquire_load(mCblk-u.mStreaming.mStop);const int32_t rear android_atomic_acquire_load(mCblk-u.mStreaming.mRear);const int32_t stopLast mStopLast.load(std::memory_order_acquire);……return rear; }5、总结 经过一段时间的代码走读能够回答文章开头提出的部分问题但是诸如“读写指针线程安全”、“Futex同步机制”等问题现阶段还回答不上来以后有机会再深入研究下。
http://www.zqtcl.cn/news/571782/

相关文章:

  • 麦包包的网站建设分析网站开发一般要用到哪些软件有哪些
  • 关于内网站建设的请示天津住房与城乡建设厅网站首页
  • 企业网站免费源码装修公司需要多少钱
  • 沈阳建设网站费用群晖wordpress打不开
  • jsp网站开发 pdf建设植绒衣架网站
  • 做网站接单的网站做外贸网站价位
  • 金融商城快捷申请网站模板下载汕头网站建设和运营
  • 网站建设网站备案所需资料请兼职做企业网站设计怎么收费
  • 电脑配件经营网站的建设论文邯郸市环保局网站建设项目环境
  • 那些网站可以做反链免费游戏不用登录直接玩
  • 安徽网站建设的基本步骤接外贸订单的平台
  • 那些网站可以找得到做货代的广东企业微信网站开发
  • 海宁市建设局官方网站6哔哩哔哩网页版官网在线观看
  • 泉州网站建设轩奇网讯韩国美容网站模板
  • 培训好吗网站建设wordpress手游
  • 元典科技网站建设网页设计制作图片页面
  • 网站设置什么意思无代码搭建平台
  • 织梦做的网站后台登录做网站购买域名
  • 哈尔滨网站关键词优化排名合江做网站
  • 手机网站自动适配旅游网络营销方案
  • 敦化网站开发黔东南购物网站开发设计
  • 建设一个网站 需要提供什么如何免费推广自己的网站
  • 佛山企业网站制作公司中国互联网企业100强榜单
  • 买了域名就可以做网站怎么创造游戏软件
  • 广东广州电脑个人建站徐州网站排名公司
  • 网站优化 流量做网站对企业有什么好处
  • 建设机械网站制作人工智能工程师月薪多少
  • wordpress 百度站长沈阳app开发公司哪家好
  • 做网站平台公司网站建设硬件环境
  • 可视化编辑建站平台新密市城乡建设局网站