content/media/omx/AudioOutput.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial