Threadloop_write到snd_pcm_open

我只是一个虾纸丫 提交于 2019-12-10 03:28:14


本文以MixerThread为例

1. threadloop到streamout的write函数

start执行下来的broadcast_l(),唤醒了MixerThread::threadloop
MixerThread线程环接收到广播信号,开始处理。
注意:我这版本的代码没有重新编写MixerThread::threadloop,故执行在AudioFlinger::PlaybackThread::threadLoop中。此版本的线程环包含了其他线程的判断。

AudioFlinger::PlaybackThread::threadLoop
	|- AudioFlinger::MixerThread::threadLoop_write
		|- AudioFlinger::PlaybackThread::threadLoop_write
			|- write
//Threads.cpp
bool AudioFlinger::PlaybackThread::threadLoop()
{
	//处理配置
	processConfigEvents_l();

	if (mNormalSink != 0) {
		//······
	}
	
	//准备数据
	// mMixerStatusIgnoringFastTracks is also updated internally
	mMixerStatus = prepareTracks_l(&tracksToRemove);

	//写到hal
	ret = threadLoop_write();
}




//Threads.cpp
ssize_t AudioFlinger::MixerThread::threadLoop_write()
{
                // FIXME workaround for first HAL write being CPU bound on some devices
	mOutput->write((char *)mSinkBuffer, 0);
    
	 //调到playback thread类定义的write,这里是实际的赋值
	return PlaybackThread::threadLoop_write();
}



//Threads.cpp
ssize_t AudioFlinger::PlaybackThread::threadLoop_write()
{
    mInWrite = true;
    ssize_t bytesWritten;
    const size_t offset = mCurrentWriteLength - mBytesRemaining;

    // If an NBAIO sink is present, use it to write the normal mixer's submix
    if (mNormalSink != 0) {
		//······
		
		//mNormalSink的write操作,具体看下mNormalSink的定义
        ssize_t framesWritten = mNormalSink->write((char *)mSinkBuffer + offset, count);
        
    // otherwise use the HAL / AudioStreamOut directly
    } else {
        // Direct output and offload threads

		//
        bytesWritten = mOutput->write((char *)mSinkBuffer + offset, mBytesRemaining);
    }
}

到这里可以看出来,从线程环执行到具体的write函数,不过这个write函数有两种:

  1. mNormalSink->write
  2. mOutput->write

2. streamout的write函数

我们来分别看下这两种调用的flow

2.1 mNormalSink->write

2.1.1 mNormalSink定义

//-----------------------------mNormalSink-------------------------
//@Threads.h
class PlaybackThread : public ThreadBase, public StreamOutHalInterfaceCallback,
    public VolumeInterface {
    
	sp<NBAIO_Sink>          mNormalSink;
}

//@NBAIO.h
class NBAIO_Sink : public NBAIO_Port {
    virtual ssize_t write(const void *buffer, size_t count) = 0;
}

mNormalSink变量是PlaybackThread 类中的变量
其类型是NBAIO_Sink类的强指针

mNormalSink->write是NBAIO_Sink类中定义的一个纯虚函数,需要查找这个write的具体执行函数

2.1.2 mNormalSink创建

mNormalSink是PlaybackThread 类中的变量,所以在PlaybackThread的初始化中看下是否对它进行赋值。

查看PlaybackThread的构造函数,没有找到mNormalSink变量的初始化,那就去mixerthread中找找看(因为mixerthread继承自PlaybackThread,所以mixerthread也有mNormalSink变量)。

