Hi,
Am Montag, 29. Oktober 2007 10:32 schrieb Michael Riepe:
> > Supported input fields are the cut-list supplied with the
> > "-cut"-CLI-option, the <start>/<stop>-tags in project files and the
> > search boxes in the GUI (did I forget something?).
>
> I guess it's not necessary to support the format in the project file -
> unless you're going to create project files with a script.
That was, actually the idea behind that... when editing project files by hand
or automatically by some script and you don't have a frame number
but a time and you are to lazy to calculate. ;-)
> > BTW, we now also have an "-exp"-CLI-switch to specify an export
> > file/location in addition to the (optional) <expfile>-projectfile-tag.
> > Nevertheless, the latter has still priority...
>
> It's usually the other way round: command line switches override
> configuration files.
Hey,... no problem with that! I also find it more logical to override a
projectfile default with a CLI-option, since the latter is easier to
change... ;-)
Also -idx is implemented that way... to be consistent CLI should overrule PRJ
for all options!
And should I also override the start/stop-markers from the project file with
the "-cut" the option? At the moment the -cut-markers are just added...
(BUG-Alert!!! This causes strange behavoir, since when adding new start/stop
markers, the result won't be necessarily alternated anymore!!!).
So either I delete any old ones (also in GUI-mode with convert bookmarks!)
or always just insert/add new markers, sort the whole list and then alternate
START/STOP... at the moment the appended patch will implement the first
option.
Another option would be to replace only in batch mode and add in gui-mode...?
>
> [...]
> > - if (it->export_flag)
> > + if (it->export_flag && it!=quick_picture_lookup.end())
> I'm pretty sure this change is useless. `it' can't be at the end of the
> list because it has just been decremented (i.e. moved towards the front
> by one position).
Hmmm,... of course you are right... very strange,... I thought I tested
that...?!? :-|
OK,... in the updated patch file it is now compared to
"quick_picture_lookup.end()-1"!
A cleaner solution maybe would be to set the export_flag of a START-entry only
to true, if there follows a STOP-entry...?
The appended patch also implements no strict CLI overrules PRJ and adds a
few more context menu entries (hmmm..., quite a long list now!).
ciao
Ralph
PS: Thanks for looking over my not always 100% tested patches... :)
--- svn/ChangeLog 2007-10-25 19:22:04.000000000 +0200
+++ r96-timestamp/ChangeLog 2007-10-29 12:39:00.000000000 +0100
@@ -1,3 +1,18 @@
+2007-10-28
+
+ * src/dvbcut.cpp:
+ * src/dvbcut.h:
+ * src/main.cpp:
+ * src/dvbcutbase.ui:
+ Allow timestamps in input fields, added -exp option.
+ -exp/-cut/-idx options overrule project file defaults.
+ Add specific "Delete"-entries to marker context menu.
+ Fixed bugs with quick_picture_lookuptable.
+
+ * src/pts.cpp:
+ * src/pts.h:
+ Function to convert formatted timestamps to pts_t
+
2007-10-25 Michael Riepe <[EMAIL PROTECTED]>
* SConstruct:
diff -Naur svn/src/dvbcutbase.ui r96-timestamp/src/dvbcutbase.ui
--- svn/src/dvbcutbase.ui 2007-10-25 19:22:04.000000000 +0200
+++ r96-timestamp/src/dvbcutbase.ui 2007-10-28 11:26:12.000000000 +0100
@@ -132,7 +132,7 @@
</sizepolicy>
</property>
<property name="maxLength">
- <number>7</number>
+ <number>16</number>
</property>
</widget>
<widget class="QPushButton">
@@ -179,7 +179,7 @@
</sizepolicy>
</property>
<property name="maxLength">
- <number>7</number>
+ <number>16</number>
</property>
</widget>
<widget class="QPushButton">
diff -Naur svn/src/dvbcut.cpp r96-timestamp/src/dvbcut.cpp
--- svn/src/dvbcut.cpp 2007-10-25 14:33:26.000000000 +0200
+++ r96-timestamp/src/dvbcut.cpp 2007-10-29 13:19:10.000000000 +0100
@@ -705,7 +705,19 @@
void dvbcut::addStartStopItems(std::vector<int> cutlist)
{
- // take list of frame numbers and set alternating START/STOP markers
+ // take list of frame numbers and set alternating START/STOP markers
+
+ // make sure list is sorted...
+ sort(cutlist.begin(),cutlist.end());
+
+ // ...AND there are no old START/STOP pairs!!!
+ for (QListBoxItem *item=eventlist->firstItem();item;item=item->next())
+ if (item->rtti()==EventListItem::RTTI()) {
+ EventListItem *eli=(EventListItem*)item;
+ if (eli->geteventtype()==EventListItem::start || eli->geteventtype()==EventListItem::stop)
+ delete item;
+ }
+
EventListItem::eventtype type=EventListItem::start;
for (std::vector<int>::iterator it = cutlist.begin(); it != cutlist.end(); ++it) {
addEventListItem(*it, type);
@@ -714,6 +726,7 @@
else
type=EventListItem::start;
}
+
update_quick_picture_lookup_table();
}
@@ -995,15 +1008,18 @@
popup.insertItem("Delete",2);
popup.insertItem("Delete others",3);
popup.insertItem("Delete all",4);
- popup.insertItem("Delete all bookmarks",5);
- popup.insertItem("Convert to start marker",6);
- popup.insertItem("Convert to stop marker",7);
- popup.insertItem("Convert to chapter marker",8);
- popup.insertItem("Convert to bookmark",9);
- popup.insertItem("Display difference from this picture",10);
+ popup.insertItem("Delete all start/stops",5);
+ popup.insertItem("Delete all chapters",6);
+ popup.insertItem("Delete all bookmarks",7);
+ popup.insertItem("Convert to start marker",8);
+ popup.insertItem("Convert to stop marker",9);
+ popup.insertItem("Convert to chapter marker",10);
+ popup.insertItem("Convert to bookmark",11);
+ popup.insertItem("Display difference from this picture",12);
QListBox *lb=lbi->listBox();
QListBoxItem *first=lb->firstItem(),*current,*next;
+ EventListItem::eventtype cmptype=EventListItem::none, cmptype2=EventListItem::none;
switch (popup.exec(point)) {
case 1:
@@ -1016,8 +1032,7 @@
{
EventListItem::eventtype type=eli.geteventtype();
delete lbi;
-
- if (type==EventListItem::start or type==EventListItem::stop)
+ if (type==EventListItem::start || type==EventListItem::stop)
update_quick_picture_lookup_table();
}
break;
@@ -1038,32 +1053,42 @@
break;
case 5:
+ cmptype=EventListItem::start;
+ cmptype2=EventListItem::stop;
+ case 6:
+ if(cmptype==EventListItem::none) cmptype=EventListItem::chapter;
+ case 7:
+ if(cmptype==EventListItem::none) cmptype=EventListItem::bookmark;
current=first;
while(current) {
next=current->next();
const EventListItem &eli_current=*static_cast<const EventListItem*>(current);
- if(eli_current.geteventtype()==EventListItem::bookmark) delete current;
+ if(eli_current.geteventtype()==cmptype || eli_current.geteventtype()==cmptype2)
+ delete current;
current=next;
- }
+ }
+ if (cmptype==EventListItem::start) update_quick_picture_lookup_table();
break;
- case 6:
+ case 8:
eli.seteventtype(EventListItem::start);
+ update_quick_picture_lookup_table();
break;
- case 7:
+ case 9:
eli.seteventtype(EventListItem::stop);
+ update_quick_picture_lookup_table();
break;
- case 8:
+ case 10:
eli.seteventtype(EventListItem::chapter);
break;
- case 9:
+ case 11:
eli.seteventtype(EventListItem::bookmark);
break;
- case 10:
+ case 12:
if (imgp)
delete imgp;
imgp=new differenceimageprovider(*mpg,eli.getpicture(),new dvbcutbusy(this),false,viewscalefactor);
@@ -1081,7 +1106,13 @@
QString text=goinput->text();
text.stripWhiteSpace();
bool okay=false;
- int inpic=text.toInt(&okay,0);
+ int inpic;
+ if(text.contains(':') || text.contains('.')) {
+ okay=true;
+ inpic=string2pts(text)/getTimePerFrame();
+ }
+ else
+ inpic=text.toInt(&okay,0);
if (okay) {
fine=true;
linslider->setValue(inpic);
@@ -1095,8 +1126,14 @@
QString text=goinput2->text();
text.stripWhiteSpace();
bool okay=false;
- int inpic, outpic=text.toInt(&okay,0);
- if (okay) {
+ int inpic, outpic;
+ if(text.contains(':') || text.contains('.')) {
+ okay=true;
+ outpic=string2pts(text)/getTimePerFrame();
+ }
+ else
+ outpic=text.toInt(&okay,0);
+ if (okay && !quick_picture_lookup.empty()) {
// find the entry in the quick_picture_lookup table that corresponds to given output picture
quick_picture_lookup_t::iterator it=
std::upper_bound(quick_picture_lookup.begin(),quick_picture_lookup.end(),outpic,quick_picture_lookup_s::cmp_outpicture());
@@ -1255,7 +1292,7 @@
// **************************************************************************
// *** public functions
-void dvbcut::open(std::list<std::string> filenames, std::string idxfilename)
+void dvbcut::open(std::list<std::string> filenames, std::string idxfilename, std::string expfilename)
{
if (filenames.empty()) {
QStringList fn = QFileDialog::getOpenFileNames(
@@ -1356,7 +1393,7 @@
linslider->setEnabled(false);
jogslider->setEnabled(false);
- std::string prjfilename,expfilename;
+ std::string prjfilename;
QDomDocument domdoc;
{
QFile infile(filename);
@@ -1382,7 +1419,11 @@
// parse elements, new-style first
QDomNode n;
filenames.clear();
+ if(!nogui) {
+ // in batch mode CLI-switches have priority!
idxfilename.clear();
+ expfilename.clear();
+ }
for (n = domdoc.documentElement().firstChild(); !n.isNull(); n = n.nextSibling()) {
QDomElement e = n.toElement();
if (e.isNull())
@@ -1392,12 +1433,12 @@
if (!qs.isEmpty())
filenames.push_back((const char*)qs);
}
- else if (e.tagName() == "idxfile") {
+ else if (e.tagName() == "idxfile" && idxfilename.empty()) {
QString qs = e.attribute("path");
if (!qs.isEmpty())
idxfilename = (const char*)qs;
}
- else if (e.tagName() == "expfile") {
+ else if (e.tagName() == "expfile" && expfilename.empty()) {
QString qs = e.attribute("path");
if (!qs.isEmpty())
expfilename = (const char*)qs;
@@ -1569,6 +1610,7 @@
addtorecentfiles(prjfilen);
firstpts=(*mpg)[0].getpts();
+ timeperframe=(*mpg)[1].getpts()-(*mpg)[0].getpts();
double fps=27.e6/double(mpgfile::frameratescr[(*mpg)[0].getframerate()]);
linslider->setMaxValue(pictures-1);
@@ -1617,7 +1659,14 @@
else
continue;
bool okay=false;
- int picnum=e.attribute("picture","-1").toInt(&okay,0);
+ int picnum;
+ QString str=e.attribute("picture","-1");
+ if(str.contains(':') || str.contains('.')) {
+ okay=true;
+ picnum=string2pts(str)/getTimePerFrame();
+ }
+ else
+ picnum=str.toInt(&okay,0);
if (okay && picnum>=0 && picnum<pictures) {
new EventListItem(eventlist,imgp->getimage(picnum),evt,picnum,(*mpg)[picnum].getpicturetype(),(*mpg)[picnum].getpts()-firstpts);
qApp->processEvents();
@@ -1823,11 +1872,11 @@
{
// curpic is not before the first entry of the table
--it;
- if (it->export_flag)
+ if (it->export_flag && it!=(quick_picture_lookup.end()-1))
{
// the corresponding entry says export_flag==true,
// so this pic is after a START entry and is going to
- // be exported
+ // be exported (But ONLY if it's not the last entry!).
outpic=curpic-it->picture+it->outpicture;
outpts=pts-it->pts+it->outpts;
diff -Naur svn/src/dvbcut.h r96-timestamp/src/dvbcut.h
--- svn/src/dvbcut.h 2007-10-25 12:40:50.000000000 +0200
+++ r96-timestamp/src/dvbcut.h 2007-10-28 12:03:15.000000000 +0100
@@ -78,6 +78,7 @@
int curpic;
double alpha;
pts_t firstpts;
+ int timeperframe;
bool showimage;
bool fine;
bool jogsliding;
@@ -121,11 +122,13 @@
public:
~dvbcut();
dvbcut(QWidget *parent = 0, const char *name = 0, WFlags fl = WType_TopLevel|WDestructiveClose );
- void open(std::list<std::string> filenames=std::list<std::string>(), std::string idxfilename=std::string());
+ void open(std::list<std::string> filenames=std::list<std::string>(),
+ std::string idxfilename=std::string(), std::string expfilename=std::string());
void setbusy(bool b=true);
void batchmode(bool b=true) { nogui = b; }
// static dvbcut *New(std::string filename=std::string(), std::string idxfilename=std::string());
void addStartStopItems(std::vector<int>);
+ int getTimePerFrame() { return timeperframe>0 && timeperframe<5000 ? timeperframe : 3003; };
public slots:
virtual void fileNew();
diff -Naur svn/src/main.cpp r96-timestamp/src/main.cpp
--- svn/src/main.cpp 2007-10-25 19:22:04.000000000 +0200
+++ r96-timestamp/src/main.cpp 2007-10-28 20:52:06.000000000 +0100
@@ -53,8 +53,8 @@
usage_exit(int rv=1) {
fprintf(stderr,
"Usage ("VERSION_STRING"):\n"
- " %s -generateidx [-idx <indexfilename>] [<mpgfilename> ...]\n"
- " %s -batch [ -cut AR|TS|<list> ] <prjfilename> | <mpgfilename> ...\n\n",
+ " %s -generateidx [-idx <idxfilename>] [<mpgfilename> ...]\n"
+ " %s -batch [-cut AR|TS|<list>] [-exp <expfilename>] <prjfilename> | <mpgfilename> ...\n\n",
argv0, argv0);
fprintf(stderr,
"If no input files are specified, `dvbcut -generateidx' reads from\n"
@@ -64,7 +64,7 @@
"In batch mode you can use `-cut' to create automatically alternating\n"
"START/STOP cut markers for each found aspect ratio change (AR), for\n"
"the bookmarks imported from the input transport stream (TS) or for\n"
- "a given list of frame numbers (you can use ',-|;:/' as separators).\n"
+ "a given list of frame numbers / time stamps (use ',-|;' as separators).\n"
"Without any (valid) cut markers the whole file will be converted!\n\n");
fprintf(stderr,
"Options may be abbreviated as long as they remain unambiguous.\n\n");
@@ -76,8 +76,8 @@
argv0=argv[0];
bool generateidx=false;
bool batchmode=false;
- std::string idxfilename, cut;
- std::vector<int> cutlist;
+ std::string idxfilename, expfilename;
+ std::vector<std::string> cutlist;
int i;
setlocale(LC_ALL, "");
@@ -97,15 +97,17 @@
generateidx = true;
else if (strncmp(argv[i], "-idx", n) == 0 && ++i < argc)
idxfilename = argv[i];
+ else if (strncmp(argv[i], "-exp", n) == 0 && ++i < argc)
+ expfilename = argv[i];
else if (strncmp(argv[i], "-cut", n) == 0 && ++i < argc) {
- cut=argv[i];
- char *pch=strtok(argv[i],",-|;:/");
+ char *pch = strtok(argv[i],",-|;");
while(pch) {
- cutlist.push_back(atoi(pch));
- pch=strtok(NULL,",-|;:/");
- }
- } else
- usage_exit();
+ if(strlen(pch))
+ cutlist.push_back((std::string)pch);
+ pch = strtok(NULL,",-|;");
+ }
+ } else
+ usage_exit();
}
/*
@@ -195,18 +197,24 @@
if (batchmode) {
if (filenames.empty()) // must provide at least one filename
usage_exit();
- main->open(filenames,idxfilename);
- if(!cut.empty()) {
- if(cut=="AR") {
+ main->open(filenames,idxfilename,expfilename);
+ if(!cutlist.empty()) {
+ if(cutlist.front()=="AR") {
main->editSuggest();
main->editConvert();
- } else if(cut=="TS") {
+ } else if(cutlist.front()=="TS") {
main->editImport();
main->editConvert();
} else if(cutlist.size()>1) {
- // just one entry entry makes no sense and/or can be a typo (atoi() returned 0)!
- main->addStartStopItems(cutlist);
- if(cutlist.size()%2)
+ // just one entry makes no sense and/or can be a typo!
+ std::vector<int> piclist;
+ for (unsigned int j=0; j<cutlist.size(); j++)
+ if(cutlist[j].find(':')!=std::string::npos || cutlist[j].find('.')!=std::string::npos)
+ piclist.push_back(string2pts(cutlist[j])/main->getTimePerFrame()); // pts divided by 3600(PAL) or 3003(NTSC)
+ else
+ piclist.push_back(atoi(cutlist[j].c_str())); // integers are treated as frame numbers!
+ main->addStartStopItems(piclist);
+ if(piclist.size()%2)
fprintf(stderr,"*** Cut list contained an odd number of entries, discarded last one! ***\n");
} else
fprintf(stderr,"*** Problems parsing parameter provided with option `-cut'! ***\n");
@@ -218,7 +226,7 @@
main->show();
if (!filenames.empty())
- main->open(filenames,idxfilename);
+ main->open(filenames,idxfilename,expfilename);
if (main) {
a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) );
diff -Naur svn/src/pts.cpp r96-timestamp/src/pts.cpp
--- svn/src/pts.cpp 2007-10-14 01:19:43.000000000 +0200
+++ r96-timestamp/src/pts.cpp 2007-10-28 19:39:28.000000000 +0100
@@ -23,7 +23,9 @@
#include <cstdio>
#include <cstdlib>
#include <string>
+#include <list>
+// convert a pts (1/90000 sec) to a readable timestamp string
std::string ptsstring(pts_t pts)
{
char *str=0;
@@ -46,3 +48,53 @@
free(str);
return s;
}
+
+// parse timestamp string (hh:mm:ss.frac/nn) and convert to pts (1/90000 of a second)
+pts_t string2pts(std::string str)
+ {
+ int hour=0,min=0,sec=0,ms=0,sub=0,sign=1;
+ double dsec;
+ std::list<std::string> tokens;
+
+ size_t from=0, pos;
+ while((pos=str.find(':',from))!=std::string::npos) {
+ tokens.push_back(str.substr(from,pos-from));
+ from=pos+1;
+ }
+ tokens.push_back(str.substr(from));
+
+ if(!tokens.empty()) {
+ std::string t=tokens.back();
+ pos=t.find('/');
+ dsec=atof(t.substr(0,pos).c_str());
+ if(dsec<0) {
+ dsec*=-1;
+ sign=-1;
+ }
+ sec=int(dsec);
+ ms=int(1000*(dsec-sec)+0.5);
+
+ if(pos!=std::string::npos)
+ sub=atoi(t.substr(pos+1).c_str())%90;
+ tokens.pop_back();
+
+ if(!tokens.empty()) {
+ min=atoi(tokens.back().c_str());
+ if(min<0) {
+ min*=-1;
+ sign=-1;
+ }
+ tokens.pop_back();
+
+ if(!tokens.empty()) {
+ hour=atoi(tokens.back().c_str());
+ if(hour<0) {
+ hour*=-1;
+ sign=-1;
+ }
+ }
+ }
+ }
+
+ return sign*((((hour*60 + min)*60 + sec)*1000 + ms)*90 + sub);
+ }
diff -Naur svn/src/pts.h r96-timestamp/src/pts.h
--- svn/src/pts.h 2007-10-11 20:03:19.000000000 +0200
+++ r96-timestamp/src/pts.h 2007-10-27 14:21:14.000000000 +0200
@@ -38,5 +38,6 @@
}
std::string ptsstring(pts_t pts);
+pts_t string2pts(std::string);
#endif
-------------------------------------------------------------------------
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