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