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