~mil/sxmo-devel

sxmo-utils: camera: low latency preview and picture v1 APPLIED

Anjandev Momi: 1
 camera: low latency preview and picture

 3 files changed, 143 insertions(+), 6 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~mil/sxmo-devel/patches/12058/mbox | git am -3
Learn more about email & git

[PATCH sxmo-utils] camera: low latency preview and picture Export this patch

- Take pictures by pressing "s" when the preview opens.
- Depends on sxmo_autorotate.sh
- movie is not currently working. See comments in code
- uses sxiv for image previews of photos taken during that photoshoot
- TODO: use sxiv keyhandlers to add a delete photo function
	- See: /usr/share/examples/sxiv/key-handler
	- I dont know how we would distribute this
---
 scripts/core/sxmo_appmenu.sh |   1 +
 scripts/core/sxmo_camera.sh  | 147 +++++++++++++++++++++++++++++++++--
 scripts/core/sxmo_xinit.sh   |   1 +
 3 files changed, 143 insertions(+), 6 deletions(-)
diff --git a/scripts/core/sxmo_appmenu.sh b/scripts/core/sxmo_appmenu.sh
index 16cdf34..3deccc3 100755
--- a/scripts/core/sxmo_appmenu.sh
+++ b/scripts/core/sxmo_appmenu.sh
@@ -134,6 +134,7 @@ programchoicesinit() {
		 Rotate ↻        ^ 1 ^ key greater
		 Flip ⇄          ^ 1 ^ key question
		 Flip ⇅          ^ 1 ^ key bar
		 Thumbnail ⊡     ^ 0 ^ key Return
		"
		WINNAME=Sxiv && return
	elif echo "$WMCLASS" | grep -i "st-256color"; then
diff --git a/scripts/core/sxmo_camera.sh b/scripts/core/sxmo_camera.sh
index 9e02ff9..61a23d2 100755
--- a/scripts/core/sxmo_camera.sh
+++ b/scripts/core/sxmo_camera.sh
@@ -1,8 +1,143 @@
#!/usr/bin/env sh
err() {
	printf %b "$1" | dmenu -fn Terminus-20 -c -l 10
	exit 1
 #!/usr/bin/env sh

SXMO_IMAGESDIR="$XDG_PICTURES_DIR/sxmo"

node_rear="ov5640 3-004c"
route_rear="ov5640"
mode_rear="1920x1080@20"

node_front="gc2145 3-003c"
route_front="gc2145"
mode_front="1600x1200@15"

pixfmt='UYVY'

set_route () {
	camera="$1"
	if [ "$camera" = "$route_rear" ]
	then
		link1='"gc2145 3-003c":0->"sun6i-csi":0[0]'
		link2='"ov5640 3-004c":0->"sun6i-csi":0[1]'
	elif [ "$camera" = "$route_front"  ]
	then
		link1='"ov5640 3-004c":0->"sun6i-csi":0[0]'
		link2='"gc2145 3-003c":0->"sun6i-csi":0[1]'
	fi

	media-ctl -d /dev/media1 --links "$link1" && media-ctl -d /dev/media1 --links "$link2" || exit 1
}

setup () {
	node="$1" 
	mode="$2" 

	res="${mode%%@*}"
	speed="${mode##*@}"

	busfmt='UYVY8_2X8'

	setup="media-ctl -d /dev/media1 --set-v4l2 '\"$node\":0[fmt:$busfmt/$res@1/$speed]'"
	eval "$setup"

	height="${res%%x*}"
	width="${res##*x}"

	v4l2-ctl --device /dev/video1 --set-fmt-video="width=$width,height=$height,pixelformat=$pixfmt"
}

still () {
	node="$1" 
	mode="$2" 
	angle="$3"
	skip="$4"

	setup "$node" "$mode"

	speed="30"
	res="${mode%%@*}"
	speed="${mode##*@}"

	height="${res##*x}"
	width="${res%%x*}"

	mkdir "$SXMO_IMAGESDIR"

	SCREENSHOT_PRE="$(date)"

	mplayer tv:// -tv driver=v4l2:width=$width:height=$height:device=/dev/video1 -fps $speed -vf rotate="$angle",screenshot="$SXMO_IMAGESDIR/$SCREENSHOT_PRE"

	find "$SXMO_IMAGESDIR" -iname "$SCREENSHOT_PRE*" | sxiv -t -i -

	# mpv command doesnt work =( https://wiki.archlinux.org/index.php/Webcam_setup#MPlayer
	# mpv --demuxer-lavf-format=video4linux2 --demuxer-lavf-o-set=input_format=rawvideo:video_size=1920x1080:framerate=20 av://v4l2:/dev/video1 --profile=low-latency

}

movie () {
	# Not working but shows off the performance of this script
	node="$1" 
	mode="$2" 
	angle="$3"
	skip="$4"

	setup "$node" "$mode"

	speed="30"
	res="${mode%%@*}"
	speed="${mode##*@}"

	height="${res##*x}"
	width="${res%%x*}"

	VIDEO_NAME="$SXMO_IMAGESDIR"/"$(date)".mkv
	# this command gives the best performance but I cannot get a video preview with this command =(
	# please note, to stop recording, you need to type `killall ffmpeg` in a terminal
	ffmpeg -f v4l2 -framerate $speed -video_size $res -i /dev/video1 -preset ultrafast -filter:v fps=fps=$speed -f matroska "$VIDEO_NAME"


	save="Save: $VIDEO_NAME"
	playback="Playback: $(ffprobe -v quiet -of csv=p=0 -show_entries format=duration "$VIDEO_NAME")"
	delete="Delete Recording"

	DONE=0

	while [ $DONE != 1 ]; do
		result="$(printf %b "$save\n$playback\n$delete" | dmenu -fn Terminus-30 -c -p "Record" -l 20)"
		if [ "$result" = "$save" ]; then
			return 0
		elif [ "$result" = "$playback" ]; then
			mpv "$VIDEO_NAME"
		else
			rm "$VIDEO_NAME"
			return 0
		fi
	done


	# outputs 10 fps =(
	# ffmpeg -f v4l2 -framerate $speed -video_size $res -i /dev/video1 -preset ultrafast -filter:v fps=fps=$speed -f matroska pipe: | tee file.mkv | mplayer - -fps $speed -vf screenshot

	# I tried forking ffmpeg to background and using mplayer. When mplayer closes, killall ffmpeg. It didnt work =(
	#mplayer tv:// -tv driver=v4l2:width=$width:height=$height:device=/dev/video1 -fps $speed -vf screenshot 

}

media-ctl -d /dev/media1 --set-v4l2 '"ov5640 3-004c":0[fmt:UYVY8_2X8/1280x720]' || err "Couldn't open camera, is camera enabled?"
mpv --video-rotate=90 av://v4l2:/dev/video1

type="$(printf %b "picture\nmovie" | dmenu -fn Terminus-30 -c -p "Record" -l 20)"
camera="$(printf %b "front\nrear" | dmenu -fn Terminus-30 -c -p "Record" -l 20)"

# Note: "angle" is set according to mplayer's conventions. See man mplayer and look for "rotate"

[ "$camera" = "rear" ] && set_route "$route_rear" && skip=5 && node="$node_rear" && mode="$mode_rear" && angle="1"
[ "$camera" = "front" ] && set_route "$route_front" && skip=0 && node="$node_front" && mode="$mode_front" && angle="2"

# our angle variables are set for rotnormal orientation
# rotating will ruin the preview
RUNNING_AUTO="$(ps aux | grep "sh /usr/bin/sxmo_autorotate.sh" | grep -v grep | cut -f2 -d' ')"
[ -n "$RUNNING_AUTO" ] && echo "$RUNNING_AUTO" | tr '\n' ' ' | xargs kill -9; notify-send "Turning autorotate off"
sxmo_rotate.sh isrotated && sxmo_rotate.sh rotnormal

[ "$type" = "picture" ] && still "$node" "$mode" "$angle" "$skip"
[ "$type" = "movie" ] && movie "$node" "$mode" "$angle" "$skip"

[ -n "$RUNNING_AUTO" ] && sxmo_autorotate.sh
diff --git a/scripts/core/sxmo_xinit.sh b/scripts/core/sxmo_xinit.sh
index 9becdb1..d9d1b6a 100755
--- a/scripts/core/sxmo_xinit.sh
+++ b/scripts/core/sxmo_xinit.sh
@@ -12,6 +12,7 @@ envvars() {
	[ -z "$XDG_CACHE_HOME" ] && export XDG_CACHE_HOME=~/.cache
	[ -z "$XDG_DATA_HOME" ] && export XDG_DATA_HOME=~/.local/share
	[ -z "$XDG_RUNTIME_HOME" ] && export XDG_RUNTIME_HOME=~/.local/run
	[ -z "$XDG_PICTURES_DIR" ] && export XDG_PICTURES_DIR=~/Pictures
}

setupxdgruntimedir() {
-- 
2.28.0
Anjandev Momi <anjan@momi.ca> wrote:
> - Take pictures by pressing "s" when the preview opens.
> - Depends on sxmo_autorotate.sh
> - movie is not currently working. See comments in code
> - uses sxiv for image previews of photos taken during that photoshoot
> - TODO: use sxiv keyhandlers to add a delete photo function
> 	- See: /usr/share/examples/sxiv/key-handler
> 	- I dont know how we would distribute this
> ---
>  scripts/core/sxmo_appmenu.sh |   1 +
>  scripts/core/sxmo_camera.sh  | 147 +++++++++++++++++++++++++++++++++--
>  scripts/core/sxmo_xinit.sh   |   1 +
>  3 files changed, 143 insertions(+), 6 deletions(-)

Thanks for doing the work on this and figuring out the camera
routing! This is substantially better then things were previously. I've
applied and changed the stream to use mpv rather then mplayer since we
only install mpv. Speed is the same as with mplayer. I also did some
minor refactoring to keep things in the same style as other scripts.

For pictures the user can already use the context menu in mpv to take a
'screenshot'.  For videos, I want to add an option to arbitrarily record
videos in mpv. This will also have the added benefit that users can
record other streaming videos other then the camera as well.

The only downside to mpv currently is that I'm struggling to figure
out how to rotate the stream in mpv without re-encoding / inducing lag.
What I've been trying is:

-vf=tranpose=1

But unfortunately, for some reason that triggers the reencoder where
mplayer's rotate doesn't. We could switch to use mplayer instead but
I'd rather have 1 media player (since there should be good record +
picture support in the 1 media player we choose); and we already use
mpv extensively for ytdl and other things.

For the interim until we can figure out how to have mpv or v4l rotate
without inducing lag, I've set the sxmo_rotate.sh to do the work of
rotating X instead of mpv.