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;
}
Beispiel #3
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 = 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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
/**
 * 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;
}
Beispiel #6
0
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);
}
Beispiel #7
0
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;
}