static void _bus_handler (GstBus * bus, GstMessage * message, GstValidatePipelineMonitor * monitor) { GError *err = NULL; gchar *debug = NULL; const GstStructure *details = NULL; gint error_flow = GST_FLOW_OK; switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ERROR: gst_message_parse_error (message, &err, &debug); gst_message_parse_error_details (message, &details); if (g_error_matches (err, GST_CORE_ERROR, GST_CORE_ERROR_MISSING_PLUGIN)) { GST_VALIDATE_REPORT (monitor, MISSING_PLUGIN, "Error: %s -- Debug message: %s", err->message, debug); } else if ((g_error_matches (err, GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED) && details && gst_structure_get_int (details, "flow-return", &error_flow) && error_flow == GST_FLOW_NOT_NEGOTIATED) || g_error_matches (err, GST_STREAM_ERROR, GST_STREAM_ERROR_FORMAT)) { gchar *report = _generate_not_negotiated_error_report (message); GST_VALIDATE_REPORT (monitor, NOT_NEGOTIATED, "%s", report); g_free (report); } else { GST_VALIDATE_REPORT (monitor, ERROR_ON_BUS, "Got error: %s -- Debug message: %s", err->message, debug); } GST_VALIDATE_MONITOR_LOCK (monitor); monitor->got_error = TRUE; GST_VALIDATE_MONITOR_UNLOCK (monitor); g_error_free (err); g_free (debug); break; case GST_MESSAGE_WARNING: gst_message_parse_warning (message, &err, &debug); GST_VALIDATE_REPORT (monitor, WARNING_ON_BUS, "Got warning: %s -- Debug message: %s", err->message, debug); g_error_free (err); g_free (debug); break; case GST_MESSAGE_STATE_CHANGED: { if (GST_MESSAGE_SRC (message) == GST_VALIDATE_MONITOR (monitor)->target) { GstState oldstate, newstate, pending; gst_message_parse_state_changed (message, &oldstate, &newstate, &pending); if (oldstate == GST_STATE_READY && newstate == GST_STATE_PAUSED) { monitor->print_pos_srcid = g_timeout_add (PRINT_POSITION_TIMEOUT, (GSourceFunc) print_position, monitor); } else if (oldstate >= GST_STATE_PAUSED && newstate <= GST_STATE_READY) { if (monitor->print_pos_srcid && g_source_remove (monitor->print_pos_srcid)) monitor->print_pos_srcid = 0; monitor->got_error = FALSE; } } break; } case GST_MESSAGE_BUFFERING: { JsonBuilder *jbuilder = json_builder_new (); GstBufferingMode mode; gint percent; gst_message_parse_buffering (message, &percent); gst_message_parse_buffering_stats (message, &mode, NULL, NULL, NULL); json_builder_begin_object (jbuilder); json_builder_set_member_name (jbuilder, "type"); json_builder_add_string_value (jbuilder, "buffering"); json_builder_set_member_name (jbuilder, "state"); if (percent == 100) { /* a 100% message means buffering is done */ gst_validate_printf (NULL, "\nDone buffering\n"); json_builder_add_string_value (jbuilder, "done"); if (monitor->buffering) { monitor->print_pos_srcid = g_timeout_add (PRINT_POSITION_TIMEOUT, (GSourceFunc) print_position, monitor); monitor->buffering = FALSE; } } else { /* buffering... */ if (!monitor->buffering) { monitor->buffering = TRUE; gst_validate_printf (NULL, "\nStart buffering\n"); json_builder_add_string_value (jbuilder, "started"); if (monitor->print_pos_srcid && g_source_remove (monitor->print_pos_srcid)) { monitor->print_pos_srcid = 0; } } else { json_builder_add_string_value (jbuilder, "progress"); } gst_validate_printf (NULL, "%s %d%% \r", "Buffering...", percent); } json_builder_set_member_name (jbuilder, "position"); json_builder_add_int_value (jbuilder, percent); json_builder_end_object (jbuilder); gst_validate_send (json_builder_get_root (jbuilder)); g_object_unref (jbuilder); break; } case GST_MESSAGE_STREAM_COLLECTION: { GstStreamCollection *collection = NULL; gst_message_parse_stream_collection (message, &collection); gst_object_replace ((GstObject **) & monitor->stream_collection, (GstObject *) collection); gst_object_unref (collection); break; } case GST_MESSAGE_STREAMS_SELECTED: { guint i; if (monitor->streams_selected) { g_list_free_full (monitor->streams_selected, gst_object_unref); monitor->streams_selected = NULL; } for (i = 0; i < gst_message_streams_selected_get_size (message); i++) { GstStream *stream = gst_message_streams_selected_get_stream (message, i); monitor->streams_selected = g_list_append (monitor->streams_selected, stream); } break; } default: break; } }
int BufferingMessage::averageOutputRate() const { gint a; gst_message_parse_buffering_stats(object<GstMessage>(), NULL, NULL, &a, NULL); return a; }
qint64 BufferingMessage::bufferingTimeLeft() const { gint64 a; gst_message_parse_buffering_stats(object<GstMessage>(), NULL, NULL, NULL, &a); return a; }
BufferingMode BufferingMessage::mode() const { GstBufferingMode m; gst_message_parse_buffering_stats(object<GstMessage>(), &m, NULL, NULL, NULL); return static_cast<BufferingMode>(m); }
static gboolean master_bus_msg (GstBus * bus, GstMessage * msg, gpointer data) { GstPipeline *pipeline = data; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_ERROR:{ GError *err; gchar *dbg; gst_message_parse_error (msg, &err, &dbg); g_printerr ("MASTER: ERROR: %s\n", err->message); if (dbg != NULL) g_printerr ("MASTER: ERROR debug information: %s\n", dbg); g_error_free (err); g_free (dbg); GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "ipc.master.error"); g_main_loop_quit (loop); break; } case GST_MESSAGE_WARNING:{ GError *err; gchar *dbg; gst_message_parse_warning (msg, &err, &dbg); g_printerr ("MASTER: WARNING: %s\n", err->message); if (dbg != NULL) g_printerr ("MASTER: WARNING debug information: %s\n", dbg); g_error_free (err); g_free (dbg); GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "ipc.master.warning"); break; } case GST_MESSAGE_ASYNC_DONE: GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "ipc.master.async-done"); break; case GST_MESSAGE_EOS: g_print ("EOS on master\n"); gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); g_main_loop_quit (loop); break; case GST_MESSAGE_BUFFERING:{ gint percent; GstBufferingMode bufmode; if (!buffering) g_print ("\n"); gst_message_parse_buffering (msg, &percent); g_print ("%s %d%% \r", "Buffering...", percent); gst_message_parse_buffering_stats (msg, &bufmode, NULL, NULL, NULL); /* no state management needed for live pipelines */ if (bufmode != GST_BUFFERING_LIVE) { if (percent == 100) { /* a 100% message means buffering is done */ if (buffering) { buffering = FALSE; gst_element_set_state (GST_ELEMENT (pipeline), desired_state); g_print ("\n%s\n", gst_element_state_get_name (desired_state)); } } else { /* buffering... */ if (!buffering) { gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED); buffering = TRUE; } } } break; } case GST_MESSAGE_CLOCK_LOST:{ g_print ("Clock lost, selecting a new one\n"); gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED); gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); break; } case GST_MESSAGE_LATENCY: { gst_bin_recalculate_latency (GST_BIN (pipeline)); break; } case GST_MESSAGE_REQUEST_STATE:{ GstState state; gchar *name; name = gst_object_get_path_string (GST_MESSAGE_SRC (msg)); gst_message_parse_request_state (msg, &state); GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline), GST_DEBUG_GRAPH_SHOW_VERBOSE, "ipc.slave.reqstate"); g_print ("Setting state to %s as requested by %s...\n", gst_element_state_get_name (state), name); gst_element_set_state (GST_ELEMENT (pipeline), state); g_free (name); break; } case GST_MESSAGE_ELEMENT: { GstNavigationMessageType mtype = gst_navigation_message_get_type (msg); if (mtype == GST_NAVIGATION_MESSAGE_EVENT) { GstEvent *ev = NULL; if (gst_navigation_message_parse_event (msg, &ev)) { GstNavigationEventType e_type = gst_navigation_event_get_type (ev); switch (e_type) { case GST_NAVIGATION_EVENT_KEY_PRESS: { const gchar *key; if (gst_navigation_event_parse_key_event (ev, &key)) { GST_INFO ("Key press: %s", key); if (strcmp (key, "Left") == 0) key = GST_PLAY_KB_ARROW_LEFT; else if (strcmp (key, "Right") == 0) key = GST_PLAY_KB_ARROW_RIGHT; else if (strcmp (key, "Up") == 0) key = GST_PLAY_KB_ARROW_UP; else if (strcmp (key, "Down") == 0) key = GST_PLAY_KB_ARROW_DOWN; else if (strcmp (key, "space") == 0) key = " "; else if (strlen (key) > 1) break; keyboard_cb (key, GST_ELEMENT (pipeline)); } break; } case GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS: { gint button; if (gst_navigation_event_parse_mouse_button_event (ev, &button, NULL, NULL)) { if (button == 4) { /* wheel up */ relative_seek (GST_ELEMENT (pipeline), +0.08); } else if (button == 5) { /* wheel down */ relative_seek (GST_ELEMENT (pipeline), -0.01); } } break; } default: break; } } if (ev) gst_event_unref (ev); } break; } default: break; } return TRUE; }
void eServiceMP3::gstBusCall(GstMessage *msg) { if (!msg) return; gchar *sourceName; GstObject *source; source = GST_MESSAGE_SRC(msg); if (!GST_IS_OBJECT(source)) return; sourceName = gst_object_get_name(source); #if 0 gchar *string; if (gst_message_get_structure(msg)) string = gst_structure_to_string(gst_message_get_structure(msg)); else string = g_strdup(GST_MESSAGE_TYPE_NAME(msg)); eDebug("eTsRemoteSource::gst_message from %s: %s", sourceName, string); g_free(string); #endif switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: m_event((iPlayableService*)this, evEOF); break; case GST_MESSAGE_STATE_CHANGED: { if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin)) break; GstState old_state, new_state; gst_message_parse_state_changed(msg, &old_state, &new_state, NULL); if(old_state == new_state) break; eDebug("eServiceMP3::state transition %s -> %s", gst_element_state_get_name(old_state), gst_element_state_get_name(new_state)); GstStateChange transition = (GstStateChange)GST_STATE_TRANSITION(old_state, new_state); switch(transition) { case GST_STATE_CHANGE_NULL_TO_READY: { } break; case GST_STATE_CHANGE_READY_TO_PAUSED: { GstElement *subsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); if (subsink) { #ifdef GSTREAMER_SUBTITLE_SYNC_MODE_BUG /* * HACK: disable sync mode for now, gstreamer suffers from a bug causing sparse streams to loose sync, after pause/resume / skip * see: https://bugzilla.gnome.org/show_bug.cgi?id=619434 * Sideeffect of using sync=false is that we receive subtitle buffers (far) ahead of their * display time. * Not too far ahead for subtitles contained in the media container. * But for external srt files, we could receive all subtitles at once. * And not just once, but after each pause/resume / skip. * So as soon as gstreamer has been fixed to keep sync in sparse streams, sync needs to be re-enabled. */ g_object_set (G_OBJECT (subsink), "sync", FALSE, NULL); #endif #if 0 /* we should not use ts-offset to sync with the decoder time, we have to do our own decoder timekeeping */ g_object_set (G_OBJECT (subsink), "ts-offset", -2L * GST_SECOND, NULL); /* late buffers probably will not occur very often */ g_object_set (G_OBJECT (subsink), "max-lateness", 0L, NULL); /* avoid prerolling (it might not be a good idea to preroll a sparse stream) */ g_object_set (G_OBJECT (subsink), "async", TRUE, NULL); #endif eDebug("eServiceMP3::subsink properties set!"); gst_object_unref(subsink); } setAC3Delay(ac3_delay); setPCMDelay(pcm_delay); } break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: { if ( m_sourceinfo.is_streaming && m_streamingsrc_timeout ) m_streamingsrc_timeout->stop(); } break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED: { } break; case GST_STATE_CHANGE_PAUSED_TO_READY: { } break; case GST_STATE_CHANGE_READY_TO_NULL: { } break; } break; } case GST_MESSAGE_ERROR: { gchar *debug; GError *err; gst_message_parse_error (msg, &err, &debug); g_free (debug); eWarning("Gstreamer error: %s (%i) from %s", err->message, err->code, sourceName ); if ( err->domain == GST_STREAM_ERROR ) { if ( err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND ) { if ( g_strrstr(sourceName, "videosink") ) m_event((iPlayableService*)this, evUser+11); else if ( g_strrstr(sourceName, "audiosink") ) m_event((iPlayableService*)this, evUser+10); } } g_error_free(err); break; } case GST_MESSAGE_INFO: { gchar *debug; GError *inf; gst_message_parse_info (msg, &inf, &debug); g_free (debug); if ( inf->domain == GST_STREAM_ERROR && inf->code == GST_STREAM_ERROR_DECODE ) { if ( g_strrstr(sourceName, "videosink") ) m_event((iPlayableService*)this, evUser+14); } g_error_free(inf); break; } case GST_MESSAGE_TAG: { GstTagList *tags, *result; gst_message_parse_tag(msg, &tags); result = gst_tag_list_merge(m_stream_tags, tags, GST_TAG_MERGE_REPLACE); if (result) { if (m_stream_tags) gst_tag_list_free(m_stream_tags); m_stream_tags = result; } const GValue *gv_image = gst_tag_list_get_value_index(tags, GST_TAG_IMAGE, 0); if ( gv_image ) { GstBuffer *buf_image; buf_image = gst_value_get_buffer (gv_image); int fd = open("/tmp/.id3coverart", O_CREAT|O_WRONLY|O_TRUNC, 0644); int ret = write(fd, GST_BUFFER_DATA(buf_image), GST_BUFFER_SIZE(buf_image)); close(fd); eDebug("eServiceMP3::/tmp/.id3coverart %d bytes written ", ret); m_event((iPlayableService*)this, evUser+13); } gst_tag_list_free(tags); m_event((iPlayableService*)this, evUpdatedInfo); break; } case GST_MESSAGE_ASYNC_DONE: { if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin)) break; GstTagList *tags; gint i, active_idx, n_video = 0, n_audio = 0, n_text = 0; g_object_get (m_gst_playbin, "n-video", &n_video, NULL); g_object_get (m_gst_playbin, "n-audio", &n_audio, NULL); g_object_get (m_gst_playbin, "n-text", &n_text, NULL); eDebug("eServiceMP3::async-done - %d video, %d audio, %d subtitle", n_video, n_audio, n_text); if ( n_video + n_audio <= 0 ) stop(); active_idx = 0; m_audioStreams.clear(); m_subtitleStreams.clear(); for (i = 0; i < n_audio; i++) { audioStream audio; gchar *g_codec, *g_lang; GstPad* pad = 0; g_signal_emit_by_name (m_gst_playbin, "get-audio-pad", i, &pad); GstCaps* caps = gst_pad_get_negotiated_caps(pad); if (!caps) continue; GstStructure* str = gst_caps_get_structure(caps, 0); const gchar *g_type = gst_structure_get_name(str); eDebug("AUDIO STRUCT=%s", g_type); audio.type = gstCheckAudioPad(str); g_codec = g_strdup(g_type); g_lang = g_strdup_printf ("und"); g_signal_emit_by_name (m_gst_playbin, "get-audio-tags", i, &tags); if ( tags && gst_is_tag_list(tags) ) { gst_tag_list_get_string(tags, GST_TAG_AUDIO_CODEC, &g_codec); gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); gst_tag_list_free(tags); } audio.language_code = std::string(g_lang); audio.codec = std::string(g_codec); eDebug("eServiceMP3::audio stream=%i codec=%s language=%s", i, g_codec, g_lang); m_audioStreams.push_back(audio); g_free (g_lang); g_free (g_codec); gst_caps_unref(caps); } for (i = 0; i < n_text; i++) { gchar *g_codec = NULL, *g_lang = NULL; g_signal_emit_by_name (m_gst_playbin, "get-text-tags", i, &tags); subtitleStream subs; g_lang = g_strdup_printf ("und"); if ( tags && gst_is_tag_list(tags) ) { gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); gst_tag_list_get_string(tags, GST_TAG_SUBTITLE_CODEC, &g_codec); gst_tag_list_free(tags); } subs.language_code = std::string(g_lang); eDebug("eServiceMP3::subtitle stream=%i language=%s codec=%s", i, g_lang, g_codec); GstPad* pad = 0; g_signal_emit_by_name (m_gst_playbin, "get-text-pad", i, &pad); if ( pad ) g_signal_connect (G_OBJECT (pad), "notify::caps", G_CALLBACK (gstTextpadHasCAPS), this); subs.type = getSubtitleType(pad, g_codec); m_subtitleStreams.push_back(subs); g_free (g_lang); } m_event((iPlayableService*)this, evUpdatedInfo); if ( m_errorInfo.missing_codec != "" ) { if ( m_errorInfo.missing_codec.find("video/") == 0 || ( m_errorInfo.missing_codec.find("audio/") == 0 && getNumberOfTracks() == 0 ) ) m_event((iPlayableService*)this, evUser+12); } break; } case GST_MESSAGE_ELEMENT: { if (const GstStructure *msgstruct = gst_message_get_structure(msg)) { if ( gst_is_missing_plugin_message(msg) ) { GstCaps *caps; gst_structure_get (msgstruct, "detail", GST_TYPE_CAPS, &caps, NULL); std::string codec = (const char*) gst_caps_to_string(caps); gchar *description = gst_missing_plugin_message_get_description(msg); if ( description ) { eDebug("eServiceMP3::m_errorInfo.missing_codec = %s", codec.c_str()); m_errorInfo.error_message = "GStreamer plugin " + (std::string)description + " not available!\n"; m_errorInfo.missing_codec = codec.substr(0,(codec.find_first_of(','))); g_free(description); } gst_caps_unref(caps); } else { const gchar *eventname = gst_structure_get_name(msgstruct); if ( eventname ) { if (!strcmp(eventname, "eventSizeChanged") || !strcmp(eventname, "eventSizeAvail")) { gst_structure_get_int (msgstruct, "aspect_ratio", &m_aspect); gst_structure_get_int (msgstruct, "width", &m_width); gst_structure_get_int (msgstruct, "height", &m_height); if (strstr(eventname, "Changed")) m_event((iPlayableService*)this, evVideoSizeChanged); } else if (!strcmp(eventname, "eventFrameRateChanged") || !strcmp(eventname, "eventFrameRateAvail")) { gst_structure_get_int (msgstruct, "frame_rate", &m_framerate); if (strstr(eventname, "Changed")) m_event((iPlayableService*)this, evVideoFramerateChanged); } else if (!strcmp(eventname, "eventProgressiveChanged") || !strcmp(eventname, "eventProgressiveAvail")) { gst_structure_get_int (msgstruct, "progressive", &m_progressive); if (strstr(eventname, "Changed")) m_event((iPlayableService*)this, evVideoProgressiveChanged); } } } } break; } case GST_MESSAGE_BUFFERING: { GstBufferingMode mode; gst_message_parse_buffering(msg, &(m_bufferInfo.bufferPercent)); gst_message_parse_buffering_stats(msg, &mode, &(m_bufferInfo.avgInRate), &(m_bufferInfo.avgOutRate), &(m_bufferInfo.bufferingLeft)); m_event((iPlayableService*)this, evBuffering); break; } case GST_MESSAGE_STREAM_STATUS: { GstStreamStatusType type; GstElement *owner; gst_message_parse_stream_status (msg, &type, &owner); if ( type == GST_STREAM_STATUS_TYPE_CREATE && m_sourceinfo.is_streaming ) { if ( GST_IS_PAD(source) ) owner = gst_pad_get_parent_element(GST_PAD(source)); else if ( GST_IS_ELEMENT(source) ) owner = GST_ELEMENT(source); else owner = 0; if ( owner ) { GstElementFactory *factory = gst_element_get_factory(GST_ELEMENT(owner)); const gchar *name = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory)); if (!strcmp(name, "souphttpsrc")) { m_streamingsrc_timeout->start(HTTP_TIMEOUT*1000, true); g_object_set (G_OBJECT (owner), "timeout", HTTP_TIMEOUT, NULL); eDebug("eServiceMP3::GST_STREAM_STATUS_TYPE_CREATE -> setting timeout on %s to %is", name, HTTP_TIMEOUT); } } if ( GST_IS_PAD(source) ) gst_object_unref(owner); } break; } default: break; } g_free (sourceName); }
static void _bus_handler (GstBus * bus, GstMessage * message, GstValidatePipelineMonitor * monitor) { GError *err = NULL; gchar *debug = NULL; switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ERROR: gst_message_parse_error (message, &err, &debug); if (g_error_matches (err, GST_CORE_ERROR, GST_CORE_ERROR_MISSING_PLUGIN)) { GST_VALIDATE_REPORT (monitor, MISSING_PLUGIN, "Error: %s -- Debug message: %s", err->message, debug); } else { GST_VALIDATE_REPORT (monitor, ERROR_ON_BUS, "Got error: %s -- Debug message: %s", err->message, debug); } GST_VALIDATE_MONITOR_LOCK (monitor); monitor->got_error = TRUE; GST_VALIDATE_MONITOR_UNLOCK (monitor); g_error_free (err); g_free (debug); break; case GST_MESSAGE_WARNING: gst_message_parse_warning (message, &err, &debug); GST_VALIDATE_REPORT (monitor, WARNING_ON_BUS, "Got warning: %s -- Debug message: %s", err->message, debug); g_error_free (err); g_free (debug); break; case GST_MESSAGE_STATE_CHANGED: { if (GST_MESSAGE_SRC (message) == GST_VALIDATE_MONITOR (monitor)->target) { GstState oldstate, newstate, pending; gst_message_parse_state_changed (message, &oldstate, &newstate, &pending); if (oldstate == GST_STATE_READY && newstate == GST_STATE_PAUSED) { monitor->print_pos_srcid = g_timeout_add (PRINT_POSITION_TIMEOUT, (GSourceFunc) print_position, monitor); } else if (oldstate >= GST_STATE_PAUSED && newstate <= GST_STATE_READY) { if (monitor->print_pos_srcid && g_source_remove (monitor->print_pos_srcid)) monitor->print_pos_srcid = 0; monitor->got_error = FALSE; } } break; } case GST_MESSAGE_BUFFERING: { GstBufferingMode mode; gint percent; gst_message_parse_buffering (message, &percent); gst_message_parse_buffering_stats (message, &mode, NULL, NULL, NULL); if (percent == 100) { /* a 100% message means buffering is done */ if (monitor->buffering) { monitor->print_pos_srcid = g_timeout_add (PRINT_POSITION_TIMEOUT, (GSourceFunc) print_position, monitor); monitor->buffering = FALSE; } } else { /* buffering... */ if (!monitor->buffering) { monitor->buffering = TRUE; if (monitor->print_pos_srcid && g_source_remove (monitor->print_pos_srcid)) monitor->print_pos_srcid = 0; } } break; } default: break; } }
void __mm_player_streaming_buffering(mm_player_streaming_t* streamer, GstMessage *buffering_msg) { GstBufferingMode mode = GST_BUFFERING_STREAM; gint byte_in_rate = 0; gint byte_out_rate = 0; gint64 buffering_left = -1; gdouble buffering_time = DEFAULT_BUFFERING_TIME; gdouble low_percent = 0.0; gdouble high_percent = 0.0; guint high_percent_byte = 0; gint buffer_percent = 0; guint buffer_criteria = 0; return_if_fail ( streamer ); return_if_fail ( buffering_msg ); return_if_fail ( GST_IS_MESSAGE ( buffering_msg ) ); return_if_fail ( GST_MESSAGE_TYPE ( buffering_msg ) == GST_MESSAGE_BUFFERING ); /* update when buffering has started. */ if ( !streamer->is_buffering ) { debug_log ( "buffering has started.\n" ); streamer->is_buffering = TRUE; streamer->buffering_percent = -1; streamer->need_update = TRUE; } /* update buffer percent */ gst_message_parse_buffering ( buffering_msg, &buffer_percent ); if ( streamer->buffering_percent < buffer_percent ) { debug_log ( "buffering %d%%....\n", buffer_percent ); streamer->buffering_percent = buffer_percent; } if ( streamer->buffering_percent == MAX_BUFFER_PERCENT ) { debug_log ( "buffering had done.\n" ); streamer->is_buffering = FALSE; } if (!streamer->need_update) { debug_log ( "don't need to update buffering stats during buffering.\n" ); return; } /* Note : Parse the buffering message to get the in/out throughput. * avg_in is the network throughput and avg_out is the consumed throughtput by the linkded element. */ gst_message_parse_buffering_stats ( buffering_msg, &mode, &byte_in_rate, &byte_out_rate, &buffering_left ); if (streamer->buffer_max_bitrate > 0) { buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate); byte_out_rate = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate /3); } else if (streamer->buffer_avg_bitrate > 0) { buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate * 3); byte_out_rate = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate); } debug_log ( "in rate is %d, out rate is %d (bytes/sec).\n", byte_in_rate, byte_out_rate ); if ( byte_in_rate > 0 && byte_out_rate > 0) buffering_time = byte_out_rate / byte_in_rate; else if (byte_in_rate <= 0 && byte_out_rate > 0) buffering_time = MAX_BUFFERING_TIME; else buffering_time = DEFAULT_BUFFERING_TIME; streaming_set_buffering_time(streamer, buffering_time); /* calculate buffer low/high percent */ low_percent = DEFAULT_BUFFER_LOW_PERCENT; if ( buffer_criteria > 0 ) { high_percent_byte = buffer_criteria * streamer->buffering_time; high_percent = ( (gdouble)high_percent_byte * 100.0 ) / (gdouble)streamer->buffer_size; } else { high_percent_byte = streamer->buffer_high_percent * streamer->buffer_size / 100; high_percent= streamer->buffer_high_percent; } if ( streamer->buffer_size < high_percent_byte ) { debug_log ( "buffer size[%d bytes] is smaller than high threshold[%d bytes]. update it. \n", streamer->buffer_size, high_percent_byte ); streaming_set_buffer_size(streamer, high_percent_byte * 1.1); } streaming_set_buffer_percent(streamer, low_percent, high_percent); streamer->need_update = FALSE; return; }