//threads.cpp
AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
                                             AudioStreamOut* output,
                                             audio_io_handle_t id,
                                             audio_devices_t device,
                                             type_t type,
                                             bool systemReady)
    :   ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type, systemReady),
        mNormalFrameCount(0), mSinkBuffer(NULL),
        mMixerBufferEnabled(AudioFlinger::kEnableExtendedPrecision),
        mMixerBuffer(NULL),
        mMixerBufferSize(0),
        mMixerBufferFormat(AUDIO_FORMAT_INVALID),
        mMixerBufferValid(false),
        mEffectBufferEnabled(AudioFlinger::kEnableExtendedPrecision),
        mEffectBuffer(NULL),
        mEffectBufferSize(0),
        mEffectBufferFormat(AUDIO_FORMAT_INVALID),
        mEffectBufferValid(false),
        mSuspended(0), mBytesWritten(0),
        mFramesWritten(0),
        mSuspendedFrames(0),
        mActiveTracks(&this->mLocalLog),
        // mStreamTypes[] initialized in constructor body
        mOutput(output),
        mLastWriteTime(-1), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
        mMixerStatus(MIXER_IDLE),
        mMixerStatusIgnoringFastTracks(MIXER_IDLE),
        mStandbyDelayNs(AudioFlinger::mStandbyTimeInNsecs),
        mBytesRemaining(0),
        mCurrentWriteLength(0),
        mUseAsyncWrite(false),
        mWriteAckSequence(0),
        mDrainSequence(0),
        mScreenState(AudioFlinger::mScreenState),
        // index 0 is reserved for normal mixer's submix
        mFastTrackAvailMask(((1 << FastMixerState::sMaxFastTracks) - 1) & ~1),
        mHwSupportsPause(false), mHwPaused(false), mFlushPending(false),
        mLeftVolFloat(-1.0), mRightVolFloat(-1.0), mHwSupportsSuspend(false)
{
    snprintf(mThreadName, kThreadNameLength, "AudioOut_%X", id);
    mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mThreadName);

    // Assumes constructor is called by AudioFlinger with it's mLock held, but
    // it would be safer to explicitly pass initial masterVolume/masterMute as
    // parameter.
    //
    // If the HAL we are using has support for master volume or master mute,
    // then do not attenuate or mute during mixing (just leave the volume at 1.0
    // and the mute set to false).
    mMasterVolume = audioFlinger->masterVolume_l();
    mMasterMute = audioFlinger->masterMute_l();
    if (mOutput && mOutput->audioHwDev) {
        if (mOutput->audioHwDev->canSetMasterVolume()) {
            mMasterVolume = 1.0;
        }

        if (mOutput->audioHwDev->canSetMasterMute()) {
            mMasterMute = false;
        }
    }

    readOutputParameters_l();

    // ++ operator does not compile
    for (audio_stream_type_t stream = AUDIO_STREAM_MIN; stream < AUDIO_STREAM_CNT;
            stream = (audio_stream_type_t) (stream + 1)) {
        mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream);
        mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
    }
}


//threads.cpp
AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
        audio_io_handle_t id, audio_devices_t device, bool systemReady, type_t type)
    :   PlaybackThread(audioFlinger, output, id, device, type, systemReady),
        // mAudioMixer below
        // mFastMixer below
        mFastMixerFutex(0),
        mMasterMono(false)
        // mOutputSink below
        // mPipeSink below
        // mNormalSink below
{
    mOutputSink = new AudioStreamOutSink(output->stream);

	mOutputSink->negotiate(offers, 1, NULL, numCounterOffers);

	NBAIO_Format format = mOutputSink->format();

	state->mOutputSink = mOutputSink.get();

    switch (kUseFastMixer) {
    case FastMixer_Never:
    case FastMixer_Dynamic:
        mNormalSink = mOutputSink;
        break;
    case FastMixer_Always:
        mNormalSink = mPipeSink;
        break;
    case FastMixer_Static:
        mNormalSink = initFastMixer ? mPipeSink : mOutputSink;
        break;
    }
    
}

在MixerThread构造函数中发现了mNormalSink 的初始化,这里分为两种情况

  1. mNormalSink = mOutputSink
  2. mNormalSink = mPipeSink

这里简单介绍第一种情况

在MixerThread构造函数中,为AudioStreamOutSink类分配了空间,并把mOutputSink(后面赋值给mNormalSink)指向该空间。

接下来查看两点

 1.入参output->stream的由来
 2.AudioStreamOutSink的构造函数

2.1.2.1 new AudioStreamOutSink的入参

MixerThread构造函数中将output->stream作为AudioStreamOutSink的入参,而output又是MixerThread的入参,查看下创建MixerThread的函数

//AudioFlinger.cpp
sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
                                                            audio_io_handle_t *output,
                                                            audio_config_t *config,
                                                            audio_devices_t devices,
                                                            const String8& address,
                                                            audio_output_flags_t flags)

{
    AudioStreamOut *outputStream = NULL;
    status_t status = outHwDev->openOutputStream(
            &outputStream,
            *output,
            devices,
            flags,
            config,
            address.string());

	thread = new MixerThread(this, outputStream, *output, devices, mSystemReady);
}

