adapted and included xmbc patch for VDR 1.4.x

Modified Files:
 Tag: v0_4
	CONTRIBUTORS HISTORY Makefile common.h server/connectionVTP.c
	server/connectionVTP.h
Added Files:
 Tag: v0_4
	server/recplayer.c server/recplayer.h
This commit is contained in:
schmirl 2009-09-30 10:02:26 +00:00
parent 7ea2353728
commit e0f60bbd81
8 changed files with 1132 additions and 97 deletions

View File

@ -109,3 +109,6 @@ Joachim K
Artem Makhutov Artem Makhutov
for suggesting and heavy testing IGMP based multicast streaming for suggesting and heavy testing IGMP based multicast streaming
pingpong
for adding XBMC support by extending VTP capabilities

View File

@ -1,6 +1,7 @@
VDR Plugin 'streamdev' Revision History VDR Plugin 'streamdev' Revision History
--------------------------------------- ---------------------------------------
- adapted and included xmbc patch for VDR 1.4.x
- cleaned up common.h / common.c - cleaned up common.h / common.c
- dropped cStreamdevMenuSetupPage - dropped cStreamdevMenuSetupPage
- report charset in HTTP replies (suggested by Rolf Ahrenberg) - report charset in HTTP replies (suggested by Rolf Ahrenberg)

View File

@ -1,7 +1,7 @@
# #
# Makefile for a Video Disk Recorder plugin # Makefile for a Video Disk Recorder plugin
# #
# $Id: Makefile,v 1.15.2.2 2009/06/29 06:25:27 schmirl Exp $ # $Id: Makefile,v 1.15.2.3 2009/09/30 10:02:26 schmirl Exp $
# The official name of this plugin. # The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin. # This name will be used in the '-P...' option of VDR to load the plugin.
@ -61,7 +61,7 @@ SERVEROBJS = $(PLUGIN)-server.o \
server/componentVTP.o server/componentHTTP.o server/componentIGMP.o \ server/componentVTP.o server/componentHTTP.o server/componentIGMP.o \
server/connectionVTP.o server/connectionHTTP.o server/connectionIGMP.o \ server/connectionVTP.o server/connectionHTTP.o server/connectionIGMP.o \
server/streamer.o server/livestreamer.o server/livefilter.o \ server/streamer.o server/livestreamer.o server/livefilter.o \
server/suspend.o server/setup.o server/menuHTTP.o \ server/suspend.o server/setup.o server/menuHTTP.o server/recplayer.o \
remux/tsremux.o remux/ts2pes.o remux/ts2ps.o remux/ts2es.o remux/extern.o remux/tsremux.o remux/ts2pes.o remux/ts2ps.o remux/ts2es.o remux/extern.o
ifdef DEBUG ifdef DEBUG

View File

