1/*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "audio_sink.h"
17#include "common/media_log.h"
18
19namespace OHOS {
20namespace Sharing {
21
22AudioSink::AudioSink(uint32_t playerId) : audioRenderer_(nullptr)
23{
24    SHARING_LOGD("playerId: %{public}u  tid: %{public}d.", playerId, gettid());
25    playerId_ = playerId;
26}
27
28AudioSink::~AudioSink()
29{
30    SHARING_LOGD("playerId: %{public}u.", playerId_);
31    Stop();
32    Release();
33    SHARING_LOGD("renderthread release success,playerId: %{public}u.", playerId_);
34}
35
36int32_t AudioSink::Prepare()
37{
38    SHARING_LOGD("playerId: %{public}u.", playerId_);
39    audioRenderer_ = AudioStandard::AudioRenderer::Create(AudioStandard::AudioStreamType::STREAM_MUSIC);
40    if (!audioRenderer_) {
41        SHARING_LOGE("audioRenderer_ is NULL.");
42        return PLAYER_ERROR_EMPTY_INSTANCE;
43    }
44
45    return PLAYER_SUCCESS;
46}
47
48int32_t AudioSink::Prepare(int32_t channels, int32_t sampleRate)
49{
50    SHARING_LOGD("channels(%{public}d) sampleRate(%{public}d) playerId: %{public}u.", channels, sampleRate, playerId_);
51    audioRenderer_ = AudioStandard::AudioRenderer::Create(AudioStandard::AudioStreamType::STREAM_MUSIC);
52    if (!audioRenderer_) {
53        SHARING_LOGE("audioRenderer_ is NULL.");
54        return PLAYER_ERROR_EMPTY_INSTANCE;
55    }
56
57    int32_t res = SetParameters(16, channels, sampleRate);
58    SHARING_LOGD("leave.");
59    return res;
60}
61
62int32_t AudioSink::Start()
63{
64    SHARING_LOGD("playerId: %{public}u.", playerId_);
65    if (!audioRenderer_) {
66        SHARING_LOGE("audioRenderer_ is NULL.");
67        return PLAYER_ERROR_EMPTY_INSTANCE;
68    }
69
70    audioRenderer_->Start();
71    running_ = true;
72    return PLAYER_SUCCESS;
73}
74
75int32_t AudioSink::Stop()
76{
77    SHARING_LOGD("playerId: %{public}u.", playerId_);
78    if (!audioRenderer_) {
79        SHARING_LOGE("audioRenderer_ is NULL playerId: %{public}u!", playerId_);
80        return PLAYER_ERROR_EMPTY_INSTANCE;
81    }
82
83    if (!running_) {
84        SHARING_LOGE("running_ is false playerId: %{public}u!", playerId_);
85        return PLAYER_ERROR_INVALID_STATE;
86    }
87
88    running_ = false;
89    audioRenderer_->Stop();
90    SHARING_LOGD("success, playerId: %{public}u.", playerId_);
91    return PLAYER_SUCCESS;
92}
93
94int32_t AudioSink::Pause()
95{
96    SHARING_LOGD("playerId: %{public}u.", playerId_);
97    if (!audioRenderer_) {
98        SHARING_LOGE("audioRenderer_ is NULL.");
99        return PLAYER_ERROR_EMPTY_INSTANCE;
100    }
101
102    if (audioRenderer_->Pause() != true) {
103        SHARING_LOGE("failed!");
104        return -1;
105    }
106
107    return PLAYER_SUCCESS;
108}
109
110int32_t AudioSink::Drain()
111{
112    SHARING_LOGD("playerId: %{public}u.", playerId_);
113    if (!audioRenderer_) {
114        SHARING_LOGE("audioRenderer_ is NULL.");
115        return PLAYER_ERROR_EMPTY_INSTANCE;
116    }
117
118    if (audioRenderer_->Drain() != true) {
119        SHARING_LOGE("failed!");
120        return -1;
121    }
122
123    return PLAYER_SUCCESS;
124}
125
126int32_t AudioSink::Flush()
127{
128    SHARING_LOGD("playerId: %{public}u.", playerId_);
129    if (!audioRenderer_) {
130        SHARING_LOGE("audioRenderer_ is NULL.");
131        return PLAYER_ERROR_EMPTY_INSTANCE;
132    }
133
134    if (audioRenderer_->Flush() != true) {
135        SHARING_LOGE("failed!");
136        return -1;
137    }
138
139    return PLAYER_SUCCESS;
140}
141
142int32_t AudioSink::Release()
143{
144    SHARING_LOGD("playerId: %{public}u.", playerId_);
145    if (!audioRenderer_) {
146        SHARING_LOGE("audioRenderer_ is NULL.");
147        return PLAYER_ERROR_EMPTY_INSTANCE;
148    }
149
150    audioRenderer_ = nullptr;
151    return PLAYER_SUCCESS;
152}
153
154int32_t AudioSink::SetParameters(int32_t bitsPerSample, int32_t channels, int32_t sampleRate)
155{
156    SHARING_LOGD("playerId: %{public}u.", playerId_);
157    (void)bitsPerSample;
158    SHARING_LOGD("enter, channels:%{public}d, sampleRate:%{public}d.", channels, sampleRate);
159
160    if (!audioRenderer_) {
161        SHARING_LOGE("audioRenderer_ is NULL.");
162        return PLAYER_ERROR_EMPTY_INSTANCE;
163    }
164
165    AudioStandard::AudioRendererParams params;
166    std::vector<AudioStandard::AudioSamplingRate> supportedSampleList =
167        AudioStandard::AudioRenderer::GetSupportedSamplingRates();
168    if (supportedSampleList.empty()) {
169        SHARING_LOGE("GetSupportedSamplingRates empty.");
170        return -1;
171    }
172
173    bool isValidSampleRate = false;
174    for (size_t i = 0; i < supportedSampleList.size(); i++) {
175        if (sampleRate <= supportedSampleList[i] && supportedSampleList[i] > 0) {
176            params.sampleRate = supportedSampleList[i];
177            isValidSampleRate = true;
178            break;
179        }
180    }
181
182    if (!isValidSampleRate) {
183        SHARING_LOGE("Unsupported sample ratefailed.");
184        return -1;
185    }
186
187    std::vector<AudioStandard::AudioChannel> supportedChannelsList =
188        AudioStandard::AudioRenderer::GetSupportedChannels();
189    if (supportedChannelsList.empty()) {
190        SHARING_LOGE("GetSupportedChannels empty.");
191        return -1;
192    }
193
194    bool isValidChannels = false;
195    for (size_t i = 0; i < supportedChannelsList.size(); i++) {
196        if (channels == supportedChannelsList[i] && supportedChannelsList[i] > 0) {
197            params.channelCount = supportedChannelsList[i];
198            isValidChannels = true;
199            break;
200        }
201    }
202
203    if (!isValidChannels) {
204        SHARING_LOGE("Unsupported sample ratefailed.");
205        return -1;
206    }
207
208    params.sampleFormat = AudioStandard::SAMPLE_S16LE;
209    params.encodingType = AudioStandard::ENCODING_PCM;
210    SHARING_LOGD("channels:%{public}d, sampleRate:%{public}d.", params.channelCount, params.sampleRate);
211
212    if (audioRenderer_->SetParams(params) != 0) {
213        SHARING_LOGE("failed.");
214        return -1;
215    }
216
217    return PLAYER_SUCCESS;
218}
219
220int32_t AudioSink::GetParameters(int32_t &bitsPerSample, int32_t &channels, int32_t &sampleRate)
221{
222    SHARING_LOGD("playerId: %{public}u.", playerId_);
223    if (!audioRenderer_) {
224        SHARING_LOGE("audioRenderer_ is NULL.");
225        return PLAYER_ERROR_EMPTY_INSTANCE;
226    }
227
228    AudioStandard::AudioRendererParams params;
229    if (audioRenderer_->GetParams(params) != 0) {
230        SHARING_LOGE("failed.");
231        return -1;
232    }
233
234    channels = params.channelCount;
235    sampleRate = params.sampleRate;
236    bitsPerSample = (int32_t)params.sampleFormat;
237    return PLAYER_SUCCESS;
238}
239
240int32_t AudioSink::GetBufferSize(int32_t &bufferSize)
241{
242    SHARING_LOGD("playerId: %{public}u.", playerId_);
243    if (!audioRenderer_) {
244        SHARING_LOGE("audioRenderer_ is NULL.");
245        return PLAYER_ERROR_EMPTY_INSTANCE;
246    }
247
248    size_t size = 0;
249    if (audioRenderer_->GetBufferSize(size) != 0) {
250        SHARING_LOGE("failed!");
251        return -1;
252    }
253
254    bufferSize = (int32_t)size;
255    return PLAYER_SUCCESS;
256}
257
258int32_t AudioSink::SetVolume(float volume)
259{
260    SHARING_LOGD("playerId: %{public}u.", playerId_);
261    if (!audioRenderer_) {
262        SHARING_LOGE("audioRenderer_ is NULL.");
263        return PLAYER_ERROR_EMPTY_INSTANCE;
264    }
265
266    if (audioRenderer_->SetVolume(volume) != 0) {
267        SHARING_LOGE("failed!");
268        return -1;
269    }
270
271    return PLAYER_SUCCESS;
272}
273
274int32_t AudioSink::GetVolume(float &volume)
275{
276    SHARING_LOGD("playerId: %{public}u.", playerId_);
277    if (!audioRenderer_) {
278        SHARING_LOGE("audioRenderer_ is NULL.");
279        return PLAYER_ERROR_EMPTY_INSTANCE;
280    }
281
282    volume = audioRenderer_->GetVolume();
283    return PLAYER_SUCCESS;
284}
285
286int32_t AudioSink::Write(uint8_t *buffer, size_t size)
287{
288    MEDIA_LOGD("playerId: %{public}u.", playerId_);
289    if (!audioRenderer_) {
290        SHARING_LOGE("audioRenderer_ is NULL.");
291        return PLAYER_ERROR_EMPTY_INSTANCE;
292    }
293
294    size_t bytesWritten = 0;
295    int32_t bytesSingle = 0;
296    while (audioRenderer_ && bytesWritten < size && running_) {
297        bytesSingle = audioRenderer_->Write(buffer + bytesWritten, size - bytesWritten);
298        if (bytesSingle <= 0) {
299            MEDIA_LOGE("audioRenderer Write failed. playerId: %{public}u.", playerId_);
300            continue;
301        }
302
303        bytesWritten += static_cast<size_t>(bytesSingle);
304        if (bytesWritten < static_cast<size_t>(bytesSingle)) {
305            MEDIA_LOGE("audioRenderer Write failed playerId: %{public}u.", playerId_);
306            continue;
307        }
308        MEDIA_LOGD("audioRenderer Write end. playerId: %{public}u.", playerId_);
309    }
310
311    MEDIA_LOGD("recv data(len:%{public}zu.)", size);
312    return PLAYER_SUCCESS;
313}
314
315} // namespace Sharing
316} // namespace OHOS