可以看到,AudioStreamOutSink的入参output == MixerThread的入参outputStream,而outputStream又是在outHwDev->openOutputStream()函数中进行初始化的,openOutputStream函数是初始化这个outputStream参数的流程参见这篇文章

2.1.2.2 AudioStreamOutSink的构造函数

//AudioStreamOutSink.h
class AudioStreamOutSink : public NBAIO_Sink {
    sp<StreamOutHalInterface> mStream;
}

//AudioStreamOutSink.cpp
AudioStreamOutSink::AudioStreamOutSink(sp<StreamOutHalInterface> stream) :
        NBAIO_Sink(),
        mStream(stream),
        mStreamBufferSizeBytes(0)
{
    ALOG_ASSERT(stream != 0);
}


//@threads.cpp
AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
        audio_io_handle_t id, audio_devices_t device, bool systemReady, type_t type)
    :   PlaybackThread(audioFlinger, output, id, device, type, systemReady)
{
    // create an NBAIO sink for the HAL output stream, and negotiate
	mOutputSink = new AudioStreamOutSink(output->stream);
}

AudioStreamOutSink的构造函数将入参stream(即output->stream)赋值给AudioStreamOutSink类中的变量mStream。之后在AudioStreamOutSink的ops中就可以直接获取mStream进行处理。

需要注意的是mStream类型,它是一个强指针,而且是一个hal接口,具体的操作定义后面遇到了讨论。

2.1.2.3 AudioStreamOutSink的ops

mNormalSink->write执行的是AudioStreamOutSink::write()函数

看下定义

//AudioStreamOutSink.h
class AudioStreamOutSink : public NBAIO_Sink 
	virtual ssize_t write(const void *buffer, size_t count);
}

这里可以发现,AudioStreamOutSink类型继承自NBAIO_Sink,又重新定义了write函数,看下write函数的具体实现

//AudioStreamOutSink.cpp
ssize_t AudioStreamOutSink::write(const void *buffer, size_t count)
{
    status_t ret = mStream->write(buffer, count * mFrameSize, &written);
}

//AudioStreamOutSink.h
class AudioStreamOutSink : public NBAIO_Sink {
    sp<StreamOutHalInterface> mStream;
}

//AudioStreamOutSink.cpp
AudioStreamOutSink::AudioStreamOutSink(sp<StreamOutHalInterface> stream) :
        NBAIO_Sink(),
        mStream(stream),
        mStreamBufferSizeBytes(0)
{
    ALOG_ASSERT(stream != 0);
}

NBAIO_Sink的实现类是:AudioStreamOutSink
mStream是AudioStreamOutSink类中的变量,其类型是StreamOutHalInterface的指针。
就是传入的那个output->stream参数,接下来查看下这个变量的操作。

output->stream变量的初始化在openoutput()中实现,具体调用内容参考这篇文章

直接看下mStream的write操作

//@audio_hw.c
//初始化输出流的操作
static int adev_open_output_stream(struct audio_hw_device *dev,
                                   audio_io_handle_t handle,
                                   audio_devices_t devices,
                                   audio_output_flags_t flags,
                                   struct audio_config *config,
                                   struct audio_stream_out **stream_out,
                                   const char *address __unused)
{
    out->stream.write = out_write;
}

这里进行了初始化,所以AudioStreamOutSink::write执行的write就是out_write函数。
out_write的调用在第三章,接下来分析另一种情况,使用mOutput->write。

总结下:这里我以mNormalSink == mOutputSink为例,理一下流程

  1. openOutputStream中创建并初始化了outputStream (注意这里初始化了mNormalSink->write)
  2. 创建MixerThread,这里进行了情况判断,具体mNormalSink是用哪一个变量mPipeSink还是mOutputSink
  3. MixerThread的播放线程环内打开流,使用到了mNormalSink。

至此使用NBAIO的情况就结束了,接下来介绍下另一种方式,直接运用HAL或者AudioStreamOut进行写操作

2.2 mOutput->write

2.2.1 mOutput定义

首先查看下moutput参数的定义

//threads.cpp
class PlaybackThread : public ThreadBase, public StreamOutHalInterfaceCallback,
    public VolumeInterface {
		AudioStreamOut	*mOutput;
}

mOutput在playbackthread类中定义,并且类型是AudioStreamOut。

2.2.2 mOutput创建

2.2.2.1 mOutput来源

接下来看下它的初始化

mOutput是playbackthread的变量,查看playbackthread的构造函数

