Hi,
with this patch it's possible to use formatted timestamps
[[hh:]mm:]ss.[frac][/nn]
as alternative to frame numbers in input fields!
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?).
Please notice the (additional) period, if you want to specify just full
integer seconds (without min/hours)!!! If you omit it, the string will be
interpreted as frame number as usual...
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...
ciao
Ralph
PS: I also fixed 2 bugs concerning the quick_picture_lookuptable...
forgot to update update when converting to start/stop-marker via context menu
and there should be NO output frames/*-mark when the last marker is a start
marker without matching stop!
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-28 20:11:39.000000000 +0100
@@ -705,7 +705,11 @@
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());
+
EventListItem::eventtype type=EventListItem::start;
for (std::vector<int>::iterator it = cutlist.begin(); it != cutlist.end(); ++it) {
addEventListItem(*it, type);
@@ -714,6 +718,7 @@
else
type=EventListItem::start;
}
+
update_quick_picture_lookup_table();
}
@@ -1049,10 +1054,12 @@
case 6:
eli.seteventtype(EventListItem::start);
+ update_quick_picture_lookup_table();
break;
case 7:
eli.seteventtype(EventListItem::stop);
+ update_quick_picture_lookup_table();
break;
case 8:
@@ -1081,7 +1088,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 +1108,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 +1274,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 +1375,7 @@
linslider->setEnabled(false);
jogslider->setEnabled(false);
- std::string prjfilename,expfilename;
+ std::string prjfilename;
QDomDocument domdoc;
{
QFile infile(filename);
@@ -1397,7 +1416,7 @@
if (!qs.isEmpty())
idxfilename = (const char*)qs;
}
- else if (e.tagName() == "expfile") {
+ else if (e.tagName() == "expfile") { // this will overrule a expfilename given with the -exp-CLI-switch!
QString qs = e.attribute("path");
if (!qs.isEmpty())
expfilename = (const char*)qs;
@@ -1569,6 +1588,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 +1637,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 +1850,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())
{
// 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
--- svn/ChangeLog 2007-10-25 19:22:04.000000000 +0200
+++ r96-timestamp/ChangeLog 2007-10-28 21:25:29.000000000 +0100
@@ -1,3 +1,16 @@
+2007-10-28
+
+ * src/dvbcut.cpp:
+ * src/dvbcut.h:
+ * src/main.cpp:
+ * src/dvbcutbase.ui:
+ Allow timestamps in input fields & -exp option.
+ 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:
-------------------------------------------------------------------------
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