• Stagefright AudioPlayer 流程


    Stagefright中关于audio的部分由AudioPlayer处理,输出使用AudioSink 或AudioTrack。

    AwesomePlayer在initAudioDecoder方法中建立audio decoder

    status_t AwesomePlayer::initAudioDecoder() {
        ...
        if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
            mAudioSource = mAudioTrack;
        } else {
            mAudioSource = OMXCodec::Create(
                    mClient.interface(), mAudioTrack->getFormat(),
                    false, // createEncoder
                    mAudioTrack);
        }    
        ...
    }

    当调用play_l方法的时候建立AudioPlayer,并把Audio Decoder[mAudioSource]传递给它

    status_t AwesomePlayer::play_l() {
        ...
        if (mAudioSource != NULL) {
            if (mAudioPlayer == NULL) {
                if (mAudioSink != NULL) {
                    mAudioPlayer = new AudioPlayer(mAudioSink, this);
                    mAudioPlayer->setSource(mAudioSource);
            ...
        }
        ...
    }

    AudioPlayer在调用start方法的时候会开启audioSink,并传递回调函数AudioSinkCallback

    status_t AudioPlayer::start(bool sourceAlreadyStarted) {
        ...
        if (mAudioSink.get() != NULL) {
            status_t err = mAudioSink->open(
                mSampleRate, numChannels, AudioSystem::PCM_16_BIT,
                DEFAULT_AUDIOSINK_BUFFERCOUNT,
                &AudioPlayer::AudioSinkCallback, this);
        ...
        mAudioSink->start();
        ...
    }

    之后AudioSink会在需要Sample数据的时候回调AudioSinkCallback,要求将size大小Sample数据填充到buffer。这里调用fillBuffer函数从audio decoder读取解码后的Sample数据。

    size_t AudioPlayer::AudioSinkCallback(
            MediaPlayerBase::AudioSink *audioSink,
            void *buffer, size_t size, void *cookie) {
        AudioPlayer *me = (AudioPlayer *)cookie;
     
        LOGI("[%s:%d]_____ enter AudioPlayer::AudioSinkCallback size = %d", __FUNCTION__, __LINE__, size);
        
        return me->fillBuffer(buffer, size);
    }
     
    void AudioPlayer::AudioCallback(int event, void *info) {
        if (event != AudioTrack::EVENT_MORE_DATA) {
            return;
        }
     
        AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
        size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
     
        buffer->size = numBytesWritten;
    }
     
     
    size_t AudioPlayer::fillBuffer(void *data, size_t size) {
        ...
        size_t size_done = 0;
        size_t size_remaining = size;
        while (size_remaining > 0) {
            ...
            err = mSource->read(&mInputBuffer, &options);
            ...
            memcpy((char *)data + size_done,
                  (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
                  copy);
     
            mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
                                   mInputBuffer->range_length() - copy);
     
            size_done += copy;
            size_remaining -= copy;
            ...
        }
        ...
    }

    这里的mSource实际上是decoder,其read方法会调用mAudioTrack的read方法获取DataSource的未解码数据,然后解码,返回解码后的数据。

    总流程如下

    AudioSink
        |
        +- AudioPlayer#AudioSinkCallback
                            |
                            +- AudioDecoder#read
                                             |
                                             +- Extractor::MediaSource#read

    参考

  • 相关阅读:
    一、定义枚举类,并随机取值
    常用Linux日志查询命令
    一、爬虫之基础
    Jmeter接口自动化-3-生成HTML报告
    Jmeter接口自动化-2-查看结果数只能显示有限的数据,查看全部数据
    Jmeter接口自动化-1-启动报错:Could not initialize class org.apache.jmeter.gui.util.MenuFactory
    三十一、Java基础之Collection集合
    设计模式
    缓存
    Ckeditor配置
  • 原文地址:https://www.cnblogs.com/shaobin0604/p/2219929.html
Copyright © 2020-2023  润新知