OK,... that was easier than expected... ;-)
The attached new patch file contains a version with an menu entry "Import
markers" to put MPG bookmarks into the event list using a mpg::getbookmarks()
method which returns a pointer to the read TS bookmarks (in frame numbers!)
or NULL if the input file was a PS file!
The conversion to frame numbers occurs in getbookmarks() on-the-fly when
called for the first time if the TS bookmarks have been read originally as
byte positions. That way it doesn't matters what the receiver or
inputfile-specific read function really delivers...
Guess that version is now much more general... :)
ciao
Ralph
diff -Naur svn/src/dvbcutbase.ui r91-bookmarks2/src/dvbcutbase.ui
--- svn/src/dvbcutbase.ui 2007-10-17 16:34:34.000000000 +0200
+++ r91-bookmarks2/src/dvbcutbase.ui 2007-10-21 20:18:26.000000000 +0200
@@ -373,6 +373,7 @@
<action name="editBookmarkAction"/>
<separator/>
<action name="editSuggestAction"/>
+ <action name="editImportAction"/>
</item>
<item text="View" name="viewMenu">
<action name="viewNormalAction"/>
@@ -662,6 +663,20 @@
</action>
<action>
<property name="name">
+ <cstring>editImportAction</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Import markers</string>
+ </property>
+ <property name="accel">
+ <string>I</string>
+ </property>
+ </action>
+ <action>
+ <property name="name">
<cstring>fileNewAction</cstring>
</property>
<property name="iconSet">
@@ -899,6 +914,12 @@
<slot>editSuggest()</slot>
</connection>
<connection>
+ <sender>editImportAction</sender>
+ <signal>activated()</signal>
+ <receiver>dvbcutbase</receiver>
+ <slot>editImport()</slot>
+ </connection>
+ <connection>
<sender>eventlist</sender>
<signal>doubleClicked(QListBoxItem*)</signal>
<receiver>dvbcutbase</receiver>
@@ -1023,6 +1044,7 @@
<slot>editChapter()</slot>
<slot>editBookmark()</slot>
<slot>editSuggest()</slot>
+ <slot>editImport()</slot>
<slot>doubleclickedeventlist(QListBoxItem *)</slot>
<slot>eventlistcontextmenu(QListBoxItem *, const QPoint &)</slot>
<slot>clickedgo()</slot>
diff -Naur svn/src/dvbcut.cpp r91-bookmarks2/src/dvbcut.cpp
--- svn/src/dvbcut.cpp 2007-10-17 19:36:48.000000000 +0200
+++ r91-bookmarks2/src/dvbcut.cpp 2007-10-22 00:15:25.000000000 +0200
@@ -612,6 +612,14 @@
void dvbcut::addEventListItem(int pic, EventListItem::eventtype type)
{
+ //check if requested EventListItem is already in list to avoid doubles!
+ for (QListBoxItem *item=eventlist->firstItem();item;item=item->next())
+ if (item->rtti()==EventListItem::RTTI()) {
+ EventListItem *eli=(EventListItem*)item;
+ if (pic==eli->getpicture() && type==eli->geteventtype())
+ return;
+ }
+
QPixmap p;
if (imgp && imgp->rtti() == IMAGEPROVIDER_STANDARD)
p = imgp->getimage(pic);
@@ -654,6 +662,13 @@
addEventListItem(pic, EventListItem::bookmark);
}
+void dvbcut::editImport()
+{
+ int *bookmark = mpg->getbookmarks();
+ while(bookmark && *bookmark)
+ addEventListItem(*bookmark++, EventListItem::bookmark);
+}
+
void dvbcut::viewDifference()
{
viewNormalAction->setOn(false);
@@ -932,7 +947,8 @@
popup.insertItem("Delete",2);
popup.insertItem("Delete others",3);
popup.insertItem("Delete all",4);
- popup.insertItem("Display difference from this picture",5);
+ popup.insertItem("Delete all bookmarks",5);
+ popup.insertItem("Display difference from this picture",6);
QListBox *lb=lbi->listBox();
QListBoxItem *first=lb->firstItem(),*current,*next;
@@ -970,6 +986,16 @@
break;
case 5:
+ current=first;
+ while(current) {
+ next=current->next();
+ const EventListItem &eli_current=*static_cast<const EventListItem*>(current);
+ if(eli_current.geteventtype()==EventListItem::bookmark) delete current;
+ current=next;
+ }
+ break;
+
+ case 6:
if (imgp)
delete imgp;
imgp=new differenceimageprovider(*mpg,eli.getpicture(),new dvbcutbusy(this),false,viewscalefactor);
@@ -1218,6 +1244,7 @@
editStartAction->setEnabled(false);
editStopAction->setEnabled(false);
editSuggestAction->setEnabled(false);
+ editImportAction->setEnabled(false);
editChapterAction->setEnabled(false);
editBookmarkAction->setEnabled(false);
@@ -1512,7 +1539,7 @@
}
update_quick_picture_lookup_table();
-
+
fileOpenAction->setEnabled(true);
fileSaveAction->setEnabled(true);
fileSaveAsAction->setEnabled(true);
@@ -1525,6 +1552,7 @@
editStartAction->setEnabled(true);
editStopAction->setEnabled(true);
editSuggestAction->setEnabled(true);
+ editImportAction->setEnabled(true);
editChapterAction->setEnabled(true);
editBookmarkAction->setEnabled(true);
viewNormalAction->setEnabled(true);
diff -Naur svn/src/dvbcut.h r91-bookmarks2/src/dvbcut.h
--- svn/src/dvbcut.h 2007-10-11 20:03:19.000000000 +0200
+++ r91-bookmarks2/src/dvbcut.h 2007-10-21 20:02:29.000000000 +0200
@@ -132,6 +132,7 @@
virtual void editStop();
virtual void editStart();
virtual void editSuggest();
+ virtual void editImport();
virtual void viewDifference();
virtual void viewUnscaled();
virtual void viewNormal();
diff -Naur svn/src/index.h r91-bookmarks2/src/index.h
--- svn/src/index.h 2007-10-11 20:03:19.000000000 +0200
+++ r91-bookmarks2/src/index.h 2007-10-18 17:05:19.000000000 +0200
@@ -141,11 +141,19 @@
int seq=pic;
while (seq > 0 && !p[seq].getseqheader())
--seq;
- pic=pic-seq;
+ pic-=seq;
while(seq < pictures && p[seq].getsequencenumber()!=pic)
++seq;
return seq;
}
+ int picturenr(int ind) const // the reverse function
+ {
+ int pic=p[ind].getsequencenumber();
+ while (ind > 0 && !p[ind].getseqheader())
+ --ind;
+ pic+=ind-skipfirst;
+ return pic;
+ }
const picture &operator[](unsigned int i) const
{
return p[i];
diff -Naur svn/src/mpgfile.h r91-bookmarks2/src/mpgfile.h
--- svn/src/mpgfile.h 2007-10-14 01:19:43.000000000 +0200
+++ r91-bookmarks2/src/mpgfile.h 2007-10-22 00:17:16.000000000 +0200
@@ -65,6 +65,10 @@
{
return false;
}
+ virtual int *getbookmarks()
+ {
+ return NULL;
+ }
int getinitialoffset() const
{
@@ -127,6 +131,42 @@
}
return -1;
}
+ int getpictureatposition(dvbcut_off_t position) const
+ {
+ // binary search for the picture at nearest file position (in bytes)
+ int firstpic=0, lastpic=pictures-1;
+ int first=idx.indexnr(firstpic), mid, last=idx.indexnr(lastpic);
+ dvbcut_off_t firstpos=idx[first].getpos();
+ dvbcut_off_t lastpos=idx[last].getpos();
+ dvbcut_off_t midpos;
+
+ if(position<firstpos || position>lastpos) return -1;
+
+ while( last-first > 1 )
+ {
+ mid = (first + last)/2;
+ midpos = idx[mid].getpos();
+
+ if(position > midpos) {
+ first = mid;
+ firstpos = midpos;
+ } else if(position < midpos) {
+ last = mid;
+ lastpos = midpos;
+ } else { // equality
+ first = mid;
+ firstpos = midpos;
+ last = mid;
+ lastpos = midpos;
+ }
+ }
+
+ // index of picture at nearest file position
+ int ind = (position-firstpos)<(lastpos-position) ? first : last;
+
+ // get the corresponding picture number
+ return idx.picturenr(ind);
+ }
AVCodecContext *getavcc(int str)
{
return s[str].avcc;
diff -Naur svn/src/tsfile.cpp r91-bookmarks2/src/tsfile.cpp
--- svn/src/tsfile.cpp 2007-10-11 20:03:19.000000000 +0200
+++ r91-bookmarks2/src/tsfile.cpp 2007-10-22 00:00:41.000000000 +0200
@@ -29,6 +29,15 @@
for(unsigned int i=0;i<8192;++i)
streamnumber[i]=-1;
+ // 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"};
+ 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);
+
// Find video PID and audio PID(s)
buf.providedata(buf.getsize(), initialoffset);
if (check_si_tables())
@@ -241,6 +250,102 @@
return -1;
}
+// 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) {
+ unsigned int magic, version, unit=0;
+ unsigned int frequency, symbolrate, modulation;
+ int boff=len, off=0, type=0, hlen=0, verbose=0;
+
+ // initialize bookmark array!
+ byte_bookmarks[0] = 0;
+ bytes = true;
+
+ // just in case there's a corrupted TS packet at the beginning
+ if(verbose) fprintf(stderr,"Header length: %d\n",len);
+ if(len<TSPACKETSIZE) return -1;
+
+ // identify the specific header via the magic number 'TFrc'
+ magic = (header[0]<<24)|(header[1]<<16)|(header[2]<<8)|header[3];
+ if(magic==TF5XXXPVR_MAGIC) { // all newer models of type TF5???PVR and TF6???PVR
+ hlen = TF5XXXPVR_LEN;
+ unit = (1<<9)*TSPACKETSIZE;
+ // There are 2 different versions, one with 4 bytes larger ServiceInfoStructure (UK models?)
+ version = (header[4]<<8)|header[5];
+ if(verbose) fprintf(stderr,"magic: %x version: %x\n",magic,version);
+ if(version==TF5000PVR_VERSION) {
+ off = 0;
+ boff = TF5000PVR_POS;
+ type = 2;
+ } else if(version==TF5010PVR_VERSION) {
+ off = 4;
+ boff = TF5010PVR_POS;
+ type = 3;
+ } else
+ return -3;
+ // DVB-C boxes have a 4bytes smaller TransponderInfoStructure... grmbl!!!
+ // And there's no identifier or version number to indicate this... arghhhh!!
+ // ==> check a few transponder parameters (which are stored at different positions if DVB-S or -T!?!)
+ frequency = (header[52+off]<<24)|(header[53+off]<<16)|(header[54+off]<<8)|header[55+off];
+ symbolrate = (header[56+off]<<8)|header[57+off];
+ modulation = header[62+off];
+ if(verbose) fprintf(stderr,"DVB-C? freq=%d symb=%d mod=%d\n",frequency,symbolrate,modulation);
+ if(frequency>=47000 && frequency<=862000 && symbolrate>=2000 && symbolrate<=30000 && modulation<=4) {
+ boff-=4;
+ type+=2;
+ }
+ } else {
+ // the old TF4000PVR don't writes a simple magic/version number at the beginning...
+ // but start/stop time (MJD/hour/time) ==> check for consistency!
+ // start can be equal to stop (if recording is COPY/CUT), but should be year 2000+ (MJD=51543)!
+ version = (header[4]<<24)|(header[5]<<16)|(header[6]<<8)|header[7];
+ unsigned int duration = (header[8]<<8)|header[9]; // in minutes
+ unsigned int servicetype = (header[12]<<8)|header[13]; // 0:TV, 1:Radio
+ unsigned int polarity = header[53]; // 0x80, 0x08, 0x88, 0x00 (hi/lo, hor/ver)
+ frequency = (header[54]<<8)|header[55];
+ symbolrate = (header[56]<<8)|header[57];
+ if(verbose) fprintf(stderr,"TF4000? start=%x stop=%x dur=%d serv=%d freq=%d symb=%d pol=%d\n",
+ magic,version,duration,servicetype,frequency,symbolrate,polarity);
+ if(magic<=version && (magic>>16)>51543 &&
+ header[2]<24 && header[3]<60 && header[6]<24 && header[7]<60 &&
+ duration>0 && duration<1440 && servicetype==0 && // up to one full day TV recording should be enough!
+ frequency>=10000 && frequency<=13000 && // there's only a DVB-S device, AFAIK!
+ symbolrate>=2000 && symbolrate<=30000 && (polarity&0x77)==0) {
+ // the above should be sufficient... together with the required length of the header!
+ hlen = TF4000PVR_LEN;
+ unit = (1<<17);
+ boff = TF4000PVR_POS;
+ type = 1;
+ } else
+ return -2;
+ }
+
+ // 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*MAX_BOOKMARKS) {
+ // 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)
+ unsigned int bookmark;
+ do {
+ bookmark = (header[boff]<<24)|(header[boff+1]<<16)|(header[boff+2]<<8)|header[boff+3];
+ // bookmark is stored in 128 resp. 94kbyte units
+ byte_bookmarks[bnum] = bookmark*unit;
+ if(verbose && bookmark) fprintf(stderr,"BOOKMARK[%d] = %lld\n",bnum,byte_bookmarks[bnum]);
+ bnum++;
+ boff+=4;
+ }
+ while(bookmark && bnum<MAX_BOOKMARKS);
+ // add a terminating zero marker!
+ if(bnum==MAX_BOOKMARKS) byte_bookmarks[bnum] = 0;
+ else bnum--;
+ } else // receiver model identified but header to short!
+ fprintf(stderr,"Header probabely corrupted (%dbytes to short), discarding bookmarks!\n",hlen-len);
+
+ return type*100+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 r91-bookmarks2/src/tsfile.h
--- svn/src/tsfile.h 2007-10-11 20:03:19.000000000 +0200
+++ r91-bookmarks2/src/tsfile.h 2007-10-22 00:15:18.000000000 +0200
@@ -26,6 +26,18 @@
#define TSPACKETSIZE (188)
#define TSSYNCBYTE (0x47)
+// stuff to identify proprietary (topfield) headers and find bookmarks
+// ==> magic (&version) number, position of bookmarks, length of header
+#define TF5XXXPVR_MAGIC (0x54467263)
+#define TF5XXXPVR_LEN (20*TSPACKETSIZE)
+#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 MAX_BOOKMARKS (64)
+
/**
@author Sven Over
*/
@@ -90,6 +102,14 @@
bool check_si_tables();
size_t get_si_table(uint8_t*, size_t, size_t&, int, int);
+ int isTOPFIELD(const uint8_t*, int);
+ // indicates type of read bookmarks (frame numbers or byte positions)
+ bool bytes;
+ // to store the bookmarks in byte positions (terminated by a zero-bookmark)
+ dvbcut_off_t byte_bookmarks[MAX_BOOKMARKS+1];
+ // to store the bookmarks in frame numbers (terminated by a zero-bookmark)
+ int pic_bookmarks[MAX_BOOKMARKS+1];
+
public:
tsfile(inbuffer &b, int initial_offset);
@@ -102,6 +122,17 @@
virtual bool istransportstream() {
return true;
}
+ virtual int *getbookmarks() {
+ if(bytes) {
+ int pic, nbp=0,nbb=0;
+ while(byte_bookmarks[nbb])
+ if((pic = getpictureatposition(byte_bookmarks[nbb++])) >= 0)
+ pic_bookmarks[nbp++] = pic;
+ pic_bookmarks[nbp] = 0;
+ bytes = false;
+ }
+ return pic_bookmarks;
+ }
};
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
DVBCUT-user mailing list
DVBCUT-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dvbcut-user