手机
当前位置:查字典教程网 >编程开发 >安卓软件开发 >AudioTrack中write函数size疑问
AudioTrack中write函数size疑问
摘要:AudioTrack中write函数size疑问最近在看《深入理解Android》中Audio相关部分时,看到AudioTrack::wri...

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。

因此之前的担心点也就不用担心了。

【AudioTrack中write函数size疑问】相关文章:

Android三种GSM手机定位技术分析

Android ellipsize的小问题介绍

Andorid TextView字幕效果实例

android中Invalidate和postInvalidate的更新view区别

Android中BroadcastReceiver(异步接收广播Intent)的使用

ListView的View回收引起的checkbox状态改变监听等问题解决方案

Android 混淆代码详解及实例

Android按返回键退出程序但不销毁代码

Android中实现EditText圆角的方法

Android 的Bitmap的修改方法

精品推荐
分类导航