58 lines
1.5 KiB
Elixir
58 lines
1.5 KiB
Elixir
|
defmodule AugieWeb.CameraController do
|
||
|
use AugieWeb, :controller
|
||
|
|
||
|
@camera Application.get_env(:picam, :camera, Picam.Camera)
|
||
|
|
||
|
def static(conn, _params) do
|
||
|
Picam.set_size(640, 480)
|
||
|
|
||
|
conn
|
||
|
|> put_resp_header("Age", "0")
|
||
|
|> put_resp_header("Cache-Control", "no-cache, private")
|
||
|
|> put_resp_header("Pragma", "no-cache")
|
||
|
|> put_resp_header("Content-Type", "image/jpeg")
|
||
|
|> send_chunked(200)
|
||
|
|> send_image()
|
||
|
end
|
||
|
|
||
|
def stream(conn, _params) do
|
||
|
Picam.set_size(640, 480)
|
||
|
|
||
|
boundary = generate_boundary(16)
|
||
|
|
||
|
conn
|
||
|
|> put_resp_header("Age", "0")
|
||
|
|> put_resp_header("Cache-Control", "no-cache, private")
|
||
|
|> put_resp_header("Pragma", "no-cache")
|
||
|
|> put_resp_header("Content-Type", "multipart/x-mixed-replace; boundary=#{boundary}")
|
||
|
|> send_chunked(200)
|
||
|
|> send_stream(boundary)
|
||
|
end
|
||
|
|
||
|
defp send_image(conn) do
|
||
|
jpg = GenServer.call(@camera, :next_frame)
|
||
|
|
||
|
with {:ok, conn} <- chunk(conn, jpg),
|
||
|
do: conn
|
||
|
end
|
||
|
|
||
|
defp send_stream(conn, boundary) do
|
||
|
jpg = GenServer.call(@camera, :next_frame)
|
||
|
size = byte_size(jpg)
|
||
|
header = "------#{boundary}\r\nContent-Type: image/jpeg\r\nContent-length: #{size}\r\n\r\n"
|
||
|
footer = "\r\n"
|
||
|
|
||
|
with {:ok, conn} <- chunk(conn, header),
|
||
|
{:ok, conn} <- chunk(conn, jpg),
|
||
|
{:ok, conn} <- chunk(conn, footer),
|
||
|
do: conn
|
||
|
end
|
||
|
|
||
|
defp generate_boundary(length) do
|
||
|
length
|
||
|
|> :crypto.strong_rand_bytes()
|
||
|
|> Base.encode64()
|
||
|
|> binary_part(0, length)
|
||
|
end
|
||
|
end
|