From 42547e1c5ebe3c21c39e567c370810ea5308fe70 Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Wed, 26 May 2010 16:44:50 +0200 Subject: fix empty streams list crash, correctly show/hide color key buttons, re-implement plugin-hook for blue key, fix possible exit crash Conflicts: lib/python/Screens/AudioSelection.py --- lib/service/servicemp3.cpp | 263 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 203 insertions(+), 60 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index 4ecbd76b..9625f555 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -322,15 +323,44 @@ eServiceMP3::eServiceMP3(eServiceReference ref) g_free(uri); - GstElement *subsink = gst_element_factory_make("appsink", "subtitle_sink"); - if (!subsink) + m_gst_subtitlebin = gst_bin_new("subtitle_bin"); + + GstElement *appsink = gst_element_factory_make("appsink", "subtitle_sink"); + + if (!appsink) eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-appsink"); - else - { - m_subs_to_pull_handler_id = g_signal_connect (subsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); - g_object_set (G_OBJECT (subsink), "caps", gst_caps_from_string("text/plain; text/x-plain; text/x-pango-markup"), NULL); - g_object_set (G_OBJECT (m_gst_playbin), "text-sink", subsink, NULL); - } +// <<<<<<< HEAD +// else +// { +// m_subs_to_pull_handler_id = g_signal_connect (subsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); +// g_object_set (G_OBJECT (subsink), "caps", gst_caps_from_string("text/plain; text/x-plain; text/x-pango-markup"), NULL); +// g_object_set (G_OBJECT (m_gst_playbin), "text-sink", subsink, NULL); +// } +// ======= + + GstElement *dvdsubdec = gst_element_factory_make("dvdsubdec", "vobsubtitle_decoder"); + if ( !dvdsubdec ) + eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-dvdsub"); + + gst_bin_add_many(GST_BIN(m_gst_subtitlebin), dvdsubdec, appsink, NULL); +// GstPad *ghostpad = gst_ghost_pad_new("sink", gst_element_get_static_pad (appsink, "sink")); + GstPad *ghostpad = gst_ghost_pad_new("sink", gst_element_get_static_pad (dvdsubdec, "sink")); + gst_element_add_pad (m_gst_subtitlebin, ghostpad); + eDebug("eServiceMP3::construct dvdsubdec=%p, appsink=%p, ghostpad=%p,", dvdsubdec, appsink, ghostpad); + + g_signal_connect (ghostpad, "notify::caps", G_CALLBACK (gstCBsubtitleCAPS), this); + + GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-dvd-subpicture; video/x-raw-rgb"); + g_object_set (G_OBJECT (appsink), "caps", caps, NULL); + g_object_set (G_OBJECT (dvdsubdec), "singlebuffer", TRUE, NULL); + gst_caps_unref(caps); + + int ret = gst_element_link(dvdsubdec, appsink); + eDebug("eServiceMP3::linking elements dvdsubdec and subsink appsink %i", ret); + + g_object_set (G_OBJECT (m_gst_playbin), "text-sink", m_gst_subtitlebin, NULL); + m_subs_to_pull_handler_id = g_signal_connect (appsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); +// >>>>>>> fix empty streams list crash, correctly show/hide color key buttons, re-implement plugin-hook for blue key, fix possible exit crash if ( m_gst_playbin ) { @@ -366,12 +396,12 @@ eServiceMP3::eServiceMP3(eServiceReference ref) eServiceMP3::~eServiceMP3() { // disconnect subtitle callback - GstElement *sink; - g_object_get (G_OBJECT (m_gst_playbin), "text-sink", &sink, NULL); - if (sink) + GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); + + if (appsink) { - g_signal_handler_disconnect (sink, m_subs_to_pull_handler_id); - gst_object_unref(sink); + g_signal_handler_disconnect (appsink, m_subs_to_pull_handler_id); + gst_object_unref(appsink); } delete m_subtitle_widget; @@ -1091,6 +1121,28 @@ RESULT eServiceMP3::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i) return 0; } +subtype_t getSubtitleType(GstPad* pad) +{ + subtype_t type = stUnknown; + GstCaps* caps = gst_pad_get_negotiated_caps(pad); + + if (!caps) + return type; + + GstStructure* str = gst_caps_get_structure(caps, 0); + const gchar *g_type = gst_structure_get_name(str); + eDebug("getSubtitleType::subtitle probe type=%s", g_type); + + if ( !strcmp(g_type, "video/x-dvd-subpicture") ) + type = stVOB; + else if ( !strcmp(g_type, "text/x-pango-markup") ) + type = stSSA; + else if ( !strcmp(g_type, "text/plain") ) + type = stPlainText; + + return type; +} + void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) { if (!msg) @@ -1137,15 +1189,15 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) } break; case GST_STATE_CHANGE_READY_TO_PAUSED: { - GstElement *sink; - g_object_get (G_OBJECT (m_gst_playbin), "text-sink", &sink, NULL); - if (sink) + GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); + if (appsink) { - g_object_set (G_OBJECT (sink), "max-buffers", 2, NULL); - g_object_set (G_OBJECT (sink), "sync", FALSE, NULL); - g_object_set (G_OBJECT (sink), "async", FALSE, NULL); - g_object_set (G_OBJECT (sink), "emit-signals", TRUE, NULL); - gst_object_unref(sink); + g_object_set (G_OBJECT (appsink), "max-buffers", 2, NULL); + g_object_set (G_OBJECT (appsink), "sync", FALSE, NULL); + g_object_set (G_OBJECT (appsink), "async", FALSE, NULL); + g_object_set (G_OBJECT (appsink), "emit-signals", TRUE, NULL); + eDebug("eServiceMP3::appsink properties set!"); + gst_object_unref(appsink); } setAC3Delay(ac3_delay); setPCMDelay(pcm_delay); @@ -1261,7 +1313,6 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) continue; GstStructure* str = gst_caps_get_structure(caps, 0); 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); g_lang = g_strdup_printf ("und"); @@ -1282,25 +1333,23 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) } for (i = 0; i < n_text; i++) - { + { gchar *g_lang; -// gchar *g_type; -// GstPad* pad = 0; -// g_signal_emit_by_name (m_gst_playbin, "get-text-pad", i, &pad); -// GstCaps* caps = gst_pad_get_negotiated_caps(pad); -// GstStructure* str = gst_caps_get_structure(caps, 0); -// g_type = gst_structure_get_name(str); -// g_signal_emit_by_name (m_gst_playbin, "get-text-tags", i, &tags); + g_signal_emit_by_name (m_gst_playbin, "get-text-tags", i, &tags); subtitleStream subs; - subs.type = stPlainText; + g_lang = g_strdup_printf ("und"); if ( tags && gst_is_tag_list(tags) ) gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); subs.language_code = std::string(g_lang); - eDebug("eServiceMP3::subtitle stream=%i language=%s"/* type=%s*/, i, g_lang/*, g_type*/); + eDebug("eServiceMP3::subtitle stream=%i language=%s unknown type", i, g_lang); + + GstPad* pad = 0; + g_signal_emit_by_name (m_gst_playbin, "get-text-pad", i, &pad); + subs.type = getSubtitleType(pad); + m_subtitleStreams.push_back(subs); g_free (g_lang); -// g_free (g_type); } m_event((iPlayableService*)this, evUpdatedEventInfo); } @@ -1433,17 +1482,70 @@ eAutoInitPtr init_eServiceFactoryMP3(eAutoInitNumbers::servi void eServiceMP3::gstCBsubtitleAvail(GstElement *appsink, gpointer user_data) { - eServiceMP3 *_this = (eServiceMP3*)user_data; + eServiceMP3 *_this = (eServiceMP3*)user_data; eSingleLocker l(_this->m_subs_to_pull_lock); ++_this->m_subs_to_pull; _this->m_pump.send(2); } +void eServiceMP3::gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer user_data) +{ + eDebug("gstCBsubtitleCAPS:: signal::caps callback obj=%p", obj); + + eServiceMP3 *_this = (eServiceMP3*)user_data; + eDebug("gstCBsubtitleCAPS:: m_currentSubtitleStream=%i, m_subtitleStreams.size()=%i", _this->m_currentSubtitleStream, _this->m_subtitleStreams.size()); + + if ( _this->m_currentSubtitleStream >= _this->m_subtitleStreams.size() ) + { + eDebug("return"); + return; + } + + subtitleStream subs = _this->m_subtitleStreams[_this->m_currentSubtitleStream]; + + if ( subs.type == stUnknown ) + { + GstTagList *tags; + eDebug("gstCBsubtitleCAPS::m_subtitleStreams[%i].type == stUnknown...", _this->m_currentSubtitleStream); + + gchar *g_lang; + g_signal_emit_by_name (_this->m_gst_playbin, "get-text-tags", _this->m_currentSubtitleStream, &tags); + + g_lang = g_strdup_printf ("und"); + if ( tags && gst_is_tag_list(tags) ) + gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); + subs.language_code = std::string(g_lang); + + subs.type = getSubtitleType(GST_PAD(obj)); + + _this->m_subtitleStreams[_this->m_currentSubtitleStream] = subs; + + g_free (g_lang); + } + + if ( subs.type == stVOB ) + { + GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); + GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); + GstPad *subdecsinkpad = gst_element_get_static_pad (dvdsubdec, "sink"); + eDebug("gstCBsubtitleCAPS:: dvdsubdec=%p, subdecsinkpad=%p, ghostpad=%p,", dvdsubdec, subdecsinkpad, ghostpad); + gst_ghost_pad_set_target((GstGhostPad*)ghostpad, subdecsinkpad); + } + else + { + GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); + GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); + GstPad *appsinkpad = gst_element_get_static_pad (appsink, "sink"); + eDebug("gstCBsubtitleCAPS:: appsink=%p, appsinkpad=%p, ghostpad=%p,", appsink, appsinkpad, ghostpad); + gst_ghost_pad_set_target((GstGhostPad*)ghostpad, appsinkpad); + } +} + void eServiceMP3::pullSubtitle() { - GstElement *sink; - g_object_get (G_OBJECT (m_gst_playbin), "text-sink", &sink, NULL); - if (sink) + GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); + + if (appsink) { while (m_subs_to_pull && m_subtitle_pages.size() < 2) { @@ -1451,28 +1553,52 @@ 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 (appsink, "pull-buffer", &buffer); } if (buffer) { gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); gint64 duration_ns = GST_BUFFER_DURATION(buffer); size_t len = GST_BUFFER_SIZE(buffer); - 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); - ePangoSubtitlePage page; - gRGB rgbcol(0xD0,0xD0,0xD0); - page.m_elements.push_back(ePangoSubtitlePageElement(rgbcol, (const char*)line)); - page.show_pts = buf_pos / 11111L; - page.m_timeout = duration_ns / 1000000; - m_subtitle_pages.push_back(page); - pushSubtitles(); + + if ( m_subtitleStreams[m_currentSubtitleStream].type < stVOB ) + { + unsigned char line[len+1]; + memcpy(line, GST_BUFFER_DATA(buffer), len); + line[len] = 0; + eDebug("got new text subtitle @ buf_pos = %lld ns (in pts=%lld): '%s' ", buf_pos, buf_pos/11111, line); + ePangoSubtitlePage* page = new ePangoSubtitlePage; + gRGB rgbcol(0xD0,0xD0,0xD0); + page->m_elements.push_back(ePangoSubtitlePageElement(rgbcol, (const char*)line)); + page->show_pts = buf_pos / 11111L; + page->m_timeout = duration_ns / 1000000; + SubtitlePage subtitlepage; + subtitlepage.pango_page = page; + subtitlepage.vob_page = NULL; + m_subtitle_pages.push_back(subtitlepage); + pushSubtitles(); + } + else + { + eDebug("got new subpicture @ buf_pos = %lld ns (in pts=%lld), len=%i bytes. ", buf_pos, buf_pos/11111, len); + eVobSubtitlePage* page = new eVobSubtitlePage; + eSize size = eSize(720, 576); + page->m_pixmap = new gPixmap(size, 32, 0); +// ePtr pixmap; +// pixmap = new gPixmap(size, 32, 1); /* allocate accel surface (if possible) */ + memcpy(page->m_pixmap->surface->data, GST_BUFFER_DATA(buffer), len); + page->show_pts = buf_pos / 11111L; + page->m_timeout = duration_ns / 1000000; + SubtitlePage subtitlepage; + subtitlepage.vob_page = page; + subtitlepage.pango_page = NULL; + m_subtitle_pages.push_back(subtitlepage); + pushSubtitles(); + } gst_buffer_unref(buffer); } } - gst_object_unref(sink); + gst_object_unref(appsink); } else eDebug("no subtitle sink!"); @@ -1480,19 +1606,31 @@ void eServiceMP3::pullSubtitle() void eServiceMP3::pushSubtitles() { - ePangoSubtitlePage page; pts_t running_pts; while ( !m_subtitle_pages.empty() ) { + SubtitlePage frontpage = m_subtitle_pages.front(); + gint64 diff_ms; + getPlayPosition(running_pts); - page = m_subtitle_pages.front(); - gint64 diff_ms = ( page.show_pts - running_pts ) / 90; - eDebug("eServiceMP3::pushSubtitles show_pts = %lld running_pts = %lld diff = %lld", page.show_pts, running_pts, diff_ms); - if (diff_ms < -100) + + if ( frontpage.pango_page != 0 ) + { + diff_ms = ( frontpage.pango_page->show_pts - running_pts ) / 90; + eDebug("eServiceMP3::pushSubtitles TEXT show_pts = %lld running_pts = %lld diff = %lld", frontpage.pango_page->show_pts, running_pts, diff_ms); + } + + if ( frontpage.vob_page != 0 ) + { + diff_ms = ( frontpage.vob_page->show_pts - running_pts ) / 90; + eDebug("eServiceMP3::pushSubtitles VOB show_pts = %lld running_pts = %lld diff = %lld", frontpage.vob_page->show_pts, running_pts, diff_ms); + } + + if ( diff_ms < -100 ) { GstFormat fmt = GST_FORMAT_TIME; gint64 now; - if (gst_element_query_position(m_gst_playbin, &fmt, &now) != -1) + if ( gst_element_query_position(m_gst_playbin, &fmt, &now) != -1 ) { now /= 11111; diff_ms = abs((now - running_pts) / 90); @@ -1511,14 +1649,18 @@ void eServiceMP3::pushSubtitles() } else if ( diff_ms > 20 ) { -// eDebug("start recheck timer"); + eDebug("start recheck timer"); m_subtitle_sync_timer->start(diff_ms > 1000 ? 1000 : diff_ms, true); break; } else // immediate show { - if (m_subtitle_widget) - m_subtitle_widget->setPage(page); + if ( m_subtitle_widget && frontpage.pango_page != 0) + m_subtitle_widget->setPage(*(frontpage.pango_page)); + else if ( m_subtitle_widget && frontpage.vob_page != 0) + { + m_subtitle_widget->setPixmap(frontpage.vob_page->m_pixmap, eRect(0, 0, 720, 576)); + } m_subtitle_pages.pop_front(); } } @@ -1592,7 +1734,8 @@ PyObject *eServiceMP3::getSubtitleList() ePyObject l = PyList_New(0); int stream_count[sizeof(subtype_t)]; - for ( unsigned int i = 0; i < sizeof(subtype_t); i++ ) + + for ( unsigned int i = 0; i <= sizeof(subtype_t); i++ ) stream_count[i] = 0; for (std::vector::iterator IterSubtitleStream(m_subtitleStreams.begin()); IterSubtitleStream != m_subtitleStreams.end(); ++IterSubtitleStream) -- cgit v1.2.3 From 6e09f26f57500f8acfe5bcf28faa930849d457a2 Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Thu, 27 May 2010 18:48:09 +0200 Subject: more experimenting on vobsubs --- data/skin_default.xml | 25 +++++++++++ lib/python/Screens/AudioSelection.py | 9 ++-- lib/service/servicemp3.cpp | 85 +++++++++++++++++++----------------- 3 files changed, 74 insertions(+), 45 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/data/skin_default.xml b/data/skin_default.xml index edf61357..9f70e0d0 100755 --- a/data/skin_default.xml +++ b/data/skin_default.xml @@ -62,8 +62,13 @@ +<<<<<<< HEAD +======= + + +>>>>>>> more experimenting on vobsubs @@ -78,6 +83,7 @@ +<<<<<<< HEAD @@ -96,10 +102,16 @@ +======= + + + +>>>>>>> more experimenting on vobsubs {"templates": {"default": (25, [ MultiContentEntryText(pos = (0, 0), size = (35, 25), font = 0, flags = RT_HALIGN_LEFT, text = 1), # key, +<<<<<<< HEAD {"templates": {"default": (25, [ @@ -125,6 +137,19 @@ } +======= + MultiContentEntryText(pos = (40, 0), size = (55, 25), font = 0, flags = RT_HALIGN_LEFT, text = 2), # number, + MultiContentEntryText(pos = (100, 0), size = (120, 25), font = 0, flags = RT_HALIGN_LEFT, text = 3), # description, + MultiContentEntryText(pos = (230, 0), size = (200, 25), font = 0, flags = RT_HALIGN_LEFT, text = 4), # language, + MultiContentEntryText(pos = (440, 4), size = (60, 25), font = 1, flags = RT_HALIGN_RIGHT, text = 5), # selection, + ], True, "showNever"), + "notselected": (25, [ + MultiContentEntryText(pos = (0, 0), size = (35, 25), font = 0, flags = RT_HALIGN_LEFT, text = 1), # key, + MultiContentEntryText(pos = (40, 0), size = (55, 25), font = 0, flags = RT_HALIGN_LEFT, text = 2), # number, + MultiContentEntryText(pos = (100, 0), size = (120, 25), font = 0, flags = RT_HALIGN_LEFT, text = 3), # description, + MultiContentEntryText(pos = (230, 0), size = (200, 25), font = 0, flags = RT_HALIGN_LEFT, text = 4), # language, + MultiContentEntryText(pos = (440, 4), size = (60, 25), font = 1, flags = RT_HALIGN_RIGHT, text = 5), # selection, +>>>>>>> more experimenting on vobsubs ], False, "showNever") }, "fonts": [gFont("Regular", 20), gFont("Regular", 16)], diff --git a/lib/python/Screens/AudioSelection.py b/lib/python/Screens/AudioSelection.py index bacc00c1..b4ee929d 100644 --- a/lib/python/Screens/AudioSelection.py +++ b/lib/python/Screens/AudioSelection.py @@ -46,7 +46,7 @@ class AudioSelection(Screen, ConfigListScreen): "cancel": self.cancel, "up": self.keyUp, "down": self.keyDown, - }, -3) + }, -2) self.settings = ConfigSubsection() choicelist = [(PAGE_AUDIO,_("audio tracks")), (PAGE_SUBTITLES,_("Subtitles"))] @@ -110,6 +110,8 @@ class AudioSelection(Screen, ConfigListScreen): streams.append((x, "", number, description, language, selected)) else: + conflist.append(getConfigListEntry("", self.settings.dummy)) + self["key_green"].setBoolean(False) streams = [] conflist.append(('',)) self["key_green"].setBoolean(False) @@ -156,7 +158,7 @@ class AudioSelection(Screen, ConfigListScreen): number = "%x%02x" % (x[3],x[2]) elif x[0] == 2: - types = ("UTF-8 text","SSA / AAS",".SRT file") + types = (_(""), "UTF-8 text", "SSA / AAS", ".SRT", "VOB") description = types[x[2]] streams.append((x, "", number, description, language, selected)) @@ -310,5 +312,4 @@ class AudioSelection(Screen, ConfigListScreen): class SubtitleSelection(AudioSelection): def __init__(self, session, infobar=None): - AudioSelection.__init__(self, session, infobar, page=PAGE_SUBTITLES) - self.skinName = ["AudioSelection"] + AudioSelection.__init__(self, session, infobar, PAGE_SUBTITLES) diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index 9625f555..c5bd04d4 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -1152,7 +1152,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) source = GST_MESSAGE_SRC(msg); sourceName = gst_object_get_name(source); -#if 0 +#if 1 if (gst_message_get_structure(msg)) { gchar *string = gst_structure_to_string(gst_message_get_structure(msg)); @@ -1560,40 +1560,44 @@ void eServiceMP3::pullSubtitle() gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); gint64 duration_ns = GST_BUFFER_DURATION(buffer); size_t len = GST_BUFFER_SIZE(buffer); - - if ( m_subtitleStreams[m_currentSubtitleStream].type < stVOB ) - { - unsigned char line[len+1]; - memcpy(line, GST_BUFFER_DATA(buffer), len); - line[len] = 0; - eDebug("got new text subtitle @ buf_pos = %lld ns (in pts=%lld): '%s' ", buf_pos, buf_pos/11111, line); - ePangoSubtitlePage* page = new ePangoSubtitlePage; - gRGB rgbcol(0xD0,0xD0,0xD0); - page->m_elements.push_back(ePangoSubtitlePageElement(rgbcol, (const char*)line)); - page->show_pts = buf_pos / 11111L; - page->m_timeout = duration_ns / 1000000; - SubtitlePage subtitlepage; - subtitlepage.pango_page = page; - subtitlepage.vob_page = NULL; - m_subtitle_pages.push_back(subtitlepage); - pushSubtitles(); - } - else + eDebug("pullSubtitle m_subtitleStreams[m_currentSubtitleStream].type=%i",m_subtitleStreams[m_currentSubtitleStream].type); + + if ( m_subtitleStreams[m_currentSubtitleStream].type ) { - eDebug("got new subpicture @ buf_pos = %lld ns (in pts=%lld), len=%i bytes. ", buf_pos, buf_pos/11111, len); - eVobSubtitlePage* page = new eVobSubtitlePage; - eSize size = eSize(720, 576); - page->m_pixmap = new gPixmap(size, 32, 0); -// ePtr pixmap; -// pixmap = new gPixmap(size, 32, 1); /* allocate accel surface (if possible) */ - memcpy(page->m_pixmap->surface->data, GST_BUFFER_DATA(buffer), len); - page->show_pts = buf_pos / 11111L; - page->m_timeout = duration_ns / 1000000; - SubtitlePage subtitlepage; - subtitlepage.vob_page = page; - subtitlepage.pango_page = NULL; - m_subtitle_pages.push_back(subtitlepage); - pushSubtitles(); + if ( m_subtitleStreams[m_currentSubtitleStream].type < stVOB ) + { + unsigned char line[len+1]; + memcpy(line, GST_BUFFER_DATA(buffer), len); + line[len] = 0; + eDebug("got new text subtitle @ buf_pos = %lld ns (in pts=%lld): '%s' ", buf_pos, buf_pos/11111, line); + ePangoSubtitlePage* page = new ePangoSubtitlePage; + gRGB rgbcol(0xD0,0xD0,0xD0); + page->m_elements.push_back(ePangoSubtitlePageElement(rgbcol, (const char*)line)); + page->show_pts = buf_pos / 11111L; + page->m_timeout = duration_ns / 1000000; + SubtitlePage subtitlepage; + subtitlepage.pango_page = page; + subtitlepage.vob_page = NULL; + m_subtitle_pages.push_back(subtitlepage); + pushSubtitles(); + } + else + { + eDebug("got new subpicture @ buf_pos = %lld ns (in pts=%lld), duration=%lld ns, len=%i bytes. ", buf_pos, buf_pos/11111, duration_ns, len); + eVobSubtitlePage* page = new eVobSubtitlePage; + eSize size = eSize(720, 576); + page->m_pixmap = new gPixmap(size, 32, 0); + // ePtr pixmap; + // pixmap = new gPixmap(size, 32, 1); /* allocate accel surface (if possible) */ + memcpy(page->m_pixmap->surface->data, GST_BUFFER_DATA(buffer), len); + page->show_pts = buf_pos / 11111L; + page->m_timeout = duration_ns / 1000000; + SubtitlePage subtitlepage; + subtitlepage.vob_page = page; + subtitlepage.pango_page = NULL; + m_subtitle_pages.push_back(subtitlepage); + pushSubtitles(); + } } gst_buffer_unref(buffer); } @@ -1704,6 +1708,7 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) g_object_get (G_OBJECT (m_gst_playbin), "current-text", &text_pid, NULL); eDebug ("eServiceMP3::switched to subtitle stream %i", text_pid); + m_event((iPlayableService*)this, evUpdatedInfo); return 0; @@ -1731,26 +1736,24 @@ PyObject *eServiceMP3::getCachedSubtitle() PyObject *eServiceMP3::getSubtitleList() { eDebug("eServiceMP3::getSubtitleList"); - ePyObject l = PyList_New(0); - int stream_count[sizeof(subtype_t)]; + int stream_idx = 0; - for ( unsigned int i = 0; i <= sizeof(subtype_t); i++ ) - stream_count[i] = 0; - for (std::vector::iterator IterSubtitleStream(m_subtitleStreams.begin()); IterSubtitleStream != m_subtitleStreams.end(); ++IterSubtitleStream) { subtype_t type = IterSubtitleStream->type; ePyObject tuple = PyTuple_New(5); + eDebug("eServiceMP3::getSubtitleList idx=%i type=%i, code=%s", stream_idx, int(type), (IterSubtitleStream->language_code).c_str()); PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(2)); - PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(stream_count[type])); + PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(stream_idx)); PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(int(type))); PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(0)); PyTuple_SET_ITEM(tuple, 4, PyString_FromString((IterSubtitleStream->language_code).c_str())); PyList_Append(l, tuple); Py_DECREF(tuple); - stream_count[type]++; + stream_idx++; } + eDebug("eServiceMP3::getSubtitleList finished"); return l; } -- cgit v1.2.3 From add1ffa5cf984cf677ef27010acac78e9fac3d4a Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Tue, 8 Jun 2010 12:47:29 +0200 Subject: experiments --- lib/service/servicemp3.cpp | 164 ++++++++++++++++++++++++++++++--------------- lib/service/servicemp3.h | 5 +- 2 files changed, 115 insertions(+), 54 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index c5bd04d4..58d89281 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -219,6 +219,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref) { m_seekTimeout = eTimer::create(eApp); m_subtitle_sync_timer = eTimer::create(eApp); + m_subtitle_hide_timer = eTimer::create(eApp); m_stream_tags = 0; m_currentAudioStream = -1; m_currentSubtitleStream = 0; @@ -228,6 +229,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref) m_buffer_size = 1*1024*1024; CONNECT(m_seekTimeout->timeout, eServiceMP3::seekTimeoutCB); CONNECT(m_subtitle_sync_timer->timeout, eServiceMP3::pushSubtitles); + CONNECT(m_subtitle_hide_timer->timeout, eServiceMP3::hideSubtitles); CONNECT(m_pump.recv_msg, eServiceMP3::gstPoll); m_aspect = m_width = m_height = m_framerate = m_progressive = -1; @@ -338,27 +340,32 @@ eServiceMP3::eServiceMP3(eServiceReference ref) // } // ======= - GstElement *dvdsubdec = gst_element_factory_make("dvdsubdec", "vobsubtitle_decoder"); - if ( !dvdsubdec ) - eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-dvdsub"); - - gst_bin_add_many(GST_BIN(m_gst_subtitlebin), dvdsubdec, appsink, NULL); +// GstElement *dvdsubdec = gst_element_factory_make("dvdsubdec", "vobsubtitle_decoder"); +// if ( !dvdsubdec ) +// eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-dvdsub"); +// +// gst_bin_add_many(GST_BIN(m_gst_subtitlebin), dvdsubdec, appsink, NULL); // GstPad *ghostpad = gst_ghost_pad_new("sink", gst_element_get_static_pad (appsink, "sink")); - GstPad *ghostpad = gst_ghost_pad_new("sink", gst_element_get_static_pad (dvdsubdec, "sink")); - gst_element_add_pad (m_gst_subtitlebin, ghostpad); - eDebug("eServiceMP3::construct dvdsubdec=%p, appsink=%p, ghostpad=%p,", dvdsubdec, appsink, ghostpad); - - g_signal_connect (ghostpad, "notify::caps", G_CALLBACK (gstCBsubtitleCAPS), this); +// // GstPad *ghostpad = gst_ghost_pad_new("sink", gst_element_get_static_pad (dvdsubdec, "sink")); +// gst_element_add_pad (m_gst_subtitlebin, ghostpad); +// eDebug("eServiceMP3::construct dvdsubdec=%p, appsink=%p, ghostpad=%p,", dvdsubdec, appsink, ghostpad); +// +// g_signal_connect (ghostpad, "notify::caps", G_CALLBACK (gstCBsubtitleCAPS), this); +// +// GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-raw-rgb"); +// g_object_set (G_OBJECT (appsink), "caps", caps, NULL); +// g_object_set (G_OBJECT (dvdsubdec), "singlebuffer", TRUE, NULL); +// gst_caps_unref(caps); +// +// int ret = gst_element_link(dvdsubdec, appsink); +// eDebug("eServiceMP3::linking elements dvdsubdec and subsink appsink %i", ret); + +// g_object_set (G_OBJECT (m_gst_playbin), "text-sink", m_gst_subtitlebin, NULL); - GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-dvd-subpicture; video/x-raw-rgb"); + GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup"); g_object_set (G_OBJECT (appsink), "caps", caps, NULL); - g_object_set (G_OBJECT (dvdsubdec), "singlebuffer", TRUE, NULL); - gst_caps_unref(caps); - - int ret = gst_element_link(dvdsubdec, appsink); - eDebug("eServiceMP3::linking elements dvdsubdec and subsink appsink %i", ret); - - g_object_set (G_OBJECT (m_gst_playbin), "text-sink", m_gst_subtitlebin, NULL); + + g_object_set (G_OBJECT (m_gst_playbin), "text-sink", appsink, NULL); m_subs_to_pull_handler_id = g_signal_connect (appsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); // >>>>>>> fix empty streams list crash, correctly show/hide color key buttons, re-implement plugin-hook for blue key, fix possible exit crash @@ -1121,25 +1128,37 @@ RESULT eServiceMP3::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i) return 0; } -subtype_t getSubtitleType(GstPad* pad) +subtype_t getSubtitleType(GstPad* pad, gchar *g_codec=NULL) { subtype_t type = stUnknown; GstCaps* caps = gst_pad_get_negotiated_caps(pad); - - if (!caps) - return type; - - GstStructure* str = gst_caps_get_structure(caps, 0); - const gchar *g_type = gst_structure_get_name(str); - eDebug("getSubtitleType::subtitle probe type=%s", g_type); - - if ( !strcmp(g_type, "video/x-dvd-subpicture") ) - type = stVOB; - else if ( !strcmp(g_type, "text/x-pango-markup") ) - type = stSSA; - else if ( !strcmp(g_type, "text/plain") ) - type = stPlainText; - + + if ( caps ) + { + GstStructure* str = gst_caps_get_structure(caps, 0); + const gchar *g_type = gst_structure_get_name(str); + eDebug("getSubtitleType::subtitle probe caps type=%s", g_type); + + if ( !strcmp(g_type, "video/x-dvd-subpicture") ) + type = stVOB; + else if ( !strcmp(g_type, "text/x-pango-markup") ) + type = stSSA; + else if ( !strcmp(g_type, "text/plain") ) + type = stPlainText; + } + else if ( g_codec ) + { + eDebug("getSubtitleType::subtitle probe codec tag=%s", g_codec); + if ( !strcmp(g_codec, "VOB") ) + type = stVOB; + else if ( !strcmp(g_codec, "SubStation Alpha") ) + type = stSSA; + else if ( !strcmp(g_codec, "ASS") ) + type = stASS; + else if ( !strcmp(g_codec, "UTF-8 plain text") ) + type = stPlainText; + } + return type; } @@ -1189,7 +1208,8 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) } break; case GST_STATE_CHANGE_READY_TO_PAUSED: { - GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); + GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); if (appsink) { g_object_set (G_OBJECT (appsink), "max-buffers", 2, NULL); @@ -1334,19 +1354,25 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) for (i = 0; i < n_text; i++) { - gchar *g_lang; + gchar *g_codec = NULL, *g_lang = NULL; g_signal_emit_by_name (m_gst_playbin, "get-text-tags", i, &tags); subtitleStream subs; g_lang = g_strdup_printf ("und"); if ( tags && gst_is_tag_list(tags) ) + { gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); + gst_tag_list_get_string(tags, GST_TAG_SUBTITLE_CODEC, &g_codec); + gst_tag_list_free(tags); + } + subs.language_code = std::string(g_lang); - eDebug("eServiceMP3::subtitle stream=%i language=%s unknown type", i, g_lang); + eDebug("eServiceMP3::subtitle stream=%i language=%s", i, g_lang); GstPad* pad = 0; g_signal_emit_by_name (m_gst_playbin, "get-text-pad", i, &pad); - subs.type = getSubtitleType(pad); + if ( subs.type != stSRT ) + subs.type = getSubtitleType(pad, g_codec); m_subtitleStreams.push_back(subs); g_free (g_lang); @@ -1522,28 +1548,34 @@ void eServiceMP3::gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer us g_free (g_lang); } +} - if ( subs.type == stVOB ) +void eServiceMP3::gstCBsubtitleLink(subtype_t type, gpointer user_data) +{ + eServiceMP3 *_this = (eServiceMP3*)user_data; + + if ( type == stVOB ) { GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); GstPad *subdecsinkpad = gst_element_get_static_pad (dvdsubdec, "sink"); - eDebug("gstCBsubtitleCAPS:: dvdsubdec=%p, subdecsinkpad=%p, ghostpad=%p,", dvdsubdec, subdecsinkpad, ghostpad); - gst_ghost_pad_set_target((GstGhostPad*)ghostpad, subdecsinkpad); + int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, subdecsinkpad); + eDebug("gstCBsubtitleLink:: dvdsubdec=%p, subdecsinkpad=%p, ghostpad=%p, link=%i", dvdsubdec, subdecsinkpad, ghostpad, ret); } else { GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); GstPad *appsinkpad = gst_element_get_static_pad (appsink, "sink"); - eDebug("gstCBsubtitleCAPS:: appsink=%p, appsinkpad=%p, ghostpad=%p,", appsink, appsinkpad, ghostpad); - gst_ghost_pad_set_target((GstGhostPad*)ghostpad, appsinkpad); + int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, appsinkpad); + eDebug("gstCBsubtitleLink:: appsink=%p, appsinkpad=%p, ghostpad=%p, link=%i", appsink, appsinkpad, ghostpad, ret); } } void eServiceMP3::pullSubtitle() { - GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); + GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); if (appsink) { @@ -1591,7 +1623,7 @@ void eServiceMP3::pullSubtitle() // pixmap = new gPixmap(size, 32, 1); /* allocate accel surface (if possible) */ memcpy(page->m_pixmap->surface->data, GST_BUFFER_DATA(buffer), len); page->show_pts = buf_pos / 11111L; - page->m_timeout = duration_ns / 1000000; + page->m_timeout = duration_ns / 1000; SubtitlePage subtitlepage; subtitlepage.vob_page = page; subtitlepage.pango_page = NULL; @@ -1659,11 +1691,20 @@ void eServiceMP3::pushSubtitles() } else // immediate show { - if ( m_subtitle_widget && frontpage.pango_page != 0) - m_subtitle_widget->setPage(*(frontpage.pango_page)); - else if ( m_subtitle_widget && frontpage.vob_page != 0) + if ( m_subtitle_widget ) { - m_subtitle_widget->setPixmap(frontpage.vob_page->m_pixmap, eRect(0, 0, 720, 576)); + if ( frontpage.pango_page != 0) + { + eDebug("immediate show pango subtitle line"); + m_subtitle_widget->setPage(*(frontpage.pango_page)); + } + else if ( frontpage.vob_page != 0) + { + m_subtitle_widget->setPixmap(frontpage.vob_page->m_pixmap, eRect(0, 0, 720, 576)); + eDebug("blit vobsub pixmap... hide in %i ms", frontpage.vob_page->m_timeout); + m_subtitle_hide_timer->start(frontpage.vob_page->m_timeout, true); + } + m_subtitle_widget->show(); } m_subtitle_pages.pop_front(); } @@ -1672,12 +1713,21 @@ void eServiceMP3::pushSubtitles() pullSubtitle(); } +void eServiceMP3::hideSubtitles() +{ + eDebug("eServiceMP3::hideSubtitles()"); + if ( m_subtitle_widget ) + m_subtitle_widget->hide(); +} + RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) { + eDebug ("eServiceMP3::enableSubtitles m_currentSubtitleStream=%i",m_currentSubtitleStream); ePyObject entry; int tuplesize = PyTuple_Size(tuple); int pid, type; gint text_pid = 0; + eSingleLocker l(m_subs_to_pull_lock); if (!PyTuple_Check(tuple)) goto error_out; @@ -1692,14 +1742,19 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) goto error_out; type = PyInt_AsLong(entry); - if (m_currentSubtitleStream != pid) - { - eSingleLocker l(m_subs_to_pull_lock); + eDebug ("eServiceMP3::enableSubtitles new pid=%i",pid); +// if (m_currentSubtitleStream != pid) +// { + g_object_set (G_OBJECT (m_gst_playbin), "current-text", pid, NULL); +eDebug ("eServiceMP3::enableSubtitles g_object_set"); m_currentSubtitleStream = pid; m_subs_to_pull = 0; m_subtitle_pages.clear(); - } +eDebug ("eServiceMP3::enableSubtitles cleared"); +// } + +// gstCBsubtitleLink(m_subtitleStreams[m_currentSubtitleStream].type, this); m_subtitle_widget = 0; m_subtitle_widget = new eSubtitleWidget(parent); @@ -1722,8 +1777,11 @@ RESULT eServiceMP3::disableSubtitles(eWidget *parent) { eDebug("eServiceMP3::disableSubtitles"); m_subtitle_pages.clear(); + eDebug("eServiceMP3::disableSubtitles cleared"); delete m_subtitle_widget; + eDebug("eServiceMP3::disableSubtitles deleted"); m_subtitle_widget = 0; + eDebug("eServiceMP3::disableSubtitles nulled"); return 0; } diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index d38dbb84..7aa6cdd7 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -47,7 +47,7 @@ public: typedef struct _GstElement GstElement; typedef enum { atUnknown, atMPEG, atMP3, atAC3, atDTS, atAAC, atPCM, atOGG, atFLAC } audiotype_t; -typedef enum { stUnknown, stPlainText, stSSA, stSRT, stVOB } subtype_t; +typedef enum { stUnknown, stPlainText, stSSA, stASS, stSRT, stVOB } subtype_t; typedef enum { ctNone, ctMPEGTS, ctMPEGPS, ctMKV, ctAVI, ctMP4, ctVCD, ctCDA } containertype_t; struct SubtitlePage @@ -214,13 +214,16 @@ private: static GstBusSyncReply gstBusSyncHandler(GstBus *bus, GstMessage *message, gpointer user_data); static void gstCBsubtitleAvail(GstElement *element, gpointer user_data); static void gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer user_data); + static void gstCBsubtitleLink(subtype_t type, gpointer user_data); GstPad* gstCreateSubtitleSink(eServiceMP3* _this, subtype_t type); void gstPoll(const int&); std::list m_subtitle_pages; ePtr m_subtitle_sync_timer; + ePtr m_subtitle_hide_timer; void pushSubtitles(); void pullSubtitle(); + void hideSubtitles(); int m_subs_to_pull; eSingleLock m_subs_to_pull_lock; gulong m_subs_to_pull_handler_id; -- cgit v1.2.3 From cc366765588bfabc84a52b0bc3e3511078191b84 Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Wed, 9 Jun 2010 02:29:39 +0200 Subject: experiments --- data/skin_default.xml | 68 ++++++----------------------- lib/python/Screens/AudioSelection.py | 22 +++++++--- lib/service/servicemp3.cpp | 85 +++++++++++++++++++++--------------- lib/service/servicemp3.h | 1 - 4 files changed, 78 insertions(+), 98 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/data/skin_default.xml b/data/skin_default.xml index 9f70e0d0..aceafd73 100755 --- a/data/skin_default.xml +++ b/data/skin_default.xml @@ -62,28 +62,8 @@ -<<<<<<< HEAD -======= - - ->>>>>>> more experimenting on vobsubs - - - - - - - - - - - - - - -<<<<<<< HEAD @@ -100,18 +80,7 @@ - -======= - - - ->>>>>>> more experimenting on vobsubs - - {"templates": - {"default": (25, [ - MultiContentEntryText(pos = (0, 0), size = (35, 25), font = 0, flags = RT_HALIGN_LEFT, text = 1), # key, -<<<<<<< HEAD {"templates": {"default": (25, [ @@ -121,9 +90,6 @@ MultiContentEntryText(pos = (240, 0), size = (200, 25), font = 0, flags = RT_HALIGN_LEFT, text = 4), # language, MultiContentEntryText(pos = (450, 4), size = (90, 25), font = 1, flags = RT_HALIGN_RIGHT, text = 5), # selection, ], True, "showNever"), - "notselected": (25, [ - MultiContentEntryText(pos = (0, 0), size = (35, 25), font = 0, flags = RT_HALIGN_LEFT, text = 1), # key, - ], True, "showNever"), "notselected": (25, [ MultiContentEntryText(pos = (0, 0), size = (35, 25), font = 0, flags = RT_HALIGN_LEFT, text = 1), # key, MultiContentEntryText(pos = (40, 0), size = (60, 25), font = 0, flags = RT_HALIGN_LEFT, text = 2), # number, @@ -137,26 +103,6 @@ } -======= - MultiContentEntryText(pos = (40, 0), size = (55, 25), font = 0, flags = RT_HALIGN_LEFT, text = 2), # number, - MultiContentEntryText(pos = (100, 0), size = (120, 25), font = 0, flags = RT_HALIGN_LEFT, text = 3), # description, - MultiContentEntryText(pos = (230, 0), size = (200, 25), font = 0, flags = RT_HALIGN_LEFT, text = 4), # language, - MultiContentEntryText(pos = (440, 4), size = (60, 25), font = 1, flags = RT_HALIGN_RIGHT, text = 5), # selection, - ], True, "showNever"), - "notselected": (25, [ - MultiContentEntryText(pos = (0, 0), size = (35, 25), font = 0, flags = RT_HALIGN_LEFT, text = 1), # key, - MultiContentEntryText(pos = (40, 0), size = (55, 25), font = 0, flags = RT_HALIGN_LEFT, text = 2), # number, - MultiContentEntryText(pos = (100, 0), size = (120, 25), font = 0, flags = RT_HALIGN_LEFT, text = 3), # description, - MultiContentEntryText(pos = (230, 0), size = (200, 25), font = 0, flags = RT_HALIGN_LEFT, text = 4), # language, - MultiContentEntryText(pos = (440, 4), size = (60, 25), font = 1, flags = RT_HALIGN_RIGHT, text = 5), # selection, ->>>>>>> more experimenting on vobsubs - ], False, "showNever") - }, - "fonts": [gFont("Regular", 20), gFont("Regular", 16)], - "itemHeight": 25 - } - - @@ -670,7 +616,19 @@ self.instance.move(ePoint(orgpos.x() + (orgwidth - newwidth)/2, orgpos.y())) - + + + {"template": [ + MultiContentEntryText(pos = (85, 6), size = (440, 28), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_TOP, text = 1), # index 1 is the interfacename + MultiContentEntryText(pos = (85, 43), size = (440, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_BOTTOM, text = 2), # index 2 is the description + MultiContentEntryPixmapAlphaTest(pos = (2, 8), size = (54, 54), png = 3), # index 3 is the interface pixmap + MultiContentEntryPixmapAlphaTest(pos = (63, 46), size = (15, 16), png = 4), # index 4 is the default pixmap + ], + "fonts": [gFont("Regular", 28),gFont("Regular", 20)], + "itemHeight": 70 + } + + diff --git a/lib/python/Screens/AudioSelection.py b/lib/python/Screens/AudioSelection.py index 0245cffb..2d35cff6 100644 --- a/lib/python/Screens/AudioSelection.py +++ b/lib/python/Screens/AudioSelection.py @@ -50,25 +50,33 @@ class AudioSelection(Screen, ConfigListScreen): self.settings = ConfigSubsection() choicelist = [(PAGE_AUDIO,_("audio tracks")), (PAGE_SUBTITLES,_("Subtitles"))] + print "debug 1: choicelist", page self.settings.menupage = ConfigSelection(choices = choicelist, default=page) self.settings.menupage.addNotifier(self.fillList) + print "debug 2" self.onLayoutFinish.append(self.__layoutFinished) + print "debug 3" def __layoutFinished(self): + print "[__layoutFinished]" self["config"].instance.setSelectionEnable(False) + print "after instance.setSelectionEnable" self.focus = FOCUS_STREAMS + print "debug 4" def fillList(self, arg=None): + print "debug fillList" streams = [] conflist = [] selectedidx = 0 - service = self.session.nav.getCurrentService() - self.audioTracks = audio = service and service.audioTracks() - n = audio and audio.getNumberOfTracks() or 0 + print "debug fillList 2" if self.settings.menupage.getValue() == PAGE_AUDIO: self.setTitle(_("Select audio track")) + service = self.session.nav.getCurrentService() + self.audioTracks = audio = service and service.audioTracks() + n = audio and audio.getNumberOfTracks() or 0 if SystemInfo["CanDownmixAC3"]: self.settings.downmix = ConfigOnOff(default=config.av.downmix_ac3.value) self.settings.downmix.addNotifier(self.changeAC3Downmix, initial_call = False) @@ -110,13 +118,12 @@ class AudioSelection(Screen, ConfigListScreen): streams.append((x, "", number, description, language, selected)) else: - conflist.append(getConfigListEntry("", self.settings.dummy)) - self["key_green"].setBoolean(False) streams = [] conflist.append(('',)) self["key_green"].setBoolean(False) elif self.settings.menupage.getValue() == PAGE_SUBTITLES: + print "debug PAGE_SUBTITLES" self.setTitle(_("Subtitle selection")) conflist.append(('',)) conflist.append(('',)) @@ -131,6 +138,7 @@ class AudioSelection(Screen, ConfigListScreen): idx = 0 subtitlelist = self.getSubtitleList() + print ">>>>>>>>subtitlelist", subtitlelist if len(subtitlelist): for x in subtitlelist: @@ -162,6 +170,7 @@ class AudioSelection(Screen, ConfigListScreen): description = types[x[2]] streams.append((x, "", number, description, language, selected)) + print "appending", x, "", number, description, language, selected idx += 1 else: @@ -312,4 +321,5 @@ class AudioSelection(Screen, ConfigListScreen): class SubtitleSelection(AudioSelection): def __init__(self, session, infobar=None): - AudioSelection.__init__(self, session, infobar, PAGE_SUBTITLES) + AudioSelection.__init__(self, session, infobar, page=PAGE_SUBTITLES) + self.skinName = ["AudioSelection"] diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index 58d89281..f29d0c52 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -326,48 +326,40 @@ eServiceMP3::eServiceMP3(eServiceReference ref) g_free(uri); m_gst_subtitlebin = gst_bin_new("subtitle_bin"); - + GstElement *appsink = gst_element_factory_make("appsink", "subtitle_sink"); + GstElement *fakesink = gst_element_factory_make("fakesink", "subtitle_fakesink"); if (!appsink) eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-appsink"); // <<<<<<< HEAD // else // { -// m_subs_to_pull_handler_id = g_signal_connect (subsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); -// g_object_set (G_OBJECT (subsink), "caps", gst_caps_from_string("text/plain; text/x-plain; text/x-pango-markup"), NULL); -// g_object_set (G_OBJECT (m_gst_playbin), "text-sink", subsink, NULL); +// m_subs_to_pull_handler_id = g_signal_connect (appsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); +// g_object_set (G_OBJECT (appsink), "caps", gst_caps_from_string("text/plain; text/x-pango-markup"), NULL); +// g_object_set (G_OBJECT (m_gst_playbin), "text-sink", appsink, NULL); // } // ======= -// GstElement *dvdsubdec = gst_element_factory_make("dvdsubdec", "vobsubtitle_decoder"); -// if ( !dvdsubdec ) -// eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-dvdsub"); -// -// gst_bin_add_many(GST_BIN(m_gst_subtitlebin), dvdsubdec, appsink, NULL); -// GstPad *ghostpad = gst_ghost_pad_new("sink", gst_element_get_static_pad (appsink, "sink")); + GstElement *dvdsubdec = gst_element_factory_make("dvdsubdec", "vobsubtitle_decoder"); + if ( !dvdsubdec ) + eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-dvdsub"); + + gst_bin_add_many(GST_BIN(m_gst_subtitlebin), dvdsubdec, appsink, fakesink, NULL); + GstPad *ghostpad = gst_ghost_pad_new("sink", gst_element_get_static_pad (fakesink, "sink")); // // GstPad *ghostpad = gst_ghost_pad_new("sink", gst_element_get_static_pad (dvdsubdec, "sink")); -// gst_element_add_pad (m_gst_subtitlebin, ghostpad); -// eDebug("eServiceMP3::construct dvdsubdec=%p, appsink=%p, ghostpad=%p,", dvdsubdec, appsink, ghostpad); -// -// g_signal_connect (ghostpad, "notify::caps", G_CALLBACK (gstCBsubtitleCAPS), this); -// -// GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-raw-rgb"); -// g_object_set (G_OBJECT (appsink), "caps", caps, NULL); -// g_object_set (G_OBJECT (dvdsubdec), "singlebuffer", TRUE, NULL); -// gst_caps_unref(caps); -// -// int ret = gst_element_link(dvdsubdec, appsink); -// eDebug("eServiceMP3::linking elements dvdsubdec and subsink appsink %i", ret); - -// g_object_set (G_OBJECT (m_gst_playbin), "text-sink", m_gst_subtitlebin, NULL); + gst_element_add_pad (m_gst_subtitlebin, ghostpad); + eDebug("eServiceMP3::construct dvdsubdec=%p, appsink=%p, fakesink=%p, ghostpad=%p,", dvdsubdec, appsink, fakesink, ghostpad); + + g_signal_connect (ghostpad, "notify::caps", G_CALLBACK (gstCBsubtitleCAPS), this); - GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup"); + GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-raw-rgb"); g_object_set (G_OBJECT (appsink), "caps", caps, NULL); - - g_object_set (G_OBJECT (m_gst_playbin), "text-sink", appsink, NULL); + g_object_set (G_OBJECT (dvdsubdec), "singlebuffer", TRUE, NULL); + gst_caps_unref(caps); + + g_object_set (G_OBJECT (m_gst_playbin), "text-sink", m_gst_subtitlebin, NULL); m_subs_to_pull_handler_id = g_signal_connect (appsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); -// >>>>>>> fix empty streams list crash, correctly show/hide color key buttons, re-implement plugin-hook for blue key, fix possible exit crash if ( m_gst_playbin ) { @@ -404,6 +396,7 @@ eServiceMP3::~eServiceMP3() { // disconnect subtitle callback GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); if (appsink) { @@ -686,6 +679,7 @@ RESULT eServiceMP3::getPlayPosition(pts_t &pts) /* pos is in nanoseconds. we have 90 000 pts per second. */ pts = pos / 11111; + eDebug("gst_element_query_position %lld pts (%lld ms)", pts, pos/1000000); return 0; } @@ -1145,19 +1139,25 @@ subtype_t getSubtitleType(GstPad* pad, gchar *g_codec=NULL) type = stSSA; else if ( !strcmp(g_type, "text/plain") ) type = stPlainText; + else + eDebug("getSubtitleType::unsupported subtitle caps %s (%s)", g_type, g_codec); } else if ( g_codec ) { eDebug("getSubtitleType::subtitle probe codec tag=%s", g_codec); if ( !strcmp(g_codec, "VOB") ) type = stVOB; - else if ( !strcmp(g_codec, "SubStation Alpha") ) + else if ( !strcmp(g_codec, "SubStation Alpha") || !strcmp(g_codec, "SSA") ) type = stSSA; else if ( !strcmp(g_codec, "ASS") ) type = stASS; else if ( !strcmp(g_codec, "UTF-8 plain text") ) type = stPlainText; + else + eDebug("getSubtitleType::unsupported subtitle codec %s", g_codec); } + else + eDebug("getSubtitleType::unidentifiable subtitle stream!"); return type; } @@ -1208,8 +1208,8 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) } break; case GST_STATE_CHANGE_READY_TO_PAUSED: { -// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); - GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); + GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); if (appsink) { g_object_set (G_OBJECT (appsink), "max-buffers", 2, NULL); @@ -1357,6 +1357,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) gchar *g_codec = NULL, *g_lang = NULL; g_signal_emit_by_name (m_gst_playbin, "get-text-tags", i, &tags); subtitleStream subs; + int ret; g_lang = g_strdup_printf ("und"); if ( tags && gst_is_tag_list(tags) ) @@ -1367,7 +1368,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) } subs.language_code = std::string(g_lang); - eDebug("eServiceMP3::subtitle stream=%i language=%s", i, g_lang); + eDebug("eServiceMP3::subtitle stream=%i language=%s codec=%s", i, g_lang, g_codec); GstPad* pad = 0; g_signal_emit_by_name (m_gst_playbin, "get-text-pad", i, &pad); @@ -1560,22 +1561,34 @@ void eServiceMP3::gstCBsubtitleLink(subtype_t type, gpointer user_data) GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); GstPad *subdecsinkpad = gst_element_get_static_pad (dvdsubdec, "sink"); int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, subdecsinkpad); + GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); + ret += gst_element_link(dvdsubdec, appsink); eDebug("gstCBsubtitleLink:: dvdsubdec=%p, subdecsinkpad=%p, ghostpad=%p, link=%i", dvdsubdec, subdecsinkpad, ghostpad, ret); } - else + else if ( type < stVOB && type > stUnknown ) { GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); GstPad *appsinkpad = gst_element_get_static_pad (appsink, "sink"); + GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); + gst_element_unlink(dvdsubdec, appsink); int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, appsinkpad); eDebug("gstCBsubtitleLink:: appsink=%p, appsinkpad=%p, ghostpad=%p, link=%i", appsink, appsinkpad, ghostpad, ret); } + else + { + GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); + GstElement *fakesink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_fakesink"); + GstPad *fakesinkpad = gst_element_get_static_pad (fakesink, "sink"); + int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, fakesinkpad); + eDebug("gstCBsubtitleLink:: unsupported subtitles ... throwing them into fakesink"); + } } void eServiceMP3::pullSubtitle() { -// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); - GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); + GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); if (appsink) { @@ -1754,7 +1767,7 @@ eDebug ("eServiceMP3::enableSubtitles g_object_set"); eDebug ("eServiceMP3::enableSubtitles cleared"); // } -// gstCBsubtitleLink(m_subtitleStreams[m_currentSubtitleStream].type, this); + gstCBsubtitleLink(m_subtitleStreams[m_currentSubtitleStream].type, this); m_subtitle_widget = 0; m_subtitle_widget = new eSubtitleWidget(parent); diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index 7aa6cdd7..c31090e7 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -215,7 +215,6 @@ private: static void gstCBsubtitleAvail(GstElement *element, gpointer user_data); static void gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer user_data); static void gstCBsubtitleLink(subtype_t type, gpointer user_data); - GstPad* gstCreateSubtitleSink(eServiceMP3* _this, subtype_t type); void gstPoll(const int&); std::list m_subtitle_pages; -- cgit v1.2.3 From 6693714648a697fd1c86c760222795ed0341b140 Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Fri, 11 Jun 2010 15:34:27 +0200 Subject: experimentally enable vob subtitles --- lib/python/Screens/AudioSelection.py | 16 +---- lib/service/servicemp3.cpp | 109 +++++++++++++++++++++-------------- lib/service/servicemp3.h | 3 +- 3 files changed, 69 insertions(+), 59 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/lib/python/Screens/AudioSelection.py b/lib/python/Screens/AudioSelection.py index 2d35cff6..b5278389 100644 --- a/lib/python/Screens/AudioSelection.py +++ b/lib/python/Screens/AudioSelection.py @@ -50,28 +50,19 @@ class AudioSelection(Screen, ConfigListScreen): self.settings = ConfigSubsection() choicelist = [(PAGE_AUDIO,_("audio tracks")), (PAGE_SUBTITLES,_("Subtitles"))] - print "debug 1: choicelist", page self.settings.menupage = ConfigSelection(choices = choicelist, default=page) self.settings.menupage.addNotifier(self.fillList) - print "debug 2" self.onLayoutFinish.append(self.__layoutFinished) - print "debug 3" def __layoutFinished(self): - print "[__layoutFinished]" self["config"].instance.setSelectionEnable(False) - print "after instance.setSelectionEnable" self.focus = FOCUS_STREAMS - print "debug 4" def fillList(self, arg=None): - print "debug fillList" streams = [] conflist = [] selectedidx = 0 - - print "debug fillList 2" - + if self.settings.menupage.getValue() == PAGE_AUDIO: self.setTitle(_("Select audio track")) service = self.session.nav.getCurrentService() @@ -123,7 +114,6 @@ class AudioSelection(Screen, ConfigListScreen): self["key_green"].setBoolean(False) elif self.settings.menupage.getValue() == PAGE_SUBTITLES: - print "debug PAGE_SUBTITLES" self.setTitle(_("Subtitle selection")) conflist.append(('',)) conflist.append(('',)) @@ -138,7 +128,6 @@ class AudioSelection(Screen, ConfigListScreen): idx = 0 subtitlelist = self.getSubtitleList() - print ">>>>>>>>subtitlelist", subtitlelist if len(subtitlelist): for x in subtitlelist: @@ -170,7 +159,6 @@ class AudioSelection(Screen, ConfigListScreen): description = types[x[2]] streams.append((x, "", number, description, language, selected)) - print "appending", x, "", number, description, language, selected idx += 1 else: @@ -196,7 +184,7 @@ class AudioSelection(Screen, ConfigListScreen): conflist.append(getConfigListEntry(Plugins[0][0], ConfigNothing())) self.plugincallfunc = Plugins[0][1] if len(Plugins) > 1: - print "these plugins are installed but not displayed in the dialog box:", Plugins[1:] + print "plugin(s) installed but not displayed in the dialog box:", Plugins[1:] self["config"].list = conflist self["config"].l.setList(conflist) diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index f29d0c52..74c15b2f 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -320,49 +320,44 @@ eServiceMP3::eServiceMP3(eServiceReference ref) g_object_set (G_OBJECT (m_gst_playbin), "uri", uri, NULL); - int flags = 0x47; // ( == GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_TEXT ) + int flags = 0x47; // ( GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_TEXT ); g_object_set (G_OBJECT (m_gst_playbin), "flags", flags, NULL); g_free(uri); m_gst_subtitlebin = gst_bin_new("subtitle_bin"); + + if ( m_gst_playbin ) + { + GstElement *appsink = gst_element_factory_make("appsink", "subtitle_sink"); + GstElement *fakesink = gst_element_factory_make("fakesink", "subtitle_fakesink"); - GstElement *appsink = gst_element_factory_make("appsink", "subtitle_sink"); - GstElement *fakesink = gst_element_factory_make("fakesink", "subtitle_fakesink"); + if (!appsink) + eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-appsink"); - if (!appsink) - eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-appsink"); -// <<<<<<< HEAD -// else -// { -// m_subs_to_pull_handler_id = g_signal_connect (appsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); -// g_object_set (G_OBJECT (appsink), "caps", gst_caps_from_string("text/plain; text/x-pango-markup"), NULL); -// g_object_set (G_OBJECT (m_gst_playbin), "text-sink", appsink, NULL); -// } -// ======= + GstElement *dvdsubdec = gst_element_factory_make("dvdsubdec", "vobsubtitle_decoder"); + if ( !dvdsubdec ) + eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-dvdsub"); - GstElement *dvdsubdec = gst_element_factory_make("dvdsubdec", "vobsubtitle_decoder"); - if ( !dvdsubdec ) - eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-dvdsub"); + gst_bin_add_many(GST_BIN(m_gst_subtitlebin), dvdsubdec, appsink, fakesink, NULL); + GstPad *ghostpad = gst_ghost_pad_new("sink", gst_element_get_static_pad (fakesink, "sink")); + gst_element_add_pad (m_gst_subtitlebin, ghostpad); - gst_bin_add_many(GST_BIN(m_gst_subtitlebin), dvdsubdec, appsink, fakesink, NULL); - GstPad *ghostpad = gst_ghost_pad_new("sink", gst_element_get_static_pad (fakesink, "sink")); -// // GstPad *ghostpad = gst_ghost_pad_new("sink", gst_element_get_static_pad (dvdsubdec, "sink")); - gst_element_add_pad (m_gst_subtitlebin, ghostpad); - eDebug("eServiceMP3::construct dvdsubdec=%p, appsink=%p, fakesink=%p, ghostpad=%p,", dvdsubdec, appsink, fakesink, ghostpad); + eDebug("eServiceMP3::construct dvdsubdec=%p, appsink=%p, fakesink=%p, ghostpad=%p", dvdsubdec, appsink, fakesink, ghostpad); - g_signal_connect (ghostpad, "notify::caps", G_CALLBACK (gstCBsubtitleCAPS), this); + g_signal_connect (ghostpad, "notify::caps", G_CALLBACK (gstCBsubtitleCAPS), this); - GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-raw-rgb"); - g_object_set (G_OBJECT (appsink), "caps", caps, NULL); - g_object_set (G_OBJECT (dvdsubdec), "singlebuffer", TRUE, NULL); - gst_caps_unref(caps); + GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-raw-rgb"); + g_object_set (G_OBJECT (appsink), "caps", caps, NULL); + g_object_set (G_OBJECT (dvdsubdec), "singlebuffer", TRUE, NULL); + g_object_set (G_OBJECT (appsink), "async", FALSE, NULL); + g_object_set (G_OBJECT (fakesink), "async", FALSE, NULL); - g_object_set (G_OBJECT (m_gst_playbin), "text-sink", m_gst_subtitlebin, NULL); - m_subs_to_pull_handler_id = g_signal_connect (appsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); + gst_caps_unref(caps); - if ( m_gst_playbin ) - { + g_object_set (G_OBJECT (m_gst_playbin), "text-sink", m_gst_subtitlebin, NULL); + m_subs_to_pull_handler_id = g_signal_connect (appsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); + gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)), gstBusSyncHandler, this); char srt_filename[strlen(filename)+1]; strncpy(srt_filename,filename,strlen(filename)-3); @@ -452,6 +447,9 @@ RESULT eServiceMP3::stop() if (m_state == stStopped) return -1; + + GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_gst_subtitlebin),GST_DEBUG_GRAPH_SHOW_ALL,"e2-subtitlebin"); + GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_gst_playbin),GST_DEBUG_GRAPH_SHOW_ALL,"e2-playbin"); eDebug("eServiceMP3::stop %s", m_ref.path.c_str()); gst_element_set_state(m_gst_playbin, GST_STATE_NULL); @@ -679,7 +677,7 @@ RESULT eServiceMP3::getPlayPosition(pts_t &pts) /* pos is in nanoseconds. we have 90 000 pts per second. */ pts = pos / 11111; - eDebug("gst_element_query_position %lld pts (%lld ms)", pts, pos/1000000); +// eDebug("gst_element_query_position %lld pts (%lld ms)", pts, pos/1000000); return 0; } @@ -1214,7 +1212,6 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) { g_object_set (G_OBJECT (appsink), "max-buffers", 2, NULL); g_object_set (G_OBJECT (appsink), "sync", FALSE, NULL); - g_object_set (G_OBJECT (appsink), "async", FALSE, NULL); g_object_set (G_OBJECT (appsink), "emit-signals", TRUE, NULL); eDebug("eServiceMP3::appsink properties set!"); gst_object_unref(appsink); @@ -1524,7 +1521,7 @@ void eServiceMP3::gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer us if ( _this->m_currentSubtitleStream >= _this->m_subtitleStreams.size() ) { - eDebug("return"); + eDebug("return invalid stream count"); return; } @@ -1549,6 +1546,7 @@ void eServiceMP3::gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer us g_free (g_lang); } + eDebug("return sub type already known: %i", subs.type); } void eServiceMP3::gstCBsubtitleLink(subtype_t type, gpointer user_data) @@ -1563,7 +1561,7 @@ void eServiceMP3::gstCBsubtitleLink(subtype_t type, gpointer user_data) int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, subdecsinkpad); GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); ret += gst_element_link(dvdsubdec, appsink); - eDebug("gstCBsubtitleLink:: dvdsubdec=%p, subdecsinkpad=%p, ghostpad=%p, link=%i", dvdsubdec, subdecsinkpad, ghostpad, ret); + eDebug("gstCBsubtitleLink:: dvdsubdec=%p, subdecsinkpad=%p, ghostpad=%p, set target & link=%i", dvdsubdec, subdecsinkpad, ghostpad, ret); } else if ( type < stVOB && type > stUnknown ) { @@ -1573,7 +1571,7 @@ void eServiceMP3::gstCBsubtitleLink(subtype_t type, gpointer user_data) GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); gst_element_unlink(dvdsubdec, appsink); int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, appsinkpad); - eDebug("gstCBsubtitleLink:: appsink=%p, appsinkpad=%p, ghostpad=%p, link=%i", appsink, appsinkpad, ghostpad, ret); + eDebug("gstCBsubtitleLink:: appsink=%p, appsinkpad=%p, ghostpad=%p, set target=%i", appsink, appsinkpad, ghostpad, ret); } else { @@ -1581,10 +1579,26 @@ void eServiceMP3::gstCBsubtitleLink(subtype_t type, gpointer user_data) GstElement *fakesink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_fakesink"); GstPad *fakesinkpad = gst_element_get_static_pad (fakesink, "sink"); int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, fakesinkpad); - eDebug("gstCBsubtitleLink:: unsupported subtitles ... throwing them into fakesink"); + eDebug("gstCBsubtitleLink:: unsupported subtitles ... throwing them into fakesink %i", ret); } } +gboolean eServiceMP3::gstCBsubtitleDrop(GstPad *pad, GstBuffer *buffer, gpointer user_data) +{ + eDebug("gstCBsubtitleDrop"); + + gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); + gint64 duration_ns = GST_BUFFER_DURATION(buffer); + size_t len = GST_BUFFER_SIZE(buffer); + + unsigned char line[len+1]; + memcpy(line, GST_BUFFER_DATA(buffer), len); + line[len] = 0; + eDebug("dropping buffer '%s' ", line); + return false; +} + + void eServiceMP3::pullSubtitle() { GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); @@ -1659,7 +1673,7 @@ void eServiceMP3::pushSubtitles() while ( !m_subtitle_pages.empty() ) { SubtitlePage frontpage = m_subtitle_pages.front(); - gint64 diff_ms; + gint64 diff_ms = 0; getPlayPosition(running_pts); @@ -1742,6 +1756,11 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) gint text_pid = 0; eSingleLocker l(m_subs_to_pull_lock); +// GstPad *pad = 0; +// g_signal_emit_by_name (m_gst_playbin, "get-text-pad", m_currentSubtitleStream, &pad); +// gst_element_get_static_pad(m_gst_subtitlebin, "sink"); +// gulong subprobe_handler_id = gst_pad_add_buffer_probe (pad, G_CALLBACK (gstCBsubtitleDrop), NULL); + if (!PyTuple_Check(tuple)) goto error_out; if (tuplesize < 1) @@ -1756,19 +1775,19 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) type = PyInt_AsLong(entry); eDebug ("eServiceMP3::enableSubtitles new pid=%i",pid); -// if (m_currentSubtitleStream != pid) -// { - + if (m_currentSubtitleStream != pid) + { + gstCBsubtitleLink(stUnknown, this); + g_object_set (G_OBJECT (m_gst_playbin), "current-text", pid, NULL); -eDebug ("eServiceMP3::enableSubtitles g_object_set"); + eDebug ("eServiceMP3::enableSubtitles g_object_set current-text = %i", pid); m_currentSubtitleStream = pid; m_subs_to_pull = 0; m_subtitle_pages.clear(); -eDebug ("eServiceMP3::enableSubtitles cleared"); -// } + } gstCBsubtitleLink(m_subtitleStreams[m_currentSubtitleStream].type, this); - + m_subtitle_widget = 0; m_subtitle_widget = new eSubtitleWidget(parent); m_subtitle_widget->resize(parent->size()); /* full size */ @@ -1776,6 +1795,8 @@ eDebug ("eServiceMP3::enableSubtitles cleared"); g_object_get (G_OBJECT (m_gst_playbin), "current-text", &text_pid, NULL); eDebug ("eServiceMP3::switched to subtitle stream %i", text_pid); + gst_pad_remove_buffer_probe (pad, subprobe_handler_id); + m_event((iPlayableService*)this, evUpdatedInfo); return 0; diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index c31090e7..6aff90e3 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -215,8 +215,9 @@ private: static void gstCBsubtitleAvail(GstElement *element, gpointer user_data); static void gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer user_data); static void gstCBsubtitleLink(subtype_t type, gpointer user_data); + static gboolean gstCBsubtitleDrop(GstPad *pad, GstBuffer *buffer, gpointer user_data); void gstPoll(const int&); - + std::list m_subtitle_pages; ePtr m_subtitle_sync_timer; ePtr m_subtitle_hide_timer; -- cgit v1.2.3 From 4fb2d81afcc8bc781ee8c705dca2488fef201c51 Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Fri, 11 Jun 2010 23:03:52 +0200 Subject: more vob experiments --- lib/python/Components/ConfigList.py | 2 +- lib/service/servicemp3.cpp | 54 +++++++++++++++++++++++-------------- lib/service/servicemp3.h | 1 + 3 files changed, 36 insertions(+), 21 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/lib/python/Components/ConfigList.py b/lib/python/Components/ConfigList.py index ffbc69af..5a02c38d 100755 --- a/lib/python/Components/ConfigList.py +++ b/lib/python/Components/ConfigList.py @@ -88,7 +88,7 @@ class ConfigList(HTMLComponent, GUIComponent, object): if l is not None: for x in l: - assert isinstance(x[1], ConfigElement), "entry in ConfigList " + str(x[1]) + " must be a ConfigElement" + assert isinstance(x, ConfigElement), "entry in ConfigList " + str(x) + " must be a ConfigElement" def getList(self): return self.__list diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index 74c15b2f..7d463bd7 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -21,6 +21,8 @@ #include #include +static GstStaticPadTemplate subsinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("text/plain; text/x-pango-markup; video/x-dvd-subpicture")); + // eServiceFactoryMP3 eServiceFactoryMP3::eServiceFactoryMP3() @@ -330,7 +332,6 @@ eServiceMP3::eServiceMP3(eServiceReference ref) if ( m_gst_playbin ) { GstElement *appsink = gst_element_factory_make("appsink", "subtitle_sink"); - GstElement *fakesink = gst_element_factory_make("fakesink", "subtitle_fakesink"); if (!appsink) eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-appsink"); @@ -339,22 +340,33 @@ eServiceMP3::eServiceMP3(eServiceReference ref) if ( !dvdsubdec ) eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-dvdsub"); - gst_bin_add_many(GST_BIN(m_gst_subtitlebin), dvdsubdec, appsink, fakesink, NULL); - GstPad *ghostpad = gst_ghost_pad_new("sink", gst_element_get_static_pad (fakesink, "sink")); - gst_element_add_pad (m_gst_subtitlebin, ghostpad); + gst_bin_add_many(GST_BIN(m_gst_subtitlebin), dvdsubdec, appsink, NULL); + +// GstPad *ghostpad = gst_ghost_pad_new("sink", gst_element_get_static_pad (appsink, "sink")); - eDebug("eServiceMP3::construct dvdsubdec=%p, appsink=%p, fakesink=%p, ghostpad=%p", dvdsubdec, appsink, fakesink, ghostpad); + GstPadTemplate *templ; + templ = gst_static_pad_template_get (&subsinktemplate); + + GstPad *ghostpad = gst_ghost_pad_new_no_target_from_template("sink", templ); + gst_element_add_pad (m_gst_subtitlebin, ghostpad); g_signal_connect (ghostpad, "notify::caps", G_CALLBACK (gstCBsubtitleCAPS), this); GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-raw-rgb"); g_object_set (G_OBJECT (appsink), "caps", caps, NULL); + gst_caps_unref(caps); + +// GstCaps* caps2 = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-dvd-subpicture"); +// int ret = gst_pad_set_caps (ghostpad, caps2); +// gst_caps_unref(caps2); + g_object_set (G_OBJECT (dvdsubdec), "singlebuffer", TRUE, NULL); g_object_set (G_OBJECT (appsink), "async", FALSE, NULL); - g_object_set (G_OBJECT (fakesink), "async", FALSE, NULL); - gst_caps_unref(caps); + gst_pad_set_getcaps_function (ghostpad, gstGhostpadGetCAPS); + eDebug("eServiceMP3::construct dvdsubdec=%p, appsink=%p, ghostpad=%p", dvdsubdec, appsink, ghostpad); + g_object_set (G_OBJECT (m_gst_playbin), "text-sink", m_gst_subtitlebin, NULL); m_subs_to_pull_handler_id = g_signal_connect (appsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); @@ -448,7 +460,6 @@ RESULT eServiceMP3::stop() if (m_state == stStopped) return -1; - GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_gst_subtitlebin),GST_DEBUG_GRAPH_SHOW_ALL,"e2-subtitlebin"); GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_gst_playbin),GST_DEBUG_GRAPH_SHOW_ALL,"e2-playbin"); eDebug("eServiceMP3::stop %s", m_ref.path.c_str()); @@ -1512,6 +1523,16 @@ void eServiceMP3::gstCBsubtitleAvail(GstElement *appsink, gpointer user_data) _this->m_pump.send(2); } +GstCaps* eServiceMP3::gstGhostpadGetCAPS (GstPad * pad) +{ + eDebug("eServiceMP3::gstGhostpadGetCAPS"); + return gst_static_pad_template_get_caps(&subsinktemplate); +// return gst_pad_get_pad_template_caps(pad); +// return get_pad_template_caps(pad); +// GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-dvd-subpicture"); +// return caps; +} + void eServiceMP3::gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer user_data) { eDebug("gstCBsubtitleCAPS:: signal::caps callback obj=%p", obj); @@ -1519,7 +1540,7 @@ void eServiceMP3::gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer us eServiceMP3 *_this = (eServiceMP3*)user_data; eDebug("gstCBsubtitleCAPS:: m_currentSubtitleStream=%i, m_subtitleStreams.size()=%i", _this->m_currentSubtitleStream, _this->m_subtitleStreams.size()); - if ( _this->m_currentSubtitleStream >= _this->m_subtitleStreams.size() ) + if ( _this->m_currentSubtitleStream >= (int)_this->m_subtitleStreams.size() ) { eDebug("return invalid stream count"); return; @@ -1546,7 +1567,8 @@ void eServiceMP3::gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer us g_free (g_lang); } - eDebug("return sub type already known: %i", subs.type); + + gstCBsubtitleLink(subs.type, _this); } void eServiceMP3::gstCBsubtitleLink(subtype_t type, gpointer user_data) @@ -1575,11 +1597,7 @@ void eServiceMP3::gstCBsubtitleLink(subtype_t type, gpointer user_data) } else { - GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); - GstElement *fakesink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_fakesink"); - GstPad *fakesinkpad = gst_element_get_static_pad (fakesink, "sink"); - int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, fakesinkpad); - eDebug("gstCBsubtitleLink:: unsupported subtitles ... throwing them into fakesink %i", ret); + eDebug("gstCBsubtitleLink:: unsupported subtitles"); } } @@ -1777,8 +1795,6 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) eDebug ("eServiceMP3::enableSubtitles new pid=%i",pid); if (m_currentSubtitleStream != pid) { - gstCBsubtitleLink(stUnknown, this); - g_object_set (G_OBJECT (m_gst_playbin), "current-text", pid, NULL); eDebug ("eServiceMP3::enableSubtitles g_object_set current-text = %i", pid); m_currentSubtitleStream = pid; @@ -1786,8 +1802,6 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) m_subtitle_pages.clear(); } - gstCBsubtitleLink(m_subtitleStreams[m_currentSubtitleStream].type, this); - m_subtitle_widget = 0; m_subtitle_widget = new eSubtitleWidget(parent); m_subtitle_widget->resize(parent->size()); /* full size */ @@ -1795,7 +1809,7 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) g_object_get (G_OBJECT (m_gst_playbin), "current-text", &text_pid, NULL); eDebug ("eServiceMP3::switched to subtitle stream %i", text_pid); - gst_pad_remove_buffer_probe (pad, subprobe_handler_id); +// gst_pad_remove_buffer_probe (pad, subprobe_handler_id); m_event((iPlayableService*)this, evUpdatedInfo); diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index 6aff90e3..19d0af4d 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -213,6 +213,7 @@ private: void gstBusCall(GstBus *bus, GstMessage *msg); static GstBusSyncReply gstBusSyncHandler(GstBus *bus, GstMessage *message, gpointer user_data); static void gstCBsubtitleAvail(GstElement *element, gpointer user_data); + static GstCaps* gstGhostpadGetCAPS (GstPad * pad); static void gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer user_data); static void gstCBsubtitleLink(subtype_t type, gpointer user_data); static gboolean gstCBsubtitleDrop(GstPad *pad, GstBuffer *buffer, gpointer user_data); -- cgit v1.2.3 From 032f04eacfaaa0a616b4d0cf34e85b497de62d9f Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Mon, 21 Jun 2010 08:59:18 +0200 Subject: try fixing hot switching between text and vobsub streams --- lib/service/servicemp3.cpp | 345 +++++++++++++++++++++++++++++++++++++-------- lib/service/servicemp3.h | 18 ++- 2 files changed, 300 insertions(+), 63 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index 7d463bd7..1aa3b5b5 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -21,7 +21,7 @@ #include #include -static GstStaticPadTemplate subsinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("text/plain; text/x-pango-markup; video/x-dvd-subpicture")); +static GstStaticPadTemplate subsinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS("text/plain; text/x-pango-markup; video/x-dvd-subpicture")); // eServiceFactoryMP3 @@ -350,8 +350,6 @@ eServiceMP3::eServiceMP3(eServiceReference ref) GstPad *ghostpad = gst_ghost_pad_new_no_target_from_template("sink", templ); gst_element_add_pad (m_gst_subtitlebin, ghostpad); - g_signal_connect (ghostpad, "notify::caps", G_CALLBACK (gstCBsubtitleCAPS), this); - GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-raw-rgb"); g_object_set (G_OBJECT (appsink), "caps", caps, NULL); gst_caps_unref(caps); @@ -362,8 +360,21 @@ eServiceMP3::eServiceMP3(eServiceReference ref) g_object_set (G_OBJECT (dvdsubdec), "singlebuffer", TRUE, NULL); g_object_set (G_OBJECT (appsink), "async", FALSE, NULL); + g_object_set (G_OBJECT (appsink), "sync", TRUE, NULL); + g_object_set (G_OBJECT (appsink), "emit-signals", TRUE, NULL); + g_object_set (G_OBJECT (appsink), "ts-offset", 0 * GST_SECOND, NULL); + g_object_set_data (G_OBJECT (ghostpad), "application-instance", this); + g_signal_connect (G_OBJECT (ghostpad), "notify::caps", G_CALLBACK (gstGhostpadHasCAPS), this); gst_pad_set_getcaps_function (ghostpad, gstGhostpadGetCAPS); + gst_pad_set_acceptcaps_function (ghostpad, gstGhostpadAcceptCAPS); + m_ghost_pad_buffer_alloc = GST_PAD_BUFFERALLOCFUNC(ghostpad); + m_ghost_pad_chain_function = GST_PAD_CHAINFUNC(ghostpad); + m_ghost_pad_subtitle_sink_event = GST_PAD_EVENTFUNC(ghostpad); + gst_pad_set_bufferalloc_function (ghostpad, GST_DEBUG_FUNCPTR(gstGhostpadBufferAlloc)); + gst_pad_set_event_function (ghostpad, GST_DEBUG_FUNCPTR(gstGhostpadSinkEvent)); + gst_pad_set_chain_function (ghostpad, GST_DEBUG_FUNCPTR(gstGhostpadChainFunction)); + m_gst_prev_subtitle_caps = gst_caps_new_empty(); eDebug("eServiceMP3::construct dvdsubdec=%p, appsink=%p, ghostpad=%p", dvdsubdec, appsink, ghostpad); @@ -412,6 +423,7 @@ eServiceMP3::~eServiceMP3() } delete m_subtitle_widget; + gst_caps_unref(this->m_gst_prev_subtitle_caps); // disconnect sync handler callback gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)), NULL, NULL); @@ -1217,16 +1229,16 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) } break; case GST_STATE_CHANGE_READY_TO_PAUSED: { - GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); // GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); - if (appsink) - { - g_object_set (G_OBJECT (appsink), "max-buffers", 2, NULL); - g_object_set (G_OBJECT (appsink), "sync", FALSE, NULL); - g_object_set (G_OBJECT (appsink), "emit-signals", TRUE, NULL); - eDebug("eServiceMP3::appsink properties set!"); - gst_object_unref(appsink); - } +// if (appsink) +// { +// g_object_set (G_OBJECT (appsink), "max-buffers", 2, NULL); +// g_object_set (G_OBJECT (appsink), "sync", FALSE, NULL); +// g_object_set (G_OBJECT (appsink), "emit-signals", TRUE, NULL); +// eDebug("eServiceMP3::appsink properties set!"); +// gst_object_unref(appsink); +// } setAC3Delay(ac3_delay); setPCMDelay(pcm_delay); } break; @@ -1523,35 +1535,186 @@ void eServiceMP3::gstCBsubtitleAvail(GstElement *appsink, gpointer user_data) _this->m_pump.send(2); } -GstCaps* eServiceMP3::gstGhostpadGetCAPS (GstPad * pad) +gboolean eServiceMP3::gstGhostpadSinkEvent(GstPad * pad, GstEvent * event) +{ + eDebug("eServiceMP3::gstGhostpadSinkEvent %s", gst_structure_get_name (event->structure)); + +// eServiceMP3 *_this = (eServiceMP3*) (gst_pad_get_parent (pad)); + eServiceMP3 *_this = g_object_get_data (G_OBJECT (pad), "application-instance"); + gboolean ret; + GstFormat format; + + if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB && event->structure && strcmp (gst_structure_get_name (event->structure), "subtitleoverlay-flush-subtitle") == 0) + { + eDebug ("Custom subtitle flush event"); +// GST_SUBTITLE_OVERLAY_LOCK (self); +// self->subtitle_flush = TRUE; +// self->subtitle_error = FALSE; +// if (self->subtitle_block_pad) +// gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE, +// _pad_blocked_cb, gst_object_ref (self), +// (GDestroyNotify) gst_object_unref); +// if (self->video_block_pad) +// gst_pad_set_blocked_async_full (self->video_block_pad, TRUE, +// _pad_blocked_cb, gst_object_ref (self), +// (GDestroyNotify) gst_object_unref); +// GST_SUBTITLE_OVERLAY_UNLOCK (self); +// + gst_event_unref (event); + event = NULL; + ret = TRUE; + goto out; + } else if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) + { + gst_event_parse_new_segment_full (event, NULL, NULL, NULL, &format, NULL, NULL, NULL); + if (_this->m_gst_subtitle_segment.format != GST_FORMAT_UNDEFINED && _this->m_gst_subtitle_segment.format != format) + { + eDebug("Subtitle segment format changed: %s -> %s", gst_format_get_name(_this->m_gst_subtitle_segment.format), gst_format_get_name(format)); + gst_segment_init (&_this->m_gst_subtitle_segment, GST_FORMAT_UNDEFINED); + } + } + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + eDebug("Resetting subtitle segment because of flush-stop"); + gst_segment_init (&_this->m_gst_subtitle_segment, GST_FORMAT_UNDEFINED); + /* fall through */ + case GST_EVENT_FLUSH_START: + case GST_EVENT_NEWSEGMENT: + case GST_EVENT_EOS: +// eDebug("GST_EVENT_FLUSH_START GST_EVENT_NEWSEGMENT GST_EVENT_EOS"); + /* Add our event marker to make sure no events from here go ever outside + * the element, they're only interesting for our internal elements */ +// event = +// GST_EVENT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST +// (event))); +// if (!event->structure) { +// event->structure = +// gst_structure_id_empty_new (_subtitle_overlay_event_marker_id); +// gst_structure_set_parent_refcount (event->structure, +// &event->mini_object.refcount); +// } +// gst_structure_id_set (event->structure, _subtitle_overlay_event_marker_id, +// G_TYPE_BOOLEAN, TRUE, NULL); + break; + default: + eDebug("GST_EVENT_TYPE other: %i", GST_EVENT_TYPE (event)); + break; + } + + ret = _this->m_ghost_pad_subtitle_sink_event (pad, gst_event_ref (event)); +eDebug("original EVENTFUNC returned %i", ret); + + if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) { + gboolean update; + gdouble rate, applied_rate; + gint64 start, stop, position; + + GST_DEBUG_OBJECT (pad, "Newsegment event: %" GST_PTR_FORMAT, + event->structure); + gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, + &format, &start, &stop, &position); + + GST_DEBUG_OBJECT (pad, "Old subtitle segment: %" GST_SEGMENT_FORMAT, + &_this->m_gst_subtitle_segment); + if (_this->m_gst_subtitle_segment.format != format) { + GST_DEBUG_OBJECT (pad, "Subtitle segment format changed: %s -> %s", + gst_format_get_name (_this->m_gst_subtitle_segment.format), + gst_format_get_name (format)); + gst_segment_init (&_this->m_gst_subtitle_segment, format); + } + + gst_segment_set_newsegment_full (&_this->m_gst_subtitle_segment, update, rate, + applied_rate, format, start, stop, position); + GST_DEBUG_OBJECT (pad, "New subtitle segment: %" GST_SEGMENT_FORMAT, + &_this->m_gst_subtitle_segment); + } + gst_event_unref (event); +// +out: +// gst_object_unref (_this); + return ret; +} + +GstCaps* eServiceMP3::gstGhostpadGetCAPS(GstPad * pad) { eDebug("eServiceMP3::gstGhostpadGetCAPS"); return gst_static_pad_template_get_caps(&subsinktemplate); -// return gst_pad_get_pad_template_caps(pad); -// return get_pad_template_caps(pad); -// GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-dvd-subpicture"); -// return caps; } -void eServiceMP3::gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer user_data) +gboolean eServiceMP3::gstGhostpadAcceptCAPS(GstPad * pad, GstCaps * caps) { - eDebug("gstCBsubtitleCAPS:: signal::caps callback obj=%p", obj); + GstCaps *templ_caps = gst_static_pad_template_get_caps (&subsinktemplate); + gboolean ret = gst_caps_can_intersect (templ_caps, caps); + + eDebug("gstGhostpadAcceptCAPS templ=%s, given=%s ret=%i", gst_caps_to_string(templ_caps), gst_caps_to_string(caps), ret); + gst_caps_unref (templ_caps); + + return ret; +} +void eServiceMP3::gstGhostpadLink(gpointer user_data, GstCaps * caps) +{ + GstStructure *s; + GstPad *sinkpad; eServiceMP3 *_this = (eServiceMP3*)user_data; - eDebug("gstCBsubtitleCAPS:: m_currentSubtitleStream=%i, m_subtitleStreams.size()=%i", _this->m_currentSubtitleStream, _this->m_subtitleStreams.size()); - if ( _this->m_currentSubtitleStream >= (int)_this->m_subtitleStreams.size() ) + // FIXME: Need to cache events from the ghostpad and pass them forward + // now... and keep track of the segment and pass newsegment events + // downstream. + s = gst_caps_get_structure (caps, 0); + + GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); + GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); + GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); + + gst_ghost_pad_set_target(GST_GHOST_PAD(ghostpad), NULL); + gst_element_unlink(dvdsubdec, appsink); + int ret = -1; + + if (gst_structure_has_name (s, "video/x-dvd-subpicture")) { - eDebug("return invalid stream count"); - return; + sinkpad = gst_element_get_static_pad (dvdsubdec, "sink"); + ret = gst_element_link_pads (dvdsubdec, "src", appsink, "sink"); + eDebug("gstGhostpadLink:: dvdsubdec+appsink = %i", ret); + } + else + { + sinkpad = gst_element_get_static_pad (appsink, "sink"); + eDebug("gstGhostpadLink:: appsink"); } + gst_ghost_pad_set_target (GST_GHOST_PAD(ghostpad), sinkpad); +} + +GstFlowReturn eServiceMP3::gstGhostpadBufferAlloc(GstPad *pad, guint64 offset, guint size, GstCaps *caps, GstBuffer **buf) +{ + eServiceMP3 *_this = g_object_get_data (G_OBJECT (pad), "application-instance"); + + eDebug("eServiceMP3::gstGhostpadBufferAlloc prevcaps=%s newcaps=%s", gst_caps_to_string(_this->m_gst_prev_subtitle_caps), gst_caps_to_string(caps)); + if (!GST_PAD_CAPS (pad) || !gst_caps_is_equal (_this->m_gst_prev_subtitle_caps, caps)) + gstGhostpadLink (_this, caps); + + return _this->m_ghost_pad_buffer_alloc (pad, offset, size, caps, buf); +} + +void eServiceMP3::gstGhostpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data) +{ + GstCaps *caps; + eServiceMP3 *_this = (eServiceMP3*)user_data; + + g_object_get (G_OBJECT (pad), "caps", &caps, NULL); + eDebug("gstGhostpadHasCAPS:: signal::caps = %s", gst_caps_to_string(caps)); + + if (!caps) + return; + subtitleStream subs = _this->m_subtitleStreams[_this->m_currentSubtitleStream]; if ( subs.type == stUnknown ) { GstTagList *tags; - eDebug("gstCBsubtitleCAPS::m_subtitleStreams[%i].type == stUnknown...", _this->m_currentSubtitleStream); + eDebug("gstGhostpadHasCAPS::m_subtitleStreams[%i].type == stUnknown...", _this->m_currentSubtitleStream); gchar *g_lang; g_signal_emit_by_name (_this->m_gst_playbin, "get-text-tags", _this->m_currentSubtitleStream, &tags); @@ -1560,47 +1723,112 @@ void eServiceMP3::gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer us if ( tags && gst_is_tag_list(tags) ) gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); subs.language_code = std::string(g_lang); - - subs.type = getSubtitleType(GST_PAD(obj)); + GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); + subs.type = getSubtitleType(ghostpad); _this->m_subtitleStreams[_this->m_currentSubtitleStream] = subs; g_free (g_lang); } - gstCBsubtitleLink(subs.type, _this); + eDebug("gstGhostpadHasCAPS:: _this->m_gst_prev_subtitle_caps=%s equal=%i",gst_caps_to_string(_this->m_gst_prev_subtitle_caps),gst_caps_is_equal(_this->m_gst_prev_subtitle_caps, caps)); + + if (!GST_PAD_CAPS (pad) || !gst_caps_is_equal (_this->m_gst_prev_subtitle_caps, caps)) + gstGhostpadLink(_this, caps); + + _this->m_gst_prev_subtitle_caps = gst_caps_copy(caps); + gst_caps_unref (caps); } -void eServiceMP3::gstCBsubtitleLink(subtype_t type, gpointer user_data) +GstFlowReturn eServiceMP3::gstGhostpadChainFunction(GstPad * pad, GstBuffer * buffer) { - eServiceMP3 *_this = (eServiceMP3*)user_data; + GstFlowReturn ret = GST_FLOW_OK; - if ( type == stVOB ) - { - GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); - GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); - GstPad *subdecsinkpad = gst_element_get_static_pad (dvdsubdec, "sink"); - int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, subdecsinkpad); - GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); - ret += gst_element_link(dvdsubdec, appsink); - eDebug("gstCBsubtitleLink:: dvdsubdec=%p, subdecsinkpad=%p, ghostpad=%p, set target & link=%i", dvdsubdec, subdecsinkpad, ghostpad, ret); - } - else if ( type < stVOB && type > stUnknown ) - { - GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); - GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); - GstPad *appsinkpad = gst_element_get_static_pad (appsink, "sink"); - GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); - gst_element_unlink(dvdsubdec, appsink); - int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, appsinkpad); - eDebug("gstCBsubtitleLink:: appsink=%p, appsinkpad=%p, ghostpad=%p, set target=%i", appsink, appsinkpad, ghostpad, ret); - } - else - { - eDebug("gstCBsubtitleLink:: unsupported subtitles"); - } + eServiceMP3 *_this = g_object_get_data (G_OBJECT (pad), "application-instance"); + + gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); + gint64 duration_ns = GST_BUFFER_DURATION(buffer); + size_t len = GST_BUFFER_SIZE(buffer); + + unsigned char line[len+1]; + memcpy(line, GST_BUFFER_DATA(buffer), len); + line[len] = 0; + eDebug("gstGhostpadChainFunction buffer: '%s' caps: %s ", line, gst_caps_to_string(GST_BUFFER_CAPS(buffer))); + + ret = _this->m_ghost_pad_chain_function(pad, buffer); + eDebug("original chain func returns %i", ret); +// eDebug("original chain func not called. returning %i", ret); + return ret; } + +// void eServiceMP3::gstCBsubtitleLink(GObject *obj, GParamSpec *pspec, gpointer user_data) +// { +// +// eServiceMP3 *_this = (eServiceMP3*)user_data; +// eDebug("gstCBsubtitleCAPS:: m_currentSubtitleStream=%i, m_subtitleStreams.size()=%i", _this->m_currentSubtitleStream, _this->m_subtitleStreams.size()); +// +// if ( _this->m_currentSubtitleStream >= (int)_this->m_subtitleStreams.size() ) +// { +// eDebug("return invalid stream count"); +// return; +// } +// +// subtitleStream subs = _this->m_subtitleStreams[_this->m_currentSubtitleStream]; +// +// if ( subs.type == stUnknown ) +// { +// GstTagList *tags; +// eDebug("gstCBsubtitleCAPS::m_subtitleStreams[%i].type == stUnknown...", _this->m_currentSubtitleStream); +// +// gchar *g_lang; +// g_signal_emit_by_name (_this->m_gst_playbin, "get-text-tags", _this->m_currentSubtitleStream, &tags); +// +// g_lang = g_strdup_printf ("und"); +// if ( tags && gst_is_tag_list(tags) ) +// gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); +// subs.language_code = std::string(g_lang); +// +// subs.type = getSubtitleType(GST_PAD(obj)); +// +// _this->m_subtitleStreams[_this->m_currentSubtitleStream] = subs; +// +// g_free (g_lang); +// } +// +// gstCBsubtitleLink(subs.type, _this); +// } + +// void eServiceMP3::gstCBsubtitleLink(subtype_t type, gpointer user_data) +// { +// eServiceMP3 *_this = (eServiceMP3*)user_data; +// +// if ( type == stVOB ) +// { +// GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); +// GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); +// GstPad *subdecsinkpad = gst_element_get_static_pad (dvdsubdec, "sink"); +// int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, subdecsinkpad); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); +// ret += gst_element_link(dvdsubdec, appsink); +// eDebug("gstCBsubtitleLink:: dvdsubdec=%p, subdecsinkpad=%p, ghostpad=%p, set target & link=%i", dvdsubdec, subdecsinkpad, ghostpad, ret); +// } +// else if ( type < stVOB && type > stUnknown ) +// { +// GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); +// GstPad *appsinkpad = gst_element_get_static_pad (appsink, "sink"); +// GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); +// gst_element_unlink(dvdsubdec, appsink); +// int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, appsinkpad); +// eDebug("gstCBsubtitleLink:: appsink=%p, appsinkpad=%p, ghostpad=%p, set target=%i", appsink, appsinkpad, ghostpad, ret); +// } +// else +// { +// eDebug("gstCBsubtitleLink:: unsupported subtitles"); +// } +// } +/* gboolean eServiceMP3::gstCBsubtitleDrop(GstPad *pad, GstBuffer *buffer, gpointer user_data) { eDebug("gstCBsubtitleDrop"); @@ -1614,7 +1842,7 @@ gboolean eServiceMP3::gstCBsubtitleDrop(GstPad *pad, GstBuffer *buffer, gpointer line[len] = 0; eDebug("dropping buffer '%s' ", line); return false; -} +}*/ void eServiceMP3::pullSubtitle() @@ -1707,7 +1935,7 @@ void eServiceMP3::pushSubtitles() eDebug("eServiceMP3::pushSubtitles VOB show_pts = %lld running_pts = %lld diff = %lld", frontpage.vob_page->show_pts, running_pts, diff_ms); } - if ( diff_ms < -100 ) + if ( diff_ms < -9000 ) { GstFormat fmt = GST_FORMAT_TIME; gint64 now; @@ -1725,7 +1953,7 @@ void eServiceMP3::pushSubtitles() } else eDebug("query position for decoder/pipeline check failed!"); - eDebug("subtitle to late... drop"); + eDebug("subtitle too late... drop"); m_subtitle_pages.pop_front(); } else if ( diff_ms > 20 ) @@ -1767,7 +1995,7 @@ void eServiceMP3::hideSubtitles() RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) { - eDebug ("eServiceMP3::enableSubtitles m_currentSubtitleStream=%i",m_currentSubtitleStream); + eDebug ("eServiceMP3::enableSubtitles m_currentSubtitleStream=%i this=%p",m_currentSubtitleStream, this); ePyObject entry; int tuplesize = PyTuple_Size(tuple); int pid, type; @@ -1825,11 +2053,8 @@ RESULT eServiceMP3::disableSubtitles(eWidget *parent) { eDebug("eServiceMP3::disableSubtitles"); m_subtitle_pages.clear(); - eDebug("eServiceMP3::disableSubtitles cleared"); delete m_subtitle_widget; - eDebug("eServiceMP3::disableSubtitles deleted"); m_subtitle_widget = 0; - eDebug("eServiceMP3::disableSubtitles nulled"); return 0; } diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index 19d0af4d..7a5b152e 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -214,11 +214,23 @@ private: static GstBusSyncReply gstBusSyncHandler(GstBus *bus, GstMessage *message, gpointer user_data); static void gstCBsubtitleAvail(GstElement *element, gpointer user_data); static GstCaps* gstGhostpadGetCAPS (GstPad * pad); - static void gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer user_data); + static gboolean gstGhostpadAcceptCAPS(GstPad * pad, GstCaps * caps); + static void gstGhostpadLink(gpointer user_data, GstCaps * caps); + static GstFlowReturn gstGhostpadBufferAlloc(GstPad *pad, guint64 offset, guint size, GstCaps *caps, GstBuffer **buf); + static void gstGhostpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data); + static gboolean gstGhostpadSinkEvent(GstPad * pad, GstEvent * event); + static GstFlowReturn gstGhostpadChainFunction(GstPad * pad, GstBuffer * buffer); +/* static void gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer user_data); static void gstCBsubtitleLink(subtype_t type, gpointer user_data); - static gboolean gstCBsubtitleDrop(GstPad *pad, GstBuffer *buffer, gpointer user_data); + static gboolean gstCBsubtitleDrop(GstPad *pad, GstBuffer *buffer, gpointer user_data);*/ void gstPoll(const int&); - + GstPadBufferAllocFunction m_ghost_pad_buffer_alloc; + GstPadChainFunction m_ghost_pad_chain_function; + GstPadEventFunction m_ghost_pad_subtitle_sink_event; + GstCaps *m_gst_prev_subtitle_caps; + GstSegment m_gst_subtitle_segment; + GstPadEventFunction m_gst_sink_event; + std::list m_subtitle_pages; ePtr m_subtitle_sync_timer; ePtr m_subtitle_hide_timer; -- cgit v1.2.3 From c443b776e07c18301f9c7d05b80741e6a6aea681 Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Tue, 6 Jul 2010 12:47:53 +0200 Subject: fix playback of containers with PGS subpicture streams (by ignoring them) --- lib/service/servicemp3.cpp | 18 +++++++++++++----- lib/service/servicemp3.h | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index 1aa3b5b5..5cccbaea 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -21,7 +21,9 @@ #include #include -static GstStaticPadTemplate subsinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS("text/plain; text/x-pango-markup; video/x-dvd-subpicture")); +static GstStaticPadTemplate subsinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS("text/plain; text/x-pango-markup; video/x-dvd-subpicture; subpicture/x-pgs")); +// int ret = gst_pad_set_caps (ghostpad, caps2); +// gst_caps_unref(caps2);)); // eServiceFactoryMP3 @@ -350,7 +352,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref) GstPad *ghostpad = gst_ghost_pad_new_no_target_from_template("sink", templ); gst_element_add_pad (m_gst_subtitlebin, ghostpad); - GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-raw-rgb"); + GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-raw-rgb; subpicture/x-pgs"); g_object_set (G_OBJECT (appsink), "caps", caps, NULL); gst_caps_unref(caps); @@ -1160,6 +1162,8 @@ subtype_t getSubtitleType(GstPad* pad, gchar *g_codec=NULL) type = stSSA; else if ( !strcmp(g_type, "text/plain") ) type = stPlainText; + else if ( !strcmp(g_type, "subpicture/x-pgs") ) + type = stPGS; else eDebug("getSubtitleType::unsupported subtitle caps %s (%s)", g_type, g_codec); } @@ -1537,7 +1541,7 @@ void eServiceMP3::gstCBsubtitleAvail(GstElement *appsink, gpointer user_data) gboolean eServiceMP3::gstGhostpadSinkEvent(GstPad * pad, GstEvent * event) { - eDebug("eServiceMP3::gstGhostpadSinkEvent %s", gst_structure_get_name (event->structure)); +// eDebug("eServiceMP3::gstGhostpadSinkEvent %s", gst_structure_get_name (event->structure)); // eServiceMP3 *_this = (eServiceMP3*) (gst_pad_get_parent (pad)); eServiceMP3 *_this = g_object_get_data (G_OBJECT (pad), "application-instance"); @@ -1603,7 +1607,7 @@ gboolean eServiceMP3::gstGhostpadSinkEvent(GstPad * pad, GstEvent * event) } ret = _this->m_ghost_pad_subtitle_sink_event (pad, gst_event_ref (event)); -eDebug("original EVENTFUNC returned %i", ret); +// eDebug("original EVENTFUNC returned %i", ret); if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) { gboolean update; @@ -1886,7 +1890,7 @@ void eServiceMP3::pullSubtitle() m_subtitle_pages.push_back(subtitlepage); pushSubtitles(); } - else + else if ( m_subtitleStreams[m_currentSubtitleStream].type == stVOB ) { eDebug("got new subpicture @ buf_pos = %lld ns (in pts=%lld), duration=%lld ns, len=%i bytes. ", buf_pos, buf_pos/11111, duration_ns, len); eVobSubtitlePage* page = new eVobSubtitlePage; @@ -1903,6 +1907,10 @@ void eServiceMP3::pullSubtitle() m_subtitle_pages.push_back(subtitlepage); pushSubtitles(); } + else + { + eDebug("unsupported subpicture... ignoring"); + } } gst_buffer_unref(buffer); } diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index 7a5b152e..4057f022 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -47,7 +47,7 @@ public: typedef struct _GstElement GstElement; typedef enum { atUnknown, atMPEG, atMP3, atAC3, atDTS, atAAC, atPCM, atOGG, atFLAC } audiotype_t; -typedef enum { stUnknown, stPlainText, stSSA, stASS, stSRT, stVOB } subtype_t; +typedef enum { stUnknown, stPlainText, stSSA, stASS, stSRT, stVOB, stPGS } subtype_t; typedef enum { ctNone, ctMPEGTS, ctMPEGPS, ctMKV, ctAVI, ctMP4, ctVCD, ctCDA } containertype_t; struct SubtitlePage -- cgit v1.2.3 From da583812c4b20dcf72b69415d65dc1398fd849ce Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Mon, 26 Jul 2010 12:30:11 +0200 Subject: add experimental vobsub support (requires gst-plugin-dvdsub) / ignore PGS subs (fixes #537) --- lib/gui/esubtitle.h | 8 + lib/python/Screens/AudioSelection.py | 15 +- lib/service/servicemp3.cpp | 654 ++++++++++++++++++++++++++++++----- lib/service/servicemp3.h | 33 +- 4 files changed, 611 insertions(+), 99 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/lib/gui/esubtitle.h b/lib/gui/esubtitle.h index 45345db1..2b0ec8ff 100644 --- a/lib/gui/esubtitle.h +++ b/lib/gui/esubtitle.h @@ -29,9 +29,17 @@ struct ePangoSubtitlePage void clear() { m_elements.clear(); } }; +struct eVobSubtitlePage +{ + pts_t show_pts; + int m_timeout; /* in milliseconds */ + ePtr m_pixmap; +}; + class eDVBTeletextSubtitlePage; class eDVBPangoSubtitlePage; class ePangoSubtitlePage; +class eVobSubtitlePage; class eSubtitleWidget: public eWidget, public Object { diff --git a/lib/python/Screens/AudioSelection.py b/lib/python/Screens/AudioSelection.py index a0bfcab9..068da870 100644 --- a/lib/python/Screens/AudioSelection.py +++ b/lib/python/Screens/AudioSelection.py @@ -46,7 +46,7 @@ class AudioSelection(Screen, ConfigListScreen): "cancel": self.cancel, "up": self.keyUp, "down": self.keyDown, - }, -3) + }, -2) self.settings = ConfigSubsection() choicelist = [(PAGE_AUDIO,_("audio tracks")), (PAGE_SUBTITLES,_("Subtitles"))] @@ -62,13 +62,12 @@ class AudioSelection(Screen, ConfigListScreen): streams = [] conflist = [] selectedidx = 0 - - service = self.session.nav.getCurrentService() - self.audioTracks = audio = service and service.audioTracks() - n = audio and audio.getNumberOfTracks() or 0 - + if self.settings.menupage.getValue() == PAGE_AUDIO: self.setTitle(_("Select audio track")) + service = self.session.nav.getCurrentService() + self.audioTracks = audio = service and service.audioTracks() + n = audio and audio.getNumberOfTracks() or 0 if SystemInfo["CanDownmixAC3"]: self.settings.downmix = ConfigOnOff(default=config.av.downmix_ac3.value) self.settings.downmix.addNotifier(self.changeAC3Downmix, initial_call = False) @@ -156,7 +155,7 @@ class AudioSelection(Screen, ConfigListScreen): number = "%x%02x" % (x[3],x[2]) elif x[0] == 2: - types = ("UTF-8 text","SSA / AAS",".SRT file") + types = (_(""), "UTF-8 text", "SSA", "AAS", ".SRT file", "VOB", "PGS (unsupported)") description = types[x[2]] streams.append((x, "", number, description, language, selected)) @@ -185,7 +184,7 @@ class AudioSelection(Screen, ConfigListScreen): conflist.append(getConfigListEntry(Plugins[0][0], ConfigNothing())) self.plugincallfunc = Plugins[0][1] if len(Plugins) > 1: - print "these plugins are installed but not displayed in the dialog box:", Plugins[1:] + print "plugin(s) installed but not displayed in the dialog box:", Plugins[1:] self["config"].list = conflist self["config"].l.setList(conflist) diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index 9c24d4bb..5fe15c1e 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -21,6 +22,9 @@ #include #define HTTP_TIMEOUT 10 +static GstStaticPadTemplate subsinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS("text/plain; text/x-pango-markup; video/x-dvd-subpicture; subpicture/x-pgs")); +// int ret = gst_pad_set_caps (ghostpad, caps2); +// gst_caps_unref(caps2);)); // eServiceFactoryMP3 @@ -221,6 +225,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref) m_seekTimeout = eTimer::create(eApp); m_subtitle_sync_timer = eTimer::create(eApp); m_streamingsrc_timeout = 0; + m_subtitle_hide_timer = eTimer::create(eApp); m_stream_tags = 0; m_currentAudioStream = -1; m_currentSubtitleStream = 0; @@ -230,6 +235,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref) m_buffer_size = 1*1024*1024; CONNECT(m_seekTimeout->timeout, eServiceMP3::seekTimeoutCB); CONNECT(m_subtitle_sync_timer->timeout, eServiceMP3::pushSubtitles); + CONNECT(m_subtitle_hide_timer->timeout, eServiceMP3::hideSubtitles); CONNECT(m_pump.recv_msg, eServiceMP3::gstPoll); m_aspect = m_width = m_height = m_framerate = m_progressive = -1; @@ -335,18 +341,64 @@ eServiceMP3::eServiceMP3(eServiceReference ref) g_free(uri); - GstElement *subsink = gst_element_factory_make("appsink", "subtitle_sink"); - if (!subsink) - eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-appsink"); - else - { - m_subs_to_pull_handler_id = g_signal_connect (subsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); - g_object_set (G_OBJECT (subsink), "caps", gst_caps_from_string("text/plain; text/x-plain; text/x-pango-markup"), NULL); - g_object_set (G_OBJECT (m_gst_playbin), "text-sink", subsink, NULL); - } - + m_gst_subtitlebin = gst_bin_new("subtitle_bin"); + if ( m_gst_playbin ) { + GstElement *appsink = gst_element_factory_make("appsink", "subtitle_sink"); + + if (!appsink) + eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-appsink"); + + GstElement *dvdsubdec = gst_element_factory_make("dvdsubdec", "vobsubtitle_decoder"); + if ( dvdsubdec ) + { + gst_bin_add_many(GST_BIN(m_gst_subtitlebin), dvdsubdec, appsink, NULL); + g_object_set (G_OBJECT (dvdsubdec), "singlebuffer", TRUE, NULL); + } + else + { + eDebug("eServiceMP3::missing gst-plugin-dvdsub, no vob subtitle support!"); + gst_bin_add(GST_BIN(m_gst_subtitlebin), appsink); + } + +// GstPad *ghostpad = gst_ghost_pad_new("sink", gst_element_get_static_pad (appsink, "sink")); + + GstPadTemplate *templ; + templ = gst_static_pad_template_get (&subsinktemplate); + + GstPad *ghostpad = gst_ghost_pad_new_no_target_from_template("sink", templ); + gst_element_add_pad (m_gst_subtitlebin, ghostpad); + + GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-raw-rgb; subpicture/x-pgs"); + g_object_set (G_OBJECT (appsink), "caps", caps, NULL); + gst_caps_unref(caps); + +// GstCaps* caps2 = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-dvd-subpicture"); +// int ret = gst_pad_set_caps (ghostpad, caps2); +// gst_caps_unref(caps2); + + + g_object_set (G_OBJECT (appsink), "async", FALSE, NULL); + g_object_set (G_OBJECT (appsink), "sync", TRUE, NULL); + g_object_set (G_OBJECT (appsink), "emit-signals", TRUE, NULL); + g_object_set (G_OBJECT (appsink), "ts-offset", 0 * GST_SECOND, NULL); + + g_object_set_data (G_OBJECT (ghostpad), "application-instance", this); + g_signal_connect (G_OBJECT (ghostpad), "notify::caps", G_CALLBACK (gstGhostpadHasCAPS), this); + gst_pad_set_getcaps_function (ghostpad, gstGhostpadGetCAPS); + gst_pad_set_acceptcaps_function (ghostpad, gstGhostpadAcceptCAPS); + m_ghost_pad_buffer_alloc = GST_PAD_BUFFERALLOCFUNC(ghostpad); + m_ghost_pad_chain_function = GST_PAD_CHAINFUNC(ghostpad); + m_ghost_pad_subtitle_sink_event = GST_PAD_EVENTFUNC(ghostpad); + gst_pad_set_bufferalloc_function (ghostpad, GST_DEBUG_FUNCPTR(gstGhostpadBufferAlloc)); + gst_pad_set_event_function (ghostpad, GST_DEBUG_FUNCPTR(gstGhostpadSinkEvent)); + gst_pad_set_chain_function (ghostpad, GST_DEBUG_FUNCPTR(gstGhostpadChainFunction)); + m_gst_prev_subtitle_caps = gst_caps_new_empty(); + + g_object_set (G_OBJECT (m_gst_playbin), "text-sink", m_gst_subtitlebin, NULL); + m_subs_to_pull_handler_id = g_signal_connect (appsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); + gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)), gstBusSyncHandler, this); char srt_filename[strlen(filename)+1]; strncpy(srt_filename,filename,strlen(filename)-3); @@ -383,15 +435,17 @@ eServiceMP3::eServiceMP3(eServiceReference ref) eServiceMP3::~eServiceMP3() { // disconnect subtitle callback - GstElement *sink; - g_object_get (G_OBJECT (m_gst_playbin), "text-sink", &sink, NULL); - if (sink) + GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); + + if (appsink) { - g_signal_handler_disconnect (sink, m_subs_to_pull_handler_id); - gst_object_unref(sink); + g_signal_handler_disconnect (appsink, m_subs_to_pull_handler_id); + gst_object_unref(appsink); } delete m_subtitle_widget; + gst_caps_unref(this->m_gst_prev_subtitle_caps); // disconnect sync handler callback gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)), NULL, NULL); @@ -445,6 +499,8 @@ RESULT eServiceMP3::stop() if (m_state == stStopped) return -1; + + //GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_gst_playbin),GST_DEBUG_GRAPH_SHOW_ALL,"e2-playbin"); eDebug("eServiceMP3::stop %s", m_ref.path.c_str()); gst_element_set_state(m_gst_playbin, GST_STATE_NULL); @@ -672,6 +728,7 @@ RESULT eServiceMP3::getPlayPosition(pts_t &pts) /* pos is in nanoseconds. we have 90 000 pts per second. */ pts = pos / 11111; +// eDebug("gst_element_query_position %lld pts (%lld ms)", pts, pos/1000000); return 0; } @@ -1114,6 +1171,48 @@ RESULT eServiceMP3::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i) return 0; } +subtype_t getSubtitleType(GstPad* pad, gchar *g_codec=NULL) +{ + subtype_t type = stUnknown; + GstCaps* caps = gst_pad_get_negotiated_caps(pad); + + if ( caps ) + { + GstStructure* str = gst_caps_get_structure(caps, 0); + const gchar *g_type = gst_structure_get_name(str); + eDebug("getSubtitleType::subtitle probe caps type=%s", g_type); + + if ( !strcmp(g_type, "video/x-dvd-subpicture") ) + type = stVOB; + else if ( !strcmp(g_type, "text/x-pango-markup") ) + type = stSSA; + else if ( !strcmp(g_type, "text/plain") ) + type = stPlainText; + else if ( !strcmp(g_type, "subpicture/x-pgs") ) + type = stPGS; + else + eDebug("getSubtitleType::unsupported subtitle caps %s (%s)", g_type, g_codec); + } + else if ( g_codec ) + { + eDebug("getSubtitleType::subtitle probe codec tag=%s", g_codec); + if ( !strcmp(g_codec, "VOB") ) + type = stVOB; + else if ( !strcmp(g_codec, "SubStation Alpha") || !strcmp(g_codec, "SSA") ) + type = stSSA; + else if ( !strcmp(g_codec, "ASS") ) + type = stASS; + else if ( !strcmp(g_codec, "UTF-8 plain text") ) + type = stPlainText; + else + eDebug("getSubtitleType::unsupported subtitle codec %s", g_codec); + } + else + eDebug("getSubtitleType::unidentifiable subtitle stream!"); + + return type; +} + void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) { if (!msg) @@ -1160,16 +1259,16 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) } break; case GST_STATE_CHANGE_READY_TO_PAUSED: { - GstElement *sink; - g_object_get (G_OBJECT (m_gst_playbin), "text-sink", &sink, NULL); - if (sink) - { - g_object_set (G_OBJECT (sink), "max-buffers", 2, NULL); - g_object_set (G_OBJECT (sink), "sync", FALSE, NULL); - g_object_set (G_OBJECT (sink), "async", FALSE, NULL); - g_object_set (G_OBJECT (sink), "emit-signals", TRUE, NULL); - gst_object_unref(sink); - } +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); +// if (appsink) +// { +// g_object_set (G_OBJECT (appsink), "max-buffers", 2, NULL); +// g_object_set (G_OBJECT (appsink), "sync", FALSE, NULL); +// g_object_set (G_OBJECT (appsink), "emit-signals", TRUE, NULL); +// eDebug("eServiceMP3::appsink properties set!"); +// gst_object_unref(appsink); +// } setAC3Delay(ac3_delay); setPCMDelay(pcm_delay); } break; @@ -1307,25 +1406,30 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) } for (i = 0; i < n_text; i++) - { - gchar *g_lang; -// gchar *g_type; -// GstPad* pad = 0; -// g_signal_emit_by_name (m_gst_playbin, "get-text-pad", i, &pad); -// GstCaps* caps = gst_pad_get_negotiated_caps(pad); -// GstStructure* str = gst_caps_get_structure(caps, 0); -// g_type = gst_structure_get_name(str); -// g_signal_emit_by_name (m_gst_playbin, "get-text-tags", i, &tags); + { + gchar *g_codec = NULL, *g_lang = NULL; + g_signal_emit_by_name (m_gst_playbin, "get-text-tags", i, &tags); subtitleStream subs; - subs.type = stPlainText; + int ret; + g_lang = g_strdup_printf ("und"); if ( tags && gst_is_tag_list(tags) ) + { gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); + gst_tag_list_get_string(tags, GST_TAG_SUBTITLE_CODEC, &g_codec); + gst_tag_list_free(tags); + } + subs.language_code = std::string(g_lang); - eDebug("eServiceMP3::subtitle stream=%i language=%s"/* type=%s*/, i, g_lang/*, g_type*/); + eDebug("eServiceMP3::subtitle stream=%i language=%s codec=%s", i, g_lang, g_codec); + + GstPad* pad = 0; + g_signal_emit_by_name (m_gst_playbin, "get-text-pad", i, &pad); + if ( subs.type != stSRT ) + subs.type = getSubtitleType(pad, g_codec); + m_subtitleStreams.push_back(subs); g_free (g_lang); -// g_free (g_type); } m_event((iPlayableService*)this, evUpdatedEventInfo); break; @@ -1499,17 +1603,327 @@ eAutoInitPtr init_eServiceFactoryMP3(eAutoInitNumbers::servi void eServiceMP3::gstCBsubtitleAvail(GstElement *appsink, gpointer user_data) { - eServiceMP3 *_this = (eServiceMP3*)user_data; + eServiceMP3 *_this = (eServiceMP3*)user_data; eSingleLocker l(_this->m_subs_to_pull_lock); ++_this->m_subs_to_pull; _this->m_pump.send(2); } +gboolean eServiceMP3::gstGhostpadSinkEvent(GstPad * pad, GstEvent * event) +{ +// eDebug("eServiceMP3::gstGhostpadSinkEvent %s", gst_structure_get_name (event->structure)); + +// eServiceMP3 *_this = (eServiceMP3*) (gst_pad_get_parent (pad)); + eServiceMP3 *_this = g_object_get_data (G_OBJECT (pad), "application-instance"); + gboolean ret; + GstFormat format; + + if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB && event->structure && strcmp (gst_structure_get_name (event->structure), "subtitleoverlay-flush-subtitle") == 0) + { + eDebug ("Custom subtitle flush event"); +// GST_SUBTITLE_OVERLAY_LOCK (self); +// self->subtitle_flush = TRUE; +// self->subtitle_error = FALSE; +// if (self->subtitle_block_pad) +// gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE, +// _pad_blocked_cb, gst_object_ref (self), +// (GDestroyNotify) gst_object_unref); +// if (self->video_block_pad) +// gst_pad_set_blocked_async_full (self->video_block_pad, TRUE, +// _pad_blocked_cb, gst_object_ref (self), +// (GDestroyNotify) gst_object_unref); +// GST_SUBTITLE_OVERLAY_UNLOCK (self); +// + gst_event_unref (event); + event = NULL; + ret = TRUE; + goto out; + } else if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) + { + gst_event_parse_new_segment_full (event, NULL, NULL, NULL, &format, NULL, NULL, NULL); + if (_this->m_gst_subtitle_segment.format != GST_FORMAT_UNDEFINED && _this->m_gst_subtitle_segment.format != format) + { + eDebug("Subtitle segment format changed: %s -> %s", gst_format_get_name(_this->m_gst_subtitle_segment.format), gst_format_get_name(format)); + gst_segment_init (&_this->m_gst_subtitle_segment, GST_FORMAT_UNDEFINED); + } + } + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + eDebug("Resetting subtitle segment because of flush-stop"); + gst_segment_init (&_this->m_gst_subtitle_segment, GST_FORMAT_UNDEFINED); + /* fall through */ + case GST_EVENT_FLUSH_START: + case GST_EVENT_NEWSEGMENT: + case GST_EVENT_EOS: +// eDebug("GST_EVENT_FLUSH_START GST_EVENT_NEWSEGMENT GST_EVENT_EOS"); + /* Add our event marker to make sure no events from here go ever outside + * the element, they're only interesting for our internal elements */ +// event = +// GST_EVENT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST +// (event))); +// if (!event->structure) { +// event->structure = +// gst_structure_id_empty_new (_subtitle_overlay_event_marker_id); +// gst_structure_set_parent_refcount (event->structure, +// &event->mini_object.refcount); +// } +// gst_structure_id_set (event->structure, _subtitle_overlay_event_marker_id, +// G_TYPE_BOOLEAN, TRUE, NULL); + break; + default: + eDebug("GST_EVENT_TYPE other: %i", GST_EVENT_TYPE (event)); + break; + } + + ret = _this->m_ghost_pad_subtitle_sink_event (pad, gst_event_ref (event)); +// eDebug("original EVENTFUNC returned %i", ret); + + if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) { + gboolean update; + gdouble rate, applied_rate; + gint64 start, stop, position; + + GST_DEBUG_OBJECT (pad, "Newsegment event: %" GST_PTR_FORMAT, + event->structure); + gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, + &format, &start, &stop, &position); + + GST_DEBUG_OBJECT (pad, "Old subtitle segment: %" GST_SEGMENT_FORMAT, + &_this->m_gst_subtitle_segment); + if (_this->m_gst_subtitle_segment.format != format) { + GST_DEBUG_OBJECT (pad, "Subtitle segment format changed: %s -> %s", + gst_format_get_name (_this->m_gst_subtitle_segment.format), + gst_format_get_name (format)); + gst_segment_init (&_this->m_gst_subtitle_segment, format); + } + + gst_segment_set_newsegment_full (&_this->m_gst_subtitle_segment, update, rate, + applied_rate, format, start, stop, position); + GST_DEBUG_OBJECT (pad, "New subtitle segment: %" GST_SEGMENT_FORMAT, + &_this->m_gst_subtitle_segment); + } + gst_event_unref (event); +// +out: +// gst_object_unref (_this); + return ret; +} + +GstCaps* eServiceMP3::gstGhostpadGetCAPS(GstPad * pad) +{ +// eDebug("eServiceMP3::gstGhostpadGetCAPS"); + return gst_static_pad_template_get_caps(&subsinktemplate); +} + +gboolean eServiceMP3::gstGhostpadAcceptCAPS(GstPad * pad, GstCaps * caps) +{ + GstCaps *templ_caps = gst_static_pad_template_get_caps (&subsinktemplate); + gboolean ret = gst_caps_can_intersect (templ_caps, caps); + +// eDebug("gstGhostpadAcceptCAPS templ=%s, given=%s ret=%i", gst_caps_to_string(templ_caps), gst_caps_to_string(caps), ret); + gst_caps_unref (templ_caps); + + return ret; +} + +void eServiceMP3::gstGhostpadLink(gpointer user_data, GstCaps * caps) +{ + GstStructure *s; + GstPad *sinkpad; + eServiceMP3 *_this = (eServiceMP3*)user_data; + + // FIXME: Need to cache events from the ghostpad and pass them forward + // now... and keep track of the segment and pass newsegment events + // downstream. + s = gst_caps_get_structure (caps, 0); + + GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); + GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); + GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); + + gst_ghost_pad_set_target(GST_GHOST_PAD(ghostpad), NULL); + gst_element_unlink(dvdsubdec, appsink); + int ret = -1; + + if ( gst_structure_has_name (s, "video/x-dvd-subpicture") && dvdsubdec ) + { + sinkpad = gst_element_get_static_pad (dvdsubdec, "sink"); + ret = gst_element_link_pads (dvdsubdec, "src", appsink, "sink"); +// eDebug("gstGhostpadLink:: dvdsubdec+appsink = %i", ret); + } + else + { + sinkpad = gst_element_get_static_pad (appsink, "sink"); +// eDebug("gstGhostpadLink:: appsink"); + } + + gst_ghost_pad_set_target (GST_GHOST_PAD(ghostpad), sinkpad); +} + +GstFlowReturn eServiceMP3::gstGhostpadBufferAlloc(GstPad *pad, guint64 offset, guint size, GstCaps *caps, GstBuffer **buf) +{ + eServiceMP3 *_this = g_object_get_data (G_OBJECT (pad), "application-instance"); + +// eDebug("eServiceMP3::gstGhostpadBufferAlloc prevcaps=%s newcaps=%s", gst_caps_to_string(_this->m_gst_prev_subtitle_caps), gst_caps_to_string(caps)); + if (!GST_PAD_CAPS (pad) || !gst_caps_is_equal (_this->m_gst_prev_subtitle_caps, caps)) + gstGhostpadLink (_this, caps); + + return _this->m_ghost_pad_buffer_alloc (pad, offset, size, caps, buf); +} + +void eServiceMP3::gstGhostpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data) +{ + GstCaps *caps; + eServiceMP3 *_this = (eServiceMP3*)user_data; + + g_object_get (G_OBJECT (pad), "caps", &caps, NULL); +// eDebug("gstGhostpadHasCAPS:: signal::caps = %s", gst_caps_to_string(caps)); + + if (!caps) + return; + + subtitleStream subs = _this->m_subtitleStreams[_this->m_currentSubtitleStream]; + + if ( subs.type == stUnknown ) + { + GstTagList *tags; +// eDebug("gstGhostpadHasCAPS::m_subtitleStreams[%i].type == stUnknown...", _this->m_currentSubtitleStream); + + gchar *g_lang; + g_signal_emit_by_name (_this->m_gst_playbin, "get-text-tags", _this->m_currentSubtitleStream, &tags); + + g_lang = g_strdup_printf ("und"); + if ( tags && gst_is_tag_list(tags) ) + gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); + subs.language_code = std::string(g_lang); + GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); + subs.type = getSubtitleType(ghostpad); + + _this->m_subtitleStreams[_this->m_currentSubtitleStream] = subs; + + g_free (g_lang); + } + +// eDebug("gstGhostpadHasCAPS:: _this->m_gst_prev_subtitle_caps=%s equal=%i",gst_caps_to_string(_this->m_gst_prev_subtitle_caps),gst_caps_is_equal(_this->m_gst_prev_subtitle_caps, caps)); + + if (!GST_PAD_CAPS (pad) || !gst_caps_is_equal (_this->m_gst_prev_subtitle_caps, caps)) + gstGhostpadLink(_this, caps); + + _this->m_gst_prev_subtitle_caps = gst_caps_copy(caps); + gst_caps_unref (caps); +} + +GstFlowReturn eServiceMP3::gstGhostpadChainFunction(GstPad * pad, GstBuffer * buffer) +{ + GstFlowReturn ret = GST_FLOW_OK; + + eServiceMP3 *_this = g_object_get_data (G_OBJECT (pad), "application-instance"); + + gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); + gint64 duration_ns = GST_BUFFER_DURATION(buffer); + size_t len = GST_BUFFER_SIZE(buffer); + + unsigned char line[len+1]; + memcpy(line, GST_BUFFER_DATA(buffer), len); + line[len] = 0; +// eDebug("gstGhostpadChainFunction buffer: '%s' caps: %s ", line, gst_caps_to_string(GST_BUFFER_CAPS(buffer))); + + ret = _this->m_ghost_pad_chain_function(pad, buffer); +// eDebug("original chain func returns %i", ret); + return ret; +} + + +// void eServiceMP3::gstCBsubtitleLink(GObject *obj, GParamSpec *pspec, gpointer user_data) +// { +// +// eServiceMP3 *_this = (eServiceMP3*)user_data; +// eDebug("gstCBsubtitleCAPS:: m_currentSubtitleStream=%i, m_subtitleStreams.size()=%i", _this->m_currentSubtitleStream, _this->m_subtitleStreams.size()); +// +// if ( _this->m_currentSubtitleStream >= (int)_this->m_subtitleStreams.size() ) +// { +// eDebug("return invalid stream count"); +// return; +// } +// +// subtitleStream subs = _this->m_subtitleStreams[_this->m_currentSubtitleStream]; +// +// if ( subs.type == stUnknown ) +// { +// GstTagList *tags; +// eDebug("gstCBsubtitleCAPS::m_subtitleStreams[%i].type == stUnknown...", _this->m_currentSubtitleStream); +// +// gchar *g_lang; +// g_signal_emit_by_name (_this->m_gst_playbin, "get-text-tags", _this->m_currentSubtitleStream, &tags); +// +// g_lang = g_strdup_printf ("und"); +// if ( tags && gst_is_tag_list(tags) ) +// gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); +// subs.language_code = std::string(g_lang); +// +// subs.type = getSubtitleType(GST_PAD(obj)); +// +// _this->m_subtitleStreams[_this->m_currentSubtitleStream] = subs; +// +// g_free (g_lang); +// } +// +// gstCBsubtitleLink(subs.type, _this); +// } + +// void eServiceMP3::gstCBsubtitleLink(subtype_t type, gpointer user_data) +// { +// eServiceMP3 *_this = (eServiceMP3*)user_data; +// +// if ( type == stVOB ) +// { +// GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); +// GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); +// GstPad *subdecsinkpad = gst_element_get_static_pad (dvdsubdec, "sink"); +// int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, subdecsinkpad); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); +// ret += gst_element_link(dvdsubdec, appsink); +// eDebug("gstCBsubtitleLink:: dvdsubdec=%p, subdecsinkpad=%p, ghostpad=%p, set target & link=%i", dvdsubdec, subdecsinkpad, ghostpad, ret); +// } +// else if ( type < stVOB && type > stUnknown ) +// { +// GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); +// GstPad *appsinkpad = gst_element_get_static_pad (appsink, "sink"); +// GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); +// gst_element_unlink(dvdsubdec, appsink); +// int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, appsinkpad); +// eDebug("gstCBsubtitleLink:: appsink=%p, appsinkpad=%p, ghostpad=%p, set target=%i", appsink, appsinkpad, ghostpad, ret); +// } +// else +// { +// eDebug("gstCBsubtitleLink:: unsupported subtitles"); +// } +// } +/* +gboolean eServiceMP3::gstCBsubtitleDrop(GstPad *pad, GstBuffer *buffer, gpointer user_data) +{ + eDebug("gstCBsubtitleDrop"); + + gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); + gint64 duration_ns = GST_BUFFER_DURATION(buffer); + size_t len = GST_BUFFER_SIZE(buffer); + + unsigned char line[len+1]; + memcpy(line, GST_BUFFER_DATA(buffer), len); + line[len] = 0; + eDebug("dropping buffer '%s' ", line); + return false; +}*/ + + void eServiceMP3::pullSubtitle() { - GstElement *sink; - g_object_get (G_OBJECT (m_gst_playbin), "text-sink", &sink, NULL); - if (sink) + GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); +// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); + + if (appsink) { while (m_subs_to_pull && m_subtitle_pages.size() < 2) { @@ -1517,28 +1931,60 @@ 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 (appsink, "pull-buffer", &buffer); } if (buffer) { gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); gint64 duration_ns = GST_BUFFER_DURATION(buffer); size_t len = GST_BUFFER_SIZE(buffer); - 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); - ePangoSubtitlePage page; - gRGB rgbcol(0xD0,0xD0,0xD0); - page.m_elements.push_back(ePangoSubtitlePageElement(rgbcol, (const char*)line)); - page.show_pts = buf_pos / 11111L; - page.m_timeout = duration_ns / 1000000; - m_subtitle_pages.push_back(page); - pushSubtitles(); + eDebug("pullSubtitle m_subtitleStreams[m_currentSubtitleStream].type=%i",m_subtitleStreams[m_currentSubtitleStream].type); + + if ( m_subtitleStreams[m_currentSubtitleStream].type ) + { + if ( m_subtitleStreams[m_currentSubtitleStream].type < stVOB ) + { + unsigned char line[len+1]; + memcpy(line, GST_BUFFER_DATA(buffer), len); + line[len] = 0; + eDebug("got new text subtitle @ buf_pos = %lld ns (in pts=%lld): '%s' ", buf_pos, buf_pos/11111, line); + ePangoSubtitlePage* page = new ePangoSubtitlePage; + gRGB rgbcol(0xD0,0xD0,0xD0); + page->m_elements.push_back(ePangoSubtitlePageElement(rgbcol, (const char*)line)); + page->show_pts = buf_pos / 11111L; + page->m_timeout = duration_ns / 1000000; + SubtitlePage subtitlepage; + subtitlepage.pango_page = page; + subtitlepage.vob_page = NULL; + m_subtitle_pages.push_back(subtitlepage); + pushSubtitles(); + } + else if ( m_subtitleStreams[m_currentSubtitleStream].type == stVOB ) + { + eDebug("got new subpicture @ buf_pos = %lld ns (in pts=%lld), duration=%lld ns, len=%i bytes. ", buf_pos, buf_pos/11111, duration_ns, len); + eVobSubtitlePage* page = new eVobSubtitlePage; + eSize size = eSize(720, 576); + page->m_pixmap = new gPixmap(size, 32, 0); + // ePtr pixmap; + // pixmap = new gPixmap(size, 32, 1); /* allocate accel surface (if possible) */ + memcpy(page->m_pixmap->surface->data, GST_BUFFER_DATA(buffer), len); + page->show_pts = buf_pos / 11111L; + page->m_timeout = duration_ns / 1000; + SubtitlePage subtitlepage; + subtitlepage.vob_page = page; + subtitlepage.pango_page = NULL; + m_subtitle_pages.push_back(subtitlepage); + pushSubtitles(); + } + else + { + eDebug("unsupported subpicture... ignoring"); + } + } gst_buffer_unref(buffer); } } - gst_object_unref(sink); + gst_object_unref(appsink); } else eDebug("no subtitle sink!"); @@ -1546,45 +1992,65 @@ void eServiceMP3::pullSubtitle() void eServiceMP3::pushSubtitles() { - ePangoSubtitlePage page; pts_t running_pts; while ( !m_subtitle_pages.empty() ) { + SubtitlePage frontpage = m_subtitle_pages.front(); + gint64 diff_ms = 0; + gint64 show_pts = 0; + getPlayPosition(running_pts); - page = m_subtitle_pages.front(); - gint64 diff_ms = ( page.show_pts - running_pts ) / 90; - eDebug("eServiceMP3::pushSubtitles show_pts = %lld running_pts = %lld diff = %lld", page.show_pts, running_pts, diff_ms); - if (diff_ms < -100) + + if ( frontpage.pango_page != 0 ) + show_pts = frontpage.pango_page->show_pts; + else if ( frontpage.vob_page != 0 ) + show_pts = frontpage.vob_page->show_pts; + + diff_ms = ( show_pts - running_pts ) / 90; + GstFormat fmt = GST_FORMAT_TIME; + gint64 now; + if ( gst_element_query_position(m_gst_playbin, &fmt, &now) != -1 ) + eDebug("check decoder/pipeline diff: decoder: %lld, pipeline: %lld, show_pts: %lld, diff: %lld ms", running_pts/90, now/1000000, show_pts/90, diff_ms); + else + eDebug("query position for decoder/pipeline check failed!"); + + if ( diff_ms < -100 ) { - GstFormat fmt = GST_FORMAT_TIME; - gint64 now; - if (gst_element_query_position(m_gst_playbin, &fmt, &now) != -1) + now /= 11111; + diff_ms = abs((now - running_pts) / 90); + + if (diff_ms > 100000) { - now /= 11111; - diff_ms = abs((now - running_pts) / 90); - eDebug("diff < -100ms check decoder/pipeline diff: decoder: %lld, pipeline: %lld, diff: %lld", running_pts, now, diff_ms); - if (diff_ms > 100000) - { - eDebug("high decoder/pipeline difference.. assume decoder has now started yet.. check again in 1sec"); - m_subtitle_sync_timer->start(1000, true); - break; - } + eDebug("high decoder/pipeline difference.. assume decoder has now started yet.. check again in 1sec"); + m_subtitle_sync_timer->start(1000, true); + break; } - else - eDebug("query position for decoder/pipeline check failed!"); - eDebug("subtitle to late... drop"); + eDebug("subtitle too late... drop"); m_subtitle_pages.pop_front(); } else if ( diff_ms > 20 ) { -// eDebug("start recheck timer"); + eDebug("start recheck timer"); m_subtitle_sync_timer->start(diff_ms > 1000 ? 1000 : diff_ms, true); break; } else // immediate show { - if (m_subtitle_widget) - m_subtitle_widget->setPage(page); + if ( m_subtitle_widget ) + { + if ( frontpage.pango_page != 0) + { +// eDebug("immediate show pango subtitle line"); + m_subtitle_widget->setPage(*(frontpage.pango_page)); + } + else if ( frontpage.vob_page != 0) + { + m_subtitle_widget->setPixmap(frontpage.vob_page->m_pixmap, eRect(0, 0, 720, 576)); + eDebug("blit vobsub pixmap... hide in %i ms", frontpage.vob_page->m_timeout); + m_subtitle_hide_timer->start(frontpage.vob_page->m_timeout, true); + } + m_subtitle_widget->show(); + } m_subtitle_pages.pop_front(); } } @@ -1592,12 +2058,26 @@ void eServiceMP3::pushSubtitles() pullSubtitle(); } +void eServiceMP3::hideSubtitles() +{ +// eDebug("eServiceMP3::hideSubtitles()"); + if ( m_subtitle_widget ) + m_subtitle_widget->hide(); +} + RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) { +// eDebug ("eServiceMP3::enableSubtitles m_currentSubtitleStream=%i this=%p",m_currentSubtitleStream, this); ePyObject entry; int tuplesize = PyTuple_Size(tuple); int pid, type; gint text_pid = 0; + eSingleLocker l(m_subs_to_pull_lock); + +// GstPad *pad = 0; +// g_signal_emit_by_name (m_gst_playbin, "get-text-pad", m_currentSubtitleStream, &pad); +// gst_element_get_static_pad(m_gst_subtitlebin, "sink"); +// gulong subprobe_handler_id = gst_pad_add_buffer_probe (pad, G_CALLBACK (gstCBsubtitleDrop), NULL); if (!PyTuple_Check(tuple)) goto error_out; @@ -1612,10 +2092,11 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) goto error_out; type = PyInt_AsLong(entry); +// eDebug ("eServiceMP3::enableSubtitles new pid=%i",pid); if (m_currentSubtitleStream != pid) { - eSingleLocker l(m_subs_to_pull_lock); g_object_set (G_OBJECT (m_gst_playbin), "current-text", pid, NULL); +// eDebug ("eServiceMP3::enableSubtitles g_object_set current-text = %i", pid); m_currentSubtitleStream = pid; m_subs_to_pull = 0; m_subtitle_pages.clear(); @@ -1628,6 +2109,9 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) g_object_get (G_OBJECT (m_gst_playbin), "current-text", &text_pid, NULL); eDebug ("eServiceMP3::switched to subtitle stream %i", text_pid); +// gst_pad_remove_buffer_probe (pad, subprobe_handler_id); + + m_event((iPlayableService*)this, evUpdatedInfo); return 0; @@ -1654,25 +2138,23 @@ PyObject *eServiceMP3::getCachedSubtitle() PyObject *eServiceMP3::getSubtitleList() { - eDebug("eServiceMP3::getSubtitleList"); - +// eDebug("eServiceMP3::getSubtitleList"); ePyObject l = PyList_New(0); - int stream_count[sizeof(subtype_t)]; - for ( unsigned int i = 0; i < sizeof(subtype_t); i++ ) - stream_count[i] = 0; - + int stream_idx = 0; + for (std::vector::iterator IterSubtitleStream(m_subtitleStreams.begin()); IterSubtitleStream != m_subtitleStreams.end(); ++IterSubtitleStream) { subtype_t type = IterSubtitleStream->type; ePyObject tuple = PyTuple_New(5); +// eDebug("eServiceMP3::getSubtitleList idx=%i type=%i, code=%s", stream_idx, int(type), (IterSubtitleStream->language_code).c_str()); PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(2)); - PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(stream_count[type])); + PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(stream_idx)); PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(int(type))); PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(0)); PyTuple_SET_ITEM(tuple, 4, PyString_FromString((IterSubtitleStream->language_code).c_str())); PyList_Append(l, tuple); Py_DECREF(tuple); - stream_count[type]++; + stream_idx++; } return l; } diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index 01f7cf7f..ceb3b491 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -47,9 +47,15 @@ public: typedef struct _GstElement GstElement; typedef enum { atUnknown, atMPEG, atMP3, atAC3, atDTS, atAAC, atPCM, atOGG, atFLAC } audiotype_t; -typedef enum { stPlainText, stSSA, stSRT } subtype_t; +typedef enum { stUnknown, stPlainText, stSSA, stASS, stSRT, stVOB, stPGS } subtype_t; typedef enum { ctNone, ctMPEGTS, ctMPEGPS, ctMKV, ctAVI, ctMP4, ctVCD, ctCDA } containertype_t; +struct SubtitlePage +{ + ePangoSubtitlePage *pango_page; + eVobSubtitlePage *vob_page; +}; + class eServiceMP3: public iPlayableService, public iPauseableService, public iServiceInformation, public iSeekableService, public iAudioTrackSelection, public iAudioChannelSelection, public iSubtitleOutput, public iStreamedService, public iAudioDelay, public Object @@ -198,6 +204,7 @@ private: }; int m_state; GstElement *m_gst_playbin; + GstElement *m_gst_subtitlebin; GstTagList *m_stream_tags; eFixedMessagePump m_pump; std::string m_error_message; @@ -205,17 +212,33 @@ private: audiotype_t gstCheckAudioPad(GstStructure* structure); void gstBusCall(GstBus *bus, GstMessage *msg); static GstBusSyncReply gstBusSyncHandler(GstBus *bus, GstMessage *message, gpointer user_data); + static void gstHTTPSourceSetAgent(GObject *source, GParamSpec *unused, gpointer user_data); static void gstCBsubtitleAvail(GstElement *element, gpointer user_data); - GstPad* gstCreateSubtitleSink(eServiceMP3* _this, subtype_t type); + static GstCaps* gstGhostpadGetCAPS (GstPad * pad); + static gboolean gstGhostpadAcceptCAPS(GstPad * pad, GstCaps * caps); + static void gstGhostpadLink(gpointer user_data, GstCaps * caps); + static GstFlowReturn gstGhostpadBufferAlloc(GstPad *pad, guint64 offset, guint size, GstCaps *caps, GstBuffer **buf); + static void gstGhostpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data); + static gboolean gstGhostpadSinkEvent(GstPad * pad, GstEvent * event); + static GstFlowReturn gstGhostpadChainFunction(GstPad * pad, GstBuffer * buffer); +/* static void gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer user_data); + static void gstCBsubtitleLink(subtype_t type, gpointer user_data); + static gboolean gstCBsubtitleDrop(GstPad *pad, GstBuffer *buffer, gpointer user_data);*/ void gstPoll(const int&); - static void gstHTTPSourceSetAgent(GObject *source, GParamSpec *unused, gpointer user_data); + GstPadBufferAllocFunction m_ghost_pad_buffer_alloc; + GstPadChainFunction m_ghost_pad_chain_function; + GstPadEventFunction m_ghost_pad_subtitle_sink_event; + GstCaps *m_gst_prev_subtitle_caps; + GstSegment m_gst_subtitle_segment; + GstPadEventFunction m_gst_sink_event; - std::list m_subtitle_pages; + std::list m_subtitle_pages; ePtr m_subtitle_sync_timer; - + ePtr m_subtitle_hide_timer; ePtr m_streamingsrc_timeout; void pushSubtitles(); void pullSubtitle(); + void hideSubtitles(); void sourceTimeout(); int m_subs_to_pull; sourceStream m_sourceinfo; -- cgit v1.2.3 From b9c0b3c8ec8c7979848126d9c88764043d685d26 Mon Sep 17 00:00:00 2001 From: ghost Date: Thu, 2 Dec 2010 11:24:40 +0100 Subject: switch appsink to async again (fixes embedded mkv text subtitles) --- lib/service/servicemp3.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index 8628c269..42f84206 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -1252,16 +1252,16 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) } break; case GST_STATE_CHANGE_READY_TO_PAUSED: { -// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); + GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); // GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); -// if (appsink) -// { -// g_object_set (G_OBJECT (appsink), "max-buffers", 2, NULL); -// g_object_set (G_OBJECT (appsink), "sync", FALSE, NULL); -// g_object_set (G_OBJECT (appsink), "emit-signals", TRUE, NULL); -// eDebug("eServiceMP3::appsink properties set!"); -// gst_object_unref(appsink); -// } + if (appsink) + { + g_object_set (G_OBJECT (appsink), "max-buffers", 2, NULL); + g_object_set (G_OBJECT (appsink), "sync", FALSE, NULL); + g_object_set (G_OBJECT (appsink), "emit-signals", TRUE, NULL); + eDebug("eServiceMP3::appsink properties set!"); + gst_object_unref(appsink); + } setAC3Delay(ac3_delay); setPCMDelay(pcm_delay); } break; -- cgit v1.2.3 From 685f45442990ede7b2b3bc92177e419d9de7aad3 Mon Sep 17 00:00:00 2001 From: ghost Date: Fri, 3 Dec 2010 00:13:26 +0100 Subject: servicemp3.h/cpp: fix segfault on mkv start, thread safety fixes, fix compiler warnings --- lib/service/servicemp3.cpp | 112 ++++++++++++++++++++++++++++----------------- lib/service/servicemp3.h | 27 ++++++++++- 2 files changed, 96 insertions(+), 43 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index 42f84206..c9d3bf6e 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -1215,7 +1215,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) source = GST_MESSAGE_SRC(msg); sourceName = gst_object_get_name(source); -#if 1 +#if 0 if (gst_message_get_structure(msg)) { gchar *string = gst_structure_to_string(gst_message_get_structure(msg)); @@ -1402,7 +1402,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) gchar *g_codec = NULL, *g_lang = NULL; g_signal_emit_by_name (m_gst_playbin, "get-text-tags", i, &tags); subtitleStream subs; - int ret; +// int ret; g_lang = g_strdup_printf ("und"); if ( tags && gst_is_tag_list(tags) ) @@ -1514,7 +1514,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) GstBusSyncReply eServiceMP3::gstBusSyncHandler(GstBus *bus, GstMessage *message, gpointer user_data) { eServiceMP3 *_this = (eServiceMP3*)user_data; - _this->m_pump.send(1); + _this->m_pump.send(Message(1)); /* wake */ return GST_BUS_PASS; } @@ -1568,7 +1568,7 @@ audiotype_t eServiceMP3::gstCheckAudioPad(GstStructure* structure) return atUnknown; } -void eServiceMP3::gstPoll(const int &msg) +void eServiceMP3::gstPoll(const Message &msg) { /* ok, we have a serious problem here. gstBusSyncHandler sends us the wakup signal, but likely before it was posted. @@ -1576,7 +1576,7 @@ void eServiceMP3::gstPoll(const int &msg) I need to understand the API a bit more to make this work proplerly. */ - if (msg == 1) + if (msg.type == 1) { GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)); GstMessage *message; @@ -1587,8 +1587,12 @@ void eServiceMP3::gstPoll(const int &msg) gst_message_unref (message); } } - else + else if (msg.type == 2) pullSubtitle(); + else if (msg.type == 3) + gstGhostpadHasCAPS_synced(msg.d.pad); + else + eDebug("gstPoll unhandled Message %d\n", msg.type); } eAutoInitPtr init_eServiceFactoryMP3(eAutoInitNumbers::service+1, "eServiceFactoryMP3"); @@ -1598,7 +1602,7 @@ void eServiceMP3::gstCBsubtitleAvail(GstElement *appsink, gpointer user_data) eServiceMP3 *_this = (eServiceMP3*)user_data; eSingleLocker l(_this->m_subs_to_pull_lock); ++_this->m_subs_to_pull; - _this->m_pump.send(2); + _this->m_pump.send(Message(2)); } gboolean eServiceMP3::gstGhostpadSinkEvent(GstPad * pad, GstEvent * event) @@ -1606,7 +1610,7 @@ gboolean eServiceMP3::gstGhostpadSinkEvent(GstPad * pad, GstEvent * event) // eDebug("eServiceMP3::gstGhostpadSinkEvent %s", gst_structure_get_name (event->structure)); // eServiceMP3 *_this = (eServiceMP3*) (gst_pad_get_parent (pad)); - eServiceMP3 *_this = g_object_get_data (G_OBJECT (pad), "application-instance"); + eServiceMP3 *_this = (eServiceMP3*) g_object_get_data (G_OBJECT (pad), "application-instance"); gboolean ret; GstFormat format; @@ -1755,7 +1759,7 @@ void eServiceMP3::gstGhostpadLink(gpointer user_data, GstCaps * caps) GstFlowReturn eServiceMP3::gstGhostpadBufferAlloc(GstPad *pad, guint64 offset, guint size, GstCaps *caps, GstBuffer **buf) { - eServiceMP3 *_this = g_object_get_data (G_OBJECT (pad), "application-instance"); + eServiceMP3 *_this = (eServiceMP3*) g_object_get_data (G_OBJECT (pad), "application-instance"); // eDebug("eServiceMP3::gstGhostpadBufferAlloc prevcaps=%s newcaps=%s", gst_caps_to_string(_this->m_gst_prev_subtitle_caps), gst_caps_to_string(caps)); if (!GST_PAD_CAPS (pad) || !gst_caps_is_equal (_this->m_gst_prev_subtitle_caps, caps)) @@ -1766,54 +1770,80 @@ GstFlowReturn eServiceMP3::gstGhostpadBufferAlloc(GstPad *pad, guint64 offset, g void eServiceMP3::gstGhostpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data) { - GstCaps *caps; eServiceMP3 *_this = (eServiceMP3*)user_data; + gst_object_ref (pad); + + _this->m_pump.send(Message(3, pad)); +} + +// after messagepump +void eServiceMP3::gstGhostpadHasCAPS_synced(GstPad *pad) +{ + GstCaps *caps; + g_object_get (G_OBJECT (pad), "caps", &caps, NULL); -// eDebug("gstGhostpadHasCAPS:: signal::caps = %s", gst_caps_to_string(caps)); - if (!caps) - return; +// eDebug("gstGhostpadHasCAPS:: signal::caps = %s", gst_caps_to_string(caps)); - subtitleStream subs = _this->m_subtitleStreams[_this->m_currentSubtitleStream]; - - if ( subs.type == stUnknown ) + if (caps) { - GstTagList *tags; -// eDebug("gstGhostpadHasCAPS::m_subtitleStreams[%i].type == stUnknown...", _this->m_currentSubtitleStream); - - gchar *g_lang; - g_signal_emit_by_name (_this->m_gst_playbin, "get-text-tags", _this->m_currentSubtitleStream, &tags); - - g_lang = g_strdup_printf ("und"); - if ( tags && gst_is_tag_list(tags) ) - gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); - subs.language_code = std::string(g_lang); - GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); - subs.type = getSubtitleType(ghostpad); - - _this->m_subtitleStreams[_this->m_currentSubtitleStream] = subs; + subtitleStream subs; - g_free (g_lang); - } +// eDebug("gstGhostpadHasCAPS_synced %p %d", pad, m_subtitleStreams.size()); -// eDebug("gstGhostpadHasCAPS:: _this->m_gst_prev_subtitle_caps=%s equal=%i",gst_caps_to_string(_this->m_gst_prev_subtitle_caps),gst_caps_is_equal(_this->m_gst_prev_subtitle_caps, caps)); + if (!m_subtitleStreams.empty()) + subs = m_subtitleStreams[m_currentSubtitleStream]; + else { + subs.type = stUnknown; + subs.pad = pad; + } - if (!GST_PAD_CAPS (pad) || !gst_caps_is_equal (_this->m_gst_prev_subtitle_caps, caps)) - gstGhostpadLink(_this, caps); - - _this->m_gst_prev_subtitle_caps = gst_caps_copy(caps); - gst_caps_unref (caps); + if ( subs.type == stUnknown ) + { + GstTagList *tags; +// eDebug("gstGhostpadHasCAPS::m_subtitleStreams[%i].type == stUnknown...", m_currentSubtitleStream); + + gchar *g_lang; + g_signal_emit_by_name (m_gst_playbin, "get-text-tags", m_currentSubtitleStream, &tags); + + g_lang = g_strdup_printf ("und"); + if ( tags && gst_is_tag_list(tags) ) + gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); + + subs.language_code = std::string(g_lang); + GstPad *ghostpad = gst_element_get_static_pad(m_gst_subtitlebin, "sink"); + subs.type = getSubtitleType(ghostpad); + + if (!m_subtitleStreams.empty()) + m_subtitleStreams[m_currentSubtitleStream] = subs; + else + m_subtitleStreams.push_back(subs); + + g_free (g_lang); + } + +// eDebug("gstGhostpadHasCAPS:: m_gst_prev_subtitle_caps=%s equal=%i",gst_caps_to_string(m_gst_prev_subtitle_caps),gst_caps_is_equal(m_gst_prev_subtitle_caps, caps)); + + if (!GST_PAD_CAPS (pad) || !gst_caps_is_equal (m_gst_prev_subtitle_caps, caps)) + gstGhostpadLink(this, caps); + + m_gst_prev_subtitle_caps = gst_caps_copy(caps); + + gst_caps_unref (caps); + } + + gst_object_unref (pad); } GstFlowReturn eServiceMP3::gstGhostpadChainFunction(GstPad * pad, GstBuffer * buffer) { GstFlowReturn ret = GST_FLOW_OK; - eServiceMP3 *_this = g_object_get_data (G_OBJECT (pad), "application-instance"); + eServiceMP3 *_this = (eServiceMP3*)g_object_get_data (G_OBJECT (pad), "application-instance"); - gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); - gint64 duration_ns = GST_BUFFER_DURATION(buffer); +// gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); +// gint64 duration_ns = GST_BUFFER_DURATION(buffer); size_t len = GST_BUFFER_SIZE(buffer); unsigned char line[len+1]; diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index ceb3b491..11bf125c 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -206,7 +206,28 @@ private: GstElement *m_gst_playbin; GstElement *m_gst_subtitlebin; GstTagList *m_stream_tags; - eFixedMessagePump m_pump; + + struct Message + { + Message() + :type(-1) + {} + Message(int type) + :type(type) + {} + Message(int type, GstPad *pad) + :type(type) + { + d.pad=pad; + } + + int type; + union { + GstPad *pad; // for msg type 3 + } d; + }; + + eFixedMessagePump m_pump; std::string m_error_message; audiotype_t gstCheckAudioPad(GstStructure* structure); @@ -224,7 +245,9 @@ private: /* static void gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer user_data); static void gstCBsubtitleLink(subtype_t type, gpointer user_data); static gboolean gstCBsubtitleDrop(GstPad *pad, GstBuffer *buffer, gpointer user_data);*/ - void gstPoll(const int&); + void gstPoll(const Message&); + void gstGhostpadHasCAPS_synced(GstPad *pad); + GstPadBufferAllocFunction m_ghost_pad_buffer_alloc; GstPadChainFunction m_ghost_pad_chain_function; GstPadEventFunction m_ghost_pad_subtitle_sink_event; -- cgit v1.2.3 From 4f0779fd3cd5951698d537c721dc17e85f15a681 Mon Sep 17 00:00:00 2001 From: ghost Date: Sun, 5 Dec 2010 01:57:48 +0100 Subject: small code cleanup, fix memleaks refs #537 --- lib/gui/esubtitle.h | 8 +++--- lib/service/servicemp3.cpp | 65 ++++++++++++++++++++-------------------------- lib/service/servicemp3.h | 13 +++++----- 3 files changed, 38 insertions(+), 48 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/lib/gui/esubtitle.h b/lib/gui/esubtitle.h index 2b0ec8ff..cdad7286 100644 --- a/lib/gui/esubtitle.h +++ b/lib/gui/esubtitle.h @@ -23,7 +23,7 @@ struct ePangoSubtitlePageElement struct ePangoSubtitlePage { - pts_t show_pts; + pts_t m_show_pts; int m_timeout; /* in milliseconds */ std::vector m_elements; void clear() { m_elements.clear(); } @@ -31,15 +31,13 @@ struct ePangoSubtitlePage struct eVobSubtitlePage { - pts_t show_pts; + pts_t m_show_pts; int m_timeout; /* in milliseconds */ ePtr m_pixmap; }; class eDVBTeletextSubtitlePage; -class eDVBPangoSubtitlePage; -class ePangoSubtitlePage; -class eVobSubtitlePage; +class eDVBSubtitlePage; class eSubtitleWidget: public eWidget, public Object { diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index c9d3bf6e..db935e4f 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -1967,35 +1967,28 @@ void eServiceMP3::pullSubtitle() if ( m_subtitleStreams[m_currentSubtitleStream].type < stVOB ) { unsigned char line[len+1]; + SubtitlePage page; memcpy(line, GST_BUFFER_DATA(buffer), len); line[len] = 0; eDebug("got new text subtitle @ buf_pos = %lld ns (in pts=%lld): '%s' ", buf_pos, buf_pos/11111, line); - ePangoSubtitlePage* page = new ePangoSubtitlePage; gRGB rgbcol(0xD0,0xD0,0xD0); - page->m_elements.push_back(ePangoSubtitlePageElement(rgbcol, (const char*)line)); - page->show_pts = buf_pos / 11111L; - page->m_timeout = duration_ns / 1000000; - SubtitlePage subtitlepage; - subtitlepage.pango_page = page; - subtitlepage.vob_page = NULL; - m_subtitle_pages.push_back(subtitlepage); + page.type = SubtitlePage::Pango; + page.pango_page.m_elements.push_back(ePangoSubtitlePageElement(rgbcol, (const char*)line)); + page.pango_page.m_show_pts = buf_pos / 11111L; + page.pango_page.m_timeout = duration_ns / 1000000; + m_subtitle_pages.push_back(page); pushSubtitles(); } else if ( m_subtitleStreams[m_currentSubtitleStream].type == stVOB ) { + SubtitlePage page; eDebug("got new subpicture @ buf_pos = %lld ns (in pts=%lld), duration=%lld ns, len=%i bytes. ", buf_pos, buf_pos/11111, duration_ns, len); - eVobSubtitlePage* page = new eVobSubtitlePage; - eSize size = eSize(720, 576); - page->m_pixmap = new gPixmap(size, 32, 0); - // ePtr pixmap; - // pixmap = new gPixmap(size, 32, 1); /* allocate accel surface (if possible) */ - memcpy(page->m_pixmap->surface->data, GST_BUFFER_DATA(buffer), len); - page->show_pts = buf_pos / 11111L; - page->m_timeout = duration_ns / 1000; - SubtitlePage subtitlepage; - subtitlepage.vob_page = page; - subtitlepage.pango_page = NULL; - m_subtitle_pages.push_back(subtitlepage); + page.type = SubtitlePage::Vob; + page.vob_page.m_pixmap = new gPixmap(eSize(720, 576), 32, 1); + memcpy(page.vob_page.m_pixmap->surface->data, GST_BUFFER_DATA(buffer), len); + page.vob_page.m_show_pts = buf_pos / 11111L; + page.vob_page.m_timeout = duration_ns / 1000; + m_subtitle_pages.push_back(page); pushSubtitles(); } else @@ -2017,17 +2010,17 @@ void eServiceMP3::pushSubtitles() pts_t running_pts; while ( !m_subtitle_pages.empty() ) { - SubtitlePage frontpage = m_subtitle_pages.front(); + SubtitlePage &frontpage = m_subtitle_pages.front(); gint64 diff_ms = 0; - gint64 show_pts = 0; - + gint64 show_pts; + + if (frontpage.type == SubtitlePage::Pango) + show_pts = frontpage.pango_page.m_show_pts; + else + show_pts = frontpage.vob_page.m_show_pts; + getPlayPosition(running_pts); - - if ( frontpage.pango_page != 0 ) - show_pts = frontpage.pango_page->show_pts; - else if ( frontpage.vob_page != 0 ) - show_pts = frontpage.vob_page->show_pts; - + diff_ms = ( show_pts - running_pts ) / 90; GstFormat fmt = GST_FORMAT_TIME; gint64 now; @@ -2060,15 +2053,13 @@ void eServiceMP3::pushSubtitles() { if ( m_subtitle_widget ) { - if ( frontpage.pango_page != 0) - { - m_subtitle_widget->setPage(*(frontpage.pango_page)); - } - else if ( frontpage.vob_page != 0) + if ( frontpage.type == SubtitlePage::Pango) + m_subtitle_widget->setPage(frontpage.pango_page); + else { - m_subtitle_widget->setPixmap(frontpage.vob_page->m_pixmap, eRect(0, 0, 720, 576)); - eDebug("blit vobsub pixmap... hide in %i ms", frontpage.vob_page->m_timeout); - m_subtitle_hide_timer->start(frontpage.vob_page->m_timeout, true); + m_subtitle_widget->setPixmap(frontpage.vob_page.m_pixmap, eRect(0, 0, 720, 576)); + eDebug("blit vobsub pixmap... hide in %i ms", frontpage.vob_page.m_timeout); + m_subtitle_hide_timer->start(frontpage.vob_page.m_timeout, true); } m_subtitle_widget->show(); } diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index 11bf125c..01ed13a0 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -50,12 +50,6 @@ typedef enum { atUnknown, atMPEG, atMP3, atAC3, atDTS, atAAC, atPCM, atOGG, atFL typedef enum { stUnknown, stPlainText, stSSA, stASS, stSRT, stVOB, stPGS } subtype_t; typedef enum { ctNone, ctMPEGTS, ctMPEGPS, ctMKV, ctAVI, ctMP4, ctVCD, ctCDA } containertype_t; -struct SubtitlePage -{ - ePangoSubtitlePage *pango_page; - eVobSubtitlePage *vob_page; -}; - class eServiceMP3: public iPlayableService, public iPauseableService, public iServiceInformation, public iSeekableService, public iAudioTrackSelection, public iAudioChannelSelection, public iSubtitleOutput, public iStreamedService, public iAudioDelay, public Object @@ -255,6 +249,13 @@ private: GstSegment m_gst_subtitle_segment; GstPadEventFunction m_gst_sink_event; + struct SubtitlePage + { + enum { Unknown, Pango, Vob } type; + ePangoSubtitlePage pango_page; + eVobSubtitlePage vob_page; + }; + std::list m_subtitle_pages; ePtr m_subtitle_sync_timer; ePtr m_subtitle_hide_timer; -- cgit v1.2.3 From 85cf8dd019e8c44fb42802b01efb0677f328fa7c Mon Sep 17 00:00:00 2001 From: ghost Date: Fri, 10 Dec 2010 12:30:14 +0100 Subject: small cleanup, work on subtitle sync handling refs #537 --- lib/service/servicemp3.cpp | 63 ++++++++++++++++++++++++---------------------- lib/service/servicemp3.h | 3 +++ 2 files changed, 36 insertions(+), 30 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index db935e4f..fb6e7030 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -233,6 +233,9 @@ eServiceMP3::eServiceMP3(eServiceReference ref) m_currentTrickRatio = 0; m_subs_to_pull = 0; m_buffer_size = 1*1024*1024; + m_prev_decoder_time = -1; + m_decoder_time_valid_state = 0; + CONNECT(m_seekTimeout->timeout, eServiceMP3::seekTimeoutCB); CONNECT(m_subtitle_sync_timer->timeout, eServiceMP3::pushSubtitles); CONNECT(m_subtitle_hide_timer->timeout, eServiceMP3::hideSubtitles); @@ -620,6 +623,8 @@ RESULT eServiceMP3::seekTo(pts_t to) if (!(ret = seekToImpl(to))) { m_subtitle_pages.clear(); + m_prev_decoder_time = -1; + m_decoder_time_valid_state = 0; m_subs_to_pull = 0; } } @@ -1570,18 +1575,11 @@ audiotype_t eServiceMP3::gstCheckAudioPad(GstStructure* structure) void eServiceMP3::gstPoll(const Message &msg) { - /* ok, we have a serious problem here. gstBusSyncHandler sends - us the wakup signal, but likely before it was posted. - the usleep, an EVIL HACK (DON'T DO THAT!!!) works around this. - - I need to understand the API a bit more to make this work - proplerly. */ if (msg.type == 1) { GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)); GstMessage *message; - usleep(1); - while ((message = gst_bus_pop (bus))) + while (message = gst_bus_pop(bus)) { gstBusCall(bus, message); gst_message_unref (message); @@ -1977,7 +1975,8 @@ void eServiceMP3::pullSubtitle() page.pango_page.m_show_pts = buf_pos / 11111L; page.pango_page.m_timeout = duration_ns / 1000000; m_subtitle_pages.push_back(page); - pushSubtitles(); + if (m_subtitle_pages.size()==1) + pushSubtitles(); } else if ( m_subtitleStreams[m_currentSubtitleStream].type == stVOB ) { @@ -1989,7 +1988,8 @@ void eServiceMP3::pullSubtitle() page.vob_page.m_show_pts = buf_pos / 11111L; page.vob_page.m_timeout = duration_ns / 1000; m_subtitle_pages.push_back(page); - pushSubtitles(); + if (m_subtitle_pages.size()==1) + pushSubtitles(); } else { @@ -2007,52 +2007,54 @@ void eServiceMP3::pullSubtitle() void eServiceMP3::pushSubtitles() { - pts_t running_pts; while ( !m_subtitle_pages.empty() ) { SubtitlePage &frontpage = m_subtitle_pages.front(); + pts_t running_pts; gint64 diff_ms = 0; gint64 show_pts; + getPlayPosition(running_pts); + + if (m_decoder_time_valid_state < 4) { + ++m_decoder_time_valid_state; + if (m_prev_decoder_time == running_pts) + m_decoder_time_valid_state = 0; + if (m_decoder_time_valid_state < 4) { +// if (m_decoder_time_valid_state) +// eDebug("%d: decoder time not valid! prev %lld, now %lld\n", m_decoder_time_valid_state, m_prev_decoder_time/90, running_pts/90); +// else +// eDebug("%d: decoder time not valid! now %lld\n", m_decoder_time_valid_state, running_pts/90); + m_subtitle_sync_timer->start(25, true); + m_prev_decoder_time = running_pts; + break; + } + } + if (frontpage.type == SubtitlePage::Pango) show_pts = frontpage.pango_page.m_show_pts; else show_pts = frontpage.vob_page.m_show_pts; - getPlayPosition(running_pts); - diff_ms = ( show_pts - running_pts ) / 90; - GstFormat fmt = GST_FORMAT_TIME; - gint64 now; - if ( gst_element_query_position(m_gst_playbin, &fmt, &now) != -1 ) - eDebug("check decoder/pipeline diff: decoder: %lld, pipeline: %lld, show_pts: %lld, diff: %lld ms", running_pts/90, now/1000000, show_pts/90, diff_ms); - else - eDebug("query position for decoder/pipeline check failed!"); + eDebug("check subtitle: decoder: %lld, show_pts: %lld, diff: %lld ms", running_pts/90, show_pts/90, diff_ms); if ( diff_ms < -100 ) { - now /= 11111; - diff_ms = abs((now - running_pts) / 90); - - if (diff_ms > 100000) - { - eDebug("high decoder/pipeline difference.. assume decoder has now started yet.. check again in 1sec"); - m_subtitle_sync_timer->start(1000, true); - break; - } eDebug("subtitle too late... drop"); m_subtitle_pages.pop_front(); } else if ( diff_ms > 20 ) { - eDebug("start recheck timer"); - m_subtitle_sync_timer->start(diff_ms > 1000 ? 1000 : diff_ms, true); + eDebug("start timer"); + m_subtitle_sync_timer->start(diff_ms, true); break; } else // immediate show { if ( m_subtitle_widget ) { + eDebug("show!\n"); if ( frontpage.type == SubtitlePage::Pango) m_subtitle_widget->setPage(frontpage.pango_page); else @@ -2111,6 +2113,7 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) // eDebug ("eServiceMP3::enableSubtitles g_object_set current-text = %i", pid); m_currentSubtitleStream = pid; m_subs_to_pull = 0; + m_prev_decoder_time = -1; m_subtitle_pages.clear(); } diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index 01ed13a0..a14a1234 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -260,6 +260,9 @@ private: ePtr m_subtitle_sync_timer; ePtr m_subtitle_hide_timer; ePtr m_streamingsrc_timeout; + pts_t m_prev_decoder_time; + int m_decoder_time_valid_state; + void pushSubtitles(); void pullSubtitle(); void hideSubtitles(); -- cgit v1.2.3 From f8203ea5c494f34cee4fb72fb99b5ca3e429c8a1 Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Mon, 13 Dec 2010 10:51:56 +0100 Subject: remove ghostpads and revert to good ol'appsink while still allow playback of files containing vob and pgs subs, hopefully (#537) --- lib/service/servicemp3.cpp | 411 ++++----------------------------------------- lib/service/servicemp3.h | 113 ++++++------- 2 files changed, 79 insertions(+), 445 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index fb6e7030..31ae9573 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -22,9 +22,6 @@ #include #define HTTP_TIMEOUT 10 -static GstStaticPadTemplate subsinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS("text/plain; text/x-pango-markup; video/x-dvd-subpicture; subpicture/x-pgs")); -// int ret = gst_pad_set_caps (ghostpad, caps2); -// gst_caps_unref(caps2);)); // eServiceFactoryMP3 @@ -225,7 +222,6 @@ eServiceMP3::eServiceMP3(eServiceReference ref) m_seekTimeout = eTimer::create(eApp); m_subtitle_sync_timer = eTimer::create(eApp); m_streamingsrc_timeout = 0; - m_subtitle_hide_timer = eTimer::create(eApp); m_stream_tags = 0; m_currentAudioStream = -1; m_currentSubtitleStream = 0; @@ -238,7 +234,6 @@ eServiceMP3::eServiceMP3(eServiceReference ref) CONNECT(m_seekTimeout->timeout, eServiceMP3::seekTimeoutCB); CONNECT(m_subtitle_sync_timer->timeout, eServiceMP3::pushSubtitles); - CONNECT(m_subtitle_hide_timer->timeout, eServiceMP3::hideSubtitles); CONNECT(m_pump.recv_msg, eServiceMP3::gstPoll); m_aspect = m_width = m_height = m_framerate = m_progressive = -1; @@ -344,57 +339,19 @@ eServiceMP3::eServiceMP3(eServiceReference ref) g_free(uri); - m_gst_subtitlebin = gst_bin_new("subtitle_bin"); - - if ( m_gst_playbin ) + GstElement *subsink = gst_element_factory_make("appsink", "subtitle_sink"); + if (!subsink) + eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-appsink"); + else { - GstElement *appsink = gst_element_factory_make("appsink", "subtitle_sink"); - - if (!appsink) - eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-appsink"); - - GstElement *dvdsubdec = gst_element_factory_make("dvdsubdec", "vobsubtitle_decoder"); - if ( dvdsubdec ) - { - gst_bin_add_many(GST_BIN(m_gst_subtitlebin), dvdsubdec, appsink, NULL); - g_object_set (G_OBJECT (dvdsubdec), "singlebuffer", TRUE, NULL); - } - else - { - eDebug("eServiceMP3::missing gst-plugin-dvdsub, no vob subtitle support!"); - gst_bin_add(GST_BIN(m_gst_subtitlebin), appsink); - } - - GstPadTemplate *templ; - templ = gst_static_pad_template_get (&subsinktemplate); - - GstPad *ghostpad = gst_ghost_pad_new_no_target_from_template("sink", templ); - gst_element_add_pad (m_gst_subtitlebin, ghostpad); - - GstCaps* caps = gst_caps_from_string("text/plain; text/x-pango-markup; video/x-raw-rgb; subpicture/x-pgs"); - g_object_set (G_OBJECT (appsink), "caps", caps, NULL); - gst_caps_unref(caps); - - g_object_set (G_OBJECT (appsink), "async", FALSE, NULL); - g_object_set (G_OBJECT (appsink), "sync", TRUE, NULL); - g_object_set (G_OBJECT (appsink), "emit-signals", TRUE, NULL); - g_object_set (G_OBJECT (appsink), "ts-offset", 0 * GST_SECOND, NULL); - - g_object_set_data (G_OBJECT (ghostpad), "application-instance", this); - g_signal_connect (G_OBJECT (ghostpad), "notify::caps", G_CALLBACK (gstGhostpadHasCAPS), this); - gst_pad_set_getcaps_function (ghostpad, gstGhostpadGetCAPS); - gst_pad_set_acceptcaps_function (ghostpad, gstGhostpadAcceptCAPS); - m_ghost_pad_buffer_alloc = GST_PAD_BUFFERALLOCFUNC(ghostpad); - m_ghost_pad_chain_function = GST_PAD_CHAINFUNC(ghostpad); - m_ghost_pad_subtitle_sink_event = GST_PAD_EVENTFUNC(ghostpad); - gst_pad_set_bufferalloc_function (ghostpad, GST_DEBUG_FUNCPTR(gstGhostpadBufferAlloc)); - gst_pad_set_event_function (ghostpad, GST_DEBUG_FUNCPTR(gstGhostpadSinkEvent)); - gst_pad_set_chain_function (ghostpad, GST_DEBUG_FUNCPTR(gstGhostpadChainFunction)); - m_gst_prev_subtitle_caps = gst_caps_new_empty(); - - g_object_set (G_OBJECT (m_gst_playbin), "text-sink", m_gst_subtitlebin, NULL); - m_subs_to_pull_handler_id = g_signal_connect (appsink, "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 (subsink), "caps", gst_caps_from_string("text/plain; text/x-plain; text/x-pango-markup; video/x-dvd-subpicture; subpicture/x-pgs"), NULL); + g_object_set (G_OBJECT (m_gst_playbin), "text-sink", subsink, NULL); + } + + if ( m_gst_playbin ) + { gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)), gstBusSyncHandler, this); char srt_filename[strlen(filename)+1]; strncpy(srt_filename,filename,strlen(filename)-3); @@ -410,10 +367,6 @@ eServiceMP3::eServiceMP3(eServiceReference ref) subs.language_code = std::string("und"); m_subtitleStreams.push_back(subs); } - if ( m_sourceinfo.is_streaming ) - { - g_signal_connect (G_OBJECT (m_gst_playbin), "notify::source", G_CALLBACK (gstHTTPSourceSetAgent), this); - } } else { m_event((iPlayableService*)this, evUser+12); @@ -431,8 +384,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref) eServiceMP3::~eServiceMP3() { // disconnect subtitle callback - GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); -// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); + GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); if (appsink) { @@ -441,7 +393,6 @@ eServiceMP3::~eServiceMP3() } delete m_subtitle_widget; - gst_caps_unref(this->m_gst_prev_subtitle_caps); // disconnect sync handler callback gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)), NULL, NULL); @@ -1220,7 +1171,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) source = GST_MESSAGE_SRC(msg); sourceName = gst_object_get_name(source); -#if 0 +#if 1 if (gst_message_get_structure(msg)) { gchar *string = gst_structure_to_string(gst_message_get_structure(msg)); @@ -1257,8 +1208,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) } break; case GST_STATE_CHANGE_READY_TO_PAUSED: { - GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); -// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); + GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); if (appsink) { g_object_set (G_OBJECT (appsink), "max-buffers", 2, NULL); @@ -1422,6 +1372,8 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) GstPad* pad = 0; g_signal_emit_by_name (m_gst_playbin, "get-text-pad", i, &pad); + if ( pad ) + g_signal_connect (G_OBJECT (pad), "notify::caps", G_CALLBACK (gstTextpadHasCAPS), this); if ( subs.type != stSRT ) subs.type = getSubtitleType(pad, g_codec); @@ -1579,7 +1531,7 @@ void eServiceMP3::gstPoll(const Message &msg) { GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)); GstMessage *message; - while (message = gst_bus_pop(bus)) + while ((message = gst_bus_pop(bus))) { gstBusCall(bus, message); gst_message_unref (message); @@ -1588,7 +1540,7 @@ void eServiceMP3::gstPoll(const Message &msg) else if (msg.type == 2) pullSubtitle(); else if (msg.type == 3) - gstGhostpadHasCAPS_synced(msg.d.pad); + gstTextpadHasCAPS_synced(msg.d.pad); else eDebug("gstPoll unhandled Message %d\n", msg.type); } @@ -1603,170 +1555,7 @@ void eServiceMP3::gstCBsubtitleAvail(GstElement *appsink, gpointer user_data) _this->m_pump.send(Message(2)); } -gboolean eServiceMP3::gstGhostpadSinkEvent(GstPad * pad, GstEvent * event) -{ -// eDebug("eServiceMP3::gstGhostpadSinkEvent %s", gst_structure_get_name (event->structure)); - -// eServiceMP3 *_this = (eServiceMP3*) (gst_pad_get_parent (pad)); - eServiceMP3 *_this = (eServiceMP3*) g_object_get_data (G_OBJECT (pad), "application-instance"); - gboolean ret; - GstFormat format; - - if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB && event->structure && strcmp (gst_structure_get_name (event->structure), "subtitleoverlay-flush-subtitle") == 0) - { - eDebug ("Custom subtitle flush event"); -// GST_SUBTITLE_OVERLAY_LOCK (self); -// self->subtitle_flush = TRUE; -// self->subtitle_error = FALSE; -// if (self->subtitle_block_pad) -// gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE, -// _pad_blocked_cb, gst_object_ref (self), -// (GDestroyNotify) gst_object_unref); -// if (self->video_block_pad) -// gst_pad_set_blocked_async_full (self->video_block_pad, TRUE, -// _pad_blocked_cb, gst_object_ref (self), -// (GDestroyNotify) gst_object_unref); -// GST_SUBTITLE_OVERLAY_UNLOCK (self); -// - gst_event_unref (event); - event = NULL; - ret = TRUE; - goto out; - } else if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) - { - gst_event_parse_new_segment_full (event, NULL, NULL, NULL, &format, NULL, NULL, NULL); - if (_this->m_gst_subtitle_segment.format != GST_FORMAT_UNDEFINED && _this->m_gst_subtitle_segment.format != format) - { - eDebug("Subtitle segment format changed: %s -> %s", gst_format_get_name(_this->m_gst_subtitle_segment.format), gst_format_get_name(format)); - gst_segment_init (&_this->m_gst_subtitle_segment, GST_FORMAT_UNDEFINED); - } - } - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_STOP: - eDebug("Resetting subtitle segment because of flush-stop"); - gst_segment_init (&_this->m_gst_subtitle_segment, GST_FORMAT_UNDEFINED); - /* fall through */ - case GST_EVENT_FLUSH_START: - case GST_EVENT_NEWSEGMENT: - case GST_EVENT_EOS: -// eDebug("GST_EVENT_FLUSH_START GST_EVENT_NEWSEGMENT GST_EVENT_EOS"); - /* Add our event marker to make sure no events from here go ever outside - * the element, they're only interesting for our internal elements */ -// event = -// GST_EVENT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST -// (event))); -// if (!event->structure) { -// event->structure = -// gst_structure_id_empty_new (_subtitle_overlay_event_marker_id); -// gst_structure_set_parent_refcount (event->structure, -// &event->mini_object.refcount); -// } -// gst_structure_id_set (event->structure, _subtitle_overlay_event_marker_id, -// G_TYPE_BOOLEAN, TRUE, NULL); - break; - default: - eDebug("GST_EVENT_TYPE other: %i", GST_EVENT_TYPE (event)); - break; - } - - ret = _this->m_ghost_pad_subtitle_sink_event (pad, gst_event_ref (event)); -// eDebug("original EVENTFUNC returned %i", ret); - - if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) { - gboolean update; - gdouble rate, applied_rate; - gint64 start, stop, position; - - GST_DEBUG_OBJECT (pad, "Newsegment event: %" GST_PTR_FORMAT, - event->structure); - gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, - &format, &start, &stop, &position); - - GST_DEBUG_OBJECT (pad, "Old subtitle segment: %" GST_SEGMENT_FORMAT, - &_this->m_gst_subtitle_segment); - if (_this->m_gst_subtitle_segment.format != format) { - GST_DEBUG_OBJECT (pad, "Subtitle segment format changed: %s -> %s", - gst_format_get_name (_this->m_gst_subtitle_segment.format), - gst_format_get_name (format)); - gst_segment_init (&_this->m_gst_subtitle_segment, format); - } - - gst_segment_set_newsegment_full (&_this->m_gst_subtitle_segment, update, rate, - applied_rate, format, start, stop, position); - GST_DEBUG_OBJECT (pad, "New subtitle segment: %" GST_SEGMENT_FORMAT, - &_this->m_gst_subtitle_segment); - } - gst_event_unref (event); -// -out: -// gst_object_unref (_this); - return ret; -} - -GstCaps* eServiceMP3::gstGhostpadGetCAPS(GstPad * pad) -{ -// eDebug("eServiceMP3::gstGhostpadGetCAPS"); - return gst_static_pad_template_get_caps(&subsinktemplate); -} - -gboolean eServiceMP3::gstGhostpadAcceptCAPS(GstPad * pad, GstCaps * caps) -{ - GstCaps *templ_caps = gst_static_pad_template_get_caps (&subsinktemplate); - gboolean ret = gst_caps_can_intersect (templ_caps, caps); - -// eDebug("gstGhostpadAcceptCAPS templ=%s, given=%s ret=%i", gst_caps_to_string(templ_caps), gst_caps_to_string(caps), ret); - gst_caps_unref (templ_caps); - - return ret; -} - -void eServiceMP3::gstGhostpadLink(gpointer user_data, GstCaps * caps) -{ - GstStructure *s; - GstPad *sinkpad; - eServiceMP3 *_this = (eServiceMP3*)user_data; - - // FIXME: Need to cache events from the ghostpad and pass them forward - // now... and keep track of the segment and pass newsegment events - // downstream. - s = gst_caps_get_structure (caps, 0); - - GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); - GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); - GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); - - gst_ghost_pad_set_target(GST_GHOST_PAD(ghostpad), NULL); - gst_element_unlink(dvdsubdec, appsink); - int ret = -1; - - if ( gst_structure_has_name (s, "video/x-dvd-subpicture") && dvdsubdec ) - { - sinkpad = gst_element_get_static_pad (dvdsubdec, "sink"); - ret = gst_element_link_pads (dvdsubdec, "src", appsink, "sink"); -// eDebug("gstGhostpadLink:: dvdsubdec+appsink = %i", ret); - } - else - { - sinkpad = gst_element_get_static_pad (appsink, "sink"); -// eDebug("gstGhostpadLink:: appsink"); - } - - gst_ghost_pad_set_target (GST_GHOST_PAD(ghostpad), sinkpad); -} - -GstFlowReturn eServiceMP3::gstGhostpadBufferAlloc(GstPad *pad, guint64 offset, guint size, GstCaps *caps, GstBuffer **buf) -{ - eServiceMP3 *_this = (eServiceMP3*) g_object_get_data (G_OBJECT (pad), "application-instance"); - -// eDebug("eServiceMP3::gstGhostpadBufferAlloc prevcaps=%s newcaps=%s", gst_caps_to_string(_this->m_gst_prev_subtitle_caps), gst_caps_to_string(caps)); - if (!GST_PAD_CAPS (pad) || !gst_caps_is_equal (_this->m_gst_prev_subtitle_caps, caps)) - gstGhostpadLink (_this, caps); - - return _this->m_ghost_pad_buffer_alloc (pad, offset, size, caps, buf); -} - -void eServiceMP3::gstGhostpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data) +void eServiceMP3::gstTextpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data) { eServiceMP3 *_this = (eServiceMP3*)user_data; @@ -1776,13 +1565,13 @@ void eServiceMP3::gstGhostpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer } // after messagepump -void eServiceMP3::gstGhostpadHasCAPS_synced(GstPad *pad) +void eServiceMP3::gstTextpadHasCAPS_synced(GstPad *pad) { GstCaps *caps; g_object_get (G_OBJECT (pad), "caps", &caps, NULL); -// eDebug("gstGhostpadHasCAPS:: signal::caps = %s", gst_caps_to_string(caps)); + eDebug("gstTextpadHasCAPS:: signal::caps = %s", gst_caps_to_string(caps)); if (caps) { @@ -1810,8 +1599,7 @@ void eServiceMP3::gstGhostpadHasCAPS_synced(GstPad *pad) gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); subs.language_code = std::string(g_lang); - GstPad *ghostpad = gst_element_get_static_pad(m_gst_subtitlebin, "sink"); - subs.type = getSubtitleType(ghostpad); + subs.type = getSubtitleType(pad); if (!m_subtitleStreams.empty()) m_subtitleStreams[m_currentSubtitleStream] = subs; @@ -1823,127 +1611,18 @@ void eServiceMP3::gstGhostpadHasCAPS_synced(GstPad *pad) // eDebug("gstGhostpadHasCAPS:: m_gst_prev_subtitle_caps=%s equal=%i",gst_caps_to_string(m_gst_prev_subtitle_caps),gst_caps_is_equal(m_gst_prev_subtitle_caps, caps)); - if (!GST_PAD_CAPS (pad) || !gst_caps_is_equal (m_gst_prev_subtitle_caps, caps)) - gstGhostpadLink(this, caps); - - m_gst_prev_subtitle_caps = gst_caps_copy(caps); - gst_caps_unref (caps); } gst_object_unref (pad); } -GstFlowReturn eServiceMP3::gstGhostpadChainFunction(GstPad * pad, GstBuffer * buffer) -{ - GstFlowReturn ret = GST_FLOW_OK; - - eServiceMP3 *_this = (eServiceMP3*)g_object_get_data (G_OBJECT (pad), "application-instance"); - -// gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); -// gint64 duration_ns = GST_BUFFER_DURATION(buffer); - size_t len = GST_BUFFER_SIZE(buffer); - - unsigned char line[len+1]; - memcpy(line, GST_BUFFER_DATA(buffer), len); - line[len] = 0; -// eDebug("gstGhostpadChainFunction buffer: '%s' caps: %s ", line, gst_caps_to_string(GST_BUFFER_CAPS(buffer))); - - ret = _this->m_ghost_pad_chain_function(pad, buffer); -// eDebug("original chain func returns %i", ret); - return ret; -} - - -// void eServiceMP3::gstCBsubtitleLink(GObject *obj, GParamSpec *pspec, gpointer user_data) -// { -// -// eServiceMP3 *_this = (eServiceMP3*)user_data; -// eDebug("gstCBsubtitleCAPS:: m_currentSubtitleStream=%i, m_subtitleStreams.size()=%i", _this->m_currentSubtitleStream, _this->m_subtitleStreams.size()); -// -// if ( _this->m_currentSubtitleStream >= (int)_this->m_subtitleStreams.size() ) -// { -// eDebug("return invalid stream count"); -// return; -// } -// -// subtitleStream subs = _this->m_subtitleStreams[_this->m_currentSubtitleStream]; -// -// if ( subs.type == stUnknown ) -// { -// GstTagList *tags; -// eDebug("gstCBsubtitleCAPS::m_subtitleStreams[%i].type == stUnknown...", _this->m_currentSubtitleStream); -// -// gchar *g_lang; -// g_signal_emit_by_name (_this->m_gst_playbin, "get-text-tags", _this->m_currentSubtitleStream, &tags); -// -// g_lang = g_strdup_printf ("und"); -// if ( tags && gst_is_tag_list(tags) ) -// gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang); -// subs.language_code = std::string(g_lang); -// -// subs.type = getSubtitleType(GST_PAD(obj)); -// -// _this->m_subtitleStreams[_this->m_currentSubtitleStream] = subs; -// -// g_free (g_lang); -// } -// -// gstCBsubtitleLink(subs.type, _this); -// } - -// void eServiceMP3::gstCBsubtitleLink(subtype_t type, gpointer user_data) -// { -// eServiceMP3 *_this = (eServiceMP3*)user_data; -// -// if ( type == stVOB ) -// { -// GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); -// GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); -// GstPad *subdecsinkpad = gst_element_get_static_pad (dvdsubdec, "sink"); -// int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, subdecsinkpad); -// GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); -// ret += gst_element_link(dvdsubdec, appsink); -// eDebug("gstCBsubtitleLink:: dvdsubdec=%p, subdecsinkpad=%p, ghostpad=%p, set target & link=%i", dvdsubdec, subdecsinkpad, ghostpad, ret); -// } -// else if ( type < stVOB && type > stUnknown ) -// { -// GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink"); -// GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink"); -// GstPad *appsinkpad = gst_element_get_static_pad (appsink, "sink"); -// GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder"); -// gst_element_unlink(dvdsubdec, appsink); -// int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, appsinkpad); -// eDebug("gstCBsubtitleLink:: appsink=%p, appsinkpad=%p, ghostpad=%p, set target=%i", appsink, appsinkpad, ghostpad, ret); -// } -// else -// { -// eDebug("gstCBsubtitleLink:: unsupported subtitles"); -// } -// } -/* -gboolean eServiceMP3::gstCBsubtitleDrop(GstPad *pad, GstBuffer *buffer, gpointer user_data) -{ - eDebug("gstCBsubtitleDrop"); - - gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); - gint64 duration_ns = GST_BUFFER_DURATION(buffer); - size_t len = GST_BUFFER_SIZE(buffer); - - unsigned char line[len+1]; - memcpy(line, GST_BUFFER_DATA(buffer), len); - line[len] = 0; - eDebug("dropping buffer '%s' ", line); - return false; -}*/ - - void eServiceMP3::pullSubtitle() { - GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_subtitlebin), "subtitle_sink"); -// GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink"); - - if (appsink) + GstElement *sink; + g_object_get (G_OBJECT (m_gst_playbin), "text-sink", &sink, NULL); + + if (sink) { while (m_subs_to_pull && m_subtitle_pages.size() < 2) { @@ -1951,7 +1630,7 @@ void eServiceMP3::pullSubtitle() { eSingleLocker l(m_subs_to_pull_lock); --m_subs_to_pull; - g_signal_emit_by_name (appsink, "pull-buffer", &buffer); + g_signal_emit_by_name (sink, "pull-buffer", &buffer); } if (buffer) { @@ -1978,19 +1657,6 @@ void eServiceMP3::pullSubtitle() if (m_subtitle_pages.size()==1) pushSubtitles(); } - else if ( m_subtitleStreams[m_currentSubtitleStream].type == stVOB ) - { - SubtitlePage page; - eDebug("got new subpicture @ buf_pos = %lld ns (in pts=%lld), duration=%lld ns, len=%i bytes. ", buf_pos, buf_pos/11111, duration_ns, len); - page.type = SubtitlePage::Vob; - page.vob_page.m_pixmap = new gPixmap(eSize(720, 576), 32, 1); - memcpy(page.vob_page.m_pixmap->surface->data, GST_BUFFER_DATA(buffer), len); - page.vob_page.m_show_pts = buf_pos / 11111L; - page.vob_page.m_timeout = duration_ns / 1000; - m_subtitle_pages.push_back(page); - if (m_subtitle_pages.size()==1) - pushSubtitles(); - } else { eDebug("unsupported subpicture... ignoring"); @@ -1999,7 +1665,7 @@ void eServiceMP3::pullSubtitle() gst_buffer_unref(buffer); } } - gst_object_unref(appsink); + gst_object_unref(sink); } else eDebug("no subtitle sink!"); @@ -2012,7 +1678,7 @@ void eServiceMP3::pushSubtitles() SubtitlePage &frontpage = m_subtitle_pages.front(); pts_t running_pts; gint64 diff_ms = 0; - gint64 show_pts; + gint64 show_pts = 0; getPlayPosition(running_pts); @@ -2033,8 +1699,6 @@ void eServiceMP3::pushSubtitles() if (frontpage.type == SubtitlePage::Pango) show_pts = frontpage.pango_page.m_show_pts; - else - show_pts = frontpage.vob_page.m_show_pts; diff_ms = ( show_pts - running_pts ) / 90; eDebug("check subtitle: decoder: %lld, show_pts: %lld, diff: %lld ms", running_pts/90, show_pts/90, diff_ms); @@ -2057,12 +1721,6 @@ void eServiceMP3::pushSubtitles() eDebug("show!\n"); if ( frontpage.type == SubtitlePage::Pango) m_subtitle_widget->setPage(frontpage.pango_page); - else - { - m_subtitle_widget->setPixmap(frontpage.vob_page.m_pixmap, eRect(0, 0, 720, 576)); - eDebug("blit vobsub pixmap... hide in %i ms", frontpage.vob_page.m_timeout); - m_subtitle_hide_timer->start(frontpage.vob_page.m_timeout, true); - } m_subtitle_widget->show(); } m_subtitle_pages.pop_front(); @@ -2072,16 +1730,10 @@ void eServiceMP3::pushSubtitles() pullSubtitle(); } -void eServiceMP3::hideSubtitles() -{ -// eDebug("eServiceMP3::hideSubtitles()"); - if ( m_subtitle_widget ) - m_subtitle_widget->hide(); -} RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) { -// eDebug ("eServiceMP3::enableSubtitles m_currentSubtitleStream=%i this=%p",m_currentSubtitleStream, this); + eDebug ("eServiceMP3::enableSubtitles m_currentSubtitleStream=%i this=%p",m_currentSubtitleStream, this); ePyObject entry; int tuplesize = PyTuple_Size(tuple); int pid, type; @@ -2106,11 +1758,10 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) goto error_out; type = PyInt_AsLong(entry); -// eDebug ("eServiceMP3::enableSubtitles new pid=%i",pid); if (m_currentSubtitleStream != pid) { g_object_set (G_OBJECT (m_gst_playbin), "current-text", pid, NULL); -// eDebug ("eServiceMP3::enableSubtitles g_object_set current-text = %i", pid); + eDebug ("eServiceMP3::enableSubtitles g_object_set current-text = %i", pid); m_currentSubtitleStream = pid; m_subs_to_pull = 0; m_prev_decoder_time = -1; diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index a14a1234..3aeeab16 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -195,59 +195,43 @@ private: enum { stIdle, stRunning, stStopped, - }; - int m_state; - GstElement *m_gst_playbin; - GstElement *m_gst_subtitlebin; - GstTagList *m_stream_tags; - - struct Message - { - Message() - :type(-1) - {} - Message(int type) - :type(type) - {} - Message(int type, GstPad *pad) - :type(type) - { - d.pad=pad; - } - - int type; - union { - GstPad *pad; // for msg type 3 - } d; - }; - - eFixedMessagePump m_pump; - std::string m_error_message; - - audiotype_t gstCheckAudioPad(GstStructure* structure); - void gstBusCall(GstBus *bus, GstMessage *msg); - static GstBusSyncReply gstBusSyncHandler(GstBus *bus, GstMessage *message, gpointer user_data); - static void gstHTTPSourceSetAgent(GObject *source, GParamSpec *unused, gpointer user_data); - static void gstCBsubtitleAvail(GstElement *element, gpointer user_data); - static GstCaps* gstGhostpadGetCAPS (GstPad * pad); - static gboolean gstGhostpadAcceptCAPS(GstPad * pad, GstCaps * caps); - static void gstGhostpadLink(gpointer user_data, GstCaps * caps); - static GstFlowReturn gstGhostpadBufferAlloc(GstPad *pad, guint64 offset, guint size, GstCaps *caps, GstBuffer **buf); - static void gstGhostpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data); - static gboolean gstGhostpadSinkEvent(GstPad * pad, GstEvent * event); - static GstFlowReturn gstGhostpadChainFunction(GstPad * pad, GstBuffer * buffer); -/* static void gstCBsubtitleCAPS(GObject *obj, GParamSpec *pspec, gpointer user_data); - static void gstCBsubtitleLink(subtype_t type, gpointer user_data); - static gboolean gstCBsubtitleDrop(GstPad *pad, GstBuffer *buffer, gpointer user_data);*/ + }; + int m_state; + GstElement *m_gst_playbin; + GstTagList *m_stream_tags; + + struct Message + { + Message() + :type(-1) + {} + Message(int type) + :type(type) + {} + Message(int type, GstPad *pad) + :type(type) + { + d.pad=pad; + } + + int type; + union { + GstPad *pad; // for msg type 3 + } d; + }; + + eFixedMessagePump m_pump; + std::string m_error_message; + + audiotype_t gstCheckAudioPad(GstStructure* structure); + void gstBusCall(GstBus *bus, GstMessage *msg); + static GstBusSyncReply gstBusSyncHandler(GstBus *bus, GstMessage *message, gpointer user_data); + static void gstTextpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data); + void gstTextpadHasCAPS_synced(GstPad *pad); + static void gstCBsubtitleAvail(GstElement *element, gpointer user_data); + GstPad* gstCreateSubtitleSink(eServiceMP3* _this, subtype_t type); void gstPoll(const Message&); - void gstGhostpadHasCAPS_synced(GstPad *pad); - - GstPadBufferAllocFunction m_ghost_pad_buffer_alloc; - GstPadChainFunction m_ghost_pad_chain_function; - GstPadEventFunction m_ghost_pad_subtitle_sink_event; - GstCaps *m_gst_prev_subtitle_caps; - GstSegment m_gst_subtitle_segment; - GstPadEventFunction m_gst_sink_event; + static void gstHTTPSourceSetAgent(GObject *source, GParamSpec *unused, gpointer user_data); struct SubtitlePage { @@ -256,19 +240,18 @@ private: eVobSubtitlePage vob_page; }; - std::list m_subtitle_pages; - ePtr m_subtitle_sync_timer; - ePtr m_subtitle_hide_timer; - ePtr m_streamingsrc_timeout; - pts_t m_prev_decoder_time; - int m_decoder_time_valid_state; - - void pushSubtitles(); - void pullSubtitle(); - void hideSubtitles(); - void sourceTimeout(); - int m_subs_to_pull; - sourceStream m_sourceinfo; + std::list m_subtitle_pages; + ePtr m_subtitle_sync_timer; + + ePtr m_streamingsrc_timeout; + pts_t m_prev_decoder_time; + int m_decoder_time_valid_state; + + void pushSubtitles(); + void pullSubtitle(); + void sourceTimeout(); + int m_subs_to_pull; + sourceStream m_sourceinfo; eSingleLock m_subs_to_pull_lock; gulong m_subs_to_pull_handler_id; -- cgit v1.2.3 From 706a18038f5da82d10529188e699e37bb4a9f76a Mon Sep 17 00:00:00 2001 From: ghost Date: Mon, 13 Dec 2010 12:15:20 +0100 Subject: disable debug output, remove SRT workaround refs #537 --- lib/service/servicemp3.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index 31ae9573..04b1773f 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -362,10 +362,6 @@ eServiceMP3::eServiceMP3(eServiceReference ref) { eDebug("eServiceMP3::subtitle uri: %s", g_filename_to_uri(srt_filename, NULL, NULL)); g_object_set (G_OBJECT (m_gst_playbin), "suburi", g_filename_to_uri(srt_filename, NULL, NULL), NULL); - subtitleStream subs; - subs.type = stSRT; - subs.language_code = std::string("und"); - m_subtitleStreams.push_back(subs); } } else { @@ -1171,7 +1167,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) source = GST_MESSAGE_SRC(msg); sourceName = gst_object_get_name(source); -#if 1 +#if 0 if (gst_message_get_structure(msg)) { gchar *string = gst_structure_to_string(gst_message_get_structure(msg)); @@ -1374,8 +1370,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) g_signal_emit_by_name (m_gst_playbin, "get-text-pad", i, &pad); if ( pad ) g_signal_connect (G_OBJECT (pad), "notify::caps", G_CALLBACK (gstTextpadHasCAPS), this); - if ( subs.type != stSRT ) - subs.type = getSubtitleType(pad, g_codec); + subs.type = getSubtitleType(pad, g_codec); m_subtitleStreams.push_back(subs); g_free (g_lang); -- cgit v1.2.3 From f2381d07785eb22548298f3b3b268c986ab1c882 Mon Sep 17 00:00:00 2001 From: ghost Date: Mon, 13 Dec 2010 12:05:33 +0100 Subject: dont show unsupported subtitles in subtitle list (refs #537) --- lib/service/servicemp3.cpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'lib/service/servicemp3.cpp') diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index 04b1773f..dc84b428 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -1806,15 +1806,25 @@ PyObject *eServiceMP3::getSubtitleList() for (std::vector::iterator IterSubtitleStream(m_subtitleStreams.begin()); IterSubtitleStream != m_subtitleStreams.end(); ++IterSubtitleStream) { subtype_t type = IterSubtitleStream->type; - ePyObject tuple = PyTuple_New(5); -// eDebug("eServiceMP3::getSubtitleList idx=%i type=%i, code=%s", stream_idx, int(type), (IterSubtitleStream->language_code).c_str()); - PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(2)); - PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(stream_idx)); - PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(int(type))); - PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(0)); - PyTuple_SET_ITEM(tuple, 4, PyString_FromString((IterSubtitleStream->language_code).c_str())); - PyList_Append(l, tuple); - Py_DECREF(tuple); + switch(type) + { + case stUnknown: + case stVOB: + case stPGS: + break; + default: + { + ePyObject tuple = PyTuple_New(5); +// eDebug("eServiceMP3::getSubtitleList idx=%i type=%i, code=%s", stream_idx, int(type), (IterSubtitleStream->language_code).c_str()); + PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(2)); + PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(stream_idx)); + PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(int(type))); + PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(0)); + PyTuple_SET_ITEM(tuple, 4, PyString_FromString((IterSubtitleStream->language_code).c_str())); + PyList_Append(l, tuple); + Py_DECREF(tuple); + } + } stream_idx++; } eDebug("eServiceMP3::getSubtitleList finished"); -- cgit v1.2.3