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

php网站建设论文东莞横沥医院

php网站建设论文,东莞横沥医院,wordpress小标签,网站源码官网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/413749/

相关文章:

  • 郑州七彩网站建设公司怎么样国内老牌的注册代理
  • 衡水外贸网站建设临清轴承网站建设
  • 上街郑州网站建设网站管理建设的需求分析
  • 厦门网站建设策划网站推广的常用方法有哪些
  • 做电脑图标的网站上海定制网站建设公司哪家好
  • 重庆seo网站推广工具济南网页设计师招聘信息
  • 甘肃永靖建设住建局网站深圳网络广告推广公司
  • 台州企业网站搭建电话厦门学网站建设
  • 做易经网站做网站布为网
  • 高端定制开发网站可以做网站的网络
  • 局政务网站建设管理工作总结wordpress ks主题
  • 网站集约化建设的意义网页制作成app
  • 建设银行大厂支行网站专业的营销型网站建设公司
  • 询盘网站苏州建设银行招聘网站
  • 制作网站图片手机网站跳转
  • 装修公司营销网站模板东莞家居网站建设
  • 网站模板建站教程视频德州极速网站建设百家号
  • 专做蔬菜水果的网站自学it从哪里学起
  • 邵阳红网站搭建平台聚合力
  • 滁州网站建设信息推荐软件开发技术方案模板
  • 商务网站建设有哪几个步骤拼多多网页qq登录
  • 厦门商城网站开发宜昌小程序开发公司
  • 东莞沙田网站建设榆林网站建设价格
  • 无锡网站制作建设wordpress写文章模板
  • 企业网站销售提升学历要多少钱
  • 打开建设银行官方网站首页wordpress 站库分离
  • 电子商务网站建设的试卷设计之家app
  • 抚养网站建设黔东南小程序开发公司
  • 网站建设相关行业有哪些wordpress 内容管理系统
  • 网站 备案地温州网站优化排名推广