void NWaveformBuilderGstreamer::update() { GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(m_playbin)); GstMessage *msg = gst_bus_pop_filtered(bus, GstMessageType(GST_MESSAGE_EOS | GST_MESSAGE_ERROR)); if (msg) { switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_EOS: peaks()->complete(); #if defined(QT_DEBUG) && !defined(QT_NO_DEBUG) qDebug() << "WaveformBuilder ::" << "completed" << peaks()->size(); #endif stop(); break; case GST_MESSAGE_ERROR: #if defined(QT_DEBUG) && !defined(QT_NO_DEBUG) gchar *debug; GError *err = NULL; gst_message_parse_error(msg, &err, &debug); g_free(debug); qWarning() << "WaveformBuilder :: error ::" << QString::fromUtf8(err->message); if (err) g_error_free(err); #endif break; default: break; } gst_message_unref(msg); } gst_object_unref(bus); }
static void check_get_dtmf_event_message (GstBus * bus, gint number, gint volume) { GstMessage *message; gboolean have_message = FALSE; while (!have_message && (message = gst_bus_pop_filtered (bus, GST_MESSAGE_ELEMENT)) != NULL) { if (gst_message_has_name (message, "dtmf-event")) { const GstStructure *s = gst_message_get_structure (message); gint stype, snumber, smethod, svolume; fail_unless (gst_structure_get (s, "type", G_TYPE_INT, &stype, "number", G_TYPE_INT, &snumber, "method", G_TYPE_INT, &smethod, "volume", G_TYPE_INT, &svolume, NULL)); fail_unless (stype == 1); fail_unless (smethod == 1); fail_unless (snumber == number); fail_unless (svolume == volume); have_message = TRUE; } gst_message_unref (message); } fail_unless (have_message); }
CAMLprim value ocaml_gstreamer_bus_pop_filtered(value _bus, value _filter) { CAMLparam2(_bus, _filter); CAMLlocal1(ans); GstBus *bus = Bus_val(_bus); GstMessageType filter = 0; GstMessage *msg; int i; for(i = 0; i < Wosize_val(_filter); i++) filter |= message_type_of_int(Int_val(Field(_filter, i))); caml_release_runtime_system(); msg = gst_bus_pop_filtered(bus, filter); caml_acquire_runtime_system(); if(!msg) ans = Val_int(0); else { ans = caml_alloc_tuple(1); Store_field(ans, 0, value_of_message(msg)); } CAMLreturn(ans); }
bool tcStreamWrapper::end_of_stream() { if(mpPLine == NULL) return false; #ifndef WIN32 return mpPLine->endofstream; #else // Windows Qt doesn't hook into the gst main loop // so we need to poll it and see if there is an // end of line message posted GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(mpPLine->pipeline)); return gst_bus_pop_filtered(bus, GST_MESSAGE_EOS) != NULL; #endif }
static void check_no_dtmf_event_message (GstBus * bus) { GstMessage *message; gboolean have_message = FALSE; while (!have_message && (message = gst_bus_pop_filtered (bus, GST_MESSAGE_ELEMENT)) != NULL) { if (gst_message_has_name (message, "dtmf-event") || gst_message_has_name (message, "dtmf-event-processed") || gst_message_has_name (message, "dtmf-event-dropped")) { have_message = TRUE; } gst_message_unref (message); } fail_unless (!have_message); }
/* * cheese_camera_device_get_caps: * @device: a #CheeseCameraDevice * * Probe the #GstCaps that the @device supports. */ static void cheese_camera_device_get_caps (CheeseCameraDevice *device) { CheeseCameraDevicePrivate *priv = device->priv; gchar *pipeline_desc; GstElement *pipeline; GstStateChangeReturn ret; GstMessage *msg; GstBus *bus; GError *err = NULL; pipeline_desc = g_strdup_printf ("%s name=source device=%s ! fakesink", priv->src, priv->device_node); pipeline = gst_parse_launch (pipeline_desc, &err); if ((pipeline != NULL) && (err == NULL)) { /* Start the pipeline and wait for max. 10 seconds for it to start up */ gst_element_set_state (pipeline, GST_STATE_READY); ret = gst_element_get_state (pipeline, NULL, NULL, 10 * GST_SECOND); /* Check if any error messages were posted on the bus */ bus = gst_element_get_bus (pipeline); msg = gst_bus_pop_filtered (bus, GST_MESSAGE_ERROR); gst_object_unref (bus); if ((msg == NULL) && (ret == GST_STATE_CHANGE_SUCCESS)) { GstElement *src; GstPad *pad; GstCaps *caps; src = gst_bin_get_by_name (GST_BIN (pipeline), "source"); GST_LOG ("Device: %s (%s)\n", priv->name, priv->device_node); pad = gst_element_get_static_pad (src, "src"); caps = gst_pad_get_allowed_caps (pad); gst_caps_unref (priv->caps); priv->caps = cheese_camera_device_filter_caps (device, caps, supported_formats); if (!gst_caps_is_empty (priv->caps)) cheese_camera_device_update_format_table (device); else { g_set_error_literal (&priv->construct_error, CHEESE_CAMERA_DEVICE_ERROR, CHEESE_CAMERA_DEVICE_ERROR_UNSUPPORTED_CAPS, _("Device capabilities not supported")); } gst_object_unref (pad); gst_caps_unref (caps); gst_object_unref (src); } else { if (msg) { gchar *dbg_info = NULL; gst_message_parse_error (msg, &err, &dbg_info); GST_WARNING ("Failed to start the capability probing pipeline"); GST_WARNING ("Error from element %s: %s, %s", GST_OBJECT_NAME (msg->src), err->message, (dbg_info) ? dbg_info : "no extra debug detail"); g_error_free (err); err = NULL; /* construct_error is meant to be displayed in the UI * (although it currently isn't displayed in cheese), * err->message from gstreamer is too technical for this * purpose, the idea is warn the user about an error and point * him to the logs for more info */ g_set_error (&priv->construct_error, CHEESE_CAMERA_DEVICE_ERROR, CHEESE_CAMERA_DEVICE_ERROR_FAILED_INITIALIZATION, _("Failed to initialize device %s for capability probing"), priv->device_node); } } gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); } if (err) g_error_free (err); g_free (pipeline_desc); }
static GstElement * gst_auto_video_src_find_best (GstAutoVideoSrc * src) { GList *list, *item; GstElement *choice = NULL; GstMessage *message = NULL; GSList *errors = NULL; GstBus *bus = gst_bus_new (); GstPad *el_pad = NULL; GstCaps *el_caps = NULL, *intersect = NULL; gboolean no_match = TRUE; list = gst_registry_feature_filter (gst_registry_get_default (), (GstPluginFeatureFilter) gst_auto_video_src_factory_filter, FALSE, src); list = g_list_sort (list, (GCompareFunc) gst_auto_video_src_compare_ranks); GST_LOG_OBJECT (src, "Trying to find usable video devices ..."); for (item = list; item != NULL; item = item->next) { GstElementFactory *f = GST_ELEMENT_FACTORY (item->data); GstElement *el; if ((el = gst_auto_video_src_create_element_with_pretty_name (src, f))) { GstStateChangeReturn ret; GST_DEBUG_OBJECT (src, "Testing %s", GST_PLUGIN_FEATURE (f)->name); /* If AutoVideoSrc has been provided with filter caps, * accept only sources that match with the filter caps */ if (src->filter_caps) { el_pad = gst_element_get_static_pad (GST_ELEMENT (el), "src"); el_caps = gst_pad_get_caps (el_pad); gst_object_unref (el_pad); GST_DEBUG_OBJECT (src, "Checking caps: %" GST_PTR_FORMAT " vs. %" GST_PTR_FORMAT, src->filter_caps, el_caps); intersect = gst_caps_intersect (src->filter_caps, el_caps); no_match = gst_caps_is_empty (intersect); gst_caps_unref (el_caps); gst_caps_unref (intersect); if (no_match) { GST_DEBUG_OBJECT (src, "Incompatible caps"); gst_object_unref (el); continue; } else { GST_DEBUG_OBJECT (src, "Found compatible caps"); } } gst_element_set_bus (el, bus); ret = gst_element_set_state (el, GST_STATE_READY); if (ret == GST_STATE_CHANGE_SUCCESS) { GST_DEBUG_OBJECT (src, "This worked!"); choice = el; break; } /* collect all error messages */ while ((message = gst_bus_pop_filtered (bus, GST_MESSAGE_ERROR))) { GST_DEBUG_OBJECT (src, "error message %" GST_PTR_FORMAT, message); errors = g_slist_append (errors, message); } gst_element_set_state (el, GST_STATE_NULL); gst_object_unref (el); } } GST_DEBUG_OBJECT (src, "done trying"); if (!choice) { if (errors) { /* FIXME: we forward the first error for now; but later on it might make * sense to actually analyse them */ gst_message_ref (GST_MESSAGE (errors->data)); GST_DEBUG_OBJECT (src, "reposting message %p", errors->data); gst_element_post_message (GST_ELEMENT (src), GST_MESSAGE (errors->data)); } else { /* send warning message to application and use a fakesrc */ GST_ELEMENT_WARNING (src, RESOURCE, NOT_FOUND, (NULL), ("Failed to find a usable video source")); choice = gst_element_factory_make ("fakesrc", "fake-video-src"); if (g_object_class_find_property (G_OBJECT_GET_CLASS (choice), "sync")) g_object_set (choice, "sync", TRUE, NULL); gst_element_set_state (choice, GST_STATE_READY); } } gst_object_unref (bus); gst_plugin_feature_list_free (list); g_slist_foreach (errors, (GFunc) gst_mini_object_unref, NULL); g_slist_free (errors); return choice; }
void NPlaybackEngineGStreamer::checkStatus() { GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(m_playbin)); GstMessage *msg; while ((msg = gst_bus_pop_filtered(bus, GstMessageType(GST_MESSAGE_EOS | GST_MESSAGE_ERROR))) != NULL) { switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_EOS: { stop(); emit finished(); emit stateChanged(m_oldState = N::PlaybackStopped); break; } case GST_MESSAGE_ERROR: { gchar *debug; GError *err = NULL; gst_message_parse_error(msg, &err, &debug); g_free(debug); emit message(QMessageBox::Critical, QFileInfo(m_currentMedia).absoluteFilePath(), err ? QString::fromUtf8(err->message) : "unknown error"); fail(); if (err) g_error_free(err); break; } default: break; } gst_message_unref(msg); } gst_object_unref(bus); GstState gstState; if (gst_element_get_state(m_playbin, &gstState, NULL, 0) != GST_STATE_CHANGE_SUCCESS) return; N::PlaybackState state = fromGstState(gstState); if (m_oldState != state) emit stateChanged(m_oldState = state); if (state == N::PlaybackPlaying || state == N::PlaybackPaused) { // duration may change for some reason // TODO use DURATION_CHANGED in gstreamer1.0 gboolean res = gst_element_query_duration(m_playbin, GST_FORMAT_TIME, &m_durationNsec); if (!res) m_durationNsec = 0; } if (m_posponedPosition >= 0 && m_durationNsec > 0) { setPosition(m_posponedPosition); m_posponedPosition = -1; emit positionChanged(m_posponedPosition); } else { qreal pos; gint64 gstPos = 0; if (!hasMedia() || m_durationNsec <= 0) { pos = -1; } else { gboolean res = gst_element_query_position(m_playbin, GST_FORMAT_TIME, &gstPos); if (!res) gstPos = 0; pos = (qreal)gstPos / m_durationNsec; } if (m_oldPosition != pos) { if (m_oldPosition > pos) m_crossfading = false; m_oldPosition = pos; emit positionChanged(m_crossfading ? 0 : m_oldPosition); } emit tick(m_crossfading ? 0 : gstPos / NSEC_IN_MSEC); } qreal vol = volume(); if (qAbs(m_oldVolume - vol) > 0.0001) { m_oldVolume = vol; emit volumeChanged(vol); } if (state == N::PlaybackStopped) m_timer->stop(); }
static gboolean gst_switch_commit_new_kid (GstSwitchSink * sink) { GstPad *targetpad; GstState kid_state; GstElement *new_kid, *old_kid; gboolean is_fakesink = FALSE; GstBus *bus; /* need locking around member accesses */ GST_OBJECT_LOCK (sink); /* If we're currently changing state, set the child to the next state * we're transitioning too, rather than our current state which is * about to change */ if (GST_STATE_NEXT (sink) != GST_STATE_VOID_PENDING) kid_state = GST_STATE_NEXT (sink); else kid_state = GST_STATE (sink); new_kid = sink->new_kid; sink->new_kid = NULL; GST_OBJECT_UNLOCK (sink); /* Fakesink by default if NULL is passed as the new child */ if (new_kid == NULL) { GST_DEBUG_OBJECT (sink, "Replacing kid with fakesink"); new_kid = gst_element_factory_make ("fakesink", "testsink"); if (new_kid == NULL) { GST_ERROR_OBJECT (sink, "Failed to create fakesink"); return FALSE; } /* Add a reference, as it would if the element came from sink->new_kid */ gst_object_ref (new_kid); g_object_set (new_kid, "sync", TRUE, NULL); is_fakesink = TRUE; } else { GST_DEBUG_OBJECT (sink, "Setting new kid"); } /* set temporary bus of our own to catch error messages from the child * (could we just set our own bus on it, or would the state change messages * from the not-yet-added element confuse the state change algorithm? Let's * play it safe for now) */ bus = gst_bus_new (); gst_element_set_bus (new_kid, bus); gst_object_unref (bus); if (gst_element_set_state (new_kid, kid_state) == GST_STATE_CHANGE_FAILURE) { GstMessage *msg; /* check if child posted an error message and if so re-post it on our bus * so that the application gets to see a decent error and not our generic * fallback error message which is completely indecipherable to the user */ msg = gst_bus_pop_filtered (GST_ELEMENT_BUS (new_kid), GST_MESSAGE_ERROR); if (msg) { GST_INFO_OBJECT (sink, "Forwarding kid error: %" GST_PTR_FORMAT, msg); gst_element_post_message (GST_ELEMENT (sink), msg); } /* FIXME: need a translated error message that tells the user to check * her GConf audio/video settings */ GST_ELEMENT_ERROR (sink, CORE, STATE_CHANGE, (NULL), ("Failed to set state on new child.")); gst_element_set_bus (new_kid, NULL); gst_object_unref (new_kid); return FALSE; } gst_element_set_bus (new_kid, NULL); gst_bin_add (GST_BIN (sink), new_kid); /* Now, replace the existing child */ GST_OBJECT_LOCK (sink); old_kid = sink->kid; sink->kid = new_kid; /* Mark whether a custom kid or fakesink has been installed */ sink->have_kid = !is_fakesink; GST_OBJECT_UNLOCK (sink); /* kill old element */ if (old_kid) { GST_DEBUG_OBJECT (sink, "Removing old kid %" GST_PTR_FORMAT, old_kid); gst_element_set_state (old_kid, GST_STATE_NULL); gst_bin_remove (GST_BIN (sink), old_kid); gst_object_unref (old_kid); } /* re-attach ghostpad */ GST_DEBUG_OBJECT (sink, "Creating new ghostpad"); targetpad = gst_element_get_static_pad (sink->kid, "sink"); gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad); gst_object_unref (targetpad); GST_DEBUG_OBJECT (sink, "done changing child of switchsink"); /* FIXME: Push new-segment info and pre-roll buffer(s) into the kid */ /* Unblock the target pad if necessary */ if (sink->awaiting_block) { gst_pad_set_blocked (sink->pad, FALSE); sink->awaiting_block = FALSE; } return TRUE; }
/* Decode */ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { block_t *p_block; picture_t *p_pic = NULL; decoder_sys_t *p_sys = p_dec->p_sys; GstMessage *p_msg; GstBuffer *p_buf; if( !pp_block ) return NULL; p_block = *pp_block; if( !p_block ) goto check_messages; if( unlikely( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED ) ) ) { if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) Flush( p_dec ); if( p_block->i_flags & BLOCK_FLAG_CORRUPTED ) { block_Release( p_block ); goto done; } } if( likely( p_block->i_buffer ) ) { p_buf = gst_buffer_new_wrapped_full( GST_MEMORY_FLAG_READONLY, p_block->p_start, p_block->i_size, p_block->p_buffer - p_block->p_start, p_block->i_buffer, p_block, ( GDestroyNotify )block_Release ); if( unlikely( p_buf == NULL ) ) { msg_Err( p_dec, "failed to create input gstbuffer" ); p_dec->b_error = true; block_Release( p_block ); goto done; } if( p_block->i_dts > VLC_TS_INVALID ) GST_BUFFER_DTS( p_buf ) = gst_util_uint64_scale( p_block->i_dts, GST_SECOND, GST_MSECOND ); if( p_block->i_pts <= VLC_TS_INVALID ) GST_BUFFER_PTS( p_buf ) = GST_BUFFER_DTS( p_buf ); else GST_BUFFER_PTS( p_buf ) = gst_util_uint64_scale( p_block->i_pts, GST_SECOND, GST_MSECOND ); if( p_block->i_length > VLC_TS_INVALID ) GST_BUFFER_DURATION( p_buf ) = gst_util_uint64_scale( p_block->i_length, GST_SECOND, GST_MSECOND ); if( p_dec->fmt_in.video.i_frame_rate && p_dec->fmt_in.video.i_frame_rate_base ) GST_BUFFER_DURATION( p_buf ) = gst_util_uint64_scale( GST_SECOND, p_dec->fmt_in.video.i_frame_rate_base, p_dec->fmt_in.video.i_frame_rate ); /* Give the input buffer to GStreamer Bin. * * libvlc libvlc * \ (i/p) (o/p) ^ * \ / * ___v____GSTREAMER BIN_____/____ * | | * | appsrc-->decode-->vlcsink | * |_______________________________| * * * * * * * * * * * * * * * * * * * * * */ if( unlikely( gst_app_src_push_buffer( GST_APP_SRC_CAST( p_sys->p_decode_src ), p_buf ) != GST_FLOW_OK ) ) { /* block will be released internally, * when gst_buffer_unref() is called */ p_dec->b_error = true; msg_Err( p_dec, "failed to push buffer" ); goto done; } } else block_Release( p_block ); check_messages: /* Poll for any messages, errors */ p_msg = gst_bus_pop_filtered( p_sys->p_bus, GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_ERROR | GST_MESSAGE_EOS | GST_MESSAGE_WARNING | GST_MESSAGE_INFO ); if( p_msg ) { switch( GST_MESSAGE_TYPE( p_msg ) ){ case GST_MESSAGE_EOS: /* for debugging purpose */ msg_Warn( p_dec, "got unexpected eos" ); break; /* First buffer received */ case GST_MESSAGE_ASYNC_DONE: /* for debugging purpose */ p_sys->b_prerolled = true; msg_Dbg( p_dec, "Pipeline is prerolled" ); break; default: p_dec->b_error = default_msg_handler( p_dec, p_msg ); if( p_dec->b_error ) { gst_message_unref( p_msg ); goto done; } break; } gst_message_unref( p_msg ); } /* Look for any output buffers in the queue */ if( gst_atomic_queue_peek( p_sys->p_que ) ) { GstBuffer *p_buf = GST_BUFFER_CAST( gst_atomic_queue_pop( p_sys->p_que )); GstMemory *p_mem; if(( p_mem = gst_buffer_peek_memory( p_buf, 0 )) && GST_IS_VLC_PICTURE_PLANE_ALLOCATOR( p_mem->allocator )) { p_pic = picture_Hold(( (GstVlcPicturePlane*) p_mem )->p_pic ); } else { GstVideoFrame frame; /* Get a new picture */ p_pic = decoder_NewPicture( p_dec ); if( !p_pic ) goto done; if( unlikely( !gst_video_frame_map( &frame, &p_sys->vinfo, p_buf, GST_MAP_READ ) ) ) { msg_Err( p_dec, "failed to map gst video frame" ); gst_buffer_unref( p_buf ); p_dec->b_error = true; goto done; } gst_CopyPicture( p_pic, &frame ); gst_video_frame_unmap( &frame ); } if( likely( GST_BUFFER_PTS_IS_VALID( p_buf ) ) ) p_pic->date = gst_util_uint64_scale( GST_BUFFER_PTS( p_buf ), GST_MSECOND, GST_SECOND ); else msg_Warn( p_dec, "Gst Buffer has no timestamp" ); gst_buffer_unref( p_buf ); } done: *pp_block = NULL; return p_pic; }
static GstElement * gst_auto_audio_sink_find_best (GstAutoAudioSink * sink) { GList *list, *item; GstElement *choice = NULL; GstMessage *message = NULL; GSList *errors = NULL; GstBus *bus = gst_bus_new (); GstPad *el_pad = NULL; GstCaps *el_caps = NULL; gboolean no_match = TRUE; list = gst_registry_feature_filter (gst_registry_get (), (GstPluginFeatureFilter) gst_auto_audio_sink_factory_filter, FALSE, sink); list = g_list_sort (list, (GCompareFunc) gst_auto_audio_sink_compare_ranks); /* We don't treat sound server sinks special. Our policy is that sound * server sinks that have a rank must not auto-spawn a daemon under any * circumstances, so there's nothing for us to worry about here */ GST_LOG_OBJECT (sink, "Trying to find usable audio devices ..."); for (item = list; item != NULL; item = item->next) { GstElementFactory *f = GST_ELEMENT_FACTORY (item->data); GstElement *el; if ((el = gst_auto_audio_sink_create_element_with_pretty_name (sink, f))) { GstStateChangeReturn ret; GST_DEBUG_OBJECT (sink, "Testing %s", GST_OBJECT_NAME (f)); /* If autoaudiosink has been provided with filter caps, * accept only sinks that match with the filter caps */ if (sink->filter_caps) { el_pad = gst_element_get_static_pad (GST_ELEMENT (el), "sink"); el_caps = gst_pad_query_caps (el_pad, NULL); gst_object_unref (el_pad); GST_DEBUG_OBJECT (sink, "Checking caps: %" GST_PTR_FORMAT " vs. %" GST_PTR_FORMAT, sink->filter_caps, el_caps); no_match = !gst_caps_can_intersect (sink->filter_caps, el_caps); gst_caps_unref (el_caps); if (no_match) { GST_DEBUG_OBJECT (sink, "Incompatible caps"); gst_object_unref (el); continue; } else { GST_DEBUG_OBJECT (sink, "Found compatible caps"); } } gst_element_set_bus (el, bus); ret = gst_element_set_state (el, GST_STATE_READY); if (ret == GST_STATE_CHANGE_SUCCESS) { GST_DEBUG_OBJECT (sink, "This worked!"); choice = el; break; } /* collect all error messages */ while ((message = gst_bus_pop_filtered (bus, GST_MESSAGE_ERROR))) { GST_DEBUG_OBJECT (sink, "error message %" GST_PTR_FORMAT, message); errors = g_slist_append (errors, message); } gst_element_set_state (el, GST_STATE_NULL); gst_object_unref (el); } } GST_DEBUG_OBJECT (sink, "done trying"); if (!choice) { if (errors) { /* FIXME: we forward the first error for now; but later on it might make * sense to actually analyse them */ gst_message_ref (GST_MESSAGE (errors->data)); GST_DEBUG_OBJECT (sink, "reposting message %p", errors->data); gst_element_post_message (GST_ELEMENT (sink), GST_MESSAGE (errors->data)); } else { /* send warning message to application and use a fakesink */ GST_ELEMENT_WARNING (sink, RESOURCE, NOT_FOUND, (NULL), ("Failed to find a usable audio sink")); choice = gst_element_factory_make ("fakesink", "fake-audio-sink"); if (g_object_class_find_property (G_OBJECT_GET_CLASS (choice), "sync")) g_object_set (choice, "sync", TRUE, NULL); gst_element_set_state (choice, GST_STATE_READY); } } gst_object_unref (bus); gst_plugin_feature_list_free (list); g_slist_foreach (errors, (GFunc) gst_mini_object_unref, NULL); g_slist_free (errors); return choice; }
int main (int argc, char *argv[]) { GstNetClientInternalClock *clock; GstBus *bus; GIOChannel *channel; GIOStatus status; GError *error = NULL; GOptionContext *context; gchar *line; int ret = 1; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); g_option_context_add_group (context, gst_init_get_option_group ()); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_print ("Failed to parse options: %s\n\n", error->message); g_error_free (error); return 1; } if (input) { if (!(channel = g_io_channel_new_file (input, "r", NULL))) { g_print ("Could not read input file: %s\n", input); return 1; } } else { if (!(channel = g_io_channel_unix_new (0))) { g_print ("Could not read stdin"); return 1; } } clock = g_object_new (GST_TYPE_NET_CLIENT_INTERNAL_CLOCK, NULL); bus = gst_bus_new (); /* FIXME: Find a way to do this without touching the structure internals */ if (rtt_limit) clock->roundtrip_limit = rtt_limit * GST_MSECOND; clock->busses = g_list_prepend (clock->busses, bus); while ((status = g_io_channel_read_line (channel, &line, NULL, NULL, &error)) == G_IO_STATUS_NORMAL) { GstClockTime local_1, local_2, remote_1, remote_2; GstMessage *message; if (sscanf (line, "%" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT, &local_1, &remote_1, &remote_2, &local_2) != 4) { g_print ("Failed to get local/remote time values from: %s\n", line); goto done; } if (debug) g_print ("%s", line); gst_net_client_internal_clock_observe_times (clock, local_1, remote_1, remote_2, local_2); g_free (line); if ((message = gst_bus_pop_filtered (bus, GST_MESSAGE_ELEMENT))) { const GstStructure *st; gchar *str; st = gst_message_get_structure (message); str = gst_structure_to_string (st); g_print ("%s\n", str); g_free (str); gst_message_unref (message); } } if (status == G_IO_CHANNEL_ERROR) { g_print ("Error reading file: %s\n", error->message); g_error_free (error); goto done; } g_io_channel_unref (channel); g_free (input); gst_object_unref (bus); ret = 0; done: return ret; }