diff options
author | methodus <methodus@web.de> | 2012-10-15 00:40:17 +0200 |
---|---|---|
committer | methodus <methodus@web.de> | 2012-10-15 00:40:17 +0200 |
commit | 9a99d7295fc3ac0cda69e695a6286cddd2fe587d (patch) | |
tree | 1877ed577c77992954a7abb4015355ab0707140a | |
parent | 9477809ce23623f1ad9da06482d9b4c0ff045445 (diff) | |
download | vdr-plugin-upnp-9a99d7295fc3ac0cda69e695a6286cddd2fe587d.tar.gz vdr-plugin-upnp-9a99d7295fc3ac0cda69e695a6286cddd2fe587d.tar.bz2 |
Continued recProvider to stream recordings. Finished vdrDVBProfiler. It detects Codec without ffmpeg.
-rw-r--r-- | media/mediaManager.cpp | 2 | ||||
-rw-r--r-- | plugins/profiler/vdrDVBProfiler/dvbProfiler.cpp | 103 | ||||
-rw-r--r-- | plugins/provider/recProvider/recProvider.cpp | 121 |
3 files changed, 202 insertions, 24 deletions
diff --git a/media/mediaManager.cpp b/media/mediaManager.cpp index 01fdea7..25e44f1 100644 --- a/media/mediaManager.cpp +++ b/media/mediaManager.cpp @@ -906,7 +906,7 @@ bool cMediaManager::RefreshObject(cMetadata& metadata){ .setString("protocolInfo", (*it).GetProtocolInfo()); ((*it).GetSize()) ? - resourcestmt2.setInt("size",(*it).GetSize()) : + resourcestmt2.setLong("size",(*it).GetSize()) : resourcestmt2.setNull("size"); (!(*it).GetDuration().empty()) ? diff --git a/plugins/profiler/vdrDVBProfiler/dvbProfiler.cpp b/plugins/profiler/vdrDVBProfiler/dvbProfiler.cpp index a54c1af..35c754f 100644 --- a/plugins/profiler/vdrDVBProfiler/dvbProfiler.cpp +++ b/plugins/profiler/vdrDVBProfiler/dvbProfiler.cpp @@ -8,10 +8,12 @@ #include <tools/codec.h> #include <server.h> #include <webserver.h> +#include <vdr/videodir.h> #include <vdr/recording.h> #include <vdr/channels.h> #include <vdr/epg.h> #include <vdr/tools.h> +#include <vdr/remux.h> #include <plugin.h> #include <tools.h> #include <string> @@ -48,41 +50,107 @@ public: private: - virtual bool GetRecordingMetadata(const string& uri, cMetadata& metadata){ - cRecording* recording = Recordings.GetByName(uri.substr(6).c_str()); + bool GetRecordingMetadata(const string& u, cMetadata& metadata){ + string videoDir = string(VideoDirectory), uri = u.substr(6), recStr = videoDir + "/" + uri; + cRecording* recording = Recordings.GetByName(recStr.c_str()); if(!recording) return false; - string parentUri = recording->FileName(); + char* fileBuf = strdup(recording->Name()); + fileBuf = ExchangeChars(fileBuf, true); + string fs = fileBuf; + free(fileBuf); + + int pos = 0; + if((pos = fs.find_last_of('/')) != string::npos){ + fs = fs.substr(0,pos+1); + } else { + fs = ""; + } + fs = u.substr(0,6) + fs; const cRecordingInfo* info = recording->Info(); metadata.SetObjectIDByUri(uri); - metadata.SetParentIDByUri(parentUri); + metadata.SetParentIDByUri(fs); metadata.SetProperty(cMetadata::Property(property::object::KEY_CLASS, string("object.item.videoItem.videoBroadcast"))); metadata.SetProperty(cMetadata::Property(property::object::KEY_RESTRICTED, true)); - metadata.SetProperty(cMetadata::Property(property::object::KEY_TITLE, string(info->Title()))); - metadata.SetProperty(cMetadata::Property(property::object::KEY_DESCRIPTION, string(info->ShortText()))); - metadata.SetProperty(cMetadata::Property(property::object::KEY_LONG_DESCRIPTION, string(info->Description()))); + metadata.SetProperty(cMetadata::Property(property::object::KEY_TITLE, string(info->Title()?info->Title():recording->Title()))); + metadata.SetProperty(cMetadata::Property(property::object::KEY_DESCRIPTION, string(info->ShortText()?info->ShortText():""))); + metadata.SetProperty(cMetadata::Property(property::object::KEY_LONG_DESCRIPTION, string(info->Description()?info->Description():""))); boost::posix_time::ptime date = boost::posix_time::from_time_t(info->GetEvent()->StartTime()); metadata.SetProperty(cMetadata::Property(property::object::KEY_DATE, boost::gregorian::to_iso_extended_string(date.date()))); -// cMetadata::Resource resource; -// -// codec::cFormatContext formatContext; -// -// if(formatContext.Open(recording->FileName())){ -// -// } -// -// metadata.AddResource(resource); + cMetadata::Resource resource; + + char filename[1024]; strncpy(filename, recording->FileName(), 1024); + char* pFileNumber = filename + strlen(filename); + sprintf(pFileNumber, "/%05d.ts", 1); + FILE *fd = fopen(filename, "r"); + if(!fd) return false; + + int pmtV, patV, pid; + unsigned char buf[TS_SIZE]; + cPatPmtParser parser; + while(fread(buf, 1, TS_SIZE, fd) == TS_SIZE){ + if(buf[0] == TS_SYNC_BYTE){ + pid = TsPid(buf); + if(pid == 0){ + parser.ParsePat(buf, TS_SIZE); + } else if (pid == parser.PmtPid()) { + parser.ParsePmt(buf, TS_SIZE); + if(parser.GetVersions(patV, pmtV)) + break; + } + } + } + fclose(fd); + + int i = 1; + uint32_t size = 0; + + sprintf(pFileNumber, "/%05d.ts", i); + while(access(filename, F_OK) == 0){ + fd = fopen(filename, "r"); + fseek(fd, 0, SEEK_END); + size += ftell(fd); + sprintf(pFileNumber, "/%05d.ts", ++i); + fclose(fd); + } + + // TODO: implement check for radio stations + DLNA4thField fourthfield; + switch (parser.Vtype()) { + case 0x02: + fourthfield = DLNA4thField("MPEG_TS_SD_EU_ISO", DLNA_OPERATION_RANGE, + DLNA_PLAYSPEEDS_NONE, DLNA_CONVERSION_NONE, + DLNA_FLAG_STREAMING_TRANSFER | + DLNA_FLAG_BYTE_BASED_SEEK | + DLNA_FLAG_VERSION_1_5 ); + break; + case 0x1B: + fourthfield = DLNA4thField("AVC_TS_HD_EU_ISO", DLNA_OPERATION_RANGE, + DLNA_PLAYSPEEDS_NONE, DLNA_CONVERSION_NONE, + DLNA_FLAG_STREAMING_TRANSFER | + DLNA_FLAG_BYTE_BASED_SEEK | + DLNA_FLAG_VERSION_1_5 ); + break; + default: + return false; + } + + resource.SetSize(size); + resource.SetResourceUri(u); + resource.SetProtocolInfo(ProtocolInfo("video/mpeg", fourthfield).ToString()); + + metadata.AddResource(resource); return true; } - virtual bool GetChannelMetadata(const string& uri, cMetadata& metadata){ + bool GetChannelMetadata(const string& uri, cMetadata& metadata){ tChannelID channelID = tChannelID::FromString(uri.substr(6).c_str()); if(!channelID.Valid()) return false; @@ -151,7 +219,6 @@ private: break; default: return false; - break; } resource.SetProtocolInfo(ProtocolInfo("video/mpeg", fourthfield).ToString()); diff --git a/plugins/provider/recProvider/recProvider.cpp b/plugins/provider/recProvider/recProvider.cpp index 3a7d8ce..55d465c 100644 --- a/plugins/provider/recProvider/recProvider.cpp +++ b/plugins/provider/recProvider/recProvider.cpp @@ -45,9 +45,55 @@ private: return false; } + FILE* fileFD; + int currentFileNumber; + int lastFileNumber; + string filename; + vector<size_t> offsets; + + void CloseFile(){ + fclose(fileFD); + fileFD = NULL; + } + + bool OpenFile(int i = 1){ + static int fileNumber = i; + + if(fileNumber != i && fileFD){ + CloseFile(); + } + + char fileBuf[1024]; strncpy(fileBuf, filename.c_str(), 1024); + char* pFileNumber = fileBuf + strlen(fileBuf); + sprintf(pFileNumber, "/%05d.ts", fileNumber); + + fileFD = fopen(fileBuf, "r"); + if(!fileFD) return false; + + currentFileNumber = i; + return true; + } + + bool OpenNext(){ + return OpenFile(++currentFileNumber); + } + + bool ScanFiles(){ + if(!OpenFile(1)) return false; + do { + fseek(fileFD, 0, SEEK_END); + offsets[currentFileNumber-1] = ftell(fileFD); + } while(OpenNext()); + lastFileNumber = currentFileNumber; + return OpenFile(1); + } + public: RecProvider() + : fileFD(NULL) + , currentFileNumber(1) + , offsets(65536) { } @@ -65,13 +111,14 @@ public: if(!IsRootContainer(u)) return StringList(); StringList list; - string videoDir(VideoDirectory); string fs, uri = u.substr(6); - int pos, vl = videoDir.length(), ul = uri.length(), vul = vl + ul + 1; + string videoDir(VideoDirectory), fs, uri = u.substr(6); + int pos = 0, vl = videoDir.length(), ul = uri.length(), vul = vl + ul + 1; for(cRecording* rec = Recordings.First(); rec; rec = Recordings.Next(rec)){ char* file = strdup(rec->Name()); file = ExchangeChars(file, true); fs = file; + free(file); if(fs.find(uri) != string::npos){ fs = fs.substr(ul); if((pos = fs.find_first_of('/')) != string::npos){ @@ -81,7 +128,6 @@ public: } list.push_back(fs); } - free(file); } return list; @@ -93,8 +139,12 @@ public: stringstream filename; filename << VideoDirectory << "/" << uri.substr(6); - if(!Recordings.GetByName(filename.str().c_str())) return true; - else return false; + if(!Recordings.GetByName(filename.str().c_str())){ + return true; + } + else { + return false; + } } virtual bool IsLink(const string& uri, string& target){ @@ -139,6 +189,67 @@ public: return true; } + virtual bool Open(const string& uri){ + filename = uri.substr(6); + currentFileNumber = 1; + return ScanFiles(); + } + + virtual size_t Read(char* buf, size_t bufLen){ + if(!fileFD) return -1; + + char secondBuf[bufLen]; + + size_t bytesRead = 0; + + bytesRead += fread(secondBuf, 1, bufLen, fileFD); + if(bytesRead != bufLen && OpenNext()){ + bytesRead += fread(secondBuf + bytesRead, 1, bufLen - bytesRead, fileFD); + } + + return bytesRead; + } + + virtual bool Seek(size_t offset, int origin){ + if(!fileFD) return false; + + off_t curpos = fseek(fileFD, 0, SEEK_CUR); // this should not change anything + switch(origin){ + case SEEK_END: + offset = offsets[lastFileNumber] + offset; + break; + case SEEK_CUR: + offset = offsets[currentFileNumber-1] + curpos + offset; + break; + case SEEK_SET: + // Nothing to change + break; + default: + return false; + } + + if(!OpenFile(1)) return false; + size_t size = 0; + while(true){ + fseek(fileFD, 0, SEEK_END); + size = ftell(fileFD); + if(offset < size){ + return fseek(fileFD, offset, SEEK_SET) == 0; + } else { + offset -= size; + if(OpenNext()) return false; + } + } + + return false; + + } + + virtual void Close(){ + currentFileNumber = 1; + CloseFile(); + } + virtual void Action(){ while(Running()){ int state = 0; |