blob: ac637ef846c05471614cdbc01f71611092cdec42 [file] [log] [blame]
Phil Burk062e67a2015-02-11 13:40:50 -08001/*
2**
3** Copyright 2015, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#define LOG_TAG "AudioFlinger"
19//#define LOG_NDEBUG 0
20#include <hardware/audio.h>
21#include <utils/Log.h>
22
23#include <audio_utils/spdif/SPDIFEncoder.h>
24
25#include "AudioHwDevice.h"
26#include "AudioStreamOut.h"
27#include "SpdifStreamOut.h"
28
29namespace android {
30
31/**
32 * If the AudioFlinger is processing encoded data and the HAL expects
33 * PCM then we need to wrap the data in an SPDIF wrapper.
34 */
Phil Burk23d89972015-04-06 16:22:23 -070035SpdifStreamOut::SpdifStreamOut(AudioHwDevice *dev,
36 audio_output_flags_t flags,
37 audio_format_t format)
Phil Burk062e67a2015-02-11 13:40:50 -080038 : AudioStreamOut(dev,flags)
39 , mRateMultiplier(1)
Phil Burk23d89972015-04-06 16:22:23 -070040 , mSpdifEncoder(this, format)
Phil Burk062e67a2015-02-11 13:40:50 -080041 , mRenderPositionHal(0)
42 , mPreviousHalPosition32(0)
43{
44}
45
46status_t SpdifStreamOut::open(
47 audio_io_handle_t handle,
48 audio_devices_t devices,
49 struct audio_config *config,
50 const char *address)
51{
52 struct audio_config customConfig = *config;
53
Phil Burk062e67a2015-02-11 13:40:50 -080054 // Some data bursts run at a higher sample rate.
Phil Burk23d89972015-04-06 16:22:23 -070055 // TODO Move this into the audio_utils as a static method.
Phil Burk062e67a2015-02-11 13:40:50 -080056 switch(config->format) {
57 case AUDIO_FORMAT_E_AC3:
58 mRateMultiplier = 4;
59 break;
60 case AUDIO_FORMAT_AC3:
Phil Burk23d89972015-04-06 16:22:23 -070061 case AUDIO_FORMAT_DTS:
62 case AUDIO_FORMAT_DTS_HD:
Phil Burk062e67a2015-02-11 13:40:50 -080063 mRateMultiplier = 1;
64 break;
65 default:
66 ALOGE("ERROR SpdifStreamOut::open() unrecognized format 0x%08X\n",
67 config->format);
68 return BAD_VALUE;
69 }
70 customConfig.sample_rate = config->sample_rate * mRateMultiplier;
71
Phil Burk23d89972015-04-06 16:22:23 -070072 customConfig.format = AUDIO_FORMAT_PCM_16_BIT;
73 customConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
74
Phil Burk062e67a2015-02-11 13:40:50 -080075 // Always print this because otherwise it could be very confusing if the
76 // HAL and AudioFlinger are using different formats.
77 // Print before open() because HAL may modify customConfig.
78 ALOGI("SpdifStreamOut::open() AudioFlinger requested"
79 " sampleRate %d, format %#x, channelMask %#x",
80 config->sample_rate,
81 config->format,
82 config->channel_mask);
83 ALOGI("SpdifStreamOut::open() HAL configured for"
84 " sampleRate %d, format %#x, channelMask %#x",
85 customConfig.sample_rate,
86 customConfig.format,
87 customConfig.channel_mask);
88
89 status_t status = AudioStreamOut::open(
90 handle,
91 devices,
92 &customConfig,
93 address);
94
95 ALOGI("SpdifStreamOut::open() status = %d", status);
96
97 return status;
98}
99
100// Account for possibly higher sample rate.
101status_t SpdifStreamOut::getRenderPosition(uint32_t *frames)
102{
103 uint32_t halPosition = 0;
104 status_t status = AudioStreamOut::getRenderPosition(&halPosition);
105 if (status != NO_ERROR) {
106 return status;
107 }
108
109 // Accumulate a 64-bit position so that we wrap at the right place.
110 if (mRateMultiplier != 1) {
111 // Maintain a 64-bit render position.
112 int32_t deltaHalPosition = (int32_t)(halPosition - mPreviousHalPosition32);
113 mPreviousHalPosition32 = halPosition;
114 mRenderPositionHal += deltaHalPosition;
115
116 // Scale from device sample rate to application rate.
117 uint64_t renderPositionApp = mRenderPositionHal / mRateMultiplier;
118 ALOGV("SpdifStreamOut::getRenderPosition() "
119 "renderPositionAppRate = %llu = %llu / %u\n",
120 renderPositionApp, mRenderPositionHal, mRateMultiplier);
121
122 *frames = (uint32_t)renderPositionApp;
123 } else {
124 *frames = halPosition;
125 }
126 return status;
127}
128
129int SpdifStreamOut::flush()
130{
Phil Burk48e6ea92015-06-18 15:37:08 -0700131 mSpdifEncoder.reset();
Phil Burk062e67a2015-02-11 13:40:50 -0800132 mRenderPositionHal = 0;
133 mPreviousHalPosition32 = 0;
134 return AudioStreamOut::flush();
135}
136
137int SpdifStreamOut::standby()
138{
Phil Burk48e6ea92015-06-18 15:37:08 -0700139 mSpdifEncoder.reset();
Phil Burk062e67a2015-02-11 13:40:50 -0800140 mRenderPositionHal = 0;
141 mPreviousHalPosition32 = 0;
142 return AudioStreamOut::standby();
143}
144
145// Account for possibly higher sample rate.
146// This is much easier when all the values are 64-bit.
147status_t SpdifStreamOut::getPresentationPosition(uint64_t *frames,
148 struct timespec *timestamp)
149{
150 uint64_t halFrames = 0;
151 status_t status = AudioStreamOut::getPresentationPosition(&halFrames, timestamp);
152 *frames = halFrames / mRateMultiplier;
153 return status;
154}
155
156size_t SpdifStreamOut::getFrameSize()
157{
158 return sizeof(int8_t);
159}
160
161ssize_t SpdifStreamOut::writeDataBurst(const void* buffer, size_t bytes)
162{
163 return AudioStreamOut::write(buffer, bytes);
164}
165
166ssize_t SpdifStreamOut::write(const void* buffer, size_t bytes)
167{
168 // Write to SPDIF wrapper. It will call back to writeDataBurst().
169 return mSpdifEncoder.write(buffer, bytes);
170}
171
172} // namespace android