AudioStreamRecord.cpp revision 35e80f34a9649752fceafa53e2094cd8eda50a0a
1e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk/*
2e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Copyright 2016 The Android Open Source Project
3e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *
4e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Licensed under the Apache License, Version 2.0 (the "License");
5e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * you may not use this file except in compliance with the License.
6e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * You may obtain a copy of the License at
7e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *
8e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *      http://www.apache.org/licenses/LICENSE-2.0
9e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *
10e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Unless required by applicable law or agreed to in writing, software
11e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * distributed under the License is distributed on an "AS IS" BASIS,
12e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * See the License for the specific language governing permissions and
14e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * limitations under the License.
15e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk */
16e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
17e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#define LOG_TAG "AudioStreamRecord"
18e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk//#define LOG_NDEBUG 0
19e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <utils/Log.h>
20e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
21e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <stdint.h>
22e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <utils/String16.h>
23e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <media/AudioRecord.h>
245ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include <aaudio/AAudio.h>
25e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
26e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include "AudioClock.h"
27e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include "AudioStreamRecord.h"
2835e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk#include "utility/AAudioUtilities.h"
29e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
30e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkusing namespace android;
315ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio;
32e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
33e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamRecord::AudioStreamRecord()
34e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    : AudioStream()
35e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
36e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
37e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
38e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamRecord::~AudioStreamRecord()
39e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
405ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    const aaudio_stream_state_t state = getState();
415ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    bool bad = !(state == AAUDIO_STREAM_STATE_UNINITIALIZED || state == AAUDIO_STREAM_STATE_CLOSED);
42e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    ALOGE_IF(bad, "stream not closed, in state %d", state);
43e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
44e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
455ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::open(const AudioStreamBuilder& builder)
46e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_result_t result = AAUDIO_OK;
48e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
49e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    result = AudioStream::open(builder);
505ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (result != AAUDIO_OK) {
51e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        return result;
52e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
53e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
54e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // Try to create an AudioRecord
55e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
56e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO Support UNSPECIFIED in AudioTrack. For now, use stereo if unspecified.
575ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED)
58e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk                              ? 2 : getSamplesPerFrame();
59e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(samplesPerFrame);
60e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
61d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    AudioRecord::callback_t callback = nullptr;
62e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    audio_input_flags_t flags = (audio_input_flags_t) AUDIO_INPUT_FLAG_NONE;
63e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
643df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk    size_t frameCount = (builder.getBufferCapacity() == AAUDIO_UNSPECIFIED) ? 0
653df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk                        : builder.getBufferCapacity();
66e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO implement an unspecified Android format then use that.
675ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    audio_format_t format = (getFormat() == AAUDIO_UNSPECIFIED)
68e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            ? AUDIO_FORMAT_PCM_FLOAT
695ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            : AAudioConvert_aaudioToAndroidDataFormat(getFormat());
70e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
71e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    mAudioRecord = new AudioRecord(
72e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            AUDIO_SOURCE_DEFAULT,
73e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            getSampleRate(),
74e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            format,
75e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            channelMask,
76e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            mOpPackageName, // const String16& opPackageName TODO does not compile
773df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk            frameCount,
78e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            callback,
79d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk            nullptr, //    void* user = nullptr,
80e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            0,    //    uint32_t notificationFrames = 0,
81e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            AUDIO_SESSION_ALLOCATE,
82e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            AudioRecord::TRANSFER_DEFAULT,
83e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            flags
843df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk            //   int uid = -1,
853df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk            //   pid_t pid = -1,
863df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk            //   const audio_attributes_t* pAttributes = nullptr
873df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk            );
88e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
89e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // Did we get a valid track?
90e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    status_t status = mAudioRecord->initCheck();
91e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (status != OK) {
92e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        close();
93e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        ALOGE("AudioStreamRecord::open(), initCheck() returned %d", status);
945ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(status);
95e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
96e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
97e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // Get the actual rate.
98e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    setSampleRate(mAudioRecord->getSampleRate());
99e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    setSamplesPerFrame(mAudioRecord->channelCount());
1005ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    setFormat(AAudioConvert_androidToAAudioDataFormat(mAudioRecord->format()));
101e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
1025ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    setState(AAUDIO_STREAM_STATE_OPEN);
103e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
1045ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
105e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
106e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
1075ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::close()
108e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
109e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO add close() or release() to AudioRecord API then call it from here
1105ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (getState() != AAUDIO_STREAM_STATE_CLOSED) {
111e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        mAudioRecord.clear();
1125ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        setState(AAUDIO_STREAM_STATE_CLOSED);
113e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
1145ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
115e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
116e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
1175ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestStart()
118e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
119d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    if (mAudioRecord.get() == nullptr) {
1205ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
121e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
122e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // Get current position so we can detect when the track is playing.
123e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    status_t err = mAudioRecord->getPosition(&mPositionWhenStarting);
124e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (err != OK) {
1255ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(err);
126e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
127e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    err = mAudioRecord->start();
128e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (err != OK) {
1295ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(err);
130e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    } else {
1315ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        setState(AAUDIO_STREAM_STATE_STARTING);
132e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
1335ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
134e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
135e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
1365ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestPause()
137e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
1385ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_ERROR_UNIMPLEMENTED;
139e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
140e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
1415ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestFlush() {
1425ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_ERROR_UNIMPLEMENTED;
143e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
144e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
1455ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestStop() {
146d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    if (mAudioRecord.get() == nullptr) {
1475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
148e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
1495ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    setState(AAUDIO_STREAM_STATE_STOPPING);
150e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    mAudioRecord->stop();
1515ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
152e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
153e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
1545ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::updateState()
155e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
1565ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_result_t result = AAUDIO_OK;
1575ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_wrapping_frames_t position;
158e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    status_t err;
159e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    switch (getState()) {
160e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO add better state visibility to AudioRecord
1615ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    case AAUDIO_STREAM_STATE_STARTING:
162e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        err = mAudioRecord->getPosition(&position);
163e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        if (err != OK) {
1645ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            result = AAudioConvert_androidToAAudioResult(err);
165e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        } else if (position != mPositionWhenStarting) {
1665ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            setState(AAUDIO_STREAM_STATE_STARTED);
167e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        }
168e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
1695ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    case AAUDIO_STREAM_STATE_STOPPING:
170e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        if (mAudioRecord->stopped()) {
1715ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            setState(AAUDIO_STREAM_STATE_STOPPED);
172e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        }
173e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
174e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    default:
175e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
176e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
177e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    return result;
178e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
179e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
1805ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::read(void *buffer,
1813316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk                                      int32_t numFrames,
1823316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk                                      int64_t timeoutNanoseconds)
183e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
1843316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    int32_t bytesPerFrame = getBytesPerFrame();
1853316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    int32_t numBytes;
1865ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_result_t result = AAudioConvert_framesToBytes(numFrames, bytesPerFrame, &numBytes);
1875ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (result != AAUDIO_OK) {
188e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        return result;
189e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
190e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
191e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO add timeout to AudioRecord
192e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    bool blocking = (timeoutNanoseconds > 0);
193e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    ssize_t bytesRead = mAudioRecord->read(buffer, numBytes, blocking);
194e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (bytesRead == WOULD_BLOCK) {
195e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        return 0;
196e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    } else if (bytesRead < 0) {
1975ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(bytesRead);
198e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
1993316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    int32_t framesRead = (int32_t)(bytesRead / bytesPerFrame);
2005ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return (aaudio_result_t) framesRead;
201e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
202e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
2033316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkaaudio_result_t AudioStreamRecord::setBufferSize(int32_t requestedFrames)
204e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
2053316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    return getBufferSize();
206e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
207e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
2083316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getBufferSize() const
209e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
210e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    return getBufferCapacity(); // TODO implement in AudioRecord?
211e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
212e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
2133316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getBufferCapacity() const
214e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
2153316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    return static_cast<int32_t>(mAudioRecord->frameCount());
216e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
217e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
218e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkint32_t AudioStreamRecord::getXRunCount() const
219e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
2205ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_ERROR_UNIMPLEMENTED; // TODO implement when AudioRecord supports it
221e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
222e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
2233316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getFramesPerBurst() const
224e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
225e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    return 192; // TODO add query to AudioRecord.cpp
226e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
227e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
22835e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burkaaudio_result_t AudioStreamRecord::getTimestamp(clockid_t clockId,
22935e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk                                               int64_t *framePosition,
23035e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk                                               int64_t *timeNanoseconds) {
23135e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    ExtendedTimestamp extendedTimestamp;
23235e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    status_t status = mAudioRecord->getTimestamp(&extendedTimestamp);
23335e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    if (status != NO_ERROR) {
23435e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk        return AAudioConvert_androidToAAudioResult(status);
23535e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    }
23635e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    // TODO Merge common code into AudioStreamLegacy after rebasing.
23735e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    int timebase;
23835e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    switch(clockId) {
23935e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk        case CLOCK_BOOTTIME:
24035e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk            timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME;
24135e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk            break;
24235e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk        case CLOCK_MONOTONIC:
24335e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk            timebase = ExtendedTimestamp::TIMEBASE_MONOTONIC;
24435e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk            break;
24535e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk        default:
24635e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk            ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId);
24735e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk            return AAUDIO_ERROR_UNEXPECTED_VALUE;
24835e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk            break;
24935e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    }
25035e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    status = extendedTimestamp.getBestTimestamp(framePosition, timeNanoseconds, timebase);
25135e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    return AAudioConvert_androidToAAudioResult(status);
25235e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk}
253