Android Audio System - MixerThread, TrackThread 구조 분석
Android의 오디오 시스템은 복잡한 구조로 이루어져 있으며, AudioFlinger는 그 중심에서 오디오 데이터를 관리하고 믹싱하는 중요한 역할을 담당합니다. 특히 AudioFlinger 내부의 MixerThread
와 TrackThread
는 오디오 데이터의 흐름을 제어하는 핵심 컴포넌트로, 각각의 역할과 동작 방식에 대해 깊이 있는 분석이 필요합니다. 이번 글에서는 MixerThread
와 TrackThread
의 구조를 살펴보고, 이들이 어떻게 Android 오디오 시스템에서 동작하는지 설명하겠습니다.
1. AudioFlinger 개요
AudioFlinger
는 Android의 오디오 프레임워크에서 중요한 역할을 하는 컴포넌트로, 클라이언트(Application)와 하드웨어(오디오 HAL) 사이에서 오디오 데이터를 관리하고 믹싱하는 역할을 합니다. AudioFlinger 내부에는 여러 개의 오디오 처리 스레드(Audio Processing Thread)가 존재하며, 이 중에서도 MixerThread
와 TrackThread
는 핵심적인 역할을 합니다.
오디오 데이터는 클라이언트 애플리케이션에서 AudioTrack
을 통해 AudioFlinger에 전달되며, AudioFlinger는 이를 적절한 오디오 스레드에서 처리한 후 오디오 하드웨어로 전송합니다. 이 과정에서 MixerThread
와 TrackThread
는 각각 다음과 같은 역할을 수행합니다.
MixerThread
: 여러 개의Track
에서 입력된 오디오 데이터를 하나의 출력 스트림으로 믹싱하는 역할을 수행합니다.TrackThread
: 특정 클라이언트의 오디오 데이터를 직접 처리하고, 별도의 믹싱 없이 오디오 하드웨어로 전달하는 역할을 합니다.
2. MixerThread 분석
2.1 MixerThread의 역할
MixerThread
는 다수의 오디오 스트림을 하나로 합쳐야 할 때 사용됩니다. 예를 들어, 음악 플레이어 앱과 알람 앱이 동시에 소리를 출력해야 하는 경우, 두 개의 오디오 스트림을 믹싱하여 단일 오디오 스트림으로 변환하는 작업을 수행합니다.
MixerThread
는 ThreadBase
클래스를 상속하여 동작하며, 주기적으로 오디오 데이터를 가져와 믹싱하고 이를 HAL로 전달하는 역할을 합니다. MixerThread
의 핵심 동작 방식은 다음과 같습니다.
Track
리스트에서 활성화된 트랙을 확인합니다.- 각 트랙에서 오디오 데이터를 가져옵니다.
- 가져온 데이터를 소프트웨어 믹서를 이용하여 하나의 오디오 스트림으로 병합합니다.
- 믹싱된 오디오 데이터를 오디오 하드웨어로 전송합니다.
2.2 MixerThread의 주요 함수 분석
2.2.1 threadLoop()
threadLoop()
함수는 MixerThread
의 메인 루프 역할을 수행하며, 지속적으로 오디오 데이터를 처리하는 역할을 합니다. 주요 동작 과정은 다음과 같습니다.
bool MixerThread::threadLoop() {
while (!exitPending()) {
processConfigEvents();
readTracks();
mixTracks();
writeOutput();
}
return false;
}
processConfigEvents()
: 설정 변경 이벤트를 처리합니다.readTracks()
: 활성화된Track
의 오디오 데이터를 읽어옵니다.mixTracks()
: 가져온 데이터를 하나의 오디오 스트림으로 믹싱합니다.writeOutput()
: 믹싱된 오디오 데이터를 오디오 HAL로 전달합니다.
2.2.2 mixTracks()
이 함수는 여러 개의 트랙에서 오디오 데이터를 가져와 믹싱하는 역할을 합니다.
void MixerThread::mixTracks() {
for (size_t i = 0; i < mTracks.size(); ++i) {
Track* track = mTracks[i];
track->getNextBuffer();
mixBuffer(track);
}
}
이 함수는 활성화된 Track
을 순회하면서 각 Track
에서 오디오 버퍼를 가져와 믹싱하는 방식으로 동작합니다.
3. TrackThread 분석
3.1 TrackThread의 역할
TrackThread
는 단일 클라이언트의 오디오 데이터를 별도의 믹싱 과정 없이 오디오 하드웨어로 직접 전달하는 역할을 수행합니다. 주로 Direct Output Stream
과 같은 특정 오디오 스트림을 처리하는 데 사용됩니다.
예를 들어, VoIP 애플리케이션에서 통화 중 발생하는 오디오 데이터를 믹싱하지 않고 바로 출력해야 할 때 TrackThread
가 사용됩니다. TrackThread
는 DirectOutputThread
라는 이름으로 구현되어 있으며, MixerThread
와 유사한 구조를 가지지만 믹싱 과정이 없습니다.
3.2 TrackThread의 주요 함수 분석
3.2.1 threadLoop()
MixerThread
와 유사하게, TrackThread
도 threadLoop()
함수를 통해 동작합니다.
bool TrackThread::threadLoop() {
while (!exitPending()) {
processConfigEvents();
readTrack();
writeOutput();
}
return false;
}
processConfigEvents()
: 설정 변경 이벤트를 처리합니다.readTrack()
: 단일Track
의 오디오 데이터를 읽어옵니다.writeOutput()
: 오디오 데이터를 오디오 HAL로 직접 전달합니다.
3.2.2 readTrack()
이 함수는 현재 활성화된 트랙의 오디오 데이터를 읽어오는 역할을 합니다.
void TrackThread::readTrack() {
Track* track = getActiveTrack();
if (track) {
track->getNextBuffer();
}
}
4. MixerThread와 TrackThread의 차이점
항목 | MixerThread | TrackThread |
---|---|---|
역할 | 여러 트랙을 믹싱하여 하나의 오디오 스트림 생성 | 단일 클라이언트의 오디오 데이터를 직접 전송 |
믹싱 과정 | 있음 | 없음 |
주요 사용 사례 | 음악 앱, 멀티미디어 재생 | VoIP, 알람, 특수 오디오 출력 |
클래스 이름 | MixerThread | DirectOutputThread |
5. 결론
Android 오디오 시스템에서 MixerThread
와 TrackThread
는 오디오 데이터를 처리하는 핵심적인 역할을 담당합니다. MixerThread
는 여러 개의 오디오 트랙을 하나의 스트림으로 믹싱하는 역할을 수행하며, TrackThread
는 특정한 오디오 스트림을 별도의 믹싱 없이 직접 출력하는 역할을 합니다. 이러한 구조를 이해하면 Android의 오디오 시스템을 보다 효과적으로 활용하고, 최적화된 오디오 애플리케이션을 개발하는 데 도움이 될 것입니다.
'Android > Android Audio' 카테고리의 다른 글
Android Audio Service 개요 (0) | 2025.06.17 |
---|---|
Android AudioFlinger: 오디오 리샘플링 및 효과 적용 (0) | 2025.06.16 |
Android Audio System: AudioTrack, AudioRecord의 내부 동작 원리 (0) | 2025.06.14 |
AudioFlinger 개요 및 주요 역할 (0) | 2025.06.13 |
Android Audio System: Audio HAL과 Audio Flinger의 관계 (0) | 2025.06.12 |