AudioStreamRecord.cpp revision e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3
1/* 2 * Copyright 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "AudioStreamRecord" 18//#define LOG_NDEBUG 0 19#include <utils/Log.h> 20 21#include <stdint.h> 22#include <utils/String16.h> 23#include <media/AudioRecord.h> 24#include <aaudio/AAudio.h> 25 26#include "AudioClock.h" 27#include "legacy/AudioStreamLegacy.h" 28#include "legacy/AudioStreamRecord.h" 29#include "utility/FixedBlockWriter.h" 30 31using namespace android; 32using namespace aaudio; 33 34AudioStreamRecord::AudioStreamRecord() 35 : AudioStreamLegacy() 36 , mFixedBlockWriter(*this) 37{ 38} 39 40AudioStreamRecord::~AudioStreamRecord() 41{ 42 const aaudio_stream_state_t state = getState(); 43 bool bad = !(state == AAUDIO_STREAM_STATE_UNINITIALIZED || state == AAUDIO_STREAM_STATE_CLOSED); 44 ALOGE_IF(bad, "stream not closed, in state %d", state); 45} 46 47aaudio_result_t AudioStreamRecord::open(const AudioStreamBuilder& builder) 48{ 49 aaudio_result_t result = AAUDIO_OK; 50 51 result = AudioStream::open(builder); 52 if (result != AAUDIO_OK) { 53 return result; 54 } 55 56 // Try to create an AudioRecord 57 58 // TODO Support UNSPECIFIED in AudioTrack. For now, use stereo if unspecified. 59 int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED) 60 ? 2 : getSamplesPerFrame(); 61 audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(samplesPerFrame); 62 63 audio_input_flags_t flags = (audio_input_flags_t) AUDIO_INPUT_FLAG_NONE; 64 65 size_t frameCount = (builder.getBufferCapacity() == AAUDIO_UNSPECIFIED) ? 0 66 : builder.getBufferCapacity(); 67 // TODO implement an unspecified Android format then use that. 68 audio_format_t format = (getFormat() == AAUDIO_UNSPECIFIED) 69 ? AUDIO_FORMAT_PCM_FLOAT 70 : AAudioConvert_aaudioToAndroidDataFormat(getFormat()); 71 72 // Setup the callback if there is one. 73 AudioRecord::callback_t callback = nullptr; 74 void *callbackData = nullptr; 75 AudioRecord::transfer_type streamTransferType = AudioRecord::transfer_type::TRANSFER_SYNC; 76 if (builder.getDataCallbackProc() != nullptr) { 77 streamTransferType = AudioRecord::transfer_type::TRANSFER_CALLBACK; 78 callback = getLegacyCallback(); 79 callbackData = this; 80 } 81 mCallbackBufferSize = builder.getFramesPerDataCallback(); 82 83 mAudioRecord = new AudioRecord( 84 AUDIO_SOURCE_DEFAULT, 85 getSampleRate(), 86 format, 87 channelMask, 88 mOpPackageName, // const String16& opPackageName TODO does not compile 89 frameCount, 90 callback, 91 callbackData, 92 0, // uint32_t notificationFrames = 0, 93 AUDIO_SESSION_ALLOCATE, 94 streamTransferType, 95 flags 96 // int uid = -1, 97 // pid_t pid = -1, 98 // const audio_attributes_t* pAttributes = nullptr 99 ); 100 101 // Did we get a valid track? 102 status_t status = mAudioRecord->initCheck(); 103 if (status != OK) { 104 close(); 105 ALOGE("AudioStreamRecord::open(), initCheck() returned %d", status); 106 return AAudioConvert_androidToAAudioResult(status); 107 } 108 109 // Get the actual rate. 110 setSampleRate(mAudioRecord->getSampleRate()); 111 setSamplesPerFrame(mAudioRecord->channelCount()); 112 setFormat(AAudioConvert_androidToAAudioDataFormat(mAudioRecord->format())); 113 114 // We may need to pass the data through a block size adapter to guarantee constant size. 115 if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) { 116 int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize; 117 mFixedBlockWriter.open(callbackSizeBytes); 118 mBlockAdapter = &mFixedBlockWriter; 119 } else { 120 mBlockAdapter = nullptr; 121 } 122 123 setState(AAUDIO_STREAM_STATE_OPEN); 124 125 return AAUDIO_OK; 126} 127 128aaudio_result_t AudioStreamRecord::close() 129{ 130 // TODO add close() or release() to AudioRecord API then call it from here 131 if (getState() != AAUDIO_STREAM_STATE_CLOSED) { 132 mAudioRecord.clear(); 133 setState(AAUDIO_STREAM_STATE_CLOSED); 134 } 135 mFixedBlockWriter.close(); 136 return AAUDIO_OK; 137} 138 139void AudioStreamRecord::processCallback(int event, void *info) { 140 141 ALOGD("AudioStreamRecord::processCallback(), event %d", event); 142 switch (event) { 143 case AudioRecord::EVENT_MORE_DATA: 144 processCallbackCommon(AAUDIO_CALLBACK_OPERATION_PROCESS_DATA, info); 145 break; 146 147 // Stream got rerouted so we disconnect. 148 case AudioRecord::EVENT_NEW_IAUDIORECORD: 149 processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info); 150 break; 151 152 default: 153 break; 154 } 155 return; 156} 157 158aaudio_result_t AudioStreamRecord::requestStart() 159{ 160 if (mAudioRecord.get() == nullptr) { 161 return AAUDIO_ERROR_INVALID_STATE; 162 } 163 // Get current position so we can detect when the track is playing. 164 status_t err = mAudioRecord->getPosition(&mPositionWhenStarting); 165 if (err != OK) { 166 return AAudioConvert_androidToAAudioResult(err); 167 } 168 169 err = mAudioRecord->start(); 170 if (err != OK) { 171 return AAudioConvert_androidToAAudioResult(err); 172 } else { 173 setState(AAUDIO_STREAM_STATE_STARTING); 174 } 175 return AAUDIO_OK; 176} 177 178aaudio_result_t AudioStreamRecord::requestPause() 179{ 180 return AAUDIO_ERROR_UNIMPLEMENTED; 181} 182 183aaudio_result_t AudioStreamRecord::requestFlush() { 184 return AAUDIO_ERROR_UNIMPLEMENTED; 185} 186 187aaudio_result_t AudioStreamRecord::requestStop() { 188 if (mAudioRecord.get() == nullptr) { 189 return AAUDIO_ERROR_INVALID_STATE; 190 } 191 setState(AAUDIO_STREAM_STATE_STOPPING); 192 mAudioRecord->stop(); 193 return AAUDIO_OK; 194} 195 196aaudio_result_t AudioStreamRecord::updateStateWhileWaiting() 197{ 198 aaudio_result_t result = AAUDIO_OK; 199 aaudio_wrapping_frames_t position; 200 status_t err; 201 switch (getState()) { 202 // TODO add better state visibility to AudioRecord 203 case AAUDIO_STREAM_STATE_STARTING: 204 err = mAudioRecord->getPosition(&position); 205 if (err != OK) { 206 result = AAudioConvert_androidToAAudioResult(err); 207 } else if (position != mPositionWhenStarting) { 208 setState(AAUDIO_STREAM_STATE_STARTED); 209 } 210 break; 211 case AAUDIO_STREAM_STATE_STOPPING: 212 if (mAudioRecord->stopped()) { 213 setState(AAUDIO_STREAM_STATE_STOPPED); 214 } 215 break; 216 default: 217 break; 218 } 219 return result; 220} 221 222aaudio_result_t AudioStreamRecord::read(void *buffer, 223 int32_t numFrames, 224 int64_t timeoutNanoseconds) 225{ 226 int32_t bytesPerFrame = getBytesPerFrame(); 227 int32_t numBytes; 228 aaudio_result_t result = AAudioConvert_framesToBytes(numFrames, bytesPerFrame, &numBytes); 229 if (result != AAUDIO_OK) { 230 return result; 231 } 232 233 // TODO add timeout to AudioRecord 234 bool blocking = (timeoutNanoseconds > 0); 235 ssize_t bytesRead = mAudioRecord->read(buffer, numBytes, blocking); 236 if (bytesRead == WOULD_BLOCK) { 237 return 0; 238 } else if (bytesRead < 0) { 239 return AAudioConvert_androidToAAudioResult(bytesRead); 240 } 241 int32_t framesRead = (int32_t)(bytesRead / bytesPerFrame); 242 return (aaudio_result_t) framesRead; 243} 244 245aaudio_result_t AudioStreamRecord::setBufferSize(int32_t requestedFrames) 246{ 247 return getBufferSize(); 248} 249 250int32_t AudioStreamRecord::getBufferSize() const 251{ 252 return getBufferCapacity(); // TODO implement in AudioRecord? 253} 254 255int32_t AudioStreamRecord::getBufferCapacity() const 256{ 257 return static_cast<int32_t>(mAudioRecord->frameCount()); 258} 259 260int32_t AudioStreamRecord::getXRunCount() const 261{ 262 return AAUDIO_ERROR_UNIMPLEMENTED; // TODO implement when AudioRecord supports it 263} 264 265int32_t AudioStreamRecord::getFramesPerBurst() const 266{ 267 return 192; // TODO add query to AudioRecord.cpp 268} 269 270aaudio_result_t AudioStreamRecord::getTimestamp(clockid_t clockId, 271 int64_t *framePosition, 272 int64_t *timeNanoseconds) { 273 ExtendedTimestamp extendedTimestamp; 274 status_t status = mAudioRecord->getTimestamp(&extendedTimestamp); 275 if (status != NO_ERROR) { 276 return AAudioConvert_androidToAAudioResult(status); 277 } 278 // TODO Merge common code into AudioStreamLegacy after rebasing. 279 int timebase; 280 switch(clockId) { 281 case CLOCK_BOOTTIME: 282 timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME; 283 break; 284 case CLOCK_MONOTONIC: 285 timebase = ExtendedTimestamp::TIMEBASE_MONOTONIC; 286 break; 287 default: 288 ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId); 289 return AAUDIO_ERROR_UNEXPECTED_VALUE; 290 break; 291 } 292 status = extendedTimestamp.getBestTimestamp(framePosition, timeNanoseconds, timebase); 293 return AAudioConvert_androidToAAudioResult(status); 294} 295