[audio] AudioTrack (六) 共享内存使用分析

环形缓冲区,[ audio_track_cblk_t ] [ FIFO ] 如何读取和写入

环形缓冲区:初始 R = 0,W = 0,buf 长度为 LEN

写入一个数据:w = W % LEN;buf[w] = data;W++;等价于 w = W & (LEN -1)

读取一个数据:r = R % LEN;buf[r] = data;R++;等价于 r = R & (LEN -1)

判断 满:W - R == LEN

判断 空:W == R


接上文

https://blog.csdn.net/we1less/article/details/156458655?spm=1001.2014.3001.5502

av/media/libaudioclient/AudioTrack.cpp createTrack_l

**STATIC:**StaticAudioTrackClientProxy

**STREAM:**AudioTrackClientProxy

cblk, buffers, mFrameCount, mFrameSize

cpp 复制代码
status_t AudioTrack::createTrack_l()
{
    status_t status;
 
    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
    
    // 使用返回的 response 解析出 Cblk
    status = audioFlinger->createTrack(aidlInput.value(), response);
    
    output.audioTrack->getCblk(&sfr);
 
    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
    
    mCblk = cblk;
 
    void* buffers;
    if (mSharedBuffer == 0) {
        
        // STREAM 模式下音频数据 buffers 就是 + 1
        buffers = cblk + 1;
    } else {
        // STATIC 模式下音频数据 buffers 就是传进来的 buffer
        buffers = mSharedBuffer->unsecurePointer();
 
        }
    }

    if (mSharedBuffer == 0) {
        mStaticProxy.clear();
        
        //stream
        mProxy = new AudioTrackClientProxy(cblk, buffers, mFrameCount, mFrameSize);
    } else {

        //static
        mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, mFrameCount, mFrameSize);
        mProxy = mStaticProxy;
    }
    
 
    return logIfErrorAndReturnStatus(status, "");
}

app 调用 streamTrack.write(buffer, 0, len)

base/media/java/android/media/AudioTrack.java

native_write_byte

java 复制代码
public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
        @WriteMode int writeMode) {


    final int ret = native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat,
            writeMode == WRITE_BLOCKING);


    return ret;
}

base/core/jni/android_media_AudioTrack.cpp android_media_AudioTrack_writeArray

STATIC 模式下直接使用的memcpy

cpp 复制代码
template <typename T>
static jint android_media_AudioTrack_writeArray(JNIEnv *env, jobject thiz,
                                                T javaAudioData,
                                                jint offsetInSamples, jint sizeInSamples,
                                                jint javaAudioFormat,
                                                jboolean isWriteBlocking) {
    //ALOGV("android_media_AudioTrack_writeArray(offset=%d, sizeInSamples=%d) called",
    //        offsetInSamples, sizeInSamples);
    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);


    jint samplesWritten = writeToTrack(lpTrack, javaAudioFormat, cAudioData,
            offsetInSamples, sizeInSamples, isWriteBlocking == JNI_TRUE /* blocking */);

    return samplesWritten;
}


template <typename T>
static jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const T *data,
                         jint offsetInSamples, jint sizeInSamples, bool blocking) {

    ssize_t written = 0;

    size_t sizeInBytes = sizeInSamples * sizeof(T);
    if (track->sharedBuffer() == 0) {

        written = track->write(data + offsetInSamples, sizeInBytes, blocking);

        if (written == (ssize_t) WOULD_BLOCK) {
            written = 0;
        }
    } else {
        
        // STATIC 模式下直接使用的memcpy

        if ((size_t)sizeInBytes > track->sharedBuffer()->size()) {
            sizeInBytes = track->sharedBuffer()->size();
        }

        memcpy(track->sharedBuffer()->unsecurePointer(), data + offsetInSamples, sizeInBytes);

        written = sizeInBytes;
    }

    if (written >= 0) {
        return written / sizeof(T);
    }

    return interpretWriteSizeError(written);
}

audioflinger

av/services/audioflinger/Threads.cpp createTrack_l

相关推荐
533_21 小时前
[vxe-table] 表头:点击出现输入框
android·java·javascript
天若有情67321 小时前
颠覆C++传统玩法!Property属性与伪类,开辟静态语言新维度
java·c++·servlet
写不来代码的草莓熊21 小时前
el-date-picker ,自定义输入数字自动转换显示yyyy-mm-dd HH:mm:ss格式 【仅双日历 datetimerange专用】
开发语言·前端·javascript
硅基导游21 小时前
linux系统与进程内存使用情况探测
java·linux·运维
I疯子21 小时前
2026-04-13 打卡第 6 天
开发语言·python
LucaJu21 小时前
Java + EasyExcel 实现单个接口导出多个Excel
java·excel
断眉的派大星21 小时前
值传递和引用传递
开发语言
大邳草民21 小时前
Python 对象模型与属性访问机制
开发语言·笔记·python
xyq202421 小时前
Swift 下标脚本
开发语言
橘子编程21 小时前
密码学完全指南:从基础到实战
java·python·密码学