AudioTrack中write函數size疑問

來源:互聯網
上載者:User

  AudioTrack中write函數size疑問

  最近在看《深入理解Android》中Audio相關部分時,看到AudioTrack::write函數的實現時,對其中操作的size有些疑問。

  函數完整代碼如下:

  ssize_t AudioTrack::write(const void* buffer, size_t userSize)

  {

  if (mSharedBuffer != 0) return INVALID_OPERATION;

  if (mIsTimed) return INVALID_OPERATION;

  if (ssize_t(userSize) < 0) {

  // Sanity-check: user is most-likely passing an error code, and it would

  // make the return value ambiguous (actualSize vs error).

  ALOGE("AudioTrack::write(buffer=%p, size=%u (%d)",

  buffer, userSize, userSize);

  return BAD_VALUE;

  }

  ALOGV("write %p: %d bytes, mActive=%d", this, userSize, mActive);

  if (userSize == 0) {

  return 0;

  }

  // acquire a strong reference on the IMemory and IAudioTrack so that they cannot be destroyed

  // while we are accessing the cblk

  mLock.lock();

  sp audioTrack = mAudioTrack;

  sp iMem = mCblkMemory;

  mLock.unlock();

  ssize_t written = 0;

  const int8_t *src = (const int8_t *)buffer;

  Buffer audioBuffer;

  size_t frameSz = frameSize();

  do {

  audioBuffer.frameCount = userSize/frameSz;

  status_t err = obtainBuffer(&audioBuffer, -1);

  if (err < 0) {

  // out of buffers, return #bytes written

  if (err == status_t(NO_MORE_BUFFERS))

  break;

  return ssize_t(err);

  }

  size_t toWrite;

  if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {

  // Divide capacity by 2 to take expansion into account

  toWrite = audioBuffer.size>>1;

  memcpy_to_i16_from_u8(audioBuffer.i16, (const uint8_t *) src, toWrite);

  } else {

  // !!!疑問點!!!

  toWrite = audioBuffer.size;

  memcpy(audioBuffer.i8, src, toWrite);

  src += toWrite;

  }

  userSize -= toWrite;

  written += toWrite;

  releaseBuffer(&audioBuffer);

  } while (userSize >= frameSz);

  return written;

  }

  疑問點就是上面代碼中標識出的疑問點。

  因為audioBuffer是調用obtainBuffer擷取的,此處copy資料時只考慮到了audioBuffer的size,而沒考慮來源資料src的size,如果audioBuffer的size大於src的size,豈不是會copy到無效資料?

  除非audioBuffer的size與src的size有一定關係。

  看看obtainBuffer的實現(只列出相關部分):

  status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)

  {

  AutoMutex lock(mLock);

  ...

  audio_track_cblk_t* cblk = mCblk;

  // 關注點 1

  uint32_t framesReq = audioBuffer->frameCount;

  ...

  audioBuffer->frameCount = 0;

  audioBuffer->size = 0;

  uint32_t framesAvail = cblk->framesAvailable();

  ...

  cblk->lock.unlock();

  if (framesAvail == 0) {

  cblk->lock.lock();

  goto start_loop_here;

  while (framesAvail == 0) {

  // 迴圈嘗試擷取可寫的空間

  ...

  // read the server count again

  start_loop_here:

  framesAvail = cblk->framesAvailable_l();

  }

  cblk->lock.unlock();

  }

  cblk->waitTimeMs = 0;

  // 關注點 2

  if (framesReq > framesAvail) {

  framesReq = framesAvail;

  }

  uint32_t u = cblk->user;

  uint32_t bufferEnd = cblk->userBase + cblk->frameCount;

  // 關注點 3

  if (framesReq > bufferEnd - u) {

  framesReq = bufferEnd - u;

  }

  audioBuffer->flags = mMuted ? Buffer::MUTE : 0;

  audioBuffer->channelCount = mChannelCount;

  audioBuffer->frameCount = framesReq;

  // 關注點 4

  audioBuffer->size = framesReq * cblk->frameSize;

  if (audio_is_linear_pcm(mFormat)) {

  audioBuffer->format = AUDIO_FORMAT_PCM_16_BIT;

  } else {

  audioBuffer->format = mFormat;

  }

  audioBuffer->raw = (int8_t *)cblk->buffer(u);

  active = mActive;

  return active ? status_t(NO_ERROR) : status_t(STOPPED);

  }

  從上面的4個關注點可知,audioBuffer的size來源於framesReq,即audioBuffer->frameCount,當然中間設計到比較適配處理。

  從函數AudioTrack::write的實現可知,audioBuffer->frameCount是根據src的size計算得來:

  audioBuffer.frameCount = userSize/frameSz;

  也就是說,audioBuffer的size最終來源於src的size。

  並且根據上述關注點2、3的處理可知,audioBuffer的size小於或等於src的size。

  因此之前的擔心點也就不用擔心了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.