接上文
https://blog.csdn.net/we1less/article/details/156491150?spm=1001.2014.3001.5502
https://blog.csdn.net/we1less/article/details/156506593?spm=1001.2014.3001.5502
audioflinger
av/services/audioflinger/Threads.cpp threadLoop_write
AudioMixerBase 将mSinkBuffer 填充, mNormalSink 将数据写入到 hal 中
cpp
ssize_t PlaybackThread::threadLoop_write()
{
ssize_t bytesWritten;
const size_t offset = mCurrentWriteLength - mBytesRemaining;
if (mNormalSink != 0) {
const size_t count = mBytesRemaining / mFrameSize;
ssize_t framesWritten = mNormalSink->write((char *)mSinkBuffer + offset, count);
}
return bytesWritten;
}
看下这个 mNormalSink 是从哪来的
av/services/audioflinger/Threads.cpp mNormalSink
可以看出 mNormalSink 是由 构造 AudioStreamOutSink 赋值而来
cpp
/* static */
sp<IAfPlaybackThread> IAfPlaybackThread::createMixerThread(
const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
audio_io_handle_t id, bool systemReady, type_t type, audio_config_base_t* mixerConfig) {
return sp<MixerThread>::make(afThreadCallback, output, id, systemReady, type, mixerConfig);
}
MixerThread::MixerThread(const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
audio_io_handle_t id, bool systemReady, type_t type, audio_config_base_t *mixerConfig)
: PlaybackThread(afThreadCallback, output, id, type, systemReady, mixerConfig),
// mOutputSink below
// mPipeSink below
// mNormalSink below
{
mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
mOutputSink = new AudioStreamOutSink(output->stream);
mNormalSink = mOutputSink;
}
av/media/libnbaio/AudioStreamOutSink.cpp write
上文已经得知,在 AudioStreamOutSink 的构造器中保存了output->stream 为mStream 后续的 write 数据就是用 mStream
上文可得知,mStream 是由 AudioStreamOut 构造而来
cpp
AudioStreamOutSink::AudioStreamOutSink(sp<StreamOutHalInterface> stream) :
NBAIO_Sink(),
mStream(stream),
mStreamBufferSizeBytes(0)
{
ALOG_ASSERT(stream != 0);
}
ssize_t AudioStreamOutSink::write(const void *buffer, size_t count)
{
size_t written;
status_t ret = mStream->write(buffer, count * mFrameSize, &written);
auto processor = mMelProcessor.load();
processor->process(buffer, written);
written /= mFrameSize;
mFramesWritten += written;
return written;
}
av/services/audioflinger/datapath/AudioStreamOut.cpp write
上文可得知,这里的 stream 是 StreamOutHalHidl
cpp
ssize_t AudioStreamOut::write(const void *buffer, size_t numBytes)
{
size_t bytesWritten;
const status_t result = stream->write(buffer, numBytes, &bytesWritten);
if (result == OK && bytesWritten > 0 && mHalFrameSize > 0) {
mFramesWritten += bytesWritten / mHalFrameSize;
}
return result == OK ? bytesWritten : result;
}
av/media/libaudiohal/impl/StreamHalHidl.cpp StreamOutHalHidl::write
cpp
status_t StreamOutHalHidl::write(const void *buffer, size_t bytes, size_t *written) {
status_t status;
if (!mDataMQ) {
size_t bufferSize;
if ((status = getCachedBufferSize(&bufferSize)) != OK) {
return status;
}
if (bytes > bufferSize) bufferSize = bytes;
if ((status = prepareForWriting(bufferSize)) != OK) {
return status;
}
}
status = callWriterThread(
WriteCommand::WRITE, "write", static_cast<const uint8_t*>(buffer), bytes,
[&] (const WriteStatus& writeStatus) {
*written = writeStatus.reply.written;
});
return status;
}
status_t StreamOutHalHidl::callWriterThread(
WriteCommand cmd, const char* cmdName,
const uint8_t* data, size_t dataSize, StreamOutHalHidl::WriterCallback callback) {
mCommandMQ->write(&cmd);
size_t availableToWrite = mDataMQ->availableToWrite();
mDataMQ->write(data, dataSize);
mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
uint32_t efState = 0;
retry:
status_t ret = mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)) {
WriteStatus writeStatus;
writeStatus.retval = Result::NOT_INITIALIZED;
mStatusMQ->read(&writeStatus);
if (writeStatus.retval == Result::OK) {
ret = OK;
callback(writeStatus);
} else {
ret = processReturn(cmdName, writeStatus.retval);
}
return ret;
}
if (ret == -EAGAIN || ret == -EINTR) {
goto retry;
}
return ret;
}
av/media/libaudiohal/impl/StreamHalHidl.h
cpp
typedef MessageQueue<WriteCommand, hardware::kSynchronizedReadWrite> CommandMQ;
typedef MessageQueue<uint8_t, hardware::kSynchronizedReadWrite> DataMQ;
typedef MessageQueue<WriteStatus, hardware::kSynchronizedReadWrite> StatusMQ;
std::unique_ptr<CommandMQ> mCommandMQ;
std::unique_ptr<DataMQ> mDataMQ;
std::unique_ptr<StatusMQ> mStatusMQ;
libfmq/include/fmq/MessageQueue.h fast message queue 快速共享内存消息队列方案
bash
NX563J:/ # ps -A | grep audio
root 491 2 0 0 rescuer_thread 0 S [uaudio_svc]
u0_a153 3329 1024 14529584 77320 SyS_epoll_wait 0 S org.lineageos.audiofx
audioserver 3975 1 53432 18240 binder_ioctl_write_read 0 S android.hardware.audio.service
audioserver 3976 1 11615784 22980 binder_ioctl_write_read 0 S audioserver
NX563J:/ # cat proc/3976/maps | grep Ashmem
1|NX563J:/ # cat proc/3976/maps | grep ashmem
741dcf7000-741dd00000 rw-s 00000000 00:05 48339 /dev/ashmem/MemoryHeapBase (deleted)
741de1c000-741de1d000 rw-s 00000000 00:05 72121 /dev/ashmem/MessageQueue (deleted)
741de64000-741de65000 rw-s 00000000 00:05 72121 /dev/ashmem/MessageQueue (deleted)
741dec7000-741dec8000 rw-s 00000000 00:05 72121 /dev/ashmem/MessageQueue (deleted)
741df5f000-741df60000 rw-s 00001000 00:05 72120 /dev/ashmem/MessageQueue (deleted)
741e0a4000-741e0a6000 rw-s 00000000 00:05 72120 /dev/ashmem/MessageQueue (deleted)
741e122000-741e127000 rw-s 00000000 00:05 88955 /dev/ashmem/MemoryHeapBase (deleted)
741e34e000-741e34f000 rw-s 00000000 00:05 72120 /dev/ashmem/MessageQueue (deleted)
741e34f000-741e350000 rw-s 00000000 00:05 72120 /dev/ashmem/MessageQueue (deleted)
741e350000-741e355000 rw-s 00000000 00:05 47035 /dev/ashmem/MemoryHeapBase (deleted)
741e53e000-741e53f000 rw-s 00000000 00:05 72119 /dev/ashmem/MessageQueue (deleted)
741e540000-741e541000 rw-s 00000000 00:05 72119 /dev/ashmem/MessageQueue (deleted)
741e541000-741e542000 rw-s 00000000 00:05 72119 /dev/ashmem/MessageQueue (deleted)
741e547000-741e548000 rw-s 00000000 00:05 60603 /dev/ashmem/MemoryHeapBase (deleted)
741e548000-741e549000 rw-s 00000000 00:05 62515 /dev/ashmem/MessageQueue (deleted)
741e549000-741e54a000 rw-s 00000000 00:05 62515 /dev/ashmem/MessageQueue (deleted)
741e54a000-741e54b000 rw-s 00000000 00:05 62515 /dev/ashmem/MessageQueue (deleted)
741e54c000-741e54d000 rw-s 00000000 00:05 62514 /dev/ashmem/MessageQueue (deleted)
741e54d000-741e54e000 rw-s 00000000 00:05 62514 /dev/ashmem/MessageQueue (deleted)
741e54f000-741e550000 rw-s 00000000 00:05 62514 /dev/ashmem/MessageQueue (deleted)
741e550000-741e551000 rw-s 00000000 00:05 62514 /dev/ashmem/MessageQueue (deleted)
741e551000-741e552000 rw-s 00000000 00:05 62513 /dev/ashmem/MessageQueue (deleted)
741e554000-741e555000 rw-s 00000000 00:05 62513 /dev/ashmem/MessageQueue (deleted)
741f709000-741f70a000 rw-s 00000000 00:05 62513 /dev/ashmem/MessageQueue (deleted)
741f70a000-741f70b000 rw-s 00000000 00:05 48109 /dev/ashmem/MemoryHeapBase (deleted)
NX563J:/ # cat proc/3975/maps | grep ashmem
e74df000-e74e0000 rw-s 00000000 00:05 72121 /dev/ashmem/MessageQueue (deleted)
e74e0000-e74e1000 rw-s 00000000 00:05 72121 /dev/ashmem/MessageQueue (deleted)
e74e1000-e74e2000 rw-s 00000000 00:05 72121 /dev/ashmem/MessageQueue (deleted)
e74e2000-e74e3000 rw-s 00001000 00:05 72120 /dev/ashmem/MessageQueue (deleted)
e74e3000-e74e5000 rw-s 00000000 00:05 72120 /dev/ashmem/MessageQueue (deleted)
e74e5000-e74e6000 rw-s 00000000 00:05 72120 /dev/ashmem/MessageQueue (deleted)
e74e6000-e74e7000 rw-s 00000000 00:05 72120 /dev/ashmem/MessageQueue (deleted)
e74e7000-e74e8000 rw-s 00000000 00:05 72119 /dev/ashmem/MessageQueue (deleted)
e74e8000-e74e9000 rw-s 00000000 00:05 72119 /dev/ashmem/MessageQueue (deleted)
e74e9000-e74ea000 rw-s 00000000 00:05 72119 /dev/ashmem/MessageQueue (deleted)
e74fe000-e74ff000 rw-s 00000000 00:05 62515 /dev/ashmem/MessageQueue (deleted)
e74ff000-e7500000 rw-s 00000000 00:05 62515 /dev/ashmem/MessageQueue (deleted)
e7500000-e7501000 rw-s 00000000 00:05 62515 /dev/ashmem/MessageQueue (deleted)
e7501000-e7502000 rw-s 00000000 00:05 62514 /dev/ashmem/MessageQueue (deleted)
e75bb000-e75bc000 rw-s 00000000 00:05 62514 /dev/ashmem/MessageQueue (deleted)
e75bc000-e75bd000 rw-s 00000000 00:05 62514 /dev/ashmem/MessageQueue (deleted)
e75be000-e75bf000 rw-s 00000000 00:05 62514 /dev/ashmem/MessageQueue (deleted)
e75bf000-e75c0000 rw-s 00000000 00:05 62513 /dev/ashmem/MessageQueue (deleted)
e75c0000-e75c1000 rw-s 00000000 00:05 62513 /dev/ashmem/MessageQueue (deleted)
e75c1000-e75c2000 rw-s 00000000 00:05 62513 /dev/ashmem/MessageQueue (deleted)
e787c000-e787d000 rw-s 00000000 00:05 49782 /dev/ashmem/MessageQueue (deleted)
e787d000-e787e000 rw-s 00000000 00:05 49782 /dev/ashmem/MessageQueue (deleted)
e787e000-e787f000 rw-s 00000000 00:05 49782 /dev/ashmem/MessageQueue (deleted)
e79a6000-e79a7000 rw-s 00000000 00:05 49782 /dev/ashmem/MessageQueue (deleted)
e7a76000-e7a77000 rw-s 00001000 00:05 40712 /dev/ashmem/MessageQueue (deleted)
e7a77000-e7a79000 rw-s 00000000 00:05 40712 /dev/ashmem/MessageQueue (deleted)
e7a79000-e7a7a000 rw-s 00000000 00:05 40712 /dev/ashmem/MessageQueue (deleted)
e7a7a000-e7a7b000 rw-s 00000000 00:05 40712 /dev/ashmem/MessageQueue (deleted)
av/media/libaudiohal/impl/StreamHalHidl.cpp prepareForWriting
cpp
status_t StreamOutHalHidl::prepareForWriting(size_t bufferSize) {
std::unique_ptr<CommandMQ> tempCommandMQ;
std::unique_ptr<DataMQ> tempDataMQ;
std::unique_ptr<StatusMQ> tempStatusMQ;
Result retval;
pid_t halThreadPid, halThreadTid;
Return<void> ret = mStream->prepareForWriting(
1, bufferSize,
[&](Result r,
const CommandMQ::Descriptor& commandMQ,
const DataMQ::Descriptor& dataMQ,
const StatusMQ::Descriptor& statusMQ,
const auto& halThreadInfo) {
retval = r;
if (retval == Result::OK) {
tempCommandMQ.reset(new CommandMQ(commandMQ));
tempDataMQ.reset(new DataMQ(dataMQ));
tempStatusMQ.reset(new StatusMQ(statusMQ));
if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
}
halThreadPid = halThreadInfo.pid;
halThreadTid = halThreadInfo.tid;
}
});
if (!ret.isOk() || retval != Result::OK) {
return processReturn("prepareForWriting", ret, retval);
}
requestHalThreadPriority(halThreadPid, halThreadTid);
mCommandMQ = std::move(tempCommandMQ);
mDataMQ = std::move(tempDataMQ);
mStatusMQ = std::move(tempStatusMQ);
mWriterClient = gettid();
return OK;
}
audio-hal
interfaces/audio/core/all-versions/default/StreamOut.cpp
cpp
Return<void> StreamOut::prepareForWriting(uint32_t frameSize, uint32_t framesCount,
prepareForWriting_cb _hidl_cb) {
status_t status;
std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1));
std::unique_ptr<DataMQ> tempDataMQ(new DataMQ(frameSize * framesCount, true /* EventFlag */));
std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1));
auto tempWriteThread =
sp<WriteThread>::make(&mStopWriteThread, mStream, tempCommandMQ.get(), tempDataMQ.get(),
tempStatusMQ.get(), tempElfGroup.get());
tempWriteThread->init();
status = tempWriteThread->run("writer", PRIORITY_URGENT_AUDIO);
mCommandMQ = std::move(tempCommandMQ);
mDataMQ = std::move(tempDataMQ);
mStatusMQ = std::move(tempStatusMQ);
mWriteThread = tempWriteThread;
_hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(),
threadInfo);
return Void();
}
interfaces/audio/core/all-versions/default/StreamOut.cpp
cpp
bool WriteThread::threadLoop() {
while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
uint32_t efState = 0;
mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);
if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY))) {
continue; // Nothing to do.
}
if (!mCommandMQ->read(&mStatus.replyTo)) {
continue; // Nothing to do.
}
switch (mStatus.replyTo) {
case IStreamOut::WriteCommand::WRITE:
doWrite();
break;
case IStreamOut::WriteCommand::GET_PRESENTATION_POSITION:
doGetPresentationPosition();
break;
case IStreamOut::WriteCommand::GET_LATENCY:
doGetLatency();
break;
}
if (!mStatusMQ->write(&mStatus)) {
ALOGE("status message queue write failed");
}
mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
}
return false;
}
void WriteThread::doWrite() {
const size_t availToRead = mDataMQ->availableToRead();
mStatus.retval = Result::OK;
mStatus.reply.written = 0;
if (mDataMQ->read(&mBuffer[0], availToRead)) {
ssize_t writeResult = mStream->write(mStream, &mBuffer[0], availToRead);
if (writeResult >= 0) {
mStatus.reply.written = writeResult;
} else {
mStatus.retval = Stream::analyzeStatus("write", writeResult);
}
}
}