SlideShare ist ein Scribd-Unternehmen logo
1 von 15
안드로이드 아나토미 정리




 Android Audio System
(오디오 출력-트랙생성)




                             박철희

                        1
1.오디오 출력                                                            안드로이드 아나토미 정리


오디오 출력은 크게 3단계로 구성됨.
1)Track생성
2)Track 활성화단계
3)PCM 데이터 출력 요청 단계

Ex)Mediaplayerservice에서의 오디오 출력 예
1)선행단계 -> audiooutput class를 audiosink 함수로 설정 함.
  Audioplayer의 audiosink가 불리면 mediaplayerservice의
   audiooutput class가 호출 됨.
                            MediaplayerBase

                                AudioSink




   Mediaplayer            MediaplayerService
   Interface
                              AudioOutput       setAudioSink(AudioOutput)



   stagefrightPlayer
                                Awesomeplayer
                                                                        AudioPlayer



                                                                            2
1.오디오 출력                                                                                     안드로이드 아나토미 정리

                                                           AudioPlayer.cpp
 2)Track생성 및 활성화                                           status_t AudioPlayer::start(bool sourceAlreadyStarted) {

                                                           mAudioSink->open(
  Mediaplayerservice.cpp
                                                                   mSampleRate, numChannels,
  status_t MediaPlayerService::Client::start()
                                                                       AudioSystem::PCM_16_BIT,
  {
                                                                   DEFAULT_AUDIOSINK_BUFFERCOUNT,
     LOGV("[%d] start", mConnId);
                                                                   &AudioPlayer::AudioSinkCallback, this);
     sp<MediaPlayerBase> p = getPlayer();
     if (p == 0) return UNKNOWN_ERROR;
                                                           mAudioSink->start();
     p->setLooping(mLoop);
     return p->start();
                                                           }
  }

 Stagefrightplayer.cpp                                 status_t MediaPlayerService::AudioOutput::open(){
 status_t StagefrightPlayer::start() {
    LOGV("start");                                             t = new AudioTrack(…);   Track생성

     return mPlayer->play();                           }
 }
                                                       void MediaPlayerService::AudioOutput::start()
 status_t AwesomePlayer::play() {                      {
    return play_l();                                      if (mTrack) {
 }                                                                      mTrack->start(); Track활성화
                                                          }
                                                       }
 status_t AwesomePlayer::play_l() {                     ssize_t MediaPlayerService::AudioOutput::write
   mAudioPlayer = new AudioPlayer(mAudioSink, this);    {
   mAudioPlayer->start();                                  if (mTrack) {
                                                               ssize_t ret = mTrack->write(buffer, size); PCM데이터
 }
                                                               return ret;                                출력
                                                           }
2.트랙 생성 단계                           안드로이드 아나토미 정리




  AudioTrack.java



  Android_media_
  AudiioTrack.cpp


  Audiotrack.cpp




                    서비스 클라이언트   서비스 서버
2.트랙 생성 단계(서비스 클라이언트)                                                                           안드로이드 아나토미 정리


  Audiotrack.java
  public AudioTrack(…){
    int initResult = native_setup(new WeakReference<AudioTrack>(this),
              mStreamType, mSampleRate, mChannels, mAudioFormat,
              mNativeBufferSizeInBytes, mDataLoadMode, session);
  }


  Android_media_audiotrack.cpp
  android_media_AudioTrack_native_setup{
    lpTrack->set(
          atStreamType,// stream type
          sampleRateInHertz,
          format,// word length, PCM
          channels,
          frameCount,
          0,// flags
          audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
          0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
          0,// shared mem
          true,// thread can call Java
          sessionId);// audio session ID
  }


  AudioTrack.cpp
  status_t AudioTrack::set(…){
   1)출력 스트림 핸들 획득
   audio_io_handle_t output = AudioSystem::getOutput((AudioSystem::stream_type)streamType,
         sampleRate, format, channels, (AudioSystem::output_flags)flags);
2.트랙 생성 단계(서비스 클라이언트)                                                                               안드로이드 아나토미 정리


 2)트랙 생성 요청
status_t status = createTrack(streamType, sampleRate, format, channelCount,frameCount, flags, sharedBuffer, output, true);


 status_t AudioTrack::createTrack(){
  sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
                                   streamType,
                                   sampleRate,
                                   format,
                                   channelCount,
                                   frameCount,
                                   ((uint16_t)flags) << 16,
                                   sharedBuffer,
                                   output,
                                   &mSessionId,
                                   &status);
 }

 3)트랙 핸들 서비스 프록시 획득
 mAudioTrack = track;
  mAudioTrack 은 trackhandle 서비스의 proxy를 가리킨다.
   즉,이 mAudioTrack 변수를 통해서 trackhandle 서비스로 접근해서 생성된 track을 control한다.

 4)오디오 트랙 쓰레드 생성
 if (cbf != 0) {
       mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
 }
