commit 4f9105eea4c731c150e11c6f870848f672b31e9e
parent abbd596011e09f661eab0033999f5fb43ae3e56f
Author: rbckman <rob@tarina.org>
Date: Thu, 14 Apr 2022 11:52:28 +0100
binned 2028x1080 as standard mode for video, hide/show menu, shut screen power on off
Diffstat:
4 files changed, 164 insertions(+), 36 deletions(-)
diff --git a/extras/h264streamer.py b/extras/h264streamer.py
@@ -0,0 +1,64 @@
+import io
+import picamerax as picamera
+import time
+from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
+from wsgiref.simple_server import make_server
+from ws4py.websocket import WebSocket
+from ws4py.server.wsgirefserver import WSGIServer, WebSocketWSGIHandler, WebSocketWSGIRequestHandler
+from ws4py.server.wsgiutils import WebSocketWSGIApplication
+from threading import Thread, Condition
+
+
+class FrameBuffer(object):
+ def __init__(self):
+ self.frame = None
+ self.buffer = io.BytesIO()
+ self.condition = Condition()
+
+ def write(self, buf):
+ if buf.startswith(b'\x00\x00\x00\x01'):
+ with self.condition:
+ self.buffer.seek(0)
+ self.buffer.write(buf)
+ self.buffer.truncate()
+ self.frame = self.buffer.getvalue()
+ self.condition.notify_all()
+
+
+def stream():
+ with picamera.PiCamera(resolution='1920x816', framerate=25) as camera:
+ broadcasting = True
+ frame_buffer = FrameBuffer()
+ camera.start_recording(frame_buffer, format='h264', profile="baseline")
+ try:
+ WebSocketWSGIHandler.http_version = '1.1'
+ websocketd = make_server('', 9000, server_class=WSGIServer,
+ handler_class=WebSocketWSGIRequestHandler,
+ app=WebSocketWSGIApplication(handler_cls=WebSocket))
+ websocketd.initialize_websockets_manager()
+ websocketd_thread = Thread(target=websocketd.serve_forever)
+
+ httpd = ThreadingHTTPServer(('', 8000), SimpleHTTPRequestHandler)
+ httpd_thread = Thread(target=httpd.serve_forever)
+
+ try:
+ websocketd_thread.start()
+ httpd_thread.start()
+ while broadcasting:
+ with frame_buffer.condition:
+ frame_buffer.condition.wait()
+ websocketd.manager.broadcast(frame_buffer.frame, binary=True)
+ except KeyboardInterrupt:
+ pass
+ finally:
+ websocketd.shutdown()
+ httpd.shutdown()
+ broadcasting = False
+ raise KeyboardInterrupt
+ except KeyboardInterrupt:
+ pass
+ finally:
+ camera.stop_recording()
+
+if __name__ == "__main__":
+ stream()
diff --git a/gui/src/main.c b/gui/src/main.c
@@ -44,12 +44,20 @@ int32_t render_subtitle(GRAPHICS_RESOURCE_HANDLE img, const char *text, const ui
graphics_get_resource_size(img, &img_w, &img_h);
// split now points to last line of text. split-text = length of initial text. text_length-(split-text) is length of last line
+ if (fontcolor == 6) {
+ graphics_resource_render_text_ext(img, x_offset, y_offset-height,
+ GRAPHICS_RESOURCE_WIDTH,
+ GRAPHICS_RESOURCE_HEIGHT,
+ GRAPHICS_RGBA32(225,255,255,0), /* fg */
+ GRAPHICS_RGBA32(0,0,0,0), /* bg */
+ text, 80, text_size);
+ }
if (fontcolor == 5) {
graphics_resource_render_text_ext(img, x_offset, y_offset-height,
GRAPHICS_RESOURCE_WIDTH,
GRAPHICS_RESOURCE_HEIGHT,
GRAPHICS_RGBA32(225,255,255,0xff), /* fg */
- GRAPHICS_RGBA32(0,0,0,0xff), /* bg */
+ GRAPHICS_RGBA32(0,0,0,150), /* bg */
text, 80, text_size);
}
if (fontcolor == 4) {
@@ -57,7 +65,7 @@ int32_t render_subtitle(GRAPHICS_RESOURCE_HANDLE img, const char *text, const ui
GRAPHICS_RESOURCE_WIDTH,
GRAPHICS_RESOURCE_HEIGHT,
GRAPHICS_RGBA32(30,255,255,0xff), /* fg */
- GRAPHICS_RGBA32(0,0,0,0xff), /* bg */
+ GRAPHICS_RGBA32(0,0,0,150), /* bg */
text, 80, text_size);
}
if (fontcolor == 3) {
@@ -65,7 +73,7 @@ int32_t render_subtitle(GRAPHICS_RESOURCE_HANDLE img, const char *text, const ui
GRAPHICS_RESOURCE_WIDTH,
GRAPHICS_RESOURCE_HEIGHT,
GRAPHICS_RGBA32(30,30,255,0xff), /* fg */
- GRAPHICS_RGBA32(0,0,0,0xff), /* bg */
+ GRAPHICS_RGBA32(0,0,0,150), /* bg */
text, 80, text_size);
}
if (fontcolor == 2) {
@@ -73,7 +81,7 @@ int32_t render_subtitle(GRAPHICS_RESOURCE_HANDLE img, const char *text, const ui
GRAPHICS_RESOURCE_WIDTH,
GRAPHICS_RESOURCE_HEIGHT,
GRAPHICS_RGBA32(30,255,30,0xff), /* fg */
- GRAPHICS_RGBA32(0,0,0,0xff), /* bg */
+ GRAPHICS_RGBA32(0,0,0,150), /* bg */
text, 80, text_size);
}
if (fontcolor == 1) {
@@ -119,6 +127,8 @@ int main(void)
ssize_t read = 0;
int linenr = 0;
int selected;
+ int showmenu;
+ int menuadd = 1;
char newread[500];
char oldread[500];
char vumeter[130];
@@ -147,7 +157,7 @@ int main(void)
// selected 0 1 2 3 4 5 6 7 8
int space = 10;
int morespace = 12;
- int color = 5;
+ int color = 3;
int row1 = 0;
int row2 = 0;
int row3 = 0;
@@ -164,42 +174,50 @@ int main(void)
//printf("%s",line);
if (linenr == 0)
selected = atoi(line);
- if (linenr == selected + 2)
+ if (linenr == 1)
+ showmenu = atoi(line);
+ if (linenr == selected + 2 + menuadd)
color = 1; //selected color
else
- color = 5; //unselected
- if ((linenr == 1) && (read > 0))
+ if (showmenu == 1)
+ color = 5; //unselected;
+ else
+ color = 6;
+ if ((linenr == 1 + menuadd) && (read > 0))
header = 1; //write header menu
- if ((linenr == 1) && (read == 0))
+ if ((linenr == 1 + menuadd) && (read == 0))
header = 0; //write normal menu
if (header == 0) {
- if ((linenr == 6) && (read > 0)) //show recording time if there is any
- render_subtitle(img, line, text_size, 700, y_offset3, 3);
- if (linenr >= 2 && linenr <= 5){
+ if ((linenr == 6 + menuadd) && (read > 0)){ //show recording time if there is any
+ render_subtitle(img, line, text_size, 700, y_offset2, 3);
+ }
+ if (linenr >= 2 + menuadd && linenr <= 5 + menuadd){
+ if (color == 6)
+ color = 2;
render_subtitle(img, line, text_size, row1, y_offset2, color);
row1 += read * space + morespace;
}
- if (linenr >= 7 && linenr <= 12){
+ if (linenr >= 7+menuadd && linenr <= 12+menuadd){
render_subtitle(img, line, text_size, row2, y_offset3, color);
row2 += read * space + morespace;
}
- if (linenr >= 13 && linenr <= 20){
+ if (linenr >= 13+menuadd && linenr <= 20+menuadd){
render_subtitle(img, line, text_size, row3, y_offset4, color);
row3 += read * space + morespace;
}
- if (linenr >= 21 && linenr <= 27){
+ if (linenr >= 21+menuadd && linenr <= 27+menuadd){
render_subtitle(img, line, text_size, row4, y_offset5, color);
row4 += read * space + morespace;
}
- if (linenr >= 28 && linenr <= 40){
+ if (linenr >= 28+menuadd && linenr <= 40+menuadd){
render_subtitle(img, line, text_size, row5, y_offset6, color);
row5 += read * space + morespace;
}
}
if (header == 1) {
- if (linenr == 1)
+ if (linenr == 1+menuadd)
render_subtitle(img, line, text_size, 0, y_offset2, 5);
- if (linenr > 1) {
+ if (linenr > 1+menuadd) {
render_subtitle(img, line, text_size, row1, y_offset3, color);
row1 += read * space + morespace;
}
diff --git a/gui/tarinagui.bin b/gui/tarinagui.bin
Binary files differ.
diff --git a/tarina.py b/tarina.py
@@ -74,7 +74,7 @@ while probei2c < 10:
#MAIN
def main():
- global headphoneslevel, miclevel, tarinafolder, screen, loadfilmsettings, plughw, channels, filmfolder, filmname, scene
+ global headphoneslevel, miclevel, tarinafolder, screen, loadfilmsettings, plughw, channels, filmfolder, filmname, scene, showmenu
# Get path of the current dir, then use it as working directory:
rundir = os.path.dirname(__file__)
if rundir != '':
@@ -84,6 +84,7 @@ def main():
if os.path.isdir(filmfolder) == False:
os.makedirs(filmfolder)
tarinafolder = os.getcwd()
+
#MENUS
menu = 'FILM:', 'SCENE:', 'SHOT:', 'TAKE:', '', 'SHUTTER:', 'ISO:', 'RED:', 'BLUE:', 'FPS:', 'Q:', 'BRIGHT:', 'CONT:', 'SAT:', 'FLIP:', 'BEEP:', 'LENGTH:', 'HW:', 'CH:', 'MIC:', 'PHONES:', 'COMP:', 'TIMELAPSE', 'LENS:', 'DSK:', 'SHUTDOWN', 'SRV:', 'WIFI:', 'UPDATE', 'UPLOAD', 'BACKUP', 'LOAD', 'NEW', 'TITLE', 'LIVE:'
#STANDARD VALUES (some of these may not be needed, should do some clean up)
@@ -102,7 +103,9 @@ def main():
retake = False
lastmenu = ''
rendermenu = True
+ showmenu = 1
overlay = None
+ underlay = None
reclenght = 0
t = 0
rectime = ''
@@ -150,12 +153,16 @@ def main():
run_command('tvservice -o')
#Kernel page cache optimization for sd card
run_command('sudo ' + tarinafolder + '/extras/sdcardhack.sh')
+ #Make screen shut off work and run full brightness
+ run_command('gpio -g mode 19 pwm ')
+ run_command('gpio -g pwm 19 1023')
#COUNT DISKSPACE
disk = os.statvfs(filmfolder)
diskleft = str(int(disk.f_bavail * disk.f_frsize / 1024 / 1024 / 1024)) + 'Gb'
#START INTERFACE
startinterface()
camera = startcamera(lens,fps)
+
#LOAD FILM AND SCENE SETTINGS
try:
filmname = getfilms(filmfolder)[0][0]
@@ -198,7 +205,7 @@ def main():
peakshot = shot - 1
peaktake = counttakes(filmname, filmfolder, scene, peakshot)
p_imagename = filmfolder + filmname + '/scene' + str(scene).zfill(3) + '/shot' + str(peakshot).zfill(3) + '/take' + str(peaktake).zfill(3) + '.jpeg'
- overlay = displayimage(camera, p_imagename, overlay)
+ overlay = displayimage(camera, p_imagename, overlay, 3)
while holdbutton == 'peak':
pressed, buttonpressed, buttontime, holdbutton, event, keydelay = getbutton(pressed, buttonpressed, buttontime, holdbutton)
writemessage('peaking ' + str(peakshot))
@@ -264,7 +271,7 @@ def main():
trim_filename = foldername + 'take' + str(take).zfill(3)
videotrim(foldername + filename, trim_filename, trim[0], trim[1])
imagename = foldername + filename + '.jpeg'
- overlay = displayimage(camera, imagename, overlay)
+ overlay = displayimage(camera, imagename, overlay, 3)
camera.start_preview()
#DUB SHOT
elif pressed == 'middle' and menu[selected] == 'SHOT:':
@@ -522,6 +529,12 @@ def main():
elif backlight == True:
run_command('gpio -g pwm 19 0')
backlight = False
+ elif pressed == 'showmenu':
+ if showmenu == 1:
+ # requires wiringpi installed
+ showmenu = 0
+ elif showmenu == 0:
+ showmenu = 1
#REMOVE
#take
elif pressed == 'remove' and menu[selected] == 'TAKE:':
@@ -585,9 +598,10 @@ def main():
if os.path.isdir(foldername) == False:
os.makedirs(foldername)
os.system(tarinafolder + '/alsa-utils-1.1.3/aplay/arecord -D plughw:' + str(plughw) + ' -f S16_LE -c ' + str(channels) + ' -r44100 -vv /dev/shm/' + filename + '.wav &')
- camera.start_recording(foldername + filename + '.h264', format='h264', quality=quality)
+ camera.start_recording(foldername + filename + '.h264', format='h264', quality=quality, level='4.2')
starttime = time.time()
recording = True
+ showmenu = 0
elif beepcountdown > 0 and beeping == True:
beeping = False
beepcountdown = 0
@@ -596,6 +610,7 @@ def main():
disk = os.statvfs(tarinafolder + '/')
diskleft = str(int(disk.f_bavail * disk.f_frsize / 1024 / 1024 / 1024)) + 'Gb'
recording = False
+ showmenu = 1
camera.stop_recording()
#time.sleep(0.005) #get audio at least 0.1 longer
os.system('pkill arecord')
@@ -990,7 +1005,7 @@ def main():
p = counttakes(filmname, filmfolder, 1, 1)
imagename = filmfolder + filmname + '/scene' + str(1).zfill(3) + '/shot' + str(1).zfill(3) + '/take' + str(p).zfill(3) + '.jpeg'
imagename = filmfolder + filmname + '/scene' + str(scene).zfill(3) + '/shot' + str(shot).zfill(3) + '/take' + str(take).zfill(3) + '.jpeg'
- overlay = displayimage(camera, imagename, overlay)
+ overlay = displayimage(camera, imagename, overlay, 3)
oldscene = scene
oldshot = shot
oldtake = take
@@ -1018,7 +1033,7 @@ def main():
if buttonpressed == True or recording == True or rendermenu == True:
lastmenu = menu[selected]
settings = filmname, str(scene) + '/' + str(scenes), str(shot) + '/' + str(shots), str(take) + '/' + str(takes), rectime, camerashutter, cameraiso, camerared, camerablue, str(camera.framerate), str(quality), str(camera.brightness), str(camera.contrast), str(camera.saturation), str(flip), str(beeps), str(reclenght), str(plughw), str(channels), str(miclevel), str(headphoneslevel), str(comp), '', lens, diskleft, '', serverstate, wifistate, '', '', '', '', '', '', live
- writemenu(menu,settings,selected,'')
+ writemenu(menu,settings,selected,'',showmenu)
#Rerender menu if picamera settings change
if settings != oldsettings:
rendermenu = True
@@ -1069,9 +1084,10 @@ def loadsettings(filmfolder, filmname):
#--------------Write the menu layer to dispmanx--------------
-def writemenu(menu,settings,selected,header):
+def writemenu(menu,settings,selected,header,showmenu):
menudone = ''
menudone += str(selected) + '\n'
+ menudone += str(showmenu) + '\n'
menudone += header + '\n'
for i, s in zip(menu, settings):
menudone += i + s + '\n'
@@ -1214,9 +1230,33 @@ def run_command(command_line):
logger.info('Process finished')
return True
+#-------------Display bakg-------------------
+
+def displaybakg(camera, filename, underlay, layer):
+ # Load the arbitrarily sized image
+ img = Image.open(filename)
+ # Create an image padded to the required size with
+ # mode 'RGB'
+ pad = Image.new('RGB', (
+ ((img.size[0] + 31) // 32) * 32,
+ ((img.size[1] + 15) // 16) * 16,
+ ))
+ # Paste the original image into the padded one
+ pad.paste(img, (0, 0))
+
+ # Add the overlay with the padded image as the source,
+ # but the original image's dimensions
+ underlay = camera.add_overlay(pad.tobytes(), size=img.size)
+ # By default, the overlay is in layer 0, beneath the
+ # preview (which defaults to layer 2). Here we make
+ # the new overlay semi-transparent, then move it above
+ # the preview
+ underlay.alpha = 255
+ underlay.layer = layer
+
#-------------Display jpeg-------------------
-def displayimage(camera, filename, overlay):
+def displayimage(camera, filename, overlay, layer):
# Load the arbitrarily sized image
try:
img = Image.open(filename)
@@ -1242,7 +1282,7 @@ def displayimage(camera, filename, overlay):
# the new overlay semi-transparent, then move it above
# the preview
overlay.alpha = 255
- overlay.layer = 3
+ overlay.layer = layer
return overlay
def removeimage(camera, overlay):
@@ -1385,7 +1425,7 @@ def getconfig(camera):
menu = 'rev.C', 'rev.D', 'hq-camera'
while True:
settings = '', '', ''
- writemenu(menu,settings,selected,header)
+ writemenu(menu,settings,selected,header,showmenu)
pressed, buttonpressed, buttontime, holdbutton, event, keydelay = getbutton(pressed, buttonpressed, buttontime, holdbutton)
if pressed == 'right':
if selected < (len(settings) - 1):
@@ -1419,7 +1459,7 @@ def loadfilm(filmname, filmfolder):
menu = 'FILM:', 'BACK'
while True:
settings = films[selectedfilm][0], ''
- writemenu(menu,settings,selected,header)
+ writemenu(menu,settings,selected,header,showmenu)
pressed, buttonpressed, buttontime, holdbutton, event, keydelay = getbutton(pressed, buttonpressed, buttontime, holdbutton)
if pressed == 'down':
if selectedfilm < filmstotal:
@@ -1530,7 +1570,7 @@ def timelapse(beeps,camera,foldername,filename,between,duration):
menu = 'DELAY:', 'DURATION:', 'START', 'BACK'
while True:
settings = str(round(between,2)), str(round(duration,2)), '', ''
- writemenu(menu,settings,selected,header)
+ writemenu(menu,settings,selected,header,showmenu)
seconds = (3600 / between) * duration
vumetermessage('1 h timelapse filming equals ' + str(round(seconds,2)) + ' second clip ')
pressed, buttonpressed, buttontime, holdbutton, event, keydelay = getbutton(pressed, buttonpressed, buttontime, holdbutton)
@@ -1656,7 +1696,7 @@ def remove(filmfolder, filmname, scene, shot, take, sceneshotortake):
settings = 'NO', 'YES'
selected = 0
while True:
- writemenu(menu,settings,selected,header)
+ writemenu(menu,settings,selected,header,showmenu)
pressed, buttonpressed, buttontime, holdbutton, event, keydelay = getbutton(pressed, buttonpressed, buttontime, holdbutton)
if pressed == 'right':
if selected < (len(settings) - 1):
@@ -2309,7 +2349,7 @@ def removedub(dubfolder, dubnr):
menu = 'NO', 'YES'
settings = '', ''
while True:
- writemenu(menu,settings,selected,header)
+ writemenu(menu,settings,selected,header,showmenu)
pressed, buttonpressed, buttontime, holdbutton, event, keydelay = getbutton(pressed, buttonpressed, buttontime, holdbutton)
if pressed == 'right':
if selected < (len(menu) - 1):
@@ -2393,7 +2433,7 @@ def clipsettings(filmfolder, filmname, scene, shot, plughw):
else:
menu = 'BACK', 'ADD:', '', ''
settings = '', 'd:' + str(nmix) + '/o:' + str(ndub), 'in:' + str(nfadein), 'out:' + str(nfadeout)
- writemenu(menu,settings,selected,header)
+ writemenu(menu,settings,selected,header,showmenu)
pressed, buttonpressed, buttontime, holdbutton, event, keydelay = getbutton(pressed, buttonpressed, buttontime, holdbutton)
#NEW DUB SETTINGS
@@ -2604,7 +2644,7 @@ def playdub(filename, player_menu):
header = 'Dubbing ' + str(round(t,1))
else:
header = 'Playing ' + str(round(t,1)) + ' of ' + str(clipduration) + ' s'
- writemenu(menu,settings,selected,header)
+ writemenu(menu,settings,selected,header,showmenu)
pressed, buttonpressed, buttontime, holdbutton, event, keydelay = getbutton(pressed, buttonpressed, buttontime, holdbutton)
if buttonpressed == True:
flushbutton()
@@ -2975,7 +3015,7 @@ def uploadfilm(filename, filmname):
selected = 0
while True:
header = 'Where do you want to upload?'
- writemenu(menu,settings,selected,header)
+ writemenu(menu,settings,selected,header,showmenu)
pressed, buttonpressed, buttontime, holdbutton, event, keydelay = getbutton(pressed, buttonpressed, buttontime, holdbutton)
if pressed == 'right':
if selected < (len(menu) - 1):
@@ -3191,6 +3231,8 @@ def getbutton(lastbutton, buttonpressed, buttontime, holdbutton):
pressed = 'peak'
elif (readbus2 == 245 and readbus == 223):
pressed = 'screen'
+ elif (readbus2 == 245 and readbus == 247):
+ pressed = 'showmenu'
elif event == 'I' or event == 'P' or (readbus2 == 244 and readbus == 255):
pressed = 'insert'
elif event == 'C' or (readbus2 == 245 and readbus == 254):
@@ -3233,7 +3275,11 @@ def stopinterface(camera):
def startcamera(lens, fps):
camera = picamera.PiCamera()
- camera.resolution = (1920, 1080) #tested modes 1920x816, 1296x552/578, v2 1640x698, 1640x1232
+ camera.resolution = (2028, 1080) #tested modes 1920x816, 1296x552/578, v2 1640x698, 1640x1232, hqbinned 2028x1080
+ #Background image
+ underlay = None
+ bakgimg = tarinafolder + '/extras/bakg.jpg'
+ displaybakg(camera, bakgimg, underlay, 2)
#lensshade = ''
#npzfile = np.load('lenses/' + lens)
#lensshade = npzfile['lens_shading_table']