static gboolean
gst_play_sink_convert_bin_sink_setcaps (GstPlaySinkConvertBin * self,
    GstCaps * caps)
{
  GstStructure *s;
  const gchar *name;
  gboolean reconfigure = FALSE;
  gboolean raw;

  GST_DEBUG_OBJECT (self, "setcaps");
  GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
  s = gst_caps_get_structure (caps, 0);
  name = gst_structure_get_name (s);

  if (self->audio) {
    raw = g_str_equal (name, "audio/x-raw");
  } else {
    raw = g_str_equal (name, "video/x-raw");
  }

  GST_DEBUG_OBJECT (self, "raw %d, self->raw %d, blocked %d",
      raw, self->raw, gst_pad_is_blocked (self->sink_proxypad));

  if (raw) {
    if (!gst_pad_is_blocked (self->sink_proxypad)) {
      GstPad *target = gst_ghost_pad_get_target (GST_GHOST_PAD (self->sinkpad));

      if (!self->raw || (target && !gst_pad_query_accept_caps (target, caps))) {
        if (!self->raw)
          GST_DEBUG_OBJECT (self, "Changing caps from non-raw to raw");
        else
          GST_DEBUG_OBJECT (self, "Changing caps in an incompatible way");

        reconfigure = TRUE;
        block_proxypad (self);
      }

      if (target)
        gst_object_unref (target);
    }
  } else {
    if (self->raw && !gst_pad_is_blocked (self->sink_proxypad)) {
      GST_DEBUG_OBJECT (self, "Changing caps from raw to non-raw");
      reconfigure = TRUE;
      block_proxypad (self);
    }
  }

  /* Otherwise the setcaps below fails */
  if (reconfigure) {
    gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->sinkpad), NULL);
    gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), NULL);
  }

  GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);

  GST_DEBUG_OBJECT (self, "Setting sink caps %" GST_PTR_FORMAT, caps);

  return TRUE;
}
static GstStateChangeReturn
gst_play_sink_video_convert_change_state (GstElement * element,
        GstStateChange transition)
{
    GstStateChangeReturn ret;
    GstPlaySinkVideoConvert *self = GST_PLAY_SINK_VIDEO_CONVERT_CAST (element);

    switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
        GST_PLAY_SINK_VIDEO_CONVERT_LOCK (self);
        if (gst_pad_is_blocked (self->sink_proxypad))
            gst_pad_set_blocked_async_full (self->sink_proxypad, FALSE,
                                            (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
                                            (GDestroyNotify) gst_object_unref);
        GST_PLAY_SINK_VIDEO_CONVERT_UNLOCK (self);
        break;
    default:
        break;
    }

    ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
    if (ret == GST_STATE_CHANGE_FAILURE)
        return ret;

    switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
        GST_PLAY_SINK_VIDEO_CONVERT_LOCK (self);
        gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
        if (self->conv) {
            gst_element_set_state (self->conv, GST_STATE_NULL);
            gst_bin_remove (GST_BIN_CAST (self), self->conv);
            self->conv = NULL;
        }
        if (self->scale) {
            gst_element_set_state (self->scale, GST_STATE_NULL);
            gst_bin_remove (GST_BIN_CAST (self), self->scale);
            self->scale = NULL;
        }
        gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad),
                                  self->sink_proxypad);
        self->raw = FALSE;
        GST_PLAY_SINK_VIDEO_CONVERT_UNLOCK (self);
        break;
    case GST_STATE_CHANGE_READY_TO_PAUSED:
        GST_PLAY_SINK_VIDEO_CONVERT_LOCK (self);
        if (!gst_pad_is_blocked (self->sink_proxypad))
            gst_pad_set_blocked_async_full (self->sink_proxypad, TRUE,
                                            (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
                                            (GDestroyNotify) gst_object_unref);
        GST_PLAY_SINK_VIDEO_CONVERT_UNLOCK (self);
    default:
        break;
    }

    return ret;
}
static gboolean
gst_play_sink_video_convert_sink_setcaps (GstPad * pad, GstCaps * caps)
{
    GstPlaySinkVideoConvert *self =
        GST_PLAY_SINK_VIDEO_CONVERT (gst_pad_get_parent (pad));
    gboolean ret;
    GstStructure *s;
    const gchar *name;
    gboolean reconfigure = FALSE;

    GST_PLAY_SINK_VIDEO_CONVERT_LOCK (self);
    s = gst_caps_get_structure (caps, 0);
    name = gst_structure_get_name (s);

    if (g_str_has_prefix (name, "video/x-raw-")) {
        if (!self->raw && !gst_pad_is_blocked (self->sink_proxypad)) {
            GST_DEBUG_OBJECT (self, "Changing caps from non-raw to raw");
            reconfigure = TRUE;
            gst_pad_set_blocked_async_full (self->sink_proxypad, TRUE,
                                            (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
                                            (GDestroyNotify) gst_object_unref);
        }
    } else {
        if (self->raw && !gst_pad_is_blocked (self->sink_proxypad)) {
            GST_DEBUG_OBJECT (self, "Changing caps from raw to non-raw");
            reconfigure = TRUE;
            gst_pad_set_blocked_async_full (self->sink_proxypad, TRUE,
                                            (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
                                            (GDestroyNotify) gst_object_unref);
        }
    }

    /* Otherwise the setcaps below fails */
    if (reconfigure) {
        gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->sinkpad), NULL);
        gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), NULL);
    }
    GST_PLAY_SINK_VIDEO_CONVERT_UNLOCK (self);

    ret = gst_ghost_pad_setcaps_default (pad, caps);

    GST_DEBUG_OBJECT (self, "Setting sink caps %" GST_PTR_FORMAT ": %d", caps,
                      ret);

    gst_object_unref (self);

    return ret;
}
void _bp_replaygain_pipeline_rebuild (BansheePlayer* player)
{
    GstPad* srcPad;

    g_return_if_fail (IS_BANSHEE_PLAYER (player));
    g_return_if_fail (GST_IS_ELEMENT (player->before_rgvolume));
    srcPad = gst_element_get_static_pad (player->before_rgvolume, "src");

    if (gst_pad_is_active (srcPad) && !gst_pad_is_blocked (srcPad)) {
        player->rg_pad_block_id = gst_pad_add_probe (srcPad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, &pad_block_cb, player, NULL);
    } else if (!player->rg_pad_block_id) {
        pad_block_cb (srcPad, NULL, player);
    }
}
void QGstreamerPlayerSession::finishVideoOutputChange()
{
    if (!m_pendingVideoSink)
        return;

#ifdef DEBUG_PLAYBIN
    qDebug() << "finishVideoOutputChange" << m_pendingVideoSink;
#endif

    GstPad *srcPad = gst_element_get_static_pad(m_videoIdentity, "src");

    if (!gst_pad_is_blocked(srcPad)) {
        //pad is not blocked, it's possible to swap outputs only in the null state
        qWarning() << "Pad is not blocked yet, could not switch video sink";
        GstState identityElementState = GST_STATE_NULL;
        gst_element_get_state(m_videoIdentity, &identityElementState, NULL, GST_CLOCK_TIME_NONE);
        if (identityElementState != GST_STATE_NULL) {
            gst_object_unref(GST_OBJECT(srcPad));
            return; //can't change vo yet, received async call from the previous change
        }

    }

    if (m_pendingVideoSink == m_videoSink) {
        //video output was change back to the current one,
        //no need to torment the pipeline, just unblock the pad
        if (gst_pad_is_blocked(srcPad))
            gst_pad_set_blocked_async(srcPad, false, &block_pad_cb, 0);

        m_pendingVideoSink = 0;
        gst_object_unref(GST_OBJECT(srcPad));
        return;
    }  

    gst_element_set_state(m_videoSink, GST_STATE_NULL);

    gst_element_unlink(m_videoIdentity, m_videoSink);

    gst_bin_remove(GST_BIN(m_videoOutputBin), m_videoSink);

    m_videoSink = m_pendingVideoSink;
    m_pendingVideoSink = 0;

    gst_bin_add(GST_BIN(m_videoOutputBin), m_videoSink);
    if (!gst_element_link(m_videoIdentity, m_videoSink))
        qWarning() << "Linking video output element failed";

    GstState state;

    switch (m_pendingState) {
    case QMediaPlayer::StoppedState:
        state = GST_STATE_NULL;
        break;
    case QMediaPlayer::PausedState:
        state = GST_STATE_PAUSED;
        break;
    case QMediaPlayer::PlayingState:
        state = GST_STATE_PLAYING;
        break;
    }

    gst_element_set_state(m_videoSink, state);    

    //don't have to wait here, it will unblock eventually
    if (gst_pad_is_blocked(srcPad))
        gst_pad_set_blocked_async(srcPad, false, &block_pad_cb, 0);
    gst_object_unref(GST_OBJECT(srcPad));

#ifdef DEBUG_VO_BIN_DUMP
    dumpNum++;
    _gst_debug_bin_to_dot_file(GST_BIN(m_playbin),
                                  GstDebugGraphDetails(/*GST_DEBUG_GRAPH_SHOW_ALL */ GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES),
                                  QString("playbin_%1_finish").arg(dumpNum).toAscii().constData());
#endif
}
Beispiel #6
0
bool Pad::isBlocked() const
{
    return gst_pad_is_blocked(object<GstPad>());
}