2.트랙 생성 단계(서비스 클라이언트)                                                                             안드로이드 아나토미 정리

 AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver, bool bCanCallJava)
   : Thread(bCanCallJava), mReceiver(receiver)
 {
 }

 bool AudioTrack::AudioTrackThread::threadLoop()
 {
   return mReceiver.processAudioBuffer(this);
 }

 status_t AudioTrack::AudioTrackThread::readyToRun()
 {
    return NO_ERROR;
 }

 void AudioTrack::AudioTrackThread::onFirstRef()
 {
 }
 onFirstRef 에 아무 code 도 없기 때문에 readyToRun, threadLoop 이 불리지 않는다.
  AudioTrack::start() 에서 t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT); 이 불리면
  readyToRun-> threadLoop이 호출 된다.
  threadLoop 에서는 AudioTrack::processAudioBuffer를 반복 호출 한다.
                                                           tonegenerator        AudioPlayer        Android_media_audiotrack

                                                            Audiocallback()     Audiocallback()        Audiocallback()

         AudioTrackThread

                                                                                                   EVENT_MORE_DAT
                                                                                                   A
                                                                                      event        EVENT_UNDERRU
                                                                                                   N
        processAudioBuffer
                                                                                                   EVENT_NEW_POS
2.트랙 생성 단계(서비스 클라이언트)                                                         안드로이드 아나토미 정리


 Ex) EVENT_MORE_DATA 생성 및 처리

 1) processAudioBuffer 에서 EVENT_MORE_DATA 생성
 -EVENT_MORE_DATA:오디오 버퍼에 PCM 데이터를 쓰도록 요청
 status_t err = obtainBuffer(&audioBuffer, 1);
 오디오 버퍼를 확보.
 mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
 확보된 오디오 버퍼를 인자로 EVENT_MORE_DATA event 전달

                             Audioplayer.cpp에 AudioCallback이 등록된 경우

 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;
 }
                                       오디오 버퍼에 전달된 data를 copy한다.



  size_t AudioPlayer::fillBuffer(void *data, size_t size) {

  memcpy((char *)data + size_done,
         (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
         copy);
  }
2.트랙 생성 단계(서비스 서버)                                                                     안드로이드 아나토미 정리


 서비스 클라이언트로 부터 요청 받은 track 생성 요구를 서비스 서버에서 처리하는 과정이다.


 sp<IAudioTrack> AudioFlinger::createTrack(…,output..){

 PlaybackThread *thread = checkPlaybackThread_l(output);  1)playbackthread 획득

 client = new Client(this, pid);  2) 트랙 공유 메모리 생성

 track = thread->createTrack_l(client, streamType, sampleRate, format,
            channelCount, frameCount, sharedBuffer, lSessionId, &lStatus);
             3) 트랙 생성

 trackHandle = new TrackHandle(track);  4) 트랙 핸들 리모트 서비스 생성 후 반환
 return trackHandle;


 1)playbackthread 획득
   인자로 들어온 출력스트림(output)을 이용하여 playbackthread를 획득한다.

 AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
 {
   PlaybackThread *thread = NULL;
   if (mPlaybackThreads.indexOfKey(output) >= 0) {
       thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
   }
   return thread;
 }
2.트랙 생성 단계(서비스 서버)                                                                                    안드로이드 아나토미 정리


 2) 트랙 공유 메모리 생성
   서비스 클라이언트와 서비스 서버간의 PCM 데이터를 공유하기 위한 공유 메모리 생성
   Client 객체가 생성될 때 공유 메모리 생성 됨.

 sp<IAudioTrack> AudioFlinger::createTrack{                   AudioFlinger::Client::Client()
                                                                   : mMemoryDealer(
 wclient = mClients.valueFor(pid);                                         new MemoryDealer(1024*1024, "AudioFlinger::Client")
                                                              Client 생성자는 MemoryDealer를
      if (wclient != NULL) {                                    통해 1Mbytes의 공유 메모리확보
          client = wclient.promote();
      } else {
          client = new Client(this, pid);
          mClients.add(pid, client);
      }
 }
 Singletone pattern으로 하나의 process당 하나의 Client만 존재하게 된다.
   (즉, application은 audioflinger에 있는 createtrack()함수를 여러 번 호출 할 수 있지만, 하나의 Client만 생성하게 된다.)

       AudioTrack++                            Audioflinger




                             write          read                       write              android
                                                                                          kernel
                Track[3        32kbyte
                1]
    AudioFlinger::Client
                                               1M                                     Audio
    (shared memory)
                                                                                      Driver
                  Track[0]                                                            buffer
2.트랙 생성 단계(서비스 서버)                                                                                 안드로이드 아나토미 정리


 3) 트랙 생성
 sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
 track = new Track(this, client, streamType, sampleRate, format,
           channelCount, frameCount, sharedBuffer, sessionId);



  AudioFlinger::PlaybackThread::Track::Track()
    : TrackBase(thread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer, sessionId),
  {
       …
  }
             Trackbase의 생성자가 먼저 호출됨.(오디오 트랙 컨트롤 블록 생성)


 AudioFlinger::ThreadBase::TrackBase::TrackBase(){
  size_t size = sizeof(audio_track_cblk_t);
  size_t bufferSize = 0;
  if ( (format == AudioSystem::PCM_16_BIT) ||
       (format == AudioSystem::PCM_8_BIT))
  {
      bufferSize = frameCount*channelCount*sizeof(int16_t);
  }
   size += bufferSize;
   mCblkMemory = client->heap()->allocate(size);  1)size 만큼 메모리 할당
    mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
    new(mCblk) audio_track_cblk_t();  2)할당 된 메모리에 64kbyte의 audio_track_cblk_t 구조체 생성
    mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); 3)pcm 데이터 공유 버퍼 설정
    memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
    mBufferEnd = (uint8_t *)mBuffer + bufferSize;
