collect scripts in oxtools
This commit is contained in:
commit
4f9c3da160
22 changed files with 1297 additions and 0 deletions
216
oxgst/timeline.py
Normal file
216
oxgst/timeline.py
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
# GPL 2008
|
||||
import gobject
|
||||
gobject.threads_init()
|
||||
|
||||
from glob import glob
|
||||
import math
|
||||
import os
|
||||
import time
|
||||
|
||||
import pygst
|
||||
pygst.require("0.10")
|
||||
import gst
|
||||
import Image
|
||||
|
||||
from singledecodebin import SingleDecodeBin
|
||||
from imagesink import ImageSink
|
||||
from video import Video
|
||||
|
||||
|
||||
class Timeline(Video):
|
||||
def __init__(self, uri):
|
||||
Video.__init__(self, uri)
|
||||
|
||||
bus = self.get_bus()
|
||||
bus.add_signal_watch()
|
||||
self.watch_id = bus.connect("message", self.onBusMessage)
|
||||
|
||||
self.mainloop = gobject.MainLoop()
|
||||
|
||||
def extract(self, prefix, width, height):
|
||||
self.tile_width = width
|
||||
self.tile_height = height
|
||||
self.prefix = prefix
|
||||
self.timeline_fps = 25
|
||||
self.input_tile_width = int(math.ceil((float(self.framerate)/self.timeline_fps) * width))
|
||||
ntiles = int(math.ceil(float(self.frames)/self.input_tile_width))
|
||||
self.tiles = []
|
||||
for i in range(ntiles):
|
||||
tile = Image.new("RGB", (self.input_tile_width, height))
|
||||
self.tiles.append(tile)
|
||||
|
||||
self.set_state(gst.STATE_PLAYING)
|
||||
self.mainloop.run()
|
||||
|
||||
for i in range(ntiles):
|
||||
tile = self.tiles[i]
|
||||
if tile.size[0] != self.tile_width:
|
||||
tile = tile.resize((self.tile_width, self.tile_height), Image.ANTIALIAS)
|
||||
if i < (ntiles-1):
|
||||
frames = self.input_tile_width
|
||||
else:
|
||||
frames = self.frames-((ntiles-1)*self.input_tile_width)
|
||||
tile_width = int(math.ceil(self.timeline_fps*frames)/float(self.framerate))
|
||||
if -2 < self.tile_width - tile_width < 2:
|
||||
tile_width = self.tile_width
|
||||
tile = tile.crop((0, 0, tile_width, self.tile_height))
|
||||
filename = "%s.%s.%04d.png" % (self.prefix, self.tile_height, i)
|
||||
tile.save(filename)
|
||||
|
||||
def done(self):
|
||||
self.mainloop.quit()
|
||||
|
||||
def _sbinPadAddedCb(self, unused_sbin, pad):
|
||||
self.log("pad : %s" % pad)
|
||||
pad.link(self.csp.get_pad("sink"))
|
||||
|
||||
def _frameCb(self, unused_thsink, frame, timestamp):
|
||||
self.log("image:%s, timestamp:%s" % (frame, gst.TIME_ARGS(timestamp)))
|
||||
|
||||
if not self._ready:
|
||||
# we know we're prerolled when we get the initial thumbnail
|
||||
self._ready = True
|
||||
else:
|
||||
framePos = int(math.ceil((float(timestamp) / (gst.SECOND) * float(self.framerate))))
|
||||
tile = int(math.floor(float(framePos) / self.input_tile_width))
|
||||
tilePos = framePos - (tile * self.input_tile_width)
|
||||
frame = frame.resize((1, self.tile_height), Image.ANTIALIAS)
|
||||
for i in range(self.tile_height):
|
||||
self.tiles[tile].putpixel((tilePos, i), frame.getpixel((0, i)))
|
||||
|
||||
if self.mainloop and timestamp >= self.duration:
|
||||
self.done()
|
||||
|
||||
def onBusMessage(self, bus, message):
|
||||
if message.src == self and message.type == gst.MESSAGE_EOS:
|
||||
self.done()
|
||||
|
||||
def loadTimeline(timeline_prefix, height=64):
|
||||
files = sorted(glob('%s.%s.*.png' % (timeline_prefix, height)))
|
||||
f = Image.open(files[0])
|
||||
width = f.size[0]
|
||||
f = Image.open(files[-1])
|
||||
duration = f.size[0] + (len(files)-1)*width
|
||||
timeline = Image.new("RGB", (duration, height))
|
||||
pos = 0
|
||||
for f in files:
|
||||
part = Image.open(f)
|
||||
timeline.paste(part, (pos, 0, pos + part.size[0], height))
|
||||
pos += part.size[0]
|
||||
return timeline
|
||||
|
||||
def createTimelineMultiline(timeline_prefix, width=600, height=16):
|
||||
lineWidth = width
|
||||
timlelineHeight = height
|
||||
|
||||
timeline = loadTimeline(timeline_prefix)
|
||||
duration = timeline.size[0]
|
||||
|
||||
width = duration/25 #one pixel per second
|
||||
timeline = timeline.resize((width, timlelineHeight), Image.ANTIALIAS).convert('RGBA')
|
||||
|
||||
lineHeight = timlelineHeight + 2 * 4
|
||||
|
||||
lines = int(math.ceil(width / lineWidth) + 1)
|
||||
size = (lineWidth, lineHeight * lines)
|
||||
|
||||
timelineColor = (64, 64, 64)
|
||||
i = Image.new("RGBA", size)
|
||||
|
||||
#padd end with nothing to fit to grid
|
||||
t = Image.new("RGBA", (lineWidth * lines, timlelineHeight))
|
||||
t.paste(timeline, (0, 0))
|
||||
|
||||
for currentLine in range(0, lines):
|
||||
offset = currentLine * lineHeight + 4
|
||||
toffset = currentLine * lineWidth
|
||||
try:
|
||||
tbox = t.crop((toffset, 0, toffset + lineWidth, timlelineHeight))
|
||||
box = ((0, offset , tbox.size[0], offset + tbox.size[1]))
|
||||
i.paste(tbox, box)
|
||||
except:
|
||||
broken = True
|
||||
width = lineWidth
|
||||
if currentLine == lines -1:
|
||||
width = duration - (lines - 1) * lineWidth
|
||||
box = ((0, offset , width, offset + timlelineHeight))
|
||||
i.paste(timelineColor, box)
|
||||
timeline_file = '%s.timeline.overview.png' % (timeline_prefix)
|
||||
i.save(timeline_file, 'PNG')
|
||||
|
||||
def makeTimelineByFramesPerPixel(timeline_prefix, frames_per_pixel, inpoint=0, outpoint=0, height=16):
|
||||
pos = 0
|
||||
input_scale = 25
|
||||
|
||||
timeline_file = '%s.timeline.%s.png' % (timeline_prefix, width)
|
||||
if outpoint > 0:
|
||||
timeline_file = '%s.timeline.%s.%d-%d.png' % (timeline_prefix, width, inpoint, outpoint)
|
||||
|
||||
timeline = loadTimeline(timeline_prefix)
|
||||
duration = timeline.size[0]
|
||||
|
||||
|
||||
width = duration / frames_per_pixel
|
||||
|
||||
if inpoint<=0:
|
||||
inpoint = 0
|
||||
else:
|
||||
inpoint = inpoint * input_scale
|
||||
if outpoint<=0:
|
||||
outpoint = pos
|
||||
else:
|
||||
outpoint = outpoint * input_scale
|
||||
|
||||
timeline = timeline.crop((inpoint, 0, outpoint, timeline.size[1])).resize((width, height), Image.ANTIALIAS)
|
||||
timeline.save(timeline_file)
|
||||
|
||||
def makeTimelineOverview(timeline_prefix, width, inpoint=0, outpoint=0, duration=-1, height=16):
|
||||
input_scale = 25
|
||||
|
||||
timeline_file = '%s.timeline.%s.png' % (timeline_prefix, width)
|
||||
if outpoint > 0:
|
||||
timeline_file = '%s.timeline.%s.%d-%d.png' % (timeline_prefix, width, inpoint, outpoint)
|
||||
|
||||
timeline = loadTimeline(timeline_prefix)
|
||||
duration = timeline.size[0]
|
||||
|
||||
if inpoint<=0:
|
||||
inpoint = 0
|
||||
else:
|
||||
inpoint = inpoint * input_scale
|
||||
if outpoint<=0:
|
||||
outpoint = duration
|
||||
else:
|
||||
outpoint = outpoint * input_scale
|
||||
|
||||
timeline = timeline.crop((inpoint, 0, outpoint, timeline.size[1])).resize((width, height), Image.ANTIALIAS)
|
||||
timeline.save(timeline_file)
|
||||
|
||||
def makeTiles(timeline_prefix, height=16):
|
||||
files = glob('%s.64.*.png' % timeline_prefix)
|
||||
part_step = 60
|
||||
output_width = 300
|
||||
width = len(files) * part_step
|
||||
timeline = Image.new("RGB", (width, height))
|
||||
|
||||
pos = 0
|
||||
for f in sorted(files):
|
||||
part = Image.open(f)
|
||||
part_width = int(part.size[0] / 25)
|
||||
part = part.resize((part_width, height), Image.ANTIALIAS)
|
||||
timeline.paste(part, (pos, 0, pos+part_width, height))
|
||||
pos += part_width
|
||||
|
||||
timeline = timeline.crop((0, 0, pos, height))
|
||||
|
||||
pos = 0
|
||||
i = 0
|
||||
while pos < timeline.size[0]:
|
||||
end = min(pos+output_width, timeline.size[0])
|
||||
timeline.crop((pos, 0, end, timeline.size[1])).save('%s.%s.%04d.png' % (timeline_prefix, timeline.size[1], i))
|
||||
pos += output_width
|
||||
i += 5
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue