Muss das extern "C" dort weg, oder wie bekomme ich das gelöst?
Wenn du die Funktion überall mit extern "C" deklarierst, dann sollte es auch gehen.
Gerald
Muss das extern "C" dort weg, oder wie bekomme ich das gelöst?
Wenn du die Funktion überall mit extern "C" deklarierst, dann sollte es auch gehen.
Gerald
Irgendwie steh ich grad aufm Schlauch oder es ist schon spät. Ich nutze das Makro in den Plugins, wie das der VDR mit seinen Plugins auch tut. Welche Funktion muss mit extern "C" deklariert werden?
Irgendwie steh ich grad aufm Schlauch oder es ist schon spät. Ich nutze das Makro in den Plugins, wie das der VDR mit seinen Plugins auch tut. Welche Funktion muss mit extern "C" deklariert werden?
Na ja, ich kenne deinen Code nicht, aber irgendwo greift jemand auf eine Funktion zu die als extern "C" deklariert wurde, aber der Aufrufer weiß nichts davon. Das bekommst du schon raus. Ich bin auch totmüde.
Gerald
Ich habe es leider nicht geschafft. Der Fehler kommt immer noch. Ich habe mit nm mir folgenden Output liefern lassen:
nm plugins/provider/vdrProvider/libupnp-vdr-provider.so -DC
U Channels
U SysLogLevel
0000000000001800 T UPnPCreateResourceProvider
w _Jv_RegisterClasses
U _Unwind_Resume
U syslog_with_tid(int, char const*, ...)
00000000000018b0 W upnp::VdrProvider::GetHTTPUri(std::string const&, std::string const&)
0000000000001970 W upnp::VdrProvider::GetMetadata(std::string const&, upnp::cMetadata&)
0000000000001a30 W upnp::VdrProvider::IsContainer(std::string const&)
0000000000001880 W upnp::VdrProvider::ProvidesSchema()
0000000000001b00 W upnp::VdrProvider::GetRootContainer()
0000000000001c60 W upnp::VdrProvider::GetContainerEntries(std::string const&)
0000000000001840 W upnp::VdrProvider::GetContainerUpdateId(std::string const&)
0000000000001830 W upnp::VdrProvider::IsLink(std::string const&, std::string&)
0000000000001860 W upnp::VdrProvider::~VdrProvider()
0000000000001850 W upnp::VdrProvider::~VdrProvider()
0000000000001850 W upnp::VdrProvider::~VdrProvider()
U upnp::cUPnPResourceProvider::Open(std::string const&)
U upnp::cUPnPResourceProvider::Read(char*, unsigned long)
U upnp::cUPnPResourceProvider::Seek(unsigned long, int)
U upnp::cUPnPResourceProvider::Close()
U cString::~cString()
U cChannels::GetNextNormal(int)
U tChannelID::ToString() const
U upnp::cUPnPResourceProvider::Seekable() const
U cChannel::Transponder() const
U cListBase::Get(int) const
U std::string::find(char const*, unsigned long, unsigned long) const
U std::string::_Rep::_M_destroy(std::allocator<char> const&)
U std::string::_Rep::_S_empty_rep_storage
U std::string::append(char const*, unsigned long)
U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)
U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&)
U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()
0000000000001bb0 W std::_List_base<std::string, std::allocator<std::string> >::~_List_base()
0000000000001bb0 W std::_List_base<std::string, std::allocator<std::string> >::~_List_base()
U std::__detail::_List_node_base::_M_hook(std::__detail::_List_node_base*)
U std::ios_base::Init::Init()
U std::ios_base::Init::~Init()
0000000000202db0 V typeinfo for upnp::VdrProvider
U typeinfo for upnp::cUPnPResourceProvider
0000000000002150 V typeinfo name for upnp::VdrProvider
U vtable for __cxxabiv1::__si_class_type_info
0000000000202d20 V vtable for upnp::VdrProvider
U vtable for upnp::cUPnPResourceProvider
U operator delete(void*)
U operator new(unsigned long)
00000000002030d0 A __bss_start
U __cxa_atexit
U __cxa_begin_catch
U __cxa_end_catch
w __cxa_finalize
U __cxa_rethrow
w __gmon_start__
U __gxx_personality_v0
00000000002030d0 A _edata
00000000002030e8 A _end
00000000000020f8 T _fini
0000000000001558 T _init
U memcmp
w pthread_cancel
Alles anzeigen
Die ganzen Provider-Sachen scheinen tatsächlich zu fehlen oder interpretiere ich die Ausgabe falsch? Wenn ich den gleichen Befehl auf die libvdr-upnp.so mache, sind die ganzen cPlugin-Symbole auch undefiniert. Woran kann es noch alles scheitern?
Edit: Folgende Zeile kommt bei nm auf libvdr-upnp.so:
Die Funktion als solches ist also in der Haupt-SO dabei.
Ich habe die Antwort über stackoverflow erhalten: http://stackoverflow.com/q/12762910/798406
Die Lösung ist noch nicht schon, aber es geht erst einmal. Ein PAtch für den VDR könnte auch helfen, das muss ich allerdings erst einmal testen:
--- vdr-1.7.27_p/plugin.c 2012-07-30 19:55:26.000000000 +0200
+++ vdr-1.7.27/plugin.c 2012-10-04 05:17:57.375774453 +0200
@@ -203,7 +203,7 @@ bool cDll::Load(bool Log)
esyslog("attempt to load plugin '%s' twice!", fileName);
return false;
}
- handle = dlopen(fileName, RTLD_NOW);
+ handle = dlopen(fileName, RTLD_NOW | RTLD_GLOBAL);
const char *error = dlerror();
if (!error) {
void *(*creator)(void);
Alles anzeigen
Senderlogos gehen jetzt auch:
[Blockierte Grafik: http://www.methodus.de/wp-content/gallery/vdr/CameraZOOM-20121014065540032.jpg]
Allerdings habe ich nur sehr wenige Logos, weil zum einen habe ich nur eine ziemlich kleine Auswahl und zum anderen sind in den Sendernamen Leerzeichen. Wie machen hier die Skins das, um die Logos zu laden?
Nächste Frage: wie kann ich aus einer VDR-Aufnahme ein Thumbnail erzeugen und irgendwo zwischenspeichern?
Live-TV geht. Leider muss man, um auf Samsung-Geräten gucken zu können, Streamdev anpassen, da die Samsung-Dinger mit HEAD-Requests arbeiten, was Streamdev noch nicht unterstützt.
Live-TV geht. Leider muss man, um auf Samsung-Geräten gucken zu können, Streamdev anpassen, da die Samsung-Dinger mit HEAD-Requests arbeiten, was Streamdev noch nicht unterstützt.
Das klingt sehr interessant.
Kannst Du sagen, mit welchen TVs ein Live-TV über Dein Plugin möglich ist?
Mit allen, die MPEG_TS_SD_EU_ISO bzw. AVC_TS_HD_EU_ISO verstehen. Das sollten eigentlich 90% aller TV-Geräte können.
Wenn die das nicht können, wäre ein transcoding notwendig, was über die externremux des streamdev eigentlich dann auch möglich sein sollte. Da brauch ich aber input, welche Formate man da am besten anspricht.
edit: also mein Motorola Defy kanns schonmal nicht abspielen mit der eingebauten DLNA-App.. vielleicht bekomme ich das noch raus, welches Transkoding hier notwendig ist.
Ich wieder... es gibt mal wieder ein Problem: ich versuche momentan die VDR-Aufnahmen mit der Serienstruktur zu scannen, aber habe Schwierigkeiten zu erkennen, ob die aktuelle Aufnahme ein Verzeichnis enthält oder eine Aufnahme selbst und nicht weiter gescannt werden muss.
Ich habe folgenden Code:
virtual StringList GetContainerEntries(const string& uri){
cerr << "Getting container entries for recordings in " << uri << endl;
if(!IsRootContainer(uri)) return StringList();
StringList list;
string videoDir(VideoDirectory), file;
int l = videoDir.length();
for(cRecording* rec = Recordings.First(); rec; rec = Recordings.Next(rec)){
file = rec->FileName()+l+1;
if(file.find(uri.substr(6),0) == 0){
if(strcmp(rec->Title(' ', false, GetLevel(uri)+2),"") != 0){
char* filename = strdup(rec->Name());
filename = ExchangeChars(filename, true);
cerr << "URI " << GetByLevel(filename, GetLevel(uri) + 2) << endl;
list.push_back(filename);
free(filename);
} else {
list.push_back(file);
}
}
}
return list;
}
virtual bool IsContainer(const string& uri){
if(GetRootContainer().compare(uri) == 0) return true;
stringstream filename;
filename << VideoDirectory << "/" << uri.substr(6);
if(!Recordings.GetByName(filename.str().c_str())) return true;
else return false;
}
Alles anzeigen
Die IsContainer scheint theoretisch zu funktionieren, aber die GetContainerEntries ist murks. Ich hab jetzt 3 Tage dran gesessen und komme nicht weiter. Wer kann mir weiter helfen? Die übergebe URI wird bei jedem Aufruf um den Teil, der in der Liste zurückgegeben wird, erweitert. Also zum Beispiel:
1. Aufruf:
rec://
list: Matrix/xxx.rec, 8_Mile/xxx.rec, Illuminati/xxx.rec, Bob_Ross
Bob_Ross ist eine Serie
2. Aufruf
rec://Bob_Ross
list: Autumn, Spring
3. Aufruf
rec://Bob_Ross/Spring... usw.
Am Ende muss der vollständige Pfadde wie in Recording::Filename() rauskommen, nur ohne VideoDirectory.
Aufnahmen streamen scheint jetzt erstmal zu gehen. Es könnte ja mal jemand ausprobieren (pn an mich, wenn Hilfe bei Bauen oder Installieren notwendig ist). Spulen geht noch nicht, da ich mir das erstmal angucken muss, was DLNA da genau haben will.
Wenn jemand unter euch sein sollte, der weiß, wie TimeBased-Seek funktioniert, würde ich mich freuen, wenn er sich bei mir meldet.
Du willst den Stream ab einer bestimmten Zeit abspielen?
Dafür mußt du den Stream analysieren um Bytes / Sekunde herauszubekommen.
Einfach ist wenn du die Gesamtlänge des Stream kennst.
Gesamt-Größe / Gesamt-Länge = Bytes-pro-Sekunde.
Dann gehst im File an die Postion, suchst den nächsten Zeitstempel und wenn der nicht simmt,
machst eine Binary Suche für den richtigen.
Schwierig wirds wenn es keinen Index und keine Zeitstempel gibt.
Dann kannst die Position einfach als Näherung nehmen oder du
kannst nur im Schnelllauf an die richtige Stelle gehen.
Johns
Hmm.. funktioniert dann nur mit CBR oder?
Ich lese grad, dass der Range-Header in jedem Fall Vorrang hat, falls sowohl TimeBasedSeek und ByteBasedSeek angeboten wird. Da die Samsung-Geräte auch nur mit ByteBasedSeek anfragen, wäre jetzt die Frage an die unter euch, die bereits erfolgreich mit anderen DLNA-Servern Aufnahmen streamen und spulen können: Mit was fragt euer TV beim Server an? Könnt ihr mir Traces dazu geben?
Wenn du eine Zeitinformation hast, entweder über einen Index oder Timestemps, dann klappt es auch mit CBR.
Nur mußt du dann bei Timestamps den richtigen Suchen.
Ansonsten geht nur eine Annäherung schnell.
Johns
Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!