示例#1
0
static void
on_pad_added (GstElement * element, GstPad * pad, GstElement * pipeline)
{
  GstElement *ipcpipelinesink;
  GstPad *sinkpad;
  GstCaps *caps;
  const GstStructure *structure;
  GstIterator *it;
  GValue elem = G_VALUE_INIT;
  int sockets[2];
  gboolean create_sockets;

  caps = gst_pad_get_current_caps (pad);
  structure = gst_caps_get_structure (caps, 0);

  it = gst_bin_iterate_sinks (GST_BIN (pipeline));
  if (gst_iterator_find_custom (it, find_ipcpipelinesink, &elem,
          (gpointer) gst_structure_get_name (structure))) {
    ipcpipelinesink = g_value_get_object (&elem);
    create_sockets = FALSE;
    g_value_reset (&elem);
  } else {
    ipcpipelinesink = gst_element_factory_make ("ipcpipelinesink", NULL);
    gst_bin_add (GST_BIN (pipeline), ipcpipelinesink);
    create_sockets = TRUE;
  }

  sinkpad = gst_element_get_static_pad (ipcpipelinesink, "sink");
  if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK) {
    fprintf (stderr, "Failed to link ipcpipelinesink\n");
    exit (1);
  }
  gst_object_unref (sinkpad);

  g_signal_connect (pad, "unlinked", (GCallback) on_pad_unlinked, pipeline);

  if (create_sockets) {
    if (socketpair (AF_UNIX, SOCK_STREAM, 0, sockets)) {
      fprintf (stderr, "Error creating sockets: %s\n", strerror (errno));
      exit (1);
    }
    if (fcntl (sockets[0], F_SETFL, O_NONBLOCK) < 0 ||
        fcntl (sockets[1], F_SETFL, O_NONBLOCK) < 0) {
      fprintf (stderr, "Error setting O_NONBLOCK on sockets: %s\n",
          strerror (errno));
      exit (1);
    }
    g_object_set (ipcpipelinesink, "fdin", sockets[0], "fdout", sockets[0],
        NULL);

    printf ("new socket %d\n", sockets[1]);
    sendfd (pipes[1], sockets[1]);
  }

  gst_element_set_state (ipcpipelinesink, GST_STATE_PLAYING);

  GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
      GST_DEBUG_GRAPH_SHOW_ALL, "pad.added");
}
示例#2
0
static GstElement *
find_composition (GESTrack * track)
{
  GstIterator *it = gst_bin_iterate_recurse (GST_BIN (track));
  GValue val = { 0, };
  GstElement *ret = NULL;

  if (gst_iterator_find_custom (it, (GCompareFunc) find_composition_func, &val,
          NULL))
    ret = g_value_get_object (&val);

  g_value_unset (&val);
  gst_iterator_free (it);

  return ret;
}
示例#3
0
文件: utility.cpp 项目: dv1/nxplay
GstElement *find_element_by_factory_name(GstBin *p_bin, std::string const &p_factory_name)
{
	GstIterator *iter = gst_bin_iterate_recurse(p_bin);
	if (iter == nullptr)
		return nullptr;

	GValue result = G_VALUE_INIT;
	gboolean found = gst_iterator_find_custom(iter, find_by_factory_func, &result, (gpointer)(&p_factory_name));
	gst_iterator_free(iter);

	if (found)
	{
		GstElement *elem = GST_ELEMENT(g_value_dup_object(&result));
		g_value_unset(&result);
		return elem;
	}
	else
		return nullptr;
}
GstElement *
rb_player_gst_find_element_with_property (GstElement *element, const char *property)
{
	GstIterator *iter;
	GstElement *result;

	if (GST_IS_BIN (element) == FALSE) {
		if (g_object_class_find_property (G_OBJECT_GET_CLASS (element),
						  property) != NULL) {
			return g_object_ref (element);
		}
		return NULL;
	}

	rb_debug ("iterating bin looking for property %s", property);
	iter = gst_bin_iterate_recurse (GST_BIN (element));
	result = gst_iterator_find_custom (iter,
					   (GCompareFunc) find_property_element,
					   (gpointer) property);
	gst_iterator_free (iter);
	return result;
}
static void
suboverlay_child_added_cb (GstElement * suboverlay, GstElement * child,
    InsanityTest * test)
{
  GstIterator *it = NULL;
  GstPad *render_sub_sink, *tmppad;
  GstElementFactory *fact;
  const gchar *klass, *name;
  gulong probe_id;
  GValue value = { 0, };

  gboolean is_renderer = FALSE;


  /* cc-ed from -base/gstsubtitleoveraly.c */
  fact = gst_element_get_factory (child);
  klass = gst_element_factory_get_metadata (fact, GST_ELEMENT_METADATA_KLASS);

  if (GST_IS_BIN (child))
    return;

  name = gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (fact));

  if (g_strrstr (klass, "Overlay/Subtitle") != NULL ||
      g_strrstr (klass, "Overlay/SubPicture") != NULL)
    is_renderer = TRUE;

  else if (g_strcmp0 (name, "textoverlay") == 0)
    is_renderer = TRUE;

  if (is_renderer == FALSE)
    goto done;

  LOG (test, "Renderer found: %s", name);

  /* Now adding the probe to the renderer "subtitle" sink pad */
  it = gst_element_iterate_sink_pads (child);
  if (gst_iterator_find_custom (it,
          (GCompareFunc) find_renderer_subtitle_sinkpad, &value, NULL)) {
    render_sub_sink = g_value_get_object (&value);
  } else {
    goto done;
  }

  if (insanity_gst_test_add_data_probe (INSANITY_GST_TEST (test),
          GST_BIN (glob_pipeline), GST_OBJECT_NAME (child),
          GST_ELEMENT_NAME (render_sub_sink), &tmppad, &probe_id,
          &renderer_probe_cb, NULL, NULL) == TRUE) {

    glob_renderer_sink_probe = g_slice_new0 (ProbeContext);
    glob_renderer_sink_probe->probe_id = probe_id;
    glob_renderer_sink_probe->pad = render_sub_sink;
    glob_renderer_sink_probe->element = child;
    glob_renderer_sink_probe->test = test;
    glob_renderer_sink_probe->waiting_first_segment = TRUE;

    insanity_test_validate_checklist_item (test, "install-probes", TRUE, NULL);
  } else {
    insanity_test_validate_checklist_item (test, "install-probes", FALSE,
        "Failed to attach probe to fakesink");
    insanity_test_done (test);

    goto done;
  }