2.트랙 생성 단계(서비스 서버)                                                               안드로이드 아나토미 정리




                                                                               Track

frameCount*ch                             PCM 데이터                            mBufferEnd
annelCount*                               공유 버퍼
sizeof(int16_t);                                                              mBuffer

                                                                              mCblk


        64kbytes                    오디오 컨트롤 블록



                                                         user
                                                                        출력 대기중인
    struct audio_track_cblk_t                                           PCM 데이터
    {                                                                                        server
                                                               User
                                                               offset
        volatile     uint32_t user;                                                       Server
        volatile     uint32_t server;                                                     offset
                   uint32_t userBase;
                   uint32_t serverBase;
                   void*    buffers;                userBase                                 serverBase
                   uint32_t frameCount;
                   …
    }                                                                   오디오 컨트롤 블록
2.트랙 생성 단계(서비스 서버)                                            안드로이드 아나토미 정리



  Useroffset 계산 과정(user-userbase)




     -512 프레임씩 write한다고 가정.
     -pcm 데이터 공유 버퍼 framecount 3,072
     -pcm 데이터 공유 버퍼가 full 인 상태(user가 3,072)에서 write할려고 할 경우
      buffer overflow 발생
      userbase를 0에서 framecount 인 3,072로 변경
      유저오프셋=user(3,072)-userbase(3,072)=0
        즉,buffer의 제일 처음 부터 다시 write함.
2.트랙 생성 단계(서비스 서버)                                                                               안드로이드 아나토미 정리



 -Track class 생성자 실행
 AudioFlinger::PlaybackThread::Track::Track()
 {
     mName = playbackThread->getTrackName_l();트랙 이름(0x1000)부터 시작,1씩 증가함.
     mMainBuffer = playbackThread->mixBuffer(); mixerbuffer를 가리킴.
     mCblk->frameSize = AudioSystem::isLinearPCM(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
 }
                    Audioflinger

                       Track

                     mBufferEnd
                       mBuffer
                       mCblk

                       mName                             Mixer
                     mMainBuffer                         buffer


                                                                                                        android

                                                                                                         kernel
                                                                                Audio
                          PCM 데이터                                               Driver
                          공유 버퍼                                                 buffer


                     오디오 컨트롤 블록
2.트랙 생성 단계(트랙 공유 메모리 참조)-서비스 클라이언트                                                 안드로이드 아나토미 정리


 서비스 클라이언트가(audiotrack) 트랙 생성을 요청한 이후 서비스 서버측(audioflinger)에 의해
 생성된 트랙 공유 메모리를 참조하는 과정


 status_t AudioTrack::createTrack()
 {
   sp<IAudioTrack> track = audioFlinger->createTrack();

      sp<IMemory> cblk = track->getCblk(); 1)trackhandle의 getCblk() 호출 함으로써 트랙 공유 메모리의
                                        공유 메모리 서비스 프락시를 얻어온다.
       mCblkMemory = cblk;
       mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
       트랙 공유 메모리의 오디오 컨트롤 블록을 가리킨다.
       mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
       pcm 데이터 공유 버퍼를 가리킨다.
  }



                                                                                      Track
       AudioTrack                                  PCM 데이터
                                                   공유 버퍼                           mBufferEnd

         mBuffer                                                                     mBuffer

                                                                                     mCblk
         mCblk
                                                오디오 컨트롤 블록

Weitere ähnliche Inhalte

Was ist angesagt?

Android audio system(audio_hardwareinterace)
Android audio system(audio_hardwareinterace)Android audio system(audio_hardwareinterace)
Android audio system(audio_hardwareinterace)
fefe7270
 
Using and Customizing the Android Framework / part 4 of Embedded Android Work...
Using and Customizing the Android Framework / part 4 of Embedded Android Work...Using and Customizing the Android Framework / part 4 of Embedded Android Work...
Using and Customizing the Android Framework / part 4 of Embedded Android Work...
Opersys inc.
 

Was ist angesagt? (20)

Android Multimedia Framework
Android Multimedia FrameworkAndroid Multimedia Framework
Android Multimedia Framework
 
Android media framework overview
Android media framework overviewAndroid media framework overview
Android media framework overview
 
Embedded Android : System Development - Part III (Audio / Video HAL)
Embedded Android : System Development - Part III (Audio / Video HAL)Embedded Android : System Development - Part III (Audio / Video HAL)
Embedded Android : System Development - Part III (Audio / Video HAL)
 
Embedded Android : System Development - Part IV
Embedded Android : System Development - Part IVEmbedded Android : System Development - Part IV
Embedded Android : System Development - Part IV
 
Android audio system(audio_hardwareinterace)
Android audio system(audio_hardwareinterace)Android audio system(audio_hardwareinterace)
Android audio system(audio_hardwareinterace)
 
