content/media/omx/AudioOutput.cpp

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
     3 /*
     4  * Copyright (c) 2014 The Linux Foundation. All rights reserved.
     5  * Copyright (C) 2008 The Android Open Source Project
     6  *
     7  * Licensed under the Apache License, Version 2.0 (the "License");
     8  * you may not use this file except in compliance with the License.
     9  * You may obtain a copy of the License at
    10  *
    11  *      http://www.apache.org/licenses/LICENSE-2.0
    12  *
    13  * Unless required by applicable law or agreed to in writing, software
    14  * distributed under the License is distributed on an "AS IS" BASIS,
    15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  * See the License for the specific language governing permissions and
    17  * limitations under the License.
    18  */
    20 #include <stagefright/foundation/ADebug.h>
    21 #include "AudioOutput.h"
    23 namespace mozilla {
    25 #ifdef PR_LOGGING
    26 extern PRLogModuleInfo* gAudioOffloadPlayerLog;
    27 #define AUDIO_OFFLOAD_LOG(type, msg) \
    28   PR_LOG(gAudioOffloadPlayerLog, type, msg)
    29 #else
    30 #define AUDIO_OFFLOAD_LOG(type, msg)
    31 #endif
    33 using namespace android;
    35 AudioOutput::AudioOutput(int aSessionId, int aUid) :
    36   mCallback(nullptr),
    37   mCallbackCookie(nullptr),
    38   mCallbackData(nullptr),
    39   mSessionId(aSessionId),
    40   mUid(aUid)
    41 {
    42 #ifdef PR_LOGGING
    43   if (!gAudioOffloadPlayerLog) {
    44     gAudioOffloadPlayerLog = PR_NewLogModule("AudioOffloadPlayer");
    45   }
    46 #endif
    47 }
    49 AudioOutput::~AudioOutput()
    50 {
    51   Close();
    52 }
    54 ssize_t AudioOutput::FrameSize() const
    55 {
    56   if (!mTrack.get()) {
    57     return NO_INIT;
    58   }
    59   return mTrack->frameSize();
    60 }
    62 status_t AudioOutput::GetPosition(uint32_t *aPosition) const
    63 {
    64   if (!mTrack.get()) {
    65     return NO_INIT;
    66   }
    67   return mTrack->getPosition(aPosition);
    68 }
    70 status_t AudioOutput::SetVolume(float aVolume) const
    71 {
    72   if (!mTrack.get()) {
    73     return NO_INIT;
    74   }
    75   return mTrack->setVolume(aVolume);
    76 }
    78 status_t AudioOutput::SetParameters(const String8& aKeyValuePairs)
    79 {
    80   if (!mTrack.get()) {
    81     return NO_INIT;
    82   }
    83   return mTrack->setParameters(aKeyValuePairs);
    84 }
    86 status_t AudioOutput::Open(uint32_t aSampleRate,
    87                            int aChannelCount,
    88                            audio_channel_mask_t aChannelMask,
    89                            audio_format_t aFormat,
    90                            AudioCallback aCb,
    91                            void* aCookie,
    92                            audio_output_flags_t aFlags,
    93                            const audio_offload_info_t *aOffloadInfo)
    94 {
    95   mCallback = aCb;
    96   mCallbackCookie = aCookie;
    98   if (((aFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) || !aCb ||
    99       !aOffloadInfo) {
   100     return BAD_VALUE;
   101   }
   103   AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("open(%u, %d, 0x%x, 0x%x, %d 0x%x)",
   104       aSampleRate, aChannelCount, aChannelMask, aFormat, mSessionId, aFlags));
   106   if (aChannelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
   107     aChannelMask = audio_channel_out_mask_from_count(aChannelCount);
   108     if (0 == aChannelMask) {
   109       AUDIO_OFFLOAD_LOG(PR_LOG_ERROR, ("open() error, can\'t derive mask for"
   110           " %d audio channels", aChannelCount));
   111       return NO_INIT;
   112     }
   113   }
   115   sp<AudioTrack> t;
   116   CallbackData* newcbd = new CallbackData(this);
   118   t = new AudioTrack(
   119       AUDIO_STREAM_MUSIC,
   120       aSampleRate,
   121       aFormat,
   122       aChannelMask,
   123       0,  // Offloaded tracks will get frame count from AudioFlinger
   124       aFlags,
   125       CallbackWrapper,
   126       newcbd,
   127       0,  // notification frames
   128       mSessionId,
   129       AudioTrack::TRANSFER_CALLBACK,
   130       aOffloadInfo,
   131       mUid);
   133   if ((!t.get()) || (t->initCheck() != NO_ERROR)) {
   134     AUDIO_OFFLOAD_LOG(PR_LOG_ERROR, ("Unable to create audio track"));
   135     delete newcbd;
   136     return NO_INIT;
   137   }
   139   mCallbackData = newcbd;
   140   t->setVolume(1.0);
   142   mTrack = t;
   143   return NO_ERROR;
   144 }
   146 status_t AudioOutput::Start()
   147 {
   148   AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("%s", __PRETTY_FUNCTION__));
   149   if (!mTrack.get()) {
   150     return NO_INIT;
   151   }
   152   mTrack->setVolume(1.0);
   153   return mTrack->start();
   154 }
   156 void AudioOutput::Stop()
   157 {
   158   AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("%s", __PRETTY_FUNCTION__));
   159   if (mTrack.get()) {
   160     mTrack->stop();
   161   }
   162 }
   164 void AudioOutput::Flush()
   165 {
   166   if (mTrack.get()) {
   167     mTrack->flush();
   168   }
   169 }
   171 void AudioOutput::Pause()
   172 {
   173   if (mTrack.get()) {
   174     mTrack->pause();
   175   }
   176 }
   178 void AudioOutput::Close()
   179 {
   180   AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("%s", __PRETTY_FUNCTION__));
   181   mTrack.clear();
   183   delete mCallbackData;
   184   mCallbackData = nullptr;
   185 }
   187 // static
   188 void AudioOutput::CallbackWrapper(int aEvent, void* aCookie, void* aInfo)
   189 {
   190   CallbackData* data = (CallbackData*) aCookie;
   191   data->Lock();
   192   AudioOutput* me = data->GetOutput();
   193   AudioTrack::Buffer* buffer = (AudioTrack::Buffer*) aInfo;
   194   if (!me) {
   195     // no output set, likely because the track was scheduled to be reused
   196     // by another player, but the format turned out to be incompatible.
   197     data->Unlock();
   198     if (buffer) {
   199       buffer->size = 0;
   200     }
   201     return;
   202   }
   204   switch(aEvent) {
   206     case AudioTrack::EVENT_MORE_DATA: {
   208       size_t actualSize = (*me->mCallback)(me, buffer->raw, buffer->size,
   209           me->mCallbackCookie, CB_EVENT_FILL_BUFFER);
   211       if (actualSize == 0 && buffer->size > 0) {
   212         // We've reached EOS but the audio track is not stopped yet,
   213         // keep playing silence.
   214         memset(buffer->raw, 0, buffer->size);
   215         actualSize = buffer->size;
   216       }
   218       buffer->size = actualSize;
   219     } break;
   221     case AudioTrack::EVENT_STREAM_END:
   222       AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Callback wrapper: EVENT_STREAM_END"));
   223       (*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
   224           me->mCallbackCookie, CB_EVENT_STREAM_END);
   225       break;
   227     case AudioTrack::EVENT_NEW_IAUDIOTRACK :
   228       AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Callback wrapper: EVENT_TEAR_DOWN"));
   229       (*me->mCallback)(me,  nullptr /* buffer */, 0 /* size */,
   230           me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
   231       break;
   233     default:
   234       AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("received unknown event type: %d in"
   235           " Callback wrapper!", aEvent));
   236       break;
   237   }
   239   data->Unlock();
   240 }
   242 } // namespace mozilla

mercurial