X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/dd146530e8a1c9743d32b953d55e392ec5375744..13c4d4b662a1ff4b2545ccc125b61c47ee4c38a3:/lib/service/servicemp3.cpp diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index d1c50b22..34d09363 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -17,12 +17,6 @@ /* for subtitles */ #include -#ifndef GST_SEEK_FLAG_SKIP -#warning Compiling for legacy gstreamer, things will break -#define GST_SEEK_FLAG_SKIP 0 -#define GST_TAG_HOMEPAGE "" -#endif - // eServiceFactoryMP3 eServiceFactoryMP3::eServiceFactoryMP3() @@ -40,6 +34,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"); @@ -48,7 +43,6 @@ eServiceFactoryMP3::eServiceFactoryMP3() extensions.push_back("mp4"); extensions.push_back("mov"); extensions.push_back("m4a"); - extensions.push_back("m2ts"); sc->addServiceFactory(eServiceFactoryMP3::id, this, extensions); } @@ -101,6 +95,7 @@ public: RESULT deleteFromDisk(int simulate); RESULT getListOfFilenames(std::list &); + RESULT reindex(); }; DEFINE_REF(eMP3ServiceOfflineOperations); @@ -143,6 +138,11 @@ RESULT eMP3ServiceOfflineOperations::getListOfFilenames(std::list & return 0; } +RESULT eMP3ServiceOfflineOperations::reindex() +{ + return -1; +} + RESULT eServiceFactoryMP3::offlineOperations(const eServiceReference &ref, ePtr &ptr) { @@ -194,7 +194,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 +236,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 +302,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 +335,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 +367,7 @@ eServiceMP3::~eServiceMP3() } } -DEFINE_REF(eServiceMP3); +DEFINE_REF(eServiceMP3); RESULT eServiceMP3::connectEvent(const Slot2 &event, ePtr &connection) { @@ -366,25 +378,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; } @@ -440,24 +457,19 @@ RESULT eServiceMP3::pause() { if (!m_gst_playbin || m_state != stRunning) return -1; - GstStateChangeReturn res = gst_element_set_state(m_gst_playbin, GST_STATE_PAUSED); - if (res == GST_STATE_CHANGE_ASYNC) - { - pts_t ppos; - getPlayPosition(ppos); - seekTo(ppos); - } + + gst_element_set_state(m_gst_playbin, GST_STATE_PAUSED); + return 0; } RESULT eServiceMP3::unpause() { - m_subtitle_pages.clear(); if (!m_gst_playbin || m_state != stRunning) return -1; - GstStateChangeReturn res; - res = gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING); + gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING); + return 0; } @@ -472,9 +484,10 @@ RESULT eServiceMP3::getLength(pts_t &pts) { if (!m_gst_playbin) return -1; + if (m_state != stRunning) return -1; - + GstFormat fmt = GST_FORMAT_TIME; gint64 len; @@ -486,11 +499,8 @@ RESULT eServiceMP3::getLength(pts_t &pts) return 0; } -RESULT eServiceMP3::seekTo(pts_t to) +RESULT eServiceMP3::seekToImpl(pts_t to) { - if (!m_gst_playbin) - return -1; - /* convert pts to nanoseconds */ gint64 time_nanoseconds = to * 11111LL; if (!gst_element_seek (m_gst_playbin, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, @@ -501,13 +511,26 @@ RESULT eServiceMP3::seekTo(pts_t to) return -1; } - m_subtitle_pages.clear(); - eSingleLocker l(m_subs_to_pull_lock); - m_subs_to_pull = 0; - return 0; } +RESULT eServiceMP3::seekTo(pts_t to) +{ + RESULT ret = -1; + + if (m_gst_playbin) { + eSingleLocker l(m_subs_to_pull_lock); // this is needed to dont handle incomming subtitles during seek! + if (!(ret = seekToImpl(to))) + { + m_subtitle_pages.clear(); + m_subs_to_pull = 0; + } + } + + return ret; +} + + RESULT eServiceMP3::trickSeek(gdouble ratio) { if (!m_gst_playbin) @@ -516,11 +539,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); @@ -531,13 +554,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)) @@ -567,14 +590,16 @@ RESULT eServiceMP3::seekRelative(int direction, pts_t to) RESULT eServiceMP3::getPlayPosition(pts_t &pts) { + GstFormat fmt = GST_FORMAT_TIME; + gint64 pos; + GstElement *sink; + pts = 0; + if (!m_gst_playbin) return -1; if (m_state != stRunning) return -1; - GstFormat fmt = GST_FORMAT_TIME; - gint64 pos; - GstElement *sink; g_object_get (G_OBJECT (m_gst_playbin), "audio-sink", &sink, NULL); if (!sink) @@ -584,15 +609,20 @@ RESULT eServiceMP3::getPlayPosition(pts_t &pts) return -1; gchar *name = gst_element_get_name(sink); + gboolean use_get_decoder_time = strstr(name, "dvbaudiosink") || strstr(name, "dvbvideosink"); + g_free(name); - if (strstr(name, "dvbaudiosink") || strstr(name, "dvbvideosink")) + if (use_get_decoder_time) g_signal_emit_by_name(sink, "get-decoder-time", &pos); - else if (!gst_element_query_position(m_gst_playbin, &fmt, &pos)) - return -1; gst_object_unref(sink); - /* pos is in nanoseconds. we have 90 000 pts per second. */ + if (!use_get_decoder_time && !gst_element_query_position(m_gst_playbin, &fmt, &pos)) { + eDebug("gst_element_query_position failed in getPlayPosition"); + return -1; + } + + /* pos is in nanoseconds. we have 90 000 pts per second. */ pts = pos / 11111; return 0; } @@ -886,10 +916,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); @@ -897,16 +924,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) @@ -934,16 +962,24 @@ 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; } RESULT eServiceMP3::selectTrack(unsigned int i) { - int ret = selectAudioStream(i); - /* flush */ pts_t ppos; getPlayPosition(ppos); - seekTo(ppos); + ppos -= 90000; + if (ppos < 0) + ppos = 0; + + int ret = selectAudioStream(i); + if (!ret) { + /* flush */ + seekTo(ppos); + } return ret; } @@ -1028,13 +1064,13 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) case GST_MESSAGE_STATE_CHANGED: { if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin)) - return; + break; GstState old_state, new_state; gst_message_parse_state_changed(msg, &old_state, &new_state, NULL); if(old_state == new_state) - return; + break; eDebug("eServiceMP3::state transition %s -> %s", gst_element_state_get_name(old_state), gst_element_state_get_name(new_state)); @@ -1077,7 +1113,6 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) { gchar *debug; GError *err; - gst_message_parse_error (msg, &err, &debug); g_free (debug); eWarning("Gstreamer error: %s (%i) from %s", err->message, err->code, sourceName ); @@ -1139,6 +1174,9 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) } case GST_MESSAGE_ASYNC_DONE: { + if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin)) + break; + GstTagList *tags; gint i, active_idx, n_video = 0, n_audio = 0, n_text = 0; @@ -1148,6 +1186,9 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) eDebug("eServiceMP3::async-done - %d video, %d audio, %d subtitle", n_video, n_audio, n_text); + if ( n_video + n_audio <= 0 ) + stop(); + active_idx = 0; m_audioStreams.clear(); @@ -1163,8 +1204,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); @@ -1245,7 +1285,6 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) if (strstr(eventname, "Changed")) m_event((iPlayableService*)this, evVideoProgressiveChanged); } - g_free(eventname); } } break; @@ -1278,12 +1317,12 @@ audiotype_t eServiceMP3::gstCheckAudioPad(GstStructure* structure) if ( gst_structure_has_name (structure, "audio/mpeg")) { - gint mpegversion, layer = -1; + gint mpegversion, layer = -1; if (!gst_structure_get_int (structure, "mpegversion", &mpegversion)) return atUnknown; switch (mpegversion) { - case 1: + case 1: { gst_structure_get_int (structure, "layer", &layer); if ( layer == 3 ) @@ -1356,8 +1395,8 @@ void eServiceMP3::pullSubtitle() { eSingleLocker l(m_subs_to_pull_lock); --m_subs_to_pull; + g_signal_emit_by_name (sink, "pull-buffer", &buffer); } - g_signal_emit_by_name (sink, "pull-buffer", &buffer); if (buffer) { gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); @@ -1366,7 +1405,7 @@ void eServiceMP3::pullSubtitle() unsigned char line[len+1]; memcpy(line, GST_BUFFER_DATA(buffer), len); line[len] = 0; - eDebug("got new subtitle @ buf_pos = %lld ns (in pts=%lld): '%s' ", buf_pos, buf_pos/11111, line); + eDebug("got new subtitle @ buf_pos = %lld ns (in pts=%lld): '%s' ", buf_pos, buf_pos/11111, line); ePangoSubtitlePage page; gRGB rgbcol(0xD0,0xD0,0xD0); page.m_elements.push_back(ePangoSubtitlePageElement(rgbcol, (const char*)line)); @@ -1453,9 +1492,9 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) if (m_currentSubtitleStream != pid) { + eSingleLocker l(m_subs_to_pull_lock); g_object_set (G_OBJECT (m_gst_playbin), "current-text", pid, NULL); m_currentSubtitleStream = pid; - eSingleLocker l(m_subs_to_pull_lock); m_subs_to_pull = 0; m_subtitle_pages.clear(); } @@ -1468,7 +1507,6 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) eDebug ("eServiceMP3::switched to subtitle stream %i", text_pid); - return 0; error_out: