• 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 "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