static gboolean gst_ss_demux_create_download_pipe (GstSSDemux * demux, GstSSDemuxStream *stream, const gchar * uri, guint64 start_ts) { gchar *name = NULL; GstCaps *caps = NULL; if (!gst_uri_is_valid (uri)) return FALSE; name = g_strdup_printf("%s-%s", stream->name, "downloader"); stream->pipe = gst_pipeline_new (name); if (!stream->pipe) { GST_ERROR_OBJECT (demux, "failed to create pipeline"); return FALSE; } g_free(name); name = g_strdup_printf("%s-%s", stream->name, "httpsrc"); GST_DEBUG ("Creating source element for the URI:%s", uri); stream->urisrc = gst_element_make_from_uri (GST_URI_SRC, uri, name); if (!stream->urisrc) { GST_ERROR_OBJECT (demux, "failed to create urisrc"); return FALSE; } g_free(name); if (GST_SSM_PARSE_IS_LIVE_PRESENTATION(demux->parser)) g_object_set (G_OBJECT (stream->urisrc), "is-live", TRUE, NULL); else g_object_set (G_OBJECT (stream->urisrc), "is-live", FALSE, NULL); name = g_strdup_printf("%s-%s", stream->name, "parser"); stream->parser = gst_element_factory_make ("piffdemux", name); if (!stream->parser) { GST_ERROR_OBJECT (demux, "failed to create piffdemux element"); return FALSE; } caps = ssm_parse_get_stream_caps (demux->parser, stream->type); GST_INFO_OBJECT (stream->pad, "prepare caps = %s", gst_caps_to_string(caps)); g_object_set (G_OBJECT (stream->parser), "caps", caps, NULL); g_object_set (G_OBJECT (stream->parser), "start-ts", start_ts, NULL); g_object_set (G_OBJECT (stream->parser), "duration", GST_SSM_PARSE_GET_DURATION(demux->parser), NULL); g_object_set (G_OBJECT (stream->parser), "is-live", GST_SSM_PARSE_IS_LIVE_PRESENTATION(demux->parser), NULL); g_object_set (G_OBJECT (stream->parser), "lookahead-count", GST_SSM_PARSE_LOOKAHEAD_COUNT(demux->parser), NULL); g_signal_connect (stream->parser, "live-param", G_CALLBACK (gst_ss_demux_append_live_params), stream); g_free(name); name = g_strdup_printf("%s-%s", stream->name, "sink"); stream->sink = gst_element_factory_make ("appsink", name); if (!stream->sink) { GST_ERROR_OBJECT (demux, "failed to create appsink element"); return FALSE; } g_object_set (G_OBJECT (stream->sink), "emit-signals", TRUE, "sync", FALSE, NULL); g_signal_connect (stream->sink, "new-buffer", G_CALLBACK (gst_ssm_demux_on_new_buffer), stream); g_free(name); gst_bin_add_many (GST_BIN (stream->pipe), stream->urisrc, stream->parser, stream->sink, NULL); if (!gst_element_link_many (stream->urisrc, stream->parser, stream->sink, NULL)) { GST_ERROR ("failed to link elements..."); return FALSE; } stream->bus = gst_pipeline_get_bus (GST_PIPELINE (stream->pipe)); gst_bus_add_watch (stream->bus, (GstBusFunc)gst_ss_demux_download_bus_cb, stream); gst_object_unref (stream->bus); return TRUE; }
static gboolean gst_ss_demux_create_dummy_pipe (GstSSDemux * demux, GstSSDemuxStream *stream) { gchar *name = NULL; GstCaps *caps = NULL; GstElement *capsfilter = NULL; GstElement *enc = NULL; guint64 avg_dur = -1; guint frame_rate = 0; name = g_strdup_printf("%s-%s", stream->name, "dummy"); stream->pipe = gst_pipeline_new (name); if (!stream->pipe) { GST_ERROR_OBJECT (demux, "failed to create pipeline"); return FALSE; } g_free(name); /* create dummy sender source */ name = g_strdup_printf("%s-%s", stream->name, "dummysrc"); stream->urisrc = gst_element_factory_make ("imagereader", name); if (!stream->urisrc) { GST_ERROR_OBJECT (demux,"failed to create filesrc element"); return FALSE; } g_free(name); g_object_set (G_OBJECT (stream->urisrc), "location", "/opt/home/root/aonly_VGA_1frame_I420.yuv", NULL); g_object_set (G_OBJECT (stream->urisrc), "framerate", 25, NULL); g_object_set (G_OBJECT (stream->urisrc), "num-buffers", 60, NULL); /* caps filter */ capsfilter = gst_element_factory_make ("capsfilter", NULL); if (!capsfilter) { GST_ERROR_OBJECT (demux, "failed to create capsfilter element"); return FALSE; } caps = gst_caps_new_simple ("video/x-raw-yuv", "width", G_TYPE_INT, 640, "height", G_TYPE_INT, 480, "framerate",GST_TYPE_FRACTION, 25,1, "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'), NULL); g_object_set (G_OBJECT (capsfilter), "caps", caps, NULL); /* create h264parse element */ enc = gst_element_factory_make ("savsenc_h264", "H264 encoder"); if (!enc) { GST_ERROR_OBJECT (demux, "failed to create h264 parse element"); return FALSE; } name = g_strdup_printf("%s-%s", stream->name, "sink"); stream->sink = gst_element_factory_make ("appsink", name); if (!stream->sink) { GST_ERROR_OBJECT (demux, "failed to create appsink element"); return FALSE; } g_free(name); g_object_set (G_OBJECT (stream->sink), "emit-signals", TRUE, "sync", FALSE, NULL); g_signal_connect (stream->sink, "new-buffer", G_CALLBACK (gst_ssm_demux_on_new_buffer), stream); /* add to pipeline & link all elements */ gst_bin_add_many (GST_BIN (stream->pipe), stream->urisrc, capsfilter, enc, stream->sink, NULL); if (!gst_element_link_many (stream->urisrc, capsfilter, enc, stream->sink, NULL)) { GST_ERROR_OBJECT (demux,"failed to link dummy pipe elements..."); return FALSE; } stream->bus = gst_pipeline_get_bus (GST_PIPELINE (stream->pipe)); gst_bus_add_watch (stream->bus, (GstBusFunc)gst_ss_demux_download_bus_cb, stream); gst_object_unref (stream->bus); return TRUE; }
/***************************************************************************** * 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 = 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; }
gboolean ly_mdh_push(LyMdhMetadata *md) { if(!md||!g_str_has_prefix(md->uri, "file://")) return FALSE; if(!g_mutex_trylock(ly_mdh_put_mutex)) { ly_log_put_with_flag(G_LOG_LEVEL_WARNING, _("An old task is running, Tag Failed!")); return FALSE; } /* * BUILD */ GstElement *filesrc=NULL; GstElement *demux=NULL; GstElement *mux=NULL; GstElement *parse=NULL; GstElement *filesink=NULL; GstElement *tagger=NULL; GstBus *bus=NULL; const gchar *codec=NULL; ly_mdh_put_pipeline=gst_pipeline_new("pipeline"); filesrc=gst_element_factory_make("filesrc","filesrc"); filesink=gst_element_factory_make("filesink","filesink"); if(!ly_mdh_put_pipeline||!filesrc||!filesink) { if(ly_mdh_put_pipeline); gst_object_unref(ly_mdh_put_pipeline); g_mutex_unlock(ly_mdh_put_mutex); return FALSE; } //MP3 if(strstr(md->codec,"MP3")!=NULL) { demux=gst_element_factory_make("id3demux","demux"); tagger=gst_element_factory_make("id3v2mux","tagger"); codec = "LAME"; if(!demux||!tagger) { gst_object_unref(ly_mdh_put_pipeline); g_mutex_unlock(ly_mdh_put_mutex); return FALSE; } } //OGG else if(strstr(md->codec,"Vorbis")!=NULL) { tagger = gst_element_factory_make("vorbistag", "tagger"); demux=gst_element_factory_make("oggdemux","demux"); mux=gst_element_factory_make("oggmux","mux"); parse = gst_element_factory_make("vorbisparse", "parse"); codec = "Vorbis"; if(!demux||!mux||!tagger||!parse) { gst_object_unref(ly_mdh_put_pipeline); g_mutex_unlock(ly_mdh_put_mutex); return FALSE; } } //FLAC else if(strstr(md->codec,"FLAC")!=NULL) { tagger = gst_element_factory_make("flactag", "tagger"); codec="FLAC"; if(!tagger) { gst_object_unref(ly_mdh_put_pipeline); g_mutex_unlock(ly_mdh_put_mutex); return FALSE; } } //APE else if(strstr(md->codec,"Monkey's Audio")!=NULL) { demux=gst_element_factory_make("apedemux","demux"); tagger=gst_element_factory_make("apev2mux","tagger"); codec="LAME"; if(!demux||!tagger) { gst_object_unref(ly_mdh_put_pipeline); g_mutex_unlock(ly_mdh_put_mutex); return FALSE; } } else { gst_object_unref(ly_mdh_put_pipeline); g_mutex_unlock(ly_mdh_put_mutex); return FALSE; } /* * SET */ gchar location_i[1024]=""; gchar location_o[1024]=""; g_snprintf(location_i, sizeof(location_i), "%s", md->uri+7); g_snprintf(location_o, sizeof(location_o), "%s%s-%s.audio", LY_GLA_TEMPDIR, md->artist, md->title); g_object_set(G_OBJECT(filesrc), "location", location_i, NULL); g_object_set(G_OBJECT(filesink), "location", location_o, NULL); gst_tag_setter_add_tags(GST_TAG_SETTER(tagger), GST_TAG_MERGE_REPLACE_ALL, GST_TAG_TITLE, md->title, GST_TAG_ARTIST, md->artist, GST_TAG_ALBUM, md->album, GST_TAG_GENRE, md->genre, GST_TAG_TRACK_NUMBER, md->track, GST_TAG_ENCODER, "Linnya", GST_TAG_ENCODER_VERSION, 1, GST_TAG_CODEC,codec, NULL); /* *LINK */ //MP3 if(strstr(md->codec,"MP3")!=NULL) { gst_bin_add_many(GST_BIN(ly_mdh_put_pipeline), filesrc, demux,tagger,filesink, NULL); g_signal_connect(demux, "pad-added",G_CALLBACK(ly_mdh_push_add_id3_pad_cb), tagger); gst_element_link(filesrc, demux); gst_element_link(tagger, filesink); } //OGG else if(strstr(md->codec,"Vorbis")!=NULL) { gst_bin_add_many(GST_BIN(ly_mdh_put_pipeline), filesrc, demux, tagger, parse, mux, filesink, NULL); g_signal_connect(demux, "pad-added",G_CALLBACK(ly_mdh_push_add_ogg_pad_cb), tagger); gst_element_link(filesrc, demux); gst_element_link_many(tagger, parse, mux, filesink,NULL); } //FLAC else if(strstr(md->codec,"FLAC")!=NULL) { gst_bin_add_many(GST_BIN(ly_mdh_put_pipeline), filesrc, tagger, filesink, NULL); gst_element_link_many(filesrc, tagger, filesink, NULL); } //APE else if(strstr(md->codec,"Monkey's Audio")!=NULL) { gst_bin_add_many(GST_BIN(ly_mdh_put_pipeline), filesrc, demux,tagger,filesink, NULL); g_signal_connect(demux, "pad-added",G_CALLBACK(ly_mdh_push_add_id3_pad_cb), tagger); gst_element_link(filesrc, demux); gst_element_link(tagger, filesink); } else { gst_object_unref(ly_mdh_put_pipeline); g_mutex_unlock(ly_mdh_put_mutex); return FALSE; } bus = gst_pipeline_get_bus(GST_PIPELINE(ly_mdh_put_pipeline)); gst_bus_add_watch(bus, (GstBusFunc)ly_mdh_push_handler_cb, g_memdup(md,sizeof(LyMdhMetadata))); gst_object_unref(bus); gst_element_set_state(ly_mdh_put_pipeline, GST_STATE_NULL); gst_element_set_state(ly_mdh_put_pipeline, GST_STATE_READY); if(gst_element_set_state(ly_mdh_put_pipeline, GST_STATE_PLAYING)==GST_STATE_CHANGE_FAILURE) { gst_element_set_state(ly_mdh_put_pipeline, GST_STATE_NULL); gst_object_unref(ly_mdh_put_pipeline); g_mutex_unlock(ly_mdh_put_mutex); return FALSE; } return TRUE; }
/** * ly_gla_fina: * * Create a new allocate LyMdhMetadata type structure based on a uri. It fills * all fields in metadata struct. * * Returns: a newly allocated metadata struct. */ LyMdhMetadata* ly_mdh_new_with_uri_full (char *uri) { /* * test file */ char *prefix=ly_gla_uri_get_prefix(uri); char *path=ly_gla_uri_get_path(uri); if(!g_str_equal(prefix, "file://")) { g_free(prefix); ly_log_put_with_flag(G_LOG_LEVEL_DEBUG, _("Cannot open file: %s. unsupported protocol!"), uri); return NULL; } g_free(prefix); if(!g_file_test(path, G_FILE_TEST_EXISTS)) { g_free(path); ly_log_put_with_flag(G_LOG_LEVEL_DEBUG, _("Cannot open file: %s. file not found!"), uri); return NULL; } g_free(path); ly_mdh_pipeline=NULL; ly_mdh_md_eos=FALSE; /* * create and initial metadata */ LyMdhMetadata *metadata=ly_mdh_new(); g_strlcpy(metadata->uri, uri, sizeof(metadata->uri)); /* * build the pipeline */ GstFormat fmt=GST_FORMAT_TIME; GstElement *urisrc; GstElement *decodebin; GstElement *fakesink; GstBus *bus=NULL; gint changeTimeout = 0; GstStateChangeReturn rt; GstMessage *msg; ly_mdh_pipeline=gst_pipeline_new("pipeline"); urisrc=gst_element_make_from_uri(GST_URI_SRC,metadata->uri,"urisrc"); decodebin=gst_element_factory_make("decodebin","decodebin"); fakesink=gst_element_factory_make("fakesink","fakesink"); gst_bin_add_many(GST_BIN(ly_mdh_pipeline),urisrc,decodebin,fakesink,NULL); gst_element_link(urisrc,decodebin); g_signal_connect_object(G_OBJECT(decodebin),"new-decoded-pad",G_CALLBACK(ly_mdh_new_with_uri_pipe_cb),fakesink,0); bus = gst_pipeline_get_bus(GST_PIPELINE(ly_mdh_pipeline)); gst_element_set_state(ly_mdh_pipeline,GST_STATE_NULL); gst_element_set_state(ly_mdh_pipeline,GST_STATE_READY); rt = gst_element_set_state(ly_mdh_pipeline,GST_STATE_PAUSED); if(!rt) { if(ly_mdh_pipeline!=NULL) gst_object_unref(GST_OBJECT(ly_mdh_pipeline)); ly_mdh_md_eos=FALSE; ly_mdh_pipeline=NULL; return FALSE; } while(rt==GST_STATE_CHANGE_ASYNC && !ly_mdh_md_eos && changeTimeout < 5) { msg = gst_bus_timed_pop(bus, 1 * GST_SECOND); if(msg!=NULL) { ly_mdh_new_with_uri_full_bus_cb(bus, msg, metadata); gst_message_unref(msg); changeTimeout = 0; } else changeTimeout++; rt = gst_element_get_state(ly_mdh_pipeline, NULL, NULL, 0); } gst_object_unref(bus); ly_mdh_new_with_uri_full_loop_cb(metadata, ly_mdh_pipeline, FALSE); if(rt!=GST_STATE_CHANGE_SUCCESS) { gst_element_set_state(ly_mdh_pipeline,GST_STATE_NULL); if(ly_mdh_pipeline!=NULL) gst_object_unref(GST_OBJECT(ly_mdh_pipeline)); return FALSE; } /* * get duration */ gint64 dura=0; gst_element_query_duration(ly_mdh_pipeline,&fmt,&dura); char *duration=ly_mdh_time_int2str(dura); g_strlcpy(metadata->duration,duration,sizeof(metadata->duration)); g_free(duration); rt = gst_element_set_state(ly_mdh_pipeline,GST_STATE_NULL); gst_object_unref(ly_mdh_pipeline); char *str; if(g_str_equal(metadata->title,"")||g_str_equal(metadata->title,"unknown")) { str=ly_gla_uri_get_filename(uri); g_strlcpy(metadata->title,str,sizeof(metadata->title)); g_free(str); } ly_mdh_pipeline=NULL; ly_mdh_md_eos=FALSE; return metadata; }
void CddaSongLoader::LoadSongs() { QMutexLocker locker(&mutex_load_); cdio_ = cdio_open(url_.path().toLocal8Bit().constData(), DRIVER_DEVICE); if (cdio_ == nullptr) { return; } // Create gstreamer cdda element GError* error = nullptr; cdda_ = gst_element_make_from_uri(GST_URI_SRC, "cdda://", nullptr, &error); if (error) { qLog(Error) << error->code << error->message; } if (cdda_ == nullptr) { return; } if (!url_.isEmpty()) { g_object_set(cdda_, "device", g_strdup(url_.path().toLocal8Bit().constData()), nullptr); } if (g_object_class_find_property (G_OBJECT_GET_CLASS (cdda_), "paranoia-mode")) { g_object_set (cdda_, "paranoia-mode", 0, NULL); } // Change the element's state to ready and paused, to be able to query it if (gst_element_set_state(cdda_, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE || gst_element_set_state(cdda_, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { gst_element_set_state(cdda_, GST_STATE_NULL); gst_object_unref(GST_OBJECT(cdda_)); return; } // Get number of tracks GstFormat fmt = gst_format_get_by_nick("track"); GstFormat out_fmt = fmt; gint64 num_tracks = 0; if (!gst_element_query_duration(cdda_, out_fmt, &num_tracks) || out_fmt != fmt) { qLog(Error) << "Error while querying cdda GstElement"; gst_object_unref(GST_OBJECT(cdda_)); return; } SongList songs; for (int track_number = 1; track_number <= num_tracks; track_number++) { // Init song Song song; song.set_id(track_number); song.set_valid(true); song.set_filetype(Song::Type_Cdda); song.set_url( GetUrlFromTrack(track_number)); song.set_title(QString("Track %1").arg(track_number)); song.set_track(track_number); songs << song; } emit SongsLoaded(songs); gst_tag_register_musicbrainz_tags(); GstElement* pipeline = gst_pipeline_new("pipeline"); GstElement* sink = gst_element_factory_make ("fakesink", NULL); gst_bin_add_many (GST_BIN (pipeline), cdda_, sink, NULL); gst_element_link (cdda_, sink); gst_element_set_state(pipeline, GST_STATE_READY); gst_element_set_state(pipeline, GST_STATE_PAUSED); // Get TOC and TAG messages GstMessage* msg = nullptr; GstMessage* msg_toc = nullptr; GstMessage* msg_tag = nullptr; while ((msg = gst_bus_timed_pop_filtered(GST_ELEMENT_BUS(pipeline), GST_SECOND, (GstMessageType)(GST_MESSAGE_TOC | GST_MESSAGE_TAG)))) { if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_TOC) { if (msg_toc) gst_message_unref(msg_toc); // Shouldn't happen, but just in case msg_toc = msg; } else if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_TAG) { if (msg_tag) gst_message_unref(msg_tag); msg_tag = msg; } } // Handle TOC message: get tracks duration if (msg_toc) { GstToc* toc; gst_message_parse_toc (msg_toc, &toc, nullptr); if (toc) { GList* entries = gst_toc_get_entries(toc); if (entries && songs.size() <= g_list_length (entries)) { int i = 0; for (GList* node = entries; node != nullptr; node = node->next) { GstTocEntry *entry = static_cast<GstTocEntry*>(node->data); quint64 duration = 0; gint64 start, stop; if (gst_toc_entry_get_start_stop_times (entry, &start, &stop)) duration = stop - start; songs[i++].set_length_nanosec(duration); } } } gst_message_unref(msg_toc); } emit SongsDurationLoaded(songs); // Handle TAG message: generate MusicBrainz DiscId if (msg_tag) { GstTagList* tags = nullptr; gst_message_parse_tag(msg_tag, &tags); char* string_mb = nullptr; if (gst_tag_list_get_string(tags, GST_TAG_CDDA_MUSICBRAINZ_DISCID, &string_mb)) { QString musicbrainz_discid(string_mb); qLog(Info) << "MusicBrainz discid: " << musicbrainz_discid; MusicBrainzClient* musicbrainz_client = new MusicBrainzClient; connect(musicbrainz_client, SIGNAL(Finished(const QString&, const QString&, MusicBrainzClient::ResultList)), SLOT(AudioCDTagsLoaded(const QString&, const QString&, MusicBrainzClient::ResultList))); musicbrainz_client->StartDiscIdRequest(musicbrainz_discid); g_free(string_mb); gst_message_unref(msg_tag); gst_tag_list_free(tags); } } gst_element_set_state(pipeline, GST_STATE_NULL); // This will also cause cdda_ to be unref'd. gst_object_unref(pipeline); }
static GstElement * gst_auto_audio_src_find_best (GstAutoAudioSrc * src) { GList *list, *item; GstElement *choice = NULL; GstMessage *message = NULL; GSList *errors = NULL; GstBus *bus = gst_bus_new (); GstPad *el_pad = NULL; GstCaps *el_caps = NULL, *intersect = NULL; gboolean no_match = TRUE; list = gst_registry_feature_filter (gst_registry_get_default (), (GstPluginFeatureFilter) gst_auto_audio_src_factory_filter, FALSE, src); list = g_list_sort (list, (GCompareFunc) gst_auto_audio_src_compare_ranks); /* We don't treat sound server sources special. Our policy is that sound * server sources that have a rank must not auto-spawn a daemon under any * circumstances, so there's nothing for us to worry about here */ GST_LOG_OBJECT (src, "Trying to find usable audio devices ..."); for (item = list; item != NULL; item = item->next) { GstElementFactory *f = GST_ELEMENT_FACTORY (item->data); GstElement *el; if ((el = gst_auto_audio_src_create_element_with_pretty_name (src, f))) { GstStateChangeReturn ret; GST_DEBUG_OBJECT (src, "Testing %s", GST_PLUGIN_FEATURE (f)->name); /* If autoAudioSrc has been provided with filter caps, * accept only sources that match with the filter caps */ if (src->filter_caps) { el_pad = gst_element_get_static_pad (GST_ELEMENT (el), "src"); el_caps = gst_pad_get_caps (el_pad); gst_object_unref (el_pad); GST_DEBUG_OBJECT (src, "Checking caps: %" GST_PTR_FORMAT " vs. %" GST_PTR_FORMAT, src->filter_caps, el_caps); intersect = gst_caps_intersect (src->filter_caps, el_caps); no_match = gst_caps_is_empty (intersect); gst_caps_unref (el_caps); gst_caps_unref (intersect); if (no_match) { GST_DEBUG_OBJECT (src, "Incompatible caps"); gst_object_unref (el); continue; } else { GST_DEBUG_OBJECT (src, "Found compatible caps"); } } gst_element_set_bus (el, bus); ret = gst_element_set_state (el, GST_STATE_READY); if (ret == GST_STATE_CHANGE_SUCCESS) { GST_DEBUG_OBJECT (src, "This worked!"); choice = el; break; } /* collect all error messages */ while ((message = gst_bus_pop_filtered (bus, GST_MESSAGE_ERROR))) { GST_DEBUG_OBJECT (src, "error message %" GST_PTR_FORMAT, message); errors = g_slist_append (errors, message); } gst_element_set_state (el, GST_STATE_NULL); gst_object_unref (el); } } GST_DEBUG_OBJECT (src, "done trying"); if (!choice) { if (errors) { /* FIXME: we forward the first error for now; but later on it might make * sense to actually analyse them */ gst_message_ref (GST_MESSAGE (errors->data)); GST_DEBUG_OBJECT (src, "reposting message %p", errors->data); gst_element_post_message (GST_ELEMENT (src), GST_MESSAGE (errors->data)); } else { /* send warning message to application and use a fakesrc */ GST_ELEMENT_WARNING (src, RESOURCE, NOT_FOUND, (NULL), ("Failed to find a usable audio source")); choice = gst_element_factory_make ("fakesrc", "fake-audio-src"); if (g_object_class_find_property (G_OBJECT_GET_CLASS (choice), "sync")) g_object_set (choice, "sync", TRUE, NULL); gst_element_set_state (choice, GST_STATE_READY); } } gst_object_unref (bus); gst_plugin_feature_list_free (list); g_slist_foreach (errors, (GFunc) gst_mini_object_unref, NULL); g_slist_free (errors); return choice; }