From d48d64273d5da9bf596b239bb0aec622086655f0 Mon Sep 17 00:00:00 2001 From: thlo Date: Sun, 17 Mar 2013 09:28:01 +0100 Subject: v0.9.6. Use UrlEncoding for guid. Determine Bitrate from file size. --- vdr-smarttvweb/httpresource.c | 52 ++++++++++++++++++++++++++++++----------- vdr-smarttvweb/httpresource.h | 5 ++-- vdr-smarttvweb/smarttvfactory.c | 8 +++---- vdr-smarttvweb/smarttvfactory.h | 5 ++-- vdr-smarttvweb/smarttvweb.conf | 4 ++-- vdr-smarttvweb/stvw_cfg.c | 10 ++++---- vdr-smarttvweb/stvw_cfg.h | 4 ++-- 7 files changed, 55 insertions(+), 33 deletions(-) diff --git a/vdr-smarttvweb/httpresource.c b/vdr-smarttvweb/httpresource.c index 84e6b06..79d39bc 100755 --- a/vdr-smarttvweb/httpresource.c +++ b/vdr-smarttvweb/httpresource.c @@ -1135,7 +1135,9 @@ int cHttpResource::sendManifest (struct stat *statbuf, bool is_hls) { cRecordings* recordings = &Recordings; cRecording* rec = recordings->GetByName(mDir.c_str()); double duration = rec->NumFrames() / rec->FramesPerSecond(); - + + int bitrate = (int)((getVdrFileSize() *8.0 * mFactory->getConfig()->getHasBitrateCorrection()/ duration) +0.5); + time_t now = time(NULL); if (rec->Info() != NULL){ @@ -1159,12 +1161,8 @@ int cHttpResource::sendManifest (struct stat *statbuf, bool is_hls) { // duration is now either the actual duration of the asset or the target duration of the asset int end_seg = int (duration / seg_dur) +1; - // FIXME: Test Only - /* if (rec->FramesPerSecond() > 40) - end_seg = int (duration *2 / seg_dur) +1; -*/ *(mLog->log()) << DEBUGPREFIX - << " m3u8 for mDir= " << mDir + << " Manifest for mDir= " << mDir << " duration= " << duration << " seg_dur= " << seg_dur << " end_seg= " << end_seg @@ -1173,17 +1171,17 @@ int cHttpResource::sendManifest (struct stat *statbuf, bool is_hls) { if (is_hls) { - writeM3U8(duration, seg_dur, end_seg); + writeM3U8(duration, bitrate, seg_dur, end_seg); } else { - writeMPD(duration, seg_dur, end_seg); + writeMPD(duration, bitrate, seg_dur, end_seg); } #endif return OKAY; } -void cHttpResource::writeM3U8(double duration, float seg_dur, int end_seg) { +void cHttpResource::writeM3U8(double duration, int bitrate, float seg_dur, int end_seg) { mResponseMessage = new string(); mResponseMessagePos = 0; *mResponseMessage = ""; @@ -1219,7 +1217,8 @@ void cHttpResource::writeM3U8(double duration, float seg_dur, int end_seg) { sendHeaders(200, "OK", NULL, "application/x-mpegURL", mResponseMessage->size(), -1); } -void cHttpResource::writeMPD(double duration, float seg_dur, int end_seg) { + +void cHttpResource::writeMPD(double duration, int bitrate, float seg_dur, int end_seg) { mResponseMessage = new string(); mResponseMessagePos = 0; *mResponseMessage = ""; @@ -1243,8 +1242,11 @@ void cHttpResource::writeMPD(double duration, float seg_dur, int end_seg) { *mResponseMessage += "\n"; *mResponseMessage += "\n"; *mResponseMessage += "\n"; - - snprintf(line, sizeof(line), "\n", mFactory->getConfig()->getHasBitrate()); + // SD: 720x 576 + // HD: 1280x 720 + // snprintf(line, sizeof(line), "\n", mFactory->getConfig()->getHasBitrate()); + snprintf(line, sizeof(line), "\n", + bitrate, ((bitrate < 10000000)? "width=\"720\" height=\"576\"" : "width=\"1280\" height=\"720\"")); *mResponseMessage = *mResponseMessage + line; hdr = "Name()), link, "NA", desc, - cUrlEncode::doXmlSaveEncode(recording->FileName()).c_str(), + cUrlEncode::doUrlSaveEncode(recording->FileName()).c_str(), -1, recording->Start(), rec_dur, recording->FramesPerSecond(), (recording->IsPesRecording() ? 0: 1), (recording->IsNew() ? 0: 1)) == ERROR) @@ -2743,6 +2745,28 @@ string cHttpResource::getOwnIp(int fd) { return string (inet_ntoa(sock.sin_addr)); } +uint64_t cHttpResource::getVdrFileSize() { + // iter over all vdr files and get file size + struct stat statbuf; + string file_structure = "%s/%05d.ts"; // Only ts supported for HLS and HAS + char pathbuf[4096]; + int vdr_idx = 0; + uint64_t total_file_size = 0; + bool more_to_go = true; + + while (more_to_go) { + vdr_idx ++; + snprintf(pathbuf, sizeof(pathbuf), file_structure.c_str(), mDir.c_str(), vdr_idx); + if (stat(pathbuf, &statbuf) >= 0) { + total_file_size += statbuf.st_size; + } + else { + more_to_go = false; + } + } + return total_file_size; +} + int cHttpResource::parseHttpRequestLine(string line) { mMethod = line.substr(0, line.find_first_of(" ")); mRequest = line.substr(line.find_first_of(" ") +1, (line.find_last_of(" ") - line.find_first_of(" ") -1)); diff --git a/vdr-smarttvweb/httpresource.h b/vdr-smarttvweb/httpresource.h index 8185026..fbbab4d 100755 --- a/vdr-smarttvweb/httpresource.h +++ b/vdr-smarttvweb/httpresource.h @@ -154,8 +154,8 @@ class cHttpResource { int receiveResume(); int deleteRecording(); - void writeM3U8(double duration, float seg_dur, int end_seg); - void writeMPD(double duration, float seg_dur, int end_seg); + void writeM3U8(double duration, int bitrate, float seg_dur, int end_seg); + void writeMPD(double duration, int bitrate, float seg_dur, int end_seg); int sendMediaSegment (struct stat *statbuf); @@ -169,6 +169,7 @@ class cHttpResource { const char *getMimeType(const char *name); string getConnStateName(); string getOwnIp(int fd); + uint64_t getVdrFileSize(); void checkRecording(); bool isTimeRequest(struct stat *statbuf); int parseRangeHeaderValue(string); diff --git a/vdr-smarttvweb/smarttvfactory.c b/vdr-smarttvweb/smarttvfactory.c index d0196c9..3478e9d 100755 --- a/vdr-smarttvweb/smarttvfactory.c +++ b/vdr-smarttvweb/smarttvfactory.c @@ -71,7 +71,7 @@ void SmartTvServerStartThread(void* arg) { } SmartTvServer::SmartTvServer(): mRequestCount(0), isInited(false), serverPort(PORT), mServerFd(-1), - mSegmentDuration(10), mHasMinBufferTime(40), mHasBitrate(6000000), mLiveChannels(20), + mSegmentDuration(10), mHasMinBufferTime(40), mLiveChannels(20), clientList(), mActiveSessions(0), mConfig(NULL) { } @@ -214,8 +214,8 @@ void SmartTvServer::loop() { << " --------------------- Received connection ---------------------" << endl; #endif - FD_SET(rfd, &mReadState); /* neuen Client fd dazu */ - FD_SET(rfd, &mWriteState); /* neuen Client fd dazu */ + FD_SET(rfd, &mReadState); + FD_SET(rfd, &mWriteState); if (rfd > maxfd) { maxfd = rfd; @@ -225,7 +225,6 @@ void SmartTvServer::loop() { clientList.resize(rfd+1, NULL); // Check. } clientList[rfd] = new cHttpResource(rfd, req_id, serverPort, this); - // clientList[rfd] = new cHttpResource(rfd, req_id, mOwnIp, serverPort, this); mActiveSessions ++; *(mLog.log()) << " + mActiveSessions= " << mActiveSessions << endl; } @@ -352,7 +351,6 @@ void SmartTvServer::initServer(string dir) { mSegmentDuration= mConfig->getSegmentDuration(); mHasMinBufferTime= mConfig->getHasMinBufferTime(); - mHasBitrate = mConfig->getHasBitrate(); mLiveChannels = mConfig->getLiveChannels(); *(mLog.log()) <<"HTTP server listening on port " << serverPort << endl; diff --git a/vdr-smarttvweb/smarttvfactory.h b/vdr-smarttvweb/smarttvfactory.h index 171b1b8..1073ab0 100644 --- a/vdr-smarttvweb/smarttvfactory.h +++ b/vdr-smarttvweb/smarttvfactory.h @@ -38,8 +38,8 @@ using namespace std; -#define PLG_VERSION "0.9.5" -#define SERVER "SmartTvWeb/0.9.5" +#define PLG_VERSION "0.9.6" +#define SERVER "SmartTvWeb/0.9.6" class SmartTvServer { public: @@ -68,7 +68,6 @@ class SmartTvServer { int mServerFd; unsigned int mSegmentDuration; int mHasMinBufferTime; - unsigned int mHasBitrate; int mLiveChannels; vector clientList; diff --git a/vdr-smarttvweb/smarttvweb.conf b/vdr-smarttvweb/smarttvweb.conf index c9f52ed..07920dc 100644 --- a/vdr-smarttvweb/smarttvweb.conf +++ b/vdr-smarttvweb/smarttvweb.conf @@ -10,8 +10,8 @@ SegmentDuration 10 # minBufferTime value for the DASH MPD HasMinBufferTime 30 -# Bitrate parameter in the DASH MPD -HasBitrate 60000000 +# Bitrate correction parameter for Hls and DASH MPD +HasBitrateCorrection 1.1 # Default number of Live Channel entries included in the channels.xml, when not requested specifically. LiveChannels 30 diff --git a/vdr-smarttvweb/stvw_cfg.c b/vdr-smarttvweb/stvw_cfg.c index e323856..75b8de6 100755 --- a/vdr-smarttvweb/stvw_cfg.c +++ b/vdr-smarttvweb/stvw_cfg.c @@ -32,7 +32,7 @@ #include cSmartTvConfig::cSmartTvConfig(string d): mConfigDir(d), mLog(NULL), mCfgFile(NULL), - mLogFile(), mMediaFolder(), mSegmentDuration(), mHasMinBufferTime(), mHasBitrate(), + mLogFile(), mMediaFolder(), mSegmentDuration(), mHasMinBufferTime(), mHasBitrateCorrection(), mLiveChannels(), mGroupSep(IGNORE), mServerAddress("") { #ifndef STANDALONE @@ -45,7 +45,7 @@ cSmartTvConfig::cSmartTvConfig(string d): mConfigDir(d), mLog(NULL), mCfgFile(NU mMediaFolder= "/hd2/mpeg"; mSegmentDuration = 10; mHasMinBufferTime = 40; - mHasBitrate = 6000000; + mHasBitrateCorrection = 1.1; mLiveChannels = 30; readConfig(); @@ -64,7 +64,7 @@ void cSmartTvConfig::printConfig() { *(mLog->log()) << " MediaFolder:" << mMediaFolder << endl; *(mLog->log()) << " SegmentDuration: " << mSegmentDuration << endl; *(mLog->log()) << " HasMinBufferTime: " << mHasMinBufferTime << endl; - *(mLog->log()) << " HasBitrate: " << mHasBitrate << endl; + *(mLog->log()) << " HasBitrateCorrection: " << mHasBitrateCorrection << endl; *(mLog->log()) << " LiveChannels: " << mLiveChannels << endl; *(mLog->log()) << " GroupSeparators: " << ((mGroupSep==IGNORE)? "Ignore" : ((mGroupSep==EMPTYIGNORE)? "EmptyIgnore": "EmptyFolderDown")) << endl; *(mLog->log()) << " ServerAddress: " << mServerAddress << endl; @@ -117,8 +117,8 @@ void cSmartTvConfig::readConfig() { // cout << " Found mHasMinBufferTime= " << mHasMinBufferTime << endl; continue; } - if (strcmp(attr, "HasBitrate") == 0) { - mHasBitrate = atoi(value); + if (strcmp(attr, "HasBitrateCorrection") == 0) { + mHasBitrateCorrection = atof(value); // cout << " Found mHasBitrate= " <