• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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