//threads.cpp
AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
                                             AudioStreamOut* output,
                                             audio_io_handle_t id,
                                             audio_devices_t device,
                                             type_t type,
                                             bool systemReady)
	mOutput(output),
{
}

PlaybackThread的入参output赋值给PlaybackThread->mOutput变量。
看下PlaybackThread是哪里创建的,一般PlaybackThread是由播放线程实例(如mixerthread)的构造函数中继承过来,查看下mixerthread的构造函数。

//threads.cpp
AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
        audio_io_handle_t id, audio_devices_t device, bool systemReady, type_t type)
    :   PlaybackThread(audioFlinger, output, id, device, type, systemReady),
        // mAudioMixer below
        // mFastMixer below
        mFastMixerFutex(0),
        mMasterMono(false)
        // mOutputSink below
        // mPipeSink below
        // mNormalSink below
{
}

看到了,mixerthread的构造函数中先执行PlaybackThread构造函数,同时把output传入,那查看下mixerthread的入参是从哪里来的

//AudioStreamOut.h
class AudioStreamOut {
    sp<StreamOutHalInterface> stream;
}

//AudioFlinger.cpp
sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
                                                            audio_io_handle_t *output,
                                                            audio_config_t *config,
                                                            audio_devices_t devices,
                                                            const String8& address,
                                                            audio_output_flags_t flags)
{
	//这里outputStream的初始化
    AudioStreamOut *outputStream = NULL;
    status_t status = outHwDev->openOutputStream(
            &outputStream,
            *output,
            devices,
            flags,
            config,
            address.string());

	//创建MixerThread线程
	thread = new MixerThread(this, outputStream, *output, devices, mSystemReady);	
}

MixerThread的构造函数的第二个入参outputStream就是我们要的mOutput变量。

outputStream变量的初始化在openoutput()中实现,具体调用内容参考这篇文章

