AudioStreamRecord.cpp revision e1ce491a25faf06fdeab00dd938515f71f28b095
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 <oboe/OboeAudio.h> 25 26#include "AudioClock.h" 27#include "AudioStreamRecord.h" 28 29using namespace android; 30using namespace oboe; 31 32AudioStreamRecord::AudioStreamRecord() 33 : AudioStream() 34{ 35} 36 37AudioStreamRecord::~AudioStreamRecord() 38{ 39 const oboe_stream_state_t state = getState(); 40 bool bad = !(state == OBOE_STREAM_STATE_UNINITIALIZED || state == OBOE_STREAM_STATE_CLOSED); 41 ALOGE_IF(bad, "stream not closed, in state %d", state); 42} 43 44oboe_result_t AudioStreamRecord::open(const AudioStreamBuilder& builder) 45{ 46 oboe_result_t result = OBOE_OK; 47 48 result = AudioStream::open(builder); 49 if (result != OBOE_OK) { 50 return result; 51 } 52 53 // Try to create an AudioRecord 54 55 // TODO Support UNSPECIFIED in AudioTrack. For now, use stereo if unspecified. 56 int32_t samplesPerFrame = (getSamplesPerFrame() == OBOE_UNSPECIFIED) 57 ? 2 : getSamplesPerFrame(); 58 audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(samplesPerFrame); 59 60 AudioRecord::callback_t callback = NULL; 61 audio_input_flags_t flags = (audio_input_flags_t) AUDIO_INPUT_FLAG_NONE; 62 63 // TODO implement an unspecified Android format then use that. 64 audio_format_t format = (getFormat() == OBOE_UNSPECIFIED) 65 ? AUDIO_FORMAT_PCM_FLOAT 66 : OboeConvert_oboeToAndroidDataFormat(getFormat()); 67 68 mAudioRecord = new AudioRecord( 69 AUDIO_SOURCE_DEFAULT, 70 getSampleRate(), 71 format, 72 channelMask, 73 74 mOpPackageName, // const String16& opPackageName TODO does not compile 75 76 0, // size_t frameCount = 0, 77 callback, 78 NULL, // void* user = NULL, 79 0, // uint32_t notificationFrames = 0, 80 AUDIO_SESSION_ALLOCATE, 81 AudioRecord::TRANSFER_DEFAULT, 82 flags 83 // int uid = -1, 84 // pid_t pid = -1, 85 // const audio_attributes_t* pAttributes = NULL 86 ); 87 88 // Did we get a valid track? 89 status_t status = mAudioRecord->initCheck(); 90 if (status != OK) { 91 close(); 92 ALOGE("AudioStreamRecord::open(), initCheck() returned %d", status); 93 return OboeConvert_androidToOboeError(status); 94 } 95 96 // Get the actual rate. 97 setSampleRate(mAudioRecord->getSampleRate()); 98 setSamplesPerFrame(mAudioRecord->channelCount()); 99 setFormat(OboeConvert_androidToOboeDataFormat(mAudioRecord->format())); 100 101 setState(OBOE_STREAM_STATE_OPEN); 102 103 return OBOE_OK; 104} 105 106oboe_result_t AudioStreamRecord::close() 107{ 108 // TODO add close() or release() to AudioRecord API then call it from here 109 if (getState() != OBOE_STREAM_STATE_CLOSED) { 110 mAudioRecord.clear(); 111 setState(OBOE_STREAM_STATE_CLOSED); 112 } 113 return OBOE_OK; 114} 115 116oboe_result_t AudioStreamRecord::requestStart() 117{ 118 if (mAudioRecord.get() == NULL) { 119 return OBOE_ERROR_INVALID_STATE; 120 } 121 // Get current position so we can detect when the track is playing. 122 status_t err = mAudioRecord->getPosition(&mPositionWhenStarting); 123 if (err != OK) { 124 return OboeConvert_androidToOboeError(err); 125 } 126 err = mAudioRecord->start(); 127 if (err != OK) { 128 return OboeConvert_androidToOboeError(err); 129 } else { 130 setState(OBOE_STREAM_STATE_STARTING); 131 } 132 return OBOE_OK; 133} 134 135oboe_result_t AudioStreamRecord::requestPause() 136{ 137 return OBOE_ERROR_UNIMPLEMENTED; 138} 139 140oboe_result_t AudioStreamRecord::requestFlush() { 141 return OBOE_ERROR_UNIMPLEMENTED; 142} 143 144oboe_result_t AudioStreamRecord::requestStop() { 145 if (mAudioRecord.get() == NULL) { 146 return OBOE_ERROR_INVALID_STATE; 147 } 148 setState(OBOE_STREAM_STATE_STOPPING); 149 mAudioRecord->stop(); 150 return OBOE_OK; 151} 152 153oboe_result_t AudioStreamRecord::updateState() 154{ 155 oboe_result_t result = OBOE_OK; 156 oboe_wrapping_frames_t position; 157 status_t err; 158 switch (getState()) { 159 // TODO add better state visibility to AudioRecord 160 case OBOE_STREAM_STATE_STARTING: 161 err = mAudioRecord->getPosition(&position); 162 if (err != OK) { 163 result = OboeConvert_androidToOboeError(err); 164 } else if (position != mPositionWhenStarting) { 165 setState(OBOE_STREAM_STATE_STARTED); 166 } 167 break; 168 case OBOE_STREAM_STATE_STOPPING: 169 if (mAudioRecord->stopped()) { 170 setState(OBOE_STREAM_STATE_STOPPED); 171 } 172 break; 173 default: 174 break; 175 } 176 return result; 177} 178 179oboe_result_t AudioStreamRecord::read(void *buffer, 180 oboe_size_frames_t numFrames, 181 oboe_nanoseconds_t timeoutNanoseconds) 182{ 183 oboe_size_frames_t bytesPerFrame = getBytesPerFrame(); 184 oboe_size_bytes_t numBytes; 185 oboe_result_t result = OboeConvert_framesToBytes(numFrames, bytesPerFrame, &numBytes); 186 if (result != OBOE_OK) { 187 return result; 188 } 189 190 // TODO add timeout to AudioRecord 191 bool blocking = (timeoutNanoseconds > 0); 192 ssize_t bytesRead = mAudioRecord->read(buffer, numBytes, blocking); 193 if (bytesRead == WOULD_BLOCK) { 194 return 0; 195 } else if (bytesRead < 0) { 196 return OboeConvert_androidToOboeError(bytesRead); 197 } 198 oboe_size_frames_t framesRead = (oboe_size_frames_t)(bytesRead / bytesPerFrame); 199 return (oboe_result_t) framesRead; 200} 201 202oboe_result_t AudioStreamRecord::setBufferSize(oboe_size_frames_t requestedFrames, 203 oboe_size_frames_t *actualFrames) 204{ 205 *actualFrames = getBufferCapacity(); 206 return OBOE_OK; 207} 208 209oboe_size_frames_t AudioStreamRecord::getBufferSize() const 210{ 211 return getBufferCapacity(); // TODO implement in AudioRecord? 212} 213 214oboe_size_frames_t AudioStreamRecord::getBufferCapacity() const 215{ 216 return static_cast<oboe_size_frames_t>(mAudioRecord->frameCount()); 217} 218 219int32_t AudioStreamRecord::getXRunCount() const 220{ 221 return OBOE_ERROR_UNIMPLEMENTED; // TODO implement when AudioRecord supports it 222} 223 224oboe_size_frames_t AudioStreamRecord::getFramesPerBurst() const 225{ 226 return 192; // TODO add query to AudioRecord.cpp 227} 228 229// TODO implement getTimestamp 230 231