Merge lp:~jderose/novacut/renderer into lp:novacut
- renderer
- Merge into trunk
Proposed by
Jason Gerard DeRose
Status: | Merged |
---|---|
Merged at revision: | 73 |
Proposed branch: | lp:~jderose/novacut/renderer |
Merge into: | lp:novacut |
Diff against target: |
926 lines (+672/-32) 14 files modified
create-demo-project.py (+73/-0) debian/control (+1/-0) demo.json (+157/-0) novacut-cli (+6/-0) novacut-renderer (+50/-0) novacut-service (+39/-9) novacut/schema.py (+52/-2) novacut2/builder.py (+2/-2) novacut2/extractor.py (+186/-0) novacut2/renderer.py (+8/-7) novacut2/tests/test_renderer.py (+9/-8) novacut2/worker.py (+82/-0) setup.py (+6/-0) setup2.py (+1/-4) |
To merge this branch: | bzr merge lp:~jderose/novacut/renderer |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Novacut Dev | Pending | ||
Review via email: mp+89452@code.launchpad.net |
Commit message
Description of the change
Yup, too tired to go into details!
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'create-demo-project.py' | |||
2 | --- create-demo-project.py 1970-01-01 00:00:00 +0000 | |||
3 | +++ create-demo-project.py 2012-01-20 15:32:24 +0000 | |||
4 | @@ -0,0 +1,73 @@ | |||
5 | 1 | #!/usr/bin/python3 | ||
6 | 2 | |||
7 | 3 | import json | ||
8 | 4 | import time | ||
9 | 5 | from microfiber import dmedia_env, Database, Conflict | ||
10 | 6 | from novacut import schema | ||
11 | 7 | from collections import OrderedDict | ||
12 | 8 | |||
13 | 9 | docs = json.load(open('demo.json', 'r')) | ||
14 | 10 | for doc in docs: | ||
15 | 11 | doc['ver'] = 0 | ||
16 | 12 | doc['time'] = time.time() | ||
17 | 13 | |||
18 | 14 | |||
19 | 15 | p = { | ||
20 | 16 | '_id': '5A236DNAC6NMS5XIBUMHTY2A', | ||
21 | 17 | 'ver': 0, | ||
22 | 18 | 'title': '2 Clip Demo', | ||
23 | 19 | 'db_name': 'novacut-0-5a236dnac6nms5xibumhty2a', | ||
24 | 20 | 'time': 1327022245.45872, | ||
25 | 21 | 'atime': 1327022245.45872, | ||
26 | 22 | 'type': 'novacut/project', | ||
27 | 23 | } | ||
28 | 24 | |||
29 | 25 | env = dmedia_env() | ||
30 | 26 | db = Database('novacut-0', env) | ||
31 | 27 | db.ensure() | ||
32 | 28 | project = Database(p['db_name'], env) | ||
33 | 29 | if project.ensure(): | ||
34 | 30 | project.post(p) | ||
35 | 31 | project.post({'docs': docs}, '_bulk_docs') | ||
36 | 32 | try: | ||
37 | 33 | db.save(p) | ||
38 | 34 | except Conflict: | ||
39 | 35 | pass | ||
40 | 36 | db.post({'docs': docs}, '_bulk_docs') | ||
41 | 37 | |||
42 | 38 | root = schema.save_to_intrinsic('AUABDULVRZIBH727GQP2HXSA', project, db) | ||
43 | 39 | print('root:', root) | ||
44 | 40 | |||
45 | 41 | node = { | ||
46 | 42 | 'muxer': {'name': 'oggmux'}, | ||
47 | 43 | 'video': { | ||
48 | 44 | 'encoder': { | ||
49 | 45 | 'name': 'theoraenc', | ||
50 | 46 | 'props': { | ||
51 | 47 | 'quality': 52, | ||
52 | 48 | }, | ||
53 | 49 | }, | ||
54 | 50 | 'filter': { | ||
55 | 51 | 'mime': 'video/x-raw-yuv', | ||
56 | 52 | 'caps': { | ||
57 | 53 | 'width': 960, | ||
58 | 54 | 'height': 540, | ||
59 | 55 | }, | ||
60 | 56 | }, | ||
61 | 57 | }, | ||
62 | 58 | } | ||
63 | 59 | doc = schema.create_settings(node) | ||
64 | 60 | try: | ||
65 | 61 | db.save(doc) | ||
66 | 62 | except Conflict: | ||
67 | 63 | pass | ||
68 | 64 | print('settings:', doc['_id']) | ||
69 | 65 | |||
70 | 66 | doc = schema.create_job(root, doc['_id']) | ||
71 | 67 | try: | ||
72 | 68 | db.save(doc) | ||
73 | 69 | except Conflict: | ||
74 | 70 | pass | ||
75 | 71 | print('job:', doc['_id']) | ||
76 | 72 | |||
77 | 73 | |||
78 | 0 | 74 | ||
79 | === modified file 'debian/control' | |||
80 | --- debian/control 2012-01-17 07:29:22 +0000 | |||
81 | +++ debian/control 2012-01-20 15:32:24 +0000 | |||
82 | @@ -18,6 +18,7 @@ | |||
83 | 18 | python-gst0.10, | 18 | python-gst0.10, |
84 | 19 | python-dbus, | 19 | python-dbus, |
85 | 20 | dmedia (>= 12.01), | 20 | dmedia (>= 12.01), |
86 | 21 | dc3 (>= 12.01), | ||
87 | 21 | python3-microfiber (>= 12.01), | 22 | python3-microfiber (>= 12.01), |
88 | 22 | python3-userwebkit (>= 12.01), | 23 | python3-userwebkit (>= 12.01), |
89 | 23 | python3-gi | python3-gobject, | 24 | python3-gi | python3-gobject, |
90 | 24 | 25 | ||
91 | === added file 'demo.json' | |||
92 | --- demo.json 1970-01-01 00:00:00 +0000 | |||
93 | +++ demo.json 2012-01-20 15:32:24 +0000 | |||
94 | @@ -0,0 +1,157 @@ | |||
95 | 1 | [ | ||
96 | 2 | { | ||
97 | 3 | "_id": "AUABDULVRZIBH727GQP2HXSA", | ||
98 | 4 | "node": { | ||
99 | 5 | "src": [ | ||
100 | 6 | "XBIMKG7RJRSCNBWLI24BMIVS", | ||
101 | 7 | "THYLBLNPTA2BBFSBGPUDSE3J", | ||
102 | 8 | "TNSLSNXN7UCRC6XECSZ46LHC", | ||
103 | 9 | "7FR4UH4JQPO4ISOPOWFDJ3FO", | ||
104 | 10 | "SZ6A53C2YTYQMUMLY3SXWHKX", | ||
105 | 11 | "5B6QDHAFTHJUU3TWX6JWE5TV", | ||
106 | 12 | "QD3FLQVR5TQIQDQHXAZ5EPXM", | ||
107 | 13 | "WXW4VPQJDG4K5XVIHX5ZTVBJ" | ||
108 | 14 | ], | ||
109 | 15 | "type": "sequence" | ||
110 | 16 | }, | ||
111 | 17 | "type": "novacut/node" | ||
112 | 18 | }, | ||
113 | 19 | { | ||
114 | 20 | "_id": "WXW4VPQJDG4K5XVIHX5ZTVBJ", | ||
115 | 21 | "node": { | ||
116 | 22 | "src": "VQIXPULW3G77W4XLGROMEDGFAH2XJBN4SAVFUGOZRFSIVU7N", | ||
117 | 23 | "start": { | ||
118 | 24 | "frame": 421 | ||
119 | 25 | }, | ||
120 | 26 | "stop": { | ||
121 | 27 | "frame": 436 | ||
122 | 28 | }, | ||
123 | 29 | "stream": "video", | ||
124 | 30 | "type": "slice" | ||
125 | 31 | }, | ||
126 | 32 | "type": "novacut/node" | ||
127 | 33 | }, | ||
128 | 34 | { | ||
129 | 35 | "_id": "QD3FLQVR5TQIQDQHXAZ5EPXM", | ||
130 | 36 | "node": { | ||
131 | 37 | "src": "W62OZLFQUSKE4K6SLJWJ4EHFDUTRLD7JKQXUQMDJSSUG6TAQ", | ||
132 | 38 | "start": { | ||
133 | 39 | "frame": 294 | ||
134 | 40 | }, | ||
135 | 41 | "stop": { | ||
136 | 42 | "frame": 309 | ||
137 | 43 | }, | ||
138 | 44 | "stream": "video", | ||
139 | 45 | "type": "slice" | ||
140 | 46 | }, | ||
141 | 47 | "type": "novacut/node" | ||
142 | 48 | }, | ||
143 | 49 | { | ||
144 | 50 | "_id": "5B6QDHAFTHJUU3TWX6JWE5TV", | ||
145 | 51 | "node": { | ||
146 | 52 | "src": "VQIXPULW3G77W4XLGROMEDGFAH2XJBN4SAVFUGOZRFSIVU7N", | ||
147 | 53 | "start": { | ||
148 | 54 | "frame": 381 | ||
149 | 55 | }, | ||
150 | 56 | "stop": { | ||
151 | 57 | "frame": 406 | ||
152 | 58 | }, | ||
153 | 59 | "stream": "video", | ||
154 | 60 | "type": "slice" | ||
155 | 61 | }, | ||
156 | 62 | "type": "novacut/node" | ||
157 | 63 | }, | ||
158 | 64 | { | ||
159 | 65 | "_id": "SZ6A53C2YTYQMUMLY3SXWHKX", | ||
160 | 66 | "node": { | ||
161 | 67 | "src": "W62OZLFQUSKE4K6SLJWJ4EHFDUTRLD7JKQXUQMDJSSUG6TAQ", | ||
162 | 68 | "start": { | ||
163 | 69 | "frame": 244 | ||
164 | 70 | }, | ||
165 | 71 | "stop": { | ||
166 | 72 | "frame": 269 | ||
167 | 73 | }, | ||
168 | 74 | "stream": "video", | ||
169 | 75 | "type": "slice" | ||
170 | 76 | }, | ||
171 | 77 | "type": "novacut/node" | ||
172 | 78 | }, | ||
173 | 79 | { | ||
174 | 80 | "_id": "7FR4UH4JQPO4ISOPOWFDJ3FO", | ||
175 | 81 | "node": { | ||
176 | 82 | "src": "VQIXPULW3G77W4XLGROMEDGFAH2XJBN4SAVFUGOZRFSIVU7N", | ||
177 | 83 | "start": { | ||
178 | 84 | "frame": 318 | ||
179 | 85 | }, | ||
180 | 86 | "stop": { | ||
181 | 87 | "frame": 356 | ||
182 | 88 | }, | ||
183 | 89 | "stream": "video", | ||
184 | 90 | "type": "slice" | ||
185 | 91 | }, | ||
186 | 92 | "type": "novacut/node" | ||
187 | 93 | }, | ||
188 | 94 | { | ||
189 | 95 | "_id": "TNSLSNXN7UCRC6XECSZ46LHC", | ||
190 | 96 | "node": { | ||
191 | 97 | "src": "W62OZLFQUSKE4K6SLJWJ4EHFDUTRLD7JKQXUQMDJSSUG6TAQ", | ||
192 | 98 | "start": { | ||
193 | 99 | "frame": 168 | ||
194 | 100 | }, | ||
195 | 101 | "stop": { | ||
196 | 102 | "frame": 206 | ||
197 | 103 | }, | ||
198 | 104 | "stream": "video", | ||
199 | 105 | "type": "slice" | ||
200 | 106 | }, | ||
201 | 107 | "type": "novacut/node" | ||
202 | 108 | }, | ||
203 | 109 | { | ||
204 | 110 | "_id": "THYLBLNPTA2BBFSBGPUDSE3J", | ||
205 | 111 | "node": { | ||
206 | 112 | "src": "VQIXPULW3G77W4XLGROMEDGFAH2XJBN4SAVFUGOZRFSIVU7N", | ||
207 | 113 | "start": { | ||
208 | 114 | "frame": 230 | ||
209 | 115 | }, | ||
210 | 116 | "stop": { | ||
211 | 117 | "frame": 280 | ||
212 | 118 | }, | ||
213 | 119 | "stream": "video", | ||
214 | 120 | "type": "slice" | ||
215 | 121 | }, | ||
216 | 122 | "type": "novacut/node" | ||
217 | 123 | }, | ||
218 | 124 | { | ||
219 | 125 | "_id": "XBIMKG7RJRSCNBWLI24BMIVS", | ||
220 | 126 | "node": { | ||
221 | 127 | "src": "W62OZLFQUSKE4K6SLJWJ4EHFDUTRLD7JKQXUQMDJSSUG6TAQ", | ||
222 | 128 | "start": { | ||
223 | 129 | "frame": 68 | ||
224 | 130 | }, | ||
225 | 131 | "stop": { | ||
226 | 132 | "frame": 118 | ||
227 | 133 | }, | ||
228 | 134 | "stream": "video", | ||
229 | 135 | "type": "slice" | ||
230 | 136 | }, | ||
231 | 137 | "type": "novacut/node" | ||
232 | 138 | }, | ||
233 | 139 | { | ||
234 | 140 | "_id": "W62OZLFQUSKE4K6SLJWJ4EHFDUTRLD7JKQXUQMDJSSUG6TAQ", | ||
235 | 141 | "framerate": { | ||
236 | 142 | "denom": 1, | ||
237 | 143 | "num": 25 | ||
238 | 144 | }, | ||
239 | 145 | "samplerate": 48000, | ||
240 | 146 | "type": "dmedia/file" | ||
241 | 147 | }, | ||
242 | 148 | { | ||
243 | 149 | "_id": "VQIXPULW3G77W4XLGROMEDGFAH2XJBN4SAVFUGOZRFSIVU7N", | ||
244 | 150 | "framerate": { | ||
245 | 151 | "denom": 1, | ||
246 | 152 | "num": 25 | ||
247 | 153 | }, | ||
248 | 154 | "samplerate": 48000, | ||
249 | 155 | "type": "dmedia/file" | ||
250 | 156 | } | ||
251 | 157 | ] | ||
252 | 0 | 158 | ||
253 | === modified file 'novacut-cli' | |||
254 | --- novacut-cli 2012-01-17 08:37:54 +0000 | |||
255 | +++ novacut-cli 2012-01-20 15:32:24 +0000 | |||
256 | @@ -105,6 +105,12 @@ | |||
257 | 105 | return '{} was running for {}'.format(self.bus, minsec(seconds)) | 105 | return '{} was running for {}'.format(self.bus, minsec(seconds)) |
258 | 106 | 106 | ||
259 | 107 | 107 | ||
260 | 108 | class Render(_Method): | ||
261 | 109 | 'Render an edit' | ||
262 | 110 | |||
263 | 111 | args = ['job_id'] | ||
264 | 112 | |||
265 | 113 | |||
266 | 108 | 114 | ||
267 | 109 | parser = optparse.OptionParser( | 115 | parser = optparse.OptionParser( |
268 | 110 | usage='%prog METHOD [ARGS...]', | 116 | usage='%prog METHOD [ARGS...]', |
269 | 111 | 117 | ||
270 | === added file 'novacut-renderer' | |||
271 | --- novacut-renderer 1970-01-01 00:00:00 +0000 | |||
272 | +++ novacut-renderer 2012-01-20 15:32:24 +0000 | |||
273 | @@ -0,0 +1,50 @@ | |||
274 | 1 | #!/usr/bin/python | ||
275 | 2 | |||
276 | 3 | # novacut: the collaborative video editor | ||
277 | 4 | # Copyright (C) 2011 Novacut Inc | ||
278 | 5 | # | ||
279 | 6 | # This file is part of `novacut`. | ||
280 | 7 | # | ||
281 | 8 | # `novacut` is free software: you can redistribute it and/or modify it under | ||
282 | 9 | # the terms of the GNU Affero General Public License as published by the Free | ||
283 | 10 | # Software Foundation, either version 3 of the License, or (at your option) | ||
284 | 11 | # any later version. | ||
285 | 12 | # | ||
286 | 13 | # `novacut` is distributed in the hope that it will be useful, but WITHOUT ANY | ||
287 | 14 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
288 | 15 | # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for | ||
289 | 16 | # more details. | ||
290 | 17 | # | ||
291 | 18 | # You should have received a copy of the GNU Affero General Public License | ||
292 | 19 | # along with `novacut`. If not, see <http://www.gnu.org/licenses/>. | ||
293 | 20 | # | ||
294 | 21 | # Authors: | ||
295 | 22 | # Jason Gerard DeRose <jderose@novacut.com> | ||
296 | 23 | |||
297 | 24 | """ | ||
298 | 25 | Script to fire-off a render. | ||
299 | 26 | """ | ||
300 | 27 | |||
301 | 28 | import optparse | ||
302 | 29 | import novacut2 | ||
303 | 30 | |||
304 | 31 | import gobject | ||
305 | 32 | import dbus | ||
306 | 33 | from dbus.mainloop.glib import DBusGMainLoop | ||
307 | 34 | |||
308 | 35 | |||
309 | 36 | gobject.threads_init() | ||
310 | 37 | DBusGMainLoop(set_as_default=True) | ||
311 | 38 | session = dbus.SessionBus() | ||
312 | 39 | |||
313 | 40 | |||
314 | 41 | parser = optparse.OptionParser( | ||
315 | 42 | version=novacut2.__version__, | ||
316 | 43 | ) | ||
317 | 44 | (options, args) = parser.parse_args() | ||
318 | 45 | job_id = args[0] | ||
319 | 46 | |||
320 | 47 | from novacut2.worker import Worker | ||
321 | 48 | worker = Worker() | ||
322 | 49 | _id = worker.run(job_id) | ||
323 | 50 | print(_id) | ||
324 | 0 | 51 | ||
325 | === modified file 'novacut-service' | |||
326 | --- novacut-service 2012-01-17 05:42:15 +0000 | |||
327 | +++ novacut-service 2012-01-20 15:32:24 +0000 | |||
328 | @@ -1,4 +1,4 @@ | |||
330 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python3 |
331 | 2 | 2 | ||
332 | 3 | # novacut: the collaborative video editor | 3 | # novacut: the collaborative video editor |
333 | 4 | # Copyright (C) 2011 Novacut Inc | 4 | # Copyright (C) 2011 Novacut Inc |
334 | @@ -31,31 +31,42 @@ | |||
335 | 31 | import optparse | 31 | import optparse |
336 | 32 | import json | 32 | import json |
337 | 33 | from os import path | 33 | from os import path |
338 | 34 | from threading import Thread | ||
339 | 35 | import subprocess | ||
340 | 34 | 36 | ||
341 | 35 | import dbus | 37 | import dbus |
342 | 36 | import dbus.service | 38 | import dbus.service |
343 | 37 | from dbus.mainloop.glib import DBusGMainLoop | 39 | from dbus.mainloop.glib import DBusGMainLoop |
345 | 38 | import gobject | 40 | from gi.repository import GObject |
346 | 39 | 41 | ||
348 | 40 | import novacut2 | 42 | import novacut |
349 | 41 | 43 | ||
350 | 42 | 44 | ||
351 | 43 | BUS = 'com.novacut.Renderer' | 45 | BUS = 'com.novacut.Renderer' |
352 | 44 | IFACE = BUS | 46 | IFACE = BUS |
353 | 45 | 47 | ||
355 | 46 | gobject.threads_init() | 48 | GObject.threads_init() |
356 | 47 | DBusGMainLoop(set_as_default=True) | 49 | DBusGMainLoop(set_as_default=True) |
357 | 48 | session = dbus.SessionBus() | 50 | session = dbus.SessionBus() |
358 | 49 | 51 | ||
359 | 50 | 52 | ||
362 | 51 | def dumps(obj): | 53 | renderer = path.join(path.dirname(__file__), 'novacut-renderer') |
363 | 52 | return json.dumps(obj, sort_keys=True, separators=(',', ': '), indent=4) | 54 | assert path.isfile(renderer) |
364 | 55 | |||
365 | 56 | |||
366 | 57 | def _start_thread(target, *args): | ||
367 | 58 | thread = Thread(target=target, args=args) | ||
368 | 59 | thread.daemon = True | ||
369 | 60 | thread.start() | ||
370 | 61 | return thread | ||
371 | 53 | 62 | ||
372 | 54 | 63 | ||
373 | 55 | class Service(dbus.service.Object): | 64 | class Service(dbus.service.Object): |
374 | 65 | workers = {} | ||
375 | 66 | |||
376 | 56 | def __init__(self, bus): | 67 | def __init__(self, bus): |
377 | 57 | self.bus = bus | 68 | self.bus = bus |
379 | 58 | self.mainloop = gobject.MainLoop() | 69 | self.mainloop = GObject.MainLoop() |
380 | 59 | super(Service, self).__init__(session, object_path='/') | 70 | super(Service, self).__init__(session, object_path='/') |
381 | 60 | self.busname = dbus.service.BusName(bus, session) | 71 | self.busname = dbus.service.BusName(bus, session) |
382 | 61 | 72 | ||
383 | @@ -65,12 +76,17 @@ | |||
384 | 65 | def kill(self): | 76 | def kill(self): |
385 | 66 | self.mainloop.quit() | 77 | self.mainloop.quit() |
386 | 67 | 78 | ||
387 | 79 | def render(self, job_id): | ||
388 | 80 | cmd = [renderer, job_id] | ||
389 | 81 | file_id = subprocess.check_output(cmd).decode('utf-8') | ||
390 | 82 | self.RenderFinished(job_id, file_id) | ||
391 | 83 | |||
392 | 68 | @dbus.service.method(IFACE, in_signature='', out_signature='s') | 84 | @dbus.service.method(IFACE, in_signature='', out_signature='s') |
393 | 69 | def Version(self): | 85 | def Version(self): |
394 | 70 | """ | 86 | """ |
395 | 71 | Return Novacut version. | 87 | Return Novacut version. |
396 | 72 | """ | 88 | """ |
398 | 73 | return novacut2.__version__ | 89 | return novacut.__version__ |
399 | 74 | 90 | ||
400 | 75 | @dbus.service.method(IFACE, in_signature='', out_signature='i') | 91 | @dbus.service.method(IFACE, in_signature='', out_signature='i') |
401 | 76 | def Kill(self): | 92 | def Kill(self): |
402 | @@ -80,9 +96,23 @@ | |||
403 | 80 | self.kill() | 96 | self.kill() |
404 | 81 | return int(time.time() - start_time) | 97 | return int(time.time() - start_time) |
405 | 82 | 98 | ||
406 | 99 | @dbus.service.method(IFACE, in_signature='s', out_signature='b') | ||
407 | 100 | def Render(self, job_id): | ||
408 | 101 | """ | ||
409 | 102 | Render an edit. | ||
410 | 103 | """ | ||
411 | 104 | if job_id in self.workers: | ||
412 | 105 | return False | ||
413 | 106 | self.workers[job_id] = _start_thread(self.render, job_id) | ||
414 | 107 | return True | ||
415 | 108 | |||
416 | 109 | @dbus.service.signal(IFACE, signature='ss') | ||
417 | 110 | def RenderFinished(self, job_id, file_id): | ||
418 | 111 | del self.workers[job_id] | ||
419 | 112 | |||
420 | 83 | 113 | ||
421 | 84 | parser = optparse.OptionParser( | 114 | parser = optparse.OptionParser( |
423 | 85 | version=novacut2.__version__, | 115 | version=novacut.__version__, |
424 | 86 | ) | 116 | ) |
425 | 87 | parser.add_option('--bus', | 117 | parser.add_option('--bus', |
426 | 88 | help='DBus bus name; default is {!r}'.format(BUS), | 118 | help='DBus bus name; default is {!r}'.format(BUS), |
427 | 89 | 119 | ||
428 | === modified file 'novacut/schema.py' | |||
429 | --- novacut/schema.py 2012-01-17 12:15:44 +0000 | |||
430 | +++ novacut/schema.py 2012-01-20 15:32:24 +0000 | |||
431 | @@ -132,7 +132,7 @@ | |||
432 | 132 | from collections import namedtuple | 132 | from collections import namedtuple |
433 | 133 | 133 | ||
434 | 134 | from skein import skein512 | 134 | from skein import skein512 |
436 | 135 | from microfiber import random_id, RANDOM_B32LEN | 135 | from microfiber import random_id, RANDOM_B32LEN, Conflict |
437 | 136 | from dmedia.schema import ( | 136 | from dmedia.schema import ( |
438 | 137 | _label, | 137 | _label, |
439 | 138 | _value, | 138 | _value, |
440 | @@ -267,6 +267,17 @@ | |||
441 | 267 | return inode.id | 267 | return inode.id |
442 | 268 | 268 | ||
443 | 269 | 269 | ||
444 | 270 | def save_to_intrinsic(root, src, dst): | ||
445 | 271 | results = {} | ||
446 | 272 | iroot = intrinsic_graph(root, src.get, results) | ||
447 | 273 | for inode in results.values(): | ||
448 | 274 | doc = create_inode(inode) | ||
449 | 275 | try: | ||
450 | 276 | dst.save(doc) | ||
451 | 277 | except Conflict: | ||
452 | 278 | pass | ||
453 | 279 | return iroot | ||
454 | 280 | |||
455 | 270 | 281 | ||
456 | 271 | def check_novacut(doc): | 282 | def check_novacut(doc): |
457 | 272 | """ | 283 | """ |
458 | @@ -411,7 +422,46 @@ | |||
459 | 411 | } | 422 | } |
460 | 412 | }, | 423 | }, |
461 | 413 | 'ver': VER, | 424 | 'ver': VER, |
463 | 414 | 'type': 'novacut/node', | 425 | 'type': 'novacut/inode', |
464 | 426 | 'time': time.time(), | ||
465 | 427 | 'node': inode.node, | ||
466 | 428 | 'renders': {}, | ||
467 | 429 | } | ||
468 | 430 | |||
469 | 431 | |||
470 | 432 | def create_settings(node): | ||
471 | 433 | inode = intrinsic_node(node) | ||
472 | 434 | return { | ||
473 | 435 | '_id': inode.id, | ||
474 | 436 | '_attachments': { | ||
475 | 437 | 'node': { | ||
476 | 438 | 'data': b64encode(inode.data).decode('utf-8'), | ||
477 | 439 | 'content_type': 'application/json', | ||
478 | 440 | } | ||
479 | 441 | }, | ||
480 | 442 | 'ver': VER, | ||
481 | 443 | 'type': 'novacut/settings', | ||
482 | 444 | 'time': time.time(), | ||
483 | 445 | 'node': inode.node, | ||
484 | 446 | } | ||
485 | 447 | |||
486 | 448 | |||
487 | 449 | def create_job(root, settings): | ||
488 | 450 | node = { | ||
489 | 451 | 'root': root, | ||
490 | 452 | 'settings': settings, | ||
491 | 453 | } | ||
492 | 454 | inode = intrinsic_node(node) | ||
493 | 455 | return { | ||
494 | 456 | '_id': inode.id, | ||
495 | 457 | '_attachments': { | ||
496 | 458 | 'node': { | ||
497 | 459 | 'data': b64encode(inode.data).decode('utf-8'), | ||
498 | 460 | 'content_type': 'application/json', | ||
499 | 461 | } | ||
500 | 462 | }, | ||
501 | 463 | 'ver': VER, | ||
502 | 464 | 'type': 'novacut/job', | ||
503 | 415 | 'time': time.time(), | 465 | 'time': time.time(), |
504 | 416 | 'node': inode.node, | 466 | 'node': inode.node, |
505 | 417 | 'renders': {}, | 467 | 'renders': {}, |
506 | 418 | 468 | ||
507 | === modified file 'novacut2/builder.py' | |||
508 | --- novacut2/builder.py 2012-01-18 01:02:46 +0000 | |||
509 | +++ novacut2/builder.py 2012-01-20 15:32:24 +0000 | |||
510 | @@ -61,11 +61,11 @@ | |||
511 | 61 | 61 | ||
512 | 62 | 62 | ||
513 | 63 | class LiveBuilder(Builder): | 63 | class LiveBuilder(Builder): |
515 | 64 | def __init__(self, project_id): | 64 | def __init__(self): |
516 | 65 | self.Dmedia = session.get_object('org.freedesktop.Dmedia', '/') | 65 | self.Dmedia = session.get_object('org.freedesktop.Dmedia', '/') |
517 | 66 | env = json.loads(self.Dmedia.GetEnv()) | 66 | env = json.loads(self.Dmedia.GetEnv()) |
518 | 67 | env['url'] = env['url'].encode('utf-8') | 67 | env['url'] = env['url'].encode('utf-8') |
520 | 68 | self.db = Database(project_db_name(project_id), env) | 68 | self.db = Database('novacut-0', env) |
521 | 69 | self._cache = {} | 69 | self._cache = {} |
522 | 70 | 70 | ||
523 | 71 | def resolve_file(self, _id): | 71 | def resolve_file(self, _id): |
524 | 72 | 72 | ||
525 | === added file 'novacut2/extractor.py' | |||
526 | --- novacut2/extractor.py 1970-01-01 00:00:00 +0000 | |||
527 | +++ novacut2/extractor.py 2012-01-20 15:32:24 +0000 | |||
528 | @@ -0,0 +1,186 @@ | |||
529 | 1 | # novacut: the distributed video editor | ||
530 | 2 | # Copyright (C) 2011 Novacut Inc | ||
531 | 3 | # | ||
532 | 4 | # This file is part of `novacut`. | ||
533 | 5 | # | ||
534 | 6 | # `novacut` is free software: you can redistribute it and/or modify it under | ||
535 | 7 | # the terms of the GNU Affero General Public License as published by the Free | ||
536 | 8 | # Software Foundation, either version 3 of the License, or (at your option) | ||
537 | 9 | # any later version. | ||
538 | 10 | # | ||
539 | 11 | # `novacut` is distributed in the hope that it will be useful, but WITHOUT ANY | ||
540 | 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
541 | 13 | # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for | ||
542 | 14 | # more details. | ||
543 | 15 | # | ||
544 | 16 | # You should have received a copy of the GNU Affero General Public License | ||
545 | 17 | # along with `novacut`. If not, see <http://www.gnu.org/licenses/>. | ||
546 | 18 | # | ||
547 | 19 | # Authors: | ||
548 | 20 | # Jason Gerard DeRose <jderose@novacut.com> | ||
549 | 21 | |||
550 | 22 | import sys | ||
551 | 23 | import gst | ||
552 | 24 | import gobject | ||
553 | 25 | |||
554 | 26 | |||
555 | 27 | gobject.threads_init() | ||
556 | 28 | |||
557 | 29 | |||
558 | 30 | class FakeBin(gst.Bin): | ||
559 | 31 | def __init__(self, doc, rate): | ||
560 | 32 | super(FakeBin, self).__init__() | ||
561 | 33 | self._doc = doc | ||
562 | 34 | self._q = gst.element_factory_make('queue') | ||
563 | 35 | self._rate = gst.element_factory_make(rate) | ||
564 | 36 | self._sink = gst.element_factory_make('fakesink') | ||
565 | 37 | self.add(self._q, self._rate, self._sink) | ||
566 | 38 | self._q.link(self._rate) | ||
567 | 39 | self._rate.link(self._sink) | ||
568 | 40 | |||
569 | 41 | # Ghost Pads | ||
570 | 42 | pad = self._q.get_pad('sink') | ||
571 | 43 | self.add_pad( | ||
572 | 44 | gst.GhostPad('sink', pad) | ||
573 | 45 | ) | ||
574 | 46 | pad.connect('notify::caps', self._on_notify_caps) | ||
575 | 47 | |||
576 | 48 | def _get_doc(self): | ||
577 | 49 | self._finalize() | ||
578 | 50 | return self._doc | ||
579 | 51 | |||
580 | 52 | def _query_duration(self, pad): | ||
581 | 53 | q = gst.query_new_duration(gst.FORMAT_TIME) | ||
582 | 54 | if pad.get_peer().query(q): | ||
583 | 55 | (format, duration) = q.parse_duration() | ||
584 | 56 | if format == gst.FORMAT_TIME: | ||
585 | 57 | return duration | ||
586 | 58 | |||
587 | 59 | |||
588 | 60 | class VideoBin(FakeBin): | ||
589 | 61 | def __init__(self, doc): | ||
590 | 62 | super(VideoBin, self).__init__(doc, 'videorate') | ||
591 | 63 | |||
592 | 64 | def _on_notify_caps(self, pad, args): | ||
593 | 65 | caps = pad.get_negotiated_caps() | ||
594 | 66 | if not caps: | ||
595 | 67 | return | ||
596 | 68 | d = caps[0] | ||
597 | 69 | num = d['framerate'].num | ||
598 | 70 | denom = d['framerate'].denom | ||
599 | 71 | self._doc['framerate'] = { | ||
600 | 72 | 'num': num, | ||
601 | 73 | 'denom': denom, | ||
602 | 74 | } | ||
603 | 75 | self._doc['width'] = d['width'] | ||
604 | 76 | self._doc['height'] = d['height'] | ||
605 | 77 | ns = self._query_duration(pad) | ||
606 | 78 | if ns: | ||
607 | 79 | self._doc['video_ns'] = ns | ||
608 | 80 | self._doc['frames'] = ns * num / denom / gst.SECOND | ||
609 | 81 | |||
610 | 82 | def _finalize(self): | ||
611 | 83 | self._doc['frames2'] = self._rate.get_property('in') | ||
612 | 84 | |||
613 | 85 | |||
614 | 86 | class AudioBin(FakeBin): | ||
615 | 87 | def __init__(self, doc): | ||
616 | 88 | super(AudioBin, self).__init__(doc, 'audiorate') | ||
617 | 89 | |||
618 | 90 | def _on_notify_caps(self, pad, args): | ||
619 | 91 | caps = pad.get_negotiated_caps() | ||
620 | 92 | if not caps: | ||
621 | 93 | return | ||
622 | 94 | d = caps[0] | ||
623 | 95 | self._doc['samplerate'] = d['rate'] | ||
624 | 96 | self._doc['channels'] = d['channels'] | ||
625 | 97 | ns = self._query_duration(pad) | ||
626 | 98 | if ns: | ||
627 | 99 | self._doc['audio_ns'] = ns | ||
628 | 100 | self._doc['samples'] = d['rate'] * ns / gst.SECOND | ||
629 | 101 | |||
630 | 102 | def _finalize(self): | ||
631 | 103 | # FIXME: why is this so worthless? | ||
632 | 104 | if 'samples' not in self._doc: | ||
633 | 105 | self._doc['samples'] = self._rate.get_property('in') | ||
634 | 106 | |||
635 | 107 | |||
636 | 108 | class Extractor(object): | ||
637 | 109 | def __init__(self, filename): | ||
638 | 110 | self.doc = {'video_ns': 0, 'audio_ns': 0} | ||
639 | 111 | self.mainloop = gobject.MainLoop() | ||
640 | 112 | self.pipeline = gst.Pipeline() | ||
641 | 113 | |||
642 | 114 | # Create bus and connect several handlers | ||
643 | 115 | self.bus = self.pipeline.get_bus() | ||
644 | 116 | self.bus.add_signal_watch() | ||
645 | 117 | self.bus.connect('message::eos', self.on_eos) | ||
646 | 118 | self.bus.connect('message::error', self.on_error) | ||
647 | 119 | |||
648 | 120 | # Create elements | ||
649 | 121 | self.src = gst.element_factory_make('filesrc') | ||
650 | 122 | self.dec = gst.element_factory_make('decodebin2') | ||
651 | 123 | |||
652 | 124 | # Set properties | ||
653 | 125 | self.src.set_property('location', filename) | ||
654 | 126 | |||
655 | 127 | # Connect handler for 'new-decoded-pad' signal | ||
656 | 128 | self.dec.connect('pad-added', self.on_pad_added) | ||
657 | 129 | self.dec.connect('no-more-pads', self.on_no_more_pads) | ||
658 | 130 | self.typefind = self.dec.get_by_name('typefind') | ||
659 | 131 | self.typefind.connect('have-type', self.on_have_type) | ||
660 | 132 | |||
661 | 133 | # Add elements to pipeline | ||
662 | 134 | self.pipeline.add(self.src, self.dec) | ||
663 | 135 | |||
664 | 136 | # Link elements | ||
665 | 137 | self.src.link(self.dec) | ||
666 | 138 | |||
667 | 139 | self.audio = None | ||
668 | 140 | self.video = None | ||
669 | 141 | |||
670 | 142 | def run(self): | ||
671 | 143 | self.pipeline.set_state(gst.STATE_PLAYING) | ||
672 | 144 | self.mainloop.run() | ||
673 | 145 | |||
674 | 146 | def kill(self): | ||
675 | 147 | ns = max(self.doc['video_ns'], self.doc['audio_ns']) | ||
676 | 148 | self.doc['seconds'] = float(ns) / gst.SECOND | ||
677 | 149 | self.pipeline.set_state(gst.STATE_NULL) | ||
678 | 150 | self.pipeline.get_state() | ||
679 | 151 | self.mainloop.quit() | ||
680 | 152 | |||
681 | 153 | def link_pad(self, pad, name): | ||
682 | 154 | cls = {'audio': AudioBin, 'video': VideoBin}[name] | ||
683 | 155 | fakebin = cls(self.doc) | ||
684 | 156 | self.pipeline.add(fakebin) | ||
685 | 157 | pad.link(fakebin.get_pad('sink')) | ||
686 | 158 | fakebin.set_state(gst.STATE_PLAYING) | ||
687 | 159 | return fakebin | ||
688 | 160 | |||
689 | 161 | def on_pad_added(self, element, pad): | ||
690 | 162 | name = pad.get_caps()[0].get_name() | ||
691 | 163 | if name.startswith('audio/'): | ||
692 | 164 | assert self.audio is None | ||
693 | 165 | self.audio = self.link_pad(pad, 'audio') | ||
694 | 166 | elif name.startswith('video/'): | ||
695 | 167 | assert self.video is None | ||
696 | 168 | self.video = self.link_pad(pad, 'video') | ||
697 | 169 | |||
698 | 170 | def on_no_more_pads(self, element): | ||
699 | 171 | print('no more decoded pads') | ||
700 | 172 | |||
701 | 173 | def on_have_type(self, element, prop, caps): | ||
702 | 174 | self.doc['content_type'] = caps.to_string() | ||
703 | 175 | |||
704 | 176 | def on_eos(self, bus, msg): | ||
705 | 177 | if self.video: | ||
706 | 178 | self.video._finalize() | ||
707 | 179 | self.kill() | ||
708 | 180 | |||
709 | 181 | def on_error(self, bus, msg): | ||
710 | 182 | error = msg.parse_error()[1] | ||
711 | 183 | self.kill() | ||
712 | 184 | print(error) | ||
713 | 185 | sys.exit(2) | ||
714 | 186 | |||
715 | 0 | 187 | ||
716 | === modified file 'novacut2/renderer.py' | |||
717 | --- novacut2/renderer.py 2012-01-17 05:15:04 +0000 | |||
718 | +++ novacut2/renderer.py 2012-01-20 15:32:24 +0000 | |||
719 | @@ -251,14 +251,15 @@ | |||
720 | 251 | 251 | ||
721 | 252 | 252 | ||
722 | 253 | class Renderer(object): | 253 | class Renderer(object): |
724 | 254 | def __init__(self, job, builder, dst): | 254 | def __init__(self, root, settings, builder, dst): |
725 | 255 | """ | 255 | """ |
726 | 256 | Initialize. | 256 | Initialize. |
727 | 257 | 257 | ||
728 | 258 | :param job: a ``dict`` describing the transcode to perform. | 258 | :param job: a ``dict`` describing the transcode to perform. |
729 | 259 | :param fs: a `FileStore` instance in which to store transcoded file | 259 | :param fs: a `FileStore` instance in which to store transcoded file |
730 | 260 | """ | 260 | """ |
732 | 261 | self.job = job | 261 | self.root = root |
733 | 262 | self.settings = settings | ||
734 | 262 | self.builder = builder | 263 | self.builder = builder |
735 | 263 | self.mainloop = gobject.MainLoop() | 264 | self.mainloop = gobject.MainLoop() |
736 | 264 | self.pipeline = gst.Pipeline() | 265 | self.pipeline = gst.Pipeline() |
737 | @@ -270,8 +271,8 @@ | |||
738 | 270 | self.bus.connect('message::error', self.on_error) | 271 | self.bus.connect('message::error', self.on_error) |
739 | 271 | 272 | ||
740 | 272 | # Create elements | 273 | # Create elements |
743 | 273 | self.src = builder.build(job['src']) | 274 | self.src = builder.build(root) |
744 | 274 | self.mux = make_element(job['muxer']) | 275 | self.mux = make_element(settings['muxer']) |
745 | 275 | self.sink = gst.element_factory_make('filesink') | 276 | self.sink = gst.element_factory_make('filesink') |
746 | 276 | 277 | ||
747 | 277 | # Add elements to pipeline | 278 | # Add elements to pipeline |
748 | @@ -301,15 +302,15 @@ | |||
749 | 301 | 302 | ||
750 | 302 | def link_pad(self, pad, name, key): | 303 | def link_pad(self, pad, name, key): |
751 | 303 | log.info('link_pad: %r, %r, %r', pad, name, key) | 304 | log.info('link_pad: %r, %r, %r', pad, name, key) |
753 | 304 | if key in self.job: | 305 | if key in self.settings: |
754 | 305 | klass = {'audio': AudioEncoder, 'video': VideoEncoder}[key] | 306 | klass = {'audio': AudioEncoder, 'video': VideoEncoder}[key] |
756 | 306 | el = klass(self.job[key]) | 307 | el = klass(self.settings[key]) |
757 | 307 | else: | 308 | else: |
758 | 308 | el = gst.element_factory_make('fakesink') | 309 | el = gst.element_factory_make('fakesink') |
759 | 309 | self.pipeline.add(el) | 310 | self.pipeline.add(el) |
760 | 310 | log.info('Linking pad %r with %r', name, el) | 311 | log.info('Linking pad %r with %r', name, el) |
761 | 311 | pad.link(el.get_compatible_pad(pad, pad.get_caps())) | 312 | pad.link(el.get_compatible_pad(pad, pad.get_caps())) |
763 | 312 | if key in self.job: | 313 | if key in self.settings: |
764 | 313 | el.link(self.mux) | 314 | el.link(self.mux) |
765 | 314 | el.set_state(gst.STATE_PLAYING) | 315 | el.set_state(gst.STATE_PLAYING) |
766 | 315 | return el | 316 | return el |
767 | 316 | 317 | ||
768 | === modified file 'novacut2/tests/test_renderer.py' | |||
769 | --- novacut2/tests/test_renderer.py 2012-01-17 05:15:04 +0000 | |||
770 | +++ novacut2/tests/test_renderer.py 2012-01-20 15:32:24 +0000 | |||
771 | @@ -535,26 +535,27 @@ | |||
772 | 535 | tmp = TempDir() | 535 | tmp = TempDir() |
773 | 536 | builder = DummyBuilder(docs) | 536 | builder = DummyBuilder(docs) |
774 | 537 | 537 | ||
777 | 538 | job = { | 538 | root = sequence1 |
778 | 539 | 'src': sequence1, | 539 | settings = { |
779 | 540 | 'muxer': {'name': 'oggmux'}, | 540 | 'muxer': {'name': 'oggmux'}, |
780 | 541 | } | 541 | } |
781 | 542 | dst = tmp.join('out1.ogv') | 542 | dst = tmp.join('out1.ogv') |
783 | 543 | inst = renderer.Renderer(job, builder, dst) | 543 | inst = renderer.Renderer(root, settings, builder, dst) |
784 | 544 | 544 | ||
787 | 545 | self.assertTrue(inst.job is job) | 545 | self.assertIs(inst.root, root) |
788 | 546 | self.assertTrue(inst.builder is builder) | 546 | self.assertIs(inst.settings, settings) |
789 | 547 | self.assertIs(inst.builder, builder) | ||
790 | 547 | 548 | ||
791 | 548 | self.assertIsInstance(inst.src, gst.Element) | 549 | self.assertIsInstance(inst.src, gst.Element) |
793 | 549 | self.assertTrue(inst.src.get_parent() is inst.pipeline) | 550 | self.assertIs(inst.src.get_parent(), inst.pipeline) |
794 | 550 | self.assertEqual(inst.src.get_factory().get_name(), 'gnlcomposition') | 551 | self.assertEqual(inst.src.get_factory().get_name(), 'gnlcomposition') |
795 | 551 | 552 | ||
796 | 552 | self.assertIsInstance(inst.mux, gst.Element) | 553 | self.assertIsInstance(inst.mux, gst.Element) |
798 | 553 | self.assertTrue(inst.mux.get_parent() is inst.pipeline) | 554 | self.assertIs(inst.mux.get_parent(), inst.pipeline) |
799 | 554 | self.assertEqual(inst.mux.get_factory().get_name(), 'oggmux') | 555 | self.assertEqual(inst.mux.get_factory().get_name(), 'oggmux') |
800 | 555 | 556 | ||
801 | 556 | self.assertIsInstance(inst.sink, gst.Element) | 557 | self.assertIsInstance(inst.sink, gst.Element) |
803 | 557 | self.assertTrue(inst.sink.get_parent() is inst.pipeline) | 558 | self.assertIs(inst.sink.get_parent(), inst.pipeline) |
804 | 558 | self.assertEqual(inst.sink.get_factory().get_name(), 'filesink') | 559 | self.assertEqual(inst.sink.get_factory().get_name(), 'filesink') |
805 | 559 | self.assertEqual(inst.sink.get_property('location'), dst) | 560 | self.assertEqual(inst.sink.get_property('location'), dst) |
806 | 560 | 561 | ||
807 | 561 | 562 | ||
808 | === added file 'novacut2/worker.py' | |||
809 | --- novacut2/worker.py 1970-01-01 00:00:00 +0000 | |||
810 | +++ novacut2/worker.py 2012-01-20 15:32:24 +0000 | |||
811 | @@ -0,0 +1,82 @@ | |||
812 | 1 | # novacut: the distributed video editor | ||
813 | 2 | # Copyright (C) 2011 Novacut Inc | ||
814 | 3 | # | ||
815 | 4 | # This file is part of `novacut`. | ||
816 | 5 | # | ||
817 | 6 | # `novacut` is free software: you can redistribute it and/or modify it under | ||
818 | 7 | # the terms of the GNU Affero General Public License as published by the Free | ||
819 | 8 | # Software Foundation, either version 3 of the License, or (at your option) | ||
820 | 9 | # any later version. | ||
821 | 10 | # | ||
822 | 11 | # `novacut` is distributed in the hope that it will be useful, but WITHOUT ANY | ||
823 | 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
824 | 13 | # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for | ||
825 | 14 | # more details. | ||
826 | 15 | # | ||
827 | 16 | # You should have received a copy of the GNU Affero General Public License | ||
828 | 17 | # along with `novacut`. If not, see <http://www.gnu.org/licenses/>. | ||
829 | 18 | # | ||
830 | 19 | # Authors: | ||
831 | 20 | # Jason Gerard DeRose <jderose@novacut.com> | ||
832 | 21 | |||
833 | 22 | import json | ||
834 | 23 | |||
835 | 24 | import dbus | ||
836 | 25 | from dbus.mainloop.glib import DBusGMainLoop | ||
837 | 26 | import gobject | ||
838 | 27 | from dc3lib.microfiber import Database | ||
839 | 28 | |||
840 | 29 | from renderer import Builder, Renderer | ||
841 | 30 | |||
842 | 31 | |||
843 | 32 | gobject.threads_init() | ||
844 | 33 | DBusGMainLoop(set_as_default=True) | ||
845 | 34 | session = dbus.SessionBus() | ||
846 | 35 | |||
847 | 36 | |||
848 | 37 | class LiveBuilder(Builder): | ||
849 | 38 | def __init__(self, Dmedia, db): | ||
850 | 39 | self.Dmedia = Dmedia | ||
851 | 40 | self.db = db | ||
852 | 41 | self._cache = {} | ||
853 | 42 | |||
854 | 43 | def resolve_file(self, _id): | ||
855 | 44 | return self.Dmedia.Resolve(_id) | ||
856 | 45 | |||
857 | 46 | def get_doc(self, _id): | ||
858 | 47 | try: | ||
859 | 48 | return self._cache[_id] | ||
860 | 49 | except KeyError: | ||
861 | 50 | doc = self.db.get(_id) | ||
862 | 51 | self._cache[_id] = doc | ||
863 | 52 | return doc | ||
864 | 53 | |||
865 | 54 | |||
866 | 55 | class Worker(object): | ||
867 | 56 | def __init__(self): | ||
868 | 57 | self.Dmedia = session.get_object('org.freedesktop.Dmedia', '/') | ||
869 | 58 | env = json.loads(self.Dmedia.GetEnv()) | ||
870 | 59 | env['url'] = env['url'].encode('utf-8') | ||
871 | 60 | self.novacut = Database('novacut-0', env) | ||
872 | 61 | self.dmedia = Database('dmedia-0', env) | ||
873 | 62 | |||
874 | 63 | def run(self, job_id): | ||
875 | 64 | job = self.novacut.get(job_id) | ||
876 | 65 | root = job['node']['root'] | ||
877 | 66 | settings = self.novacut.get(job['node']['settings']) | ||
878 | 67 | builder = LiveBuilder(self.Dmedia, self.novacut) | ||
879 | 68 | dst = self.Dmedia.AllocateTmp() | ||
880 | 69 | renderer = Renderer(root, settings['node'], builder, dst) | ||
881 | 70 | renderer.run() | ||
882 | 71 | _id = self.Dmedia.HashAndMove(dst, 'render') | ||
883 | 72 | doc = self.dmedia.get(_id) | ||
884 | 73 | doc['render_of'] = job_id | ||
885 | 74 | self.dmedia.save(doc) | ||
886 | 75 | job['renders'][_id] = { | ||
887 | 76 | 'bytes': doc['bytes'], | ||
888 | 77 | 'time': doc['time'], | ||
889 | 78 | } | ||
890 | 79 | self.novacut.save(job) | ||
891 | 80 | return _id | ||
892 | 81 | |||
893 | 82 | |||
894 | 0 | 83 | ||
895 | === modified file 'setup.py' | |||
896 | --- setup.py 2012-01-17 08:37:54 +0000 | |||
897 | +++ setup.py 2012-01-20 15:32:24 +0000 | |||
898 | @@ -147,6 +147,12 @@ | |||
899 | 147 | ('share/icons/hicolor/48x48/apps', | 147 | ('share/icons/hicolor/48x48/apps', |
900 | 148 | ['data/novacut.svg'] | 148 | ['data/novacut.svg'] |
901 | 149 | ), | 149 | ), |
902 | 150 | ('lib/novacut', | ||
903 | 151 | ['novacut-service'], | ||
904 | 152 | ), | ||
905 | 153 | ('share/dbus-1/services/', | ||
906 | 154 | ['data/com.novacut.Renderer.service'] | ||
907 | 155 | ), | ||
908 | 150 | ], | 156 | ], |
909 | 151 | cmdclass={'test': Test}, | 157 | cmdclass={'test': Test}, |
910 | 152 | ) | 158 | ) |
911 | 153 | 159 | ||
912 | === modified file 'setup2.py' | |||
913 | --- setup2.py 2012-01-17 08:26:59 +0000 | |||
914 | +++ setup2.py 2012-01-20 15:32:24 +0000 | |||
915 | @@ -134,10 +134,7 @@ | |||
916 | 134 | packages=['novacut2'], | 134 | packages=['novacut2'], |
917 | 135 | data_files=[ | 135 | data_files=[ |
918 | 136 | ('lib/novacut', | 136 | ('lib/novacut', |
923 | 137 | ['novacut-service'], | 137 | ['novacut-renderer'], |
920 | 138 | ), | ||
921 | 139 | ('share/dbus-1/services/', | ||
922 | 140 | ['data/com.novacut.Renderer.service'] | ||
924 | 141 | ), | 138 | ), |
925 | 142 | ], | 139 | ], |
926 | 143 | ) | 140 | ) |