Embedded Android : System Development - Part I
Embedded Android : System Development - Part IEmbedded Android : System Development - Part I
Embedded Android : System Development - Part I
 
Embedded Android : System Development - Part II (HAL)
Embedded Android : System Development - Part II (HAL)Embedded Android : System Development - Part II (HAL)
Embedded Android : System Development - Part II (HAL)
 
Android Things : Building Embedded Devices
Android Things : Building Embedded DevicesAndroid Things : Building Embedded Devices
Android Things : Building Embedded Devices
 
Linux Audio Drivers. ALSA
Linux Audio Drivers. ALSALinux Audio Drivers. ALSA
Linux Audio Drivers. ALSA
 
Booting Android: bootloaders, fastboot and boot images
Booting Android: bootloaders, fastboot and boot imagesBooting Android: bootloaders, fastboot and boot images
Booting Android: bootloaders, fastboot and boot images
 
Android presentation
Android presentationAndroid presentation
Android presentation
 
Low Level View of Android System Architecture
Low Level View of Android System ArchitectureLow Level View of Android System Architecture
Low Level View of Android System Architecture
 
Embedded Android : System Development - Part III
Embedded Android : System Development - Part IIIEmbedded Android : System Development - Part III
Embedded Android : System Development - Part III
 
Q4.11: Porting Android to new Platforms
Q4.11: Porting Android to new PlatformsQ4.11: Porting Android to new Platforms
Q4.11: Porting Android to new Platforms
 
08 android multimedia_framework_overview
08 android multimedia_framework_overview08 android multimedia_framework_overview
08 android multimedia_framework_overview
 
Android internals By Rajesh Khetan
Android internals By Rajesh KhetanAndroid internals By Rajesh Khetan
Android internals By Rajesh Khetan
 
Using and Customizing the Android Framework / part 4 of Embedded Android Work...
Using and Customizing the Android Framework / part 4 of Embedded Android Work...Using and Customizing the Android Framework / part 4 of Embedded Android Work...
Using and Customizing the Android Framework / part 4 of Embedded Android Work...
 
MediaPlayer Playing Flow
MediaPlayer Playing FlowMediaPlayer Playing Flow
MediaPlayer Playing Flow
 
Explore Android Internals
Explore Android InternalsExplore Android Internals
Explore Android Internals
 
Android Binder: Deep Dive
Android Binder: Deep DiveAndroid Binder: Deep Dive
Android Binder: Deep Dive
 

Andere mochten auch

Surface flingerservice(서피스 출력 요청 jb)
Surface flingerservice(서피스 출력 요청 jb)Surface flingerservice(서피스 출력 요청 jb)
Surface flingerservice(서피스 출력 요청 jb)
fefe7270
 
Android audio system(오디오 출력-트랙활성화)
Android audio system(오디오 출력-트랙활성화)Android audio system(오디오 출력-트랙활성화)
Android audio system(오디오 출력-트랙활성화)
fefe7270
 
Surface flingerservice(서피스 플링거 연결 jb)
Surface flingerservice(서피스 플링거 연결 jb)Surface flingerservice(서피스 플링거 연결 jb)
Surface flingerservice(서피스 플링거 연결 jb)
fefe7270
 
Surface flingerservice(그래픽 공유 버퍼 생성 및 등록)
Surface flingerservice(그래픽 공유 버퍼 생성 및 등록)Surface flingerservice(그래픽 공유 버퍼 생성 및 등록)
Surface flingerservice(그래픽 공유 버퍼 생성 및 등록)
fefe7270
 
Surface flingerservice(서피스 상태 변경 jb)
Surface flingerservice(서피스 상태 변경 jb)Surface flingerservice(서피스 상태 변경 jb)
Surface flingerservice(서피스 상태 변경 jb)
fefe7270
 
Surface flingerservice(서피스 플링거 연결 ics)
Surface flingerservice(서피스 플링거 연결 ics)Surface flingerservice(서피스 플링거 연결 ics)
Surface flingerservice(서피스 플링거 연결 ics)
fefe7270
 
Camera camcorder framework overview(ginger bread)
Camera camcorder framework overview(ginger bread)Camera camcorder framework overview(ginger bread)
Camera camcorder framework overview(ginger bread)
fefe7270
 
Surface flingerservice(서피스 상태 변경 및 출력 요청)
Surface flingerservice(서피스 상태 변경 및 출력 요청)Surface flingerservice(서피스 상태 변경 및 출력 요청)
Surface flingerservice(서피스 상태 변경 및 출력 요청)
fefe7270
 
Surface flingerservice(서피스 플링거 연결)
Surface flingerservice(서피스 플링거 연결)Surface flingerservice(서피스 플링거 연결)
Surface flingerservice(서피스 플링거 연결)
fefe7270
 
Surface flingerservice(서피스플링거서비스초기화 ics)
Surface flingerservice(서피스플링거서비스초기화 ics)Surface flingerservice(서피스플링거서비스초기화 ics)
Surface flingerservice(서피스플링거서비스초기화 ics)
fefe7270
 
