blob: dd5e3c095bab0fc65d55c04a60c10372b9dd79a1 [file] [log] [blame]
Phil Burke4d7bb42017-03-28 11:32:39 -07001/*
2 * Copyright 2017 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 "AudioStreamLegacy"
18//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20
21#include <stdint.h>
22#include <utils/String16.h>
23#include <media/AudioTrack.h>
24#include <aaudio/AAudio.h>
25
26#include "core/AudioStream.h"
27#include "legacy/AudioStreamLegacy.h"
28
29using namespace android;
30using namespace aaudio;
31
32AudioStreamLegacy::AudioStreamLegacy()
Eric Laurentfb00fc72017-05-25 18:17:12 -070033 : AudioStream(), mDeviceCallback(new StreamDeviceCallback(this)) {
Phil Burke4d7bb42017-03-28 11:32:39 -070034}
35
36AudioStreamLegacy::~AudioStreamLegacy() {
37}
38
39// Called from AudioTrack.cpp or AudioRecord.cpp
40static void AudioStreamLegacy_callback(int event, void* userData, void *info) {
41 AudioStreamLegacy *streamLegacy = (AudioStreamLegacy *) userData;
42 streamLegacy->processCallback(event, info);
43}
44
45aaudio_legacy_callback_t AudioStreamLegacy::getLegacyCallback() {
46 return AudioStreamLegacy_callback;
47}
48
49// Implement FixedBlockProcessor
50int32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) {
51 int32_t frameCount = numBytes / getBytesPerFrame();
52 // Call using the AAudio callback interface.
53 AAudioStream_dataCallback appCallback = getDataCallbackProc();
54 return (*appCallback)(
55 (AAudioStream *) this,
56 getDataCallbackUserData(),
57 buffer,
58 frameCount);
59}
60
61void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode, void *info) {
62 aaudio_data_callback_result_t callbackResult;
Eric Laurentfb00fc72017-05-25 18:17:12 -070063
64 if (!mCallbackEnabled.load()) {
65 return;
66 }
67
Phil Burke4d7bb42017-03-28 11:32:39 -070068 switch (opcode) {
69 case AAUDIO_CALLBACK_OPERATION_PROCESS_DATA: {
Eric Laurentfb00fc72017-05-25 18:17:12 -070070 if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
71 // Note that this code assumes an AudioTrack::Buffer is the same as
72 // AudioRecord::Buffer
73 // TODO define our own AudioBuffer and pass it from the subclasses.
74 AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
75 if (audioBuffer->frameCount == 0) return;
Phil Burke4d7bb42017-03-28 11:32:39 -070076
Eric Laurentfb00fc72017-05-25 18:17:12 -070077 // If the caller specified an exact size then use a block size adapter.
78 if (mBlockAdapter != nullptr) {
79 int32_t byteCount = audioBuffer->frameCount * getBytesPerFrame();
80 callbackResult = mBlockAdapter->processVariableBlock(
81 (uint8_t *) audioBuffer->raw, byteCount);
82 } else {
83 // Call using the AAudio callback interface.
84 callbackResult = (*getDataCallbackProc())(
85 (AAudioStream *) this,
86 getDataCallbackUserData(),
87 audioBuffer->raw,
88 audioBuffer->frameCount
89 );
90 }
91 if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
92 audioBuffer->size = audioBuffer->frameCount * getBytesPerFrame();
93 incrementClientFrameCounter(audioBuffer->frameCount);
94 } else {
95 audioBuffer->size = 0;
96 }
97 break;
Phil Burke4d7bb42017-03-28 11:32:39 -070098 }
99 }
Eric Laurentfb00fc72017-05-25 18:17:12 -0700100 /// FALL THROUGH
Phil Burke4d7bb42017-03-28 11:32:39 -0700101
102 // Stream got rerouted so we disconnect.
103 case AAUDIO_CALLBACK_OPERATION_DISCONNECTED: {
Eric Laurentfb00fc72017-05-25 18:17:12 -0700104 setState(AAUDIO_STREAM_STATE_DISCONNECTED);
105 ALOGD("processCallbackCommon() stream disconnected");
Phil Burke4d7bb42017-03-28 11:32:39 -0700106 if (getErrorCallbackProc() != nullptr) {
107 (*getErrorCallbackProc())(
108 (AAudioStream *) this,
109 getErrorCallbackUserData(),
Eric Laurentfb00fc72017-05-25 18:17:12 -0700110 AAUDIO_ERROR_DISCONNECTED
Phil Burke4d7bb42017-03-28 11:32:39 -0700111 );
112 }
113 mCallbackEnabled.store(false);
114 }
115 break;
116
117 default:
118 break;
119 }
120}
Phil Burk5204d312017-05-04 17:16:13 -0700121
122aaudio_result_t AudioStreamLegacy::getBestTimestamp(clockid_t clockId,
123 int64_t *framePosition,
124 int64_t *timeNanoseconds,
125 ExtendedTimestamp *extendedTimestamp) {
126 int timebase;
127 switch (clockId) {
128 case CLOCK_BOOTTIME:
129 timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME;
130 break;
131 case CLOCK_MONOTONIC:
132 timebase = ExtendedTimestamp::TIMEBASE_MONOTONIC;
133 break;
134 default:
135 ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId);
Phil Burk17fff382017-05-16 14:06:45 -0700136 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
Phil Burk5204d312017-05-04 17:16:13 -0700137 break;
138 }
139 status_t status = extendedTimestamp->getBestTimestamp(framePosition, timeNanoseconds, timebase);
140 return AAudioConvert_androidToAAudioResult(status);
141}
Eric Laurentfb00fc72017-05-25 18:17:12 -0700142
143void AudioStreamLegacy::onAudioDeviceUpdate(audio_port_handle_t deviceId)
144{
145 ALOGD("onAudioDeviceUpdate() deviceId %d", (int)deviceId);
146 if (getDeviceId() != AAUDIO_UNSPECIFIED && getDeviceId() != deviceId &&
147 getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
148 setState(AAUDIO_STREAM_STATE_DISCONNECTED);
149 // if we have a data callback and the stream is active, send the error callback from
150 // data callback thread when it sees the DISCONNECTED state
151 if (!isDataCallbackActive() && getErrorCallbackProc() != nullptr) {
152 (*getErrorCallbackProc())(
153 (AAudioStream *) this,
154 getErrorCallbackUserData(),
155 AAUDIO_ERROR_DISCONNECTED
156 );
157 }
158 }
159 setDeviceId(deviceId);
160}