Android/Android Audio

Android Audio System - MixerThread, TrackThread 구조 분석

임베디드 친구 2025. 6. 15. 16:04
728x90
반응형

Android Audio System - MixerThread, TrackThread 구조 분석

Android의 오디오 시스템은 복잡한 구조로 이루어져 있으며, AudioFlinger는 그 중심에서 오디오 데이터를 관리하고 믹싱하는 중요한 역할을 담당합니다. 특히 AudioFlinger 내부의 MixerThreadTrackThread는 오디오 데이터의 흐름을 제어하는 핵심 컴포넌트로, 각각의 역할과 동작 방식에 대해 깊이 있는 분석이 필요합니다. 이번 글에서는 MixerThreadTrackThread의 구조를 살펴보고, 이들이 어떻게 Android 오디오 시스템에서 동작하는지 설명하겠습니다.

1. AudioFlinger 개요

AudioFlinger는 Android의 오디오 프레임워크에서 중요한 역할을 하는 컴포넌트로, 클라이언트(Application)와 하드웨어(오디오 HAL) 사이에서 오디오 데이터를 관리하고 믹싱하는 역할을 합니다. AudioFlinger 내부에는 여러 개의 오디오 처리 스레드(Audio Processing Thread)가 존재하며, 이 중에서도 MixerThreadTrackThread는 핵심적인 역할을 합니다.

오디오 데이터는 클라이언트 애플리케이션에서 AudioTrack을 통해 AudioFlinger에 전달되며, AudioFlinger는 이를 적절한 오디오 스레드에서 처리한 후 오디오 하드웨어로 전송합니다. 이 과정에서 MixerThreadTrackThread는 각각 다음과 같은 역할을 수행합니다.

  • MixerThread: 여러 개의 Track에서 입력된 오디오 데이터를 하나의 출력 스트림으로 믹싱하는 역할을 수행합니다.
  • TrackThread: 특정 클라이언트의 오디오 데이터를 직접 처리하고, 별도의 믹싱 없이 오디오 하드웨어로 전달하는 역할을 합니다.

2. MixerThread 분석

2.1 MixerThread의 역할

MixerThread는 다수의 오디오 스트림을 하나로 합쳐야 할 때 사용됩니다. 예를 들어, 음악 플레이어 앱과 알람 앱이 동시에 소리를 출력해야 하는 경우, 두 개의 오디오 스트림을 믹싱하여 단일 오디오 스트림으로 변환하는 작업을 수행합니다.

MixerThreadThreadBase 클래스를 상속하여 동작하며, 주기적으로 오디오 데이터를 가져와 믹싱하고 이를 HAL로 전달하는 역할을 합니다. MixerThread의 핵심 동작 방식은 다음과 같습니다.

  1. Track 리스트에서 활성화된 트랙을 확인합니다.
  2. 각 트랙에서 오디오 데이터를 가져옵니다.
  3. 가져온 데이터를 소프트웨어 믹서를 이용하여 하나의 오디오 스트림으로 병합합니다.
  4. 믹싱된 오디오 데이터를 오디오 하드웨어로 전송합니다.

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가 사용됩니다. TrackThreadDirectOutputThread라는 이름으로 구현되어 있으며, MixerThread와 유사한 구조를 가지지만 믹싱 과정이 없습니다.

3.2 TrackThread의 주요 함수 분석

3.2.1 threadLoop()

MixerThread와 유사하게, TrackThreadthreadLoop() 함수를 통해 동작합니다.

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 오디오 시스템에서 MixerThreadTrackThread는 오디오 데이터를 처리하는 핵심적인 역할을 담당합니다. MixerThread는 여러 개의 오디오 트랙을 하나의 스트림으로 믹싱하는 역할을 수행하며, TrackThread는 특정한 오디오 스트림을 별도의 믹싱 없이 직접 출력하는 역할을 합니다. 이러한 구조를 이해하면 Android의 오디오 시스템을 보다 효과적으로 활용하고, 최적화된 오디오 애플리케이션을 개발하는 데 도움이 될 것입니다.

728x90
반응형