X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/9b9ac227931a2f378e45bddd5d3917816181b9b9..8a1642be593db66a12a14f50e20cc297232a1ce2:/lib/service/servicemp3.cpp diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index a1c035ba..0c528997 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -2,20 +2,23 @@ /* note: this requires gstreamer 0.10.x and a big list of plugins. */ /* it's currently hardcoded to use a big-endian alsasink as sink. */ +#include #include +#include +#include +#include #include -#include -#include +#include +#include +#include #include #include -#include -#include -#include + +#include + #include #include #include -/* for subtitles */ -#include // eServiceFactoryMP3 @@ -34,6 +37,7 @@ eServiceFactoryMP3::eServiceFactoryMP3() extensions.push_back("vob"); extensions.push_back("wav"); extensions.push_back("wave"); + extensions.push_back("m4v"); extensions.push_back("mkv"); extensions.push_back("avi"); extensions.push_back("divx"); @@ -187,6 +191,8 @@ int eStaticServiceMP3Info::getLength(const eServiceReference &ref) } // eServiceMP3 +int eServiceMP3::ac3_delay, + eServiceMP3::pcm_delay; eServiceMP3::eServiceMP3(eServiceReference ref) :m_ref(ref), m_pump(eApp, 1) @@ -194,7 +200,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref) m_seekTimeout = eTimer::create(eApp); m_subtitle_sync_timer = eTimer::create(eApp); m_stream_tags = 0; - m_currentAudioStream = 0; + m_currentAudioStream = -1; m_currentSubtitleStream = 0; m_subtitle_widget = 0; m_currentTrickRatio = 0; @@ -236,7 +242,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref) sourceinfo.containertype = ctAVI; sourceinfo.is_video = TRUE; } - else if ( strcasecmp(ext, ".mp4") == 0 || strcasecmp(ext, ".mov") == 0) + else if ( strcasecmp(ext, ".mp4") == 0 || strcasecmp(ext, ".mov") == 0 || strcasecmp(ext, ".m4v") == 0) { sourceinfo.containertype = ctMP4; sourceinfo.is_video = TRUE; @@ -302,7 +308,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref) eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-appsink"); else { - g_signal_connect (subsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); + m_subs_to_pull_handler_id = g_signal_connect (subsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); g_object_set (G_OBJECT (m_gst_playbin), "text-sink", subsink, NULL); } @@ -335,16 +341,28 @@ eServiceMP3::eServiceMP3(eServiceReference ref) m_gst_playbin = 0; } - gst_element_set_state (m_gst_playbin, GST_STATE_PLAYING); setBufferSize(m_buffer_size); } eServiceMP3::~eServiceMP3() { + // disconnect subtitle callback + GstElement *sink; + g_object_get (G_OBJECT (m_gst_playbin), "text-sink", &sink, NULL); + if (sink) + { + g_signal_handler_disconnect (sink, m_subs_to_pull_handler_id); + gst_object_unref(sink); + } + delete m_subtitle_widget; + + // disconnect sync handler callback + gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)), NULL, NULL); + if (m_state == stRunning) stop(); - + if (m_stream_tags) gst_tag_list_free(m_stream_tags); @@ -355,7 +373,7 @@ eServiceMP3::~eServiceMP3() } } -DEFINE_REF(eServiceMP3); +DEFINE_REF(eServiceMP3); RESULT eServiceMP3::connectEvent(const Slot2 &event, ePtr &connection) { @@ -366,25 +384,30 @@ RESULT eServiceMP3::connectEvent(const Slot2 &event, RESULT eServiceMP3::start() { ASSERT(m_state == stIdle); - + m_state = stRunning; if (m_gst_playbin) { eDebug("eServiceMP3::starting pipeline"); gst_element_set_state (m_gst_playbin, GST_STATE_PLAYING); } + m_event(this, evStart); + return 0; } RESULT eServiceMP3::stop() { ASSERT(m_state != stIdle); + if (m_state == stStopped) return -1; + eDebug("eServiceMP3::stop %s", m_ref.path.c_str()); gst_element_set_state(m_gst_playbin, GST_STATE_NULL); m_state = stStopped; + return 0; } @@ -522,11 +545,11 @@ RESULT eServiceMP3::trickSeek(gdouble ratio) return seekRelative(0, 0); GstEvent *s_event; - GstSeekFlags flags; + int flags; flags = GST_SEEK_FLAG_NONE; - flags |= GstSeekFlags (GST_SEEK_FLAG_FLUSH); + flags |= GST_SEEK_FLAG_FLUSH; // flags |= GstSeekFlags (GST_SEEK_FLAG_ACCURATE); - flags |= GstSeekFlags (GST_SEEK_FLAG_KEY_UNIT); + flags |= GST_SEEK_FLAG_KEY_UNIT; // flags |= GstSeekFlags (GST_SEEK_FLAG_SEGMENT); // flags |= GstSeekFlags (GST_SEEK_FLAG_SKIP); @@ -537,13 +560,13 @@ RESULT eServiceMP3::trickSeek(gdouble ratio) if ( ratio >= 0 ) { - s_event = gst_event_new_seek (ratio, GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, len); + s_event = gst_event_new_seek (ratio, GST_FORMAT_TIME, (GstSeekFlags)flags, GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, len); eDebug("eServiceMP3::trickSeek with rate %lf to %" GST_TIME_FORMAT " ", ratio, GST_TIME_ARGS (pos)); } else { - s_event = gst_event_new_seek (ratio, GST_FORMAT_TIME, GST_SEEK_FLAG_SKIP|GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1); + s_event = gst_event_new_seek (ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_SKIP|GST_SEEK_FLAG_FLUSH), GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1); } if (!gst_element_send_event ( GST_ELEMENT (m_gst_playbin), s_event)) @@ -642,7 +665,6 @@ RESULT eServiceMP3::getName(std::string &name) return 0; } - int eServiceMP3::getInfo(int w) { const gchar *tag = 0; @@ -899,10 +921,7 @@ PyObject *eServiceMP3::getInfoObject(int w) default: break; } - gdouble value; - if ( !tag || !m_stream_tags ) - value = 0.0; - PyObject *pyValue; + if ( isBuffer ) { const GValue *gv_buffer = gst_tag_list_get_value_index(m_stream_tags, tag, 0); @@ -910,16 +929,17 @@ PyObject *eServiceMP3::getInfoObject(int w) { GstBuffer *buffer; buffer = gst_value_get_buffer (gv_buffer); - pyValue = PyBuffer_FromMemory(GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); + return PyBuffer_FromMemory(GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); } } else { + gdouble value = 0.0; gst_tag_list_get_double(m_stream_tags, tag, &value); - pyValue = PyFloat_FromDouble(value); + return PyFloat_FromDouble(value); } - return pyValue; + return 0; } RESULT eServiceMP3::audioChannel(ePtr &ptr) @@ -940,6 +960,12 @@ RESULT eServiceMP3::subtitle(ePtr &ptr) return 0; } +RESULT eServiceMP3::audioDelay(ePtr &ptr) +{ + ptr = this; + return 0; +} + int eServiceMP3::getNumberOfTracks() { return m_audioStreams.size(); @@ -947,6 +973,8 @@ int eServiceMP3::getNumberOfTracks() int eServiceMP3::getCurrentTrack() { + if (m_currentAudioStream == -1) + g_object_get (G_OBJECT (m_gst_playbin), "current-audio", &m_currentAudioStream, NULL); return m_currentAudioStream; } @@ -1076,6 +1104,8 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) g_object_set (G_OBJECT (sink), "emit-signals", TRUE, NULL); gst_object_unref(sink); } + setAC3Delay(ac3_delay); + setPCMDelay(pcm_delay); } break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: { @@ -1187,8 +1217,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) if (!caps) continue; GstStructure* str = gst_caps_get_structure(caps, 0); - gchar *g_type; - g_type = gst_structure_get_name(str); + const gchar *g_type = gst_structure_get_name(str); eDebug("AUDIO STRUCT=%s", g_type); audio.type = gstCheckAudioPad(str); g_codec = g_strdup(g_type); @@ -1563,6 +1592,77 @@ int eServiceMP3::setBufferSize(int size) return 0; } +int eServiceMP3::getAC3Delay() +{ + return ac3_delay; +} + +int eServiceMP3::getPCMDelay() +{ + return pcm_delay; +} + +void eServiceMP3::setAC3Delay(int delay) +{ + ac3_delay = delay; + if (!m_gst_playbin || m_state != stRunning) + return; + else + { + GstElement *sink; + std::string config_delay; + int config_delay_int = delay; + if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0) + config_delay_int += atoi(config_delay.c_str()); + + g_object_get (G_OBJECT (m_gst_playbin), "audio-sink", &sink, NULL); + + if (!sink) + return; + else { + gchar *name = gst_element_get_name(sink); + + if (strstr(name, "dvbaudiosink")) + eTSMPEGDecoder::setHwAC3Delay(config_delay_int); + g_free(name); + gst_object_unref(sink); + } + } +} + +void eServiceMP3::setPCMDelay(int delay) +{ + pcm_delay = delay; + if (!m_gst_playbin || m_state != stRunning) + return; + else + { + GstElement *sink; + std::string config_delay; + int config_delay_int = delay; + if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0) + config_delay_int += atoi(config_delay.c_str()); + + g_object_get (G_OBJECT (m_gst_playbin), "audio-sink", &sink, NULL); + + if (!sink) + return; + else { + gchar *name = gst_element_get_name(sink); + + if (strstr(name, "dvbaudiosink")) + eTSMPEGDecoder::setHwPCMDelay(config_delay_int); + else { + // this is realy untested..and not used yet + gint64 offset = config_delay_int; + offset *= 1000000; // milli to nano + g_object_set (G_OBJECT (m_gst_playbin), "ts-offset", offset, NULL); + } + g_free(name); + gst_object_unref(sink); + } + } +} #else #warning gstreamer not available, not building media player