1 /*
2 * Copyright (C) 2021 Huawei Device 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 "config.h"
17 #include "gst_audio_server_sink.h"
18 #include <cinttypes>
19 #include <gst/gst.h>
20 #include "gst/audio/audio.h"
21 #include "media_errors.h"
22 #include "media_log.h"
23 #include "media_dfx.h"
24 #include "audio_sink_factory.h"
25 #include "securec.h"
26 #include "audio_effect.h"
27
28 static GstStaticPadTemplate g_sinktemplate = GST_STATIC_PAD_TEMPLATE("sink",
29 GST_PAD_SINK,
30 GST_PAD_ALWAYS,
31 GST_STATIC_CAPS("audio/x-raw, "
32 "format = (string) S16LE, "
33 "layout = (string) interleaved, "
34 "rate = (int) [ 1, MAX ], "
35 "channels = (int) [ 1, MAX ]"));
36
37 using namespace OHOS::Media;
38 namespace {
39 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "audio_server_sink"};
40 constexpr float DEFAULT_VOLUME = 1.0f;
41 constexpr uint32_t DEFAULT_BITS_PER_SAMPLE = 16;
42 constexpr uint64_t AUDIO_EFFECT_NONE_RENDER_DELAY = 270000000; // unit ns, empirical value
43 constexpr uint64_t AUDIO_EFFECT_DEFAULT_RENDER_DELAY = 270000000; // unit ns, empirical value
44 }
45
46 enum {
47 PROP_0,
48 PROP_BITS_PER_SAMPLE,
49 PROP_CHANNELS,
50 PROP_SAMPLE_RATE,
51 PROP_APP_UID,
52 PROP_APP_PID,
53 PROP_APP_TOKEN_ID,
54 PROP_VOLUME,
55 PROP_MAX_VOLUME,
56 PROP_MIN_VOLUME,
57 PROP_AUDIO_RENDERER_DESC,
58 PROP_AUDIO_RENDERER_FLAG,
59 PROP_AUDIO_INTERRUPT_MODE,
60 PROP_LAST_RENDER_PTS,
61 PROP_ENABLE_OPT_RENDER_DELAY,
62 PROP_LAST_RUNNING_TIME_DIFF,
63 PROP_AUDIO_EFFECT_MODE,
64 PROP_DELAY_TIME,
65 };
66
67 #define gst_audio_server_sink_parent_class parent_class
68 G_DEFINE_TYPE(GstAudioServerSink, gst_audio_server_sink, GST_TYPE_BASE_SINK);
69
70 static void gst_audio_server_sink_finalize(GObject *object);
71 static void gst_audio_server_sink_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
72 static void gst_audio_server_sink_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
73 static GstStateChangeReturn gst_audio_server_sink_change_state(GstElement *element, GstStateChange transition);
74 static GstCaps *gst_audio_server_sink_get_caps(GstBaseSink *basesink, GstCaps *caps);
75 static gboolean gst_audio_server_sink_set_caps(GstBaseSink *basesink, GstCaps *caps);
76 static gboolean gst_audio_server_sink_event(GstBaseSink *basesink, GstEvent *event);
77 static gboolean gst_audio_server_sink_start(GstBaseSink *basesink);
78 static gboolean gst_audio_server_sink_stop(GstBaseSink *basesink);
79 static GstFlowReturn gst_audio_server_sink_render(GstBaseSink *basesink, GstBuffer *buffer);
80 static void gst_audio_server_sink_clear_cache_buffer(GstAudioServerSink *sink);
81 static GstClockTime gst_audio_server_sink_update_reach_time(GstBaseSink *basesink, GstClockTime reach_time,
82 gboolean *need_drop_this_buffer);
83
gst_audio_server_sink_class_init(GstAudioServerSinkClass * klass)84 static void gst_audio_server_sink_class_init(GstAudioServerSinkClass *klass)
85 {
86 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
87 GstElementClass *gstelement_class = GST_ELEMENT_CLASS(klass);
88 GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS(klass);
89 g_return_if_fail((gobject_class != nullptr) && (gstelement_class != nullptr) && (gstbasesink_class != nullptr));
90
91 gobject_class->finalize = gst_audio_server_sink_finalize;
92 gobject_class->set_property = gst_audio_server_sink_set_property;
93 gobject_class->get_property = gst_audio_server_sink_get_property;
94
95 g_signal_new("interrupt-event", G_TYPE_FROM_CLASS(klass),
96 static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), 0, NULL,
97 NULL, NULL, G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); // 3 parameters
98
99 g_signal_new("audio-state-event", G_TYPE_FROM_CLASS(klass),
100 static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), 0, NULL,
101 NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT); // 1 parameters
102
103 g_signal_new("segment-updated", G_TYPE_FROM_CLASS(klass),
104 static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), 0, NULL,
105 NULL, NULL, G_TYPE_NONE, 0); // no parameters
106
107 g_signal_new("audio-service-died", G_TYPE_FROM_CLASS(klass),
108 static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), 0, NULL,
109 NULL, NULL, G_TYPE_NONE, 0); // no parameters
110 g_object_class_install_property(gobject_class, PROP_BITS_PER_SAMPLE,
111 g_param_spec_uint("bps", "Bits Per Sample",
112 "Audio Format", 0, G_MAXINT32, 0,
113 (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
114
115 g_object_class_install_property(gobject_class, PROP_CHANNELS,
116 g_param_spec_uint("channels", "Channels",
117 "Channels", 0, G_MAXINT32, 0,
118 (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
119
120 g_object_class_install_property(gobject_class, PROP_SAMPLE_RATE,
121 g_param_spec_uint("sample-rate", "Sample Rate",
122 "Sample Rate", 0, G_MAXINT32, 0,
123 (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
124
125 g_object_class_install_property(gobject_class, PROP_APP_UID,
126 g_param_spec_int("app-uid", "Appuid",
127 "APP UID", 0, G_MAXINT32, 0,
128 (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
129
130 g_object_class_install_property(gobject_class, PROP_APP_PID,
131 g_param_spec_int("app-pid", "Apppid",
132 "APP PID", 0, G_MAXINT32, 0,
133 (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
134
135 g_object_class_install_property(gobject_class, PROP_APP_TOKEN_ID,
136 g_param_spec_uint("app-token-id", "Apptokenid",
137 "APP TOKEN ID", 0, G_MAXINT32, 0,
138 (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
139
140 g_object_class_install_property(gobject_class, PROP_VOLUME,
141 g_param_spec_float("volume", "Volume",
142 "Volume", 0, G_MAXFLOAT, 0,
143 (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
144
145 g_object_class_install_property(gobject_class, PROP_MAX_VOLUME,
146 g_param_spec_float("max-volume", "Maximum Volume",
147 "Maximum Volume", 0, G_MAXFLOAT, G_MAXFLOAT,
148 (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
149
150 g_object_class_install_property(gobject_class, PROP_MIN_VOLUME,
151 g_param_spec_float("min-volume", "Minimum Volume",
152 "Minimum Volume", 0, G_MAXFLOAT, 0,
153 (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
154
155 g_object_class_install_property(gobject_class, PROP_AUDIO_RENDERER_DESC,
156 g_param_spec_int("audio-renderer-desc", "Audio Renderer Desc",
157 "Audio Renderer Desc", 0, G_MAXINT32, 0,
158 (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
159
160 g_object_class_install_property(gobject_class, PROP_AUDIO_RENDERER_FLAG,
161 g_param_spec_int("audio-renderer-flag", "Audio Renderer Flag",
162 "Audio Renderer Flag", 0, G_MAXINT32, 0,
163 (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
164
165 g_object_class_install_property(gobject_class, PROP_AUDIO_INTERRUPT_MODE,
166 g_param_spec_int("audio-interrupt-mode", "Audio Interrupt Mode",
167 "Audio Interrupt Mode", 0, G_MAXINT32, 0,
168 (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
169
170 g_object_class_install_property(gobject_class, PROP_AUDIO_EFFECT_MODE,
171 g_param_spec_int("audio-effect-mode", "Audio Effect Mode",
172 "Audio Effect Mode", 0, G_MAXINT32, 0,
173 (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
174
175 g_object_class_install_property(gobject_class, PROP_LAST_RENDER_PTS,
176 g_param_spec_uint64("last-render-pts", "last-render-pts", "last render pts", 0, G_MAXUINT64,
177 0, (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
178
179 g_object_class_install_property(gobject_class, PROP_ENABLE_OPT_RENDER_DELAY,
180 g_param_spec_boolean("enable-opt-render-delay", "enable opt render delay",
181 "If TRUE, use DEFAULT_AUDIO_RENDER_DELAY instead of the latency provided by AudioStandard",
182 FALSE, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
183
184 g_object_class_install_property(gobject_class, PROP_LAST_RUNNING_TIME_DIFF,
185 g_param_spec_int64("last-running-time-diff", "last running time diff", "last running time diff",
186 0, G_MAXINT64, 0, (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
187
188 g_object_class_install_property(gobject_class, PROP_DELAY_TIME,
189 g_param_spec_uint("audio-delay-time", "audio delay time", "audio delay time", 0, G_MAXINT32,
190 0, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
191
192 gst_element_class_set_static_metadata(gstelement_class,
193 "Audio server sink", "Sink/Audio",
194 "Push pcm data to Audio server", "OpenHarmony");
195
196 gst_element_class_add_static_pad_template(gstelement_class, &g_sinktemplate);
197
198 gstelement_class->change_state = gst_audio_server_sink_change_state;
199
200 gstbasesink_class->get_caps = gst_audio_server_sink_get_caps;
201 gstbasesink_class->set_caps = gst_audio_server_sink_set_caps;
202 gstbasesink_class->event = gst_audio_server_sink_event;
203 gstbasesink_class->start = gst_audio_server_sink_start;
204 gstbasesink_class->stop = gst_audio_server_sink_stop;
205 gstbasesink_class->render = gst_audio_server_sink_render;
206 gstbasesink_class->update_reach_time = gst_audio_server_sink_update_reach_time;
207 }
208
gst_audio_server_sink_init(GstAudioServerSink * sink)209 static void gst_audio_server_sink_init(GstAudioServerSink *sink)
210 {
211 MediaTrace trace("Audio::gst_audio_server_sink_init");
212 g_return_if_fail(sink != nullptr);
213 sink->audio_sink = nullptr;
214 sink->bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
215 sink->channels = 0;
216 sink->sample_rate = 0;
217 sink->appuid = 0;
218 sink->apppid = 0;
219 sink->volume = DEFAULT_VOLUME;
220 sink->max_volume = G_MAXFLOAT;
221 sink->min_volume = 0;
222 sink->min_buffer_size = 0;
223 sink->min_frame_count = 0;
224 sink->pause_cache_buffer = nullptr;
225 sink->frame_after_segment = FALSE;
226 sink->renderer_desc = 0;
227 sink->renderer_flag = 0;
228 g_mutex_init(&sink->render_lock);
229 sink->last_render_pts = 0;
230 sink->enable_opt_render_delay = FALSE;
231 sink->last_running_time_diff = 0;
232 sink->pre_power_on = FALSE;
233 sink->start_first_render = FALSE;
234 sink->delay_time = AUDIO_EFFECT_DEFAULT_RENDER_DELAY;
235 }
236
gst_audio_server_sink_finalize(GObject * object)237 static void gst_audio_server_sink_finalize(GObject *object)
238 {
239 MediaTrace trace("Audio::gst_audio_server_sink_finalize");
240 g_return_if_fail(object != nullptr);
241 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(object);
242 g_return_if_fail(sink != nullptr);
243 GST_INFO_OBJECT(sink, "gst_audio_server_sink_finalize in");
244
245 g_mutex_clear(&sink->render_lock);
246 if (sink->audio_sink != nullptr) {
247 (void)sink->audio_sink->Release();
248 sink->audio_sink = nullptr;
249 }
250 gst_audio_server_sink_clear_cache_buffer(sink);
251
252 G_OBJECT_CLASS(parent_class)->finalize(object);
253 }
254
gst_audio_server_sink_set_volume(GstAudioServerSink * sink,gfloat volume)255 static gboolean gst_audio_server_sink_set_volume(GstAudioServerSink *sink, gfloat volume)
256 {
257 MediaTrace trace("Audio::gst_audio_server_sink_set_volume");
258 gboolean ret = FALSE;
259 g_return_val_if_fail(sink != nullptr, FALSE);
260 g_return_val_if_fail(sink->audio_sink != nullptr, FALSE);
261 g_return_val_if_fail(volume <= sink->max_volume, FALSE);
262 g_return_val_if_fail(volume >= sink->min_volume, FALSE);
263
264 if (sink->audio_sink->SetVolume(volume) == MSERR_OK) {
265 sink->volume = volume;
266 ret = TRUE;
267 }
268
269 GST_INFO_OBJECT(sink, "set volume(%f) finish, ret=%d", volume, ret);
270 return ret;
271 }
272
gst_audio_server_sink_interrupt_callback(GstBaseSink * basesink,guint eventType,guint forceType,guint hintType)273 static void gst_audio_server_sink_interrupt_callback(GstBaseSink *basesink,
274 guint eventType, guint forceType, guint hintType)
275 {
276 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(basesink);
277 g_signal_emit_by_name(sink, "interrupt-event", eventType, forceType, hintType);
278 }
279
gst_audio_server_sink_state_callback(GstBaseSink * basesink,guint state)280 static void gst_audio_server_sink_state_callback(GstBaseSink *basesink, guint state)
281 {
282 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(basesink);
283 g_signal_emit_by_name(sink, "audio-state-event", state);
284 }
285
gst_audio_server_sink_error_callback(GstBaseSink * basesink,const std::string & errMsg)286 static void gst_audio_server_sink_error_callback(GstBaseSink *basesink, const std::string &errMsg)
287 {
288 MEDIA_LOGE("audio render error: %{public}s", errMsg.c_str());
289 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(basesink);
290 GST_ELEMENT_ERROR(sink, STREAM, FAILED, (NULL), ("audio render error: %s", errMsg.c_str()));
291 }
292
gst_audio_server_sink_segment_callback(GstBaseSink * basesink)293 static void gst_audio_server_sink_segment_callback(GstBaseSink *basesink)
294 {
295 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(basesink);
296 g_signal_emit_by_name(sink, "segment-updated");
297 }
298
gst_audio_server_sink_service_died_callback(GstBaseSink * basesink)299 static void gst_audio_server_sink_service_died_callback(GstBaseSink *basesink)
300 {
301 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(basesink);
302 g_signal_emit_by_name(sink, "audio-service-died");
303 }
304
gst_audio_server_sink_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)305 static void gst_audio_server_sink_set_property(GObject *object, guint prop_id,
306 const GValue *value, GParamSpec *pspec)
307 {
308 MEDIA_LOGI("audiorender: gst_audio_server_sink_set_property");
309 MediaTrace trace("Audio::gst_audio_server_sink_set_property");
310 g_return_if_fail(object != nullptr && value != nullptr);
311 (void)pspec;
312 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(object);
313 g_return_if_fail(sink != nullptr);
314 switch (prop_id) {
315 case PROP_VOLUME:
316 if (gst_audio_server_sink_set_volume(sink, g_value_get_float(value))) {
317 GST_INFO_OBJECT(sink, "set volume success!");
318 g_object_notify(G_OBJECT(sink), "volume");
319 }
320 break;
321 case PROP_AUDIO_RENDERER_DESC:
322 sink->renderer_desc = g_value_get_int(value);
323 break;
324 case PROP_APP_UID:
325 sink->appuid = g_value_get_int(value);
326 GST_INFO_OBJECT(sink, "set app uid success!");
327 g_object_notify(G_OBJECT(sink), "app-uid");
328 break;
329 case PROP_APP_PID:
330 sink->apppid = g_value_get_int(value);
331 GST_INFO_OBJECT(sink, "set app uid success!");
332 g_object_notify(G_OBJECT(sink), "app-pid");
333 break;
334 case PROP_APP_TOKEN_ID:
335 sink->apptokenid = g_value_get_uint(value);
336 GST_INFO_OBJECT(sink, "set app token id success!");
337 g_object_notify(G_OBJECT(sink), "app-token-id");
338 break;
339 case PROP_AUDIO_RENDERER_FLAG:
340 sink->renderer_flag = g_value_get_int(value);
341 break;
342 case PROP_AUDIO_INTERRUPT_MODE:
343 g_return_if_fail(sink->audio_sink != nullptr);
344 sink->audio_sink->SetAudioInterruptMode(g_value_get_int(value));
345 break;
346 case PROP_ENABLE_OPT_RENDER_DELAY:
347 sink->enable_opt_render_delay = g_value_get_boolean(value);
348 break;
349 case PROP_AUDIO_EFFECT_MODE:
350 g_return_if_fail(sink->audio_sink != nullptr);
351 (void)sink->audio_sink->SetAudioEffectMode(g_value_get_int(value));
352 break;
353 default:
354 break;
355 }
356 }
357
gst_audio_server_sink_get_delay(GstAudioServerSink * sink,GValue * value)358 static void gst_audio_server_sink_get_delay(GstAudioServerSink *sink, GValue *value)
359 {
360 g_return_if_fail(sink != nullptr);
361 g_return_if_fail(sink->audio_sink != nullptr);
362 g_mutex_lock(&sink->render_lock);
363 int32_t mode;
364 (void)sink->audio_sink->GetAudioEffectMode(mode);
365 sink->delay_time = mode == OHOS::AudioStandard::AudioEffectMode::EFFECT_DEFAULT ?
366 AUDIO_EFFECT_DEFAULT_RENDER_DELAY : AUDIO_EFFECT_NONE_RENDER_DELAY;
367 uint32_t delay_time = sink->enable_opt_render_delay ? sink->delay_time : 0;
368 g_value_set_uint(value, delay_time);
369 g_mutex_unlock(&sink->render_lock);
370 }
371
gst_audio_server_sink_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)372 static void gst_audio_server_sink_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
373 {
374 MediaTrace trace("Audio::gst_audio_server_sink_get_property");
375 gint mode = -1;
376 g_return_if_fail(object != nullptr);
377 g_return_if_fail(value != nullptr);
378 (void)pspec;
379 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(object);
380 g_return_if_fail(sink != nullptr);
381 switch (prop_id) {
382 case PROP_BITS_PER_SAMPLE:
383 g_value_set_uint(value, sink->bits_per_sample);
384 break;
385 case PROP_CHANNELS:
386 g_value_set_uint(value, sink->channels);
387 break;
388 case PROP_SAMPLE_RATE:
389 g_value_set_uint(value, sink->sample_rate);
390 break;
391 case PROP_VOLUME:
392 if (sink->audio_sink != nullptr) {
393 (void)sink->audio_sink->GetVolume(sink->volume);
394 }
395 g_value_set_float(value, sink->volume);
396 break;
397 case PROP_MAX_VOLUME:
398 g_value_set_float(value, sink->max_volume);
399 break;
400 case PROP_MIN_VOLUME:
401 g_value_set_float(value, sink->min_volume);
402 break;
403 case PROP_LAST_RENDER_PTS:
404 g_mutex_lock(&sink->render_lock);
405 g_value_set_uint64(value, static_cast<guint64>(sink->last_render_pts));
406 g_mutex_unlock(&sink->render_lock);
407 break;
408 case PROP_LAST_RUNNING_TIME_DIFF:
409 g_mutex_lock(&sink->render_lock);
410 g_value_set_int64(value, static_cast<gint64>(sink->last_running_time_diff));
411 g_mutex_unlock(&sink->render_lock);
412 break;
413 case PROP_AUDIO_EFFECT_MODE:
414 g_return_if_fail(sink->audio_sink != nullptr);
415 (void)sink->audio_sink->GetAudioEffectMode(mode);
416 g_value_set_int(value, mode);
417 break;
418 case PROP_DELAY_TIME:
419 gst_audio_server_sink_get_delay(sink, value);
420 break;
421 default:
422 break;
423 }
424 }
425
gst_audio_server_sink_get_caps(GstBaseSink * basesink,GstCaps * caps)426 static GstCaps *gst_audio_server_sink_get_caps(GstBaseSink *basesink, GstCaps *caps)
427 {
428 MediaTrace trace("Audio::gst_audio_server_sink_get_caps");
429 (void)caps;
430 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(basesink);
431 g_return_val_if_fail(sink != nullptr, FALSE);
432 g_return_val_if_fail(sink->audio_sink != nullptr, FALSE);
433 return sink->audio_sink->GetCaps();
434 }
435
gst_audio_server_sink_update_reach_time(GstBaseSink * basesink,GstClockTime reach_time,gboolean * need_drop_this_buffer)436 static GstClockTime gst_audio_server_sink_update_reach_time(GstBaseSink *basesink, GstClockTime reach_time,
437 gboolean *need_drop_this_buffer)
438 {
439 MediaTrace trace("Audio::gst_audio_server_sink_update_reach_time");
440 (void)need_drop_this_buffer;
441 g_return_val_if_fail(basesink != nullptr, reach_time);
442 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(basesink);
443 GstClockTime base_time = gst_element_get_base_time(GST_ELEMENT(basesink)); // get base time
444 GstClockTime cur_clock_time = gst_clock_get_time(GST_ELEMENT_CLOCK(basesink)); // get current clock time
445 if (!GST_CLOCK_TIME_IS_VALID(base_time) || !GST_CLOCK_TIME_IS_VALID(cur_clock_time)) {
446 return reach_time;
447 }
448 if (cur_clock_time < base_time) {
449 return reach_time;
450 }
451 GstClockTime cur_running_time = cur_clock_time - base_time; // get running time
452 g_mutex_lock(&sink->render_lock);
453 sink->last_running_time_diff =
454 static_cast<GstClockTimeDiff>(cur_running_time) - static_cast<GstClockTimeDiff>(reach_time);
455 g_mutex_unlock(&sink->render_lock);
456
457 return GST_BASE_SINK_CLASS(parent_class)->update_reach_time(basesink, reach_time, need_drop_this_buffer);
458 }
459
gst_audio_server_sink_set_caps(GstBaseSink * basesink,GstCaps * caps)460 static gboolean gst_audio_server_sink_set_caps(GstBaseSink *basesink, GstCaps *caps)
461 {
462 MediaTrace trace("Audio::gst_audio_server_sink_set_caps");
463 g_return_val_if_fail(basesink != nullptr, FALSE);
464 g_return_val_if_fail(caps != nullptr, FALSE);
465 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(basesink);
466 g_return_val_if_fail(sink != nullptr, FALSE);
467 g_return_val_if_fail(sink->audio_sink != nullptr, FALSE);
468
469 GstStructure *structure = gst_caps_get_structure(caps, 0);
470 g_return_val_if_fail(structure != nullptr, FALSE);
471 gint channels = 0;
472 gint rate = 0;
473 if (!gst_structure_get_int(structure, "rate", &rate) || !gst_structure_get_int(structure, "channels", &channels)) {
474 GST_ERROR_OBJECT(basesink, "Incomplete caps");
475 return FALSE;
476 }
477 g_return_val_if_fail(channels > 0 && rate > 0, FALSE);
478 sink->sample_rate = static_cast<uint32_t>(rate);
479 sink->channels = static_cast<uint32_t>(channels);
480 g_return_val_if_fail(sink->audio_sink->SetParameters(sink->bits_per_sample, sink->channels,
481 sink->sample_rate) == MSERR_OK, FALSE);
482 g_return_val_if_fail(sink->audio_sink->SetVolume(sink->volume) == MSERR_OK, FALSE);
483 g_return_val_if_fail(sink->audio_sink->GetParameters(sink->bits_per_sample,
484 sink->channels, sink->sample_rate) == MSERR_OK, FALSE);
485 g_return_val_if_fail(sink->audio_sink->GetMinimumBufferSize(sink->min_buffer_size) == MSERR_OK, FALSE);
486 g_return_val_if_fail(sink->audio_sink->GetMinimumFrameCount(sink->min_frame_count) == MSERR_OK, FALSE);
487
488 if (sink->pre_power_on) {
489 g_return_val_if_fail(sink->audio_sink->Pause() == MSERR_OK, FALSE);
490 sink->pre_power_on = FALSE;
491 }
492
493 return TRUE;
494 }
495
gst_audio_server_sink_handle_segment_event(GstBaseSink * basesink,GstEvent * event)496 static gboolean gst_audio_server_sink_handle_segment_event(GstBaseSink *basesink, GstEvent *event)
497 {
498 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(basesink);
499 g_mutex_lock(&sink->render_lock);
500 gboolean ret = GST_BASE_SINK_CLASS(parent_class)->event(basesink, event);
501 sink->frame_after_segment = TRUE;
502 gst_audio_server_sink_segment_callback(basesink);
503 g_mutex_unlock(&sink->render_lock);
504 return ret;
505 }
506
gst_audio_server_sink_event(GstBaseSink * basesink,GstEvent * event)507 static gboolean gst_audio_server_sink_event(GstBaseSink *basesink, GstEvent *event)
508 {
509 g_return_val_if_fail(basesink != nullptr, FALSE);
510 g_return_val_if_fail(event != nullptr, FALSE);
511 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(basesink);
512 g_return_val_if_fail(sink != nullptr, FALSE);
513 switch (GST_EVENT_TYPE(event)) {
514 case GST_EVENT_EOS:
515 if (sink->audio_sink == nullptr) {
516 break;
517 }
518 // close audio/video sync
519 g_mutex_lock(&sink->render_lock);
520 sink->last_running_time_diff = 0;
521 g_mutex_unlock(&sink->render_lock);
522 if (sink->audio_sink->Drain() != MSERR_OK) {
523 GST_ERROR_OBJECT(basesink, "fail to call Drain when handling EOS event");
524 }
525 break;
526 case GST_EVENT_SEGMENT:
527 return gst_audio_server_sink_handle_segment_event(basesink, event);
528 case GST_EVENT_FLUSH_START:
529 basesink->stream_group_done = FALSE;
530 gst_audio_server_sink_clear_cache_buffer(sink);
531 if (sink->audio_sink == nullptr) {
532 break;
533 }
534 (void)sink->audio_sink->Pause();
535 (void)sink->audio_sink->Flush();
536 GST_DEBUG_OBJECT(basesink, "received FLUSH_START");
537 break;
538 case GST_EVENT_FLUSH_STOP:
539 GST_DEBUG_OBJECT(basesink, "received FLUSH_STOP");
540 break;
541 case GST_EVENT_STREAM_GROUP_DONE:
542 basesink->stream_group_done = TRUE;
543 GST_DEBUG_OBJECT(basesink, "received STREAM_GROUP_DONE, set stream_group_done TRUE");
544 if (basesink->need_preroll) {
545 /* may async start to change state, preroll STREAM_GROUP_DONE to async done */
546 gst_base_sink_do_preroll (basesink, GST_MINI_OBJECT_CAST(event));
547 }
548 break;
549 case GST_EVENT_STREAM_START:
550 basesink->stream_group_done = FALSE;
551 GST_DEBUG_OBJECT(basesink, "received STREAM_START, set stream_group_done FALSE");
552 break;
553 default:
554 break;
555 }
556 return GST_BASE_SINK_CLASS(parent_class)->event(basesink, event);
557 }
558
gst_audio_server_sink_start(GstBaseSink * basesink)559 static gboolean gst_audio_server_sink_start(GstBaseSink *basesink)
560 {
561 MediaTrace trace("Audio::gst_audio_server_sink_start");
562 g_return_val_if_fail(basesink != nullptr, FALSE);
563 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(basesink);
564 MEDIA_LOGI("uid: %{public}d, pid: %{public}d, tokenid: %{public}u", sink->appuid, sink->apppid, sink->apptokenid);
565 g_return_val_if_fail(sink != nullptr, FALSE);
566 sink->audio_sink = OHOS::Media::AudioSinkFactory::CreateAudioSink(basesink);
567 g_return_val_if_fail(sink->audio_sink != nullptr, FALSE);
568 g_return_val_if_fail(sink->audio_sink->SetRendererInfo(sink->renderer_desc,
569 sink->renderer_flag) == MSERR_OK, FALSE);
570 g_return_val_if_fail(sink->audio_sink->Prepare(sink->appuid, sink->apppid, sink->apptokenid) == MSERR_OK, FALSE);
571 sink->audio_sink->SetAudioSinkCb(gst_audio_server_sink_interrupt_callback,
572 gst_audio_server_sink_state_callback,
573 gst_audio_server_sink_error_callback,
574 gst_audio_server_sink_service_died_callback);
575 g_return_val_if_fail(sink->audio_sink->GetMaxVolume(sink->max_volume) == MSERR_OK, FALSE);
576 g_return_val_if_fail(sink->audio_sink->GetMinVolume(sink->min_volume) == MSERR_OK, FALSE);
577 g_return_val_if_fail(sink->audio_sink->Start() == MSERR_OK, FALSE);
578 sink->pre_power_on = TRUE;
579 return TRUE;
580 }
581
gst_audio_server_sink_clear_cache_buffer(GstAudioServerSink * sink)582 static void gst_audio_server_sink_clear_cache_buffer(GstAudioServerSink *sink)
583 {
584 std::unique_lock<std::mutex> lock(sink->mutex_);
585 if (sink->pause_cache_buffer != nullptr) {
586 gst_buffer_unref(sink->pause_cache_buffer);
587 sink->pause_cache_buffer = nullptr;
588 }
589 }
590
gst_audio_server_sink_stop(GstBaseSink * basesink)591 static gboolean gst_audio_server_sink_stop(GstBaseSink *basesink)
592 {
593 MediaTrace trace("Audio::gst_audio_server_sink_stop");
594 g_return_val_if_fail(basesink != nullptr, FALSE);
595 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(basesink);
596 g_return_val_if_fail(sink != nullptr, FALSE);
597 g_return_val_if_fail(sink->audio_sink != nullptr, FALSE);
598 g_return_val_if_fail(sink->audio_sink->Stop() == MSERR_OK, FALSE);
599 g_return_val_if_fail(sink->audio_sink->Release() == MSERR_OK, FALSE);
600 sink->audio_sink = nullptr;
601
602 return TRUE;
603 }
604
gst_audio_server_sink_change_state(GstElement * element,GstStateChange transition)605 static GstStateChangeReturn gst_audio_server_sink_change_state(GstElement *element, GstStateChange transition)
606 {
607 g_return_val_if_fail(element != nullptr, GST_STATE_CHANGE_FAILURE);
608 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(element);
609 g_return_val_if_fail(sink != nullptr, GST_STATE_CHANGE_FAILURE);
610 GstBaseSink *basesink = GST_BASE_SINK(element);
611 g_return_val_if_fail(basesink != nullptr, GST_STATE_CHANGE_FAILURE);
612
613 switch (transition) {
614 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
615 MEDIA_LOGI("GST_STATE_CHANGE_PAUSED_TO_PLAYING");
616 g_return_val_if_fail(sink->audio_sink != nullptr, GST_STATE_CHANGE_FAILURE);
617 if (sink->audio_sink->Start() == MSERR_OK) {
618 sink->start_first_render = TRUE;
619 }
620
621 if (sink->pause_cache_buffer != nullptr) {
622 GST_INFO_OBJECT(basesink, "pause to play");
623 if (gst_audio_server_sink_render(basesink, sink->pause_cache_buffer) != GST_FLOW_OK) {
624 GST_ERROR_OBJECT(sink, "audio sink gst_audio_server_sink_render failed!");
625 GST_ELEMENT_ERROR(sink, STREAM, FAILED,
626 ("audio sink gst_audio_server_sink_render failed!"), (NULL));
627 return GST_STATE_CHANGE_FAILURE;
628 }
629 gst_buffer_unref(sink->pause_cache_buffer);
630 sink->pause_cache_buffer = nullptr;
631 }
632 break;
633 default:
634 break;
635 }
636 GstStateChangeReturn ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
637
638 switch (transition) {
639 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
640 MEDIA_LOGI("GST_STATE_CHANGE_PLAYING_TO_PAUSED");
641 {
642 std::unique_lock<std::mutex> lock(sink->mutex_);
643 g_return_val_if_fail(sink->audio_sink != nullptr, GST_STATE_CHANGE_FAILURE);
644 /**
645 * When executing release task, call stop first.
646 * if report pause fail message, it will abort stop task. Then,
647 * release task will free resources. Due to stop failed, the plugin
648 * not stopped will use destoryed mutex. It will lead to service crash.
649 */
650 (void)sink->audio_sink->Pause();
651 }
652 break;
653 case GST_STATE_CHANGE_PAUSED_TO_READY:
654 MEDIA_LOGD("GST_STATE_CHANGE_PAUSED_TO_READY");
655 gst_audio_server_sink_clear_cache_buffer(sink);
656 g_mutex_lock(&sink->render_lock);
657 sink->last_render_pts = 0;
658 sink->last_running_time_diff = 0;
659 g_mutex_unlock(&sink->render_lock);
660 break;
661 default:
662 break;
663 }
664
665 return ret;
666 }
667
gst_audio_server_sink_get_latency(GstAudioServerSink * sink,const GstBuffer * buffer)668 static void gst_audio_server_sink_get_latency(GstAudioServerSink *sink, const GstBuffer *buffer)
669 {
670 MediaTrace trace("Audio::gst_audio_server_sink_get_latency");
671 g_mutex_lock(&sink->render_lock);
672 if (sink->frame_after_segment) {
673 sink->frame_after_segment = FALSE;
674 uint64_t latency = 0;
675 GST_INFO_OBJECT(sink, "the first audio frame after segment has been sent to audio server");
676 if (sink->audio_sink->GetLatency(latency) != MSERR_OK) {
677 GST_INFO_OBJECT(sink, "fail to get latency");
678 } else {
679 GST_INFO_OBJECT(sink, "frame render latency is (%" PRIu64 ")", latency);
680 }
681 }
682 if (GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) {
683 sink->last_render_pts = GST_BUFFER_PTS(buffer);
684 }
685 g_mutex_unlock(&sink->render_lock);
686 }
687
gst_audio_server_sink_render(GstBaseSink * basesink,GstBuffer * buffer)688 static GstFlowReturn gst_audio_server_sink_render(GstBaseSink *basesink, GstBuffer *buffer)
689 {
690 pthread_setname_np(pthread_self(), "audioSinkRender");
691 MediaTrace trace("Audio::gst_audio_server_sink_render");
692 g_return_val_if_fail(basesink != nullptr, GST_FLOW_ERROR);
693 g_return_val_if_fail(buffer != nullptr, GST_FLOW_ERROR);
694 if (gst_buffer_get_size(buffer) == 0) {
695 GST_INFO_OBJECT(basesink, "gst_buffer_get_size = 0");
696 return GST_FLOW_OK;
697 }
698 GstAudioServerSink *sink = GST_AUDIO_SERVER_SINK(basesink);
699 g_return_val_if_fail(sink != nullptr, GST_FLOW_ERROR);
700 g_return_val_if_fail(sink->audio_sink != nullptr, GST_FLOW_ERROR);
701
702 {
703 std::unique_lock<std::mutex> lock(sink->mutex_);
704 if (!sink->audio_sink->Writeable()) {
705 if (sink->pause_cache_buffer == nullptr) {
706 sink->pause_cache_buffer = gst_buffer_ref(buffer);
707 g_return_val_if_fail(sink->pause_cache_buffer != nullptr, GST_FLOW_ERROR);
708 GST_INFO_OBJECT(basesink, "cache buffer for pause state");
709 return GST_FLOW_OK;
710 } else {
711 GST_ERROR_OBJECT(basesink, "cache buffer is not null");
712 }
713 }
714
715 if (sink->start_first_render) {
716 // 1st write prebuf and trigger audio write rebuf
717 // 2nd flush audio invalid prebuf and 3rd write valid buf
718 const int32_t bufSize = 1024; // default 1024
719 std::unique_ptr<uint8_t[]> preBuf = std::make_unique<uint8_t[]>(bufSize);
720 (void)memset_s(preBuf.get(), bufSize, 0, bufSize);
721 (void)sink->audio_sink->Write(preBuf.get(), bufSize);
722 (void)sink->audio_sink->Flush();
723 sink->start_first_render = FALSE;
724 }
725
726 GstMapInfo map;
727 if (gst_buffer_map(buffer, &map, GST_MAP_READ) != TRUE) {
728 GST_ERROR_OBJECT(basesink, "unknown error happened during gst_buffer_map");
729 return GST_FLOW_ERROR;
730 }
731 if (sink->audio_sink->Write(map.data, map.size) != MSERR_OK) {
732 GST_ERROR_OBJECT(basesink, "unknown error happened during Write");
733 gst_buffer_unmap(buffer, &map);
734 return GST_FLOW_ERROR;
735 }
736 gst_buffer_unmap(buffer, &map);
737 }
738
739 gst_audio_server_sink_get_latency(sink, buffer);
740 return GST_FLOW_OK;
741 }
742
plugin_init(GstPlugin * plugin)743 static gboolean plugin_init(GstPlugin *plugin)
744 {
745 g_return_val_if_fail(plugin != nullptr, FALSE);
746 gboolean ret = gst_element_register(plugin, "audioserversink", GST_RANK_PRIMARY, GST_TYPE_AUDIO_SERVER_SINK);
747 return ret;
748 }
749
750 GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
751 GST_VERSION_MINOR,
752 _audio_server_sink,
753 "GStreamer Audio Server Sink",
754 plugin_init,
755 PACKAGE_VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
756