static VALUE info_parse(VALUE self) { VALUE result; GError *error; gchar *debug; gst_message_parse_info(SELF(self), &error, &debug); result = rb_ary_new3(2, GERROR2RVAL(error), CSTR2RVAL_FREE(debug)); return result; }
static bool default_msg_handler( decoder_t *p_dec, GstMessage *p_msg ) { bool err = false; switch( GST_MESSAGE_TYPE( p_msg ) ){ case GST_MESSAGE_ERROR: { gchar *psz_debug; GError *p_error; gst_message_parse_error( p_msg, &p_error, &psz_debug ); g_free( psz_debug ); msg_Err( p_dec, "Error from %s: %s", GST_ELEMENT_NAME( GST_MESSAGE_SRC( p_msg ) ), p_error->message ); g_error_free( p_error ); err = true; } break; case GST_MESSAGE_WARNING: { gchar *psz_debug; GError *p_error; gst_message_parse_warning( p_msg, &p_error, &psz_debug ); g_free( psz_debug ); msg_Warn( p_dec, "Warning from %s: %s", GST_ELEMENT_NAME( GST_MESSAGE_SRC( p_msg ) ), p_error->message ); g_error_free( p_error ); } break; case GST_MESSAGE_INFO: { gchar *psz_debug; GError *p_error; gst_message_parse_info( p_msg, &p_error, &psz_debug ); g_free( psz_debug ); msg_Info( p_dec, "Info from %s: %s", GST_ELEMENT_NAME( GST_MESSAGE_SRC( p_msg ) ), p_error->message ); g_error_free( p_error ); } break; default: break; } return err; }
QString InfoMessage::debugMessage() const { gchar *debug; GError *e; //Passing a NULL pointer for the GError is not supported gst_message_parse_info(object<GstMessage>(), &e, &debug); if (e) { g_error_free (e); } return QGlib::Private::stringFromGCharPtr(debug); }
gboolean CGstPlayback::HandleMessage(GstBus *bus, GstMessage *msg) { switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: g_print ("End of stream"); if (m_sink) m_sink->onCompletion(); //g_main_loop_quit (m_main_loop); break; case GST_MESSAGE_STATE_CHANGED: { GstState state = GST_STATE_NULL; gint iret = gst_element_get_state(m_playbin, &state, NULL, NULL); if (iret != GST_STATE_CHANGE_FAILURE && m_sink) { m_sink->onPlayState(state); } g_print("state changed to=%d", (gint)state); break; } case GST_MESSAGE_ERROR: { gchar *debug; GError *error; gst_message_parse_error (msg, &error, &debug); g_printerr ("Error: %s", error->message); if (m_sink) m_sink->onError(error->code, error->message); g_free (debug); g_error_free (error); //g_main_loop_quit (m_main_loop); break; } case GST_MESSAGE_INFO: { gchar *debug; GError *error; gst_message_parse_info (msg, &error, &debug); g_printerr ("Info: %s", error->message); if (m_sink) m_sink->onInfo(error->code, error->message); g_free (debug); g_error_free (error); break; } default: break; } return TRUE; }
std::string GetLogMessage(GstMessage * msg) { std::string ret; gchar * debug(0); GError * error(0); switch (msg->type) { case GST_MESSAGE_INFO: { gst_message_parse_info(msg, &error, &debug); break; } case GST_MESSAGE_WARNING: { gst_message_parse_warning(msg, &error, &debug); break; } case GST_MESSAGE_ERROR: { gst_message_parse_error(msg, &error, &debug); break; } default: { ret = "This message is not of type info, warning or error. "; break; } } if (error) { ret += std::string(error->message) + ". "; } if (debug) { ret += "Debug string: " + std::string(debug) + ". "; } g_free(debug); g_error_free(error); return ret; }
/* returns TRUE if there was an error or we caught a keyboard interrupt. */ static gboolean event_loop (GstElement * pipeline, gboolean blocking, GstState target_state) { GstBus *bus; GstMessage *message = NULL; gboolean res = FALSE; gboolean buffering = FALSE; bus = gst_element_get_bus (GST_ELEMENT (pipeline)); #ifndef DISABLE_FAULT_HANDLER g_timeout_add (50, (GSourceFunc) check_intr, pipeline); #endif while (TRUE) { message = gst_bus_poll (bus, GST_MESSAGE_ANY, blocking ? -1 : 0); /* if the poll timed out, only when !blocking */ if (message == NULL) goto exit; switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_NEW_CLOCK: { GstClock *clock; gst_message_parse_new_clock (message, &clock); g_print ("New clock: %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL")); break; } case GST_MESSAGE_EOS: g_print ("Got EOS from element \"%s\".\n", GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message)))); goto exit; case GST_MESSAGE_TAG: if (tags) { GstTagList *tags; gst_message_parse_tag (message, &tags); g_print ("FOUND TAG : found by element \"%s\".\n", GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message)))); gst_tag_list_foreach (tags, print_tag, NULL); gst_tag_list_free (tags); } break; case GST_MESSAGE_INFO:{ GError *gerror; gchar *debug; gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message)); gst_message_parse_info (message, &gerror, &debug); if (debug) { g_print ("INFO:\n%s\n", debug); } g_error_free (gerror); g_free (debug); g_free (name); break; } case GST_MESSAGE_WARNING:{ GError *gerror; gchar *debug; gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message)); /* dump graph on warning */ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.warning"); gst_message_parse_warning (message, &gerror, &debug); g_print ("WARNING: from element %s: %s\n", name, gerror->message); if (debug) { g_print ("Additional debug info:\n%s\n", debug); } g_error_free (gerror); g_free (debug); g_free (name); break; } case GST_MESSAGE_ERROR:{ GError *gerror; gchar *debug; /* dump graph on error */ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.error"); gst_message_parse_error (message, &gerror, &debug); gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug); g_error_free (gerror); g_free (debug); /* we have an error */ res = TRUE; goto exit; } case GST_MESSAGE_STATE_CHANGED:{ GstState old, newX, pending; gst_message_parse_state_changed (message, &old, &newX, &pending); /* we only care about pipeline state change messages */ if (GST_MESSAGE_SRC (message) != GST_OBJECT_CAST (pipeline)) break; /* dump graph for pipeline state changes */ { gchar *dump_name = g_strdup_printf ("gst-launch.%s_%s", gst_element_state_get_name (old), gst_element_state_get_name (newX)); GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline), GST_DEBUG_GRAPH_SHOW_ALL, dump_name); g_free (dump_name); } /* ignore when we are buffering since then we mess with the states * ourselves. */ if (buffering) { fprintf (stderr, "Prerolled, waiting for buffering to finish...\n"); break; } /* if we reached the final target state, exit */ if (target_state == GST_STATE_PAUSED && newX == target_state) goto exit; /* else not an interesting message */ break; } case GST_MESSAGE_BUFFERING:{ gint percent; gst_message_parse_buffering (message, &percent); fprintf (stderr, "%s %d%% \r", "buffering...", percent); /* no state management needed for live pipelines */ if (is_live) break; if (percent == 100) { /* a 100% message means buffering is done */ buffering = FALSE; /* if the desired state is playing, go back */ if (target_state == GST_STATE_PLAYING) { fprintf (stderr, "Done buffering, setting pipeline to PLAYING ...\n"); gst_element_set_state (pipeline, GST_STATE_PLAYING); } else goto exit; } else { /* buffering busy */ if (buffering == FALSE && target_state == GST_STATE_PLAYING) { /* we were not buffering but PLAYING, PAUSE the pipeline. */ fprintf (stderr, "Buffering, setting pipeline to PAUSED ...\n"); gst_element_set_state (pipeline, GST_STATE_PAUSED); } buffering = TRUE; } break; } case GST_MESSAGE_LATENCY: { fprintf (stderr, "Redistribute latency...\n"); gst_bin_recalculate_latency (GST_BIN (pipeline)); break; } case GST_MESSAGE_APPLICATION:{ const GstStructure *s; s = gst_message_get_structure (message); if (gst_structure_has_name (s, "GstLaunchInterrupt")) { /* this application message is posted when we caught an interrupt and * we need to stop the pipeline. */ fprintf (stderr, "Interrupt: Stopping pipeline ...\n"); /* return TRUE when we caught an interrupt */ res = TRUE; goto exit; } } default: /* just be quiet by default */ break; } if (message) gst_message_unref (message); } g_assert_not_reached (); exit: { if (message) gst_message_unref (message); gst_object_unref (bus); return res; } }
static gboolean bus_message(GstBus *bus, GstMessage *message, void *pv) { switch (GST_MESSAGE_TYPE(message)) { case GST_MESSAGE_ERROR: { GError *err = NULL; gchar *dbg_info = NULL; gst_message_parse_error(message, &err, &dbg_info); AVB_LOGF_ERROR("GStreamer ERROR message from element %s: %s", GST_OBJECT_NAME(message->src), err->message); AVB_LOGF_ERROR("Additional info: %s\n", (dbg_info) ? dbg_info : "none"); g_error_free(err); g_free(dbg_info); break; } case GST_MESSAGE_WARNING: { GError *err = NULL; gchar *dbg_info = NULL; gst_message_parse_warning(message, &err, &dbg_info); AVB_LOGF_WARNING("GStreamer WARNING message from element %s: %s", GST_OBJECT_NAME(message->src), err->message); AVB_LOGF_WARNING("Additional info: %s\n", (dbg_info) ? dbg_info : "none"); g_error_free(err); g_free(dbg_info); break; } case GST_MESSAGE_INFO: { GError *err = NULL; gchar *dbg_info = NULL; gst_message_parse_info(message, &err, &dbg_info); AVB_LOGF_ERROR("GStreamer INFO message from element %s: %s", GST_OBJECT_NAME(message->src), err->message); AVB_LOGF_ERROR("Additional info: %s\n", (dbg_info) ? dbg_info : "none"); g_error_free(err); g_free(dbg_info); break; } case GST_MESSAGE_STATE_CHANGED: { GstState old_state, new_state; gst_message_parse_state_changed(message, &old_state, &new_state, NULL); AVB_LOGF_DEBUG("Element %s changed state from %s to %s", GST_OBJECT_NAME(message->src), gst_element_state_get_name(old_state), gst_element_state_get_name(new_state)); break; } case GST_MESSAGE_STREAM_STATUS: { // not so valuable break; } case GST_MESSAGE_EOS: AVB_LOG_INFO("EOS received"); break; default: AVB_LOGF_INFO("GStreamer '%s' message from element %s", gst_message_type_get_name(GST_MESSAGE_TYPE(message)), GST_OBJECT_NAME(message->src)); break; } return TRUE; }
void Pipeline::handleBusMessage(GstMessage *message) { switch (GST_MESSAGE_TYPE(message)) { case GST_MESSAGE_ELEMENT: { // The only message we are handling here is the prepare-xwindow-id one if (gst_structure_has_name (message->structure, "prepare-xwindow-id")) { gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(viewfinder), windowId); } break; } case GST_MESSAGE_ERROR: { GError *gerror = 0; gchar *debug = 0; gst_message_parse_error(message, &gerror, &debug); qCritical() << "Debug" << debug << " Error " << gerror->message; g_free(debug); g_error_free(gerror); break; } case GST_MESSAGE_WARNING: { GError *gerror = 0; gchar *debug = 0; gst_message_parse_warning(message, &gerror, &debug); qWarning() << "Debug" << debug << " Warning " << gerror->message; g_free(debug); g_error_free(gerror); break; } case GST_MESSAGE_INFO: { GError *gerror = 0; gchar *debug = 0; gst_message_parse_info(message, &gerror, &debug); qDebug() << "Debug" << debug << " Info " << gerror->message; g_free(debug); g_error_free(gerror); break; } case GST_MESSAGE_STATE_CHANGED: { if (GST_ELEMENT(GST_MESSAGE_SRC(message)) == camerabin) { GstState oldstate, newstate, pending; gst_message_parse_state_changed(message, &oldstate, &newstate, &pending); qDebug() << Q_FUNC_INFO << gst_element_state_get_name(oldstate) << "->" << gst_element_state_get_name(newstate) << "=>" << gst_element_state_get_name(pending); GstStateChange stateTransition = GST_STATE_TRANSITION(oldstate, newstate); switch (stateTransition) { case GST_STATE_CHANGE_PAUSED_TO_PLAYING: QMetaObject::invokeMethod(this, "pipelinePlaying", Qt::QueuedConnection); break; default: break; } } break; } default: break; } }
bool GstPipelineWrapper::GstMessageParser(GstBus* bus, GstMessage* msg, GstPipelineWrapper* pipeline) { if (!pipeline->get_is_verbose()) return true; if (msg != NULL) { GError* err = 0; gchar* debug_info = 0; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_ERROR: gst_message_parse_error (msg, &err, &debug_info); g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); g_clear_error (&err); g_free (debug_info); break; case GST_MESSAGE_WARNING: gst_message_parse_warning(msg, &err, &debug_info); g_printerr ("Warning received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); g_clear_error (&err); g_free (debug_info); break; case GST_MESSAGE_INFO: gst_message_parse_info(msg, &err, &debug_info); g_printerr ("Info received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); g_clear_error (&err); g_free (debug_info); break; case GST_MESSAGE_EOS: g_print ("End-Of-Stream reached.\n"); break; case GST_MESSAGE_STATE_CHANGED: GstState old_state, new_state; gst_message_parse_state_changed(msg, &old_state, &new_state, 0); g_print ("Element %s changed state from %s to %s.\n", GST_OBJECT_NAME (msg->src), gst_element_state_get_name (old_state),gst_element_state_get_name (new_state)); break; case GST_MESSAGE_QOS: break; case GST_MESSAGE_STREAM_STATUS: GstStreamStatusType stream_status_type; GstElement* owner; const gchar* stream_status_type_string; gst_message_parse_stream_status(msg, &stream_status_type, &owner); switch (stream_status_type) { case GST_STREAM_STATUS_TYPE_CREATE : stream_status_type_string = "CREATE"; break; case GST_STREAM_STATUS_TYPE_ENTER : stream_status_type_string = "ENTER"; break; case GST_STREAM_STATUS_TYPE_LEAVE : stream_status_type_string = "LEAVE"; break; case GST_STREAM_STATUS_TYPE_DESTROY : stream_status_type_string = "DESTROY"; break; case GST_STREAM_STATUS_TYPE_START : stream_status_type_string = "START"; break; case GST_STREAM_STATUS_TYPE_PAUSE : stream_status_type_string = "PAUSE"; break; case GST_STREAM_STATUS_TYPE_STOP : stream_status_type_string = "STOP"; break; } g_printerr ("STREAM STATUS received from element %s: %s\n", GST_OBJECT_NAME (owner), stream_status_type_string); //g_free (stream_status_type_string); break; default: g_printerr ("Unparsed message received of type: %s\n", gst_message_type_get_name(GST_MESSAGE_TYPE(msg))); break; } } return true; }
//static gboolean LLMediaImplGStreamer::bus_callback(GstBus *bus, GstMessage *message, gpointer data) { #ifdef LL_GST_REPORT_STATE_CHANGES LL_DEBUGS("MediaCallback") << "Got GST message type: " << GST_MESSAGE_TYPE_NAME (message) << LL_ENDL; #endif LLMediaImplGStreamer *impl = (LLMediaImplGStreamer*)data; switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_BUFFERING: { gint percent = 0; gst_message_parse_buffering(message, &percent); #ifdef LL_GST_REPORT_STATE_CHANGES LL_DEBUGS("MediaBuffering") << "GST buffering: " << percent << "%%" << LL_ENDL; #endif LLMediaEvent event( impl, percent ); impl->getEventEmitter().update( &LLMediaObserver::onUpdateProgress, event ); } break; case GST_MESSAGE_STATE_CHANGED: { GstState old_state; GstState new_state; GstState pending_state; gst_message_parse_state_changed(message, &old_state, &new_state, &pending_state); #ifdef LL_GST_REPORT_STATE_CHANGES // not generally very useful, and rather spammy. LL_DEBUGS("MediaState") << "GST state change (old,<new>,pending): "<< get_gst_state_name(old_state) << ",<" << get_gst_state_name(new_state) << ">," << get_gst_state_name(pending_state) << LL_ENDL; #endif // LL_GST_REPORT_STATE_CHANGES switch (new_state) { case GST_STATE_VOID_PENDING: break; case GST_STATE_NULL: #ifdef LL_GST_REPORT_STATE_CHANGES LL_DEBUGS("MediaImpl") << "State changed to NULL" << LL_ENDL; #endif if (impl->getState() == GST_STATE_PLAYING) { // Stream was probably dropped, trying to restart impl->play(); #ifdef LL_GST_REPORT_STATE_CHANGES LL_DEBUGS("MediaImpl") << "Trying to restart." << LL_ENDL; #endif } break; case GST_STATE_READY: break; case GST_STATE_PAUSED: break; case GST_STATE_PLAYING: //impl->mLastTitle = ""; LLMediaEvent event( impl, 100 ); impl->getEventEmitter().update( &LLMediaObserver::onUpdateProgress, event ); // emit an event to say that a media source was loaded LLMediaEvent event2( impl ); impl->getEventEmitter().update( &LLMediaObserver::onMediaLoaded, event2 ); break; } break; } case GST_MESSAGE_ERROR: { GError *err = NULL; gchar *debug = NULL; gst_message_parse_error (message, &err, &debug); LL_WARNS("MediaImpl") << "GST Error: " << err->message << LL_ENDL; g_error_free (err); g_free (debug); impl->addCommand(LLMediaBase::COMMAND_STOP); //impl->addCommand(LLMediaBase::COMMAND_START); break; } case GST_MESSAGE_INFO: { GError *err = NULL; gchar *debug = NULL; gst_message_parse_info (message, &err, &debug); LL_INFOS("MediaImpl") << "GST info: " << err->message << LL_ENDL; g_error_free (err); g_free (debug); break; } case GST_MESSAGE_WARNING: { GError *err = NULL; gchar *debug = NULL; gst_message_parse_warning (message, &err, &debug); LL_WARNS("MediaImpl") << "GST warning: " << err->message << LL_ENDL; g_error_free (err); g_free (debug); break; } case GST_MESSAGE_TAG: { GstTagList *new_tags; gst_message_parse_tag( message, &new_tags ); gchar *title; if ( gst_tag_list_get_string(new_tags, GST_TAG_TITLE, &title) ) { LL_INFOS("MediaInfo") << "Title: " << title << LL_ENDL; std::string newtitle(title); gst_tag_list_free(new_tags); if ( newtitle != impl->mLastTitle && newtitle != "" ) { impl->mLastTitle = newtitle; LLMediaEvent event( impl, impl->mLastTitle ); impl->getEventEmitter().update( &LLMediaObserver::onMediaTitleChange, event ); } g_free(title); } break; } case GST_MESSAGE_EOS: { /* end-of-stream */ LL_DEBUGS("MediaImpl") << "GST end-of-stream." << LL_ENDL; if (impl->isLooping()) { LL_DEBUGS("MediaImpl") << "looping media..." << LL_ENDL; impl->stop(); impl->play(); } else { // inject a COMMAND_STOP impl->addCommand(LLMediaBase::COMMAND_STOP); } break; } default: /* unhandled message */ break; } /* we want to be notified again the next time there is a message * on the bus, so return true (false means we want to stop watching * for messages on the bus and our callback should not be called again) */ return TRUE; }
QGlib::Error InfoMessage::error() const { GError *e; gst_message_parse_info(object<GstMessage>(), &e, NULL); return QGlib::Error(e); }
gboolean MediaPluginGStreamer010::processGSTEvents(GstBus *bus, GstMessage *message) { if (!message) return TRUE; // shield against GStreamer bug if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_STATE_CHANGED && GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING) { DEBUGMSG("Got GST message type: %s", GST_MESSAGE_TYPE_NAME (message)); } else { // TODO: grok 'duration' message type DEBUGMSG("Got GST message type: %s", GST_MESSAGE_TYPE_NAME (message)); } switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_BUFFERING: { // NEEDS GST 0.10.11+ and America discovered by C.Columbus gint percent = 0; gst_message_parse_buffering(message, &percent); DEBUGMSG("GST buffering: %d%%", percent); break; } case GST_MESSAGE_STATE_CHANGED: { GstState old_state; GstState new_state; GstState pending_state; gst_message_parse_state_changed(message, &old_state, &new_state, &pending_state); #ifdef LL_GST_REPORT_STATE_CHANGES // not generally very useful, and rather spammy. DEBUGMSG("state change (old,<new>,pending): %s,<%s>,%s", get_gst_state_name(old_state), get_gst_state_name(new_state), get_gst_state_name(pending_state)); #endif // LL_GST_REPORT_STATE_CHANGES switch (new_state) { case GST_STATE_VOID_PENDING: break; case GST_STATE_NULL: break; case GST_STATE_READY: setStatus(STATUS_LOADED); break; case GST_STATE_PAUSED: setStatus(STATUS_PAUSED); break; case GST_STATE_PLAYING: setStatus(STATUS_PLAYING); break; } break; } case GST_MESSAGE_ERROR: { GError *err = NULL; gchar *debug = NULL; gst_message_parse_error (message, &err, &debug); WARNMSG("GST error: %s", err?err->message:"(unknown)"); if (err) g_error_free (err); g_free (debug); mCommand = COMMAND_STOP; setStatus(STATUS_ERROR); break; } case GST_MESSAGE_INFO: { GError *err = NULL; gchar *debug = NULL; gst_message_parse_info (message, &err, &debug); INFOMSG("GST info: %s", err?err->message:"(unknown)"); if (err) g_error_free (err); g_free (debug); break; } case GST_MESSAGE_WARNING: { GError *err = NULL; gchar *debug = NULL; gst_message_parse_warning (message, &err, &debug); WARNMSG("GST warning: %s", err?err->message:"(unknown)"); if (err) g_error_free (err); g_free (debug); break; } case GST_MESSAGE_TAG: { GstTagList *new_tags; gst_message_parse_tag( message, &new_tags ); gchar *title = NULL; if ( gst_tag_list_get_string(new_tags, GST_TAG_TITLE, &title) ) { //WARMING("Title: %s", title); std::string newtitle(title); gst_tag_list_free(new_tags); if ( newtitle != mLastTitle && !newtitle.empty() ) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); message.setValue("name", newtitle ); sendMessage( message ); mLastTitle = newtitle; } g_free(title); } break; } case GST_MESSAGE_EOS: { /* end-of-stream */ DEBUGMSG("GST end-of-stream."); if (mIsLooping) { DEBUGMSG("looping media..."); double eos_pos_sec = 0.0F; bool got_eos_position = getTimePos(eos_pos_sec); if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC) { // if we know that the movie is really short, don't // loop it else it can easily become a time-hog // because of GStreamer spin-up overhead DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec); // inject a COMMAND_PAUSE mCommand = COMMAND_PAUSE; } else { #undef LLGST_LOOP_BY_SEEKING // loop with a stop-start instead of a seek, because it actually seems rather // faster than seeking on remote streams. #ifdef LLGST_LOOP_BY_SEEKING // first, try looping by an explicit rewind bool seeksuccess = seek(0.0); if (seeksuccess) { play(1.0); } else #endif // LLGST_LOOP_BY_SEEKING { // use clumsy stop-start to loop DEBUGMSG("didn't loop by rewinding - stopping and starting instead..."); stop(); play(1.0); } } } else // not a looping media { // inject a COMMAND_STOP mCommand = COMMAND_STOP; } } break; default: /* unhandled message */ break; } /* we want to be notified again the next time there is a message * on the bus, so return true (false means we want to stop watching * for messages on the bus and our callback should not be called again) */ return TRUE; }
// ---------------------------------------------------------------------------- // Retrieve and process a bus message bool GStreamerImportFileHandle::ProcessBusMessage(bool & success) { bool cont = true; // Default to no errors success = true; // Get the next message GstMessage *msg = gst_bus_timed_pop(mBus, 100 * GST_MSECOND); if (!msg) { // Timed out...not an error return cont; } #if defined(__WXDEBUG__) gchar *objname = NULL; if (msg->src != NULL) { objname = gst_object_get_name(msg->src); } wxLogMessage(wxT("GStreamer: Got %s%s%s"), wxString::FromUTF8(GST_MESSAGE_TYPE_NAME(msg)).c_str(), objname ? wxT(" from ") : wxT(""), objname ? wxString::FromUTF8(objname).c_str() : wxT("")); if (objname != NULL) { g_free(objname); } #endif // Handle based on message type switch (GST_MESSAGE_TYPE(msg)) { // Handle error message from gstreamer case GST_MESSAGE_ERROR: { GError *err = NULL; gchar *debug = NULL; gst_message_parse_error(msg, &err, &debug); if (err) { wxString m; m.Printf(wxT("%s%s%s"), wxString::FromUTF8(err->message).c_str(), debug ? wxT("\n") : wxT(""), debug ? wxString::FromUTF8(debug).c_str() : wxT("")); #if defined(_DEBUG) wxMessageBox(m, wxT("GStreamer Error:")); #else wxLogMessage(wxT("GStreamer Error: %s"), m.c_str()); #endif g_error_free(err); } if (debug) { g_free(debug); } success = false; cont = false; } break; // Handle warning message from gstreamer case GST_MESSAGE_WARNING: { GError *err = NULL; gchar *debug = NULL; gst_message_parse_warning(msg, &err, &debug); if (err) { wxLogMessage(wxT("GStreamer Warning: %s%s%s"), wxString::FromUTF8(err->message).c_str(), debug ? wxT("\n") : wxT(""), debug ? wxString::FromUTF8(debug).c_str() : wxT("")); g_error_free(err); } if (debug) { g_free(debug); } } break; // Handle warning message from gstreamer case GST_MESSAGE_INFO: { GError *err = NULL; gchar *debug = NULL; gst_message_parse_info(msg, &err, &debug); if (err) { wxLogMessage(wxT("GStreamer Info: %s%s%s"), wxString::FromUTF8(err->message).c_str(), debug ? wxT("\n") : wxT(""), debug ? wxString::FromUTF8(debug).c_str() : wxT("")); g_error_free(err); } if (debug) { g_free(debug); } } break; // Handle metadata tags case GST_MESSAGE_TAG: { GstTagList *tags = NULL; // Retrieve tag list from message...just ignore failure gst_message_parse_tag(msg, &tags); if (tags) { // Go process the list OnTag(GST_APP_SINK(GST_MESSAGE_SRC(msg)), tags); // Done with list gst_tag_list_unref(tags); } } break; // Pre-roll is done...will happen for each group // (like with chained OGG files) case GST_MESSAGE_ASYNC_DONE: { // If this is the first async-done message, then tell // caller to end loop, but leave it active so that // gstreamer threads can still queue up. // // We'll receive multiple async-done messages for chained // ogg files, so ignore the message the 2nd and subsequent // occurrences. if (!mAsyncDone) { cont = false; mAsyncDone = true; } } break; // End of the stream (and all sub-streams) case GST_MESSAGE_EOS: { // Terminate loop cont = false; } break; } // Release the message gst_message_unref(msg); return cont; }
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); }
GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) { gchar * sourceName; // source GstObject * source; source = GST_MESSAGE_SRC(msg); if (!GST_IS_OBJECT(source)) return GST_BUS_DROP; sourceName = gst_object_get_name(source); switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_EOS: { g_message("End-of-stream"); end_eof = 1; break; } case GST_MESSAGE_ERROR: { gchar * debug; GError *err; gst_message_parse_error(msg, &err, &debug); g_free (debug); lt_info_c( "%s:%s - GST_MESSAGE_ERROR: %s (%i) from %s\n", FILENAME, __FUNCTION__, 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") ) lt_info_c( "%s:%s - GST_MESSAGE_ERROR: videosink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? else if ( g_strrstr(sourceName, "audiosink") ) lt_info_c( "%s:%s - GST_MESSAGE_ERROR: audioSink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? } } g_error_free(err); end_eof = 1; // NOTE: just to exit 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") ) lt_info_c( "%s:%s - GST_MESSAGE_INFO: videosink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? } 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); if(fd >= 0) { int ret = write(fd, GST_BUFFER_DATA(buf_image), GST_BUFFER_SIZE(buf_image)); close(fd); lt_info_c( "%s:%s - GST_MESSAGE_INFO: cPlayback::state /tmp/.id3coverart %d bytes written\n", FILENAME, __FUNCTION__ , ret); } //FIXME: how shall playback handle this event??? } gst_tag_list_free(tags); lt_info_c( "%s:%s - GST_MESSAGE_INFO: update info tags\n", FILENAME, __FUNCTION__); //FIXME: how shall playback handle this event??? 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; lt_info_c( "%s:%s - GST_MESSAGE_STATE_CHANGED: state transition %s -> %s\n", FILENAME, __FUNCTION__, 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: { GstIterator *children; if (audioSink) { gst_object_unref(GST_OBJECT(audioSink)); audioSink = NULL; } if (videoSink) { gst_object_unref(GST_OBJECT(videoSink)); videoSink = NULL; } children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin)); audioSink = GST_ELEMENT_CAST(gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, (gpointer)"GstDVBAudioSink")); videoSink = GST_ELEMENT_CAST(gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, (gpointer)"GstDVBVideoSink")); gst_iterator_free(children); } break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: { } break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED: { } break; case GST_STATE_CHANGE_PAUSED_TO_READY: { if (audioSink) { gst_object_unref(GST_OBJECT(audioSink)); audioSink = NULL; } if (videoSink) { gst_object_unref(GST_OBJECT(videoSink)); videoSink = NULL; } } break; case GST_STATE_CHANGE_READY_TO_NULL: { } break; } break; } #if 0 case GST_MESSAGE_ELEMENT: { if(gst_structure_has_name(gst_message_get_structure(msg), "prepare-xwindow-id")) { // set window id gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC (msg)), glfb->getWindowID()); // reshape window gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(GST_MESSAGE_SRC (msg)), 0, 0, glfb->getOSDWidth(), glfb->getOSDHeight()); // sync frames gst_x_overlay_expose(GST_X_OVERLAY(GST_MESSAGE_SRC (msg))); } } #endif break; default: break; } return GST_BUS_DROP; }
void QGstreamerPlayerSession::busMessage(const QGstreamerMessage &message) { GstMessage* gm = message.rawMessage(); if (gm == 0) { // Null message, query current position quint32 newPos = position(); if (newPos/1000 != m_lastPosition) { m_lastPosition = newPos/1000; emit positionChanged(newPos); } double volume = 1.0; g_object_get(G_OBJECT(m_playbin), "volume", &volume, NULL); if (m_volume != int(volume*100)) { m_volume = int(volume*100); emit volumeChanged(m_volume); } } else { //tag message comes from elements inside playbin, not from playbin itself if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_TAG) { //qDebug() << "tag message"; GstTagList *tag_list; gst_message_parse_tag(gm, &tag_list); gst_tag_list_foreach(tag_list, addTagToMap, &m_tags); //qDebug() << m_tags; emit tagsChanged(); } if (GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_playbin)) { switch (GST_MESSAGE_TYPE(gm)) { case GST_MESSAGE_STATE_CHANGED: { GstState oldState; GstState newState; GstState pending; gst_message_parse_state_changed(gm, &oldState, &newState, &pending); #ifdef DEBUG_PLAYBIN QStringList states; states << "GST_STATE_VOID_PENDING" << "GST_STATE_NULL" << "GST_STATE_READY" << "GST_STATE_PAUSED" << "GST_STATE_PLAYING"; qDebug() << QString("state changed: old: %1 new: %2 pending: %3") \ .arg(states[oldState]) \ .arg(states[newState]) \ .arg(states[pending]); #endif switch (newState) { case GST_STATE_VOID_PENDING: case GST_STATE_NULL: setSeekable(false); finishVideoOutputChange(); if (m_state != QMediaPlayer::StoppedState) emit stateChanged(m_state = QMediaPlayer::StoppedState); break; case GST_STATE_READY: setSeekable(false); if (m_state != QMediaPlayer::StoppedState) emit stateChanged(m_state = QMediaPlayer::StoppedState); break; case GST_STATE_PAUSED: { QMediaPlayer::State prevState = m_state; m_state = QMediaPlayer::PausedState; //check for seekable if (oldState == GST_STATE_READY) { getStreamsInfo(); updateVideoResolutionTag(); /* //gst_element_seek_simple doesn't work reliably here, have to find a better solution GstFormat format = GST_FORMAT_TIME; gint64 position = 0; bool seekable = false; if (gst_element_query_position(m_playbin, &format, &position)) { seekable = gst_element_seek_simple(m_playbin, format, GST_SEEK_FLAG_NONE, position); } setSeekable(seekable); */ setSeekable(true); if (!qFuzzyCompare(m_playbackRate, qreal(1.0))) { qreal rate = m_playbackRate; m_playbackRate = 1.0; setPlaybackRate(rate); } } if (m_state != prevState) emit stateChanged(m_state); break; } case GST_STATE_PLAYING: if (m_state != QMediaPlayer::PlayingState) emit stateChanged(m_state = QMediaPlayer::PlayingState); break; } } break; case GST_MESSAGE_EOS: emit playbackFinished(); break; case GST_MESSAGE_TAG: case GST_MESSAGE_STREAM_STATUS: case GST_MESSAGE_UNKNOWN: break; case GST_MESSAGE_ERROR: { GError *err; gchar *debug; gst_message_parse_error (gm, &err, &debug); emit error(int(QMediaPlayer::ResourceError), QString::fromUtf8(err->message)); qWarning() << "Error:" << QString::fromUtf8(err->message); g_error_free (err); g_free (debug); } break; case GST_MESSAGE_WARNING: { GError *err; gchar *debug; gst_message_parse_warning (gm, &err, &debug); qWarning() << "Warning:" << QString::fromUtf8(err->message); g_error_free (err); g_free (debug); } break; case GST_MESSAGE_INFO: #ifdef DEBUG_PLAYBIN { GError *err; gchar *debug; gst_message_parse_info (gm, &err, &debug); qDebug() << "Info:" << QString::fromUtf8(err->message); g_error_free (err); g_free (debug); } #endif break; case GST_MESSAGE_BUFFERING: { int progress = 0; gst_message_parse_buffering(gm, &progress); emit bufferingProgressChanged(progress); } break; case GST_MESSAGE_STATE_DIRTY: case GST_MESSAGE_STEP_DONE: case GST_MESSAGE_CLOCK_PROVIDE: case GST_MESSAGE_CLOCK_LOST: case GST_MESSAGE_NEW_CLOCK: case GST_MESSAGE_STRUCTURE_CHANGE: case GST_MESSAGE_APPLICATION: case GST_MESSAGE_ELEMENT: break; case GST_MESSAGE_SEGMENT_START: { const GstStructure *structure = gst_message_get_structure(gm); qint64 position = g_value_get_int64(gst_structure_get_value(structure, "position")); position /= 1000000; m_lastPosition = position; emit positionChanged(position); } break; case GST_MESSAGE_SEGMENT_DONE: break; case GST_MESSAGE_DURATION: { GstFormat format = GST_FORMAT_TIME; gint64 duration = 0; if (gst_element_query_duration(m_playbin, &format, &duration)) { int newDuration = duration / 1000000; if (m_duration != newDuration) { m_duration = newDuration; emit durationChanged(m_duration); } } } break; case GST_MESSAGE_LATENCY: #if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 13) case GST_MESSAGE_ASYNC_START: case GST_MESSAGE_ASYNC_DONE: #if GST_VERSION_MICRO >= 23 case GST_MESSAGE_REQUEST_STATE: #endif #endif case GST_MESSAGE_ANY: break; default: break; } } else if (m_videoSink && m_renderer && GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_videoSink) && GST_MESSAGE_TYPE(gm) == GST_MESSAGE_STATE_CHANGED) { GstState oldState; GstState newState; gst_message_parse_state_changed(gm, &oldState, &newState, 0); if (oldState == GST_STATE_READY && newState == GST_STATE_PAUSED) m_renderer->precessNewStream(); } } }
static gboolean gst_switchui_handle_message (GstBus * bus, GstMessage * message, gpointer data) { GstSwitchUI *switchui = (GstSwitchUI *) data; switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_EOS: gst_switchui_handle_eos (switchui); break; case GST_MESSAGE_ERROR: { GError *error = NULL; gchar *debug; gst_message_parse_error (message, &error, &debug); gst_switchui_handle_error (switchui, error, debug); } break; case GST_MESSAGE_WARNING: { GError *error = NULL; gchar *debug; gst_message_parse_warning (message, &error, &debug); gst_switchui_handle_warning (switchui, error, debug); } break; case GST_MESSAGE_INFO: { GError *error = NULL; gchar *debug; gst_message_parse_info (message, &error, &debug); gst_switchui_handle_info (switchui, error, debug); } break; case GST_MESSAGE_TAG: { GstTagList *tag_list; gst_message_parse_tag (message, &tag_list); if (verbose) g_print ("tag\n"); } break; case GST_MESSAGE_STATE_CHANGED: { GstState oldstate, newstate, pending; gst_message_parse_state_changed (message, &oldstate, &newstate, &pending); if (GST_ELEMENT (message->src) == switchui->pipeline) { if (verbose) g_print ("state change from %s to %s\n", gst_element_state_get_name (oldstate), gst_element_state_get_name (newstate)); switch (GST_STATE_TRANSITION (oldstate, newstate)) { case GST_STATE_CHANGE_NULL_TO_READY: gst_switchui_handle_null_to_ready (switchui); break; case GST_STATE_CHANGE_READY_TO_PAUSED: gst_switchui_handle_ready_to_paused (switchui); break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: gst_switchui_handle_paused_to_playing (switchui); break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED: gst_switchui_handle_playing_to_paused (switchui); break; case GST_STATE_CHANGE_PAUSED_TO_READY: gst_switchui_handle_paused_to_ready (switchui); break; case GST_STATE_CHANGE_READY_TO_NULL: gst_switchui_handle_ready_to_null (switchui); break; default: if (verbose) g_print ("unknown state change from %s to %s\n", gst_element_state_get_name (oldstate), gst_element_state_get_name (newstate)); } } } break; case GST_MESSAGE_BUFFERING: { int percent; gst_message_parse_buffering (message, &percent); //g_print("buffering %d\n", percent); if (!switchui->paused_for_buffering && percent < 100) { g_print ("pausing for buffing\n"); switchui->paused_for_buffering = TRUE; gst_element_set_state (switchui->pipeline, GST_STATE_PAUSED); } else if (switchui->paused_for_buffering && percent == 100) { g_print ("unpausing for buffing\n"); switchui->paused_for_buffering = FALSE; gst_element_set_state (switchui->pipeline, GST_STATE_PLAYING); } } break; case GST_MESSAGE_STATE_DIRTY: case GST_MESSAGE_CLOCK_PROVIDE: case GST_MESSAGE_CLOCK_LOST: case GST_MESSAGE_NEW_CLOCK: case GST_MESSAGE_STRUCTURE_CHANGE: case GST_MESSAGE_STREAM_STATUS: break; case GST_MESSAGE_STEP_DONE: case GST_MESSAGE_APPLICATION: case GST_MESSAGE_ELEMENT: case GST_MESSAGE_SEGMENT_START: case GST_MESSAGE_SEGMENT_DONE: //case GST_MESSAGE_DURATION: case GST_MESSAGE_LATENCY: case GST_MESSAGE_ASYNC_START: case GST_MESSAGE_ASYNC_DONE: case GST_MESSAGE_REQUEST_STATE: case GST_MESSAGE_STEP_START: case GST_MESSAGE_QOS: default: if (verbose) { g_print ("message: %s\n", GST_MESSAGE_TYPE_NAME (message)); } break; } return TRUE; }
static gboolean gst_PlayRegion_handle_message (GstBus * bus, GstMessage * message, gpointer data) { GstPlayRegion *PlayRegion = (GstPlayRegion *) data; switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_APPLICATION: if (gst_message_has_name (message, "ExPrerolled")) { /* it's our message */ g_print ("we are all prerolled, do seek\n"); gst_element_seek (PlayRegion->pipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, 2 * GST_SECOND, GST_SEEK_TYPE_SET, 5 * GST_SECOND); gst_element_set_state (PlayRegion->pipeline, GST_STATE_PLAYING); } break; case GST_MESSAGE_EOS: gst_PlayRegion_handle_eos (PlayRegion); break; case GST_MESSAGE_ERROR: { GError *error = NULL; gchar *debug; gst_message_parse_error (message, &error, &debug); gst_PlayRegion_handle_error (PlayRegion, error, debug); } break; case GST_MESSAGE_WARNING: { GError *error = NULL; gchar *debug; gst_message_parse_warning (message, &error, &debug); gst_PlayRegion_handle_warning (PlayRegion, error, debug); } break; case GST_MESSAGE_INFO: { GError *error = NULL; gchar *debug; gst_message_parse_info (message, &error, &debug); gst_PlayRegion_handle_info (PlayRegion, error, debug); } break; case GST_MESSAGE_TAG: { GstTagList *tag_list; gst_message_parse_tag (message, &tag_list); if (verbose) g_print ("tag\n"); } break; case GST_MESSAGE_STATE_CHANGED: { GstState oldstate, newstate, pending; gst_message_parse_state_changed (message, &oldstate, &newstate, &pending); if (GST_ELEMENT (message->src) == PlayRegion->pipeline) { if (verbose) g_print ("state change from %s to %s\n", gst_element_state_get_name (oldstate), gst_element_state_get_name (newstate)); switch (GST_STATE_TRANSITION (oldstate, newstate)) { case GST_STATE_CHANGE_NULL_TO_READY: gst_PlayRegion_handle_null_to_ready (PlayRegion); break; case GST_STATE_CHANGE_READY_TO_PAUSED: gst_PlayRegion_handle_ready_to_paused (PlayRegion); break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: gst_PlayRegion_handle_paused_to_playing (PlayRegion); break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED: gst_PlayRegion_handle_playing_to_paused (PlayRegion); break; case GST_STATE_CHANGE_PAUSED_TO_READY: gst_PlayRegion_handle_paused_to_ready (PlayRegion); break; case GST_STATE_CHANGE_READY_TO_NULL: gst_PlayRegion_handle_ready_to_null (PlayRegion); break; default: if (verbose) g_print ("unknown state change from %s to %s\n", gst_element_state_get_name (oldstate), gst_element_state_get_name (newstate)); } } } break; case GST_MESSAGE_BUFFERING: { int percent; gst_message_parse_buffering (message, &percent); //g_print("buffering %d\n", percent); if (!PlayRegion->paused_for_buffering && percent < 100) { g_print ("pausing for buffing\n"); PlayRegion->paused_for_buffering = TRUE; gst_element_set_state (PlayRegion->pipeline, GST_STATE_PAUSED); } else if (PlayRegion->paused_for_buffering && percent == 100) { g_print ("unpausing for buffing\n"); PlayRegion->paused_for_buffering = FALSE; gst_element_set_state (PlayRegion->pipeline, GST_STATE_PLAYING); } } break; case GST_MESSAGE_STATE_DIRTY: case GST_MESSAGE_CLOCK_PROVIDE: case GST_MESSAGE_CLOCK_LOST: case GST_MESSAGE_NEW_CLOCK: case GST_MESSAGE_STRUCTURE_CHANGE: case GST_MESSAGE_STREAM_STATUS: break; case GST_MESSAGE_STEP_DONE: case GST_MESSAGE_ELEMENT: case GST_MESSAGE_SEGMENT_START: case GST_MESSAGE_SEGMENT_DONE: case GST_MESSAGE_DURATION: case GST_MESSAGE_LATENCY: case GST_MESSAGE_ASYNC_START: case GST_MESSAGE_ASYNC_DONE: case GST_MESSAGE_REQUEST_STATE: case GST_MESSAGE_STEP_START: case GST_MESSAGE_QOS: default: if (verbose) { g_print ("message: %s\n", GST_MESSAGE_TYPE_NAME (message)); } break; } return TRUE; }