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 17cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk#define LOG_TAG "AAudio" 18e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk//#define LOG_NDEBUG 0 19e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <utils/Log.h> 20e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 21e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <stdint.h> 22e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <media/AudioTrack.h> 23e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 24e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include <aaudio/AAudio.h> 25c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "utility/AudioClock.h" 26e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "legacy/AudioStreamLegacy.h" 27e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "legacy/AudioStreamTrack.h" 28e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "utility/FixedBlockReader.h" 29e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 30e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkusing namespace android; 315ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio; 32e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 33e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk// Arbitrary and somewhat generous number of bursts. 34e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#define DEFAULT_BURSTS_PER_BUFFER_CAPACITY 8 35e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 36e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk/* 37e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Create a stream that uses the AudioTrack. 38e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk */ 39e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamTrack::AudioStreamTrack() 40e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk : AudioStreamLegacy() 41e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk , mFixedBlockReader(*this) 42e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 43e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 44e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 45e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamTrack::~AudioStreamTrack() 46e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const aaudio_stream_state_t state = getState(); 485ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk bool bad = !(state == AAUDIO_STREAM_STATE_UNINITIALIZED || state == AAUDIO_STREAM_STATE_CLOSED); 49e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ALOGE_IF(bad, "stream not closed, in state %d", state); 50e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 51e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 525ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamTrack::open(const AudioStreamBuilder& builder) 53e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 545ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 55e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 56e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk result = AudioStream::open(builder); 57e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (result != OK) { 58e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return result; 59e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 60e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 61e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Try to create an AudioTrack 625204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk // Use stereo if unspecified. 635ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED) 64e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ? 2 : getSamplesPerFrame(); 65e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(samplesPerFrame); 66e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 67e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE; 6830a707773a043e5eebd552d369c0882f886b67e5Phil Burk aaudio_performance_mode_t perfMode = getPerformanceMode(); 6930a707773a043e5eebd552d369c0882f886b67e5Phil Burk switch(perfMode) { 70e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY: 71e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk // Bypass the normal mixer and go straight to the FAST mixer. 72e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW); 73e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk break; 74e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk 75e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk case AAUDIO_PERFORMANCE_MODE_POWER_SAVING: 76e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk // This uses a mixer that wakes up less often than the FAST mixer. 77e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; 78e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk break; 79e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk 80e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk case AAUDIO_PERFORMANCE_MODE_NONE: 81e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk default: 82e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk // No flags. Use a normal mixer in front of the FAST mixer. 83e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk break; 84e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk } 85e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 86cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk size_t frameCount = (size_t)builder.getBufferCapacity(); 87e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 88e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk int32_t notificationFrames = 0; 89e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 90e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk audio_format_t format = (getFormat() == AAUDIO_FORMAT_UNSPECIFIED) 91e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ? AUDIO_FORMAT_PCM_FLOAT 925ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk : AAudioConvert_aaudioToAndroidDataFormat(getFormat()); 93e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 94e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Setup the callback if there is one. 95e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk AudioTrack::callback_t callback = nullptr; 96e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk void *callbackData = nullptr; 97e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Note that TRANSFER_SYNC does not allow FAST track 98e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk AudioTrack::transfer_type streamTransferType = AudioTrack::transfer_type::TRANSFER_SYNC; 99e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (builder.getDataCallbackProc() != nullptr) { 100e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk streamTransferType = AudioTrack::transfer_type::TRANSFER_CALLBACK; 101e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk callback = getLegacyCallback(); 102e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk callbackData = this; 103e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 104e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // If the total buffer size is unspecified then base the size on the burst size. 1054485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk if (frameCount == 0 1064485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk && ((flags & AUDIO_OUTPUT_FLAG_FAST) != 0)) { 107e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Take advantage of a special trick that allows us to create a buffer 108e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // that is some multiple of the burst size. 109e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk notificationFrames = 0 - DEFAULT_BURSTS_PER_BUFFER_CAPACITY; 1104485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk } else { 1114485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk notificationFrames = builder.getFramesPerDataCallback(); 112e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 113e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 114e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackBufferSize = builder.getFramesPerDataCallback(); 115e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 116cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk ALOGD("AudioStreamTrack::open(), request notificationFrames = %d, frameCount = %u", 117cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk notificationFrames, (uint)frameCount); 118fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent mAudioTrack = new AudioTrack(); 119fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent if (getDeviceId() != AAUDIO_UNSPECIFIED) { 120fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent mAudioTrack->setOutputDevice(getDeviceId()); 121fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent } 122fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent mAudioTrack->set( 123e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk (audio_stream_type_t) AUDIO_STREAM_MUSIC, 124e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk getSampleRate(), 125e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk format, 126e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk channelMask, 127e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk frameCount, 128e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk flags, 129e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk callback, 130e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk callbackData, 131e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk notificationFrames, 132fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent 0 /*sharedBuffer*/, 133fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent false /*threadCanCallJava*/, 134e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk AUDIO_SESSION_ALLOCATE, 135e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk streamTransferType 136e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ); 137e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 138e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Did we get a valid track? 139e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t status = mAudioTrack->initCheck(); 140dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk if (status != NO_ERROR) { 141e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk close(); 142e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ALOGE("AudioStreamTrack::open(), initCheck() returned %d", status); 1435ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(status); 144e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 145e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 1461d32e9f8e5ba52d69c6319270c8a63a995d2c4f2Eric Laurent //TrackPlayerBase init 1471d32e9f8e5ba52d69c6319270c8a63a995d2c4f2Eric Laurent init(mAudioTrack.get(), PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA); 1481d32e9f8e5ba52d69c6319270c8a63a995d2c4f2Eric Laurent 149e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Get the actual values from the AudioTrack. 150e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk setSamplesPerFrame(mAudioTrack->channelCount()); 1519dca9824da74d50be02bc81f539cc77b7bde678aPhil Burk aaudio_format_t aaudioFormat = 152e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk AAudioConvert_androidToAAudioDataFormat(mAudioTrack->format()); 153e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk setFormat(aaudioFormat); 154e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 155cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk int32_t actualSampleRate = mAudioTrack->getSampleRate(); 156cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk ALOGW_IF(actualSampleRate != getSampleRate(), 157cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk "AudioStreamTrack::open() sampleRate changed from %d to %d", 158cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk getSampleRate(), actualSampleRate); 159cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk setSampleRate(actualSampleRate); 160cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk 161e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // We may need to pass the data through a block size adapter to guarantee constant size. 162e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) { 163e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize; 164e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mFixedBlockReader.open(callbackSizeBytes); 165e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mBlockAdapter = &mFixedBlockReader; 166e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } else { 167e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mBlockAdapter = nullptr; 168e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 169e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 1705ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_OPEN); 171c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk setDeviceId(mAudioTrack->getRoutedDeviceId()); 172fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent mAudioTrack->addAudioDeviceCallback(mDeviceCallback); 173e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 17430a707773a043e5eebd552d369c0882f886b67e5Phil Burk // Update performance mode based on the actual stream. 17530a707773a043e5eebd552d369c0882f886b67e5Phil Burk // For example, if the sample rate is not allowed then you won't get a FAST track. 17630a707773a043e5eebd552d369c0882f886b67e5Phil Burk audio_output_flags_t actualFlags = mAudioTrack->getFlags(); 17730a707773a043e5eebd552d369c0882f886b67e5Phil Burk aaudio_performance_mode_t actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE; 17830a707773a043e5eebd552d369c0882f886b67e5Phil Burk if ((actualFlags & (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW)) 17930a707773a043e5eebd552d369c0882f886b67e5Phil Burk == (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW)) { 18030a707773a043e5eebd552d369c0882f886b67e5Phil Burk actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY; 18130a707773a043e5eebd552d369c0882f886b67e5Phil Burk 18230a707773a043e5eebd552d369c0882f886b67e5Phil Burk } else if ((actualFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) { 18330a707773a043e5eebd552d369c0882f886b67e5Phil Burk actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING; 18430a707773a043e5eebd552d369c0882f886b67e5Phil Burk } 18530a707773a043e5eebd552d369c0882f886b67e5Phil Burk setPerformanceMode(actualPerformanceMode); 18630a707773a043e5eebd552d369c0882f886b67e5Phil Burk // Log warning if we did not get what we asked for. 18730a707773a043e5eebd552d369c0882f886b67e5Phil Burk ALOGW_IF(actualFlags != flags, 18830a707773a043e5eebd552d369c0882f886b67e5Phil Burk "AudioStreamTrack::open() flags changed from 0x%08X to 0x%08X", 18930a707773a043e5eebd552d369c0882f886b67e5Phil Burk flags, actualFlags); 19030a707773a043e5eebd552d369c0882f886b67e5Phil Burk ALOGW_IF(actualPerformanceMode != perfMode, 19130a707773a043e5eebd552d369c0882f886b67e5Phil Burk "AudioStreamTrack::open() perfMode changed from %d to %d", 19230a707773a043e5eebd552d369c0882f886b67e5Phil Burk perfMode, actualPerformanceMode); 19330a707773a043e5eebd552d369c0882f886b67e5Phil Burk 1945ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 195e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 196e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 1975ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamTrack::close() 198e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 1995ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (getState() != AAUDIO_STREAM_STATE_CLOSED) { 2001d32e9f8e5ba52d69c6319270c8a63a995d2c4f2Eric Laurent destroy(); 2015ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_CLOSED); 202e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 203e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mFixedBlockReader.close(); 2045ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 205e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 206e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 207e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkvoid AudioStreamTrack::processCallback(int event, void *info) { 208e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 209e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk switch (event) { 210e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk case AudioTrack::EVENT_MORE_DATA: 211e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk processCallbackCommon(AAUDIO_CALLBACK_OPERATION_PROCESS_DATA, info); 212e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 213e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 214e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Stream got rerouted so we disconnect. 215e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk case AudioTrack::EVENT_NEW_IAUDIOTRACK: 216e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info); 217e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 218e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 219e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk default: 220e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 221e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 222e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return; 223e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk} 224e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 2255ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamTrack::requestStart() 226e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 227e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk std::lock_guard<std::mutex> lock(mStreamMutex); 228e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 229d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk if (mAudioTrack.get() == nullptr) { 2305ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 231e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 232e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Get current position so we can detect when the track is playing. 233e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t err = mAudioTrack->getPosition(&mPositionWhenStarting); 234e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 2355ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(err); 236e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 237e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 2381d32e9f8e5ba52d69c6319270c8a63a995d2c4f2Eric Laurent err = startWithStatus(); 239e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 2405ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(err); 241e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else { 242fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent onStart(); 2435ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTING); 244e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 2455ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 246e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 247e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2485ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamTrack::requestPause() 249e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 250e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk std::lock_guard<std::mutex> lock(mStreamMutex); 251e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 252d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk if (mAudioTrack.get() == nullptr) { 2535ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 2545ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk } else if (getState() != AAUDIO_STREAM_STATE_STARTING 2555ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk && getState() != AAUDIO_STREAM_STATE_STARTED) { 256e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk ALOGE("requestPause(), called when state is %s", 257e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk AAudio_convertStreamStateToText(getState())); 2585ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 259e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 260fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent onStop(); 2615ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_PAUSING); 2621d32e9f8e5ba52d69c6319270c8a63a995d2c4f2Eric Laurent pause(); 263e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t err = mAudioTrack->getPosition(&mPositionWhenPausing); 264e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 2655ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(err); 266e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 2675ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 268e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 269e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2705ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamTrack::requestFlush() { 271e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk std::lock_guard<std::mutex> lock(mStreamMutex); 272e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 273d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk if (mAudioTrack.get() == nullptr) { 2745ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 2755ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk } else if (getState() != AAUDIO_STREAM_STATE_PAUSED) { 2765ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 277e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 2785ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_FLUSHING); 279e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk incrementFramesRead(getFramesWritten() - getFramesRead()); 280e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mAudioTrack->flush(); 281e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mFramesWritten.reset32(); 2825ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 283e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 284e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2855ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamTrack::requestStop() { 286e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk std::lock_guard<std::mutex> lock(mStreamMutex); 287e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 288d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk if (mAudioTrack.get() == nullptr) { 2895ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 290e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 291fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent onStop(); 2925ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STOPPING); 293e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk incrementFramesRead(getFramesWritten() - getFramesRead()); // TODO review 2941d32e9f8e5ba52d69c6319270c8a63a995d2c4f2Eric Laurent stop(); 295e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mFramesWritten.reset32(); 2965ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 297e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 298e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 299e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkaaudio_result_t AudioStreamTrack::updateStateWhileWaiting() 300e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 301e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t err; 3025ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_wrapping_frames_t position; 303e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk switch (getState()) { 304e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO add better state visibility to AudioTrack 3055ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STARTING: 306e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (mAudioTrack->hasStarted()) { 3075ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTED); 308e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 309e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 3105ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_PAUSING: 311e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (mAudioTrack->stopped()) { 312e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk err = mAudioTrack->getPosition(&position); 313e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 3145ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(err); 315e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else if (position == mPositionWhenPausing) { 316e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Has stream really stopped advancing? 3175ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_PAUSED); 318e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 319e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mPositionWhenPausing = position; 320e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 321e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 3225ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_FLUSHING: 323e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk { 324e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk err = mAudioTrack->getPosition(&position); 325e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 3265ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(err); 327e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else if (position == 0) { 3285204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk // TODO Advance frames read to match written. 3295ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_FLUSHED); 330e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 331e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 332e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 3335ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STOPPING: 334e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (mAudioTrack->stopped()) { 3355ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STOPPED); 336e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 337e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 338e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk default: 339e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 340e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 3415ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 342e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 343e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 3445ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamTrack::write(const void *buffer, 3453316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t numFrames, 3463316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t timeoutNanoseconds) 347e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 3483316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t bytesPerFrame = getBytesPerFrame(); 3493316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t numBytes; 3505ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAudioConvert_framesToBytes(numFrames, bytesPerFrame, &numBytes); 3515ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 352e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return result; 353e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 354e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 355fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED) { 356fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent return AAUDIO_ERROR_DISCONNECTED; 357fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent } 358fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent 359e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO add timeout to AudioTrack 360e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk bool blocking = timeoutNanoseconds > 0; 361e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ssize_t bytesWritten = mAudioTrack->write(buffer, numBytes, blocking); 362e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (bytesWritten == WOULD_BLOCK) { 363e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return 0; 364e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else if (bytesWritten < 0) { 365e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ALOGE("invalid write, returned %d", (int)bytesWritten); 366fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent // in this context, a DEAD_OBJECT is more likely to be a disconnect notification due to 367fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent // AudioTrack invalidation 368fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent if (bytesWritten == DEAD_OBJECT) { 369fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent setState(AAUDIO_STREAM_STATE_DISCONNECTED); 370fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent return AAUDIO_ERROR_DISCONNECTED; 371fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent } 3725ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(bytesWritten); 373e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 3743316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t framesWritten = (int32_t)(bytesWritten / bytesPerFrame); 375e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk incrementFramesWritten(framesWritten); 376e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return framesWritten; 377e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 378e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 3793316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkaaudio_result_t AudioStreamTrack::setBufferSize(int32_t requestedFrames) 380e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 381e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ssize_t result = mAudioTrack->setBufferSizeInFrames(requestedFrames); 3823316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk if (result < 0) { 3835ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(result); 384e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else { 3853316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk return result; 386e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 387e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 388e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 3893316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamTrack::getBufferSize() const 390e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 3913316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk return static_cast<int32_t>(mAudioTrack->getBufferSizeInFrames()); 392e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 393e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 3943316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamTrack::getBufferCapacity() const 395e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 3963316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk return static_cast<int32_t>(mAudioTrack->frameCount()); 397e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 398e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 399e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkint32_t AudioStreamTrack::getXRunCount() const 400e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 401e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return static_cast<int32_t>(mAudioTrack->getUnderrunCount()); 402e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 403e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 404e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkint32_t AudioStreamTrack::getFramesPerBurst() const 405e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 406b588402d48c9634fa72e7e13ca6d6f2a0766cb98Phil Burk return static_cast<int32_t>(mAudioTrack->getNotificationPeriodInFrames()); 407e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 408e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 4093316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint64_t AudioStreamTrack::getFramesRead() { 4105ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_wrapping_frames_t position; 411e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t result; 412e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk switch (getState()) { 4135ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STARTING: 4145ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STARTED: 4155ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STOPPING: 4164c5129b410884ec0400cbe65fce56d0ade12d11bPhil Burk case AAUDIO_STREAM_STATE_PAUSING: 4174c5129b410884ec0400cbe65fce56d0ade12d11bPhil Burk case AAUDIO_STREAM_STATE_PAUSED: 418e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk result = mAudioTrack->getPosition(&position); 419e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (result == OK) { 420e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mFramesRead.update32(position); 421e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 422e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 423e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk default: 424e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 425e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 426e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return AudioStream::getFramesRead(); 427e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 42835e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk 42935e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burkaaudio_result_t AudioStreamTrack::getTimestamp(clockid_t clockId, 43035e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk int64_t *framePosition, 43135e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk int64_t *timeNanoseconds) { 43235e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk ExtendedTimestamp extendedTimestamp; 43335e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk status_t status = mAudioTrack->getTimestamp(&extendedTimestamp); 43435e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk if (status != NO_ERROR) { 43535e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk return AAudioConvert_androidToAAudioResult(status); 43635e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk } 4375204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk return getBestTimestamp(clockId, framePosition, timeNanoseconds, &extendedTimestamp); 43835e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk} 439