Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cereal/log.capnp
Original file line number Diff line number Diff line change
Expand Up @@ -2604,6 +2604,8 @@ struct Event {
livestreamRoadEncodeData @120 :EncodeData;
livestreamWideRoadEncodeData @121 :EncodeData;
livestreamDriverEncodeData @122 :EncodeData;
youtubeRoadEncodeData @152 :EncodeData;
youtubeRoadEncodeIdx @153 :EncodeIndex;

# *********** Custom: reserved for forks ***********

Expand Down
1 change: 1 addition & 0 deletions cereal/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ def __init__(self, should_log: bool, frequency: float, decimation: Optional[int]
"livestreamWideRoadEncodeData": (False, 20., None, QueueSize.MEDIUM),
"livestreamRoadEncodeData": (False, 20., None, QueueSize.MEDIUM),
"livestreamDriverEncodeData": (False, 20., None, QueueSize.MEDIUM),
"youtubeRoadEncodeData": (False, 20., None, QueueSize.BIG),
"customReservedRawData0": (True, 0.),
"customReservedRawData1": (True, 0.),
"customReservedRawData2": (True, 0.),
Expand Down
3 changes: 3 additions & 0 deletions common/params_keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"ClusterHudRadarDisplay", {PERSISTENT, INT, "0"}},
{"ClusterHudRadarSourceColor", {PERSISTENT, INT, "0"}},
{"RecordRoadCam", {PERSISTENT, INT, "0"}},
{"CarrotYouTubeLive", {PERSISTENT, INT, "0"}},
{"CarrotYouTubeQuality", {PERSISTENT, INT, "0"}},
{"CarrotYouTubeTimestamp", {PERSISTENT, INT, "0"}},
{"HDPuse", {PERSISTENT, INT, "0"}},

{"AutoCruiseControl", {PERSISTENT, INT, "0"}},
Expand Down
2 changes: 2 additions & 0 deletions selfdrive/carrot/server/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
CARROT_WEB_SETTINGS_PATH = os.path.join(CARROT_STATE_DIR, "web_settings.json")
CARROT_SETTING_FAVORITES_PATH = os.path.join(CARROT_STATE_DIR, "setting_favorites.json")
CARROT_SETTING_PROFILES_PATH = os.path.join(CARROT_STATE_DIR, "setting_profiles.json")
CARROT_YOUTUBE_LIVE_STATE_PATH = os.path.join(CARROT_STATE_DIR, "youtube_live.json")
CARROT_YOUTUBE_LIVE_SECRET_PATH = os.path.join(CARROT_STATE_DIR, "youtube_live_secret.json")

# Dashcam
DASHCAM_ROOT = "/data/media/0/realdata"
Expand Down
2 changes: 2 additions & 0 deletions selfdrive/carrot/server/features/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
vision_test,
web_settings,
ws,
youtube_live,
)


Expand All @@ -39,5 +40,6 @@ def register_all(app: web.Application) -> None:
dashcam.register(app)
screenrecord.register(app)
tools.register(app)
youtube_live.register(app)
vision_test.register(app)
vision_diag.register(app)
86 changes: 86 additions & 0 deletions selfdrive/carrot/server/features/youtube_live.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from __future__ import annotations

import asyncio

from aiohttp import web

from ..services.youtube_live import YouTubeLiveService


YOUTUBE_LIVE_APP_KEY = "youtube_live_service"


def _service(request: web.Request) -> YouTubeLiveService:
service = request.app.get(YOUTUBE_LIVE_APP_KEY)
if not isinstance(service, YouTubeLiveService):
raise web.HTTPServiceUnavailable(text="youtube live service unavailable")
return service


async def youtube_live_context(app: web.Application):
service = YouTubeLiveService()
app[YOUTUBE_LIVE_APP_KEY] = service
await service.start()
try:
yield
finally:
await service.stop()
app.pop(YOUTUBE_LIVE_APP_KEY, None)


async def api_status(request: web.Request) -> web.Response:
return web.json_response({"ok": True, **_service(request).status()})


async def api_set_stream_key(request: web.Request) -> web.Response:
try:
body = await request.json()
except Exception:
return web.json_response({"ok": False, "error": "invalid json"}, status=400)
key = body.get("stream_key", body.get("key", ""))
try:
status = _service(request).set_stream_key(str(key or ""))
except ValueError as exc:
return web.json_response({"ok": False, "error": str(exc)}, status=400)
return web.json_response({"ok": True, **status})


async def api_get_stream_key(request: web.Request) -> web.Response:
stream_key = _service(request).get_stream_key()
return web.json_response({"ok": True, "configured": bool(stream_key), "stream_key": stream_key})


async def api_clear_stream_key(request: web.Request) -> web.Response:
return web.json_response({"ok": True, **_service(request).clear_stream_key()})


async def api_test(request: web.Request) -> web.Response:
result = await asyncio.to_thread(_service(request).test_config)
return web.json_response(result, status=200 if result.get("ok") else 409)


async def api_validate_stream_key(request: web.Request) -> web.Response:
body = {}
if request.can_read_body:
try:
body = await request.json()
except Exception:
return web.json_response({"ok": False, "error": "invalid json"}, status=400)
key = body.get("stream_key", body.get("key")) if isinstance(body, dict) else None
result = await asyncio.to_thread(_service(request).validate_stream_key, key)
return web.json_response(result, status=200 if result.get("ok") else 409)


async def api_diagnostics(request: web.Request) -> web.Response:
return web.json_response({"ok": True, "diagnostics": _service(request).diagnostics()})


def register(app: web.Application) -> None:
app.cleanup_ctx.append(youtube_live_context)
app.router.add_get("/api/youtube_live/status", api_status)
app.router.add_get("/api/youtube_live/diagnostics", api_diagnostics)
app.router.add_get("/api/youtube_live/stream_key", api_get_stream_key)
app.router.add_post("/api/youtube_live/stream_key", api_set_stream_key)
app.router.add_post("/api/youtube_live/stream_key/validate", api_validate_stream_key)
app.router.add_delete("/api/youtube_live/stream_key", api_clear_stream_key)
app.router.add_post("/api/youtube_live/test", api_test)
Loading
Loading