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

Reply via email to