OK,....2nd version...
I moved the file reading part to mpgfile::readfile()...
or should we have a separate utility.cpp/h?
Also I changed the parameter order in the overloaded inbuffer::open a bit and
initialized filename if not given (for instance when called in main() with
input fom STDIN... forgot that this could happen ;-))!
ciao
Ralph
diff -Naur svn/ChangeLog r101-tf7700hdpvr/ChangeLog
--- svn/ChangeLog 2007-11-14 20:04:07.000000000 +0100
+++ r101-tf7700hdpvr/ChangeLog 2007-11-24 14:17:23.000000000 +0100
@@ -1,3 +1,17 @@
+2007-11-24 Ralph Glasstetter <[EMAIL PROTECTED]> (mr)
+
+ * src/tsfile.cpp
+ * src/tsfile.h
+ Import bookmarks from new Topfield TF7700HDPVR
+
+ * src/mpgfile.cpp
+ * src/mpgfile.h
+ readfile() to read (small) files to memory
+
+ * src/buffer.cpp
+ * src/buffer.h
+ Store filename in files structure
+
2007-11-12 Michael Riepe <[EMAIL PROTECTED]>
* src/lavfmuxer.cpp:
diff -Naur svn/src/buffer.cpp r101-tf7700hdpvr/src/buffer.cpp
--- svn/src/buffer.cpp 2007-10-14 01:19:43.000000000 +0200
+++ r101-tf7700hdpvr/src/buffer.cpp 2007-11-24 12:38:54.000000000 +0100
@@ -176,7 +176,7 @@
*errmsg = filename + ": open: " + strerror(errno);
return false;
}
- if (!open(fd, errmsg, true)) {
+ if (!open(fd, errmsg, true, filename)) {
if (errmsg)
*errmsg = filename + ": " + *errmsg;
return false;
@@ -185,10 +185,11 @@
}
bool
-inbuffer::open(int fd, std::string *errmsg, bool closeme) {
+inbuffer::open(int fd, std::string *errmsg, bool closeme, std::string filename) {
infile f;
f.fd = fd;
+ f.name = filename;
f.closeme = closeme;
if (pipe_mode) {
// no more files please!
@@ -482,6 +483,12 @@
}
return -1;
}
+
+std::string
+inbuffer::getfilename(int filenum) {
+ return files.at(filenum).name;
+}
+
// OUTBUFFER ****************************************************************
diff -Naur svn/src/buffer.h r101-tf7700hdpvr/src/buffer.h
--- svn/src/buffer.h 2007-10-11 20:03:19.000000000 +0200
+++ r101-tf7700hdpvr/src/buffer.h 2007-11-24 12:38:19.000000000 +0100
@@ -149,6 +149,7 @@
dvbcut_off_t end;
bool closeme;
int fd;
+ std::string name;
};
std::vector<infile> files;
bool eof;
@@ -165,7 +166,7 @@
public:
inbuffer(unsigned int _size, unsigned int mmapsize = 0);
~inbuffer();
- bool open(int fd, std::string *errmsg = 0, bool closeme = false);
+ bool open(int fd, std::string *errmsg = 0, bool closeme = false, std::string filename="");
bool open(std::string filename, std::string *errmsg = 0);
void reset();
@@ -191,6 +192,7 @@
dvbcut_off_t getfilesize() const { return filesize; }
dvbcut_off_t getfilepos() const { return pos + readpos; }
int getfilenum(dvbcut_off_t offset, dvbcut_off_t &fileoff);
+ std::string getfilename(int filenum);
void setsequential(bool flag) { sequential = flag; }
};
diff -Naur svn/src/mpgfile.cpp r101-tf7700hdpvr/src/mpgfile.cpp
--- svn/src/mpgfile.cpp 2007-10-14 01:19:43.000000000 +0200
+++ r101-tf7700hdpvr/src/mpgfile.cpp 2007-11-24 13:44:19.000000000 +0100
@@ -803,3 +803,39 @@
buf[6] = (ss<<5) & 0xe0 | (pp>>1) & 0x1f;
buf[7] |= (pp<<7) & 0x80;
}
+
+// general purpose utility function to
+// read a binary file to memory for further processing
+// ATTENTION: BE SURE YOU HAVE ENOUGH!!! */
+size_t mpgfile::readfile(std::string filename, uint8_t **buffer) {
+
+ FILE *pFile;
+ size_t len, lSize;
+
+ pFile = fopen(filename.c_str() , "rb");
+ if (pFile==NULL) return -1;
+
+ // obtain file size
+ fseek (pFile , 0 , SEEK_END);
+ lSize = ftell(pFile);
+ rewind(pFile);
+
+ // allocate memory to contain the whole file
+ *buffer = (uint8_t*) malloc(sizeof(uint8_t)*lSize);
+ if (buffer == NULL) {
+ fclose(pFile);
+ return -2;
+ }
+
+ // copy the file into the buffer
+ len = fread(*buffer, 1, lSize, pFile);
+ if (len != lSize) {
+ fclose(pFile);
+ free(buffer);
+ return -3;
+ }
+
+ fclose(pFile);
+ return len;
+
+}
diff -Naur svn/src/mpgfile.h r101-tf7700hdpvr/src/mpgfile.h
--- svn/src/mpgfile.h 2007-10-22 22:25:20.000000000 +0200
+++ r101-tf7700hdpvr/src/mpgfile.h 2007-11-24 13:40:20.000000000 +0100
@@ -168,6 +168,16 @@
// get the corresponding picture number
return idx.picturenr(ind);
}
+ int getpictureattime(pts_t time) const
+ {
+ int first=idx.indexnr(0), second=idx.indexnr(1);
+ pts_t firstpts=idx[first].getpts(), secondpts=idx[second].getpts();
+
+ int timeperframe=secondpts-firstpts;
+ timeperframe = timeperframe>0 && timeperframe<5000 ? timeperframe : 3003;
+
+ return time/timeperframe;
+ }
AVCodecContext *getavcc(int str)
{
return s[str].avcc;
@@ -203,6 +213,7 @@
void recodevideo(muxer &mux, int start, int stop, pts_t offset,
int progresspics=0, int progresstotal=0, logoutput *log=0);
void fixtimecode(uint8_t *buf, int len, pts_t pts);
+ size_t readfile(std::string filename, uint8_t **buffer);
dvbcut_off_t getfilesize()
{
diff -Naur svn/src/tsfile.cpp r101-tf7700hdpvr/src/tsfile.cpp
--- svn/src/tsfile.cpp 2007-11-03 22:06:15.000000000 +0100
+++ r101-tf7700hdpvr/src/tsfile.cpp 2007-11-24 13:45:33.000000000 +0100
@@ -31,12 +31,13 @@
// check the "header" for receiver specific bookmarks
const uint8_t *header = (const uint8_t*) buf.data();
- const char *model[6]={"???","TF4000","TF5000","TF5010","TF5000c","TF5010c"};
+ const char *model[7]={"???","TF4000","TF5000","TF5010","TF5000c","TF5010c","TF7700"};
int irc;
- if((irc=isTOPFIELD(header, initial_offset))>0)
- fprintf(stderr,"Found Topfield %s header with %d bookmarks\n",model[irc/100],irc%100);
- //else
- // fprintf(stderr,"Unknown, corrupted or no proprietary TS header at all, IRC=%d\n",irc);
+ bmtype = none;
+ if((irc=isTOPFIELD(header, initial_offset, buf.getfilename(0)))>0)
+ fprintf(stderr,"Found Topfield %s recording (%d bytes header, %d bookmarks)\n",model[irc/100],initial_offset,irc%100);
+ else
+ fprintf(stderr,"Analyzed transport stream, %d bytes of initial data (IRC=%d)\n",initial_offset,irc);
// Find video PID and audio PID(s)
buf.providedata(buf.getsize(), initialoffset);
@@ -253,16 +254,19 @@
// test for Topfield TF4000PVR & TF5xxxPVR and read bookmarks from the proprietary header
// return codes: <type>*100+<number of bookmarks> or
// -1: header far to short for topfield/bookmarks, -2: magic mismatch, -3: version mismatch
-int tsfile::isTOPFIELD(const uint8_t *header, int len) {
+int
+tsfile::isTOPFIELD(const uint8_t *header, int len, std::string recfile) {
unsigned int magic, version, unit=0;
unsigned int frequency, symbolrate, modulation;
- int boff=len, off=0, type=0, hlen=0, verbose=0;
+ int boff=len, off=0, type=0, hlen=0, verbose=0, irc;
- // this routine stores bookmarks as byte positions!
- bytes = true;
+ if(verbose) fprintf(stderr,"Header length of %s: %d\n",recfile.c_str(),len);
- // just in case there's a corrupted TS packet at the beginning
- if(verbose) fprintf(stderr,"Header length: %d\n",len);
+ // topfield receiver with additional info file?
+ if((irc=isTF7700HDPVR(recfile))>0) return irc;
+ else if(verbose) fprintf(stderr,"No TF7700HDPVR! IRC=%d\n",irc);
+
+ // just in case there's a corrupted TS packet at the beginning
if(len<TSPACKETSIZE) return -1;
// identify the specific header via the magic number 'TFrc'
@@ -323,12 +327,12 @@
// OK,... we identified a receiver model!
int bnum = 0;
//if(len>=hlen) // discard ALL (slightly) to small headers...? No, only require enough space for the bookmarks...
- if(len>=boff+4*TF_MAX_BOOKMARKS) {
+ if(len>=boff+4*TF5XXXPVR_MAX) {
// Seems to be a Topfield TF4000PVR/TF5xxxPVR TS-header with 576/3760bytes total length
// and up to 64 bookmarks (BUT can be shorter/corrupted due to COPY/CUT-procedure on reveiver)
dvbcut_off_t bookmark;
while ((bookmark=(header[boff]<<24)|(header[boff+1]<<16)|(header[boff+2]<<8)|header[boff+3])
- && bnum<TF_MAX_BOOKMARKS) {
+ && bnum<TF5XXXPVR_MAX) {
// bookmark is stored in 128 resp. 94kbyte units
bookmark*=unit;
if(verbose) fprintf(stderr,"BOOKMARK[%d] = %lld\n",bnum,bookmark);
@@ -340,9 +344,71 @@
} else // receiver model identified but header to short!
fprintf(stderr,"Header probabely corrupted (%dbytes to short), discarding bookmarks!\n",hlen-len);
+ // this routine stores bookmarks as byte positions!
+ bmtype = byte;
+
return type*100+bnum;
}
+// newest topfield receivers (i.e. TF7700HDPVR) with additional ADD-file instead of a TS-header
+int
+tsfile::isTF7700HDPVR(std::string recfile) {
+ int verbose=0;
+ std::string addfile;
+
+ // contruct the expected file name of the additonal info file
+ if (!recfile.empty()) {
+ int lastdot = recfile.rfind('.');
+ int lastslash = recfile.rfind('/');
+ if (lastdot >= 0 && lastdot >= lastslash)
+ addfile = recfile.substr(0,lastdot) + ".add";
+ else
+ return -20;
+ } else
+ return -10;
+
+ uint8_t *buffer;
+ int len = readfile(addfile, &buffer);
+ if(len<0) return -30;
+
+ /* the whole file (normally 2636 bytes) is now loaded in the memory buffer. */
+
+ int bnum = 0, boff = TF7700HDPVR_POS+4*TF7700HDPVR_MAX, unit=90000;
+ // there has to be space for up to 48 bookmarks magic number!
+ if(len>=boff+4) {
+ // is it a topfield file?
+ unsigned int magic = (buffer[boff]<<24)|(buffer[boff+1]<<16)|(buffer[boff+2]<<8)|buffer[boff+3];
+ if(magic!=TF5XXXPVR_MAGIC) {
+ free(buffer);
+ return -40;
+ }
+ else if(verbose) fprintf(stderr,"Found Topfield ADD-file: %s\n",addfile.c_str());
+
+ boff = TF7700HDPVR_POS;
+ pts_t bookmark;
+ // changed byte order compared to old receivers!?!
+ while ((bookmark=(buffer[boff+3]<<24)|(buffer[boff+2]<<16)|(buffer[boff+1]<<8)|buffer[boff])
+ && bnum<TF7700HDPVR_MAX) {
+ if(verbose) fprintf(stderr,"BOOKMARK[%d] = %lld\n",bnum,bookmark);
+ // bookmark is stored in seconds now, but we'll use full pts!
+ bookmark*=unit;
+ // fill bookmark vector with times
+ time_bookmarks.push_back(bookmark);
+ bnum++;
+ boff+=4;
+ }
+ } else // receiver model identified but file to short!
+ fprintf(stderr,"ADD-File probabely corrupted (%dbytes to short), discarding bookmarks!\n",TF7700HDPVR_LEN-len);
+
+ // terminate
+ free(buffer);
+
+ // this routine stores bookmarks as times!
+ bmtype = time;
+
+ return 600+bnum;
+}
+
size_t
tsfile::get_si_table(uint8_t *tbl, size_t max, size_t &index, int pid, int tid) {
const uint8_t *d = (uint8_t*)buf.data();
diff -Naur svn/src/tsfile.h r101-tf7700hdpvr/src/tsfile.h
--- svn/src/tsfile.h 2007-10-22 22:25:20.000000000 +0200
+++ r101-tf7700hdpvr/src/tsfile.h 2007-11-23 19:15:59.000000000 +0100
@@ -27,16 +27,19 @@
#define TSSYNCBYTE (0x47)
// stuff to identify proprietary (topfield) headers and find bookmarks
-// ==> magic (&version) number, position of bookmarks, length of header
+// ==> magic ('TFrc') &version number, position of bookmarks, length of header, max number of bookmarks
#define TF5XXXPVR_MAGIC (0x54467263)
#define TF5XXXPVR_LEN (20*TSPACKETSIZE)
+#define TF5XXXPVR_MAX (64)
#define TF5000PVR_VERSION (0x5000)
#define TF5000PVR_POS (1400)
#define TF5010PVR_VERSION (0x5010)
#define TF5010PVR_POS (1404)
#define TF4000PVR_LEN (3*TSPACKETSIZE)
#define TF4000PVR_POS (216)
-#define TF_MAX_BOOKMARKS (64)
+#define TF7700HDPVR_LEN (2636)
+#define TF7700HDPVR_MAX (48)
+#define TF7700HDPVR_POS (1040)
/**
@author Sven Over
@@ -102,10 +105,13 @@
bool check_si_tables();
size_t get_si_table(uint8_t*, size_t, size_t&, int, int);
- int isTOPFIELD(const uint8_t*, int);
- bool bytes; // indicates type of read bookmarks
- std::vector<dvbcut_off_t> byte_bookmarks; // to store the bookmarks in byte positions
- std::vector<int> pic_bookmarks; // to store the bookmarks in frame numbers
+ int isTOPFIELD(const uint8_t*, int, std::string);
+ int isTF7700HDPVR(std::string);
+ enum bookmarktype { none, byte, time, pic };
+ bookmarktype bmtype; // indicates type of read bookmarks
+ std::vector<int> pic_bookmarks; // to store the bookmarks as frame numbers (returned by getbookmarks)
+ std::vector<dvbcut_off_t> byte_bookmarks; // to store the bookmarks as byte positions
+ std::vector<pts_t> time_bookmarks; // to store the bookmarks as time stamps
public:
tsfile(inbuffer &b, int initial_offset);
@@ -120,13 +126,20 @@
return true;
}
virtual std::vector<int> getbookmarks() {
- if(bytes) {
+ if(bmtype==byte) {
// convert byte positions to frame numbers if not already done/stored
- int pic;
+ int picnr;
for (std::vector<dvbcut_off_t>::iterator b = byte_bookmarks.begin(); b != byte_bookmarks.end(); ++b)
- if((pic = getpictureatposition(*b)) >= 0)
- pic_bookmarks.push_back(pic);
- bytes = false;
+ if((picnr = getpictureatposition(*b)) >= 0)
+ pic_bookmarks.push_back(picnr);
+ bmtype = pic;
+ } else if(bmtype==time) {
+ // convert pts positions to frame numbers if not already done/stored
+ int picnr;
+ for (std::vector<dvbcut_off_t>::iterator b = time_bookmarks.begin(); b != time_bookmarks.end(); ++b)
+ if((picnr = getpictureattime(*b)) >= 0)
+ pic_bookmarks.push_back(picnr);
+ bmtype = pic;
}
return pic_bookmarks;
}
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
DVBCUT-user mailing list
DVBCUT-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dvbcut-user