done:
  if (it)
    gst_iterator_free (it);

}
static gboolean
validate_codec_profile (FsCodec *codec,const gchar *bin_description,
    gboolean is_send)
{
  GError *error = NULL;
  GstElement *bin = NULL;
  guint src_pad_count = 0, sink_pad_count = 0;
  GstCaps *caps;
  gpointer matching_pad = NULL;
  GstIterator *iter;

  bin = parse_bin_from_description_all_linked (bin_description,
      &src_pad_count, &sink_pad_count, &error);

  /* if could not build bin, fail */
  if (!bin)
  {
    GST_WARNING ("Could not build profile (%s): %s", bin_description,
        error->message);
    g_clear_error (&error);
    return FALSE;
  }
  g_clear_error (&error);

  caps = fs_codec_to_gst_caps (codec);

  if (is_send)
    iter = gst_element_iterate_src_pads (bin);
  else
    iter = gst_element_iterate_sink_pads (bin);

  matching_pad = gst_iterator_find_custom (iter, find_matching_pad, caps);
  gst_iterator_free (iter);

  if (!matching_pad)
  {
    GST_WARNING ("Invalid profile (%s), has no %s pad that matches the codec"
        " details", is_send ? "src" : "sink", bin_description);
    gst_caps_unref (caps);
    gst_object_unref (bin);
    return FALSE;
  }

  gst_caps_unref (caps);
  gst_object_unref (bin);

  if (is_send)
  {
    if (src_pad_count == 0)
    {
      GST_WARNING ("Invalid profile (%s), has 0 src pad", bin_description);
      return FALSE;
    }
  }
  else
  {
    if (src_pad_count != 1)
    {
      GST_WARNING ("Invalid profile (%s), has %u src pads, should have one",
          bin_description, src_pad_count);
      return FALSE;
    }
  }

  if (sink_pad_count != 1)
  {
    GST_WARNING ("Invalid profile (%s), has %u sink pads, should have one",
        bin_description, sink_pad_count);
    return FALSE;
  }

  return TRUE;
}
static gboolean
hls_test_bus_message (InsanityGstPipelineTest * ptest, GstMessage * msg)
{
  switch (GST_MESSAGE_TYPE (msg)) {
    case GST_MESSAGE_BUFFERING:
    {
      gint per;

      gst_message_parse_buffering (msg, &per);

      /* First buffering happend properly, this is requiered to be able to
       * start seeking */
      if (G_UNLIKELY (glob_buffered == FALSE)) {
        if (per == 100) {
          insanity_test_validate_checklist_item (INSANITY_TEST (ptest),
              "done-buffering", TRUE, NULL);
          glob_buffered = TRUE;

          if (glob_buffering_timeout != 0) {
            g_source_remove (glob_buffering_timeout);
            glob_buffering_timeout = 0;
          }
        } else {
          glob_buffering_timeout = g_timeout_add (250,
              (GSourceFunc) buffering_timeout, INSANITY_TEST (ptest));
        }
      }

      break;
    }
    case GST_MESSAGE_STATE_CHANGED:
      if (GST_MESSAGE_SRC (msg) == GST_OBJECT (glob_pipeline)) {
        const char *validate_checklist_item = glob_validate_on_playing;
        GstState oldstate, newstate, pending;

        gst_message_parse_state_changed (msg, &oldstate, &newstate, &pending);
        if (newstate == GST_STATE_PAUSED && oldstate == GST_STATE_READY) {
          GstIterator *it;
          GValue v = { 0, };
          gboolean queried;
          InsanityTest *test = INSANITY_TEST (ptest);
          GstQuery *query = gst_query_new_latency ();
          const gchar *step_message = "Could not query seeking\n";

          if ((queried = gst_element_query (glob_pipeline, query))) {
            gst_query_parse_latency (query, &glob_is_live, NULL, NULL);
            step_message = NULL;
          } else
            insanity_test_printf (test, "Could not query\n");

          insanity_gst_pipeline_test_set_live (ptest, glob_is_live);
          insanity_test_validate_checklist_item (test, "queried-live", queried,
              step_message);
          gst_query_unref (query);

          step_message = "Could not query seekable\n";
          query = gst_query_new_seeking (GST_FORMAT_TIME);
          if ((queried = gst_element_query (glob_pipeline, query))) {
            gst_query_parse_seeking (query, NULL, &glob_is_seekable, NULL,
                NULL);
            step_message = NULL;
          } else
            insanity_test_printf (test, "Could not query\n");

          insanity_test_validate_checklist_item (test, "queried-seekable",
              queried, step_message);
          gst_query_unref (query);

          /* Iterate over the bins to find a hlsdemux */
          it = gst_bin_iterate_recurse (GST_BIN (glob_pipeline));
          if (gst_iterator_find_custom (it, (GCompareFunc) find_hlsdemux, &v,
                  NULL)) {
            glob_hlsdemux = g_value_dup_object (&v);
          }
          g_value_unset (&v);
          gst_iterator_free (it);

          if (glob_hlsdemux != NULL) {
            insanity_test_validate_checklist_item (test, "protocol-is-hls",
                TRUE, "HLS protocol in use");

            gst_object_unref (glob_hlsdemux);
          } else {
            insanity_test_validate_checklist_item (test, "protocol-is-hls",
                FALSE, "HLS protocol in use");
            insanity_test_done (test);
          }

          /* Watch pipeline only if seekable */
          if (glob_is_seekable)
            watch_pipeline (ptest);

        } else if (newstate == GST_STATE_PLAYING
            && pending == GST_STATE_VOID_PENDING && validate_checklist_item) {
          glob_validate_on_playing = NULL;
          insanity_test_validate_checklist_item (INSANITY_TEST (ptest),
              validate_checklist_item, TRUE, NULL);
          /* let it run a couple seconds */
          glob_wait_time = hls_test_get_wait_time (INSANITY_TEST (ptest));
          glob_timer_id =
              g_timeout_add (250, (GSourceFunc) & wait_and_end_step,
              INSANITY_TEST (ptest));
        }
      }
      break;
    case GST_MESSAGE_EOS:
      return FALSE;
    default:
      break;
  }

  return TRUE;

}
/* This function looks for an input-selector, and, if one is found,
   cycle through its sink pads */
