summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormethodus <methodus@web.de>2012-10-15 00:40:17 +0200
committermethodus <methodus@web.de>2012-10-15 00:40:17 +0200
commit9a99d7295fc3ac0cda69e695a6286cddd2fe587d (patch)
tree1877ed577c77992954a7abb4015355ab0707140a
parent9477809ce23623f1ad9da06482d9b4c0ff045445 (diff)
downloadvdr-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.cpp2
-rw-r--r--plugins/profiler/vdrDVBProfiler/dvbProfiler.cpp103
-rw-r--r--plugins/provider/recProvider/recProvider.cpp121
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;