static gpointer owr_payload_detect_codecs(gpointer data) { GList *decoder_factories; GList *encoder_factories; GstCaps *caps; OWR_UNUSED(data); decoder_factories = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL); encoder_factories = gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, GST_RANK_MARGINAL); caps = gst_caps_new_empty_simple("video/x-h264"); h264_decoders = gst_element_factory_list_filter(decoder_factories, caps, GST_PAD_SINK, FALSE); h264_encoders = gst_element_factory_list_filter(encoder_factories, caps, GST_PAD_SRC, FALSE); gst_caps_unref (caps); caps = gst_caps_new_empty_simple("video/x-vp8"); vp8_decoders = gst_element_factory_list_filter(decoder_factories, caps, GST_PAD_SINK, FALSE); vp8_encoders = gst_element_factory_list_filter(encoder_factories, caps, GST_PAD_SRC, FALSE); gst_caps_unref (caps); gst_plugin_feature_list_free(decoder_factories); gst_plugin_feature_list_free(encoder_factories); h264_decoders = g_list_sort(h264_decoders, gst_plugin_feature_rank_compare_func); h264_encoders = g_list_sort(h264_encoders, gst_plugin_feature_rank_compare_func); vp8_decoders = g_list_sort(vp8_decoders, gst_plugin_feature_rank_compare_func); vp8_encoders = g_list_sort(vp8_encoders, gst_plugin_feature_rank_compare_func); return NULL; }
static GstElement * find_demuxer (GstCaps * caps) { GList *factories = gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_DEMUXER, GST_RANK_MARGINAL); GList *compat_elements; GstElement *e = NULL; if (factories == NULL) return NULL; compat_elements = gst_element_factory_list_filter (factories, caps, GST_PAD_SINK, TRUE); if (compat_elements) { /* Just take the first (highest ranked) option */ GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (compat_elements->data); e = gst_element_factory_create (factory, NULL); gst_plugin_feature_list_free (compat_elements); } if (factories) gst_plugin_feature_list_free (factories); return e; }
static GstElement * create_parser_for_caps (const GstCaps * caps) { GList *parser_list, *filtered_list, *l; GstElementFactory *parser_factory = NULL; GstElement *parser = NULL; parser_list = gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_PARSER, GST_RANK_NONE); filtered_list = gst_element_factory_list_filter (parser_list, caps, GST_PAD_SINK, FALSE); for (l = filtered_list; l != NULL && parser_factory == NULL; l = l->next) { parser_factory = GST_ELEMENT_FACTORY (l->data); if (gst_element_factory_get_num_pad_templates (parser_factory) != 2) parser_factory = NULL; } if (parser_factory != NULL) { parser = gst_element_factory_create (parser_factory, NULL); } else { parser = gst_element_factory_make ("capsfilter", NULL); } gst_plugin_feature_list_free (filtered_list); gst_plugin_feature_list_free (parser_list); return parser; }
static GstElement * get_encoder (const GstCaps * caps, GError ** err) { GList *encoders = NULL; GList *filtered = NULL; GstElementFactory *factory = NULL; GstElement *encoder = NULL; encoders = gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE, GST_RANK_NONE); if (encoders == NULL) { *err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_MISSING_PLUGIN, "Cannot find any image encoder"); goto fail; } GST_INFO ("got factory list %p", encoders); gst_plugin_feature_list_debug (encoders); filtered = gst_element_factory_list_filter (encoders, caps, GST_PAD_SRC, FALSE); GST_INFO ("got filtered list %p", filtered); if (filtered == NULL) { gchar *tmp = gst_caps_to_string (caps); *err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_MISSING_PLUGIN, "Cannot find any image encoder for caps %s", tmp); g_free (tmp); goto fail; } gst_plugin_feature_list_debug (filtered); factory = (GstElementFactory *) filtered->data; GST_INFO ("got factory %p", factory); encoder = gst_element_factory_create (factory, NULL); GST_INFO ("created encoder element %p, %s", encoder, gst_element_get_name (encoder)); fail: if (encoders) gst_plugin_feature_list_free (encoders); if (filtered) gst_plugin_feature_list_free (filtered); return encoder; }
static GstElement * create_payloader_for_caps (const GstCaps * caps) { GList *payloader_list, *filtered_list, *l; GstElementFactory *payloader_factory = NULL; GstElement *payloader = NULL; payloader_list = gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_PAYLOADER, GST_RANK_NONE); filtered_list = gst_element_factory_list_filter (payloader_list, caps, GST_PAD_SRC, FALSE); for (l = filtered_list; l != NULL && payloader_factory == NULL; l = l->next) { payloader_factory = GST_ELEMENT_FACTORY (l->data); if (gst_element_factory_get_num_pad_templates (payloader_factory) != 2) payloader_factory = NULL; } if (payloader_factory != NULL) { payloader = gst_element_factory_create (payloader_factory, NULL); } if (payloader) { GParamSpec *pspec; pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (payloader), "config-interval"); if (pspec != NULL && G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_UINT) { g_object_set (payloader, "config-interval", 1, NULL); } pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (payloader), "picture-id-mode"); if (pspec != NULL && G_TYPE_IS_ENUM (G_PARAM_SPEC_VALUE_TYPE (pspec))) { /* Set picture id so that remote peer can determine continuity if */ /* there are lost FEC packets and if it has to NACK them */ g_object_set (payloader, "picture-id-mode", PICTURE_ID_15_BIT, NULL); } } gst_plugin_feature_list_free (filtered_list); gst_plugin_feature_list_free (payloader_list); return payloader; }
static void type_found_cb (GstElement * typefind, guint probability, GstCaps * caps, InsanityTest * test) { GList *demuxers = NULL, *capable_demuxers = NULL; GstPad *typefsrcpad = NULL; typefsrcpad = gst_element_get_static_pad (typefind, "src"); /* First try to directly link to the decoder */ if (pad_added_cb (typefind, typefsrcpad, test) == TRUE) return; /* if we can't find a demuxer that is concidered as good * (ie with rank primary, we just don't run the test */ demuxers = gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_DEMUXER, GST_RANK_PRIMARY); if (demuxers == NULL) { ERROR (test, "Could not find a demuxer concidered as good enough"); insanity_test_done (test); goto done; } capable_demuxers = gst_element_factory_list_filter (demuxers, caps, GST_PAD_SINK, FALSE); glob_demuxer = gst_element_factory_create (capable_demuxers->data, "demuxer"); if (glob_demuxer == NULL) { insanity_test_done (test); goto done; } gst_bin_add (GST_BIN (glob_pipeline), glob_demuxer); gst_element_link (glob_typefinder, glob_demuxer); gst_element_sync_state_with_parent (glob_demuxer); connect_element (test, glob_demuxer); done: gst_plugin_feature_list_free (demuxers); gst_plugin_feature_list_free (capable_demuxers); }
/** * gst_protection_select_system: * @system_identifiers: (transfer none): A null terminated array of strings * that contains the UUID values of each protection system that is to be * checked. * * Iterates the supplied list of UUIDs and checks the GstRegistry for * an element that supports one of the supplied UUIDs. If more than one * element matches, the system ID of the highest ranked element is selected. * * Returns: (transfer none): One of the strings from @system_identifiers that * indicates the highest ranked element that implements the protection system * indicated by that system ID, or %NULL if no element has been found. * * Since: 1.6 */ const gchar * gst_protection_select_system (const gchar ** system_identifiers) { GList *decryptors, *walk; const gchar *retval = NULL; decryptors = gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_DECRYPTOR, GST_RANK_MARGINAL); for (walk = decryptors; !retval && walk; walk = g_list_next (walk)) { GstElementFactory *fact = (GstElementFactory *) walk->data; retval = gst_protection_factory_check (fact, system_identifiers); } gst_plugin_feature_list_free (decryptors); return retval; }
static void kms_enc_tree_bin_create_encoder_for_caps (KmsEncTreeBin * self, const GstCaps * caps, gint target_bitrate) { GList *encoder_list, *filtered_list, *l; GstElementFactory *encoder_factory = NULL; encoder_list = gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER, GST_RANK_NONE); /* HACK: Augment the openh264 rank */ for (l = encoder_list; l != NULL; l = l->next) { encoder_factory = GST_ELEMENT_FACTORY (l->data); if (g_str_has_prefix (GST_OBJECT_NAME (encoder_factory), "openh264")) { encoder_list = g_list_remove (encoder_list, l->data); encoder_list = g_list_prepend (encoder_list, encoder_factory); break; } } encoder_factory = NULL; filtered_list = gst_element_factory_list_filter (encoder_list, caps, GST_PAD_SRC, FALSE); for (l = filtered_list; l != NULL && encoder_factory == NULL; l = l->next) { encoder_factory = GST_ELEMENT_FACTORY (l->data); if (gst_element_factory_get_num_pad_templates (encoder_factory) != 2) encoder_factory = NULL; } if (encoder_factory != NULL) { self->priv->enc = gst_element_factory_create (encoder_factory, NULL); kms_enc_tree_bin_set_encoder_type (self); configure_encoder (self->priv->enc, self->priv->enc_type, target_bitrate); } gst_plugin_feature_list_free (filtered_list); gst_plugin_feature_list_free (encoder_list); }
GstElement * rygel_gst_utils_get_rtp_depayloader (GstCaps *caps) { GList *features; GList *filtered; const gchar *feature_name; if (!rygel_gst_utils_need_rtp_depayloader (caps)) { return NULL; } features = gst_element_factory_list_get_elements ((GstElementFactoryListType) GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER, GST_RANK_NONE); filtered = gst_element_factory_list_filter (features, caps, GST_PAD_SINK, FALSE); gst_plugin_feature_list_free (features); feature_name = gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (filtered->data)); /* If most "fitting" depayloader was rtpdepay skip it because it is * just some kind of proxy. */ if (g_strcmp0 (feature_name, "rtpdepay") == 0) { if (filtered->next) { GstElement* element = gst_element_factory_create (GST_ELEMENT_FACTORY (filtered->next->data), NULL); if (element) { gst_object_ref_sink (element); } gst_plugin_feature_list_free (filtered); return element; } return NULL; } else { GstElement* element = gst_element_factory_create (GST_ELEMENT_FACTORY (filtered->data), NULL); if (element) { gst_object_ref_sink (element); } gst_plugin_feature_list_free (filtered); return element; } }
static GstElementFactory * get_encoder_factory (GstCaps * caps) { GstElementFactory *fact = NULL; GList *encoders, *tmp; tmp = gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER, GST_RANK_MARGINAL); encoders = gst_element_factory_list_filter (tmp, caps, GST_PAD_SRC, FALSE); gst_plugin_feature_list_free (tmp); for (tmp = encoders; tmp; tmp = tmp->next) { /* We just pick the first one */ fact = (GstElementFactory *) tmp->data; gst_object_ref (fact); break; } gst_plugin_feature_list_free (encoders); return fact; }
static GstElementFactory * get_audio_encoder_factory (GstEncodingProfile *profile) { GstEncodingProfile *p = get_audio_encoding_profile (profile); GstElementFactory *f; GList *l; GList *fl; if (p == NULL) return NULL; l = gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER, GST_RANK_MARGINAL); fl = gst_element_factory_list_filter (l, gst_encoding_profile_get_format (p), GST_PAD_SRC, FALSE); if (fl != NULL) { f = gst_object_ref (fl->data); } else { g_warning ("no encoder factory for profile %s", gst_encoding_profile_get_name (p)); f = NULL; } gst_plugin_feature_list_free (l); gst_plugin_feature_list_free (fl); return f; }
void GstUtils::element_factory_list_to_g_enum(GEnumValue *target_enum, GstElementFactoryListType type, GstRank minrank, bool insert_none_first, const std::vector<std::string> &black_list) { GList *element_list = gst_element_factory_list_get_elements(type, minrank); GList *iter = element_list; gint i = 0; if (insert_none_first) { target_enum[0].value = 0; target_enum[0].value_name = g_strdup("None"); target_enum[0].value_nick = g_strdup("None"); i++; } while (iter != nullptr) { if (black_list.end() == std::find( black_list.begin(), black_list.end(), gst_plugin_feature_get_name((GstPluginFeature *) iter->data))){ target_enum[i].value = i; target_enum[i].value_name = g_strdup(gst_element_factory_get_longname((GstElementFactory *) iter->data)); target_enum[i].value_nick = g_strdup(gst_plugin_feature_get_name((GstPluginFeature *) iter->data)); i++; } iter = g_list_next(iter); } target_enum[i].value = 0; target_enum[i].value_name = nullptr; target_enum[i].value_nick = nullptr; gst_plugin_feature_list_free(element_list); }
int main (int argc, char **argv) { GError *err = NULL; gchar *outputuri = NULL; gchar *format = NULL; gchar *aformat = NULL; gchar *vformat = NULL; gboolean allmissing = FALSE; gboolean listcodecs = FALSE; GOptionEntry options[] = { { "silent", 's', 0, G_OPTION_ARG_NONE, &silent, "Don't output the information structure", NULL }, { "outputuri", 'o', 0, G_OPTION_ARG_STRING, &outputuri, "URI to encode to", "URI (<protocol>://<location>)" }, { "format", 'f', 0, G_OPTION_ARG_STRING, &format, "Container format", "<GstCaps>" }, { "vformat", 'v', 0, G_OPTION_ARG_STRING, &vformat, "Video format", "<GstCaps>" }, { "aformat", 'a', 0, G_OPTION_ARG_STRING, &aformat, "Audio format", "<GstCaps>" }, { "allmissing", 'm', 0, G_OPTION_ARG_NONE, &allmissing, "encode to all matching format/codec that aren't specified", NULL }, { "list-codecs", 'l', 0, G_OPTION_ARG_NONE, &listcodecs, "list all available codecs and container formats", NULL }, {NULL} }; GOptionContext *ctx; GstEncodingProfile *prof; gchar *inputuri; ctx = g_option_context_new ("- encode URIs with GstProfile and encodebin"); g_option_context_add_main_entries (ctx, options, NULL); g_option_context_add_group (ctx, gst_init_get_option_group ()); if (!g_option_context_parse (ctx, &argc, &argv, &err)) { g_print ("Error initializing: %s\n", err->message); exit (1); } if (listcodecs) { list_codecs (); g_option_context_free (ctx); exit (0); } if (outputuri == NULL || argc != 2) { g_print ("%s", g_option_context_get_help (ctx, TRUE, NULL)); g_option_context_free (ctx); exit (-1); } g_option_context_free (ctx); /* Fixup outputuri to be a URI */ inputuri = ensure_uri (argv[1]); outputuri = ensure_uri (outputuri); if (allmissing) { GList *muxers; GstCaps *formats = NULL; GstCaps *vformats = NULL; GstCaps *aformats = NULL; guint f, v, a, flen, vlen, alen; if (!format) formats = gst_caps_list_container_formats (GST_RANK_NONE); else formats = gst_caps_from_string (format); if (!vformat) vformats = gst_caps_list_video_encoding_formats (GST_RANK_NONE); else vformats = gst_caps_from_string (vformat); if (!aformat) aformats = gst_caps_list_audio_encoding_formats (GST_RANK_NONE); else aformats = gst_caps_from_string (aformat); muxers = gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER, GST_RANK_NONE); flen = gst_caps_get_size (formats); for (f = 0; f < flen; f++) { GstCaps *container = gst_caps_new_full (gst_caps_steal_structure (formats, 0), NULL); GstCaps *compatv = gst_caps_list_compatible_codecs (container, vformats, muxers); GstCaps *compata = gst_caps_list_compatible_codecs (container, aformats, muxers); vlen = gst_caps_get_size (compatv); alen = gst_caps_get_size (compata); for (v = 0; v < vlen; v++) { GstCaps *vcodec = gst_caps_new_full (gst_structure_copy (gst_caps_get_structure (compatv, v)), NULL); for (a = 0; a < alen; a++) { GstCaps *acodec = gst_caps_new_full (gst_structure_copy (gst_caps_get_structure (compata, a)), NULL); prof = create_profile ((GstCaps *) container, (GstCaps *) vcodec, (GstCaps *) acodec); if (G_UNLIKELY (prof == NULL)) { g_print ("Wrong arguments\n"); break; } outputuri = ensure_uri (generate_filename (container, vcodec, acodec)); transcode_file (inputuri, outputuri, prof); gst_encoding_profile_unref (prof); gst_caps_unref (acodec); } gst_caps_unref (vcodec); } gst_caps_unref (container); } } else { /* Create the profile */ prof = create_profile_from_string (format, vformat, aformat); if (G_UNLIKELY (prof == NULL)) { g_print ("Encoding arguments are not valid !\n"); return 1; } /* Transcode file */ transcode_file (inputuri, outputuri, prof); /* cleanup */ gst_encoding_profile_unref (prof); } return 0; }
int main (int argc, char *argv[]) { /* Initialisation */ gst_init (&argc, &argv); GList *element_list = gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER, GST_RANK_NONE); GList *iter = element_list; while (iter != NULL) { g_print ("+++++\n"); g_print ("%s -- ", gst_element_factory_get_longname ((GstElementFactory *)iter->data)); g_print ("%s\n", gst_plugin_feature_get_name ((GstPluginFeature *)iter->data)); const GList *static_pads = gst_element_factory_get_static_pad_templates ((GstElementFactory *)iter->data); while (NULL != static_pads) { GstStaticPadTemplate *pad = (GstStaticPadTemplate *)static_pads->data; //the following is EMPTY gchar *caps_str = gst_caps_to_string (&pad->static_caps.caps); //g_free (caps_str); /* g_print ("string: %s\n", */ /* pad->static_caps.string); */ GstCaps *caps = gst_caps_from_string (pad->static_caps.string); guint caps_size = gst_caps_get_size (caps); if (! gst_caps_is_any (caps)) for (guint i = caps_size; i > 0; i--) { GstStructure *caps_struct = gst_caps_get_structure (caps, i-1); if (gst_structure_has_name (caps_struct,"application/x-rtp")) { g_print ("string: %s\n", gst_structure_to_string (caps_struct)); {//payload const GValue *val = gst_structure_get_value (caps_struct, "payload"); if (NULL != val) { //g_print ("payload struct type %s\n", G_VALUE_TYPE_NAME (val)); if(GST_VALUE_HOLDS_INT_RANGE(val)) { g_print ("payload min %d\n", gst_value_get_int_range_min (val)); } if (GST_VALUE_HOLDS_LIST(val)) { for (guint i = 0; i < gst_value_list_get_size (val); i++) { const GValue *item_val = gst_value_list_get_value (val, i); g_print ("payload list %d\n", g_value_get_int (item_val)); } } if (G_VALUE_HOLDS_INT (val)) { g_print ("payload int %d\n", g_value_get_int (val)); } } } { //encodeing-name const GValue *val = gst_structure_get_value (caps_struct, "encoding-name"); if (NULL != val) { //g_print ("encoding-name struct type %s\n", G_VALUE_TYPE_NAME (val)); if (GST_VALUE_HOLDS_LIST(val)) { for (guint i = 0; i < gst_value_list_get_size (val); i++) { const GValue *item_val = gst_value_list_get_value (val, i); g_print ("encoding-name list %s\n", g_value_get_string (item_val)); } } if (G_VALUE_HOLDS_STRING (val)) { g_print ("encoding-name string %s\n", g_value_get_string (val)); } } } {//media const GValue *val = gst_structure_get_value (caps_struct, "media"); if (NULL != val) { if (GST_VALUE_HOLDS_LIST(val)) { for (guint i = 0; i < gst_value_list_get_size (val); i++) { const GValue *item_val = gst_value_list_get_value (val, i); g_print ("media list %s\n", g_value_get_string (item_val)); } } if (G_VALUE_HOLDS_STRING (val)) { g_print ("media string %s\n", g_value_get_string (val)); } } } {//clock rate const GValue *val = gst_structure_get_value (caps_struct, "clock-rate"); if (NULL != val) { //g_print ("payload struct type %s\n", G_VALUE_TYPE_NAME (val)); if(GST_VALUE_HOLDS_INT_RANGE(val)) { g_print ("clock-rate min %d\n", gst_value_get_int_range_min (val)); } if (GST_VALUE_HOLDS_LIST(val)) { for (guint i = 0; i < gst_value_list_get_size (val); i++) { const GValue *item_val = gst_value_list_get_value (val, i); g_print ("clock-rate list %d\n", g_value_get_int (item_val)); } } if (G_VALUE_HOLDS_INT (val)) { g_print ("clock-rate int %d\n", g_value_get_int (val)); } } } /* g_print ("\nencoding-name %s\n", */ /* gst_structure_get_string (caps_struct, */ /* "encoding-name")); */ } } static_pads = g_list_next (static_pads); gst_caps_unref (caps); } iter = g_list_next (iter); } gst_plugin_feature_list_free (element_list); return 0; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = ( decoder_t* )p_this; decoder_sys_t *p_sys; GstStateChangeReturn i_ret; gboolean b_ret; sink_src_caps_t caps = { NULL, NULL }; GstStructure *p_str; GstAppSrcCallbacks cb; int i_rval = VLC_SUCCESS; GList *p_list; bool dbin; #define VLC_GST_CHECK( r, v, s, t ) \ { if( r == v ){ msg_Err( p_dec, s ); i_rval = t; goto fail; } } if( !vlc_gst_init( )) { msg_Err( p_dec, "failed to register vlcvideosink" ); return VLC_EGENERIC; } p_str = vlc_to_gst_fmt( &p_dec->fmt_in ); if( !p_str ) return VLC_EGENERIC; /* Allocate the memory needed to store the decoder's structure */ p_sys = p_dec->p_sys = calloc( 1, sizeof( *p_sys ) ); if( p_sys == NULL ) { gst_structure_free( p_str ); return VLC_ENOMEM; } dbin = var_CreateGetBool( p_dec, "use-decodebin" ); msg_Dbg( p_dec, "Using decodebin? %s", dbin ? "yes ":"no" ); caps.p_sinkcaps = gst_caps_new_empty( ); gst_caps_append_structure( caps.p_sinkcaps, p_str ); /* Currently supports only system memory raw output format */ caps.p_srccaps = gst_caps_new_empty_simple( "video/x-raw" ); /* Get the list of all the available gstreamer decoders */ p_list = gst_element_factory_list_get_elements( GST_ELEMENT_FACTORY_TYPE_DECODER, GST_RANK_MARGINAL ); VLC_GST_CHECK( p_list, NULL, "no decoder list found", VLC_ENOMOD ); if( !dbin ) { GList *p_l; /* Sort them as per ranks */ p_list = g_list_sort( p_list, gst_plugin_feature_rank_compare_func ); VLC_GST_CHECK( p_list, NULL, "failed to sort decoders list", VLC_ENOMOD ); p_l = g_list_find_custom( p_list, &caps, find_decoder_func ); VLC_GST_CHECK( p_l, NULL, "no suitable decoder found", VLC_ENOMOD ); /* create the decoder with highest rank */ p_sys->p_decode_in = gst_element_factory_create( ( GstElementFactory* )p_l->data, NULL ); VLC_GST_CHECK( p_sys->p_decode_in, NULL, "failed to create decoder", VLC_ENOMOD ); } else { GList *p_l; /* Just check if any suitable decoder exists, rest will be * handled by decodebin */ p_l = g_list_find_custom( p_list, &caps, find_decoder_func ); VLC_GST_CHECK( p_l, NULL, "no suitable decoder found", VLC_ENOMOD ); } gst_plugin_feature_list_free( p_list ); p_list = NULL; gst_caps_unref( caps.p_srccaps ); caps.p_srccaps = NULL; p_sys->b_prerolled = false; p_sys->b_running = false; /* Queue: GStreamer thread will dump buffers into this queue, * DecodeBlock() will pop out the buffers from the queue */ p_sys->p_que = gst_atomic_queue_new( 0 ); VLC_GST_CHECK( p_sys->p_que, NULL, "failed to create queue", VLC_ENOMEM ); p_sys->p_decode_src = gst_element_factory_make( "appsrc", NULL ); VLC_GST_CHECK( p_sys->p_decode_src, NULL, "appsrc not found", VLC_ENOMOD ); g_object_set( G_OBJECT( p_sys->p_decode_src ), "caps", caps.p_sinkcaps, "emit-signals", TRUE, "format", GST_FORMAT_BYTES, "stream-type", GST_APP_STREAM_TYPE_SEEKABLE, /* Making DecodeBlock() to block on appsrc with max queue size of 1 byte. * This will make the push_buffer() tightly coupled with the buffer * flow from appsrc -> decoder. push_buffer() will only return when * the same buffer it just fed to appsrc has also been fed to the * decoder element as well */ "block", TRUE, "max-bytes", ( guint64 )1, NULL ); gst_caps_unref( caps.p_sinkcaps ); caps.p_sinkcaps = NULL; cb.enough_data = NULL; cb.need_data = NULL; cb.seek_data = seek_data_cb; gst_app_src_set_callbacks( GST_APP_SRC( p_sys->p_decode_src ), &cb, p_dec, NULL ); if( dbin ) { p_sys->p_decode_in = gst_element_factory_make( "decodebin", NULL ); VLC_GST_CHECK( p_sys->p_decode_in, NULL, "decodebin not found", VLC_ENOMOD ); //g_object_set( G_OBJECT( p_sys->p_decode_in ), //"max-size-buffers", 2, NULL ); //g_signal_connect( G_OBJECT( p_sys->p_decode_in ), "no-more-pads", //G_CALLBACK( no_more_pads_cb ), p_dec ); g_signal_connect( G_OBJECT( p_sys->p_decode_in ), "pad-added", G_CALLBACK( pad_added_cb ), p_dec ); } /* videosink: will emit signal for every available buffer */ p_sys->p_decode_out = gst_element_factory_make( "vlcvideosink", NULL ); VLC_GST_CHECK( p_sys->p_decode_out, NULL, "vlcvideosink not found", VLC_ENOMOD ); p_sys->p_allocator = gst_vlc_picture_plane_allocator_new( (gpointer) p_dec ); g_object_set( G_OBJECT( p_sys->p_decode_out ), "sync", FALSE, "allocator", p_sys->p_allocator, "id", (gpointer) p_dec, NULL ); g_signal_connect( G_OBJECT( p_sys->p_decode_out ), "new-buffer", G_CALLBACK( frame_handoff_cb ), p_dec ); //FIXME: caps_signal #if 0 g_signal_connect( G_OBJECT( p_sys->p_decode_out ), "new-caps", G_CALLBACK( caps_handoff_cb ), p_dec ); #else GST_VLC_VIDEO_SINK( p_sys->p_decode_out )->new_caps = caps_handoff_cb; #endif p_sys->p_decoder = GST_ELEMENT( gst_bin_new( "decoder" ) ); VLC_GST_CHECK( p_sys->p_decoder, NULL, "bin not found", VLC_ENOMOD ); p_sys->p_bus = gst_bus_new( ); VLC_GST_CHECK( p_sys->p_bus, NULL, "failed to create bus", VLC_ENOMOD ); gst_element_set_bus( p_sys->p_decoder, p_sys->p_bus ); gst_bin_add_many( GST_BIN( p_sys->p_decoder ), p_sys->p_decode_src, p_sys->p_decode_in, p_sys->p_decode_out, NULL ); gst_object_ref( p_sys->p_decode_src ); gst_object_ref( p_sys->p_decode_in ); gst_object_ref( p_sys->p_decode_out ); b_ret = gst_element_link( p_sys->p_decode_src, p_sys->p_decode_in ); VLC_GST_CHECK( b_ret, FALSE, "failed to link src <-> in", VLC_EGENERIC ); if( !dbin ) { b_ret = gst_element_link( p_sys->p_decode_in, p_sys->p_decode_out ); VLC_GST_CHECK( b_ret, FALSE, "failed to link in <-> out", VLC_EGENERIC ); } p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat; /* set the pipeline to playing */ i_ret = gst_element_set_state( p_sys->p_decoder, GST_STATE_PLAYING ); VLC_GST_CHECK( i_ret, GST_STATE_CHANGE_FAILURE, "set state failure", VLC_EGENERIC ); p_sys->b_running = true; /* Set callbacks */ p_dec->pf_decode_video = DecodeBlock; p_dec->pf_flush = Flush; return VLC_SUCCESS; fail: if( caps.p_sinkcaps ) gst_caps_unref( caps.p_sinkcaps ); if( caps.p_srccaps ) gst_caps_unref( caps.p_srccaps ); if( p_list ) gst_plugin_feature_list_free( p_list ); CloseDecoder( ( vlc_object_t* )p_dec ); return i_rval; }