1 /*
2 * Copyright (c) 2022 Unionman Technology 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 <mutex>
17 #include <cstdint>
18 #include <cstdio>
19 #include <cstdlib>
20 #include <cstring>
21 #include <fstream>
22 #include <thread>
23 #include <map>
24 #include <condition_variable>
25 #include <dlfcn.h>
26 #include "errors.h"
27 #include "media_log.h"
28 #include "audio_info.h"
29 #include "audio_renderer_sink.h"
30 #include "audio_types.h"
31
32 #include "audio_external_render.h"
33
34 namespace
35 {
36 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AMPLAYER_AUDIO_RENDER"};
37 }
38
39 namespace OHOS
40 {
41 namespace AudioStandard
42 {
43
44 AudioRendererSink *g_audioRendrSinkInstance = nullptr;
45
audio_render_init(struct audio_render_s * r)46 static int audio_render_init(struct audio_render_s *r)
47 {
48 MEDIA_LOGD("%{public}s() in", __func__);
49 IAudioSinkAttr sample_attrs;
50 int32_t ret;
51 #ifdef __aarch64__
52 char resolvedPath[100] = "/system/lib64/libaudio_renderer_sink.z.so";
53 #else
54 char resolvedPath[100] = "/system/lib/libaudio_renderer_sink.z.so";
55 #endif
56 AudioRendererSink *(*GetInstance)() = nullptr;
57
58 void *handle_ = dlopen(resolvedPath, 1);
59 if (handle_ == nullptr) {
60 MEDIA_LOGE("Open so Fail");
61 return -1;
62 }
63 MEDIA_LOGI("dlopen successful");
64
65 GetInstance = (AudioRendererSink *(*)())(dlsym(handle_, "_ZN4OHOS13AudioStandard17AudioRendererSink11GetInstanceEv"));
66 if (GetInstance == nullptr) {
67 return -1;
68 }
69 MEDIA_LOGI("GetInstance done");
70
71 g_audioRendrSinkInstance = GetInstance();
72 if (g_audioRendrSinkInstance == nullptr) {
73 return -1;
74 }
75 MEDIA_LOGI("audioRendrSinkInstance created");
76
77 sample_attrs.adapterName = "primary";
78 sample_attrs.format = SAMPLE_S16LE;
79 sample_attrs.sampleFmt = AUDIO_FORMAT_TYPE_PCM_16_BIT;
80 sample_attrs.sampleRate = 48000;
81 sample_attrs.channel = 2;
82 sample_attrs.volume = 1.0;
83
84 ret = g_audioRendrSinkInstance->Init(sample_attrs);
85 if (ret != 0) {
86 MEDIA_LOGE("Error: audiorender Init() failed!");
87 return -1;
88 }
89
90 return 0;
91 }
92
audio_render_finalize(struct audio_render_s * r)93 static int audio_render_finalize(struct audio_render_s *r)
94 {
95 MEDIA_LOGD("%{public}s() in", __func__);
96
97 g_audioRendrSinkInstance->Stop();
98 g_audioRendrSinkInstance->DeInit();
99
100 return 0;
101 }
102
audio_render_config(struct audio_render_s * r,uint32_t channels,uint32_t bits_per_sample,uint32_t sample_rate)103 static int audio_render_config(struct audio_render_s *r, uint32_t channels,
104 uint32_t bits_per_sample, uint32_t sample_rate)
105 {
106 MEDIA_LOGD("audio_render_config in, channels:%{public}d, sampleRate:%{public}d", channels, sample_rate);
107
108 return 0;
109 }
110
audio_render_write(struct audio_render_s * r,uint8_t * data,uint32_t size)111 static int audio_render_write(struct audio_render_s *r, uint8_t *data, uint32_t size)
112 {
113 MEDIA_LOGD("%{public}s() size=%{public}u", __func__, size);
114 uint64_t writeLen = 0;
115 CHECK_AND_RETURN_RET(g_audioRendrSinkInstance->RenderFrame(*((char *)data), size, writeLen) == 0, -1);
116 return (int)writeLen;
117 }
118
audio_render_start(struct audio_render_s * r)119 static int audio_render_start(struct audio_render_s *r)
120 {
121 MEDIA_LOGD("%{public}s() in", __func__);
122
123 CHECK_AND_RETURN_RET(g_audioRendrSinkInstance->Start() == 0, -1);
124 return 0;
125 }
126
audio_render_stop(struct audio_render_s * r)127 static int audio_render_stop(struct audio_render_s *r)
128 {
129 MEDIA_LOGD("%{public}s() in", __func__);
130
131 CHECK_AND_RETURN_RET(g_audioRendrSinkInstance->Stop() == 0, -1);
132 return 0;
133 }
134
audio_render_pause(struct audio_render_s * r)135 static int audio_render_pause(struct audio_render_s *r)
136 {
137 MEDIA_LOGD("%{public}s() in", __func__);
138
139 CHECK_AND_RETURN_RET(g_audioRendrSinkInstance->Pause() == 0, -1);
140 return 0;
141 }
142
audio_render_resume(struct audio_render_s * r)143 static int audio_render_resume(struct audio_render_s *r)
144 {
145 MEDIA_LOGD("%{public}s() in", __func__);
146
147 CHECK_AND_RETURN_RET(g_audioRendrSinkInstance->Resume() == 0, -1);
148 return 0;
149 }
150
get_latency_from_driver(struct audio_render_s * r)151 static uint32_t get_latency_from_driver(struct audio_render_s *r)
152 {
153 uint32_t latency = 0;
154 char line[256];
155 FILE *fp = fopen("/proc/asound/card0/pcm1p/sub0/status", "rt");
156 if (!fp) {
157 return 0;
158 }
159
160 while (fgets(line, sizeof(line), fp)) {
161 line[sizeof(line) - 1] = '\0';
162 if (!strncmp(line, "delay", 5)) {
163 uint32_t frames = 0;
164 if (1 != sscanf(line, "%*[^:]:%u", &frames)) {
165 MEDIA_LOGE("Error: parse line failed: %{public}s", line);
166 break;
167 }
168 latency = (frames * 1000) / 48000;
169 // MEDIA_LOGD("get latency: %{public}u, %{public}u", frames, latency);
170 break;
171 }
172 }
173
174 fclose(fp);
175
176 return latency;
177 }
178
audio_render_get_latency(struct audio_render_s * r)179 static uint32_t audio_render_get_latency(struct audio_render_s *r)
180 {
181 uint32_t latency;
182
183 // CHECK_AND_RETURN_RET(g_audioRendrSinkInstance->GetLatency(&latency) == 0, -1);
184 latency = get_latency_from_driver(r);
185
186 return latency;
187 }
188
audio_render_set_mute(struct audio_render_s * r,int mute)189 static int audio_render_set_mute(struct audio_render_s *r, int mute)
190 {
191 MEDIA_LOGD("%{public}s() in. mute=%{public}d", __func__, mute);
192 return 0;
193 }
194
audio_render_set_volume(struct audio_render_s * r,float volume)195 static int audio_render_set_volume(struct audio_render_s *r, float volume)
196 {
197 MEDIA_LOGD("%{public}s() in. volume=%{public}f", __func__, volume);
198
199 CHECK_AND_RETURN_RET(g_audioRendrSinkInstance->SetVolume(volume, volume) == 0, -1);
200 return 0;
201 }
202
203 static audio_render_t audio_render_ops = {
204 .init = audio_render_init,
205 .finalize = audio_render_finalize,
206 .config = audio_render_config,
207 .write = audio_render_write,
208 .start = audio_render_start,
209 .stop = audio_render_stop,
210 .pause = audio_render_pause,
211 .resume = audio_render_resume,
212 .get_latency = audio_render_get_latency,
213 .set_mute = audio_render_set_mute,
214 .set_volume = audio_render_set_volume
215 };
216
217 } // namespace AudioStandard
218 } // namespace OHOS
219
audio_render_get(void)220 __attribute__((visibility("default"))) audio_render_t *audio_render_get(void)
221 {
222 return &OHOS::AudioStandard::audio_render_ops;
223 }
224