[xiph-commits] r16338 - in trunk/ffmpeg2theora: frontend frontend/theoraenc src
j at svn.xiph.org
j at svn.xiph.org
Sun Jul 26 07:17:55 PDT 2009
Author: j
Date: 2009-07-26 07:17:54 -0700 (Sun, 26 Jul 2009)
New Revision: 16338
Modified:
trunk/ffmpeg2theora/frontend/Simple Theora Encoder.py
trunk/ffmpeg2theora/frontend/theoraenc/addVideoDialog.py
trunk/ffmpeg2theora/frontend/theoraenc/theoraenc.py
trunk/ffmpeg2theora/src/theorautils.c
Log:
cleanup frontend a bit, update status less often
Modified: trunk/ffmpeg2theora/frontend/Simple Theora Encoder.py
===================================================================
--- trunk/ffmpeg2theora/frontend/Simple Theora Encoder.py 2009-07-26 10:52:02 UTC (rev 16337)
+++ trunk/ffmpeg2theora/frontend/Simple Theora Encoder.py 2009-07-26 14:17:54 UTC (rev 16338)
@@ -1,6 +1,6 @@
#!/usr/bin/env python
+# vi:si:et:sw=2:sts=2:ts=2
# -*- coding: utf-8 -*-
-# vi:si:et:sw=2:sts=2:ts=2
# Written 2007 by j at v2v.cc
#
# see LICENSE.txt for license information
@@ -32,31 +32,39 @@
_qd_key = {}
encodingQueueInitialized = False
inputFile = False
+ encoding = False
+ quit = False
+
def initMainInterface(self):
#TODO: addd menue
self.encodingQueue = wx.ListCtrl(self, -1, style=wx.LC_REPORT)
- self.encodingQueue.SetPosition(wx.Point(15,50))
- self.encodingQueue.SetSize(wx.Size(435, 165))
+ self.encodingQueue.SetPosition(wx.Point(10,50))
+ self.encodingQueue.SetSize(wx.Size(440, 165))
self.encodingQueue.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
- buttonSize = wx.Size(88,-1)
- self.addItem = wx.Button(self, wx.ID_ANY, "Add...", wx.Point(462, 71), buttonSize)
+ buttonSize = wx.Size(80,-1)
+ self.addItem = wx.Button(self, wx.ID_ANY, "Add...", wx.Point(460, 70), buttonSize)
self.Bind(wx.EVT_BUTTON, self.OnClickAdd, self.addItem)
- self.removeItem = wx.Button(self, wx.ID_ANY, "Remove", wx.Point(462, 106), buttonSize)
+ self.removeItem = wx.Button(self, wx.ID_ANY, "Remove", wx.Point(460, 100), buttonSize)
self.Bind(wx.EVT_BUTTON, self.OnClickRemove, self.removeItem)
self.removeItem.Disable()
- self.buttonQuit = wx.Button(self, wx.ID_ANY, "Quit", wx.Point(462, 187), buttonSize)
- self.Bind(wx.EVT_BUTTON, self.OnExit, self.buttonQuit)
-
+ self.buttonEncode = wx.Button(self, wx.ID_ANY, "Encode", wx.Point(460, 190), buttonSize)
+ self.Bind(wx.EVT_BUTTON, self.OnEncode, self.buttonEncode)
+ self.buttonEncode.Disable()
+
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+
#Title
- self.title = wx.StaticText(self, -1, "Simple Theora Encoder", wx.Point(15, 10))
+ titleFont = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False, u'Sans')
+ self.title = wx.StaticText(self, -1, "Simple Theora Encoder", wx.Point(10, 10))
+ self.title.SetFont(titleFont)
def __init__(self, parent, id, title, inputFile=None):
- wx.Frame.__init__(self, parent, id, title, size=(559,260))
+ wx.Frame.__init__(self, parent, id, title, size=(550,230))
self.inputFile = inputFile
self.initMainInterface()
self.Show(True)
@@ -69,7 +77,7 @@
q.ClearAll()
q.InsertColumn(0, "Name")
q.InsertColumn(1, "Stats")
- q.SetColumnWidth(0, 195)
+ q.SetColumnWidth(0, 200)
q.SetColumnWidth(1, 240)
q.itemDataMap = self.queuedata
@@ -106,8 +114,8 @@
itemID = item['itemID']
if item['status'] != status:
item['status'] = status
+ #self.title.SetLabel(os.path.basename(item['path']) +': '+ status)
self.encodingQueue.SetStringItem(itemID, 1, status)
- now = time.mktime(time.localtime())
def getSettings(self, options):
settings = []
@@ -131,12 +139,36 @@
settings.append('%s' % s['encoding'])
return settings
- def addItemThread(self, item):
- if not item['enc'].encode():
- print "encoding failed"
- return
- return True
-
+ def encodeItem(self, item):
+ item['encoding'] = True
+ if self.currentItem == item['itemID']:
+ self.removeItem.SetLabel('Cancel')
+ self.setItemStatus(item['itemID'], 'encoding')
+ result = item['enc'].encode()
+ if not result:
+ self.setItemStatus(item['itemID'], 'encoding failed.')
+ else:
+ self.setItemStatus(item['itemID'], 'encoding done.')
+
+ item['encoded'] = True
+ item['encoding'] = False
+ return result
+
+ def encodeQueue(self, foo):
+ def nextItem():
+ items = self.queuedata.items()
+ for x in range(len(items)):
+ key, item = items[x]
+ if not item['encoded']:
+ return item
+ return None
+
+ next = nextItem()
+ while next and not self.quit:
+ self.encodeItem(next)
+ next = nextItem()
+ self.encoding = False
+
def addItemToQueue(self, videoFile, options):
name = os.path.basename(videoFile)
display_path = videoFile
@@ -146,10 +178,12 @@
path = videoFile,
options = options,
display_path = display_path,
- status = 'encoding... ',
+ status = 'waiting... ',
listID = 0,
name = name,
)
+ item['encoding'] = False
+ item['encoded'] = False
item['enc'] = theoraenc.TheoraEnc(videoFile, None, lambda x: self.updateItemStatus(name, x))
item['enc'].settings = self.getSettings(options)
@@ -170,10 +204,15 @@
self.queuedata[key] = item
self.initializeUploadQueue()
self._qd_key[name] = key
- thread.start_new_thread(self.addItemThread, (item, ))
def OnItemSelected(self, event):
self.currentItem = event.m_itemIndex
+ key = self.encodingQueue.GetItemData(self.currentItem)
+ item = self.queuedata[key]
+ if item['encoding']:
+ self.removeItem.SetLabel('Cancel')
+ else:
+ self.removeItem.SetLabel('Remove')
self.removeItem.Enable()
def OnClickAdd(self, event):
@@ -181,24 +220,42 @@
time.sleep(0.5)
if result['ok']:
self.addItemToQueue(result['videoFile'], result)
+ if not self.encoding:
+ self.buttonEncode.Enable()
def OnClickRemove(self, event):
key = self.encodingQueue.GetItemData(self.currentItem)
- print key
if 'enc' in self.queuedata[key]:
self.queuedata[key]['enc'].cancel()
del self.queuedata[key]
self.initializeUploadQueue(self.currentItem)
- def OnExit(self, event):
- for key in self.queuedata:
- if 'enc' in self.queuedata[key]:
- try:
- self.queuedata[key]['enc'].cancel()
- except:
- pass
- sys.exit()
+ def OnEncode(self, event):
+ if not self.encoding:
+ self.encoding = True
+ thread.start_new_thread(self.encodeQueue, ("foo", ))
+ self.buttonEncode.Disable()
+ def OnClose(self, event):
+ close = True
+ if self.encoding:
+ dlg = wx.MessageDialog(self,
+ "Videos are still encoded.\nDo you really want to close Simple Theora Encoder?",
+ "Confirm Exit", wx.OK|wx.CANCEL|wx.ICON_QUESTION)
+ result = dlg.ShowModal()
+ dlg.Destroy()
+ if result != wx.ID_OK:
+ close = False
+ if close:
+ self.quit = True
+ for key in self.queuedata:
+ if 'enc' in self.queuedata[key]:
+ try:
+ self.queuedata[key]['enc'].cancel()
+ except:
+ pass
+ self.Destroy()
+
def gui(inputFile = None):
app = wx.PySimpleApp()
frame=SimpleTheoraEncoder(None, wx.ID_ANY, 'Simple Theora Encoder', inputFile = inputFile)
Modified: trunk/ffmpeg2theora/frontend/theoraenc/addVideoDialog.py
===================================================================
--- trunk/ffmpeg2theora/frontend/theoraenc/addVideoDialog.py 2009-07-26 10:52:02 UTC (rev 16337)
+++ trunk/ffmpeg2theora/frontend/theoraenc/addVideoDialog.py 2009-07-26 14:17:54 UTC (rev 16338)
@@ -7,6 +7,8 @@
from addSubtitlesDialog import addSubtitlesPropertiesDialog, SubtitlesList
import wx
+
+import theoraenc
class AddVideoDialog(wx.Dialog):
def __init__(
@@ -273,7 +275,7 @@
self.btnOK = wx.Button(self, wx.ID_OK)
self.btnOK.SetDefault()
self.btnOK.Disable()
- self.btnOK.SetLabel('Encode')
+ self.btnOK.SetLabel('Add to queue')
hbox.Add(self.btnOK, 0, wx.EXPAND|wx.ALL, padding)
hbox = wx.BoxSizer(wx.HORIZONTAL)
@@ -304,14 +306,25 @@
return filename
def selectVideoFile(self, videoFile):
- self.videoFile = videoFile
- lValue = videoFile
- lLength = 45
- if len(lValue) > lLength:
- lValue = "..." + lValue[-lLength:]
- self.btnVideoFile.SetLabel(lValue)
- self.btnOK.Enable()
+ self.info = theoraenc.fileInfo(videoFile)
+ if self.info:
+ #FIXME: enable/disable options based on input
+ """
+ if "video" in self.info: #source has video
+ #enable video options
+ if "audio" in self.info: #source has audio
+ #enable audio options
+ if "audio" in self.info: #source has audio
+ """
+ self.videoFile = videoFile
+ lValue = videoFile
+ lLength = 45
+ if len(lValue) > lLength:
+ lValue = "..." + lValue[-lLength:]
+ self.btnVideoFile.SetLabel(lValue)
+ self.btnOK.Enable()
+
def CheckSubtitlesSelection(self, event):
idx=self.subtitles.GetFirstSelected()
if idx<0:
@@ -380,8 +393,22 @@
encoding = dlg.subtitles.GetItem(idx, 2).GetText()
file = dlg.subtitles.GetItem(idx, 3).GetText()
result['subtitles'].append({'encoding':encoding, 'language':language, 'category':category, 'file':file})
- print result
else:
result['ok'] = False
dlg.Destroy()
return result
+if __name__ == "__main__":
+ import sys
+ class Frame(wx.Frame):
+ inputFile = None
+ def __init__(self):
+ wx.Frame.__init__(self, None, wx.ID_ANY, "add video test", size=(559,260))
+ self.Show(True)
+
+ app = wx.PySimpleApp()
+ frame=Frame()
+ if len(sys.argv) > 1:
+ frame.inputFile = sys.argv[1]
+ result = addVideoDialog(frame, True)
+ print result
+
Modified: trunk/ffmpeg2theora/frontend/theoraenc/theoraenc.py
===================================================================
--- trunk/ffmpeg2theora/frontend/theoraenc/theoraenc.py 2009-07-26 10:52:02 UTC (rev 16337)
+++ trunk/ffmpeg2theora/frontend/theoraenc/theoraenc.py 2009-07-26 14:17:54 UTC (rev 16338)
@@ -7,8 +7,10 @@
import sys
import signal
import subprocess
+import threading
import simplejson
+import wx
resourcePath = abspath(dirname(__file__))
@@ -45,6 +47,22 @@
seconds = (seconds-((hours*3600)+(minutes*60)))
return '%02d:%02d:%02d' % (hours, minutes, seconds)
+class ThreadWorker(threading.Thread):
+ def __init__(self, callable, *args, **kwargs):
+ super(ThreadWorker, self).__init__()
+ self.callable = callable
+ self.args = args
+ self.kwargs = kwargs
+ self.setDaemon(True)
+
+ def run(self):
+ try:
+ self.callable(*self.args, **self.kwargs)
+ except wx.PyDeadObjectError:
+ pass
+ except Exception, e:
+ print e
+
class TheoraEnc:
settings = []
p = None
@@ -88,44 +106,52 @@
def encode(self):
cmd = self.commandline()
- print cmd
p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, close_fds=True)
self.p = p
- f = p.stdout
- line = f.readline()
info = dict()
status = ''
self.warning_timeout = 0
- while line:
- now = time.time()
- try:
- data = simplejson.loads(line)
- for key in data:
- info[key] = data[key]
- if 'WARNING' in info:
- status = info['WARNING']
- self.warning_timeout = now + 3
- del info['WARNING']
+
+ def worker(pipe):
+ while True:
+ line = pipe.readline()
+ if line == '':
+ break
else:
- status=None
- if now >= self.warning_timeout:
- if 'position' in info:
- if 'duration' in info and float(info['duration']):
- encoded = "encoding % 3d %% done " % ((float(info['position']) / float(info['duration'])) * 100)
- else:
- encoded = "encoded %s/" % timestr(float(info['position']))
- if float(info['remaining'])>0:
- status = encoded + '/ '+ timestr(float(info['remaining']))
- else:
- status = encoded
+ now = time.time()
+ try:
+ data = simplejson.loads(line)
+ for key in data:
+ info[key] = data[key]
+ if 'WARNING' in info:
+ status = info['WARNING']
+ self.warning_timeout = now + 3
+ del info['WARNING']
else:
- status = "encoding.."
- if status != None:
- self.updateGUI(status)
- except:
- pass
- line = f.readline()
- f.close()
+ status=None
+ if now >= self.warning_timeout:
+ if 'position' in info:
+ if 'duration' in info and float(info['duration']):
+ encoded = "encoding % 3d %% done " % ((float(info['position']) / float(info['duration'])) * 100)
+ else:
+ encoded = "encoded %s/" % timestr(float(info['position']))
+ if float(info['remaining'])>0:
+ status = encoded + '/ '+ timestr(float(info['remaining']))
+ else:
+ status = encoded
+ status = "encoding % 3d %% done " % ((float(info['position']) / float(info['duration'])) * 100)
+ else:
+ status = "encoding.."
+ if status != None:
+ self.updateGUI(status)
+ except:
+ pass
+
+ stdout_worker = ThreadWorker(worker, p.stdout)
+ stdout_worker.start()
+
+ p.wait()
+
if info.get('result', 'no') == 'ok':
self.updateGUI('Encoding done.')
return True
@@ -133,6 +159,20 @@
self.updateGUI(info.get('result', 'Encoding failed.'))
return False
+
+def fileInfo(filename):
+ cmd = []
+ cmd.append(ffmpeg2theora)
+ cmd.append('--info')
+ cmd.append(filename)
+ p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, close_fds=True)
+ data, err = p.communicate()
+ try:
+ info = simplejson.loads(data)
+ except:
+ info = None
+ return info
+
ffmpeg2theora = probe_ffmpeg2theora()
hasKate = probe_kate(ffmpeg2theora)
Modified: trunk/ffmpeg2theora/src/theorautils.c
===================================================================
--- trunk/ffmpeg2theora/src/theorautils.c 2009-07-26 10:52:02 UTC (rev 16337)
+++ trunk/ffmpeg2theora/src/theorautils.c 2009-07-26 14:17:54 UTC (rev 16338)
@@ -631,6 +631,7 @@
}
static void print_stats(oggmux_info *info, double timebase) {
+ static double last = -2;
int hundredths = timebase * 100 - (long) timebase * 100;
int seconds = (long) timebase % 60;
int minutes = ((long) timebase / 60) % 60;
@@ -639,34 +640,37 @@
int remaining_seconds = (long) remaining % 60;
int remaining_minutes = ((long) remaining / 60) % 60;
int remaining_hours = (long) remaining / 3600;
- if (info->frontend) {
- fprintf(info->frontend, "{\"duration\": %lf, \"position\": %.02lf, \"audio_kbps\": %d, \"video_kbps\": %d, \"remaining\": %.02lf}\n",
- (double)info->duration,
- timebase,
- info->akbps, info->vkbps,
- remaining
- );
- fflush (info->frontend);
- }
- else if (timebase > 0 ) {
- if (!remaining) {
- remaining = time(NULL) - info->start_time;
- remaining_seconds = (long) remaining % 60;
- remaining_minutes = ((long) remaining / 60) % 60;
- remaining_hours = (long) remaining / 3600;
- fprintf (stderr,"\r %d:%02d:%02d.%02d audio: %dkbps video: %dkbps, time elapsed: %02d:%02d:%02d ",
- hours, minutes, seconds, hundredths,
+ if (timebase - last > 0.5) {
+ last = timebase;
+ if (info->frontend) {
+ fprintf(info->frontend, "{\"duration\": %lf, \"position\": %.02lf, \"audio_kbps\": %d, \"video_kbps\": %d, \"remaining\": %.02lf}\n",
+ (double)info->duration,
+ timebase,
info->akbps, info->vkbps,
- remaining_hours, remaining_minutes, remaining_seconds
+ remaining
);
+ fflush (info->frontend);
}
- else {
- fprintf (stderr,"\r %d:%02d:%02d.%02d audio: %dkbps video: %dkbps, ET: %02d:%02d:%02d, est. size: %.01lf MB ",
- hours, minutes, seconds, hundredths,
- info->akbps, info->vkbps,
- remaining_hours, remaining_minutes, remaining_seconds,
- estimated_size(info, timebase)
- );
+ else if (timebase > 0 ) {
+ if (!remaining) {
+ remaining = time(NULL) - info->start_time;
+ remaining_seconds = (long) remaining % 60;
+ remaining_minutes = ((long) remaining / 60) % 60;
+ remaining_hours = (long) remaining / 3600;
+ fprintf (stderr,"\r %d:%02d:%02d.%02d audio: %dkbps video: %dkbps, time elapsed: %02d:%02d:%02d ",
+ hours, minutes, seconds, hundredths,
+ info->akbps, info->vkbps,
+ remaining_hours, remaining_minutes, remaining_seconds
+ );
+ }
+ else {
+ fprintf (stderr,"\r %d:%02d:%02d.%02d audio: %dkbps video: %dkbps, ET: %02d:%02d:%02d, est. size: %.01lf MB ",
+ hours, minutes, seconds, hundredths,
+ info->akbps, info->vkbps,
+ remaining_hours, remaining_minutes, remaining_seconds,
+ estimated_size(info, timebase)
+ );
+ }
}
}
}
More information about the commits
mailing list