@ -1,5 +1,5 @@
/* /*
* $Id: common.h,v 1.11.2.1 2009/09/18 10:41:11 schmirl Exp $ * $Id: common.h,v 1.11.2.2 2009/09/30 10:02:26 schmirl Exp $
*/ */
#ifndef VDR_STREAMDEV_COMMON_H #ifndef VDR_STREAMDEV_COMMON_H
@ -53,6 +53,7 @@ enum eSocketId {
siLive, siLive,
siReplay, siReplay,
siLiveFilter, siLiveFilter,
siDataRespond,
si_Count si_Count
}; };

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
#define VDR_STREAMDEV_SERVERS_CONNECTIONVTP_H #define VDR_STREAMDEV_SERVERS_CONNECTIONVTP_H
#include "server/connection.h" #include "server/connection.h"
#include "server/recplayer.h"
class cTBSocket; class cTBSocket;
class cStreamdevLiveStreamer; class cStreamdevLiveStreamer;
@ -9,6 +10,7 @@ class cStreamdevFilterStreamer;
class cLSTEHandler; class cLSTEHandler;
class cLSTCHandler; class cLSTCHandler;
class cLSTTHandler; class cLSTTHandler;
class cLSTRHandler;
class cConnectionVTP: public cServerConnection { class cConnectionVTP: public cServerConnection {
friend class cLSTEHandler; friend class cLSTEHandler;
@ -21,16 +23,19 @@ private:
cStreamdevLiveStreamer *m_LiveStreamer; cStreamdevLiveStreamer *m_LiveStreamer;
cTBSocket *m_FilterSocket; cTBSocket *m_FilterSocket;
cStreamdevFilterStreamer *m_FilterStreamer; cStreamdevFilterStreamer *m_FilterStreamer;
cTBSocket *m_RecSocket;
cTBSocket *m_DataSocket;
char *m_LastCommand; char *m_LastCommand;
eStreamType m_StreamType; eStreamType m_StreamType;
bool m_FiltersSupport; bool m_FiltersSupport;
RecPlayer *m_RecPlayer;
// Members adopted for SVDRP // Members adopted for SVDRP
cRecordings Recordings;
cLSTEHandler *m_LSTEHandler; cLSTEHandler *m_LSTEHandler;
cLSTCHandler *m_LSTCHandler; cLSTCHandler *m_LSTCHandler;
cLSTTHandler *m_LSTTHandler; cLSTTHandler *m_LSTTHandler;
cLSTRHandler *m_LSTRHandler;
protected: protected:
template<class cHandler> template<class cHandler>
@ -51,7 +56,9 @@ public:
bool CmdCAPS(char *Opts); bool CmdCAPS(char *Opts);
bool CmdPROV(char *Opts); bool CmdPROV(char *Opts);
bool CmdPORT(char *Opts); bool CmdPORT(char *Opts);
bool CmdREAD(char *Opts);
bool CmdTUNE(char *Opts); bool CmdTUNE(char *Opts);
bool CmdPLAY(char *Opts);
bool CmdADDP(char *Opts); bool CmdADDP(char *Opts);
bool CmdDELP(char *Opts); bool CmdDELP(char *Opts);
bool CmdADDF(char *Opts); bool CmdADDF(char *Opts);
@ -64,14 +71,20 @@ public:
bool CmdLSTE(char *Opts); bool CmdLSTE(char *Opts);
bool CmdLSTC(char *Opts); bool CmdLSTC(char *Opts);
bool CmdLSTT(char *Opts); bool CmdLSTT(char *Opts);
bool CmdLSTR(char *Opts);
// Commands adopted from SVDRP // Commands adopted from SVDRP
bool CmdSTAT(const char *Option);
bool CmdMODT(const char *Option); bool CmdMODT(const char *Option);
bool CmdNEWT(const char *Option); bool CmdNEWT(const char *Option);
bool CmdDELT(const char *Option); bool CmdDELT(const char *Option);
bool CmdNEXT(const char *Option);
//bool CmdLSTR(char *Opts); bool CmdNEWC(const char *Option);
//bool CmdDELR(char *Opts); bool CmdMODC(const char *Option);
bool CmdMOVC(const char *Option);
bool CmdDELC(const char *Option);
bool CmdDELR(const char *Option);
bool CmdRENR(const char *Option);
bool Respond(int Code, const char *Message, ...) bool Respond(int Code, const char *Message, ...)
__attribute__ ((format (printf, 3, 4))); __attribute__ ((format (printf, 3, 4)));

288
server/recplayer.c Normal file
View File

@ -0,0 +1,288 @@
/*
Copyright 2004-2005 Chris Tallon
This file is part of VOMP.
and adopted for streamdev to play recordings
VOMP is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
VOMP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with VOMP; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "recplayer.h"
#define _XOPEN_SOURCE 600
#include <fcntl.h>
RecPlayer::RecPlayer(cRecording* rec)
{
file = NULL;
fileOpen = 0;
lastPosition = 0;
recording = rec;
for(int i = 1; i < 1000; i++) segments[i] = NULL;
// FIXME find out max file path / name lengths
#if VDRVERSNUM >= 10703
indexFile = new cIndexFile(recording->FileName(), false, rec->IsPesRecording());
#else
indexFile = new cIndexFile(recording->FileName(), false);
#endif
if (!indexFile) esyslog("ERROR: Streamdev: Failed to create indexfile!");
scan();
}
void RecPlayer::scan()
{
if (file) fclose(file);
totalLength = 0;
fileOpen = 0;
totalFrames = 0;
int i = 1;
while(segments[i++]) delete segments[i];
char fileName[2048];
for(i = 1; i < 1000; i++)
{
#if APIVERSNUM < 10703
snprintf(fileName, 2047, "%s/%03i.vdr", recording->FileName(), i);
//log->log("RecPlayer", Log::DEBUG, "FILENAME: %s", fileName);
file = fopen(fileName, "r");
#else
snprintf(fileName, 2047, "%s/%05i.ts", recording->FileName(), i);
file = fopen(fileName, "r");
if (!file) {
snprintf(fileName, 2047, "%s/%03i.vdr", recording->FileName(), i);
file = fopen(fileName, "r");
}
#endif
if (!file) break;
segments[i] = new Segment();
segments[i]->start = totalLength;
fseek(file, 0, SEEK_END);
totalLength += ftell(file);
totalFrames = indexFile->Last();
//log->log("RecPlayer", Log::DEBUG, "File %i found, totalLength now %llu, numFrames = %lu", i, totalLength, totalFrames);
segments[i]->end = totalLength;
fclose(file);
}
file = NULL;
}
RecPlayer::~RecPlayer()
{
//log->log("RecPlayer", Log::DEBUG, "destructor");
int i = 1;
while(segments[i++]) delete segments[i];
if (file) fclose(file);
}
int RecPlayer::openFile(int index)
{
if (file) fclose(file);
char fileName[2048];
#if APIVERSNUM >= 10703
snprintf(fileName, 2047, "%s/%05i.ts", recording->FileName(), index);
isyslog("openFile called for index %i string:%s", index, fileName);
file = fopen(fileName, "r");
if (file)
{
fileOpen = index;
return 1;
}
#endif
snprintf(fileName, 2047, "%s/%03i.vdr", recording->FileName(), index);
isyslog("openFile called for index %i string:%s", index, fileName);
//log->log("RecPlayer", Log::DEBUG, "openFile called for index %i string:%s", index, fileName);
file = fopen(fileName, "r");
if (file)
{
fileOpen = index;
return 1;
}
//log->log("RecPlayer", Log::DEBUG, "file failed to open");
fileOpen = 0;
return 0;
}
uint64_t RecPlayer::getLengthBytes()
{
return totalLength;
}
uint32_t RecPlayer::getLengthFrames()
{
return totalFrames;
}
unsigned long RecPlayer::getBlock(unsigned char* buffer, uint64_t position, unsigned long amount)
{
if ((amount > totalLength) || (amount > 500000))
{
//log->log("RecPlayer", Log::DEBUG, "Amount %lu requested and rejected", amount);
return 0;
}
if (position >= totalLength)
{
//log->log("RecPlayer", Log::DEBUG, "Client asked for data starting past end of recording!");
return 0;
}
if ((position + amount) > totalLength)
{
//log->log("RecPlayer", Log::DEBUG, "Client asked for some data past the end of recording, adjusting amount");
amount = totalLength - position;
}
// work out what block position is in
int segmentNumber;
for(segmentNumber = 1; segmentNumber < 1000; segmentNumber++)
{
if ((position >= segments[segmentNumber]->start) && (position < segments[segmentNumber]->end)) break;
// position is in this block
}
// we could be seeking around
if (segmentNumber != fileOpen)
{
if (!openFile(segmentNumber)) return 0;
}
uint64_t currentPosition = position;
uint32_t yetToGet = amount;
uint32_t got = 0;
uint32_t getFromThisSegment = 0;
uint32_t filePosition;
while(got < amount)
{
if (got)
{
// if(got) then we have already got some and we are back around
// advance the file pointer to the next file
if (!openFile(++segmentNumber)) return 0;
}
// is the request completely in this block?
if ((currentPosition + yetToGet) <= segments[segmentNumber]->end)
getFromThisSegment = yetToGet;
else
getFromThisSegment = segments[segmentNumber]->end - currentPosition;
filePosition = currentPosition - segments[segmentNumber]->start;
fseek(file, filePosition, SEEK_SET);
if (fread(&buffer[got], getFromThisSegment, 1, file) != 1) return 0; // umm, big problem.
// Tell linux not to bother keeping the data in the FS cache
posix_fadvise(file->_fileno, filePosition, getFromThisSegment, POSIX_FADV_DONTNEED);
got += getFromThisSegment;
currentPosition += getFromThisSegment;
yetToGet -= getFromThisSegment;
}
lastPosition = position;
return got;
}
uint64_t RecPlayer::getLastPosition()
{
return lastPosition;
}
cRecording* RecPlayer::getCurrentRecording()
{
return recording;
}
uint64_t RecPlayer::positionFromFrameNumber(uint32_t frameNumber)
{
if (!indexFile) return 0;
#if VDRVERSNUM >= 10703
uint16_t retFileNumber;
off_t retFileOffset;
#else
uchar retFileNumber;
int retFileOffset;
#endif
if (!indexFile->Get((int)frameNumber, &retFileNumber, &retFileOffset))
{
return 0;
}
// log->log("RecPlayer", Log::DEBUG, "FN: %u FO: %i", retFileNumber, retFileOffset);
if (!segments[retFileNumber]) return 0;
uint64_t position = segments[retFileNumber]->start + retFileOffset;
// log->log("RecPlayer", Log::DEBUG, "Pos: %llu", position);
return position;
}
uint32_t RecPlayer::frameNumberFromPosition(uint64_t position)
{
if (!indexFile) return 0;
if (position >= totalLength)
{
//log->log("RecPlayer", Log::DEBUG, "Client asked for data starting past end of recording!");
return 0;
}
uint8_t segmentNumber;
for(segmentNumber = 1; segmentNumber < 255; segmentNumber++)
{
if ((position >= segments[segmentNumber]->start) && (position < segments[segmentNumber]->end)) break;
// position is in this block
}
uint32_t askposition = position - segments[segmentNumber]->start;
return indexFile->Get((int)segmentNumber, askposition);
}
bool RecPlayer::getNextIFrame(uint32_t frameNumber, uint32_t direction, uint64_t* rfilePosition, uint32_t* rframeNumber, uint32_t* rframeLength)
{
// 0 = backwards
// 1 = forwards
if (!indexFile) return false;
int iframeLength;
int indexReturnFrameNumber;
indexReturnFrameNumber = (uint32_t)indexFile->GetNextIFrame(frameNumber, (direction==1 ? true : false), NULL, NULL, &iframeLength);
//log->log("RecPlayer", Log::DEBUG, "GNIF input framenumber:%lu, direction=%lu, output:framenumber=%i, framelength=%i", frameNumber, direction, indexReturnFrameNumber, iframeLength);
if (indexReturnFrameNumber == -1) return false;
*rfilePosition = positionFromFrameNumber(indexReturnFrameNumber);
*rframeNumber = (uint32_t)indexReturnFrameNumber;
*rframeLength = (uint32_t)iframeLength;
return true;
}

63
server/recplayer.h Normal file
View File

@ -0,0 +1,63 @@
/*
Copyright 2004-2005 Chris Tallon
This file is part of VOMP.
VOMP is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
VOMP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with VOMP; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RECPLAYER_H
#define RECPLAYER_H
#include <stdio.h>
#include <vdr/recording.h>
#include "server/streamer.h"
class Segment
{
public:
uint64_t start;
uint64_t end;
};
class RecPlayer
{
public:
RecPlayer(cRecording* rec);
~RecPlayer();
uint64_t getLengthBytes();
uint32_t getLengthFrames();
unsigned long getBlock(unsigned char* buffer, uint64_t position, unsigned long amount);
int openFile(int index);
uint64_t getLastPosition();
cRecording* getCurrentRecording();
void scan();
uint64_t positionFromFrameNumber(uint32_t frameNumber);
uint32_t frameNumberFromPosition(uint64_t position);
bool getNextIFrame(uint32_t frameNumber, uint32_t direction, uint64_t* rfilePosition, uint32_t* rframeNumber, uint32_t* rframeLength);
private:
cRecording* recording;
cIndexFile* indexFile;
FILE* file;
int fileOpen;
Segment* segments[1000];
uint64_t totalLength;
uint64_t lastPosition;
uint32_t totalFrames;
};
#endif