[xiph-commits] r12816 - in trunk/ffmpeg2theora: . frontend
j at svn.xiph.org
j at svn.xiph.org
Wed Mar 28 11:02:59 PDT 2007
Author: j
Date: 2007-03-28 11:02:54 -0700 (Wed, 28 Mar 2007)
New Revision: 12816
Added:
trunk/ffmpeg2theora/frontend/
trunk/ffmpeg2theora/frontend/README
trunk/ffmpeg2theora/frontend/Simple Theora Encoder.py
trunk/ffmpeg2theora/frontend/Simple Theora Encoder.rsrc.py
trunk/ffmpeg2theora/frontend/setup.macosx.py
Modified:
trunk/ffmpeg2theora/ffmpeg2theora.c
trunk/ffmpeg2theora/theorautils.c
trunk/ffmpeg2theora/theorautils.h
Log:
- frontend mode that prints out stats in a way that can be parsed better.
- minimal PythonCard based frontend with encoding queue
Modified: trunk/ffmpeg2theora/ffmpeg2theora.c
===================================================================
--- trunk/ffmpeg2theora/ffmpeg2theora.c 2007-03-28 13:50:40 UTC (rev 12815)
+++ trunk/ffmpeg2theora/ffmpeg2theora.c 2007-03-28 18:02:54 UTC (rev 12816)
@@ -58,6 +58,7 @@
#define INPUTFPS_FLAG 11
#define AUDIOSTREAM_FLAG 12
#define VHOOK_FLAG 13
+#define FRONTEND_FLAG 14
#define V2V_PRESET_PRO 1
#define V2V_PRESET_PREVIEW 2
@@ -285,7 +286,6 @@
this->frame_rightBand=0;
this->pix_fmt = PIX_FMT_YUV420P;
-
}
return this;
}
@@ -1099,6 +1099,7 @@
{"endtime",required_argument,NULL,'e'},
{"sync",0,&flag,SYNC_FLAG},
{"optimize",0,&flag,OPTIMIZE_FLAG},
+ {"frontend",0,&flag,FRONTEND_FLAG},
{"artist",required_argument,&metadata_flag,10},
{"title",required_argument,&metadata_flag,11},
@@ -1154,6 +1155,10 @@
convert->quick_p = 0;
flag = -1;
break;
+ case FRONTEND_FLAG:
+ info.frontend = 1;
+ flag = -1;
+ break;
#ifdef VIDEO4LINUX_ENABLED
case V4L_FLAG:
formatParams = malloc(sizeof(AVFormatParameters));
@@ -1453,7 +1458,12 @@
}
info.outfile = fopen(outputfile_name,"wb");
#endif
- dump_format (convert->context, 0,inputfile_name, 0);
+ if(info.frontend) {
+ fprintf(stderr, "\nf2t ;duration: %d;\n", convert->context->duration / AV_TIME_BASE);
+ }
+ else {
+ dump_format (convert->context, 0,inputfile_name, 0);
+ }
if(convert->disable_audio){
fprintf(stderr," [audio disabled].\n");
}
@@ -1464,7 +1474,10 @@
convert->pts_offset =
(double) convert->context->start_time / AV_TIME_BASE;
if(!info.outfile) {
- fprintf (stderr,"\nUnable to open output file `%s'.\n", outputfile_name);
+ if(info.frontend)
+ fprintf(stderr, "\nf2t ;result: Unable to open output file.;\n");
+ else
+ fprintf (stderr,"\nUnable to open output file `%s'.\n", outputfile_name);
return(1);
}
if (convert->context->duration != AV_NOPTS_VALUE) {
@@ -1474,8 +1487,11 @@
convert->audio_index =convert->video_index = -1;
}
else{
- fprintf (stderr,"\nUnable to decode input.\n");
- return(1);
+ if(info.frontend)
+ fprintf(stderr, "\nf2t ;result: input format not suported.;\n");
+ else
+ fprintf (stderr,"\nUnable to decode input.\n");
+ return(1);
}
av_close_input_file (convert->context);
}
@@ -1486,9 +1502,11 @@
ff2theora_close (convert);
fprintf(stderr,"\n");
- if (*pidfile_name)
- {
+ if (*pidfile_name)
unlink(pidfile_name);
- }
+
+ if(info.frontend)
+ fprintf(stderr, "\nf2t ;result: ok;\n");
+
return(0);
}
Added: trunk/ffmpeg2theora/frontend/README
===================================================================
--- trunk/ffmpeg2theora/frontend/README 2007-03-28 13:50:40 UTC (rev 12815)
+++ trunk/ffmpeg2theora/frontend/README 2007-03-28 18:02:54 UTC (rev 12816)
@@ -0,0 +1,6 @@
+Simple Theora Encoder a PythonCard based cross platform GUI
+for ffmpeg2theora.
+
+for those that fear the command line
+
+FIXME: figure out how to get smaller binaries
Added: trunk/ffmpeg2theora/frontend/Simple Theora Encoder.py
===================================================================
--- trunk/ffmpeg2theora/frontend/Simple Theora Encoder.py 2007-03-28 13:50:40 UTC (rev 12815)
+++ trunk/ffmpeg2theora/frontend/Simple Theora Encoder.py 2007-03-28 18:02:54 UTC (rev 12816)
@@ -0,0 +1,213 @@
+#!/usr/bin/envpython
+
+"""
+__version__ = "1.0"
+"""
+
+from PythonCard import model, dialog
+import wx
+
+import os
+from os.path import join, dirname, basename
+
+import thread
+
+
+"""
+ Format seconds
+"""
+def sec2time(seconds):
+ seconds = int(seconds)
+ minutes = int(seconds / 60)
+ seconds = seconds % 60
+ hours = int(minutes / 60)
+ minutes = minutes % 60
+ return "%02d:%02d:%02d" % (hours, minutes, seconds)
+
+
+class Encoder:
+ working = False
+ inputfile = ''
+ outputfile = ''
+ settings = "-p preview"
+ ffmpeg2theora_path = os.path.abspath(join(dirname(__file__), 'ffmpeg2theora'))
+
+ def commandline(self):
+ cmd = "'%s' --frontend %s '%s'" % (self.ffmpeg2theora_path, self.settings, self.inputfile.replace("'", "\'"))
+ if self.outputfile:
+ cmd += " -o '%s'" % self.outputfile.replace("'", "\'")
+ cmd += " 2>&1"
+ return cmd
+
+
+ def encodeItem(self, item):
+ self.inputfile = self.queuedata[item]['path']
+ self.settings = self.queuedata[item]['settings']
+ itemID = self.queuedata[item]['itemID']
+ self.itemStatus(itemID, 'encoding...')
+ cmd = self.commandline()
+ f = os.popen(cmd)
+ line = f.readline()
+ info = dict()
+ while line:
+ if line.startswith('f2t'):
+ for o in line.split(';')[1:]:
+ oo = o.split(': ')
+ if len(oo) >= 2:
+ info[oo[0]] = ": ".join(oo[1:]).strip()
+ if info.has_key('position'):
+ encoded = "encoded %s/" % sec2time(float(info['position']))
+ if info.has_key('duration') and float(info['duration']):
+ encoded = "% 3d %% done, " % ((float(info['position']) / float(info['duration'])) * 100)
+ line = encoded + 'remaining: '+ sec2time(float(info['remaining']))
+ else:
+ line = "encoding.."
+ self.itemStatus(itemID, line)
+ line = f.readline()
+ f.close()
+ if info.get('result', 'no') == 'ok':
+ self.itemStatus(itemID, 'Done.')
+ else:
+ self.itemStatus(itemID, info.get('result', 'Failed.'))
+
+ def encodeQueueThread(self):
+ self.working = True
+ for key in self.queuedata:
+ if self.queuedata[key]['status'] != 'Done.':
+ self.encodeItem(key)
+ self.working = False
+ self.encodingFinished()
+
+ def encodeQueue(self, queuedata, itemStatus, encodingFinished):
+ self.itemStatus = itemStatus
+ self.encodingFinished = encodingFinished
+ self.queuedata = queuedata
+ encoding_thread = thread.start_new_thread(self.encodeQueueThread, ())
+
+
+
+class SimpleTheoraEncoderBackground(model.Background):
+ encoder = Encoder()
+ queuedata = {}
+ encodingQueueInitialized = False
+
+ def on_initialize(self,event):
+ list = self.components.encodingQueue
+ list.InsertColumn(0, "Name")
+ list.InsertColumn(1, "Status")
+ pass
+
+ # so how much to wrap and how much to leave raw wxPython?
+ def initializeEncodingQueue(self, select = 0):
+ list = self.components.encodingQueue
+ list.Clear()
+ items = self.queuedata.items()
+
+ for x in range(len(items)):
+ key, item = items[x]
+ self.queuedata[key]['itemID'] = x
+ list.InsertStringItem(x, item['path'])
+ list.SetStringItem(x, 0, item['display_path'])
+ list.SetStringItem(x, 1, item['status'])
+ list.SetItemData(x, key)
+
+ list.SetColumnWidth(0, 180)
+ list.SetColumnWidth(1, 250)
+
+ list.SetItemDataMap(self.queuedata)
+
+ # show how to select an item
+ self.currentItem = select
+ if items:
+ list.SetItemState(self.currentItem, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
+
+ self.encodingQueueInitialized = True
+ self.components.encodeQueue.enabled = True
+
+ def setItemStatus(self, itemID, value):
+ key = self.components.encodingQueue.GetItemData(self.currentItem)
+ self.queuedata[key]['status'] = value
+ self.components.encodingQueue.SetStringItem(itemID, 1, value)
+
+ def addItemToQueue(self, input_path, settings):
+ list = self.components.encodingQueue
+ display_path = input_path
+ if len(display_path) > 26:
+ display_path = "..." + input_path[-23:]
+
+ item = dict(
+ path = input_path,
+ settings = settings,
+ display_path = display_path,
+ status = 'waiting... ',
+ listID = 0
+ )
+ if self.encodingQueueInitialized:
+ x = list.GetItemCount()
+ if self.queuedata:
+ key = max(self.queuedata.keys()) + 1
+ else:
+ key = 1
+ item['itemID'] = x
+ self.queuedata[key] = item
+ list.InsertStringItem(x, item['path'])
+ list.SetStringItem(x, 0, item['display_path'])
+ list.SetStringItem(x, 1, item['status'])
+ list.SetItemData(x, key)
+ else:
+ key = 1
+ self.queuedata[key] = item
+ self.initializeEncodingQueue()
+
+ def on_addItem_mouseClick(self, event):
+ wildcard = "Video files|*.AVI;*.avi;*.OGG;*.ogg;*.mov;*.MOV;*.dv;*.DV;*.mp4;*.MP4;*.mpg;*.mpeg;*.wmv;*.MPG;*.flv;*.FLV|All Files (*.*)|*.*"
+
+ result = dialog.fileDialog(self, 'Add Video..', '', '', wildcard )
+ if result.accepted:
+ for input_path in result.paths:
+ settings = '-p preview'
+ self.addItemToQueue(input_path, settings)
+
+ def on_removeItem_mouseClick(self, event):
+ list = self.components.encodingQueue
+ print "remove", self.currentItem
+ key = self.components.encodingQueue.GetItemData(self.currentItem)
+ self.queuedata.pop(key)
+ self.initializeEncodingQueue(self.currentItem)
+
+ def on_editItem_mouseClick(self, event):
+ print "edit settings here"
+ list = self.components.encodingQueue
+ key = self.components.encodingQueue.GetItemData(self.currentItem)
+ result = dialog.textEntryDialog(self,
+ 'This parametes are passed to ffmpeg2theora adjust to your needs',
+ 'Encoding Settings',
+ self.queuedata[key]['settings'])
+ if result.accepted:
+ self.queuedata[key]['settings'] = result.text
+
+ def on_encodeQueue_mouseClick(self, event):
+ self.components.addItem.enabled = False
+ self.components.editItem.enabled = False
+ self.components.removeItem.enabled = False
+ self.components.encodeQueue.enabled = False
+ self.encoder.encodeQueue(self.queuedata, self.setItemStatus, self.encodingFinished)
+
+ def encodingFinished(self):
+ self.components.addItem.enabled = True
+ self.components.editItem.enabled = True
+ self.components.removeItem.enabled = True
+ self.components.encodeQueue.enabled = True
+
+
+ def on_encodingQueue_select(self, event):
+ self.currentItem = event.m_itemIndex
+ key = self.components.encodingQueue.GetItemData(self.currentItem)
+ print self.queuedata[key]
+ self.components.editItem.enabled = True
+ self.components.removeItem.enabled = True
+
+
+if __name__ == '__main__':
+ app = model.Application(SimpleTheoraEncoderBackground)
+ app.MainLoop()
Property changes on: trunk/ffmpeg2theora/frontend/Simple Theora Encoder.py
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/ffmpeg2theora/frontend/Simple Theora Encoder.rsrc.py
===================================================================
--- trunk/ffmpeg2theora/frontend/Simple Theora Encoder.rsrc.py 2007-03-28 13:50:40 UTC (rev 12815)
+++ trunk/ffmpeg2theora/frontend/Simple Theora Encoder.rsrc.py 2007-03-28 18:02:54 UTC (rev 12816)
@@ -0,0 +1,76 @@
+{'application':{'type':'Application',
+ 'name':'SimpleTheoraEncoder',
+ 'backgrounds': [
+ {'type':'Background',
+ 'name':'bgTemplate',
+ 'title':'Simple Theora Encoder',
+ 'size':(559, 260),
+ 'style':['resizeable'],
+
+ 'menubar': {'type':'MenuBar',
+ 'menus': [
+ {'type':'Menu',
+ 'name':'menuFile',
+ 'label':'&File',
+ 'items': [
+ {'type':'MenuItem',
+ 'name':'menuFileExit',
+ 'label':'E&xit',
+ 'command':'exit',
+ },
+ ]
+ },
+ ]
+ },
+ 'components': [
+
+{'type':'Button',
+ 'name':'encodeQueue',
+ 'position':(462, 187),
+ 'enabled':False,
+ 'label':u'Encode...',
+ },
+
+{'type':'Button',
+ 'name':'editItem',
+ 'position':(461, 104),
+ 'enabled':False,
+ 'label':u'Edit...',
+ },
+
+{'type':'Button',
+ 'name':'removeItem',
+ 'position':(461, 136),
+ 'enabled':False,
+ 'label':u'Remove',
+ },
+
+{'type':'Button',
+ 'name':'addItem',
+ 'position':(462, 71),
+ 'label':u'Add...',
+ },
+
+{'type':'StaticText',
+ 'name':'title',
+ 'position':(15, 9),
+ 'font':{'faceName': u'Lucida Grande', 'family': 'sansSerif', 'size': 28},
+ 'text':u'Simple Theora Encoder',
+ },
+
+{'type':'MultiColumnList',
+ 'name':'encodingQueue',
+ 'position':(15, 49),
+ 'size':(431, 164),
+ 'backgroundColor':(255, 255, 255),
+ 'columnHeadings':[],
+ 'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 12},
+ 'items':[],
+ 'maxColumns':20,
+ 'rules':1,
+ },
+
+] # end components
+} # end background
+] # end backgrounds
+} }
Added: trunk/ffmpeg2theora/frontend/setup.macosx.py
===================================================================
--- trunk/ffmpeg2theora/frontend/setup.macosx.py 2007-03-28 13:50:40 UTC (rev 12815)
+++ trunk/ffmpeg2theora/frontend/setup.macosx.py 2007-03-28 18:02:54 UTC (rev 12816)
@@ -0,0 +1,34 @@
+from distutils.core import setup
+from py2app.build_app import py2app
+
+import os
+import shutil
+
+class mypy2app(py2app):
+ def run(self):
+ py2app.run(self)
+ print ">>>>> installing ffmpeg2theora <<<<<<"
+ resourcesRoot = os.path.join(self.dist_dir, 'Simple Theora Encoder.app/Contents/Resources')
+ shutil.copy('ffmpeg2theora', os.path.join(resourcesRoot, 'ffmpeg2theora'))
+ rsrc_file = "Simple Theora Encoder.rsrc.py"
+ shutil.copy(rsrc_file, os.path.join(resourcesRoot, rsrc_file))
+
+ imgPath = os.path.join(self.dist_dir, "Simple Theora Encoder.dmg")
+ os.system('''hdiutil create -srcfolder "%s" -volname "Simple Theora Encoder" -format UDZO "%s"''' %
+ (self.dist_dir, os.path.join(self.dist_dir, "Simple Theora Encoder.tmp.dmg")))
+ os.system('''hdiutil convert -format UDZO -imagekey zlib-level=9 -o "%s" "%s"''' %
+ (imgPath, os.path.join(self.dist_dir, "Simple Theora Encoder.tmp.dmg")))
+ os.remove(os.path.join(self.dist_dir,"Simple Theora Encoder.tmp.dmg"))
+
+setup(
+ app=['Simple Theora Encoder.py'],
+ name='Simple Theora Encoder',
+ options={'py2app': {
+ 'strip': True,
+ 'packages': ['PythonCard', 'wx']
+ }},
+ cmdclass = {'py2app': mypy2app }
+
+)
+
+
Modified: trunk/ffmpeg2theora/theorautils.c
===================================================================
--- trunk/ffmpeg2theora/theorautils.c 2007-03-28 13:50:40 UTC (rev 12815)
+++ trunk/ffmpeg2theora/theorautils.c 2007-03-28 18:02:54 UTC (rev 12816)
@@ -43,6 +43,7 @@
void init_info(oggmux_info *info) {
info->with_skeleton = 0; /* skeleton is disabled by default */
+ info->frontend = 0; /*frontend mode*/
info->videotime = 0;
info->audiotime = 0;
info->audio_bytesout = 0;
@@ -395,12 +396,21 @@
int remaining_seconds = (long) remaining % 60;
int remaining_minutes = ((long) remaining / 60) % 60;
int remaining_hours = (long) remaining / 3600;
-
- fprintf (stderr,"\r %d:%02d:%02d.%02d audio: %dkbps video: %dkbps, time remaining: %02d:%02d:%02d ",
- hours, minutes, seconds, hundredths,
- info->akbps, info->vkbps,
- remaining_hours, remaining_minutes, remaining_seconds
- );
+ if(info->frontend) {
+ fprintf (stderr,"\nf2t ;position: %.02lf;audio_kbps: %d;video_kbps: %d;remaining: %.02lf\n",
+ timebase,
+ info->akbps, info->vkbps,
+ remaining
+ );
+
+ }
+ else {
+ fprintf (stderr,"\r %d:%02d:%02d.%02d audio: %dkbps video: %dkbps, time remaining: %02d:%02d:%02d ",
+ hours, minutes, seconds, hundredths,
+ info->akbps, info->vkbps,
+ remaining_hours, remaining_minutes, remaining_seconds
+ );
+ }
}
static int write_audio_page(oggmux_info *info)
Modified: trunk/ffmpeg2theora/theorautils.h
===================================================================
--- trunk/ffmpeg2theora/theorautils.h 2007-03-28 13:50:40 UTC (rev 12815)
+++ trunk/ffmpeg2theora/theorautils.h 2007-03-28 18:02:54 UTC (rev 12816)
@@ -41,7 +41,7 @@
int audio_only;
int video_only;
int with_skeleton;
-
+ int frontend;
/* vorbis settings */
int sample_rate;
int channels;
More information about the commits
mailing list