```cpp
//@AudioHwDevice.cpp
//打开输出流
status_t AudioHwDevice::openOutputStream(
        AudioStreamOut **ppStreamOut,
        audio_io_handle_t handle,
        audio_devices_t devices,
        audio_output_flags_t flags,
        struct audio_config *config,
        const char *address)
{
	//创建AudioStreamOut音频输出流
    AudioStreamOut *outputStream = new AudioStreamOut(this, flags);

	//创建成功后就打开这个输出流,这里是是outputStream的操作初始化
    status_t status = outputStream->open(handle, devices, config, address);
    
	//将这个指针赋值给传入的参数,实现参数的传出
    *ppStreamOut = outputStream;
    return status;
}

这里创建了AudioStreamOut对象,并传出,作为mixerthread的第二个入参。

对比一下mNormalSink,这两种情况都是传入outputStream,同一个参数
区别:mNormalSink情况下,在mixerthread的构造函数中利用outputStream创建了AudioStreamOutSink,之后就是针对这个类的对象进行操作
mOutput情况下,直接利用传入的outputStream参数(AudioStreamOut 类型)进行处理。

待整理
moutput是在PlaybackThread的构造函数中赋初值的,所以要看下PlaybackThread的初始化传入参数哪来的。查看下前文openoutput中创建的线程。需要注意的是PlaybackThread构造函数的第二个参数才是我们需要的,看下new mixerhthread中的第二个参数outputStream。
注意:传入函数的时候使用的参数名可能更改了,要注意区别,可能会和之后的参数同名(比如outputStream和output)

好的,至此我们知道了mOutput->write的初始化是在openoutput()函数中调用了openOutputStream创建的。具体看下openOutputStream函数

2.2.2.1 mOutput的ops

write操作定义

//AudioHwDevice.cpp
status_t AudioHwDevice::openOutputStream(
        AudioStreamOut **ppStreamOut,
        audio_io_handle_t handle,
        audio_devices_t devices,
        audio_output_flags_t flags,
        struct audio_config *config,
        const char *address)
{
	//创建一个AudioStreamOut对象,并给到AudioStreamOut指针
    AudioStreamOut *outputStream = new AudioStreamOut(this, flags);

	//创建成功后就打开这个输出流,这里是是outputStream的操作初始化
    status_t status = outputStream->open(handle, devices, config, address);
    
	//将这个指针赋值给传入的参数,实现参数的传出
    *ppStreamOut = outputStream;
    return status;
}


//AudioStreamOut.cpp
status_t AudioStreamOut::open(
        audio_io_handle_t handle,
        audio_devices_t devices,
        struct audio_config *config,
        const char *address)
{
    sp<StreamOutHalInterface> outStream;

    int status = hwDev()->openOutputStream(
            handle,
            devices,
            customFlags,
            config,
            address,
            &outStream);

    return status;
}


//中间还有调用,具体细节查看openoutput文章


//@audio_hw.c
//初始化输出流的操作
static int adev_open_output_stream(struct audio_hw_device *dev,
                                   audio_io_handle_t handle,
                                   audio_devices_t devices,
                                   audio_output_flags_t flags,
                                   struct audio_config *config,
                                   struct audio_stream_out **stream_out,
                                   const char *address __unused)
{
    out->stream.write = out_write;
}

openOutputStream()函数中会对stream进行初始化,moutput->write执行的函数就是这里定义的,该write操作就是执行的out_write()函数。之后就和第一种情况一样。

待处理
总结:这种直接调用方法和上一种的区别在于,上一种中间创建了audiostreamsink类,重新封装了write函数,但是最终都调用到audiohw.cpp中的操作。

3. out_write

这里介绍下上面都调到的部分,out_write()函数,这里开始两种方式执行的都一样。

//@audio_hw.c
static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
                         size_t bytes)
{
    struct stream_out *out = (struct stream_out *)stream;

	ret = start_output_stream(out);
}


int start_output_stream(struct stream_out *out)
{
	out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
						flags, &out->config);
}

//\external\tinyalsa\pcm.c
struct pcm *pcm_open(unsigned int card, unsigned int device,
                     unsigned int flags, struct pcm_config *config)
{
    char fn[256];

	//初始化fn,打开设备路径
    snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device,
             flags & PCM_IN ? 'c' : 'p');

    pcm->flags = flags;
    pcm->fd = open(fn, O_RDWR|O_NONBLOCK);

}

注意:这里就是打开内核中文件系统的pcm设备,open(),打开设备会执行设备定义的操作,来看下pcm字符设备定义的操作。
到这里就有点进行不下去了,因为这要具体的pcm字符设备号。
查看sound.c文件,可以发现打开设备的函数

static int snd_open(struct inode *inode, struct file *file)
{
	unsigned int minor = iminor(inode);
	struct snd_minor *mptr = NULL;
	const struct file_operations *new_fops;
	int err = 0;

	if (minor >= ARRAY_SIZE(snd_minors))
		return -ENODEV;
	mutex_lock(&sound_mutex);
	mptr = snd_minors[minor];
	if (mptr == NULL) {
		mptr = autoload_device(minor);
		if (!mptr) {
			mutex_unlock(&sound_mutex);
			return -ENODEV;
		}
	}

	//获取文件的操作函数,具体要看这个pcm设备的声卡号等
	new_fops = fops_get(mptr->f_ops);
	mutex_unlock(&sound_mutex);
	if (!new_fops)
		return -ENODEV;
	replace_fops(file, new_fops);

	//这里执行pcmC0D00的具体操作
	if (file->f_op->open)
		err = file->f_op->open(inode, file);
	return err;
}

这里的open函数执行到我的Xmind文件alsa创建流程中的pcm使用部分,具体的调用之后再写。只要知道这句open语句执行之后,就进入到了pcm设备的打开,可以先参考这篇文章,很详细地讲解了pcm的创建和使用,可以直接看使用部分,图4.3.2.1中的file system就是open这个环节。

至此,就成功地从native到了kernel的driver中。超nice
结合之前看到ALSA,可以看到之后的调用。
从应用层到内核驱动的线路就此打通了一条小路,还有很多其他知识点需要再梳理。先这样吧,哈哈哈哈。

以下仅作参考

这里是我往下挖的变量类型定义,而上面是从调用的角度找函数的初始化,上面那个效率更高

这里有两个文件,一个是hidl下的,一个是local下的,具体调用到哪一个还不确定。这两个类都是由StreamOutHalInterface继承而来

//StreamHalHidl.h
class StreamOutHalHidl : public StreamOutHalInterface, public StreamHalHidl {
    virtual status_t write(const void *buffer, size_t bytes, size_t *written);
}

//StreamOutHalLocal.h
class StreamOutHalLocal : public StreamOutHalInterface, public StreamHalLocal {
    virtual status_t write(const void *buffer, size_t bytes, size_t *written);
}
//------------------------local---------------------------------
//StreamOutHalLocal.cpp
status_t StreamOutHalLocal::write(const void *buffer, size_t bytes, size_t *written) {
    ssize_t writeResult = mStream->write(mStream, buffer, bytes);
    if (writeResult > 0) {
        *written = writeResult;
        mStreamPowerLog.log(buffer, *written);
        return OK;
    } else {
        *written = 0;
        return writeResult;
    }
}


//------------------------hidl---------------------------------
status_t StreamOutHalHidl::write(const void *buffer, size_t bytes, size_t *written) {
    if (mStream == 0) return NO_INIT;
    *written = 0;

    if (bytes == 0 && !mDataMQ) {
        // Can't determine the size for the MQ buffer. Wait for a non-empty write request.
        ALOGW_IF(mCallback.unsafe_get(), "First call to async write with 0 bytes");
        return OK;
    }

    status_t status;
    if (!mDataMQ) {
        // In case if playback starts close to the end of a compressed track, the bytes
        // that need to be written is less than the actual buffer size. Need to use
        // full buffer size for the MQ since otherwise after seeking back to the middle
        // data will be truncated.
        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;
                // Diagnostics of the cause of b/35813113.
                ALOGE_IF(*written > bytes,
                        "hal reports more bytes written than asked for: %lld > %lld",
                        (long long)*written, (long long)bytes);
            });
    mStreamPowerLog.log(buffer, *written);
    return status;

hidl中创建线程,具体调用看参考的文档

local中的

//StreamOutHalLocal.h
class StreamOutHalLocal : public StreamOutHalInterface, public StreamHalLocal {
    audio_stream_out_t *mStream;
}

//audio.h
typedef struct audio_stream_out audio_stream_out_t;

struct audio_stream_out {
    ssize_t (*write)(struct audio_stream_out *stream, const void* buffer,
                     size_t bytes);
}

local代码中最终调用到audio_stream_out结构体中的write函数。

mOutput->write

NBAIO_Sink的class中查看到了write(),这是一个纯虚函数,所以看其实现在哪里。

AudioStreamOutSink类继承自NBAIO_Sink类,所以NBAIO_Sink的write函数的具体实现是在AudioStreamOutSink::write()中。

上面代码可以看到

//-----------------------------mOutput-------------------------
//Threads.h
AudioStreamOut	*mOutput;





//@AudioStreamOutSink.h
class AudioStreamOutSink : public NBAIO_Sink {
    virtual ssize_t write(const void *buffer, size_t count);
}


AudioStreamOutSink::AudioStreamOutSink(sp<StreamOutHalInterface> stream) :
        NBAIO_Sink(),
        mStream(stream),
        mStreamBufferSizeBytes(0)
{
    ALOG_ASSERT(stream != 0);
}
//Threads.h
AudioStreamOut	*mOutput;
sp<NBAIO_Sink>          mNormalSink;

//Threads.cpp
ssize_t AudioFlinger::PlaybackThread::threadLoop_write()
{
    if (mNormalSink != 0) {
        ssize_t framesWritten = mNormalSink->write((char *)mSinkBuffer + offset, count);
    } else {
        bytesWritten = mOutput->write((char *)mSinkBuffer + offset, mBytesRemaining);
    }
}

先看下AudioStreamOutSink::write

//@AudioStreamOutSink.h
class AudioStreamOutSink : public NBAIO_Sink {
	sp<StreamOutHalInterface> mStream;
}

//StreamHalInterface.h
class StreamHalInterface : public virtual RefBase



//AudioStreamOutSink.cpp
ssize_t AudioStreamOutSink::write(const void *buffer, size_t count)
{
    status_t ret = mStream->write(buffer, count * mFrameSize, &written);
}

这里执行到流输出槽接口类StreamHalInterface ,看了下文件,推测是在StreamOutHalLocal.cpp中实现的具体函数。

找到了mStream的类型是audio_stream_out,现在要找它在哪里进行初始化。

static int adev_open_output_stream(struct audio_hw_device *dev,
                                   audio_io_handle_t handle,
                                   audio_devices_t devices,
                                   audio_output_flags_t flags,
                                   struct audio_config *config,
                                   struct audio_stream_out **stream_out,
                                   const char *address __unused)
{
    out->stream.write = out_write;
}

目前就先查到这,具体是否在这里初始化等明天看

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!