Surface flingerservice(서피스플링거서비스초기화)
Surface flingerservice(서피스플링거서비스초기화)Surface flingerservice(서피스플링거서비스초기화)
Surface flingerservice(서피스플링거서비스초기화)
fefe7270
 
Surface flingerservice(서피스플링거서비스초기화 jb)
Surface flingerservice(서피스플링거서비스초기화 jb)Surface flingerservice(서피스플링거서비스초기화 jb)
Surface flingerservice(서피스플링거서비스초기화 jb)
fefe7270
 
Android media codec 사용하기
Android media codec 사용하기Android media codec 사용하기
Android media codec 사용하기
Taehwan kwon
 

Andere mochten auch (18)

Surface flingerservice(서피스 출력 요청 jb)
Surface flingerservice(서피스 출력 요청 jb)Surface flingerservice(서피스 출력 요청 jb)
Surface flingerservice(서피스 출력 요청 jb)
 
Android audio system(오디오 출력-트랙활성화)
Android audio system(오디오 출력-트랙활성화)Android audio system(오디오 출력-트랙활성화)
Android audio system(오디오 출력-트랙활성화)
 
Surface flingerservice(서피스 플링거 연결 jb)
Surface flingerservice(서피스 플링거 연결 jb)Surface flingerservice(서피스 플링거 연결 jb)
Surface flingerservice(서피스 플링거 연결 jb)
 
Surface flingerservice(그래픽 공유 버퍼 생성 및 등록)
Surface flingerservice(그래픽 공유 버퍼 생성 및 등록)Surface flingerservice(그래픽 공유 버퍼 생성 및 등록)
Surface flingerservice(그래픽 공유 버퍼 생성 및 등록)
 
Surface flingerservice(서피스 상태 변경 jb)
Surface flingerservice(서피스 상태 변경 jb)Surface flingerservice(서피스 상태 변경 jb)
Surface flingerservice(서피스 상태 변경 jb)
 
Android Training (Media)
Android Training (Media)Android Training (Media)
Android Training (Media)
 
Surface flingerservice(서피스 플링거 연결 ics)
Surface flingerservice(서피스 플링거 연결 ics)Surface flingerservice(서피스 플링거 연결 ics)
Surface flingerservice(서피스 플링거 연결 ics)
 
Camera camcorder framework overview(ginger bread)
Camera camcorder framework overview(ginger bread)Camera camcorder framework overview(ginger bread)
Camera camcorder framework overview(ginger bread)
 
Surface flingerservice(서피스 상태 변경 및 출력 요청)
Surface flingerservice(서피스 상태 변경 및 출력 요청)Surface flingerservice(서피스 상태 변경 및 출력 요청)
Surface flingerservice(서피스 상태 변경 및 출력 요청)
 
Surface flingerservice(서피스 플링거 연결)
Surface flingerservice(서피스 플링거 연결)Surface flingerservice(서피스 플링거 연결)
Surface flingerservice(서피스 플링거 연결)
 
Surface flingerservice(서피스플링거서비스초기화 ics)
Surface flingerservice(서피스플링거서비스초기화 ics)Surface flingerservice(서피스플링거서비스초기화 ics)
Surface flingerservice(서피스플링거서비스초기화 ics)
 
Surface flingerservice(서피스플링거서비스초기화)
Surface flingerservice(서피스플링거서비스초기화)Surface flingerservice(서피스플링거서비스초기화)
Surface flingerservice(서피스플링거서비스초기화)
 
2016-08-20 01 Дмитрий Рабецкий, Сергей Сорокин. Опыт работы с Android Medi...
2016-08-20 01 Дмитрий Рабецкий, Сергей Сорокин. Опыт работы с Android Medi...2016-08-20 01 Дмитрий Рабецкий, Сергей Сорокин. Опыт работы с Android Medi...
2016-08-20 01 Дмитрий Рабецкий, Сергей Сорокин. Опыт работы с Android Medi...
 
Surface flingerservice(서피스플링거서비스초기화 jb)
Surface flingerservice(서피스플링거서비스초기화 jb)Surface flingerservice(서피스플링거서비스초기화 jb)
Surface flingerservice(서피스플링거서비스초기화 jb)
 
안드로이드 MediaPlayer & VideoView
안드로이드 MediaPlayer & VideoView안드로이드 MediaPlayer & VideoView
안드로이드 MediaPlayer & VideoView
 
Android media codec 사용하기
Android media codec 사용하기Android media codec 사용하기
Android media codec 사용하기
 
Android Audio & OpenSL
Android Audio & OpenSLAndroid Audio & OpenSL
Android Audio & OpenSL
 
안드로이드 플랫폼 설명
안드로이드 플랫폼 설명안드로이드 플랫폼 설명
안드로이드 플랫폼 설명
 

Ähnlich wie Android audio system(오디오 출력-트랙생성)

제2회 hello world 오픈세미나 Web Audio API-가능성엿보기
제2회 hello world 오픈세미나 Web Audio API-가능성엿보기제2회 hello world 오픈세미나 Web Audio API-가능성엿보기
제2회 hello world 오픈세미나 Web Audio API-가능성엿보기
NAVER D2
 
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
주영 송
 

Ähnlich wie Android audio system(오디오 출력-트랙생성) (17)

