+audiotype_t eServiceMP3::gstCheckAudioPad(GstStructure* structure)
+{
+ const gchar* type;
+ type = gst_structure_get_name(structure);
+
+ if (!strcmp(type, "audio/mpeg")) {
+ gint mpegversion, layer = 0;
+ gst_structure_get_int (structure, "mpegversion", &mpegversion);
+ gst_structure_get_int (structure, "layer", &layer);
+ eDebug("mime audio/mpeg version %d layer %d", mpegversion, layer);
+ switch (mpegversion) {
+ case 1:
+ {
+ if ( layer == 3 )
+ return atMP3;
+ else
+ return atMPEG;
+ }
+ case 2:
+ return atMPEG;
+ case 4:
+ return atAAC;
+ default:
+ return atUnknown;
+ }
+ }
+ else
+ {
+ eDebug("mime %s", type);
+ if (!strcmp(type, "audio/x-ac3") || !strcmp(type, "audio/ac3"))
+ return atAC3;
+ else if (!strcmp(type, "audio/x-dts") || !strcmp(type, "audio/dts"))
+ return atDTS;
+ else if (!strcmp(type, "audio/x-raw-int"))
+ return atPCM;
+ }
+ return atUnknown;
+}
+
+void eServiceMP3::gstCBpadAdded(GstElement *decodebin, GstPad *pad, gpointer user_data)
+{
+ const gchar* type;
+ GstCaps* caps;
+ GstStructure* str;
+ caps = gst_pad_get_caps(pad);
+ str = gst_caps_get_structure(caps, 0);
+ type = gst_structure_get_name(str);
+
+ eDebug("A new pad %s:%s was created", GST_OBJECT_NAME (decodebin), GST_OBJECT_NAME (pad));
+
+ eServiceMP3 *_this = (eServiceMP3*)user_data;
+ GstBin *pipeline = GST_BIN(_this->m_gst_pipeline);
+ if (g_strrstr(type,"audio"))
+ {
+ audioStream audio;
+ audio.type = _this->gstCheckAudioPad(str);
+ GstElement *switch_audio = gst_bin_get_by_name(pipeline , "switch_audio");
+ if ( switch_audio )
+ {
+ GstPad *sinkpad = gst_element_get_request_pad (switch_audio, "sink%d");
+ gst_pad_link(pad, sinkpad);
+ audio.pad = sinkpad;
+ _this->m_audioStreams.push_back(audio);
+
+ if ( _this->m_audioStreams.size() == 1 )
+ {
+ _this->selectAudioStream(0);
+ gst_element_set_state (_this->m_gst_pipeline, GST_STATE_PLAYING);
+ }
+ else
+ g_object_set (G_OBJECT (switch_audio), "select-all", FALSE, NULL);
+ }
+ else
+ {
+ gst_pad_link(pad, gst_element_get_static_pad(gst_bin_get_by_name(pipeline,"queue_audio"), "sink"));
+ _this->m_audioStreams.push_back(audio);
+ }
+ }
+ if (g_strrstr(type,"video"))
+ {
+ gst_pad_link(pad, gst_element_get_static_pad(gst_bin_get_by_name(pipeline,"queue_video"), "sink"));
+ }
+ if (g_strrstr(type,"application/x-ssa") || g_strrstr(type,"application/x-ass"))
+ {
+ GstPad *switchpad = _this->gstCreateSubtitleSink(_this, stSSA);
+ gst_pad_link(pad, switchpad);
+ subtitleStream subs;
+ subs.pad = switchpad;
+ subs.type = stSSA;
+ _this->m_subtitleStreams.push_back(subs);
+ }
+ if (g_strrstr(type,"text/plain"))
+ {
+ GstPad *switchpad = _this->gstCreateSubtitleSink(_this, stPlainText);
+ gst_pad_link(pad, switchpad);
+ subtitleStream subs;
+ subs.pad = switchpad;
+ subs.type = stPlainText;
+ _this->m_subtitleStreams.push_back(subs);
+ }
+}
+
+GstPad* eServiceMP3::gstCreateSubtitleSink(eServiceMP3* _this, subtype_t type)
+{
+ GstBin *pipeline = GST_BIN(_this->m_gst_pipeline);
+ GstElement *switch_subparse = gst_bin_get_by_name(pipeline,"switch_subparse");
+ if ( !switch_subparse )
+ {
+ switch_subparse = gst_element_factory_make ("input-selector", "switch_subparse");
+ GstElement *sink = gst_element_factory_make("fakesink", "sink_subtitles");
+ gst_bin_add_many(pipeline, switch_subparse, sink, NULL);
+ gst_element_link(switch_subparse, sink);
+ g_object_set (G_OBJECT(sink), "signal-handoffs", TRUE, NULL);
+ g_object_set (G_OBJECT(sink), "sync", TRUE, NULL);
+ g_object_set (G_OBJECT(sink), "async", FALSE, NULL);
+ g_signal_connect(sink, "handoff", G_CALLBACK(_this->gstCBsubtitleAvail), _this);
+
+ // order is essential since requested sink pad names can't be explicitely chosen
+ GstElement *switch_substream_plain = gst_element_factory_make ("input-selector", "switch_substream_plain");
+ gst_bin_add(pipeline, switch_substream_plain);
+ GstPad *sinkpad_plain = gst_element_get_request_pad (switch_subparse, "sink%d");
+ gst_pad_link(gst_element_get_pad (switch_substream_plain, "src"), sinkpad_plain);
+
+ GstElement *switch_substream_ssa = gst_element_factory_make ("input-selector", "switch_substream_ssa");
+ GstElement *ssaparse = gst_element_factory_make("ssaparse", "ssaparse");
+ gst_bin_add_many(pipeline, switch_substream_ssa, ssaparse, NULL);
+ GstPad *sinkpad_ssa = gst_element_get_request_pad (switch_subparse, "sink%d");
+ gst_element_link(switch_substream_ssa, ssaparse);
+ gst_pad_link(gst_element_get_pad (ssaparse, "src"), sinkpad_ssa);
+
+ GstElement *switch_substream_srt = gst_element_factory_make ("input-selector", "switch_substream_srt");
+ GstElement *srtparse = gst_element_factory_make("subparse", "srtparse");
+ gst_bin_add_many(pipeline, switch_substream_srt, srtparse, NULL);
+ GstPad *sinkpad_srt = gst_element_get_request_pad (switch_subparse, "sink%d");
+ gst_element_link(switch_substream_srt, srtparse);
+ gst_pad_link(gst_element_get_pad (srtparse, "src"), sinkpad_srt);
+ g_object_set (G_OBJECT(srtparse), "subtitle-encoding", "ISO-8859-15", NULL);
+ }
+
+ switch (type)
+ {
+ case stSSA:
+ return gst_element_get_request_pad (gst_bin_get_by_name(pipeline,"switch_substream_ssa"), "sink%d");
+ case stSRT:
+ return gst_element_get_request_pad (gst_bin_get_by_name(pipeline,"switch_substream_srt"), "sink%d");
+ case stPlainText:
+ default:
+ break;
+ }
+ return gst_element_get_request_pad (gst_bin_get_by_name(pipeline,"switch_substream_plain"), "sink%d");
+}
+
+void eServiceMP3::gstCBfilterPadAdded(GstElement *filter, GstPad *pad, gpointer user_data)
+{
+ eServiceMP3 *_this = (eServiceMP3*)user_data;
+ GstElement *decoder = gst_bin_get_by_name(GST_BIN(_this->m_gst_pipeline),"decoder");
+ gst_pad_link(pad, gst_element_get_static_pad (decoder, "sink"));
+}
+