static gboolean
check_track_selection (GstValidateMediaInfo * mi, gchar ** error_message)
{
  GstElement *playbin;
  GstElement *videosink, *audiosink;
  GstElement *input_selector = NULL;
  GstBus *bus;
  GstMessage *msg;
  gboolean ret = TRUE;
  GstStateChangeReturn state_ret;
  GstIterator *iterator;
  GstPad *original_pad;
  static const GstClockTime switch_delay = GST_SECOND * 5;
  GValue value = { 0, };

  playbin = gst_element_factory_make ("playbin", "fc-playbin");
  videosink = gst_element_factory_make ("fakesink", "fc-videosink");
  audiosink = gst_element_factory_make ("fakesink", "fc-audiosink");

  if (!playbin || !videosink || !audiosink) {
    *error_message = g_strdup ("Playbin and/or fakesink not available");
  }

  g_object_set (playbin, "video-sink", videosink, "audio-sink", audiosink,
      "uri", mi->uri, NULL);
  g_object_set (videosink, "sync", TRUE, NULL);
  g_object_set (audiosink, "sync", TRUE, NULL);

  bus = gst_pipeline_get_bus (GST_PIPELINE (playbin));

  state_ret = gst_element_set_state (playbin, GST_STATE_PAUSED);
  if (state_ret == GST_STATE_CHANGE_FAILURE) {
    *error_message = g_strdup ("Failed to change pipeline to paused");
    ret = FALSE;
    goto end;
  } else if (state_ret == GST_STATE_CHANGE_ASYNC) {
    msg =
        gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
        GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_EOS | GST_MESSAGE_ERROR);
    if (msg && GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_DONE) {
      gst_message_unref (msg);
    } else {
      ret = FALSE;
      *error_message = g_strdup ("Playback finihshed unexpectedly");
      goto end;
    }
  }

  if (gst_element_set_state (playbin,
          GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
    *error_message = g_strdup ("Failed to set pipeline to playing");
    ret = FALSE;
    goto end;
  }

  iterator = gst_bin_iterate_recurse (GST_BIN (playbin));
  if (!gst_iterator_find_custom (iterator,
          (GCompareFunc) find_input_selector, &value, NULL)) {
    /* It's fine, there's only one if several tracks of the same type */
    gst_iterator_free (iterator);
    input_selector = NULL;
    goto end;
  }
  input_selector = g_value_dup_object (&value);
  g_value_reset (&value);
  gst_iterator_free (iterator);
  g_object_get (input_selector, "active-pad", &original_pad, NULL);
  if (!original_pad) {
    /* Unexpected, log an error somehow ? */
    ret = FALSE;
    gst_object_unref (input_selector);
    input_selector = NULL;
    goto end;
  }

  /* Attach a buffer counter to each pad */
  setup_input_selector_counters (input_selector);

  while (1) {
    msg =
        gst_bus_timed_pop_filtered (bus, switch_delay,
        GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
    if (msg) {
      if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) {
        /* all good */
        ret = TRUE;
      } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
        GError *error = NULL;
        gchar *debug = NULL;

        gst_message_parse_error (msg, &error, &debug);
        *error_message = g_strdup_printf ("Playback error: %s : %s",
            error->message, debug);
        g_error_free (error);
        g_free (debug);

        ret = FALSE;
      } else {
        g_assert_not_reached ();
      }
      gst_message_unref (msg);
    } else {
      /* Timeout, switch track if we have more, or stop */
      GstPad *active_pad, *next_pad;

      g_object_get (input_selector, "active-pad", &active_pad, NULL);
      if (!active_pad) {
        *error_message =
            g_strdup ("Failed to get active-pad from input-selector");
        ret = FALSE;
        goto end;
      }
      next_pad = find_next_pad (input_selector, active_pad);
      gst_object_unref (active_pad);
      if (!next_pad) {
        ret = FALSE;
        goto end;
      }
      if (next_pad == original_pad) {
        goto end;
      }
      g_object_set (input_selector, "active-pad", next_pad, NULL);
      gst_object_unref (next_pad);
    }
  }

end:
  if (input_selector) {
    if (!check_and_remove_input_selector_counters (input_selector,
            error_message))
      ret = FALSE;
    gst_object_unref (input_selector);
  }
  gst_object_unref (bus);
  gst_element_set_state (playbin, GST_STATE_NULL);
  gst_object_unref (playbin);

  return ret;
}
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;
}