Developing game audio with the Web Audio API
Developing game audio with the Web Audio APIDeveloping game audio with the Web Audio API
Developing game audio with the Web Audio API
 
Android Screen Recorder
Android Screen RecorderAndroid Screen Recorder
Android Screen Recorder
 
제2회 hello world 오픈세미나 Web Audio API-가능성엿보기
제2회 hello world 오픈세미나 Web Audio API-가능성엿보기제2회 hello world 오픈세미나 Web Audio API-가능성엿보기
제2회 hello world 오픈세미나 Web Audio API-가능성엿보기
 
[2018] Java를 위한, Java에 의한 도구들
[2018] Java를 위한, Java에 의한 도구들[2018] Java를 위한, Java에 의한 도구들
[2018] Java를 위한, Java에 의한 도구들
 
[SWCON211] LectureCode_13_Matlab Practice.pptx
[SWCON211] LectureCode_13_Matlab Practice.pptx[SWCON211] LectureCode_13_Matlab Practice.pptx
[SWCON211] LectureCode_13_Matlab Practice.pptx
 
Windows Phone Mango 아키텍처-멀티태스킹(2)
Windows Phone Mango 아키텍처-멀티태스킹(2)Windows Phone Mango 아키텍처-멀티태스킹(2)
Windows Phone Mango 아키텍처-멀티태스킹(2)
 
사운드처리_텀과제_이정근.pptx
사운드처리_텀과제_이정근.pptx사운드처리_텀과제_이정근.pptx
사운드처리_텀과제_이정근.pptx
 
TR 069 클라이언트 검토자료 3편
TR 069 클라이언트 검토자료 3편TR 069 클라이언트 검토자료 3편
TR 069 클라이언트 검토자료 3편
 
웹 사이트 시각화 및 성능 관리
웹 사이트 시각화 및 성능 관리웹 사이트 시각화 및 성능 관리
웹 사이트 시각화 및 성능 관리
 
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
 
Clova Skill 에서 AudioPlayer 구현
Clova Skill 에서 AudioPlayer 구현Clova Skill 에서 AudioPlayer 구현
Clova Skill 에서 AudioPlayer 구현
 
Media labguide bootcamp_20180327
Media labguide bootcamp_20180327Media labguide bootcamp_20180327
Media labguide bootcamp_20180327
 
20201121 코드 삼분지계
20201121 코드 삼분지계20201121 코드 삼분지계
20201121 코드 삼분지계
 
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
 
컵드론 멀티콥터 펌웨어 분석 2015. 3.28.
컵드론 멀티콥터 펌웨어 분석 2015. 3.28.컵드론 멀티콥터 펌웨어 분석 2015. 3.28.
컵드론 멀티콥터 펌웨어 분석 2015. 3.28.
 
XNA2.0 Network Programming
XNA2.0 Network ProgrammingXNA2.0 Network Programming
XNA2.0 Network Programming
 
한컴MDS_무기체계 SW 개발을 위한 TRACE32 활용방안
한컴MDS_무기체계 SW 개발을 위한 TRACE32 활용방안한컴MDS_무기체계 SW 개발을 위한 TRACE32 활용방안
한컴MDS_무기체계 SW 개발을 위한 TRACE32 활용방안
 

