static void gst_navseek_change_playback_rate (GstNavSeek * navseek, gdouble rate) { gboolean ret; GstPad *peer_pad; gint64 current_position; peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad); ret = gst_pad_query_position (peer_pad, GST_FORMAT_TIME, ¤t_position); if (ret) { GstEvent *event; gint64 start; gint64 stop; if (rate > 0.0) { start = current_position; stop = -1; } else { /* negative rate: we play from stop to start */ start = 0; stop = current_position; } event = gst_event_new_seek (rate, GST_FORMAT_TIME, GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP, GST_SEEK_TYPE_SET, start, GST_SEEK_TYPE_SET, stop); gst_pad_send_event (peer_pad, event); } gst_object_unref (peer_pad); }
static void gst_navseek_seek (GstNavSeek * navseek, gint64 offset) { gboolean ret; GstPad *peer_pad; gint64 peer_value; /* Query for the current time then attempt to set to time + offset */ peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad); ret = gst_pad_query_position (peer_pad, GST_FORMAT_TIME, &peer_value); if (ret) { GstEvent *event; peer_value += offset; if (peer_value < 0) peer_value = 0; event = gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, peer_value, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); gst_pad_send_event (peer_pad, event); } gst_object_unref (peer_pad); }
static gboolean gst_vorbis_enc_src_query (GstPad * pad, GstQuery * query) { gboolean res = TRUE; GstVorbisEnc *vorbisenc; GstPad *peerpad; vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad)); peerpad = gst_pad_get_peer (GST_PAD (vorbisenc->sinkpad)); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: { GstFormat fmt, req_fmt; gint64 pos, val; gst_query_parse_position (query, &req_fmt, NULL); if ((res = gst_pad_query_position (peerpad, &req_fmt, &val))) { gst_query_set_position (query, req_fmt, val); break; } fmt = GST_FORMAT_TIME; if (!(res = gst_pad_query_position (peerpad, &fmt, &pos))) break; if ((res = gst_pad_query_convert (peerpad, fmt, pos, &req_fmt, &val))) { gst_query_set_position (query, req_fmt, val); } break; } case GST_QUERY_DURATION: { GstFormat fmt, req_fmt; gint64 dur, val; gst_query_parse_duration (query, &req_fmt, NULL); if ((res = gst_pad_query_duration (peerpad, &req_fmt, &val))) { gst_query_set_duration (query, req_fmt, val); break; } fmt = GST_FORMAT_TIME; if (!(res = gst_pad_query_duration (peerpad, &fmt, &dur))) break; if ((res = gst_pad_query_convert (peerpad, fmt, dur, &req_fmt, &val))) { gst_query_set_duration (query, req_fmt, val); } break; } case GST_QUERY_CONVERT: { GstFormat src_fmt, dest_fmt; gint64 src_val, dest_val; gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); if (!(res = gst_vorbis_enc_convert_src (pad, src_fmt, src_val, &dest_fmt, &dest_val))) goto error; gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); break; } default: res = gst_pad_query_default (pad, query); break; } error: gst_object_unref (peerpad); gst_object_unref (vorbisenc); return res; }
static gboolean xing_mp3_encoder_src_query(GstPad * pad, GstQuery * query) { gboolean res = TRUE; XingMp3Encoder *encoder; GstPad *peerpad; encoder = XING_MP3_ENCODER(gst_pad_get_parent(pad)); peerpad = gst_pad_get_peer(GST_PAD(encoder->sinkpad)); switch(GST_QUERY_TYPE(query)) { case GST_QUERY_DURATION: { GstFormat fmt, req_fmt; gint64 dur, val; gst_query_parse_duration(query, &req_fmt, NULL); if((res = gst_pad_query_duration(peerpad, &req_fmt, &val))) { gst_query_set_duration(query, req_fmt, val); break; } fmt = GST_FORMAT_TIME; if(!(res = gst_pad_query_duration (peerpad, &fmt, &dur))) { break; } if((res = gst_pad_query_convert(peerpad, fmt, dur, &req_fmt, &val))) { gst_query_set_duration(query, req_fmt, val); } break; } case GST_QUERY_POSITION: { GstFormat fmt, req_fmt; gint64 pos, val; gst_query_parse_position(query, &req_fmt, NULL); if((res = gst_pad_query_position(peerpad, &req_fmt, &val))) { gst_query_set_position (query, req_fmt, val); break; } fmt = GST_FORMAT_TIME; if(!(res = gst_pad_query_position(peerpad, &fmt, &pos))) { break; } if((res = gst_pad_query_convert(peerpad, fmt, pos, &req_fmt, &val))) { gst_query_set_position(query, req_fmt, val); } break; } case GST_QUERY_CONVERT: { GstFormat src_fmt, dest_fmt; gint64 src_val, dest_val; gst_query_parse_convert(query, &src_fmt, &src_val, &dest_fmt, &dest_val); if(!(res = xing_mp3_encoder_convert_src(pad, src_fmt, src_val, &dest_fmt, &dest_val))) { gst_object_unref(peerpad); gst_object_unref(encoder); } gst_query_set_convert(query, src_fmt, src_val, dest_fmt, dest_val); break; } default: res = gst_pad_query_default(pad, query); break; } return res; }
// ---------------------------------------------------------------------------- // Handle the "pad-added" message void GStreamerImportFileHandle::OnPadAdded(GstPad *pad) { // Retrieve the stream caps...skip stream if unavailable GstCaps *caps = gst_pad_get_current_caps(pad); if (!caps) { WARN(mPipeline, ("OnPadAdded: unable to retrieve stream caps")); return; } // Get the caps structure...no need to release GstStructure *str = gst_caps_get_structure(caps, 0); if (!str) { WARN(mPipeline, ("OnPadAdded: unable to retrieve caps structure")); gst_caps_unref(caps); return; } // Only accept audio streams...no need to release const gchar *name = gst_structure_get_name(str); if (!g_strrstr(name, "audio")) { WARN(mPipeline, ("OnPadAdded: bypassing '%s' stream", name)); gst_caps_unref(caps); return; } // Allocate a new stream context GStreamContext *c = g_new0(GStreamContext, 1); if (!c) { WARN(mPipeline, ("OnPadAdded: unable to allocate stream context")); gst_caps_unref(caps); return; } // Set initial state c->mUse = true; // Always add it to the context list to keep the number of contexts // in sync with the number of streams g_mutex_lock(&mStreamsLock); g_ptr_array_add(mStreams, c); g_mutex_unlock(&mStreamsLock); // Need pointer to context during pad removal (pad-remove signal) SETCTX(pad, c); // Save the stream's start time and duration gst_pad_query_position(pad, GST_FORMAT_TIME, &c->mPosition); gst_pad_query_duration(pad, GST_FORMAT_TIME, &c->mDuration); // Retrieve the number of channels and validate gint channels = -1; gst_structure_get_int(str, "channels", &channels); if (channels <= 0) { WARN(mPipeline, ("OnPadAdded: channel count is invalid %d", channels)); gst_caps_unref(caps); return; } c->mNumChannels = channels; // Retrieve the sample rate and validate gint rate = -1; gst_structure_get_int(str, "rate", &rate); if (rate <= 0) { WARN(mPipeline, ("OnPadAdded: sample rate is invalid %d", rate)); gst_caps_unref(caps); return; } c->mSampleRate = (double) rate; c->mType = g_strdup(name); if (c->mType == NULL) { WARN(mPipeline, ("OnPadAdded: unable to allocate audio type")); gst_caps_unref(caps); return; } // Done with capabilities gst_caps_unref(caps); // Create audioconvert element c->mConv = gst_element_factory_make("audioconvert", NULL); if (!c->mConv) { WARN(mPipeline, ("OnPadAdded: failed to create audioconvert element")); return; } // Create appsink element c->mSink = gst_element_factory_make("appsink", NULL); if (!c->mSink) { WARN(mPipeline, ("OnPadAdded: failed to create appsink element")); return; } SETCTX(c->mSink, c); // Set the appsink callbacks and add the context pointer gst_app_sink_set_callbacks(GST_APP_SINK(c->mSink), &AppSinkCallbacks, this, NULL); // Set the capabilities that we desire caps = gst_static_caps_get(&supportedCaps); if (!caps) { WARN(mPipeline, ("OnPadAdded: failed to create static caps")); return; } gst_app_sink_set_caps(GST_APP_SINK(c->mSink), caps); gst_caps_unref(caps); // Do not sync to the clock...process as quickly as possible gst_base_sink_set_sync(GST_BASE_SINK(c->mSink), FALSE); // Don't drop buffers...allow queue to build unfettered gst_app_sink_set_drop(GST_APP_SINK(c->mSink), FALSE); // Add both elements to the pipeline gst_bin_add_many(GST_BIN(mPipeline), c->mConv, c->mSink, NULL); // Link them together if (!gst_element_link(c->mConv, c->mSink)) { WARN(mPipeline, ("OnPadAdded: failed to link autioconvert and appsink")); return; } // Link the audiconvert sink pad to the src pad GstPadLinkReturn ret = GST_PAD_LINK_OK; GstPad *convsink = gst_element_get_static_pad(c->mConv, "sink"); if (convsink) { ret = gst_pad_link(pad, convsink); gst_object_unref(convsink); } if (!convsink || ret != GST_PAD_LINK_OK) { WARN(mPipeline, ("OnPadAdded: failed to link uridecodebin to audioconvert - %d", ret)); return; } // Synchronize audioconvert state with parent if (!gst_element_sync_state_with_parent(c->mConv)) { WARN(mPipeline, ("OnPadAdded: unable to sync audioconvert state")); return; } // Synchronize appsink state with parent if (!gst_element_sync_state_with_parent(c->mSink)) { WARN(mPipeline, ("OnPadAdded: unable to sync appaink state")); return; } return; }