Exemple #1
0
static void
gst_h264_parse_init (GstH264Parse * h264parse, GstH264ParseClass * g_class)
{
  h264parse->frame_out = gst_adapter_new ();

  /* retrieve and intercept baseparse.
   * Quite HACKish, but fairly OK since it is needed to perform avc packet
   * splitting, which is the penultimate de-parsing */
  h264parse->parse_chain =
      GST_PAD_CHAINFUNC (GST_BASE_PARSE_SINK_PAD (h264parse));
  gst_pad_set_chain_function (GST_BASE_PARSE_SINK_PAD (h264parse),
      gst_h264_parse_chain);
}
static void
gst_dtsdec_init (GstDtsDec * dtsdec)
{
  dtsdec->request_channels = DCA_CHANNEL;
  dtsdec->dynamic_range_compression = FALSE;

  /* retrieve and intercept base class chain.
   * Quite HACKish, but that's dvd specs for you,
   * since one buffer needs to be split into 2 frames */
  dtsdec->base_chain = GST_PAD_CHAINFUNC (GST_AUDIO_DECODER_SINK_PAD (dtsdec));
  gst_pad_set_chain_function (GST_AUDIO_DECODER_SINK_PAD (dtsdec),
      GST_DEBUG_FUNCPTR (gst_dtsdec_chain));
}
static void
gst_a52dec_init (GstA52Dec * a52dec)
{
  a52dec->request_channels = A52_CHANNEL;
  a52dec->dynamic_range_compression = FALSE;

  a52dec->state = NULL;
  a52dec->samples = NULL;

  /* retrieve and intercept base class chain.
   * Quite HACKish, but that's dvd specs/caps for you,
   * since one buffer needs to be split into 2 frames */
  a52dec->base_chain = GST_PAD_CHAINFUNC (GST_AUDIO_DECODER_SINK_PAD (a52dec));
  gst_pad_set_chain_function (GST_AUDIO_DECODER_SINK_PAD (a52dec),
      GST_DEBUG_FUNCPTR (gst_a52dec_chain));
}
static void
stop_typefinding (GstTypeFindElement * typefind)
{
  GstState state;
  gboolean push_cached_buffers;

  gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, 0);

  push_cached_buffers = (state >= GST_STATE_PAUSED);

  GST_DEBUG_OBJECT (typefind, "stopping typefinding%s",
      push_cached_buffers ? " and pushing cached buffers" : "");

  if (typefind->store) {
    if (!push_cached_buffers) {
      gst_buffer_unref (typefind->store);
    } else {
      GstPad *peer = gst_pad_get_peer (typefind->src);

      typefind->mode = MODE_NORMAL;
      gst_buffer_set_caps (typefind->store, typefind->caps);

      /* make sure the user gets a meaningful error message in this case,
       * which is not a core bug or bug of any kind (as the default error
       * message emitted by gstpad.c otherwise would make you think) */
      if (peer && GST_PAD_CHAINFUNC (peer) == NULL) {
        GST_DEBUG_OBJECT (typefind, "upstream only supports push mode, while "
            "downstream element only works in pull mode, erroring out");
        GST_ELEMENT_ERROR (typefind, STREAM, FAILED,
            ("%s cannot work in push mode. The operation is not supported "
                "with this source element or protocol.",
                G_OBJECT_TYPE_NAME (GST_PAD_PARENT (peer))),
            ("Downstream pad %s:%s has no chainfunction, and the upstream "
                "element does not support pull mode",
                GST_DEBUG_PAD_NAME (peer)));
        typefind->mode = MODE_ERROR;    /* make the chain function error out */
      } else {
        gst_type_find_element_send_cached_events (typefind);
        gst_pad_push (typefind->src, typefind->store);
      }

      if (peer)
        gst_object_unref (peer);
    }
    typefind->store = NULL;
  }
}
static void
link_element_to_tee (GstElement * tee, GstElement * element)
{
  GstPad *tee_src = gst_element_get_request_pad (tee, "src_%u");
  GstPad *element_sink = gst_element_get_static_pad (element, "sink");
  GstPadLinkReturn ret;
  GstPadChainFunction old_func;

  /*
   * HACK Add a custom chain function that does not return error, this way
   * we avoid race conditions produced by reconnect events not using the stream
   * lock
   */
  old_func = GST_PAD_CHAINFUNC (element_sink);

  if (old_func != NULL) {
    if (old_func != no_fail_chain) {
      g_object_set_data (G_OBJECT (element_sink), OLD_CHAIN_KEY, old_func);
    }
    gst_pad_set_chain_function (element_sink, no_fail_chain);
  }

  remove_element_on_unlinked (element, "src", "sink");
  g_signal_connect (tee_src, "unlinked", G_CALLBACK (remove_tee_pad_on_unlink),
      NULL);

  gst_pad_add_probe (tee_src, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, tee_src_probe,
      NULL, NULL);

  ret = gst_pad_link_full (tee_src, element_sink, GST_PAD_LINK_CHECK_NOTHING);

  if (G_UNLIKELY (GST_PAD_LINK_FAILED (ret))) {
    GST_ERROR ("Linking %" GST_PTR_FORMAT " with %" GST_PTR_FORMAT " result %d",
        tee_src, element_sink, ret);
  }

  g_object_unref (element_sink);
  g_object_unref (tee_src);
}
static void
stop_typefinding (GstTypeFindElement * typefind)
{
  GstState state;
  gboolean push_cached_buffers;
  gsize avail;
  GstBuffer *buffer;
  GstClockTime pts, dts;

  gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, 0);

  push_cached_buffers = (state >= GST_STATE_PAUSED && typefind->caps);

  GST_DEBUG_OBJECT (typefind, "stopping typefinding%s",
      push_cached_buffers ? " and pushing cached events and buffers" : "");

  typefind->mode = MODE_NORMAL;
  if (push_cached_buffers)
    gst_type_find_element_send_cached_events (typefind);

  GST_OBJECT_LOCK (typefind);
  avail = gst_adapter_available (typefind->adapter);
  if (avail == 0)
    goto no_data;

  pts = gst_adapter_prev_pts (typefind->adapter, NULL);
  dts = gst_adapter_prev_dts (typefind->adapter, NULL);
  buffer = gst_adapter_take_buffer (typefind->adapter, avail);
  GST_BUFFER_PTS (buffer) = pts;
  GST_BUFFER_DTS (buffer) = dts;
  GST_BUFFER_OFFSET (buffer) = typefind->initial_offset;
  GST_OBJECT_UNLOCK (typefind);

  if (!push_cached_buffers) {
    gst_buffer_unref (buffer);
  } else {
    GstPad *peer = gst_pad_get_peer (typefind->src);

    /* make sure the user gets a meaningful error message in this case,
     * which is not a core bug or bug of any kind (as the default error
     * message emitted by gstpad.c otherwise would make you think) */
    if (peer && GST_PAD_CHAINFUNC (peer) == NULL) {
      GST_DEBUG_OBJECT (typefind, "upstream only supports push mode, while "
          "downstream element only works in pull mode, erroring out");
      GST_ELEMENT_ERROR (typefind, STREAM, FAILED,
          ("%s cannot work in push mode. The operation is not supported "
              "with this source element or protocol.",
              G_OBJECT_TYPE_NAME (GST_PAD_PARENT (peer))),
          ("Downstream pad %s:%s has no chainfunction, and the upstream "
              "element does not support pull mode", GST_DEBUG_PAD_NAME (peer)));
      typefind->mode = MODE_ERROR;      /* make the chain function error out */
      gst_buffer_unref (buffer);
    } else {
      gst_pad_push (typefind->src, buffer);
    }
    if (peer)
      gst_object_unref (peer);
  }
  return;

  /* ERRORS */
no_data:
  {
    GST_DEBUG_OBJECT (typefind, "we have no data to typefind");
    GST_OBJECT_UNLOCK (typefind);
    return;
  }
}