Android audio system(오디오 출력-트랙생성)

  • 1. 안드로이드 아나토미 정리 Android Audio System (오디오 출력-트랙생성) 박철희 1
  • 2. 1.오디오 출력 안드로이드 아나토미 정리 오디오 출력은 크게 3단계로 구성됨. 1)Track생성 2)Track 활성화단계 3)PCM 데이터 출력 요청 단계 Ex)Mediaplayerservice에서의 오디오 출력 예 1)선행단계 -> audiooutput class를 audiosink 함수로 설정 함. Audioplayer의 audiosink가 불리면 mediaplayerservice의 audiooutput class가 호출 됨. MediaplayerBase AudioSink Mediaplayer MediaplayerService Interface AudioOutput setAudioSink(AudioOutput) stagefrightPlayer Awesomeplayer AudioPlayer 2
  • 3. 1.오디오 출력 안드로이드 아나토미 정리 AudioPlayer.cpp 2)Track생성 및 활성화 status_t AudioPlayer::start(bool sourceAlreadyStarted) { mAudioSink->open( Mediaplayerservice.cpp mSampleRate, numChannels, status_t MediaPlayerService::Client::start() AudioSystem::PCM_16_BIT, { DEFAULT_AUDIOSINK_BUFFERCOUNT, LOGV("[%d] start", mConnId); &AudioPlayer::AudioSinkCallback, this); sp<MediaPlayerBase> p = getPlayer(); if (p == 0) return UNKNOWN_ERROR; mAudioSink->start(); p->setLooping(mLoop); return p->start(); } } Stagefrightplayer.cpp status_t MediaPlayerService::AudioOutput::open(){ status_t StagefrightPlayer::start() { LOGV("start"); t = new AudioTrack(…); Track생성 return mPlayer->play(); } } void MediaPlayerService::AudioOutput::start() status_t AwesomePlayer::play() { { return play_l(); if (mTrack) { } mTrack->start(); Track활성화 } } status_t AwesomePlayer::play_l() { ssize_t MediaPlayerService::AudioOutput::write mAudioPlayer = new AudioPlayer(mAudioSink, this); { mAudioPlayer->start(); if (mTrack) { ssize_t ret = mTrack->write(buffer, size); PCM데이터 } return ret; 출력 }
  • 4. 2.트랙 생성 단계 안드로이드 아나토미 정리 AudioTrack.java Android_media_ AudiioTrack.cpp Audiotrack.cpp 서비스 클라이언트 서비스 서버
  • 5. 2.트랙 생성 단계(서비스 클라이언트) 안드로이드 아나토미 정리 Audiotrack.java public AudioTrack(…){ int initResult = native_setup(new WeakReference<AudioTrack>(this), mStreamType, mSampleRate, mChannels, mAudioFormat, mNativeBufferSizeInBytes, mDataLoadMode, session); } Android_media_audiotrack.cpp android_media_AudioTrack_native_setup{ lpTrack->set( atStreamType,// stream type sampleRateInHertz, format,// word length, PCM channels, frameCount, 0,// flags audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user) 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack 0,// shared mem true,// thread can call Java sessionId);// audio session ID } AudioTrack.cpp status_t AudioTrack::set(…){ 1)출력 스트림 핸들 획득 audio_io_handle_t output = AudioSystem::getOutput((AudioSystem::stream_type)streamType, sampleRate, format, channels, (AudioSystem::output_flags)flags);
  • 6. 2.트랙 생성 단계(서비스 클라이언트) 안드로이드 아나토미 정리 2)트랙 생성 요청 status_t status = createTrack(streamType, sampleRate, format, channelCount,frameCount, flags, sharedBuffer, output, true); status_t AudioTrack::createTrack(){ sp<IAudioTrack> track = audioFlinger->createTrack(getpid(), streamType, sampleRate, format, channelCount, frameCount, ((uint16_t)flags) << 16, sharedBuffer, output, &mSessionId, &status); } 3)트랙 핸들 서비스 프록시 획득 mAudioTrack = track;  mAudioTrack 은 trackhandle 서비스의 proxy를 가리킨다. 즉,이 mAudioTrack 변수를 통해서 trackhandle 서비스로 접근해서 생성된 track을 control한다. 4)오디오 트랙 쓰레드 생성 if (cbf != 0) { mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava); }
  • 7. 2.트랙 생성 단계(서비스 클라이언트) 안드로이드 아나토미 정리 AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver, bool bCanCallJava) : Thread(bCanCallJava), mReceiver(receiver) { } bool AudioTrack::AudioTrackThread::threadLoop() { return mReceiver.processAudioBuffer(this); } status_t AudioTrack::AudioTrackThread::readyToRun() { return NO_ERROR; } void AudioTrack::AudioTrackThread::onFirstRef() { } onFirstRef 에 아무 code 도 없기 때문에 readyToRun, threadLoop 이 불리지 않는다. AudioTrack::start() 에서 t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT); 이 불리면 readyToRun-> threadLoop이 호출 된다. threadLoop 에서는 AudioTrack::processAudioBuffer를 반복 호출 한다. tonegenerator AudioPlayer Android_media_audiotrack Audiocallback() Audiocallback() Audiocallback() AudioTrackThread EVENT_MORE_DAT A event EVENT_UNDERRU N processAudioBuffer EVENT_NEW_POS
  • 8. 2.트랙 생성 단계(서비스 클라이언트) 안드로이드 아나토미 정리 Ex) EVENT_MORE_DATA 생성 및 처리 1) processAudioBuffer 에서 EVENT_MORE_DATA 생성 -EVENT_MORE_DATA:오디오 버퍼에 PCM 데이터를 쓰도록 요청 status_t err = obtainBuffer(&audioBuffer, 1); 오디오 버퍼를 확보. mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); 확보된 오디오 버퍼를 인자로 EVENT_MORE_DATA event 전달 Audioplayer.cpp에 AudioCallback이 등록된 경우 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; } 오디오 버퍼에 전달된 data를 copy한다. size_t AudioPlayer::fillBuffer(void *data, size_t size) { memcpy((char *)data + size_done, (const char *)mInputBuffer->data() + mInputBuffer->range_offset(), copy); }
  • 9. 2.트랙 생성 단계(서비스 서버) 안드로이드 아나토미 정리 서비스 클라이언트로 부터 요청 받은 track 생성 요구를 서비스 서버에서 처리하는 과정이다. sp<IAudioTrack> AudioFlinger::createTrack(…,output..){ PlaybackThread *thread = checkPlaybackThread_l(output);  1)playbackthread 획득 client = new Client(this, pid);  2) 트랙 공유 메모리 생성 track = thread->createTrack_l(client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer, lSessionId, &lStatus);  3) 트랙 생성 trackHandle = new TrackHandle(track);  4) 트랙 핸들 리모트 서비스 생성 후 반환 return trackHandle; 1)playbackthread 획득 인자로 들어온 출력스트림(output)을 이용하여 playbackthread를 획득한다. AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const { PlaybackThread *thread = NULL; if (mPlaybackThreads.indexOfKey(output) >= 0) { thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get(); } return thread; }
  • 10. 2.트랙 생성 단계(서비스 서버) 안드로이드 아나토미 정리 2) 트랙 공유 메모리 생성 서비스 클라이언트와 서비스 서버간의 PCM 데이터를 공유하기 위한 공유 메모리 생성 Client 객체가 생성될 때 공유 메모리 생성 됨. sp<IAudioTrack> AudioFlinger::createTrack{ AudioFlinger::Client::Client() : mMemoryDealer( wclient = mClients.valueFor(pid); new MemoryDealer(1024*1024, "AudioFlinger::Client") Client 생성자는 MemoryDealer를 if (wclient != NULL) { 통해 1Mbytes의 공유 메모리확보 client = wclient.promote(); } else { client = new Client(this, pid); mClients.add(pid, client); } } Singletone pattern으로 하나의 process당 하나의 Client만 존재하게 된다. (즉, application은 audioflinger에 있는 createtrack()함수를 여러 번 호출 할 수 있지만, 하나의 Client만 생성하게 된다.) AudioTrack++ Audioflinger write read write android kernel Track[3 32kbyte 1] AudioFlinger::Client 1M Audio (shared memory) Driver Track[0] buffer
  • 11. 2.트랙 생성 단계(서비스 서버) 안드로이드 아나토미 정리 3) 트랙 생성 sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l( track = new Track(this, client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer, sessionId); AudioFlinger::PlaybackThread::Track::Track() : TrackBase(thread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer, sessionId), { … } Trackbase의 생성자가 먼저 호출됨.(오디오 트랙 컨트롤 블록 생성) AudioFlinger::ThreadBase::TrackBase::TrackBase(){ size_t size = sizeof(audio_track_cblk_t); size_t bufferSize = 0; if ( (format == AudioSystem::PCM_16_BIT) || (format == AudioSystem::PCM_8_BIT)) { bufferSize = frameCount*channelCount*sizeof(int16_t); } size += bufferSize; mCblkMemory = client->heap()->allocate(size);  1)size 만큼 메모리 할당 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer()); new(mCblk) audio_track_cblk_t();  2)할당 된 메모리에 64kbyte의 audio_track_cblk_t 구조체 생성 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); 3)pcm 데이터 공유 버퍼 설정 memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); mBufferEnd = (uint8_t *)mBuffer + bufferSize;
  • 12. 2.트랙 생성 단계(서비스 서버) 안드로이드 아나토미 정리 Track frameCount*ch PCM 데이터 mBufferEnd annelCount* 공유 버퍼 sizeof(int16_t); mBuffer mCblk 64kbytes 오디오 컨트롤 블록 user 출력 대기중인 struct audio_track_cblk_t PCM 데이터 { server User offset volatile uint32_t user; Server volatile uint32_t server; offset uint32_t userBase; uint32_t serverBase; void* buffers; userBase serverBase uint32_t frameCount; … } 오디오 컨트롤 블록
  • 13. 2.트랙 생성 단계(서비스 서버) 안드로이드 아나토미 정리 Useroffset 계산 과정(user-userbase) -512 프레임씩 write한다고 가정. -pcm 데이터 공유 버퍼 framecount 3,072 -pcm 데이터 공유 버퍼가 full 인 상태(user가 3,072)에서 write할려고 할 경우 buffer overflow 발생 userbase를 0에서 framecount 인 3,072로 변경 유저오프셋=user(3,072)-userbase(3,072)=0 즉,buffer의 제일 처음 부터 다시 write함.
  • 14. 2.트랙 생성 단계(서비스 서버) 안드로이드 아나토미 정리 -Track class 생성자 실행 AudioFlinger::PlaybackThread::Track::Track() { mName = playbackThread->getTrackName_l();트랙 이름(0x1000)부터 시작,1씩 증가함. mMainBuffer = playbackThread->mixBuffer(); mixerbuffer를 가리킴. mCblk->frameSize = AudioSystem::isLinearPCM(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t); } Audioflinger Track mBufferEnd mBuffer mCblk mName Mixer mMainBuffer buffer android kernel Audio PCM 데이터 Driver 공유 버퍼 buffer 오디오 컨트롤 블록
  • 15. 2.트랙 생성 단계(트랙 공유 메모리 참조)-서비스 클라이언트 안드로이드 아나토미 정리 서비스 클라이언트가(audiotrack) 트랙 생성을 요청한 이후 서비스 서버측(audioflinger)에 의해 생성된 트랙 공유 메모리를 참조하는 과정 status_t AudioTrack::createTrack() { sp<IAudioTrack> track = audioFlinger->createTrack(); sp<IMemory> cblk = track->getCblk(); 1)trackhandle의 getCblk() 호출 함으로써 트랙 공유 메모리의 공유 메모리 서비스 프락시를 얻어온다. mCblkMemory = cblk; mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); 트랙 공유 메모리의 오디오 컨트롤 블록을 가리킨다. mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); pcm 데이터 공유 버퍼를 가리킨다. } Track AudioTrack PCM 데이터 공유 버퍼 mBufferEnd mBuffer mBuffer mCblk mCblk 오디오 컨트롤 블록